This commit is contained in:
2026-09-07 15:07:34 +08:00
parent 693e10188c
commit 1b47158770
37 changed files with 688 additions and 144 deletions
@@ -58,8 +58,10 @@ CREATE TABLE IF NOT EXISTS ll_order (
customer_name VARCHAR(255) COMMENT '货主名称',
source_warehouse_id VARCHAR(128) COMMENT '来源国内装柜仓 ID 快照',
source_warehouse_name VARCHAR(255) COMMENT '来源国内装柜仓名称快照',
overseas_warehouse_id VARCHAR(128) COMMENT '海外实际收货仓 ID,由绑定仓库的PDA操作员认领柜号时冻结',
overseas_warehouse_name VARCHAR(255) COMMENT '海外仓名称',
overseas_warehouse_id VARCHAR(128) NOT NULL DEFAULT '193000000000200003' COMMENT '海外接柜仓ID,新产生普通尾程整柜默认洛杉矶仓',
overseas_warehouse_code VARCHAR(128) NOT NULL DEFAULT 'US-LAX-01' COMMENT '海外接柜仓业务编码快照',
overseas_warehouse_name VARCHAR(255) NOT NULL DEFAULT '洛杉矶仓' COMMENT '海外接柜仓名称快照',
receiving_warehouse_version INT NOT NULL DEFAULT 0 COMMENT '柜级接柜仓分配乐观锁版本',
transfer_warehouse_id VARCHAR(128) COMMENT '转入目的仓 ID',
transfer_warehouse_code VARCHAR(128) COMMENT '转入目的仓编码',
transfer_warehouse_name VARCHAR(255) COMMENT '转入目的仓名称',
@@ -177,6 +179,20 @@ CREATE TABLE IF NOT EXISTS ll_order_operation_log (
KEY idx_ll_order_operation_customer_order(customer_id,order_id,created_at)
) ENGINE=InnoDB COMMENT='尾程订单操作记录';
CREATE TABLE IF NOT EXISTS ll_receiving_warehouse_operation (
id BIGINT NOT NULL COMMENT '柜级接柜仓修改操作ID',
source_container_booking_id VARCHAR(128) NOT NULL COMMENT '稳定来源柜预订ID',
idempotency_key VARCHAR(255) NOT NULL COMMENT '平台请求幂等键',
request_hash VARCHAR(64) NOT NULL COMMENT '规范化修改请求SHA-256摘要',
result_version INT NOT NULL COMMENT '修改成功后的柜级分配版本',
operator_name VARCHAR(128) NOT NULL COMMENT '平台操作人名称',
remark VARCHAR(500) NULL COMMENT '接柜仓修改备注',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '操作时间',
PRIMARY KEY(id),
UNIQUE KEY uk_ll_receiving_warehouse_idempotency(idempotency_key),
KEY idx_ll_receiving_warehouse_container(source_container_booking_id,created_at)
) ENGINE=InnoDB COMMENT='柜级海外接柜仓修改幂等审计记录';
-- 派送单列表与详情快照、转派送费用及操作记录。
CREATE TABLE IF NOT EXISTS ll_delivery_order (
id BIGINT NOT NULL COMMENT '派送单主键ID',
@@ -357,8 +373,10 @@ ALTER TABLE ll_order
MODIFY COLUMN source_order_no VARCHAR(128) NULL COMMENT '来源订单号',
MODIFY COLUMN root_order_id VARCHAR(128) NULL COMMENT '根订单 ID',
MODIFY COLUMN customer_name VARCHAR(255) NULL COMMENT '货主名称',
MODIFY COLUMN overseas_warehouse_id VARCHAR(128) NULL COMMENT '海外仓 ID',
MODIFY COLUMN overseas_warehouse_name VARCHAR(255) NULL COMMENT '海外仓名称',
MODIFY COLUMN overseas_warehouse_id VARCHAR(128) NOT NULL DEFAULT '193000000000200003' COMMENT '海外接柜仓ID,新产生普通尾程整柜默认洛杉矶仓',
MODIFY COLUMN overseas_warehouse_code VARCHAR(128) NOT NULL DEFAULT 'US-LAX-01' COMMENT '海外接柜仓业务编码快照',
MODIFY COLUMN overseas_warehouse_name VARCHAR(255) NOT NULL DEFAULT '洛杉矶仓' COMMENT '海外接柜仓名称快照',
MODIFY COLUMN receiving_warehouse_version INT NOT NULL DEFAULT 0 COMMENT '柜级接柜仓分配乐观锁版本',
MODIFY COLUMN fba_warehouse_code VARCHAR(128) NULL COMMENT 'FBA 仓库编码',
MODIFY COLUMN container_no VARCHAR(64) NULL COMMENT '集装箱号',
MODIFY COLUMN container_status VARCHAR(32) NULL DEFAULT '待转柜' COMMENT '货柜状态',
@@ -485,7 +503,7 @@ CREATE TABLE IF NOT EXISTS ll_inbound_plan (
customer_id VARCHAR(128) NOT NULL COMMENT '租户/客户账号标识',
source_order_id BIGINT NOT NULL COMMENT '来源尾程订单ID,一张入仓单对应一张入库计划',
container_no VARCHAR(64) NOT NULL COMMENT '集装箱号',
overseas_warehouse_id BIGINT NULL COMMENT '海外实际收货共享物理仓ID,由PDA认领柜号时冻结',
overseas_warehouse_id BIGINT NOT NULL DEFAULT 193000000000200003 COMMENT '平台预分配的海外实际收货共享物理仓ID',
status VARCHAR(32) NOT NULL DEFAULT 'PLANNED' COMMENT '入库计划状态',
line_count INT NOT NULL DEFAULT 0 COMMENT '入仓码明细数量',
pallet_count INT NOT NULL DEFAULT 0 COMMENT '系统自动分配托盘数量',
@@ -851,7 +869,7 @@ WHERE (l.fba_warehouse_code IS NULL AND o.fba_warehouse_code IS NOT NULL)
CREATE TABLE IF NOT EXISTS ll_receiving_container_session (
id BIGINT NOT NULL COMMENT '柜号签收会话ID', customer_id VARCHAR(128) NOT NULL COMMENT '所选柜解析出的客户标识',
source_container_booking_id VARCHAR(128) NOT NULL COMMENT '稳定来源柜预订ID', container_fact_hash VARCHAR(64) NOT NULL COMMENT '领取时整柜订单与计划事实摘要',
container_no VARCHAR(64) NOT NULL COMMENT '集装箱号', overseas_warehouse_id BIGINT NOT NULL COMMENT '操作员Token绑定并冻结的海外实际收货共享物理仓ID', overseas_warehouse_name VARCHAR(255) NOT NULL COMMENT '仓库服务校验后的海外实际收货共享物理仓名称快照', operator_key VARCHAR(128) NOT NULL COMMENT '操作账号唯一标识',
container_no VARCHAR(64) NOT NULL COMMENT '集装箱号', overseas_warehouse_id BIGINT NOT NULL COMMENT '平台预分配并由操作员Token匹配的海外接柜仓ID', overseas_warehouse_code VARCHAR(128) NOT NULL COMMENT '海外接柜仓业务编码快照', overseas_warehouse_name VARCHAR(255) NOT NULL COMMENT '仓库服务校验后的海外接柜仓名称快照', operator_key VARCHAR(128) NOT NULL COMMENT '操作账号唯一标识',
operator_name VARCHAR(255) NULL COMMENT '操作账号名称', active_operator_key VARCHAR(255) NULL COMMENT '未完成会话平台操作账号全局唯一锁键',
active_container_key VARCHAR(255) NULL COMMENT '未完成会话柜号全局唯一锁键', status VARCHAR(32) NOT NULL DEFAULT 'WAIT_SIGN' COMMENT '会话状态:WAIT_SIGN、SIGNED、RECEIVING、COMPLETED',
sign_photos JSON NULL COMMENT '签收卸柜照片角色与文件ID列表', prepared_at DATETIME(3) NULL COMMENT '选择柜号时间',
@@ -298,6 +298,23 @@ paths:
code: { type: string, enum: ['200'] }
data: { $ref: '#/components/schemas/ContainerPlanProgressDetail' }
'404': { description: 稳定柜 ID 不存在 }
/api/platform/v1/last-leg/orders/container-summaries/{sourceContainerBookingId}/receiving-warehouse:
put:
summary: 修改整柜海外接柜仓
description: 权限 platform:overseas-warehouse:order:edit;目标必须为国内 Warehouse Service 有效 OVERSEAS 仓。使用柜级版本和 Idempotency-Key,事务内原子同步柜内全部尾程订单及已有入库计划;海外PDA一旦建立接柜会话即永久锁定。
security: [{ bearerAuth: [] }]
parameters:
- { name: sourceContainerBookingId, in: path, required: true, schema: { type: string, minLength: 1, maxLength: 128 } }
- { name: Idempotency-Key, in: header, required: true, schema: { type: string, minLength: 1, maxLength: 255 } }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/ChangeReceivingWarehouseRequest' }
responses:
'200': { description: 更新后的柜级摘要, content: { application/json: { schema: { type: object, properties: { code: { type: string, enum: ['200'] }, data: { $ref: '#/components/schemas/ContainerPlanProgressSummary' } } } } }
'400': { description: 请求无效或目标不是有效 OVERSEAS 仓 }
'409': { description: 版本冲突、幂等键冲突或PDA接柜会话已建立 }
/api/platform/v1/last-leg/orders/{id}/destination:
put:
summary: 将单票尾程订单转入 FBA 目的仓
@@ -331,6 +348,39 @@ paths:
'200': { description: 统一 ApiResponse 包装的更新订单数 }
'400': { description: 所选FBA仓不存在、已停用、类型错误或字段不一致 }
'503': { description: 国内FBA仓权威主数据暂不可用,写入失败关闭 }
/api/platform/v1/last-leg/inbound-plans:
get:
summary: 平台分页查询海外入库订单
description: 权限 platform:overseas-warehouse:inbound-order:list;列表中的 overseasWarehouseCode/overseasWarehouseName 只取尾程订单预分配接柜仓事实,warehouseCode/warehouseName 仍表示目的仓。
security: [{ bearerAuth: [] }]
parameters:
- { name: customerId, in: query, required: false, schema: { type: string, pattern: '^[1-9][0-9]*$' } }
- { name: page, in: query, schema: { type: integer, minimum: 1, default: 1 } }
- { name: size, in: query, schema: { type: integer, minimum: 1, maximum: 200, default: 20 } }
- { name: planNo, in: query, schema: { type: string } }
- { name: inboundCode, in: query, schema: { type: string } }
- { name: lxCode, in: query, schema: { type: string } }
- { name: status, in: query, schema: { type: string } }
- { name: overseasWarehouseId, in: query, schema: { type: string } }
- { name: destinationWarehouseCode, in: query, schema: { type: string } }
- { name: warehouse, in: query, schema: { type: string } }
- { name: fbaWarehouseCode, in: query, schema: { type: string } }
- { name: appointmentStatus, in: query, schema: { type: string, enum: [UNAPPOINTED, PENDING, SUCCESS, FAILED, CANCELLED] } }
- { name: dispatchStatus, in: query, schema: { type: string, enum: [UNSCHEDULED, SCHEDULED] } }
- { name: createdFrom, in: query, schema: { type: string, format: date-time } }
- { name: createdTo, in: query, schema: { type: string, format: date-time } }
responses: { '200': { description: 平台入库订单分页, content: { application/json: { schema: { $ref: '#/components/schemas/InboundPlanPageResponse' } } } } }
/api/platform/v1/last-leg/inbound-plans/{planNo}:
get:
summary: 平台查询海外入库订单详情
description: 权限 platform:overseas-warehouse:inbound-order:list;详情中的 overseasWarehouseCode/overseasWarehouseName 只取当前计划来源尾程订单的预分配接柜仓事实。
security: [{ bearerAuth: [] }]
parameters:
- { name: planNo, in: path, required: true, schema: { type: string } }
- { name: customerId, in: query, required: false, schema: { type: string, pattern: '^[1-9][0-9]*$' } }
responses:
'200': { description: 平台入库订单详情, content: { application/json: { schema: { $ref: '#/components/schemas/InboundPlanDetailResponse' } } } }
'404': { description: 入库订单不存在或不属于指定客户 }
/api/platform/v1/last-leg/inbound-plans/convert:
post:
summary: 平台生成入库计划
@@ -811,7 +861,7 @@ paths:
/api/merchant/v1/last-leg/inbound-plans:
get:
summary: 客户分页查询自己的海外入库订单
description: 权限 merchant:warehouse:inbound:list;客户范围只取认证 Token,不接收 customerId。
description: 权限 merchant:warehouse:inbound:list;客户范围只取认证 Token,不接收 customerId;overseasWarehouseCode/overseasWarehouseName 只取该客户尾程订单预分配接柜仓事实,warehouseCode/warehouseName 仍表示目的仓。
security: [{ bearerAuth: [] }]
parameters:
- { name: page, in: query, schema: { type: integer, minimum: 1, default: 1 } }
@@ -829,7 +879,7 @@ paths:
/api/merchant/v1/last-leg/inbound-plans/{planNo}:
get:
summary: 客户查询自己的海外入库订单详情
description: 权限 merchant:warehouse:inbound:list;列表权限包含详情只读,不接收 customerId。
description: 权限 merchant:warehouse:inbound:list;列表权限包含详情只读,不接收 customerId;overseasWarehouseCode/overseasWarehouseName 只取该计划来源尾程订单的预分配接柜仓事实。
security: [{ bearerAuth: [] }]
parameters: [{ name: planNo, in: path, required: true, schema: { type: string } }]
responses: { '200': { description: 当前客户入库订单详情, content: { application/json: { schema: { $ref: '#/components/schemas/InboundPlanDetailResponse' } } } }, '404': { description: 当前客户下入库订单不存在 } }
@@ -1093,10 +1143,16 @@ components:
items: { type: string, pattern: '^[1-9][0-9]*$' }
ContainerPlanProgressSummary:
type: object
required: [sourceContainerBookingId, containerNo, totalOrderCount, inboundCodeCount, missingInboundCodeCount, planCount, plannedInboundCodeCount, pendingPlanCount, allPlansReady]
required: [sourceContainerBookingId, containerNo, overseasWarehouseId, overseasWarehouseCode, overseasWarehouseName, assignmentVersion, canChangeReceivingWarehouse, totalOrderCount, inboundCodeCount, missingInboundCodeCount, planCount, plannedInboundCodeCount, pendingPlanCount, allPlansReady]
properties:
sourceContainerBookingId: { type: string }
containerNo: { type: string, pattern: '^[A-Z]{3}[UJZ][0-9]{7}$', description: 装柜完成事件非空且通过 ISO 6346 校验位验证的规范化真实集装箱号;不使用 cabinetNo、订单号或内部 ID 回退 }
overseasWarehouseId: { type: string, pattern: '^[1-9][0-9]*$', description: 平台预分配的海外接柜仓ID,不是FBA目的仓 }
overseasWarehouseCode: { type: string, description: 海外接柜仓业务编码 }
overseasWarehouseName: { type: string, description: 海外接柜仓业务名称 }
assignmentVersion: { type: integer, minimum: 0, description: 柜级接柜仓乐观锁版本 }
canChangeReceivingWarehouse: { type: boolean }
receivingWarehouseLockReason: { type: string, nullable: true }
totalOrderCount: { type: integer, format: int64 }
inboundCodeCount: { type: integer, format: int64 }
missingInboundCodeCount: { type: integer, format: int64 }
@@ -1106,6 +1162,13 @@ components:
plannedArrivalAt: { type: string, format: date-time, nullable: true, description: 仅来源于装柜完成事件 estimatedWarehouseArrivalAt 冻结的 ll_order.estimated_warehouse_at }
allPlansReady: { type: boolean, description: 全柜每票均有入仓码且均存在有效独立计划时为 true }
blockingReason: { type: string, nullable: true }
ChangeReceivingWarehouseRequest:
type: object
required: [overseasWarehouseId, expectedVersion]
properties:
overseasWarehouseId: { type: integer, format: int64, minimum: 1 }
expectedVersion: { type: integer, minimum: 0 }
remark: { type: string, maxLength: 500, nullable: true }
ContainerPlanProgressDetail:
type: object
required: [summary, orders]
@@ -1329,10 +1392,12 @@ components:
warehouseName: { type: string, description: 国内Warehouse Service主档维护的当前中文名称 }
ReceivingCandidate:
type: object
required: [sourceContainerBookingId, containerNo, status, totalOrderCount, inboundCodeCount, missingInboundCodeCount, planCount, plannedInboundCodeCount, pendingPlanCount, destinationCodes, plannedPalletCount, totalPackages, receivedPackages, operable, allPlansReady, currentAccount]
required: [sourceContainerBookingId, containerNo, overseasWarehouseCode, overseasWarehouseName, status, totalOrderCount, inboundCodeCount, missingInboundCodeCount, planCount, plannedInboundCodeCount, pendingPlanCount, destinationCodes, plannedPalletCount, totalPackages, receivedPackages, operable, allPlansReady, currentAccount]
properties:
sourceContainerBookingId: { type: string, description: 头程与尾程共享的稳定柜身份 }
containerNo: { type: string }
overseasWarehouseCode: { type: string }
overseasWarehouseName: { type: string }
status: { type: string, enum: [WAIT_SIGN, SIGNED, RECEIVING, COMPLETED] }
totalOrderCount: { type: integer, minimum: 1 }
missingInboundCodeCount: { type: integer, minimum: 0 }
@@ -1351,10 +1416,11 @@ components:
currentAccount: { type: boolean }
ReceivingSession:
type: object
required: [containerNo, overseasWarehouseId, overseasWarehouseName, status, version, photos, totalPackages, receivedPackages, pendingPackages, inbounds]
required: [containerNo, overseasWarehouseId, overseasWarehouseCode, overseasWarehouseName, status, version, photos, totalPackages, receivedPackages, pendingPackages, inbounds]
properties:
containerNo: { type: string }
overseasWarehouseId: { type: string, pattern: '^\d+$', description: PDA Token绑定并在认领柜号时冻结的共享实际海外收货仓ID }
overseasWarehouseId: { type: string, pattern: '^\d+$', description: 平台预分配并与PDA Token匹配的海外接柜仓ID }
overseasWarehouseCode: { type: string, description: 海外接柜仓业务编码快照 }
overseasWarehouseName: { type: string, description: Warehouse Overseas服务校验后的共享实际海外收货仓名称快照 }
status: { type: string, enum: [WAIT_SIGN, SIGNED, RECEIVING, COMPLETED] }
operatorName: { type: string, nullable: true }
@@ -1911,7 +1977,7 @@ components:
properties: { records: { type: array, items: { $ref: '#/components/schemas/InboundPlanSummary' } } }
InboundPlanSummary:
type: object
required: [lineId, planId, planNo, customerId, orderId, inboundCode, packageCount, pickedPackageCount, palletCount, status, createdAt, version]
required: [lineId, planId, planNo, customerId, orderId, inboundCode, overseasWarehouseCode, overseasWarehouseName, packageCount, pickedPackageCount, palletCount, status, createdAt, version]
properties:
lineId: { type: string, pattern: '^[0-9]+$' }
planId: { type: string, pattern: '^[0-9]+$' }
@@ -1920,6 +1986,8 @@ components:
orderId: { type: string, pattern: '^[0-9]+$' }
inboundCode: { type: string }
orderType: { type: string, nullable: true }
overseasWarehouseCode: { type: string, description: 接柜仓编码,取自尾程订单预分配接收仓事实 }
overseasWarehouseName: { type: string, description: 接柜仓名称,取自尾程订单预分配接收仓事实 }
warehouseId: { type: string, nullable: true }
warehouseCode: { type: string, nullable: true }
warehouseName: { type: string, nullable: true }
@@ -1939,13 +2007,15 @@ components:
version: { type: integer }
InboundPlanDetail:
type: object
required: [id, planNo, customerId, status, lineCount, palletCount, totalVolumeCbm, expectedPackageCount, pickedPackageCount, lines, pallets, allocations, version]
required: [id, planNo, customerId, overseasWarehouseCode, overseasWarehouseName, status, lineCount, palletCount, totalVolumeCbm, expectedPackageCount, pickedPackageCount, lines, pallets, allocations, version]
properties:
id: { type: string, pattern: '^[0-9]+$' }
planNo: { type: string }
customerId: { type: string }
sourceOrderId: { type: string, pattern: '^[0-9]+$', nullable: true }
containerNo: { type: string, nullable: true }
overseasWarehouseCode: { type: string, description: 接柜仓编码,取自尾程订单预分配接收仓事实 }
overseasWarehouseName: { type: string, description: 接柜仓名称,取自尾程订单预分配接收仓事实 }
status: { type: string }
lineCount: { type: integer }
palletCount: { type: integer }