diff --git a/lastleg-service/src/main/java/com/baiyue/lastleg/inventory/mapper/InventoryBalanceMapper.java b/lastleg-service/src/main/java/com/baiyue/lastleg/inventory/mapper/InventoryBalanceMapper.java index 8026eecc2..7bad7d5e6 100644 --- a/lastleg-service/src/main/java/com/baiyue/lastleg/inventory/mapper/InventoryBalanceMapper.java +++ b/lastleg-service/src/main/java/com/baiyue/lastleg/inventory/mapper/InventoryBalanceMapper.java @@ -27,6 +27,12 @@ public interface InventoryBalanceMapper extends BaseMapper { WHERE c.customer_id=#{customerId} AND t.inbound_order_id=#{inboundOrderId} AND t.operating_warehouse_id=#{warehouseId} AND c.status='COUNTED' AND (c.carton_mark=#{cartonMark} OR c.customer_carton_mark=#{cartonMark}) + UNION ALL + SELECT 1 FROM ll_dropship_carton c + JOIN ll_order o ON o.id=c.order_id AND o.customer_id=c.customer_id + JOIN ll_inbound_order i ON i.customer_id=o.customer_id AND i.inbound_code=o.inbound_code + WHERE c.customer_id=#{customerId} AND i.id=#{inboundOrderId} + AND o.overseas_warehouse_id=#{warehouseId} AND c.carton_mark=#{cartonMark} ) """) boolean cartonBelongsToInbound(@Param("customerId") String customerId, diff --git a/lastleg-service/src/main/java/com/baiyue/lastleg/service/LastlegOrderService.java b/lastleg-service/src/main/java/com/baiyue/lastleg/service/LastlegOrderService.java index e1fbc7690..8b5b024d9 100644 --- a/lastleg-service/src/main/java/com/baiyue/lastleg/service/LastlegOrderService.java +++ b/lastleg-service/src/main/java/com/baiyue/lastleg/service/LastlegOrderService.java @@ -109,21 +109,26 @@ public class LastlegOrderService { if (query.sailingStage() == null && relabelNo == null) return aggregateAllPage(customerId, query); Page page = orderMapper.selectPage( new Page<>(query.page(), query.size()), filter(customerId, query, relabelNo).orderByDesc(LastlegOrder::getCreatedAt).orderByDesc(LastlegOrder::getId)); - Map> mergeRelations = palletMergeRelations(page.getRecords()); - returnOrderReferences.populateForRead(page.getRecords()); - refreshReturnVolumes(page.getRecords()); - Map containerNodes = containerNodes(page.getRecords()); - Map dispatchStatuses = dispatchStatuses(page.getRecords()); - Map weights = orderWeights(page.getRecords()); - Map> relabels = relabelSubOrders(page.getRecords()); - Map businessSources = businessSources(page.getRecords()); - var quantities = transferQuantities.forOrders(page.getRecords()); - return new PageResult<>(page.getRecords().stream().map(order -> summary(order, mergeRelations.get(order.getId()), + return new PageResult<>(nativeSummaries(page.getRecords()), + page.getCurrent(), page.getSize(), page.getTotal(), page.getPages()); + } + + /** 全部及已开船列表使用同一组业务事实,避免聚合列表丢失并托、排车和换标信息。 */ + private List nativeSummaries(List orders) { + Map> mergeRelations = palletMergeRelations(orders); + returnOrderReferences.populateForRead(orders); + refreshReturnVolumes(orders); + Map containerNodes = containerNodes(orders); + Map dispatchStatuses = dispatchStatuses(orders); + Map weights = orderWeights(orders); + Map> relabels = relabelSubOrders(orders); + Map businessSources = businessSources(orders); + var quantities = transferQuantities.forOrders(orders); + return orders.stream().map(order -> summary(order, mergeRelations.get(order.getId()), StringUtils.hasText(order.getSourceContainerBookingId()) ? containerNodes.get(order.getSourceContainerBookingId()) : null, dispatchStatuses.getOrDefault(order.getId(), "UNSCHEDULED"), weights.get(order.getId()), - relabels.getOrDefault(order.getId(), List.of()), businessSources.get(order.getId()), quantities.get(order.getId()))).toList(), - page.getCurrent(), page.getSize(), page.getTotal(), page.getPages()); + relabels.getOrDefault(order.getId(), List.of()), businessSources.get(order.getId()), quantities.get(order.getId()))).toList(); } /** 全部页签合并订单服务的未开船头程数据与本服务已有尾程单,尾程记录优先覆盖同一来源订单。 */ @@ -132,18 +137,14 @@ public class LastlegOrderService { if (source == null || source.data() == null) throw new ResponseStatusException(HttpStatus.SERVICE_UNAVAILABLE, "订单服务暂时不可用"); List existing = orderMapper.selectList(filter(customerId, query, null) .orderByDesc(LastlegOrder::getCreatedAt).orderByDesc(LastlegOrder::getId)); - Map existingNodes = containerNodes(existing); - Map existingWeights = orderWeights(existing); Map merged = new LinkedHashMap<>(); source.data().records().forEach(row -> { var summary = preDepartureSummary(row); merged.put(orderKey(summary.customerId(), summary.sourceOrderNo()), summary); }); - for (LastlegOrder order : existing) { - String key = orderKey(order.getCustomerId(), StringUtils.hasText(order.getSourceOrderNo()) ? order.getSourceOrderNo() : order.getOrderNo()); - merged.put(key, summary(order, List.of(), StringUtils.hasText(order.getSourceContainerBookingId()) - ? existingNodes.get(order.getSourceContainerBookingId()) : null, "UNSCHEDULED", - existingWeights.get(order.getId()), List.of(), null, null)); + for (LastlegOrderSummary order : nativeSummaries(existing)) { + String key = orderKey(order.customerId(), StringUtils.hasText(order.sourceOrderNo()) ? order.sourceOrderNo() : order.orderNo()); + merged.put(key, order); } List rows = merged.values().stream().sorted(java.util.Comparator.comparing(LastlegOrderSummary::createdAt, java.util.Comparator.nullsLast(java.util.Comparator.reverseOrder()))).toList(); diff --git a/lastleg-service/src/test/java/com/baiyue/lastleg/inventory/mapper/InventoryCartonOwnershipTest.java b/lastleg-service/src/test/java/com/baiyue/lastleg/inventory/mapper/InventoryCartonOwnershipTest.java index ae7a6470c..ccad7973f 100644 --- a/lastleg-service/src/test/java/com/baiyue/lastleg/inventory/mapper/InventoryCartonOwnershipTest.java +++ b/lastleg-service/src/test/java/com/baiyue/lastleg/inventory/mapper/InventoryCartonOwnershipTest.java @@ -16,6 +16,7 @@ class InventoryCartonOwnershipTest { var ds = new DriverManagerDataSource("jdbc:h2:mem:" + UUID.randomUUID() + ";MODE=MySQL;DB_CLOSE_DELAY=-1", "sa", ""); var db = new JdbcTemplate(ds); db.execute("CREATE TABLE ll_inbound_plan_carton(order_id BIGINT,customer_id VARCHAR,carton_mark VARCHAR)"); + db.execute("CREATE TABLE ll_dropship_carton(order_id BIGINT,customer_id VARCHAR,carton_mark VARCHAR)"); db.execute("CREATE TABLE ll_order(id BIGINT,customer_id VARCHAR,inbound_code VARCHAR,overseas_warehouse_id VARCHAR)"); db.execute("CREATE TABLE ll_inbound_order(id BIGINT,customer_id VARCHAR,inbound_code VARCHAR)"); db.execute("CREATE TABLE ll_warehouse_transfer_order(id BIGINT,customer_id VARCHAR,inbound_order_id BIGINT,operating_warehouse_id VARCHAR)"); @@ -23,19 +24,20 @@ class InventoryCartonOwnershipTest { db.update("INSERT INTO ll_inbound_order VALUES(1,'C1','IN1'),(2,'C1','IN2')"); db.update("INSERT INTO ll_order VALUES(10,'C1','IN1','WH1'),(20,'C1','IN2','WH1')"); db.update("INSERT INTO ll_inbound_plan_carton VALUES(10,'C1','BOX1'),(20,'C1','OTHER-ORDER')"); + db.update("INSERT INTO ll_dropship_carton VALUES(10,'C1','DROPSHIP-BOX'),(20,'C1','DROPSHIP-OTHER-ORDER'),(10,'C2','DROPSHIP-FOREIGN')"); db.update("INSERT INTO ll_warehouse_transfer_order VALUES(30,'C1',1,'WH1'),(40,'C2',1,'WH1')"); db.update("INSERT INTO ll_warehouse_transfer_carton VALUES(30,'C1','TRANSFER-BOX','CUSTOMER-BOX','COUNTED'),(30,'C1','UNCHECKED','CUSTOMER-UNCHECKED','NOT_RECEIVED'),(40,'C2','OTHER-CUSTOMER',NULL,'COUNTED')"); var config = new Configuration(new Environment("test", new JdbcTransactionFactory(), ds)); config.addMapper(InventoryBalanceMapper.class); try (var session = new SqlSessionFactoryBuilder().build(config).openSession()) { var mapper = session.getMapper(InventoryBalanceMapper.class); - for (String mark : new String[]{"BOX1", "TRANSFER-BOX", "CUSTOMER-BOX"}) { + for (String mark : new String[]{"BOX1", "TRANSFER-BOX", "CUSTOMER-BOX", "DROPSHIP-BOX"}) { assertTrue(mapper.cartonBelongsToInbound("C1", "WH1", 1L, mark)); assertFalse(mapper.cartonBelongsToInbound("C1", "WH2", 1L, mark)); assertFalse(mapper.cartonBelongsToInbound("C2", "WH1", 1L, mark)); assertFalse(mapper.cartonBelongsToInbound("C1", "WH1", 2L, mark)); } - for (String mark : new String[]{"MISSING", "OTHER-ORDER", "OTHER-CUSTOMER", "UNCHECKED"}) + for (String mark : new String[]{"MISSING", "OTHER-ORDER", "OTHER-CUSTOMER", "UNCHECKED", "DROPSHIP-OTHER-ORDER", "DROPSHIP-FOREIGN"}) assertFalse(mapper.cartonBelongsToInbound("C1", "WH1", 1L, mark)); } } diff --git a/lastleg-service/src/test/java/com/baiyue/lastleg/service/LastlegOrderServiceTest.java b/lastleg-service/src/test/java/com/baiyue/lastleg/service/LastlegOrderServiceTest.java index 7cd7faa73..a07004054 100644 --- a/lastleg-service/src/test/java/com/baiyue/lastleg/service/LastlegOrderServiceTest.java +++ b/lastleg-service/src/test/java/com/baiyue/lastleg/service/LastlegOrderServiceTest.java @@ -1,6 +1,9 @@ package com.baiyue.lastleg.service; import com.baiyue.lastleg.dto.LastlegOrderRequests; +import com.baiyue.lastleg.client.OrderPreDepartureClient; +import com.baiyue.common.core.api.ApiResponse; +import com.baiyue.common.core.api.PageResult; import com.baiyue.lastleg.dto.LastlegOrderSummary; import com.baiyue.lastleg.dto.ContainerPlanProgressDetail; import com.baiyue.lastleg.dto.ContainerPlanProgressSummary; @@ -74,6 +77,7 @@ class LastlegOrderServiceTest { @Mock ContainerArrivalTimeOperationMapper containerArrivalTimeOperations; @Mock WarehouseResourceGateway warehouseResourceGateway; @Mock ContainerShippingGateMapper containerShippingGates; + @Mock OrderPreDepartureClient preDeparture; @Mock ReturnOrderReferenceResolver returnOrderReferences; @Mock com.baiyue.lastleg.returnreceipt.service.ReturnReceiptService returnReceipts; LastlegOrderService service; @@ -137,6 +141,9 @@ class LastlegOrderServiceTest { ReflectionTestUtils.setField(service, "containerArrivalTimeOperations", containerArrivalTimeOperations); ReflectionTestUtils.setField(service, "warehouseResourceGateway", warehouseResourceGateway); ReflectionTestUtils.setField(service, "containerShippingGates", containerShippingGates); + ReflectionTestUtils.setField(service, "orderPreDepartureClient", preDeparture); + lenient().when(preDeparture.page(any(), any(), any(), any(), anyInt(), anyInt())) + .thenReturn(ApiResponse.success(new PageResult<>(List.of(), 1, 2000, 0, 0))); } @Test @@ -401,7 +408,8 @@ class LastlegOrderServiceTest { @Test void pageUsesPaginationAndPlatformFiltersWithoutCustomerScope() { var query = new LastlegOrderRequests.Query(3L, 25L, "LL-", "FIRST_LEG", "IN-", null, - null, "", "PENDING_ASSIGNMENT", null, "LAX", null, null, null, null, null, null, null, null, null); + null, "", "PENDING_ASSIGNMENT", null, "LAX", null, null, null, null, null, + LastlegOrderRequests.SailingStage.AFTER_DEPARTURE, null, null, null); var resultPage = new com.baomidou.mybatisplus.extension.plugins.pagination.Page(3, 25); resultPage.setTotal(0); when(orders.selectPage(any(), any())).thenReturn(resultPage); @@ -553,7 +561,7 @@ class LastlegOrderServiceTest { var resultPage = new com.baomidou.mybatisplus.extension.plugins.pagination.Page(1, 10); resultPage.setRecords(List.of(order)); resultPage.setTotal(1); - when(orders.selectPage(any(), any())).thenReturn(resultPage); + when(orders.selectList(any())).thenReturn(resultPage.getRecords()); when(orders.findPalletMergeRelations(List.of(11L))).thenReturn(List.of( new LastlegOrderMapper.PalletMergeRelationRow(11L, "INBOUND-2", "PMG-1"), new LastlegOrderMapper.PalletMergeRelationRow(11L, "INBOUND-3", "PMG-1"))); @@ -580,7 +588,7 @@ class LastlegOrderServiceTest { var resultPage = new com.baomidou.mybatisplus.extension.plugins.pagination.Page(1, 10); resultPage.setRecords(List.of(relabel, looseboard, firstleg)); resultPage.setTotal(3); - when(orders.selectPage(any(), any())).thenReturn(resultPage); + when(orders.selectList(any())).thenReturn(resultPage.getRecords()); var query = new LastlegOrderRequests.Query(1L, 10L, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null); @@ -611,14 +619,14 @@ class LastlegOrderServiceTest { row.setOverseasWarehouseName("洛杉矶仓"); resultPage.setRecords(matched ? List.of(row) : List.of()); resultPage.setTotal(matched ? 1 : 0); - when(orders.selectPage(any(), any())).thenReturn(resultPage); + when(orders.selectList(any())).thenReturn(resultPage.getRecords()); var result = service.page(null, new LastlegOrderRequests.Query(1L, 10L, null, null, null, null, null, null, null, null, input, null, null, null, null, null, null, null, null, null)); ArgumentCaptor> filter = ArgumentCaptor.forClass(com.baomidou.mybatisplus.core.conditions.Wrapper.class); - verify(orders).selectPage(any(), filter.capture()); + verify(orders).selectList(filter.capture()); var wrapper = (com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper) filter.getValue(); String warehouseSql = wrapper.getExpression().getNormal().getSqlSegment(); assertTrue(warehouseSql.contains("LOWER(TRIM(overseas_warehouse_code))"));