src/EditProductTab1.cpp

Mon, 18 Jul 2022 17:04:02 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Mon, 18 Jul 2022 17:04:02 +0200
changeset 359
dfbb012c631c
parent 344
9ffac162000c
child 361
ec8de79f6ff6
permissions
-rw-r--r--

Redesign of the water tabs in product and recipe editors. Prepare for sparge water salt additions. Acid additions are now automatic or manual for mash and sparge. Fixed error in acid calculation strength. Fixed phophoric SG value.

/**
 * EditProduct.cpp is part of bmsapp.
 *
 * Tab 1, generic settings.
 *
 * bmsapp is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * bmsapp is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */


void EditProduct::code_changed(QString code)
{
    product->code = code;
    is_changed();
}


void EditProduct::name_changed(QString name)
{
    product->name = name;
    is_changed();
}


void EditProduct::notes_changed()
{
    /* The text cannot be passed in a simple way :) */
    product->notes = ui->notesEdit->toPlainText();
    is_changed();
}


/*
 * New beerstyle is selected.
 */
void EditProduct::style_changed(int val)
{
    QSqlQuery query;

    query.prepare("SELECT * FROM profile_styles ORDER BY style_guide,style_letter,name");
    query.exec();
    query.first();
    // Skip to the record index.
    for (int i = 0; i < (val - 1); i++) {
        query.next();
    }
    // Set relevant fields and update ranges.
    product->st_name = query.value(1).toString();
    product->st_category = query.value(2).toString();
    product->st_category_number = query.value(3).toInt();
    product->st_letter = query.value(4).toString();
    product->st_guide = query.value(5).toString();
    product->st_type = query.value(6).toInt();
    product->st_og_min = query.value(7).toDouble();
    product->st_og_max = query.value(8).toDouble();
    product->st_fg_min = query.value(9).toDouble();
    product->st_fg_max = query.value(10).toDouble();
    product->st_ibu_min = query.value(11).toDouble();
    product->st_ibu_max = query.value(12).toDouble();
    product->st_color_min = query.value(13).toDouble();
    product->st_color_max = query.value(14).toDouble();
    product->st_carb_min = query.value(15).toDouble();
    product->st_carb_max = query.value(16).toDouble();
    product->st_abv_min = query.value(17).toDouble();
    product->st_abv_max = query.value(18).toDouble();

    ui->st_nameEdit->setText(product->st_name);
    ui->st_groupEdit->setText(product->st_letter);
    ui->st_guideEdit->setText(product->st_guide);
    ui->st_catEdit->setText(product->st_category);
    ui->st_catnrEdit->setText(QString("%1").arg(product->st_category_number));
    ui->st_typeEdit->setText(QCoreApplication::translate("BeerType", g_style_types[product->st_type]));

    ui->est_ogShow->setRange(query.value(7).toDouble(), query.value(8).toDouble());
    ui->est_fgShow->setRange(query.value(9).toDouble(), query.value(10).toDouble());
    ui->est_ibuShow->setRange(query.value(11).toDouble(), query.value(12).toDouble());
    ui->est_colorShow->setRange(query.value(13).toDouble(), query.value(14).toDouble());
    ui->est_carbShow->setRange(query.value(15).toDouble(), query.value(16).toDouble());
    ui->est_abvShow->setRange(query.value(17).toDouble(), query.value(18).toDouble());

    is_changed();
}


void EditProduct::colormethod_changed(int val)
{
    product->color_method = val;
    calcFermentables();
    is_changed();
}


void EditProduct::ibumethod_changed(int val)
{
    product->ibu_method = val;
    calcIBUs();
    is_changed();
    emit refreshAll();
}


void EditProduct::est_og_changed(double val)
{
    product->est_og = val;
    calcFermentablesFromOG(val);// Adjust fermentables amounts
    calcFermentables();		// Update the product details
    calcIBUs();
    calcMash();
    is_changed();
    emit refreshAll();
}


void EditProduct::efficiency_changed(double val)
{
    double estog = product->est_og;
    product->efficiency = val;
    calcFermentablesFromOG(estog);
    calcFermentables();
    calcIBUs();
    is_changed();
    emit refreshAll();
}


void EditProduct::boil_time_changed(int val)
{
    qDebug() << "boil_time_changed" << val;
    double new_evap = (0.1 * product->batch_size) * val / 60.0;
    product->boil_size = product->batch_size + new_evap;
    product->boil_time = val;
    ui->boil_sizeEdit->setValue(product->boil_size);
    ui->brew_preboilvolShow->setValue(product->boil_size * 1.04);
    calcFermentables();
    calcIBUs();
    is_changed();
}


void EditProduct::batch_size_changed(double val)
{
    qDebug() << "batch_size_changed" << val << "old" << product->batch_size;

    double evap = (0.1 * val) * product->boil_time / 60.0;
    product->boil_size = val + evap;
    double factor = val / product->batch_size;
    ui->boil_sizeEdit->setValue(product->boil_size);
    ui->brew_preboilvolShow->setValue(product->boil_size * 1.04);
    product->sparge_volume *= factor;
    ui->sp_volEdit->setValue(product->sparge_volume);
    ui->brew_spargevolShow->setValue(product->sparge_volume);
    product->batch_size = val;
    calcFermentablesFromOG(product->est_og);	// Keep the OG
    adjustWaters(factor);
    calcFermentables();
    adjustHops(factor);
    adjustMiscs(factor);
    adjustYeasts(factor);
    calcIBUs();
    calcWater();
    calcMash();
    is_changed();
    emit refreshAll();
}


void EditProduct::brew_type_changed(int val)
{
    product->type;
    is_changed();
}


void EditProduct::locked_changed(bool val)
{
    qDebug() << "locked_changed" << val;

    if (product->stage < PROD_STAGE_READY)
	return;

    product->locked = val;
    product->stage = val ? PROD_STAGE_CLOSED : PROD_STAGE_READY;
    setStage();
    is_changed();
}


