Added an include_sub_products parameter to the API endpoint /stock/products/{productId}/locations

This commit is contained in:
Bernd Bestel 2020-11-19 18:37:16 +01:00
parent 211239a5d3
commit 166748788b
No known key found for this signature in database
GPG Key ID: 71BD34C0D4891300
4 changed files with 30 additions and 9 deletions

View File

@ -199,6 +199,7 @@
- New endpoints GET/POST/PUT `/users/{userId}/permissions` for the new user permissions feature mentioned above - New endpoints GET/POST/PUT `/users/{userId}/permissions` for the new user permissions feature mentioned above
- The stock journal (entity `stock_log`) is now also available via the endpoint `/objects/{entity}` (=> `/objects/stock_log`) - The stock journal (entity `stock_log`) is now also available via the endpoint `/objects/{entity}` (=> `/objects/stock_log`)
- Performance improvements of the `/stock/products/*` endpoints (thanks @fipwmaqzufheoxq92ebc) - Performance improvements of the `/stock/products/*` endpoints (thanks @fipwmaqzufheoxq92ebc)
- The endpoint `/stock/products/{productId}/locations` now also has an optional query parameter `include_sub_products` to optionally also return locations of sub products of the given product
- Fixed that the endpoint `/objects/{entity}/{objectId}` always returned successfully, even when the given object not exists (now returns `404` when the object is not found) (thanks @fipwmaqzufheoxq92ebc) - Fixed that the endpoint `/objects/{entity}/{objectId}` always returned successfully, even when the given object not exists (now returns `404` when the object is not found) (thanks @fipwmaqzufheoxq92ebc)
- Fixed that the endpoint `/stock/volatile` didn't include products which expire today (thanks @fipwmaqzufheoxq92ebc) - Fixed that the endpoint `/stock/volatile` didn't include products which expire today (thanks @fipwmaqzufheoxq92ebc)
- Fixed that the endpoint `/objects/{entity}` did not include Userfields for Userentities (so the effective endpoint `/objects/userobjects`) - Fixed that the endpoint `/objects/{entity}` did not include Userfields for Userentities (so the effective endpoint `/objects/userobjects`)

View File

@ -578,7 +578,6 @@ class StockApiController extends BaseApiController
public function ProductStockEntries(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args) public function ProductStockEntries(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
{ {
$allowSubproductSubstitution = false; $allowSubproductSubstitution = false;
if (isset($request->getQueryParams()['include_sub_products']) && filter_var($request->getQueryParams()['include_sub_products'], FILTER_VALIDATE_BOOLEAN)) if (isset($request->getQueryParams()['include_sub_products']) && filter_var($request->getQueryParams()['include_sub_products'], FILTER_VALIDATE_BOOLEAN))
{ {
$allowSubproductSubstitution = true; $allowSubproductSubstitution = true;
@ -589,7 +588,13 @@ class StockApiController extends BaseApiController
public function ProductStockLocations(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args) public function ProductStockLocations(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
{ {
return $this->FilteredApiResponse($response, $this->getStockService()->GetProductStockLocations($args['productId']), $request->getQueryParams()); $allowSubproductSubstitution = false;
if (isset($request->getQueryParams()['include_sub_products']) && filter_var($request->getQueryParams()['include_sub_products'], FILTER_VALIDATE_BOOLEAN))
{
$allowSubproductSubstitution = true;
}
return $this->FilteredApiResponse($response, $this->getStockService()->GetProductStockLocations($args['productId'], $allowSubproductSubstitution), $request->getQueryParams());
} }
public function RemoveProductFromShoppingList(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args) public function RemoveProductFromShoppingList(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)

View File

@ -1518,6 +1518,15 @@
"type": "integer" "type": "integer"
} }
}, },
{
"in": "query",
"name": "include_sub_products",
"required": false,
"description": "If sub product locations should be included (if the given product is a parent product and in addition to the ones of the given product)",
"schema": {
"type": "boolean"
}
},
{ {
"$ref": "#/components/parameters/query" "$ref": "#/components/parameters/query"
}, },

View File

@ -662,27 +662,27 @@ class StockService extends BaseService
public function GetProductStockEntries($productId, $excludeOpened = false, $allowSubproductSubstitution = false, $ordered = true) public function GetProductStockEntries($productId, $excludeOpened = false, $allowSubproductSubstitution = false, $ordered = true)
{ {
// In order of next use:
// First due first, then first in first out
$sqlWhereProductId = 'product_id = ' . $productId; $sqlWhereProductId = 'product_id = ' . $productId;
if ($allowSubproductSubstitution) if ($allowSubproductSubstitution)
{ {
$sqlWhereProductId = 'product_id IN (SELECT sub_product_id FROM products_resolved WHERE parent_product_id = ' . $productId . ')'; $sqlWhereProductId = 'product_id IN (SELECT sub_product_id FROM products_resolved WHERE parent_product_id = ' . $productId . ')';
} }
$sqlWhereAndOpen = 'AND open IN (0, 1)'; $sqlWhereAndOpen = 'AND open IN (0, 1)';
if ($excludeOpened) if ($excludeOpened)
{ {
$sqlWhereAndOpen = 'AND open = 0'; $sqlWhereAndOpen = 'AND open = 0';
} }
$result = $this->getDatabase()->stock()->where($sqlWhereProductId . ' ' . $sqlWhereAndOpen); $result = $this->getDatabase()->stock()->where($sqlWhereProductId . ' ' . $sqlWhereAndOpen);
// In order of next use:
// First due first, then first in first out
if ($ordered) if ($ordered)
{ {
return $result->orderBy('best_before_date', 'ASC')->orderBy('purchased_date', 'ASC'); return $result->orderBy('best_before_date', 'ASC')->orderBy('purchased_date', 'ASC');
} }
return $result; return $result;
} }
@ -692,9 +692,15 @@ class StockService extends BaseService
return FindAllObjectsInArrayByPropertyValue($stockEntries, 'location_id', $locationId); return FindAllObjectsInArrayByPropertyValue($stockEntries, 'location_id', $locationId);
} }
public function GetProductStockLocations($productId) public function GetProductStockLocations($productId, $allowSubproductSubstitution = false)
{ {
return $this->getDatabase()->stock_current_locations()->where('product_id', $productId); $sqlWhereProductId = 'product_id = ' . $productId;
if ($allowSubproductSubstitution)
{
$sqlWhereProductId = 'product_id IN (SELECT sub_product_id FROM products_resolved WHERE parent_product_id = ' . $productId . ')';
}
return $this->getDatabase()->stock_current_locations()->where($sqlWhereProductId);
} }
public function GetStockEntry($entryId) public function GetStockEntry($entryId)