From 41d5df10a5dba895389409998a22850b5c637fd2 Mon Sep 17 00:00:00 2001 From: Fai Luk Date: Fri, 2 Oct 2026 00:41:04 +0800 Subject: [PATCH] =?UTF-8?q?make=20the=20stock=20take=20qty=20can=20be=20ed?= =?UTF-8?q?it=20before=20=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modules/stock/entity/StockTakeRecord.kt | 4 ++ .../stock/service/StockTakeRecordService.kt | 52 ++++++++++++++++++- .../stock/web/model/StockTakeRecordReponse.kt | 6 ++- .../01_add_picker_revise_count.sql | 5 ++ 4 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 src/main/resources/db/changelog/changes/20261001_picker_revise_count/01_add_picker_revise_count.sql diff --git a/src/main/java/com/ffii/fpsms/modules/stock/entity/StockTakeRecord.kt b/src/main/java/com/ffii/fpsms/modules/stock/entity/StockTakeRecord.kt index 72a03b0b..4e4bc56f 100644 --- a/src/main/java/com/ffii/fpsms/modules/stock/entity/StockTakeRecord.kt +++ b/src/main/java/com/ffii/fpsms/modules/stock/entity/StockTakeRecord.kt @@ -81,6 +81,10 @@ open class StockTakeRecord : BaseEntity() { @Column(name = "lastSelect") open var lastSelect: Int? = null + /** How many times the picker has changed an already saved first count. Max 2. */ + @Column(name = "pickerReviseCount", nullable = false) + open var pickerReviseCount: Int? = 0 + @Column(name = "approverTime") open var approverTime: LocalDateTime? = null @Column(name = "date", nullable = false) 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 2fdbbb0c..d4d3c308 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 @@ -1200,6 +1200,7 @@ open class StockTakeRecordService( stockTakerName = rec.stockTakerName, stockTakeEndTime = rec.stockTakeEndTime, approverTime = rec.approverTime, + pickerReviseCount = rec.pickerReviseCount ?: 0, ) } @@ -1296,6 +1297,7 @@ open class StockTakeRecordService( stockTakerName = stockTakeRecord?.stockTakerName, stockTakeEndTime = stockTakeRecord?.stockTakeEndTime, approverTime = stockTakeRecord?.approverTime, + pickerReviseCount = stockTakeRecord?.pickerReviseCount ?: 0, ) } @@ -1342,12 +1344,59 @@ open class StockTakeRecordService( .subtract(inventoryLotLine.outQty ?: BigDecimal.ZERO) //.subtract(inventoryLotLine.holdQty ?: BigDecimal.ZERO) + if (request.reviseFirstQty && request.stockTakeRecordId == null) { + throw IllegalArgumentException("Stock take record ID is required") + } + // 3. 新建、更新預建記錄之第一次盤點、或第二次盤點 val stockTakeRecord: StockTakeRecord = if (request.stockTakeRecordId != null) { val existingRecord = stockTakeRecordRepository.findByIdAndDeletedIsFalse(request.stockTakeRecordId) ?: throw IllegalArgumentException("Stock take record not found: ${request.stockTakeRecordId}") + val headerStatus = stockTake.status + val headerStillOpen = headerStatus == StockTakeStatus.PENDING || + headerStatus == StockTakeStatus.STOCKTAKING || + headerStatus == StockTakeStatus.APPROVING + val revisingOpenPass = existingRecord.pickerFirstStockTakeQty != null && + existingRecord.pickerSecondStockTakeQty == null && + existingRecord.approverStockTakeQty == null && + existingRecord.status.equals("pass", ignoreCase = true) && + headerStillOpen when { + // 已盤點的列在區域「已完成」前可改第一次數量。列狀態已完成、或區域已完成,不能改。 + request.reviseFirstQty || revisingOpenPass -> { + if (!headerStillOpen) { + throw IllegalArgumentException("Cannot change counted qty after the section is completed") + } + if (!existingRecord.status.equals("pass", ignoreCase = true)) { + throw IllegalArgumentException("Only counted records can be changed") + } + if (existingRecord.pickerFirstStockTakeQty == null) { + throw IllegalArgumentException("No first count to change") + } + if (existingRecord.pickerSecondStockTakeQty != null || existingRecord.approverStockTakeQty != null) { + throw IllegalArgumentException("Cannot change the first count after a later count exists") + } + val reviseCount = existingRecord.pickerReviseCount ?: 0 + if (reviseCount >= 2) { + throw IllegalArgumentException("This count can only be changed 2 times") + } + val varianceQty = availableQty - request.qty - request.badQty + existingRecord.apply { + this.pickerFirstStockTakeQty = request.qty + this.pickerFirstBadQty = request.badQty + this.bookQty = availableQty + this.varianceQty = varianceQty + this.stockTakerId = stockTakerId + this.stockTakerName = user?.name + this.status = "pass" + this.pickerSecondStockTakeQty = null + this.pickerSecondBadQty = null + this.stockTakeEndTime = null + this.pickerReviseCount = reviseCount + 1 + } + existingRecord + } existingRecord.pickerFirstStockTakeQty == null -> { val isCompled = inventoryLotLine.inQty == inventoryLotLine.outQty val varianceQty = availableQty - request.qty - request.badQty @@ -1367,7 +1416,8 @@ open class StockTakeRecordService( } existingRecord } - existingRecord.pickerSecondStockTakeQty == null -> { + existingRecord.pickerSecondStockTakeQty == null && + existingRecord.status.equals("notMatch", ignoreCase = true) -> { val varianceQty = availableQty - request.qty - request.badQty existingRecord.apply { this.stockTakeRoundId = this.stockTakeRoundId ?: (stockTake.stockTakeRoundId ?: stockTake.id) diff --git a/src/main/java/com/ffii/fpsms/modules/stock/web/model/StockTakeRecordReponse.kt b/src/main/java/com/ffii/fpsms/modules/stock/web/model/StockTakeRecordReponse.kt index d96bf61f..791c52ba 100644 --- a/src/main/java/com/ffii/fpsms/modules/stock/web/model/StockTakeRecordReponse.kt +++ b/src/main/java/com/ffii/fpsms/modules/stock/web/model/StockTakeRecordReponse.kt @@ -80,6 +80,8 @@ data class InventoryLotDetailResponse( val lastSelect: Int? = null, /** Stock UoM short label (e.g. 包), shown beside the count input. */ val uomShortDesc: String? = null, + /** Times the picker has changed this saved first count. */ + val pickerReviseCount: Int? = 0, ) data class InventoryLotLineListRequest( val warehouseCode: String @@ -90,7 +92,9 @@ data class SaveStockTakeRecordRequest( val qty: BigDecimal, // QTY(第一次或第二次,后端判断) val badQty: BigDecimal, // val stockTakerName: String, - val remark: String? = null + val remark: String? = null, + /** true = 區域仍在盤點中時,覆寫已盤點的第一次數量;不寫入第二次盤點 */ + val reviseFirstQty: Boolean = false, ) /** diff --git a/src/main/resources/db/changelog/changes/20261001_picker_revise_count/01_add_picker_revise_count.sql b/src/main/resources/db/changelog/changes/20261001_picker_revise_count/01_add_picker_revise_count.sql new file mode 100644 index 00000000..864f978c --- /dev/null +++ b/src/main/resources/db/changelog/changes/20261001_picker_revise_count/01_add_picker_revise_count.sql @@ -0,0 +1,5 @@ +-- liquibase formatted sql +-- changeset fpsms:20261001-picker-revise-count + +ALTER TABLE `fpsmsdb`.`stocktakerecord` +ADD COLUMN `pickerReviseCount` INT NOT NULL DEFAULT 0 AFTER `lastSelect`;