feat: explain supplemental pallet counts
This commit is contained in:
@@ -18,6 +18,8 @@
|
||||
|
||||
人工计划自动生成托盘与资源重试:`inboundplan/controller/InboundPlanController.java` → `inboundplan/service/ContainerInboundPlanConversionCoordinator.java` 的 `convertManualAndAutoMaterialize`;保存单票后重读全柜预览,全员为 `PLANNED/RESOURCE_PENDING`、预览就绪且存在待绑定资源时自动调用柜级 `confirm`。一票柜立即触发,多票柜在最后一票齐全后触发;资源异常沿 `resourcePendingPlanCount` 和原柜级预览/确认入口重试,不新增独立正常人工步骤。回归入口为 `src/test/java/com/baiyue/lastleg/inboundplan/service/ContainerInboundPlanConversionCoordinatorTest.java`。
|
||||
|
||||
柜级预览同时返回 `sourcePalletCount/supplementPalletCount/targetPalletCount`:头程冻结托盘码原样保留,海外仓最终托数较多时按同柜同 FBA 编码序列补足差额,不因头尾装托密度不同阻断;页面必须分别展示头程已有、海外补充和最终托数,不能把最终总数误称为“本次新增”。
|
||||
|
||||
头程来源托盘快照:`service/LoadingCompletedConsumer.java`、`mapper/LastlegSourcePalletMapper.java`;来源标签随装柜完成事件落入 `ll_order_source_pallet`,后续由 `inboundplan/service/InboundPlanService.java` 与 `ContainerInboundPlanConversionCoordinator.java` 传递给海外资源批量预留。排查标签跨区丢失时沿此链路核对,不能在尾程页面重新生成头程托盘码。
|
||||
|
||||
| 功能 | 入口 |
|
||||
|
||||
+7
@@ -17,6 +17,8 @@ public record ContainerInboundPlanPreviewResponse(
|
||||
int blockedOrderCount,
|
||||
int pendingOrderCount,
|
||||
int pendingPalletCount,
|
||||
int sourcePalletCount,
|
||||
int supplementPalletCount,
|
||||
int existingPlannedPalletCount,
|
||||
int totalSuggestedPalletCount,
|
||||
int totalPlannedPalletCount,
|
||||
@@ -31,6 +33,8 @@ public record ContainerInboundPlanPreviewResponse(
|
||||
int orderCount,
|
||||
int pendingOrderCount,
|
||||
int pendingPalletCount,
|
||||
int sourcePalletCount,
|
||||
int supplementPalletCount,
|
||||
int existingPlannedPalletCount,
|
||||
int suggestedPalletCount,
|
||||
int plannedPalletCount,
|
||||
@@ -52,6 +56,9 @@ public record ContainerInboundPlanPreviewResponse(
|
||||
int packageCount,
|
||||
BigDecimal volumeCbm,
|
||||
Integer suggestedPalletCount,
|
||||
int sourcePalletCount,
|
||||
int targetPalletCount,
|
||||
int supplementPalletCount,
|
||||
Integer plannedPalletCount,
|
||||
String existingPlanNo,
|
||||
String planStatus,
|
||||
|
||||
+4
-2
@@ -27,7 +27,7 @@ public interface InboundPlanOrderMapper {
|
||||
String overseasWarehouseName, String fbaWarehouseCode, String destinationWarehouseId,
|
||||
String destinationWarehouseCode, String destinationWarehouseName, int destinationCount,
|
||||
boolean detained, int version, String planNo, String planStatus,
|
||||
Integer plannedPalletCount, Integer materializedPalletCount
|
||||
Integer plannedPalletCount, Integer materializedPalletCount, Integer sourcePalletCount
|
||||
) { }
|
||||
|
||||
@Select("SELECT o.customer_id AS customerId,o.id AS orderId,o.order_no AS orderNo," +
|
||||
@@ -45,7 +45,9 @@ public interface InboundPlanOrderMapper {
|
||||
"o.detained AS detained,o.version AS version,p.plan_no AS planNo,p.status AS planStatus," +
|
||||
"p.pallet_count AS plannedPalletCount," +
|
||||
"(SELECT COUNT(*) FROM ll_inbound_plan_pallet pp WHERE pp.customer_id=p.customer_id " +
|
||||
"AND pp.plan_id=p.id AND pp.warehouse_pallet_id IS NOT NULL) AS materializedPalletCount " +
|
||||
"AND pp.plan_id=p.id AND pp.warehouse_pallet_id IS NOT NULL) AS materializedPalletCount," +
|
||||
"(SELECT COUNT(*) FROM ll_order_source_pallet sp WHERE sp.customer_id=o.customer_id " +
|
||||
"AND sp.order_id=o.id) AS sourcePalletCount " +
|
||||
"FROM ll_order o LEFT JOIN ll_inbound_plan p ON p.customer_id=o.customer_id AND p.source_order_id=o.id " +
|
||||
"WHERE o.source_container_booking_id=#{sourceContainerBookingId} ORDER BY o.customer_id,o.id")
|
||||
List<ContainerPreviewOrderRow> containerPreviewOrders(
|
||||
|
||||
+18
-5
@@ -207,6 +207,10 @@ public class InboundPlanService {
|
||||
items.stream().filter(InboundPlanService::requiresContainerConversion)
|
||||
.map(InboundPlanService::pendingPalletCount)
|
||||
.filter(Objects::nonNull).mapToInt(Integer::intValue).sum(),
|
||||
items.stream().filter(InboundPlanService::requiresContainerConversion)
|
||||
.mapToInt(ContainerInboundPlanPreviewResponse.Order::sourcePalletCount).sum(),
|
||||
items.stream().filter(InboundPlanService::requiresContainerConversion)
|
||||
.mapToInt(ContainerInboundPlanPreviewResponse.Order::supplementPalletCount).sum(),
|
||||
items.stream().filter(item -> "PLANNED".equals(item.readiness()))
|
||||
.map(ContainerInboundPlanPreviewResponse.Order::plannedPalletCount)
|
||||
.filter(Objects::nonNull).mapToInt(Integer::intValue).sum(),
|
||||
@@ -220,6 +224,10 @@ public class InboundPlanService {
|
||||
int pendingPallets = orders.stream().filter(InboundPlanService::requiresContainerConversion)
|
||||
.map(InboundPlanService::pendingPalletCount)
|
||||
.filter(Objects::nonNull).mapToInt(Integer::intValue).sum();
|
||||
int sourcePallets = orders.stream().filter(InboundPlanService::requiresContainerConversion)
|
||||
.mapToInt(ContainerInboundPlanPreviewResponse.Order::sourcePalletCount).sum();
|
||||
int supplementPallets = orders.stream().filter(InboundPlanService::requiresContainerConversion)
|
||||
.mapToInt(ContainerInboundPlanPreviewResponse.Order::supplementPalletCount).sum();
|
||||
int existingPallets = orders.stream().filter(item -> "PLANNED".equals(item.readiness()))
|
||||
.map(ContainerInboundPlanPreviewResponse.Order::plannedPalletCount)
|
||||
.filter(Objects::nonNull).mapToInt(Integer::intValue).sum();
|
||||
@@ -228,7 +236,7 @@ public class InboundPlanService {
|
||||
bookingId, containerNo, warehouseId, snapshotVersion, orders));
|
||||
return new ContainerInboundPlanPreviewResponse(bookingId, containerNo, warehouseId, warehouseCode,
|
||||
warehouseName, snapshotVersion, snapshotHash, orders.size(), orders.size() - blocked, blocked,
|
||||
pendingOrders, pendingPallets, existingPallets,
|
||||
pendingOrders, pendingPallets, sourcePallets, supplementPallets, existingPallets,
|
||||
orders.stream().map(ContainerInboundPlanPreviewResponse.Order::suggestedPalletCount)
|
||||
.filter(Objects::nonNull).mapToInt(Integer::intValue).sum(),
|
||||
orders.stream().map(ContainerInboundPlanPreviewResponse.Order::plannedPalletCount)
|
||||
@@ -258,6 +266,12 @@ public class InboundPlanService {
|
||||
|| row.packageCount() > 0 && row.volumeCbm().signum() == 0) blockers.add("CARGO_FACT_INVALID");
|
||||
}
|
||||
Integer suggested = suggestedPalletCount(row, blockers);
|
||||
int sourcePalletCount = "ONE_CLICK_DROPSHIP".equals(row.orderType())
|
||||
? Objects.requireNonNullElse(suggested, 0)
|
||||
: Objects.requireNonNullElse(row.sourcePalletCount(), 0);
|
||||
int targetPalletCount = Objects.requireNonNullElse(row.plannedPalletCount(),
|
||||
Objects.requireNonNullElse(suggested, 0));
|
||||
int supplementPalletCount = Math.max(0, targetPalletCount - sourcePalletCount);
|
||||
if (!planned && (suggested == null || suggested <= 0)) blockers.add("PALLET_COUNT_NOT_READY");
|
||||
String destinationType = destinationType(row);
|
||||
String fbaWarehouseCode = isFbaDestination(row) ? trimToNull(row.fbaWarehouseCode()) : null;
|
||||
@@ -281,7 +295,8 @@ public class InboundPlanService {
|
||||
String.valueOf(row.orderId()), trimToNull(row.orderNo()) == null ? row.sourceOrderNo() : row.orderNo(),
|
||||
row.inboundCode(), row.orderType(), destinationType, row.destinationWarehouseId(),
|
||||
destinationCode, row.destinationWarehouseName(), fbaWarehouseCode, row.packageCount(), row.volumeCbm(),
|
||||
suggested, row.plannedPalletCount(), row.planNo(), row.planStatus(), row.version(), readiness,
|
||||
suggested, sourcePalletCount, targetPalletCount, supplementPalletCount,
|
||||
row.plannedPalletCount(), row.planNo(), row.planStatus(), row.version(), readiness,
|
||||
List.copyOf(blockers));
|
||||
}
|
||||
|
||||
@@ -321,9 +336,7 @@ public class InboundPlanService {
|
||||
}
|
||||
|
||||
private static Integer pendingPalletCount(ContainerInboundPlanPreviewResponse.Order order) {
|
||||
return "RESOURCE_PENDING".equals(order.readiness())
|
||||
? Objects.requireNonNullElse(order.plannedPalletCount(), 0)
|
||||
: Objects.requireNonNullElse(order.suggestedPalletCount(), 0);
|
||||
return order.targetPalletCount();
|
||||
}
|
||||
|
||||
private static String destinationType(InboundPlanOrderMapper.ContainerPreviewOrderRow row) {
|
||||
|
||||
@@ -169,7 +169,7 @@ paths:
|
||||
/api/platform/v1/last-leg/orders:
|
||||
get:
|
||||
summary: 分页查询尾程订单
|
||||
description: 权限 platform:overseas-warehouse:last-mile-order:list;平台管理员省略 customerId 时查询全部客户。
|
||||
description: 权限 platform:overseas-warehouse:last-mile-order:list;平台管理员省略 customerId 时查询全部客户。containerNode 来自稳定 sourceContainerBookingId 对应的柜级船节点门禁。
|
||||
security: [{ bearerAuth: [] }]
|
||||
parameters:
|
||||
- { name: page, in: query, schema: { type: integer, minimum: 1, default: 1 } }
|
||||
@@ -190,7 +190,7 @@ paths:
|
||||
/api/platform/v1/last-leg/orders/{id}:
|
||||
get:
|
||||
summary: 查询尾程订单详情
|
||||
description: 权限 platform:overseas-warehouse:last-mile-order:list;返回订单、货物、状态历史、费用明细和操作记录。
|
||||
description: 权限 platform:overseas-warehouse:last-mile-order:list;返回订单、货物、状态历史、费用明细和操作记录。订单中的 containerNode 来自稳定 sourceContainerBookingId 对应的柜级船节点门禁。
|
||||
security: [{ bearerAuth: [] }]
|
||||
parameters:
|
||||
- { name: id, in: path, required: true, schema: { type: integer, format: int64 } }
|
||||
@@ -2806,7 +2806,7 @@ components:
|
||||
version: { type: integer }
|
||||
ContainerInboundPlanPreview:
|
||||
type: object
|
||||
required: [sourceContainerBookingId, snapshotVersion, snapshotHash, totalOrderCount, readyOrderCount, blockedOrderCount, pendingOrderCount, pendingPalletCount, existingPlannedPalletCount, totalSuggestedPalletCount, totalPlannedPalletCount, ready, groups]
|
||||
required: [sourceContainerBookingId, snapshotVersion, snapshotHash, totalOrderCount, readyOrderCount, blockedOrderCount, pendingOrderCount, pendingPalletCount, sourcePalletCount, supplementPalletCount, existingPlannedPalletCount, totalSuggestedPalletCount, totalPlannedPalletCount, ready, groups]
|
||||
properties:
|
||||
sourceContainerBookingId: { type: string }
|
||||
containerNo: { type: string, nullable: true }
|
||||
@@ -2819,7 +2819,9 @@ components:
|
||||
readyOrderCount: { type: integer }
|
||||
blockedOrderCount: { type: integer }
|
||||
pendingOrderCount: { type: integer, description: 本次确认将新建计划的 READY 订单数 }
|
||||
pendingPalletCount: { type: integer, description: 本次确认将向资源服务批量预留的新托盘数 }
|
||||
pendingPalletCount: { type: integer, description: 本次确认最终向资源服务批量预留的托盘总数,包含头程已有编码及海外补充编码 }
|
||||
sourcePalletCount: { type: integer, description: 本次处理订单随头程装柜完成事件冻结并传入的托盘码数 }
|
||||
supplementPalletCount: { type: integer, description: 最终托数超过头程已有托盘码数时,在海外仓连续补充的托盘码数 }
|
||||
existingPlannedPalletCount: { type: integer, description: 已有有效计划的托盘总数,不计入本次新增 }
|
||||
totalSuggestedPalletCount: { type: integer }
|
||||
totalPlannedPalletCount: { type: integer }
|
||||
@@ -2827,7 +2829,7 @@ components:
|
||||
groups: { type: array, items: { $ref: '#/components/schemas/ContainerInboundPlanPreviewGroup' } }
|
||||
ContainerInboundPlanPreviewGroup:
|
||||
type: object
|
||||
required: [destinationType, orderCount, pendingOrderCount, pendingPalletCount, existingPlannedPalletCount, suggestedPalletCount, plannedPalletCount, orders]
|
||||
required: [destinationType, orderCount, pendingOrderCount, pendingPalletCount, sourcePalletCount, supplementPalletCount, existingPlannedPalletCount, suggestedPalletCount, plannedPalletCount, orders]
|
||||
properties:
|
||||
destinationType: { type: string, enum: [FBA, ONE_CLICK_DROPSHIP, PRIVATE_ADDRESS] }
|
||||
destinationWarehouseId: { type: string, nullable: true }
|
||||
@@ -2836,13 +2838,15 @@ components:
|
||||
orderCount: { type: integer }
|
||||
pendingOrderCount: { type: integer }
|
||||
pendingPalletCount: { type: integer }
|
||||
sourcePalletCount: { type: integer }
|
||||
supplementPalletCount: { type: integer }
|
||||
existingPlannedPalletCount: { type: integer }
|
||||
suggestedPalletCount: { type: integer }
|
||||
plannedPalletCount: { type: integer }
|
||||
orders: { type: array, items: { $ref: '#/components/schemas/ContainerInboundPlanPreviewOrder' } }
|
||||
ContainerInboundPlanPreviewOrder:
|
||||
type: object
|
||||
required: [customerId, orderId, businessOrderNo, orderType, destinationType, packageCount, volumeCbm, orderVersion, readiness, blockers]
|
||||
required: [customerId, orderId, businessOrderNo, orderType, destinationType, packageCount, volumeCbm, sourcePalletCount, targetPalletCount, supplementPalletCount, orderVersion, readiness, blockers]
|
||||
properties:
|
||||
customerId: { type: string }
|
||||
customerName: { type: string, nullable: true }
|
||||
@@ -2858,11 +2862,14 @@ components:
|
||||
packageCount: { type: integer }
|
||||
volumeCbm: { type: number }
|
||||
suggestedPalletCount: { type: integer, nullable: true }
|
||||
sourcePalletCount: { type: integer, description: 头程已经冻结并传入的托盘码数 }
|
||||
targetPalletCount: { type: integer, description: 本票最终生成的托盘总数,不少于头程已有托盘码数 }
|
||||
supplementPalletCount: { type: integer, description: 本票需要在海外仓连续补充的托盘码数 }
|
||||
plannedPalletCount: { type: integer, nullable: true }
|
||||
existingPlanNo: { type: string, nullable: true }
|
||||
planStatus: { type: string, nullable: true }
|
||||
orderVersion: { type: integer, minimum: 0 }
|
||||
readiness: { type: string, enum: [READY, PLANNED, BLOCKED] }
|
||||
readiness: { type: string, enum: [READY, RESOURCE_PENDING, PLANNED, BLOCKED] }
|
||||
blockers: { type: array, items: { type: string } }
|
||||
InboundPlanLine:
|
||||
type: object
|
||||
|
||||
+19
-18
@@ -87,7 +87,7 @@ class ContainerInboundPlanConversionCoordinatorTest {
|
||||
var ready = new ContainerInboundPlanPreviewResponse.Order(
|
||||
"200", "Customer 200", "12", "LM-12", "RK-2", "FIRST_LEG", "FBA",
|
||||
null, "ONT8", "Amazon ONT8", "ONT8", 10, BigDecimal.ONE, 1,
|
||||
null, null, null, 0, "READY", List.of());
|
||||
0, 1, 1, null, null, null, 0, "READY", List.of());
|
||||
when(plans.convertManual(request, "manual-key", "7")).thenReturn(logical);
|
||||
when(plans.sourceContainerBookingId("100", 11L)).thenReturn(BOOKING_ID);
|
||||
when(plans.previewContainer(BOOKING_ID)).thenReturn(manualPreview(List.of(resourcePendingOrder(), ready)));
|
||||
@@ -272,11 +272,11 @@ class ContainerInboundPlanConversionCoordinatorTest {
|
||||
var fba = previewOrder("100", "11", "RK-FBA", "ABE3", "ABE3");
|
||||
var overseas = previewOrder("200", "12", "RK-OVERSEAS", "US-LAX-01", null);
|
||||
var preview = new ContainerInboundPlanPreviewResponse(BOOKING_ID, "MSCU6639870", "31", "US-LAX-01",
|
||||
"Los Angeles", 7L, SNAPSHOT_HASH, 2, 2, 0, 2, 2, 0, 2, 0, true,
|
||||
"Los Angeles", 7L, SNAPSHOT_HASH, 2, 2, 0, 2, 2, 2, 0, 0, 2, 0, true,
|
||||
List.of(new ContainerInboundPlanPreviewResponse.Group("ONE_CLICK_DROPSHIP", null, "ABE3", "Amazon ABE3",
|
||||
1, 1, 1, 0, 1, 0, List.of(fba)),
|
||||
1, 1, 1, 1, 0, 0, 1, 0, List.of(fba)),
|
||||
new ContainerInboundPlanPreviewResponse.Group("ONE_CLICK_DROPSHIP", "31", "US-LAX-01", "Los Angeles",
|
||||
1, 1, 1, 0, 1, 0, List.of(overseas))));
|
||||
1, 1, 1, 1, 0, 0, 1, 0, List.of(overseas))));
|
||||
when(plans.previewContainer(BOOKING_ID)).thenReturn(preview);
|
||||
when(numbers.next(eq("INBOUND_PLAN"), any(String.class), any(Long.class)))
|
||||
.thenReturn("IP-FBA", "IP-OVERSEAS");
|
||||
@@ -305,11 +305,11 @@ class ContainerInboundPlanConversionCoordinatorTest {
|
||||
var overseas = new ContainerInboundPlanPreviewResponse.Order(
|
||||
"200", "Customer 200", "12", "LM-12", "RK-OVERSEAS", "FIRST_LEG", "FIRST_LEG",
|
||||
"31", "US-LAX-01", "Los Angeles", null, 10, BigDecimal.ONE, 2,
|
||||
null, null, null, 0, "READY", List.of());
|
||||
0, 2, 2, null, null, null, 0, "READY", List.of());
|
||||
var preview = new ContainerInboundPlanPreviewResponse(BOOKING_ID, "MSCU6639870", "31", "US-LAX-01",
|
||||
"Los Angeles", 7L, SNAPSHOT_HASH, 1, 1, 0, 2, 2, 0, 1, 0, true,
|
||||
"Los Angeles", 7L, SNAPSHOT_HASH, 1, 1, 0, 1, 2, 0, 2, 0, 1, 0, true,
|
||||
List.of(new ContainerInboundPlanPreviewResponse.Group("FIRST_LEG", "31", "US-LAX-01", "Los Angeles",
|
||||
1, 1, 2, 0, 2, 0, List.of(overseas))));
|
||||
1, 1, 2, 0, 2, 0, 2, 0, List.of(overseas))));
|
||||
when(plans.previewContainer(BOOKING_ID)).thenReturn(preview);
|
||||
when(numbers.next(eq("INBOUND_PLAN"), any(String.class), any(Long.class))).thenReturn("IP-OVERSEAS");
|
||||
when(plans.sourcePalletNos("200", 12L, "FIRST_LEG")).thenReturn(List.of());
|
||||
@@ -337,11 +337,11 @@ class ContainerInboundPlanConversionCoordinatorTest {
|
||||
var order = new ContainerInboundPlanPreviewResponse.Order(
|
||||
"100", "Customer 100", "11", "LM-11", "RK-FBA", "FIRST_LEG", "FBA",
|
||||
null, "ACY2", "Amazon ACY2", "ACY2", 20, new BigDecimal("5.8000"), 3,
|
||||
null, null, null, 0, "READY", List.of());
|
||||
2, 3, 1, null, null, null, 0, "READY", List.of());
|
||||
var preview = new ContainerInboundPlanPreviewResponse(BOOKING_ID, "MSCU6639870", "31", "US-LAX-01",
|
||||
"Los Angeles", 7L, SNAPSHOT_HASH, 1, 1, 0, 1, 3, 0, 3, 0, true,
|
||||
"Los Angeles", 7L, SNAPSHOT_HASH, 1, 1, 0, 1, 3, 2, 1, 0, 3, 0, true,
|
||||
List.of(new ContainerInboundPlanPreviewResponse.Group("FBA", null, "ACY2", "Amazon ACY2",
|
||||
1, 1, 3, 0, 3, 0, List.of(order))));
|
||||
1, 1, 3, 2, 1, 0, 3, 0, List.of(order))));
|
||||
when(plans.previewContainer(BOOKING_ID)).thenReturn(preview);
|
||||
when(numbers.next(eq("INBOUND_PLAN"), any(String.class), any(Long.class))).thenReturn("IP-ACY2");
|
||||
when(plans.sourcePalletNos("100", 11L, "FIRST_LEG")).thenReturn(List.of(
|
||||
@@ -369,11 +369,11 @@ class ContainerInboundPlanConversionCoordinatorTest {
|
||||
var order = new ContainerInboundPlanPreviewResponse.Order(
|
||||
"100", "Customer 100", "11", "LM-11", "RK-FBA", "FIRST_LEG", "FBA",
|
||||
null, "ACY2", "Amazon ACY2", "ACY2", 20, new BigDecimal("5.8000"), 3,
|
||||
3, "IP-MANUAL", "PENDING_ASSIGNMENT", 1, "RESOURCE_PENDING", List.of());
|
||||
2, 3, 1, 3, "IP-MANUAL", "PENDING_ASSIGNMENT", 1, "RESOURCE_PENDING", List.of());
|
||||
var preview = new ContainerInboundPlanPreviewResponse(BOOKING_ID, "MSCU6639870", "31", "US-LAX-01",
|
||||
"Los Angeles", 7L, SNAPSHOT_HASH, 1, 1, 0, 1, 3, 3, 3, 3, true,
|
||||
"Los Angeles", 7L, SNAPSHOT_HASH, 1, 1, 0, 1, 3, 2, 1, 3, 3, 3, true,
|
||||
List.of(new ContainerInboundPlanPreviewResponse.Group("FBA", null, "ACY2", "Amazon ACY2",
|
||||
1, 1, 3, 3, 3, 3, List.of(order))));
|
||||
1, 1, 3, 2, 1, 3, 3, 3, List.of(order))));
|
||||
when(plans.previewContainer(BOOKING_ID)).thenReturn(preview);
|
||||
when(plans.sourcePalletNos("100", 11L, "FIRST_LEG")).thenReturn(List.of(
|
||||
"MSCU6639870-101-001", "MSCU6639870-101-002"));
|
||||
@@ -404,7 +404,8 @@ class ContainerInboundPlanConversionCoordinatorTest {
|
||||
"LM-" + orderId, inboundCode, "ONE_CLICK_DROPSHIP", "ONE_CLICK_DROPSHIP",
|
||||
fbaWarehouseCode == null ? "31" : null, destinationCode,
|
||||
fbaWarehouseCode == null ? "Los Angeles" : "Amazon " + destinationCode,
|
||||
fbaWarehouseCode, 10, BigDecimal.ONE, 1, null, null, null, 0, "READY", List.of());
|
||||
fbaWarehouseCode, 10, BigDecimal.ONE, 1, 1, 1, 0,
|
||||
null, null, null, 0, "READY", List.of());
|
||||
}
|
||||
|
||||
private ManualInboundPlanRequest manualRequest() {
|
||||
@@ -416,7 +417,7 @@ class ContainerInboundPlanConversionCoordinatorTest {
|
||||
return new ContainerInboundPlanPreviewResponse.Order(
|
||||
"100", "Customer 100", "11", "LM-11", "RK-1", "FIRST_LEG", "FBA",
|
||||
null, "ACY2", "Amazon ACY2", "ACY2", 10, BigDecimal.ONE, 1,
|
||||
1, "IP-MANUAL", "PENDING_ASSIGNMENT", 1, "RESOURCE_PENDING", List.of());
|
||||
1, 1, 0, 1, "IP-MANUAL", "PENDING_ASSIGNMENT", 1, "RESOURCE_PENDING", List.of());
|
||||
}
|
||||
|
||||
private ContainerInboundPlanPreviewResponse manualPreview(
|
||||
@@ -425,9 +426,9 @@ class ContainerInboundPlanConversionCoordinatorTest {
|
||||
|| "READY".equals(order.readiness())).count();
|
||||
return new ContainerInboundPlanPreviewResponse(BOOKING_ID, "MSCU6639870", "31", "US-LAX-01",
|
||||
"Los Angeles", 7L, SNAPSHOT_HASH, orders.size(), orders.size(), 0, pending, pending,
|
||||
0, orders.size(), 1, true,
|
||||
pending, 0, 0, orders.size(), 1, true,
|
||||
List.of(new ContainerInboundPlanPreviewResponse.Group("FBA", null, "ACY2", "Amazon ACY2",
|
||||
orders.size(), pending, pending, 0, orders.size(), 1, orders)));
|
||||
orders.size(), pending, pending, pending, 0, 0, orders.size(), 1, orders)));
|
||||
}
|
||||
|
||||
private InboundPlanResponse plan(String planNo, List<InboundPlanResponse.Pallet> pallets) {
|
||||
@@ -475,6 +476,6 @@ class ContainerInboundPlanConversionCoordinatorTest {
|
||||
|
||||
private ContainerInboundPlanPreviewResponse preview(long version, String hash) {
|
||||
return new ContainerInboundPlanPreviewResponse(BOOKING_ID, "MSCU6639870", "31", "US-LAX-01",
|
||||
"Los Angeles", version, hash, 1, 1, 0, 0, 0, 1, 1, 1, true, List.of());
|
||||
"Los Angeles", version, hash, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, true, List.of());
|
||||
}
|
||||
}
|
||||
|
||||
+25
-2
@@ -57,6 +57,8 @@ class ContainerInboundPlanPreviewTest {
|
||||
assertFalse(result.ready());
|
||||
assertEquals(4, result.pendingOrderCount());
|
||||
assertEquals(7, result.pendingPalletCount());
|
||||
assertEquals(7, result.sourcePalletCount());
|
||||
assertEquals(0, result.supplementPalletCount());
|
||||
assertEquals(2, result.existingPlannedPalletCount());
|
||||
assertEquals(List.of("A-01", "B-02", "C-03", "DROPSHIP", ""), result.groups().stream()
|
||||
.map(group -> group.destinationWarehouseCode() == null ? "" : group.destinationWarehouseCode()).toList());
|
||||
@@ -74,7 +76,7 @@ class ContainerInboundPlanPreviewTest {
|
||||
new InboundPlanOrderMapper.ContainerPreviewOrderRow("100", 1L, "LM-1", "FO-1", "测试客户",
|
||||
"FIRST_LEG", "OVERSEAS", "IN-1", "PENDING_ASSIGNMENT", null, null, 0, 0,
|
||||
BigDecimal.ZERO, null, null, null, null, null, null, null, 0, false, 1,
|
||||
null, null, null, null)));
|
||||
null, null, null, null, null)));
|
||||
|
||||
var result = service.previewContainer("BOOKING-NULL");
|
||||
|
||||
@@ -118,6 +120,27 @@ class ContainerInboundPlanPreviewTest {
|
||||
assertEquals("RESOURCE_PENDING", result.groups().get(0).orders().get(0).readiness());
|
||||
}
|
||||
|
||||
@Test
|
||||
void exposesHeadLegExistingSupplementAndFinalPalletCountsWithoutBlocking() {
|
||||
when(orderMapper.containerPreviewOrders("BOOKING-SUPPLEMENT")).thenReturn(List.of(
|
||||
new InboundPlanOrderMapper.ContainerPreviewOrderRow("100", 1L, "LM-1", "FO-1",
|
||||
"测试客户", "FIRST_LEG", "FBA", "IN-1", "PENDING_ASSIGNMENT", null,
|
||||
"MSCU6639870", 2, 250, new BigDecimal("5.3000"), "31", "US-LAX-01",
|
||||
"洛杉矶仓", "ACY2", null, null, "Amazon ACY2", 0, false, 1,
|
||||
null, null, null, null, 2)));
|
||||
|
||||
var result = service.previewContainer("BOOKING-SUPPLEMENT");
|
||||
var order = result.groups().get(0).orders().get(0);
|
||||
|
||||
assertEquals(2, order.sourcePalletCount());
|
||||
assertEquals(3, order.targetPalletCount());
|
||||
assertEquals(1, order.supplementPalletCount());
|
||||
assertEquals(2, result.sourcePalletCount());
|
||||
assertEquals(1, result.supplementPalletCount());
|
||||
assertEquals(3, result.pendingPalletCount());
|
||||
assertEquals("READY", order.readiness());
|
||||
}
|
||||
|
||||
private InboundPlanOrderMapper.ContainerPreviewOrderRow row(
|
||||
long id, String orderNo, String orderType, String destinationType, String destinationCode, String destinationName,
|
||||
int recommendedPallets, String planNo, Integer plannedPallets, int version) {
|
||||
@@ -137,6 +160,6 @@ class ContainerInboundPlanPreviewTest {
|
||||
"FBA".equals(destinationType) || destinationCode == null ? null : "WH-" + id,
|
||||
"FBA".equals(destinationType) ? null : destinationCode, destinationName,
|
||||
"FBA".equals(destinationType) || destinationCode == null ? 0 : 1, false, version, planNo,
|
||||
planStatus, plannedPallets, materializedPallets);
|
||||
planStatus, plannedPallets, materializedPallets, recommendedPallets);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user