diff --git a/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickExecutionIssueService.kt b/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickExecutionIssueService.kt index e9151a4..f165f96 100644 --- a/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickExecutionIssueService.kt +++ b/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickExecutionIssueService.kt @@ -2370,7 +2370,7 @@ private fun updateInventoryAfterLotLineChange(lotLine: InventoryLotLine) { e.printStackTrace() } } -/** FP-MTMS Version Checklist | Functions Ref. No. 46 | v1.0.0 | 2026-08-03 */ +/** FP-MTMS Version Checklist | Functions Ref. No. 46 | v1.0.1 | 2026-08-05 */ private fun createStockLedgerForStockOut( stockOutLine: StockOutLine, ledgerType: String? = null, @@ -2875,7 +2875,7 @@ open fun submitIssueWithQty(request: SubmitIssueWithQtyRequest): MessageResponse } // New: Create stock ledger with explicit balance (to avoid double subtraction) -/** FP-MTMS Version Checklist | Functions Ref. No. 46 | v1.0.0 | 2026-08-03 */ +/** FP-MTMS Version Checklist | Functions Ref. No. 46 | v1.0.1 | 2026-08-05 */ private fun createStockLedgerForStockOutWithBalance( stockOutLine: StockOutLine, balance: Double, diff --git a/src/main/java/com/ffii/fpsms/modules/report/service/DoUserPickAuditReportService.kt b/src/main/java/com/ffii/fpsms/modules/report/service/DoUserPickAuditReportService.kt index 0d57eae..91516f9 100644 --- a/src/main/java/com/ffii/fpsms/modules/report/service/DoUserPickAuditReportService.kt +++ b/src/main/java/com/ffii/fpsms/modules/report/service/DoUserPickAuditReportService.kt @@ -8,10 +8,10 @@ class DoUserPickAuditReportService( private val jdbcDao: JdbcDao, ) { /** - * FP-MTMS Version Checklist | Functions Ref. No. 39 | v1.0.0 | 2026-08-03 + * FP-MTMS Version Checklist | Functions Ref. No. 39 | v1.0.1 | 2026-08-05 * DO workbench user-audit rows (Just issue only). - * issueTypes may combine: 不正常已完成+超出提料+未完全提料+不正常換批. - * 未完全提料/超出提料 use POL-level SUM(stock_out_line.qty) vs pol.qty (multi-lot split OK if total matches). + * issueTypes may combine: 跳過提料(使用「已完成」)+多提+少提+擅自換批/揀錯批. + * 少提/多提 use POL-level SUM(stock_out_line.qty) vs pol.qty (multi-lot split OK if total matches). * Only completed tickets (`dop.ticketStatus = completed`) are included. * * Perf: filter day/completed SOL first (`day_sol`) by pickTime only (idx_sol_pickTime_deleted), @@ -120,14 +120,14 @@ class DoUserPickAuditReportService( IFNULL(d.isIssueJustComplete, 0) AS issueJustComplete, COALESCE(u.name, d.handlerName, '') AS user, TRIM(BOTH '+' FROM CONCAT_WS('+', - CASE WHEN IFNULL(d.isIssueJustComplete, 0) = 1 THEN '不正常已完成' ELSE NULL END, + CASE WHEN IFNULL(d.isIssueJustComplete, 0) = 1 THEN '跳過提料(使用「已完成」)' ELSE NULL END, CASE WHEN d.polQty IS NOT NULL - AND COALESCE(pp.pickedTotal, 0) > d.polQty THEN '超出提料' ELSE NULL END, + AND COALESCE(pp.pickedTotal, 0) > d.polQty THEN '多提' ELSE NULL END, CASE WHEN d.polQty IS NOT NULL AND COALESCE(pp.pickedTotal, 0) < d.polQty - AND d.inventoryLotLineId IS NOT NULL THEN '未完全提料' ELSE NULL END, + AND d.inventoryLotLineId IS NOT NULL THEN '少提' ELSE NULL END, CASE WHEN sug_lot.lotNo IS NOT NULL AND act_lot.lotNo IS NOT NULL - AND sug_lot.lotNo <> act_lot.lotNo THEN '不正常換批' ELSE NULL END + AND sug_lot.lotNo <> act_lot.lotNo THEN '擅自換批/揀錯批' ELSE NULL END )) AS issueTypes, d.solId AS stockOutLineId FROM day_sol d @@ -183,7 +183,7 @@ class DoUserPickAuditReportService( return jdbcDao.queryForList(sql, args) as List> } - /** FP-MTMS Version Checklist | Functions Ref. No. 39 | v1.0.0 | 2026-08-03 */ + /** FP-MTMS Version Checklist | Functions Ref. No. 39 | v1.0.1 | 2026-08-05 */ fun getDistinctHandlers(): List { val sql = """ SELECT DISTINCT TRIM(COALESCE(u.name, dop.handlerName, '')) AS handler diff --git a/src/main/java/com/ffii/fpsms/modules/report/web/DoUserPickAuditReportController.kt b/src/main/java/com/ffii/fpsms/modules/report/web/DoUserPickAuditReportController.kt index df21292..5fa8ecb 100644 --- a/src/main/java/com/ffii/fpsms/modules/report/web/DoUserPickAuditReportController.kt +++ b/src/main/java/com/ffii/fpsms/modules/report/web/DoUserPickAuditReportController.kt @@ -23,11 +23,11 @@ import java.io.ByteArrayOutputStream class DoUserPickAuditReportController( private val doUserPickAuditReportService: DoUserPickAuditReportService, ) { - /** FP-MTMS Version Checklist | Functions Ref. No. 39 | v1.0.0 | 2026-08-03 */ + /** FP-MTMS Version Checklist | Functions Ref. No. 39 | v1.0.1 | 2026-08-05 */ @GetMapping("/do-user-pick-audit-handlers") fun handlers(): List = doUserPickAuditReportService.getDistinctHandlers() - /** FP-MTMS Version Checklist | Functions Ref. No. 39 | v1.0.0 | 2026-08-03 */ + /** FP-MTMS Version Checklist | Functions Ref. No. 39 | v1.0.1 | 2026-08-05 */ @GetMapping("/print-do-user-pick-audit-excel") fun exportExcel( @RequestParam(required = false) dateStart: String?, @@ -93,9 +93,9 @@ class DoUserPickAuditReportController( "actualQty" to "實際提料數量", "lotBeforeQty" to "提料前庫存", "lotAfterQty" to "提料後庫存", - "issueJustComplete" to "不正常已完成", + "issueJustComplete" to "跳過提料(使用「已完成」)", "user" to "提料人", - "issueTypes" to "問題類型", + "issueTypes" to "偏離類型", ) var r = 0 diff --git a/src/main/java/com/ffii/fpsms/modules/stock/entity/StockLedger.kt b/src/main/java/com/ffii/fpsms/modules/stock/entity/StockLedger.kt index 16995c0..16099af 100644 --- a/src/main/java/com/ffii/fpsms/modules/stock/entity/StockLedger.kt +++ b/src/main/java/com/ffii/fpsms/modules/stock/entity/StockLedger.kt @@ -21,7 +21,20 @@ open class StockLedger: BaseEntity() { @JoinColumn(name = "stockOutLineId") open var stockOutLine: StockOutLine? = null - /** Lot line for this movement; prefer this over resolving via stock in/out line. */ + /** + * FP-MTMS Version Checklist | Functions Ref. No. 46 | v1.0.1 | 2026-08-05 + * + * stock_ledger.inventoryLotLineId = the **actual** inventory_lot_line.id this + * in/out movement posted against (the lot whose qty changed). + * + * Not a suggested lot. For pick-order flows (FG / JO / PO), this must align with + * suggested_pick_lot.actualPickLotLineId (and stock_out_line.inventoryLotLineId), + * NOT suggested_pick_lot.suggestedLotLineId. + * If the picker switches lot (suggested A, scan B), ledger points to B. + * + * Prefer reading this column directly; do not infer lot only via stockInLine / + * stockOutLine when this is populated. + */ @ManyToOne @JoinColumn(name = "inventoryLotLineId") open var inventoryLotLine: InventoryLotLine? = null @@ -40,11 +53,17 @@ open class StockLedger: BaseEntity() { @Column(name = "balance") open var balance: Double? = null - /** Lot available qty (in−out) before this movement; null for pre-V2 rows. */ + /** + * FP-MTMS Version Checklist | Functions Ref. No. 46 | v1.0.1 | 2026-08-05 + * Available qty of that same actual lot (in−out) **before** this movement; null for pre-V2 rows. + */ @Column(name = "lotQtyBefore", precision = 14, scale = 2) open var lotQtyBefore: BigDecimal? = null - /** Lot available qty (in−out) after this movement; null for pre-V2 rows. */ + /** + * FP-MTMS Version Checklist | Functions Ref. No. 46 | v1.0.1 | 2026-08-05 + * Available qty of that same actual lot (in−out) **after** this movement; null for pre-V2 rows. + */ @Column(name = "lotQtyAfter", precision = 14, scale = 2) open var lotQtyAfter: BigDecimal? = null diff --git a/src/main/java/com/ffii/fpsms/modules/stock/entity/SuggestedPickLot.kt b/src/main/java/com/ffii/fpsms/modules/stock/entity/SuggestedPickLot.kt index 7cb48d8..989d58a 100644 --- a/src/main/java/com/ffii/fpsms/modules/stock/entity/SuggestedPickLot.kt +++ b/src/main/java/com/ffii/fpsms/modules/stock/entity/SuggestedPickLot.kt @@ -29,7 +29,14 @@ open class SuggestedPickLot: BaseEntity() { @JoinColumn(name = "suggestedLotLineId") open var suggestedLotLine: InventoryLotLine? = null - /** Actual picked lot line; switch/scan updates this without changing [suggestedLotLine]. */ + /** + * FP-MTMS Version Checklist | Functions Ref. No. 33 | v1.0.2 | 2026-08-03 + * + * Actual picked inventory_lot_line.id. + * On create: init = suggestedLotLineId; lot switch/scan updates this only (suggested stays). + * Downstream (display, COALESCE reads, stock_ledger.inventoryLotLineId / SOL.inventoryLotLineId) + * must use this, not [suggestedLotLine]. + */ @ManyToOne @JoinColumn(name = "actualPickLotLineId") open var actualPickLotLine: InventoryLotLine? = null diff --git a/src/main/java/com/ffii/fpsms/modules/stock/service/StockInLineService.kt b/src/main/java/com/ffii/fpsms/modules/stock/service/StockInLineService.kt index fa4c1ab..a016e83 100644 --- a/src/main/java/com/ffii/fpsms/modules/stock/service/StockInLineService.kt +++ b/src/main/java/com/ffii/fpsms/modules/stock/service/StockInLineService.kt @@ -1378,7 +1378,7 @@ open class StockInLineService( } @Transactional - /** FP-MTMS Version Checklist | Functions Ref. No. 46 | v1.0.0 | 2026-08-03 */ + /** FP-MTMS Version Checklist | Functions Ref. No. 46 | v1.0.1 | 2026-08-05 */ private fun createStockLedgerForStockIn(stockInLine: StockInLine, inQty: Double) { val _t0 = System.nanoTime() fun _msSince(t: Long): Double = (System.nanoTime() - t) / 1_000_000.0 diff --git a/src/main/java/com/ffii/fpsms/modules/stock/service/StockLedgerLotSnapshot.kt b/src/main/java/com/ffii/fpsms/modules/stock/service/StockLedgerLotSnapshot.kt index 88768a6..54820c8 100644 --- a/src/main/java/com/ffii/fpsms/modules/stock/service/StockLedgerLotSnapshot.kt +++ b/src/main/java/com/ffii/fpsms/modules/stock/service/StockLedgerLotSnapshot.kt @@ -5,15 +5,28 @@ import com.ffii.fpsms.modules.stock.entity.StockLedger import java.math.BigDecimal /** - * FP-MTMS Version Checklist | Functions Ref. No. 46 | v1.0.0 | 2026-08-03 - * Fills [StockLedger.inventoryLotLine], [lotQtyBefore], [lotQtyAfter]. - * Prefer explicit [inventoryLotLine]; else fall back to stockOutLine / stockInLine related lot. + * FP-MTMS Version Checklist | Functions Ref. No. 46 | v1.0.1 | 2026-08-05 * - * [lotAvailableAfterMove] = lot (in−out) **after** this movement has already been applied on the lot line. - * [signedDelta] = +inQty or −outQty for this ledger row (stock-in positive, stock-out negative of posted qty). + * Fills [StockLedger.inventoryLotLine], [lotQtyBefore], [lotQtyAfter] for each movement. + * + * [StockLedger.inventoryLotLine] / inventoryLotLineId = **actual** moved lot line id + * (the lot whose qty changed). Prefer explicit [inventoryLotLine]; else fall back to + * stockOutLine / stockInLine related lot. + * + * On pick/suggestion flows: pass/resolve the lot that was actually picked/posted + * (= suggested_pick_lot.actualPickLotLineId / stock_out_line.inventoryLotLineId), + * never suggested_pick_lot.suggestedLotLineId alone. Lot switch (suggested A, scan B) + * → ledger must point to B. + * + * [lotQtyBefore]/[lotQtyAfter] are snapshots of that same actual lot's available qty. + * [lotAvailableAfterMove] = lot (in−out) **after** this movement has already been applied. + * [signedDelta] = +inQty or −outQty for this ledger row (stock-in positive, stock-out negative). */ object StockLedgerLotSnapshot { - /** FP-MTMS Version Checklist | Functions Ref. No. 46 | v1.0.0 | 2026-08-03 */ + /** + * FP-MTMS Version Checklist | Functions Ref. No. 46 | v1.0.1 | 2026-08-05 + * Sets ledger.inventoryLotLine to the actual lot, then lotQtyBefore/After from that lot. + */ fun apply( ledger: StockLedger, inventoryLotLine: InventoryLotLine? = null, @@ -34,12 +47,12 @@ object StockLedgerLotSnapshot { ledger.lotQtyBefore = lotAvailableAfterMove.subtract(signedDelta) } - /** FP-MTMS Version Checklist | Functions Ref. No. 46 | v1.0.0 | 2026-08-03 */ + /** FP-MTMS Version Checklist | Functions Ref. No. 46 | v1.0.1 | 2026-08-05 */ fun availableQty(ill: InventoryLotLine): BigDecimal = (ill.inQty ?: BigDecimal.ZERO).subtract(ill.outQty ?: BigDecimal.ZERO) /** - * FP-MTMS Version Checklist | Functions Ref. No. 46 | v1.0.0 | 2026-08-03 + * FP-MTMS Version Checklist | Functions Ref. No. 46 | v1.0.1 | 2026-08-05 * Ledger UOM must follow the lot line's stock ItemUom → uom.id * (same item may have lots with different UOMs; item stockUnit flag can change later). */ diff --git a/src/main/java/com/ffii/fpsms/modules/stock/service/StockOutLineService.kt b/src/main/java/com/ffii/fpsms/modules/stock/service/StockOutLineService.kt index eea245b..e32492d 100644 --- a/src/main/java/com/ffii/fpsms/modules/stock/service/StockOutLineService.kt +++ b/src/main/java/com/ffii/fpsms/modules/stock/service/StockOutLineService.kt @@ -1509,7 +1509,7 @@ open fun newBatchSubmit(request: QrPickBatchSubmitRequest): MessageResponse { } } @Transactional - /** FP-MTMS Version Checklist | Functions Ref. No. 46 | v1.0.0 | 2026-08-03 */ + /** FP-MTMS Version Checklist | Functions Ref. No. 46 | v1.0.1 | 2026-08-05 */ private fun createStockLedgerForStockOut(stockOutLine: StockOutLine) { val item = stockOutLine.item ?: return val inventory = itemUomService.findInventoryForItemBaseUom(item.id!!) ?: return @@ -1757,7 +1757,7 @@ open fun newBatchSubmit(request: QrPickBatchSubmitRequest): MessageResponse { } - /** FP-MTMS Version Checklist | Functions Ref. No. 46 | v1.0.0 | 2026-08-03 */ + /** FP-MTMS Version Checklist | Functions Ref. No. 46 | v1.0.1 | 2026-08-05 */ private fun createStockLedgerForPickDelta( stockOutLine: StockOutLine, deltaQty: BigDecimal, diff --git a/src/main/java/com/ffii/fpsms/modules/stock/service/StockTakeRecordService.kt b/src/main/java/com/ffii/fpsms/modules/stock/service/StockTakeRecordService.kt index c8b4f7f..4597177 100644 --- a/src/main/java/com/ffii/fpsms/modules/stock/service/StockTakeRecordService.kt +++ b/src/main/java/com/ffii/fpsms/modules/stock/service/StockTakeRecordService.kt @@ -2488,7 +2488,7 @@ private fun applyVarianceAdjustment( } val newBalance = previousBalance - qtyToRemove.toDouble() - // FP-MTMS Version Checklist | Functions Ref. No. 46 | v1.0.0 | 2026-08-03 + // FP-MTMS Version Checklist | Functions Ref. No. 46 | v1.0.1 | 2026-08-05 // Snapshot from live lot line (in−out) at approve time — not stock_take_record.bookQty. val lotAfterAvail = StockLedgerLotSnapshot.availableQty(latestLine).subtract(qtyToRemove)