Finalize stock booking undo API (references #63 and #97)

This commit is contained in:
Bernd Bestel 2018-10-27 10:19:06 +02:00
parent 1080c3486c
commit 3e6cf545d7
No known key found for this signature in database
GPG Key ID: 71BD34C0D4891300
5 changed files with 23 additions and 17 deletions

View File

@ -170,7 +170,7 @@ class StockApiController extends BaseApiController
{ {
try try
{ {
$this->ApiResponse($this->StockService->UndoBooking($args['stockLogId'])); $this->ApiResponse($this->StockService->UndoBooking($args['bookingId']));
return $this->ApiResponse(array('success' => true)); return $this->ApiResponse(array('success' => true));
} }
catch (\Exception $ex) catch (\Exception $ex)

View File

@ -1288,7 +1288,7 @@
} }
} }
}, },
"/stock/undo-booking/{stockLogId}": { "/stock/undo-booking/{bookingId}": {
"get": { "get": {
"description": "Undoes a booking", "description": "Undoes a booking",
"tags": [ "tags": [
@ -1297,9 +1297,9 @@
"parameters": [ "parameters": [
{ {
"in": "path", "in": "path",
"name": "stockLogId", "name": "bookingId",
"required": true, "required": true,
"description": "A valid stock log id", "description": "A valid stock booking id",
"schema": { "schema": {
"type": "integer" "type": "integer"
} }

View File

@ -1,5 +1,8 @@
ALTER TABLE stock_log ALTER TABLE stock_log
ADD undone TINYINT NOT NULL DEFAULT 0 CHECK(undone IN (0, 1)); ADD undone TINYINT NOT NULL DEFAULT 0 CHECK(undone IN (0, 1));
UPDATE stock_log
SET undone = 0;
ALTER TABLE stock_log ALTER TABLE stock_log
ADD undone_timestamp DATETIME; ADD undone_timestamp DATETIME;

View File

@ -114,7 +114,7 @@ $app->group('/api', function()
$this->get('/stock/add-missing-products-to-shoppinglist', '\Grocy\Controllers\StockApiController:AddMissingProductsToShoppingList'); $this->get('/stock/add-missing-products-to-shoppinglist', '\Grocy\Controllers\StockApiController:AddMissingProductsToShoppingList');
$this->get('/stock/clear-shopping-list', '\Grocy\Controllers\StockApiController:ClearShoppingList'); $this->get('/stock/clear-shopping-list', '\Grocy\Controllers\StockApiController:ClearShoppingList');
$this->get('/stock/external-barcode-lookup/{barcode}', '\Grocy\Controllers\StockApiController:ExternalBarcodeLookup'); $this->get('/stock/external-barcode-lookup/{barcode}', '\Grocy\Controllers\StockApiController:ExternalBarcodeLookup');
$this->get('/stock/undo-booking/{stockLogId}', '\Grocy\Controllers\StockApiController:UndoBooking'); $this->get('/stock/undo-booking/{bookingId}', '\Grocy\Controllers\StockApiController:UndoBooking');
// Recipes // Recipes
$this->get('/recipes/add-not-fulfilled-products-to-shopping-list/{recipeId}', '\Grocy\Controllers\RecipesApiController:AddNotFulfilledProductsToShoppingList'); $this->get('/recipes/add-not-fulfilled-products-to-shopping-list/{recipeId}', '\Grocy\Controllers\RecipesApiController:AddNotFulfilledProductsToShoppingList');

View File

@ -47,14 +47,14 @@ class StockService extends BaseService
$product = $this->Database->products($productId); $product = $this->Database->products($productId);
$productStockAmount = $this->Database->stock()->where('product_id', $productId)->sum('amount'); $productStockAmount = $this->Database->stock()->where('product_id', $productId)->sum('amount');
$productLastPurchased = $this->Database->stock_log()->where('product_id', $productId)->where('transaction_type', self::TRANSACTION_TYPE_PURCHASE)->max('purchased_date'); $productLastPurchased = $this->Database->stock_log()->where('product_id', $productId)->where('transaction_type', self::TRANSACTION_TYPE_PURCHASE)->max('purchased_date')->where('undone', 0);
$productLastUsed = $this->Database->stock_log()->where('product_id', $productId)->where('transaction_type', self::TRANSACTION_TYPE_CONSUME)->max('used_date'); $productLastUsed = $this->Database->stock_log()->where('product_id', $productId)->where('transaction_type', self::TRANSACTION_TYPE_CONSUME)->max('used_date')->where('undone', 0);
$nextBestBeforeDate = $this->Database->stock()->where('product_id', $productId)->min('best_before_date'); $nextBestBeforeDate = $this->Database->stock()->where('product_id', $productId)->min('best_before_date');
$quPurchase = $this->Database->quantity_units($product->qu_id_purchase); $quPurchase = $this->Database->quantity_units($product->qu_id_purchase);
$quStock = $this->Database->quantity_units($product->qu_id_stock); $quStock = $this->Database->quantity_units($product->qu_id_stock);
$lastPrice = null; $lastPrice = null;
$lastLogRow = $this->Database->stock_log()->where('product_id = :1 AND transaction_type = :2', $productId, self::TRANSACTION_TYPE_PURCHASE)->orderBy('row_created_timestamp', 'DESC')->limit(1)->fetch(); $lastLogRow = $this->Database->stock_log()->where('product_id = :1 AND transaction_type = :2 AND undone = 0', $productId, self::TRANSACTION_TYPE_PURCHASE)->orderBy('row_created_timestamp', 'DESC')->limit(1)->fetch();
if ($lastLogRow !== null && !empty($lastLogRow)) if ($lastLogRow !== null && !empty($lastLogRow))
{ {
$lastPrice = $lastLogRow->price; $lastPrice = $lastLogRow->price;
@ -80,7 +80,7 @@ class StockService extends BaseService
} }
$returnData = array(); $returnData = array();
$rows = $this->Database->stock_log()->where('product_id = :1 AND transaction_type = :2', $productId, self::TRANSACTION_TYPE_PURCHASE)->whereNOT('price', null)->orderBy('purchased_date', 'DESC'); $rows = $this->Database->stock_log()->where('product_id = :1 AND transaction_type = :2 AND undone = 0', $productId, self::TRANSACTION_TYPE_PURCHASE)->whereNOT('price', null)->orderBy('purchased_date', 'DESC');
foreach ($rows as $row) foreach ($rows as $row)
{ {
$returnData[] = array( $returnData[] = array(
@ -306,18 +306,21 @@ class StockService extends BaseService
return $pluginOutput; return $pluginOutput;
} }
public function UndoBooking($stockLogId) public function UndoBooking($bookingId)
{ {
//TODO: This is not possible when the given booking has subsequent bookings $logRow = $this->Database->stock_log()->where('id = :1 AND undone = 0', $bookingId)->fetch();
$logRow = $this->Database->stock_log()->where('id = :1', $stockLogId)->fetch();
if ($logRow == null) if ($logRow == null)
{ {
throw new \Exception('Booking does not exist'); throw new \Exception('Booking does not exist or was already undone');
} }
if ($logRow->transaction_type === self::TRANSACTION_TYPE_PURCHASE) $hasSubsequentBookings = $this->Database->stock_log()->where('stock_id = :1 AND id != :2 AND id > :2', $logRow->stock_id, $logRow->id)->count() > 0;
if ($hasSubsequentBookings)
{
throw new \Exception('Booking has subsequent dependent bookings, undo not possible');
}
if ($logRow->transaction_type === self::TRANSACTION_TYPE_PURCHASE || ($logRow->transaction_type === self::TRANSACTION_TYPE_INVENTORY_CORRECTION && $logRow->amount > 0))
{ {
// Remove corresponding stock entry // Remove corresponding stock entry
$stockRows = $this->Database->stock()->where('stock_id', $logRow->stock_id); $stockRows = $this->Database->stock()->where('stock_id', $logRow->stock_id);
@ -329,7 +332,7 @@ class StockService extends BaseService
'undone_timestamp' => date('Y-m-d H:i:s') 'undone_timestamp' => date('Y-m-d H:i:s')
)); ));
} }
elseif ($logRow->transaction_type === self::TRANSACTION_TYPE_CONSUME || $logRow->transaction_type === self::TRANSACTION_TYPE_INVENTORY_CORRECTION) elseif ($logRow->transaction_type === self::TRANSACTION_TYPE_CONSUME || ($logRow->transaction_type === self::TRANSACTION_TYPE_INVENTORY_CORRECTION && $logRow->amount < 0))
{ {
// Add corresponding amount back to stock // Add corresponding amount back to stock
$stockRow = $this->Database->stock()->createRow(array( $stockRow = $this->Database->stock()->createRow(array(