From 66d6acb4b5173c1a918733624499a5622b717a29 Mon Sep 17 00:00:00 2001 From: "kelvin.yau" Date: Wed, 15 Apr 2026 14:17:53 +0800 Subject: [PATCH] Stock TRF v2 --- .../stock/service/StockInLineService.kt | 20 ++++++++-- .../service/StockTransferRecordService.kt | 37 +++++++++++++++---- 2 files changed, 46 insertions(+), 11 deletions(-) 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 38f5fbd..a0d2906 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 @@ -1454,7 +1454,19 @@ open class StockInLineService( } val savedStockIn = stockInRepository.save(stockIn) - // Step 2: Create StockInLine and link to existing InventoryLotLine + // Step 2: Increase qty on the matched target lot line instead of creating a new lot line + val updatedInventoryLotLine = existingInventoryLotLine.apply { + this.inQty = (this.inQty ?: BigDecimal.ZERO).add(request.acceptedQty) + this.status = inventoryLotLineService.deriveInventoryLotLineStatus( + this.status, + this.inQty, + this.outQty, + this.holdQty + ) + } + val savedInventoryLotLine = inventoryLotLineRepository.saveAndFlush(updatedInventoryLotLine) + + // Step 3: Create StockInLine and link to existing InventoryLotLine val item = itemRepository.findById(request.itemId).orElseThrow() val stockInLine = StockInLine().apply { @@ -1472,12 +1484,12 @@ open class StockInLineService( this.dnNo = request.dnNo this.type = request.type // Link to existing InventoryLot and InventoryLotLine - this.inventoryLot = existingInventoryLotLine.inventoryLot - this.inventoryLotLine = existingInventoryLotLine + this.inventoryLot = savedInventoryLotLine.inventoryLot + this.inventoryLotLine = savedInventoryLotLine } val savedStockInLine = saveAndFlush(stockInLine) - // Step 3: Create Stock Ledger entry + // Step 4: Create Stock Ledger entry createStockLedgerForStockIn(savedStockInLine, request.acceptedQty.toDouble()) return savedStockInLine diff --git a/src/main/java/com/ffii/fpsms/modules/stock/service/StockTransferRecordService.kt b/src/main/java/com/ffii/fpsms/modules/stock/service/StockTransferRecordService.kt index 3e164fd..1d7a505 100644 --- a/src/main/java/com/ffii/fpsms/modules/stock/service/StockTransferRecordService.kt +++ b/src/main/java/com/ffii/fpsms/modules/stock/service/StockTransferRecordService.kt @@ -12,8 +12,6 @@ import com.ffii.fpsms.modules.stock.web.model.StockInRequest import com.ffii.fpsms.modules.stock.web.model.StockOutRequest import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional -import java.math.BigDecimal -import java.time.LocalDate import com.ffii.fpsms.modules.stock.entity.InventoryLotLineRepository import com.ffii.fpsms.modules.stock.entity.enum.InventoryLotLineStatus @@ -29,6 +27,10 @@ open class StockTransferRecordService( jdbcDao, stockTransferRecordRepository ) { + private enum class TransferStockInMode { + MERGED_EXISTING_LOT, + CREATED_NEW_LOT + } @Transactional open fun createStockTransfer(request: CreateStockTransferRequest): MessageResponse { @@ -36,7 +38,7 @@ open class StockTransferRecordService( val stockOutLine = createStockOut(request) // Step 2: Stock In - using generic function - val stockInLine = createStockIn(request) + val (stockInLine, stockInMode) = createStockIn(request) // Step 3: Create Stock Transfer Record val stockTransferRecord = createStockTransferRecord(request, stockOutLine, stockInLine) @@ -44,9 +46,15 @@ open class StockTransferRecordService( return MessageResponse( id = stockTransferRecord.id, name = "Stock Transfer Record", - code = "STOCK_TRANSFER_CREATED", + code = when (stockInMode) { + TransferStockInMode.MERGED_EXISTING_LOT -> "MERGED_EXISTING_LOT" + TransferStockInMode.CREATED_NEW_LOT -> "CREATED_NEW_LOT" + }, type = "success", - message = "Stock transfer completed successfully", + message = when (stockInMode) { + TransferStockInMode.MERGED_EXISTING_LOT -> "Stock transfer completed successfully (merged into existing target lot)" + TransferStockInMode.CREATED_NEW_LOT -> "Stock transfer completed successfully (created new target lot)" + }, errorPosition = null ) } @@ -62,7 +70,7 @@ open class StockTransferRecordService( return stockOutLineService.createStockOut(stockOutRequest) } - private fun createStockIn(request: CreateStockTransferRequest): StockInLine { + private fun createStockIn(request: CreateStockTransferRequest): Pair { // Step 1: Get inventoryLotLine to extract item information val inventoryLotLine = inventoryLotLineRepository.findById(request.inventoryLotLineId) .orElseThrow { IllegalArgumentException("InventoryLotLine not found with id: ${request.inventoryLotLineId}") } @@ -107,7 +115,22 @@ open class StockTransferRecordService( warehouseId = request.warehouseId ) - return stockInLineService.createStockIn(stockInRequest) + val existingTargetLotLine = inventoryLotLineRepository.findByLotNoAndItemIdAndWarehouseId( + lotNo = lotNo, + itemId = itemId, + warehouseId = request.warehouseId + ) + + return if ( + existingTargetLotLine != null && + existingTargetLotLine.status == InventoryLotLineStatus.AVAILABLE && + existingTargetLotLine.id != inventoryLotLine.id + ) { + stockInLineService.createStockInForExistingInventoryLotLine(stockInRequest, existingTargetLotLine) to + TransferStockInMode.MERGED_EXISTING_LOT + } else { + stockInLineService.createStockIn(stockInRequest) to TransferStockInMode.CREATED_NEW_LOT + } } private fun createStockTransferRecord(