Skip to content

Commit

Permalink
Merge pull request #168 from globaldyne/v10.0
Browse files Browse the repository at this point in the history
V10.0
  • Loading branch information
globaldyne authored May 10, 2024
2 parents af7e343 + 927c205 commit 87b3d81
Show file tree
Hide file tree
Showing 44 changed files with 2,828 additions and 1,125 deletions.
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,23 @@
# CHANGELOG
### Version 10.0
- Discord server link added
- Added archive option when deleting a formula
- Added JSON export for customers
- Added inventory create/update info for customers
- Customers messages changed to toast
- Added JSON export for lids
- Added inventory create/update info for compounds
- Added JSON import/export for compounds
- Allow a formula to be marked complete when contains skipped materials
- Bottle edit page format update
- Weight added for the bottles inventory
- Bottles inventory messages changed to toast
- Added Inventory for finished Compounds
- Added document size and created date in fotmula attachements page
- Fix search when replacing a material
- PV Scale integration - WIP
- Log ingredient id in history

### Version 9.9
- Record replaced ingredients when finalising a formula in the generated PDF
- Increase toast duration for formula making to 10 seconds
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ A sophisticated tool to help perfumers organize their formulas, ingredients and
This is a FREE software provided as is without ANY warranty under MIT license.

[![Current Release](https://img.shields.io/github/v/release/globaldyne/parfumvault.svg "Current Release")](https://github.com/globaldyne/parfumvault/releases/latest) [![PayPal](https://img.shields.io/badge/donate-PayPal-green.svg)](https://paypal.me/jbparfum)
![Discord](https://img.shields.io/discord/1238069309356638217)


# Features
Expand Down
2 changes: 1 addition & 1 deletion VERSION.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
9.9
10.0
1 change: 1 addition & 0 deletions core/formula_timeline_data.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@

$r['id'] = (int)$h['id'];
$r['fid'] = (string)$h['fid'];
$r['ing_id'] = (int)$h['ing_id'];
$r['change_made'] = (string)$h['change_made'];
$r['date_time'] = (string)$h['date_time'];
$r['user'] = (string)$h['user'];
Expand Down
5 changes: 4 additions & 1 deletion core/list_bottle_data.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,14 @@
$r['height'] = (double)$rq['height']?:0;
$r['width'] = (double)$rq['width']?:0;
$r['diameter'] = (double)$rq['diameter']?:0;
$r['weight'] = (double)$rq['weight']?:0;
$r['supplier'] = (string)$rq['supplier']?:'N/A';
$r['supplier_link'] = (string)$rq['supplier_link']?:'N/A';
$r['notes'] = (string)$rq['notes']?:'N/A';
$r['pieces'] = (int)$rq['pieces']?:0;

$r['created'] = (string)$rq['created']?:'00:00:00';
$r['updated'] = (string)$rq['updated']?:'00:00:00';

$photo = mysqli_fetch_array(mysqli_query($conn,"SELECT docData FROM documents WHERE type = '4' AND ownerID = '".$r['id']."'"));
$r['photo'] = (string)$photo['docData']?:'data:image/png;base64,'.$defImage;

Expand Down
4 changes: 3 additions & 1 deletion core/list_customer_data.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@
$r['phone'] = (string)$rq['phone']?:'N/A';
$r['email'] = (string)$rq['email']?:'N/A';
$r['web'] = (string)$rq['web']?:'N/A';

$r['created'] = (string)$rq['created']?:'00:00:00';
$r['updated'] = (string)$rq['updated']?:'00:00:00';

$rx[]=$r;
}
$total = mysqli_fetch_assoc(mysqli_query($conn,"SELECT COUNT(id) AS entries FROM customers"));
Expand Down
1 change: 1 addition & 0 deletions core/list_formula_attachments_data.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
$r['type'] = (int)$doc['type'];
$r['name'] = (string)$doc['name']?:'N/A';
$r['notes'] = (string)$doc['notes']?:'N/A';
$r['created'] = (string)$doc['created']?:'N/A';
$r['docData'] = (string)$doc['docData'];
$r['docSize'] = (string)formatBytes(strlen($doc['docData']));

Expand Down
88 changes: 88 additions & 0 deletions core/list_inventory_compounds_data.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<?php
define('__ROOT__', dirname(dirname(__FILE__)));

require_once(__ROOT__.'/inc/sec.php');
require_once(__ROOT__.'/inc/opendb.php');
require_once(__ROOT__.'/inc/settings.php');

$row = $_POST['start'] ?: 0;
$limit = $_POST['length'] ?: 10;
$defBtlSize = $_POST['btlSize'] ?: 100;

$order_by = $_POST['order_by'] ?: 'name';
$order = $_POST['order_as'] ?: 'ASC';
$extra = "ORDER BY ".$order_by." ".$order;

$s = trim($_POST['search']['value']);
$t = 'inventory_compounds';

if($s != ''){
$f = "WHERE 1 AND (name LIKE '%".$s."%')";
}

$q = mysqli_query($conn, "SELECT * FROM $t $f $extra LIMIT $row, $limit");
while($res = mysqli_fetch_array($q)){
$rs[] = $res;
}



function calculateBottles($totalVolume, $alcoholPercentage, $defBtlSize) {
$alcoholVolume = $defBtlSize * ($alcoholPercentage / 100); // volume of alcohol in each bottle
$numBottles = floor($totalVolume / $alcoholVolume); // total number of bottles
return $numBottles;
}


$pt = mysqli_query($conn, "SELECT id,name,concentration,description FROM perfumeTypes");
while($rt = mysqli_fetch_array($pt)){
$types[] = $rt;
}

$rx = [];

foreach ($rs as $rq) {
$r['id'] = (int)$rq['id'];
$r['name'] = (string)$rq['name'] ?: 'N/A';
$r['description'] = (string)$rq['description'] ?: 'N/A';
$r['batch_id'] = (int)$rq['batch_id'];
$r['size'] = (double)$rq['size'] ?: 0;
$r['updated'] = (string)$rq['updated'] ?: '00:00:00';
$r['created'] = (string)$rq['created'] ?: '00:00:00';
$r['label_info'] = (string)$rq['label_info'] ?: '-';
$r['location'] = (string)$rq['location'] ?: '-';
$r['owner_id'] = (int)$rq['owner_id'] ?: 0;
$r['btlSize'] = (double)$defBtlSize;

$rt = [];
foreach ($types as $type) {
$bottleSize = $r['size']; // Bottle size calculated here
$rt[] = [
'name' => $type['name'],
'concentration' => $type['concentration'],
'bottles_total' => calculateBottles($bottleSize, $type['concentration'], $defBtlSize)
];
}

$r['breakDown'] = $rt;
$rx[] = $r;
}

$total = mysqli_fetch_assoc(mysqli_query($conn,"SELECT COUNT(id) AS entries FROM $t"));
$filtered = mysqli_fetch_assoc(mysqli_query($conn,"SELECT COUNT(id) AS entries FROM $t ".$f));

$response = array(
"draw" => (int)$_POST['draw'],
"recordsTotal" => (int)$total['entries'],
"recordsFiltered" => (int)$filtered['entries'],
"data" => $rx
);

if(empty($r)){
$response['data'] = [];
}

header('Content-Type: application/json; charset=utf-8');
echo json_encode($response);
return;
?>
6 changes: 6 additions & 0 deletions css/vault.css
Original file line number Diff line number Diff line change
Expand Up @@ -1449,3 +1449,9 @@ th.dt-center, td.dt-center {
#liveToast {
width: 100%;
}

.pvScale-data-footer {
position: -webkit-sticky;
position: sticky;
bottom: 0;
}
18 changes: 14 additions & 4 deletions db/pvault.sql
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,13 @@ CREATE TABLE `bottles` (
`height` varchar(255) COLLATE utf8_general_ci DEFAULT NULL,
`width` varchar(255) COLLATE utf8_general_ci DEFAULT NULL,
`diameter` varchar(255) COLLATE utf8_general_ci DEFAULT NULL,
`weight` DOUBLE NOT NULL DEFAULT '0',
`supplier` varchar(255) COLLATE utf8_general_ci DEFAULT NULL,
`supplier_link` varchar(255) COLLATE utf8_general_ci DEFAULT NULL,
`notes` text COLLATE utf8_general_ci DEFAULT NULL,
`pieces` int(11) NOT NULL DEFAULT 0
`pieces` int(11) NOT NULL DEFAULT 0,
`updated` TIMESTAMP on update CURRENT_TIMESTAMP NOT NULL,
`created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;

CREATE TABLE `customers` (
Expand All @@ -40,7 +43,10 @@ CREATE TABLE `customers` (
`address` varchar(255) COLLATE utf8_general_ci DEFAULT NULL,
`email` varchar(225) COLLATE utf8_general_ci DEFAULT NULL,
`phone` varchar(255) COLLATE utf8_general_ci DEFAULT NULL,
`web` varchar(255) COLLATE utf8_general_ci DEFAULT NULL
`web` varchar(255) COLLATE utf8_general_ci DEFAULT NULL,
`owner_id` INT NOT NULL DEFAULT '0',
`updated` TIMESTAMP on update CURRENT_TIMESTAMP NOT NULL,
`created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;

CREATE TABLE `formulas` (
Expand Down Expand Up @@ -495,6 +501,7 @@ CREATE TABLE `documents` (
`name` varchar(255) COLLATE utf8_general_ci NOT NULL,
`notes` varchar(255) COLLATE utf8_general_ci DEFAULT NULL,
`docData` longblob NOT NULL,
`isBatch` INT NOT NULL DEFAULT '0',
`created` datetime NOT NULL DEFAULT current_timestamp(),
`updated` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
PRIMARY KEY (`id`),
Expand Down Expand Up @@ -599,6 +606,7 @@ CREATE TABLE `formulasRevisions` (
CREATE TABLE `formula_history` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`fid` varchar(255) NOT NULL,
`ing_id` INT NOT NULL DEFAULT '0',
`change_made` text COLLATE utf8_general_ci NOT NULL,
`date_time` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
`user` varchar(255) COLLATE utf8_general_ci NOT NULL,
Expand Down Expand Up @@ -679,7 +687,9 @@ CREATE TABLE `backup_provider` (
`description` varchar(255) NOT NULL,
`gdrive_name` varchar(255) NOT NULL DEFAULT 'pvault',
UNIQUE KEY `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci;
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;

INSERT INTO `backup_provider` (`id`, `credentials`, `provider`, `schedule`, `enabled`, `description`, `gdrive_name`) VALUES
(1, '{}', 'Google', '00:00:00', 1, 'My PV Backups', 'pvault');
(1, '{}', 'Google', '00:00:00', 1, 'My PV Backups', 'pvault');

CREATE TABLE `inventory_compounds` ( `id` INT NOT NULL AUTO_INCREMENT , `name` VARCHAR(255) NOT NULL , `description` TEXT NOT NULL , `batch_id` VARCHAR(255) NOT NULL DEFAULT '-' , `size` DOUBLE NOT NULL DEFAULT '0' , `updated` TIMESTAMP on update CURRENT_TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP , `created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP , `owner_id` INT NOT NULL DEFAULT '0' , `location` VARCHAR(255) NOT NULL , `label_info` TEXT NOT NULL , PRIMARY KEY (`id`)) ENGINE = InnoDB CHARSET=utf8 COLLATE utf8_general_ci;
2 changes: 1 addition & 1 deletion db/schema.ver
Original file line number Diff line number Diff line change
@@ -1 +1 @@
9.9
10.0
6 changes: 6 additions & 0 deletions db/updates/update_9.9-10.0.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
CREATE TABLE `inventory_compounds` ( `id` INT NOT NULL AUTO_INCREMENT , `name` VARCHAR(255) NOT NULL , `description` TEXT NOT NULL , `batch_id` VARCHAR(255) NOT NULL DEFAULT '-' , `size` DOUBLE NOT NULL DEFAULT '0' , `updated` TIMESTAMP on update CURRENT_TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP , `created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP , `owner_id` INT NOT NULL DEFAULT '0' , `location` VARCHAR(255) NOT NULL , `label_info` TEXT NOT NULL , PRIMARY KEY (`id`)) ENGINE = InnoDB CHARSET=utf8 COLLATE utf8_general_ci;
ALTER TABLE `documents` ADD `isBatch` INT NOT NULL DEFAULT '0' AFTER `docData`;
ALTER TABLE `bottles` ADD `weight` DOUBLE NOT NULL DEFAULT '0' AFTER `supplier`;
ALTER TABLE `customers` ADD `owner_id` INT NOT NULL DEFAULT '0' AFTER `web`, ADD `updated` TIMESTAMP on update CURRENT_TIMESTAMP NOT NULL AFTER `owner_id`, ADD `created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP AFTER `updated`;
ALTER TABLE `bottles` ADD `updated` TIMESTAMP on update CURRENT_TIMESTAMP NOT NULL AFTER `pieces`, ADD `created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP AFTER `updated`;
ALTER TABLE `formula_history` ADD `ing_id` INT NOT NULL DEFAULT '0' AFTER `fid`;
2 changes: 1 addition & 1 deletion func/genBatchPDF.php
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ function Code39($xpos, $ypos, $code, $baseline=0.5, $height=5){
$docData = 'data:application/pdf;base64,' .$pdf;
if($formulaTable == "makeFormula"){

mysqli_query($conn, "INSERT INTO documents (ownerID,type,name,notes,docData) VALUES (".$meta['id'].",'5','$batchID','Auto generated by Formula Make','$docData')");
mysqli_query($conn, "INSERT INTO documents (ownerID,type,name,notes,docData,isBatch) VALUES (".$meta['id'].",'5','$batchID','Auto generated by Formula Make','$docData','1')");


}else{
Expand Down
Binary file added img/pvScaleSP1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 5 additions & 2 deletions index.php
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ function chkUpdate() {

<li class="nav-item">
<?php
if($_GET['do'] == 'ingredients' || $_GET['do'] == 'bottles' || $_GET['do'] == 'lids' || $_GET['do'] == 'suppliers' || $_GET['do'] == 'customers'){
if($_GET['do'] == 'ingredients' || $_GET['do'] == 'bottles' || $_GET['do'] == 'lids' || $_GET['do'] == 'suppliers' || $_GET['do'] == 'customers' || $_GET['do'] == 'compounds'){
$expand = 'show';
$class = '';
$aria = 'true';
Expand All @@ -231,6 +231,8 @@ function chkUpdate() {
<a class="collapse-item <?php if($_GET['do'] == 'ingredients'){ echo 'active';}?>" href="/?do=ingredients">Ingredients</a>
<a class="collapse-item <?php if($_GET['do'] == 'suppliers'){ echo 'active';}?>" href="/?do=suppliers">Suppliers</a>
<a class="collapse-item <?php if($_GET['do'] == 'customers'){ echo 'active';}?>" href="/?do=customers">Customers</a>
<a class="collapse-item <?php if($_GET['do'] == 'compounds'){ echo 'active';}?>" href="/?do=compounds">Compounds</a>

<a class="collapse-item <?php if($_GET['do'] == 'bottles'){ echo 'active';}?>" href="/?do=bottles">Bottles</a>
<a class="collapse-item <?php if($_GET['do'] == 'lids'){ echo 'active';}?>" href="/?do=lids">Bottle Lids</a>
</div>
Expand Down Expand Up @@ -313,7 +315,8 @@ function chkUpdate() {
require_once(__ROOT__.'/pages/customers.php');
}elseif($_GET['do'] == 'compareFormulas'){
require_once(__ROOT__.'/pages/compareFormulas.php');

}elseif($_GET['do'] == 'compounds'){
require_once(__ROOT__.'/pages/compounds.php');
}else{
require_once(__ROOT__.'/pages/dashboard.php');
}
Expand Down
Loading

0 comments on commit 87b3d81

Please sign in to comment.