fix: materialize signed manual pallet plans
This commit is contained in:
@@ -14,7 +14,7 @@
|
|||||||
| 功能 | 入口 |
|
| 功能 | 入口 |
|
||||||
|---|---|
|
|---|---|
|
||||||
| 内部模块化基线与依赖分析 | `docs/lastleg-internal-modularization-baseline.md`、`scripts/analyze-lastleg-dependencies.mjs`、`scripts/analyze-lastleg-dependencies.test.mjs`、`src/test/resources/architecture/lastleg-slice-dependencies.json`;只约束本服务内部包依赖,不改变部署单元或数据库边界 |
|
| 内部模块化基线与依赖分析 | `docs/lastleg-internal-modularization-baseline.md`、`scripts/analyze-lastleg-dependencies.mjs`、`scripts/analyze-lastleg-dependencies.test.mjs`、`src/test/resources/architecture/lastleg-slice-dependencies.json`;只约束本服务内部包依赖,不改变部署单元或数据库边界 |
|
||||||
| 事件接收、平台订单列表/详情/导出、柜级进度、目的仓调整 | `src/main/java/com/baiyue/lastleg/controller/LastlegOrderController.java`;`/api/platform/v1/last-leg/orders/container-summaries` 按 `sourceContainerBookingId` 服务端聚合全柜订单、入仓码和有效计划并分页返回全部稳定来源柜,已完成计划转换的柜仍保留用于接柜仓查询与修改,生成资格只由 `allPlansReady/pendingPlanCount` 表达;`/{sourceContainerBookingId}` 返回柜内全部订单/入仓码/计划状态且不受订单分页截断;`plannedArrivalAt` 只取装柜完成事件 `estimatedWarehouseArrivalAt` 冻结到 `ll_order.estimated_warehouse_at` 的正式事实,按其升序、null 最后、稳定柜 ID 排序;目的仓调整仅接受国内 Warehouse Service 平台公共 `ACTIVE + FBA` 主档,写入前由 `service/FbaWarehouseValidator.java` 经内部只读目录校验 ID/编码/名称一致 |
|
| 事件接收、平台订单列表/详情/导出、柜级进度、目的仓调整 | `src/main/java/com/baiyue/lastleg/controller/LastlegOrderController.java`;`/api/platform/v1/last-leg/orders/container-summaries` 按 `sourceContainerBookingId` 服务端聚合全柜订单、入仓码、有效计划及待补真实托盘计划并分页返回全部稳定来源柜,已完成计划转换的柜仍保留用于接柜仓查询与修改,生成资格由 `pendingPlanCount/resourcePendingPlanCount` 表达;`/{sourceContainerBookingId}` 返回柜内全部订单/入仓码/计划状态且不受订单分页截断;`plannedArrivalAt` 只取装柜完成事件 `estimatedWarehouseArrivalAt` 冻结到 `ll_order.estimated_warehouse_at` 的正式事实,按其升序、null 最后、稳定柜 ID 排序;目的仓调整仅接受国内 Warehouse Service 平台公共 `ACTIVE + FBA` 主档,写入前由 `service/FbaWarehouseValidator.java` 经内部只读目录校验 ID/编码/名称一致 |
|
||||||
| 尾程订单完整计划、暂扣与人工节点 | `controller/LastlegOrderController.java`、`service/LastlegOrderCommandService.java`、`inboundplan/service/InboundPlanService.java`、`dto/LastlegOrderCommandDtos.java`;单票计划写入校验订单版本、客户范围、订单冻结入仓码、稳定接柜仓 ID、当前仓库主档与幂等键;接柜仓编码/名称以该 ID 当前目录快照为准,不要求订单残留旧展示快照。暂扣/解除写不可变历史并发布 `InboundOrderDetainedOutboxService`,已拣货、已发运或已有出库单时禁止新增暂扣;暂扣期间不得进入排车或出库。人工节点必须一次提交固定八行完整快照且至少一个时间,首次保存后永久使用 `MANUAL` 来源,不得回退柜级节点或反向修改头程船节点 |
|
| 尾程订单完整计划、暂扣与人工节点 | `controller/LastlegOrderController.java`、`service/LastlegOrderCommandService.java`、`inboundplan/service/InboundPlanService.java`、`dto/LastlegOrderCommandDtos.java`;单票计划写入校验订单版本、客户范围、订单冻结入仓码、稳定接柜仓 ID、当前仓库主档与幂等键;接柜仓编码/名称以该 ID 当前目录快照为准,不要求订单残留旧展示快照。暂扣/解除写不可变历史并发布 `InboundOrderDetainedOutboxService`,已拣货、已发运或已有出库单时禁止新增暂扣;暂扣期间不得进入排车或出库。人工节点必须一次提交固定八行完整快照且至少一个时间,首次保存后永久使用 `MANUAL` 来源,不得回退柜级节点或反向修改头程船节点 |
|
||||||
| 客户尾程订单列表与详情 | `controller/MerchantLastlegOrderController.java`;客户范围只取认证身份,稳定类型/状态见 `model/LastlegOrderType.java`、`LastlegOrderStatus.java` |
|
| 客户尾程订单列表与详情 | `controller/MerchantLastlegOrderController.java`;客户范围只取认证身份,稳定类型/状态见 `model/LastlegOrderType.java`、`LastlegOrderStatus.java` |
|
||||||
| 装柜完成事件消费 | `service/LoadingCompletedConsumer.java`;当前生产信封为 `FIRST_LEG_LOADING_PLAN_COMPLETED` V2,消费端冻结 `destinationType`:FBA 可按箱数且不生成逐箱作业账,OVERSEAS 必须逐箱校验并生成箱级事实;历史缺字段事件仅按明确 FBA 单号或目的仓与接柜仓一致性安全推断,歧义直接拒绝 |
|
| 装柜完成事件消费 | `service/LoadingCompletedConsumer.java`;当前生产信封为 `FIRST_LEG_LOADING_PLAN_COMPLETED` V2,消费端冻结 `destinationType`:FBA 可按箱数且不生成逐箱作业账,OVERSEAS 必须逐箱校验并生成箱级事实;历史缺字段事件仅按明确 FBA 单号或目的仓与接柜仓一致性安全推断,歧义直接拒绝 |
|
||||||
|
|||||||
+2
-1
@@ -18,6 +18,7 @@ public record ContainerPlanProgressSummary(
|
|||||||
long planCount,
|
long planCount,
|
||||||
long plannedInboundCodeCount,
|
long plannedInboundCodeCount,
|
||||||
long pendingPlanCount,
|
long pendingPlanCount,
|
||||||
|
long resourcePendingPlanCount,
|
||||||
LocalDateTime plannedArrivalAt,
|
LocalDateTime plannedArrivalAt,
|
||||||
boolean allPlansReady,
|
boolean allPlansReady,
|
||||||
String blockingReason
|
String blockingReason
|
||||||
@@ -30,6 +31,6 @@ public record ContainerPlanProgressSummary(
|
|||||||
String blockingReason) {
|
String blockingReason) {
|
||||||
this(sourceContainerBookingId, containerNo, null, null, null, -1, false, null,
|
this(sourceContainerBookingId, containerNo, null, null, null, -1, false, null,
|
||||||
totalOrderCount, inboundCodeCount, missingInboundCodeCount, planCount,
|
totalOrderCount, inboundCodeCount, missingInboundCodeCount, planCount,
|
||||||
plannedInboundCodeCount, pendingPlanCount, plannedArrivalAt, allPlansReady, blockingReason);
|
plannedInboundCodeCount, pendingPlanCount, 0, plannedArrivalAt, allPlansReady, blockingReason);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-3
@@ -261,7 +261,8 @@ public class InboundPlanService {
|
|||||||
&& row.materializedPalletCount() > 0) {
|
&& row.materializedPalletCount() > 0) {
|
||||||
blockers.add("PLAN_PALLET_BINDING_INCOMPLETE");
|
blockers.add("PLAN_PALLET_BINDING_INCOMPLETE");
|
||||||
}
|
}
|
||||||
if (planned && !materialized && !"PENDING_ASSIGNMENT".equals(row.planStatus())) {
|
if (planned && !materialized && !("PENDING_ASSIGNMENT".equals(row.planStatus())
|
||||||
|
|| "SIGNED".equals(row.planStatus()))) {
|
||||||
blockers.add("PLAN_ALREADY_STARTED");
|
blockers.add("PLAN_ALREADY_STARTED");
|
||||||
}
|
}
|
||||||
String readiness = planned ? materialized ? "PLANNED"
|
String readiness = planned ? materialized ? "PLANNED"
|
||||||
@@ -636,8 +637,8 @@ public class InboundPlanService {
|
|||||||
|| !Objects.equals(ref.orderId(), prepared.orderId())) {
|
|| !Objects.equals(ref.orderId(), prepared.orderId())) {
|
||||||
throw new ResponseStatusException(HttpStatus.CONFLICT, "人工计划与柜级托盘预留快照不一致");
|
throw new ResponseStatusException(HttpStatus.CONFLICT, "人工计划与柜级托盘预留快照不一致");
|
||||||
}
|
}
|
||||||
if (!"PENDING_ASSIGNMENT".equals(plan.getStatus())) {
|
if (!("PENDING_ASSIGNMENT".equals(plan.getStatus()) || "SIGNED".equals(plan.getStatus()))) {
|
||||||
throw new ResponseStatusException(HttpStatus.CONFLICT, "仅未开始作业的已有计划可由整柜生成补齐托盘");
|
throw new ResponseStatusException(HttpStatus.CONFLICT, "仅待入库或已签收但未实收的已有计划可由整柜生成补齐托盘");
|
||||||
}
|
}
|
||||||
List<InboundPlanPallet> pallets = palletMapper.selectList(new LambdaQueryWrapper<InboundPlanPallet>()
|
List<InboundPlanPallet> pallets = palletMapper.selectList(new LambdaQueryWrapper<InboundPlanPallet>()
|
||||||
.eq(InboundPlanPallet::getCustomerId, plan.getCustomerId())
|
.eq(InboundPlanPallet::getCustomerId, plan.getCustomerId())
|
||||||
|
|||||||
@@ -42,6 +42,10 @@ public interface LastlegOrderMapper extends BaseMapper<LastlegOrder> {
|
|||||||
"AND NULLIF(TRIM(p.status),'') IS NOT NULL THEN NULLIF(TRIM(o.inbound_code),'') END) AS plannedInboundCodeCount," +
|
"AND NULLIF(TRIM(p.status),'') IS NOT NULL THEN NULLIF(TRIM(o.inbound_code),'') END) AS plannedInboundCodeCount," +
|
||||||
"SUM(CASE WHEN p.id IS NULL OR NULLIF(TRIM(p.plan_no),'') IS NULL OR NULLIF(TRIM(p.status),'') IS NULL " +
|
"SUM(CASE WHEN p.id IS NULL OR NULLIF(TRIM(p.plan_no),'') IS NULL OR NULLIF(TRIM(p.status),'') IS NULL " +
|
||||||
"THEN 1 ELSE 0 END) AS pendingPlanCount," +
|
"THEN 1 ELSE 0 END) AS pendingPlanCount," +
|
||||||
|
"SUM(CASE WHEN p.id IS NOT NULL AND COALESCE(p.pallet_count,0)>0 AND " +
|
||||||
|
"(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)<COALESCE(p.pallet_count,0) " +
|
||||||
|
"THEN 1 ELSE 0 END) AS resourcePendingPlanCount," +
|
||||||
"CASE WHEN COUNT(o.estimated_warehouse_at)=COUNT(*) " +
|
"CASE WHEN COUNT(o.estimated_warehouse_at)=COUNT(*) " +
|
||||||
"AND COUNT(DISTINCT o.estimated_warehouse_at)=1 THEN MAX(o.estimated_warehouse_at) ELSE NULL END AS plannedArrivalAt," +
|
"AND COUNT(DISTINCT o.estimated_warehouse_at)=1 THEN MAX(o.estimated_warehouse_at) ELSE NULL END AS plannedArrivalAt," +
|
||||||
"CASE WHEN SUM(CASE WHEN NULLIF(TRIM(o.inbound_code),'') IS NULL THEN 1 ELSE 0 END)=0 " +
|
"CASE WHEN SUM(CASE WHEN NULLIF(TRIM(o.inbound_code),'') IS NULL THEN 1 ELSE 0 END)=0 " +
|
||||||
|
|||||||
@@ -176,7 +176,7 @@ public class LastlegOrderService {
|
|||||||
summary.assignmentVersion(), invalidContainer ? false : summary.canChangeReceivingWarehouse(),
|
summary.assignmentVersion(), invalidContainer ? false : summary.canChangeReceivingWarehouse(),
|
||||||
invalidContainer ? issue : summary.receivingWarehouseLockReason(), summary.totalOrderCount(),
|
invalidContainer ? issue : summary.receivingWarehouseLockReason(), summary.totalOrderCount(),
|
||||||
summary.inboundCodeCount(), summary.missingInboundCodeCount(), summary.planCount(),
|
summary.inboundCodeCount(), summary.missingInboundCodeCount(), summary.planCount(),
|
||||||
summary.plannedInboundCodeCount(), summary.pendingPlanCount(), summary.plannedArrivalAt(),
|
summary.plannedInboundCodeCount(), summary.pendingPlanCount(), summary.resourcePendingPlanCount(), summary.plannedArrivalAt(),
|
||||||
false, issue);
|
false, issue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1289,7 +1289,7 @@ components:
|
|||||||
items: { type: string, pattern: '^[1-9][0-9]*$' }
|
items: { type: string, pattern: '^[1-9][0-9]*$' }
|
||||||
ContainerPlanProgressSummary:
|
ContainerPlanProgressSummary:
|
||||||
type: object
|
type: object
|
||||||
required: [sourceContainerBookingId, containerNo, overseasWarehouseId, overseasWarehouseCode, overseasWarehouseName, assignmentVersion, canChangeReceivingWarehouse, totalOrderCount, inboundCodeCount, missingInboundCodeCount, planCount, plannedInboundCodeCount, pendingPlanCount, allPlansReady]
|
required: [sourceContainerBookingId, containerNo, overseasWarehouseId, overseasWarehouseCode, overseasWarehouseName, assignmentVersion, canChangeReceivingWarehouse, totalOrderCount, inboundCodeCount, missingInboundCodeCount, planCount, plannedInboundCodeCount, pendingPlanCount, resourcePendingPlanCount, allPlansReady]
|
||||||
properties:
|
properties:
|
||||||
sourceContainerBookingId: { type: string }
|
sourceContainerBookingId: { type: string }
|
||||||
containerNo: { type: string, pattern: '^[A-Z]{3}[UJZ][0-9]{7}$', description: 装柜完成事件非空且通过 ISO 6346 校验位验证的规范化真实集装箱号;不使用 cabinetNo、订单号或内部 ID 回退 }
|
containerNo: { type: string, pattern: '^[A-Z]{3}[UJZ][0-9]{7}$', description: 装柜完成事件非空且通过 ISO 6346 校验位验证的规范化真实集装箱号;不使用 cabinetNo、订单号或内部 ID 回退 }
|
||||||
@@ -1305,6 +1305,7 @@ components:
|
|||||||
planCount: { type: integer, format: int64 }
|
planCount: { type: integer, format: int64 }
|
||||||
plannedInboundCodeCount: { type: integer, format: int64 }
|
plannedInboundCodeCount: { type: integer, format: int64 }
|
||||||
pendingPlanCount: { type: integer, format: int64, description: 尚未生成有效计划的尾程订单数,即未操作数 }
|
pendingPlanCount: { type: integer, format: int64, description: 尚未生成有效计划的尾程订单数,即未操作数 }
|
||||||
|
resourcePendingPlanCount: { type: integer, format: int64, description: 已有有效计划但尚未完整绑定海外仓真实托盘的订单数 }
|
||||||
plannedArrivalAt: { type: string, format: date-time, nullable: true, description: 仅来源于装柜完成事件 estimatedWarehouseArrivalAt 冻结的 ll_order.estimated_warehouse_at }
|
plannedArrivalAt: { type: string, format: date-time, nullable: true, description: 仅来源于装柜完成事件 estimatedWarehouseArrivalAt 冻结的 ll_order.estimated_warehouse_at }
|
||||||
allPlansReady: { type: boolean, description: 全柜每票均有入仓码且均存在有效独立计划时为 true }
|
allPlansReady: { type: boolean, description: 全柜每票均有入仓码且均存在有效独立计划时为 true }
|
||||||
blockingReason: { type: string, nullable: true }
|
blockingReason: { type: string, nullable: true }
|
||||||
|
|||||||
+25
-1
@@ -103,9 +103,33 @@ class ContainerInboundPlanPreviewTest {
|
|||||||
.map(ContainerInboundPlanPreviewResponse.Group::destinationType).toList());
|
.map(ContainerInboundPlanPreviewResponse.Group::destinationType).toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void signedManualPlanWithoutWarehousePalletsRemainsResourcePending() {
|
||||||
|
when(orderMapper.containerPreviewOrders("BOOKING-SIGNED")).thenReturn(List.of(
|
||||||
|
row(1L, "LM-SIGNED", "FIRST_LEG", "FBA", "ACY2", "Amazon ACY2", 3,
|
||||||
|
"IP-SIGNED", 3, 1, "SIGNED", 0)
|
||||||
|
));
|
||||||
|
|
||||||
|
var result = service.previewContainer("BOOKING-SIGNED");
|
||||||
|
|
||||||
|
assertEquals(true, result.ready());
|
||||||
|
assertEquals(1, result.pendingOrderCount());
|
||||||
|
assertEquals(3, result.pendingPalletCount());
|
||||||
|
assertEquals("RESOURCE_PENDING", result.groups().get(0).orders().get(0).readiness());
|
||||||
|
}
|
||||||
|
|
||||||
private InboundPlanOrderMapper.ContainerPreviewOrderRow row(
|
private InboundPlanOrderMapper.ContainerPreviewOrderRow row(
|
||||||
long id, String orderNo, String orderType, String destinationType, String destinationCode, String destinationName,
|
long id, String orderNo, String orderType, String destinationType, String destinationCode, String destinationName,
|
||||||
int recommendedPallets, String planNo, Integer plannedPallets, int version) {
|
int recommendedPallets, String planNo, Integer plannedPallets, int version) {
|
||||||
|
return row(id, orderNo, orderType, destinationType, destinationCode, destinationName,
|
||||||
|
recommendedPallets, planNo, plannedPallets, version,
|
||||||
|
planNo == null ? null : "PENDING_ASSIGNMENT", plannedPallets);
|
||||||
|
}
|
||||||
|
|
||||||
|
private InboundPlanOrderMapper.ContainerPreviewOrderRow row(
|
||||||
|
long id, String orderNo, String orderType, String destinationType, String destinationCode, String destinationName,
|
||||||
|
int recommendedPallets, String planNo, Integer plannedPallets, int version, String planStatus,
|
||||||
|
Integer materializedPallets) {
|
||||||
return new InboundPlanOrderMapper.ContainerPreviewOrderRow("100", id, orderNo, "FO-" + id,
|
return new InboundPlanOrderMapper.ContainerPreviewOrderRow("100", id, orderNo, "FO-" + id,
|
||||||
"测试客户", orderType, destinationType, "IN-" + id, "PENDING_ASSIGNMENT", planNo,
|
"测试客户", orderType, destinationType, "IN-" + id, "PENDING_ASSIGNMENT", planNo,
|
||||||
"MSCU6639870", recommendedPallets, 10, new BigDecimal("1.0000"),
|
"MSCU6639870", recommendedPallets, 10, new BigDecimal("1.0000"),
|
||||||
@@ -113,6 +137,6 @@ class ContainerInboundPlanPreviewTest {
|
|||||||
"FBA".equals(destinationType) || destinationCode == null ? null : "WH-" + id,
|
"FBA".equals(destinationType) || destinationCode == null ? null : "WH-" + id,
|
||||||
"FBA".equals(destinationType) ? null : destinationCode, destinationName,
|
"FBA".equals(destinationType) ? null : destinationCode, destinationName,
|
||||||
"FBA".equals(destinationType) || destinationCode == null ? 0 : 1, false, version, planNo,
|
"FBA".equals(destinationType) || destinationCode == null ? 0 : 1, false, version, planNo,
|
||||||
planNo == null ? null : "PENDING_ASSIGNMENT", plannedPallets, plannedPallets);
|
planStatus, plannedPallets, materializedPallets);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -181,10 +181,11 @@ class InboundPlanServiceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void containerConversionBindsRealWarehousePalletsBackToExistingManualPlan() {
|
void containerConversionBindsRealWarehousePalletsBackToSignedManualPlanBeforeReceiving() {
|
||||||
InboundPlan plan = existingPlan("100", 2L, "IP-MANUAL");
|
InboundPlan plan = existingPlan("100", 2L, "IP-MANUAL");
|
||||||
plan.setCreationMode("MANUAL");
|
plan.setCreationMode("MANUAL");
|
||||||
plan.setPalletCount(2);
|
plan.setPalletCount(2);
|
||||||
|
plan.setStatus("SIGNED");
|
||||||
InboundPlanPallet first = new InboundPlanPallet();
|
InboundPlanPallet first = new InboundPlanPallet();
|
||||||
first.setId(301L); first.setCustomerId("100"); first.setPlanId(plan.getId()); first.setSequenceNo(1);
|
first.setId(301L); first.setCustomerId("100"); first.setPlanId(plan.getId()); first.setSequenceNo(1);
|
||||||
InboundPlanPallet second = new InboundPlanPallet();
|
InboundPlanPallet second = new InboundPlanPallet();
|
||||||
|
|||||||
+2
-1
@@ -27,7 +27,7 @@ class ContainerPlanProgressContractTest {
|
|||||||
assertEquals(List.of("sourceContainerBookingId", "containerNo", "overseasWarehouseId",
|
assertEquals(List.of("sourceContainerBookingId", "containerNo", "overseasWarehouseId",
|
||||||
"overseasWarehouseCode", "overseasWarehouseName", "assignmentVersion",
|
"overseasWarehouseCode", "overseasWarehouseName", "assignmentVersion",
|
||||||
"canChangeReceivingWarehouse", "receivingWarehouseLockReason", "totalOrderCount", "inboundCodeCount",
|
"canChangeReceivingWarehouse", "receivingWarehouseLockReason", "totalOrderCount", "inboundCodeCount",
|
||||||
"missingInboundCodeCount", "planCount", "plannedInboundCodeCount", "pendingPlanCount",
|
"missingInboundCodeCount", "planCount", "plannedInboundCodeCount", "pendingPlanCount", "resourcePendingPlanCount",
|
||||||
"plannedArrivalAt", "allPlansReady", "blockingReason"),
|
"plannedArrivalAt", "allPlansReady", "blockingReason"),
|
||||||
Arrays.stream(ContainerPlanProgressSummary.class.getRecordComponents())
|
Arrays.stream(ContainerPlanProgressSummary.class.getRecordComponents())
|
||||||
.map(value -> value.getName()).toList());
|
.map(value -> value.getName()).toList());
|
||||||
@@ -40,6 +40,7 @@ class ContainerPlanProgressContractTest {
|
|||||||
LastlegOrderRequests.ContainerProgressQuery.class, long.class, long.class).getAnnotation(Select.class);
|
LastlegOrderRequests.ContainerProgressQuery.class, long.class, long.class).getAnnotation(Select.class);
|
||||||
String sql = String.join("", rows.value()).toLowerCase();
|
String sql = String.join("", rows.value()).toLowerCase();
|
||||||
assertTrue(sql.contains("left join ll_inbound_plan"));
|
assertTrue(sql.contains("left join ll_inbound_plan"));
|
||||||
|
assertTrue(sql.contains("ll_inbound_plan_pallet"));
|
||||||
assertTrue(sql.contains("o.estimated_warehouse_at"));
|
assertTrue(sql.contains("o.estimated_warehouse_at"));
|
||||||
assertTrue(sql.contains("group by o.source_container_booking_id"));
|
assertTrue(sql.contains("group by o.source_container_booking_id"));
|
||||||
assertFalse(sql.contains("having "));
|
assertFalse(sql.contains("having "));
|
||||||
|
|||||||
+4
-4
@@ -97,7 +97,7 @@ class LastlegOrderServiceTest {
|
|||||||
}
|
}
|
||||||
var updated = new ContainerPlanProgressSummary("BOOKING-1", "MSCU6639870", "900",
|
var updated = new ContainerPlanProgressSummary("BOOKING-1", "MSCU6639870", "900",
|
||||||
"US-NYC-01", "纽约仓", 1, true, null, 2, 2, 0, 2, 2, 0,
|
"US-NYC-01", "纽约仓", 1, true, null, 2, 2, 0, 2, 2, 0,
|
||||||
null, true, null);
|
0, null, true, null);
|
||||||
when(orders.lockContainerOrders("BOOKING-1")).thenReturn(List.of(first, second));
|
when(orders.lockContainerOrders("BOOKING-1")).thenReturn(List.of(first, second));
|
||||||
when(warehouseResourceGateway.requireActiveSharedWarehouse(900L)).thenReturn(
|
when(warehouseResourceGateway.requireActiveSharedWarehouse(900L)).thenReturn(
|
||||||
new WarehouseResourceGateway.WarehouseReference(900L, "US-NYC-01", "纽约仓", "ACTIVE"));
|
new WarehouseResourceGateway.WarehouseReference(900L, "US-NYC-01", "纽约仓", "ACTIVE"));
|
||||||
@@ -382,7 +382,7 @@ class LastlegOrderServiceTest {
|
|||||||
var healthy = summary(false, 3, "存在3票尚未生成有效入库计划");
|
var healthy = summary(false, 3, "存在3票尚未生成有效入库计划");
|
||||||
var missingWarehouse = new ContainerPlanProgressSummary("BOOKING-2", "MSCU6639870",
|
var missingWarehouse = new ContainerPlanProgressSummary("BOOKING-2", "MSCU6639870",
|
||||||
null, null, null, 0, true, null, 2, 2, 0, 0, 0, 2,
|
null, null, null, 0, true, null, 2, 2, 0, 0, 0, 2,
|
||||||
LocalDateTime.of(2026, 10, 4, 9, 0), false, "存在2票尚未生成有效入库计划");
|
0, LocalDateTime.of(2026, 10, 4, 9, 0), false, "存在2票尚未生成有效入库计划");
|
||||||
when(orders.countContainerProgress(query)).thenReturn(2L);
|
when(orders.countContainerProgress(query)).thenReturn(2L);
|
||||||
when(orders.pageContainerProgress(query, 0, 10)).thenReturn(List.of(healthy, missingWarehouse));
|
when(orders.pageContainerProgress(query, 0, 10)).thenReturn(List.of(healthy, missingWarehouse));
|
||||||
|
|
||||||
@@ -402,7 +402,7 @@ class LastlegOrderServiceTest {
|
|||||||
var locked = new ContainerPlanProgressSummary("BOOKING-2", "TSTU0000061",
|
var locked = new ContainerPlanProgressSummary("BOOKING-2", "TSTU0000061",
|
||||||
"193000000000200003", "US-LAX-01", "洛杉矶仓", 4, false,
|
"193000000000200003", "US-LAX-01", "洛杉矶仓", 4, false,
|
||||||
"海外PDA已建立接柜会话,接柜仓已永久锁定", 1, 1, 0, 1, 1, 0,
|
"海外PDA已建立接柜会话,接柜仓已永久锁定", 1, 1, 0, 1, 1, 0,
|
||||||
LocalDateTime.of(2026, 10, 4, 9, 0), true, null);
|
0, LocalDateTime.of(2026, 10, 4, 9, 0), true, null);
|
||||||
when(orders.countContainerProgress(query)).thenReturn(2L);
|
when(orders.countContainerProgress(query)).thenReturn(2L);
|
||||||
when(orders.pageContainerProgress(query, 0, 10)).thenReturn(List.of(ready, locked));
|
when(orders.pageContainerProgress(query, 0, 10)).thenReturn(List.of(ready, locked));
|
||||||
|
|
||||||
@@ -419,7 +419,7 @@ class LastlegOrderServiceTest {
|
|||||||
private static ContainerPlanProgressSummary summary(boolean ready, long pending, String reason) {
|
private static ContainerPlanProgressSummary summary(boolean ready, long pending, String reason) {
|
||||||
return new ContainerPlanProgressSummary("BOOKING-1", "MSCU6639870", "193000000000200003",
|
return new ContainerPlanProgressSummary("BOOKING-1", "MSCU6639870", "193000000000200003",
|
||||||
"US-LAX-01", "洛杉矶仓", 0, true, null, 15, 15, 0,
|
"US-LAX-01", "洛杉矶仓", 0, true, null, 15, 15, 0,
|
||||||
15 - pending, 15 - pending, pending, LocalDateTime.of(2026, 10, 3, 9, 0), ready, reason);
|
15 - pending, 15 - pending, pending, 0, LocalDateTime.of(2026, 10, 3, 9, 0), ready, reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in New Issue
Block a user