Added the product divide scripts. All parts have all the volumes and weights divided, including the master record. Splitted batches have their own records with the product code formatted as code-n. From this design, we can rebuild the print and checklist. divide

Wed, 23 Oct 2019 14:20:50 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Wed, 23 Oct 2019 14:20:50 +0200
branch
divide
changeset 533
be8691b7d634
parent 532
d8f4ca915468
child 534
01fa81a33b70

Added the product divide scripts. All parts have all the volumes and weights divided, including the master record. Splitted batches have their own records with the product code formatted as code-n. From this design, we can rebuild the print and checklist.

README.design file | annotate | diff | comparison | revisions
www/includes/db_divides.php file | annotate | diff | comparison | revisions
www/includes/db_product.php file | annotate | diff | comparison | revisions
www/js/prod_divide.js file | annotate | diff | comparison | revisions
www/js/prod_edit.js file | annotate | diff | comparison | revisions
www/js/prod_new.js file | annotate | diff | comparison | revisions
--- a/README.design	Mon Oct 21 14:39:49 2019 +0200
+++ b/README.design	Wed Oct 23 14:20:50 2019 +0200
@@ -52,12 +52,12 @@
  5. After lagering (separated packaging)
 
 Split fields:
-divide_type	0:none 1:after mash 2:after boil 3:after primary 4:after secondary 5:after tertiary
+divide_type	0:none 1:after mash 2:after boil 3:after cooling 4:after primary 5:after secondary 6:after tertiary
 divide_size	amount in liters of this part.
-divide_percent	percentage of this part.
+divide_factor	factor size of this part.
 divide_parts	hoeveel afsplitsingen.
 divide_part	0=hoofdbatch.
-divide_from	uuid
+
 Via Export module dialoog  maken, keuze aantal afsplitsels en grootte per stuk. 10 stuks.
 Procedure: Genereer afsplitsels in db_product. Pas volumes aan na splitspunt.
 Afsplitsels naam aanpassen, code en -n volgnummer toevoegen.
--- a/www/includes/db_divides.php	Mon Oct 21 14:39:49 2019 +0200
+++ b/www/includes/db_divides.php	Wed Oct 23 14:20:50 2019 +0200
@@ -4,75 +4,388 @@
 require($_SERVER['DOCUMENT_ROOT']."/version.php");
 
 #Connect to the database
