修改提交
This commit is contained in:
@@ -1271,7 +1271,7 @@ CREATE TABLE IF NOT EXISTS ll_outbound_pallet_item (
|
||||
id BIGINT NOT NULL COMMENT '主键ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户租户ID', outbound_order_id BIGINT NOT NULL COMMENT '出库单ID',
|
||||
warehouse_pallet_id BIGINT NULL COMMENT '仓库实物托盘ID', pallet_no VARCHAR(128) NULL COMMENT '托盘号',
|
||||
destination_warehouse_id VARCHAR(128) NULL COMMENT '目的仓ID', destination_warehouse_code VARCHAR(128) NULL COMMENT '目的仓编码快照', destination_warehouse_name VARCHAR(255) NULL COMMENT '目的仓名称快照',
|
||||
package_count INT NOT NULL DEFAULT 0 COMMENT '箱数', picked_package_count INT NOT NULL DEFAULT 0 COMMENT '已拣箱数', status VARCHAR(32) NOT NULL DEFAULT 'WAIT_PICK' COMMENT '拣货状态', sku_code VARCHAR(128) NULL COMMENT '一件代发SKU', order_refs VARCHAR(2000) NULL COMMENT '关联订单信息', inbound_code VARCHAR(128) NULL COMMENT '入仓单号快照',
|
||||
package_count INT NOT NULL DEFAULT 0 COMMENT '箱数', picked_package_count INT NOT NULL DEFAULT 0 COMMENT '已拣箱数', status VARCHAR(32) NOT NULL DEFAULT 'WAIT_PICK' COMMENT '拣货状态', sku_code VARCHAR(128) NULL COMMENT '一件代发SKU', carton_marks VARCHAR(4000) NULL COMMENT '本次出库指定箱唛,逗号分隔', order_refs VARCHAR(2000) NULL COMMENT '关联订单信息', inbound_code VARCHAR(128) NULL COMMENT '入仓单号快照',
|
||||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', PRIMARY KEY (id),
|
||||
UNIQUE KEY uk_ll_outbound_pallet (customer_id,outbound_order_id,warehouse_pallet_id),
|
||||
KEY idx_ll_outbound_pallet_list (customer_id,outbound_order_id), KEY idx_ll_outbound_pallet_destination (customer_id,destination_warehouse_code)
|
||||
@@ -1466,10 +1466,22 @@ CREATE TABLE IF NOT EXISTS ll_relabel_item (
|
||||
carton_mark VARCHAR(255) NULL COMMENT '客户自有箱唛',
|
||||
fba_carton_mark VARCHAR(255) NULL COMMENT '关联FBA箱唛',
|
||||
destination_warehouse_id VARCHAR(128) NOT NULL COMMENT '该箱目的海外仓ID',
|
||||
destination_fba_warehouse_code VARCHAR(128) NOT NULL COMMENT 'FBA目的仓编码(与海外操作仓分离)',
|
||||
operation_type VARCHAR(32) NOT NULL DEFAULT 'CARTON_LABEL' COMMENT '换标模式:箱唛、SKU或组合换标',
|
||||
sku_relabel_items_json JSON NULL COMMENT '同箱SKU换标子明细快照(数量按件)',
|
||||
source_inventory_balance_id BIGINT NOT NULL COMMENT '原库存余额ID',
|
||||
source_inventory_position_id BIGINT NOT NULL COMMENT '原库存库位ID',
|
||||
source_inbound_order_id BIGINT NOT NULL COMMENT '原入仓单ID',
|
||||
source_inbound_order_no VARCHAR(128) NULL COMMENT '原入仓单号快照',
|
||||
source_inbound_code VARCHAR(128) NULL COMMENT '原进仓编码快照',
|
||||
source_warehouse_id VARCHAR(128) NOT NULL COMMENT '原海外中转仓ID',
|
||||
source_warehouse_code VARCHAR(128) NULL COMMENT '原海外中转仓编码快照',
|
||||
source_warehouse_name VARCHAR(255) NULL COMMENT '原海外中转仓名称快照',
|
||||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
|
||||
PRIMARY KEY (id),
|
||||
KEY idx_ll_relabel_item_application (customer_id,application_id),
|
||||
KEY idx_ll_relabel_item_sku (customer_id,sku_code)
|
||||
KEY idx_ll_relabel_item_sku (customer_id,sku_code),
|
||||
KEY idx_ll_relabel_item_source_position (customer_id,source_inventory_position_id)
|
||||
) ENGINE=InnoDB COMMENT='换标货物冻结明细';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ll_relabel_status_history (
|
||||
@@ -1885,6 +1897,25 @@ CREATE TABLE IF NOT EXISTS ll_security_projection (
|
||||
KEY idx_security_projection_permission (aggregate_id,permission_version)
|
||||
) ENGINE=InnoDB COMMENT='海外IAM安全状态与权限版本投影';
|
||||
|
||||
-- 兼容已有的旧版投影表:CREATE TABLE IF NOT EXISTS 不会补充后续新增字段。
|
||||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE()
|
||||
AND table_name='ll_security_projection' AND column_name='roles_json'), 'SELECT 1',
|
||||
'ALTER TABLE ll_security_projection ADD COLUMN roles_json JSON NULL COMMENT ''IAM投影的当前角色快照'' AFTER permission_version'));
|
||||
PREPARE stmt FROM @ddl;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE()
|
||||
AND table_name='ll_security_projection' AND column_name='authorities_json'), 'SELECT 1',
|
||||
'ALTER TABLE ll_security_projection ADD COLUMN authorities_json JSON NULL COMMENT ''IAM投影的当前海外权限快照'' AFTER roles_json'));
|
||||
PREPARE stmt FROM @ddl;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
UPDATE ll_security_projection SET roles_json=JSON_ARRAY() WHERE roles_json IS NULL;
|
||||
UPDATE ll_security_projection SET authorities_json=JSON_ARRAY() WHERE authorities_json IS NULL;
|
||||
ALTER TABLE ll_security_projection
|
||||
MODIFY COLUMN roles_json JSON NOT NULL COMMENT 'IAM投影的当前角色快照',
|
||||
MODIFY COLUMN authorities_json JSON NOT NULL COMMENT 'IAM投影的当前海外权限快照';
|
||||
|
||||
-- 开发基线固定管理员;后续真实 IAM 事件从 aggregate_version=1 单调覆盖该 version=0 投影。
|
||||
INSERT IGNORE INTO ll_security_projection (
|
||||
aggregate_type,aggregate_id,tenant_id,security_status,permission_version,roles_json,authorities_json,aggregate_version,
|
||||
@@ -1956,3 +1987,82 @@ CREATE TABLE IF NOT EXISTS ll_destuff_pallet_cost_allocation (
|
||||
PRIMARY KEY(id), UNIQUE KEY uk_ll_destuff_customer(cost_id,customer_id), UNIQUE KEY uk_ll_destuff_fee_source(fee_source_id),
|
||||
CONSTRAINT chk_ll_destuff_allocation CHECK(actual_volume_cbm>0 AND allocated_amount>=0)
|
||||
) ENGINE=InnoDB COMMENT='拆柜打托成本按客户实收体积分摊';
|
||||
|
||||
-- 客户退货预报、PDA 签收与仓储费起算批次
|
||||
CREATE TABLE IF NOT EXISTS ll_return_order (
|
||||
id BIGINT NOT NULL COMMENT '退货订单ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户ID和隔离键', return_no VARCHAR(128) NOT NULL COMMENT '退货订单号', overseas_warehouse_id VARCHAR(128) NOT NULL COMMENT '操作海外仓ID', customer_reference_no VARCHAR(128) NULL COMMENT '客户参考号', status VARCHAR(32) NOT NULL COMMENT 'PENDING_RECEIPT、PARTIALLY_RECEIVED或COMPLETED', expected_sku_types INT NOT NULL COMMENT '预报SKU种类数', expected_quantity BIGINT NOT NULL COMMENT '预报总数量', received_quantity BIGINT NOT NULL DEFAULT 0 COMMENT '累计实收总数量', remark VARCHAR(1000) NULL COMMENT '客户备注', idempotency_key VARCHAR(255) NOT NULL COMMENT '创建幂等键', request_hash CHAR(64) NOT NULL COMMENT '创建请求SHA-256', created_by VARCHAR(128) NULL COMMENT '创建操作人ID', created_at DATETIME(3) NOT NULL COMMENT '创建时间', updated_at DATETIME(3) NOT NULL COMMENT '最后更新时间',
|
||||
PRIMARY KEY(id), UNIQUE KEY uk_ll_return_order_customer_no(customer_id,return_no), UNIQUE KEY uk_ll_return_order_customer_key(customer_id,idempotency_key), KEY idx_ll_return_order_warehouse_status(overseas_warehouse_id,status,created_at), CONSTRAINT chk_ll_return_order_quantity CHECK(expected_sku_types>0 AND expected_quantity>0 AND received_quantity>=0 AND received_quantity<=expected_quantity)
|
||||
) ENGINE=InnoDB COMMENT='客户退货订单及SKU实收汇总';
|
||||
CREATE TABLE IF NOT EXISTS ll_return_order_item (
|
||||
id BIGINT NOT NULL COMMENT '退货预报明细ID', return_order_id BIGINT NOT NULL COMMENT '退货订单ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户ID和隔离键', sku_code VARCHAR(128) NOT NULL COMMENT 'SKU编码', product_name_zh VARCHAR(255) NULL COMMENT '中文品名', expected_quantity BIGINT NOT NULL COMMENT 'SKU预报数量', received_quantity BIGINT NOT NULL DEFAULT 0 COMMENT 'SKU累计实收数量', created_at DATETIME(3) NOT NULL COMMENT '创建时间', updated_at DATETIME(3) NOT NULL COMMENT '最后更新时间',
|
||||
PRIMARY KEY(id), UNIQUE KEY uk_ll_return_item_order_sku(return_order_id,sku_code), KEY idx_ll_return_item_sku(sku_code,received_quantity), CONSTRAINT chk_ll_return_item_quantity CHECK(expected_quantity>0 AND received_quantity>=0 AND received_quantity<=expected_quantity)
|
||||
) ENGINE=InnoDB COMMENT='客户退货订单的SKU预报与实收明细';
|
||||
CREATE TABLE IF NOT EXISTS ll_return_receipt (
|
||||
id BIGINT NOT NULL COMMENT 'PDA退货签收单ID', return_order_id BIGINT NOT NULL COMMENT '退货订单ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户ID和隔离键', receipt_no VARCHAR(128) NOT NULL COMMENT '签收单号', receipt_batch_no VARCHAR(128) NOT NULL COMMENT '签收批次号', tracking_no VARCHAR(128) NULL COMMENT '本次签收包裹的可选快递单号', bound_by VARCHAR(16) NOT NULL COMMENT '开始签收方式,RETURN_NO退货单号或SKU候选', status VARCHAR(32) NOT NULL COMMENT '签收状态,当前SIGNED', received_quantity BIGINT NOT NULL COMMENT '本次实收数量', operator_id VARCHAR(128) NOT NULL COMMENT 'PDA操作人ID', operator_name VARCHAR(128) NULL COMMENT 'PDA操作人名称', idempotency_key VARCHAR(255) NOT NULL COMMENT 'PDA确认幂等键', request_hash CHAR(64) NOT NULL COMMENT 'PDA确认请求SHA-256', signed_at DATETIME(3) NOT NULL COMMENT '签收时间', created_at DATETIME(3) NOT NULL COMMENT '创建时间',
|
||||
PRIMARY KEY(id), UNIQUE KEY uk_ll_return_receipt_no(receipt_no), UNIQUE KEY uk_ll_return_receipt_batch(receipt_batch_no), UNIQUE KEY uk_ll_return_receipt_operator_key(operator_id,idempotency_key), KEY idx_ll_return_receipt_order(return_order_id,signed_at), CONSTRAINT chk_ll_return_receipt_quantity CHECK(received_quantity>0), CONSTRAINT chk_ll_return_receipt_bound CHECK(bound_by IN('RETURN_NO','SKU'))
|
||||
) ENGINE=InnoDB COMMENT='PDA退货实收签收事实';
|
||||
|
||||
-- 已创建开发库升级为“客户只预报 SKU,快递单号仅属于签收批次”的最终模型。
|
||||
SET @ll_return_item_drop_tracking_order_sku = (SELECT IF(COUNT(*) > 0, 'ALTER TABLE ll_return_order_item DROP INDEX uk_ll_return_item_order_tracking_sku', 'SELECT 1') FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='ll_return_order_item' AND index_name='uk_ll_return_item_order_tracking_sku');
|
||||
PREPARE ll_return_item_drop_tracking_order_sku_stmt FROM @ll_return_item_drop_tracking_order_sku;
|
||||
EXECUTE ll_return_item_drop_tracking_order_sku_stmt;
|
||||
DEALLOCATE PREPARE ll_return_item_drop_tracking_order_sku_stmt;
|
||||
SET @ll_return_item_drop_tracking = (SELECT IF(COUNT(*) > 0, 'ALTER TABLE ll_return_order_item DROP INDEX idx_ll_return_item_tracking', 'SELECT 1') FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='ll_return_order_item' AND index_name='idx_ll_return_item_tracking');
|
||||
PREPARE ll_return_item_drop_tracking_stmt FROM @ll_return_item_drop_tracking;
|
||||
EXECUTE ll_return_item_drop_tracking_stmt;
|
||||
DEALLOCATE PREPARE ll_return_item_drop_tracking_stmt;
|
||||
SET @ll_return_item_drop_order = (SELECT IF(COUNT(*) > 0, 'ALTER TABLE ll_return_order_item DROP INDEX idx_ll_return_item_order', 'SELECT 1') FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='ll_return_order_item' AND index_name='idx_ll_return_item_order');
|
||||
PREPARE ll_return_item_drop_order_stmt FROM @ll_return_item_drop_order;
|
||||
EXECUTE ll_return_item_drop_order_stmt;
|
||||
DEALLOCATE PREPARE ll_return_item_drop_order_stmt;
|
||||
SET @ll_return_item_drop_tracking_no = (SELECT IF(COUNT(*) > 0, 'ALTER TABLE ll_return_order_item DROP COLUMN tracking_no', 'SELECT 1') FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_return_order_item' AND column_name='tracking_no');
|
||||
PREPARE ll_return_item_drop_tracking_no_stmt FROM @ll_return_item_drop_tracking_no;
|
||||
EXECUTE ll_return_item_drop_tracking_no_stmt;
|
||||
DEALLOCATE PREPARE ll_return_item_drop_tracking_no_stmt;
|
||||
SET @ll_return_item_add_order_sku = (SELECT IF(COUNT(*) = 0, 'ALTER TABLE ll_return_order_item ADD UNIQUE KEY uk_ll_return_item_order_sku(return_order_id,sku_code)', 'SELECT 1') FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='ll_return_order_item' AND index_name='uk_ll_return_item_order_sku');
|
||||
PREPARE ll_return_item_add_order_sku_stmt FROM @ll_return_item_add_order_sku;
|
||||
EXECUTE ll_return_item_add_order_sku_stmt;
|
||||
DEALLOCATE PREPARE ll_return_item_add_order_sku_stmt;
|
||||
SET @ll_return_item_add_sku_idx = (SELECT IF(COUNT(*) = 0, 'ALTER TABLE ll_return_order_item ADD KEY idx_ll_return_item_sku(sku_code,received_quantity)', 'SELECT 1') FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='ll_return_order_item' AND index_name='idx_ll_return_item_sku');
|
||||
PREPARE ll_return_item_add_sku_idx_stmt FROM @ll_return_item_add_sku_idx;
|
||||
EXECUTE ll_return_item_add_sku_idx_stmt;
|
||||
DEALLOCATE PREPARE ll_return_item_add_sku_idx_stmt;
|
||||
UPDATE ll_return_receipt SET bound_by='RETURN_NO' WHERE bound_by='TRACKING';
|
||||
SET @ll_return_receipt_drop_bound_check = (SELECT IF(COUNT(*) > 0, 'ALTER TABLE ll_return_receipt DROP CHECK chk_ll_return_receipt_bound', 'SELECT 1') FROM information_schema.table_constraints WHERE constraint_schema=DATABASE() AND table_name='ll_return_receipt' AND constraint_name='chk_ll_return_receipt_bound');
|
||||
PREPARE ll_return_receipt_drop_bound_check_stmt FROM @ll_return_receipt_drop_bound_check;
|
||||
EXECUTE ll_return_receipt_drop_bound_check_stmt;
|
||||
DEALLOCATE PREPARE ll_return_receipt_drop_bound_check_stmt;
|
||||
SET @ll_return_receipt_alter = 'ALTER TABLE ll_return_receipt MODIFY COLUMN tracking_no VARCHAR(128) NULL COMMENT ''本次签收包裹的可选快递单号'', MODIFY COLUMN bound_by VARCHAR(16) NOT NULL COMMENT ''开始签收方式,RETURN_NO退货单号或SKU候选'', ADD CONSTRAINT chk_ll_return_receipt_bound CHECK(bound_by IN(''RETURN_NO'',''SKU''))';
|
||||
PREPARE ll_return_receipt_alter_stmt FROM @ll_return_receipt_alter;
|
||||
EXECUTE ll_return_receipt_alter_stmt;
|
||||
DEALLOCATE PREPARE ll_return_receipt_alter_stmt;
|
||||
CREATE TABLE IF NOT EXISTS ll_return_receipt_item (
|
||||
id BIGINT NOT NULL COMMENT '签收SKU明细ID', receipt_id BIGINT NOT NULL COMMENT 'PDA退货签收单ID', return_order_item_id BIGINT NOT NULL COMMENT '退货预报明细ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户ID和隔离键', sku_code VARCHAR(128) NOT NULL COMMENT 'SKU编码', received_quantity BIGINT NOT NULL COMMENT '本次SKU实收数量',
|
||||
PRIMARY KEY(id), KEY idx_ll_return_receipt_item_receipt(receipt_id), KEY idx_ll_return_receipt_item_order_item(return_order_item_id), CONSTRAINT chk_ll_return_receipt_item_quantity CHECK(received_quantity>0)
|
||||
) ENGINE=InnoDB COMMENT='PDA退货签收SKU实际数量明细';
|
||||
CREATE TABLE IF NOT EXISTS ll_return_receipt_batch (
|
||||
id BIGINT NOT NULL COMMENT '退货仓储计费批次ID', return_order_id BIGINT NOT NULL COMMENT '退货订单ID', receipt_id BIGINT NOT NULL COMMENT 'PDA退货签收单ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户ID和隔离键', batch_no VARCHAR(128) NOT NULL COMMENT '签收批次号', overseas_warehouse_id VARCHAR(128) NOT NULL COMMENT '操作海外仓ID', storage_billing_status VARCHAR(32) NOT NULL COMMENT '仓储计费状态,初始PENDING_PRICING', storage_started_at DATETIME(3) NOT NULL COMMENT '仓储计费起算时间', created_at DATETIME(3) NOT NULL COMMENT '创建时间',
|
||||
PRIMARY KEY(id), UNIQUE KEY uk_ll_return_batch_no(batch_no), UNIQUE KEY uk_ll_return_batch_receipt(receipt_id), KEY idx_ll_return_batch_billing(customer_id,overseas_warehouse_id,storage_billing_status,storage_started_at)
|
||||
) ENGINE=InnoDB COMMENT='每次退货签收生成的仓储费起算批次';
|
||||
|
||||
-- 退货库存:签收即生成箱号,库存按客户、海外仓和SKU汇总;箱内明细保留给合箱与箱唛。
|
||||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_return_receipt' AND column_name='carton_mark'), 'SELECT 1', 'ALTER TABLE ll_return_receipt ADD COLUMN carton_mark VARCHAR(128) NULL COMMENT ''签收生成或绑定的退货箱号'' AFTER receipt_batch_no'));
|
||||
PREPARE return_receipt_carton_mark_stmt FROM @ddl; EXECUTE return_receipt_carton_mark_stmt; DEALLOCATE PREPARE return_receipt_carton_mark_stmt;
|
||||
CREATE TABLE IF NOT EXISTS ll_return_inventory_carton (
|
||||
id BIGINT NOT NULL COMMENT '退货库存箱ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户ID和隔离键', overseas_warehouse_id VARCHAR(128) NOT NULL COMMENT '海外仓ID', source_receipt_id BIGINT NULL COMMENT '来源PDA签收单ID', source_batch_no VARCHAR(128) NULL COMMENT '来源签收批次号', carton_mark VARCHAR(128) NOT NULL COMMENT '退货箱号和箱唛编码', status VARCHAR(32) NOT NULL COMMENT 'AVAILABLE可用或MERGED已合箱', sku_types INT NOT NULL COMMENT '箱内SKU种类数', total_quantity BIGINT NOT NULL COMMENT '箱内总件数', length DECIMAL(12,3) NULL COMMENT '箱长CM', width DECIMAL(12,3) NULL COMMENT '箱宽CM', height DECIMAL(12,3) NULL COMMENT '箱高CM', weight DECIMAL(12,3) NULL COMMENT '箱重KG', created_at DATETIME(3) NOT NULL COMMENT '创建时间', updated_at DATETIME(3) NOT NULL COMMENT '最后更新时间', merged_at DATETIME(3) NULL COMMENT '合箱完成时间',
|
||||
PRIMARY KEY(id), UNIQUE KEY uk_ll_return_inventory_carton_mark(carton_mark), UNIQUE KEY uk_ll_return_inventory_carton_receipt(source_receipt_id), KEY idx_ll_return_inventory_carton_customer(customer_id,overseas_warehouse_id,status,created_at), CONSTRAINT chk_ll_return_inventory_carton_quantity CHECK(sku_types>0 AND total_quantity>0), CONSTRAINT chk_ll_return_inventory_carton_status CHECK(status IN('AVAILABLE','MERGED'))
|
||||
) ENGINE=InnoDB COMMENT='退货实物库存箱及箱唛';
|
||||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_return_inventory_carton' AND column_name='source_return_no'), 'SELECT 1', 'ALTER TABLE ll_return_inventory_carton ADD COLUMN source_return_no VARCHAR(2000) NULL COMMENT ''来源退货单号'' AFTER source_batch_no'));
|
||||
PREPARE return_inventory_carton_return_no_stmt FROM @ddl; EXECUTE return_inventory_carton_return_no_stmt; DEALLOCATE PREPARE return_inventory_carton_return_no_stmt;
|
||||
CREATE TABLE IF NOT EXISTS ll_return_inventory_carton_item (
|
||||
id BIGINT NOT NULL COMMENT '退货库存箱SKU明细ID', carton_id BIGINT NOT NULL COMMENT '退货库存箱ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户ID和隔离键', sku_code VARCHAR(128) NOT NULL COMMENT 'SKU编码', product_name_zh VARCHAR(255) NULL COMMENT '中文品名', quantity BIGINT NOT NULL COMMENT '该SKU箱内数量',
|
||||
PRIMARY KEY(id), UNIQUE KEY uk_ll_return_inventory_carton_item(carton_id,sku_code), KEY idx_ll_return_inventory_carton_item_customer(customer_id,sku_code), CONSTRAINT chk_ll_return_inventory_carton_item_quantity CHECK(quantity>0)
|
||||
) ENGINE=InnoDB COMMENT='退货库存箱内SKU和数量';
|
||||
CREATE TABLE IF NOT EXISTS ll_return_inventory_balance (
|
||||
id BIGINT NOT NULL COMMENT '退货库存余额ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户ID和隔离键', overseas_warehouse_id VARCHAR(128) NOT NULL COMMENT '海外仓ID', sku_code VARCHAR(128) NOT NULL COMMENT 'SKU编码', product_name_zh VARCHAR(255) NULL COMMENT '中文品名', available_quantity BIGINT NOT NULL COMMENT '可用上架数量', carton_quantity BIGINT NOT NULL COMMENT '包含该SKU的可用箱数', created_at DATETIME(3) NOT NULL COMMENT '创建时间', updated_at DATETIME(3) NOT NULL COMMENT '最后更新时间',
|
||||
PRIMARY KEY(id), UNIQUE KEY uk_ll_return_inventory_balance(customer_id,overseas_warehouse_id,sku_code), CONSTRAINT chk_ll_return_inventory_balance_quantity CHECK(available_quantity>=0 AND carton_quantity>=0)
|
||||
) ENGINE=InnoDB COMMENT='退货库存按客户海外仓SKU汇总余额';
|
||||
CREATE TABLE IF NOT EXISTS ll_return_inventory_operation (
|
||||
id BIGINT NOT NULL COMMENT '退货库存PDA操作ID', operator_id VARCHAR(128) NOT NULL COMMENT 'PDA操作人ID', idempotency_key VARCHAR(255) NOT NULL COMMENT '操作幂等键', request_hash CHAR(64) NOT NULL COMMENT '请求内容SHA-256', operation_type VARCHAR(32) NOT NULL COMMENT '操作类型,当前MERGE', result_carton_id BIGINT NULL COMMENT '合箱结果退货库存箱ID', created_at DATETIME(3) NOT NULL COMMENT '创建时间', updated_at DATETIME(3) NOT NULL COMMENT '最后更新时间',
|
||||
PRIMARY KEY(id), UNIQUE KEY uk_ll_return_inventory_operation_operator_key(operator_id,idempotency_key), KEY idx_ll_return_inventory_operation_result(result_carton_id)
|
||||
) ENGINE=InnoDB COMMENT='退货库存PDA合箱幂等操作审计';
|
||||
|
||||
@@ -1018,8 +1018,174 @@ 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/merchant/v1/last-leg/return-orders:
|
||||
get:
|
||||
summary: 客户分页查询退货签收订单
|
||||
description: 客户范围只取认证 Token。可按退货单号、快递单号、SKU 和签收状态过滤;实收数量以仓库 PDA 签收为准。
|
||||
security: [{ bearerAuth: [] }]
|
||||
parameters:
|
||||
- { 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: returnNo, in: query, schema: { type: string } }
|
||||
- { name: trackingNo, in: query, schema: { type: string } }
|
||||
- { name: skuCode, in: query, schema: { type: string } }
|
||||
- { name: status, in: query, schema: { type: string, enum: [PENDING_RECEIPT, PARTIALLY_RECEIVED, COMPLETED] } }
|
||||
responses: { '200': { description: 当前客户退货订单分页 } }
|
||||
post:
|
||||
summary: 客户创建退货预报订单
|
||||
description: 客户只预报不重复的 SKU 和预计数量,不要求提前知道快递单号;仓库 PDA 实收数量才是实际入库事实。
|
||||
security: [{ bearerAuth: [] }]
|
||||
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/ReturnOrderCreate' } } } }
|
||||
responses: { '200': { description: 创建后的退货订单详情 }, '409': { description: 幂等键冲突 } }
|
||||
/api/merchant/v1/last-leg/return-orders/{returnNo}:
|
||||
get:
|
||||
summary: 客户查询退货订单与签收批次
|
||||
description: 返回各 SKU 的预报和实收数量,以及每次 PDA 签收产生的批次号和可选快递单号。
|
||||
security: [{ bearerAuth: [] }]
|
||||
parameters: [{ name: returnNo, in: path, required: true, schema: { type: string } }]
|
||||
responses: { '200': { description: 当前客户退货订单详情 }, '404': { description: 当前客户下退货订单不存在 } }
|
||||
/api/pda/v1/last-leg/return-receipts/start:
|
||||
post:
|
||||
summary: PDA 以退件单号开始签收
|
||||
description: 仓库先从包裹收件信息取得客户填写的退件单号。仅当前绑定仓的 PENDING_RECEIPT(待签收)和 PARTIALLY_RECEIVED(签收中)退货单可开始签收,并返回该单尚未签收的 SKU 明细。
|
||||
security: [{ bearerAuth: [] }]
|
||||
requestBody: { required: true, content: { application/json: { schema: { type: object, required: [returnNo], properties: { returnNo: { type: string, maxLength: 128 } } } } } }
|
||||
responses: { '200': { description: 可开始签收的退货单及未签收 SKU 明细 }, '404': { description: 当前仓没有待签收或签收中的退货单 } }
|
||||
/api/pda/v1/last-leg/return-receipts/sku-candidates:
|
||||
post:
|
||||
summary: PDA 扫描 SKU 查询候选退货单
|
||||
description: 仅查询当前 PDA 绑定仓内待签收或签收中的退货单,最多返回 50 个候选。仓库人员根据退货单号、客户和数量选择后,再调用 start 进入统一签收流程。
|
||||
security: [{ bearerAuth: [] }]
|
||||
requestBody: { required: true, content: { application/json: { schema: { type: object, required: [skuCode], properties: { skuCode: { type: string, maxLength: 128 } } } } } }
|
||||
responses: { '200': { description: SKU 及候选退货单列表;没有匹配时 candidates 为空数组 } }
|
||||
/api/pda/v1/last-leg/return-receipts/confirm:
|
||||
post:
|
||||
summary: PDA 确认退货签收
|
||||
description: PDA 仅能操作绑定海外仓。startedBy 记录通过退货单号或 SKU 候选进入;trackingNo 为本次包裹可选快递单号。按预报可签收数量校验、禁止超收;每次成功确认创建唯一签收单及仓储计费批次。全部预报 SKU 数量吻合时自动 COMPLETED。
|
||||
security: [{ bearerAuth: [] }]
|
||||
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/ReturnReceiptConfirm' } } } }
|
||||
responses: { '200': { description: 签收结果及自动完成状态 }, '409': { description: 超收、错绑或幂等键冲突 } }
|
||||
/api/merchant/v1/last-leg/return-inventory:
|
||||
get:
|
||||
summary: 客户查询退货库存
|
||||
description: 客户范围只取认证 Token。库存按客户、海外仓、SKU 和箱号查询,数量以仓库 PDA 实收上架数量为准。
|
||||
security: [{ bearerAuth: [] }]
|
||||
parameters:
|
||||
- { 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: overseasWarehouseId, in: query, schema: { type: string, maxLength: 128 } }
|
||||
- { name: skuCode, in: query, schema: { type: string, maxLength: 128 } }
|
||||
- { name: cartonMark, in: query, schema: { type: string, maxLength: 128 } }
|
||||
responses: { '200': { description: 当前客户退货库存分页 } }
|
||||
/api/merchant/v1/last-leg/return-inventory/summary:
|
||||
get:
|
||||
summary: 客户查询退货库存 SKU 汇总
|
||||
description: 客户范围只取认证 Token。按海外仓和 SKU 汇总 PDA 实收上架数量及可用箱数。
|
||||
security: [{ bearerAuth: [] }]
|
||||
parameters:
|
||||
- { 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: overseasWarehouseId, in: query, schema: { type: string, maxLength: 128 } }
|
||||
- { name: skuCode, in: query, schema: { type: string, maxLength: 128 } }
|
||||
responses: { '200': { description: 当前客户 SKU 汇总库存分页 } }
|
||||
/api/merchant/v1/last-leg/return-inventory/cartons/{cartonMark}:
|
||||
get:
|
||||
summary: 客户查询退货箱明细
|
||||
description: 仅返回当前客户的箱号、签收批次和箱内 SKU 数量。
|
||||
security: [{ bearerAuth: [] }]
|
||||
parameters: [{ name: cartonMark, in: path, required: true, schema: { type: string, maxLength: 128 } }]
|
||||
responses: { '200': { description: 当前客户退货箱明细 }, '404': { description: 当前客户下退货箱不存在 } }
|
||||
/api/merchant/v1/last-leg/return-inventory/cartons/{cartonMark}/label:
|
||||
get:
|
||||
summary: 客户获取退货箱唛
|
||||
description: 返回当前客户退货箱的可打印标签及 SKU 数量,客户可据此打印或复核箱唛。
|
||||
security: [{ bearerAuth: [] }]
|
||||
parameters: [{ name: cartonMark, in: path, required: true, schema: { type: string, maxLength: 128 } }]
|
||||
responses: { '200': { description: 当前客户退货箱唛 }, '404': { description: 当前客户下退货箱不存在 } }
|
||||
/api/pda/v1/last-leg/return-inventory/cartons/merge:
|
||||
post:
|
||||
summary: PDA 合并退货箱
|
||||
description: 仅当前 PDA 绑定海外仓可操作。选择同一客户的已完成退货单,按查询出的 SKU 填写本箱数量并录入箱规;系统扣减可用库存并生成合箱箱号。
|
||||
security: [{ bearerAuth: [] }]
|
||||
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/ReturnInventoryMerge' } } } }
|
||||
responses: { '200': { description: 新箱号、SKU 汇总数量及可打印箱唛 }, '409': { description: 箱状态、客户或 SKU 不满足合箱条件,或幂等键冲突 } }
|
||||
/api/pda/v1/last-leg/return-inventory/packing/orders:
|
||||
get:
|
||||
summary: PDA 查询可合箱退货单和 SKU 库存
|
||||
security: [{ bearerAuth: [] }]
|
||||
parameters: [{ name: returnNo, in: query, required: false, schema: { type: string, maxLength: 128 } }]
|
||||
responses: { '200': { description: 当前仓已完成签收退货单及可用 SKU 数量 } }
|
||||
/api/pda/v1/last-leg/return-inventory/cartons/{cartonMark}/label:
|
||||
get:
|
||||
summary: PDA 获取退货箱唛
|
||||
description: 返回当前绑定仓退货箱的结构化数据及 100mm x 150mm 可打印 HTML,包含箱号、仓库、客户、签收批次及 SKU 数量。
|
||||
security: [{ bearerAuth: [] }]
|
||||
parameters: [{ name: cartonMark, in: path, required: true, schema: { type: string, maxLength: 128 } }]
|
||||
responses: { '200': { description: 退货箱唛打印数据 }, '404': { description: 当前仓没有该退货箱 } }
|
||||
components:
|
||||
schemas:
|
||||
ReturnOrderCreate:
|
||||
type: object
|
||||
required: [overseasWarehouseId, idempotencyKey, items]
|
||||
properties:
|
||||
overseasWarehouseId: { type: string, maxLength: 128 }
|
||||
customerReferenceNo: { type: string, maxLength: 128 }
|
||||
remark: { type: string, maxLength: 1000 }
|
||||
idempotencyKey: { type: string, maxLength: 255 }
|
||||
items:
|
||||
type: array
|
||||
minItems: 1
|
||||
maxItems: 500
|
||||
items:
|
||||
type: object
|
||||
required: [skuCode, expectedQuantity]
|
||||
properties:
|
||||
skuCode: { type: string, maxLength: 128 }
|
||||
productNameZh: { type: string, maxLength: 255 }
|
||||
expectedQuantity: { type: integer, minimum: 1 }
|
||||
ReturnReceiptConfirm:
|
||||
type: object
|
||||
required: [returnNo, startedBy, items, idempotencyKey]
|
||||
properties:
|
||||
returnNo: { type: string, maxLength: 128 }
|
||||
trackingNo: { type: string, nullable: true, maxLength: 128, description: '本次签收包裹有快递面单时扫描绑定;没有时为空' }
|
||||
startedBy: { type: string, enum: [RETURN_NO, SKU], description: '本次通过退货单号查询或 SKU 候选开始签收' }
|
||||
cartonMark: { type: string, nullable: true, maxLength: 128, description: PDA 实际绑定的箱号;不传时由系统生成 }
|
||||
idempotencyKey: { type: string, maxLength: 255 }
|
||||
items:
|
||||
type: array
|
||||
minItems: 1
|
||||
maxItems: 500
|
||||
items:
|
||||
type: object
|
||||
required: [skuCode, receivedQuantity]
|
||||
properties:
|
||||
skuCode: { type: string, maxLength: 128 }
|
||||
receivedQuantity: { type: integer, minimum: 1 }
|
||||
ReturnInventoryMerge:
|
||||
type: object
|
||||
required: [returnNos, items, length, width, height, weight, idempotencyKey]
|
||||
properties:
|
||||
returnNos:
|
||||
type: array
|
||||
minItems: 1
|
||||
maxItems: 100
|
||||
items: { type: string, minLength: 1, maxLength: 128 }
|
||||
items:
|
||||
type: array
|
||||
minItems: 1
|
||||
maxItems: 500
|
||||
items:
|
||||
type: object
|
||||
required: [skuCode, quantity]
|
||||
properties:
|
||||
skuCode: { type: string, maxLength: 128 }
|
||||
quantity: { type: integer, minimum: 1 }
|
||||
length: { type: number, exclusiveMinimum: 0, description: '箱长,CM' }
|
||||
width: { type: number, exclusiveMinimum: 0, description: '箱宽,CM' }
|
||||
height: { type: number, exclusiveMinimum: 0, description: '箱高,CM' }
|
||||
weight: { type: number, exclusiveMinimum: 0, description: '箱重,KG' }
|
||||
idempotencyKey: { type: string, minLength: 1, maxLength: 255 }
|
||||
InboundCodeRelationship:
|
||||
type: object
|
||||
required: [inboundCode, found, taillegOrders, inboundPlans, palletCodes, inventory]
|
||||
@@ -1645,7 +1811,7 @@ components:
|
||||
required: [customerOrderNo, labelDeadline, contactName, contactPhone, chargeAmount, idempotencyKey, items]
|
||||
properties:
|
||||
customerOrderNo: { type: string, maxLength: 128 }
|
||||
overseasWarehouseId: { type: string, nullable: true, maxLength: 128, description: 统一目的海外仓;明细未填写目的仓时使用 }
|
||||
operationWarehouseId: { type: string, maxLength: 128, description: 换标操作所在海外中转仓,和FBA目的仓分离 }
|
||||
labelDeadline: { type: string, format: date-time }
|
||||
contactName: { type: string, maxLength: 128 }
|
||||
contactPhone: { type: string, maxLength: 64 }
|
||||
@@ -1655,8 +1821,11 @@ components:
|
||||
items: { type: array, minItems: 1, maxItems: 500, items: { $ref: '#/components/schemas/RelabelItem' } }
|
||||
RelabelItem:
|
||||
type: object
|
||||
required: [productNameZh, totalPackageCount, notifiedPackageCount, shipmentNo, newSkuCode, cartonMark, fbaCartonMark]
|
||||
required: [sourceInventoryBalanceId, sourceInventoryPositionId, sourceInboundOrderId, productNameZh, totalPackageCount, notifiedPackageCount, shipmentNo, cartonMark]
|
||||
properties:
|
||||
sourceInventoryBalanceId: { type: string, pattern: '^[0-9]+$', description: 来源库存余额ID }
|
||||
sourceInventoryPositionId: { type: string, pattern: '^[0-9]+$', description: 来源库存仓位ID;同箱任务唯一冻结依据 }
|
||||
sourceInboundOrderId: { type: string, pattern: '^[0-9]+$', description: 来源历史入仓单ID }
|
||||
skuCode: { type: string, nullable: true, maxLength: 128, description: 商品 SKU(选填) }
|
||||
productImageFileId: { type: string, nullable: true, maxLength: 128 }
|
||||
productImageFileName: { type: string, nullable: true, maxLength: 255 }
|
||||
@@ -1666,14 +1835,24 @@ components:
|
||||
notifiedPackageCount: { type: integer, minimum: 1 }
|
||||
shipmentNo: { type: string, maxLength: 128 }
|
||||
trackingCode: { type: string, nullable: true, maxLength: 255 }
|
||||
newSkuCode: { type: string, maxLength: 128 }
|
||||
newSkuCode: { type: string, nullable: true, maxLength: 128, description: 箱唛换标时的单个新SKU兼容字段 }
|
||||
labelRequirement: { type: string, nullable: true, maxLength: 1000 }
|
||||
relabelFileId: { type: string, nullable: true, maxLength: 128 }
|
||||
relabelFileName: { type: string, nullable: true, maxLength: 255 }
|
||||
relabelFileUrl: { type: string, nullable: true, maxLength: 1000 }
|
||||
cartonMark: { type: string, maxLength: 255, description: 客户自有箱唛(不在编辑列表展示) }
|
||||
fbaCartonMark: { type: string, maxLength: 255, description: 关联 FBA 箱唛 }
|
||||
destinationWarehouseId: { type: string, nullable: true, maxLength: 128, description: 该箱目的海外仓;为空时使用申请统一目的仓 }
|
||||
cartonMark: { type: string, maxLength: 255, description: 我方箱唛;同一申请内不可重复,整箱库存只冻结一次 }
|
||||
fbaCartonMark: { type: string, nullable: true, maxLength: 255, description: 新FBA箱唛;箱唛或组合换标必填 }
|
||||
destinationFbaWarehouseCode: { type: string, nullable: true, maxLength: 128, description: FBA目的仓编码;箱唛或组合换标必填 }
|
||||
operationType: { type: string, enum: [CARTON_LABEL, SKU_LABEL, CARTON_AND_SKU], description: 箱唛换标、SKU换标或组合换标 }
|
||||
skuItems: { type: array, maxItems: 100, description: 同一箱唛内SKU换标子明细,数量按件;SKU或组合换标必填, items: { $ref: '#/components/schemas/RelabelSkuItem' } }
|
||||
RelabelSkuItem:
|
||||
type: object
|
||||
required: [skuCode, newSkuCode, quantity]
|
||||
properties:
|
||||
skuCode: { type: string, maxLength: 128, description: 原SKU }
|
||||
newSkuCode: { type: string, maxLength: 128, description: 换标后SKU }
|
||||
quantity: { type: integer, minimum: 1, description: 换标件数 }
|
||||
remark: { type: string, nullable: true, maxLength: 1000 }
|
||||
RelabelStatusChange:
|
||||
type: object
|
||||
required: [status]
|
||||
|
||||
@@ -185,7 +185,7 @@ paths:
|
||||
responses: { '200': { description: 已认领任务, content: { application/json: { schema: { $ref: '#/components/schemas/RelabelDetailResponse' } } } }, '409': { description: 仓库、状态或幂等冲突 } }
|
||||
/api/pda/v1/last-leg/relabel-tasks/{relabelNo}/units:
|
||||
post:
|
||||
summary: 登记一件正常换标事实
|
||||
summary: 扫描我方箱唛并登记整箱正常换标事实;可只传oldLabel由服务端定位箱唛任务
|
||||
parameters: [{ name: relabelNo, in: path, required: true, schema: { type: string } }]
|
||||
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/RelabelUnit' } } } }
|
||||
responses: { '200': { description: 更新后的任务, content: { application/json: { schema: { $ref: '#/components/schemas/RelabelDetailResponse' } } } }, '409': { description: 旧标重复、新标不符或版本冲突 } }
|
||||
@@ -485,10 +485,22 @@ components:
|
||||
relabelFileId: { type: string, nullable: true }
|
||||
relabelFileName: { type: string, nullable: true }
|
||||
relabelFileUrl: { type: string, nullable: true }
|
||||
cartonMark: { type: string, nullable: true, description: 我方箱唛 }
|
||||
fbaCartonMark: { type: string, nullable: true, description: 新FBA箱唛 }
|
||||
operationType: { type: string, enum: [CARTON_LABEL, SKU_LABEL, CARTON_AND_SKU] }
|
||||
skuItems: { type: array, items: { $ref: '#/components/schemas/RelabelSkuItem' } }
|
||||
expectedPackages: { type: integer }
|
||||
relabelledPackages: { type: integer }
|
||||
skippedPackages: { type: integer }
|
||||
exceptionPackages: { type: integer }
|
||||
RelabelSkuItem:
|
||||
type: object
|
||||
required: [skuCode, newSkuCode, quantity]
|
||||
properties:
|
||||
skuCode: { type: string }
|
||||
newSkuCode: { type: string }
|
||||
quantity: { type: integer, description: 换标件数 }
|
||||
remark: { type: string, nullable: true }
|
||||
RelabelUnitFact:
|
||||
type: object
|
||||
properties:
|
||||
|
||||
Reference in New Issue
Block a user