feat: close overseas wallet and pallet cost flow
This commit is contained in:
@@ -1421,6 +1421,12 @@ CREATE TABLE IF NOT EXISTS ll_relabel_application (
|
||||
item_count INT NOT NULL DEFAULT 0 COMMENT '明细数量',
|
||||
total_package_count INT NOT NULL DEFAULT 0 COMMENT '总箱数',
|
||||
notified_package_count INT NOT NULL DEFAULT 0 COMMENT '已通知箱数',
|
||||
charge_amount DECIMAL(20,2) NOT NULL DEFAULT 0 COMMENT '换标费用CNY',
|
||||
charge_currency CHAR(3) NOT NULL DEFAULT 'CNY' COMMENT '费用币种',
|
||||
wallet_status VARCHAR(32) NOT NULL DEFAULT 'FREEZE_PENDING' COMMENT '资金状态',
|
||||
wallet_error_code VARCHAR(64) NULL COMMENT '资金错误码',
|
||||
wallet_error_message VARCHAR(500) NULL COMMENT '资金错误说明',
|
||||
wallet_command_event_id VARCHAR(64) NULL COMMENT '当前资金指令事件ID',
|
||||
idempotency_key VARCHAR(255) NOT NULL COMMENT '业务幂等键',
|
||||
request_hash CHAR(64) NOT NULL COMMENT '请求内容哈希',
|
||||
created_by VARCHAR(128) NULL COMMENT '创建人ID',
|
||||
@@ -1879,3 +1885,65 @@ INSERT IGNORE INTO ll_security_projection (
|
||||
'baseline-platform-admin-user-v0','1970-01-01 00:00:00.000','1970-01-01 00:00:00.000'),
|
||||
('AUTHORIZATION','1000001',0,NULL,0,0,SHA2('lastleg-baseline:platform_admin:AUTHORIZATION:0',256),
|
||||
'baseline-platform-admin-authorization-v0','1970-01-01 00:00:00.000','1970-01-01 00:00:00.000');
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ll_wallet_event_inbox (
|
||||
event_id VARCHAR(64) NOT NULL COMMENT '国内Finance资金结果事件ID',
|
||||
command_event_id VARCHAR(64) NOT NULL COMMENT '原海外资金指令事件ID',
|
||||
payload_hash CHAR(64) NOT NULL COMMENT '规范化载荷SHA-256',
|
||||
payload_json JSON NOT NULL COMMENT '冻结事件信封',
|
||||
status VARCHAR(16) NOT NULL COMMENT 'RECEIVED或PROCESSED',
|
||||
received_at DATETIME(3) NOT NULL COMMENT '接收时间',
|
||||
processed_at DATETIME(3) NULL COMMENT '处理完成时间',
|
||||
PRIMARY KEY (event_id),
|
||||
UNIQUE KEY uk_ll_wallet_command_result (command_event_id),
|
||||
KEY idx_ll_wallet_event_status (status,received_at)
|
||||
) ENGINE=InnoDB COMMENT='跨区客户资金结果幂等收件箱';
|
||||
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ll_procurement_daily_sequence (
|
||||
customer_id VARCHAR(128) NOT NULL COMMENT '客户ID',
|
||||
business_date DATE NOT NULL COMMENT '北京时间业务日期',
|
||||
sequence_value INT NOT NULL COMMENT '客户当日已分配最大序号',
|
||||
PRIMARY KEY (customer_id,business_date),
|
||||
CONSTRAINT chk_ll_procurement_sequence CHECK (sequence_value BETWEEN 1 AND 9999)
|
||||
) ENGINE=InnoDB COMMENT='海外采购客户日序列';
|
||||
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ll_overseas_procurement_file (
|
||||
id BIGINT NOT NULL COMMENT '主键ID', order_id BIGINT NOT NULL COMMENT '采购订单ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户ID',
|
||||
category VARCHAR(16) NOT NULL COMMENT 'RECEIPT签收文件或VOUCHER费用凭证', file_id BIGINT NOT NULL COMMENT 'File服务文件ID',
|
||||
file_name VARCHAR(255) NOT NULL COMMENT '文件名快照', content_type VARCHAR(128) NULL COMMENT '媒体类型', size_bytes BIGINT NOT NULL DEFAULT 0 COMMENT '文件大小',
|
||||
created_by VARCHAR(128) NULL COMMENT '上传人', created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '上传时间',
|
||||
PRIMARY KEY(id), UNIQUE KEY uk_ll_procurement_file(order_id,file_id), KEY idx_ll_procurement_file_order(customer_id,order_id,category,created_at),
|
||||
CONSTRAINT chk_ll_procurement_file_category CHECK(category IN ('RECEIPT','VOUCHER'))
|
||||
) ENGINE=InnoDB COMMENT='海外采购签收文件及费用凭证';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ll_overseas_procurement_fee (
|
||||
id BIGINT NOT NULL COMMENT '主键ID', order_id BIGINT NOT NULL COMMENT '采购订单ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户ID',
|
||||
fee_no VARCHAR(64) NOT NULL COMMENT '费用业务号', fee_item_code VARCHAR(32) NOT NULL COMMENT '费用项编码', fee_item_name VARCHAR(128) NOT NULL COMMENT '费用项名称',
|
||||
amount DECIMAL(20,2) NOT NULL COMMENT 'CNY金额', currency CHAR(3) NOT NULL DEFAULT 'CNY' COMMENT '费用币种', voucher_file_id BIGINT NOT NULL COMMENT '凭证文件ID',
|
||||
voucher_file_name VARCHAR(255) NOT NULL COMMENT '凭证文件名', remark VARCHAR(500) NULL COMMENT '说明',
|
||||
wallet_status VARCHAR(32) NOT NULL COMMENT '资金状态', wallet_error_code VARCHAR(64) NULL COMMENT '资金错误码', wallet_error_message VARCHAR(500) NULL COMMENT '资金错误说明',
|
||||
wallet_command_event_id VARCHAR(64) NULL COMMENT '当前资金指令事件ID', created_by VARCHAR(128) NULL COMMENT '登记人',
|
||||
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_procurement_fee_no(fee_no), KEY idx_ll_procurement_fee_order(customer_id,order_id,created_at),
|
||||
CONSTRAINT chk_ll_procurement_fee_amount CHECK(amount>0), CONSTRAINT chk_ll_procurement_fee_currency CHECK(currency='CNY')
|
||||
) ENGINE=InnoDB COMMENT='海外采购费用明细及资金生命周期';
|
||||
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ll_destuff_pallet_cost (
|
||||
id BIGINT NOT NULL COMMENT '主键ID', source_container_booking_id VARCHAR(128) NOT NULL COMMENT '来源柜次业务ID', container_no VARCHAR(64) NOT NULL COMMENT '集装箱号', warehouse_id BIGINT NULL COMMENT '海外仓ID',
|
||||
pallet_count INT NOT NULL COMMENT '实际打托数', total_actual_volume_cbm DECIMAL(20,6) NOT NULL COMMENT '客户实收总体积', total_cost DECIMAL(20,2) NOT NULL COMMENT '打托总成本', currency CHAR(3) NOT NULL DEFAULT 'CNY' COMMENT '成本币种',
|
||||
status VARCHAR(16) NOT NULL COMMENT '生成状态', created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', PRIMARY KEY(id),
|
||||
UNIQUE KEY uk_ll_destuff_cost_booking(source_container_booking_id), CONSTRAINT chk_ll_destuff_cost CHECK(pallet_count>0 AND total_actual_volume_cbm>0 AND total_cost>0 AND currency='CNY')
|
||||
) ENGINE=InnoDB COMMENT='拆柜打托实际成本汇总';
|
||||
CREATE TABLE IF NOT EXISTS ll_destuff_pallet_cost_allocation (
|
||||
id BIGINT NOT NULL COMMENT '主键ID', cost_id BIGINT NOT NULL COMMENT '打托成本汇总ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户ID', actual_volume_cbm DECIMAL(20,6) NOT NULL COMMENT '客户实收体积',
|
||||
allocated_amount DECIMAL(20,2) NOT NULL COMMENT '客户分摊金额', fee_source_id BIGINT NOT NULL COMMENT '海外费用来源ID', created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
|
||||
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='拆柜打托成本按客户实收体积分摊';
|
||||
|
||||
@@ -678,6 +678,27 @@ paths:
|
||||
required: true
|
||||
content: { application/json: { schema: { $ref: '#/components/schemas/ProcurementReview' } } }
|
||||
responses: { '200': { description: 统一 ApiResponse 包装的采购订单详情 } }
|
||||
/api/platform/v1/last-leg/overseas-procurements/{orderNo}/files/{category}:
|
||||
post:
|
||||
summary: 上传采购签收文件或费用凭证
|
||||
description: 权限 platform:overseas-business:purchase:edit;category 仅允许 RECEIPT 或 VOUCHER。
|
||||
security: [{ bearerAuth: [] }]
|
||||
parameters:
|
||||
- { name: orderNo, in: path, required: true, schema: { type: string } }
|
||||
- { name: category, in: path, required: true, schema: { type: string, enum: [RECEIPT, VOUCHER] } }
|
||||
- { name: customerId, in: query, required: true, schema: { type: string, pattern: '^[1-9][0-9]*$' } }
|
||||
requestBody: { required: true, content: { multipart/form-data: { schema: { type: object, required: [file], properties: { file: { type: string, format: binary } } } } } }
|
||||
responses: { '200': { description: 已保存文件元数据 } }
|
||||
/api/platform/v1/last-leg/overseas-procurements/{orderNo}/fees:
|
||||
post:
|
||||
summary: 登记采购费用并发起资金冻结
|
||||
description: 权限 platform:overseas-business:purchase:edit;订单必须已审核通过,费用凭证必须属于本订单。
|
||||
security: [{ bearerAuth: [] }]
|
||||
parameters:
|
||||
- { name: orderNo, in: path, required: true, schema: { type: string } }
|
||||
- { name: customerId, in: query, required: true, schema: { type: string, pattern: '^[1-9][0-9]*$' } }
|
||||
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/ProcurementFeeCreate' } } } }
|
||||
responses: { '200': { description: 已创建费用并进入冻结流程 }, '409': { description: 订单状态或凭证不允许 } }
|
||||
/api/merchant/v1/last-leg/delivery-orders:
|
||||
get:
|
||||
summary: 客户分页查询自己的派送单
|
||||
@@ -1641,13 +1662,14 @@ components:
|
||||
RelabelStatus: { type: string, enum: [PENDING_PROCESSING, PROCESSING, COMPLETED, REJECTED, CANCELLED] }
|
||||
RelabelCreate:
|
||||
type: object
|
||||
required: [customerOrderNo, overseasWarehouseId, labelDeadline, contactName, contactPhone, idempotencyKey, items]
|
||||
required: [customerOrderNo, overseasWarehouseId, labelDeadline, contactName, contactPhone, chargeAmount, idempotencyKey, items]
|
||||
properties:
|
||||
customerOrderNo: { type: string, maxLength: 128 }
|
||||
overseasWarehouseId: { type: string, maxLength: 128 }
|
||||
labelDeadline: { type: string, format: date-time }
|
||||
contactName: { type: string, maxLength: 128 }
|
||||
contactPhone: { type: string, maxLength: 64 }
|
||||
chargeAmount: { type: number, minimum: 0.01, description: 换标费用,币种固定 CNY }
|
||||
remark: { type: string, nullable: true, maxLength: 1000 }
|
||||
idempotencyKey: { type: string, maxLength: 255 }
|
||||
items: { type: array, minItems: 1, maxItems: 500, items: { $ref: '#/components/schemas/RelabelItem' } }
|
||||
@@ -1764,7 +1786,7 @@ components:
|
||||
updatedAt: { type: string, format: date-time }
|
||||
ProcurementDetail:
|
||||
type: object
|
||||
required: [summary, histories, outboundDetails]
|
||||
required: [summary, histories, outboundDetails, files, fees]
|
||||
properties:
|
||||
summary: { $ref: '#/components/schemas/ProcurementSummary' }
|
||||
productUrl: { type: string, nullable: true }
|
||||
@@ -1783,6 +1805,42 @@ components:
|
||||
reviewedAt: { type: string, format: date-time, nullable: true }
|
||||
histories: { type: array, items: { $ref: '#/components/schemas/BusinessHistory' } }
|
||||
outboundDetails: { type: array, items: { $ref: '#/components/schemas/ProcurementOutboundDetail' } }
|
||||
files: { type: array, items: { $ref: '#/components/schemas/ProcurementFile' } }
|
||||
fees: { type: array, items: { $ref: '#/components/schemas/ProcurementFee' } }
|
||||
ProcurementFeeCreate:
|
||||
type: object
|
||||
required: [feeItemCode, feeItemName, amount, voucherFileId]
|
||||
properties:
|
||||
feeItemCode: { type: string, maxLength: 64 }
|
||||
feeItemName: { type: string, maxLength: 128 }
|
||||
amount: { type: number, minimum: 0.01 }
|
||||
voucherFileId: { type: string, pattern: '^[0-9]+$' }
|
||||
remark: { type: string, nullable: true, maxLength: 500 }
|
||||
ProcurementFile:
|
||||
type: object
|
||||
properties:
|
||||
id: { type: string }
|
||||
category: { type: string, enum: [RECEIPT, VOUCHER] }
|
||||
fileId: { type: string }
|
||||
fileName: { type: string }
|
||||
contentType: { type: string, nullable: true }
|
||||
sizeBytes: { type: integer, format: int64 }
|
||||
createdAt: { type: string, format: date-time }
|
||||
ProcurementFee:
|
||||
type: object
|
||||
properties:
|
||||
id: { type: string }
|
||||
feeNo: { type: string }
|
||||
feeItemCode: { type: string }
|
||||
feeItemName: { type: string }
|
||||
amount: { type: number }
|
||||
currency: { type: string, enum: [CNY] }
|
||||
voucherFileId: { type: string }
|
||||
voucherFileName: { type: string }
|
||||
remark: { type: string, nullable: true }
|
||||
walletStatus: { type: string }
|
||||
walletErrorMessage: { type: string, nullable: true }
|
||||
createdAt: { type: string, format: date-time }
|
||||
ProcurementOutboundDetail:
|
||||
type: object
|
||||
properties:
|
||||
|
||||
Reference in New Issue
Block a user