diff --git a/controllers/RecipesApiController.php b/controllers/RecipesApiController.php index fd2cce5a..570b2ac9 100644 --- a/controllers/RecipesApiController.php +++ b/controllers/RecipesApiController.php @@ -19,4 +19,17 @@ class RecipesApiController extends BaseApiController $this->RecipesService->AddNotFulfilledProductsToShoppingList($args['recipeId']); return $this->VoidApiActionResponse($response); } + + public function ConsumeRecipe(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args) + { + try + { + $this->RecipesService->ConsumeRecipe($args['recipeId']); + return $this->VoidApiActionResponse($response); + } + catch (\Exception $ex) + { + return $this->VoidApiActionResponse($response, false, 400, $ex->getMessage()); + } + } } diff --git a/grocy.openapi.json b/grocy.openapi.json index 63c7f28d..206b758b 100644 --- a/grocy.openapi.json +++ b/grocy.openapi.json @@ -1010,6 +1010,37 @@ } } }, + "/recipes/consume-recipe/{recipeId}": { + "get": { + "description": "Consumes all products of the given recipe", + "tags": [ + "Recipes" + ], + "parameters": [ + { + "in": "path", + "name": "recipeId", + "required": true, + "description": "A valid recipe id", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "A VoidApiActionResponse object", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VoidApiActionResponse" + } + } + } + } + } + } + }, "/habits/track-habit-execution/{habitId}": { "get": { "description": "Tracks an execution of the given habit", diff --git a/localization/de.php b/localization/de.php index 5b649af3..6d05a702 100644 --- a/localization/de.php +++ b/localization/de.php @@ -209,7 +209,10 @@ return array( 'This cannot be lower than #1' => 'Dies darf nicht kleiner als #1 sein', '-1 means that this product never expires' => '-1 bedeuet, dass dieses Produkt niemals abläuft', 'Quantity unit' => 'Mengeneinheit', - 'Only check if a single unit is in stock (a different quantity can then be used above)' => 'Nur prüfen, ob eine einzelne Einheit vorrätig ist (eine abweichende Mengeneinheit kann dann oben verwendet werden)', + 'Only check if a single unit is in stock (a different quantity can then be used above)' => 'Nur prüfen, ob eine einzelne Einheit vorrätig ist (eine abweichende Mengeneinheit kann dann oben verwendet werden)', + 'Are you sure to consume all ingredients needed by recipe "#1" (ingredients marked with "check only if a single unit is in stock" will be ignored)?' => 'Sicher, dass alle Zutaten die vom Rezept "#1" benötigt werden aus dem Bestand entfernt werden sollen (Zutaten markiert mit "nur prüfen, ob eine einzelne Einheit vorrätig ist" werden ignoriert)?', + 'Removed all ingredients of recipe "#1" from stock' => 'Alle Zutaten, die vom Rezept "#1" benötigt werden, wurdem aus dem Bestand entfernt', + 'Consume all ingredients needed by this recipe' => 'Alle Zutaten, die von diesem Rezept benötigt werden, aus dem Bestand enternen', //Constants 'manually' => 'Manuell', diff --git a/public/viewjs/recipes.js b/public/viewjs/recipes.js index c6133737..042b4968 100644 --- a/public/viewjs/recipes.js +++ b/public/viewjs/recipes.js @@ -104,6 +104,42 @@ $(document).on('click', '.recipe-order-missing-button', function(e) }); }); +$("#selectedRecipeConsumeButton").on('click', function(e) +{ + var objectName = $(e.currentTarget).attr('data-recipe-name'); + var objectId = $(e.currentTarget).attr('data-recipe-id'); + + bootbox.confirm({ + message: L('Are you sure to consume all ingredients needed by recipe "#1" (ingredients marked with "check only if a single unit is in stock" will be ignored)?', objectName), + buttons: { + confirm: { + label: L('Yes'), + className: 'btn-success' + }, + cancel: { + label: L('No'), + className: 'btn-danger' + } + }, + callback: function(result) + { + if (result === true) + { + Grocy.Api.Get('recipes/consume-recipe/' + objectId, + function(result) + { + toastr.success(L('Removed all ingredients of recipe "#1" from stock', objectName)); + }, + function(xhr) + { + console.error(xhr); + } + ); + } + } + }); +}); + recipesTables.on('select', function(e, dt, type, indexes) { if (type === 'row') diff --git a/routes.php b/routes.php index ee73ac0e..82bbcc19 100644 --- a/routes.php +++ b/routes.php @@ -91,6 +91,7 @@ $app->group('/api', function() // Recipes $this->get('/recipes/add-not-fulfilled-products-to-shopping-list/{recipeId}', '\Grocy\Controllers\RecipesApiController:AddNotFulfilledProductsToShoppingList'); + $this->get('/recipes/consume-recipe/{recipeId}', '\Grocy\Controllers\RecipesApiController:ConsumeRecipe'); // Habits $this->get('/habits/track-habit-execution/{habitId}', '\Grocy\Controllers\HabitsApiController:TrackHabitExecution'); diff --git a/services/RecipesService.php b/services/RecipesService.php index bbad144c..a1d11130 100644 --- a/services/RecipesService.php +++ b/services/RecipesService.php @@ -2,8 +2,18 @@ namespace Grocy\Services; +use \Grocy\Services\StockService; + class RecipesService extends BaseService { + public function __construct() + { + parent::__construct(); + $this->StockService = new StockService(); + } + + protected $StockService; + public function GetRecipesFulfillment() { $sql = 'SELECT * from recipes_fulfillment'; @@ -38,4 +48,27 @@ class RecipesService extends BaseService } } } + + public function ConsumeRecipe($recipeId) + { + if (!$this->RecipeExists($recipeId)) + { + throw new \Exception('Recipe does not exist'); + } + + $recipePositions = $this->Database->recipes_pos()->where('recipe_id', $recipeId)->fetchAll(); + foreach ($recipePositions as $recipePosition) + { + if ($recipePosition->only_check_single_unit_in_stock == 0) + { + $this->StockService->ConsumeProduct($recipePosition->product_id, $recipePosition->amount, false, StockService::TRANSACTION_TYPE_CONSUME); + } + } + } + + private function RecipeExists($recipeId) + { + $recipeRow = $this->Database->recipes()->where('id = :1', $recipeId)->fetch(); + return $recipeRow !== null; + } } diff --git a/views/recipes.blade.php b/views/recipes.blade.php index 195f6fba..5b47780e 100644 --- a/views/recipes.blade.php +++ b/views/recipes.blade.php @@ -39,9 +39,6 @@ - - -