void EditProduct::setStage()
{
    int	 stage = product->stage;
    bool locked = product->locked;

    /*
     * See if we need to set a new stage.
     */
    if ((stage == PROD_STAGE_PLAN) && (product->est_og > 1.005) && (product->est_color > 3) && (product->est_ibu > 3))
	stage = PROD_STAGE_WAIT;
    if ((stage == PROD_STAGE_WAIT) && (product->brew_date_start.date().isValid()))
	stage = PROD_STAGE_BREW;
    if ((stage == PROD_STAGE_BREW) && (! product->brew_date_start.date().isValid()))
	stage = PROD_STAGE_WAIT;
    /* from PROD_STAGE_BREW to PROD_STAGE_PRIMARY is handled in EditProductTab9.cpp */
    /* from PROD_STAGE_PRIMARY to PROD_STAGE_SECONDARY is handled in EditProductTab10.cpp */
    /* from PROD_STAGE_SECONDARY to PROD_STAGE_TERIARY is handled in EditProductTab10.cpp */
    if ((stage == PROD_STAGE_TERTIARY) && product->package_date.isValid())
	stage = PROD_STAGE_PACKAGE;
    if ((stage == PROD_STAGE_PACKAGE) && (! product->package_date.isValid()))
	stage = PROD_STAGE_TERTIARY;
    /* from PROD_STAGE_PACKAGE to PROD_STAGE_CARBONATION is handled in EditProductTab11.cpp */
    if ((stage == PROD_STAGE_CARBONATION) && (product->package_date.daysTo(QDate::currentDate()) > 14))
	stage = PROD_STAGE_MATURE;

    if (product->stage != stage) {
	qDebug() << "setStage() change state:" << g_prod_stages[product->stage] << "to:" << g_prod_stages[stage];
    	product->stage = stage;
	is_changed();
    } else {
	qDebug() << "setStage() stage:" << g_prod_stages[stage];
    }

    ui->stageEdit->setText(QCoreApplication::translate("ProdStages", g_prod_stages[stage]));

    /* Tab 1, generic */
    ui->typeEdit->setDisabled(stage > PROD_STAGE_WAIT);
    ui->color_methodEdit->setDisabled(locked);
    ui->ibu_methodEdit->setDisabled(locked);
    ui->beerstyleEdit->setDisabled(stage > PROD_STAGE_WAIT);
    ui->nameEdit->setReadOnly(stage > PROD_STAGE_WAIT);
    ui->codeEdit->setReadOnly(stage > PROD_STAGE_WAIT || product->divide_type);	/* Never change this in a splitted product. */
    ui->notesEdit->setReadOnly(locked);
    ui->batch_sizeEdit->setReadOnly(stage > PROD_STAGE_WAIT);
    ui->batch_sizeEdit->setButtonSymbols((stage > PROD_STAGE_WAIT) ? QAbstractSpinBox::NoButtons : QAbstractSpinBox::UpDownArrows);
    ui->boil_sizeEdit->setReadOnly(stage > PROD_STAGE_WAIT);
    ui->boil_sizeEdit->setButtonSymbols((stage > PROD_STAGE_WAIT) ? QAbstractSpinBox::NoButtons : QAbstractSpinBox::UpDownArrows);
    ui->boil_timeEdit->setReadOnly(stage > PROD_STAGE_WAIT);
    ui->boil_timeEdit->setButtonSymbols((stage > PROD_STAGE_WAIT) ? QAbstractSpinBox::NoButtons : QAbstractSpinBox::UpDownArrows);
    ui->efficiencyEdit->setReadOnly(stage > PROD_STAGE_WAIT);
    ui->efficiencyEdit->setButtonSymbols((stage > PROD_STAGE_WAIT) ? QAbstractSpinBox::NoButtons : QAbstractSpinBox::UpDownArrows);
    ui->est_ogEdit->setReadOnly(stage > PROD_STAGE_WAIT);
    ui->est_ogEdit->setButtonSymbols((stage > PROD_STAGE_WAIT) ? QAbstractSpinBox::NoButtons : QAbstractSpinBox::UpDownArrows);
    /*
     * The next two items are displayed on the same location.
     * But they are not needed at the same time.
     */
    if (stage > PROD_STAGE_PACKAGE) {
	ui->ok_pmptLabel->hide();
	ui->ok_pmptIcon->hide();
    } else {
	ui->ok_pmptLabel->show();
        ui->ok_pmptIcon->show();
    }
    if (stage >= PROD_STAGE_READY) {
	ui->lockedLabel->show();
	ui->lockedEdit->show();
    } else {
	ui->lockedLabel->hide();
        ui->lockedEdit->hide();
    }

    /* Tab 2, equipment */
    ui->tabWidget->setTabEnabled(1, stage < PROD_STAGE_BREW);

    /* Tab 3, fermentables */
    ui->est_og2Edit->setReadOnly(stage > PROD_STAGE_WAIT);
    ui->est_og2Edit->setButtonSymbols((stage > PROD_STAGE_WAIT) ? QAbstractSpinBox::NoButtons : QAbstractSpinBox::UpDownArrows);
    ui->addFermentable->setEnabled(stage <= PROD_STAGE_PACKAGE);

    /* Tab 4, hops */
    ui->addHop->setEnabled(stage <= PROD_STAGE_PACKAGE);

    /* Tab 5, miscs */
    ui->addMisc->setEnabled(stage <= PROD_STAGE_PACKAGE);

    /* Tab 6, yeasts */
    ui->addYeast->setEnabled(stage <= PROD_STAGE_PACKAGE);

    /* Tab 7, mash */
    ui->addMash->setEnabled(stage <= PROD_STAGE_BREW);
    ui->mash_nameEdit->setReadOnly(stage > PROD_STAGE_BREW);
    ui->mash_pickEdit->setDisabled(stage > PROD_STAGE_BREW);

    /* Tab 8, water */
    ui->wt_sourceEdit->setDisabled(stage > PROD_STAGE_BREW);
    ui->w1_nameEdit->setDisabled(stage > PROD_STAGE_BREW);
    ui->w2_nameEdit->setDisabled(stage > PROD_STAGE_BREW);
    ui->mw_acidPick->setDisabled(stage > PROD_STAGE_BREW);
    ui->sp_acidtypeEdit->setDisabled(stage > PROD_STAGE_BREW);
    ui->w2_volEdit->setReadOnly(stage > PROD_STAGE_BREW);
    ui->w2_volEdit->setButtonSymbols((stage > PROD_STAGE_BREW) ? QAbstractSpinBox::NoButtons : QAbstractSpinBox::UpDownArrows);
    //ui->sp_tempEdit->setReadOnly(stage > PROD_STAGE_BREW);
    //ui->sp_tempEdit->setButtonSymbols((stage > PROD_STAGE_BREW) ? QAbstractSpinBox::NoButtons : QAbstractSpinBox::UpDownArrows);
    ui->sp_volEdit->setReadOnly(stage > PROD_STAGE_BREW);
    ui->sp_volEdit->setButtonSymbols((stage > PROD_STAGE_BREW) ? QAbstractSpinBox::NoButtons : QAbstractSpinBox::UpDownArrows);
    ui->bs_cacl2Edit->setReadOnly(stage > PROD_STAGE_BREW);
    ui->bs_cacl2Edit->setButtonSymbols((stage > PROD_STAGE_BREW) ? QAbstractSpinBox::NoButtons : QAbstractSpinBox::UpDownArrows);
    ui->bs_caso4Edit->setReadOnly(stage > PROD_STAGE_BREW);
    ui->bs_caso4Edit->setButtonSymbols((stage > PROD_STAGE_BREW) ? QAbstractSpinBox::NoButtons : QAbstractSpinBox::UpDownArrows);
    ui->bs_mgso4Edit->setReadOnly(stage > PROD_STAGE_BREW);
    ui->bs_mgso4Edit->setButtonSymbols((stage > PROD_STAGE_BREW) ? QAbstractSpinBox::NoButtons : QAbstractSpinBox::UpDownArrows);
    ui->bs_naclEdit->setReadOnly(stage > PROD_STAGE_BREW);
    ui->bs_naclEdit->setButtonSymbols((stage > PROD_STAGE_BREW) ? QAbstractSpinBox::NoButtons : QAbstractSpinBox::UpDownArrows);
    ui->bs_mgcl2Edit->setReadOnly(stage > PROD_STAGE_BREW);
    ui->bs_mgcl2Edit->setButtonSymbols((stage > PROD_STAGE_BREW) ? QAbstractSpinBox::NoButtons : QAbstractSpinBox::UpDownArrows);
    ui->bs_nahco3Edit->setReadOnly(stage > PROD_STAGE_BREW);
    ui->bs_nahco3Edit->setButtonSymbols((stage > PROD_STAGE_BREW) ? QAbstractSpinBox::NoButtons : QAbstractSpinBox::UpDownArrows);
    ui->bs_caco3Edit->setReadOnly(stage > PROD_STAGE_BREW);
    ui->bs_caco3Edit->setButtonSymbols((stage > PROD_STAGE_BREW) ? QAbstractSpinBox::NoButtons : QAbstractSpinBox::UpDownArrows);
    if (stage > PROD_STAGE_BREW) {
    	ui->mw_phEdit->setReadOnly(true);
	ui->mw_phEdit->setButtonSymbols(QAbstractSpinBox::NoButtons);
	ui->mw_acidvolEdit->setReadOnly(true);
	ui->mw_acidvolEdit->setButtonSymbols(QAbstractSpinBox::NoButtons);
	ui->sp_phEdit->setReadOnly(true);
    	ui->sp_phEdit->setButtonSymbols(QAbstractSpinBox::NoButtons);
	ui->sp_acidvolEdit->setReadOnly(true);
        ui->sp_acidvolEdit->setButtonSymbols(QAbstractSpinBox::NoButtons);
	ui->w1_spButton->setDisabled(true);
    	ui->w2_spButton->setDisabled(true);
    	ui->wg_spButton->setDisabled(true);
    } else {
    	ui->mw_phEdit->setReadOnly(! product->calc_acid);
    	ui->mw_phEdit->setButtonSymbols(product->calc_acid ? QAbstractSpinBox::UpDownArrows : QAbstractSpinBox::NoButtons);
    	ui->mw_acidvolEdit->setReadOnly(product->calc_acid);
    	ui->mw_acidvolEdit->setButtonSymbols(product->calc_acid ? QAbstractSpinBox::NoButtons : QAbstractSpinBox::UpDownArrows);
	ui->sp_phEdit->setReadOnly(! product->calc_acid);
    	ui->sp_phEdit->setButtonSymbols(product->calc_acid ? QAbstractSpinBox::UpDownArrows : QAbstractSpinBox::NoButtons);
	ui->sp_acidvolEdit->setReadOnly(product->calc_acid);
        ui->sp_acidvolEdit->setButtonSymbols(product->calc_acid ? QAbstractSpinBox::NoButtons : QAbstractSpinBox::UpDownArrows);
    }
    ui->mw_autoEdit->setDisabled(stage > PROD_STAGE_BREW);

    /* Tab 9, brewday */
    ui->tabWidget->setTabEnabled(8, stage > PROD_STAGE_PLAN);
    if (product->log_brew) {
	ui->brew_logLabel->show();
	ui->brew_logButton->show();
    } else {
	ui->brew_logLabel->hide();
	ui->brew_logButton->hide();
    }
    ui->brew_ackLabel->hide();
    ui->brew_ackButton->hide();
    if (product->stage < PROD_STAGE_BREW) {
	ui->brew_startButton1->show();
        ui->brew_startButton2->show();
        ui->brew_startDate->setReadOnly(false);
	ui->brew_startDate->setMinimumDate(product->birth.addDays(-1));	// The birth date is the first valid date.
	ui->brew_endButton1->hide();
	ui->brew_startLabel2->hide();
	ui->brew_endLabel->hide();
	ui->brew_endLabel2->hide();
	ui->brew_startTime->hide();
        ui->brew_endDate->hide();
        ui->brew_endTime->hide();
    } else if (product->stage == PROD_STAGE_BREW) {
	ui->brew_startButton1->show();
        ui->brew_startButton2->show();
        ui->brew_startDate->setReadOnly(false);
	ui->brew_startLabel2->show();

	/*
	 * Enable brew_end settings if it is the right date or later.
	 * If some essential values are filled in.
	 */
	int brewTime = product->brew_date_start.date().daysTo(QDate::currentDate());

	if ((brewTime >= 0) && (product->brew_cooling_method > 0) && (product->brew_cooling_time > 0) &&
	    (product->brew_aboil_sg > 1.002) && (product->brew_aboil_volume > 0)) {
            ui->brew_endLabel->show();
	    ui->brew_startLabel2->show();
            ui->brew_endLabel2->show();
	    ui->brew_endButton1->show();
	    ui->brew_startTime->setButtonSymbols(QAbstractSpinBox::UpDownArrows);
	    ui->brew_startTime->show();
	    ui->brew_endDate->setButtonSymbols(QAbstractSpinBox::UpDownArrows);
            ui->brew_endDate->show();
	    ui->brew_endDate->setReadOnly(false);
	    ui->brew_endTime->setButtonSymbols(QAbstractSpinBox::UpDownArrows);
            ui->brew_endTime->show();
	    if (product->brew_date_end.isValid() && product->brew_date_start.isValid() &&
		(product->brew_date_start.msecsTo(product->brew_date_end) > 7200000)) {
		/* The start and end dates are valid, and the end is more then two hours after the start. */
		ui->brew_ackLabel->show();
		ui->brew_ackButton->show();
	    }
	} else {
	    ui->brew_endButton1->hide();
            ui->brew_startLabel2->hide();
            ui->brew_endLabel->hide();
            ui->brew_endLabel2->hide();
            ui->brew_startTime->hide();
            ui->brew_endDate->hide();
            ui->brew_endTime->hide();
	}
    } else {
	ui->brew_startButton1->hide();
        ui->brew_startButton2->hide();
        ui->brew_startDate->setReadOnly(true);
	ui->brew_startLabel2->show();
        ui->brew_endLabel->show();
        ui->brew_endLabel2->show();
	ui->brew_endButton1->hide();
	ui->brew_startTime->setButtonSymbols(QAbstractSpinBox::NoButtons);
	ui->brew_startTime->show();
	ui->brew_startTime->setReadOnly(true);
	ui->brew_endDate->setButtonSymbols(QAbstractSpinBox::NoButtons);
        ui->brew_endDate->show();
	ui->brew_endDate->setReadOnly(true);
	ui->brew_endTime->setButtonSymbols(QAbstractSpinBox::NoButtons);
        ui->brew_endTime->show();
	ui->brew_endTime->setReadOnly(true);
    }
    ui->brew_mashphEdit->setReadOnly(stage > PROD_STAGE_BREW);
    ui->brew_mashphEdit->setButtonSymbols( (stage > PROD_STAGE_BREW) ? QAbstractSpinBox::NoButtons : QAbstractSpinBox::UpDownArrows);
    ui->brew_mashsgEdit->setReadOnly(stage > PROD_STAGE_BREW);
    ui->brew_mashsgEdit->setButtonSymbols( (stage > PROD_STAGE_BREW) ? QAbstractSpinBox::NoButtons : QAbstractSpinBox::UpDownArrows);
    ui->brew_spargephEdit->setReadOnly(stage > PROD_STAGE_BREW);
    ui->brew_spargephEdit->setButtonSymbols( (stage > PROD_STAGE_BREW) ? QAbstractSpinBox::NoButtons : QAbstractSpinBox::UpDownArrows);
    ui->brew_spargetempEdit->setReadOnly(stage > PROD_STAGE_BREW);
    ui->brew_spargetempEdit->setButtonSymbols((stage > PROD_STAGE_BREW) ? QAbstractSpinBox::NoButtons : QAbstractSpinBox::UpDownArrows);
    ui->brew_preboilphEdit->setReadOnly(stage > PROD_STAGE_BREW);
    ui->brew_preboilphEdit->setButtonSymbols( (stage > PROD_STAGE_BREW) ? QAbstractSpinBox::NoButtons : QAbstractSpinBox::UpDownArrows);
    ui->brew_preboilsgEdit->setReadOnly(stage > PROD_STAGE_BREW);
    ui->brew_preboilsgEdit->setButtonSymbols( (stage > PROD_STAGE_BREW) ? QAbstractSpinBox::NoButtons : QAbstractSpinBox::UpDownArrows);
    ui->brew_preboilvolEdit->setReadOnly(stage > PROD_STAGE_BREW);
    ui->brew_preboilvolEdit->setButtonSymbols( (stage > PROD_STAGE_BREW) ? QAbstractSpinBox::NoButtons : QAbstractSpinBox::UpDownArrows);
    ui->brew_preboilButton->setDisabled(stage > PROD_STAGE_BREW);
    ui->brew_aboilphEdit->setReadOnly(stage > PROD_STAGE_BREW);
    ui->brew_aboilphEdit->setButtonSymbols( (stage > PROD_STAGE_BREW) ? QAbstractSpinBox::NoButtons : QAbstractSpinBox::UpDownArrows);
    ui->brew_aboilsgEdit->setReadOnly(stage > PROD_STAGE_BREW);
    ui->brew_aboilsgEdit->setButtonSymbols( (stage > PROD_STAGE_BREW) ? QAbstractSpinBox::NoButtons : QAbstractSpinBox::UpDownArrows);
    ui->brew_aboilvolEdit->setReadOnly(stage > PROD_STAGE_BREW);
    ui->brew_aboilvolEdit->setButtonSymbols( (stage > PROD_STAGE_BREW) ? QAbstractSpinBox::NoButtons : QAbstractSpinBox::UpDownArrows);
    ui->brew_aboilButton->setDisabled(stage > PROD_STAGE_BREW);
    ui->brew_cooltoEdit->setReadOnly(stage > PROD_STAGE_BREW);
    ui->brew_cooltoEdit->setButtonSymbols( (stage > PROD_STAGE_BREW) ? QAbstractSpinBox::NoButtons : QAbstractSpinBox::UpDownArrows);
    ui->brew_cooltimeEdit->setReadOnly(stage > PROD_STAGE_BREW);
    ui->brew_cooltimeEdit->setButtonSymbols( (stage > PROD_STAGE_BREW) ? QAbstractSpinBox::NoButtons : QAbstractSpinBox::UpDownArrows);
    ui->brew_coolwithEdit->setDisabled(stage > PROD_STAGE_BREW);
    ui->brew_whirlpool9Edit->setReadOnly(stage > PROD_STAGE_BREW);
    ui->brew_whirlpool9Edit->setButtonSymbols( (stage > PROD_STAGE_BREW) ? QAbstractSpinBox::NoButtons : QAbstractSpinBox::UpDownArrows);
    ui->brew_whirlpool7Edit->setReadOnly(stage > PROD_STAGE_BREW);
    ui->brew_whirlpool7Edit->setButtonSymbols( (stage > PROD_STAGE_BREW) ? QAbstractSpinBox::NoButtons : QAbstractSpinBox::UpDownArrows);
    ui->brew_whirlpool6Edit->setReadOnly(stage > PROD_STAGE_BREW);
    ui->brew_whirlpool6Edit->setButtonSymbols( (stage > PROD_STAGE_BREW) ? QAbstractSpinBox::NoButtons : QAbstractSpinBox::UpDownArrows);
    ui->brew_whirlpool2Edit->setReadOnly(stage > PROD_STAGE_BREW);
    ui->brew_whirlpool2Edit->setButtonSymbols( (stage > PROD_STAGE_BREW) ? QAbstractSpinBox::NoButtons : QAbstractSpinBox::UpDownArrows);
    ui->brew_aerspeedEdit->setReadOnly(stage > PROD_STAGE_BREW);
    ui->brew_aerspeedEdit->setButtonSymbols( (stage > PROD_STAGE_BREW) ? QAbstractSpinBox::NoButtons : QAbstractSpinBox::UpDownArrows);
    ui->brew_aertimeEdit->setReadOnly(stage > PROD_STAGE_BREW);
    ui->brew_aertimeEdit->setButtonSymbols( (stage > PROD_STAGE_BREW) ? QAbstractSpinBox::NoButtons : QAbstractSpinBox::UpDownArrows);
    ui->brew_aerwithEdit->setDisabled(stage > PROD_STAGE_BREW);
    ui->brew_trublossEdit->setReadOnly(stage > PROD_STAGE_BREW);
    ui->brew_trublossEdit->setButtonSymbols( (stage > PROD_STAGE_BREW) ? QAbstractSpinBox::NoButtons : QAbstractSpinBox::UpDownArrows);
    ui->brew_topupwaterEdit->setReadOnly(stage > PROD_STAGE_BREW);
    ui->brew_topupwaterEdit->setButtonSymbols( (stage > PROD_STAGE_BREW) ? QAbstractSpinBox::NoButtons : QAbstractSpinBox::UpDownArrows);

    /* Tab 10, fermentation */
    ui->tabWidget->setTabEnabled(9, stage > PROD_STAGE_WAIT);
    if (product->log_fermentation) {
	ui->ferm_log1Label->show();
	ui->ferm_log1Button->show();
    } else {
	ui->ferm_log1Label->hide();
        ui->ferm_log1Button->hide();
    }
    if (product->log_ispindel) {
	ui->ferm_log2Label->show();
        ui->ferm_log2Button->show();
    } else {
	ui->ferm_log2Label->hide();
        ui->ferm_log2Button->hide();
    }
    ui->prim_enddateEdit->setReadOnly(true);
    ui->prim_enddateEdit->setButtonSymbols(QAbstractSpinBox::NoButtons);
    ui->prim_enddateButton->hide();
    ui->prim_ackButton->hide();
    ui->sec_enddateEdit->setReadOnly(true);
    ui->sec_enddateEdit->setButtonSymbols(QAbstractSpinBox::NoButtons);
    ui->sec_enddateButton->hide();
    ui->sec_ackButton->hide();
    ui->prim_startCEdit->setReadOnly(product->stage != PROD_STAGE_PRIMARY);
    ui->prim_startCEdit->setButtonSymbols((product->stage == PROD_STAGE_PRIMARY) ? QAbstractSpinBox::UpDownArrows : QAbstractSpinBox::NoButtons);
    ui->prim_maxCEdit->setReadOnly(product->stage != PROD_STAGE_PRIMARY);
    ui->prim_maxCEdit->setButtonSymbols((product->stage == PROD_STAGE_PRIMARY) ? QAbstractSpinBox::UpDownArrows : QAbstractSpinBox::NoButtons);
    ui->prim_endCEdit->setReadOnly(product->stage != PROD_STAGE_PRIMARY);
    ui->prim_endCEdit->setButtonSymbols((product->stage == PROD_STAGE_PRIMARY) ? QAbstractSpinBox::UpDownArrows : QAbstractSpinBox::NoButtons);
    ui->prim_endsgEdit->setReadOnly(product->stage != PROD_STAGE_PRIMARY);
    ui->prim_endsgEdit->setButtonSymbols((product->stage == PROD_STAGE_PRIMARY) ? QAbstractSpinBox::UpDownArrows : QAbstractSpinBox::NoButtons);
    if (product->stage == PROD_STAGE_PRIMARY)
	ui->prim_endsgButton->show();
    else
	ui->prim_endsgButton->hide();
    if ((product->primary_start_temp > 0) && (product->primary_max_temp > 0) && (product->primary_end_temp > 0) &&
	(product->primary_end_sg > 0.980) && (product->stage == PROD_STAGE_PRIMARY)) {
	ui->prim_enddateEdit->setReadOnly(false);
	ui->prim_enddateEdit->setButtonSymbols(QAbstractSpinBox::UpDownArrows);
	ui->prim_enddateEdit->setMinimumDate(product->brew_date_end.date());
        ui->prim_enddateEdit->setMaximumDate(QDate::currentDate());
	ui->prim_enddateButton->show();
	if (product->primary_end_date.isValid()) {
	    ui->prim_ackButton->show();
	}
    }
    ui->sec_tempEdit->setReadOnly(product->stage != PROD_STAGE_SECONDARY);
    ui->sec_tempEdit->setButtonSymbols((product->stage == PROD_STAGE_SECONDARY) ? QAbstractSpinBox::UpDownArrows : QAbstractSpinBox::NoButtons);
    ui->sec_sgEdit->setReadOnly(product->stage != PROD_STAGE_SECONDARY);
    ui->sec_sgEdit->setButtonSymbols((product->stage == PROD_STAGE_SECONDARY) ? QAbstractSpinBox::UpDownArrows : QAbstractSpinBox::NoButtons);
    if (product->stage == PROD_STAGE_SECONDARY)
        ui->sec_sgButton->show();
    else
        ui->sec_sgButton->hide();
    if ((product->secondary_end_sg > 0.980) && (product->secondary_temp > 0) && (product->stage == PROD_STAGE_SECONDARY)) {
	ui->sec_enddateEdit->setReadOnly(false);
    	ui->sec_enddateEdit->setButtonSymbols(QAbstractSpinBox::UpDownArrows);
	ui->sec_enddateEdit->setMinimumDate(product->primary_end_date.addDays(-1));	// Allow same date as primary end.
	ui->sec_enddateEdit->setMaximumDate(QDate::currentDate());
    	ui->sec_enddateButton->show();
	if (product->secondary_end_date.isValid()) {
	    ui->sec_ackButton->show();
	}
    }
    ui->tert_tempEdit->setReadOnly(product->stage != PROD_STAGE_TERTIARY);
    ui->tert_tempEdit->setButtonSymbols((product->stage == PROD_STAGE_TERTIARY) ? QAbstractSpinBox::UpDownArrows : QAbstractSpinBox::NoButtons);
    ui->tert_sgEdit->setReadOnly(product->stage != PROD_STAGE_TERTIARY);
    ui->tert_sgEdit->setButtonSymbols((product->stage == PROD_STAGE_TERTIARY) ? QAbstractSpinBox::UpDownArrows : QAbstractSpinBox::NoButtons);
    if (product->stage == PROD_STAGE_TERTIARY)
        ui->tert_sgButton->show();
    else
        ui->tert_sgButton->hide();

    /* Tab 11, packaging */
    ui->tabWidget->setTabEnabled(10, stage > PROD_STAGE_PLAN);
    bool pack = ((stage > PROD_STAGE_PLAN) && (stage <= PROD_STAGE_PACKAGE)) ? true:false;
    ui->pack_volumeEdit->setReadOnly(! pack);
    ui->pack_volumeEdit->setButtonSymbols((pack) ? QAbstractSpinBox::UpDownArrows : QAbstractSpinBox::NoButtons);
    ui->pack_phEdit->setReadOnly(! pack);
    ui->pack_phEdit->setButtonSymbols((pack) ? QAbstractSpinBox::UpDownArrows : QAbstractSpinBox::NoButtons);
    ui->pack_addvolEdit->setReadOnly(! pack);
    ui->pack_addvolEdit->setButtonSymbols((pack) ? QAbstractSpinBox::UpDownArrows : QAbstractSpinBox::NoButtons);
    ui->pack_addabvEdit->setReadOnly(! pack);
    ui->pack_addabvEdit->setButtonSymbols((pack) ? QAbstractSpinBox::UpDownArrows : QAbstractSpinBox::NoButtons);
    ui->pack_notesEdit->setReadOnly(! pack);
    ui->bottle_volumeEdit->setReadOnly(! pack);
    ui->bottle_volumeEdit->setButtonSymbols((pack) ? QAbstractSpinBox::UpDownArrows : QAbstractSpinBox::NoButtons);
    ui->bottle_carbEdit->setReadOnly(! pack);
    ui->bottle_carbEdit->setButtonSymbols((pack) ? QAbstractSpinBox::UpDownArrows : QAbstractSpinBox::NoButtons);
    ui->bottle_sugarEdit->setDisabled(! pack);
    ui->bottle_sug_waterEdit->setReadOnly(! pack);
    ui->bottle_sug_waterEdit->setButtonSymbols((pack) ? QAbstractSpinBox::UpDownArrows : QAbstractSpinBox::NoButtons);
    ui->bottle_tempEdit->setReadOnly(! pack);
    ui->bottle_tempEdit->setButtonSymbols((pack) ? QAbstractSpinBox::UpDownArrows : QAbstractSpinBox::NoButtons);
    ui->keg_volumeEdit->setReadOnly(! pack);
    ui->keg_volumeEdit->setButtonSymbols((pack) ? QAbstractSpinBox::UpDownArrows : QAbstractSpinBox::NoButtons);
    ui->keg_carbEdit->setReadOnly(! pack);
    ui->keg_carbEdit->setButtonSymbols((pack) ? QAbstractSpinBox::UpDownArrows : QAbstractSpinBox::NoButtons);
    ui->keg_sugarEdit->setDisabled(! pack);
    ui->keg_sug_waterEdit->setReadOnly(! pack);
    ui->keg_sug_waterEdit->setButtonSymbols((pack) ? QAbstractSpinBox::UpDownArrows : QAbstractSpinBox::NoButtons);
    ui->keg_tempEdit->setReadOnly(! pack);
    ui->keg_tempEdit->setButtonSymbols((pack) ? QAbstractSpinBox::UpDownArrows : QAbstractSpinBox::NoButtons);
    ui->keg_forcedEdit->setDisabled(! pack);
    ui->pack_dateEdit->setReadOnly(true);
    ui->pack_dateEdit->setButtonSymbols(QAbstractSpinBox::NoButtons);
    ui->pack_dateButton->hide();
    ui->pack_ackButton->hide();
    if (product->log_co2pressure) {
        ui->carb_logLabel->show();
        ui->carb_logButton->show();
    } else {
        ui->carb_logLabel->hide();
        ui->carb_logButton->hide();
    }
    if (((stage == PROD_STAGE_TERTIARY) || (stage == PROD_STAGE_PACKAGE)) &&
	 (product->package_volume > 1) && ((product->bottle_amount + product->keg_amount) > 1)) {
	ui->pack_dateEdit->setReadOnly(false);
        ui->pack_dateEdit->setButtonSymbols(QAbstractSpinBox::UpDownArrows);
	ui->pack_dateEdit->setMinimumDate(product->secondary_end_date.addDays(-1));     // Allow same date as secondary end.
        ui->pack_dateEdit->setMaximumDate(QDate::currentDate());
        ui->pack_dateButton->show();
	if (stage == PROD_STAGE_PACKAGE)
	    ui->pack_ackButton->show();
    }

    /* Tab 12, tasting */
    ui->tabWidget->setTabEnabled(11, stage > PROD_STAGE_PACKAGE);
    ui->taste_dateEdit->setEnabled(stage == PROD_STAGE_TASTE);
    if (stage == PROD_STAGE_TASTE) {
	ui->taste_dateEdit->setMinimumDate(product->package_date.addDays(41));
	ui->taste_dateEdit->setMaximumDate(QDate::currentDate());
    }
    ui->taste_dateButton->setEnabled(stage == PROD_STAGE_TASTE);
    ui->taste_colorEdit->setEnabled(stage == PROD_STAGE_TASTE);
    ui->taste_transparencyEdit->setEnabled(stage == PROD_STAGE_TASTE);
    ui->taste_headEdit->setEnabled(stage == PROD_STAGE_TASTE);
    ui->taste_aromaEdit->setEnabled(stage == PROD_STAGE_TASTE);
    ui->taste_tasteEdit->setEnabled(stage == PROD_STAGE_TASTE);
    ui->taste_mouthfeelEdit->setEnabled(stage == PROD_STAGE_TASTE);
    ui->taste_aftertasteEdit->setEnabled(stage == PROD_STAGE_TASTE);
    ui->taste_notesEdit->setEnabled(stage == PROD_STAGE_TASTE);
    ui->taste_rateEdit->setEnabled(stage == PROD_STAGE_TASTE);
    if ((product->taste_color != "") && (product->taste_transparency != "") && (product->taste_head != "") &&
	(product->taste_aroma != "") && (product->taste_taste != "") && (product->taste_mouthfeel != "") &&
	(product->taste_aftertaste != "") && (product->taste_notes != "") && (product->taste_rate > 0) &&
	(product->taste_date.isValid() && (stage == PROD_STAGE_TASTE)))
	ui->taste_ackButton->show();
    else
	ui->taste_ackButton->hide();
}


