From 6cf144e53ddfb1f8bbfb0391219256211b455688 Mon Sep 17 00:00:00 2001 From: ouyangxq <775153912@qq.com> Date: Thu, 10 Sep 2026 21:22:06 +0800 Subject: [PATCH] feat: expose dispatch BOL lines --- .../dispatch/dto/DispatchResponse.java | 7 +++- .../dispatch/mapper/DispatchBolMapper.java | 35 +++++++++++++++++++ .../dispatch/service/DispatchService.java | 16 +++++++-- .../openapi/overseas-business-v1.yaml | 15 ++++++++ .../dispatch/service/DispatchServiceTest.java | 14 +++++++- 5 files changed, 82 insertions(+), 5 deletions(-) create mode 100644 lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/mapper/DispatchBolMapper.java diff --git a/lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/dto/DispatchResponse.java b/lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/dto/DispatchResponse.java index 5e7d2a81d..7de25f0a8 100644 --- a/lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/dto/DispatchResponse.java +++ b/lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/dto/DispatchResponse.java @@ -12,11 +12,16 @@ public record DispatchResponse(Long id, String dispatchNo, String vehiclePlate, int itemCount, int palletCount, int packageCount, int pickedPackageCount, int shippedPackageCount, int remainingPackageCount, String partialCompletionReason, LocalDateTime createdAt, - List items) { + List items, List bolLines) { public record Item(Long id, Long planPalletId, Long warehousePalletId, String palletNo, String overseasWarehouseId, String overseasWarehouseName, String orderNo, String orderRefs, String inboundCode, String destinationWarehouseCode, String destinationWarehouseName, String fbaWarehouseCode, int packageCount, BigDecimal volumeCbm, String sourceStage) { } + + public record BolLine(String containerNo, String palletNo, String fbaWarehouseCode, + String destinationWarehouseName, String warehouseNo, String fbaShipmentId, + String poReferenceNo, int packageCount) { + } } diff --git a/lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/mapper/DispatchBolMapper.java b/lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/mapper/DispatchBolMapper.java new file mode 100644 index 000000000..254dbdded --- /dev/null +++ b/lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/mapper/DispatchBolMapper.java @@ -0,0 +1,35 @@ +package com.baiyue.lastleg.dispatch.mapper; + +import com.baiyue.lastleg.dispatch.dto.DispatchResponse; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +@Mapper +public interface DispatchBolMapper { + @Select("SELECT " + + "COALESCE(MAX(NULLIF(o.container_no,'')),MAX(NULLIF(ip.container_no,''))) AS containerNo," + + "MAX(NULLIF(di.pallet_no,'')) AS palletNo," + + "COALESCE(MAX(NULLIF(l.destination_warehouse_code,'')),MAX(NULLIF(di.fba_warehouse_code,''))," + + "MAX(NULLIF(di.destination_warehouse_code,''))) AS fbaWarehouseCode," + + "COALESCE(MAX(NULLIF(l.destination_warehouse_name,'')),MAX(NULLIF(di.destination_warehouse_name,''))) AS destinationWarehouseName," + + "COALESCE(MAX(NULLIF(l.inbound_code,'')),MAX(NULLIF(di.inbound_code,''))) AS warehouseNo," + + "GROUP_CONCAT(DISTINCT NULLIF(od.shipment_no,'') ORDER BY od.shipment_no SEPARATOR ', ') AS fbaShipmentId," + + "GROUP_CONCAT(DISTINCT NULLIF(od.fba_tracking_no,'') ORDER BY od.fba_tracking_no SEPARATOR ', ') AS poReferenceNo," + + "CASE WHEN MAX(l.id) IS NULL THEN COALESCE(MAX(di.package_count),0) " + + "WHEN COALESCE(MAX(a.picked_package_count),0)>0 THEN MAX(a.picked_package_count) " + + "ELSE COALESCE(MAX(a.planned_package_count),0) END AS packageCount " + + "FROM ll_dispatch_item di " + + "LEFT JOIN ll_inbound_plan_pallet p ON p.id=di.plan_pallet_id " + + "LEFT JOIN ll_inbound_plan ip ON ip.id=p.plan_id AND ip.customer_id=di.customer_id " + + "LEFT JOIN ll_inbound_plan_pallet_allocation a ON a.pallet_id=p.id " + + "LEFT JOIN ll_inbound_plan_line l ON l.id=a.line_id AND l.customer_id=di.customer_id " + + "LEFT JOIN ll_order o ON o.id=l.order_id AND o.customer_id=di.customer_id " + + "LEFT JOIN ll_order_detail od ON od.order_id=l.order_id AND od.customer_id=di.customer_id " + + "WHERE di.customer_id=#{customerId} AND di.dispatch_order_id=#{dispatchOrderId} " + + "GROUP BY di.id,l.id ORDER BY di.id,l.id") + List findByDispatchOrder(@Param("customerId") String customerId, + @Param("dispatchOrderId") Long dispatchOrderId); +} diff --git a/lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/service/DispatchService.java b/lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/service/DispatchService.java index 9a3e3eca2..dc64903dc 100644 --- a/lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/service/DispatchService.java +++ b/lastleg-service/src/main/java/com/baiyue/lastleg/dispatch/service/DispatchService.java @@ -12,6 +12,7 @@ import com.baiyue.lastleg.dispatch.entity.DispatchPalletLock; import com.baiyue.lastleg.dispatch.entity.DispatchDraft; import com.baiyue.lastleg.dispatch.entity.DispatchDraftContainer; import com.baiyue.lastleg.dispatch.mapper.DispatchCandidateMapper; +import com.baiyue.lastleg.dispatch.mapper.DispatchBolMapper; import com.baiyue.lastleg.dispatch.mapper.DispatchItemMapper; import com.baiyue.lastleg.dispatch.mapper.DispatchOrderMapper; import com.baiyue.lastleg.dispatch.mapper.DispatchPalletLockMapper; @@ -49,6 +50,7 @@ public class DispatchService { @Resource private DispatchOrderMapper orders; @Resource private DispatchItemMapper items; + @Resource private DispatchBolMapper bolLines; @Resource private DispatchPalletLockMapper locks; @Resource private DispatchDraftMapper drafts; @Resource private DispatchDraftContainerMapper draftContainers; @@ -429,7 +431,8 @@ public class DispatchService { public DispatchResponse detail(String customerId, String dispatchNo) { DispatchOrder dispatch = find(customerId, dispatchNo); - return response(dispatch, items.findByDispatchOrder(dispatch.getCustomerId(), dispatch.getId())); + return response(dispatch, items.findByDispatchOrder(dispatch.getCustomerId(), dispatch.getId()), + bolLines.findByDispatchOrder(dispatch.getCustomerId(), dispatch.getId())); } public DispatchResponse platformDetail(String dispatchNo) { @@ -437,7 +440,8 @@ public class DispatchService { if (dispatch == null) { throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Dispatch order not found"); } - return response(dispatch, items.findByDispatchOrder(dispatch.getCustomerId(), dispatch.getId())); + return response(dispatch, items.findByDispatchOrder(dispatch.getCustomerId(), dispatch.getId()), + bolLines.findByDispatchOrder(dispatch.getCustomerId(), dispatch.getId())); } @Transactional @@ -499,6 +503,11 @@ public class DispatchService { } private DispatchResponse response(DispatchOrder order, List itemList) { + return response(order, itemList, List.of()); + } + + private DispatchResponse response(DispatchOrder order, List itemList, + List bolLineList) { String orderNos = itemList.stream().flatMap(item -> splitOrderRefs(item.getOrderRefs(), item.getOrderNo()).stream()) .distinct().collect(Collectors.joining(",")); return new DispatchResponse(order.getId(), order.getDispatchNo(), order.getVehiclePlate(), order.getDriverName(), @@ -515,7 +524,8 @@ public class DispatchService { item.getWarehousePalletId(), item.getPalletNo(), item.getOverseasWarehouseId(), item.getOverseasWarehouseName(), item.getOrderNo(), item.getOrderRefs(), item.getInboundCode(), item.getDestinationWarehouseCode(), item.getDestinationWarehouseName(), item.getFbaWarehouseCode(), - Objects.requireNonNullElse(item.getPackageCount(), 0), item.getVolumeCbm(), item.getSourceStage())).toList()); + Objects.requireNonNullElse(item.getPackageCount(), 0), item.getVolumeCbm(), item.getSourceStage())).toList(), + bolLineList == null ? List.of() : bolLineList); } private static String route(List selected) { 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 ac1d64cd3..0989a3664 100644 --- a/lastleg-service/src/main/resources/openapi/overseas-business-v1.yaml +++ b/lastleg-service/src/main/resources/openapi/overseas-business-v1.yaml @@ -2251,6 +2251,10 @@ components: partialCompletionReason: { type: string, nullable: true } createdAt: { type: string, format: date-time } items: { type: array, items: { $ref: '#/components/schemas/DispatchItem' } } + bolLines: + type: array + description: 仅详情接口返回的BOL打印聚合行;分页接口返回空数组,避免列表查询放大 + items: { $ref: '#/components/schemas/DispatchBolLine' } DispatchItem: type: object properties: @@ -2269,6 +2273,17 @@ components: packageCount: { type: integer } volumeCbm: { type: number } sourceStage: { type: string, enum: [PLAN, RECEIVED] } + DispatchBolLine: + type: object + properties: + containerNo: { type: string, nullable: true } + palletNo: { type: string, nullable: true } + fbaWarehouseCode: { type: string, nullable: true } + destinationWarehouseName: { type: string, nullable: true } + warehouseNo: { type: string, nullable: true, description: 来源入仓码/仓库单号 } + fbaShipmentId: { type: string, nullable: true, description: 来源冻结货件编号;多值以逗号分隔 } + poReferenceNo: { type: string, nullable: true, description: 来源冻结FBA跟踪/参考号;多值以逗号分隔 } + packageCount: { type: integer, minimum: 0 } RelabelStatus: { type: string, enum: [PENDING_PROCESSING, PROCESSING, CUSTOMER_CONFIRM_PENDING, READY_FOR_OUTBOUND, COMPLETED, REJECTED, CANCELLED] } RelabelMerchantPageResponse: allOf: diff --git a/lastleg-service/src/test/java/com/baiyue/lastleg/dispatch/service/DispatchServiceTest.java b/lastleg-service/src/test/java/com/baiyue/lastleg/dispatch/service/DispatchServiceTest.java index aa328d90d..9dc7d7706 100644 --- a/lastleg-service/src/test/java/com/baiyue/lastleg/dispatch/service/DispatchServiceTest.java +++ b/lastleg-service/src/test/java/com/baiyue/lastleg/dispatch/service/DispatchServiceTest.java @@ -10,6 +10,7 @@ import com.baiyue.lastleg.dispatch.entity.DispatchItem; import com.baiyue.lastleg.dispatch.entity.DispatchOrder; import com.baiyue.lastleg.dispatch.entity.DispatchPalletLock; import com.baiyue.lastleg.dispatch.mapper.DispatchCandidateMapper; +import com.baiyue.lastleg.dispatch.mapper.DispatchBolMapper; import com.baiyue.lastleg.dispatch.mapper.DispatchDraftContainerMapper; import com.baiyue.lastleg.dispatch.mapper.DispatchDraftMapper; import com.baiyue.lastleg.dispatch.mapper.DispatchItemMapper; @@ -49,6 +50,7 @@ import static org.mockito.Mockito.when; class DispatchServiceTest { @Mock DispatchOrderMapper orders; @Mock DispatchItemMapper items; + @Mock DispatchBolMapper bolLines; @Mock DispatchPalletLockMapper locks; @Mock DispatchCandidateMapper candidates; @Mock DispatchDraftMapper drafts; @@ -62,6 +64,7 @@ class DispatchServiceTest { service = new DispatchService(); ReflectionTestUtils.setField(service, "orders", orders); ReflectionTestUtils.setField(service, "items", items); + ReflectionTestUtils.setField(service, "bolLines", bolLines); ReflectionTestUtils.setField(service, "locks", locks); ReflectionTestUtils.setField(service, "candidates", candidates); ReflectionTestUtils.setField(service, "drafts", drafts); @@ -70,6 +73,7 @@ class DispatchServiceTest { ReflectionTestUtils.setField(service, "tailOrders", tailOrders); ReflectionTestUtils.setField(service, "orderNoGenerator", new com.baiyue.lastleg.service.LastlegOrderNoGenerator()); lenient().when(items.findByDispatchOrder(any(), any())).thenReturn(List.of()); + lenient().when(bolLines.findByDispatchOrder(any(), any())).thenReturn(List.of()); lenient().when(tailOrders.selectList(any())).thenReturn(List.of()); } @@ -322,6 +326,7 @@ class DispatchServiceTest { service.detail("200", "PC1"); verify(items).findByDispatchOrder("200", 1L); + verify(bolLines).findByDispatchOrder("200", 1L); } @Test @@ -339,6 +344,7 @@ class DispatchServiceTest { assertEquals(2, result.total()); verify(items).findByDispatchOrder("100", 1L); verify(items).findByDispatchOrder("200", 2L); + verify(bolLines, never()).findByDispatchOrder(any(), any()); } @Test @@ -347,9 +353,15 @@ class DispatchServiceTest { dispatch.setId(1L); dispatch.setCustomerId("200"); dispatch.setDispatchNo("PC1"); when(orders.findGlobalByDispatchNo("PC1")).thenReturn(dispatch); - service.platformDetail("PC1"); + var expected = new DispatchResponse.BolLine("D2144", "D2144-112-1", "LBE1", "Amazon LBE1", + "NPHK2607030206", "FBA19HFHQCHB", "7UH3F1DW", 138); + when(bolLines.findByDispatchOrder("200", 1L)).thenReturn(List.of(expected)); + + var result = service.platformDetail("PC1"); verify(items).findByDispatchOrder("200", 1L); + verify(bolLines).findByDispatchOrder("200", 1L); + assertEquals(List.of(expected), result.bolLines()); } @Test