Procházet zdrojové kódy

1.0 fix

fix負數倉
CANCERYS\kw093 před 5 dny
rodič
revize
1122a860bd
2 změnil soubory, kde provedl 58 přidání a 5 odebrání
  1. +57
    -5
      src/main/java/com/ffii/fpsms/modules/master/service/StockLedgerFixService.kt
  2. +1
    -0
      src/main/java/com/ffii/fpsms/modules/master/web/models/StockLedgerFixModels.kt

+ 57
- 5
src/main/java/com/ffii/fpsms/modules/master/service/StockLedgerFixService.kt Zobrazit soubor

@@ -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 = """


+ 1
- 0
src/main/java/com/ffii/fpsms/modules/master/web/models/StockLedgerFixModels.kt Zobrazit soubor

@@ -69,6 +69,7 @@ data class StockLedgerFixInventoryResponse(
val missingUomPairsAfter: Int, val missingUomPairsAfter: Int,
val patchedStockUomId: Int, val patchedStockUomId: Int,
val nullStockUomIdAfter: Int, val nullStockUomIdAfter: Int,
val orphansDeleted: Int = 0,
) )


data class StockLedgerFixSearchInventoryHit( data class StockLedgerFixSearchInventoryHit(


Načítá se…
Zrušit
Uložit