void EditProduct::reduce_fermentable(int i)
{
    QSqlQuery query;

    query.prepare("SELECT record,inventory FROM inventory_fermentables WHERE name=:name AND origin=:origin AND supplier=:supplier LIMIT 1");
    query.bindValue(":name", product->fermentables.at(i).name);
    query.bindValue(":origin", product->fermentables.at(i).origin);
    query.bindValue(":supplier", product->fermentables.at(i).supplier);
    query.exec();
    if (query.first()) {
	int record = query.value("record").toInt();
	double inventory = query.value("inventory").toDouble() - product->fermentables.at(i).amount;
	if (inventory < 0)
	    inventory = 0;
	else
	    inventory = round(inventory * 100000) / 100000;
	query.prepare("UPDATE inventory_fermentables SET inventory=:inventory WHERE record=:record");
	query.bindValue(":inventory", inventory );
	query.bindValue(":record", record);
	query.exec();
	if (query.lastError().isValid()) {
	    qWarning() << "UPDATE inventory_fermentables" << query.lastError();
	} else {
	    qInfo() << "  Reduced" << product->fermentables.at(i).name << "to" << inventory;
	}
    } else {
	qWarning() << "  Fermentable" << product->fermentables.at(i).name << "not found";
    }
}


void EditProduct::reduce_hop(int i)
{
    QSqlQuery query;

    query.prepare("SELECT record,inventory FROM inventory_hops WHERE name=:name AND origin=:origin AND form=:form LIMIT 1");
    query.bindValue(":name", product->hops.at(i).name);
    query.bindValue(":origin", product->hops.at(i).origin);
    query.bindValue(":form", product->hops.at(i).form);
    query.exec();
    if (query.first()) {
        int record = query.value("record").toInt();
        double inventory = query.value("inventory").toDouble() - product->hops.at(i).amount;
        if (inventory < 0)
            inventory = 0;
        else
            inventory = round(inventory * 100000) / 100000;
        query.prepare("UPDATE inventory_hops SET inventory=:inventory WHERE record=:record");
        query.bindValue(":inventory", inventory );
        query.bindValue(":record", record);
        query.exec();
        if (query.lastError().isValid()) {
            qWarning() << "UPDATE inventory_hops" << query.lastError();
        } else {
            qInfo() << "  Reduced" << product->hops.at(i).name << "to" << inventory;
        }
    } else {
        qWarning() << "  Hop" << product->hops.at(i).name << "not found";
    }
}