-$connect = mysqli_connect(DBASE_HOST, DBASE_USER, DBASE_PASS, DBASE_NAME);
-if (! $connect) {
+$link = mysqli_connect(DBASE_HOST, DBASE_USER, DBASE_PASS, DBASE_NAME);
+if (! $link) {
 	die('Connect Error (' . mysqli_connect_errno() . ') ' . mysqli_connect_error());
 }
-mysqli_set_charset($connect, "utf8" );
+mysqli_set_charset($link, "utf8" );
 
+$escapers = array("\\", "/", "\"", "\n", "\r", "\t", "\x08", "\x0c");
+$replacements = array("\\\\", "\\/", "\\\"", "\\n", "\\r", "\\t", "\\f", "\\b");
+$rescapers = array("'");
+$rreplacements = array("\\'");
+$disallowed = array('visibleindex','uniqueid','boundindex','uid','h_weight','m_weight');
 
-if (isset($_POST['insert']) || isset($_POST['update'])) {
-	if (isset($_POST['insert'])) {
-		$sql  = "INSERT INTO `divides` SET ";
-	}
-	if (isset($_POST['update'])) {
-		$sql  = "UPDATE `divides` SET ";
+/*
+ * Server side split batch. Parameters:
+ * record = original record.
+ * divide_type = divide moment.
+ * divide parts = number of divisions
+ * divide_data = array with { size, factor, part, name, code } where index 0 is original
+ *
+ * generate the new records and modify the original record.
+ * rollback if something goes wrong.
+ * return ok or error
+ */
+
+if (isset($_POST['record']) && isset($_POST['divide_type']) && isset($_POST['divide_parts']) && isset($_POST['divide_data'])) {
+
+    $rc = 0;
+    $record = $_POST['record'];
+    $divide_parts = $_POST['divide_parts'];
+    $divide_type = $_POST['divide_type'];
+    $divide_data = array_reverse($_POST['divide_data'], true); // reverse the array so the master record is last.
+
+    syslog(LOG_NOTICE, "db_divide: record " . $record . "  divide_type " . $divide_type . "  parts " . $divide_parts);
+
+    foreach ($divide_data as $index => &$split) {
+	syslog(LOG_NOTICE, "db_divide: index " . $index);
+
+	foreach ($split as $key => &$value) {
+	    syslog(LOG_NOTICE, "db_divide: index " . $index . " key " . $key . " value " . $value);
 	}
 
-	$sql .= "divide_from='" . mysqli_real_escape_string($connect, $_POST['divide_from']);
-	$sql .= "', divide_type='" . $_POST['divide_type'];
-	$sql .= "', divide_size='" . $_POST['divide_size'];
-	$sql .= "', divide_part='" . $_POST['divide_part'];
-	$sql .= "', name='" . mysqli_real_escape_string($connect, $_POST['name']);
-	$sql .= "', code='" . mysqli_real_escape_string($connect, $_POST['code']);
-	if (isset($_POST['insert'])) {
-		$sql .= "';";
-	}
-	if (isset($_POST['update'])) {
-		$sql .= "' WHERE record='" . $_POST['record'] . "';";
+	$result = mysqli_query($link, "SELECT * FROM products WHERE record='" . $record . "'");
+	if (! $result) {
+            syslog(LOG_NOTICE, "db_divide: result: ".mysqli_error($link));
 	}
-	syslog(LOG_NOTICE, $sql);
+	$row = mysqli_fetch_array($result);
+	$factor = floatval($split['factor']);
 
-	$result = mysqli_query($connect, $sql);
-	if (! $result) {
-		syslog(LOG_NOTICE, "db_divides: ".$sql." result: ".mysqli_error($connect));
-	} else {
-		if (isset($_POST['update'])) {
-			syslog(LOG_NOTICE, "db_divides: updated record ".$_POST['record']);
-		} else {
-			$lastid = mysqli_insert_id($connect);
-			syslog(LOG_NOTICE, "db_divides: inserted record ".$lastid);
-		}
-	}
-	echo $result;
+	if ($index == 0) {
+	    /*
+	     * Update the main record
+	     */
+	    $sql = "UPDATE `products` SET ";
+            $sql .=    "brew_sparge_volume='" . sprintf("%.1f", $row['brew_sparge_volume'] * $factor);
+            $sql .= "', brew_sparge_est='" . sprintf("%.1f", $row['brew_sparge_est'] * $factor);
+            $sql .= "', brew_preboil_volume='" . sprintf("%.1f", $row['brew_preboil_volume'] * $factor);
+            $sql .= "', brew_aboil_volume='" . sprintf("%.1f", $row['brew_aboil_volume'] * $factor);
+            $sql .= "', brew_fermenter_volume='" . sprintf("%.1f", $row['brew_fermenter_volume'] * $factor);
+            $sql .= "', brew_fermenter_extrawater='" . sprintf("%.1f", $row['brew_fermenter_extrawater'] * $factor);
+            $sql .= "', brew_fermenter_tcloss='" . sprintf("%.1f", $row['brew_fermenter_tcloss'] * $factor);
+            $sql .= "', package_volume='" . sprintf("%.1f", $row['package_volume'] * $factor);
+            $sql .= "', package_infuse_amount='" . sprintf("%.1f", $row['package_infuse_amount'] * $factor);
+            $sql .= "', bottle_amount='" . sprintf("%.1f", $row['bottle_amount'] * $factor);
+            $sql .= "', bottle_priming_water='" . sprintf("%.3f", $row['bottle_priming_water'] * $factor);
+            $sql .= "', keg_amount='" . sprintf("%.1f", $row['keg_amount'] * $factor);
+            $sql .= "', keg_priming_water='" . sprintf("%.3f", $row['keg_priming_water'] * $factor);
+            $sql .= "', batch_size='" . sprintf("%.2f", $row['batch_size'] * $factor);
+            $sql .= "', boil_size='" . sprintf("%.2f", $row['boil_size'] * $factor);
+            $sql .= "', sparge_volume='" . sprintf("%.1f", $row['sparge_volume'] * $factor);
+            $sql .= "', sparge_acid_amount='" . sprintf("%.5f", $row['sparge_acid_amount'] * $factor);
+            $sql .= "', w1_amount='" . sprintf("%.2f", $row['w1_amount'] * $factor);
+            $sql .= "', w2_amount='" . sprintf("%.2f", $row['w2_amount'] * $factor);
+            $sql .= "', wg_amount='" . sprintf("%.2f", $row['wg_amount'] * $factor);
+            $sql .= "', prop1_volume='" . sprintf("%.3f", $row['prop1_volume'] * $factor);
+            $sql .= "', prop2_volume='" . sprintf("%.3f", $row['prop2_volume'] * $factor);
+            $sql .= "', prop3_volume='" . sprintf("%.3f", $row['prop3_volume'] * $factor);
+            $sql .= "', prop4_volume='" . sprintf("%.3f", $row['prop4_volume'] * $factor);
+            $sql .= "', divide_type='" . $divide_type;
+            $sql .= "', divide_parts='" . $divide_parts;
+            $sql .= "', divide_part='" . $index;
+            $sql .= "', divide_size='" . floatval($split['size']);
+            $sql .= "', divide_factor='". $factor;
+	    syslog(LOG_NOTICE, "db_divide: index " . $index . " " . $sql);
 
-} else if (isset($_POST['delete'])) {
-	// DELETE COMMAND
-	$sql = "DELETE FROM `divides` WHERE record='".$_POST['record']."';";
-	$result = mysqli_query($connect, $sql);
-	if (! $result) {
-		syslog(LOG_NOTICE, "db_divides: ".$sql." result: ".mysqli_error($connect));
 	} else {
-		syslog(LOG_NOTICE, "db_divides: deleted record ".$_POST['record']);
+	    /*
+	     * Insert splitted batches
+	     */
+	    $sql  = "INSERT INTO `products` SET ";
+	    $sql .= "name='" . mysqli_real_escape_string($link, $split['name']);
+	    $sql .= "', uuid='" . str_replace("\n", "", file_get_contents('/proc/sys/kernel/random/uuid'));
+	    $sql .= "', code='" . mysqli_real_escape_string($link, $split['code']);
+	    $sql .= "', birth='" . $row['birth'];
+	    $sql .= "', stage='" . $row['stage'];
+	    $sql .= "', notes='" . mysqli_real_escape_string($link, $row['notes']);
+	    $sql .= "', log_brew='" . $row['log_brew'];
+	    $sql .= "', log_fermentation='" . $row['log_fermentation'];
+	    $sql .= "', inventory_reduced='" . $row['inventory_reduced'];;
+	    $sql .= "', locked='" . $row['locked'];;
+	    // Equipment
+	    $sql .= "', eq_name='" . mysqli_real_escape_string($link, $row['eq_name']);
+	    $sql .= "', eq_boil_size='" . $row['eq_boil_size'];
+	    $sql .= "', eq_batch_size='" . $row['eq_batch_size'];
+	    $sql .= "', eq_tun_volume='" . $row['eq_tun_volume'];
+	    $sql .= "', eq_tun_weight='" . $row['eq_tun_weight'];
+	    $sql .= "', eq_tun_specific_heat='" . $row['eq_tun_specific_heat'];
+	    $sql .= "', eq_tun_material='" . $row['eq_tun_material'];
+	    $sql .= "', eq_tun_height='" . $row['eq_tun_height'];
+	    $sql .= "', eq_top_up_water='" . $row['eq_top_up_water'];
+	    $sql .= "', eq_trub_chiller_loss='" . $row['eq_trub_chiller_loss'];
+	    $sql .= "', eq_evap_rate='" . $row['eq_evap_rate'];
+	    $sql .= "', eq_boil_time='" . $row['eq_boil_time'];
+	    $sql .= "', eq_calc_boil_volume='" . $row['eq_calc_boil_volume'];
+	    $sql .= "', eq_top_up_kettle='" . $row['eq_top_up_kettle'];
+	    $sql .= "', eq_hop_utilization='" . $row['eq_hop_utilization'];
+	    $sql .= "', eq_notes='" . mysqli_real_escape_string($link, $row['eq_notes']);
+	    $sql .= "', eq_lauter_volume='" . $row['eq_lauter_volume'];
+	    $sql .= "', eq_lauter_height='" . $row['eq_lauter_height'];
+	    $sql .= "', eq_lauter_deadspace='" . $row['eq_lauter_deadspace'];
+	    $sql .= "', eq_kettle_volume='" . $row['eq_kettle_volume'];
+	    $sql .= "', eq_kettle_height='" . $row['eq_kettle_height'];
+	    $sql .= "', eq_mash_volume='" . $row['eq_mash_volume'];
+	    $sql .= "', eq_mash_max='" . $row['eq_mash_max'];
+	    $sql .= "', eq_efficiency='" . $row['eq_efficiency'];
+	    // brewdate
+	    if (strlen($row['brew_date_start']))
+	    	$sql .= "', brew_date_start='" . $row['brew_date_start'] . "'";
+	    else
+		$sql .= "', brew_date_start=NULL";
+            $sql .=  ", brew_mash_ph='" . $row['brew_mash_ph'];
+            $sql .= "', brew_mash_sg='" . $row['brew_mash_sg'];
+	    $sql .= "', brew_mash_efficiency='" . $row['brew_mash_efficiency'];
+	    $sql .= "', brew_sparge_temperature='" . $row['brew_sparge_temperature'];
+	    $sql .= "', brew_sparge_volume='" . sprintf("%.1f", $row['brew_sparge_volume'] * $factor);
+            $sql .= "', brew_sparge_est='" . sprintf("%.1f", $row['brew_sparge_est'] * $factor);
+            $sql .= "', brew_sparge_ph='" . $row['brew_sparge_ph'];
+            $sql .= "', brew_preboil_volume='" . sprintf("%.1f", $row['brew_preboil_volume'] * $factor);
+            $sql .= "', brew_preboil_sg='" . $row['brew_preboil_sg'];
+            $sql .= "', brew_preboil_ph='" . $row['brew_preboil_ph'];
+	    $sql .= "', brew_preboil_efficiency='" . $row['brew_preboil_efficiency'];
+            $sql .= "', brew_aboil_volume='" . sprintf("%.1f", $row['brew_aboil_volume'] * $factor);
+            $sql .= "', brew_aboil_sg='" . $row['brew_aboil_sg'];
+            $sql .= "', brew_aboil_ph='" . $row['brew_aboil_ph'];
+            $sql .= "', brew_aboil_efficiency='" . $row['brew_aboil_efficiency'];
+	    $sql .= "', brew_cooling_method='" . $row['brew_cooling_method'];
+            $sql .= "', brew_cooling_time='" . $row['brew_cooling_time'];
+	    $sql .= "', brew_cooling_to='" . $row['brew_cooling_to'];
+	    $sql .= "', brew_whirlpool9='" . $row['brew_whirlpool9'];
+	    $sql .= "', brew_whirlpool7='" . $row['brew_whirlpool7'];
+	    $sql .= "', brew_whirlpool6='" . $row['brew_whirlpool6'];
+	    $sql .= "', brew_whirlpool2='" . $row['brew_whirlpool2'];
+	    $sql .= "', brew_aeration_time='" . $row['brew_aeration_time'];
+	    $sql .= "', brew_aeration_speed='" . $row['brew_aeration_speed'];
+	    $sql .= "', brew_aeration_type='" . $row['brew_aeration_type'];
+	    $sql .= "', brew_fermenter_volume='" . sprintf("%.1f", $row['brew_fermenter_volume'] * $factor);
+	    $sql .= "', brew_fermenter_extrawater='" . sprintf("%.1f", $row['brew_fermenter_extrawater'] * $factor);
+	    $sql .= "', brew_fermenter_tcloss='" . sprintf("%.1f", $row['brew_fermenter_tcloss'] * $factor);
+            $sql .= "', brew_fermenter_sg='" . $row['brew_fermenter_sg'];
+	    $sql .= "', brew_fermenter_ibu='" . $row['brew_fermenter_ibu'];
+	    $sql .= "', brew_fermenter_color='" . $row['brew_fermenter_color'];
+	    if (strlen($row['brew_date_end']))
+		$sql .= "', brew_date_end='" . $row['brew_date_end'] . "'";
+	    else
+		$sql .= "', brew_date_end=NULL";
+	    $sql .=  ", og='" . $row['og'];
+	    $sql .= "', fg='" . $row['fg'];
+	    $sql .= "', primary_start_temp='" . $row['primary_start_temp'];
+	    $sql .= "', primary_max_temp='" . $row['primary_max_temp'];
+	    $sql .= "', primary_end_temp='" . $row['primary_end_temp'];
+	    if (strlen($row['primary_end_date']))
+		$sql .= "', primary_end_date='" . $row['primary_end_date'] . "'";
+	    else
+	    	$sql .= "', primary_end_date=NULL";
+	    $sql .=  ", primary_end_sg='" . $row['primary_end_sg'];
+	    $sql .= "', secondary_temp='" . $row['secondary_temp'];
+	    $sql .= "', secondary_end_sg='" . $row['secondary_end_sg'];
+	    if (strlen($row['secondary_end_date']))
+		$sql .= "', secondary_end_date='" . $row['secondary_end_date'] . "'";
+	    else
+	    	$sql .= "', secondary_end_date=NULL";
+	    $sql .=  ", tertiary_temp='" . $row['tertiary_temp'];
+	    if (strlen($row['package_date']))
+		$sql .= "', package_date='" . $row['package_date'] . "'";
+	    else
+		$sql .= "', package_date=NULL";
+	    $sql .=  ", package_volume='" . sprintf("%.1f", $row['package_volume'] * $factor);
+	    $sql .= "', package_infuse_amount='" . sprintf("%.1f", $row['package_infuse_amount'] * $factor);
+	    $sql .= "', package_infuse_abv='" . $row['package_infuse_abv'];
+	    $sql .= "', package_infuse_notes='" . mysqli_real_escape_string($link, $row['package_infuse_notes']);
+	    $sql .= "', package_abv='" . $row['package_abv'];
+	    $sql .= "', package_ph='" . $row['package_ph'];
+	    $sql .= "', bottle_amount='" . sprintf("%.1f", $row['bottle_amount'] * $factor);
+	    $sql .= "', bottle_carbonation='" . $row['bottle_carbonation'];
+	    $sql .= "', bottle_priming_sugar='" . $row['bottle_priming_sugar'];
+	    $sql .= "', bottle_priming_water='" . sprintf("%.3f", $row['bottle_priming_water'] * $factor);
+	    $sql .= "', bottle_priming_amount='" . $row['bottle_priming_amount'];
+	    $sql .= "', bottle_carbonation_temp='" . $row['bottle_carbonation_temp'];
+	    $sql .= "', keg_amount='" . sprintf("%.1f", $row['keg_amount'] * $factor);
+	    $sql .= "', keg_carbonation='" . $row['keg_carbonation'];
+	    $sql .= "', keg_priming_sugar='" . $row['keg_priming_sugar'];
+	    $sql .= "', keg_priming_water='" . sprintf("%.3f", $row['keg_priming_water'] * $factor);
+	    $sql .= "', keg_priming_amount='" . $row['keg_priming_amount'];
+	    $sql .= "', keg_carbonation_temp='" . $row['keg_carbonation_temp'];
+	    $sql .= "', keg_forced_carb='" . $row['keg_forced_carb'];
+	    $sql .= "', keg_pressure='" . $row['keg_pressure'];
+	    $sql .= "', taste_notes='";
+	    $sql .= "', taste_rate='0";
+	    $sql .= "', taste_date=NULL";
+	    $sql .=  ", taste_color='";
+	    $sql .= "', taste_transparency='";
+	    $sql .= "', taste_head='";
+	    $sql .= "', taste_aroma='";
+	    $sql .= "', taste_taste='";
+	    $sql .= "', taste_mouthfeel='";
+	    $sql .= "', taste_aftertaste='";
+	    // Style
+	    $sql .= "', st_name='" . mysqli_real_escape_string($link, $row['st_name']);
+	    $sql .= "', st_letter='" . mysqli_real_escape_string($link, $row['st_letter']);
+	    $sql .= "', st_guide='" . mysqli_real_escape_string($link, $row['st_guide']);
+	    $sql .= "', st_type='" . $row['st_type'];
+	    $sql .= "', st_category='" . mysqli_real_escape_string($link, $row['st_category']);
+	    $sql .= "', st_category_number='" . $row['st_category_number'];
+	    $sql .= "', st_og_min='" . $row['st_og_min'];
+	    $sql .= "', st_og_max='" . $row['st_og_max'];
+	    $sql .= "', st_fg_min='" . $row['st_fg_min'];
+	    $sql .= "', st_fg_max='" . $row['st_fg_max'];
+	    $sql .= "', st_ibu_min='" . $row['st_ibu_min'];
+	    $sql .= "', st_ibu_max='" . $row['st_ibu_max'];
+	    $sql .= "', st_color_min='" . $row['st_color_min'];
+	    $sql .= "', st_color_max='" . $row['st_color_max'];
+	    $sql .= "', st_carb_min='" . $row['st_carb_min'];
+	    $sql .= "', st_carb_max='" . $row['st_carb_max'];
+	    $sql .= "', st_abv_min='" . $row['st_abv_min'];
+	    $sql .= "', st_abv_max='" . $row['st_abv_max'];
+	    $sql .= "', type='" . $row['type'];
+            $sql .= "', batch_size='" . sprintf("%.2f", $row['batch_size'] * $factor);
+            $sql .= "', boil_size='" . sprintf("%.2f", $row['boil_size'] * $factor);
+	    $sql .= "', boil_time='" . $row['boil_time'];
+	    $sql .= "', efficiency='" . $row['efficiency'];
+	    $sql .= "', est_og='" . $row['est_og'];
+	    $sql .= "', est_fg='" . $row['est_fg'];
+	    $sql .= "', est_abv='" . $row['est_abv'];
+	    $sql .= "', est_carb='" . $row['est_carb'];
+	    $sql .= "', est_color='" . $row['est_color'];
+	    $sql .= "', color_method='" . $row['color_method'];
+	    $sql .= "', est_ibu='" . $row['est_ibu'];
+	    $sql .= "', ibu_method='" . $row['ibu_method'];
+            $sql .= "', sparge_volume='" . sprintf("%.1f", $row['sparge_volume'] * $factor);
+            $sql .= "', sparge_acid_amount='" . sprintf("%.5f", $row['sparge_acid_amount'] * $factor);
+	    $sql .= "', sparge_temp='" . $row['sparge_temp'];
+	    $sql .= "', sparge_ph='" . $row['sparge_ph'];
+	    $sql .= "', sparge_source='" . $row['sparge_source'];
+	    $sql .= "', sparge_acid_type='" . $row['sparge_acid_type'];
+	    $sql .= "', sparge_acid_perc='" . $row['sparge_acid_perc'];
+	    $sql .= "', mash_ph='" . $row['mash_ph'];
+	    $sql .= "', mash_name='" . $row['mash_name'];
+	    $sql .= "', calc_acid='" . $row['calc_acid'];
+	    $sql .= "', w1_name='" . mysqli_real_escape_string($link, $row['w1_name']);
+            $sql .= "', w1_amount='" . sprintf("%.2f", $row['w1_amount'] * $factor);
+	    $sql .= "', w1_calcium='" . $row['w1_calcium'];
+	    $sql .= "', w1_sulfate='" . $row['w1_sulfate'];
+	    $sql .= "', w1_chloride='" . $row['w1_chloride'];
+	    $sql .= "', w1_sodium='" . $row['w1_sodium'];
+	    $sql .= "', w1_magnesium='" . $row['w1_magnesium'];
+	    $sql .= "', w1_total_alkalinity='" . $row['w1_total_alkalinity'];
+	    $sql .= "', w1_ph='" . $row['w1_ph'];
+            $sql .= "', w1_cost='" . $row['w1_cost'];
+	    $sql .= "', w2_name='" . mysqli_real_escape_string($link, $row['w2_name']);
+            $sql .= "', w2_amount='" . sprintf("%.2f", $row['w2_amount'] * $factor);
+	    $sql .= "', w2_calcium='" . $row['w2_calcium'];
+	    $sql .= "', w2_sulfate='" . $row['w2_sulfate'];
+	    $sql .= "', w2_chloride='" . $row['w2_chloride'];
+	    $sql .= "', w2_sodium='" . $row['w2_sodium'];
+	    $sql .= "', w2_magnesium='" . $row['w2_magnesium'];
+	    $sql .= "', w2_total_alkalinity='" . $row['w2_total_alkalinity'];
+	    $sql .= "', w2_ph='" . $row['w2_ph'];
+	    $sql .= "', w2_cost='" . $row['w2_cost'];
+            $sql .= "', wg_amount='" . sprintf("%.2f", $row['wg_amount'] * $factor);
+            $sql .= "', wg_calcium='" . $row['wg_calcium'];
+            $sql .= "', wg_sulfate='" . $row['wg_sulfate'];
+            $sql .= "', wg_chloride='" . $row['wg_chloride'];
+            $sql .= "', wg_sodium='" . $row['wg_sodium'];
+            $sql .= "', wg_magnesium='" . $row['wg_magnesium'];
+            $sql .= "', wg_total_alkalinity='" . $row['wg_total_alkalinity'];
+            $sql .= "', wg_ph='" . $row['wg_ph'];
+            $sql .= "', wb_calcium='" . $row['wb_calcium'];
+            $sql .= "', wb_sulfate='" . $row['wb_sulfate'];
+            $sql .= "', wb_chloride='" . $row['wb_chloride'];
+            $sql .= "', wb_sodium='" . $row['wb_sodium'];
+            $sql .= "', wb_magnesium='" . $row['wb_magnesium'];
+            $sql .= "', wb_total_alkalinity='" . $row['wb_total_alkalinity'];
+            $sql .= "', wb_ph='" . $row['wb_ph'];
+	    $sql .= "', wa_acid_name='" . $row['wa_acid_name'];
+	    $sql .= "', wa_acid_perc='" . $row['wa_acid_perc'];
+	    $sql .= "', wa_base_name='" . $row['wa_base_name'];
+	    $sql .= "', starter_enable='" . $row['starter_enable'];
+	    $sql .= "', starter_type='" . $row['starter_type'];
+	    $sql .= "', starter_sg='" . $row['starter_sg'];
+	    $sql .= "', starter_viability='" . $row['starter_viability'];
+	    $sql .= "', prop1_type='" . $row['prop1_type'];
+	    $sql .= "', prop2_type='" . $row['prop2_type'];
+	    $sql .= "', prop3_type='" . $row['prop3_type'];
+	    $sql .= "', prop4_type='" . $row['prop4_type'];
+            $sql .= "', prop1_volume='" . sprintf("%.3f", $row['prop1_volume'] * $factor);
+            $sql .= "', prop2_volume='" . sprintf("%.3f", $row['prop2_volume'] * $factor);
+            $sql .= "', prop3_volume='" . sprintf("%.3f", $row['prop3_volume'] * $factor);
+            $sql .= "', prop4_volume='" . sprintf("%.3f", $row['prop4_volume'] * $factor);
+	    $sql .= "', divide_type='" . $divide_type;
+	    $sql .= "', divide_parts='" . $divide_parts;
+            $sql .= "', divide_part='" . $index;
+            $sql .= "', divide_size='" . floatval($split['size']);
+	    $sql .= "', divide_factor='". $factor;
+	    syslog(LOG_NOTICE, "db_divide: index " . $index . " " . $sql);
 	}
-	echo $result;
+    
+	$fermentables = json_decode($row['json_fermentables'], true);
+    	for ($i = 0; $i < count($fermentables); $i++) {
+	    $fermentables[$i]['f_amount'] = sprintf("%.5f", $fermentables[$i]['f_amount'] * $factor);
+    	}
+    	// syslog(LOG_NOTICE, "db_divide: " . str_replace($rescapers,$rreplacements,json_encode($fermentables, JSON_UNESCAPED_UNICODE)));
+    	$sql .= "', json_fermentables='" . str_replace($rescapers,$rreplacements,json_encode($fermentables, JSON_UNESCAPED_UNICODE));
+
+	$hops = json_decode($row['json_hops'], true);
+	for ($i = 0; $i < count($hops); $i++) {
+	    $hops[$i]['h_amount'] = sprintf("%.5f", $hops[$i]['h_amount'] * $factor);
+	}
+	// syslog(LOG_NOTICE, "db_divide: " . str_replace($rescapers,$rreplacements,json_encode($hops, JSON_UNESCAPED_UNICODE)));
+	$sql .= "', json_hops='" . str_replace($rescapers,$rreplacements,json_encode($hops, JSON_UNESCAPED_UNICODE));
+
+	$miscs = json_decode($row['json_miscs'], true);
+	for ($i = 0; $i < count($miscs); $i++) {
+            $miscs[$i]['m_amount'] = sprintf("%.5f", $miscs[$i]['m_amount'] * $factor);
+	}
+	// syslog(LOG_NOTICE, "db_divide: " . str_replace($rescapers,$rreplacements,json_encode($miscs, JSON_UNESCAPED_UNICODE)));
+	$sql .= "', json_miscs='" . str_replace($rescapers,$rreplacements,json_encode($miscs, JSON_UNESCAPED_UNICODE));
+
+	$yeasts = json_decode($row['json_yeasts'], true);
+	for ($i = 0; $i < count($yeasts); $i++) {
+	    $yeasts[$i]['y_amount'] = sprintf("%.5f", $yeasts[$i]['y_amount'] * $factor);
+	}
+	// syslog(LOG_NOTICE, "db_divide: " . str_replace($rescapers,$rreplacements,json_encode($yeasts, JSON_UNESCAPED_UNICODE)));
+	$sql .= "', json_yeasts='" . str_replace($rescapers,$rreplacements,json_encode($yeasts, JSON_UNESCAPED_UNICODE));
 
+	$mashs = json_decode($row['json_mashs'], true);
+	for ($i = 0; $i < count($mashs); $i++) {
+	    $mashs[$i]['step_infuse_amount'] = sprintf("%.5f", $mashs[$i]['step_infuse_amount'] * $factor);
+	}
+	syslog(LOG_NOTICE, "db_divide: " . str_replace($rescapers,$rreplacements,json_encode($mashs, JSON_UNESCAPED_UNICODE)));
+	$sql .= "', json_mashs='" . str_replace($rescapers,$rreplacements,json_encode($mashs, JSON_UNESCAPED_UNICODE));
+
+	if ($index == 0) {
+	    $sql .= "' WHERE record='" . $record . "';";
+	    $result2 = mysqli_query($link, $sql);
+            if (! $result2) {
+                syslog(LOG_NOTICE, "db_divide: result: ".mysqli_error($link));
+            	$rc = 1;
+		break;
+	    } else {
+                syslog(LOG_NOTICE, "db_divide: updated record ".$record." code ".$split['code']);
+            }
+	} else {
+	    $sql .= "';";
+	    $result2 = mysqli_query($link, $sql);
+	    if (! $result2) {
+             	syslog(LOG_NOTICE, "db_divide: result: ".mysqli_error($link));
+		$rc = 1;
+		break;
+            } else {
+	     	$lastid = mysqli_insert_id($link);
+                syslog(LOG_NOTICE, "db_divide: inserted record ".$lastid." code ".$split['code']);
+	    }
+	}
+
+    }
+    syslog(LOG_NOTICE, "db_divide: rc=".$rc);
+    echo $rc;
 } else {
-	// SELECT COMMAND
-	$query = "SELECT * FROM divides ORDER BY divide_from,divide_part";
-	$result = mysqli_query($connect, $query) or die("SQL Error 1: " . mysqli_error($connect));
-	while ($row = mysqli_fetch_array($result, MYSQLI_ASSOC)) {
-		$divides[] = array(
-			'record' => $row['record'],
-			'divide_from' => $row['divide_from'],
-			'divide_type' => $row['divide_type'],
-			'divide_size' => $row['divide_size'],
-			'divide_part' => $row['divide_part'],
-			'name' => $row['name'],
-			'code' => $row['code']
-		);
-	}
-	header("Content-type: application/json");
-	echo json_encode($divides);
+    syslog(LOG_NOTICE, "db_divide: missing arguments");
+    echo 1;
 }
+
+
+
+
 ?>
--- a/www/includes/db_product.php	Mon Oct 21 14:39:49 2019 +0200
+++ b/www/includes/db_product.php	Wed Oct 23 14:20:50 2019 +0200
@@ -263,8 +263,10 @@
 		$sql .= "', prop4_volume='" . $_POST['prop4_volume'];
 	}
 	$sql .= "', divide_type='" . $_POST['divide_type'];
-	$sql .= "', divide_size='" . $_POST['divide_size'];
+	$sql .= "', divide_size='" . floatval($_POST['divide_size']);
+	$sql .= "', divide_factor='" . floatval($_POST['divide_factor']);
 	$sql .= "', divide_parts='" . $_POST['divide_parts'];
+	$sql .= "', divide_part='" . $_POST['divide_part'];
 	//syslog(LOG_NOTICE, $sql);
 
 	$fermentables = '[';
@@ -865,7 +867,9 @@
 
 		$brew .= ',"divide_type":' . $row['divide_type'];
 		$brew .= ',"divide_size":' . floatval($row['divide_size']);
+		$brew .= ',"divide_factor":' . floatval($row['divide_factor']);
 		$brew .= ',"divide_parts":' . $row['divide_parts'];
+		$brew .= ',"divide_part":' . $row['divide_part'];
 
 		if (isset($_GET['record'])) {
 			// Append stock information.
--- a/www/js/prod_divide.js	Mon Oct 21 14:39:49 2019 +0200
+++ b/www/js/prod_divide.js	Wed Oct 23 14:20:50 2019 +0200
@@ -40,10 +40,10 @@
     for (i = 0; i < rows.length; i++) {
      row = rows[i];
      leftover -= row.split_size;
-     //console.log('i:' + i + ' split_size:' + row.split_size);
+     console.log('i:' + i + ' split_size:' + row.split_size);
     }
     $('#leftover').val(leftover);
-    //console.log('calcLeftover():' + leftover);
+    console.log('calcLeftover():' + leftover);
  }
 
  // Calculate available volume but ignore the current row.
@@ -308,25 +308,6 @@
   }
  });
 
- durl = 'includes/db_divides.php',
-
- // Prepare the data
- dividerec = {
-  datatype: 'json',
-  cache: false,
-  datafields: [
-   // From prod_main
-   { name: 'record', type: 'number' },
-   { name: 'divide_from', type: 'string' },
-   { name: 'divide_type', type: 'int' },
-   { name: 'divide_size', type: 'float' },
-   { name: 'name', type: 'string' },
-   { name: 'code', type: 'string' }
-  ],
-  id: 'record',
-  url: durl + '?record=' + my_record
- };
-
  var editSplit = function(data) {
   var splitSource = {
    datatype: 'local',
@@ -479,77 +460,51 @@
   if (leftover != available) {
    console.log('Save and there are splits');
 
-   // Record 0, the master data
-   div = {};
-   div.divide_from = dataRecord.uuid;
-   div.divide_type = dataRecord.divide_type;
-   div.divide_size = leftover;
-   div.divide_part = 0;
-   div.name = dataRecord.name;
-   div.code = dataRecord.code;
-   data = 'insert=true&' + $.param(div);
-   $.ajax({
-     dataType: 'json',
-     url: durl,
-     cache: false,
-     data: data,
-     type: 'POST',
-     success: function(data, status, xhr) {
-      console.log('insert divides: 0');
-     },
-     error: function(jqXHR, textStatus, errorThrown) {
-      console.log('insert divides: ' + textStatus);
-     }
-   });
+   // Send all the info to the database. The server handles the splitting.
+   var divide_data = new Array();
+   row = {};
+   row.name = dataRecord.name;
+   row.code = dataRecord.code;
+   row.size = Round(leftover, 4);
+   row.factor = Round((leftover / available), 4);
+   row.part = 0;
+   divide_data.push(row);
 
    rows = $('#splitGrid').jqxGrid('getrows');
    for (i = 0; i < rows.length; i++) {
     row = rows[i];
     console.log('split ' + i);
     div = {};
-    div.divide_from = dataRecord.uuid;
-    div.divide_type = dataRecord.divide_type;
-    div.divide_size = row.split_size;
-    div.divide_part = i + 1;
+    div.size = Round(row.split_size, 4);
+    div.factor = Round((row.split_size / available), 4);
+    div.part = i + 1;
     div.name = row.split_name;
     div.code = row.split_code;
-    data = 'insert=true&' + $.param(div);
-    $.ajax({
+    divide_data.push(div);
+   }
+
+   // Send the data to the server
+   div = {};
+   div.record = dataRecord.record;
+   div.divide_type = dataRecord.divide_type;
+   div.divide_parts = i;
+   div.divide_data = divide_data;
+   data = $.param(div);
+   $.ajax({
      dataType: 'json',
-     url: durl,
+     url: 'includes/db_divides.php',
      cache: false,
      data: data,
      type: 'POST',
      success: function(data, status, xhr) {
-      console.log('insert divides: ' + i);
+      console.log('insert divides: success');
+      window.location.href = my_return;
      },
      error: function(jqXHR, textStatus, errorThrown) {
       console.log('insert divides: ' + textStatus);
      }
-    });
-   }
+   });
 
-   div = {};
-   div.record = dataRecord.record;
-   div.divide_type = dataRecord.divide_type;
-   div.divide_size = leftover;
-   div.divide_parts = i;
-   data = 'splitit=true&' + $.param(div);
-   $.ajax({
-     dataType: 'json',
-     url: url,
-     cache: false,
-     data: data,
-     type: 'POST',
-     success: function(data, status, xhr) {
-      console.log('updated products');
-     },
-     error: function(jqXHR, textStatus, errorThrown) {
-      console.log('updated products: ' + textStatus);
-     }
-   });
   }
-  window.location.href = my_return;
  });
