Added reduce inventory for all process stages. Added block fermentable to block buttons and inventory when the fermentable has been reduced. Added block hop to block buttons and inventory when the fermentable has been reduced. Added block misc to block buttons and inventory when the fermentable has been reduced. Added block yeast to block buttons and inventory when the fermentable has been reduced.

Thu, 23 Jun 2022 16:50:23 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Thu, 23 Jun 2022 16:50:23 +0200
changeset 305
35ce719998e1
parent 304
aa8d421bfc24
child 306
d45c502ce77f

Added reduce inventory for all process stages. Added block fermentable to block buttons and inventory when the fermentable has been reduced. Added block hop to block buttons and inventory when the fermentable has been reduced. Added block misc to block buttons and inventory when the fermentable has been reduced. Added block yeast to block buttons and inventory when the fermentable has been reduced.

src/EditProduct.cpp file | annotate | diff | comparison | revisions
src/EditProduct.h file | annotate | diff | comparison | revisions
src/EditProductTab1.cpp file | annotate | diff | comparison | revisions
src/EditProductTab3.cpp file | annotate | diff | comparison | revisions
src/EditProductTab4.cpp file | annotate | diff | comparison | revisions
src/EditProductTab5.cpp file | annotate | diff | comparison | revisions
src/EditProductTab6.cpp file | annotate | diff | comparison | revisions
--- a/src/EditProduct.cpp	Tue Jun 21 16:16:43 2022 +0200
+++ b/src/EditProduct.cpp	Thu Jun 23 16:50:23 2022 +0200
@@ -819,6 +819,7 @@
 	     */
 	    this->recno = product->record;
 	}
+	inventory_reduce();
     }
 
     ui->saveButton->setEnabled(false);
--- a/src/EditProduct.h	Tue Jun 21 16:16:43 2022 +0200
+++ b/src/EditProduct.h	Thu Jun 23 16:50:23 2022 +0200
@@ -323,6 +323,15 @@
     void toforumProduct();
     void splitProduct();
     void split_show();
+    void reduce_fermentable(int i);
+    void reduce_hop(int i);
+    void reduce_misc(int i);
+    void reduce_yeast(int i);
+    void inventory_reduce();
+    bool block_fermentable(int stage, int added);
+    bool block_hop(int stage, int useat);
+    bool block_misc(int stage, int use_use);
+    bool block_yeast(int stage, int use);
 };
 
 #endif
--- a/src/EditProductTab1.cpp	Tue Jun 21 16:16:43 2022 +0200
+++ b/src/EditProductTab1.cpp	Thu Jun 23 16:50:23 2022 +0200
@@ -608,3 +608,375 @@
 }
 
 
+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();
+	}
+    }
+}
+
+
--- a/src/EditProductTab3.cpp	Tue Jun 21 16:16:43 2022 +0200
+++ b/src/EditProductTab3.cpp	Thu Jun 23 16:50:23 2022 +0200
@@ -47,6 +47,20 @@
 }
 
 
