fix(delivery): expose signed quantity and publish correct signature instant
This commit is contained in:
+18
-2
@@ -61,12 +61,28 @@ class DeliveryLongIdJsonContractTest {
|
||||
});
|
||||
}
|
||||
|
||||
private DeliveryResponses.DeliveryRow deliveryRow() {
|
||||
@Test
|
||||
void signedPackagesMustPreserveNullZeroAndPositiveDatabaseFacts() {
|
||||
contextRunner.run(context -> {
|
||||
ObjectMapper objectMapper = context.getBean(ObjectMapper.class);
|
||||
objectMapper.setSerializationInclusion(com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL);
|
||||
for (Integer count : new Integer[] {null, 0, 3}) {
|
||||
JsonNode json = objectMapper.readTree(objectMapper.writeValueAsString(deliveryRow(count)));
|
||||
assertThat(json.has("signedPackages")).isTrue();
|
||||
if (count == null) assertThat(json.get("signedPackages").isNull()).isTrue();
|
||||
else assertThat(json.get("signedPackages").intValue()).isEqualTo(count);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private DeliveryResponses.DeliveryRow deliveryRow() { return deliveryRow(null); }
|
||||
|
||||
private DeliveryResponses.DeliveryRow deliveryRow(Integer signedPackages) {
|
||||
return new DeliveryResponses.DeliveryRow(
|
||||
DELIVERY_ID,
|
||||
null, null, "PS-1", null, null, null, null, "CREATED", null,
|
||||
null, null, null, null, null, null, null, null, null, null, null,
|
||||
0, 0, null, null, null, null, null, null, null, null, 0, java.util.List.of(), null,
|
||||
0, 0, signedPackages, null, null, null, null, null, null, null, null, 0, java.util.List.of(), null,
|
||||
com.baiyue.lastleg.delivery.service.DeliveryDocumentSnapshot.summary(null), null, null, null,
|
||||
null, null, null, null, null);
|
||||
}
|
||||
|
||||
+9
-1
@@ -34,7 +34,8 @@ class DeliveryCompletedOutboxServiceTest {
|
||||
delivery.setPackageCount(10); delivery.setSignedPackages(10);
|
||||
|
||||
service.publish(delivery, List.of(order(11, "101", "201", "IN-1", "ONT8"),
|
||||
order(12, "102", "202", "IN-2", "ACY2")), proofs(), Instant.parse("2026-09-15T08:00:00Z"));
|
||||
order(12, "102", "202", "IN-2", "ACY2")), proofs(),
|
||||
java.time.LocalDateTime.of(2026, 10, 3, 22, 13).atZone(java.time.ZoneId.of("Asia/Shanghai")).toInstant());
|
||||
|
||||
ArgumentCaptor<LastlegEventOutbox> rows = ArgumentCaptor.forClass(LastlegEventOutbox.class);
|
||||
verify(mapper, times(2)).insert(rows.capture());
|
||||
@@ -48,6 +49,13 @@ class DeliveryCompletedOutboxServiceTest {
|
||||
.containsExactly("101", "102");
|
||||
assertThat(payloads).extracting(OverseasDeliveryCompletedV1::fbaWarehouseCode)
|
||||
.containsExactly("ONT8", "ACY2");
|
||||
assertThat(payloads).extracting(OverseasDeliveryCompletedV1::completedAt)
|
||||
.containsOnly(Instant.parse("2026-10-03T14:13:00Z"));
|
||||
for (var row : rows.getAllValues()) {
|
||||
assertThat(json.readValue(row.getPayloadJson(), EventEnvelope.class).occurredAt())
|
||||
.isEqualTo(Instant.parse("2026-10-03T14:13:00Z"));
|
||||
assertThat(row.getCreatedAt()).isEqualTo(java.time.LocalDateTime.of(2026, 10, 3, 14, 13));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+28
@@ -18,6 +18,13 @@ import org.springframework.web.server.ResponseStatusException;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.TimeZone;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
import org.junit.jupiter.api.parallel.ResourceLock;
|
||||
import java.util.List;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
@@ -174,6 +181,27 @@ class DeliveryDocumentServiceTest {
|
||||
assertThat(order.getStatus()).isEqualTo("WAIT_DELIVERY");
|
||||
assertThat(order.getVersion()).isZero();
|
||||
}
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = { "Asia/Shanghai", "America/Los_Angeles" })
|
||||
@ResourceLock("java.util.TimeZone.default")
|
||||
void signatureEventUsesTheExecutionZoneInsteadOfReinterpretingLocalTimeAsUtc(String zone) {
|
||||
TimeZone previous = TimeZone.getDefault();
|
||||
try {
|
||||
TimeZone.setDefault(TimeZone.getTimeZone(zone));
|
||||
order.setStatus("WAIT_DELIVERY");
|
||||
var outbound = new OutboundOrder(); outbound.setStatus("OUTBOUNDED");
|
||||
when(outboundOrders.findByNo("100", "OUT-1")).thenReturn(outbound);
|
||||
when(orders.lockByNo("100", "DL-1")).thenReturn(order);
|
||||
when(files.metadata("100", 10, RECEIPT, 13)).thenReturn(file(13));
|
||||
Instant before = Instant.now();
|
||||
service.save("100", "DL-1", "9", request(0, "receipt-zone", List.of(new Binding(RECEIPT, List.of(13L)))));
|
||||
ArgumentCaptor<Instant> completed = ArgumentCaptor.forClass(Instant.class);
|
||||
verify(deliveryCompletedOutbox).publish(eq(order), anyList(), anyMap(), completed.capture());
|
||||
assertThat(completed.getValue()).isEqualTo(order.getSignedAt().atZone(ZoneId.of(zone)).toInstant());
|
||||
assertThat(completed.getValue()).isBetween(before, Instant.now());
|
||||
assertThat(completed.getValue()).isNotEqualTo(order.getSignedAt().toInstant(ZoneOffset.UTC));
|
||||
} finally { TimeZone.setDefault(previous); }
|
||||
}
|
||||
@Test void bolMayBePreparedBeforeOutboundWithoutCompletingDelivery() {
|
||||
order.setStatus("WAIT_DELIVERY");
|
||||
when(orders.lockByNo("100","DL-1")).thenReturn(order);
|
||||
|
||||
+12
@@ -544,6 +544,18 @@ class DeliveryTransferServiceTest {
|
||||
verify(tailOrders).selectBatchIds(List.of(901L));
|
||||
}
|
||||
|
||||
@Test
|
||||
void deliveryRowMapsOnlyTheNullableStoredSignedQuantityWithoutShipmentFallback() {
|
||||
DeliveryOrder order = new DeliveryOrder();
|
||||
order.setId(401L); order.setDeliveryNo("DEL-401"); order.setPackageCount(9);
|
||||
for (Integer signed : new Integer[] {null, 0, 3}) {
|
||||
order.setSignedPackages(signed);
|
||||
DeliveryResponses.DeliveryRow row = org.springframework.test.util.ReflectionTestUtils.invokeMethod(service, "deliveryRow", order);
|
||||
assertEquals(signed, row.signedPackages());
|
||||
assertEquals(9, row.packageCount());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void globalOutboundCancelIsIdempotentForAnUnexecutedOrder() {
|
||||
OutboundOrder outbound = outbound(301L, null, null, "OUT-301", "one-click-key");
|
||||
|
||||
Reference in New Issue
Block a user