-
 });
--- a/www/js/prod_edit.js	Mon Oct 21 14:39:49 2019 +0200
+++ b/www/js/prod_edit.js	Wed Oct 23 14:20:50 2019 +0200
@@ -307,7 +307,9 @@
    { name: 'prop4_volume', type: 'float' },
    { name: 'divide_type', type: 'int' },
    { name: 'divide_size', type: 'float' },
+   { name: 'divide_factor', type: 'float' },
    { name: 'divide_parts', type: 'int' },
+   { name: 'divide_part', type: 'int' },
    { name: 'fermentables', type: 'array' },
    { name: 'hops', type: 'array' },
    { name: 'miscs', type: 'array' },
@@ -535,7 +537,9 @@
    $('#prop4_volume').val(dataRecord.prop4_volume);
    $('#divide_type').val(SplitData[dataRecord.divide_type].nl);
    // hidden divide_size
+   // hidden divide_factor
    $('#divide_parts').val(dataRecord.divide_parts);
+   // hidden divide_part
    editFermentable(dataRecord);
    editHop(dataRecord);
    editMisc(dataRecord);
@@ -4379,7 +4383,9 @@
    prop4_volume: parseFloat($('#prop4_volume').jqxNumberInput('decimal')),
    divide_type: dataRecord.divide_type,
    divide_size: dataRecord.divide_size,