+bool EditProduct::block_fermentable(int stage, int added)
+{
+    if (stage > PROD_STAGE_PACKAGE)
+	return true;
+    if (stage > PROD_STAGE_TERTIARY && added < FERMENTABLE_ADDED_BOTTLE)
+	return true;
+    if (stage > PROD_STAGE_PRIMARY && added < FERMENTABLE_ADDED_LAGERING)
+	return true;
+    if (stage > PROD_STAGE_BREW && added < FERMENTABLE_ADDED_FERMENTATION)
+	return true;
+    return false;
+}
+
+
 void EditProduct::refreshFermentables()
 {
     QString w;
@@ -107,10 +121,14 @@
         item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
         ui->fermentablesTable->setItem(i, 7, item);
 
-	item = new QTableWidgetItem(QString("%1 Kg").arg(product->fermentables.at(i).inventory, 4, 'f', 3, '0'));
-        item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
-	if (product->fermentables.at(i).inventory < product->fermentables.at(i).amount)
-	    item->setForeground(QBrush(QColor(Qt::red)));
+	if (block_fermentable(product->stage, product->fermentables.at(i).added)) {
+	    item = new QTableWidgetItem(QString(""));
+	} else {
+	    item = new QTableWidgetItem(QString("%1 Kg").arg(product->fermentables.at(i).inventory, 4, 'f', 3, '0'));
+            item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+	    if (product->fermentables.at(i).inventory < product->fermentables.at(i).amount)
+	    	item->setForeground(QBrush(QColor(Qt::red)));
+	}
         ui->fermentablesTable->setItem(i, 8, item);
 
 	if (product->fermentables.at(i).added < FERMENTABLE_ADDED_BOTTLE) {
@@ -123,8 +141,22 @@
 
 	to100Fermentables(i);
 
-	/* Add the Delete row button */
-	if (product->fermentables.at(i).added < FERMENTABLE_ADDED_BOTTLE) {
+	/* Add the Delete and Edit row buttons if allowed. */
+	if (product->fermentables.at(i).added >= FERMENTABLE_ADDED_BOTTLE) {
+	    item = new QTableWidgetItem("");
+            item->setToolTip(tr("Edit this from the package tab"));
+            ui->fermentablesTable->setItem(i, 11, item);
+            item = new QTableWidgetItem("");
+            item->setToolTip(tr("Edit this from the package tab"));
+            ui->fermentablesTable->setItem(i, 12, item);
+	} else if (block_fermentable(product->stage, product->fermentables.at(i).added)) {
+	    item = new QTableWidgetItem("");
+            item->setToolTip(tr("Fermentable already used"));
+            ui->fermentablesTable->setItem(i, 11, item);
+            item = new QTableWidgetItem("");
+            item->setToolTip(tr("Fermentable already used"));
+            ui->fermentablesTable->setItem(i, 12, item);
+	} else {
             pWidget = new QWidget();
             QPushButton* btn_dele = new QPushButton();
             btn_dele->setObjectName(QString("%1").arg(i));  /* Send row with the button */
@@ -146,13 +178,6 @@
 	    pLayout->setContentsMargins(5, 0, 5, 0);
             pWidget->setLayout(pLayout);
             ui->fermentablesTable->setCellWidget(i, 12, pWidget);
-	} else {
-	    item = new QTableWidgetItem("");
-	    item->setToolTip(tr("Edit this from the package tab"));
-            ui->fermentablesTable->setItem(i, 11, item);
-	    item = new QTableWidgetItem("");
-            item->setToolTip(tr("Edit this from the package tab"));
-            ui->fermentablesTable->setItem(i, 12, item);
 	}
     }
 }
--- a/src/EditProductTab4.cpp	Tue Jun 21 16:16:43 2022 +0200
+++ b/src/EditProductTab4.cpp	Thu Jun 23 16:50:23 2022 +0200
@@ -35,6 +35,14 @@
 }
 
 
