支持私人地址装柜后按普通海外收货交接

This commit is contained in:
2026-11-04 12:45:05 +08:00
parent 8b56af2cae
commit 0d8e64c42c
3 changed files with 40 additions and 5 deletions
@@ -335,11 +335,13 @@ public class LoadingCompletedOutboxService {
Set<String> values = rows.stream().map(Row::getDestinationType)
.map(value -> value == null ? "" : value.trim().toUpperCase(java.util.Locale.ROOT))
.collect(java.util.stream.Collectors.toSet());
if (values.size() != 1 || (!values.contains("FBA") && !values.contains("OVERSEAS"))) {
if (values.size() != 1
|| (!values.contains("FBA") && !values.contains("OVERSEAS") && !values.contains("PRIVATE"))) {
throw new BizException(ResultCode.CONFLICT,
"装柜入仓单目的类型必须唯一且为 FBA 或 OVERSEAS,不能生成海外交接事件");
"装柜入仓单目的类型必须唯一且为 FBA、OVERSEAS 或 PRIVATE,不能生成海外交接事件");
}
return values.iterator().next();
String value = values.iterator().next();
return "PRIVATE".equals(value) ? "OVERSEAS" : value;
}
private String fulfillmentType(List<Row> rows) {
@@ -189,13 +189,46 @@ class LoadingCompletedOutboxServiceTest {
verify(manifests, org.mockito.Mockito.never()).labelPool(11L, 100L);
}
@Test void privateAddressFreezesAsOverseasWithOriginalCartonIdentity() throws Exception {
Row value = row(11, 100, 101);
value.setDestinationType("PRIVATE");
value.setDestinationWarehouseId(null);
value.setDestinationWarehouseCode(null);
value.setDestinationWarehouseName("私人地址");
when(snapshots.rows(90L)).thenReturn(List.of(value));
service.publish(90L);
ArgumentCaptor<InboundOutboxEntity> captor = ArgumentCaptor.forClass(InboundOutboxEntity.class);
verify(outbox).insert(captor.capture());
EventEnvelope event = mapper.readValue(captor.getValue().getPayloadJson(), EventEnvelope.class);
assertThat(event.payload().at("/orders/0/destinationType").asText()).isEqualTo("OVERSEAS");
assertThat(event.payload().at("/orders/0/destinationWarehouseId").isNull()).isTrue();
assertThat(event.payload().at("/orders/0/destinationWarehouseCode").isNull()).isTrue();
assertThat(event.payload().at("/orders/0/destinationWarehouseName").asText()).isEqualTo("私人地址");
assertThat(event.payload().at("/orders/0/items/0/sourceInboundDetailId").asText()).isEqualTo("101");
assertThat(event.payload().at("/orders/0/items/0/skuCode").asText()).isEqualTo("SKU101");
assertThat(event.payload().at("/orders/0/items/0/cartonMarks/0").asText()).isEqualTo("BOX-101");
verify(manifests).labelPool(11L, 100L);
}
@Test void rejectsMixedPrivateAndOverseasDestinationsInOneInbound() {
Row privateAddress = row(11, 100, 101);
privateAddress.setDestinationType("PRIVATE");
when(snapshots.rows(90L)).thenReturn(List.of(privateAddress, row(11, 100, 102)));
assertThatThrownBy(() -> service.publish(90L)).hasMessageContaining("目的类型必须唯一");
verify(outbox, org.mockito.Mockito.never()).insert(
org.mockito.ArgumentMatchers.any(InboundOutboxEntity.class));
}
@Test void rejectsUnfrozenDestinationType() {
Row value = row(11, 100, 101);
value.setDestinationType(null);
when(snapshots.rows(90L)).thenReturn(List.of(value));
assertThatThrownBy(() -> service.publish(90L))
.hasMessageContaining("目的类型必须唯一且为 FBA 或 OVERSEAS");
.hasMessageContaining("目的类型必须唯一且为 FBA、OVERSEAS 或 PRIVATE");
verify(outbox, org.mockito.Mockito.never()).insert(
org.mockito.ArgumentMatchers.any(InboundOutboxEntity.class));
}