mirror of
https://github.com/grocy/grocy.git
synced 2026-04-06 12:56:15 +02:00
Feature request : api/stock can return detailed products #487
Added a new API: /api/stock/full This API returns the same values as "/api/stock" except that it also gives the details of the corresponding product.
This commit is contained in:
parent
d4bec3bd10
commit
a014b6da06
|
|
@ -388,6 +388,11 @@ class StockApiController extends BaseApiController
|
||||||
return $this->ApiResponse($this->StockService->GetCurrentStock());
|
return $this->ApiResponse($this->StockService->GetCurrentStock());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function CurrentStockFull(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||||
|
{
|
||||||
|
return $this->ApiResponse($this->StockService->GetCurrentStockFull());
|
||||||
|
}
|
||||||
|
|
||||||
public function CurrentVolatilStock(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
public function CurrentVolatilStock(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||||
{
|
{
|
||||||
$nextXDays = 5;
|
$nextXDays = 5;
|
||||||
|
|
@ -535,7 +540,7 @@ class StockApiController extends BaseApiController
|
||||||
{
|
{
|
||||||
$addFoundProduct = true;
|
$addFoundProduct = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->ApiResponse($this->StockService->ExternalBarcodeLookup($args['barcode'], $addFoundProduct));
|
return $this->ApiResponse($this->StockService->ExternalBarcodeLookup($args['barcode'], $addFoundProduct));
|
||||||
}
|
}
|
||||||
catch (\Exception $ex)
|
catch (\Exception $ex)
|
||||||
|
|
@ -590,7 +595,7 @@ class StockApiController extends BaseApiController
|
||||||
{
|
{
|
||||||
throw new \Exception('Stock booking does not exist');
|
throw new \Exception('Stock booking does not exist');
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->ApiResponse($stockLogRow);
|
return $this->ApiResponse($stockLogRow);
|
||||||
}
|
}
|
||||||
catch (\Exception $ex)
|
catch (\Exception $ex)
|
||||||
|
|
@ -609,7 +614,7 @@ class StockApiController extends BaseApiController
|
||||||
{
|
{
|
||||||
throw new \Exception('No transaction was found by the given transaction id');
|
throw new \Exception('No transaction was found by the given transaction id');
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->ApiResponse($transactionRows);
|
return $this->ApiResponse($transactionRows);
|
||||||
}
|
}
|
||||||
catch (\Exception $ex)
|
catch (\Exception $ex)
|
||||||
|
|
|
||||||
|
|
@ -163,7 +163,7 @@
|
||||||
{
|
{
|
||||||
"$ref": "#/components/schemas/StockEntry"
|
"$ref": "#/components/schemas/StockEntry"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -626,7 +626,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/files/{group}/{fileName}": {
|
"/files/{group}/{fileName}": {
|
||||||
"get": {
|
"get": {
|
||||||
"summary": "Serves the given file",
|
"summary": "Serves the given file",
|
||||||
|
|
@ -1124,6 +1124,29 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/stock/full": {
|
||||||
|
"get": {
|
||||||
|
"summary": "Returns all products which are currently in stock incl. product details",
|
||||||
|
"tags": [
|
||||||
|
"Stock"
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "An array of CurrentStockResponse objects with product details",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/CurrentStockResponseFull"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/stock/volatile": {
|
"/stock/volatile": {
|
||||||
"get": {
|
"get": {
|
||||||
"summary": "Returns all products which are expiring soon, are already expired or currently missing",
|
"summary": "Returns all products which are expiring soon, are already expired or currently missing",
|
||||||
|
|
@ -4028,6 +4051,99 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"CurrentStockResponseFull": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"product_id": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"amount": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"amount_aggregated": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"amount_opened": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"amount_opened_aggregated": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"best_before_date": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "date",
|
||||||
|
"description": "The next best before date for this product"
|
||||||
|
},
|
||||||
|
"is_aggregated_amount": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Indicates wheter this product has sub-products or not / if the fields `amount_aggregated` and `amount_opened_aggregated` are filled"
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"location_id": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"qu_id_purchase": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"qu_id_stock": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"enable_tare_weight_handling": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"not_check_stock_fulfillment_for_recipes": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"product_group_id": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"qu_factor_purchase_to_stock": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "number"
|
||||||
|
},
|
||||||
|
"tare_weight": {
|
||||||
|
"type": "number",
|
||||||
|
"format": "number"
|
||||||
|
},
|
||||||
|
"barcode": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Can contain multiple barcodes separated by comma"
|
||||||
|
},
|
||||||
|
"min_stock_amount": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0,
|
||||||
|
"default": 0
|
||||||
|
},
|
||||||
|
"default_best_before_days": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0,
|
||||||
|
"default": 0
|
||||||
|
},
|
||||||
|
"default_best_before_days_after_open": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0,
|
||||||
|
"default": 0
|
||||||
|
},
|
||||||
|
"picture_file_name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"allow_partial_units_in_stock": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"row_created_timestamp": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "date-time"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"CurrentChoreResponse": {
|
"CurrentChoreResponse": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,7 @@ $app->group('', function()
|
||||||
$this->get('/equipment', '\Grocy\Controllers\EquipmentController:Overview');
|
$this->get('/equipment', '\Grocy\Controllers\EquipmentController:Overview');
|
||||||
$this->get('/equipment/{equipmentId}', '\Grocy\Controllers\EquipmentController:EditForm');
|
$this->get('/equipment/{equipmentId}', '\Grocy\Controllers\EquipmentController:EditForm');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calendar routes
|
// Calendar routes
|
||||||
if (GROCY_FEATURE_FLAG_CALENDAR)
|
if (GROCY_FEATURE_FLAG_CALENDAR)
|
||||||
{
|
{
|
||||||
|
|
@ -129,9 +129,9 @@ $app->group('/api', function()
|
||||||
|
|
||||||
// System
|
// System
|
||||||
$this->get('/system/info', '\Grocy\Controllers\SystemApiController:GetSystemInfo');
|
$this->get('/system/info', '\Grocy\Controllers\SystemApiController:GetSystemInfo');
|
||||||
$this->get('/system/db-changed-time', '\Grocy\Controllers\SystemApiController:GetDbChangedTime');
|
$this->get('/system/db-changed-time', '\Grocy\Controllers\SystemApiController:GetDbChangedTime');
|
||||||
$this->post('/system/log-missing-localization', '\Grocy\Controllers\SystemApiController:LogMissingLocalization');
|
$this->post('/system/log-missing-localization', '\Grocy\Controllers\SystemApiController:LogMissingLocalization');
|
||||||
|
|
||||||
// Generic entity interaction
|
// Generic entity interaction
|
||||||
$this->get('/objects/{entity}', '\Grocy\Controllers\GenericEntityApiController:GetObjects');
|
$this->get('/objects/{entity}', '\Grocy\Controllers\GenericEntityApiController:GetObjects');
|
||||||
$this->get('/objects/{entity}/{objectId}', '\Grocy\Controllers\GenericEntityApiController:GetObject');
|
$this->get('/objects/{entity}/{objectId}', '\Grocy\Controllers\GenericEntityApiController:GetObject');
|
||||||
|
|
@ -162,6 +162,7 @@ $app->group('/api', function()
|
||||||
{
|
{
|
||||||
$this->get('/stock', '\Grocy\Controllers\StockApiController:CurrentStock');
|
$this->get('/stock', '\Grocy\Controllers\StockApiController:CurrentStock');
|
||||||
$this->put('/stock', '\Grocy\Controllers\StockApiController:EditStock');
|
$this->put('/stock', '\Grocy\Controllers\StockApiController:EditStock');
|
||||||
|
$this->get('/stock/full', '\Grocy\Controllers\StockApiController:CurrentStockFull');
|
||||||
$this->get('/stock/volatile', '\Grocy\Controllers\StockApiController:CurrentVolatilStock');
|
$this->get('/stock/volatile', '\Grocy\Controllers\StockApiController:CurrentVolatilStock');
|
||||||
$this->get('/stock/products/{productId}', '\Grocy\Controllers\StockApiController:ProductDetails');
|
$this->get('/stock/products/{productId}', '\Grocy\Controllers\StockApiController:ProductDetails');
|
||||||
$this->get('/stock/products/{productId}/entries', '\Grocy\Controllers\StockApiController:ProductStockEntries');
|
$this->get('/stock/products/{productId}/entries', '\Grocy\Controllers\StockApiController:ProductStockEntries');
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,14 @@ class StockService extends BaseService
|
||||||
|
|
||||||
$sql = 'SELECT * FROM stock_current WHERE best_before_date IS NOT NULL UNION SELECT id, 0, 0, null, 0, 0, 0 FROM ' . $missingProductsView . ' WHERE id NOT IN (SELECT product_id FROM stock_current)';
|
$sql = 'SELECT * FROM stock_current WHERE best_before_date IS NOT NULL UNION SELECT id, 0, 0, null, 0, 0, 0 FROM ' . $missingProductsView . ' WHERE id NOT IN (SELECT product_id FROM stock_current)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $this->DatabaseService->ExecuteDbQuery($sql)->fetchAll(\PDO::FETCH_OBJ);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function GetCurrentStockFull()
|
||||||
|
{
|
||||||
|
$sql = 'select * from stock_current join products on products.id = stock_current.product_id';
|
||||||
|
|
||||||
return $this->DatabaseService->ExecuteDbQuery($sql)->fetchAll(\PDO::FETCH_OBJ);
|
return $this->DatabaseService->ExecuteDbQuery($sql)->fetchAll(\PDO::FETCH_OBJ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -116,7 +123,7 @@ class StockService extends BaseService
|
||||||
$quStock = $this->Database->quantity_units($product->qu_id_stock);
|
$quStock = $this->Database->quantity_units($product->qu_id_stock);
|
||||||
$location = $this->Database->locations($product->location_id);
|
$location = $this->Database->locations($product->location_id);
|
||||||
$averageShelfLifeDays = intval($this->Database->stock_average_product_shelf_life()->where('id', $productId)->fetch()->average_shelf_life_days);
|
$averageShelfLifeDays = intval($this->Database->stock_average_product_shelf_life()->where('id', $productId)->fetch()->average_shelf_life_days);
|
||||||
|
|
||||||
$lastPrice = null;
|
$lastPrice = null;
|
||||||
$lastLogRow = $this->Database->stock_log()->where('product_id = :1 AND transaction_type IN (:2, :3) AND undone = 0', $productId, self::TRANSACTION_TYPE_PURCHASE, self::TRANSACTION_TYPE_INVENTORY_CORRECTION)->orderBy('row_created_timestamp', 'DESC')->limit(1)->fetch();
|
$lastLogRow = $this->Database->stock_log()->where('product_id = :1 AND transaction_type IN (:2, :3) AND undone = 0', $productId, self::TRANSACTION_TYPE_PURCHASE, self::TRANSACTION_TYPE_INVENTORY_CORRECTION)->orderBy('row_created_timestamp', 'DESC')->limit(1)->fetch();
|
||||||
if ($lastLogRow !== null && !empty($lastLogRow))
|
if ($lastLogRow !== null && !empty($lastLogRow))
|
||||||
|
|
@ -208,20 +215,20 @@ class StockService extends BaseService
|
||||||
{
|
{
|
||||||
throw new \Exception('The amount cannot be lower or equal than the defined tare weight + current stock amount');
|
throw new \Exception('The amount cannot be lower or equal than the defined tare weight + current stock amount');
|
||||||
}
|
}
|
||||||
|
|
||||||
$amount = $amount - floatval($productDetails->stock_amount) - floatval($productDetails->product->tare_weight);
|
$amount = $amount - floatval($productDetails->stock_amount) - floatval($productDetails->product->tare_weight);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Sets the default best before date, if none is supplied
|
//Sets the default best before date, if none is supplied
|
||||||
if ($bestBeforeDate == null)
|
if ($bestBeforeDate == null)
|
||||||
{
|
{
|
||||||
if (intval($productDetails->product->default_best_before_days) == -1)
|
if (intval($productDetails->product->default_best_before_days) == -1)
|
||||||
{
|
{
|
||||||
$bestBeforeDate = date('2999-12-31');
|
$bestBeforeDate = date('2999-12-31');
|
||||||
}
|
}
|
||||||
else if (intval($productDetails->product->default_best_before_days) > 0)
|
else if (intval($productDetails->product->default_best_before_days) > 0)
|
||||||
{
|
{
|
||||||
$bestBeforeDate = date('Y-m-d', strtotime(date('Y-m-d') . ' + '.$productDetails->product->default_best_before_days.' days'));
|
$bestBeforeDate = date('Y-m-d', strtotime(date('Y-m-d') . ' + '.$productDetails->product->default_best_before_days.' days'));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -235,7 +242,7 @@ class StockService extends BaseService
|
||||||
{
|
{
|
||||||
$transactionId = uniqid();
|
$transactionId = uniqid();
|
||||||
}
|
}
|
||||||
|
|
||||||
$stockId = uniqid();
|
$stockId = uniqid();
|
||||||
|
|
||||||
$logRow = $this->Database->stock_log()->createRow(array(
|
$logRow = $this->Database->stock_log()->createRow(array(
|
||||||
|
|
@ -294,7 +301,7 @@ class StockService extends BaseService
|
||||||
{
|
{
|
||||||
throw new \Exception('The amount cannot be lower than the defined tare weight');
|
throw new \Exception('The amount cannot be lower than the defined tare weight');
|
||||||
}
|
}
|
||||||
|
|
||||||
$amount = abs($amount - floatval($productDetails->stock_amount) - floatval($productDetails->product->tare_weight));
|
$amount = abs($amount - floatval($productDetails->stock_amount) - floatval($productDetails->product->tare_weight));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -421,7 +428,7 @@ class StockService extends BaseService
|
||||||
{
|
{
|
||||||
throw new \Exception('The amount cannot be lower than the defined tare weight');
|
throw new \Exception('The amount cannot be lower than the defined tare weight');
|
||||||
}
|
}
|
||||||
|
|
||||||
$amount = abs($amount - floatval($productDetails->stock_amount) - floatval($productDetails->product->tare_weight));
|
$amount = abs($amount - floatval($productDetails->stock_amount) - floatval($productDetails->product->tare_weight));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -626,7 +633,7 @@ class StockService extends BaseService
|
||||||
{
|
{
|
||||||
$containerWeight = floatval($productDetails->product->tare_weight);
|
$containerWeight = floatval($productDetails->product->tare_weight);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($newAmount == floatval($productDetails->stock_amount) + $containerWeight)
|
if ($newAmount == floatval($productDetails->stock_amount) + $containerWeight)
|
||||||
{
|
{
|
||||||
throw new \Exception('The new amount cannot equal the current stock amount');
|
throw new \Exception('The new amount cannot equal the current stock amount');
|
||||||
|
|
@ -638,7 +645,7 @@ class StockService extends BaseService
|
||||||
{
|
{
|
||||||
$bookingAmount = $newAmount;
|
$bookingAmount = $newAmount;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->AddProduct($productId, $bookingAmount, $bestBeforeDate, self::TRANSACTION_TYPE_INVENTORY_CORRECTION, date('Y-m-d'), $price, $locationId);
|
return $this->AddProduct($productId, $bookingAmount, $bestBeforeDate, self::TRANSACTION_TYPE_INVENTORY_CORRECTION, date('Y-m-d'), $price, $locationId);
|
||||||
}
|
}
|
||||||
else if ($newAmount < $productDetails->stock_amount + $containerWeight)
|
else if ($newAmount < $productDetails->stock_amount + $containerWeight)
|
||||||
|
|
@ -819,7 +826,7 @@ class StockService extends BaseService
|
||||||
{
|
{
|
||||||
$productRow->update(array('amount' => $newAmount));
|
$productRow->update(array('amount' => $newAmount));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user