|
|
@@ -0,0 +1,380 @@ |
|
|
|
|
|
-- liquibase formatted sql |
|
|
|
|
|
|
|
|
|
|
|
-- changeset kelvin:20260921-drop-ill-triggers-for-zh |
|
|
|
|
|
-- comment: #36 Drop stock-UOM triggers so the next changesets can recreate them with Chinese SIGNAL text. |
|
|
|
|
|
DROP TRIGGER IF EXISTS `inventory_lot_line_AFTER_insert`; |
|
|
|
|
|
DROP TRIGGER IF EXISTS `inventory_lot_line_AFTER_update`; |
|
|
|
|
|
|
|
|
|
|
|
-- changeset kelvin:20260921-ill-after-insert-signal-zh splitStatements:false |
|
|
|
|
|
-- comment: #36 Recreate AFTER INSERT trigger. Same bucket logic as 20260910-ill-after-insert-stock-uom. SIGNAL text is Chinese for API/UI. |
|
|
|
|
|
CREATE DEFINER = CURRENT_USER TRIGGER `inventory_lot_line_AFTER_insert` |
|
|
|
|
|
AFTER INSERT |
|
|
|
|
|
ON `inventory_lot_line` |
|
|
|
|
|
FOR EACH ROW |
|
|
|
|
|
BEGIN |
|
|
|
|
|
DECLARE v_itemId INT; |
|
|
|
|
|
DECLARE v_stockUomId INT; -- bucket key = item_uom.uomId for NEW.stockItemUomId |
|
|
|
|
|
DECLARE v_baseUomId INT; -- baseUnit uomId; written to inventory.uomId only on CREATE |
|
|
|
|
|
DECLARE v_inventoryId INT DEFAULT NULL; |
|
|
|
|
|
DECLARE v_onHand DECIMAL(14, 2) DEFAULT 0; |
|
|
|
|
|
DECLARE v_unavailable DECIMAL(14, 2) DEFAULT 0; |
|
|
|
|
|
DECLARE v_currencyId INT DEFAULT NULL; |
|
|
|
|
|
DECLARE v_currencyName VARCHAR(30) DEFAULT 'HKD'; |
|
|
|
|
|
DECLARE v_price DECIMAL(14, 2) DEFAULT 0; |
|
|
|
|
|
|
|
|
|
|
|
-- Step 1: stockItemUomId is required to know which stock-UOM bucket this line belongs to. |
|
|
|
|
|
IF NEW.stockItemUomId IS NULL THEN |
|
|
|
|
|
SIGNAL SQLSTATE '45000' |
|
|
|
|
|
SET MESSAGE_TEXT = '入倉明細缺少庫存單位,無法入帳'; |
|
|
|
|
|
END IF; |
|
|
|
|
|
|
|
|
|
|
|
-- Step 2: Resolve bucket (itemId, stockUomId) from lot + item_uom. |
|
|
|
|
|
-- stockItemUomId -> item_uom.id; stockUomId := item_uom.uomId (must belong to the same item). |
|
|
|
|
|
SELECT il.itemId, iu.uomId |
|
|
|
|
|
INTO v_itemId, v_stockUomId |
|
|
|
|
|
FROM `inventory_lot` il |
|
|
|
|
|
INNER JOIN `item_uom` iu |
|
|
|
|
|
ON iu.id = NEW.stockItemUomId |
|
|
|
|
|
AND iu.itemId = il.itemId |
|
|
|
|
|
AND IFNULL(iu.deleted, 0) = 0 |
|
|
|
|
|
WHERE il.id = NEW.inventoryLotId |
|
|
|
|
|
AND IFNULL(il.deleted, 0) = 0 |
|
|
|
|
|
LIMIT 1; |
|
|
|
|
|
|
|
|
|
|
|
IF v_itemId IS NULL OR v_stockUomId IS NULL THEN |
|
|
|
|
|
SIGNAL SQLSTATE '45000' |
|
|
|
|
|
SET MESSAGE_TEXT = '無法對應庫存桶,請檢查貨品單位與批次'; |
|
|
|
|
|
END IF; |
|
|
|
|
|
|
|
|
|
|
|
-- Step 3: Resolve base UOM for inventory.uomId snapshot (used only if we INSERT a new inventory row). |
|
|
|
|
|
SELECT iu.uomId |
|
|
|
|
|
INTO v_baseUomId |
|
|
|
|
|
FROM `item_uom` iu |
|
|
|
|
|
WHERE iu.itemId = v_itemId |
|
|
|
|
|
AND iu.baseUnit = TRUE |
|
|
|
|
|
AND IFNULL(iu.deleted, 0) = 0 |
|
|
|
|
|
LIMIT 1; |
|
|
|
|
|
|
|
|
|
|
|
IF v_baseUomId IS NULL THEN |
|
|
|
|
|
SIGNAL SQLSTATE '45000' |
|
|
|
|
|
SET MESSAGE_TEXT = '此貨品未設定基本單位,無法建立庫存'; |
|
|
|
|
|
END IF; |
|
|
|
|
|
|
|
|
|
|
|
-- Step 4: Find existing inventory row for this stock-UOM bucket. |
|
|
|
|
|
SELECT i.id |
|
|
|
|
|
INTO v_inventoryId |
|
|
|
|
|
FROM `inventory` i |
|
|
|
|
|
WHERE i.itemId = v_itemId |
|
|
|
|
|
AND i.stockUomId = v_stockUomId |
|
|
|
|
|
AND IFNULL(i.deleted, 0) = 0 |
|
|
|
|
|
LIMIT 1; |
|
|
|
|
|
|
|
|
|
|
|
-- Step 5: Create inventory row if missing (qty starts at 0; Step 6 overwrites from lot lines). |
|
|
|
|
|
-- uomId = base snapshot once; stockUomId = bucket key. onHoldQty left at 0 and never maintained by this trigger. |
|
|
|
|
|
IF v_inventoryId IS NULL THEN |
|
|
|
|
|
-- Prefer currency/price from the lot's stock-in / PO / quotation path; fall back to HKD / first currency. |
|
|
|
|
|
SELECT c.id, COALESCE(c.name, 'HKD'), COALESCE(pql.price, 0) |
|
|
|
|
|
INTO v_currencyId, v_currencyName, v_price |
|
|
|
|
|
FROM `inventory_lot` il |
|
|
|
|
|
LEFT JOIN `stock_in_line` sil ON sil.id = il.stockInLineId |
|
|
|
|
|
LEFT JOIN `purchase_order_line` pol ON pol.id = sil.purchaseOrderLineId |
|
|
|
|
|
LEFT JOIN `purchase_quotation_line` pql |
|
|
|
|
|
ON pql.itemId = il.itemId AND pql.uomId = pol.uomId |
|
|
|
|
|
LEFT JOIN `purchase_quotation` pq ON pq.id = pql.purchaseQuotationId |
|
|
|
|
|
LEFT JOIN `currency` c ON c.id = pq.currencyId |
|
|
|
|
|
WHERE il.id = NEW.inventoryLotId |
|
|
|
|
|
LIMIT 1; |
|
|
|
|
|
|
|
|
|
|
|
IF v_currencyId IS NULL THEN |
|
|
|
|
|
SELECT c.id, COALESCE(c.name, 'HKD') |
|
|
|
|
|
INTO v_currencyId, v_currencyName |
|
|
|
|
|
FROM `currency` c |
|
|
|
|
|
WHERE c.code = 'HKD' |
|
|
|
|
|
AND IFNULL(c.deleted, 0) = 0 |
|
|
|
|
|
LIMIT 1; |
|
|
|
|
|
END IF; |
|
|
|
|
|
|
|
|
|
|
|
IF v_currencyId IS NULL THEN |
|
|
|
|
|
SELECT c.id, COALESCE(c.name, 'HKD') |
|
|
|
|
|
INTO v_currencyId, v_currencyName |
|
|
|
|
|
FROM `currency` c |
|
|
|
|
|
WHERE IFNULL(c.deleted, 0) = 0 |
|
|
|
|
|
ORDER BY c.id |
|
|
|
|
|
LIMIT 1; |
|
|
|
|
|
END IF; |
|
|
|
|
|
|
|
|
|
|
|
IF v_currencyId IS NULL THEN |
|
|
|
|
|
SIGNAL SQLSTATE '45000' |
|
|
|
|
|
SET MESSAGE_TEXT = '無法取得幣別,無法建立庫存'; |
|
|
|
|
|
END IF; |
|
|
|
|
|
|
|
|
|
|
|
INSERT INTO `inventory` (`itemId`, |
|
|
|
|
|
`onHandQty`, |
|
|
|
|
|
`onHoldQty`, |
|
|
|
|
|
`unavailableQty`, |
|
|
|
|
|
`price`, |
|
|
|
|
|
`currencyId`, |
|
|
|
|
|
`cpu`, |
|
|
|
|
|
`cpuUnit`, |
|
|
|
|
|
`cpm`, |
|
|
|
|
|
`cpmUnit`, |
|
|
|
|
|
`uomId`, |
|
|
|
|
|
`stockUomId`, |
|
|
|
|
|
`status`) |
|
|
|
|
|
VALUES (v_itemId, |
|
|
|
|
|
0, |
|
|
|
|
|
0, |
|
|
|
|
|
0, |
|
|
|
|
|
COALESCE(v_price, 0), |
|
|
|
|
|
v_currencyId, |
|
|
|
|
|
0, |
|
|
|
|
|
COALESCE(v_currencyName, 'HKD'), |
|
|
|
|
|
0, |
|
|
|
|
|
COALESCE(v_currencyName, 'HKD'), |
|
|
|
|
|
v_baseUomId, |
|
|
|
|
|
v_stockUomId, |
|
|
|
|
|
'unavailable'); |
|
|
|
|
|
|
|
|
|
|
|
SET v_inventoryId = LAST_INSERT_ID(); |
|
|
|
|
|
END IF; |
|
|
|
|
|
|
|
|
|
|
|
-- Step 6: Full recompute for THIS bucket only (not a delta on existing inventory qty). |
|
|
|
|
|
-- onHand = SUM(inQty - outQty) for all statuses |
|
|
|
|
|
-- unavailable = SUM(inQty - outQty) for status = unavailable only (holdQty ignored) |
|
|
|
|
|
SELECT COALESCE(SUM(ill.inQty - ill.outQty), 0), |
|
|
|
|
|
COALESCE(SUM(CASE |
|
|
|
|
|
WHEN LOWER(ill.status) = 'unavailable' |
|
|
|
|
|
THEN ill.inQty - ill.outQty |
|
|
|
|
|
ELSE 0 END), 0) |
|
|
|
|
|
INTO v_onHand, v_unavailable |
|
|
|
|
|
FROM `inventory_lot_line` ill |
|
|
|
|
|
INNER JOIN `inventory_lot` il ON il.id = ill.inventoryLotId AND IFNULL(il.deleted, 0) = 0 |
|
|
|
|
|
INNER JOIN `item_uom` iu ON iu.id = ill.stockItemUomId AND IFNULL(iu.deleted, 0) = 0 |
|
|
|
|
|
WHERE il.itemId = v_itemId |
|
|
|
|
|
AND iu.uomId = v_stockUomId |
|
|
|
|
|
AND IFNULL(ill.deleted, 0) = 0; |
|
|
|
|
|
|
|
|
|
|
|
-- Step 7: Overwrite inventory qty/status from the SUM (source of truth = lot lines). |
|
|
|
|
|
-- Do not touch onHoldQty, uomId, or stockUomId on an existing row. |
|
|
|
|
|
UPDATE `inventory` |
|
|
|
|
|
SET `onHandQty` = v_onHand, |
|
|
|
|
|
`unavailableQty` = v_unavailable, |
|
|
|
|
|
`status` = IF(v_onHand - v_unavailable > 0, 'available', 'unavailable'), |
|
|
|
|
|
`modified` = CURRENT_TIMESTAMP |
|
|
|
|
|
WHERE `id` = v_inventoryId; |
|
|
|
|
|
END; |
|
|
|
|
|
|
|
|
|
|
|
-- changeset kelvin:20260921-ill-after-update-signal-zh splitStatements:false |
|
|
|
|
|
-- comment: #36 Recreate AFTER UPDATE trigger. Same bucket logic as 20260910-ill-after-update-stock-uom. SIGNAL text is Chinese for API/UI. |
|
|
|
|
|
CREATE DEFINER = CURRENT_USER TRIGGER `inventory_lot_line_AFTER_update` |
|
|
|
|
|
AFTER UPDATE |
|
|
|
|
|
ON `inventory_lot_line` |
|
|
|
|
|
FOR EACH ROW |
|
|
|
|
|
BEGIN |
|
|
|
|
|
DECLARE v_itemId INT; |
|
|
|
|
|
DECLARE v_stockUomId INT; -- NEW bucket key |
|
|
|
|
|
DECLARE v_baseUomId INT; -- baseUnit uomId; used only when creating inventory |
|
|
|
|
|
DECLARE v_inventoryId INT DEFAULT NULL; |
|
|
|
|
|
DECLARE v_onHand DECIMAL(14, 2) DEFAULT 0; |
|
|
|
|
|
DECLARE v_unavailable DECIMAL(14, 2) DEFAULT 0; |
|
|
|
|
|
DECLARE v_currencyId INT DEFAULT NULL; |
|
|
|
|
|
DECLARE v_currencyName VARCHAR(30) DEFAULT 'HKD'; |
|
|
|
|
|
DECLARE v_price DECIMAL(14, 2) DEFAULT 0; |
|
|
|
|
|
|
|
|
|
|
|
DECLARE v_oldItemId INT DEFAULT NULL; |
|
|
|
|
|
DECLARE v_oldStockUomId INT DEFAULT NULL; |
|
|
|
|
|
DECLARE v_oldInventoryId INT DEFAULT NULL; |
|
|
|
|
|
DECLARE v_oldOnHand DECIMAL(14, 2) DEFAULT 0; |
|
|
|
|
|
DECLARE v_oldUnavailable DECIMAL(14, 2) DEFAULT 0; |
|
|
|
|
|
|
|
|
|
|
|
-- Step 1: NEW.stockItemUomId is required. |
|
|
|
|
|
IF NEW.stockItemUomId IS NULL THEN |
|
|
|
|
|
SIGNAL SQLSTATE '45000' |
|
|
|
|
|
SET MESSAGE_TEXT = '入倉明細缺少庫存單位,無法入帳'; |
|
|
|
|
|
END IF; |
|
|
|
|
|
|
|
|
|
|
|
-- Step 2: Resolve NEW bucket (itemId, stockUomId). |
|
|
|
|
|
SELECT il.itemId, iu.uomId |
|
|
|
|
|
INTO v_itemId, v_stockUomId |
|
|
|
|
|
FROM `inventory_lot` il |
|
|
|
|
|
INNER JOIN `item_uom` iu |
|
|
|
|
|
ON iu.id = NEW.stockItemUomId |
|
|
|
|
|
AND iu.itemId = il.itemId |
|
|
|
|
|
AND IFNULL(iu.deleted, 0) = 0 |
|
|
|
|
|
WHERE il.id = NEW.inventoryLotId |
|
|
|
|
|
AND IFNULL(il.deleted, 0) = 0 |
|
|
|
|
|
LIMIT 1; |
|
|
|
|
|
|
|
|
|
|
|
IF v_itemId IS NULL OR v_stockUomId IS NULL THEN |
|
|
|
|
|
SIGNAL SQLSTATE '45000' |
|
|
|
|
|
SET MESSAGE_TEXT = '無法對應庫存桶,請檢查貨品單位與批次'; |
|
|
|
|
|
END IF; |
|
|
|
|
|
|
|
|
|
|
|
-- Step 3: If stock UOM or lot changed, recompute the OLD bucket so qty does not stick on the wrong row. |
|
|
|
|
|
-- After this UPDATE, the line already belongs to NEW; OLD-bucket SUM naturally excludes it. |
|
|
|
|
|
IF OLD.stockItemUomId IS NOT NULL |
|
|
|
|
|
AND (OLD.stockItemUomId <> NEW.stockItemUomId |
|
|
|
|
|
OR OLD.inventoryLotId <> NEW.inventoryLotId) THEN |
|
|
|
|
|
|
|
|
|
|
|
SELECT il.itemId, iu.uomId |
|
|
|
|
|
INTO v_oldItemId, v_oldStockUomId |
|
|
|
|
|
FROM `inventory_lot` il |
|
|
|
|
|
INNER JOIN `item_uom` iu |
|
|
|
|
|
ON iu.id = OLD.stockItemUomId |
|
|
|
|
|
AND iu.itemId = il.itemId |
|
|
|
|
|
AND IFNULL(iu.deleted, 0) = 0 |
|
|
|
|
|
WHERE il.id = OLD.inventoryLotId |
|
|
|
|
|
AND IFNULL(il.deleted, 0) = 0 |
|
|
|
|
|
LIMIT 1; |
|
|
|
|
|
|
|
|
|
|
|
IF v_oldItemId IS NOT NULL |
|
|
|
|
|
AND v_oldStockUomId IS NOT NULL |
|
|
|
|
|
AND (v_oldItemId <> v_itemId OR v_oldStockUomId <> v_stockUomId) THEN |
|
|
|
|
|
|
|
|
|
|
|
SELECT i.id |
|
|
|
|
|
INTO v_oldInventoryId |
|
|
|
|
|
FROM `inventory` i |
|
|
|
|
|
WHERE i.itemId = v_oldItemId |
|
|
|
|
|
AND i.stockUomId = v_oldStockUomId |
|
|
|
|
|
AND IFNULL(i.deleted, 0) = 0 |
|
|
|
|
|
LIMIT 1; |
|
|
|
|
|
|
|
|
|
|
|
IF v_oldInventoryId IS NOT NULL THEN |
|
|
|
|
|
-- Full SUM for OLD bucket (same formulas as NEW). |
|
|
|
|
|
SELECT COALESCE(SUM(ill.inQty - ill.outQty), 0), |
|
|
|
|
|
COALESCE(SUM(CASE |
|
|
|
|
|
WHEN LOWER(ill.status) = 'unavailable' |
|
|
|
|
|
THEN ill.inQty - ill.outQty |
|
|
|
|
|
ELSE 0 END), 0) |
|
|
|
|
|
INTO v_oldOnHand, v_oldUnavailable |
|
|
|
|
|
FROM `inventory_lot_line` ill |
|
|
|
|
|
INNER JOIN `inventory_lot` il |
|
|
|
|
|
ON il.id = ill.inventoryLotId AND IFNULL(il.deleted, 0) = 0 |
|
|
|
|
|
INNER JOIN `item_uom` iu |
|
|
|
|
|
ON iu.id = ill.stockItemUomId AND IFNULL(iu.deleted, 0) = 0 |
|
|
|
|
|
WHERE il.itemId = v_oldItemId |
|
|
|
|
|
AND iu.uomId = v_oldStockUomId |
|
|
|
|
|
AND IFNULL(ill.deleted, 0) = 0; |
|
|
|
|
|
|
|
|
|
|
|
UPDATE `inventory` |
|
|
|
|
|
SET `onHandQty` = v_oldOnHand, |
|
|
|
|
|
`unavailableQty` = v_oldUnavailable, |
|
|
|
|
|
`status` = IF(v_oldOnHand - v_oldUnavailable > 0, 'available', 'unavailable'), |
|
|
|
|
|
`modified` = CURRENT_TIMESTAMP |
|
|
|
|
|
WHERE `id` = v_oldInventoryId; |
|
|
|
|
|
END IF; |
|
|
|
|
|
END IF; |
|
|
|
|
|
END IF; |
|
|
|
|
|
|
|
|
|
|
|
-- Step 4: Resolve base UOM snapshot (only needed when creating a new inventory row). |
|
|
|
|
|
SELECT iu.uomId |
|
|
|
|
|
INTO v_baseUomId |
|
|
|
|
|
FROM `item_uom` iu |
|
|
|
|
|
WHERE iu.itemId = v_itemId |
|
|
|
|
|
AND iu.baseUnit = TRUE |
|
|
|
|
|
AND IFNULL(iu.deleted, 0) = 0 |
|
|
|
|
|
LIMIT 1; |
|
|
|
|
|
|
|
|
|
|
|
IF v_baseUomId IS NULL THEN |
|
|
|
|
|
SIGNAL SQLSTATE '45000' |
|
|
|
|
|
SET MESSAGE_TEXT = '此貨品未設定基本單位,無法建立庫存'; |
|
|
|
|
|
END IF; |
|
|
|
|
|
|
|
|
|
|
|
-- Step 5: Find or create inventory row for the NEW bucket. |
|
|
|
|
|
SELECT i.id |
|
|
|
|
|
INTO v_inventoryId |
|
|
|
|
|
FROM `inventory` i |
|
|
|
|
|
WHERE i.itemId = v_itemId |
|
|
|
|
|
AND i.stockUomId = v_stockUomId |
|
|
|
|
|
AND IFNULL(i.deleted, 0) = 0 |
|
|
|
|
|
LIMIT 1; |
|
|
|
|
|
|
|
|
|
|
|
IF v_inventoryId IS NULL THEN |
|
|
|
|
|
SELECT c.id, COALESCE(c.name, 'HKD'), COALESCE(pql.price, 0) |
|
|
|
|
|
INTO v_currencyId, v_currencyName, v_price |
|
|
|
|
|
FROM `inventory_lot` il |
|
|
|
|
|
LEFT JOIN `stock_in_line` sil ON sil.id = il.stockInLineId |
|
|
|
|
|
LEFT JOIN `purchase_order_line` pol ON pol.id = sil.purchaseOrderLineId |
|
|
|
|
|
LEFT JOIN `purchase_quotation_line` pql |
|
|
|
|
|
ON pql.itemId = il.itemId AND pql.uomId = pol.uomId |
|
|
|
|
|
LEFT JOIN `purchase_quotation` pq ON pq.id = pql.purchaseQuotationId |
|
|
|
|
|
LEFT JOIN `currency` c ON c.id = pq.currencyId |
|
|
|
|
|
WHERE il.id = NEW.inventoryLotId |
|
|
|
|
|
LIMIT 1; |
|
|
|
|
|
|
|
|
|
|
|
IF v_currencyId IS NULL THEN |
|
|
|
|
|
SELECT c.id, COALESCE(c.name, 'HKD') |
|
|
|
|
|
INTO v_currencyId, v_currencyName |
|
|
|
|
|
FROM `currency` c |
|
|
|
|
|
WHERE c.code = 'HKD' |
|
|
|
|
|
AND IFNULL(c.deleted, 0) = 0 |
|
|
|
|
|
LIMIT 1; |
|
|
|
|
|
END IF; |
|
|
|
|
|
|
|
|
|
|
|
IF v_currencyId IS NULL THEN |
|
|
|
|
|
SELECT c.id, COALESCE(c.name, 'HKD') |
|
|
|
|
|
INTO v_currencyId, v_currencyName |
|
|
|
|
|
FROM `currency` c |
|
|
|
|
|
WHERE IFNULL(c.deleted, 0) = 0 |
|
|
|
|
|
ORDER BY c.id |
|
|
|
|
|
LIMIT 1; |
|
|
|
|
|
END IF; |
|
|
|
|
|
|
|
|
|
|
|
IF v_currencyId IS NULL THEN |
|
|
|
|
|
SIGNAL SQLSTATE '45000' |
|
|
|
|
|
SET MESSAGE_TEXT = '無法取得幣別,無法建立庫存'; |
|
|
|
|
|
END IF; |
|
|
|
|
|
|
|
|
|
|
|
INSERT INTO `inventory` (`itemId`, |
|
|
|
|
|
`onHandQty`, |
|
|
|
|
|
`onHoldQty`, |
|
|
|
|
|
`unavailableQty`, |
|
|
|
|
|
`price`, |
|
|
|
|
|
`currencyId`, |
|
|
|
|
|
`cpu`, |
|
|
|
|
|
`cpuUnit`, |
|
|
|
|
|
`cpm`, |
|
|
|
|
|
`cpmUnit`, |
|
|
|
|
|
`uomId`, |
|
|
|
|
|
`stockUomId`, |
|
|
|
|
|
`status`) |
|
|
|
|
|
VALUES (v_itemId, |
|
|
|
|
|
0, |
|
|
|
|
|
0, |
|
|
|
|
|
0, |
|
|
|
|
|
COALESCE(v_price, 0), |
|
|
|
|
|
v_currencyId, |
|
|
|
|
|
0, |
|
|
|
|
|
COALESCE(v_currencyName, 'HKD'), |
|
|
|
|
|
0, |
|
|
|
|
|
COALESCE(v_currencyName, 'HKD'), |
|
|
|
|
|
v_baseUomId, |
|
|
|
|
|
v_stockUomId, |
|
|
|
|
|
'unavailable'); |
|
|
|
|
|
|
|
|
|
|
|
SET v_inventoryId = LAST_INSERT_ID(); |
|
|
|
|
|
END IF; |
|
|
|
|
|
|
|
|
|
|
|
-- Step 6: Full SUM for NEW bucket + overwrite. |
|
|
|
|
|
-- onHand = all statuses; unavailable = unavailable lines only; holdQty ignored. |
|
|
|
|
|
SELECT COALESCE(SUM(ill.inQty - ill.outQty), 0), |
|
|
|
|
|
COALESCE(SUM(CASE |
|
|
|
|
|
WHEN LOWER(ill.status) = 'unavailable' |
|
|
|
|
|
THEN ill.inQty - ill.outQty |
|
|
|
|
|
ELSE 0 END), 0) |
|
|
|
|
|
INTO v_onHand, v_unavailable |
|
|
|
|
|
FROM `inventory_lot_line` ill |
|
|
|
|
|
INNER JOIN `inventory_lot` il ON il.id = ill.inventoryLotId AND IFNULL(il.deleted, 0) = 0 |
|
|
|
|
|
INNER JOIN `item_uom` iu ON iu.id = ill.stockItemUomId AND IFNULL(iu.deleted, 0) = 0 |
|
|
|
|
|
WHERE il.itemId = v_itemId |
|
|
|
|
|
AND iu.uomId = v_stockUomId |
|
|
|
|
|
AND IFNULL(ill.deleted, 0) = 0; |
|
|
|
|
|
|
|
|
|
|
|
-- Do not touch onHoldQty, uomId, or stockUomId on an existing row. |
|
|
|
|
|
UPDATE `inventory` |
|
|
|
|
|
SET `onHandQty` = v_onHand, |
|
|
|
|
|
`unavailableQty` = v_unavailable, |
|
|
|
|
|
`status` = IF(v_onHand - v_unavailable > 0, 'available', 'unavailable'), |
|
|
|
|
|
`modified` = CURRENT_TIMESTAMP |
|
|
|
|
|
WHERE `id` = v_inventoryId; |
|
|
|
|
|
END; |