feat: Added recipes/requirements route

- feat: Added requirements route to allow clients to access the requirements fulfilments of recipes
This commit is contained in:
grocy 2019-06-20 23:10:30 -05:00
parent a9c0539305
commit 7a51fb77b0
3 changed files with 3181 additions and 2687 deletions

View File

@ -40,4 +40,24 @@ class RecipesApiController extends BaseApiController
return $this->GenericErrorResponse($response, $ex->getMessage()); return $this->GenericErrorResponse($response, $ex->getMessage());
} }
} }
public function GetRecipeRequirements(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{
try {
if(!$args['recipeId']){
return $this->ApiResponse($this->RecipesService->GetRecipesResolved());
}
$recipeResolved = FindObjectInArrayByPropertyValue($this->RecipesService->GetRecipesResolved(), 'recipe_id', $args['recipeId']);
if(!$recipeResolved) {
$errorMsg ='Recipe requirments do not exist for recipe_id ' . $args['recipe_id'];
$GenericError = $this->GenericErrorResponse($response, $errorMsg);
return $GenericError;
}
return $this->ApiResponse($recipeResolved);
}
catch (\Exception $ex)
{
return $this->GenericErrorResponse($response, $ex->getMessage());
}
}
} }

View File

@ -234,8 +234,22 @@
} }
}, },
"responses": { "responses": {
"204": { "200": {
"description": "The operation was successful" "description": "The operation was successful",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"created_object_id": {
"type": "number",
"format": "integer",
"description": "The id of the created object"
}
}
}
}
}
}, },
"400": { "400": {
"description": "The operation was not successful", "description": "The operation was not successful",
@ -438,6 +452,109 @@
} }
} }
}, },
"/userfields/{entity}/{objectId}": {
"get": {
"summary": "Returns all userfields with their values of the given object of the given entity",
"tags": [
"Generic entity interactions"
],
"parameters": [
{
"in": "path",
"name": "entity",
"required": true,
"description": "A valid entity name",
"schema": {
"$ref": "#/components/internalSchemas/ExposedEntity"
}
},
{
"in": "path",
"name": "objectId",
"required": true,
"description": "A valid object id of the given entity",
"schema": {
"type": "integer"
}
}
],
"responses": {
"200": {
"description": "An entity object",
"content": {
"application/json": {
"schema": {
"type": "object",
"description": "Just key/value pairs of userfields"
}
}
}
},
"400": {
"description": "The operation was not successful",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/GenericErrorResponse"
}
}
}
}
}
},
"put": {
"summary": "Edits the given userfields of the given object of the given entity",
"tags": [
"Generic entity interactions"
],
"parameters": [
{
"in": "path",
"name": "entity",
"required": true,
"description": "A valid entity name",
"schema": {
"$ref": "#/components/internalSchemas/ExposedEntity"
}
},
{
"in": "path",
"name": "objectId",
"required": true,
"description": "A valid object id of the given entity",
"schema": {
"type": "integer"
}
}
],
"requestBody": {
"description": "A valid entity object of the entity specified in parameter *entity*",
"required": true,
"content": {
"application/json": {
"schema": {
"description": "Just key/value pairs of userfields"
}
}
}
},
"responses": {
"204": {
"description": "The operation was successful"
},
"400": {
"description": "The operation was not successful",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/GenericErrorResponse"
}
}
}
}
}
}
},
"/files/{group}/{fileName}": { "/files/{group}/{fileName}": {
"get": { "get": {
"summary": "Serves the given file", "summary": "Serves the given file",
@ -1229,6 +1346,16 @@
"type": "string", "type": "string",
"format": "date", "format": "date",
"description": "The best before date which applies to added products" "description": "The best before date which applies to added products"
},
"location_id": {
"type": "number",
"format": "integer",
"description": "If omitted, the default location of the product is used (only applies to added products)"
},
"price": {
"type": "number",
"format": "double",
"description": "If omitted, the last price of the product is used (only applies to added products)"
} }
} }
} }
@ -1325,26 +1452,84 @@
}, },
"/stock/shoppinglist/add-missing-products": { "/stock/shoppinglist/add-missing-products": {
"post": { "post": {
"summary": "Adds currently missing products (below defined min. stock amount) to the shopping list", "summary": "Adds currently missing products (below defined min. stock amount) to the given shopping list",
"tags": [ "tags": [
"Stock" "Stock"
], ],
"requestBody": {
"required": false,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"list_id": {
"type": "integer",
"description": "The shopping list to use, when omitted, the default shopping list (with id 1) is used"
}
},
"example": {
"list_id": 2
}
}
}
}
},
"responses": { "responses": {
"204": { "204": {
"description": "The operation was successful" "description": "The operation was successful"
},
"400": {
"description": "The operation was not successful (possible errors are: Not existing shopping list)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/GenericErrorResponse"
}
}
}
} }
} }
} }
}, },
"/stock/shoppinglist/clear": { "/stock/shoppinglist/clear": {
"post": { "post": {
"summary": "Removes all items from the shopping list", "summary": "Removes all items from the given shopping list",
"tags": [ "tags": [
"Stock" "Stock"
], ],
"requestBody": {
"required": false,
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"list_id": {
"type": "integer",
"description": "The shopping list id to clear, when omitted, the default shopping list (with id 1) is used"
}
},
"example": {
"list_id": 2
}
}
}
}
},
"responses": { "responses": {
"204": { "204": {
"description": "The operation was successful" "description": "The operation was successful"
},
"400": {
"description": "The operation was not successful (possible errors are: Not existing shopping list)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/GenericErrorResponse"
}
}
}
} }
} }
} }
@ -1478,6 +1663,84 @@
} }
} }
}, },
"/recipes/{recipeId}/requirements": {
"get": {
"summary": "Get requirements for recipe",
"tags": [
"Recipes"
],
"parameters": [
{
"in": "path",
"name": "recipeId",
"required": true,
"description": "A valid recipe id",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "A requirements recipe object",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RecipeRequirements"
}
}
}
},
"400": {
"description": "The operation was not successful",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/GenericErrorResponse"
}
}
}
}
}
}
},
"/recipes/requirements": {
"get": {
"summary": "Get all requirements for recipes",
"tags": [
"Recipes"
],
"responses": {
"200": {
"description": "An array of requirements recipe objects",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"oneOf": [
{
"$ref": "#/components/schemas/RecipeRequirements"
}
]
}
}
}
}
},
"400": {
"description": "The operation was not successful",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/GenericErrorResponse"
}
}
}
}
}
}
},
"/recipes/{recipeId}/consume": { "/recipes/{recipeId}/consume": {
"post": { "post": {
"summary": "Consumes all products of the given recipe", "summary": "Consumes all products of the given recipe",
@ -1959,6 +2222,7 @@
"locations", "locations",
"quantity_units", "quantity_units",
"shopping_list", "shopping_list",
"shopping_lists",
"recipes", "recipes",
"recipes_pos", "recipes_pos",
"recipes_nestings", "recipes_nestings",
@ -1966,7 +2230,9 @@
"task_categories", "task_categories",
"product_groups", "product_groups",
"equipment", "equipment",
"api_keys" "api_keys",
"userfields",
"meal_plan"
] ]
}, },
"ExposedEntitiesPreventListing": { "ExposedEntitiesPreventListing": {
@ -2007,10 +2273,23 @@
"qu_id_stock": { "qu_id_stock": {
"type": "integer" "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": { "qu_factor_purchase_to_stock": {
"type": "number", "type": "number",
"format": "double" "format": "double"
}, },
"tare_weight": {
"type": "number",
"format": "double"
},
"barcode": { "barcode": {
"type": "string", "type": "string",
"description": "Can contain multiple barcodes separated by comma" "description": "Can contain multiple barcodes separated by comma"
@ -2025,6 +2304,11 @@
"minimum": 0, "minimum": 0,
"default": 0 "default": 0
}, },
"default_best_before_days_after_open": {
"type": "integer",
"minimum": 0,
"default": 0
},
"picture_file_name": { "picture_file_name": {
"type": "string" "type": "string"
}, },
@ -2035,6 +2319,26 @@
"type": "string", "type": "string",
"format": "date-time" "format": "date-time"
} }
},
"example": {
"id": "1",
"name": "Cookies",
"description": null,
"location_id": "4",
"qu_id_purchase": "3",
"qu_id_stock": "3",
"qu_factor_purchase_to_stock": "1.0",
"barcode": "cok1",
"min_stock_amount": "8",
"default_best_before_days": "0",
"row_created_timestamp": "2019-05-02 20:12:26",
"product_group_id": "1",
"picture_file_name": "cookies.jpg",
"default_best_before_days_after_open": "0",
"allow_partial_units_in_stock": "0",
"enable_tare_weight_handling": "0",
"tare_weight": "0.0",
"not_check_stock_fulfillment_for_recipes": "0"
} }
}, },
"QuantityUnit": { "QuantityUnit": {
@ -2055,7 +2359,18 @@
"row_created_timestamp": { "row_created_timestamp": {
"type": "string", "type": "string",
"format": "date-time" "format": "date-time"
},
"plural_forms": {
"type": "string"
} }
},
"example": {
"id": "2",
"name": "Piece",
"description": null,
"row_created_timestamp": "2019-05-02 20:12:25",
"name_plural": "Pieces",
"plural_forms": null
} }
}, },
"Location": { "Location": {
@ -2074,6 +2389,12 @@
"type": "string", "type": "string",
"format": "date-time" "format": "date-time"
} }
},
"example": {
"id": "2",
"name": "0",
"description": null,
"row_created_timestamp": "2019-05-02 20:12:25"
} }
}, },
"StockEntry": { "StockEntry": {
@ -2085,6 +2406,9 @@
"product_id": { "product_id": {
"type": "integer" "type": "integer"
}, },
"location_id": {
"type": "integer"
},
"amount": { "amount": {
"type": "double" "type": "double"
}, },
@ -2100,10 +2424,61 @@
"type": "string", "type": "string",
"description": "A unique id which references this stock entry during its lifetime" "description": "A unique id which references this stock entry during its lifetime"
}, },
"price": {
"type": "double"
},
"open": {
"type": "integer"
},
"opened_date": {
"type": "string",
"format": "date"
},
"row_created_timestamp": { "row_created_timestamp": {
"type": "string", "type": "string",
"format": "date-time" "format": "date-time"
} }
},
"example": {
"id": "77",
"product_id": "1",
"amount": "2",
"best_before_date": "2019-07-07",
"purchased_date": "2019-05-03",
"stock_id": "5ccc6b2421979",
"price": null,
"open": "0",
"opened_date": null,
"row_created_timestamp": "2019-05-03 18:24:04",
"location_id": "4"
}
},
"RecipeRequirements": {
"type": "object",
"properties": {
"recipe_id": {
"type": "integer"
},
"need_fulfilled": {
"type": "boolean"
},
"need_fulfilled_with_shopping_list": {
"type": "boolean"
},
"missing_products_count": {
"type": "integer"
},
"costs": {
"type": "number",
"format": "double"
}
},
"example": {
"recipe_id": "1",
"need_fulfilled": "0",
"need_fulfilled_with_shopping_list": "0",
"missing_products_count": "2",
"costs": "17.74"
} }
}, },
"ProductDetailsResponse": { "ProductDetailsResponse": {
@ -2142,7 +2517,67 @@
}, },
"location": { "location": {
"$ref": "#/components/schemas/Location" "$ref": "#/components/schemas/Location"
},
"average_shelf_life_days": {
"type": "number",
"format": "integer"
},
"spoil_rate_percent": {
"type": "number",
"format": "double"
} }
},
"example": {
"product": {
"id": "1",
"name": "Cookies",
"description": null,
"location_id": "4",
"qu_id_purchase": "3",
"qu_id_stock": "3",
"qu_factor_purchase_to_stock": "1.0",
"barcode": "cok1",
"min_stock_amount": "8",
"default_best_before_days": "0",
"row_created_timestamp": "2019-05-02 20:12:26",
"product_group_id": "1",
"picture_file_name": "cookies.jpg",
"default_best_before_days_after_open": "0",
"allow_partial_units_in_stock": "0",
"enable_tare_weight_handling": "0",
"tare_weight": "0.0",
"not_check_stock_fulfillment_for_recipes": "0"
},
"last_purchased": null,
"last_used": null,
"stock_amount": "2",
"stock_amount_opened": null,
"quantity_unit_purchase": {
"id": "3",
"name": "Pack",
"description": null,
"row_created_timestamp": "2019-05-02 20:12:25",
"name_plural": "Packs",
"plural_forms": null
},
"quantity_unit_stock": {
"id": "3",
"name": "Pack",
"description": null,
"row_created_timestamp": "2019-05-02 20:12:25",
"name_plural": "Packs",
"plural_forms": null
},
"last_price": null,
"next_best_before_date": "2019-07-07",
"location": {
"id": "4",
"name": "Candy cupboard",
"description": null,
"row_created_timestamp": "2019-05-02 20:12:25"
},
"average_shelf_life_days": -1,
"spoil_rate_percent": 0
} }
}, },
"ProductPriceHistory": { "ProductPriceHistory": {
@ -2209,6 +2644,27 @@
"type": "string", "type": "string",
"format": "date-time" "format": "date-time"
} }
},
"example": {
"chore": {
"id": 0,
"name": "string",
"description": "string",
"period_type": "manually",
"period_days": 0,
"row_created_timestamp": "2019-05-04T11:31:04.563Z"
},
"last_tracked": "2019-05-04T11:31:04.563Z",
"track_count": 0,
"last_done_by": {
"id": 0,
"username": "string",
"first_name": "string",
"last_name": "string",
"display_name": "string",
"row_created_timestamp": "2019-05-04T11:31:04.564Z"
},
"next_estimated_execution_time": "2019-05-04T11:31:04.564Z"
} }
}, },
"BatteryDetailsResponse": { "BatteryDetailsResponse": {
@ -2230,6 +2686,19 @@
"type": "string", "type": "string",
"format": "date-time" "format": "date-time"
} }
},
"example": {
"battery": {
"id": "1",
"name": "Battery1",
"description": "Warranty ends 2023",
"used_in": "TV remote control",
"charge_interval_days": "0",
"row_created_timestamp": "2019-05-02 20:12:26"
},
"last_charged": "2019-03-13 18:12:28",
"charge_cycles_count": 4,
"next_estimated_charge_time": "2999-12-31 23:59:59"
} }
}, },
"Session": { "Session": {
@ -2418,6 +2887,9 @@
"period_days": { "period_days": {
"type": "integer" "type": "integer"
}, },
"track_date_only": {
"type": "boolean"
},
"row_created_timestamp": { "row_created_timestamp": {
"type": "string", "type": "string",
"format": "date-time" "format": "date-time"

View File

@ -156,6 +156,8 @@ $app->group('/api', function()
if (GROCY_FEATURE_FLAG_RECIPES) if (GROCY_FEATURE_FLAG_RECIPES)
{ {
$this->post('/recipes/{recipeId}/add-not-fulfilled-products-to-shoppinglist', '\Grocy\Controllers\RecipesApiController:AddNotFulfilledProductsToShoppingList'); $this->post('/recipes/{recipeId}/add-not-fulfilled-products-to-shoppinglist', '\Grocy\Controllers\RecipesApiController:AddNotFulfilledProductsToShoppingList');
$this->get('/recipes/{recipeId}/requirements', '\Grocy\Controllers\RecipesApiController:GetRecipeRequirements');
$this->get('/recipes/requirements', '\Grocy\Controllers\RecipesApiController:GetRecipeRequirements');
$this->post('/recipes/{recipeId}/consume', '\Grocy\Controllers\RecipesApiController:ConsumeRecipe'); $this->post('/recipes/{recipeId}/consume', '\Grocy\Controllers\RecipesApiController:ConsumeRecipe');
} }