Stock detail updates (#493)

* Fix spelling

* stockdetail refresh with location name

* Stock updates

* change stock_row_id to id

* fix stockdetail refresh rows after clicking undo

* fix stockdetail consume spoiled
This commit is contained in:
kriddles 2020-01-17 10:54:34 -06:00 committed by Bernd Bestel
parent d4bec3bd10
commit 2a608c41e9
7 changed files with 96 additions and 32 deletions

View File

@ -124,7 +124,7 @@ class StockApiController extends BaseApiController
throw new \Exception('Request body could not be parsed (probably invalid JSON format or missing/wrong Content-Type header)');
}
if (!array_key_exists('stock_row_id', $requestBody))
if (!array_key_exists('id', $requestBody))
{
throw new \Exception('A stock row id is required');
}
@ -152,7 +152,7 @@ class StockApiController extends BaseApiController
$locationId = $requestBody['location_id'];
}
$bookingId = $this->StockService->EditStock($requestBody['stock_row_id'], $requestBody['amount'], $bestBeforeDate, $locationId, $price);
$bookingId = $this->StockService->EditStock($requestBody['id'], $requestBody['amount'], $bestBeforeDate, $locationId, $price);
return $this->ApiResponse($this->Database->stock_log($bookingId));
}
catch (\Exception $ex)
@ -388,7 +388,7 @@ class StockApiController extends BaseApiController
return $this->ApiResponse($this->StockService->GetCurrentStock());
}
public function CurrentVolatilStock(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
public function CurrentVolatileStock(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{
$nextXDays = 5;
if (isset($request->getQueryParams()['expiring_days']) && !empty($request->getQueryParams()['expiring_days']) && is_numeric($request->getQueryParams()['expiring_days']))
@ -580,6 +580,11 @@ class StockApiController extends BaseApiController
return $this->ApiResponse($this->StockService->GetProductStockLocations($args['productId']));
}
public function StockEntry(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{
return $this->ApiResponse($this->StockService->GetStockEntry($args['entryId']));
}
public function StockBooking(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
{
try

View File

@ -1063,10 +1063,10 @@
"schema": {
"type": "object",
"properties": {
"stock_row_id": {
"id": {
"type": "number",
"format": "number",
"description": "The Stock Row Id"
"description": "The stock table id"
},
"amount": {
"type": "number",
@ -1090,7 +1090,7 @@
}
},
"example": {
"stock_row_id": 2,
"id": 2,
"amount": 1,
"best_before_date": "2019-01-19",
"location_id": 2,
@ -1124,6 +1124,47 @@
}
}
},
"/stock/{entryId}/entry": {
"get": {
"summary": "Returns details of the given stock",
"tags": [
"Stock"
],
"parameters": [
{
"in": "path",
"name": "entryId",
"required": true,
"description": "A valid stock row id",
"schema": {
"type": "integer"
}
}
],
"responses": {
"200": {
"description": "A StockEntry Response object",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/StockEntry"
}
}
}
},
"400": {
"description": "The operation was not successful (possible errors are: Not existing product)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/GenericErrorResponse"
}
}
}
}
}
}
},
"/stock/volatile": {
"get": {
"summary": "Returns all products which are expiring soon, are already expired or currently missing",
@ -3203,7 +3244,6 @@
"quantity_unit_conversions",
"shopping_list",
"shopping_lists",
"stock",
"recipes",
"recipes_pos",
"recipes_nestings",

View File

@ -68,7 +68,7 @@ $(document).on('click', '.stock-consume-button', function(e)
var stockRowId = $(e.currentTarget).attr('data-stockrow-id');
var consumeAmount = $(e.currentTarget).attr('data-consume-amount');
var wasSpoiled = $(e.currentTarget).hasClass("product-consume-button-spoiled");
var wasSpoiled = $(e.currentTarget).hasClass("stock-consume-button-spoiled");
Grocy.Api.Post('stock/products/' + productId + '/consume', { 'amount': consumeAmount, 'spoiled': wasSpoiled, 'location_id': locationId, 'stock_entry_id': specificStockEntryId},
function(bookingResponse)
@ -76,15 +76,15 @@ $(document).on('click', '.stock-consume-button', function(e)
Grocy.Api.Get('stock/products/' + productId,
function(result)
{
var toastMessage = __t('Removed %1$s of %2$s from stock', consumeAmount.toString() + " " + __n(consumeAmount, result.quantity_unit_stock.name, result.quantity_unit_stock.name_plural), result.product.name) + '<br><a class="btn btn-secondary btn-sm mt-2" href="#" onclick="UndoStockBooking(' + bookingResponse.id + ')"><i class="fas fa-undo"></i> ' + __t("Undo") + '</a>';
var toastMessage = __t('Removed %1$s of %2$s from stock', consumeAmount.toString() + " " + __n(consumeAmount, result.quantity_unit_stock.name, result.quantity_unit_stock.name_plural), result.product.name) + '<br><a class="btn btn-secondary btn-sm mt-2" href="#" onclick="UndoStockBookingEntry(' + bookingResponse.id + ',' + stockRowId + ')"><i class="fas fa-undo"></i> ' + __t("Undo") + '</a>';
if (wasSpoiled)
{
toastMessage += " (" + __t("Spoiled") + ")";
}
Grocy.FrontendHelpers.EndUiBusy();
toastr.success(toastMessage);
RefreshStockDetailRow(stockRowId);
toastr.success(toastMessage);
},
function(xhr)
{
@ -215,7 +215,7 @@ $(document).on("click", ".product-add-to-shopping-list-button", function(e)
function RefreshStockDetailRow(stockRowId)
{
Grocy.Api.Get("objects/stock/" + stockRowId,
Grocy.Api.Get("stock/" + stockRowId + "/entry",
function(result)
{
var stockRow = $('#stock-' + stockRowId + '-row');
@ -249,11 +249,20 @@ function RefreshStockDetailRow(stockRowId)
$(this).text(result.best_before_date).fadeIn(500);
});
var locationName = "";
Grocy.Api.Get("objects/locations/" + result.location_id,
function(locationResult)
{
locationName = locationResult.name;
},
function(xhr)
{
console.error(xhr);
});
$('#stock-' + stockRowId + '-location').parent().effect('highlight', { }, 500);
$('#stock-' + stockRowId + '-location').fadeOut(500, function()
{
//TODO grab location name instead of id
$(this).text(result.location_id).fadeIn(500);
$(this).text(locationName).fadeIn(500);
});
$('#stock-' + stockRowId + '-price').parent().effect('highlight', { }, 500);
@ -292,3 +301,18 @@ $(window).on("message", function(e)
RefreshStockDetailRow(data.Payload);
}
});
function UndoStockBookingEntry(bookingId, stockRowId)
{
Grocy.Api.Post('stock/bookings/' + bookingId.toString() + '/undo', { },
function(result)
{
window.postMessage(WindowMessageBag("StockDetailChanged", stockRowId), Grocy.BaseUrl);
toastr.success(__t("Booking successfully undone"));
},
function(xhr)
{
console.error(xhr);
}
);
};

View File

@ -1,6 +1,6 @@
$(document).ready(function() {
var stockRowId = GetUriParam('stockRowId');
Grocy.Api.Get("objects/stock/" + stockRowId,
Grocy.Api.Get("stock/" + stockRowId + "/entry",
function(stockEntry)
{
Grocy.Components.LocationPicker.SetId(stockEntry.location_id);
@ -79,12 +79,12 @@ $('#save-stockedit-button').on('click', function(e)
var bookingResponse = null;
var stockRowId = GetUriParam('stockRowId');
jsonData.stock_row_id = stockRowId;
jsonData.id = stockRowId;
Grocy.Api.Put("stock", jsonData,
function(result)
{
var successMessage = __t('Stock entry successfully updated') + '<br><a class="btn btn-secondary btn-sm mt-2" href="#" onclick="UndoStockBooking(\'' + result.id + '\')"><i class="fas fa-undo"></i> ' + __t("Undo") + '</a>';
var successMessage = __t('Stock entry successfully updated') + '<br><a class="btn btn-secondary btn-sm mt-2" href="#" onclick="UndoStockBookingEntry(\'' + result.id + '\',\'' + stockRowId + '\')"><i class="fas fa-undo"></i> ' + __t("Undo") + '</a>';
window.parent.postMessage(WindowMessageBag("StockDetailChanged", stockRowId), Grocy.BaseUrl);
window.parent.postMessage(WindowMessageBag("ShowSuccessMessage", successMessage), Grocy.BaseUrl);
@ -135,17 +135,3 @@ if (Grocy.Components.DateTimePicker)
Grocy.FrontendHelpers.ValidateForm('stockedit-form');
});
}
function UndoStockBooking(bookingId)
{
Grocy.Api.Post('stock/bookings/' + bookingId.toString() + '/undo', { },
function(result)
{
toastr.success(__t("Booking successfully undone"));
},
function(xhr)
{
console.error(xhr);
}
);
};

View File

@ -161,8 +161,9 @@ $app->group('/api', function()
if (GROCY_FEATURE_FLAG_STOCK)
{
$this->get('/stock', '\Grocy\Controllers\StockApiController:CurrentStock');
$this->get('/stock/{entryId}/entry', '\Grocy\Controllers\StockApiController:StockEntry');
$this->put('/stock', '\Grocy\Controllers\StockApiController:EditStock');
$this->get('/stock/volatile', '\Grocy\Controllers\StockApiController:CurrentVolatilStock');
$this->get('/stock/volatile', '\Grocy\Controllers\StockApiController:CurrentVolatileStock');
$this->get('/stock/products/{productId}', '\Grocy\Controllers\StockApiController:ProductDetails');
$this->get('/stock/products/{productId}/entries', '\Grocy\Controllers\StockApiController:ProductStockEntries');
$this->get('/stock/products/{productId}/locations', '\Grocy\Controllers\StockApiController:ProductStockLocations');

View File

@ -170,6 +170,11 @@ class StockService extends BaseService
return $returnData;
}
public function GetStockEntry($entryId)
{
return $this->Database->stock()->where('id', $entryId)->fetch();
}
public function GetProductStockEntries($productId, $excludeOpened = false)
{
// In order of next use:

View File

@ -127,10 +127,13 @@
<i class="fas fa-edit"></i> {{ $__t('Edit product') }}
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item product-consume-button product-consume-button-spoiled @if($currentStockEntry->amount < 1) disabled @endif" type="button" href="#"
<a class="dropdown-item stock-consume-button stock-consume-button-spoiled @if($currentStockEntry->amount < 1) disabled @endif" type="button" href="#"
data-product-id="{{ $currentStockEntry->product_id }}"
data-product-name="{{ FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->name }}"
data-product-qu-name="{{ FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name }}"
data-stock-id="{{ $currentStockEntry->stock_id }}"
data-stockrow-id="{{ $currentStockEntry->id }}"
data-location-id="{{ $currentStockEntry->location_id }}"
data-consume-amount="1">
<i class="fas fa-utensils"></i> {{ $__t('Consume %1$s of %2$s as spoiled', '1 ' . FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name, FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->name) }}
</a>