diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoWorkbenchReleaseService.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoWorkbenchReleaseService.kt index c45e8a8..f349b2c 100644 --- a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoWorkbenchReleaseService.kt +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoWorkbenchReleaseService.kt @@ -1066,24 +1066,31 @@ open class DoWorkbenchReleaseService( ) } + private fun isValidMergeLeftTicket(row: DopoMergeRow): Boolean { + val rt = row.releaseType?.trim()?.lowercase().orEmpty() + if (isWorkbenchMergeTicketNo(row.ticketNo)) { + return rt == WorkbenchReleaseTypeSupport.IS_EXTRA_BATCH.lowercase() || + rt == WorkbenchReleaseTypeSupport.IS_EXTRA_SINGLE.lowercase() + } + return rt == WorkbenchReleaseTypeSupport.BATCH.lowercase() || + rt == WorkbenchReleaseTypeSupport.SINGLE.lowercase() + } + @Transactional(rollbackFor = [Exception::class]) open fun mergeTicketsCase3(batchOrSingleDopoId: Long, isExtraDopoId: Long): MessageResponse { if (batchOrSingleDopoId == isExtraDopoId) { return mergeTicketsError("SAME_TICKET", "Cannot merge a ticket with itself") } val batchRow = loadDopoRowForMerge(batchOrSingleDopoId) - ?: return mergeTicketsError("NOT_FOUND", "Batch/single ticket not found") + ?: return mergeTicketsError("NOT_FOUND", "Left ticket not found") val extraRow = loadDopoRowForMerge(isExtraDopoId) ?: return mergeTicketsError("NOT_FOUND", "isExtra ticket not found") - val batchRt = batchRow.releaseType?.trim()?.lowercase().orEmpty() - if (batchRt != WorkbenchReleaseTypeSupport.BATCH.lowercase() && - batchRt != WorkbenchReleaseTypeSupport.SINGLE.lowercase() - ) { - return mergeTicketsError("INVALID_BATCH", "Left ticket must be plain batch or single") - } - if (isWorkbenchMergeTicketNo(batchRow.ticketNo)) { - return mergeTicketsError("INVALID_BATCH", "Left ticket must not be a TI-M merge ticket") + if (!isValidMergeLeftTicket(batchRow)) { + return mergeTicketsError( + "INVALID_BATCH", + "Left ticket must be plain batch/single or an active TI-M merge ticket", + ) } if (extraRow.releaseType?.trim()?.lowercase() != WorkbenchReleaseTypeSupport.LEGACY_IS_EXTRA.lowercase()) { return mergeTicketsError("INVALID_EXTRA", "Right ticket must be releaseType isExtra") @@ -1103,23 +1110,35 @@ open class DoWorkbenchReleaseService( ) } - val isSingleRelease = batchRt == WorkbenchReleaseTypeSupport.SINGLE.lowercase() - val requiredDate = batchRow.requiredDeliveryDate ?: LocalDate.now() - val storeId = batchRow.storeId - val isDefaultTruckLane = storeId.isNullOrBlank() - val ticketFloorSegment = resolveTicketFloorSegment(storeId, isDefaultTruckLane) + val leftIsExistingMerge = isWorkbenchMergeTicketNo(batchRow.ticketNo) + val batchRt = batchRow.releaseType?.trim()?.lowercase().orEmpty() + val isSingleRelease = when { + leftIsExistingMerge -> + batchRt == WorkbenchReleaseTypeSupport.IS_EXTRA_SINGLE.lowercase() + else -> batchRt == WorkbenchReleaseTypeSupport.SINGLE.lowercase() + } - val mergeHeaderId = insertMergeHeaderFromDopoRow( - template = batchRow, - isSingleRelease = isSingleRelease, - requiredDate = requiredDate, - ticketFloorSegment = ticketFloorSegment, - ) ?: return mergeTicketsError("CREATE_FAILED", "Failed to create TI-M merge ticket") + val mergeHeaderId = if (leftIsExistingMerge) { + batchOrSingleDopoId + } else { + val requiredDate = batchRow.requiredDeliveryDate ?: LocalDate.now() + val storeId = batchRow.storeId + val isDefaultTruckLane = storeId.isNullOrBlank() + val ticketFloorSegment = resolveTicketFloorSegment(storeId, isDefaultTruckLane) + insertMergeHeaderFromDopoRow( + template = batchRow, + isSingleRelease = isSingleRelease, + requiredDate = requiredDate, + ticketFloorSegment = ticketFloorSegment, + ) ?: return mergeTicketsError("CREATE_FAILED", "Failed to create TI-M merge ticket") + } - retireSourceTicketIntoMergeHeader(batchOrSingleDopoId, mergeHeaderId) + if (!leftIsExistingMerge) { + retireSourceTicketIntoMergeHeader(batchOrSingleDopoId, mergeHeaderId) + } retireSourceTicketIntoMergeHeader(isExtraDopoId, mergeHeaderId) - val newTicketNo = jdbcDao.queryForList( + val mergeTicketNo = jdbcDao.queryForList( "SELECT ticketNo AS t FROM fpsmsdb.delivery_order_pick_order WHERE id = :id", mapOf("id" to mergeHeaderId), ).firstOrNull()?.let { row -> @@ -1131,13 +1150,14 @@ open class DoWorkbenchReleaseService( code = "SUCCESS", name = "workbench_merge_tickets", type = "workbench_merge_tickets", - message = "Merged into $newTicketNo", + message = "Merged into $mergeTicketNo", errorPosition = null, entity = mapOf( "mergeDeliveryOrderPickOrderId" to mergeHeaderId, - "ticketNo" to newTicketNo, + "ticketNo" to mergeTicketNo, "batchOrSingleDopoId" to batchOrSingleDopoId, "isExtraDopoId" to isExtraDopoId, + "mergedIntoExistingTiM" to leftIsExistingMerge, ), ) } @@ -1205,8 +1225,10 @@ open class DoWorkbenchReleaseService( when (side) { "batchFamily" -> sql.append( """ - AND LOWER(COALESCE(dop.releaseType, '')) IN ('batch', 'single') - AND (dop.ticketNo IS NULL OR dop.ticketNo NOT LIKE 'TI-M-%') + AND ( + LOWER(COALESCE(dop.releaseType, '')) IN ('batch', 'single') + OR dop.ticketNo LIKE 'TI-M-%' + ) """.trimIndent().let { " $it" }, ) "isExtra" -> sql.append(" AND LOWER(COALESCE(dop.releaseType, '')) = 'isextra' ") diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/DoWorkbenchController.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/DoWorkbenchController.kt index 1761002..702db0a 100644 --- a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/DoWorkbenchController.kt +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/DoWorkbenchController.kt @@ -227,7 +227,7 @@ class DoWorkbenchController( ): WorkbenchMergeTicketCandidatesResponse = doWorkbenchReleaseService.getMergeTicketCandidates(requiredDate, shopSearch) - /** Case 3: merge selected batch/single + isExtra into a new [TI-M] ticket. */ + /** Case 3 / 3b: merge batch/single or existing [TI-M] + isExtra into [TI-M]. */ @PostMapping("/merge-tickets") fun mergeWorkbenchTickets(@RequestBody request: WorkbenchMergeTicketsRequest): MessageResponse = doWorkbenchReleaseService.mergeTicketsCase3(