diff --git a/GrocyDbMigrator.php b/GrocyDbMigrator.php index e0293963..f49645f9 100644 --- a/GrocyDbMigrator.php +++ b/GrocyDbMigrator.php @@ -13,8 +13,8 @@ class GrocyDbMigrator qu_id_purchase INTEGER NOT NULL, qu_id_stock INTEGER NOT NULL, qu_factor_purchase_to_stock REAL NOT NULL, - barcode TEXT UNIQUE, - created_timestamp DATETIME DEFAULT (datetime('now', 'localtime')) + barcode TEXT, + row_created_timestamp DATETIME DEFAULT (datetime('now', 'localtime')) )" ); @@ -23,7 +23,7 @@ class GrocyDbMigrator id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, name TEXT NOT NULL UNIQUE, description TEXT, - created_timestamp DATETIME DEFAULT (datetime('now', 'localtime')) + row_created_timestamp DATETIME DEFAULT (datetime('now', 'localtime')) )" ); @@ -32,7 +32,7 @@ class GrocyDbMigrator id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, name TEXT NOT NULL UNIQUE, description TEXT, - created_timestamp DATETIME DEFAULT (datetime('now', 'localtime')) + row_created_timestamp DATETIME DEFAULT (datetime('now', 'localtime')) )" ); @@ -43,20 +43,23 @@ class GrocyDbMigrator amount INTEGER NOT NULL, best_before_date DATE, purchased_date DATE DEFAULT (datetime('now', 'localtime')), - stock_id TEXT NOT NULL + stock_id TEXT NOT NULL, + row_created_timestamp DATETIME DEFAULT (datetime('now', 'localtime')) )" ); self::ExecuteMigrationWhenNeeded($pdo, 5, " - CREATE TABLE consumptions ( + CREATE TABLE stock_log ( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, product_id INTEGER NOT NULL, amount INTEGER NOT NULL, best_before_date DATE, purchased_date DATE, - used_date DATE DEFAULT (datetime('now', 'localtime')), + used_date DATE, spoiled INTEGER NOT NULL DEFAULT 0, - stock_id TEXT NOT NULL + stock_id TEXT NOT NULL, + transaction_type TEXT NOT NULL, + row_created_timestamp DATETIME DEFAULT (datetime('now', 'localtime')) )" ); diff --git a/GrocyDemoDataGenerator.php b/GrocyDemoDataGenerator.php index c6b801c0..1831fd32 100644 --- a/GrocyDemoDataGenerator.php +++ b/GrocyDemoDataGenerator.php @@ -15,15 +15,15 @@ class GrocyDemoDataGenerator INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('Gummibärchen', 2, 2, 2, 1); INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('Chips', 2, 2, 2, 1); INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('Eier', 1, 2, 1, 10); - - INSERT INTO stock (product_id, amount, best_before_date, stock_id) VALUES (3, 5, date('now', '+180 day'), '".uniqid()."'); - INSERT INTO stock (product_id, amount, best_before_date, stock_id) VALUES (4, 5, date('now', '+180 day'), '".uniqid()."'); - INSERT INTO stock (product_id, amount, best_before_date, stock_id) VALUES (5, 5, date('now', '+25 day'), '".uniqid()."'); "; if ($pdo->exec(utf8_encode($sql)) === false) { throw new Exception($pdo->errorInfo()); } + + GrocyLogicStock::AddProduct(3, 5, date('Y-m-d', strtotime('+180 days')), GrocyLogicStock::TRANSACTION_TYPE_PURCHASE); + GrocyLogicStock::AddProduct(4, 5, date('Y-m-d', strtotime('+180 days')), GrocyLogicStock::TRANSACTION_TYPE_PURCHASE); + GrocyLogicStock::AddProduct(5, 5, date('Y-m-d', strtotime('+25 days')), GrocyLogicStock::TRANSACTION_TYPE_PURCHASE); } } diff --git a/GrocyLogicStock.php b/GrocyLogicStock.php index 97f38650..69179ed5 100644 --- a/GrocyLogicStock.php +++ b/GrocyLogicStock.php @@ -2,6 +2,10 @@ class GrocyLogicStock { + const TRANSACTION_TYPE_PURCHASE = 'purchase'; + const TRANSACTION_TYPE_CONSUME = 'consume'; + const TRANSACTION_TYPE_INVENTORY_CORRECTION = 'inventory-correction'; + public static function GetCurrentStock() { $db = Grocy::GetDbConnectionRaw(); @@ -15,7 +19,7 @@ class GrocyLogicStock $product = $db->products($productId); $productStockAmount = $db->stock()->where('product_id', $productId)->sum('amount'); $productLastPurchased = $db->stock()->where('product_id', $productId)->max('purchased_date'); - $productLastUsed = $db->consumptions()->where('product_id', $productId)->max('used_date'); + $productLastUsed = $db->stock_log()->where('product_id', $productId)->where('transaction_type', self::TRANSACTION_TYPE_CONSUME)->max('used_date'); $quPurchase = $db->quantity_units($product->qu_id_purchase); $quStock = $db->quantity_units($product->qu_id_stock); @@ -29,7 +33,34 @@ class GrocyLogicStock ); } - public static function ConsumeProduct(int $productId, int $amount, bool $spoiled) + public static function AddProduct(int $productId, int $amount, string $bestBeforeDate, $transactionType) + { + $db = Grocy::GetDbConnection(); + $stockId = uniqid(); + + $logRow = $db->stock_log()->createRow(array( + 'product_id' => $productId, + 'amount' => $amount, + 'best_before_date' => $bestBeforeDate, + 'purchased_date' => date('Y-m-d'), + 'stock_id' => $stockId, + 'transaction_type' => $transactionType + )); + $logRow->save(); + + $stockRow = $db->stock()->createRow(array( + 'product_id' => $productId, + 'amount' => $amount, + 'best_before_date' => $bestBeforeDate, + 'purchased_date' => date('Y-m-d'), + 'stock_id' => $stockId, + )); + $stockRow->save(); + + return true; + } + + public static function ConsumeProduct(int $productId, int $amount, bool $spoiled, $transactionType) { $db = Grocy::GetDbConnection(); @@ -50,30 +81,34 @@ class GrocyLogicStock if ($amount >= $stockEntry->amount) //Take the whole stock entry { - $consumptionRow = $db->consumptions()->createRow(array( + $logRow = $db->stock_log()->createRow(array( 'product_id' => $stockEntry->product_id, - 'amount' => $stockEntry->amount, + 'amount' => $stockEntry->amount * -1, 'best_before_date' => $stockEntry->best_before_date, 'purchased_date' => $stockEntry->purchased_date, + 'used_date' => date('Y-m-d'), 'spoiled' => $spoiled, - 'stock_id' => $stockEntry->stock_id + 'stock_id' => $stockEntry->stock_id, + 'transaction_type' => $transactionType )); - $consumptionRow->save(); + $logRow->save(); $amount -= $stockEntry->amount; $stockEntry->delete(); } else //Stock entry amount is > than needed amount -> split the stock entry resp. update the amount { - $consumptionRow = $db->consumptions()->createRow(array( + $logRow = $db->stock_log()->createRow(array( 'product_id' => $stockEntry->product_id, - 'amount' => $amount, + 'amount' => $amount * -1, 'best_before_date' => $stockEntry->best_before_date, 'purchased_date' => $stockEntry->purchased_date, + 'used_date' => date('Y-m-d H:i:s'), 'spoiled' => $spoiled, - 'stock_id' => $stockEntry->stock_id + 'stock_id' => $stockEntry->stock_id, + 'transaction_type' => $transactionType )); - $consumptionRow->save(); + $logRow->save(); $restStockAmount = $stockEntry->amount - $amount; $amount = 0; diff --git a/index.php b/index.php index 6ec0dedd..d6e24fe8 100644 --- a/index.php +++ b/index.php @@ -32,10 +32,10 @@ if (!Grocy::IsDemoInstallation()) ])); } -$app->get('/', function(Request $request, Response $response) -{ - $db = Grocy::GetDbConnection(); +$db = Grocy::GetDbConnection(); +$app->get('/', function(Request $request, Response $response) use($db) +{ return $this->renderer->render($response, '/layout.php', [ 'title' => 'Dashboard', 'contentPage' => 'dashboard.php', @@ -44,10 +44,8 @@ $app->get('/', function(Request $request, Response $response) ]); }); -$app->get('/purchase', function(Request $request, Response $response) +$app->get('/purchase', function(Request $request, Response $response) use($db) { - $db = Grocy::GetDbConnection(); - return $this->renderer->render($response, '/layout.php', [ 'title' => 'Purchase', 'contentPage' => 'purchase.php', @@ -55,10 +53,8 @@ $app->get('/purchase', function(Request $request, Response $response) ]); }); -$app->get('/consumption', function(Request $request, Response $response) +$app->get('/consumption', function(Request $request, Response $response) use($db) { - $db = Grocy::GetDbConnection(); - return $this->renderer->render($response, '/layout.php', [ 'title' => 'Consumption', 'contentPage' => 'consumption.php', @@ -66,10 +62,8 @@ $app->get('/consumption', function(Request $request, Response $response) ]); }); -$app->get('/products', function(Request $request, Response $response) +$app->get('/products', function(Request $request, Response $response) use($db) { - $db = Grocy::GetDbConnection(); - return $this->renderer->render($response, '/layout.php', [ 'title' => 'Products', 'contentPage' => 'products.php', @@ -79,10 +73,8 @@ $app->get('/products', function(Request $request, Response $response) ]); }); -$app->get('/locations', function(Request $request, Response $response) +$app->get('/locations', function(Request $request, Response $response) use($db) { - $db = Grocy::GetDbConnection(); - return $this->renderer->render($response, '/layout.php', [ 'title' => 'Locations', 'contentPage' => 'locations.php', @@ -90,10 +82,8 @@ $app->get('/locations', function(Request $request, Response $response) ]); }); -$app->get('/quantityunits', function(Request $request, Response $response) +$app->get('/quantityunits', function(Request $request, Response $response) use($db) { - $db = Grocy::GetDbConnection(); - return $this->renderer->render($response, '/layout.php', [ 'title' => 'Quantity units', 'contentPage' => 'quantityunits.php', @@ -101,10 +91,8 @@ $app->get('/quantityunits', function(Request $request, Response $response) ]); }); -$app->get('/product/{productId}', function(Request $request, Response $response, $args) +$app->get('/product/{productId}', function(Request $request, Response $response, $args) use($db) { - $db = Grocy::GetDbConnection(); - if ($args['productId'] == 'new') { return $this->renderer->render($response, '/layout.php', [ @@ -128,10 +116,8 @@ $app->get('/product/{productId}', function(Request $request, Response $response, } }); -$app->get('/location/{locationId}', function(Request $request, Response $response, $args) +$app->get('/location/{locationId}', function(Request $request, Response $response, $args) use($db) { - $db = Grocy::GetDbConnection(); - if ($args['locationId'] == 'new') { return $this->renderer->render($response, '/layout.php', [ @@ -151,10 +137,8 @@ $app->get('/location/{locationId}', function(Request $request, Response $respons } }); -$app->get('/quantityunit/{quantityunitId}', function(Request $request, Response $response, $args) +$app->get('/quantityunit/{quantityunitId}', function(Request $request, Response $response, $args) use($db) { - $db = Grocy::GetDbConnection(); - if ($args['quantityunitId'] == 'new') { return $this->renderer->render($response, '/layout.php', [ @@ -174,67 +158,57 @@ $app->get('/quantityunit/{quantityunitId}', function(Request $request, Response } }); -$app->group('/api', function() +$app->group('/api', function() use($db, $app) { - $this->get('/get-objects/{entity}', function(Request $request, Response $response, $args) + $this->get('/get-objects/{entity}', function(Request $request, Response $response, $args) use($db) { - $db = Grocy::GetDbConnection(); echo json_encode($db->{$args['entity']}()); - - return $response->withHeader('Content-Type', 'application/json'); }); - $this->get('/get-object/{entity}/{objectId}', function(Request $request, Response $response, $args) + $this->get('/get-object/{entity}/{objectId}', function(Request $request, Response $response, $args) use($db) { - $db = Grocy::GetDbConnection(); echo json_encode($db->{$args['entity']}($args['objectId'])); - - return $response->withHeader('Content-Type', 'application/json'); }); - $this->post('/add-object/{entity}', function(Request $request, Response $response, $args) + $this->post('/add-object/{entity}', function(Request $request, Response $response, $args) use($db) { - $db = Grocy::GetDbConnection(); $newRow = $db->{$args['entity']}()->createRow($request->getParsedBody()); $newRow->save(); $success = $newRow->isClean(); echo json_encode(array('success' => $success)); - - return $response->withHeader('Content-Type', 'application/json'); }); - $this->post('/edit-object/{entity}/{objectId}', function(Request $request, Response $response, $args) + $this->post('/edit-object/{entity}/{objectId}', function(Request $request, Response $response, $args) use($db) { - $db = Grocy::GetDbConnection(); $row = $db->{$args['entity']}($args['objectId']); $row->update($request->getParsedBody()); $success = $row->isClean(); echo json_encode(array('success' => $success)); - - return $response->withHeader('Content-Type', 'application/json'); }); - $this->get('/delete-object/{entity}/{objectId}', function(Request $request, Response $response, $args) + $this->get('/delete-object/{entity}/{objectId}', function(Request $request, Response $response, $args) use($db) { - $db = Grocy::GetDbConnection(); $row = $db->{$args['entity']}($args['objectId']); $row->delete(); $success = $row->isClean(); echo json_encode(array('success' => $success)); - - return $response->withHeader('Content-Type', 'application/json'); }); - $this->get('/stock/get-product-details/{productId}', function(Request $request, Response $response, $args) + $this->get('/stock/add-product/{productId}/{amount}', function(Request $request, Response $response, $args) { - echo json_encode(GrocyLogicStock::GetProductDetails($args['productId'])); - return $response->withHeader('Content-Type', 'application/json'); - }); + $bestBeforeDate = date('Y-m-d'); + if (isset($request->getQueryParams()['bestbeforedate']) && !empty($request->getQueryParams()['bestbeforedate'])) + { + $bestBeforeDate = $request->getQueryParams()['bestbeforedate']; + } - $this->get('/stock/get-current-stock', function(Request $request, Response $response) - { - echo json_encode(GrocyLogicStock::GetCurrentStock()); - return $response->withHeader('Content-Type', 'application/json'); + $transactionType = GrocyLogicStock::TRANSACTION_TYPE_PURCHASE; + if (isset($request->getQueryParams()['transactiontype']) && !empty($request->getQueryParams()['transactiontype'])) + { + $transactionType = $request->getQueryParams()['transactiontype']; + } + + echo json_encode(array('success' => GrocyLogicStock::AddProduct($args['productId'], $args['amount'], $bestBeforeDate, $transactionType))); }); $this->get('/stock/consume-product/{productId}/{amount}', function(Request $request, Response $response, $args) @@ -245,15 +219,28 @@ $app->group('/api', function() $spoiled = true; } - echo json_encode(array('success' => GrocyLogicStock::ConsumeProduct($args['productId'], $args['amount'], $spoiled))); - return $response->withHeader('Content-Type', 'application/json'); + $transactionType = GrocyLogicStock::TRANSACTION_TYPE_CONSUME; + if (isset($request->getQueryParams()['transactiontype']) && !empty($request->getQueryParams()['transactiontype'])) + { + $transactionType = $request->getQueryParams()['transactiontype']; + } + + echo json_encode(array('success' => GrocyLogicStock::ConsumeProduct($args['productId'], $args['amount'], $spoiled, $transactionType))); }); - $this->get('/helper/uniqid', function(Request $request, Response $response) + $this->get('/stock/get-product-details/{productId}', function(Request $request, Response $response, $args) { - echo json_encode(array('uniqid' => uniqid())); - return $response->withHeader('Content-Type', 'application/json'); + echo json_encode(GrocyLogicStock::GetProductDetails($args['productId'])); }); + + $this->get('/stock/get-current-stock', function(Request $request, Response $response) + { + echo json_encode(GrocyLogicStock::GetCurrentStock()); + }); +})->add(function($request, $response, $next) +{ + $response = $next($request, $response); + return $response->withHeader('Content-Type', 'application/json'); }); $app->run(); diff --git a/views/consumption.php b/views/consumption.php index bb5bfb4b..bb46fe93 100644 --- a/views/consumption.php +++ b/views/consumption.php @@ -2,6 +2,7 @@

