Split the checklist out of prod_print.php into prod_checklist.php

Wed, 05 Jun 2019 15:12:14 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Wed, 05 Jun 2019 15:12:14 +0200
changeset 398
7e8f1a7ddeeb
parent 397
d3d2b277075b
child 399
6f1cde4215d3

Split the checklist out of prod_print.php into prod_checklist.php

README.design file | annotate | diff | comparison | revisions
www/Makefile file | annotate | diff | comparison | revisions
www/js/prod_export.js file | annotate | diff | comparison | revisions
www/prod_checklist.php file | annotate | diff | comparison | revisions
www/prod_export.php file | annotate | diff | comparison | revisions
www/prod_print.php file | annotate | diff | comparison | revisions
--- a/README.design	Tue Jun 04 19:51:40 2019 +0200
+++ b/README.design	Wed Jun 05 15:12:14 2019 +0200
@@ -22,5 +22,3 @@
 
 Koolzuurdruk tabel inbouwen.
 
-Fix grid popup edit updates in products and recipes.
-Also miscs during fermentation cannot have a time value.
--- a/www/Makefile	Tue Jun 04 19:51:40 2019 +0200
+++ b/www/Makefile	Wed Jun 05 15:12:14 2019 +0200
@@ -12,8 +12,8 @@
 		  log_brew.php log_fermentation.php \
 		  mon_brewer.php mon_fermenter.php mon_node.php \
 		  prod_archive_code.php prod_archive_date.php prod_archive_name.php prod_beerxml.php \
-		  prod_duplicate.php prod_edit.php prod_export.php prod_forum.php prod_impbrew.php \
-		  prod_inprod.php prod_new.php prod_print.php prod_torecipe.php \
+		  prod_checklist.php prod_duplicate.php prod_edit.php prod_export.php prod_forum.php \
+		  prod_impbrew.php prod_inprod.php prod_new.php prod_print.php prod_torecipe.php \
 		  profile_fermentation.php profile_mash.php profile_setup.php profile_styles.php \
 		  profile_water.php \
 		  rec_beerxml.php rec_duplicate.php rec_edit.php rec_export.php rec_forum.php \
--- a/www/js/prod_export.js	Tue Jun 04 19:51:40 2019 +0200
+++ b/www/js/prod_export.js	Wed Jun 05 15:12:14 2019 +0200
@@ -32,6 +32,7 @@
 	$("#jqxRadioButton3").jqxRadioButton({ theme: theme, width: 250, height: 23 });
 	$("#jqxRadioButton4").jqxRadioButton({ theme: theme, width: 250, height: 23 });
 	$("#jqxRadioButton5").jqxRadioButton({ theme: theme, width: 250, height: 23 });
+	$("#jqxRadioButton6").jqxRadioButton({ theme: theme, width: 250, height: 23 });
 	$('#jqxRadioButton1').on('checked', function (event) {
 	       	$('#Start').jqxButton({ disabled: false });
 		choice = 1;
@@ -52,6 +53,10 @@
                 $('#Start').jqxButton({ disabled: false });
                 choice = 5;
         });
