|
|
@@ -118,8 +118,10 @@ open class StockLedgerFixService( |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* A: keep existing inventory ids; |
|
|
* A: keep existing inventory ids; |
|
|
* backfill stockUomId from lot stock UOM (and set uomId to base); |
|
|
|
|
|
|
|
|
* backfill stockUomId from lot stock UOM (and set uomId to base) — one row per |
|
|
|
|
|
* (itemId, stockUomId) so uk_inventory_item_stock_uom is not violated; |
|
|
* INSERT missing (itemId, stockUomId); |
|
|
* INSERT missing (itemId, stockUomId); |
|
|
|
|
|
* soft-delete leftover NULL stockUomId rows on items that already have a bucket; |
|
|
* recalc onHand/unavailable from Σ lot qty by item+stock UOM (0 if no lots). |
|
|
* recalc onHand/unavailable from Σ lot qty by item+stock UOM (0 if no lots). |
|
|
* Does not write inventory.onHoldQty (hold stays on lot line). Does not UPDATE inventory_lot_line. |
|
|
* Does not write inventory.onHoldQty (hold stays on lot line). Does not UPDATE inventory_lot_line. |
|
|
*/ |
|
|
*/ |
|
|
@@ -156,6 +158,7 @@ open class StockLedgerFixService( |
|
|
val patchedSingleLot = jdbcDao.executeUpdate(BACKFILL_STOCK_UOM_SINGLE_LOT_SQL) |
|
|
val patchedSingleLot = jdbcDao.executeUpdate(BACKFILL_STOCK_UOM_SINGLE_LOT_SQL) |
|
|
val patchedStockUomId = patchedFromUom + patchedSingleLot |
|
|
val patchedStockUomId = patchedFromUom + patchedSingleLot |
|
|
val inserted = jdbcDao.executeUpdate(INSERT_MISSING_INVENTORY_SQL) |
|
|
val inserted = jdbcDao.executeUpdate(INSERT_MISSING_INVENTORY_SQL) |
|
|
|
|
|
val orphansDeleted = jdbcDao.executeUpdate(SOFT_DELETE_ORPHAN_NULL_STOCK_UOM_SQL) |
|
|
val updated = jdbcDao.executeUpdate(UPDATE_INVENTORY_QTY_SQL) |
|
|
val updated = jdbcDao.executeUpdate(UPDATE_INVENTORY_QTY_SQL) |
|
|
val missingAfter = toInt( |
|
|
val missingAfter = toInt( |
|
|
jdbcDao.queryForList(MISSING_UOM_PAIR_COUNT_SQL).firstOrNull()?.get("c"), |
|
|
jdbcDao.queryForList(MISSING_UOM_PAIR_COUNT_SQL).firstOrNull()?.get("c"), |
|
|
@@ -164,9 +167,10 @@ open class StockLedgerFixService( |
|
|
jdbcDao.queryForList(NULL_STOCK_UOM_COUNT_SQL).firstOrNull()?.get("c"), |
|
|
jdbcDao.queryForList(NULL_STOCK_UOM_COUNT_SQL).firstOrNull()?.get("c"), |
|
|
) |
|
|
) |
|
|
log.info( |
|
|
log.info( |
|
|
"stock-ledger-fix inventory-1.0 patchedStockUomId={} inserted={} updated={} missingAfter={} nullStockUomIdAfter={}", |
|
|
|
|
|
|
|
|
"stock-ledger-fix inventory-1.0 patchedStockUomId={} inserted={} orphansDeleted={} updated={} missingAfter={} nullStockUomIdAfter={}", |
|
|
patchedStockUomId, |
|
|
patchedStockUomId, |
|
|
inserted, |
|
|
inserted, |
|
|
|
|
|
orphansDeleted, |
|
|
updated, |
|
|
updated, |
|
|
missingAfter, |
|
|
missingAfter, |
|
|
nullStockUomIdAfter, |
|
|
nullStockUomIdAfter, |
|
|
@@ -177,6 +181,7 @@ open class StockLedgerFixService( |
|
|
missingUomPairsAfter = missingAfter, |
|
|
missingUomPairsAfter = missingAfter, |
|
|
patchedStockUomId = patchedStockUomId, |
|
|
patchedStockUomId = patchedStockUomId, |
|
|
nullStockUomIdAfter = nullStockUomIdAfter, |
|
|
nullStockUomIdAfter = nullStockUomIdAfter, |
|
|
|
|
|
orphansDeleted = orphansDeleted, |
|
|
) |
|
|
) |
|
|
} finally { |
|
|
} finally { |
|
|
inFlight.remove(inventoryLock) |
|
|
inFlight.remove(inventoryLock) |
|
|
@@ -3463,6 +3468,8 @@ open class StockLedgerFixService( |
|
|
/** |
|
|
/** |
|
|
* Old row: uomId already equals a lot stock UOM (stock, or base when base=stock). |
|
|
* Old row: uomId already equals a lot stock UOM (stock, or base when base=stock). |
|
|
* Fill stockUomId from that lot stock; move uomId to item base. |
|
|
* Fill stockUomId from that lot stock; move uomId to item base. |
|
|
|
|
|
* One keeper per (itemId, uomId); skip if that stockUomId is already taken |
|
|
|
|
|
* (including soft-deleted rows that still occupy the unique key). |
|
|
*/ |
|
|
*/ |
|
|
private const val BACKFILL_STOCK_UOM_WHEN_UOM_MATCHES_LOT_SQL = """ |
|
|
private const val BACKFILL_STOCK_UOM_WHEN_UOM_MATCHES_LOT_SQL = """ |
|
|
UPDATE inventory i |
|
|
UPDATE inventory i |
|
|
@@ -3477,10 +3484,21 @@ open class StockLedgerFixService( |
|
|
AND il.itemId IS NOT NULL |
|
|
AND il.itemId IS NOT NULL |
|
|
AND iu.uomId IS NOT NULL |
|
|
AND iu.uomId IS NOT NULL |
|
|
) b ON b.itemId = i.itemId AND b.stockUomId = i.uomId |
|
|
) b ON b.itemId = i.itemId AND b.stockUomId = i.uomId |
|
|
|
|
|
INNER JOIN ( |
|
|
|
|
|
SELECT itemId, uomId, MIN(id) AS keepId |
|
|
|
|
|
FROM inventory |
|
|
|
|
|
WHERE IFNULL(deleted, 0) = 0 |
|
|
|
|
|
AND stockUomId IS NULL |
|
|
|
|
|
GROUP BY itemId, uomId |
|
|
|
|
|
) keep ON keep.keepId = i.id |
|
|
LEFT JOIN item_uom baseIu |
|
|
LEFT JOIN item_uom baseIu |
|
|
ON baseIu.itemId = i.itemId |
|
|
ON baseIu.itemId = i.itemId |
|
|
AND baseIu.baseUnit = 1 |
|
|
AND baseIu.baseUnit = 1 |
|
|
AND IFNULL(baseIu.deleted, 0) = 0 |
|
|
AND IFNULL(baseIu.deleted, 0) = 0 |
|
|
|
|
|
LEFT JOIN inventory taken |
|
|
|
|
|
ON taken.itemId = i.itemId |
|
|
|
|
|
AND taken.stockUomId = b.stockUomId |
|
|
|
|
|
AND taken.id <> i.id |
|
|
SET |
|
|
SET |
|
|
i.stockUomId = b.stockUomId, |
|
|
i.stockUomId = b.stockUomId, |
|
|
i.uomId = COALESCE(baseIu.uomId, i.uomId), |
|
|
i.uomId = COALESCE(baseIu.uomId, i.uomId), |
|
|
@@ -3488,11 +3506,12 @@ open class StockLedgerFixService( |
|
|
i.modifiedBy = 'stock-ledger-fix' |
|
|
i.modifiedBy = 'stock-ledger-fix' |
|
|
WHERE IFNULL(i.deleted, 0) = 0 |
|
|
WHERE IFNULL(i.deleted, 0) = 0 |
|
|
AND i.stockUomId IS NULL |
|
|
AND i.stockUomId IS NULL |
|
|
|
|
|
AND taken.id IS NULL |
|
|
""" |
|
|
""" |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* Remaining NULL stockUomId: item has exactly one lot stock UOM |
|
|
* Remaining NULL stockUomId: item has exactly one lot stock UOM |
|
|
* (uomId already base, stock may differ). Skip if that bucket row already exists. |
|
|
|
|
|
|
|
|
* (uomId already base, stock may differ). Keep MIN(id) only. |
|
|
*/ |
|
|
*/ |
|
|
private const val BACKFILL_STOCK_UOM_SINGLE_LOT_SQL = """ |
|
|
private const val BACKFILL_STOCK_UOM_SINGLE_LOT_SQL = """ |
|
|
UPDATE inventory i |
|
|
UPDATE inventory i |
|
|
@@ -3509,6 +3528,13 @@ open class StockLedgerFixService( |
|
|
GROUP BY il.itemId |
|
|
GROUP BY il.itemId |
|
|
HAVING COUNT(DISTINCT iu.uomId) = 1 |
|
|
HAVING COUNT(DISTINCT iu.uomId) = 1 |
|
|
) b ON b.itemId = i.itemId |
|
|
) b ON b.itemId = i.itemId |
|
|
|
|
|
INNER JOIN ( |
|
|
|
|
|
SELECT itemId, MIN(id) AS keepId |
|
|
|
|
|
FROM inventory |
|
|
|
|
|
WHERE IFNULL(deleted, 0) = 0 |
|
|
|
|
|
AND stockUomId IS NULL |
|
|
|
|
|
GROUP BY itemId |
|
|
|
|
|
) keep ON keep.keepId = i.id |
|
|
LEFT JOIN item_uom baseIu |
|
|
LEFT JOIN item_uom baseIu |
|
|
ON baseIu.itemId = i.itemId |
|
|
ON baseIu.itemId = i.itemId |
|
|
AND baseIu.baseUnit = 1 |
|
|
AND baseIu.baseUnit = 1 |
|
|
@@ -3516,7 +3542,6 @@ open class StockLedgerFixService( |
|
|
LEFT JOIN inventory taken |
|
|
LEFT JOIN inventory taken |
|
|
ON taken.itemId = i.itemId |
|
|
ON taken.itemId = i.itemId |
|
|
AND taken.stockUomId = b.stockUomId |
|
|
AND taken.stockUomId = b.stockUomId |
|
|
AND IFNULL(taken.deleted, 0) = 0 |
|
|
|
|
|
AND taken.id <> i.id |
|
|
AND taken.id <> i.id |
|
|
SET |
|
|
SET |
|
|
i.stockUomId = b.stockUomId, |
|
|
i.stockUomId = b.stockUomId, |
|
|
@@ -3565,8 +3590,14 @@ open class StockLedgerFixService( |
|
|
AND IFNULL(baseIu.deleted, 0) = 0 |
|
|
AND IFNULL(baseIu.deleted, 0) = 0 |
|
|
LEFT JOIN inventory existing |
|
|
LEFT JOIN inventory existing |
|
|
ON existing.itemId = src.itemId |
|
|
ON existing.itemId = src.itemId |
|
|
AND COALESCE(existing.stockUomId, existing.uomId) = src.uomId |
|
|
|
|
|
AND IFNULL(existing.deleted, 0) = 0 |
|
|
AND IFNULL(existing.deleted, 0) = 0 |
|
|
|
|
|
AND ( |
|
|
|
|
|
existing.stockUomId = src.uomId |
|
|
|
|
|
OR (existing.stockUomId IS NULL AND existing.uomId = src.uomId) |
|
|
|
|
|
) |
|
|
|
|
|
LEFT JOIN inventory occupied |
|
|
|
|
|
ON occupied.itemId = src.itemId |
|
|
|
|
|
AND occupied.stockUomId = src.uomId |
|
|
LEFT JOIN inventory tpl |
|
|
LEFT JOIN inventory tpl |
|
|
ON tpl.id = ( |
|
|
ON tpl.id = ( |
|
|
SELECT MIN(i.id) |
|
|
SELECT MIN(i.id) |
|
|
@@ -3575,6 +3606,27 @@ open class StockLedgerFixService( |
|
|
AND IFNULL(i.deleted, 0) = 0 |
|
|
AND IFNULL(i.deleted, 0) = 0 |
|
|
) |
|
|
) |
|
|
WHERE existing.id IS NULL |
|
|
WHERE existing.id IS NULL |
|
|
|
|
|
AND occupied.id IS NULL |
|
|
|
|
|
""" |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* Extra old UOM rows left NULL after a keeper bucket exists for the item |
|
|
|
|
|
* (e.g. 18918 id 5261). Soft-delete so search / COALESCE fallbacks ignore them. |
|
|
|
|
|
*/ |
|
|
|
|
|
private const val SOFT_DELETE_ORPHAN_NULL_STOCK_UOM_SQL = """ |
|
|
|
|
|
UPDATE inventory i |
|
|
|
|
|
INNER JOIN ( |
|
|
|
|
|
SELECT DISTINCT itemId |
|
|
|
|
|
FROM inventory |
|
|
|
|
|
WHERE IFNULL(deleted, 0) = 0 |
|
|
|
|
|
AND stockUomId IS NOT NULL |
|
|
|
|
|
) keeper ON keeper.itemId = i.itemId |
|
|
|
|
|
SET |
|
|
|
|
|
i.deleted = 1, |
|
|
|
|
|
i.modified = NOW(), |
|
|
|
|
|
i.modifiedBy = 'stock-ledger-fix' |
|
|
|
|
|
WHERE IFNULL(i.deleted, 0) = 0 |
|
|
|
|
|
AND i.stockUomId IS NULL |
|
|
""" |
|
|
""" |
|
|
|
|
|
|
|
|
private const val UPDATE_INVENTORY_QTY_SQL = """ |
|
|
private const val UPDATE_INVENTORY_QTY_SQL = """ |
|
|
|