void EditProduct::reduce_misc(int i)
{
    QSqlQuery query;

    query.prepare("SELECT record,inventory FROM inventory_miscs WHERE name=:name LIMIT 1");
    query.bindValue(":name", product->miscs.at(i).name);
    query.exec();
    if (query.first()) {
        int record = query.value("record").toInt();
        double inventory = query.value("inventory").toDouble() - product->miscs.at(i).amount;
        if (inventory < 0)
            inventory = 0;
        else
            inventory = round(inventory * 100000) / 100000;
        query.prepare("UPDATE inventory_miscs SET inventory=:inventory WHERE record=:record");
        query.bindValue(":inventory", inventory );
        query.bindValue(":record", record);
        query.exec();
        if (query.lastError().isValid()) {
            qWarning() << "UPDATE inventory_miscs" << query.lastError();
        } else {
            qInfo() << "  Reduced" << product->miscs.at(i).name << "to" << inventory;
        }
    } else {
        qWarning() << "  Misc" << product->miscs.at(i).name << "not found";
    }
}


void EditProduct::reduce_yeast(int i)
{
    QSqlQuery query;

    query.prepare("SELECT record,inventory FROM inventory_yeasts WHERE name=:name AND laboratory=:laboratory AND product_id=:product_id AND form=:form LIMIT 1");
    query.bindValue(":name", product->yeasts.at(i).name);
    query.bindValue(":laboratory", product->yeasts.at(i).laboratory);
    query.bindValue(":product_id", product->yeasts.at(i).product_id);
    query.bindValue(":form", product->yeasts.at(i).form);
    query.exec();
    if (query.first()) {
        int record = query.value("record").toInt();
        double inventory = query.value("inventory").toDouble() - product->yeasts.at(i).amount;
        if (inventory < 0)
            inventory = 0;
        else
            inventory = round(inventory * 100000) / 100000;
        query.prepare("UPDATE inventory_yeasts SET inventory=:inventory WHERE record=:record");
        query.bindValue(":inventory", inventory );
        query.bindValue(":record", record);
        query.exec();
        if (query.lastError().isValid()) {
            qWarning() << "UPDATE inventory_yeasts" << query.lastError();
        } else {
            qInfo() << "  Reduced" << product->yeasts.at(i).name << "to" << inventory;
        }
    } else {
        qWarning() << "  Yeast" << product->yeasts.at(i).name << "not found";
    }
}