+bool EditProduct::block_hop(int stage, int useat)
+{
+    if (stage > PROD_STAGE_BREW && useat < HOP_USEAT_DRY_HOP)
+	return true;
+    return false;
+}
+
+
 void EditProduct::refreshHops()
 {
     QString w;
@@ -111,38 +119,51 @@
         item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
         ui->hopsTable->setItem(i, 8, item);
 
-	if (product->hops.at(i).inventory < 1.0) {
-            item = new QTableWidgetItem(QString("%1 gr").arg(product->hops.at(i).inventory * 1000.0, 2, 'f', 1, '0'));
-        } else {
-            item = new QTableWidgetItem(QString("%1 kg").arg(product->hops.at(i).inventory, 4, 'f', 3, '0'));
-        }
-        item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
-	if (product->hops.at(i).inventory < product->hops.at(i).amount)
-	    item->setForeground(QBrush(QColor(Qt::red)));
+	if (block_hop(product->stage, product->hops.at(i).useat)) {
+	    item = new QTableWidgetItem(QString(""));
+	} else {
+	    if (product->hops.at(i).inventory < 1.0) {
+            	item = new QTableWidgetItem(QString("%1 gr").arg(product->hops.at(i).inventory * 1000.0, 2, 'f', 1, '0'));
+            } else {
+            	item = new QTableWidgetItem(QString("%1 kg").arg(product->hops.at(i).inventory, 4, 'f', 3, '0'));
+            }
+            item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+	    if (product->hops.at(i).inventory < product->hops.at(i).amount)
+	    	item->setForeground(QBrush(QColor(Qt::red)));
+	}
         ui->hopsTable->setItem(i, 9, item);
 
 	/* Add the Delete row button */
-        pWidget = new QWidget();
-        QPushButton* btn_dele = new QPushButton();
-        btn_dele->setObjectName(QString("%1").arg(i));  /* Send row with the button */
-        btn_dele->setText(tr("Delete"));
-        connect(btn_dele, SIGNAL(clicked()), this, SLOT(deleteHopRow_clicked()));
-        pLayout = new QHBoxLayout(pWidget);
-        pLayout->addWidget(btn_dele);
-        pLayout->setContentsMargins(5, 0, 5, 0);
-        pWidget->setLayout(pLayout);
-        ui->hopsTable->setCellWidget(i, 10, pWidget);
+	if (block_hop(product->stage, product->hops.at(i).useat)) {
+	    item = new QTableWidgetItem("");
+            item->setToolTip(tr("Hop already used"));
+            ui->hopsTable->setItem(i, 10, item);
+            item = new QTableWidgetItem("");
+            item->setToolTip(tr("Hop already used"));
+            ui->hopsTable->setItem(i, 11, item);
+	} else {
+            pWidget = new QWidget();
+            QPushButton* btn_dele = new QPushButton();
+            btn_dele->setObjectName(QString("%1").arg(i));  /* Send row with the button */
+            btn_dele->setText(tr("Delete"));
+            connect(btn_dele, SIGNAL(clicked()), this, SLOT(deleteHopRow_clicked()));
+            pLayout = new QHBoxLayout(pWidget);
+            pLayout->addWidget(btn_dele);
+            pLayout->setContentsMargins(5, 0, 5, 0);
+            pWidget->setLayout(pLayout);
+            ui->hopsTable->setCellWidget(i, 10, pWidget);
 
-        pWidget = new QWidget();
-        QPushButton* btn_edit = new QPushButton();
-        btn_edit->setObjectName(QString("%1").arg(i));  /* Send row with the button */
-        btn_edit->setText(tr("Edit"));
-        connect(btn_edit, SIGNAL(clicked()), this, SLOT(editHopRow_clicked()));
-        pLayout = new QHBoxLayout(pWidget);
-        pLayout->addWidget(btn_edit);
-        pLayout->setContentsMargins(5, 0, 5, 0);
-        pWidget->setLayout(pLayout);
-        ui->hopsTable->setCellWidget(i, 11, pWidget);
+            pWidget = new QWidget();
+            QPushButton* btn_edit = new QPushButton();
+            btn_edit->setObjectName(QString("%1").arg(i));  /* Send row with the button */
+            btn_edit->setText(tr("Edit"));
+            connect(btn_edit, SIGNAL(clicked()), this, SLOT(editHopRow_clicked()));
+            pLayout = new QHBoxLayout(pWidget);
+            pLayout->addWidget(btn_edit);
+            pLayout->setContentsMargins(5, 0, 5, 0);
+            pWidget->setLayout(pLayout);
+            ui->hopsTable->setCellWidget(i, 11, pWidget);
+	}
     }
 }
 
--- a/src/EditProductTab5.cpp	Tue Jun 21 16:16:43 2022 +0200
+++ b/src/EditProductTab5.cpp	Thu Jun 23 16:50:23 2022 +0200
@@ -32,6 +32,20 @@
 }
 
 
