Track on consume for which recipe it was (closes #64 and references #64)

This commit is contained in:
Bernd Bestel 2019-03-03 18:20:06 +01:00
parent 38825c70da
commit 8020f92d6b
No known key found for this signature in database
GPG Key ID: 71BD34C0D4891300
13 changed files with 127 additions and 7 deletions

View File

@ -49,6 +49,16 @@ class BaseController
} }
$container->view->set('embedded', $embedded); $container->view->set('embedded', $embedded);
$constants = get_defined_constants();
foreach ($constants as $constant => $value)
{
if (substr($constant, 0, 19) !== 'GROCY_FEATURE_FLAG_')
{
unset($constants[$constant]);
}
}
$container->view->set('featureFlags', $constants);
try try
{ {
$usersService = new UsersService(); $usersService = new UsersService();

View File

@ -121,7 +121,13 @@ class StockApiController extends BaseApiController
$specificStockEntryId = $requestBody['stock_entry_id']; $specificStockEntryId = $requestBody['stock_entry_id'];
} }
$bookingId = $this->StockService->ConsumeProduct($args['productId'], $requestBody['amount'], $spoiled, $transactionType, $specificStockEntryId); $recipeId = null;
if (array_key_exists('recipe_id', $requestBody) && is_numeric($requestBody['recipe_id']))
{
$recipeId = $requestBody['recipe_id'];
}
$bookingId = $this->StockService->ConsumeProduct($args['productId'], $requestBody['amount'], $spoiled, $transactionType, $specificStockEntryId, $recipeId);
return $this->ApiResponse(array('booking_id' => $bookingId)); return $this->ApiResponse(array('booking_id' => $bookingId));
} }
catch (\Exception $ex) catch (\Exception $ex)

View File