Consumption

+
+
+
+ +
@@ -35,4 +40,4 @@ Last purchased:
Last used:

- \ No newline at end of file + diff --git a/views/layout.php b/views/layout.php index 429e77b0..b68ad902 100644 --- a/views/layout.php +++ b/views/layout.php @@ -38,6 +38,7 @@
+ +
diff --git a/views/locationform.php b/views/locationform.php index c2c0e270..a6c43136 100644 --- a/views/locationform.php +++ b/views/locationform.php @@ -1,4 +1,5 @@
+

@@ -8,15 +9,20 @@
+
+
+ +
+
diff --git a/views/locations.js b/views/locations.js index e23f5d56..b43511cf 100644 --- a/views/locations.js +++ b/views/locations.js @@ -41,4 +41,3 @@ $(function() ] }); }); - diff --git a/views/locations.php b/views/locations.php index c0e17216..1f4fc107 100644 --- a/views/locations.php +++ b/views/locations.php @@ -1,4 +1,5 @@
+

Locations @@ -37,4 +38,5 @@

+ diff --git a/views/productform.php b/views/productform.php index 91183028..c5836750 100644 --- a/views/productform.php +++ b/views/productform.php @@ -1,4 +1,5 @@
+

@@ -8,20 +9,24 @@
+
+
+
+
+
+
+
+

