From 7d1f42a3d2ec548d843065317b2d68025e0fc32f Mon Sep 17 00:00:00 2001 From: JB Date: Fri, 26 Jul 2024 23:31:30 +0100 Subject: [PATCH 01/10] - v10.7 --- CHANGELOG.md | 2 ++ VERSION.md | 2 +- db/schema.ver | 2 +- releasenotes.md | 5 +---- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 362a715a..6b8dc08f 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,6 @@ # CHANGELOG +### Version 10.7 + ### Version 10.6 - Ingredient Where Used page minor improvements - Ingredient Usage & Limits page minor improvements diff --git a/VERSION.md b/VERSION.md index 12c0281a..4e74f9f0 100755 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -10.6 +10.7 diff --git a/db/schema.ver b/db/schema.ver index 12c0281a..4e74f9f0 100644 --- a/db/schema.ver +++ b/db/schema.ver @@ -1 +1 @@ -10.6 +10.7 diff --git a/releasenotes.md b/releasenotes.md index d6ef9e01..29108998 100755 --- a/releasenotes.md +++ b/releasenotes.md @@ -1,6 +1,3 @@ -Whats New in v10.6 +Whats New in v10.7 -------------------------- -- Respect classification type from the IFRA Library -- Added banned/prohibited materials in the formula legend -- Discord invite update - This release may include more changes, for full details please refer to the CHANGELOG From 36ceba0cb0e288349436dd0bb21ed67b6e1e4952 Mon Sep 17 00:00:00 2001 From: JB Date: Sat, 27 Jul 2024 09:56:42 +0100 Subject: [PATCH 02/10] - Show available stock from all the available suppliers when making a formula, instead of the preferred one only --- CHANGELOG.md | 1 + core/pending_formulas_data.php | 2 +- releasenotes.md | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b8dc08f..93d24e84 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # CHANGELOG ### Version 10.7 +- Show available stock from all the available suppliers when making a formula, instead of the preferred one only ### Version 10.6 - Ingredient Where Used page minor improvements diff --git a/core/pending_formulas_data.php b/core/pending_formulas_data.php index dc4196e6..9ee84fed 100644 --- a/core/pending_formulas_data.php +++ b/core/pending_formulas_data.php @@ -45,7 +45,7 @@ foreach ($rs as $rq) { $gING = mysqli_fetch_array(mysqli_query($conn, "SELECT cas,odor FROM ingredients WHERE name = '".$rq['ingredient']."'")); - $inventory = mysqli_fetch_array(mysqli_query($conn, "SELECT stock,mUnit FROM suppliers WHERE ingID = '".$rq['ingredient_id']."' AND preferred = '1'")); + $inventory = mysqli_fetch_array(mysqli_query($conn, "SELECT SUM(stock) AS stock,mUnit FROM suppliers WHERE ingID = '".$rq['ingredient_id']."' ")); $repq = mysqli_fetch_array(mysqli_query($conn, "SELECT name FROM ingredients WHERE id = '".$rq['replacement_id']."'")); $r['id'] = (int)$rq['id']; diff --git a/releasenotes.md b/releasenotes.md index 29108998..318c5464 100755 --- a/releasenotes.md +++ b/releasenotes.md @@ -1,3 +1,4 @@ Whats New in v10.7 -------------------------- +- Show available stock from all the available suppliers when making a formula, instead of the preferred one only - This release may include more changes, for full details please refer to the CHANGELOG From 40d73e1c2d662cabadc3af1beda84dc723d046cf Mon Sep 17 00:00:00 2001 From: JB Date: Sat, 27 Jul 2024 10:50:30 +0100 Subject: [PATCH 03/10] - Choose which supplier you updating the stock when making a formula --- CHANGELOG.md | 1 + pages/makeFormula.php | 39 ++++++++++++++++++++++++++++++++++++--- pages/manageFormula.php | 16 +++++++++++++--- releasenotes.md | 1 + 4 files changed, 51 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 93d24e84..cb8b65d6 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # CHANGELOG ### Version 10.7 +- Choose which supplier you updating the stock when making a formula - Show available stock from all the available suppliers when making a formula, instead of the preferred one only ### Version 10.6 diff --git a/pages/makeFormula.php b/pages/makeFormula.php index 409a64ee..9c35d74c 100644 --- a/pages/makeFormula.php +++ b/pages/makeFormula.php @@ -26,6 +26,12 @@ $msg = ''; } +//$res_ingSupplier = mysqli_query($conn, "SELECT id,name FROM ingSuppliers ORDER BY name ASC"); + +$qS = mysqli_query($conn, "SELECT id,name FROM ingSuppliers ORDER BY name ASC"); + while($res = mysqli_fetch_array($qS)){ + $res_ingSupplier[] = $res; + } ?> @@ -118,6 +124,15 @@ diff --git a/pages/views/formula/pendingMaterials.php b/pages/views/formula/pendingMaterials.php new file mode 100644 index 00000000..950da32b --- /dev/null +++ b/pages/views/formula/pendingMaterials.php @@ -0,0 +1,104 @@ + +
+
+
+ + +
+ + + + + + + + + + +
FormulaIngredientCAS#QuantityBuy
+
+ + + + \ No newline at end of file diff --git a/releasenotes.md b/releasenotes.md index e62ee4bc..8e33d264 100755 --- a/releasenotes.md +++ b/releasenotes.md @@ -1,5 +1,6 @@ Whats New in v10.7 -------------------------- +- Added a pending materials page to list all pending materials and their quantity required for the pending formulas - Choose which supplier you updating the stock when making a formula - Show available stock from all the available suppliers when making a formula, instead of the preferred one only - This release may include more changes, for full details please refer to the CHANGELOG From 3c94248918154e37f214adf1ae4f8ef58bd2316f Mon Sep 17 00:00:00 2001 From: JB Date: Wed, 31 Jul 2024 18:09:05 +0100 Subject: [PATCH 06/10] - Added inventory for pending ingredients - Refactor of the Formula Make page --- CHANGELOG.md | 1 + core/list_pending_materials_data.php | 6 + js/makeFormula.js | 374 ++++++++++++++++++++ pages/makeFormula.php | 419 ++++------------------- pages/views/formula/pendingMaterials.php | 26 +- 5 files changed, 467 insertions(+), 359 deletions(-) create mode 100644 js/makeFormula.js diff --git a/CHANGELOG.md b/CHANGELOG.md index bc63cc44..03ed6bbf 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # CHANGELOG ### Version 10.7 +- Formula Make page refactor - Lids page minor update - Added a pending materials page to list all pending materials and their quantity required for the pending formulas - todo.php has been renamed to scheduledFormulas.php diff --git a/core/list_pending_materials_data.php b/core/list_pending_materials_data.php index d8d9373c..843c8c15 100644 --- a/core/list_pending_materials_data.php +++ b/core/list_pending_materials_data.php @@ -3,6 +3,7 @@ require_once(__ROOT__.'/inc/sec.php'); require_once(__ROOT__.'/inc/opendb.php'); +require_once(__ROOT__.'/inc/settings.php'); require_once(__ROOT__.'/func/getIngSupplier.php'); $q = mysqli_query($conn, "SELECT name,ingredient,ingredient_id,quantity FROM makeFormula WHERE toAdd = '1' AND skip = '0'"); @@ -13,11 +14,16 @@ foreach ($m as $material) { $ing = mysqli_fetch_array(mysqli_query($conn,"SELECT cas FROM ingredients WHERE id = '".$material['ingredient_id']."'")); + $inventory = mysqli_fetch_array(mysqli_query($conn, "SELECT SUM(stock) OVER() AS stock, mUnit FROM suppliers WHERE ingID = '".$material['ingredient_id']."'")); + $r['formula'] = (string)$material['name']; $r['ingredient'] = (string)$material['ingredient']; $r['quantity'] = (string)$material['quantity']; $r['cas'] = (string)$ing['cas'] ?: "N/A"; + $r['inventory']['stock'] = (float)$inventory['stock'] ?: 0; + $r['inventory']['mUnit'] = (string)$inventory['mUnit'] ?: $settings['mUnit']; + if($a = getIngSupplier($material['ingredient_id'],0,$conn)){ $j = 0; unset($r['supplier']); diff --git a/js/makeFormula.js b/js/makeFormula.js new file mode 100644 index 00000000..cdf9c078 --- /dev/null +++ b/js/makeFormula.js @@ -0,0 +1,374 @@ +//MAKE FORMULA js HELPERS +$(document).ready(function() { + + +$('#tdDataPending').on('click', '[data-bs-target*=confirm_add]', function () { + var ingID = $(this).data('ing-id'); + var ingredient = $(this).data('ingredient'); + var rowID = $(this).data('row-id'); + var quantity = $(this).data('quantity'); + var qr = $(this).data('qr'); + + // Clear previous error messages and reset input fields + $('#errMsg').html(''); + $("#ingAdded").text(ingredient); + $("#ingID").text(ingID); + $("#idRow").text(rowID); + $("#amountAdded").val(quantity); + $("#qr").text(qr); + $("#updateStock").prop("checked", true); + $('#supplier').prop('disabled', false); + $("#notes").val(''); + $("#collapseAdvanced").removeClass('show'); + + $('#msgReplace').html(''); + $("#replacement").val(''); + + + // Initialize the replacement select2 component + $("#replacement").select2({ + width: '100%', + placeholder: 'Search for ingredient (name)..', + allowClear: true, + dropdownAutoWidth: true, + containerCssClass: "replacement", + dropdownParent: $('#confirm_add .modal-content'), + templateResult: formatIngredients, + templateSelection: formatIngredientsSelection, + ajax: { + url: '/pages/views/ingredients/getIngInfo.php', + dataType: 'json', + type: 'GET', + delay: 100, + quietMillis: 250, + data: function (params) { + return { + ingID: ingID, + replacementsOnly: true, + search: params.term + }; + }, + processResults: function(data) { + return { + results: $.map(data.data, function(obj) { + return { + id: obj.id, + stock: obj.stock, + name: obj.name + }; + }) + }; + }, + cache: false, + } + }).on('select2:selecting', function (e) { + repName = e.params.args.data.name; + repID = e.params.args.data.id; + }); + + // Initialize the supplier select2 component + $("#supplier").select2({ + width: '100%', + placeholder: 'Search for supplier (name)', + allowClear: true, + dropdownAutoWidth: true, + containerCssClass: "supplier", + templateResult: formatSuppliers, + templateSelection: formatSuppliersSelection, + dropdownParent: $('#confirm_add .modal-content'), + minimumResultsForSearch: -1, + ajax: { + url: '/core/list_ing_suppliers_data.php', + dataType: 'json', + type: 'GET', + delay: 100, + quietMillis: 250, + data: function (params) { + return { + id: ingID + }; + }, + processResults: function(data) { + return { + results: $.map(data.data, function(obj) { + return { + id: obj.ingSupplierID, + name: obj.supplierName + }; + }) + }; + }, + cache: true, + } + }).on('select2:selecting', function (e) { + suppName = e.params.args.data.name; + suppID = e.params.args.data.id; + }); +}); + + + + +function formatIngredients (ingredientData) { + if (ingredientData.loading) { + return ingredientData.name; + } + + if (!ingredientData.name){ + return 'No replacement found...'; + } + + + var $container = $( + "
" + + "
" + + "
" + + "
"+ + "
" + + "
" + ); + + $container.find(".select_igredient_title").text(ingredientData.name); + if(ingredientData.stock > 0){ + $container.find("#stock").text('In stock ('+ingredientData.stock+')'); + $container.find("#stock").attr("class", "stock badge badge-instock"); + }else{ + $container.find("#stock").text('Not in stock ('+ingredientData.stock+')'); + $container.find("#stock").attr("class", "stock badge badge-nostock"); + } + + return $container; +} + + +function formatIngredientsSelection (ingredientData) { + return ingredientData.name; +} + +function formatSuppliers (supplierData) { + if (supplierData.loading) { + return supplierData.name; + } + + if (!supplierData.name){ + return 'No supplier found...'; + } + + + var $container = $( + "
" + + "
" + + "
" + ); + + $container.find(".select_supplier_name").text(supplierData.name); + + return $container; +} + + +function formatSuppliersSelection (supplierData) { + return supplierData.name; +} + + //UPDATE AMOUNT + $('#addedToFormula').click(function() { + $.ajax({ + url: '/pages/manageFormula.php', + type: 'POST', + data: { + action: "makeFormula", + q: $("#amountAdded").val(), + notes: $("#notes").val(), + qr: $("#qr").text(), + updateStock: $("#updateStock").is(':checked'), + supplier: $("#supplier").val(), + ing: $("#ingAdded").text(), + id: $("#idRow").text(), + repName: repName, + repID: repID, + ingId: $("#ingID").text(), + fid: fid, + }, + dataType: 'json', + success: function (data) { + if(data.success){ + $('#toast-title').html('' + data.success); + $('.toast-header').removeClass().addClass('toast-header alert-success'); + $('#confirm_add').modal('toggle'); + reload_data(); + $('.toast').toast('show'); + } else if(data.error) { + var msg = '
x' + data.error + '
'; + $('#errMsg').html(msg); + } + } + }); + }); + + + $('#markComplete, #markCompleteMenu').click(function() { + bootbox.dialog({ + title: "Confirm formula completion", + message : "Mark formula as complete?", + buttons :{ + main: { + label : "Mark as complete", + className : "btn-warning", + callback: function (){ + $.ajax({ + url: '/pages/manageFormula.php', + type: 'POST', + data: { + action: "todo", + markComplete: 1, + totalQuantity: total_quantity, + fid: fid + }, + dataType: 'json', + success: function (data) { + if(data.success) { + var msg = '
x' + data.success + '
'; + reload_data(); + } else { + var msg = '
x' + data.error + '
'; + } + $('#msg').html(msg); + } + }); + + return true; + } + }, + cancel: { + label : "Cancel", + className : "btn-secondary", + callback : function() { + return true; + } + } + },onEscape: function () {return true;} + + }); + }); + + //SKIP ADD + $('#skippedFromFormula').click(function() { + $.ajax({ + url: '/pages/manageFormula.php', + type: 'POST', + data: { + action: "skipMaterial", + notes: $("#skip_notes").val(), + ing: $("#ingSkipped").text(), + id: $("#idRow").text(), + ingId: $("#ingID").text(), + fid: fid, + }, + dataType: 'json', + success: function (data) { + if(data.success){ + $('#toast-title').html('' + data.success); + $('.toast-header').removeClass().addClass('toast-header alert-success'); + $('#confirm_skip').modal('toggle'); + reload_data(); + $('.toast').toast('show'); + } else if(data.error) { + var msg = '
x' + data.error + '
'; + $('#errMsg').html(msg); + } + } + }); + }); + + //ADD TO CART + $('#tdDataPending').on('click', '[id*=addToCart]', function () { + $.ajax({ + url: '/pages/manageFormula.php', + type: 'POST', + data: { + action: "addToCart", + material: $(this).attr('data-ingredient'), + purity: $(this).attr('data-concentration'), + quantity: $(this).attr('data-quantity'), + ingID: $(this).attr('data-ingID') + }, + dataType: 'json', + success: function (data) { + if(data.success) { + var msg = '
x' + data.success + '
'; + reload_data(); + } else { + var msg = '
x' + data.error + '
'; + } + $('#msg').html(msg); + } + }); + }); + + $('#tdDataPending').on('click', '[id*=ingInfo]', function () { + var id = $(this).data('id'); + var name = $(this).data('name'); + + $('.modal-title').html(name); + $('.modal-body-info').html('loading'); + + $.ajax({ + type: 'GET', + url: '/pages/views/ingredients/getIngInfo.php', + data:{ + ingID: id + }, + success: function(data) { + $('.modal-body-info').html(data); + }, + error:function(err){ + data = '
Unable to get ingredient info
'; + $('.modal-body-info').html(data); + } + }) + }); + + + $('#title').click(function() { + $('#msg').html(''); + }); + + $('#print').click(() => { + $('#tdDataPending').DataTable().button(0).trigger(); + }); + + + $('#tdDataPending').on('click', '[data-bs-target*=confirm_skip]', function () { + $('#errMsg').html(''); + $("#ingSkipped").text($(this).attr('data-ingredient')); + $("#ingID").text($(this).attr('data-ing-id')); + $("#idRow").text($(this).attr('data-row-id')); + $("#notes").val(''); + }); + + function reload_data() { + $('#tdDataPending').DataTable().ajax.reload(null, true); + } + + + $('.export_as').click(function() { + var format = $(this).attr('data-format'); + $("#tdDataPending").tableHTMLExport({ + type: format, + filename: myFNAME + "." + format, + separator: ',', + newline: '\r\n', + trimContent: true, + quoteFields: true, + ignoreColumns: '.noexport', + ignoreRows: '.noexport', + htmlContent: false, + orientation: 'l', + subtitle: 'Created with Perfumer\'s Vault Pro', + maintitle: myFNAME, + }); + }); + + +}); \ No newline at end of file diff --git a/pages/makeFormula.php b/pages/makeFormula.php index 69d3415f..1182ee04 100644 --- a/pages/makeFormula.php +++ b/pages/makeFormula.php @@ -28,9 +28,10 @@ } $qS = mysqli_query($conn, "SELECT id,name FROM ingSuppliers ORDER BY name ASC"); - while($res = mysqli_fetch_array($qS)){ - $res_ingSupplier[] = $res; - } +while($res = mysqli_fetch_array($qS)){ + $res_ingSupplier[] = $res; +} + ?> @@ -122,7 +123,12 @@ - + + @@ -332,7 +307,7 @@ $fTypes[] = $fTypes_res; } ?> -
+
@@ -441,6 +416,27 @@
+ + +