From a4b7247c57ad358ad9e15a1c51621814a2da5fde Mon Sep 17 00:00:00 2001 From: ouyangxq <775153912@qq.com> Date: Fri, 11 Sep 2026 10:32:30 +0800 Subject: [PATCH] fix: expose overseas receiving business facts --- .../service/DispatchPdaWorkflowService.java | 1 + .../inboundplan/dto/InboundPlanResponse.java | 7 ++++- .../mapper/InboundPlanOrderMapper.java | 6 ++++ .../service/InboundPlanService.java | 13 +++++++-- .../openapi/overseas-business-v1.yaml | 7 ++++- .../DispatchPdaWorkflowServiceTest.java | 28 +++++++++++++++++++ ...rInboundPlanConversionCoordinatorTest.java | 5 ++-- .../service/InboundPlanServiceTest.java | 7 +++++ 8 files changed, 68 insertions(+), 6 deletions(-) diff --git a/lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/pda/service/DispatchPdaWorkflowService.java b/lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/pda/service/DispatchPdaWorkflowService.java index dfa090572..dc4fc8858 100644 --- a/lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/pda/service/DispatchPdaWorkflowService.java +++ b/lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/pda/service/DispatchPdaWorkflowService.java @@ -221,6 +221,7 @@ public class DispatchPdaWorkflowService { outboundOrders.updateById(outbound); order.setShippedPackageCount((int) shipped); order.setStatus("DEPARTED"); + order.setDepartAt(now); order.setUpdatedAt(now); orders.updateById(order); releasePalletLocks(customerId, order.getId(), now); diff --git a/lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/dto/InboundPlanResponse.java b/lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/dto/InboundPlanResponse.java index 8188d0a75..d20d7e549 100644 --- a/lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/dto/InboundPlanResponse.java +++ b/lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/dto/InboundPlanResponse.java @@ -10,6 +10,9 @@ public record InboundPlanResponse( String planNo, String customerId, Long sourceOrderId, + String sourceOrderNo, + String customerName, + String orderType, String containerNo, String overseasWarehouseCode, String overseasWarehouseName, @@ -29,7 +32,9 @@ public record InboundPlanResponse( boolean mergeRequired, boolean urgent, String creationMode, - String remark + String remark, + LocalDateTime createdAt, + LocalDateTime updatedAt ) { public record Line(Long id, Long orderId, String inboundCode, String fbaWarehouseCode, String destinationWarehouseId, String destinationWarehouseCode, String destinationWarehouseName, diff --git a/lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/mapper/InboundPlanOrderMapper.java b/lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/mapper/InboundPlanOrderMapper.java index a4e84580b..19a6cee5f 100644 --- a/lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/mapper/InboundPlanOrderMapper.java +++ b/lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/mapper/InboundPlanOrderMapper.java @@ -16,6 +16,7 @@ public interface InboundPlanOrderMapper { String orderType) { } record ReceivingWarehouseSnapshot(String overseasWarehouseId, String overseasWarehouseCode, String overseasWarehouseName) { } + record DetailOrderSnapshot(String orderNo, String customerName, String orderType) { } record ContainerWarehouseRef(String customerId, Long orderId, String sourceContainerBookingId, String overseasWarehouseId) { } record ContainerPreviewOrderRow( @@ -99,6 +100,11 @@ public interface InboundPlanOrderMapper { ReceivingWarehouseSnapshot findReceivingWarehouse(@Param("customerId") String customerId, @Param("orderId") Long orderId); + @Select("SELECT order_no AS orderNo,customer_name AS customerName,order_type AS orderType " + + "FROM ll_order WHERE customer_id=#{customerId} AND id=#{orderId} LIMIT 1") + DetailOrderSnapshot findDetailOrder(@Param("customerId") String customerId, + @Param("orderId") Long orderId); + @Update("UPDATE ll_order SET inbound_order_no=#{planNo},current_status='INBOUND_PLANNED'," + "pallet_merge_flag='MERGED',pallet_count=#{palletCount},updated_at=#{updatedAt} " + "WHERE customer_id=#{customerId} AND id=#{orderId}") diff --git a/lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/service/InboundPlanService.java b/lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/service/InboundPlanService.java index 333d650b5..765a95c13 100644 --- a/lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/service/InboundPlanService.java +++ b/lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/service/InboundPlanService.java @@ -1000,6 +1000,11 @@ public class InboundPlanService { } WarehouseResourceGateway.WarehouseReference authoritativeWarehouse = resolvedWarehouse == null ? requiredReceivingWarehouse(receivingWarehouse.overseasWarehouseId()) : resolvedWarehouse; + InboundPlanOrderMapper.DetailOrderSnapshot sourceOrder = plan.getSourceOrderId() == null ? null + : orderMapper.findDetailOrder(plan.getCustomerId(), plan.getSourceOrderId()); + if (plan.getSourceOrderId() != null && sourceOrder == null) { + throw new ResponseStatusException(HttpStatus.CONFLICT, "入库计划关联订单不存在"); + } List lines = lineMapper.selectList(new LambdaQueryWrapper() .eq(InboundPlanLine::getPlanId, plan.getId()).orderByAsc(InboundPlanLine::getId)); List pallets = palletMapper.selectList(new LambdaQueryWrapper() @@ -1009,7 +1014,10 @@ public class InboundPlanService { .eq(InboundPlanPalletAllocation::getPlanId, plan.getId()) .orderByAsc(InboundPlanPalletAllocation::getId)); return new InboundPlanResponse(plan.getId(), plan.getPlanNo(), plan.getCustomerId(), plan.getSourceOrderId(), - plan.getContainerNo(), authoritativeWarehouse.warehouseCode(), authoritativeWarehouse.warehouseName(), + sourceOrder == null ? null : sourceOrder.orderNo(), + sourceOrder == null ? null : sourceOrder.customerName(), + sourceOrder == null ? null : sourceOrder.orderType(), plan.getContainerNo(), + authoritativeWarehouse.warehouseCode(), authoritativeWarehouse.warehouseName(), plan.getStatus(), plan.getLineCount(), plan.getPalletCount(), plan.getTotalVolumeCbm(), lines.stream().mapToInt(InboundPlanLine::getRequiredPackageCount).sum(), allocations.stream().mapToInt(InboundPlanPalletAllocation::getPickedPackageCount).sum(), @@ -1027,7 +1035,8 @@ public class InboundPlanService { item.getPickedPackageCount(), item.getActualVolumeCbm(), item.getStatus(), item.getVersion())).toList(), plan.getVersion() == null ? 0 : plan.getVersion(), plan.getPlannedArrivalDate(), plan.getPalletType(), Boolean.TRUE.equals(plan.getAssignedFlag()), Boolean.TRUE.equals(plan.getMergeRequired()), - Boolean.TRUE.equals(plan.getUrgentFlag()), plan.getCreationMode(), plan.getPlanRemark()); + Boolean.TRUE.equals(plan.getUrgentFlag()), plan.getCreationMode(), plan.getPlanRemark(), + plan.getCreatedAt(), plan.getUpdatedAt()); } private WarehouseResourceGateway.WarehouseReference requiredReceivingWarehouse(String warehouseId) { diff --git a/lastleg-service/src/main/resources/openapi/overseas-business-v1.yaml b/lastleg-service/src/main/resources/openapi/overseas-business-v1.yaml index 06efa2723..d5038ae39 100644 --- a/lastleg-service/src/main/resources/openapi/overseas-business-v1.yaml +++ b/lastleg-service/src/main/resources/openapi/overseas-business-v1.yaml @@ -2773,12 +2773,15 @@ components: version: { type: integer } InboundPlanDetail: type: object - required: [id, planNo, customerId, overseasWarehouseCode, overseasWarehouseName, status, lineCount, palletCount, totalVolumeCbm, expectedPackageCount, pickedPackageCount, lines, pallets, allocations, version] + required: [id, planNo, customerId, overseasWarehouseCode, overseasWarehouseName, status, lineCount, palletCount, totalVolumeCbm, expectedPackageCount, pickedPackageCount, lines, pallets, allocations, version, createdAt, updatedAt] properties: id: { type: string, pattern: '^[0-9]+$' } planNo: { type: string } customerId: { type: string } sourceOrderId: { type: string, pattern: '^[0-9]+$', nullable: true } + sourceOrderNo: { type: string, nullable: true, description: 关联尾程订单业务单号;手工入库计划为空 } + customerName: { type: string, nullable: true, description: 货主名称;手工入库计划为空 } + orderType: { type: string, nullable: true, description: 关联尾程订单类型;手工入库计划为空 } containerNo: { type: string, nullable: true } overseasWarehouseCode: { type: string, description: 接柜仓编码,取自尾程订单预分配接收仓事实 } overseasWarehouseName: { type: string, description: 接柜仓名称,取自尾程订单预分配接收仓事实 } @@ -2795,6 +2798,8 @@ components: urgent: { type: boolean } creationMode: { type: string, enum: [AUTO, MANUAL] } remark: { type: string, nullable: true } + createdAt: { type: string, format: date-time } + updatedAt: { type: string, format: date-time } lines: { type: array, items: { $ref: '#/components/schemas/InboundPlanLine' } } pallets: { type: array, items: { $ref: '#/components/schemas/InboundPlanPallet' } } allocations: { type: array, items: { $ref: '#/components/schemas/InboundPlanAllocation' } } diff --git a/lastleg-service/src/test/java/com/baiyue/lastleg/dispatch/pda/service/DispatchPdaWorkflowServiceTest.java b/lastleg-service/src/test/java/com/baiyue/lastleg/dispatch/pda/service/DispatchPdaWorkflowServiceTest.java index 6f34e38ae..4368e7ae2 100644 --- a/lastleg-service/src/test/java/com/baiyue/lastleg/dispatch/pda/service/DispatchPdaWorkflowServiceTest.java +++ b/lastleg-service/src/test/java/com/baiyue/lastleg/dispatch/pda/service/DispatchPdaWorkflowServiceTest.java @@ -33,6 +33,7 @@ import java.util.List; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -226,6 +227,33 @@ class DispatchPdaWorkflowServiceTest { verify(outboundOrders, never()).updateById((OutboundOrder) any()); } + @Test + void successfulDeparturePersistsBusinessDepartureTime() { + DispatchOrder order = order("100", "DSP-1", "WH-1", "READY_TO_DEPART"); + order.setVehiclePlate("CA-100"); + DispatchPdaTask task = task(11L, "100", "WH-1", "COMPLETED"); + DispatchItem item = item(21L, "100", 6); + DispatchPdaPick pick = new DispatchPdaPick(); pick.setPackages(6L); + OutboundOrder outbound = new OutboundOrder(); + outbound.setOutboundNo("OB-1"); outbound.setStatus("WAIT_OUTBOUND"); + when(orders.findGlobalByDispatchNo("DSP-1")).thenReturn(order); + when(orders.lockById("100", 1L)).thenReturn(order); + when(outboundOrders.lockByDispatch("100", 1L)).thenReturn(outbound); + when(tasks.lockByDispatch("100", 1L)).thenReturn(task); + when(items.findByDispatchOrder("100", 1L)).thenReturn(List.of(item)); + when(picks.totalItem("100", 11L, 21L)).thenReturn(6L); + when(picks.listTask("100", 11L)).thenReturn(List.of(pick)); + when(palletLocks.selectList(any())).thenReturn(List.of()); + + DispatchPdaResponses.Departed result = service.depart( + "WH-1", "DSP-1", "7", new DispatchPdaRequests.Depart("depart-1", null)); + + assertEquals("DEPARTED", result.status()); + assertNotNull(order.getDepartAt()); + assertEquals(order.getDepartAt(), order.getUpdatedAt()); + verify(orders).updateById(order); + } + @Test void exactDepartRetryReturnsPersistedResultAfterStatusChanged() throws Exception { DispatchOrder order = order("100", "DSP-1", "WH-1", "DEPARTED"); diff --git a/lastleg-service/src/test/java/com/baiyue/lastleg/inboundplan/service/ContainerInboundPlanConversionCoordinatorTest.java b/lastleg-service/src/test/java/com/baiyue/lastleg/inboundplan/service/ContainerInboundPlanConversionCoordinatorTest.java index b064e4b11..a4a843e15 100644 --- a/lastleg-service/src/test/java/com/baiyue/lastleg/inboundplan/service/ContainerInboundPlanConversionCoordinatorTest.java +++ b/lastleg-service/src/test/java/com/baiyue/lastleg/inboundplan/service/ContainerInboundPlanConversionCoordinatorTest.java @@ -431,10 +431,11 @@ class ContainerInboundPlanConversionCoordinatorTest { } private InboundPlanResponse plan(String planNo, List pallets) { - return new InboundPlanResponse(21L, planNo, "100", 11L, "MSCU6639870", "US-LAX-01", + return new InboundPlanResponse(21L, planNo, "100", 11L, "FL-WH-1", "验收客户", "ONE_CLICK_DROPSHIP", + "MSCU6639870", "US-LAX-01", "Los Angeles", "PENDING_ASSIGNMENT", 1, 1, BigDecimal.ONE, 10, 0, List.of(), pallets, List.of(), 1, LocalDate.of(2026, 9, 10), "WOOD", false, - false, false, "MANUAL", "自动生成"); + false, false, "MANUAL", "自动生成", null, null); } private ConvertContainerInboundPlanRequest request() { diff --git a/lastleg-service/src/test/java/com/baiyue/lastleg/inboundplan/service/InboundPlanServiceTest.java b/lastleg-service/src/test/java/com/baiyue/lastleg/inboundplan/service/InboundPlanServiceTest.java index edb1de9b8..2da5db8c9 100644 --- a/lastleg-service/src/test/java/com/baiyue/lastleg/inboundplan/service/InboundPlanServiceTest.java +++ b/lastleg-service/src/test/java/com/baiyue/lastleg/inboundplan/service/InboundPlanServiceTest.java @@ -84,6 +84,9 @@ class InboundPlanServiceTest { org.mockito.Mockito.lenient().when(orderMapper.findReceivingWarehouse(any(), any())).thenReturn( new InboundPlanOrderMapper.ReceivingWarehouseSnapshot( "193000000000200003", "US-LAX-01", "洛杉矶仓")); + org.mockito.Mockito.lenient().when(orderMapper.findDetailOrder(any(), anyLong())).thenReturn( + new InboundPlanOrderMapper.DetailOrderSnapshot( + "FL-WH-TEST", "测试客户", "ONE_CLICK_DROPSHIP")); org.mockito.Mockito.lenient().when(warehouseGateway.requireActiveSharedWarehouse(193000000000200003L)).thenReturn( new WarehouseResourceGateway.WarehouseReference( 193000000000200003L, "US-LAX-01", "洛杉矶仓", "ACTIVE")); @@ -324,7 +327,11 @@ class InboundPlanServiceTest { assertEquals("US-NY-01", result.overseasWarehouseCode()); assertEquals("纽约仓", result.overseasWarehouseName()); + assertEquals("FL-WH-TEST", result.sourceOrderNo()); + assertEquals("测试客户", result.customerName()); + assertEquals("ONE_CLICK_DROPSHIP", result.orderType()); verify(orderMapper).findReceivingWarehouse("100", 1L); + verify(orderMapper).findDetailOrder("100", 1L); } @Test