+
+
diff --git a/views/products.php b/views/products.php index 359eb7c1..740e2013 100644 --- a/views/products.php +++ b/views/products.php @@ -1,4 +1,5 @@
+

Products @@ -53,4 +54,5 @@

+ diff --git a/views/purchase.js b/views/purchase.js index 8c65fc96..43d60224 100644 --- a/views/purchase.js +++ b/views/purchase.js @@ -9,32 +9,19 @@ { jsonForm.amount = jsonForm.amount * productDetails.product.qu_factor_purchase_to_stock; - Grocy.FetchJson('/api/helper/uniqid', - function(uniqidResponse) - { - jsonForm.stock_id = uniqidResponse.uniqid; + Grocy.FetchJson('/api/stock/add-product/' + jsonForm.product_id + '/' + jsonForm.amount + '?bestbeforedate=' + $('#best_before_date').val(), + function (result) { + toastr.success('Added ' + jsonForm.amount + ' ' + productDetails.quantity_unit_stock.name + ' of ' + productDetails.product.name + ' to stock'); - Grocy.PostJson('/api/add-object/stock', jsonForm, - function(result) - { - toastr.success('Added ' + jsonForm.amount + ' ' + productDetails.quantity_unit_stock.name + ' of ' + productDetails.product.name + ' to stock'); - - $('#amount').val(1); - $('#best_before_date').val(''); - $('#product_id').val(''); - $('#product_id_text_input').focus(); - $('#product_id_text_input').val(''); - $('#product_id_text_input').trigger('change'); - $('#purchase-form').validator('validate'); - }, - function(xhr) - { - console.error(xhr); - } - ); + $('#amount').val(1); + $('#best_before_date').val(''); + $('#product_id').val(''); + $('#product_id_text_input').focus(); + $('#product_id_text_input').val(''); + $('#product_id_text_input').trigger('change'); + $('#purchase-form').validator('validate'); }, - function(xhr) - { + function (xhr) { console.error(xhr); } ); diff --git a/views/purchase.php b/views/purchase.php index 32acde81..06c7ed48 100644 --- a/views/purchase.php +++ b/views/purchase.php @@ -2,6 +2,7 @@

Purchase

+
+
@@ -22,12 +24,15 @@
+
+ +
@@ -40,4 +45,4 @@ Last purchased:
Last used:

- \ No newline at end of file + diff --git a/views/quantityunitform.php b/views/quantityunitform.php index 7c2d34da..c01f623e 100644 --- a/views/quantityunitform.php +++ b/views/quantityunitform.php @@ -1,4 +1,5 @@
+

@@ -8,15 +9,20 @@
+
+
+ +
+
diff --git a/views/quantityunits.php b/views/quantityunits.php index 0b562f2b..7b9350c0 100644 --- a/views/quantityunits.php +++ b/views/quantityunits.php @@ -1,4 +1,5 @@
+

Quantity units @@ -37,4 +38,5 @@

+