From f4901d155c0fb4ce962b0aa193b4d23363389a2c Mon Sep 17 00:00:00 2001 From: ouyangxq <775153912@qq.com> Date: Fri, 6 Nov 2026 20:13:41 +0800 Subject: [PATCH] fix: unify receiving discrepancy confirmation --- .../dto/InboundReceivingReconciliation.java | 4 +- .../openapi/inbound-reconciliation-v1.yaml | 4 +- ...undReceivingReconciliationRequestTest.java | 51 +++++++++++++++++++ 3 files changed, 55 insertions(+), 4 deletions(-) create mode 100644 lastleg-service/src/test/java/com/baiyue/lastleg/inboundplan/pda/service/InboundReceivingReconciliationRequestTest.java diff --git a/lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/dto/InboundReceivingReconciliation.java b/lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/dto/InboundReceivingReconciliation.java index 4a0b7b1db..be4c70b11 100644 --- a/lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/dto/InboundReceivingReconciliation.java +++ b/lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/dto/InboundReceivingReconciliation.java @@ -26,8 +26,8 @@ public final class InboundReceivingReconciliation { public record Confirm(@NotBlank String customerId, @NotBlank String snapshotHash, @NotBlank @Size(max = 200) String reason, - @NotNull @Size(max = 1000) List<@NotNull @Valid Count> pallets, - @NotNull @Size(max = 10000) List<@NotNull @Valid Quantity> receipts) { } + @NotNull List<@NotNull @Valid Count> pallets, + @NotNull List<@NotNull @Valid Quantity> receipts) { } public record Count(@NotNull Long palletId, @NotNull @Min(0) Integer countedPackageCount) { } diff --git a/lastleg-service/src/main/resources/openapi/inbound-reconciliation-v1.yaml b/lastleg-service/src/main/resources/openapi/inbound-reconciliation-v1.yaml index 83a5ac68b..86ac1f88d 100644 --- a/lastleg-service/src/main/resources/openapi/inbound-reconciliation-v1.yaml +++ b/lastleg-service/src/main/resources/openapi/inbound-reconciliation-v1.yaml @@ -105,8 +105,8 @@ components: customerId: { type: string } snapshotHash: { type: string } reason: { type: string, minLength: 1, maxLength: 200 } - pallets: { type: array, maxItems: 1000, items: { $ref: '#/components/schemas/Count' } } - receipts: { type: array, maxItems: 10000, items: { $ref: '#/components/schemas/Quantity' } } + pallets: { type: array, items: { $ref: '#/components/schemas/Count' } } + receipts: { type: array, items: { $ref: '#/components/schemas/Quantity' } } Count: type: object required: [palletId, countedPackageCount] diff --git a/lastleg-service/src/test/java/com/baiyue/lastleg/inboundplan/pda/service/InboundReceivingReconciliationRequestTest.java b/lastleg-service/src/test/java/com/baiyue/lastleg/inboundplan/pda/service/InboundReceivingReconciliationRequestTest.java new file mode 100644 index 000000000..cb90ba2cf --- /dev/null +++ b/lastleg-service/src/test/java/com/baiyue/lastleg/inboundplan/pda/service/InboundReceivingReconciliationRequestTest.java @@ -0,0 +1,51 @@ +package com.baiyue.lastleg.inboundplan.pda.service; + +import com.baiyue.lastleg.inboundplan.dto.InboundReceivingReconciliation.*; +import jakarta.validation.Validation; +import org.junit.jupiter.api.Test; +import java.util.Arrays; +import java.util.List; +import java.util.stream.IntStream; +import static org.assertj.core.api.Assertions.assertThat; + +/** 请求层接受当前完整核对范围,数量守恒与只读事实继续由服务校验。 */ +class InboundReceivingReconciliationRequestTest { + /** 多票多商品的完整矩阵不能被任意一万行上限阻塞。 */ + @Test void acceptsCompleteLargeReconciliationSnapshot() { + List rows = IntStream.range(0, 10400).mapToObj(index -> + new Quantity("100", "IP-1", 3L, 10L + index / 400, "SKU-" + index % 400, 0)).toList(); + List pallets = IntStream.range(0, 26).mapToObj(index -> new Count(10L + index, 0)).toList(); + try (var factory = Validation.buildDefaultValidatorFactory()) { + assertThat(factory.getValidator().validate(new Confirm("100", "snapshot", "逐托复核", pallets, rows))).isEmpty(); + } + } + + /** 空行必须在进入业务事务前拒绝,不能触发空引用错误。 */ + @Test void rejectsNullListElements() { + try (var factory = Validation.buildDefaultValidatorFactory()) { + var validator = factory.getValidator(); + assertThat(validator.validate(new Confirm("100", "snapshot", "现场复核", Arrays.asList((Count) null), List.of()))) + .isNotEmpty(); + assertThat(validator.validate(new Confirm("100", "snapshot", "现场复核", List.of(), Arrays.asList((Quantity) null)))) + .isNotEmpty(); + } + } + + /** 已完成只读整托可以超过普通FBA单托上限,服务仍禁止改写这些数量。 */ + @Test void acceptsReadonlySourceQuantityAboveBulkLimit() { + try (var factory = Validation.buildDefaultValidatorFactory()) { + assertThat(factory.getValidator().validate(new Confirm("100", "snapshot", "现场复核", + List.of(new Count(10L, 80)), List.of(new Quantity("100", "IP-1", 3L, 10L, "SKU-1", 80))))) + .isEmpty(); + } + } + + /** 原因必填,负数清点或SKU数量均在请求层拒绝。 */ + @Test void rejectsNegativeCountsAndMissingReason() { + try (var factory = Validation.buildDefaultValidatorFactory()) { + assertThat(factory.getValidator().validate(new Confirm("100", "snapshot", " ", + List.of(new Count(10L, -1)), List.of(new Quantity("100", "IP-1", 3L, 10L, "SKU-1", -1))))) + .hasSize(3); + } + } +}