diff --git a/grocy.openapi.json b/grocy.openapi.json
index 1e44a202..4ae93ae4 100644
--- a/grocy.openapi.json
+++ b/grocy.openapi.json
@@ -1130,7 +1130,7 @@
},
"/stock/products/{productId}/locations": {
"get": {
- "summary": "Returns all locations with current stock",
+ "summary": "Returns all locations where the given product currently has stock",
"tags": [
"Stock"
],
@@ -1427,7 +1427,7 @@
},
"/stock/products/{productId}/transfer": {
"post": {
- "summary": "Transfer the given amount of the given product from stock from one location to another",
+ "summary": "Transfers the given amount of the given product from one location to another (this is currently not supported for tare weight handling enabled products)",
"tags": [
"Stock"
],
@@ -1451,31 +1451,27 @@
"properties": {
"amount": {
"type": "number",
- "description": "The amount to remove - please note that when tare weight handling for the product is enabled, this needs to be the amount including the container weight (gross), the amount to be posted will be automatically calculated based on what is in stock and the defined tare weight"
+ "description": "The amount to transfer - please note that when tare weight handling for the product is enabled, this needs to be the amount including the container weight (gross), the amount to be posted will be automatically calculated based on what is in stock and the defined tare weight"
},
- "transaction_type": {
- "$ref": "#/components/internalSchemas/StockTransactionType"
- },
- "location_from_id": {
+ "location_id_from": {
"type": "number",
"format": "integer",
- "description": "Location the stock is transfering from"
+ "description": "A valid location id, the location from where the product should be transfered"
},
- "location_to_id": {
+ "location_id_to": {
"type": "number",
"format": "integer",
- "description": "Location the stock is transfering to"
+ "description": "A valid location id, the location to where the product should be transfered"
},
"stock_entry_id": {
"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 transfer, if used, the amount has to be 1"
}
},
"example": {
"amount": 1,
- "transaction_type": "transfer",
- "location_from_id": 1,
- "location_to_id": 2
+ "location_id_from": 1,
+ "location_id_to": 2
}
}
}
@@ -1493,7 +1489,7 @@
}
},
"400": {
- "description": "The operation was not successful (possible errors are: Not existing product, invalid transaction type, given amount > current stock amount)",
+ "description": "The operation was not successful (possible errors are: Not existing product, no existing from or to location, given amount > current stock amount at the source location)",
"content": {
"application/json": {
"schema": {
@@ -1847,6 +1843,82 @@
}
}
},
+ "/stock/products/by-barcode/{barcode}/transfer": {
+ "post": {
+ "summary": "Transfers the given amount of the by its barcode given product from one location to another (this is currently not supported for tare weight handling enabled products)",
+ "tags": [
+ "Stock"
+ ],
+ "parameters": [
+ {
+ "in": "path",
+ "name": "barcode",
+ "required": true,
+ "description": "Barcode",
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "amount": {
+ "type": "number",
+ "description": "The amount to transfer - please note that when tare weight handling for the product is enabled, this needs to be the amount including the container weight (gross), the amount to be posted will be automatically calculated based on what is in stock and the defined tare weight"
+ },
+ "location_id_from": {
+ "type": "number",
+ "format": "integer",
+ "description": "A valid location id, the location from where the product should be transfered"
+ },
+ "location_id_to": {
+ "type": "number",
+ "format": "integer",
+ "description": "A valid location id, the location to where the product should be transfered"
+ },
+ "stock_entry_id": {
+ "type": "string",
+ "description": "A specific stock entry id to transfer, if used, the amount has to be 1"
+ }
+ },
+ "example": {
+ "amount": 1,
+ "location_id_from": 1,
+ "location_id_to": 2
+ }
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "The operation was successful",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/StockLogEntry"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "The operation was not successful (possible errors are: Not existing product, no existing from or to location, given amount > current stock amount at the source location)",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/GenericErrorResponse"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
"/stock/products/by-barcode/{barcode}/inventory": {
"post": {
"summary": "Inventories the by its barcode given product (adds/removes based on the given new amount)",
diff --git a/migrations/0095.sql b/migrations/0095.sql
index 86486e66..f0cf4d5d 100644
--- a/migrations/0095.sql
+++ b/migrations/0095.sql
@@ -15,13 +15,14 @@ BEGIN
END;
DROP VIEW stock_current_locations;
-CREATE VIEW stock_current_locations AS
-SELECT
- s.id,
+CREATE VIEW stock_current_locations
+AS
+SELECT
+ 1 AS id, -- Dummy, LessQL needs an id column
s.product_id,
- IFNULL(s.location_id, p.location_id) AS location_id,
- l.name AS name
- FROM stock s
- JOIN products p ON s.product_id = p.id
- JOIN locations l on IFNULL(s.location_id, p.location_id) = l.id
-GROUP BY s.product_id, IFNULL(s.location_id, p.location_id);
+ s.location_id AS location_id,
+ l.name AS location_name
+FROM stock s
+JOIN locations l
+ ON s.location_id = l.id
+GROUP BY s.product_id, s.location_id, l.name;
diff --git a/public/viewjs/consume.js b/public/viewjs/consume.js
index 0400a682..3d6c64f9 100644
--- a/public/viewjs/consume.js
+++ b/public/viewjs/consume.js
@@ -90,7 +90,6 @@
}
else
{
-
Grocy.FrontendHelpers.EndUiBusy("consume-form");
toastr.success(successMessage);
@@ -187,56 +186,48 @@ $("#location_id").on('change', function(e)
var sumValue = 0;
$("#specific_stock_entry").find("option").remove().end().append("");
if ($("#use_specific_stock_entry").is(":checked"))
- {
- $("#use_specific_stock_entry").click();
- }
+ {
+ $("#use_specific_stock_entry").click();
+ }
if (locationId)
{
- Grocy.Api.Get("stock/products/" + Grocy.Components.ProductPicker.GetValue() + '/entries',
- function(stockEntries)
- {
- stockEntries.forEach(stockEntry =>
- {
- var openTxt = __t("Not opened");
- if (stockEntry.open == 1)
- {
- openTxt = __t("Opened");
- }
-
- if (stockEntry.location_id == locationId)
- {
- $("#specific_stock_entry").append($("");
- Grocy.Api.Get("stock/products/" + productId + '/locations',
- function(stockLocations)
- {
- var setDefault = 0;
- stockLocations.forEach(stockLocation =>
- {
- if (productDetails.location.id == stockLocation.location_id) {
- $("#location_id").append($("");
+ $("#specific_stock_entry").find("option").remove().end().append("");
$("#specific_stock_entry").attr("disabled", "");
$("#specific_stock_entry").removeAttr("required");
}
diff --git a/public/viewjs/stockoverview.js b/public/viewjs/stockoverview.js
index b0404981..5b68dbc2 100644
--- a/public/viewjs/stockoverview.js
+++ b/public/viewjs/stockoverview.js
@@ -219,7 +219,7 @@ $(document).on("click", ".product-purchase-button", function(e)
});
});
-$(document).on("click", ".product-transfer-custom-amount-button", function(e)
+$(document).on("click", ".product-transfer-button", function(e)
{
e.preventDefault();
diff --git a/public/viewjs/transfer.js b/public/viewjs/transfer.js
index 80e229b5..cbe51504 100644
--- a/public/viewjs/transfer.js
+++ b/public/viewjs/transfer.js
@@ -139,24 +139,29 @@ Grocy.Components.ProductPicker.GetPicker().on('change', function(e)
Grocy.Api.Get("stock/products/" + productId + '/locations',
function(stockLocations)
{
- var setDefault = 0;
+ var setDefault = 0;
stockLocations.forEach(stockLocation =>
{
- if (productDetails.location.id == stockLocation.location_id) {
+ if (productDetails.location.id == stockLocation.location_id)
+ {
$("#location_id_from").append($("