+   divide_factor: dataRecord.divide_factor,
    divide_parts: dataRecord.divide_parts,
+   divide_part: dataRecord.divide_part,
    fermentables: $('#fermentableGrid').jqxGrid('getrows'),
    hops: $('#hopGrid').jqxGrid('getrows'),
    miscs: $('#miscGrid').jqxGrid('getrows'),
@@ -4436,7 +4442,7 @@
    calcStage();
   }
  });
- $('#divide_parts').jqxTooltip({ content: 'Het aantal gesplitste brouw producten.' });
+ $('#divide_parts').jqxTooltip({ content: 'Het aantal extra gesplitste brouw producten.' });
  $('#divide_parts').jqxNumberInput(Show0dec);
  $('#divide_type').jqxTooltip({ content: 'Het splitsing moment in het productie proces.' });
  $('#divide_type').jqxInput({ theme: theme, width: 120, height: 23 });
--- a/www/js/prod_new.js	Mon Oct 21 14:39:49 2019 +0200
+++ b/www/js/prod_new.js	Wed Oct 23 14:20:50 2019 +0200
@@ -427,7 +427,9 @@
      starter_enable: 0,
      divide_type: 0,
      divide_size: 0,
-     divide_parts: 0
+     divide_factor: 1,
+     divide_parts: 0,
+     divide_part: 0
     };
     data = 'insert=true&return=' + my_return + '&' + $.param(newrow);
     $.ajax({

mercurial