优化提交

This commit is contained in:
2026-09-14 09:58:30 +08:00
parent 5ffd6c0118
commit 8cf7c4b9c9
93 changed files with 2945 additions and 188 deletions
@@ -1515,6 +1515,12 @@ SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE tab
PREPARE transfer_outbound_hash_stmt FROM @ddl; EXECUTE transfer_outbound_hash_stmt; DEALLOCATE PREPARE transfer_outbound_hash_stmt;
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_warehouse_transfer_order' AND column_name='outbound_at'), 'SELECT 1', 'ALTER TABLE ll_warehouse_transfer_order ADD COLUMN outbound_at DATETIME(3) NULL COMMENT ''出库时间'' AFTER outbound_request_hash'));
PREPARE transfer_outbound_at_stmt FROM @ddl; EXECUTE transfer_outbound_at_stmt; DEALLOCATE PREPARE transfer_outbound_at_stmt;
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_warehouse_transfer_order' AND column_name='estimated_ship_at'), 'SELECT 1', 'ALTER TABLE ll_warehouse_transfer_order ADD COLUMN estimated_ship_at DATETIME(3) NULL COMMENT ''预计发货时间'' AFTER estimated_arrival_at'));
PREPARE transfer_estimated_ship_stmt FROM @ddl; EXECUTE transfer_estimated_ship_stmt; DEALLOCATE PREPARE transfer_estimated_ship_stmt;
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_warehouse_transfer_order' AND column_name='label_deadline'), 'SELECT 1', 'ALTER TABLE ll_warehouse_transfer_order ADD COLUMN label_deadline DATETIME(3) NULL COMMENT ''换标截止时间'', ADD COLUMN relabel_contact_name VARCHAR(128) NULL COMMENT ''换标联系人'', ADD COLUMN relabel_contact_phone VARCHAR(64) NULL COMMENT ''换标联系电话'', ADD COLUMN relabel_charge_amount DECIMAL(20,2) NULL COMMENT ''换标费用CNY'', ADD COLUMN relabel_delivery_method VARCHAR(32) NULL COMMENT ''换标后派送方式'''));
PREPARE transfer_relabel_config_stmt FROM @ddl; EXECUTE transfer_relabel_config_stmt; DEALLOCATE PREPARE transfer_relabel_config_stmt;
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_warehouse_transfer_order' AND column_name='palletize_idempotency_key'), 'SELECT 1', 'ALTER TABLE ll_warehouse_transfer_order ADD COLUMN palletize_idempotency_key VARCHAR(255) NULL COMMENT ''PDA打托幂等键'', ADD COLUMN palletize_request_hash CHAR(64) NULL COMMENT ''PDA打托请求哈希'', ADD COLUMN confirmation_idempotency_key VARCHAR(255) NULL COMMENT ''客户测量确认幂等键'', ADD COLUMN confirmation_request_hash CHAR(64) NULL COMMENT ''客户测量确认请求哈希'', ADD COLUMN customer_confirmed_at DATETIME(3) NULL COMMENT ''客户确认测量时间'''));
PREPARE transfer_fulfillment_stmt FROM @ddl; EXECUTE transfer_fulfillment_stmt; DEALLOCATE PREPARE transfer_fulfillment_stmt;
CREATE TABLE IF NOT EXISTS ll_warehouse_transfer_source_order (
id BIGINT NOT NULL COMMENT '主键ID', transfer_order_id BIGINT NOT NULL COMMENT '转仓单ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户租户ID',
@@ -1545,6 +1551,45 @@ CREATE TABLE IF NOT EXISTS ll_warehouse_transfer_carton (
KEY idx_ll_wh_transfer_carton_list (customer_id,transfer_order_id,status)
) ENGINE=InnoDB COMMENT='仓储转运系统箱唛预报';
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_warehouse_transfer_carton' AND column_name='customer_carton_mark'), 'SELECT 1', 'ALTER TABLE ll_warehouse_transfer_carton ADD COLUMN customer_carton_mark VARCHAR(255) NULL COMMENT ''客户原箱唛,用于换标现场绑定'' AFTER carton_mark'));
PREPARE transfer_customer_carton_stmt FROM @ddl; EXECUTE transfer_customer_carton_stmt; DEALLOCATE PREPARE transfer_customer_carton_stmt;
CREATE TABLE IF NOT EXISTS ll_warehouse_transfer_pallet (
id BIGINT NOT NULL COMMENT '打托事实ID', transfer_order_id BIGINT NOT NULL COMMENT '转运单ID',
customer_id VARCHAR(128) NOT NULL COMMENT '客户租户ID', sequence_no INT NOT NULL COMMENT '托序号',
warehouse_pallet_id BIGINT NOT NULL COMMENT '海外仓真实托盘ID', pallet_no VARCHAR(128) NOT NULL COMMENT '真实托盘码',
warehouse_location_id BIGINT NOT NULL COMMENT '真实库位ID', warehouse_location_code VARCHAR(128) NULL COMMENT '真实库位码',
warehouse_resource_lock_id BIGINT NOT NULL COMMENT '仓储资源锁ID', carton_count INT NOT NULL COMMENT '本托实收箱数',
length_cm DECIMAL(12,2) NOT NULL COMMENT '实测长cm', width_cm DECIMAL(12,2) NOT NULL COMMENT '实测宽cm',
height_cm DECIMAL(12,2) NOT NULL COMMENT '实测高cm', gross_weight_kg DECIMAL(12,3) NOT NULL COMMENT '实测毛重kg',
volume_cbm DECIMAL(18,6) NOT NULL COMMENT '实测体积CBM', status VARCHAR(32) NOT NULL COMMENT '打托状态',
completed_at DATETIME(3) NOT NULL COMMENT 'PDA打托完成时间', created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
PRIMARY KEY(id), UNIQUE KEY uk_ll_transfer_pallet_seq(transfer_order_id,sequence_no),
UNIQUE KEY uk_ll_transfer_pallet_physical(customer_id,warehouse_pallet_id),
KEY idx_ll_transfer_pallet_order(customer_id,transfer_order_id,status)
) ENGINE=InnoDB COMMENT='仓储转运PDA实测打托事实';
CREATE TABLE IF NOT EXISTS ll_warehouse_transfer_pallet_item (
id BIGINT NOT NULL COMMENT '主键ID', transfer_order_id BIGINT NOT NULL COMMENT '转运单ID',
transfer_pallet_id BIGINT NOT NULL COMMENT '转运托盘事实ID', transfer_item_id BIGINT NOT NULL COMMENT '转运申报明细ID',
customer_id VARCHAR(128) NOT NULL COMMENT '客户租户ID', package_count INT NOT NULL COMMENT '本托该SKU实收箱数',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', PRIMARY KEY(id),
UNIQUE KEY uk_ll_transfer_pallet_item(transfer_pallet_id,transfer_item_id),
KEY idx_ll_transfer_pallet_item_order(customer_id,transfer_order_id)
) ENGINE=InnoDB COMMENT='仓储转运每托SKU箱数回填';
CREATE TABLE IF NOT EXISTS ll_warehouse_transfer_relabel_binding (
id BIGINT NOT NULL COMMENT '主键ID', transfer_order_id BIGINT NOT NULL COMMENT '转运单ID',
customer_id VARCHAR(128) NOT NULL COMMENT '客户租户ID', operation_type VARCHAR(32) NOT NULL COMMENT '换标类型',
customer_carton_mark VARCHAR(255) NOT NULL COMMENT '客户原箱唛', original_sku VARCHAR(128) NOT NULL COMMENT '旧SKU',
new_sku VARCHAR(128) NULL COMMENT '新SKU', quantity INT NOT NULL COMMENT '换标件数',
fba_carton_mark VARCHAR(255) NULL COMMENT '新FBA箱唛', destination_warehouse_code VARCHAR(128) NULL COMMENT 'FBA目的仓',
remark VARCHAR(1000) NULL COMMENT '备注', created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
PRIMARY KEY(id), UNIQUE KEY uk_ll_transfer_relabel_mark(transfer_order_id,customer_carton_mark),
KEY idx_ll_transfer_relabel_order(customer_id,transfer_order_id)
) ENGINE=InnoDB COMMENT='仓储转运换标预绑定明细';
CREATE TABLE IF NOT EXISTS ll_warehouse_transfer_inventory_allocation (
id BIGINT NOT NULL COMMENT '雪花主键',
transfer_order_id BIGINT NOT NULL COMMENT '转仓单ID',
@@ -534,10 +534,19 @@ paths:
'200':
description: 统一 ApiResponse 包装的候选托盘数组
content: { application/json: { schema: { type: array, items: { $ref: '#/components/schemas/SmartDispatchCandidate' } } } }
/api/platform/v1/last-leg/dispatches/{dispatchNo}/items/{itemId}:
delete:
summary: 移除已排车托盘
description: 权限 platform:overseas-warehouse:dispatch:edit;仅待发车、未拣货且尚未生成出库单时允许,成功后释放托盘锁并刷新排车汇总。
security: [{ bearerAuth: [] }]
parameters:
- { name: dispatchNo, in: path, required: true, schema: { type: string } }
- { name: itemId, in: path, required: true, schema: { type: integer, format: int64 } }
responses: { '200': { description: 更新后的 DispatchResponse }, '404': { description: 排车单或托盘不存在 }, '409': { description: 已生成出库单或排车已开始执行 } }
/api/platform/v1/last-leg/dispatches/pre-arrange:
post:
summary: 创建智能预排车单
description: 权限 platform:overseas-warehouse:inbound-order:smart-dispatch;服务端根据所选托盘解析并校验唯一客户范围,锁定同一海外仓的托盘并创建 PENDING_DEPARTURE 排车单,前端不传 customerId;本接口只负责预排车创建,编辑、取消、转出库派送和 PDA 发车使用各自独立接口与权限。
description: 权限 platform:overseas-warehouse:inbound-order:smart-dispatch;服务端根据所选托盘解析并校验唯一客户范围。首次推送创建 PENDING_DEPARTURE 排车单,未生成出库单前保留虚拟车草稿,再次推送刷新原排车单明细而不重复建单。
security: [{ bearerAuth: [] }]
requestBody:
required: true
@@ -1188,6 +1197,15 @@ paths:
- { name: relabelNo, in: path, required: true, schema: { type: string, maxLength: 64 } }
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/RelabelStatusChange' } } } }
responses: { '200': { description: 统一 ApiResponse 包装的换标单详情 }, '409': { description: 非法状态迁移或关联尾程单缺失 } }
/api/platform/v1/last-leg/relabel-applications/{relabelNo}/wallet-settlement/retry:
post:
summary: 重试失败的换标费用结算
description: 权限 platform:overseas-warehouse:relabel-order:status;仅允许已完成且资金状态为SETTLE_FAILED的换标单,使用新幂等键重新发送结算指令。
security: [{ bearerAuth: [] }]
parameters:
- { name: relabelNo, in: path, required: true, schema: { type: string, maxLength: 64 } }
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/WalletFreezeRetry' } } } }
responses: { '200': { description: 结算重试已提交 }, '409': { description: 当前换标单不满足重试条件 } }
/api/platform/v1/last-leg/relabel-applications/{relabelNo}/files:
post:
summary: 上传总换标PDF或明细换标PDF
@@ -1256,6 +1274,17 @@ paths:
responses:
'200': { description: 换标申请详情, content: { application/json: { schema: { $ref: '#/components/schemas/RelabelMerchantDetailResponse' } } } }
'409': { description: 幂等键、库存或状态冲突 }
/api/merchant/v1/last-leg/relabel-applications/historical-orders:
get:
summary: 查询贴标申请历史订单候选
description: 按海外仓和关键字查询客户历史尾程订单,并包含贴标出库单(RELABEL_OUTBOUND),供贴标申请订单下拉筛选。
security: [{ bearerAuth: [] }]
parameters:
- { name: operationWarehouseId, in: query, required: true, schema: { type: string, maxLength: 128 } }
- { name: keyword, in: query, required: false, schema: { type: string, maxLength: 128 } }
responses:
'200': { description: 历史订单候选, content: { application/json: { schema: { type: object, properties: { code: { type: string, example: '200' }, data: { type: array, items: { $ref: '#/components/schemas/RelabelHistoricalOrder' } } } } } } }
'403': { description: 缺少客户换标权限 }
/api/merchant/v1/last-leg/relabel-applications/{relabelNo}:
get:
summary: 查询客户换标申请详情
@@ -2358,6 +2387,18 @@ components:
batchNo: { type: string, nullable: true }
warehouseLocationCode: { type: string, nullable: true }
availablePackages: { type: integer, format: int64 }
RelabelHistoricalOrder:
type: object
properties:
id: { type: string, nullable: true }
orderNo: { type: string }
sourceOrderNo: { type: string, nullable: true }
outboundOrderNo: { type: string, nullable: true }
relabelOrderNo: { type: string, nullable: true }
orderType: { type: string, nullable: true }
status: { type: string, nullable: true }
packageCount: { type: integer, nullable: true }
createdAt: { type: string, format: date-time, nullable: true }
RelabelCustomerConfirm:
type: object
required: [idempotencyKey]
@@ -2406,6 +2447,12 @@ components:
properties:
status: { $ref: '#/components/schemas/RelabelStatus' }
remark: { type: string, nullable: true, maxLength: 1000 }
WalletFreezeRetry:
type: object
required: [idempotencyKey]
properties:
idempotencyKey: { type: string, minLength: 1, maxLength: 255 }
remark: { type: string, nullable: true, maxLength: 1000 }
MerchantApiResponse:
type: object
required: [code, data]
@@ -154,6 +154,12 @@ paths:
summary: 扫码查询托盘及库存内容
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/ScanCode' } } } }
responses: { '200': { description: Token绑定仓托盘内容 }, '404': { description: 托盘不存在(统一响应实际 HTTP 200,body.code=A0404), content: { application/json: { schema: { $ref: '#/components/schemas/ApiResponse' } } } } }
/api/pda/v1/last-leg/pallet-operations/relabel-pallet-label:
post:
summary: 为换标拆托幂等生成并返回可打印的新托盘标签
description: 返回空托盘编码、初始版本和打印HTML;随后可将该托盘作为relabel-disassemble的target。库存移入后仍继承原库存余额对应的客户和入库单。
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/NewRelabelPallet' } } } }
responses: { '200': { description: 新托盘及可打印标签 }, '409': { description: 换标单未确认或不属于Token绑定仓 } }
/api/pda/v1/last-leg/pallet-operations/assemble:
post:
summary: 将多个来源托盘的指定库存行组到目标托盘
@@ -411,14 +417,14 @@ components:
inventoryPositionCount: { type: integer }
WarehousePallet:
type: object
required: [palletId, palletCode, status, version, locationId, locationCode, occupiedPackages, inventoryPositionCount, inventory]
required: [palletId, palletCode, status, version, occupiedPackages, inventoryPositionCount, inventory]
properties:
palletId: { type: string, pattern: '^[0-9]+$' }
palletCode: { type: string }
status: { type: string }
version: { type: integer }
locationId: { type: string, pattern: '^[0-9]+$' }
locationCode: { type: string }
locationId: { type: string, pattern: '^[0-9]+$', nullable: true }
locationCode: { type: string, nullable: true }
occupiedPackages: { type: integer, format: int64 }
inventoryPositionCount: { type: integer }
inventory: { type: array, items: { $ref: '#/components/schemas/InventoryItem' } }
@@ -548,6 +554,12 @@ components:
type: object
required: [code]
properties: { code: { type: string, minLength: 1, maxLength: 128 } }
NewRelabelPallet:
type: object
required: [relabelNo, idempotencyKey]
properties:
relabelNo: { type: string, minLength: 1, maxLength: 64 }
idempotencyKey: { type: string, minLength: 1, maxLength: 128 }
IdempotentAction:
type: object
required: [idempotencyKey]