+	$('#jqxRadioButton6').on('checked', function (event) {
+		$('#Start').jqxButton({ disabled: false });
+		choice = 6;
+	});
 
 	$('#Start').jqxButton({ template: "success", width: '100px', theme: theme, disabled: true });
 	$('#Start').click(function () {
@@ -68,11 +73,14 @@
 			var url="prod_print.php?record=" + my_record;
 			window.open(url);
 		} else if (choice == 5) {
+			var url="prod_checklist.php?record=" + my_record;
+			window.open(url);
+		} else if (choice == 6) {
                         var url="prod_forum.php?record=" + my_record;
                         window.open(url);
                 }
 		// Return to the original product
-		window.location.href = my_return + "?record=" + my_record;
+		window.location.href = "prod_edit.php?record=" + my_record + "&return=" + my_return;
 	});
 
 });
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/www/prod_checklist.php	Wed Jun 05 15:12:14 2019 +0200
@@ -0,0 +1,583 @@
+<?php
+require_once($_SERVER['DOCUMENT_ROOT'].'/includes/global.inc.php');
+require_once($_SERVER['DOCUMENT_ROOT'].'/includes/formulas.php');
+require_once($_SERVER['DOCUMENT_ROOT'].'/fpdf/fpdf.php');
+
+
+$link = mysqli_connect(DBASE_HOST,DBASE_USER,DBASE_PASS,DBASE_NAME);
+if (! $link) {
+	die('Connect Error (' . mysqli_connect_errno() . ') ' . mysqli_connect_error());
+}
+if (! mysqli_set_charset($link, "utf8" )) {
+	echo "error";
+	return 1;
+}
+
+setlocale ( LC_ALL, 'nl_NL.UTF-8');
+$record = $_GET["record"];
+$result = mysqli_query($link, "SELECT * FROM products WHERE record='".$record."'");
+$row = mysqli_fetch_array($result);
+
+date_default_timezone_set('Europe/Amsterdam');
+$prdate = date(DATE_RFC2822);
+
+
+class PDF_MySQL_Table extends FPDF
+{
+	function Checkheader($text) {
+		$this->SetFont('Arial','B',10);
+		$this->Cell(0, 4,$text,0,0,'L',true);
+		$this->SetFont('Arial','',10);
+		$this->Ln(6);
+	}
+
+	function Checkline($text) {
+		$this->Cell(2, 4,' ',0,0,'L',true);
+		$this->Cell(4, 4,' ',1,0,'L',true);
+		$this->Cell(0, 4,' '.$text,0,1,'L',true);
+		$this->Ln(1);
+	}
+
+	function Checklist($row) {
+
+		global $my_grain_absorbtion;
+		global $my_brix_correction;
+		$mashwater = 0;
+		$numsalts = 0;
+
+		$this->AddPage();
+		$this->SetFillColor(255,255,255);
+
+		$ferms = json_decode($row['json_fermentables'], true);
+		$hops = json_decode($row['json_hops'], true);
+		$miscs = json_decode($row['json_miscs'], true);
+		$yeasts = json_decode($row['json_yeasts'], true);
+
+		if ($row['starter_enable'] && $row['prop1_volume']) {
+			$this->Checkheader('Giststarter maken');
+			$days = 0;
+			$last = 0;
+			for ($i = 1; $i < 5; $i++) {
+				$pt = "prop".$i."_type";
+				$pv = "prop".$i."_volume";
+				if (floatval($row[$pv])) {
+					$last = $i;
+					if ($row[$pt] == 0)
+						$days += 2;
+					else if ($row[$pt] == 1)
+						$days += 4;
+					else
+						$days += 6;
+				}
+			}
+			$this->Checkline("begin ongeveer ".$days." dagen voor de brouwdag met de giststarter");
+			for ($i = 1; $i < 5; $i++) {
+				$pt = "prop".$i."_type";
+				$pv = "prop".$i."_volume";
+				if (floatval($row[$pv])) {
+					$s  = "Starter stap ".$i.", van ".sprintf("%.3f",floatval($row[$pv]));
+					$s .= " liter maken met SG ".sprintf("%.3f",floatval($row['starter_sg']));
+					$this->Checkline($s);
+					if ($row[$pt] == 0) {
+						$s = "ongeveer 24 uur op een magneetroerder";
+					} else if ($row[$pt] == 1) {
+						$s = "enkele dagen regelmatig schudden";
+					} else {
+						$s = "bijna een week rustig laten staan";
+					}
+					$s .= " tot er voldoende gist is";
+					$this->Checkline($s);
+					if ($i < $last) {
+						$this->Checkline("starter minstens 24 uur in de koeling laten uitzakken");
+						$this->Checkline("starter uit de koelkast halen en afgieten");
+					} else {
+						$this->Checkline("starter in de koeling zetten tot de brouwdag");
+						$this->Checkline("starter op de brouwdag uit de koelkast halen en afgieten");
+					}
+				}
+			}
+			$this->Ln(5);
+		}
+
+		$this->Checkheader('Water en -behandeling');
+		if ($row['w1_name']) {
+			$this->Checkline(sprintf("%.1f",floatval($row['w1_amount'])).' liter water '.$row['w1_name']);
+			$mashwater += floatval($row['w1_amount']);
+		}
+		if ($row['w2_name']) {
+			$this->Checkline(sprintf("%.1f",floatval($row['w2_amount'])).' liter water '.$row['w2_name']);
+			$mashwater += floatval($row['w2_amount']);
+		}
+		foreach($miscs as $item) {
+			if ($item['m_type'] == 4) {	// Only the water agents
+				$unit = ($item['m_amount_is_weight']) ? " gram ":" ml ";
+				$this->Checkline(sprintf("%.1f",floatval($item['m_amount'] * 1000)).$unit.$item['m_name']);
+				$numsalts++;
+			}
+		}
+		$this->Ln(5);
+
+		$this->Checkheader('Mout afwegen en schroten');
+		foreach($ferms as $item) {
+			if ($item['f_added'] == 0) {	// to mash
+				$s = sprintf("%.3f",floatval($item['f_amount'])).' kg `';
+				$s .= iconv('UTF-8','windows-1252',$item['f_name']);
+				$s .= '` ('.iconv('UTF-8','windows-1252',$item['f_supplier']).')';
+				$this->Checkline($s);
+			}
+		}
+		$this->Checkline('mout schroten');
+		$this->Ln(5);
+
+		$this->Checkheader('Maischen');
+		$mvol = 0;
+		$msugars = 0;	// mash sugars
+		$grainabsorbtion = 0;
+		$arr = json_decode($row['json_mashs'], true);
+		if (count($arr) > 0) {
+			$loop = 0;
+			foreach($arr as $item) {
+				if ($item['step_type'] == 0)
+					$mvol += $item['step_infuse_amount'];	// We need this later.
+				if ($loop == 0) {
+					if ($item['step_type'] == 0)
+						$l = $item['step_infuse_amount'];
+					else
+						$l = $mashwater;
+					$s = sprintf("%.1f",$l).' liter water opwarmen tot ';
+					$s .= sprintf("%.1f",$item['step_temp']).' '.DEG.'C (';
+					$s .= sprintf("%.1f",kettle_cm($l,$row['eq_tun_volume'],$row['eq_tun_height']));
+					$s .= ' cm onder de rand)';
+					$this->Checkline($s);
+					if ($numsalts > 0)
+						$this->Checkline('brouwzouten en -zuren toevoegen');
+					$this->Checkline('mout storten en inmaischen');
+					foreach($hops as $item2) {
+						if ($item2['h_useat'] == 0) {
+							$s = sprintf("%.1f",$item2['h_amount']*1000).' gr `';
+							$s .= iconv('UTF-8','windows-1252',$item2['h_name']).'` toevoegen';
+							$this->Checkline($s);
+						}
+					}
+					foreach($miscs as $item3) {
+						if ($item3['m_use_use'] == 1 && $item3['m_type'] != 4) {	// Only if not a water agent
+							$s = sprintf("%.2f",$item3['m_amount']*1000).' gr `';
+							$s .= iconv('UTF-8','windows-1252',$item3['m_name']).'` toevoegen';
+							$this->Checkline($s);
+						}
+					}
+					$this->Checkline($item['step_time'].' min. bij '.$item['step_temp'].' '.DEG.'C');
+					$this->Checkline('pH meten en bijstellen (doel pH beslag: '.sprintf("%.1f",$row['mash_ph']).' pH)');
+				} else {
+					if ($item['step_type'] == 0) {	// Infusion
+						$s = 'toevoegen '.$item['step_infuse_amount'].' liter water van xx '.DEG.'C';
+					} else if ($item['step_type'] == 1) {	// Direct heat
+						$s = 'opwarmen tot '.$item['step_temp'].' '.DEG.'C';
+					} else {	// Decoction
+						$s = 'uitnemen, opwarmen, koken en terugstorten van '.$item['step_infuse_amount'].' liter deelbeslag';
+					}
+					$this->Checkline($s);
+					$this->Checkline($item['step_time'].' min. bij '.$item['step_temp'].' '.DEG.'C');
+				}
+				$loop++;
+			}
+			$est_mash_sg = 0;
+			foreach($ferms as $item) {
+				if ($item['f_added'] == 0) {
+					$d = $item['f_amount'] * ($item['f_yield'] / 100) * (1 - $item['f_moisture'] / 100);
+					$mvol += $item['f_amount'] * $item['f_moisture'] / 100;
+					$grainabsorbtion += $my_grain_absorbtion * $item['f_amount'];
+					$msugars += $d;
+				}
+			}
+			$sugardensity = 1.611;
+			$v = $msugars / $sugardensity + $mvol;
+			$plato = 1000 * $msugars / ($v * 10);	// deg. Plato
+			$mash_sg = plato_to_sg($plato);
+			$this->Checkline('doel SG eind maischen: '.density_str($mash_sg));
+		}
+		if ($this->GetY() > 200)
+			$this->AddPage();
+		else
+			$this->Ln(5);
+
+		$acidtype = array( 'Melkzuur', 'Zoutzuur', 'Fosforzuur', 'Zwavelzuur' );
+		$this->Checkheader('Filteren en spoelen');
+		$s = sprintf("%.1f",$row['sparge_volume']).' liter spoelwater opwarmen tot '.sprintf("%.1f",$row['sparge_temp']).' '.DEG.'C';
+		$this->Checkline($s);
+		$s = 'spoelwater aanzuren tot pH <= '.sprintf("%.1f",$row['sparge_ph']).' met ';
+		$s .= sprintf("%.1f",$row['sparge_acid_amount']*1000).' ml. '.$acidtype[$row['sparge_acid_type']];
+		$this->Checkline($s);
+		$spoelw = ($row['boil_size'] - $mashwater + $grainabsorbtion + $row['eq_lauter_deadspace']) * 1.03;	// A small heat correction
+		$this->Checkline('spoelen met ongeveer '.sprintf("%.1f",$spoelw).' liter spoelwater');
+		$s = 'doelvolume in kookketel: '.sprintf("%.1f",$row['boil_size'] * 1.04).' liter (';
+		$s .= sprintf("%.1f",kettle_cm($row['boil_size'] * 1.04,$row['eq_kettle_volume'],$row['eq_kettle_height'])).' cm onder de rand)';
+		$this->Checkline($s);
+		$pre_sg = estimate_sg($msugars * floatval($row['efficiency']) / 100,floatval($row['boil_size']));
+		$this->Checkline('doel SG in kookketel: '.density_str($pre_sg));
+		foreach($hops as $item2) {
+			if ($item2['h_useat'] == 1) {
+				$s = sprintf("%.1f",$item2['h_amount']*1000).' gr `';
+				$s .= iconv('UTF-8','windows-1252',$item2['h_name']).'` toevoegen na het spoelen';
+				$this->Checkline($s);
+			}
+		}
+		if ($this->GetY() > 200)
+			$this->AddPage();
+		else
+			$this->Ln(5);
+
+		$this->Checkheader('Koken');
+		$this->Checkline('totale kooktijd: '.$row['boil_time'].' min.');
+		for ($i = $row['boil_time']; $i >= 0; $i--) {
+			if ($i == 10) {
+				foreach($ferms as $item1) {
+					if ($item1['f_added'] == 1) {
+						$s = sprintf("%.3f",$item1['f_amount']).' kg `';
+						$s .= iconv('UTF-8','windows-1252',$item1['f_name']).'` bij 10 minuten voor einde koken';
+						$this->Checkline($s);
+					}
+				}
+				if ($row['brew_cooling_method'] == 1)
+					$this->Checkline('Plaats dompelkoeler bij 10 minuten voor einde koken');
+			}
+			foreach($hops as $item2) {
+				if (($item2['h_useat'] == 2 || $item2['h_useat'] == 3) && ($item2['h_time'] == $i)) {
+					$s = sprintf("%.1f",$item2['h_amount']*1000).' gr `';
+					$s .= iconv('UTF-8','windows-1252',$item2['h_name']).'` bij ';
+					if ($i > 0)
+						$s .= $i.' minuten voor einde koken';
+					else
+						$s .= 'vlamuit';
+					$this->Checkline($s);
+				}
+			}
+			foreach($miscs as $item3) {
+				if ($item3['m_use_use'] == 2 && $item3['m_time'] == $i) {
+					$s = sprintf("%.1f",$item3['m_amount']*1000).' gr `';
+					$s .= iconv('UTF-8','windows-1252',$item3['m_name']).'` bij ';
+					if ($i > 0)
+						$s .= $i.' minuten voor einde koken';
+					else
+						$s .= 'vlamuit';
+					$this->Checkline($s);
+				}
+			}
+
+		}
+		$s = 'doelvolume einde koken: '.sprintf("%.1f",$row['batch_size']*1.04).' liter (';
+		$s .= sprintf("%.1f",kettle_cm($row['batch_size']*1.04,$row['eq_kettle_volume'],$row['eq_kettle_height']));
+		$s .= ' cm onder de rand)';
+		$this->Checkline($s);
+		$this->Checkline('doel SG einde koken: '.density_str($row['est_og']));
+		if ($this->GetY() > 200)
+			$this->AddPage();
+		else
+			$this->Ln(5);
+
+		if (($row['brew_whirlpool9'] + $row['brew_whirlpool7'] + $row['brew_whirlpool6'] + $row['brew_whirlpool2']) > 0) {
+			$this->Checkheader('Whirlpool en koelen');
+			if ($row['brew_whirlpool9'] > 0) {
+				$s = 'Whirlpool voor '.$row['brew_whirlpool9'].' min. Temperatuur boven 85 '.DEG.'C houden';
+				$this->Checkline($s);
+			}
+			if ($row['brew_whirlpool7'] > 0) {
+				$this->Checkline('koelen tot 79 '.DEG.'C');
+				$s = 'Whirlpool voor '.$row['brew_whirlpool7'].' min. Temperatuur tussen 72 en 79 '.DEG.'C houden';
+				$this->Checkline($s);
+			}
+			if ($row['brew_whirlpool6'] > 0) {
+				$this->Checkline('koelen tot 66 '.DEG.'C');
+				$s = 'Whirlpool voor '.$row['brew_whirlpool6'].' min. Temperatuur tussen 60 en 66 '.DEG.'C houden';
+				$this->Checkline($s);
+			}
+			foreach($hops as $item2) {
+				if ($item2['h_useat'] == 4) {
+					$s = sprintf("%.1f",$item2['h_amount']*1000).' gr `';
+					$s .= iconv('UTF-8','windows-1252',$item2['h_name']).'` voor ';
+					$s .= $item2['h_time'].' minuten in de whirlpool';
+					$this->Checkline($s);
+				}
+			}
+			$this->Checkline('koelen tot '.sprintf("%.1f",$row['brew_cooling_to']).' '.DEG.'C');
+			if ($row['brew_whirlpool2'] > 0) {
+				$s = 'Whirlpool voor '.$row['brew_whirlpool2'].' min.';
+				$this->Checkline($s);
+			}
+		} else {
+			$this->Checkheader('Koelen');
+			$this->Checkline('koelen tot '.sprintf("%.1f",$row['brew_cooling_to']).' '.DEG.'C');
+		}
+		$this->Checkline('gistvat ontsmetten en evt. pomp en slangen ontsmetten');
+		$this->Checkline('wort naar gistvat overbrengen');
+		if ($this->GetY() > (300 - (5 * $lines)))
+			$this->AddPage();
+		else
+			$this->Ln(5);
+
+		$this->Checkheader('Gist enten');
+		$dry = 0;
+		foreach ($yeasts as $item) {
+			if ($item['y_use'] == 0) { // primary
+				if ($item['y_form'] == 0) { // Liquid
+					$this->Checkline($item['y_amount'].' pak '.$item['y_product_id'].', '.$item['y_name'].' gist');
+				} else if ($item['y_form'] == 1) { // Dry
+					$s = sprintf("%.1f",$item['y_amount']*1000).' gram '.$item['y_product_id'].', '.$item['y_name'];
+					$s .= ' gist';
+					$dry += $item['y_amount']*10000;
+					$this->Checkline($s);
+				} else { // Slant/Culture/Frozen/Bottle
+					$s = sprintf("%.0f",$item['y_amount']*1000).' ml '.$item['y_product_id'].', '.$item['y_name'].' gist';
+					$this->Checkline($s);
+				}
+			}
+		}
+		if ($dry > 0) {
+			$this->Checkline(' gist hydrateren in '.$dry.' ml gedesinfecteerd water van 32 '.DEG.'C');
+			$this->Checkline(' 15 minuten laten staan bij 32 '.DEG.'C');
+			$this->Checkline(' gistmengsel voorzichtig roeren en laten afkoelen tot temperatuur wort');
+			$this->Checkline(' gist toevoegen');
+			$this->Checkline('Of');
+			$this->Checkline(' gist rechtstreeks over het wort strooien');
+		} else {
+			if ($row['starter_enable'] && $row['prop1_volume'])
+				$this->Checkline('giststarter toevoegen');
+			else
+				$this->Checkline('gist toevoegen');
+		}
+		if ($row['brew_fermenter_extrawater'] > 0)
+			$this->Checkline(sprintf("%.1f", $row['brew_fermenter_extrawater']).' liter water toevoegen in gistvat');
+		if ($row['brew_aeration_type'] > 0) {
+			$s = 'wort '.$row['brew_aeration_time'].' minuten beluchten met ';
+			$s .= ($row['brew_aeration_type'] == 1) ? "lucht":"zuurstof";
+			$this->Checkline($s);
+		}
+		if ($this->GetY() > 200)
+			$this->AddPage();
+		else
+			$this->Ln(5);
+
+		$this->Checkheader('Vergisting starten');
+		$this->Checkline('klimaatkast instellen op '.sprintf("%.1f",$row['brew_cooling_to']).' '.DEG.'C');
+
+		/*
+		 * During primary fermentation: fermentables, misc
+		 */
+		$lines = 0;
+                foreach($ferms as $item1) {
+                        if ($item1['f_added'] == 2)
+				$lines++;
+		}
+                foreach($miscs as $item3) {
+                	if ($item3['m_use_use'] == 3)
+				$lines++;
+		}
+		if ($lines) {
+			if ($this->GetY() > (270 - (5 * $lines)))
+                        	$this->AddPage();
+                	else
+                        	$this->Ln(5);
+			$this->Checkheader('Hoofdgisting');
+		}
+		foreach($ferms as $item1) {
+                        if ($item1['f_added'] == 2) {
+				$s = sprintf("%.3f",$item1['f_amount']).' kg `';
+                                $s .= iconv('UTF-8','windows-1252',$item1['f_name']).'` op dag 3 of 4 toevoegen';
+                                $this->Checkline($s);
+			}
+                }
+                foreach($miscs as $item3) {
+                        if ($item3['m_use_use'] == 3) {
+				$s = sprintf("%.1f",$item3['m_amount']*1000).' gr `';
+                                $s .= iconv('UTF-8','windows-1252',$item3['m_name']).'` op dag 3 of 4 toevoegen';
+                                $this->Checkline($s);
+			}
+                }
+
+		/*
+		 * During secondary fermentation: yeast
+		 */
+		$lines = 0;
+                foreach ($yeasts as $item4) {
+                        if ($item4['y_use'] == 1)
+				$lines++;
+		}
+		if ($lines) {
+			if ($this->GetY() > (270 - (5 * $lines)))
+                        	$this->AddPage();
+                	else
+                        	$this->Ln(5);
+                        $this->Checkheader('Nagisting');
+                }
+		foreach ($yeasts as $item4) {
+                        if ($item4['y_use'] == 1) {
+				if ($item4['y_form'] == 0) { // Liquid
+                                        $this->Checkline($item4['y_amount'].' pak '.$item4['y_product_id'].', '.$item4['y_name'].' gist (eventueel met starter)');
+                                } else if ($item['y_form'] == 1) { // Dry
+                                        $s = sprintf("%.1f",$item4['y_amount']*1000).' gram '.$item4['y_product_id'].', '.$item4['y_name'];
+                                        $s .= ' gist';
+                                        $this->Checkline($s);
+                                } else { // Slant/Culture/Frozen/Bottle
+                                        $s = sprintf("%.0f",$item4['y_amount']*1000).' ml '.$item4['y_product_id'].', '.$item4['y_name'].' gist (eventueel met starter)';
+                                        $this->Checkline($s);
+                                }
+			}
+                }
+
+		/*
+		 * During tertiary fermentation: fermentables, hop, yeast, misc
+		 */
+		$lines = 0;
+		foreach($ferms as $item1) {
+                        if ($item1['f_added'] == 3)
+                                $lines++;
+                }
+                foreach($hops as $item2) {
+                        if ($item2['h_useat'] == 5)
+				$lines++;
+		}
+                foreach ($yeasts as $item4) {
+                        if ($item4['y_use'] == 2)
+                                $lines++;
+                }
+                foreach($miscs as $item3) {
+                        if ($item3['m_use_use'] == 4)
+                                $lines++;
+                }
+		if ($lines) {
+			if ($this->GetY() > (270 - (5 * $lines)))
+                                $this->AddPage();
+                        else
+                                $this->Ln(5);
+                        $this->Checkheader('Lagering');
+                }
+		foreach($ferms as $item1) {
+                        if ($item1['f_added'] == 3) {
+                                $s = sprintf("%.3f",$item1['f_amount']).' kg `';
+                                $s .= iconv('UTF-8','windows-1252',$item1['f_name']).'` toevoegen';
+                                $this->Checkline($s);
+                        }
+                }
+		foreach($hops as $item2) {
+                        if ($item2['h_useat'] == 5) {
+                                $s = sprintf("%.1f",$item2['h_amount']*1000).' gr `';
+                                $s .= iconv('UTF-8','windows-1252',$item2['h_name']).'` voor';
+				$s .= sprintf("%.0f",$item2['h_time']/1440).' dagen toevoegen';
+                                $this->Checkline($s);
+                        }
+                }
+		foreach ($yeasts as $item4) {
+                        if ($item4['y_use'] == 2) {
+                                if ($item4['y_form'] == 0) { // Liquid
+                                        $s = $item4['y_amount'].' pak '.$item4['y_product_id'].', '.$item4['y_name'].' gist (eventueel met starter)';
+                                } else if ($item4['y_form'] == 1) { // Dry
+                                        $s = sprintf("%.1f",$item4['y_amount']*1000).' gram '.$item4['y_product_id'].', '.$item4['y_name'];
+                                        $s .= ' gist';
+                                } else { // Slant/Culture/Frozen/Bottle
+                                        $s = sprintf("%.0f",$item4['y_amount']*1000).' ml '.$item4['y_product_id'].', '.$item4['y_name'];
+					$s .= ' gist (eventueel met starter)';
+                                }
+				$this->Checkline($s);
+                        }
+                }
+		foreach($miscs as $item3) {
+                        if ($item3['m_use_use'] == 4) {
+                                $s = sprintf("%.1f",$item3['m_amount']*1000).' gr `';
+                                $s .= iconv('UTF-8','windows-1252',$item3['m_name']).'` voor ';
+				$s .= sprintf("%.0f",$item3['m_time']/1440).' dagen toevoegen';
+                                $this->Checkline($s);
+                        }
+                }
+
+		/*
+		 * During packaging: fermentables, yeast, misc
+		 */
+		$lines = 0;
+		foreach($ferms as $item1) {
+                        if ($item1['f_added'] == 4)
+                                $lines++;
+                }
+		$yeasts = json_decode($row['json_yeasts'], true);
+                foreach ($yeasts as $item4) {
+                        if ($item4['y_use'] == 3)
+                                $lines++;
+                }
+		$miscs = json_decode($row['json_miscs'], true);
+                foreach($miscs as $item3) {
+                        if ($item3['m_use_use'] == 5)
+                                $lines++;
+                }
+		if ($lines) {
+			if ($this->GetY() > (270 - (5 * $lines)))
+                                $this->AddPage();
+                        else
+                                $this->Ln(5);
+                        $this->Checkheader('Verpakken');
+                }
+		foreach($ferms as $item1) {
+                        if ($item1['f_added'] == 4) {
+                                $s = sprintf("%.3f",$item1['f_amount']).' kg `';
+                                $s .= iconv('UTF-8','windows-1252',$item1['f_name']).'` bij bottelen';
+                                $this->Checkline($s);
+                        }
+                }
+		foreach ($yeasts as $item4) {
+                        if ($item4['y_use'] == 3) {
+                                if ($item4['y_form'] == 0) { // Liquid
+                                        $s = '`'.$item4['y_product_id'].', '.$item4['y_name'];
+                                } else if ($item4['y_form'] == 1) { // Dry
+                                        $s = sprintf("%.1f",$item4['y_amount']*1000).' gram `'.$item4['y_product_id'].', '.$item4['y_name'];
+                                } else { // Slant/Culture/Frozen/Bottle
+                                        $s = sprintf("%.0f",$item4['y_amount']*1000).' ml `'.$item4['y_product_id'].', '.$item4['y_name'];
+                                }
+				$s .= '` als bottelgist';
+				$this->Checkline($s);
+                        }
+                }
+		foreach($miscs as $item3) {
+                        if ($item3['m_use_use'] == 5) {
+                                $s = sprintf("%.1f",$item3['m_amount']*1000).' gr `';
+                                $s .= iconv('UTF-8','windows-1252',$item3['m_name']).'` bij bottelen toevoegen';
+                                $this->Checkline($s);
+                        }
+                }
+	}
+
+}
+
+
+
+class PDF extends PDF_MySQL_Table {
+	function Header() {
+		global $row;
+		global $prdate;
+		$stage = array( 'Plan', 'Wacht', 'Brouwen', 'Hoofdgisting', 'Nagisting', 'Lagering', 'Afvullen', 'Hergisten', 'Rijpen', 'Proeven', 'Gereed', 'Afgesloten' );
+		$this->Image('images/logo.png',10,10,30);
+		// Title
+		$this->SetFont('Helvetica','B',18);
+		$this->SetX(45);
+		$this->Cell(0,8,$row['code'].' '.$row['name'],0,1,'L');
+		$this->Ln(1);
+		$this->SetFont('Helvetica','',10);
+		$this->SetX(45);
+		$this->Cell(17,5,'Datum:',0,0,'L');
+		$this->Cell(0,5,$prdate,0,1,'L');
+		$this->SetX(45);
+		$this->Cell(17,5,'Stijl:',0,0,'L');
+		$this->Cell(0,5,$row['st_name'],0,1,'L');
+		$this->SetX(45);
+		$this->Cell(17,5,'Fase:',0,0,'L');
+		$this->Cell(0,5,$stage[$row['stage']],0,1,'L');
+		$this->Ln(6);
+		// Ensure table header is printed
+		parent::Header();
+	}
+}
+
+
+/*
+ * Generate checklist PDF from recipe data
+ */
+$pdf = new PDF();
+$pdf->Checklist($row);
+$pdf->Output();
--- a/www/prod_export.php	Tue Jun 04 19:51:40 2019 +0200
+++ b/www/prod_export.php	Wed Jun 05 15:12:14 2019 +0200
@@ -33,8 +33,12 @@
        <td align="left"><div style='margin-left: 10px;' id='jqxRadioButton4'></div></td>
       </tr>
       <tr>