/*
 * Reduce inventory depending on the production stage.
 *  Stage PROD_STAGE_BREW+, after brew, reduce sugars(0-mash, 1-boil), hops(0-mash, 1-fwh, 2-boil, 3-aroma, 4-whirlpool), miscs(0-starter, 1-mash, 2-boil)
 *  Stage PROD_STAGE_PRIMARY+, after primary, reduce sugars(2-fermention), yeasts(0-Primary), miscs(3-primary)
 *  Stage PROD_STAGE_SECONDARY+, after secondary, reduce yeasts(1-Secondary)
 *  Stage PROD_STAGE_TERTIARY+, after tertiary, reduce sugars(3-lagering), hops(5-dry-hop), yeasts(2-Tertiary), miscs(4-secondary)
 *  Stage PROD_STAGE_PACKAGE+, after packaging, reduce sugars(4-bottle, 5-kegs), hops( Extract ), yeasts(3-Bottle), miscs(5-bottling)
 */
void EditProduct::inventory_reduce()
{
    bool savethis = false;
    QSqlQuery query;

    if (product->stage == product->inventory_reduced)
	return;

    /*
     * Nothing to reduce yet, but just set inventory reduced.
     */
    if ((product->stage >= PROD_STAGE_WAIT) && (product->inventory_reduced < PROD_STAGE_WAIT)) {
	product->inventory_reduced = PROD_STAGE_WAIT;
	savethis = true;
    }
    if ((product->stage >= PROD_STAGE_BREW) && (product->inventory_reduced < PROD_STAGE_BREW)) {
	product->inventory_reduced = PROD_STAGE_BREW;
	savethis = true;
    }

    /*
     * If the brew is done, reduce the used ingredients.
     */
    if ((product->stage >= PROD_STAGE_PRIMARY) && (product->inventory_reduced < PROD_STAGE_PRIMARY)) {
	qInfo() << "Reduce brew inventory from" << product->code << product->name;

	if (product->fermentables.size()) {
	    for (int i = 0; i < product->fermentables.size(); i++) {
		if (product->fermentables.at(i).added <= FERMENTABLE_ADDED_BOIL) {	/* Mash or boil */
		    reduce_fermentable(i);
		}
	    }
	}
	if (product->hops.size()) {
	    for (int i = 0; i < product->hops.size(); i++) {
		if (product->hops.at(i).useat <= HOP_USEAT_WHIRLPOOL) {	/* Mash, FWH, Boil, Flameout, Whirlpool */
		    reduce_hop(i);
		}
	    }
	}
	if (product->miscs.size()) {
	    for (int i = 0; i < product->miscs.size(); i++) {
		if (product->miscs.at(i).use_use <= MISC_USES_BOIL) {	/* Starter, Mash, Boil */
		    reduce_misc(i);
		}
	    }
	}
	if ((product->w1_name != "") && (product->w1_amount > 0)) {
	    query.prepare("SELECT record,inventory FROM inventory_waters WHERE name=:name AND unlimited_stock=0 LIMIT 1");
	    query.bindValue(":name", product->w1_name);
	    query.exec();
	    if (query.first()) {
		int record = query.value("record").toInt();
		double inventory = query.value("inventory").toDouble() - product->w1_amount;
	        if (inventory < 0)
        	    inventory = 0;
        	else
        	    inventory = round(inventory * 100) / 100;
        	query.prepare("UPDATE inventory_waters SET inventory=:inventory WHERE record=:record");
        	query.bindValue(":inventory", inventory );
        	query.bindValue(":record", record);
        	query.exec();
        	if (query.lastError().isValid()) {
        	    qWarning() << "UPDATE inventory_waters" << query.lastError();
        	} else {
        	    qInfo() << "  Reduced" << product->w1_name << "to" << inventory;
        	}
	    }
	}
	if ((product->w2_name != "") && (product->w2_amount > 0)) {
	    query.prepare("SELECT record,inventory FROM inventory_waters WHERE name=:name AND unlimited_stock=0 LIMIT 1");
            query.bindValue(":name", product->w1_name);
            query.exec();
            if (query.first()) {
                int record = query.value("record").toInt();
                double inventory = query.value("inventory").toDouble() - product->w1_amount;
                if (inventory < 0)
                    inventory = 0;
                else
                    inventory = round(inventory * 100) / 100;
                query.prepare("UPDATE inventory_waters SET inventory=:inventory WHERE record=:record");
                query.bindValue(":inventory", inventory );
                query.bindValue(":record", record);
                query.exec();
                if (query.lastError().isValid()) {
                    qWarning() << "UPDATE inventory_waters" << query.lastError();
                } else {
                    qInfo() << "  Reduced" << product->w1_name << "to" << inventory;
                }
            }
	}
	product->inventory_reduced = PROD_STAGE_PRIMARY;
        savethis = true;
    }

    /*
     * After the Primary fermentation
     */
    if ((product->stage >= PROD_STAGE_SECONDARY) && (product->inventory_reduced < PROD_STAGE_SECONDARY)) {
	qInfo() << "Reduce primary inventory from" << product->code << product->name;

	if (product->fermentables.size()) {
            for (int i = 0; i < product->fermentables.size(); i++) {
                if (product->fermentables.at(i).added == FERMENTABLE_ADDED_FERMENTATION) {
                    reduce_fermentable(i);
                }
            }
        }
	if (product->miscs.size()) {
            for (int i = 0; i < product->miscs.size(); i++) {
                if (product->miscs.at(i).use_use == MISC_USES_PRIMARY) {
                    reduce_misc(i);
                }
            }
        }
	if (product->yeasts.size()) {
            for (int i = 0; i < product->yeasts.size(); i++) {
                if (product->yeasts.at(i).use == YEAST_USE_PRIMARY) {
                    reduce_yeast(i);
                }
            }
        }
	product->inventory_reduced = PROD_STAGE_SECONDARY;
        savethis = true;
    }

    /*
     * After the Seconday fermentation
     */
    if ((product->stage >= PROD_STAGE_TERTIARY) && (product->inventory_reduced < PROD_STAGE_TERTIARY)) {
	qInfo() << "Reduce secondary inventory from" << product->code << product->name;

	if (product->yeasts.size()) {
            for (int i = 0; i < product->yeasts.size(); i++) {
                if (product->yeasts.at(i).use == YEAST_USE_SECONDARY) {
                    reduce_yeast(i);
                }
            }
        }
	product->inventory_reduced = PROD_STAGE_TERTIARY;
        savethis = true;
    }

    /*
     * After the Tertiary fermentation
     */
    if ((product->stage >= PROD_STAGE_PACKAGE) && (product->inventory_reduced < PROD_STAGE_PACKAGE)) {
	qInfo() << "Reduce tertiary inventory from" << product->code << product->name;

	if (product->fermentables.size()) {
            for (int i = 0; i < product->fermentables.size(); i++) {
                if (product->fermentables.at(i).added == FERMENTABLE_ADDED_LAGERING) {
                    reduce_fermentable(i);
                }
            }
        }
	if (product->hops.size()) {
            for (int i = 0; i < product->hops.size(); i++) {
                if (product->hops.at(i).useat == HOP_USEAT_DRY_HOP) {
                    reduce_hop(i);
                }
            }
        }
	if (product->miscs.size()) {
            for (int i = 0; i < product->miscs.size(); i++) {
                if (product->miscs.at(i).use_use == MISC_USES_SECONDARY) {
                    reduce_misc(i);
                }
            }
        }
        if (product->yeasts.size()) {
            for (int i = 0; i < product->yeasts.size(); i++) {
                if (product->yeasts.at(i).use == YEAST_USE_TERTIARY) {
                    reduce_yeast(i);
                }
            }
        }

	product->inventory_reduced = PROD_STAGE_PACKAGE;
        savethis = true;
    }

    /*
     * After packaging
     *  reduce sugars(4/5-bottle), yeasts(3-Bottle), miscs(5-bottling)
     */
    if ((product->stage >= PROD_STAGE_CARBONATION) && (product->inventory_reduced < PROD_STAGE_CARBONATION)) {
	qInfo() << "Reduce package inventory from" << product->code << product->name;

	if (product->fermentables.size()) {
            for (int i = 0; i < product->fermentables.size(); i++) {
                if (product->fermentables.at(i).added >= FERMENTABLE_ADDED_BOTTLE) {
                    reduce_fermentable(i);
                }
            }
        }
	if (product->yeasts.size()) {
            for (int i = 0; i < product->yeasts.size(); i++) {
                if (product->yeasts.at(i).use == YEAST_USE_BOTTLE) {
                    reduce_yeast(i);
                }
            }
        }
	if (product->hops.size()) {
            for (int i = 0; i < product->hops.size(); i++) {
                if (product->hops.at(i).useat == HOP_USEAT_BOTTLING) {
                    reduce_hop(i);
                }
            }
        }
	if (product->miscs.size()) {
            for (int i = 0; i < product->miscs.size(); i++) {
                if (product->miscs.at(i).use_use == MISC_USES_BOTTLING) {
                    reduce_misc(i);
                }
            }
        }
	product->inventory_reduced = PROD_STAGE_CARBONATION;
        savethis = true;
    }

    if ((product->stage >= PROD_STAGE_MATURE) && (product->inventory_reduced < PROD_STAGE_MATURE)) {
	product->inventory_reduced = product->stage;
	savethis = true;
    }

    /*
     * Update the inventory_reduced state.
     */
    if (savethis) {
	query.prepare("UPDATE products SET inventory_reduced=:inventory_reduced WHERE record=:record");
	query.bindValue(":record", product->record);
	query.bindValue(":inventory_reduced", product->inventory_reduced);
	query.exec();
    	if (query.lastError().isValid()) {
	    qWarning() << "UPDATE products" << query.lastError();
	}
    }
}

mercurial