feat: explain supplemental pallet counts
This commit is contained in:
+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
|
||||
|
||||
Reference in New Issue
Block a user