diff --git a/CHANGELOG.md b/CHANGELOG.md
index 362a715a..7f1edd68 100755
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,17 @@
# CHANGELOG
+### Version 10.7
+- Removed ingredient purity and dilutant from Finished Product page for cleaner view
+- Moved IFRA doc to a modal window
+- Added a print button for the generated IFRA Doc
+- Fix IFRA Document failing to be generated
+- 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
+- Add suppliers in pending formulas backend
+- 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
- 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/core/list_pending_materials_data.php b/core/list_pending_materials_data.php
new file mode 100644
index 00000000..843c8c15
--- /dev/null
+++ b/core/list_pending_materials_data.php
@@ -0,0 +1,50 @@
+
diff --git a/core/pending_formulas_data.php b/core/pending_formulas_data.php
index dc4196e6..acd6eec3 100644
--- a/core/pending_formulas_data.php
+++ b/core/pending_formulas_data.php
@@ -44,36 +44,42 @@
}
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'"));
+ $gING = mysqli_fetch_array(mysqli_query($conn, "SELECT cas, odor FROM ingredients WHERE name = '".$rq['ingredient']."'"));
+ $inventory = mysqli_fetch_array(mysqli_query($conn, "SELECT ingSupplierID, SUM(stock) OVER() AS stock, mUnit FROM suppliers WHERE ingID = '".$rq['ingredient_id']."'"));
+ $supplier = mysqli_fetch_array(mysqli_query($conn, "SELECT id, name FROM ingSuppliers WHERE id = '".$inventory['ingSupplierID']."'"));
+
$repq = mysqli_fetch_array(mysqli_query($conn, "SELECT name FROM ingredients WHERE id = '".$rq['replacement_id']."'"));
-
+
$r['id'] = (int)$rq['id'];
$r['fid'] = (string)$rq['fid'];
$r['repID'] = (string)$rq['replacement_id'];
$r['repName'] = (string)$repq['name'];
$r['name'] = (string)$rq['name'];
- $r['ingredient'] = (string)$rq['ingredient'];
+ $r['ingredient'] = (string)$rq['ingredient'];
$r['ingID'] = (int)$rq['ingredient_id'];
- $r['cas'] = (string)$gING['cas']?:'N/A';
- $r['odor'] = (string)$gING['odor']?:'N/A';
-
+ $r['cas'] = (string)$gING['cas'] ?: 'N/A';
+ $r['odor'] = (string)$gING['odor'] ?: 'N/A';
+
$r['concentration'] = (float)$rq['concentration'];
$r['dilutant'] = (string)$rq['dilutant'] ?: 'None';
- $r['quantity'] = number_format((float)$rq['quantity'], $settings['qStep'],'.', '') ?: 0;
- $r['originalQuantity'] = number_format((float)$rq['originalQuantity'], $settings['qStep'],'.', '') ?: 0;
- $r['overdose'] = number_format((float)$rq['overdose'], $settings['qStep'],'.', '') ?: 0;
-
+ $r['quantity'] = number_format((float)$rq['quantity'], $settings['qStep'], '.', '') ?: 0;
+ $r['originalQuantity'] = number_format((float)$rq['originalQuantity'], $settings['qStep'], '.', '') ?: 0;
+ $r['overdose'] = number_format((float)$rq['overdose'], $settings['qStep'], '.', '') ?: 0;
+
$r['inventory']['stock'] = (float)$inventory['stock'] ?: 0;
$r['inventory']['mUnit'] = (string)$inventory['mUnit'] ?: $settings['mUnit'];
+ $r['inventory'][]['supplier'] = [
+ 'name' => (string)$supplier['name'],
+ 'id' => (string)$supplier['id']
+ ];
+
$r['toAdd'] = (int)$rq['toAdd'];
$r['toSkip'] = (int)$rq['skip'];
-
-
-
- $rx[]=$r;
+
+ $rx[] = $r;
}
+
foreach ($rsq as $rq) {
$mg['total_mg'] += $rq['quantity'];
}
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/func/genBatchPDF.php b/func/genBatchPDF.php
index 8c710642..4333cfa2 100644
--- a/func/genBatchPDF.php
+++ b/func/genBatchPDF.php
@@ -217,16 +217,17 @@ function Code39($xpos, $ypos, $code, $baseline=0.5, $height=5){
}
while ($res_all_ing = mysqli_fetch_array($qAllIng)) {
- $bldQ = mysqli_query($conn, "SELECT ing,name,cas,$defPercentage FROM ingredient_compounds WHERE ing = '".$res_all_ing['ingredient']."'");
- while($bld = mysqli_fetch_array($bldQ)){
- $pdf->Ln();
- $pdf->SetFont('Arial','',8);
-
- $pdf->Cell(68,8,$bld['ing'],1,0,'C');
-
- $pdf->Cell(68,8,$bld['name'],1,0,'C');
- $pdf->Cell(68,8,$bld['cas'],1,0,'C');
- $pdf->Cell(68,8,$bld[$defPercentage],1,0,'C');
+ if($bldQ = mysqli_query($conn, "SELECT ing,name,cas,$defPercentage FROM ingredient_compounds WHERE ing = '".$res_all_ing['ingredient']."'")){
+ while($bld = mysqli_fetch_array($bldQ)){
+ $pdf->Ln();
+ $pdf->SetFont('Arial','',8);
+
+ $pdf->Cell(68,8,$bld['ing'],1,0,'C');
+
+ $pdf->Cell(68,8,$bld['name'],1,0,'C');
+ $pdf->Cell(68,8,$bld['cas'],1,0,'C');
+ $pdf->Cell(68,8,$bld[$defPercentage],1,0,'C');
+ }
}
}
diff --git a/index.php b/index.php
index 97a62bf7..1db7709a 100755
--- a/index.php
+++ b/index.php
@@ -183,7 +183,7 @@ function chkUpdate() {
" href="/?do=compareFormulas">Compare Formulas
Finished Product
Sell Formula
- Scheduled Formulas
+ Scheduled Formulas
Batch history
@@ -312,8 +312,8 @@ function chkUpdate() {
require_once(__ROOT__.'/pages/addLid.php');
}elseif($_GET['do'] == 'batches'){
require_once(__ROOT__.'/pages/views/formula/batches.php');
- }elseif($_GET['do'] == 'todo'){
- require_once(__ROOT__.'/pages/todo.php');
+ }elseif($_GET['do'] == 'scheduledFormulas'){
+ require_once(__ROOT__.'/pages/scheduledFormulas.php');
}elseif($_GET['do'] == 'cart'){
require_once(__ROOT__.'/pages/cart.php');
}elseif($_GET['do'] == 'suppliers'){
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 = '';
+ $('#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 = '';
+ reload_data();
+ } else {
+ var msg = '';
+ }
+ $('#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 = '';
+ $('#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 = '';
+ reload_data();
+ } else {
+ var msg = '';
+ }
+ $('#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/dashboard.php b/pages/dashboard.php
index e7c8fbc5..67d3ae1b 100755
--- a/pages/dashboard.php
+++ b/pages/dashboard.php
@@ -183,7 +183,7 @@
diff --git a/pages/genFinishedProduct.php b/pages/genFinishedProduct.php
index 5da51b7f..34fd44d6 100644
--- a/pages/genFinishedProduct.php
+++ b/pages/genFinishedProduct.php
@@ -45,7 +45,7 @@
$carrier = $bottle - $new_conc;
if(validateFormula($meta['fid'], $bottle, $new_conc, $mg['total_mg'], $defCatClass, $settings['qStep'], $conn) == TRUE){
- $msg = '
Your formula contains materials, exceeding and/or missing IFRA standards. Please alter your formula.
';
+ $msg = '
Your formula contains materials, exceeding and/or missing IFRA standards. Please alter your formula
';
}
if($_POST['ingSup']){
@@ -101,9 +101,7 @@
Actions
@@ -111,13 +109,11 @@
- Ingredient
- CAS#
- Purity%
- Dilutant
- Quantity
- Concentration
- Cost
+ Ingredient
+ CAS#
+ Quantity (=$settings['mUnit']?>)
+ Concentration%
+ Cost ()
=$formula['ingredient']?>
- =$ing_q['cas']?>
- =$formula['concentration']?>
-
- None
-
- =$formula['dilutant']?>
+ =$ing_q['cas']?>
-
-
Sub Total:
=$settings['mUnit']?>
@@ -190,8 +179,6 @@
-
-
Carrier/Solvent:
=$settings['mUnit']?>
@@ -199,8 +186,6 @@
-
-
Bottle:
=$settings['mUnit']?>
@@ -208,8 +193,6 @@
-
-
Lid:
@@ -217,8 +200,6 @@
-
-
Batch No:
@@ -226,8 +207,6 @@
-
-
-
Total:
=$settings['mUnit']?>
@@ -236,11 +215,8 @@
-
-
-
*Values in: red exceeds usage level, yellow have no usage level set, green are within usage level, blue are exceeding recommended usage level
-
-
+
+
*Values in: red exceeds usage level, dark red banned/prohibited, yellow Specification,green are within usage level,blue are exceeding recommended usage level
@@ -269,11 +245,8 @@
Generate IFRA Document
-
- IMPORTANT: The generated document isn't an official IFRA certificate and needs to be reviewed by a certified person. Also, data needs to be properly verified to make sure there are no errors.
-
+
IMPORTANT: The generated document isn't an official IFRA certificate and needs to be reviewed by a certified person. Also, data needs to be properly verified to make sure there are no errors.
-
INFO: You need to create at least one formula first.';
+ echo 'INFO: You need to
create at least one formula first.
';
return;
}
if(mysqli_num_rows(mysqli_query($conn, "SELECT id FROM bottles"))== 0){
- echo 'INFO: You need to
add at least one bottle in your inventory first.
';
+ echo 'INFO: You need to
add at least one bottle in your inventory first.
';
return;
}
if(mysqli_num_rows(mysqli_query($conn, "SELECT id FROM ingredients WHERE type = 'Carrier' OR type = 'Solvent'"))== 0){
- echo 'INFO: You need to
add at least one solvent or carrier first.
';
+ echo 'INFO: You need to
add at least one solvent or carrier first.
';
return;
}
@@ -332,7 +304,7 @@
$fTypes[] = $fTypes_res;
}
?>
-