优化
This commit is contained in:
@@ -18,7 +18,7 @@ spring:
|
||||
- optional:nacos:${spring.application.name}.yml?group=BAIYUE&refreshEnabled=true
|
||||
cloud:
|
||||
nacos:
|
||||
server-addr: ${NACOS_SERVER_ADDR:127.0.0.1:8858}
|
||||
server-addr: ${NACOS_SERVER_ADDR:127.0.0.1:8848}
|
||||
username: ${NACOS_USERNAME:nacos}
|
||||
password: ${NACOS_PASSWORD:nacos}
|
||||
discovery:
|
||||
@@ -35,6 +35,16 @@ spring:
|
||||
management.endpoints.web.exposure.include: health,info,prometheus
|
||||
|
||||
baiyue:
|
||||
clients:
|
||||
domestic-warehouse:
|
||||
url: ${DOMESTIC_WAREHOUSE_URL:}
|
||||
cache-ttl: ${DOMESTIC_WAREHOUSE_CACHE_TTL:30m}
|
||||
firstleg:
|
||||
event-bridge-url: ${FIRSTLEG_EVENT_BRIDGE_URL:}
|
||||
outbox-relay:
|
||||
fixed-delay-ms: ${FIRSTLEG_OUTBOX_RELAY_FIXED_DELAY_MS:5000}
|
||||
lease-seconds: ${FIRSTLEG_OUTBOX_RELAY_LEASE_SECONDS:60}
|
||||
retry-seconds: ${FIRSTLEG_OUTBOX_RELAY_RETRY_SECONDS:30}
|
||||
security:
|
||||
internal-service-token: ${INTERNAL_SERVICE_TOKEN:phase1-local-internal-token-at-least-32-bytes}
|
||||
jwt-mode: jwks
|
||||
|
||||
@@ -519,11 +519,82 @@ CREATE TABLE IF NOT EXISTS ll_event_outbox (
|
||||
event_key VARCHAR(255) NOT NULL COMMENT '业务幂等键', payload_json LONGTEXT NOT NULL COMMENT '事件载荷JSON',
|
||||
status VARCHAR(32) NOT NULL DEFAULT 'PENDING' COMMENT '发布状态', retry_count INT NOT NULL DEFAULT 0 COMMENT '重试次数',
|
||||
next_retry_at DATETIME(3) NULL COMMENT '下次重试时间', published_at DATETIME(3) NULL COMMENT '发布时间',
|
||||
locked_at DATETIME(3) NULL COMMENT '投递租约获取时间', locked_by VARCHAR(128) NULL COMMENT '投递租约持有者',
|
||||
last_error VARCHAR(1000) NULL COMMENT '最后一次发布错误', created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
|
||||
PRIMARY KEY (id), UNIQUE KEY uk_ll_event_outbox_key (event_key),
|
||||
KEY idx_ll_event_outbox_publish (status, next_retry_at, created_at)
|
||||
) ENGINE=InnoDB COMMENT='尾程跨区业务事件发件箱';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ll_overseas_quote (
|
||||
id BIGINT NOT NULL COMMENT '报价ID', name VARCHAR(128) NOT NULL COMMENT '报价名称',
|
||||
warehouse_id BIGINT NOT NULL COMMENT '国内平台海外合作仓ID', warehouse_code VARCHAR(64) NOT NULL COMMENT '合作仓编码快照',
|
||||
warehouse_name VARCHAR(128) NOT NULL COMMENT '合作仓名称快照', country_code VARCHAR(2) NOT NULL COMMENT '国家二字码快照',
|
||||
provider_name VARCHAR(128) NOT NULL COMMENT '报价方', currency CHAR(3) NOT NULL COMMENT '币种',
|
||||
effective_start DATE NOT NULL COMMENT '生效开始日期', effective_end DATE NOT NULL COMMENT '生效结束日期',
|
||||
version_code VARCHAR(64) NOT NULL COMMENT '业务版本号', status VARCHAR(16) NOT NULL DEFAULT 'INACTIVE' COMMENT '状态:ACTIVE/INACTIVE',
|
||||
remark VARCHAR(1000) NULL COMMENT '备注', record_version BIGINT NOT NULL DEFAULT 0 COMMENT '乐观锁版本',
|
||||
created_by VARCHAR(128) NOT NULL COMMENT '创建人', updated_by VARCHAR(128) NOT NULL COMMENT '更新人',
|
||||
created_at DATETIME(3) NOT NULL COMMENT '创建时间', updated_at DATETIME(3) NOT NULL COMMENT '更新时间',
|
||||
PRIMARY KEY (id), UNIQUE KEY uk_ll_quote_warehouse_provider_version (warehouse_id,provider_name,version_code),
|
||||
KEY idx_ll_quote_page (status,updated_at,id), KEY idx_ll_quote_effective (warehouse_id,provider_name,currency,effective_start,effective_end)
|
||||
) ENGINE=InnoDB COMMENT='海外仓报价主表';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ll_overseas_quote_fee (
|
||||
id BIGINT NOT NULL COMMENT '费用明细ID', quote_id BIGINT NOT NULL COMMENT '报价ID', sequence_no INT NOT NULL COMMENT '显示顺序',
|
||||
item VARCHAR(128) NOT NULL COMMENT '费用项目', billing_unit VARCHAR(64) NOT NULL COMMENT '计费单位',
|
||||
unit_price DECIMAL(18,4) NOT NULL COMMENT '单价', minimum_charge DECIMAL(18,4) NOT NULL DEFAULT 0 COMMENT '最低收费',
|
||||
remark VARCHAR(500) NULL COMMENT '备注', PRIMARY KEY (id), UNIQUE KEY uk_ll_quote_fee_sequence (quote_id,sequence_no),
|
||||
KEY idx_ll_quote_fee_quote (quote_id)
|
||||
) ENGINE=InnoDB COMMENT='海外仓报价仓库费用';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ll_overseas_quote_transit_price (
|
||||
id BIGINT NOT NULL COMMENT '中转价格ID', quote_id BIGINT NOT NULL COMMENT '报价ID', sequence_no INT NOT NULL COMMENT '显示顺序',
|
||||
fba_warehouse_code VARCHAR(64) NOT NULL COMMENT 'FBA仓编码', delivery_method VARCHAR(64) NOT NULL COMMENT '报价运输方式',
|
||||
estimated_miles DECIMAL(18,4) NOT NULL DEFAULT 0 COMMENT '预估英里数', price DECIMAL(18,4) NOT NULL COMMENT '报价金额',
|
||||
minimum_charge DECIMAL(18,4) NOT NULL DEFAULT 0 COMMENT '最低收费', remark VARCHAR(500) NULL COMMENT '备注',
|
||||
PRIMARY KEY (id), UNIQUE KEY uk_ll_quote_transit_sequence (quote_id,sequence_no),
|
||||
KEY idx_ll_quote_transit_quote (quote_id)
|
||||
) ENGINE=InnoDB COMMENT='海外仓报价中转价格明细';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ll_monthly_exchange_rate (
|
||||
id BIGINT NOT NULL COMMENT '月度汇率ID', rate_month CHAR(7) NOT NULL COMMENT '汇率月份,格式yyyy-MM',
|
||||
base_currency CHAR(3) NOT NULL DEFAULT 'USD' COMMENT '基准币种', quote_currency CHAR(3) NOT NULL DEFAULT 'CNY' COMMENT '报价币种',
|
||||
usd_to_cny_average DECIMAL(18,8) NOT NULL COMMENT '美元兑人民币月平均汇率', status VARCHAR(16) NOT NULL DEFAULT 'ACTIVE' COMMENT '状态:ACTIVE/INACTIVE',
|
||||
remark VARCHAR(1000) NULL COMMENT '备注', record_version BIGINT NOT NULL DEFAULT 0 COMMENT '乐观锁版本',
|
||||
created_by VARCHAR(128) NOT NULL COMMENT '创建人', updated_by VARCHAR(128) NOT NULL COMMENT '更新人',
|
||||
created_at DATETIME(3) NOT NULL COMMENT '创建时间', updated_at DATETIME(3) NOT NULL COMMENT '更新时间',
|
||||
PRIMARY KEY (id), UNIQUE KEY uk_ll_exchange_rate_month (rate_month),
|
||||
KEY idx_ll_exchange_rate_page (status,rate_month)
|
||||
) ENGINE=InnoDB COMMENT='美元兑人民币月度平均汇率';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ll_monthly_exchange_rate_history (
|
||||
id BIGINT NOT NULL COMMENT '汇率变更历史ID', exchange_rate_id BIGINT NOT NULL COMMENT '月度汇率ID',
|
||||
before_rate DECIMAL(18,8) NULL COMMENT '变更前汇率', after_rate DECIMAL(18,8) NOT NULL COMMENT '变更后汇率',
|
||||
before_status VARCHAR(16) NULL COMMENT '变更前状态', after_status VARCHAR(16) NOT NULL COMMENT '变更后状态',
|
||||
operator_id VARCHAR(128) NOT NULL COMMENT '操作人', remark VARCHAR(1000) NULL COMMENT '变更说明',
|
||||
created_at DATETIME(3) NOT NULL COMMENT '创建时间', PRIMARY KEY (id),
|
||||
KEY idx_ll_exchange_rate_history (exchange_rate_id,created_at)
|
||||
) ENGINE=InnoDB COMMENT='月度汇率变更历史';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ll_vehicle (
|
||||
id BIGINT NOT NULL COMMENT '车辆档案ID', plate_number VARCHAR(64) NOT NULL COMMENT '车牌号',
|
||||
model VARCHAR(128) NOT NULL COMMENT '车型', fuel_consumption_per100_km DECIMAL(10,2) NOT NULL COMMENT '百公里油耗,单位升',
|
||||
mileage_km BIGINT NOT NULL COMMENT '当前公里码,单位公里', driver_or_dispatch_company VARCHAR(128) NULL COMMENT '司机姓名或外派单位',
|
||||
phone VARCHAR(64) NULL COMMENT '司机或外派单位联系电话', region VARCHAR(16) NOT NULL COMMENT '区域:DOMESTIC/OVERSEAS',
|
||||
ownership VARCHAR(16) NOT NULL COMMENT '车辆归属:OWNED/DISPATCHED',
|
||||
status VARCHAR(32) NOT NULL COMMENT '状态:IN_SERVICE/DISPATCHED/MAINTENANCE/INACTIVE/RETURNED',
|
||||
remark VARCHAR(1000) NULL COMMENT '备注', record_version BIGINT NOT NULL DEFAULT 0 COMMENT '乐观锁版本',
|
||||
created_by VARCHAR(128) NOT NULL COMMENT '创建人', updated_by VARCHAR(128) NOT NULL COMMENT '更新人',
|
||||
created_at DATETIME(3) NOT NULL COMMENT '创建时间', updated_at DATETIME(3) NOT NULL COMMENT '更新时间',
|
||||
PRIMARY KEY (id), UNIQUE KEY uk_ll_vehicle_plate (plate_number),
|
||||
KEY idx_ll_vehicle_page (ownership,region,status,updated_at,id)
|
||||
) ENGINE=InnoDB COMMENT='平台车辆主数据';
|
||||
|
||||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_event_outbox' AND column_name='locked_at'), 'SELECT 1', 'ALTER TABLE ll_event_outbox ADD COLUMN locked_at DATETIME(3) NULL COMMENT ''投递租约获取时间'' AFTER published_at'));
|
||||
PREPARE ll_outbox_lease_stmt FROM @ddl; EXECUTE ll_outbox_lease_stmt; DEALLOCATE PREPARE ll_outbox_lease_stmt;
|
||||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_event_outbox' AND column_name='locked_by'), 'SELECT 1', 'ALTER TABLE ll_event_outbox ADD COLUMN locked_by VARCHAR(128) NULL COMMENT ''投递租约持有者'' AFTER locked_at'));
|
||||
PREPARE ll_outbox_lease_stmt FROM @ddl; EXECUTE ll_outbox_lease_stmt; DEALLOCATE PREPARE ll_outbox_lease_stmt;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ll_inbound_pda_operation (
|
||||
id BIGINT NOT NULL COMMENT '主键ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户租户ID', task_id BIGINT NOT NULL COMMENT 'PDA任务ID',
|
||||
allocation_id BIGINT NULL COMMENT '分配记录ID', action VARCHAR(32) NOT NULL COMMENT '操作动作', idempotency_key VARCHAR(255) NOT NULL COMMENT '业务幂等键',
|
||||
@@ -604,6 +675,9 @@ CREATE TABLE IF NOT EXISTS ll_inventory_balance (
|
||||
inbound_order_id BIGINT NOT NULL COMMENT '入仓单ID',
|
||||
inbound_order_no VARCHAR(128) NULL COMMENT '入仓单号快照',
|
||||
inbound_code VARCHAR(128) NOT NULL COMMENT '入仓单号快照',
|
||||
sku_code VARCHAR(128) NOT NULL COMMENT 'SKU编码;无SKU的专项库存使用UNSPECIFIED',
|
||||
product_name_zh VARCHAR(255) NULL COMMENT '中文品名快照',
|
||||
product_name_en VARCHAR(255) NULL COMMENT '英文品名快照',
|
||||
available_packages BIGINT NOT NULL DEFAULT 0 COMMENT '可用箱数', hold_packages BIGINT NOT NULL DEFAULT 0 COMMENT '冻结箱数',
|
||||
allocated_packages BIGINT NOT NULL DEFAULT 0 COMMENT '已分配箱数', picked_packages BIGINT NOT NULL DEFAULT 0 COMMENT '已拣箱数',
|
||||
in_transit_packages BIGINT NOT NULL DEFAULT 0 COMMENT '在途箱数', receiving_packages BIGINT NOT NULL DEFAULT 0 COMMENT '收货处理中箱数',
|
||||
@@ -612,10 +686,11 @@ CREATE TABLE IF NOT EXISTS ll_inventory_balance (
|
||||
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_inventory_dimension (customer_id,overseas_warehouse_id,destination_warehouse_code,inbound_order_id,inbound_code),
|
||||
UNIQUE KEY uk_ll_inventory_dimension (customer_id,overseas_warehouse_id,destination_warehouse_code,inbound_order_id,inbound_code,sku_code),
|
||||
KEY idx_ll_inventory_list (customer_id,overseas_warehouse_id,updated_at),
|
||||
KEY idx_ll_inventory_inbound (customer_id,inbound_code)
|
||||
) ENGINE=InnoDB COMMENT='入仓单维度实时库存余额';
|
||||
KEY idx_ll_inventory_inbound (customer_id,inbound_code),
|
||||
KEY idx_ll_inventory_sku (customer_id,sku_code,updated_at)
|
||||
) ENGINE=InnoDB COMMENT='入仓单与SKU维度实时库存余额';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ll_inventory_position (
|
||||
id BIGINT NOT NULL COMMENT '主键ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户租户ID', balance_id BIGINT NOT NULL COMMENT '库存余额记录ID',
|
||||
@@ -669,13 +744,15 @@ CREATE TABLE IF NOT EXISTS ll_inbound_stock_receipt (
|
||||
id BIGINT NOT NULL COMMENT '主键ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户租户ID',
|
||||
plan_id BIGINT NOT NULL COMMENT '入仓计划ID', task_id BIGINT NOT NULL COMMENT 'PDA任务ID', allocation_id BIGINT NOT NULL COMMENT '分配记录ID',
|
||||
line_id BIGINT NOT NULL COMMENT '入仓计划明细ID', order_id BIGINT NOT NULL COMMENT '订单ID', inbound_code VARCHAR(128) NOT NULL COMMENT '入仓单号快照',
|
||||
sku_code VARCHAR(128) NOT NULL COMMENT 'SKU编码快照', product_name_zh VARCHAR(255) NULL COMMENT '中文品名快照',
|
||||
product_name_en VARCHAR(255) NULL COMMENT '英文品名快照',
|
||||
warehouse_pallet_id BIGINT NOT NULL COMMENT '仓库实物托盘ID', pallet_no VARCHAR(64) NOT NULL COMMENT '托盘号',
|
||||
warehouse_location_id BIGINT NULL COMMENT '仓库库位ID', warehouse_location_code VARCHAR(128) NULL COMMENT '仓库库位编码',
|
||||
batch_no VARCHAR(128) NOT NULL COMMENT '库存批次号', received_packages BIGINT NOT NULL COMMENT '实收箱数',
|
||||
inventory_balance_id BIGINT NOT NULL COMMENT '库存余额记录ID', inventory_position_id BIGINT NOT NULL COMMENT '库存仓位记录ID',
|
||||
inventory_operation_key VARCHAR(255) NOT NULL COMMENT '库存操作幂等键', received_at DATETIME(3) NOT NULL COMMENT '实收时间',
|
||||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
|
||||
PRIMARY KEY (id), UNIQUE KEY uk_ll_stock_receipt_task_allocation (customer_id,task_id,allocation_id),
|
||||
PRIMARY KEY (id), UNIQUE KEY uk_ll_stock_receipt_task_allocation_sku (customer_id,task_id,allocation_id,sku_code),
|
||||
KEY idx_ll_stock_receipt_plan (customer_id,plan_id,line_id), KEY idx_ll_stock_receipt_inventory (inventory_balance_id,inventory_position_id)
|
||||
) ENGINE=InnoDB COMMENT='入仓PDA库存实收快照';
|
||||
|
||||
@@ -1080,7 +1157,7 @@ CREATE TABLE IF NOT EXISTS ll_overseas_procurement_order (
|
||||
currency CHAR(3) NOT NULL DEFAULT 'USD' COMMENT '币种', receiving_address VARCHAR(1000) NULL COMMENT '收货地址',
|
||||
contact_name VARCHAR(128) NOT NULL COMMENT '联系人姓名', contact_phone VARCHAR(64) NOT NULL COMMENT '联系人电话',
|
||||
purchase_warehouse_id VARCHAR(128) NULL COMMENT '采购入仓仓库ID', purchase_warehouse_name VARCHAR(255) NULL COMMENT '采购入仓仓库名称',
|
||||
inbound_quantity BIGINT NOT NULL DEFAULT 0 COMMENT '累计入库数量', outbound_quantity BIGINT NOT NULL DEFAULT 0 COMMENT '累计出库数量',
|
||||
inbound_quantity BIGINT NOT NULL DEFAULT 0 COMMENT '采购单据累计入库数量',
|
||||
domestic_carrier VARCHAR(128) NULL COMMENT '境内承运商', domestic_tracking_no VARCHAR(128) NULL COMMENT '境内物流单号',
|
||||
overseas_carrier VARCHAR(128) NULL COMMENT '海外承运商', overseas_tracking_no VARCHAR(128) NULL COMMENT '海外物流单号',
|
||||
estimated_arrival_at DATETIME(3) NULL COMMENT '预计到达时间', status VARCHAR(32) NOT NULL DEFAULT 'PENDING_REVIEW' COMMENT '业务状态',
|
||||
@@ -1095,22 +1172,14 @@ CREATE TABLE IF NOT EXISTS ll_overseas_procurement_order (
|
||||
KEY idx_ll_overseas_procurement_warehouse(customer_id,purchase_warehouse_id,created_at)
|
||||
) ENGINE=InnoDB COMMENT='海外采购订单';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ll_overseas_procurement_outbound (
|
||||
id BIGINT NOT NULL COMMENT '主键ID', order_id BIGINT NOT NULL COMMENT '订单ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户租户ID',
|
||||
quantity BIGINT NOT NULL COMMENT '数量', outbound_no VARCHAR(128) NOT NULL COMMENT '出库单号', carrier VARCHAR(128) NULL COMMENT '承运商',
|
||||
tracking_no VARCHAR(128) NULL COMMENT '物流跟踪号', outbound_at DATETIME(3) NOT NULL COMMENT '出库时间',
|
||||
remark VARCHAR(1000) NULL COMMENT '备注', created_by VARCHAR(128) NULL COMMENT '创建人ID',
|
||||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', PRIMARY KEY(id),
|
||||
UNIQUE KEY uk_ll_overseas_procurement_outbound_no(customer_id,order_id,outbound_no),
|
||||
KEY idx_ll_overseas_procurement_outbound_order(customer_id,order_id,outbound_at)
|
||||
) ENGINE=InnoDB COMMENT='海外采购出库记录';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ll_overseas_procurement_status_history (
|
||||
id BIGINT NOT NULL COMMENT '主键ID', order_id BIGINT NOT NULL COMMENT '订单ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户租户ID',
|
||||
operation_type VARCHAR(32) NOT NULL COMMENT '操作类型:CREATE、REVIEW或UPDATE',
|
||||
from_status VARCHAR(32) NULL COMMENT '变更前状态', to_status VARCHAR(32) NOT NULL COMMENT '变更后状态', operator_id VARCHAR(128) NULL COMMENT '操作人ID',
|
||||
remark VARCHAR(1000) NULL COMMENT '备注', created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
|
||||
change_detail JSON NULL COMMENT '字段变更前后值JSON', remark VARCHAR(1000) NULL COMMENT '备注',
|
||||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
|
||||
PRIMARY KEY(id), KEY idx_ll_overseas_procurement_history(customer_id,order_id,created_at)
|
||||
) ENGINE=InnoDB COMMENT='海外采购审核历史';
|
||||
) ENGINE=InnoDB COMMENT='海外采购操作流水';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ll_us_truck_order (
|
||||
id BIGINT NOT NULL COMMENT '主键ID',
|
||||
@@ -1183,3 +1252,34 @@ CREATE TABLE IF NOT EXISTS ll_us_truck_order_status_history (
|
||||
PRIMARY KEY(id),
|
||||
KEY idx_ll_us_truck_history(customer_id,order_id,created_at)
|
||||
) ENGINE=InnoDB COMMENT='美国卡车订单状态历史';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ll_local_looseboard_order (
|
||||
id BIGINT NOT NULL COMMENT '主键ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户租户ID',
|
||||
order_no VARCHAR(64) NOT NULL COMMENT '本土散板订单号', transport_mode VARCHAR(32) NOT NULL COMMENT '运输方式:拼车或优先拼载',
|
||||
pallet_required VARCHAR(8) NOT NULL COMMENT '是否需要打盘:YES或NO', transport_type VARCHAR(32) NOT NULL COMMENT '运输类型',
|
||||
origin VARCHAR(255) NOT NULL COMMENT '起运地', origin_address VARCHAR(500) NULL COMMENT '起运详细地址',
|
||||
destination VARCHAR(255) NOT NULL COMMENT '目的地', destination_address VARCHAR(500) NULL COMMENT '目的详细地址、码头或仓号',
|
||||
container_type VARCHAR(32) NULL COMMENT '柜型', package_count INT NOT NULL DEFAULT 0 COMMENT '货物件数',
|
||||
total_weight_kg DECIMAL(18,3) NOT NULL DEFAULT 0 COMMENT '总重量(千克)',
|
||||
total_volume_cbm DECIMAL(18,6) NOT NULL DEFAULT 0 COMMENT '总体积(立方米)',
|
||||
budget_amount DECIMAL(18,2) NULL COMMENT '预算总价', currency CHAR(3) NOT NULL DEFAULT 'USD' COMMENT '预算币种',
|
||||
contact_name VARCHAR(128) NULL COMMENT '联系人姓名', contact_info VARCHAR(128) NULL COMMENT '联系人联系方式',
|
||||
requested_date DATE NULL COMMENT '要求服务日期', status VARCHAR(32) NOT NULL DEFAULT 'PENDING_ACCEPTANCE' COMMENT '本土散板订单状态',
|
||||
remark VARCHAR(1000) NULL COMMENT '备注', idempotency_key VARCHAR(255) NOT NULL COMMENT '创建幂等键',
|
||||
request_hash CHAR(64) NOT NULL COMMENT '创建请求内容哈希', created_by VARCHAR(128) NULL COMMENT '创建人ID',
|
||||
version BIGINT NOT NULL DEFAULT 0 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_local_looseboard_no(customer_id,order_no),
|
||||
UNIQUE KEY uk_ll_local_looseboard_key(customer_id,idempotency_key),
|
||||
KEY idx_ll_local_looseboard_list(customer_id,status,created_at),
|
||||
KEY idx_ll_local_looseboard_date(customer_id,requested_date,created_at)
|
||||
) ENGINE=InnoDB COMMENT='本土散板订单';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ll_local_looseboard_history (
|
||||
id BIGINT NOT NULL COMMENT '主键ID', order_id BIGINT NOT NULL COMMENT '本土散板订单ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户租户ID',
|
||||
operation_type VARCHAR(32) NOT NULL COMMENT '操作类型:CREATE、UPDATE或STATUS', from_status VARCHAR(32) NULL COMMENT '变更前状态',
|
||||
to_status VARCHAR(32) NOT NULL COMMENT '变更后状态', operator_id VARCHAR(128) NULL COMMENT '操作人ID',
|
||||
change_detail JSON NULL COMMENT '字段变更前后值JSON', remark VARCHAR(1000) NULL COMMENT '操作备注',
|
||||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', PRIMARY KEY(id),
|
||||
KEY idx_ll_local_looseboard_history(customer_id,order_id,created_at)
|
||||
) ENGINE=InnoDB COMMENT='本土散板操作流水';
|
||||
|
||||
@@ -0,0 +1,312 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
title: Lastleg Overseas Business API
|
||||
version: 1.0.0
|
||||
paths:
|
||||
/api/platform/v1/last-leg/overseas-procurements:
|
||||
get:
|
||||
summary: 分页查询海外采购订单
|
||||
description: 权限 platform:overseas-business:purchase:list;customerId 为空时查询全部客户。
|
||||
security: [{ bearerAuth: [] }]
|
||||
parameters:
|
||||
- { name: customerId, in: query, schema: { type: string } }
|
||||
- { name: page, in: query, required: true, schema: { type: integer, minimum: 1 } }
|
||||
- { name: size, in: query, required: true, schema: { type: integer, minimum: 1, maximum: 200 } }
|
||||
- { name: orderNo, in: query, schema: { type: string } }
|
||||
- { name: customerKeyword, in: query, schema: { type: string } }
|
||||
- { name: purchaseCategory, in: query, schema: { type: string } }
|
||||
- { name: productName, in: query, schema: { type: string } }
|
||||
- { name: status, in: query, schema: { $ref: '#/components/schemas/ProcurementStatus' } }
|
||||
- { name: purchaseWarehouseId, in: query, schema: { type: string } }
|
||||
responses: { '200': { description: 统一 ApiResponse 包装的采购订单分页 } }
|
||||
/api/platform/v1/last-leg/overseas-procurements/customer-options:
|
||||
get:
|
||||
summary: 查询已有采购订单的客户候选
|
||||
description: 权限 platform:overseas-business:purchase:list;候选来自尾程库采购订单客户快照,不跨库查询 IAM。
|
||||
security: [{ bearerAuth: [] }]
|
||||
parameters:
|
||||
- { name: keyword, in: query, schema: { type: string } }
|
||||
- { name: limit, in: query, schema: { type: integer, minimum: 1, maximum: 200, default: 50 } }
|
||||
responses:
|
||||
'200':
|
||||
description: 客户候选
|
||||
content: { application/json: { schema: { $ref: '#/components/schemas/CustomerOptionResponse' } } }
|
||||
/api/platform/v1/last-leg/overseas-procurements/warehouse-options:
|
||||
get:
|
||||
summary: 查询启用的海外合作采购仓候选
|
||||
description: 权限 platform:overseas-business:purchase:list;复用服务端缓存目录,浏览器不访问国内内部 API。
|
||||
security: [{ bearerAuth: [] }]
|
||||
responses:
|
||||
'200':
|
||||
description: 采购仓候选
|
||||
content: { application/json: { schema: { $ref: '#/components/schemas/WarehouseOptionResponse' } } }
|
||||
/api/platform/v1/last-leg/overseas-procurements/{orderNo}:
|
||||
parameters:
|
||||
- { name: orderNo, in: path, required: true, schema: { type: string } }
|
||||
- { name: customerId, in: query, required: true, schema: { type: string, pattern: '^[1-9][0-9]*$' } }
|
||||
get:
|
||||
summary: 查询海外采购订单详情及操作流水
|
||||
description: 权限 platform:overseas-business:purchase:list。
|
||||
security: [{ bearerAuth: [] }]
|
||||
responses: { '200': { description: 统一 ApiResponse 包装的采购订单详情 } }
|
||||
patch:
|
||||
summary: 编辑海外采购订单
|
||||
description: 权限 platform:overseas-business:purchase:edit;可选字段缺失表示不修改,显式 null 或空串表示清空。采购仓名称由 warehouse ID 对应候选快照决定。采购出库不属于本 API。
|
||||
security: [{ bearerAuth: [] }]
|
||||
requestBody:
|
||||
required: true
|
||||
content: { application/json: { schema: { $ref: '#/components/schemas/ProcurementUpdate' } } }
|
||||
responses: { '200': { description: 统一 ApiResponse 包装的采购订单详情 }, '409': { description: 乐观锁冲突或状态不允许 } }
|
||||
/api/platform/v1/last-leg/overseas-procurements/{orderNo}/review:
|
||||
post:
|
||||
summary: 审核海外采购订单
|
||||
description: 权限 platform:overseas-business:purchase:review。
|
||||
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: { type: object, required: [decision], properties: { decision: { type: string, enum: [APPROVE, REJECT] }, remark: { type: string, nullable: true, maxLength: 1000 } } } } }
|
||||
responses: { '200': { description: 统一 ApiResponse 包装的采购订单详情 } }
|
||||
/api/merchant/v1/last-leg/overseas-procurements:
|
||||
post:
|
||||
summary: 客户创建海外采购订单
|
||||
description: 客户 ID 只取认证身份;新单固定进入 PENDING_REVIEW。
|
||||
security: [{ bearerAuth: [] }]
|
||||
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/ProcurementCreate' } } } }
|
||||
responses: { '200': { description: 统一 ApiResponse 包装的采购订单详情 } }
|
||||
get:
|
||||
summary: 客户分页查询自己的海外采购订单
|
||||
security: [{ bearerAuth: [] }]
|
||||
responses: { '200': { description: 统一 ApiResponse 包装的采购订单分页 } }
|
||||
/api/merchant/v1/last-leg/overseas-procurements/{orderNo}:
|
||||
get:
|
||||
summary: 客户查询自己的海外采购订单详情及流水
|
||||
security: [{ bearerAuth: [] }]
|
||||
parameters: [{ name: orderNo, in: path, required: true, schema: { type: string } }]
|
||||
responses: { '200': { description: 统一 ApiResponse 包装的采购订单详情 } }
|
||||
/api/platform/v1/last-leg/us-truck-orders:
|
||||
get:
|
||||
summary: 分页查询本土卡车订单
|
||||
description: 权限 platform:overseas-business:truck:list。
|
||||
security: [{ bearerAuth: [] }]
|
||||
responses: { '200': { description: 统一 ApiResponse 包装的卡车订单分页 } }
|
||||
post:
|
||||
summary: 平台为指定客户创建本土卡车订单
|
||||
description: 权限 platform:overseas-business:truck:create;customerId 必填且只作为可信服务端隔离键。
|
||||
security: [{ bearerAuth: [] }]
|
||||
parameters: [{ name: customerId, in: query, required: true, schema: { type: string, pattern: '^[1-9][0-9]*$' } }]
|
||||
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/TruckCreate' } } } }
|
||||
responses: { '200': { description: 统一 ApiResponse 包装的卡车订单详情 } }
|
||||
/api/platform/v1/last-leg/us-truck-orders/{orderNo}:
|
||||
parameters:
|
||||
- { name: orderNo, in: path, required: true, schema: { type: string } }
|
||||
- { name: customerId, in: query, required: true, schema: { type: string, pattern: '^[1-9][0-9]*$' } }
|
||||
get:
|
||||
summary: 查询本土卡车订单详情
|
||||
description: 权限 platform:overseas-business:truck:list。
|
||||
security: [{ bearerAuth: [] }]
|
||||
responses: { '200': { description: 统一 ApiResponse 包装的卡车订单详情 } }
|
||||
patch:
|
||||
summary: 平台普通编辑本土卡车订单
|
||||
description: 权限 platform:overseas-business:truck:edit;仅待审核订单可编辑,不能修改状态。
|
||||
security: [{ bearerAuth: [] }]
|
||||
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/TruckUpdate' } } } }
|
||||
responses: { '200': { description: 统一 ApiResponse 包装的卡车订单详情 } }
|
||||
/api/platform/v1/last-leg/us-truck-orders/{orderNo}/status:
|
||||
patch:
|
||||
summary: 推进本土卡车订单状态
|
||||
description: 权限 platform:overseas-business:truck:status;普通编辑接口不能修改状态。
|
||||
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: { type: object, required: [version, status], properties: { version: { type: integer, format: int64, minimum: 0 }, status: { $ref: '#/components/schemas/TruckStatus' }, remark: { type: string, nullable: true, maxLength: 1000 } } } } } }
|
||||
responses: { '200': { description: 统一 ApiResponse 包装的卡车订单详情 }, '409': { description: 非法状态迁移 } }
|
||||
/api/platform/v1/last-leg/us-truck-orders/{orderNo}/receive-pallets:
|
||||
post:
|
||||
summary: 记录本土卡车订单实收托盘
|
||||
description: 权限 platform:overseas-business:truck:status;幂等记录实收,不创建海外仓出库或派送单。
|
||||
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]*$' } }
|
||||
responses: { '200': { description: 统一 ApiResponse 包装的卡车订单详情 } }
|
||||
/api/platform/v1/last-leg/local-looseboard-orders:
|
||||
get:
|
||||
summary: 分页查询本土散板订单
|
||||
description: 权限 platform:overseas-business:looseboard:list。
|
||||
security: [{ bearerAuth: [] }]
|
||||
responses: { '200': { description: 统一 ApiResponse 包装的散板订单分页 } }
|
||||
post:
|
||||
summary: 创建本土散板订单
|
||||
description: 权限 platform:overseas-business:looseboard:create;独立稳定子域,不复用卡车端点。
|
||||
security: [{ bearerAuth: [] }]
|
||||
parameters: [{ name: customerId, in: query, required: true, schema: { type: string, pattern: '^[1-9][0-9]*$' } }]
|
||||
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/LooseboardCreate' } } } }
|
||||
responses: { '200': { description: 统一 ApiResponse 包装的散板订单详情 } }
|
||||
/api/platform/v1/last-leg/local-looseboard-orders/{orderNo}:
|
||||
parameters:
|
||||
- { name: orderNo, in: path, required: true, schema: { type: string } }
|
||||
- { name: customerId, in: query, required: true, schema: { type: string, pattern: '^[1-9][0-9]*$' } }
|
||||
get:
|
||||
summary: 查询本土散板订单详情及操作流水
|
||||
description: 权限 platform:overseas-business:looseboard:list。
|
||||
security: [{ bearerAuth: [] }]
|
||||
responses: { '200': { description: 统一 ApiResponse 包装的散板订单详情 } }
|
||||
put:
|
||||
summary: 全量更新待接单的本土散板订单
|
||||
description: 权限 platform:overseas-business:looseboard:edit;可空字段传 null 或空串即清空;状态由独立端点推进。
|
||||
security: [{ bearerAuth: [] }]
|
||||
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/LooseboardUpdate' } } } }
|
||||
responses: { '200': { description: 统一 ApiResponse 包装的散板订单详情 }, '409': { description: 版本或状态冲突 } }
|
||||
/api/platform/v1/last-leg/local-looseboard-orders/{orderNo}/status:
|
||||
patch:
|
||||
summary: 推进或取消本土散板订单
|
||||
description: 权限 platform:overseas-business:looseboard:status;只允许 PENDING_ACCEPTANCE→DISPATCHED→IN_TRANSIT→COMPLETED,未完成节点按规则取消。
|
||||
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: { type: object, required: [version, status], properties: { version: { type: integer, format: int64, minimum: 0 }, status: { $ref: '#/components/schemas/LooseboardStatus' }, remark: { type: string, nullable: true, maxLength: 1000 } } } } } }
|
||||
responses: { '200': { description: 统一 ApiResponse 包装的散板订单详情 }, '409': { description: 非法状态迁移 } }
|
||||
components:
|
||||
schemas:
|
||||
ProcurementStatus: { type: string, enum: [PENDING_REVIEW, APPROVED, REJECTED] }
|
||||
ProcurementCreate:
|
||||
type: object
|
||||
required: [purchaseCategory, productName, purchaseQuantity, contactName, contactPhone, idempotencyKey]
|
||||
properties:
|
||||
customerName: { type: string, nullable: true, maxLength: 255 }
|
||||
purchaseCategory: { type: string, maxLength: 128 }
|
||||
productName: { type: string, maxLength: 255 }
|
||||
productSpecification: { type: string, nullable: true, maxLength: 500 }
|
||||
productUrl: { type: string, nullable: true, maxLength: 2000 }
|
||||
purchaseQuantity: { type: integer, format: int64, minimum: 1 }
|
||||
budgetUnitPrice: { type: number, nullable: true, minimum: 0 }
|
||||
currency: { type: string, minLength: 3, maxLength: 3, default: USD }
|
||||
receivingAddress: { type: string, nullable: true, maxLength: 1000 }
|
||||
contactName: { type: string, maxLength: 128 }
|
||||
contactPhone: { type: string, maxLength: 64 }
|
||||
remark: { type: string, nullable: true, maxLength: 1000 }
|
||||
idempotencyKey: { type: string, maxLength: 255 }
|
||||
NullableTextPatch: { type: string, nullable: true, description: 缺失不修改;null 或空串清空 }
|
||||
ProcurementUpdate:
|
||||
type: object
|
||||
required: [version]
|
||||
properties:
|
||||
version: { type: integer, format: int64, minimum: 0 }
|
||||
purchaseCategory: { type: string, maxLength: 128 }
|
||||
productName: { type: string, maxLength: 255 }
|
||||
productSpecification: { $ref: '#/components/schemas/NullableTextPatch' }
|
||||
productUrl: { $ref: '#/components/schemas/NullableTextPatch' }
|
||||
inboundQuantity: { type: integer, format: int64, minimum: 0 }
|
||||
purchaseWarehouseId: { $ref: '#/components/schemas/NullableTextPatch' }
|
||||
purchaseWarehouseName: { $ref: '#/components/schemas/NullableTextPatch' }
|
||||
domesticCarrier: { $ref: '#/components/schemas/NullableTextPatch' }
|
||||
domesticTrackingNo: { $ref: '#/components/schemas/NullableTextPatch' }
|
||||
overseasCarrier: { $ref: '#/components/schemas/NullableTextPatch' }
|
||||
overseasTrackingNo: { $ref: '#/components/schemas/NullableTextPatch' }
|
||||
estimatedArrivalAt: { type: string, format: date-time, nullable: true, description: 缺失不修改;null 或空串清空 }
|
||||
remark: { $ref: '#/components/schemas/NullableTextPatch' }
|
||||
CustomerOptionResponse:
|
||||
type: object
|
||||
properties:
|
||||
code: { type: string, enum: ['200'] }
|
||||
data: { type: array, items: { type: object, properties: { customerId: { type: string }, customerName: { type: string } } } }
|
||||
WarehouseOptionResponse:
|
||||
type: object
|
||||
properties:
|
||||
code: { type: string, enum: ['200'] }
|
||||
data: { type: array, items: { type: object, properties: { warehouseId: { type: string }, warehouseCode: { type: string }, warehouseName: { type: string }, countryCode: { type: string } } } }
|
||||
TruckStatus: { type: string, enum: [PENDING_REVIEW, WAITING_INBOUND, RECEIVING, WAITING_CONSOLIDATION, PALLET_OVERAGE_REVIEW, PARTIALLY_ALLOCATED, ALLOCATED, PENDING_DISPATCH, DISPATCHED, IN_TRANSIT, COMPLETED, REJECTED, CANCELLED] }
|
||||
TruckCreate:
|
||||
type: object
|
||||
required: [origin, destination, palletCount, totalWeightKg, totalVolumeCbm, contactName, contactInfo, requestedDate, idempotencyKey]
|
||||
properties:
|
||||
transportType: { type: string, enum: [PORT_PICKUP, WAREHOUSE_TO_WAREHOUSE, WAREHOUSE_TO_DOOR] }
|
||||
origin: { type: string, maxLength: 255 }
|
||||
originAddress: { type: string, nullable: true, maxLength: 500 }
|
||||
destination: { type: string, maxLength: 255 }
|
||||
destinationAddress: { type: string, nullable: true, maxLength: 500 }
|
||||
containerType: { type: string, nullable: true, maxLength: 32 }
|
||||
palletCount: { type: integer, minimum: 1 }
|
||||
packageCount: { type: integer, nullable: true, minimum: 0 }
|
||||
totalWeightKg: { type: number, minimum: 0 }
|
||||
totalVolumeCbm: { type: number, minimum: 0 }
|
||||
budgetAmount: { type: number, nullable: true, minimum: 0 }
|
||||
currency: { type: string, minLength: 3, maxLength: 3, default: USD }
|
||||
contactName: { type: string, maxLength: 128 }
|
||||
contactInfo: { type: string, maxLength: 128 }
|
||||
requestedDate: { type: string, format: date }
|
||||
remark: { type: string, nullable: true, maxLength: 1000 }
|
||||
idempotencyKey: { type: string, maxLength: 255 }
|
||||
TruckUpdate:
|
||||
type: object
|
||||
required: [version]
|
||||
properties:
|
||||
version: { type: integer, format: int64, minimum: 0 }
|
||||
transportType: { type: string, enum: [PORT_PICKUP, WAREHOUSE_TO_WAREHOUSE, WAREHOUSE_TO_DOOR] }
|
||||
origin: { type: string, maxLength: 255 }
|
||||
originAddress: { type: string, nullable: true, maxLength: 500 }
|
||||
destination: { type: string, maxLength: 255 }
|
||||
destinationAddress: { type: string, nullable: true, maxLength: 500 }
|
||||
containerType: { type: string, nullable: true, maxLength: 32 }
|
||||
palletCount: { type: integer, minimum: 1 }
|
||||
packageCount: { type: integer, minimum: 0 }
|
||||
totalWeightKg: { type: number, minimum: 0 }
|
||||
totalVolumeCbm: { type: number, minimum: 0 }
|
||||
budgetAmount: { type: number, nullable: true, minimum: 0 }
|
||||
currency: { type: string, minLength: 3, maxLength: 3 }
|
||||
contactName: { type: string, maxLength: 128 }
|
||||
contactInfo: { type: string, maxLength: 128 }
|
||||
requestedDate: { type: string, format: date }
|
||||
remark: { type: string, nullable: true, maxLength: 1000 }
|
||||
LooseboardStatus: { type: string, enum: [PENDING_ACCEPTANCE, DISPATCHED, IN_TRANSIT, COMPLETED, CANCELLED] }
|
||||
LooseboardCreate:
|
||||
type: object
|
||||
required: [transportMode, palletRequired, transportType, origin, destination, packageCount, totalWeightKg, totalVolumeCbm, idempotencyKey]
|
||||
properties:
|
||||
transportMode: { type: string, enum: [SHARED_TRUCK, PRIORITY_CONSOLIDATION] }
|
||||
palletRequired: { type: string, enum: [YES, NO] }
|
||||
transportType: { type: string, enum: [PORT_PICKUP, WAREHOUSE_TO_WAREHOUSE, WAREHOUSE_TO_DOOR] }
|
||||
origin: { type: string, maxLength: 255 }
|
||||
originAddress: { type: string, nullable: true, maxLength: 500 }
|
||||
destination: { type: string, maxLength: 255 }
|
||||
destinationAddress: { type: string, nullable: true, maxLength: 500 }
|
||||
containerType: { type: string, nullable: true, maxLength: 32 }
|
||||
packageCount: { type: integer, minimum: 0 }
|
||||
totalWeightKg: { type: number, minimum: 0 }
|
||||
totalVolumeCbm: { type: number, minimum: 0 }
|
||||
budgetAmount: { type: number, nullable: true, minimum: 0 }
|
||||
currency: { type: string, minLength: 3, maxLength: 3, default: USD }
|
||||
contactName: { type: string, nullable: true, maxLength: 128 }
|
||||
contactInfo: { type: string, nullable: true, maxLength: 128 }
|
||||
requestedDate: { type: string, format: date, nullable: true }
|
||||
remark: { type: string, nullable: true, maxLength: 1000 }
|
||||
idempotencyKey: { type: string, maxLength: 255 }
|
||||
LooseboardUpdate:
|
||||
type: object
|
||||
required: [version, transportMode, palletRequired, transportType, origin, destination, packageCount, totalWeightKg, totalVolumeCbm]
|
||||
properties:
|
||||
version: { type: integer, format: int64, minimum: 0 }
|
||||
transportMode: { type: string, enum: [SHARED_TRUCK, PRIORITY_CONSOLIDATION] }
|
||||
palletRequired: { type: string, enum: [YES, NO] }
|
||||
transportType: { type: string, enum: [PORT_PICKUP, WAREHOUSE_TO_WAREHOUSE, WAREHOUSE_TO_DOOR] }
|
||||
origin: { type: string, maxLength: 255 }
|
||||
originAddress: { type: string, nullable: true, maxLength: 500 }
|
||||
destination: { type: string, maxLength: 255 }
|
||||
destinationAddress: { type: string, nullable: true, maxLength: 500 }
|
||||
containerType: { type: string, nullable: true, maxLength: 32 }
|
||||
packageCount: { type: integer, minimum: 0 }
|
||||
totalWeightKg: { type: number, minimum: 0 }
|
||||
totalVolumeCbm: { type: number, minimum: 0 }
|
||||
budgetAmount: { type: number, nullable: true, minimum: 0 }
|
||||
currency: { type: string, minLength: 3, maxLength: 3, default: USD }
|
||||
contactName: { type: string, nullable: true, maxLength: 128 }
|
||||
contactInfo: { type: string, nullable: true, maxLength: 128 }
|
||||
requestedDate: { type: string, format: date, nullable: true }
|
||||
remark: { type: string, nullable: true, maxLength: 1000 }
|
||||
securitySchemes:
|
||||
bearerAuth: { type: http, scheme: bearer, bearerFormat: JWT }
|
||||
@@ -0,0 +1,273 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
title: Lastleg Overseas Master Data API
|
||||
version: 1.0.0
|
||||
description: 海外仓报价、月度汇率与车辆主数据;车辆契约不包含派送履约历史。
|
||||
paths:
|
||||
/api/platform/v1/last-leg/master-data/overseas-quotes:
|
||||
get:
|
||||
summary: 分页查询海外仓报价
|
||||
description: '权限:platform:overseas-master-data:quote:list'
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/Page'
|
||||
- $ref: '#/components/parameters/Size'
|
||||
- { name: keyword, in: query, schema: { type: string } }
|
||||
- { name: warehouseId, in: query, schema: { type: string } }
|
||||
- { name: providerName, in: query, schema: { type: string } }
|
||||
- { name: currency, in: query, schema: { type: string } }
|
||||
- { name: status, in: query, schema: { $ref: '#/components/schemas/ActiveStatus' } }
|
||||
responses: { '200': { description: 业务响应,data为PageResult<QuoteSummary> } }
|
||||
post:
|
||||
summary: 创建海外仓报价
|
||||
description: '权限:platform:overseas-master-data:quote:create;服务端读取国内overseas-partners并缓存合作仓目录30分钟'
|
||||
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/QuoteCreate' } } } }
|
||||
responses: { '200': { description: 业务响应,data为报价详情 } }
|
||||
/api/platform/v1/last-leg/master-data/overseas-quotes/warehouse-options:
|
||||
get:
|
||||
summary: 查询缓存的有效海外合作仓选项
|
||||
description: '权限:platform:overseas-master-data:quote:list;浏览器不直接调用国内内部接口'
|
||||
responses: { '200': { description: 业务响应 } }
|
||||
/api/platform/v1/last-leg/master-data/overseas-quotes/export:
|
||||
get:
|
||||
summary: 导出海外仓报价
|
||||
description: '权限:platform:overseas-master-data:quote:export;UTF-8 BOM CSV'
|
||||
parameters:
|
||||
- { name: keyword, in: query, schema: { type: string } }
|
||||
- { name: warehouseId, in: query, schema: { type: string } }
|
||||
- { name: providerName, in: query, schema: { type: string } }
|
||||
- { name: currency, in: query, schema: { type: string } }
|
||||
- { name: status, in: query, schema: { $ref: '#/components/schemas/ActiveStatus' } }
|
||||
responses: { '200': { description: CSV, content: { text/csv: { schema: { type: string, format: binary } } } } }
|
||||
/api/platform/v1/last-leg/master-data/overseas-quotes/{id}:
|
||||
parameters:
|
||||
- { name: id, in: path, required: true, schema: { type: integer, format: int64 } }
|
||||
get:
|
||||
summary: 查询海外仓报价详情
|
||||
description: '权限:platform:overseas-master-data:quote:list'
|
||||
responses: { '200': { description: 业务响应 } }
|
||||
put:
|
||||
summary: 编辑未生效的海外仓报价
|
||||
description: '权限:platform:overseas-master-data:quote:edit;recordVersion乐观锁'
|
||||
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/QuoteUpdate' } } } }
|
||||
responses: { '200': { description: 业务响应 } }
|
||||
/api/platform/v1/last-leg/master-data/overseas-quotes/{id}/status:
|
||||
patch:
|
||||
summary: 启停海外仓报价
|
||||
description: '权限:platform:overseas-master-data:quote:status'
|
||||
parameters:
|
||||
- { name: id, in: path, required: true, schema: { type: integer, format: int64 } }
|
||||
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/QuoteStatusChange' } } } }
|
||||
responses: { '200': { description: 业务响应 } }
|
||||
/api/platform/v1/last-leg/master-data/exchange-rates:
|
||||
get:
|
||||
summary: 分页查询月度汇率
|
||||
description: '权限:platform:overseas-master-data:exchange-rate:list'
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/Page'
|
||||
- $ref: '#/components/parameters/Size'
|
||||
- { name: monthFrom, in: query, schema: { type: string, pattern: '^\d{4}-(0[1-9]|1[0-2])$' } }
|
||||
- { name: monthTo, in: query, schema: { type: string, pattern: '^\d{4}-(0[1-9]|1[0-2])$' } }
|
||||
- { name: status, in: query, schema: { $ref: '#/components/schemas/ActiveStatus' } }
|
||||
responses: { '200': { description: 业务响应,data为PageResult<MonthlyExchangeRate> } }
|
||||
post:
|
||||
summary: 创建月度汇率
|
||||
description: '权限:platform:overseas-master-data:exchange-rate:create;月份唯一,初始状态ACTIVE'
|
||||
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/ExchangeRateCreate' } } } }
|
||||
responses: { '200': { description: 业务响应,data为MonthlyExchangeRate } }
|
||||
/api/platform/v1/last-leg/master-data/exchange-rates/summary:
|
||||
get:
|
||||
summary: 查询最新有效月度汇率摘要
|
||||
description: '权限:platform:overseas-master-data:exchange-rate:list'
|
||||
responses: { '200': { description: 业务响应,data含latestMonth/latestUsdToCnyAverage/updatedBy/updatedAt } }
|
||||
/api/platform/v1/last-leg/master-data/exchange-rates/export:
|
||||
get:
|
||||
summary: 导出筛选后的全部月度汇率
|
||||
description: '权限:platform:overseas-master-data:exchange-rate:export;UTF-8 BOM CSV'
|
||||
parameters:
|
||||
- { name: monthFrom, in: query, schema: { type: string } }
|
||||
- { name: monthTo, in: query, schema: { type: string } }
|
||||
- { name: status, in: query, schema: { $ref: '#/components/schemas/ActiveStatus' } }
|
||||
responses: { '200': { description: CSV, content: { text/csv: { schema: { type: string, format: binary } } } } }
|
||||
/api/platform/v1/last-leg/master-data/exchange-rates/{month}:
|
||||
parameters:
|
||||
- { name: month, in: path, required: true, schema: { type: string, pattern: '^\d{4}-(0[1-9]|1[0-2])$' } }
|
||||
get:
|
||||
summary: 查询月度汇率详情
|
||||
description: '权限:platform:overseas-master-data:exchange-rate:list'
|
||||
responses: { '200': { description: 业务响应,data为MonthlyExchangeRate } }
|
||||
put:
|
||||
summary: 编辑月度汇率
|
||||
description: '权限:platform:overseas-master-data:exchange-rate:edit;recordVersion冲突返回业务错误'
|
||||
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/ExchangeRateUpdate' } } } }
|
||||
responses: { '200': { description: 业务响应 } }
|
||||
/api/platform/v1/last-leg/master-data/exchange-rates/{month}/status:
|
||||
patch:
|
||||
summary: 变更月度汇率状态
|
||||
description: '权限:platform:overseas-master-data:exchange-rate:status'
|
||||
parameters:
|
||||
- { name: month, in: path, required: true, schema: { type: string } }
|
||||
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/ExchangeRateStatus' } } } }
|
||||
responses: { '200': { description: 业务响应 } }
|
||||
/api/platform/v1/last-leg/master-data/vehicles:
|
||||
get:
|
||||
summary: 分页查询车辆主数据
|
||||
description: '权限:platform:overseas-master-data:vehicle:list'
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/Page'
|
||||
- $ref: '#/components/parameters/Size'
|
||||
- { name: keyword, in: query, description: 车牌/车型/司机或外派单位, schema: { type: string } }
|
||||
- { name: ownership, in: query, schema: { $ref: '#/components/schemas/VehicleOwnership' } }
|
||||
- { name: region, in: query, schema: { $ref: '#/components/schemas/VehicleRegion' } }
|
||||
- { name: status, in: query, schema: { $ref: '#/components/schemas/VehicleStatus' } }
|
||||
responses: { '200': { description: 业务响应,data为PageResult<Vehicle> } }
|
||||
post:
|
||||
summary: 创建车辆主数据
|
||||
description: '权限:platform:overseas-master-data:vehicle:create;车牌号唯一'
|
||||
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/VehicleCreate' } } } }
|
||||
responses: { '200': { description: 业务响应,data为Vehicle } }
|
||||
/api/platform/v1/last-leg/master-data/vehicles/export:
|
||||
get:
|
||||
summary: 导出筛选后的全部车辆主数据
|
||||
description: '权限:platform:overseas-master-data:vehicle:export;UTF-8 BOM CSV'
|
||||
parameters:
|
||||
- { name: keyword, in: query, schema: { type: string } }
|
||||
- { name: ownership, in: query, schema: { $ref: '#/components/schemas/VehicleOwnership' } }
|
||||
- { name: region, in: query, schema: { $ref: '#/components/schemas/VehicleRegion' } }
|
||||
- { name: status, in: query, schema: { $ref: '#/components/schemas/VehicleStatus' } }
|
||||
responses: { '200': { description: CSV, content: { text/csv: { schema: { type: string, format: binary } } } } }
|
||||
/api/platform/v1/last-leg/master-data/vehicles/{id}:
|
||||
parameters:
|
||||
- { name: id, in: path, required: true, schema: { type: integer, format: int64 } }
|
||||
get:
|
||||
summary: 查询车辆档案详情
|
||||
description: '权限:platform:overseas-master-data:vehicle:list;不包含派送履约或车辆更换历史'
|
||||
responses: { '200': { description: 业务响应,data为Vehicle } }
|
||||
put:
|
||||
summary: 编辑车辆主数据
|
||||
description: '权限:platform:overseas-master-data:vehicle:edit;状态由独立接口变更'
|
||||
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/VehicleUpdate' } } } }
|
||||
responses: { '200': { description: 业务响应 } }
|
||||
/api/platform/v1/last-leg/master-data/vehicles/{id}/status:
|
||||
patch:
|
||||
summary: 变更车辆状态
|
||||
description: '权限:platform:overseas-master-data:vehicle:status;使用recordVersion乐观锁'
|
||||
parameters:
|
||||
- { name: id, in: path, required: true, schema: { type: integer, format: int64 } }
|
||||
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/VehicleStatusChange' } } } }
|
||||
responses: { '200': { description: 业务响应 } }
|
||||
components:
|
||||
parameters:
|
||||
Page: { name: page, in: query, schema: { type: integer, minimum: 1, default: 1 } }
|
||||
Size: { name: size, in: query, schema: { type: integer, minimum: 1, maximum: 200, default: 20 } }
|
||||
schemas:
|
||||
ActiveStatus: { type: string, enum: [ACTIVE, INACTIVE] }
|
||||
QuoteFee:
|
||||
type: object
|
||||
required: [item, billingUnit, unitPrice]
|
||||
properties:
|
||||
item: { type: string, maxLength: 128 }
|
||||
billingUnit: { type: string, maxLength: 64 }
|
||||
unitPrice: { type: number, minimum: 0 }
|
||||
minimumCharge: { type: number, minimum: 0, nullable: true }
|
||||
remark: { type: string, maxLength: 500, nullable: true }
|
||||
QuoteTransitPrice:
|
||||
type: object
|
||||
required: [fbaWarehouseCode, deliveryMethod, price]
|
||||
properties:
|
||||
fbaWarehouseCode: { type: string, maxLength: 64 }
|
||||
deliveryMethod: { type: string, maxLength: 64 }
|
||||
estimatedMiles: { type: number, minimum: 0, nullable: true }
|
||||
price: { type: number, minimum: 0 }
|
||||
minimumCharge: { type: number, minimum: 0, nullable: true }
|
||||
remark: { type: string, maxLength: 500, nullable: true }
|
||||
QuoteCreate:
|
||||
type: object
|
||||
required: [name, warehouseId, providerName, currency, effectiveStart, effectiveEnd, versionCode, warehouseFees]
|
||||
properties:
|
||||
name: { type: string, maxLength: 128 }
|
||||
warehouseId: { type: string, description: 国内平台海外合作仓ID }
|
||||
providerName: { type: string, maxLength: 128 }
|
||||
currency: { type: string, minLength: 3, maxLength: 3 }
|
||||
effectiveStart: { type: string, format: date }
|
||||
effectiveEnd: { type: string, format: date }
|
||||
versionCode: { type: string, maxLength: 64 }
|
||||
warehouseFees: { type: array, minItems: 1, items: { $ref: '#/components/schemas/QuoteFee' } }
|
||||
transitPrices: { type: array, items: { $ref: '#/components/schemas/QuoteTransitPrice' } }
|
||||
remark: { type: string, maxLength: 1000, nullable: true }
|
||||
QuoteUpdate:
|
||||
type: object
|
||||
required: [recordVersion, name, providerName, currency, effectiveStart, effectiveEnd, warehouseFees]
|
||||
properties:
|
||||
recordVersion: { type: integer, format: int64, minimum: 0 }
|
||||
name: { type: string, maxLength: 128 }
|
||||
providerName: { type: string, maxLength: 128 }
|
||||
currency: { type: string, minLength: 3, maxLength: 3 }
|
||||
effectiveStart: { type: string, format: date }
|
||||
effectiveEnd: { type: string, format: date }
|
||||
warehouseFees: { type: array, minItems: 1, items: { $ref: '#/components/schemas/QuoteFee' } }
|
||||
transitPrices: { type: array, items: { $ref: '#/components/schemas/QuoteTransitPrice' } }
|
||||
remark: { type: string, maxLength: 1000, nullable: true }
|
||||
QuoteStatusChange:
|
||||
type: object
|
||||
required: [status, recordVersion]
|
||||
properties:
|
||||
status: { $ref: '#/components/schemas/ActiveStatus' }
|
||||
recordVersion: { type: integer, format: int64, minimum: 0 }
|
||||
ExchangeRateCreate:
|
||||
type: object
|
||||
required: [month, usdToCnyAverage]
|
||||
properties:
|
||||
month: { type: string, example: '2026-08' }
|
||||
usdToCnyAverage: { type: number, exclusiveMinimum: true, minimum: 0, example: 7.18540000 }
|
||||
remark: { type: string, maxLength: 1000, nullable: true }
|
||||
ExchangeRateUpdate:
|
||||
type: object
|
||||
required: [recordVersion, usdToCnyAverage]
|
||||
properties:
|
||||
recordVersion: { type: integer, format: int64, minimum: 0 }
|
||||
usdToCnyAverage: { type: number, exclusiveMinimum: true, minimum: 0 }
|
||||
remark: { type: string, maxLength: 1000, nullable: true }
|
||||
ExchangeRateStatus:
|
||||
type: object
|
||||
required: [status, recordVersion]
|
||||
properties:
|
||||
status: { $ref: '#/components/schemas/ActiveStatus' }
|
||||
recordVersion: { type: integer, format: int64, minimum: 0 }
|
||||
remark: { type: string, maxLength: 500, nullable: true }
|
||||
VehicleOwnership: { type: string, enum: [OWNED, DISPATCHED] }
|
||||
VehicleRegion: { type: string, enum: [DOMESTIC, OVERSEAS] }
|
||||
VehicleStatus: { type: string, enum: [IN_SERVICE, DISPATCHED, MAINTENANCE, INACTIVE, RETURNED] }
|
||||
VehicleCreate:
|
||||
type: object
|
||||
required: [plateNumber, model, fuelConsumptionPer100Km, mileageKm, region, ownership, status]
|
||||
properties:
|
||||
plateNumber: { type: string, maxLength: 64 }
|
||||
model: { type: string, maxLength: 128 }
|
||||
fuelConsumptionPer100Km: { type: number, exclusiveMinimum: true, minimum: 0 }
|
||||
mileageKm: { type: integer, format: int64, minimum: 0 }
|
||||
driverOrDispatchCompany: { type: string, maxLength: 128, nullable: true }
|
||||
phone: { type: string, maxLength: 64, nullable: true }
|
||||
region: { $ref: '#/components/schemas/VehicleRegion' }
|
||||
ownership: { $ref: '#/components/schemas/VehicleOwnership' }
|
||||
status: { $ref: '#/components/schemas/VehicleStatus' }
|
||||
remark: { type: string, maxLength: 1000, nullable: true }
|
||||
VehicleUpdate:
|
||||
type: object
|
||||
required: [recordVersion, plateNumber, model, fuelConsumptionPer100Km, mileageKm, region, ownership]
|
||||
properties:
|
||||
recordVersion: { type: integer, format: int64, minimum: 0 }
|
||||
plateNumber: { type: string, maxLength: 64 }
|
||||
model: { type: string, maxLength: 128 }
|
||||
fuelConsumptionPer100Km: { type: number, exclusiveMinimum: true, minimum: 0 }
|
||||
mileageKm: { type: integer, format: int64, minimum: 0, description: 不得小于已有公里码 }
|
||||
driverOrDispatchCompany: { type: string, maxLength: 128, nullable: true }
|
||||
phone: { type: string, maxLength: 64, nullable: true }
|
||||
region: { $ref: '#/components/schemas/VehicleRegion' }
|
||||
ownership: { $ref: '#/components/schemas/VehicleOwnership' }
|
||||
remark: { type: string, maxLength: 1000, nullable: true }
|
||||
VehicleStatusChange:
|
||||
type: object
|
||||
required: [status, recordVersion]
|
||||
properties:
|
||||
status: { $ref: '#/components/schemas/VehicleStatus' }
|
||||
recordVersion: { type: integer, format: int64, minimum: 0 }
|
||||
Reference in New Issue
Block a user