diff --git a/public/viewjs/transfer.js b/public/viewjs/transfer.js index 9bfc8116..f6fdcb66 100644 --- a/public/viewjs/transfer.js +++ b/public/viewjs/transfer.js @@ -36,6 +36,8 @@ $('#save-transfer-button').on('click', function(e) jsonData.stock_entry_id = jsonForm.specific_stock_entry; } + var bookingResponse = null; + Grocy.Api.Get('stock/products/' + jsonForm.product_id, function(productDetails) { @@ -43,6 +45,8 @@ $('#save-transfer-button').on('click', function(e) function(result) { var addBarcode = GetUriParam('addbarcodetoselection'); + bookingResponse = result; + if (addBarcode !== undefined) { var existingBarcodes = productDetails.product.barcode || ''; @@ -71,11 +75,11 @@ $('#save-transfer-button').on('click', function(e) if (productDetails.product.enable_tare_weight_handling == 1) { - var successMessage = __t('Transfered %1$s of %2$s from %3$s to %4$s', Math.abs(jsonForm.amount - parseFloat(productDetails.product.tare_weight)) + " " + __n(jsonForm.amount, productDetails.quantity_unit_stock.name, productDetails.quantity_unit_stock.name_plural), productDetails.product.name,$('option:selected', "#location_id_from").text(), $('option:selected', "#location_id_to").text()); + var successMessage = __t('Transfered %1$s of %2$s from %3$s to %4$s', Math.abs(jsonForm.amount - parseFloat(productDetails.product.tare_weight)) + " " + __n(jsonForm.amount, productDetails.quantity_unit_stock.name, productDetails.quantity_unit_stock.name_plural), productDetails.product.name,$('option:selected', "#location_id_from").text(), $('option:selected', "#location_id_to").text()) + '
' + __t("Undo") + ''; } else { - var successMessage =__t('Transfered %1$s of %2$s from %3$s to %4$s', Math.abs(jsonForm.amount) + " " + __n(jsonForm.amount, productDetails.quantity_unit_stock.name, productDetails.quantity_unit_stock.name_plural), productDetails.product.name, $('option:selected', "#location_id_from").text(), $('option:selected', "#location_id_to").text()); + var successMessage =__t('Transfered %1$s of %2$s from %3$s to %4$s', Math.abs(jsonForm.amount) + " " + __n(jsonForm.amount, productDetails.quantity_unit_stock.name, productDetails.quantity_unit_stock.name_plural), productDetails.product.name, $('option:selected', "#location_id_from").text(), $('option:selected', "#location_id_to").text()) + '
' + __t("Undo") + ''; } if (GetUriParam("embedded") !== undefined) @@ -407,3 +411,31 @@ $("#use_specific_stock_entry").on("change", function() Grocy.FrontendHelpers.ValidateForm("transfer-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); + } + ); +}; + +function UndoStockTransaction(transactionId) +{ + Grocy.Api.Post('stock/transactions/' + transactionId.toString() + '/undo', { }, + function (result) + { + toastr.success(__t("Transaction successfully undone")); + }, + function (xhr) + { + console.error(xhr); + } + ); +}; diff --git a/services/StockService.php b/services/StockService.php index 08d7a6c0..2e42dd20 100644 --- a/services/StockService.php +++ b/services/StockService.php @@ -930,6 +930,7 @@ class StockService extends BaseService { $this->UndoBooking($correlatedBooking->id, true); } + return; } $hasSubsequentBookings = $this->Database->stock_log()->where('stock_id = :1 AND id != :2 AND (correlation_id is not null OR correlation_id != :3) AND id > :2 AND undone = 0', $logRow->stock_id, $logRow->id, $logRow->correlation_id)->count() > 0; @@ -970,6 +971,60 @@ class StockService extends BaseService 'undone_timestamp' => date('Y-m-d H:i:s') )); } + elseif ($logRow->transaction_type === self::TRANSACTION_TYPE_TRANSFER_TO) + { + $stockRow = $this->Database->stock()->where('stock_id = :1 AND location_id = :2', $logRow->stock_id, $logRow->location_id)->fetch(); + if ($stockRow === null) + { + throw new \Exception('Booking does not exist or was already undone'); + } + $newAmount = $stockRow->amount - $logRow->amount; + + if ($newAmount == 0) + { + $stockRow->delete(); + } else { + // Remove corresponding amount back to stock + $stockRow->update(array( + 'amount' => $newAmount + )); + } + + // Update log entry + $logRow->update(array( + 'undone' => 1, + 'undone_timestamp' => date('Y-m-d H:i:s') + )); + } + elseif ($logRow->transaction_type === self::TRANSACTION_TYPE_TRANSFER_FROM) + { + // Add corresponding amount back to stock or + // create a row if missing + $stockRow = $this->Database->stock()->where('stock_id = :1 AND location_id = :2', $logRow->stock_id, $logRow->location_id)->fetch(); + if ($stockRow === null) + { + $stockRow = $this->Database->stock()->createRow(array( + 'product_id' => $logRow->product_id, + 'amount' => $logRow->amount * -1, + 'best_before_date' => $logRow->best_before_date, + 'purchased_date' => $logRow->purchased_date, + 'stock_id' => $logRow->stock_id, + 'price' => $logRow->price, + 'opened_date' => $logRow->opened_date + )); + $stockRow->save(); + } else { + $stockRow->update(array( + 'amount' => $stockRow->amount - $logRow->amount + )); + } + + // Update log entry + $logRow->update(array( + 'undone' => 1, + 'undone_timestamp' => date('Y-m-d H:i:s') + )); + } elseif ($logRow->transaction_type === self::TRANSACTION_TYPE_PRODUCT_OPENED) { // Remove opened flag from corresponding log entry