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 36dd5aa..c67d38b 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 @@ -13,8 +13,6 @@ import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional import com.ffii.fpsms.modules.stock.entity.InventoryLotLineRepository import com.ffii.fpsms.modules.stock.entity.enum.InventoryLotLineStatus -import org.springframework.http.HttpStatus -import org.springframework.web.server.ResponseStatusException @Service @@ -30,6 +28,8 @@ open class StockTransferRecordService( ) { private enum class TransferStockInMode { MERGED_EXISTING_LOT, + /** Merged into smallest-id AVAILABLE line among several with same expiry (same lot key at target). */ + MERGED_EXISTING_LOT_AMBIGUOUS, CREATED_NEW_LOT } @@ -49,12 +49,17 @@ open class StockTransferRecordService( name = "Stock Transfer Record", code = when (stockInMode) { TransferStockInMode.MERGED_EXISTING_LOT -> "MERGED_EXISTING_LOT" + TransferStockInMode.MERGED_EXISTING_LOT_AMBIGUOUS -> "MERGED_EXISTING_LOT_AMBIGUOUS" TransferStockInMode.CREATED_NEW_LOT -> "CREATED_NEW_LOT" }, type = "success", 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)" + TransferStockInMode.MERGED_EXISTING_LOT -> + "Stock transfer completed successfully (merged into existing target lot)" + TransferStockInMode.MERGED_EXISTING_LOT_AMBIGUOUS -> + "已併入較早建立的批次(同批號有多筆可用)" + TransferStockInMode.CREATED_NEW_LOT -> + "Stock transfer completed successfully (created new target lot)" }, errorPosition = null ) @@ -120,20 +125,29 @@ open class StockTransferRecordService( status = InventoryLotLineStatus.AVAILABLE, ).filter { it.id != inventoryLotLine.id } + // Same expiry as source required to merge; repository orders by ill.id ASC — first = earliest-created line + val sameExpiryMergeable = mergeCandidates.filter { + val targetExpiry = it.inventoryLot?.expiryDate + targetExpiry != null && targetExpiry == expiryDate + } + return when { mergeCandidates.isEmpty() -> stockInLineService.createStockIn(stockInRequest) to TransferStockInMode.CREATED_NEW_LOT - mergeCandidates.size == 1 -> + sameExpiryMergeable.isEmpty() -> + stockInLineService.createStockIn(stockInRequest) to TransferStockInMode.CREATED_NEW_LOT + sameExpiryMergeable.size == 1 -> stockInLineService.createStockInForExistingInventoryLotLine( stockInRequest, - mergeCandidates.single(), + sameExpiryMergeable.single(), ) to TransferStockInMode.MERGED_EXISTING_LOT - else -> - throw ResponseStatusException( - HttpStatus.BAD_REQUEST, - "目標倉在同一品項與批號下有多筆可用的庫存批號行,無法自動併批;請檢查資料。" + - " (Multiple AVAILABLE inventory lot lines for same warehouse, item, lotNo.)", - ) + else -> { + val targetLine = sameExpiryMergeable.first() + stockInLineService.createStockInForExistingInventoryLotLine( + stockInRequest, + targetLine, + ) to TransferStockInMode.MERGED_EXISTING_LOT_AMBIGUOUS + } } }