feat(firstleg): implement container customs workflow

This commit is contained in:
2026-08-28 16:48:50 +08:00
parent bb9673358d
commit 0ea4aeecc9
92 changed files with 3165 additions and 2754 deletions
@@ -78,6 +78,7 @@ public class OrderInboundOutboxPublisher {
|| command.inboundCode() == null || command.inboundCode().isBlank()
|| command.customerName() == null || command.customerName().isBlank()
|| command.warehouseId() == null || command.warehouseId() <= 0
|| !("BUY_DECLARATION".equals(command.taxMode()) || "TAX_REFUND".equals(command.taxMode()))
|| command.totalPackageCount() == null || command.totalPackageCount() < 1;
}
@@ -42,6 +42,38 @@ class OrderInboundOutboxPublisherTest {
verify(fixture.repository, never()).markOutboxFailed(any(), anyLong());
}
@Test
void completeApprovedEventKeepsFrozenTaxRefundMode() {
Fixture fixture = fixture(event("FIRST_LEG_ORDER_APPROVED", 11L, 21L,
completePayload(11L, 21L, "TAX_REFUND")));
when(fixture.client.create(eq("internal-token"), any())).thenReturn(ApiResponse.success(99L));
fixture.publisher.publishApprovedOrders();
ArgumentCaptor<FirstlegInboundClient.OrderApprovedInboundCommand> command =
ArgumentCaptor.forClass(FirstlegInboundClient.OrderApprovedInboundCommand.class);
verify(fixture.client).create(eq("internal-token"), command.capture());
org.assertj.core.api.Assertions.assertThat(command.getValue().taxMode()).isEqualTo("TAX_REFUND");
verify(fixture.repository, never()).findOwned(anyLong(), anyLong());
verify(fixture.repository).markOutboxPublished(eq(11L), eq(41L), any(LocalDateTime.class));
}
@Test
void missingTaxModeIsRebuiltFromAuthoritativeOrderSnapshot() {
Fixture fixture = fixture(event("FIRST_LEG_ORDER_APPROVED", 11L, 21L,
completePayload(11L, 21L, null)), "TAX_REFUND");
when(fixture.client.create(eq("internal-token"), any())).thenReturn(ApiResponse.success(99L));
fixture.publisher.publishApprovedOrders();
ArgumentCaptor<FirstlegInboundClient.OrderApprovedInboundCommand> command =
ArgumentCaptor.forClass(FirstlegInboundClient.OrderApprovedInboundCommand.class);
verify(fixture.client).create(eq("internal-token"), command.capture());
org.assertj.core.api.Assertions.assertThat(command.getValue().taxMode()).isEqualTo("TAX_REFUND");
verify(fixture.repository).findOwned(11L, 21L);
verify(fixture.repository).markOutboxPublished(eq(11L), eq(41L), any(LocalDateTime.class));
}
@Test
void mismatchedCustomerIsPermanentlyFailedBeforeDelivery() {
Fixture fixture = fixture(event("FIRST_LEG_ORDER_APPROVED", 11L, 21L, payload(12L, 21L)));
@@ -98,6 +130,10 @@ class OrderInboundOutboxPublisherTest {
}
private Fixture fixture(OutboxEventEntity event) {
return fixture(event, "BUY_DECLARATION");
}
private Fixture fixture(OutboxEventEntity event, String authoritativeTaxMode) {
OrderRepository repository = mock(OrderRepository.class);
FirstlegInboundClient client = mock(FirstlegInboundClient.class);
when(repository.pendingInboundEvents(50)).thenReturn(List.of(event));
@@ -112,7 +148,7 @@ class OrderInboundOutboxPublisherTest {
order.setReceivingWarehouseName("测试仓");
order.setDestinationType("OVERSEAS");
order.setTransportMode("SEA");
order.setTaxMode("BUY_DECLARATION");
order.setTaxMode(authoritativeTaxMode);
order.setPricingTaxMode("TAX_EXCLUDED");
when(repository.findOwned(event.getTenantId(), event.getAggregateId())).thenReturn(order);
var firstCargo = new com.baiyue.order.entity.OrderCargoEntity();
@@ -146,6 +182,14 @@ class OrderInboundOutboxPublisherTest {
return "{\"tenantId\":" + tenantId + ",\"orderId\":" + orderId + "}";
}
private String completePayload(long tenantId, long orderId, String taxMode) {
String taxModeJson = taxMode == null ? "null" : "\"" + taxMode + "\"";
return "{\"tenantId\":" + tenantId + ",\"orderId\":" + orderId
+ ",\"orderNo\":\"FL-" + orderId + "\",\"inboundCode\":\"RK-" + orderId
+ "\",\"customerName\":\"测试客户\",\"warehouseId\":31,\"taxMode\":" + taxModeJson
+ ",\"totalPackageCount\":4}";
}
private record Fixture(OrderInboundOutboxPublisher publisher, OrderRepository repository,
FirstlegInboundClient client) {
}