+bool EditProduct::block_misc(int stage, int use_use)
+{
+    if (stage > PROD_STAGE_TERTIARY && use_use < MISC_USES_BOTTLING)
+	return true;
+    if (stage > PROD_STAGE_PRIMARY && use_use < MISC_USES_SECONDARY)
+	return true;
+    if (stage > PROD_STAGE_BREW && use_use < MISC_USES_PRIMARY)
+	return true;
+    if (stage > PROD_STAGE_WAIT && use_use < MISC_USES_MASH)
+	return true;
+    return false;
+}
+
+
 void EditProduct::refreshMiscs()
 {
     QString w;
@@ -96,18 +110,23 @@
 	item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
         ui->miscsTable->setItem(i, 4, item);
 
-	if (product->miscs.at(i).amount_is_weight)
-            item = new QTableWidgetItem(QString("%1 gr").arg(product->miscs.at(i).inventory * 1000.0, 3, 'f', 2, '0'));
-        else
-            item = new QTableWidgetItem(QString("%1 ml").arg(product->miscs.at(i).inventory * 1000.0, 3, 'f', 2, '0'));
-        item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
-	if (product->miscs.at(i).inventory < product->miscs.at(i).amount)
-            item->setForeground(QBrush(QColor(Qt::red)));
+	if (block_misc(product->stage, product->miscs.at(i).use_use)) {
+	    item = new QTableWidgetItem(QString(""));
+	} else {
+	    if (product->miscs.at(i).amount_is_weight)
+            	item = new QTableWidgetItem(QString("%1 gr").arg(product->miscs.at(i).inventory * 1000.0, 3, 'f', 2, '0'));
+            else
+            	item = new QTableWidgetItem(QString("%1 ml").arg(product->miscs.at(i).inventory * 1000.0, 3, 'f', 2, '0'));
+            item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+	    if (product->miscs.at(i).inventory < product->miscs.at(i).amount)
+            	item->setForeground(QBrush(QColor(Qt::red)));
+	}
         ui->miscsTable->setItem(i, 5, item);
 
 	/*
 	 * Add the Delete and Edit row buttons.
 	 * Not for water agents, these are set on the water tab.
+	 * And also not if the ingredient has been used.
 	 */
 	if (product->miscs.at(i).type == MISC_TYPES_WATER_AGENT) {
 	    ui->miscsTable->removeCellWidget(i, 6);	/* to remove the unneeded button */
@@ -118,6 +137,15 @@
             item = new QTableWidgetItem("");
             item->setToolTip(tr("Edit this from the water tab"));
             ui->miscsTable->setItem(i, 7, item);
+	} else if (block_misc(product->stage, product->miscs.at(i).use_use)) {
+	    ui->miscsTable->removeCellWidget(i, 6);     /* to remove the unneeded button */
+            item = new QTableWidgetItem("");
+            item->setToolTip(tr("Misc already used"));
+            ui->miscsTable->setItem(i, 6, item);
+            ui->miscsTable->removeCellWidget(i, 7);
+            item = new QTableWidgetItem("");
+            item->setToolTip(tr("Misc already used"));
+            ui->miscsTable->setItem(i, 7, item);
 	} else {
 	    if (ui->miscsTable->item(i, 6)) {
 		ui->miscsTable->takeItem(i, 6);		/* to remove the old tooltip */
--- a/src/EditProductTab6.cpp	Tue Jun 21 16:16:43 2022 +0200
+++ b/src/EditProductTab6.cpp	Thu Jun 23 16:50:23 2022 +0200
@@ -28,6 +28,20 @@
 }
 
 
+bool EditProduct::block_yeast(int stage, int use)
+{
+    if (stage > PROD_STAGE_PRIMARY && use < YEAST_USE_SECONDARY)
+	return true;
+    if (stage > PROD_STAGE_SECONDARY && use < YEAST_USE_TERTIARY)
+	return true;
+    if (stage > PROD_STAGE_TERTIARY && use < YEAST_USE_BOTTLE)
+	return true;
+    if (stage > PROD_STAGE_PACKAGE)
+	return true;
+    return false;
+}
+
+
 void EditProduct::refreshYeasts()
 {
     QString w;
@@ -98,38 +112,53 @@
         item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
         ui->yeastsTable->setItem(i, 9, item);
 
-	if (product->yeasts.at(i).form == YEAST_FORMS_LIQUID)
-            item = new QTableWidgetItem(QString("%1 pack").arg(product->yeasts.at(i).inventory, 1, 'f', 0, '0'));
-        else if (product->yeasts.at(i).form == YEAST_FORMS_DRY || product->yeasts.at(i).form == YEAST_FORMS_DRIED)
-            item = new QTableWidgetItem(QString("%1 gr").arg(product->yeasts.at(i).inventory * 1000.0, 3, 'f', 2, '0'));
-        else
-            item = new QTableWidgetItem(QString("%1 ml").arg(product->yeasts.at(i).inventory * 1000.0, 3, 'f', 2, '0'));
-        item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
-	if (product->yeasts.at(i).inventory < product->yeasts.at(i).amount)
-	    item->setForeground(QBrush(QColor(Qt::red)));
+	if (block_yeast(product->stage, product->yeasts.at(i).use)) {
+	    item = new QTableWidgetItem(QString(""));
+	} else {
+	    if (product->yeasts.at(i).form == YEAST_FORMS_LIQUID)
+            	item = new QTableWidgetItem(QString("%1 pack").arg(product->yeasts.at(i).inventory, 1, 'f', 0, '0'));
+            else if (product->yeasts.at(i).form == YEAST_FORMS_DRY || product->yeasts.at(i).form == YEAST_FORMS_DRIED)
+            	item = new QTableWidgetItem(QString("%1 gr").arg(product->yeasts.at(i).inventory * 1000.0, 3, 'f', 2, '0'));
+            else
+            	item = new QTableWidgetItem(QString("%1 ml").arg(product->yeasts.at(i).inventory * 1000.0, 3, 'f', 2, '0'));
+            item->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
+	    if (product->yeasts.at(i).inventory < product->yeasts.at(i).amount)
+	    	item->setForeground(QBrush(QColor(Qt::red)));
+	}
         ui->yeastsTable->setItem(i, 10, item);
 
-	pWidget = new QWidget();
-        QPushButton* btn_dele = new QPushButton();
-        btn_dele->setObjectName(QString("%1").arg(i));  /* Send row with the button */
-        btn_dele->setText(tr("Delete"));
-        connect(btn_dele, SIGNAL(clicked()), this, SLOT(deleteYeastRow_clicked()));
-        pLayout = new QHBoxLayout(pWidget);
-        pLayout->addWidget(btn_dele);
-        pLayout->setContentsMargins(5, 0, 5, 0);
-        pWidget->setLayout(pLayout);
-        ui->yeastsTable->setCellWidget(i, 11, pWidget);
+	if (block_yeast(product->stage, product->yeasts.at(i).use)) {
+	    ui->yeastsTable->removeCellWidget(i, 11);     /* to remove the unneeded button */
+            item = new QTableWidgetItem("");
+            item->setToolTip(tr("Yeast already used"));
+            ui->yeastsTable->setItem(i, 11, item);
+            ui->yeastsTable->removeCellWidget(i, 12);
+            item = new QTableWidgetItem("");
+            item->setToolTip(tr("Yeast already used"));
+            ui->yeastsTable->setItem(i, 12, item);
+	} else {
+	    pWidget = new QWidget();
+            QPushButton* btn_dele = new QPushButton();
+            btn_dele->setObjectName(QString("%1").arg(i));  /* Send row with the button */
+            btn_dele->setText(tr("Delete"));
+            connect(btn_dele, SIGNAL(clicked()), this, SLOT(deleteYeastRow_clicked()));
+            pLayout = new QHBoxLayout(pWidget);
+            pLayout->addWidget(btn_dele);
+            pLayout->setContentsMargins(5, 0, 5, 0);
+            pWidget->setLayout(pLayout);
+            ui->yeastsTable->setCellWidget(i, 11, pWidget);
 
-        pWidget = new QWidget();
-        QPushButton* btn_edit = new QPushButton();
-        btn_edit->setObjectName(QString("%1").arg(i));  /* Send row with the button */
-        btn_edit->setText(tr("Edit"));
-        connect(btn_edit, SIGNAL(clicked()), this, SLOT(editYeastRow_clicked()));
-        pLayout = new QHBoxLayout(pWidget);
-        pLayout->addWidget(btn_edit);
-        pLayout->setContentsMargins(5, 0, 5, 0);
-        pWidget->setLayout(pLayout);
-        ui->yeastsTable->setCellWidget(i, 12, pWidget);
+            pWidget = new QWidget();
+            QPushButton* btn_edit = new QPushButton();
+            btn_edit->setObjectName(QString("%1").arg(i));  /* Send row with the button */
+            btn_edit->setText(tr("Edit"));
+            connect(btn_edit, SIGNAL(clicked()), this, SLOT(editYeastRow_clicked()));
+            pLayout = new QHBoxLayout(pWidget);
+            pLayout->addWidget(btn_edit);
+            pLayout->setContentsMargins(5, 0, 5, 0);
+            pWidget->setLayout(pLayout);
+            ui->yeastsTable->setCellWidget(i, 12, pWidget);
+	}
     }
 }
 

mercurial