diff --git a/firstleg/src/main/java/com/baiyue/firstleg/loading/coload/model/ColoadGroupModels.java b/firstleg/src/main/java/com/baiyue/firstleg/loading/coload/model/ColoadGroupModels.java index e3f9a74d7..095379d89 100644 --- a/firstleg/src/main/java/com/baiyue/firstleg/loading/coload/model/ColoadGroupModels.java +++ b/firstleg/src/main/java/com/baiyue/firstleg/loading/coload/model/ColoadGroupModels.java @@ -34,6 +34,7 @@ public final class ColoadGroupModels { long tenantId, long orderId, long inboundId, + String inboundCode, int fullPackageCount ) { } diff --git a/firstleg/src/main/java/com/baiyue/firstleg/loading/coload/persistence/ColoadGroupMapper.java b/firstleg/src/main/java/com/baiyue/firstleg/loading/coload/persistence/ColoadGroupMapper.java index bd5e51ecc..05ba5ffdf 100644 --- a/firstleg/src/main/java/com/baiyue/firstleg/loading/coload/persistence/ColoadGroupMapper.java +++ b/firstleg/src/main/java/com/baiyue/firstleg/loading/coload/persistence/ColoadGroupMapper.java @@ -66,9 +66,15 @@ public interface ColoadGroupMapper { + "FROM fl_coload_group WHERE id=#{groupId} FOR UPDATE") GroupRow lockGroup(@Param("groupId") long groupId); - @Select("SELECT tenant_id tenantId,order_id orderId,inbound_id inboundId," - + "full_package_count fullPackageCount FROM fl_coload_group_member " - + "WHERE group_id=#{groupId} ORDER BY order_id,inbound_id") + @Select(""" + SELECT member.tenant_id tenantId,member.order_id orderId,member.inbound_id inboundId, + inbound.inbound_code inboundCode,member.full_package_count fullPackageCount + FROM fl_coload_group_member member + LEFT JOIN fl_inbound_order inbound + ON inbound.tenant_id=member.tenant_id AND inbound.id=member.inbound_id AND inbound.deleted=0 + WHERE member.group_id=#{groupId} + ORDER BY member.order_id,member.inbound_id + """) List members(@Param("groupId") long groupId); @Select(""" @@ -98,13 +104,12 @@ public interface ColoadGroupMapper { List groupsByInboundCode(@Param("inboundCode") String inboundCode); @Select(""" - SELECT DISTINCT inbound.inbound_code inboundCode + SELECT member.id memberId,member.inbound_id inboundId,inbound.inbound_code inboundCode FROM fl_coload_group_member member - JOIN fl_inbound_order inbound - ON inbound.tenant_id=member.tenant_id AND inbound.id=member.inbound_id - WHERE member.group_id=#{groupId} AND inbound.deleted=0 - AND inbound.inbound_code IS NOT NULL AND TRIM(inbound.inbound_code)<>'' - ORDER BY inbound.inbound_code + LEFT JOIN fl_inbound_order inbound + ON inbound.tenant_id=member.tenant_id AND inbound.id=member.inbound_id AND inbound.deleted=0 + WHERE member.group_id=#{groupId} + ORDER BY member.id """) List effectiveMemberCodes(@Param("groupId") long groupId); diff --git a/firstleg/src/main/java/com/baiyue/firstleg/loading/coload/persistence/ColoadPersistenceRows.java b/firstleg/src/main/java/com/baiyue/firstleg/loading/coload/persistence/ColoadPersistenceRows.java index b515c4744..ddd017b36 100644 --- a/firstleg/src/main/java/com/baiyue/firstleg/loading/coload/persistence/ColoadPersistenceRows.java +++ b/firstleg/src/main/java/com/baiyue/firstleg/loading/coload/persistence/ColoadPersistenceRows.java @@ -44,6 +44,7 @@ public final class ColoadPersistenceRows { private Long tenantId; private Long orderId; private Long inboundId; + private String inboundCode; private Integer fullPackageCount; } @@ -57,6 +58,8 @@ public final class ColoadPersistenceRows { @Getter @Setter public static class MemberCodeRow { + private Long memberId; + private Long inboundId; private String inboundCode; } diff --git a/firstleg/src/main/java/com/baiyue/firstleg/loading/coload/service/ColoadGroupService.java b/firstleg/src/main/java/com/baiyue/firstleg/loading/coload/service/ColoadGroupService.java index cee95cab3..6fd09103a 100644 --- a/firstleg/src/main/java/com/baiyue/firstleg/loading/coload/service/ColoadGroupService.java +++ b/firstleg/src/main/java/com/baiyue/firstleg/loading/coload/service/ColoadGroupService.java @@ -104,14 +104,17 @@ public class ColoadGroupService implements ColoadGroupAssignmentPort { if (distinctGroups > 1) throw conflict("入仓码关联多个有效同柜不可拆组"); long groupId = groups.get(0).getGroupId(); String status = groups.get(0).getGroupStatus(); - List members = mapper.effectiveMemberCodes(groupId).stream() - .map(row -> trim(row.getInboundCode())) - .filter(Objects::nonNull) - .distinct() - .sorted() - .map(BusinessMember::new) - .toList(); - if (members.isEmpty()) throw conflict("同柜不可拆组不存在有效入仓片段"); + var memberRows = mapper.effectiveMemberCodes(groupId); + if (memberRows.isEmpty()) throw conflict("同柜不可拆组不存在有效入仓片段"); + if (memberRows.stream().anyMatch(row -> row.getMemberId() == null || row.getInboundId() == null + || trim(row.getInboundCode()) == null)) { + throw conflict("同柜不可拆组存在缺失或无效的入仓片段业务号"); + } + List inboundCodes = memberRows.stream().map(row -> trim(row.getInboundCode())).toList(); + if (inboundCodes.stream().distinct().count() != inboundCodes.size()) { + throw conflict("同柜不可拆组存在重复入仓片段业务号"); + } + List members = inboundCodes.stream().sorted().map(BusinessMember::new).toList(); return new BusinessSummary(status, members.size(), members); } @@ -271,9 +274,20 @@ public class ColoadGroupService implements ColoadGroupAssignmentPort { } private GroupSnapshot snapshot(GroupRow row) { - List members = mapper.members(row.getId()).stream() + var memberRows = mapper.members(row.getId()); + if (memberRows.isEmpty() || memberRows.stream().anyMatch(value -> value.getTenantId() == null + || value.getOrderId() == null || value.getInboundId() == null + || trim(value.getInboundCode()) == null || value.getFullPackageCount() == null + || value.getFullPackageCount() <= 0)) { + throw conflict("同柜不可拆组存在缺失或无效的冻结成员业务事实"); + } + List codes = memberRows.stream().map(value -> trim(value.getInboundCode())).toList(); + if (codes.stream().distinct().count() != codes.size()) { + throw conflict("同柜不可拆组存在重复入仓片段业务号"); + } + List members = memberRows.stream() .map(value -> new Member(value.getTenantId(), value.getOrderId(), value.getInboundId(), - value.getFullPackageCount())) + trim(value.getInboundCode()), value.getFullPackageCount())) .toList(); return new GroupSnapshot(row.getId(), row.getGroupNo(), row.getGroupStatus(), row.getWarehouseId(), row.getChannelCode(), row.getLockedPlanId(), row.getVersion(), members, diff --git a/firstleg/src/main/resources/openapi/coload-groups-v1.yaml b/firstleg/src/main/resources/openapi/coload-groups-v1.yaml index e763a19ff..ef6ebc0a3 100644 --- a/firstleg/src/main/resources/openapi/coload-groups-v1.yaml +++ b/firstleg/src/main/resources/openapi/coload-groups-v1.yaml @@ -40,7 +40,8 @@ paths: summary: 按入仓码查询同柜组业务摘要 description: >- 需要 platform:firstleg:smart-loading:list。使用任一有效成员的全局唯一 inboundCode 查询; - 仅返回组业务状态、有效成员数和去重后的全部成员入仓码。页面不持有或展示 groupId、groupNo、orderId。 + 仅返回组业务状态、有效成员数和全部唯一成员入仓码。任一冻结成员缺少有效 inboundCode 时失败关闭; + 页面不持有或展示 groupId、groupNo、orderId,也不得从技术ID或订单号推导入仓码。 parameters: - name: inboundCode in: path @@ -107,11 +108,12 @@ components: ColoadGroupMember: type: object additionalProperties: false - required: [tenantId, orderId, inboundId, fullPackageCount] + required: [tenantId, orderId, inboundId, inboundCode, fullPackageCount] properties: tenantId: {type: string, pattern: '^[1-9][0-9]*$'} orderId: {type: string, pattern: '^[1-9][0-9]*$'} inboundId: {type: string, pattern: '^[1-9][0-9]*$'} + inboundCode: {type: string, minLength: 1, maxLength: 40, description: 冻结成员的全局唯一入仓码,禁止由技术ID推导} fullPackageCount: {type: integer, minimum: 1} ColoadGroup: type: object diff --git a/firstleg/src/test/java/com/baiyue/firstleg/loading/coload/ColoadGroupOpenApiContractTest.java b/firstleg/src/test/java/com/baiyue/firstleg/loading/coload/ColoadGroupOpenApiContractTest.java index 74c8aa868..3312539cc 100644 --- a/firstleg/src/test/java/com/baiyue/firstleg/loading/coload/ColoadGroupOpenApiContractTest.java +++ b/firstleg/src/test/java/com/baiyue/firstleg/loading/coload/ColoadGroupOpenApiContractTest.java @@ -39,6 +39,7 @@ class ColoadGroupOpenApiContractTest { .contains("fullPackageCount") .contains("platform:firstleg:smart-loading:assign") .contains("platform:firstleg:smart-loading:list") + .contains("任一冻结成员缺少有效 inboundCode 时失败关闭") .contains("全部 WAIT_SPLIT") .contains("国内仓和渠道一致") .doesNotContain("destinationType") diff --git a/firstleg/src/test/java/com/baiyue/firstleg/loading/coload/ColoadGroupServiceTest.java b/firstleg/src/test/java/com/baiyue/firstleg/loading/coload/ColoadGroupServiceTest.java index 635f9e484..aa9e63e6b 100644 --- a/firstleg/src/test/java/com/baiyue/firstleg/loading/coload/ColoadGroupServiceTest.java +++ b/firstleg/src/test/java/com/baiyue/firstleg/loading/coload/ColoadGroupServiceTest.java @@ -39,7 +39,8 @@ class ColoadGroupServiceTest { @Test void readsCrossCustomerTwoMemberGroupByEitherInboundCodeWithoutInternalIdentifiers() { when(mapper.groupsByInboundCode("IN-A")).thenReturn(List.of(lookup(500L, "ACTIVE"))); - when(mapper.effectiveMemberCodes(500L)).thenReturn(List.of(code("IN-A"), code("IN-B"))); + when(mapper.effectiveMemberCodes(500L)).thenReturn(List.of( + code(1L, 1001L, "IN-A"), code(2L, 1002L, "IN-B"))); var result = service.queryByInboundCode(" IN-A "); @@ -50,10 +51,11 @@ class ColoadGroupServiceTest { } @Test - void returnsEveryEffectiveSplitFragmentAndEliminatesDuplicateInboundCodes() { + void returnsEveryEffectiveSplitFragmentWithItsUniqueInboundCode() { when(mapper.groupsByInboundCode("MASTER-A-2")).thenReturn(List.of(lookup(500L, "LOCKED"))); when(mapper.effectiveMemberCodes(500L)).thenReturn(List.of( - code("MASTER-A-3"), code("MASTER-A-2"), code("MASTER-A-2"), code("ORDER-B"))); + code(1L, 1001L, "MASTER-A-3"), code(2L, 1002L, "MASTER-A-2"), + code(3L, 1003L, "ORDER-B"))); var result = service.queryByInboundCode("MASTER-A-2"); @@ -66,7 +68,8 @@ class ColoadGroupServiceTest { @Test void preservesConsumedStatusWhileReadingClosedFrozenMemberships() { when(mapper.groupsByInboundCode("IN-A")).thenReturn(List.of(lookup(500L, "CONSUMED"))); - when(mapper.effectiveMemberCodes(500L)).thenReturn(List.of(code("IN-A"), code("IN-B"))); + when(mapper.effectiveMemberCodes(500L)).thenReturn(List.of( + code(1L, 1001L, "IN-A"), code(2L, 1002L, "IN-B"))); assertThat(service.queryByInboundCode("IN-A").status()).isEqualTo("CONSUMED"); } @@ -84,6 +87,21 @@ class ColoadGroupServiceTest { .isInstanceOf(BizException.class).hasMessageContaining("多个有效"); } + @Test + void failsClosedInsteadOfReturningMissingOrDuplicateMemberInboundCode() { + when(mapper.groupsByInboundCode("BROKEN")).thenReturn(List.of(lookup(500L, "ACTIVE"))); + when(mapper.effectiveMemberCodes(500L)).thenReturn(List.of( + code(1L, 1001L, "IN-A"), code(2L, 1002L, " "))); + when(mapper.groupsByInboundCode("DUPLICATE")).thenReturn(List.of(lookup(501L, "LOCKED"))); + when(mapper.effectiveMemberCodes(501L)).thenReturn(List.of( + code(3L, 1003L, "IN-C"), code(4L, 1004L, "IN-C"))); + + assertThatThrownBy(() -> service.queryByInboundCode("BROKEN")) + .isInstanceOf(BizException.class).hasMessageContaining("缺失或无效"); + assertThatThrownBy(() -> service.queryByInboundCode("DUPLICATE")) + .isInstanceOf(BizException.class).hasMessageContaining("重复"); + } + @Test void internalOrderAggregationKeepsTechnicalGroupSnapshotOffPlatformContract() { when(mapper.linksByOrderIds(List.of(11L, 12L))).thenReturn(List.of( @@ -273,6 +291,7 @@ class ColoadGroupServiceTest { private static MemberRow member(long tenantId, long orderId, long inboundId, int packages) { MemberRow value = new MemberRow(); value.setTenantId(tenantId); value.setOrderId(orderId); value.setInboundId(inboundId); + value.setInboundCode("IN-" + inboundId); value.setFullPackageCount(packages); return value; } @@ -284,8 +303,10 @@ class ColoadGroupServiceTest { return value; } - private static MemberCodeRow code(String inboundCode) { + private static MemberCodeRow code(long memberId, long inboundId, String inboundCode) { MemberCodeRow value = new MemberCodeRow(); + value.setMemberId(memberId); + value.setInboundId(inboundId); value.setInboundCode(inboundCode); return value; } diff --git a/firstleg/src/test/java/com/baiyue/firstleg/loading/coload/ColoadGroupSqlContractTest.java b/firstleg/src/test/java/com/baiyue/firstleg/loading/coload/ColoadGroupSqlContractTest.java index e226daf44..2ccb20f25 100644 --- a/firstleg/src/test/java/com/baiyue/firstleg/loading/coload/ColoadGroupSqlContractTest.java +++ b/firstleg/src/test/java/com/baiyue/firstleg/loading/coload/ColoadGroupSqlContractTest.java @@ -69,7 +69,8 @@ class ColoadGroupSqlContractTest { .contains("'ACTIVE','LOCKED','CONSUMED'") .doesNotContain("group_no", "order_id=#{"); assertThat(memberSql) - .contains("SELECT DISTINCT inbound.inbound_code inboundCode") + .contains("member.id memberId", "member.inbound_id inboundId", "inbound.inbound_code inboundCode") + .contains("LEFT JOIN fl_inbound_order inbound") .contains("member.group_id=#{groupId}") .contains("inbound.deleted=0") .doesNotContain("member.active_flag=1", "inbound_role", "split_status", "split_purpose"); diff --git a/firstleg/src/test/java/com/baiyue/firstleg/service/LoadingPickServiceTest.java b/firstleg/src/test/java/com/baiyue/firstleg/service/LoadingPickServiceTest.java index 5868a702a..cc478d53f 100644 --- a/firstleg/src/test/java/com/baiyue/firstleg/service/LoadingPickServiceTest.java +++ b/firstleg/src/test/java/com/baiyue/firstleg/service/LoadingPickServiceTest.java @@ -822,7 +822,7 @@ class LoadingPickServiceTest { complete.setPickedPackageCount(5); complete.setItemStatus("PICKED"); GroupSnapshot group = coloadGroup("LOCKED", 10L, - new Member(101L, 301L, 50L, 5), new Member(101L, 301L, 60L, 5)); + new Member(101L, 301L, 50L, "IN-50", 5), new Member(101L, 301L, 60L, "IN-60", 5)); when(repository.taskForUpdate(20L)).thenReturn(task); when(repository.allTaskItemsResolved(20L)).thenReturn(true); when(repository.inboundOwners(20L)).thenReturn(List.of( @@ -883,8 +883,8 @@ class LoadingPickServiceTest { when(repository.completeAccepted(20L, 9L, "operator")).thenReturn(1); when(completionCommands.complete(903L, "worker-multi")).thenReturn(true); GroupSnapshot group = coloadGroup("LOCKED", 10L, - new Member(101L, 301L, 50L, 1), new Member(101L, 302L, 60L, 1), - new Member(202L, 303L, 70L, 1), new Member(202L, 304L, 80L, 1)); + new Member(101L, 301L, 50L, "IN-50", 1), new Member(101L, 302L, 60L, "IN-60", 1), + new Member(202L, 303L, 70L, "IN-70", 1), new Member(202L, 304L, 80L, "IN-80", 1)); when(coloadGroups.findByInbound(anyLong(), anyLong())).thenReturn(group); service.processCompletion(completionCommand(903L, "async-multi"), "worker-multi"); diff --git a/firstleg/src/test/java/com/baiyue/firstleg/service/SmartLoadingServiceTest.java b/firstleg/src/test/java/com/baiyue/firstleg/service/SmartLoadingServiceTest.java index cf79048b9..1f7802e51 100644 --- a/firstleg/src/test/java/com/baiyue/firstleg/service/SmartLoadingServiceTest.java +++ b/firstleg/src/test/java/com/baiyue/firstleg/service/SmartLoadingServiceTest.java @@ -144,7 +144,7 @@ class SmartLoadingServiceTest { Candidate first = candidate(9L, 10L, 20L, 30L, 4); Candidate second = candidate(19L, 11L, 21L, 31L, 6); GroupSnapshot group = group("ACTIVE", null, - new Member(9L, 30L, 10L, 4), new Member(19L, 31L, 11L, 6)); + new Member(9L, 30L, 10L, "IN-10", 4), new Member(19L, 31L, 11L, "IN-11", 6)); when(repository.booking(99L)).thenReturn(booking()); when(repository.candidates(100L)).thenReturn(List.of(first, second)); when(coloadGroups.findByInbound(9L, 10L)).thenReturn(group); @@ -166,7 +166,7 @@ class SmartLoadingServiceTest { void rejectsIndividualAssignmentForColoadMemberWithoutWriting() { stubAssignment(); GroupSnapshot group = group("ACTIVE", null, - new Member(9L, 30L, 10L, 10), new Member(19L, 31L, 11L, 5)); + new Member(9L, 30L, 10L, "IN-10", 10), new Member(19L, 31L, 11L, "IN-11", 5)); when(coloadGroups.findByInbound(9L, 10L)).thenReturn(group); assertThatThrownBy(() -> service.assign(1L, @@ -183,9 +183,9 @@ class SmartLoadingServiceTest { Candidate first = candidate(9L, 10L, 20L, 30L, 4); Candidate second = candidate(9L, 11L, 21L, 30L, 6, "FBA2"); GroupSnapshot active = group("ACTIVE", null, - new Member(9L, 30L, 10L, 4), new Member(9L, 30L, 11L, 6)); + new Member(9L, 30L, 10L, "IN-10", 4), new Member(9L, 30L, 11L, "IN-11", 6)); GroupSnapshot locked = group("LOCKED", 1L, - new Member(9L, 30L, 10L, 4), new Member(9L, 30L, 11L, 6)); + new Member(9L, 30L, 10L, "IN-10", 4), new Member(9L, 30L, 11L, "IN-11", 6)); AtomicInteger version = new AtomicInteger(); List saved = new ArrayList<>(); when(repository.plan(1L)).thenAnswer(invocation -> plan("EDITING", version.get())); @@ -242,8 +242,8 @@ class SmartLoadingServiceTest { Candidate second = candidate(19L, 11L, 21L, 31L, 5); Candidate third = candidate(29L, 12L, 22L, 32L, 5); GroupSnapshot group = group("ACTIVE", null, - new Member(9L, 30L, 10L, 5), new Member(19L, 31L, 11L, 5), - new Member(29L, 32L, 12L, 5)); + new Member(9L, 30L, 10L, "IN-10", 5), new Member(19L, 31L, 11L, "IN-11", 5), + new Member(29L, 32L, 12L, "IN-12", 5)); ContainerBookingEntity small = booking(); small.setCapacityCbm(new BigDecimal("5")); LoadingPlanEntity plan = plan("EDITING", 0); @@ -269,7 +269,7 @@ class SmartLoadingServiceTest { Candidate groupSecond = candidate(9L, 12L, 22L, 32L, 4); Candidate later = candidate(9L, 13L, 23L, 33L, 1); GroupSnapshot group = group("ACTIVE", null, - new Member(9L, 31L, 11L, 4), new Member(9L, 32L, 12L, 4)); + new Member(9L, 31L, 11L, "IN-11", 4), new Member(9L, 32L, 12L, "IN-12", 4)); ContainerBookingEntity small = booking(); small.setCapacityCbm(new BigDecimal("5")); AtomicInteger version = new AtomicInteger(); @@ -321,7 +321,7 @@ class SmartLoadingServiceTest { Candidate first = candidate(9L, 11L, 21L, 31L, 4); Candidate second = candidate(9L, 12L, 22L, 32L, 4); GroupSnapshot group = group("ACTIVE", null, - new Member(9L, 31L, 11L, 4), new Member(9L, 32L, 12L, 4)); + new Member(9L, 31L, 11L, "IN-11", 4), new Member(9L, 32L, 12L, "IN-12", 4)); ContainerBookingEntity small = booking(); small.setCapacityCbm(new BigDecimal("3")); when(repository.plan(1L)).thenReturn(plan("EDITING", 0)); @@ -348,7 +348,7 @@ class SmartLoadingServiceTest { LoadingPlanEntity plan = plan("EDITING", 0); LoadingPlanItemEntity item = item(8L, 9L, 20L, 4); GroupSnapshot group = group("LOCKED", 1L, - new Member(9L, 30L, 10L, 4), new Member(19L, 31L, 11L, 6)); + new Member(9L, 30L, 10L, "IN-10", 4), new Member(19L, 31L, 11L, "IN-11", 6)); when(repository.plan(1L)).thenReturn(plan); when(repository.item(1L, 8L)).thenReturn(item); when(coloadGroups.findByInbound(9L, 10L)).thenReturn(group); @@ -370,7 +370,7 @@ class SmartLoadingServiceTest { LoadingPlanEntity plan = plan("EDITING", 0); LoadingPlanItemEntity first = item(8L, 9L, 20L, 4); GroupSnapshot group = group("LOCKED", 1L, - new Member(9L, 30L, 10L, 4), new Member(19L, 31L, 11L, 6)); + new Member(9L, 30L, 10L, "IN-10", 4), new Member(19L, 31L, 11L, "IN-11", 6)); when(repository.plan(1L)).thenReturn(plan); when(repository.booking(99L)).thenReturn(booking()); when(repository.items(1L)).thenReturn(List.of(first)); @@ -396,7 +396,7 @@ class SmartLoadingServiceTest { LoadingPlanItemEntity second = item(9L, 19L, 21L, 6); second.setInboundId(11L); GroupSnapshot group = group("LOCKED", 1L, - new Member(9L, 30L, 10L, 4), new Member(19L, 31L, 11L, 6)); + new Member(9L, 30L, 10L, "IN-10", 4), new Member(19L, 31L, 11L, "IN-11", 6)); when(repository.plan(1L)).thenReturn(plan, after); when(repository.booking(99L)).thenReturn(booking()); when(repository.items(1L)).thenReturn(List.of(first, second), List.of()); @@ -407,7 +407,7 @@ class SmartLoadingServiceTest { when(coloadGroups.findByInbound(9L, 10L)).thenReturn(group); when(coloadGroups.findByInbound(19L, 11L)).thenReturn(group); GroupSnapshot unlocked = group("ACTIVE", null, - new Member(9L, 30L, 10L, 4), new Member(19L, 31L, 11L, 6)); + new Member(9L, 30L, 10L, "IN-10", 4), new Member(19L, 31L, 11L, "IN-11", 6)); when(coloadGroups.unlockWholeGroupAfterRemoval(eq(700L), eq(1L), anyString(), eq(7L), eq("u"))).thenReturn(unlocked); diff --git a/order/src/test/java/com/baiyue/order/service/UnifiedOrderQueryServiceTest.java b/order/src/test/java/com/baiyue/order/service/UnifiedOrderQueryServiceTest.java index 734870d94..a3ef21449 100644 --- a/order/src/test/java/com/baiyue/order/service/UnifiedOrderQueryServiceTest.java +++ b/order/src/test/java/com/baiyue/order/service/UnifiedOrderQueryServiceTest.java @@ -304,6 +304,31 @@ class UnifiedOrderQueryServiceTest { verify(orders, never()).findByIds(eq(null), any()); } + @Test + void platformPageUsesOneInternalBatchForTwentyRowsAndKeepsMissingGroupsNull() { + UnifiedOrderQuery query = query("PENDING_REVIEW"); + List pageOrders = IntStream.rangeClosed(1, 20).mapToObj(index -> { + OrderEntity order = order(OrderStatus.SUBMITTED); + order.setId((long) index); + order.setOrderNo("FL-" + index); + order.setInboundCode("RK-" + index); + return order; + }).toList(); + when(orders.unifiedPage(eq(10001L), eq(query), eq(List.of(OrderStatus.SUBMITTED)))) + .thenReturn(new PageResult<>(pageOrders, 1, 20, 20, 1)); + when(coloadGroups.batchQuery(eq("internal-token"), any())) + .thenReturn(ApiResponse.success(List.of())); + + var result = service.platformPage(10001L, query); + + assertThat(result.records()).hasSize(20).allSatisfy(row -> assertThat(row.coLoadGroup()).isNull()); + ArgumentCaptor request = + ArgumentCaptor.forClass(FirstlegColoadGroupClient.BatchQueryRequest.class); + verify(coloadGroups).batchQuery(eq("internal-token"), request.capture()); + assertThat(request.getValue().orderIds()).containsExactlyElementsOf( + pageOrders.stream().map(OrderEntity::getId).toList()); + } + @Test void platformDetailIncludesColoadBusinessSummary() { OrderEntity order = order(OrderStatus.APPROVED);