src/PrinterDialog.cpp

changeset 386
2e30c9c20d22
parent 379
0f2ce4ebd1b8
child 405
2c828cc3d943
--- a/src/PrinterDialog.cpp	Mon Aug 01 13:05:23 2022 +0200
+++ b/src/PrinterDialog.cpp	Mon Aug 01 21:49:57 2022 +0200
@@ -2141,6 +2141,231 @@
 		}
 	    }
 	}
+    } else if (p_job == PR_REP_TOTAL) {
+
+	qInfo() << "Print total production";
+	printHeader(&painter);
+        y = 120;
+
+	/* Report header */
+	painter.setFont(QFont("Helvetica", 9, QFont::Bold));
+        painter.setPen(Qt::black);
+        painter.fillRect( 20, y,   540, 20, c_header);
+	painter.drawText( 20, y+4,  80, 20, Qt::AlignHCenter, tr("Number"));
+	painter.drawText(100, y+4,  80, 20, Qt::AlignHCenter, tr("Year"));
+	painter.drawText(180, y+4, 120, 20, Qt::AlignRight, tr("Brew sessions"));
+	painter.drawText(300, y+4, 120, 20, Qt::AlignRight, tr("Brew volume"));
+	painter.drawText(420, y+4, 120, 20, Qt::AlignRight, tr("Average volume"));
+	y += 20;
+	painter.setFont(QFont("Helvetica", 9, QFont::Normal));
+	query.exec("SELECT DISTINCT YEAR(package_date) FROM products WHERE package_date ORDER BY package_date");
+	query.first();
+	int regel = 0, brews = 0, total = 0;
+	double packaged = 0, tvolume = 0, average;
+	QString year = "";
+	for (int i = 0 ; i < query.size() ; i++ ) {
+	    if ((y + 20) > painter.device()->height()) {
+                printer->newPage();
+                printHeader(&painter);
+                y = 120;
+            }
+
+	    brews = 0;
+	    packaged = 0;
+	    regel++;
+	    year = query.value(0).toString();
+	    QSqlQuery query2;
+	    query2.exec("SELECT package_volume FROM products WHERE package_date AND YEAR(package_date) = '" + year + "'");
+	    while (query2.next()) {
+		brews++;
+		total++;
+		packaged += query2.value(0).toDouble();
+		tvolume += query2.value(0).toDouble();
+	    }
+	    average = packaged / brews;
+	    painter.fillRect( 20, y,   540, 20, (i % 2) ? c_line1:c_line2);
+	    painter.drawText( 20, y+4,  80, 20, Qt::AlignCenter, QString("%1").arg(regel));
+            painter.drawText(100, y+4, 100, 20, Qt::AlignCenter, year);
+	    painter.drawText(180, y+4, 120, 20, Qt::AlignRight, QString("%1").arg(brews));
+	    painter.drawText(300, y+4, 120, 20, Qt::AlignRight, QString("%1 L").arg(packaged, 2, 'f', 1, '0'));
+	    painter.drawText(420, y+4, 120, 20, Qt::AlignRight, QString("%1 L").arg(average, 2, 'f', 1, '0'));
+	    query.next();
+            y += 20;
+	}
+	average = tvolume / total;
+	painter.fillRect(180, y,   360, 20, w_line);
+	painter.drawText(180, y+4, 120, 20, Qt::AlignRight, QString("%1").arg(total));
+	painter.drawText(300, y+4, 120, 20, Qt::AlignRight, QString("%1 L").arg(tvolume, 2, 'f', 1, '0'));
+	painter.drawText(420, y+4, 120, 20, Qt::AlignRight, QString("%1 L").arg(average, 2, 'f', 1, '0'));
+	y += 20;
+
+    } else if (p_job == PR_REP_EFF) {
+
+	qInfo() << "Print efficiency";
+        y = painter.device()->height() + 100;
+
+	query.exec("SELECT * FROM products WHERE package_date AND type='2' ORDER BY code");
+	query.first();
+	for (int i = 0 ; i < query.size() ; i++ ) {
+            if ((y + 20) > painter.device()->height()) {
+		if (i > 0)
+                    printer->newPage();
+                printHeader(&painter);
+                y = 120;
+
+		/* Report header */
+        	painter.setFont(QFont("Helvetica", 9, QFont::Bold));
+        	painter.setPen(Qt::black);
+        	painter.fillRect( 20, y,   715, 20, c_header);
+        	painter.drawText( 25, y+4,  65, 20, Qt::AlignLeft, tr("Code"));
+        	painter.drawText( 90, y+4, 200, 20, Qt::AlignLeft, tr("Name"));
+        	painter.drawText(290, y+4, 120, 20, Qt::AlignLeft, tr("Beer style"));
+        	painter.drawText(410, y+4,  80, 20, Qt::AlignRight, tr("Max extract"));
+        	painter.drawText(490, y+4,  80, 20, Qt::AlignRight, tr("Mash eff."));
+        	painter.drawText(570, y+4,  80, 20, Qt::AlignRight, tr("Sparge eff"));
+        	painter.drawText(650, y+4,  80, 20, Qt::AlignRight, tr("Boil eff"));
+        	y += 20;
+        	painter.setFont(QFont("Helvetica", 9, QFont::Normal));
+            }
+
+	    /*
+	     * Data is not always available, calculate the missing pieces.
+	     */
+	    double mvol = 0, msugars = 0, ssugars = 0;
+	    QJsonParseError parseError;
+
+	    const auto& ma_json = query.value("json_mashs").toString().trimmed();
+	    if (!ma_json.trimmed().isEmpty()) {
+		const auto& formattedJson = QString("%1").arg(ma_json);
+		QJsonDocument mashs = QJsonDocument::fromJson(formattedJson.toUtf8(),  &parseError);
+		if (parseError.error != QJsonParseError::NoError) {
+		    qWarning() << "Parse error: " << parseError.errorString() << "at" << parseError.offset ;
+		} else if (mashs.isArray()) {
+		    for (int j = 0; j < mashs.array().size(); j++) {
+			QJsonObject obj = mashs.array().at(j).toObject();
+			if (obj["step_type"].toInt() == 0)
+			    mvol += obj["step_infuse_amount"].toDouble();
+		    }
+		}
+	    }
+
+	    const auto& f_json = query.value("json_fermentables").toString();
+	    if (!f_json.trimmed().isEmpty()) {
+		const auto& formattedJson = QString("%1").arg(f_json);
+		QJsonDocument fermentables = QJsonDocument::fromJson(formattedJson.toUtf8(),  &parseError);
+		if (parseError.error != QJsonParseError::NoError) {
+		    qWarning() << "Parse error: " << parseError.errorString() << "at" << parseError.offset ;
+		} else if (fermentables.isArray()) {
+		    for (int j = 0; j < fermentables.array().size(); j++) {
+			QJsonObject obj = fermentables.array().at(j).toObject();
+			if (obj["f_added"].toInt() == 0) {
+			    double d = obj["f_amount"].toDouble() * (obj["f_yield"].toDouble() / 100) * (1 - obj["f_moisture"].toDouble() / 100);
+			    ssugars += obj["f_amount"].toDouble();
+			    mvol += obj["f_amount"].toDouble() * obj["f_moisture"].toDouble() / 100;
+			    msugars += d;
+			}
+		    }
+		}
+	    }
+
+	    double sugardensity = 1.611;
+	    double v = msugars / sugardensity + mvol;
+	    double plato = 1000 * msugars / (v * 10);	// deg. Plato
+	    double mash_efficiency = query.value("brew_mash_efficiency").toDouble();
+	    double mash_sg = query.value("brew_mash_sg").toDouble();
+	    if ((mash_efficiency == 0) && (mash_sg > 1)) {
+		mash_efficiency = 100 * Utils::sg_to_plato(mash_sg) / plato;
+	    }
+	    double mash_extract = 100 * msugars / ssugars;
+	    double preboil_sg = query.value("brew_preboil_sg").toDouble();
+	    double preboil_volume = query.value("brew_preboil_volume").toDouble();
+	    double est_preboil_plato = Utils::sg_to_plato(preboil_sg) * (preboil_volume / 1.04) * preboil_sg * 10 / 1000;
+	    double preboil_efficiency = query.value("brew_preboil_efficiency").toDouble();
+	    if ((msugars > 0) && (preboil_efficiency == 0))
+		preboil_efficiency = est_preboil_plato / msugars * 100;
+	    if (preboil_efficiency < 0)
+		preboil_efficiency = 0;
+	    double aboil_efficiency = query.value("brew_aboil_efficiency").toDouble();
+
+	    painter.fillRect( 20, y,   715, 20, (i % 2) ? c_line1:c_line2);
+	    painter.drawText( 25, y+4,  65, 20, Qt::AlignLeft, query.value("code").toString());
+	    painter.drawText( 90, y+4, 200, 20, Qt::AlignLeft, query.value("name").toString());
+	    painter.drawText(290, y+4, 120, 20, Qt::AlignLeft, query.value("st_name").toString());
+	    painter.drawText(410, y+4,  80, 20, Qt::AlignRight, QString("%1%").arg(mash_extract, 2, 'f', 1, '0'));
+	    painter.drawText(490, y+4,  80, 20, Qt::AlignRight, QString("%1%").arg(mash_efficiency, 2, 'f', 1, '0'));
+	    painter.drawText(570, y+4,  80, 20, Qt::AlignRight, QString("%1%").arg(preboil_efficiency, 2, 'f', 1, '0'));
+	    painter.drawText(650, y+4,  80, 20, Qt::AlignRight, QString("%1%").arg(aboil_efficiency, 2, 'f', 1, '0'));
+	    query.next();
+	    y += 20;
+	}
+
+    } else if (p_job == PR_REP_SVG) {
+
+	qInfo() << "Print fermentations";
+	y = painter.device()->height() + 100;
+	QString y_name, y_lab, y_product;
+
+	/*
+	 * Works from MariaDB 10.6.x and later, MySQL 8.x and later.
+	 * Pick the first yeast record, that should be the one used for primary.
+	 */
+	query.exec("SELECT code,name,brew_date_end,primary_end_temp,primary_end_date,secondary_temp,secondary_end_date,tertiary_temp,"
+			"package_date,brew_fermenter_sg,fg,json_yeasts,"
+		      	"JSON_EXTRACT(json_yeasts, '$[0].y_laboratory') AS yeastLab,JSON_EXTRACT(json_yeasts, '$[0].y_product_id') AS yeastID "	
+			"FROM products WHERE package_date AND type='2' ORDER BY yeastID");
+	query.first();
+
+	for (int i = 0 ; i < query.size() ; i++ ) {
+            if ((y + 20) > painter.device()->height()) {
+		if (i > 0)
+                    printer->newPage();
+                printHeader(&painter);
+                y = 120;
+
+		/* Report header */
+        	painter.setFont(QFont("Helvetica", 9, QFont::Bold));
+        	painter.setPen(Qt::black);
+        	painter.fillRect( 20, y,   715, 20, c_header);
+        	painter.drawText( 25, y+4,  65, 20, Qt::AlignLeft, tr("Code"));
+        	painter.drawText( 90, y+4, 180, 20, Qt::AlignLeft, tr("Name"));
+        	painter.drawText(270, y+4, 110, 20, Qt::AlignLeft, tr("Yeast"));
+        	painter.drawText(380, y+4,  60, 20, Qt::AlignHCenter, tr("Primary"));
+        	painter.drawText(440, y+4,  60, 20, Qt::AlignHCenter, tr("Secondary"));
+        	painter.drawText(500, y+4,  60, 20, Qt::AlignHCenter, tr("Tertiary"));
+		painter.drawText(560, y+4,  40, 20, Qt::AlignRight, tr("Days"));
+		painter.drawText(600, y+4,  40, 20, Qt::AlignRight, tr("OG"));
+		painter.drawText(640, y+4,  40, 20, Qt::AlignRight, tr("FG"));
+        	painter.drawText(680, y+4,  50, 20, Qt::AlignRight, tr("AA"));
+        	y += 20;
+        	painter.setFont(QFont("Helvetica", 9, QFont::Normal));
+            }
+
+	    int primary = query.value("brew_date_end").toDate().daysTo(query.value("primary_end_date").toDate());
+	    int secondary = query.value("primary_end_date").toDate().daysTo(query.value("secondary_end_date").toDate());
+	    int tertiary = query.value("secondary_end_date").toDate().daysTo(query.value("package_date").toDate());
+	    int total = query.value("brew_date_end").toDate().daysTo(query.value("package_date").toDate());
+	    double og = query.value("brew_fermenter_sg").toDouble();
+	    double fg = query.value("fg").toDouble();
+	    double aa = Utils::calc_svg(og, fg);
+
+	    painter.fillRect( 20, y,   715, 20, (i % 2) ? c_line1:c_line2);
+	    painter.drawText( 25, y+4,  65, 20, Qt::AlignLeft, query.value("code").toString());
+            painter.drawText( 90, y+4, 180, 20, Qt::AlignLeft, query.value("name").toString());
+	    painter.drawText(270, y+4, 110, 20, Qt::AlignLeft, query.value("yeastID").toString() + " " + query.value("yeastLab").toString());
+	    painter.drawText(380, y+4,  40, 20, Qt::AlignRight, QString("%1°").arg(query.value("primary_end_temp").toDouble(), 2, 'f', 1));
+            painter.drawText(420, y+4,  20, 20, Qt::AlignRight, QString("%1").arg(primary));
+	    painter.drawText(440, y+4,  40, 20, Qt::AlignRight, QString("%1°").arg(query.value("secondary_temp").toDouble(), 2, 'f', 1));
+            painter.drawText(480, y+4,  20, 20, Qt::AlignRight, QString("%1").arg(secondary));
+	    painter.drawText(500, y+4,  40, 20, Qt::AlignRight, QString("%1°").arg(query.value("tertiary_temp").toDouble(), 2, 'f', 1));
+	    painter.drawText(540, y+4,  20, 20, Qt::AlignRight, QString("%1").arg(tertiary));
+	    painter.drawText(560, y+4,  40, 20, Qt::AlignRight, QString("%1").arg(total));
+	    painter.drawText(600, y+4,  40, 20, Qt::AlignRight, QString("%1").arg(og, 4, 'f', 3, '0'));
+	    painter.drawText(640, y+4,  40, 20, Qt::AlignRight, QString("%1").arg(fg, 4, 'f', 3, '0'));
+	    painter.drawText(680, y+4,  50, 20, Qt::AlignRight, QString("%1%").arg(aa, 2, 'f', 1, '0'));
+
+	    query.next();
+            y += 20;
+	}
     }
 
     painter.end();
@@ -2232,6 +2457,12 @@
 	painter->drawText(140, 0,  500, 40, Qt::AlignLeft, recipe->name);
     } else if (p_job == PR_PRODUCT || p_job == PR_CHECKLIST) {
         painter->drawText(140, 0,  500, 40, Qt::AlignLeft, product->code + "  " + product->name);
+    } else if (p_job == PR_REP_TOTAL) {
+	painter->drawText(140, 0,  500, 40, Qt::AlignLeft, tr("Year production") + " " + my_brewery_name);
+    } else if (p_job == PR_REP_EFF) {
+	painter->drawText(140, 0,  500, 40, Qt::AlignLeft, tr("Brew efficiency") + " " + my_brewery_name);
+    } else if (p_job == PR_REP_SVG) {
+	painter->drawText(140, 0,  500, 40, Qt::AlignLeft, tr("Fermentations") + " " + my_brewery_name);
     } else {
         painter->drawText(140, 0,  500, 40, Qt::AlignLeft, "?? " + my_brewery_name);
     }

mercurial