优化
This commit is contained in:
+44
-2
@@ -45,6 +45,10 @@ class LoadingCompletedOutboxServiceTest {
|
||||
|
||||
@Test void groupsByAccountAndKeepsAllOrdersAndItemsStable() throws Exception {
|
||||
when(snapshots.rows(90L)).thenReturn(List.of(row(22,300,302),row(11,200,202),row(11,100,102),row(11,100,101)));
|
||||
when(snapshots.palletRows(90L)).thenReturn(List.of(
|
||||
pallet(11,100,1,"PLT-01",1,101,"SKU101",1,10,"BOX-101"),
|
||||
pallet(11,100,1,"PLT-01",1,102,"SKU102",1,10,"BOX-102"),
|
||||
pallet(11,100,2,"PLT-02",1,102,"SKU102",1,10,"BOX-102")));
|
||||
service.publish(90L);
|
||||
ArgumentCaptor<InboundOutboxEntity> captor=ArgumentCaptor.forClass(InboundOutboxEntity.class);
|
||||
verify(outbox,org.mockito.Mockito.times(2)).insert(captor.capture());
|
||||
@@ -60,6 +64,14 @@ class LoadingCompletedOutboxServiceTest {
|
||||
assertThat(first.payload().at("/orders/0/items/0/cartonMarks/0").asText()).isEqualTo("BOX-101");
|
||||
assertThat(first.payload().at("/orders/0/destinationType").asText()).isEqualTo("OVERSEAS");
|
||||
assertThat(first.payload().at("/orders/0/customerName").asText()).isEqualTo("客户-11");
|
||||
assertThat(first.payload().at("/orders/0/palletCount").asInt()).isEqualTo(2);
|
||||
assertThat(first.payload().at("/orders/0/packageCount").asInt()).isEqualTo(2);
|
||||
assertThat(first.payload().at("/orders/0/productQuantity").asInt()).isEqualTo(20);
|
||||
assertThat(first.payload().at("/orders/0/volumeCbm").decimalValue()).isEqualByComparingTo("2");
|
||||
assertThat(first.payload().at("/orders/0/volumeWeightKg").decimalValue()).isEqualByComparingTo("4");
|
||||
assertThat(first.payload().at("/estimatedPortArrivalAt").asText()).isEqualTo("2026-09-30T12:00");
|
||||
assertThat(first.payload().at("/actualPortArrivalAt").asText()).isEqualTo("2026-10-01T08:30");
|
||||
assertThat(first.payload().at("/estimatedWarehouseArrivalAt").asText()).isEqualTo("2026-10-03T09:00");
|
||||
assertThat(rows.get(0).getEventKey()).isEqualTo("FIRSTLEG_LOADING_COMPLETED:90:11:2");
|
||||
assertThat(first.eventVersion()).isEqualTo(2);
|
||||
}
|
||||
@@ -148,6 +160,28 @@ class LoadingCompletedOutboxServiceTest {
|
||||
.isNotEqualTo(captor.getAllValues().get(1).getPayloadHash());
|
||||
}
|
||||
|
||||
@Test void keepsMissingPalletAndMeasurementFactsNullInsteadOfInventingZero() throws Exception {
|
||||
Row value = row(11, 100, 101);
|
||||
value.setProductQuantity(null); value.setVolumeCbm(null); value.setDimensionalWeightKg(null);
|
||||
value.setEstimatedPortArrivalAt(null); value.setActualPortArrivalAt(null);
|
||||
value.setEstimatedWarehouseArrivalAt(null);
|
||||
when(snapshots.rows(90L)).thenReturn(List.of(value));
|
||||
when(snapshots.palletRows(90L)).thenReturn(List.of());
|
||||
|
||||
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/palletCount").isNull()).isTrue();
|
||||
assertThat(event.payload().at("/orders/0/productQuantity").isNull()).isTrue();
|
||||
assertThat(event.payload().at("/orders/0/volumeCbm").isNull()).isTrue();
|
||||
assertThat(event.payload().at("/orders/0/volumeWeightKg").isNull()).isTrue();
|
||||
assertThat(event.payload().at("/estimatedPortArrivalAt").isNull()).isTrue();
|
||||
assertThat(event.payload().at("/actualPortArrivalAt").isNull()).isTrue();
|
||||
assertThat(event.payload().at("/estimatedWarehouseArrivalAt").isNull()).isTrue();
|
||||
}
|
||||
|
||||
@Test void fillsCollapsedMeasurementDetailFromUnusedInboundLabelsWithoutDuplicates() throws Exception {
|
||||
Row first = row(11, 100, 101); first.setPackageCount(1);
|
||||
Row second = row(11, 100, 101); second.setLoadingPlanItemId(102L); second.setPackageCount(2);
|
||||
@@ -176,7 +210,9 @@ class LoadingCompletedOutboxServiceTest {
|
||||
assertThat(rowsSql).contains("p.plan_status = 'COMPLETED'")
|
||||
.contains("o.process_status = 'LOADED'")
|
||||
.contains("b.customer_id AS booking_customer_id")
|
||||
.contains("b.customer_name");
|
||||
.contains("b.customer_name")
|
||||
.contains("b.estimated_port_arrival_at", "b.actual_port_arrival_at")
|
||||
.contains("b.estimated_warehouse_arrival_at");
|
||||
for (String sql : List.of(rowsSql, palletsSql)) {
|
||||
assertThat(sql)
|
||||
.contains("actual_pick.loading_plan_item_id = i.id")
|
||||
@@ -190,6 +226,7 @@ class LoadingCompletedOutboxServiceTest {
|
||||
.doesNotContain("'PICKING'");
|
||||
}
|
||||
assertThat(palletsSql)
|
||||
.contains("a.pallet_id", "a.reservation_id")
|
||||
.contains("label.tenant_id = i.account_id")
|
||||
.contains("label.inbound_detail_id = i.inbound_detail_id")
|
||||
.contains("label.batch_status = 'ACTIVE'")
|
||||
@@ -252,6 +289,9 @@ class LoadingCompletedOutboxServiceTest {
|
||||
Row r=new Row(); r.setLoadingPlanId(90L); r.setPlanNo("P90"); r.setContainerBookingId(91L);
|
||||
r.setAggregateVersion(8); r.setContainerNo("CONT"); r.setCabinetNo("CAB"); r.setWarehouseId(92L);
|
||||
r.setWarehouseName("WH"); r.setBookingCustomerId(account); r.setCustomerName("客户-" + account);
|
||||
r.setEstimatedPortArrivalAt(java.time.LocalDateTime.of(2026, 9, 30, 12, 0));
|
||||
r.setActualPortArrivalAt(java.time.LocalDateTime.of(2026, 10, 1, 8, 30));
|
||||
r.setEstimatedWarehouseArrivalAt(java.time.LocalDateTime.of(2026, 10, 3, 9, 0));
|
||||
r.setAccountId(account); r.setSourceInboundId(inbound); r.setRootInboundId(99L);
|
||||
r.setSourceOrderId(inbound+1000); r.setSourceOrderNo("FL"+inbound); r.setRootOrderId(1099L);
|
||||
r.setInboundCode("RK"+inbound); r.setLoadingPlanItemId(detail); r.setDestinationWarehouseId(93L); r.setDestinationWarehouseCode("ONT8");
|
||||
@@ -259,13 +299,15 @@ class LoadingCompletedOutboxServiceTest {
|
||||
r.setDestinationType("OVERSEAS");
|
||||
r.setFulfillmentType("STANDARD");
|
||||
r.setPackageCount(1); r.setProductQuantity(10); r.setPalletCount(1); r.setGrossWeightKg(BigDecimal.ONE);
|
||||
r.setNetWeightKg(BigDecimal.ONE); r.setVolumeCbm(BigDecimal.ONE); return r;
|
||||
r.setNetWeightKg(BigDecimal.ONE); r.setDimensionalWeightKg(new BigDecimal("2"));
|
||||
r.setVolumeCbm(BigDecimal.ONE); return r;
|
||||
}
|
||||
|
||||
|
||||
private PalletRow pallet(long account,long inbound,int allocation,String palletNo,int allocated,
|
||||
long detail,String sku,int packages,int quantity,String boxCode) {
|
||||
PalletRow row = new PalletRow(); row.setAccountId(account); row.setSourceInboundId(inbound);
|
||||
row.setPalletId(inbound * 100 + allocation); row.setReservationId(inbound * 1000 + allocation);
|
||||
row.setAllocationNo(allocation); row.setPalletCode(palletNo); row.setAllocatedPackageCount(allocated);
|
||||
row.setSourceInboundDetailId(detail); row.setSkuCode(sku); row.setProductNameZh("产品");
|
||||
row.setPackageCount(packages); row.setProductQuantity(quantity); row.setBoxCode(boxCode); return row;
|
||||
|
||||
+28
-8
@@ -11,6 +11,7 @@ import org.springframework.context.annotation.Import;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
@SpringBootTest(classes = TaillegRealProducerAcceptanceTest.AcceptanceApplication.class,
|
||||
webEnvironment = SpringBootTest.WebEnvironment.NONE, properties = {
|
||||
@@ -53,13 +54,26 @@ class TaillegRealProducerAcceptanceTest {
|
||||
assertEquals("真实验收客户", jdbc.queryForObject(
|
||||
"SELECT JSON_UNQUOTE(JSON_EXTRACT(payload_json,'$.payload.orders[0].customerName')) " +
|
||||
"FROM fl_inbound_outbox WHERE event_key=?", String.class, eventKey));
|
||||
assertEquals("2026-09-30T12:00", jdbc.queryForObject(
|
||||
"SELECT JSON_UNQUOTE(JSON_EXTRACT(payload_json,'$.payload.estimatedPortArrivalAt')) " +
|
||||
"FROM fl_inbound_outbox WHERE event_key=?", String.class, eventKey));
|
||||
assertNull(jdbc.queryForObject(
|
||||
"SELECT JSON_UNQUOTE(JSON_EXTRACT(payload_json,'$.payload.actualPortArrivalAt')) " +
|
||||
"FROM fl_inbound_outbox WHERE event_key=?", String.class, eventKey));
|
||||
assertEquals(1, jdbc.queryForObject(
|
||||
"SELECT JSON_EXTRACT(payload_json,'$.payload.orders[0].palletCount') " +
|
||||
"FROM fl_inbound_outbox WHERE event_key=?", Integer.class, eventKey));
|
||||
assertEquals("35.0", jdbc.queryForObject(
|
||||
"SELECT JSON_UNQUOTE(JSON_EXTRACT(payload_json,'$.payload.orders[0].volumeWeightKg')) " +
|
||||
"FROM fl_inbound_outbox WHERE event_key=?", String.class, eventKey));
|
||||
}
|
||||
|
||||
private void seedCompletedLoadingPlan() {
|
||||
jdbc.update("INSERT IGNORE INTO fl_container_booking(id,booking_no,container_no,cabinet_no,warehouse_id," +
|
||||
"warehouse_name,customer_id,customer_name,container_type,created_by,updated_by) VALUES(?,?,?,?,?,?,?,?,?,1,1)",
|
||||
"warehouse_name,customer_id,customer_name,estimated_port_arrival_at,container_type,created_by,updated_by) " +
|
||||
"VALUES(?,?,?,?,?,?,?,?,?,?,1,1)",
|
||||
BOOKING, MARKER + "-BOOK", MARKER + "-CNTR", MARKER + "-CAB", 92L, "真实验收海外仓",
|
||||
CUSTOMER, "真实验收客户", "40HQ");
|
||||
CUSTOMER, "真实验收客户", java.time.LocalDateTime.of(2026, 9, 30, 12, 0), "40HQ");
|
||||
jdbc.update("INSERT IGNORE INTO fl_loading_plan(id,plan_no,container_booking_id,plan_status,created_by," +
|
||||
"updated_by,version) VALUES(?,?,?,'LOADING',1,1,0)", PLAN, MARKER + "-PLAN", BOOKING);
|
||||
seedInbound(FIRST_INBOUND, 990022221L, MARKER + "-FIRST-IN", "FBA_SEA", "STANDARD", "LOADED", "ONT8");
|
||||
@@ -70,12 +84,8 @@ class TaillegRealProducerAcceptanceTest {
|
||||
MARKER + "-FIRST-IN", "FIRST-BOX-" + i, i, 3);
|
||||
for (int i = 1; i <= 2; i++) seedLabel(990022550L + i, DROPSHIP_INBOUND, 990022222L, 990022422L,
|
||||
MARKER + "-DROP-IN", "DROP-BOX-" + i, i, 2);
|
||||
jdbc.update("INSERT IGNORE INTO fl_inbound_pallet_allocation(id,tenant_id,inbound_id,allocation_no," +
|
||||
"warehouse_id,warehouse_resource_tenant_id,pallet_id,pallet_code,pallet_capacity_cbm," +
|
||||
"allocated_volume_cbm,allocated_package_count,picked_package_count,location_id,location_code," +
|
||||
"reservation_no,allocation_status) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,'CONFIRMED')",
|
||||
990022621L, CUSTOMER, DROPSHIP_INBOUND, 1, 92L, 0L, 990022721L, MARKER + "-PALLET-D",
|
||||
1.2, 0.4, 2, 2, 990022821L, "A-01", MARKER + "-RES");
|
||||
seedAllocation(990022620L, FIRST_INBOUND, 990022720L, 990022820L, 3, "F");
|
||||
seedAllocation(990022621L, DROPSHIP_INBOUND, 990022721L, 990022821L, 2, "D");
|
||||
jdbc.update("INSERT INTO fl_loading_pick_task(id,loading_plan_id,container_booking_id,cabinet_no," +
|
||||
"container_no,task_status,started_by,started_by_name) VALUES(?,?,?,?,?,'LOADING',1,'真实验收')",
|
||||
990022901L, PLAN, BOOKING, MARKER + "-CAB", MARKER + "-CNTR");
|
||||
@@ -84,6 +94,16 @@ class TaillegRealProducerAcceptanceTest {
|
||||
jdbc.update("UPDATE fl_loading_plan SET plan_status='COMPLETED',confirmed_at=NOW(3),version=version+1 WHERE id=?", PLAN);
|
||||
}
|
||||
|
||||
private void seedAllocation(long id, long inboundId, long palletId, long locationId,
|
||||
int packages, String suffix) {
|
||||
jdbc.update("INSERT IGNORE INTO fl_inbound_pallet_allocation(id,tenant_id,inbound_id,allocation_no," +
|
||||
"warehouse_id,warehouse_resource_tenant_id,pallet_id,pallet_code,pallet_capacity_cbm," +
|
||||
"allocated_volume_cbm,allocated_package_count,picked_package_count,location_id,location_code," +
|
||||
"reservation_id,reservation_no,allocation_status) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,'CONFIRMED')",
|
||||
id, CUSTOMER, inboundId, 1, 92L, 0L, palletId, MARKER + "-PALLET-" + suffix,
|
||||
1.2, 0.4, packages, packages, locationId, "A-01", id + 1000, MARKER + "-RES-" + suffix);
|
||||
}
|
||||
|
||||
private void seedPickItem(long id, long planItemId, long inboundId, long detailId, int packages) {
|
||||
jdbc.update("INSERT INTO fl_loading_pick_item(id,pick_task_id,loading_plan_item_id,inbound_id," +
|
||||
"inbound_detail_id,planned_package_count,picked_package_count,item_status) VALUES(?,?,?,?,?,?,?,'PICKED')",
|
||||
|
||||
Reference in New Issue
Block a user