diff --git a/CHANGELOG.md b/CHANGELOG.md index 02aaaa15..d03ed4e1 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,23 @@ # CHANGELOG +### Version 11.3 +- Minor UI updates +- Fix merge ingredient returning incorrect value when nothing found +- Fix placeholder for ingredient selection in formula +- Added force delete for ingredients in use +- A new updated IFRA document added +- IFRA document will show the maximum limit per all categories for 100% concentration +- IFRA document will be generated regardless if final product is off ifra limits +- Fixed currency symbol for finished product +- Ingredient UI update +- Formula UI and backend update +- Structure update +- UI update for IFRA Library +- Refactor JSON import for IFRALibrary +- Increase filter box size +- Extended search to the product name for Batches +- Added delete option for Batches even if the pdf is missing +- Batches backend rewrite + ### Version 11.2 - Refactor of backend - Fix author name not display properly in the contact form in Marketplace diff --git a/VERSION.md b/VERSION.md index 26d6dad9..8bb42223 100755 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -11.2 +11.3 diff --git a/core/finished_formula_data.php b/core/finished_formula_data.php index 01352ad7..e233e107 100644 --- a/core/finished_formula_data.php +++ b/core/finished_formula_data.php @@ -190,7 +190,7 @@ $m['cat_class'] = (string)$defCatClass; -$m['currency'] = (string)utf8_encode($settings['currency']); +$m['currency'] = (string)$settings['currency']; $m['product_concentration'] = (int)$concentration; $m['formula_name'] = (string)$meta['name']; $m['product_name'] = (string)$meta['product_name'] ?: '-'; diff --git a/core/full_formula_data.php b/core/full_formula_data.php index 7aed4a79..54fb8670 100644 --- a/core/full_formula_data.php +++ b/core/full_formula_data.php @@ -274,6 +274,8 @@ if(empty($r)){ $response['data'] = []; + echo json_encode($response); + return; } $m['total_ingredients'] = (int)countElement("formulas WHERE fid = '".$meta['fid']."'",$conn); diff --git a/core/getIngInfo.php b/core/getIngInfo.php new file mode 100644 index 00000000..1f905f36 --- /dev/null +++ b/core/getIngInfo.php @@ -0,0 +1,41 @@ + \ No newline at end of file diff --git a/core/list_batch_data.php b/core/list_batch_data.php index ad88e1c8..02825100 100644 --- a/core/list_batch_data.php +++ b/core/list_batch_data.php @@ -5,55 +5,81 @@ require_once(__ROOT__.'/inc/opendb.php'); require_once(__ROOT__.'/inc/settings.php'); -$row = $_POST['start']?:0; -$limit = $_POST['length']?:10; +$row = isset($_POST['start']) ? (int)$_POST['start'] : 0; +$limit = isset($_POST['length']) ? (int)$_POST['length'] : 10; -$order_by = $_POST['order_by']?:'created'; -$order = $_POST['order_as']?:'ASC'; -$extra = "ORDER BY ".$order_by." ".$order; +$order_by = isset($_POST['order_by']) ? $_POST['order_by'] : 'created'; +$order = isset($_POST['order_as']) && in_array(strtoupper($_POST['order_as']), ['ASC', 'DESC']) ? strtoupper($_POST['order_as']) : 'ASC'; +$extra = "ORDER BY $order_by $order"; -$s = trim($_POST['search']['value']); +$search_value = isset($_POST['search']['value']) ? trim($_POST['search']['value']) : ''; +$f = ''; -if($s != ''){ - $f = "WHERE 1 AND (id LIKE '%".$s."%')"; +if (!empty($search_value)) { + $f = "WHERE id LIKE ? OR product_name LIKE ?"; } -$q = mysqli_query($conn, "SELECT * FROM batchIDHistory $f $extra LIMIT $row, $limit"); -while($res = mysqli_fetch_array($q)){ +$query = "SELECT * FROM batchIDHistory $f $extra LIMIT ?, ?"; +$stmt = $conn->prepare($query); + +if (!empty($search_value)) { + $search_param = "%$search_value%"; + $stmt->bind_param('ssii', $search_param, $search_param, $row, $limit); +} else { + $stmt->bind_param('ii', $row, $limit); +} + +$stmt->execute(); +$result = $stmt->get_result(); + +$rs = []; +while ($res = $result->fetch_assoc()) { $rs[] = $res; } -foreach ($rs as $rq) { - - if(file_exists(__ROOT__.'/'.$rq['pdf']) === TRUE){ - $s = 1; - } - - $r['id'] = (string)$rq['id']; - $r['fid'] = (string)$rq['fid']; - $r['product_name'] = (string)$rq['product_name']?:'N/A'; - $r['pdf'] = (string)$rq['pdf']; - $r['state'] = (int)$s?:0; - $r['created'] = (string)$rq['created']; - - $rx[]=$r; +$rx = []; +foreach ($rs as $rq) { + $state = 0; + if (file_exists(__ROOT__.'/'.$rq['pdf'])) { + $state = 1; + } + + $r = [ + 'id' => (string)$rq['id'], + 'fid' => (string)$rq['fid'], + 'product_name' => (string)$rq['product_name'] ?: 'N/A', + 'pdf' => (string)$rq['pdf'], + 'state' => (int)$state, + 'created' => (string)$rq['created'] + ]; + + $rx[] = $r; } -$total = mysqli_fetch_assoc(mysqli_query($conn,"SELECT COUNT(id) AS entries FROM batchIDHistory")); -$filtered = mysqli_fetch_assoc(mysqli_query($conn,"SELECT COUNT(id) AS entries FROM batchIDHistory ".$f)); - -$response = array( - "draw" => (int)$_POST['draw'], - "recordsTotal" => (int)$total['entries'], - "recordsFiltered" => (int)$filtered['entries'], - "data" => $rx -); - -if(empty($r)){ - $response['data'] = []; + +$total_query = "SELECT COUNT(id) AS entries FROM batchIDHistory"; +$total_result = mysqli_fetch_assoc(mysqli_query($conn, $total_query)); + +$filtered_query = "SELECT COUNT(id) AS entries FROM batchIDHistory $f"; +$filtered_stmt = $conn->prepare($filtered_query); + +if (!empty($search_value)) { + $filtered_stmt->bind_param('ss', $search_param, $search_param); } +$filtered_stmt->execute(); +$filtered_result = $filtered_stmt->get_result(); +$filtered = $filtered_result->fetch_assoc(); + +$response = [ + "draw" => isset($_POST['draw']) ? (int)$_POST['draw'] : 1, + "recordsTotal" => (int)$total_result['entries'], + "recordsFiltered" => (int)$filtered['entries'], + "data" => !empty($rx) ? $rx : [] +]; header('Content-Type: application/json; charset=utf-8'); echo json_encode($response); + return; + ?> diff --git a/css/vault.css b/css/vault.css index 3bec2a72..9ba2e069 100755 --- a/css/vault.css +++ b/css/vault.css @@ -1410,8 +1410,17 @@ hr.hr-text::before { } .dataTables_filter input { - width: 400px; - display: inline-block; + width: 400px !important; + height: 40px; + padding: 10px; + font-size: 16px; +} + +.pvCustomSearch { + width: 400px; + height: 40px; + padding: 10px; + font-size: 16px; } input[type="search"]::-webkit-search-cancel-button { diff --git a/db/pvault.sql b/db/pvault.sql index 568c3141..2def9f5b 100755 --- a/db/pvault.sql +++ b/db/pvault.sql @@ -669,7 +669,97 @@ CREATE TABLE `templates` ( UNIQUE KEY `id` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci; -INSERT INTO `templates` (`id`, `name`, `content`, `created`, `updated`, `description`) VALUES (NULL, 'IFRA Certification Template', '\r\n\r\n
\r\n \r\n \r\n \r\n \r\n\r\n\r\n\r\nThis Certificate assesses the conformity of a fragrance mixture with IFRA Standards and provides restrictions for use as necessary. It is based only on those materials subject to IFRA Standards for the toxicity endpoint(s) described in each Standard. \r\n
\r\n
\r\n
CERTIFYING PARTY:
\r\n%BRAND_NAME%
\r\n%BRAND_ADDRESS%
\r\n%BRAND_EMAIL%
\r\n%BRAND_PHONE%
\r\n\r\n\r\n \r\nCERTIFICATE DELIVERED TO: \r\n
\r\nCustomer:
\r\n%CUSTOMER_NAME%
\r\n%CUSTOMER_ADDRESS%
\r\n%CUSTOMER_EMAIL%
\r\n%CUSTOMER_WEB%
\r\n\r\n\r\n
\r\n
SCOPE OF THE CERTIFICATE:
\r\nProduct: %PRODUCT_NAME%
\r\nSize: %PRODUCT_SIZE%ml
\r\nConcentration: %PRODUCT_CONCENTRATION%%
\r\n\r\n We certify that the above mixture is in compliance with the Standards of the INTERNATIONAL FRAGRANCE ASSOCIATION (IFRA), up to and including the %IFRA_AMENDMENT% Amendment to the IFRA Standards (published %IFRA_AMENDMENT_DATE%),\r\n provided it is used in the following category(ies)\r\n at a maximum concentration level of:
\r\n\r\n
IFRA Category(ies) | \r\nLevel of use (%)* | \r\n
---|---|
%PRODUCT_CAT_CLASS% | \r\n%PRODUCT_TYPE% | \r\n
*Actual use level or maximum use level
\r\n\r\n For other kinds of, application or use at higher concentration levels, a new evaluation may be needed; please contact %BRAND_NAME%.\r\n
\r\nInformation about presence and concentration of fragrance ingredients subject to IFRA Standards in the fragrance mixture %PRODUCT_NAME% is as follows:
\r\n\r\n
Material(s) under the scope of IFRA Standards: | \r\nCAS number(s): | \r\nRecommendation (%) from IFRA Standard: | \r\nConcentration (%) in finished product: | \r\nRisk | \r\n
---|
\r\n
Signature (If generated electronically, no signature)
\r\nDate: %CURRENT_DATE%
\r\n \r\n\r\n Disclaimer:\r\n
\r\nThis Certificate provides restrictions for use of the specified product based only on those materials restricted by IFRA Standards for the toxicity endpoint(s) described in each Standard.
\r\nThis Certificate does not provide certification of a comprehensive safety assessment of all product constituents.
\r\nThis certificate is the responsibility of the fragrance supplier issuing it. It has not been prepared or endorsed by IFRA in anyway. \r\n
\r\nThis Certificate assesses the conformity of a fragrance mixture with IFRA Standards and provides restrictions for use as necessary. It is based only on those materials subject to IFRA Standards for the toxicity endpoint(s) described in each Standard. +
+
+
CERTIFYING PARTY:
+%BRAND_NAME%
+%BRAND_ADDRESS%
+%BRAND_EMAIL%
+%BRAND_PHONE%
+ + + +CERTIFICATE DELIVERED TO: +
+Customer:
+%CUSTOMER_NAME%
+%CUSTOMER_ADDRESS%
+%CUSTOMER_EMAIL%
+%CUSTOMER_WEB%
+ +
+
SCOPE OF THE CERTIFICATE:
+Product: %PRODUCT_NAME%
+Size: %PRODUCT_SIZE%ml
+Concentration: %PRODUCT_CONCENTRATION%%
++ We certify that the above mixture is in compliance with the Standards of the INTERNATIONAL FRAGRANCE ASSOCIATION (IFRA), up to and including the %IFRA_AMENDMENT% Amendment to the IFRA Standards (published %IFRA_AMENDMENT_DATE%), + provided it is used in the following category(ies) + at a maximum concentration level of:
++
IFRA Category | +Description | +Level of use (%)* | +
---|---|---|
%IFRA_CAT_LIST% | +
*Actual use level or maximum use level at 100% concentration
++ For other kinds of, application or use at higher concentration levels, a new evaluation may be needed; please contact %BRAND_NAME%. +
+Information about presence and concentration of fragrance ingredients subject to IFRA Standards in the fragrance mixture %PRODUCT_NAME% is as follows:
++
Material(s) under the scope of IFRA Standards: | +CAS number(s): | +Recommendation (%) from IFRA Standard: | +Concentration (%) in finished product: | +Risk | +
---|
+
Signature (If generated electronically, no signature)
+Date: %CURRENT_DATE%
+ ++ Disclaimer: +
+This Certificate provides restrictions for use of the specified product based only on those materials restricted by IFRA Standards for the toxicity endpoint(s) described in each Standard.
+This Certificate does not provide certification of a comprehensive safety assessment of all product constituents.
+This certificate is the responsibility of the fragrance supplier issuing it. It has not been prepared or endorsed by IFRA in anyway. +
+\n Label elements according to the regulation (EC) n°1272/2008 (CLP) and its amendments\n
\nName | \nCAS | \nEINES | \nMin percentage | \nMax percentage | \nGHS | \n %CMP_MATERIALS_LIST%\n \n
---|
This Certificate assesses the conformity of a fragrance mixture with IFRA Standards and provides restrictions for use as necessary. It is based only on those materials subject to IFRA Standards for the toxicity endpoint(s) described in each Standard. +
+
+
CERTIFYING PARTY:
+%BRAND_NAME%
+%BRAND_ADDRESS%
+%BRAND_EMAIL%
+%BRAND_PHONE%
+ + + +CERTIFICATE DELIVERED TO: +
+Customer:
+%CUSTOMER_NAME%
+%CUSTOMER_ADDRESS%
+%CUSTOMER_EMAIL%
+%CUSTOMER_WEB%
+ +
+
SCOPE OF THE CERTIFICATE:
+Product: %PRODUCT_NAME%
+Size: %PRODUCT_SIZE%ml
+Concentration: %PRODUCT_CONCENTRATION%%
++ We certify that the above mixture is in compliance with the Standards of the INTERNATIONAL FRAGRANCE ASSOCIATION (IFRA), up to and including the %IFRA_AMENDMENT% Amendment to the IFRA Standards (published %IFRA_AMENDMENT_DATE%), + provided it is used in the following category(ies) + at a maximum concentration level of:
++
IFRA Category | +Description | +Level of use (%)* | +
---|---|---|
%IFRA_CAT_LIST% | +
*Actual use level or maximum use level at 100% concentration
++ For other kinds of, application or use at higher concentration levels, a new evaluation may be needed; please contact %BRAND_NAME%. +
+Information about presence and concentration of fragrance ingredients subject to IFRA Standards in the fragrance mixture %PRODUCT_NAME% is as follows:
++
Material(s) under the scope of IFRA Standards: | +CAS number(s): | +Recommendation (%) from IFRA Standard: | +Concentration (%) in finished product: | +Risk | +
---|
+
Signature (If generated electronically, no signature)
+Date: %CURRENT_DATE%
+ ++ Disclaimer: +
+This Certificate provides restrictions for use of the specified product based only on those materials restricted by IFRA Standards for the toxicity endpoint(s) described in each Standard.
+This Certificate does not provide certification of a comprehensive safety assessment of all product constituents.
+This certificate is the responsibility of the fragrance supplier issuing it. It has not been prepared or endorsed by IFRA in anyway. +
+Permantly delete '+ $(this).attr('data-name') +' formula?
' + + message : 'Permantly delete '+ $(this).attr('data-name') +' formula?
' + 'Permantly delete '+ ing.Name +' and its data?
' + + '- Cat %: + Cat |
+
-
+
-
+
+ %
+
|