+       <td align="right" style="vertical-align: top;">Checklist van recept:</td>
+       <td align="left"><div style='margin-left: 10px;' id='jqxRadioButton5'></div></td>
+      </tr>
+      <tr>
        <td align="right" style="vertical-align: top;">Export voor forum:</td>
-       <td align="left"><div style='margin-left: 10px;' id='jqxRadioButton5'></div></td>
+       <td align="left"><div style='margin-left: 10px;' id='jqxRadioButton6'></div></td>
       </tr>
       <tr><td colspan="2">&nbsp;</td></tr>
       <tr>
--- a/www/prod_print.php	Tue Jun 04 19:51:40 2019 +0200
+++ b/www/prod_print.php	Wed Jun 05 15:12:14 2019 +0200
@@ -641,355 +641,6 @@
                 $this->Ln();
 	}
 
-	function Checkheader($text) {
-		$this->SetFont('Arial','B',10);
-		$this->Cell(0, 4,$text,0,0,'L',true);
-		$this->SetFont('Arial','',10);
-		$this->Ln(6);
-	}
-
-	function Checkline($text) {
-		$this->Cell(2, 4,' ',0,0,'L',true);
-		$this->Cell(4, 4,' ',1,0,'L',true);
-		$this->Cell(0, 4,' '.$text,0,1,'L',true);
-		$this->Ln(1);
-	}
-
-	function Checklist($row) {
-
-		global $my_grain_absorbtion;
-		global $my_brix_correction;
-		$mashwater = 0;
-		$numsalts = 0;
-
-		$this->AddPage();
-		$this->SetFillColor(255,255,255);
-
-		if ($row['starter_enable'] && $row['prop1_volume']) {
-			$this->Checkheader('Giststarter maken');
-			$days = 0;
-			$last = 0;
-			for ($i = 1; $i < 5; $i++) {
-				$pt = "prop".$i."_type";
-				$pv = "prop".$i."_volume";
-				if (floatval($row[$pv])) {
-					$last = $i;
-					if ($row[$pt] == 0)
-						$days += 2;
-					else if ($row[$pt] == 1)
-						$days += 4;
-					else
-						$days += 6;
-				}
-			}
-			$this->Checkline("begin ongeveer ".$days." dagen voor de brouwdag met de giststarter");
-			for ($i = 1; $i < 5; $i++) {
-				$pt = "prop".$i."_type";
-				$pv = "prop".$i."_volume";
-				if (floatval($row[$pv])) {
-					$s  = "Starter stap ".$i.", van ".sprintf("%.3f",floatval($row[$pv]));
-					$s .= " liter maken met SG ".sprintf("%.3f",floatval($row['starter_sg']));
-					$this->Checkline($s);
-					if ($row[$pt] == 0) {
-						$s = "ongeveer 24 uur op een magneetroerder";
-					} else if ($row[$pt] == 1) {
-						$s = "enkele dagen regelmatig schudden";
-					} else {
-						$s = "bijna een week rustig laten staan";
-					}
-					$s .= " tot er voldoende gist is";
-					$this->Checkline($s);
-					if ($i < $last) {
-						$this->Checkline("starter minstens 24 uur in de koeling laten uitzakken");
-						$this->Checkline("starter uit de koelkast halen en afgieten");
-					} else {
-						$this->Checkline("starter in de koeling zetten tot de brouwdag");
-						$this->Checkline("starter op de brouwdag uit de koelkast halen en afgieten");
-					}
-				}
-			}
-			$this->Ln(5);
-		}
-
-		$this->Checkheader('Water en -behandeling');
-		if ($row['w1_name']) {
-			$this->Checkline(sprintf("%.1f",floatval($row['w1_amount'])).' liter water '.$row['w1_name']);
-			$mashwater += floatval($row['w1_amount']);
-		}
-		if ($row['w2_name']) {
-			$this->Checkline(sprintf("%.1f",floatval($row['w2_amount'])).' liter water '.$row['w2_name']);
-			$mashwater += floatval($row['w2_amount']);
-		}
-		$arr = json_decode($row['json_miscs'], true);
-		foreach($arr as $item) {
-			if ($item['m_type'] == 4) {	// Only the water agents
-				$unit = ($item['m_amount_is_weight']) ? " gram ":" ml ";
-				$this->Checkline(sprintf("%.1f",floatval($item['m_amount'] * 1000)).$unit.$item['m_name']);
-				$numsalts++;
-			}
-		}
-		$this->Ln(5);
-
-		$this->Checkheader('Mout afwegen en schroten');
-		$arr = json_decode($row['json_fermentables'], true);
-		foreach($arr as $item) {
-			if ($item['f_added'] == 0) {	// to mash
-				$s = sprintf("%.3f",floatval($item['f_amount'])).' kg `';
-				$s .= iconv('UTF-8','windows-1252',$item['f_name']);
-				$s .= '` ('.iconv('UTF-8','windows-1252',$item['f_supplier']).')';
-				$this->Checkline($s);
-			}
-		}
-		$this->Checkline('mout schroten');
-		$this->Ln(5);
-
-		$this->Checkheader('Maischen');
-		$mvol = 0;
-		$msugars = 0;	// mash sugars
-		$grainabsorbtion = 0;
-		$arr = json_decode($row['json_mashs'], true);
-		if (count($arr) > 0) {
-			$loop = 0;
-			foreach($arr as $item) {
-				if ($item['step_type'] == 0)
-					$mvol += $item['step_infuse_amount'];	// We need this later.
-				if ($loop == 0) {
-					if ($item['step_type'] == 0)
-						$l = $item['step_infuse_amount'];
-					else
-						$l = $mashwater;
-					$s = sprintf("%.1f",$l).' liter water opwarmen tot ';
-					$s .= sprintf("%.1f",$item['step_temp']).' '.DEG.'C (';
-					$s .= sprintf("%.1f",kettle_cm($l,$row['eq_tun_volume'],$row['eq_tun_height']));
-					$s .= ' cm onder de rand)';
-					$this->Checkline($s);
-					if ($numsalts > 0)
-						$this->Checkline('brouwzouten en -zuren toevoegen');
-					$this->Checkline('mout storten en inmaischen');
-					$hops = json_decode($row['json_hops'], true);
-					foreach($hops as $item2) {
-						if ($item2['h_useat'] == 0) {
-							$s = sprintf("%.1f",$item2['h_amount']*1000).' gr `';
-							$s .= iconv('UTF-8','windows-1252',$item2['h_name']).'` toevoegen';
-							$this->Checkline($s);
-						}
-					}
-					$miscs = json_decode($row['json_miscs'], true);
-					foreach($miscs as $item3) {
-						if ($item3['m_use_use'] == 1 && $item3['m_type'] != 4) {	// Only if not a water agent
-							$s = sprintf("%.2f",$item3['m_amount']*1000).' gr `';
-							$s .= iconv('UTF-8','windows-1252',$item3['m_name']).'` toevoegen';
-							$this->Checkline($s);
-						}
-					}
-					$this->Checkline($item['step_time'].' min. bij '.$item['step_temp'].' '.DEG.'C');
-					$this->Checkline('pH meten en bijstellen (doel pH beslag: '.sprintf("%.1f",$row['mash_ph']).' pH)');
-				} else {
-					if ($item['step_type'] == 0) {	// Infusion
-						$s = 'toevoegen '.$item['step_infuse_amount'].' liter water van xx '.DEG.'C';
-					} else if ($item['step_type'] == 1) {	// Direct heat
-						$s = 'opwarmen tot '.$item['step_temp'].' '.DEG.'C';
-					} else {	// Decoction
-						$s = 'uitnemen, opwarmen, koken en terugstorten van '.$item['step_infuse_amount'].' liter deelbeslag';
-					}
-					$this->Checkline($s);
-					$this->Checkline($item['step_time'].' min. bij '.$item['step_temp'].' '.DEG.'C');
-				}
-				$loop++;
-			}
-			$est_mash_sg = 0;
-			$ferms = json_decode($row['json_fermentables'], true);
-			foreach($ferms as $item) {
-				if ($item['f_added'] == 0) {
-					$d = $item['f_amount'] * ($item['f_yield'] / 100) * (1 - $item['f_moisture'] / 100);
-					$mvol += $item['f_amount'] * $item['f_moisture'] / 100;
-					$grainabsorbtion += $my_grain_absorbtion * $item['f_amount'];
-					$msugars += $d;
-				}
-			}
-			$sugardensity = 1.611;
-			$v = $msugars / $sugardensity + $mvol;
-			$plato = 1000 * $msugars / ($v * 10);	// deg. Plato
-			$mash_sg = plato_to_sg($plato);
-			$this->Checkline('doel SG eind maischen: '.density_str($mash_sg));
-		}
-		if ($this->GetY() > 200)
-			$this->AddPage();
-		else
-			$this->Ln(5);
-
-		$acidtype = array( 'Melkzuur', 'Zoutzuur', 'Fosforzuur', 'Zwavelzuur' );
-		$this->Checkheader('Filteren en spoelen');
-		$s = sprintf("%.1f",$row['sparge_volume']).' liter spoelwater opwarmen tot '.sprintf("%.1f",$row['sparge_temp']).' '.DEG.'C';
-		$this->Checkline($s);
-		$s = 'spoelwater aanzuren tot pH <= '.sprintf("%.1f",$row['sparge_ph']).' met ';
-		$s .= sprintf("%.1f",$row['sparge_acid_amount']*1000).' ml. '.$acidtype[$row['sparge_acid_type']];
-		$this->Checkline($s);
-		$spoelw = ($row['boil_size'] - $mashwater + $grainabsorbtion + $row['eq_lauter_deadspace']) * 1.03;	// A small heat correction
-		$this->Checkline('spoelen met ongeveer '.sprintf("%.1f",$spoelw).' liter spoelwater');
-		$s = 'doelvolume in kookketel: '.sprintf("%.1f",$row['boil_size'] * 1.04).' liter (';
-		$s .= sprintf("%.1f",kettle_cm($row['boil_size'] * 1.04,$row['eq_kettle_volume'],$row['eq_kettle_height'])).' cm onder de rand)';
-		$this->Checkline($s);
-		$pre_sg = estimate_sg($msugars * floatval($row['efficiency']) / 100,floatval($row['boil_size']));
-		$this->Checkline('doel SG in kookketel: '.density_str($pre_sg));
-		$hops = json_decode($row['json_hops'], true);
-		foreach($hops as $item2) {
-			if ($item2['h_useat'] == 1) {
-				$s = sprintf("%.1f",$item2['h_amount']*1000).' gr `';
-				$s .= iconv('UTF-8','windows-1252',$item2['h_name']).'` toevoegen na het spoelen';
-				$this->Checkline($s);
-			}
-		}
-		if ($this->GetY() > 200)
-			$this->AddPage();
-		else
-			$this->Ln(5);
-
-		$this->Checkheader('Koken');
-		$this->Checkline('totale kooktijd: '.$row['boil_time'].' min.');
-		for ($i = $row['boil_time']; $i >= 0; $i--) {
-			if ($i == 10) {
-				$ferms = json_decode($row['json_fermentables'], true);
-				foreach($ferms as $item1) {
-					if ($item1['f_added'] == 1) {
-						$s = sprintf("%.3f",$item1['f_amount']).' kg `';
-						$s .= iconv('UTF-8','windows-1252',$item1['f_name']).'` bij 10 minuten voor einde koken';
-						$this->Checkline($s);
-					}
-				}
-				if ($row['brew_cooling_method'] == 1)
-					$this->Checkline('Plaats dompelkoeler bij 10 minuten voor einde koken');
-			}
-			$hops = json_decode($row['json_hops'], true);
-			foreach($hops as $item2) {
-				if (($item2['h_useat'] == 2 || $item2['h_useat'] == 3) && ($item2['h_time'] == $i)) {
-					$s = sprintf("%.1f",$item2['h_amount']*1000).' gr `';
-					$s .= iconv('UTF-8','windows-1252',$item2['h_name']).'` bij ';
-					if ($i > 0)
-						$s .= $i.' minuten voor einde koken';
-					else
-						$s .= 'vlamuit';
-					$this->Checkline($s);
-				}
-			}
-			$miscs = json_decode($row['json_miscs'], true);
-			foreach($miscs as $item3) {
-				if ($item3['m_use_use'] == 2 && $item3['m_time'] == $i) {
-					$s = sprintf("%.1f",$item3['m_amount']*1000).' gr `';
-					$s .= iconv('UTF-8','windows-1252',$item3['m_name']).'` bij ';
-					if ($i > 0)
-						$s .= $i.' minuten voor einde koken';
-					else
-						$s .= 'vlamuit';
-					$this->Checkline($s);
-				}
-			}
-
-		}
-		$s = 'doelvolume einde koken: '.sprintf("%.1f",$row['batch_size']*1.04).' liter (';
-		$s .= sprintf("%.1f",kettle_cm($row['batch_size']*1.04,$row['eq_kettle_volume'],$row['eq_kettle_height']));
-		$s .= ' cm onder de rand)';
-		$this->Checkline($s);
-		$this->Checkline('doel SG einde koken: '.density_str($row['est_og']));
-		if ($this->GetY() > 200)
-			$this->AddPage();
-		else
-			$this->Ln(5);
-
-		if (($row['brew_whirlpool9'] + $row['brew_whirlpool7'] + $row['brew_whirlpool6'] + $row['brew_whirlpool2']) > 0) {
-			$this->Checkheader('Whirlpool en koelen');
-			if ($row['brew_whirlpool9'] > 0) {
-				$s = 'Whirlpool voor '.$row['brew_whirlpool9'].' min. Temperatuur boven 85 '.DEG.'C houden';
-				$this->Checkline($s);
-			}
-			if ($row['brew_whirlpool7'] > 0) {
-				$this->Checkline('koelen tot 79 '.DEG.'C');
-				$s = 'Whirlpool voor '.$row['brew_whirlpool7'].' min. Temperatuur tussen 72 en 79 '.DEG.'C houden';
-				$this->Checkline($s);
-			}
-			if ($row['brew_whirlpool6'] > 0) {
-				$this->Checkline('koelen tot 66 '.DEG.'C');
-				$s = 'Whirlpool voor '.$row['brew_whirlpool6'].' min. Temperatuur tussen 60 en 66 '.DEG.'C houden';
-				$this->Checkline($s);
-			}
-			$hops = json_decode($row['json_hops'], true);
-			foreach($hops as $item2) {
-				if ($item2['h_useat'] == 4) {
-					$s = sprintf("%.1f",$item2['h_amount']*1000).' gr `';
-					$s .= iconv('UTF-8','windows-1252',$item2['h_name']).'` voor ';
-					$s .= $item2['h_time'].' minuten in de whirlpool';
-					$this->Checkline($s);
-				}
-			}
-			$this->Checkline('koelen tot '.sprintf("%.1f",$row['brew_cooling_to']).' '.DEG.'C');
-			if ($row['brew_whirlpool2'] > 0) {
-				$s = 'Whirlpool voor '.$row['brew_whirlpool2'].' min.';
-				$this->Checkline($s);
-			}
-		} else {
-			$this->Checkheader('Koelen');
-			$this->Checkline('koelen tot '.sprintf("%.1f",$row['brew_cooling_to']).' '.DEG.'C');
-		}
-		$this->Checkline('gistvat ontsmetten en evt. pomp en slangen ontsmetten');
-		$this->Checkline('wort naar gistvat overbrengen');
-		if ($this->GetY() > 200)
-			$this->AddPage();
-		else
-			$this->Ln(5);
-
-		$this->Checkheader('Gist enten');
-		$dry = 0;
-		$yeasts = json_decode($row['json_yeasts'], true);
-		foreach ($yeasts as $item) {
-			if ($item['y_use'] == 0) { // primary
-				if ($item['y_form'] == 0) { // Liquid
-					$this->Checkline($item['y_amount'].' pak '.$item['y_product_id'].', '.$item['y_name'].' gist');
-				} else if ($item['y_form'] == 1) { // Dry
-					$s = sprintf("%.1f",$item['y_amount']*1000).' gram '.$item['y_product_id'].', '.$item['y_name'];
-					$s .= ' gist';
-					$dry += $item['y_amount']*10000;
-					$this->Checkline($s);
-				} else { // Slant/Culture/Frozen/Bottle
-					$s = sprintf("%.0f",$item['y_amount']*1000).' ml '.$item['y_product_id'].', '.$item['y_name'].' gist';
-					$this->Checkline($s);
-				}
-			}
-		}
-		if ($dry > 0) {
-			$this->Checkline(' gist hydrateren in '.$dry.' ml gedesinfecteerd water van 32 '.DEG.'C');
-			$this->Checkline(' 15 minuten laten staan bij 32 '.DEG.'C');
-			$this->Checkline(' gistmengsel voorzichtig roeren en laten afkoelen tot temperatuur wort');
-			$this->Checkline(' gist toevoegen');
-			$this->Checkline('Of');
-			$this->Checkline(' gist rechtstreeks over het wort strooien');
-		} else {
-			if ($row['starter_enable'] && $row['prop1_volume'])
-				$this->Checkline('giststarter toevoegen');
-			else
-				$this->Checkline('gist toevoegen');
-		}
-		if ($row['brew_fermenter_extrawater'] > 0)
-			$this->Checkline(sprintf("%.1f", $row['brew_fermenter_extrawater']).' liter water toevoegen in gistvat');
-		if ($row['brew_aeration_type'] > 0) {
-			$s = 'wort '.$row['brew_aeration_time'].' minuten beluchten met ';
-			$s .= ($row['brew_aeration_type'] == 1) ? "lucht":"zuurstof";
-			$this->Checkline($s);
-		}
-		if ($this->GetY() > 200)
-			$this->AddPage();
-		else
-			$this->Ln(5);
-
-		$this->Checkheader('Vergisting starten');
-		$this->Checkline('klimaatkast instellen op '.sprintf("%.1f",$row['brew_cooling_to']).' '.DEG.'C');
-
-		// 'Toevoegingen tijdens vergisting'
-		// 'Toevoegingen tijdens nagisting/lagering'
-		// fermentables & hops & miscs  verdelen over primary/secondary/teriary
-
-		// 'Toevoegingen tijdens bottelen/op fust zetten'
-	}
-
 	function Brewday($row) {
 
 		global $my_brix_correction;
@@ -1213,9 +864,5 @@
 if ($row['stage'] > 9) {
 	// Taste notes
 }
-if ($row['stage'] == 1 || $row['stage'] == 2) {
-        $pdf->Checklist($row);
-}
-
 
 $pdf->Output();

mercurial