@ -40,7 +40,8 @@ class StockController extends BaseController
public function Consume(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args) public function Consume(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{ {
return $this->AppContainer->view->render($response, 'consume', [ return $this->AppContainer->view->render($response, 'consume', [
'products' => $this->Database->products()->orderBy('name') 'products' => $this->Database->products()->orderBy('name'),
'recipes' => $this->Database->recipes()->orderBy('name')
]); ]);
} }

View File

@ -1115,6 +1115,11 @@
"stock_entry_id": { "stock_entry_id": {
"type": "string", "type": "string",
"description": "A specific stock entry id to consume, if used, the amount has to be 1" "description": "A specific stock entry id to consume, if used, the amount has to be 1"
},
"recipe_id": {
"type": "number",
"format": "integer",
"description": "A valid recipe id for which this product was used (for statistical purposes only)"
} }
}, },
"example": { "example": {

View File

@ -333,5 +333,7 @@ return array(
'Do not check against the shopping list when adding missing items to it' => 'Do not check against the shopping list when adding missing items to it', 'Do not check against the shopping list when adding missing items to it' => 'Do not check against the shopping list when adding missing items to it',
'By default the amount to be added to the shopping list is "needed amount - stock amount - shopping list amount" - when this is enabled, it is only checked against the stock amount, not against what is already on the shopping list' => 'By default the amount to be added to the shopping list is "needed amount - stock amount - shopping list amount" - when this is enabled, it is only checked against the stock amount, not against what is already on the shopping list', 'By default the amount to be added to the shopping list is "needed amount - stock amount - shopping list amount" - when this is enabled, it is only checked against the stock amount, not against what is already on the shopping list' => 'By default the amount to be added to the shopping list is "needed amount - stock amount - shopping list amount" - when this is enabled, it is only checked against the stock amount, not against what is already on the shopping list',
'Picture' => 'Picture', 'Picture' => 'Picture',
'Uncheck ingredients to not put them on the shopping list' => 'Uncheck ingredients to not put them on the shopping list' 'Uncheck ingredients to not put them on the shopping list' => 'Uncheck ingredients to not put them on the shopping list',
'This is for statistical purposes only' => 'This is for statistical purposes only',
'You have to select a recipe' => 'You have to select a recipe'
); );

2
migrations/0055.sql Normal file
View File

@ -0,0 +1,2 @@
ALTER TABLE stock_log
ADD recipe_id INTEGER;

View File

@ -0,0 +1,55 @@
Grocy.Components.RecipePicker = { };
Grocy.Components.RecipePicker.GetPicker = function()
{
return $('#recipe_id');
}
Grocy.Components.RecipePicker.GetInputElement = function()
{
return $('#recipe_id_text_input');
}
Grocy.Components.RecipePicker.GetValue = function()
{
return $('#recipe_id').val();
}
Grocy.Components.RecipePicker.SetValue = function(value)
{
Grocy.Components.RecipePicker.GetInputElement().val(value);
Grocy.Components.RecipePicker.GetInputElement().trigger('change');
}
$('.recipe-combobox').combobox({
appendId: '_text_input',
bsVersion: '4',
clearIfNoMatch: true
});
var prefillByName = Grocy.Components.RecipePicker.GetPicker().parent().data('prefill-by-name').toString();
if (typeof prefillByName !== "undefined")
{
possibleOptionElement = $("#recipe_id option:contains('" + prefillByName + "')").first();
if (possibleOptionElement.length > 0)
{
$('#recipe_id').val(possibleOptionElement.val());
$('#recipe_id').data('combobox').refresh();
$('#recipe_id').trigger('change');
var nextInputElement = $(Grocy.Components.RecipePicker.GetPicker().parent().data('next-input-selector').toString());
nextInputElement.focus();
}
}
var prefillById = Grocy.Components.RecipePicker.GetPicker().parent().data('prefill-by-id').toString();
if (typeof prefillById !== "undefined")
{
$('#recipe_id').val(prefillById);
$('#recipe_id').data('combobox').refresh();
$('#recipe_id').trigger('change');
var nextInputElement = $(Grocy.Components.RecipePicker.GetPicker().parent().data('next-input-selector').toString());
nextInputElement.focus();
}

View File

@ -21,6 +21,11 @@
jsonData.stock_entry_id = jsonForm.specific_stock_entry; jsonData.stock_entry_id = jsonForm.specific_stock_entry;
} }
if (Grocy.FeatureFlags.GROCY_FEATURE_FLAG_RECIPES && Grocy.Components.RecipePicker.GetValue().toString().length > 0)
{
jsonData.recipe_id = Grocy.Components.RecipePicker.GetValue();
}
Grocy.Api.Get('stock/products/' + jsonForm.product_id, Grocy.Api.Get('stock/products/' + jsonForm.product_id,
function(productDetails) function(productDetails)
{ {
@ -38,6 +43,10 @@
$('#amount').val(1); $('#amount').val(1);
Grocy.Components.ProductPicker.SetValue(''); Grocy.Components.ProductPicker.SetValue('');
if (Grocy.FeatureFlags.GROCY_FEATURE_FLAG_RECIPES)
{
Grocy.Components.RecipePicker.SetValue('');
}
Grocy.Components.ProductPicker.GetInputElement().focus(); Grocy.Components.ProductPicker.GetInputElement().focus();
Grocy.FrontendHelpers.ValidateForm('consume-form'); Grocy.FrontendHelpers.ValidateForm('consume-form');
}, },

View File

@ -68,7 +68,7 @@ class RecipesService extends BaseService
{ {
if ($recipePosition->only_check_single_unit_in_stock == 0) if ($recipePosition->only_check_single_unit_in_stock == 0)
{ {
$this->StockService->ConsumeProduct($recipePosition->product_id, $recipePosition->amount, false, StockService::TRANSACTION_TYPE_CONSUME); $this->StockService->ConsumeProduct($recipePosition->product_id, $recipePosition->amount, false, StockService::TRANSACTION_TYPE_CONSUME, 'default', $recipeId);
} }
} }
} }

View File

