优化
This commit is contained in:
@@ -19,7 +19,7 @@ public interface LoadingCompletedEventMapper {
|
||||
COALESCE(o.root_inbound_id, o.id) AS root_inbound_id,
|
||||
o.order_id AS source_order_id, o.order_no AS source_order_no,
|
||||
COALESCE(root_order.order_id, o.order_id) AS root_order_id,
|
||||
o.inbound_code, o.business_type, o.destination_warehouse_id, o.destination_code AS destination_warehouse_code,
|
||||
o.inbound_code, o.business_type, o.destination_type, o.destination_warehouse_id, o.destination_code AS destination_warehouse_code,
|
||||
o.destination_name AS destination_warehouse_name,
|
||||
i.id AS loading_plan_item_id, i.inbound_detail_id AS source_inbound_detail_id, i.sku_code,
|
||||
i.product_name_zh, i.product_name_en, i.package_count, i.product_quantity,
|
||||
@@ -73,7 +73,7 @@ public interface LoadingCompletedEventMapper {
|
||||
private Integer productQuantity; private Integer palletCount; private BigDecimal grossWeightKg;
|
||||
private BigDecimal netWeightKg; private BigDecimal dimensionalWeightKg; private BigDecimal volumeCbm;
|
||||
private String fbaTrackingNo; private String shipmentNo; private String shippingMark;
|
||||
private String businessType;
|
||||
private String businessType; private String destinationType;
|
||||
private String customerRemark; private String internalRemark; private String warehouseRemark;
|
||||
}
|
||||
|
||||
|
||||
+14
-1
@@ -103,13 +103,15 @@ public class LoadingCompletedOutboxService {
|
||||
first.getDestinationWarehouseCode(), first.getDestinationWarehouseName(), sumInt(sorted, Row::getPackageCount),
|
||||
sumNullableInt(sorted, Row::getProductQuantity), "ONE_CLICK_DROPSHIP".equals(orderType)
|
||||
? pallets.size() : 0, sum(sorted, Row::getGrossWeightKg), sum(sorted, Row::getNetWeightKg),
|
||||
sum(sorted, Row::getVolumeCbm), items, string(first.getAccountId()), orderType, pallets);
|
||||
sum(sorted, Row::getVolumeCbm), items, string(first.getAccountId()), orderType, pallets,
|
||||
destinationType(sorted));
|
||||
}
|
||||
|
||||
/** 国内按实装箱数从可用标签池稳定随机抽取箱唛,重复发布同一计划时结果不变。 */
|
||||
private Map<Long, List<String>> cartonLabelPools(List<Row> rows) {
|
||||
Map<Long, List<String>> result = new java.util.LinkedHashMap<>();
|
||||
Map<LabelPoolKey, List<Row>> byInbound = rows.stream().filter(row -> !dropship(row.getBusinessType()))
|
||||
.filter(row -> "OVERSEAS".equals(destinationType(List.of(row))))
|
||||
.collect(java.util.stream.Collectors.groupingBy(
|
||||
row -> new LabelPoolKey(row.getAccountId(), row.getSourceInboundId()),
|
||||
LinkedHashMap::new, java.util.stream.Collectors.toList()));
|
||||
@@ -155,6 +157,17 @@ public class LoadingCompletedOutboxService {
|
||||
return result;
|
||||
}
|
||||
|
||||
private String destinationType(List<Row> rows) {
|
||||
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"))) {
|
||||
throw new BizException(ResultCode.CONFLICT,
|
||||
"装柜入仓单目的类型必须唯一且为 FBA 或 OVERSEAS,不能生成海外交接事件");
|
||||
}
|
||||
return values.iterator().next();
|
||||
}
|
||||
|
||||
private record LabelPoolKey(long accountId, long inboundId) { }
|
||||
|
||||
private List<FirstLegLoadingPlanCompletedV2.PalletSnapshot> palletSnapshots(List<Row> values, List<PalletRow> source) {
|
||||
|
||||
+27
@@ -58,6 +58,7 @@ class LoadingCompletedOutboxServiceTest {
|
||||
assertThat(first.payload().at("/orders/0/items/0/sourceInboundDetailId").asText()).isEqualTo("101");
|
||||
assertThat(first.payload().at("/orders/0/items/0/skuCode").asText()).isEqualTo("SKU101");
|
||||
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(rows.get(0).getEventKey()).isEqualTo("FIRSTLEG_LOADING_COMPLETED:90:11:2");
|
||||
assertThat(first.eventVersion()).isEqualTo(2);
|
||||
}
|
||||
@@ -71,6 +72,31 @@ class LoadingCompletedOutboxServiceTest {
|
||||
.hasMessageContaining("缺少 SKU");
|
||||
}
|
||||
|
||||
@Test void fbaFreezesPackageCountWithoutRequiringCartonLabels() throws Exception {
|
||||
Row value = row(11, 100, 101);
|
||||
value.setDestinationType("FBA");
|
||||
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("FBA");
|
||||
assertThat(event.payload().at("/orders/0/items/0/cartonMarks")).isEmpty();
|
||||
verify(manifests, org.mockito.Mockito.never()).labelPool(11L, 100L);
|
||||
}
|
||||
|
||||
@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");
|
||||
verify(outbox, org.mockito.Mockito.never()).insert(org.mockito.ArgumentMatchers.any());
|
||||
}
|
||||
|
||||
@Test void freezesExactlyLoadedPackagesFromLabelPoolDeterministically() throws Exception {
|
||||
Row value = row(11, 100, 101);
|
||||
value.setPackageCount(2);
|
||||
@@ -148,6 +174,7 @@ class LoadingCompletedOutboxServiceTest {
|
||||
r.setSourceOrderId(inbound+1000); r.setSourceOrderNo("FL"+inbound); r.setRootOrderId(1099L);
|
||||
r.setInboundCode("RK"+inbound); r.setLoadingPlanItemId(detail); r.setDestinationWarehouseId(93L); r.setDestinationWarehouseCode("ONT8");
|
||||
r.setDestinationWarehouseName("ONT8"); r.setSourceInboundDetailId(detail); r.setSkuCode("SKU"+detail);
|
||||
r.setDestinationType("OVERSEAS");
|
||||
r.setPackageCount(1); r.setProductQuantity(10); r.setPalletCount(1); r.setGrossWeightKg(BigDecimal.ONE);
|
||||
r.setNetWeightKg(BigDecimal.ONE); r.setVolumeCbm(BigDecimal.ONE); return r;
|
||||
}
|
||||
|
||||
+2
-2
@@ -88,9 +88,9 @@ class TaillegRealProducerAcceptanceTest {
|
||||
|
||||
private void seedInbound(long id, long orderId, String code, String type, String status, String destination) {
|
||||
jdbc.update("INSERT IGNORE INTO fl_inbound_order(id,tenant_id,order_id,order_no,inbound_code,process_status," +
|
||||
"order_status_snapshot,customer_name,warehouse_id,warehouse_name,business_type,destination_warehouse_id," +
|
||||
"order_status_snapshot,customer_name,warehouse_id,warehouse_name,business_type,destination_type,destination_warehouse_id," +
|
||||
"destination_code,destination_name,package_count,actual_volume_cbm,created_by,updated_by) " +
|
||||
"VALUES(?,?,?,?,?,?, 'IN_TRANSIT',?,92,'真实验收海外仓',?,9001,?,?,?,0.4000,1,1)",
|
||||
"VALUES(?,?,?,?,?,?, 'IN_TRANSIT',?,92,'真实验收海外仓',?,'FBA',9001,?,?,?,0.4000,1,1)",
|
||||
id, CUSTOMER, orderId, MARKER + "-ORDER-" + id, code, status, "真实验收客户", type,
|
||||
destination, "FBA " + destination, type.equals("ONE_CLICK_DROPSHIP") ? 2 : 3);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user