优化
This commit is contained in:
+23
-1
@@ -7,7 +7,14 @@ import java.util.List;
|
|||||||
public record FirstLegLoadingPlanCompletedV1(
|
public record FirstLegLoadingPlanCompletedV1(
|
||||||
String loadingPlanId, String planNo, String containerBookingId,
|
String loadingPlanId, String planNo, String containerBookingId,
|
||||||
String containerNo, String cabinetNo, String warehouseId, String warehouseName,
|
String containerNo, String cabinetNo, String warehouseId, String warehouseName,
|
||||||
|
String estimatedPortArrivalAt, String actualPortArrivalAt, String estimatedWarehouseArrivalAt,
|
||||||
List<Order> orders) {
|
List<Order> orders) {
|
||||||
|
public FirstLegLoadingPlanCompletedV1(String loadingPlanId, String planNo, String containerBookingId,
|
||||||
|
String containerNo, String cabinetNo, String warehouseId,
|
||||||
|
String warehouseName, List<Order> orders) {
|
||||||
|
this(loadingPlanId, planNo, containerBookingId, containerNo, cabinetNo, warehouseId,
|
||||||
|
warehouseName, null, null, null, orders);
|
||||||
|
}
|
||||||
|
|
||||||
public record Order(
|
public record Order(
|
||||||
String sourceInboundId, String rootInboundId,
|
String sourceInboundId, String rootInboundId,
|
||||||
@@ -16,6 +23,7 @@ public record FirstLegLoadingPlanCompletedV1(
|
|||||||
String destinationWarehouseCode, String destinationWarehouseName,
|
String destinationWarehouseCode, String destinationWarehouseName,
|
||||||
int packageCount, Integer productQuantity, Integer palletCount,
|
int packageCount, Integer productQuantity, Integer palletCount,
|
||||||
BigDecimal grossWeightKg, BigDecimal netWeightKg, BigDecimal volumeCbm,
|
BigDecimal grossWeightKg, BigDecimal netWeightKg, BigDecimal volumeCbm,
|
||||||
|
BigDecimal volumeWeightKg,
|
||||||
List<Item> items, String customerId, String customerName, String orderType, List<PalletSnapshot> pallets,
|
List<Item> items, String customerId, String customerName, String orderType, List<PalletSnapshot> pallets,
|
||||||
String destinationType) {
|
String destinationType) {
|
||||||
public Order {
|
public Order {
|
||||||
@@ -40,9 +48,23 @@ public record FirstLegLoadingPlanCompletedV1(
|
|||||||
this(sourceInboundId, rootInboundId, sourceOrderId, sourceOrderNo, rootOrderId,
|
this(sourceInboundId, rootInboundId, sourceOrderId, sourceOrderNo, rootOrderId,
|
||||||
inboundCode, destinationWarehouseId, destinationWarehouseCode,
|
inboundCode, destinationWarehouseId, destinationWarehouseCode,
|
||||||
destinationWarehouseName, packageCount, productQuantity, palletCount,
|
destinationWarehouseName, packageCount, productQuantity, palletCount,
|
||||||
grossWeightKg, netWeightKg, volumeCbm, items, customerId, customerName,
|
grossWeightKg, netWeightKg, volumeCbm, null, items, customerId, customerName,
|
||||||
orderType, pallets, null);
|
orderType, pallets, null);
|
||||||
}
|
}
|
||||||
|
public Order(String sourceInboundId, String rootInboundId,
|
||||||
|
String sourceOrderId, String sourceOrderNo, String rootOrderId,
|
||||||
|
String inboundCode, String destinationWarehouseId,
|
||||||
|
String destinationWarehouseCode, String destinationWarehouseName,
|
||||||
|
int packageCount, Integer productQuantity, Integer palletCount,
|
||||||
|
BigDecimal grossWeightKg, BigDecimal netWeightKg, BigDecimal volumeCbm,
|
||||||
|
List<Item> items, String customerId, String customerName,
|
||||||
|
String orderType, List<PalletSnapshot> pallets, String destinationType) {
|
||||||
|
this(sourceInboundId, rootInboundId, sourceOrderId, sourceOrderNo, rootOrderId,
|
||||||
|
inboundCode, destinationWarehouseId, destinationWarehouseCode,
|
||||||
|
destinationWarehouseName, packageCount, productQuantity, palletCount,
|
||||||
|
grossWeightKg, netWeightKg, volumeCbm, null, items, customerId, customerName,
|
||||||
|
orderType, pallets, destinationType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record Item(
|
public record Item(
|
||||||
|
|||||||
+25
-1
@@ -7,7 +7,15 @@ import java.util.List;
|
|||||||
public record FirstLegLoadingPlanCompletedV2(
|
public record FirstLegLoadingPlanCompletedV2(
|
||||||
String loadingPlanId, String planNo, String containerBookingId,
|
String loadingPlanId, String planNo, String containerBookingId,
|
||||||
String containerNo, String cabinetNo, String warehouseId, String warehouseName,
|
String containerNo, String cabinetNo, String warehouseId, String warehouseName,
|
||||||
|
String estimatedPortArrivalAt, String actualPortArrivalAt, String estimatedWarehouseArrivalAt,
|
||||||
List<Order> orders) {
|
List<Order> orders) {
|
||||||
|
public FirstLegLoadingPlanCompletedV2(String loadingPlanId, String planNo, String containerBookingId,
|
||||||
|
String containerNo, String cabinetNo, String warehouseId,
|
||||||
|
String warehouseName, List<Order> orders) {
|
||||||
|
this(loadingPlanId, planNo, containerBookingId, containerNo, cabinetNo, warehouseId,
|
||||||
|
warehouseName, null, null, null, orders);
|
||||||
|
}
|
||||||
|
|
||||||
public record Order(
|
public record Order(
|
||||||
String sourceInboundId, String rootInboundId,
|
String sourceInboundId, String rootInboundId,
|
||||||
String sourceOrderId, String sourceOrderNo, String rootOrderId,
|
String sourceOrderId, String sourceOrderNo, String rootOrderId,
|
||||||
@@ -15,6 +23,7 @@ public record FirstLegLoadingPlanCompletedV2(
|
|||||||
String destinationWarehouseCode, String destinationWarehouseName,
|
String destinationWarehouseCode, String destinationWarehouseName,
|
||||||
int packageCount, Integer productQuantity, Integer palletCount,
|
int packageCount, Integer productQuantity, Integer palletCount,
|
||||||
BigDecimal grossWeightKg, BigDecimal netWeightKg, BigDecimal volumeCbm,
|
BigDecimal grossWeightKg, BigDecimal netWeightKg, BigDecimal volumeCbm,
|
||||||
|
BigDecimal volumeWeightKg,
|
||||||
List<Item> items, String customerId, String customerName, String orderType, List<PalletSnapshot> pallets,
|
List<Item> items, String customerId, String customerName, String orderType, List<PalletSnapshot> pallets,
|
||||||
/** 目的类型:FBA 可按箱数收货,OVERSEAS 必须逐箱扫码。 */
|
/** 目的类型:FBA 可按箱数收货,OVERSEAS 必须逐箱扫码。 */
|
||||||
String destinationType) {
|
String destinationType) {
|
||||||
@@ -41,9 +50,24 @@ public record FirstLegLoadingPlanCompletedV2(
|
|||||||
this(sourceInboundId, rootInboundId, sourceOrderId, sourceOrderNo, rootOrderId,
|
this(sourceInboundId, rootInboundId, sourceOrderId, sourceOrderNo, rootOrderId,
|
||||||
inboundCode, destinationWarehouseId, destinationWarehouseCode,
|
inboundCode, destinationWarehouseId, destinationWarehouseCode,
|
||||||
destinationWarehouseName, packageCount, productQuantity, palletCount,
|
destinationWarehouseName, packageCount, productQuantity, palletCount,
|
||||||
grossWeightKg, netWeightKg, volumeCbm, items, customerId, customerName,
|
grossWeightKg, netWeightKg, volumeCbm, null, items, customerId, customerName,
|
||||||
orderType, pallets, null);
|
orderType, pallets, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Order(String sourceInboundId, String rootInboundId,
|
||||||
|
String sourceOrderId, String sourceOrderNo, String rootOrderId,
|
||||||
|
String inboundCode, String destinationWarehouseId,
|
||||||
|
String destinationWarehouseCode, String destinationWarehouseName,
|
||||||
|
int packageCount, Integer productQuantity, Integer palletCount,
|
||||||
|
BigDecimal grossWeightKg, BigDecimal netWeightKg, BigDecimal volumeCbm,
|
||||||
|
List<Item> items, String customerId, String customerName,
|
||||||
|
String orderType, List<PalletSnapshot> pallets, String destinationType) {
|
||||||
|
this(sourceInboundId, rootInboundId, sourceOrderId, sourceOrderNo, rootOrderId,
|
||||||
|
inboundCode, destinationWarehouseId, destinationWarehouseCode,
|
||||||
|
destinationWarehouseName, packageCount, productQuantity, palletCount,
|
||||||
|
grossWeightKg, netWeightKg, volumeCbm, null, items, customerId, customerName,
|
||||||
|
orderType, pallets, destinationType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record Item(
|
public record Item(
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ components:
|
|||||||
schemas:
|
schemas:
|
||||||
FirstLegLoadingPlanCompletedV2:
|
FirstLegLoadingPlanCompletedV2:
|
||||||
type: object
|
type: object
|
||||||
required: [loadingPlanId, containerBookingId, orders]
|
required: [loadingPlanId, containerBookingId, estimatedPortArrivalAt, actualPortArrivalAt, estimatedWarehouseArrivalAt, orders]
|
||||||
properties:
|
properties:
|
||||||
loadingPlanId: {type: string}
|
loadingPlanId: {type: string}
|
||||||
containerBookingId: {type: string}
|
containerBookingId: {type: string}
|
||||||
@@ -15,12 +15,15 @@ components:
|
|||||||
cabinetNo: {type: string}
|
cabinetNo: {type: string}
|
||||||
warehouseId: {type: string}
|
warehouseId: {type: string}
|
||||||
warehouseName: {type: string}
|
warehouseName: {type: string}
|
||||||
|
estimatedPortArrivalAt: {type: [string, 'null'], format: local-date-time, description: Frozen source-local estimated port arrival; null when Firstleg has no fact}
|
||||||
|
actualPortArrivalAt: {type: [string, 'null'], format: local-date-time, description: Frozen source-local actual port arrival; never copied from an estimate}
|
||||||
|
estimatedWarehouseArrivalAt: {type: [string, 'null'], format: local-date-time, description: Frozen source-local estimated warehouse arrival; null when Firstleg has no fact}
|
||||||
orders:
|
orders:
|
||||||
type: array
|
type: array
|
||||||
items: {$ref: '#/components/schemas/FirstLegLoadingPlanCompletedOrderV2'}
|
items: {$ref: '#/components/schemas/FirstLegLoadingPlanCompletedOrderV2'}
|
||||||
FirstLegLoadingPlanCompletedOrderV2:
|
FirstLegLoadingPlanCompletedOrderV2:
|
||||||
type: object
|
type: object
|
||||||
required: [sourceInboundId, customerId, customerName, packageCount, items, orderType, pallets, destinationType]
|
required: [sourceInboundId, customerId, customerName, palletCount, packageCount, productQuantity, volumeCbm, volumeWeightKg, items, orderType, pallets, destinationType]
|
||||||
properties:
|
properties:
|
||||||
sourceInboundId: {type: string}
|
sourceInboundId: {type: string}
|
||||||
sourceOrderId: {type: string}
|
sourceOrderId: {type: string}
|
||||||
@@ -29,6 +32,10 @@ components:
|
|||||||
customerId: {type: string, minLength: 1, description: Trusted customer identity frozen by Firstleg}
|
customerId: {type: string, minLength: 1, description: Trusted customer identity frozen by Firstleg}
|
||||||
customerName: {type: string, minLength: 1, maxLength: 128, description: Immutable trusted container/customer name snapshot; consumers must not query domestic IAM}
|
customerName: {type: string, minLength: 1, maxLength: 128, description: Immutable trusted container/customer name snapshot; consumers must not query domestic IAM}
|
||||||
packageCount: {type: integer, minimum: 1}
|
packageCount: {type: integer, minimum: 1}
|
||||||
|
productQuantity: {type: [integer, 'null'], minimum: 0, description: Final loaded product quantity; null when unavailable}
|
||||||
|
palletCount: {type: [integer, 'null'], minimum: 1, description: Distinct physical pallet count from Firstleg allocation pallet identity; never a planned zero placeholder}
|
||||||
|
volumeCbm: {type: [number, 'null'], minimum: 0, description: Final loaded volume in cubic metres}
|
||||||
|
volumeWeightKg: {type: [number, 'null'], minimum: 0, description: Sum of final loaded item dimensional weight facts; null when unavailable}
|
||||||
items: {type: array, items: {type: object}}
|
items: {type: array, items: {type: object}}
|
||||||
orderType: {type: string, enum: [FIRST_LEG, ONE_CLICK_DROPSHIP]}
|
orderType: {type: string, enum: [FIRST_LEG, ONE_CLICK_DROPSHIP]}
|
||||||
pallets: {type: array, items: {type: object}}
|
pallets: {type: array, items: {type: object}}
|
||||||
|
|||||||
+9
-2
@@ -52,13 +52,20 @@ class FirstLegLoadingPlanCompletedV1Test {
|
|||||||
void legacyParserRetainsDestinationTypeWhenV2OrderCarriesIt() throws Exception {
|
void legacyParserRetainsDestinationTypeWhenV2OrderCarriesIt() throws Exception {
|
||||||
String json = """
|
String json = """
|
||||||
{"loadingPlanId":"1","planNo":"LP-1","containerBookingId":"2","containerNo":"CONT-1",
|
{"loadingPlanId":"1","planNo":"LP-1","containerBookingId":"2","containerNo":"CONT-1",
|
||||||
"warehouseId":"3","warehouseName":"海外仓","orders":[{"sourceInboundId":"100",
|
"warehouseId":"3","warehouseName":"海外仓","estimatedPortArrivalAt":"2026-09-30T12:00",
|
||||||
"destinationWarehouseId":"3","packageCount":1,"items":[],"customerId":"9001",
|
"actualPortArrivalAt":null,"estimatedWarehouseArrivalAt":"2026-10-03T09:00",
|
||||||
|
"orders":[{"sourceInboundId":"100","destinationWarehouseId":"3","packageCount":1,
|
||||||
|
"palletCount":2,"volumeWeightKg":12.500,"items":[],"customerId":"9001",
|
||||||
"customerName":"客户甲","destinationType":"OVERSEAS"}]}
|
"customerName":"客户甲","destinationType":"OVERSEAS"}]}
|
||||||
""";
|
""";
|
||||||
|
|
||||||
FirstLegLoadingPlanCompletedV1 restored = mapper.readValue(json, FirstLegLoadingPlanCompletedV1.class);
|
FirstLegLoadingPlanCompletedV1 restored = mapper.readValue(json, FirstLegLoadingPlanCompletedV1.class);
|
||||||
|
|
||||||
assertThat(restored.orders().get(0).destinationType()).isEqualTo("OVERSEAS");
|
assertThat(restored.orders().get(0).destinationType()).isEqualTo("OVERSEAS");
|
||||||
|
assertThat(restored.estimatedPortArrivalAt()).isEqualTo("2026-09-30T12:00");
|
||||||
|
assertThat(restored.actualPortArrivalAt()).isNull();
|
||||||
|
assertThat(restored.estimatedWarehouseArrivalAt()).isEqualTo("2026-10-03T09:00");
|
||||||
|
assertThat(restored.orders().get(0).palletCount()).isEqualTo(2);
|
||||||
|
assertThat(restored.orders().get(0).volumeWeightKg()).isEqualByComparingTo("12.500");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+26
-1
@@ -4,12 +4,35 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
|||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||||
|
|
||||||
class FirstLegLoadingPlanCompletedV2Test {
|
class FirstLegLoadingPlanCompletedV2Test {
|
||||||
|
@Test
|
||||||
|
void carriesOnlyFrozenContainerTimesAndActualOrderAggregates() {
|
||||||
|
var order = new FirstLegLoadingPlanCompletedV2.Order(
|
||||||
|
"2", "2", "3", "ORD", "3", "RK", null, "ONT8", "ONT8",
|
||||||
|
12, 120, 3, null, null, new BigDecimal("2.500"), new BigDecimal("18.750"),
|
||||||
|
List.of(), "11", "客户甲", "FIRST_LEG", List.of(), "OVERSEAS");
|
||||||
|
var payload = new FirstLegLoadingPlanCompletedV2(
|
||||||
|
"4", "P", "5", "CONT", "CAB", "6", "WH",
|
||||||
|
"2026-09-30T12:00", null, "2026-10-03T09:00", List.of(order));
|
||||||
|
|
||||||
|
var json = new ObjectMapper().valueToTree(payload);
|
||||||
|
|
||||||
|
assertThat(json.at("/estimatedPortArrivalAt").asText()).isEqualTo("2026-09-30T12:00");
|
||||||
|
assertThat(json.at("/actualPortArrivalAt").isNull()).isTrue();
|
||||||
|
assertThat(json.at("/estimatedWarehouseArrivalAt").asText()).isEqualTo("2026-10-03T09:00");
|
||||||
|
assertThat(json.at("/orders/0/palletCount").asInt()).isEqualTo(3);
|
||||||
|
assertThat(json.at("/orders/0/packageCount").asInt()).isEqualTo(12);
|
||||||
|
assertThat(json.at("/orders/0/productQuantity").asInt()).isEqualTo(120);
|
||||||
|
assertThat(json.at("/orders/0/volumeCbm").decimalValue()).isEqualByComparingTo("2.500");
|
||||||
|
assertThat(json.at("/orders/0/volumeWeightKg").decimalValue()).isEqualByComparingTo("18.750");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void carriesTheThreeItemRemarks() throws Exception {
|
void carriesTheThreeItemRemarks() throws Exception {
|
||||||
var item = new FirstLegLoadingPlanCompletedV2.Item("1", "SKU", "中文", "EN", 1,
|
var item = new FirstLegLoadingPlanCompletedV2.Item("1", "SKU", "中文", "EN", 1,
|
||||||
@@ -92,6 +115,8 @@ class FirstLegLoadingPlanCompletedV2Test {
|
|||||||
.contains("required: [sourceInboundId, customerId, customerName")
|
.contains("required: [sourceInboundId, customerId, customerName")
|
||||||
.contains("customerId: {type: string, minLength: 1")
|
.contains("customerId: {type: string, minLength: 1")
|
||||||
.contains("customerName: {type: string, minLength: 1, maxLength: 128")
|
.contains("customerName: {type: string, minLength: 1, maxLength: 128")
|
||||||
.contains("consumers must not query domestic IAM");
|
.contains("consumers must not query domestic IAM")
|
||||||
|
.contains("estimatedPortArrivalAt", "actualPortArrivalAt", "estimatedWarehouseArrivalAt")
|
||||||
|
.contains("palletCount", "volumeWeightKg", "never a planned zero placeholder");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import org.apache.ibatis.annotations.Param;
|
|||||||
import org.apache.ibatis.annotations.Select;
|
import org.apache.ibatis.annotations.Select;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/** 读取 PDA 结算后的最终实装入仓单和冻结货物快照。 */
|
/** 读取 PDA 结算后的最终实装入仓单和冻结货物快照。 */
|
||||||
@@ -16,6 +17,8 @@ public interface LoadingCompletedEventMapper {
|
|||||||
SELECT p.id AS loading_plan_id, p.plan_no, p.container_booking_id, p.version AS aggregate_version,
|
SELECT p.id AS loading_plan_id, p.plan_no, p.container_booking_id, p.version AS aggregate_version,
|
||||||
b.container_no, b.cabinet_no, b.warehouse_id, b.warehouse_name,
|
b.container_no, b.cabinet_no, b.warehouse_id, b.warehouse_name,
|
||||||
b.customer_id AS booking_customer_id, b.customer_name,
|
b.customer_id AS booking_customer_id, b.customer_name,
|
||||||
|
b.estimated_port_arrival_at, b.actual_port_arrival_at,
|
||||||
|
b.estimated_warehouse_arrival_at,
|
||||||
i.account_id, i.inbound_id AS source_inbound_id,
|
i.account_id, i.inbound_id AS source_inbound_id,
|
||||||
COALESCE(o.root_inbound_id, o.id) AS root_inbound_id,
|
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,
|
o.order_id AS source_order_id, o.order_no AS source_order_no,
|
||||||
@@ -50,7 +53,8 @@ public interface LoadingCompletedEventMapper {
|
|||||||
/** 读取一键代发托盘及其箱唛快照;普通订单不会使用该结果。 */
|
/** 读取一键代发托盘及其箱唛快照;普通订单不会使用该结果。 */
|
||||||
@Select("""
|
@Select("""
|
||||||
SELECT i.account_id, i.inbound_id AS source_inbound_id,
|
SELECT i.account_id, i.inbound_id AS source_inbound_id,
|
||||||
a.pallet_code, a.allocation_no, a.picked_package_count AS allocated_package_count,
|
a.pallet_id, a.reservation_id, a.pallet_code, a.allocation_no,
|
||||||
|
a.picked_package_count AS allocated_package_count,
|
||||||
i.inbound_detail_id AS source_inbound_detail_id, i.sku_code,
|
i.inbound_detail_id AS source_inbound_detail_id, i.sku_code,
|
||||||
i.product_name_zh, i.package_count, i.product_quantity,
|
i.product_name_zh, i.package_count, i.product_quantity,
|
||||||
label.box_code
|
label.box_code
|
||||||
@@ -82,6 +86,8 @@ public interface LoadingCompletedEventMapper {
|
|||||||
private Integer aggregateVersion; private String containerNo; private String cabinetNo;
|
private Integer aggregateVersion; private String containerNo; private String cabinetNo;
|
||||||
private Long warehouseId; private String warehouseName; private Long bookingCustomerId;
|
private Long warehouseId; private String warehouseName; private Long bookingCustomerId;
|
||||||
private String customerName; private Long accountId;
|
private String customerName; private Long accountId;
|
||||||
|
private LocalDateTime estimatedPortArrivalAt; private LocalDateTime actualPortArrivalAt;
|
||||||
|
private LocalDateTime estimatedWarehouseArrivalAt;
|
||||||
private Long sourceInboundId; private Long rootInboundId; private Long sourceOrderId;
|
private Long sourceInboundId; private Long rootInboundId; private Long sourceOrderId;
|
||||||
private Long loadingPlanItemId;
|
private Long loadingPlanItemId;
|
||||||
private String sourceOrderNo; private Long rootOrderId; private String inboundCode;
|
private String sourceOrderNo; private Long rootOrderId; private String inboundCode;
|
||||||
@@ -97,7 +103,8 @@ public interface LoadingCompletedEventMapper {
|
|||||||
|
|
||||||
@Getter @Setter
|
@Getter @Setter
|
||||||
class PalletRow {
|
class PalletRow {
|
||||||
private Long accountId; private Long sourceInboundId; private String palletCode;
|
private Long accountId; private Long sourceInboundId; private Long palletId;
|
||||||
|
private Long reservationId; private String palletCode;
|
||||||
private Integer allocationNo; private Integer allocatedPackageCount;
|
private Integer allocationNo; private Integer allocatedPackageCount;
|
||||||
private Long sourceInboundDetailId; private String skuCode; private String productNameZh;
|
private Long sourceInboundDetailId; private String skuCode; private String productNameZh;
|
||||||
private Integer packageCount; private Integer productQuantity; private String boxCode;
|
private Integer packageCount; private Integer productQuantity; private String boxCode;
|
||||||
|
|||||||
+14
-4
@@ -68,7 +68,8 @@ public class LoadingCompletedOutboxService {
|
|||||||
.filter(item -> Objects.equals(item.getSourceInboundId(), value.get(0).getSourceInboundId())).toList(), cartonMarks)).toList();
|
.filter(item -> Objects.equals(item.getSourceInboundId(), value.get(0).getSourceInboundId())).toList(), cartonMarks)).toList();
|
||||||
var payload = new FirstLegLoadingPlanCompletedV2(String.valueOf(first.getLoadingPlanId()),
|
var payload = new FirstLegLoadingPlanCompletedV2(String.valueOf(first.getLoadingPlanId()),
|
||||||
first.getPlanNo(), string(first.getContainerBookingId()), first.getContainerNo(), first.getCabinetNo(),
|
first.getPlanNo(), string(first.getContainerBookingId()), first.getContainerNo(), first.getCabinetNo(),
|
||||||
string(first.getWarehouseId()), first.getWarehouseName(), orders);
|
string(first.getWarehouseId()), first.getWarehouseName(), iso(first.getEstimatedPortArrivalAt()),
|
||||||
|
iso(first.getActualPortArrivalAt()), iso(first.getEstimatedWarehouseArrivalAt()), orders);
|
||||||
JsonNode payloadNode = objectMapper.valueToTree(payload);
|
JsonNode payloadNode = objectMapper.valueToTree(payload);
|
||||||
String hash = EventPayloadHash.sha256(EventPayloadCanonicalizer.canonicalize(payloadNode));
|
String hash = EventPayloadHash.sha256(EventPayloadCanonicalizer.canonicalize(payloadNode));
|
||||||
String eventKey = "FIRSTLEG_LOADING_COMPLETED:" + first.getLoadingPlanId() + ':' + accountId + ':' + HANDOVER_VERSION;
|
String eventKey = "FIRSTLEG_LOADING_COMPLETED:" + first.getLoadingPlanId() + ':' + accountId + ':' + HANDOVER_VERSION;
|
||||||
@@ -103,12 +104,20 @@ public class LoadingCompletedOutboxService {
|
|||||||
string(first.getRootInboundId()), string(first.getSourceOrderId()), first.getSourceOrderNo(),
|
string(first.getRootInboundId()), string(first.getSourceOrderId()), first.getSourceOrderNo(),
|
||||||
string(first.getRootOrderId()), first.getInboundCode(), string(first.getDestinationWarehouseId()),
|
string(first.getRootOrderId()), first.getInboundCode(), string(first.getDestinationWarehouseId()),
|
||||||
first.getDestinationWarehouseCode(), first.getDestinationWarehouseName(), sumInt(sorted, Row::getPackageCount),
|
first.getDestinationWarehouseCode(), first.getDestinationWarehouseName(), sumInt(sorted, Row::getPackageCount),
|
||||||
sumNullableInt(sorted, Row::getProductQuantity), "ONE_CLICK_DROPSHIP".equals(orderType)
|
sumNullableInt(sorted, Row::getProductQuantity), actualPalletCount(palletRows),
|
||||||
? pallets.size() : 0, sum(sorted, Row::getGrossWeightKg), sum(sorted, Row::getNetWeightKg),
|
sum(sorted, Row::getGrossWeightKg), sum(sorted, Row::getNetWeightKg),
|
||||||
sum(sorted, Row::getVolumeCbm), items, string(first.getAccountId()), first.getCustomerName().trim(), orderType, pallets,
|
sum(sorted, Row::getVolumeCbm), sum(sorted, Row::getDimensionalWeightKg), items,
|
||||||
|
string(first.getAccountId()), first.getCustomerName().trim(), orderType, pallets,
|
||||||
destinationType(sorted));
|
destinationType(sorted));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 只按 Warehouse 已分配的物理 palletId 计数;无分配事实时保持 null。 */
|
||||||
|
private static Integer actualPalletCount(List<PalletRow> palletRows) {
|
||||||
|
Set<Long> palletIds = palletRows.stream().map(PalletRow::getPalletId)
|
||||||
|
.filter(Objects::nonNull).filter(value -> value > 0).collect(java.util.stream.Collectors.toSet());
|
||||||
|
return palletIds.isEmpty() ? null : palletIds.size();
|
||||||
|
}
|
||||||
|
|
||||||
private void validateCustomerSnapshots(List<Row> rows) {
|
private void validateCustomerSnapshots(List<Row> rows) {
|
||||||
for (Row row : rows) {
|
for (Row row : rows) {
|
||||||
if (row.getAccountId() == null || !Objects.equals(row.getAccountId(), row.getBookingCustomerId())) {
|
if (row.getAccountId() == null || !Objects.equals(row.getAccountId(), row.getBookingCustomerId())) {
|
||||||
@@ -275,6 +284,7 @@ public class LoadingCompletedOutboxService {
|
|||||||
private String json(Object value) { try { return objectMapper.writeValueAsString(value); }
|
private String json(Object value) { try { return objectMapper.writeValueAsString(value); }
|
||||||
catch (JsonProcessingException e) { throw new BizException(ResultCode.INTERNAL_ERROR, "装柜完成事件序列化失败"); } }
|
catch (JsonProcessingException e) { throw new BizException(ResultCode.INTERNAL_ERROR, "装柜完成事件序列化失败"); } }
|
||||||
private static String string(Long value) { return value == null ? null : String.valueOf(value); }
|
private static String string(Long value) { return value == null ? null : String.valueOf(value); }
|
||||||
|
private static String iso(java.time.LocalDateTime value) { return value == null ? null : value.toString(); }
|
||||||
private static int sumInt(List<Row> rows, java.util.function.Function<Row,Integer> getter) { return rows.stream().map(getter).filter(java.util.Objects::nonNull).mapToInt(Integer::intValue).sum(); }
|
private static int sumInt(List<Row> rows, java.util.function.Function<Row,Integer> getter) { return rows.stream().map(getter).filter(java.util.Objects::nonNull).mapToInt(Integer::intValue).sum(); }
|
||||||
private static Integer sumNullableInt(List<Row> rows, java.util.function.Function<Row,Integer> getter) { List<Integer> values=rows.stream().map(getter).filter(java.util.Objects::nonNull).toList(); return values.isEmpty()?null:values.stream().mapToInt(Integer::intValue).sum(); }
|
private static Integer sumNullableInt(List<Row> rows, java.util.function.Function<Row,Integer> getter) { List<Integer> values=rows.stream().map(getter).filter(java.util.Objects::nonNull).toList(); return values.isEmpty()?null:values.stream().mapToInt(Integer::intValue).sum(); }
|
||||||
private static BigDecimal sum(List<Row> rows, java.util.function.Function<Row,BigDecimal> getter) { List<BigDecimal> values=rows.stream().map(getter).filter(java.util.Objects::nonNull).toList(); return values.isEmpty()?null:values.stream().reduce(BigDecimal.ZERO, BigDecimal::add); }
|
private static BigDecimal sum(List<Row> rows, java.util.function.Function<Row,BigDecimal> getter) { List<BigDecimal> values=rows.stream().map(getter).filter(java.util.Objects::nonNull).toList(); return values.isEmpty()?null:values.stream().reduce(BigDecimal.ZERO, BigDecimal::add); }
|
||||||
|
|||||||
+44
-2
@@ -45,6 +45,10 @@ class LoadingCompletedOutboxServiceTest {
|
|||||||
|
|
||||||
@Test void groupsByAccountAndKeepsAllOrdersAndItemsStable() throws Exception {
|
@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.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);
|
service.publish(90L);
|
||||||
ArgumentCaptor<InboundOutboxEntity> captor=ArgumentCaptor.forClass(InboundOutboxEntity.class);
|
ArgumentCaptor<InboundOutboxEntity> captor=ArgumentCaptor.forClass(InboundOutboxEntity.class);
|
||||||
verify(outbox,org.mockito.Mockito.times(2)).insert(captor.capture());
|
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/items/0/cartonMarks/0").asText()).isEqualTo("BOX-101");
|
||||||
assertThat(first.payload().at("/orders/0/destinationType").asText()).isEqualTo("OVERSEAS");
|
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/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(rows.get(0).getEventKey()).isEqualTo("FIRSTLEG_LOADING_COMPLETED:90:11:2");
|
||||||
assertThat(first.eventVersion()).isEqualTo(2);
|
assertThat(first.eventVersion()).isEqualTo(2);
|
||||||
}
|
}
|
||||||
@@ -148,6 +160,28 @@ class LoadingCompletedOutboxServiceTest {
|
|||||||
.isNotEqualTo(captor.getAllValues().get(1).getPayloadHash());
|
.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 {
|
@Test void fillsCollapsedMeasurementDetailFromUnusedInboundLabelsWithoutDuplicates() throws Exception {
|
||||||
Row first = row(11, 100, 101); first.setPackageCount(1);
|
Row first = row(11, 100, 101); first.setPackageCount(1);
|
||||||
Row second = row(11, 100, 101); second.setLoadingPlanItemId(102L); second.setPackageCount(2);
|
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'")
|
assertThat(rowsSql).contains("p.plan_status = 'COMPLETED'")
|
||||||
.contains("o.process_status = 'LOADED'")
|
.contains("o.process_status = 'LOADED'")
|
||||||
.contains("b.customer_id AS booking_customer_id")
|
.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)) {
|
for (String sql : List.of(rowsSql, palletsSql)) {
|
||||||
assertThat(sql)
|
assertThat(sql)
|
||||||
.contains("actual_pick.loading_plan_item_id = i.id")
|
.contains("actual_pick.loading_plan_item_id = i.id")
|
||||||
@@ -190,6 +226,7 @@ class LoadingCompletedOutboxServiceTest {
|
|||||||
.doesNotContain("'PICKING'");
|
.doesNotContain("'PICKING'");
|
||||||
}
|
}
|
||||||
assertThat(palletsSql)
|
assertThat(palletsSql)
|
||||||
|
.contains("a.pallet_id", "a.reservation_id")
|
||||||
.contains("label.tenant_id = i.account_id")
|
.contains("label.tenant_id = i.account_id")
|
||||||
.contains("label.inbound_detail_id = i.inbound_detail_id")
|
.contains("label.inbound_detail_id = i.inbound_detail_id")
|
||||||
.contains("label.batch_status = 'ACTIVE'")
|
.contains("label.batch_status = 'ACTIVE'")
|
||||||
@@ -252,6 +289,9 @@ class LoadingCompletedOutboxServiceTest {
|
|||||||
Row r=new Row(); r.setLoadingPlanId(90L); r.setPlanNo("P90"); r.setContainerBookingId(91L);
|
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.setAggregateVersion(8); r.setContainerNo("CONT"); r.setCabinetNo("CAB"); r.setWarehouseId(92L);
|
||||||
r.setWarehouseName("WH"); r.setBookingCustomerId(account); r.setCustomerName("客户-" + account);
|
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.setAccountId(account); r.setSourceInboundId(inbound); r.setRootInboundId(99L);
|
||||||
r.setSourceOrderId(inbound+1000); r.setSourceOrderNo("FL"+inbound); r.setRootOrderId(1099L);
|
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.setInboundCode("RK"+inbound); r.setLoadingPlanItemId(detail); r.setDestinationWarehouseId(93L); r.setDestinationWarehouseCode("ONT8");
|
||||||
@@ -259,13 +299,15 @@ class LoadingCompletedOutboxServiceTest {
|
|||||||
r.setDestinationType("OVERSEAS");
|
r.setDestinationType("OVERSEAS");
|
||||||
r.setFulfillmentType("STANDARD");
|
r.setFulfillmentType("STANDARD");
|
||||||
r.setPackageCount(1); r.setProductQuantity(10); r.setPalletCount(1); r.setGrossWeightKg(BigDecimal.ONE);
|
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,
|
private PalletRow pallet(long account,long inbound,int allocation,String palletNo,int allocated,
|
||||||
long detail,String sku,int packages,int quantity,String boxCode) {
|
long detail,String sku,int packages,int quantity,String boxCode) {
|
||||||
PalletRow row = new PalletRow(); row.setAccountId(account); row.setSourceInboundId(inbound);
|
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.setAllocationNo(allocation); row.setPalletCode(palletNo); row.setAllocatedPackageCount(allocated);
|
||||||
row.setSourceInboundDetailId(detail); row.setSkuCode(sku); row.setProductNameZh("产品");
|
row.setSourceInboundDetailId(detail); row.setSkuCode(sku); row.setProductNameZh("产品");
|
||||||
row.setPackageCount(packages); row.setProductQuantity(quantity); row.setBoxCode(boxCode); return row;
|
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 org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||||
|
|
||||||
@SpringBootTest(classes = TaillegRealProducerAcceptanceTest.AcceptanceApplication.class,
|
@SpringBootTest(classes = TaillegRealProducerAcceptanceTest.AcceptanceApplication.class,
|
||||||
webEnvironment = SpringBootTest.WebEnvironment.NONE, properties = {
|
webEnvironment = SpringBootTest.WebEnvironment.NONE, properties = {
|
||||||
@@ -53,13 +54,26 @@ class TaillegRealProducerAcceptanceTest {
|
|||||||
assertEquals("真实验收客户", jdbc.queryForObject(
|
assertEquals("真实验收客户", jdbc.queryForObject(
|
||||||
"SELECT JSON_UNQUOTE(JSON_EXTRACT(payload_json,'$.payload.orders[0].customerName')) " +
|
"SELECT JSON_UNQUOTE(JSON_EXTRACT(payload_json,'$.payload.orders[0].customerName')) " +
|
||||||
"FROM fl_inbound_outbox WHERE event_key=?", String.class, eventKey));
|
"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() {
|
private void seedCompletedLoadingPlan() {
|
||||||
jdbc.update("INSERT IGNORE INTO fl_container_booking(id,booking_no,container_no,cabinet_no,warehouse_id," +
|
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, "真实验收海外仓",
|
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," +
|
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);
|
"updated_by,version) VALUES(?,?,?,'LOADING',1,1,0)", PLAN, MARKER + "-PLAN", BOOKING);
|
||||||
seedInbound(FIRST_INBOUND, 990022221L, MARKER + "-FIRST-IN", "FBA_SEA", "STANDARD", "LOADED", "ONT8");
|
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);
|
MARKER + "-FIRST-IN", "FIRST-BOX-" + i, i, 3);
|
||||||
for (int i = 1; i <= 2; i++) seedLabel(990022550L + i, DROPSHIP_INBOUND, 990022222L, 990022422L,
|
for (int i = 1; i <= 2; i++) seedLabel(990022550L + i, DROPSHIP_INBOUND, 990022222L, 990022422L,
|
||||||
MARKER + "-DROP-IN", "DROP-BOX-" + i, i, 2);
|
MARKER + "-DROP-IN", "DROP-BOX-" + i, i, 2);
|
||||||
jdbc.update("INSERT IGNORE INTO fl_inbound_pallet_allocation(id,tenant_id,inbound_id,allocation_no," +
|
seedAllocation(990022620L, FIRST_INBOUND, 990022720L, 990022820L, 3, "F");
|
||||||
"warehouse_id,warehouse_resource_tenant_id,pallet_id,pallet_code,pallet_capacity_cbm," +
|
seedAllocation(990022621L, DROPSHIP_INBOUND, 990022721L, 990022821L, 2, "D");
|
||||||
"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");
|
|
||||||
jdbc.update("INSERT INTO fl_loading_pick_task(id,loading_plan_id,container_booking_id,cabinet_no," +
|
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,'真实验收')",
|
"container_no,task_status,started_by,started_by_name) VALUES(?,?,?,?,?,'LOADING',1,'真实验收')",
|
||||||
990022901L, PLAN, BOOKING, MARKER + "-CAB", MARKER + "-CNTR");
|
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);
|
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) {
|
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," +
|
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')",
|
"inbound_detail_id,planned_package_count,picked_package_count,item_status) VALUES(?,?,?,?,?,?,?,'PICKED')",
|
||||||
|
|||||||
Reference in New Issue
Block a user