@ -165,7 +165,7 @@ class StockService extends BaseService
} }
} }
public function ConsumeProduct(int $productId, float $amount, bool $spoiled, $transactionType, $specificStockEntryId = 'default') public function ConsumeProduct(int $productId, float $amount, bool $spoiled, $transactionType, $specificStockEntryId = 'default', $recipeId = null)
{ {
if (!$this->ProductExists($productId)) if (!$this->ProductExists($productId))
{ {
@ -206,7 +206,8 @@ class StockService extends BaseService
'stock_id' => $stockEntry->stock_id, 'stock_id' => $stockEntry->stock_id,
'transaction_type' => $transactionType, 'transaction_type' => $transactionType,
'price' => $stockEntry->price, 'price' => $stockEntry->price,
'opened_date' => $stockEntry->opened_date 'opened_date' => $stockEntry->opened_date,
'recipe_id' => $recipeId
)); ));
$logRow->save(); $logRow->save();
@ -228,7 +229,8 @@ class StockService extends BaseService
'stock_id' => $stockEntry->stock_id, 'stock_id' => $stockEntry->stock_id,
'transaction_type' => $transactionType, 'transaction_type' => $transactionType,
'price' => $stockEntry->price, 'price' => $stockEntry->price,
'opened_date' => $stockEntry->opened_date 'opened_date' => $stockEntry->opened_date,
'recipe_id' => $recipeId
)); ));
$logRow->save(); $logRow->save();

View File

@ -0,0 +1,19 @@
@push('componentScripts')
<script src="{{ $U('/viewjs/components/recipepicker.js', true) }}?v={{ $version }}"></script>
@endpush
@php if(empty($prefillByName)) { $prefillByName = ''; } @endphp
@php if(empty($prefillById)) { $prefillById = ''; } @endphp
@php if(!isset($isRequired)) { $isRequired = true; } @endphp
@php if(empty($hint)) { $hint = ''; } @endphp
<div class="form-group" data-next-input-selector="{{ $nextInputSelector }}" data-prefill-by-name="{{ $prefillByName }}" data-prefill-by-id="{{ $prefillById }}">
<label for="recipe_id">{{ $L('Recipe') }}&nbsp;&nbsp;<span id="{{ $hintId }}" class="small text-muted">{{ $hint }}</span></label>
<select class="form-control recipe-combobox" id="recipe_id" name="recipe_id" @if($isRequired) required @endif>
<option value=""></option>
@foreach($recipes as $recipe)
<option value="{{ $recipe->id }}">{{ $recipe->name }}</option>
@endforeach
</select>
<div class="invalid-feedback">{{ $L('You have to select a recipe') }}</div>
</div>

View File

@ -42,6 +42,14 @@
</label> </label>
</div> </div>
@if (GROCY_FEATURE_FLAG_RECIPES)
@include('components.recipepicker', array(
'recipes' => $recipes,
'isRequired' => false,
'hint' => $L('This is for statistical purposes only')
))
@endif
<button id="save-consume-button" class="btn btn-success">{{ $L('OK') }}</button> <button id="save-consume-button" class="btn btn-success">{{ $L('OK') }}</button>
<button id="save-mark-as-open-button" class="btn btn-secondary">{{ $L('Mark as opened') }}</button> <button id="save-mark-as-open-button" class="btn btn-secondary">{{ $L('Mark as opened') }}</button>

View File

@ -54,6 +54,7 @@
Grocy.Culture = '{{ GROCY_CULTURE }}'; Grocy.Culture = '{{ GROCY_CULTURE }}';
Grocy.Currency = '{{ GROCY_CURRENCY }}'; Grocy.Currency = '{{ GROCY_CURRENCY }}';
Grocy.UserSettings = {!! json_encode($userSettings) !!}; Grocy.UserSettings = {!! json_encode($userSettings) !!};
Grocy.FeatureFlags = {!! json_encode($featureFlags) !!};
</script> </script>
</head> </head>