Przeglądaj źródła

2.7 fix be 2.7 a 2.7 b

fix負數倉
CANCERYS\kw093 3 tygodni temu
rodzic
commit
b9c6c4f27d
5 zmienionych plików z 173 dodań i 2 usunięć
  1. +3
    -0
      src/main/java/com/ffii/fpsms/modules/master/service/StockLedgerFixService.kt
  2. +129
    -1
      src/main/java/com/ffii/fpsms/modules/master/service/ledgerfix/StockLedgerFixAdjService.kt
  3. +35
    -0
      src/main/java/com/ffii/fpsms/modules/master/service/ledgerfix/StockLedgerFixExportService.kt
  4. +4
    -1
      src/main/java/com/ffii/fpsms/modules/master/web/StockLedgerFixController.kt
  5. +2
    -0
      src/main/java/com/ffii/fpsms/modules/master/web/models/StockLedgerFixModels.kt

+ 3
- 0
src/main/java/com/ffii/fpsms/modules/master/service/StockLedgerFixService.kt Wyświetl plik

@@ -61,6 +61,9 @@ open class StockLedgerFixService(
open fun applyAdjAlign(adjDateRaw: String? = null): StockLedgerFixAdjResponse =
adj.applyAdjAlign(adjDateRaw)

open fun applyAdjLotLineIn(adjDateRaw: String? = null): StockLedgerFixAdjResponse =
adj.applyAdjLotLineIn(adjDateRaw)

open fun fixDay(dateRaw: String, stepsRaw: List<String>? = null): StockLedgerFixRunResponse =
backfill.fixDay(dateRaw, stepsRaw)



+ 129
- 1
src/main/java/com/ffii/fpsms/modules/master/service/ledgerfix/StockLedgerFixAdjService.kt Wyświetl plik

@@ -20,7 +20,7 @@ open class StockLedgerFixAdjService(
private val log = LoggerFactory.getLogger(StockLedgerFixAdjService::class.java)

/**
* One ADJ per inventory bucket on [adjDate] (default yesterday; pass today on freeze-night dump).
* 2.7b. One ADJ per inventory bucket on [adjDate] (default yesterday; pass today on freeze-night dump).
* Quantity is onHandQty minus the bucket ledger net, including rows with no lot.
* The row is attached to the lot line whose own net is furthest from its ledger.
* Lot lines and inventory are not updated, so the lot-line trigger does not run.
@@ -150,6 +150,133 @@ open class StockLedgerFixAdjService(
}
}

/**
* 2.7a. Lot lines with outQty greater than inQty get inQty raised to outQty,
* and one inbound ADJ on that same lot for the gap. A second run finds no gap.
* The lot-line update fires the inventory trigger, so the ledger in must be the same qty.
*/
open fun applyAdjLotLineIn(adjDateRaw: String? = null): StockLedgerFixAdjResponse {
if (!support.tryLock(StockLedgerFixSupport.RUN_LOCK)) {
throw IllegalStateException("fix already running")
}
val (adjDate, asOfExclusive) = resolveAdjWindow(adjDateRaw)
val t0 = System.nanoTime()
try {
val gaps = loadLotLineInGaps()
var insertedIn = 0
val lotIds = linkedSetOf<Long>()
if (gaps.isNotEmpty()) {
val insTx = TransactionTemplate(support.transactionManager)
insTx.timeout = 300
insTx.execute {
var stockInId: Long? = null
fun inHeader(): Long =
stockInId ?: ensureAdjStockInHeader(adjDate).also { stockInId = it }
gaps.forEach { g ->
val raised = support.jdbcDao.executeUpdate(
"""
UPDATE inventory_lot_line
SET inQty = outQty,
modified = NOW(),
modifiedBy = 'stock-ledger-fix'
WHERE id = :id
AND IFNULL(deleted, 0) = 0
AND COALESCE(outQty, 0) > COALESCE(inQty, 0)
""".trimIndent(),
mapOf("id" to g.lotLineId),
)
if (raised == 0) return@forEach
insertAdjLedger(
g, adjDate, inQty = g.missIn, outQty = null,
remarks = ADJ_LOT_LINE_REMARKS, stockInId = inHeader(),
)
insertedIn++
lotIds.add(g.lotLineId)
}
}
}
val adjustmentRecords = TransactionTemplate(support.transactionManager).let { tx ->
tx.timeout = 300
tx.execute { insertMissingAdjustmentRecords() } ?: 0
}
val filledLotQty = support.timed("adj 2.7a 2.4") {
backfill.fillLotQtyForLotIds(lotIds.toList(), asOfExclusive)
}
val filledBalance = support.timed("adj 2.7a 2.5") {
backfill.fillBalanceOnNewAdjRows(adjDate, asOfExclusive)
}
val range = if (lotIds.isEmpty()) null else backfill.dateRangeForFilter(
"inventoryLotLineId IN (:lotIds)",
mapOf("today" to asOfExclusive, "lotIds" to lotIds.toList()),
)
val dayRows = if (range != null && lotIds.isNotEmpty()) {
support.timed("adj 2.7a 2.6") {
backfill.upsertStockLotDayRange(lotIds.toList(), range.first, range.second)
}
} else 0
log.info(
"stock-ledger-fix 2.7a {} lines={} adjRecord={} lotQty={} bal={} day={} total={}ms",
adjDate, insertedIn, adjustmentRecords, filledLotQty, filledBalance, dayRows,
(System.nanoTime() - t0) / 1_000_000,
)
return StockLedgerFixAdjResponse(
adjDate = adjDate.toString(),
insertedIn = insertedIn,
insertedOut = 0,
overIssuePatched = insertedIn,
filledLotQty = filledLotQty,
filledBalance = filledBalance,
dayRowsWritten = dayRows,
adjustmentRecords = adjustmentRecords,
)
} catch (e: Exception) {
log.warn("stock-ledger-fix 2.7a FAILED after {}ms: {}", (System.nanoTime() - t0) / 1_000_000, e.message)
throw e
} finally {
support.unlock(StockLedgerFixSupport.RUN_LOCK)
}
}

private fun loadLotLineInGaps(): List<AdjGap> {
return support.jdbcDao.queryForList(
"""
SELECT ill.id AS lotLineId,
il.itemId AS itemId,
it.code AS itemCode,
iu.uomId AS uomId,
i.id AS inventoryId,
CAST(COALESCE(ill.outQty, 0) - COALESCE(ill.inQty, 0) AS DECIMAL(14,2)) AS gap
FROM inventory_lot_line ill
INNER JOIN inventory_lot il
ON il.id = ill.inventoryLotId AND IFNULL(il.deleted, 0) = 0
INNER JOIN items it ON it.id = il.itemId
INNER JOIN item_uom iu ON iu.id = ill.stockItemUomId
LEFT JOIN inventory i
ON i.itemId = il.itemId
AND i.stockUomId = iu.uomId
AND IFNULL(i.deleted, 0) = 0
WHERE IFNULL(ill.deleted, 0) = 0
AND COALESCE(ill.outQty, 0) > COALESCE(ill.inQty, 0)
""".trimIndent(),
).mapNotNull { row ->
val gap = support.toDecimal(row["gap"])
if (gap.compareTo(ADJ_TOLERANCE) <= 0) return@mapNotNull null
AdjGap(
lotLineId = support.toLong(row["lotLineId"]),
inventoryId = support.toLongOrNull(row["inventoryId"]),
itemId = support.toLongOrNull(row["itemId"]),
itemCode = row["itemCode"]?.toString(),
uomId = support.toLongOrNull(row["uomId"]),
lineIn = BigDecimal.ZERO,
lineOut = BigDecimal.ZERO,
ledgerIn = BigDecimal.ZERO,
ledgerOut = BigDecimal.ZERO,
missIn = gap,
missOut = BigDecimal.ZERO,
)
}
}

/**
* ADJ window: ledger date = [adjDate], gap sums use `date < adjDate+1`.
* Default adjDate = yesterday. Pass today for freeze-night dump (e.g. 31/8).
@@ -680,6 +807,7 @@ open class StockLedgerFixAdjService(
companion object {
private val ADJ_TOLERANCE = BigDecimal("0.01")
private const val ADJ_DOC_REMARKS = "stock-ledger-fix bucket ADJ (lot line unchanged)"
private const val ADJ_LOT_LINE_REMARKS = "stock-ledger-fix 2.7a ADJ"
private const val ADJ_HEADER_REMARKS = "stock-ledger-fix 2.7 ADJ"
}
}

+ 35
- 0
src/main/java/com/ffii/fpsms/modules/master/service/ledgerfix/StockLedgerFixExportService.kt Wyświetl plik

@@ -436,6 +436,41 @@ open class StockLedgerFixExportService(
jdbc: NamedParameterJdbcTemplate,
args: Map<String, Any>,
) {
writeTempUpdate(
writer,
jdbc,
args,
title = "-- === 2.7a lot line inQty (out was greater; trigger refreshes onHand) ===\n",
selectSql = """
SELECT ill.id, ill.inQty, ill.modified, ill.modifiedBy
FROM inventory_lot_line ill
WHERE ill.modifiedBy = 'stock-ledger-fix'
AND IFNULL(ill.deleted, 0) = 0
AND EXISTS (
SELECT 1
FROM stock_ledger sl
INNER JOIN stock_in_line sil ON sil.id = sl.stockInLineId
WHERE sl.inventoryLotLineId = ill.id
AND sl.deleted = 0
AND sl.type = 'ADJ'
AND sl.createdBy = 'stock-ledger-fix'
AND sl.date >= :from AND sl.date < :toExclusive
AND sil.remarks = 'stock-ledger-fix 2.7a ADJ'
)
ORDER BY ill.id
""".trimIndent(),
tempName = "tmp_slf_ill_in",
columnDefs = "inQty DECIMAL(14,2) NULL, modified DATETIME NULL, modifiedBy VARCHAR(50) NULL",
columns = listOf("id", "inQty", "modified", "modifiedBy"),
updateSql = """
UPDATE inventory_lot_line ill
INNER JOIN tmp_slf_ill_in t ON t.id = ill.id
SET ill.inQty = t.inQty,
ill.modified = t.modified,
ill.modifiedBy = t.modifiedBy
""".trimIndent(),
emptyComment = "-- (no 2.7a lot-line inQty in range)",
)
writer.write("-- === 2.7 ADJ stock_in / stock_out (1 header + many lines; apply before ledger ADJ FKs) ===\n")
writeExportRows(
writer,


+ 4
- 1
src/main/java/com/ffii/fpsms/modules/master/web/StockLedgerFixController.kt Wyświetl plik

@@ -98,7 +98,10 @@ open class StockLedgerFixController(
@PreAuthorize("hasAnyAuthority('ADMIN','TESTING')")
@PostMapping("/adj")
open fun adjApply(@RequestBody(required = false) body: StockLedgerFixAdjRequest?) =
stockLedgerFixService.applyAdjAlign(body?.adjDate)
when (body?.step?.trim()?.lowercase()) {
"2.7a", "27a" -> stockLedgerFixService.applyAdjLotLineIn(body?.adjDate)
else -> stockLedgerFixService.applyAdjAlign(body?.adjDate)
}

@PreAuthorize("hasAnyAuthority('ADMIN','TESTING')")
@PostMapping("/run")


+ 2
- 0
src/main/java/com/ffii/fpsms/modules/master/web/models/StockLedgerFixModels.kt Wyświetl plik

@@ -101,6 +101,8 @@ data class StockLedgerFixSearchLotHit(
data class StockLedgerFixAdjRequest(
/** Optional ADJ ledger date (yyyy-MM-dd). Default = yesterday. Use today on freeze-night dump. */
val adjDate: String? = null,
/** `2.7a` raises lot-line inQty where outQty is greater. Empty = 2.7b bucket align. */
val step: String? = null,
)

data class StockLedgerFixAdjRow(


Ładowanie…
Anuluj
Zapisz