This commit is contained in:
2026-11-03 11:41:58 +08:00
parent 21a9ce7d27
commit 7b5ef9ba64
56 changed files with 679 additions and 173 deletions
@@ -15,14 +15,16 @@ info:
Cancellation must use the discard application workflow. PDA resolve optionally accepts
discardNo together with palletNo; ambiguous scans require selection of a discard application.
Candidates include INVENTORY positions from every document type with available warehouse stock,
plus DROPSHIP and RETURN_CARTON sources. Create items identify exactly one of orderId,
returnCartonId or inventoryPositionId and carry selected cartonIds for partial whole-carton disposal; quantities must match those IDs.
plus RETURN_CARTON sources; one-click dropship orders and positions are excluded.
Create items identify exactly one of returnCartonId or inventoryPositionId and carry selected cartonIds for partial whole-carton disposal; quantities must match those IDs.
RETURN_CARTON selections consume every SKU in the selected physical carton.
Candidates return cartons, cartonSelectionSupported and cartonSelectionBlockReason.
Stock without complete carton/pallet ownership remains available for full disposal only.
PDA tasks with real cartonMarks use CARTON scanMode, including full bound-pallet tasks.
Every distinct selected carton mark must be scanned; confirmAllCartons cannot bypass this check.
Ordinary stock without carton marks uses PALLET mode and actual carton quantities.
Ordinary stock without selected carton marks uses PALLET mode and actual carton quantities.
Each SKU returns allowedCartonMarks from the source inbound cartons or net stock-in ledger;
PDA scans must match this allowlist immediately and confirmation revalidates ownership.
The loose group uses 散箱 as its API path key, never as a scan code.
The application may select a subset of available cartons. PDA must finish every selected carton;
short actual quantities are rejected. At least one photo remains required.
@@ -35,6 +37,18 @@ info:
security:
- bearerAuth: []
paths:
/api/pda/v1/last-leg/cargo-discards:
get:
summary: 查询当前绑定仓已审核废弃任务
description: 返回 PalletTask 数组;skus.allowedCartonMarks 为当前申请明细原入仓库存允许扫描的箱唛,无归属的箱唛不得计数或确认;未知箱唛不降级为自由扫码。
responses:
'200': { description: 当前绑定仓废弃任务及明细箱唛白名单 }
/api/pda/v1/last-leg/cargo-discards/resolve:
post:
summary: 按废弃单及托盘定位任务
description: 返回 PalletTask,包括各明细的 allowedCartonMarks 供即时扫码归属校验;提交确认时服务端再次核验。
responses:
'200': { description: 当前废弃单托盘任务及明细箱唛白名单 }
/api/merchant/v1/last-leg/cargo-discards/{discardNo}/confirm-completion:
parameters:
- $ref: '#/components/parameters/DiscardNo'
@@ -105,7 +119,7 @@ paths:
required: [itemId, actualPackages]
properties:
itemId: { type: string, pattern: '^[1-9][0-9]*$' }
scannedCartonMarks: { type: array, uniqueItems: true, items: { type: string, minLength: 1, maxLength: 128 }, description: 无关联库存现场箱唛清单,数量须与actualPackages一致,整单跨托盘不重复,详情以actualCartonMarks回显 }
scannedCartonMarks: { type: array, uniqueItems: true, items: { type: string, minLength: 1, maxLength: 128 }, description: 无关联库存现场箱唛清单,数量须与actualPackages一致,整单跨托盘不重复;每个箱唛必须能溯源到本单明细原入仓库存,未知或外单箱唛拒绝;详情以actualCartonMarks回显 }
actualPackages: { type: integer, minimum: 0, description: 无精确箱唛对应关系的普通库存允许0至plannedPackages的实际箱数,剩余预留释放;有具体选箱的明细必须等于plannedPackages }
scannedCartonMarks:
type: array
@@ -124,7 +138,7 @@ paths:
uniqueItems: true
items: { type: string, pattern: '^[1-9][0-9]*$' }
responses:
'200': { description: ApiResponse containing the completed PalletTask; conflicts use business body code }
'200': { description: ApiResponse containing the completed PalletTask; skus.allowedCartonMarks provides the source-scoped scan allowlist for immediate PDA validation; conflicts use business body code }
/api/platform/v1/last-leg/cargo-discards/{discardNo}/photos/files/{fileId}/download:
parameters:
- $ref: '#/components/parameters/DiscardNo'
@@ -2665,13 +2665,13 @@ paths:
responses: { '200': { description: 当前客户货物废弃申请分页 }, '403': { description: 缺少货物废弃查看权限 } }
post:
summary: 客户创建货物废弃申请
description: 权限 merchant:overseas-warehouse:discard:create;客户范围只取认证 Token。
description: 权限 merchant:overseas-warehouse:discard:create;客户范围只取认证 Token;仅支持普通库存与退货库存,拒绝一件代发订单,申请人 createdByName 从认证账号姓名保存快照。
security: [{ bearerAuth: [] }]
responses: { '200': { description: 创建后的货物废弃申请 }, '403': { description: 缺少货物废弃创建权限 }, '409': { description: 库存或状态冲突 } }
/api/merchant/v1/last-leg/cargo-discards/inventory-candidates:
get:
summary: 查询当前客户可废弃库存候选
description: 权限 merchant:overseas-warehouse:discard:list;候选按认证客户隔离。
description: 权限 merchant:overseas-warehouse:discard:list;候选按认证客户隔离,过滤一件代发订单与库存仓位。
security: [{ bearerAuth: [] }]
responses: { '200': { description: 可废弃库存候选 }, '403': { description: 缺少货物废弃查看权限 } }
/api/merchant/v1/last-leg/cargo-discards/{discardNo}:
@@ -2837,16 +2837,25 @@ paths:
security: [{ bearerAuth: [] }]
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/TruckUpdate' } } } }
responses: { '200': { description: 统一 ApiResponse 包装的卡车订单详情 } }
/api/merchant/v1/last-leg/us-truck-orders/{orderNo}/status:
patch:
summary: 客户取消待审核本土卡车订单
description: 权限 merchant:cross-border:domestic-trucking:edit;客户范围取当前身份,仅 PENDING_REVIEW 可取消,携带版本、幂等键和取消原因,同时释放预算预占。
security: [{ bearerAuth: [] }]
parameters:
- { name: orderNo, in: path, required: true, schema: { type: string } }
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/TruckCancel' } } } }
responses: { '200': { description: 统一 ApiResponse 包装的卡车订单详情 }, '409': { description: 当前订单不可取消或版本已变化 } }
/api/platform/v1/last-leg/us-truck-orders/{orderNo}/status:
patch:
summary: 取消未发车的本土卡车订单
description: 权限 platform:overseas-business:truck:status;该通用入口只接受 CANCELLED,正向状态必须使用具名命令,不能绕过实收、超托与分配事实。
summary: 平台取消入口已禁止
description: 平台不得取消本土卡车订单,旧入口始终拒绝;由客户待审核阶段自行取消。
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/TruckCancel' } } } }
responses: { '200': { description: 统一 ApiResponse 包装的卡车订单详情 }, '409': { description: 非法状态迁移 } }
responses: { '403': { description: 平台不能取消本土卡车订单 } }
/api/platform/v1/last-leg/us-truck-orders/{orderNo}/review:
parameters: &truckOrderTarget
- { name: orderNo, in: path, required: true, schema: { type: string } }
@@ -5240,13 +5249,13 @@ components:
remark: { type: string, nullable: true, maxLength: 1000 }
TruckCreate:
type: object
required: [vehicleType, origin, destination, totalWeightKg, totalVolumeCbm, originContactName, originContactPhone, destinationContactName, destinationContactPhone, pickupAt, deliveryAt, palletCount, budgetAmount, idempotencyKey]
required: [vehicleType, origin, originAddress, destination, destinationAddress, totalWeightKg, totalVolumeCbm, originContactName, originContactPhone, destinationContactName, destinationContactPhone, pickupAt, deliveryAt, palletCount, budgetAmount, idempotencyKey]
properties:
vehicleType: { type: string, enum: [PALLET_15, PALLET_30], description: '15拖或30拖;拼车来源未知时为空' }
origin: { type: string, maxLength: 255 }
originAddress: { type: string, nullable: true, maxLength: 500 }
originAddress: { type: string, minLength: 1, maxLength: 500 }
destination: { type: string, maxLength: 255 }
destinationAddress: { type: string, nullable: true, maxLength: 500 }
destinationAddress: { type: string, minLength: 1, maxLength: 500 }
palletCount: { type: integer, minimum: 1, description: '下单预估托数' }
totalWeightKg: { type: number, minimum: 0 }
totalVolumeCbm: { type: number, minimum: 0 }
@@ -5262,14 +5271,14 @@ components:
idempotencyKey: { type: string, maxLength: 255 }
TruckUpdate:
type: object
required: [version, vehicleType, originContactName, originContactPhone, destinationContactName, destinationContactPhone, pickupAt, deliveryAt, palletCount, budgetAmount]
required: [version, vehicleType, originAddress, destinationAddress, originContactName, originContactPhone, destinationContactName, destinationContactPhone, pickupAt, deliveryAt, palletCount, budgetAmount]
properties:
version: { type: integer, format: int64, minimum: 0 }
vehicleType: { type: string, enum: [PALLET_15, PALLET_30], description: '15拖或30拖;拼车来源未知时为空' }
origin: { type: string, maxLength: 255 }
originAddress: { type: string, nullable: true, maxLength: 500 }
originAddress: { type: string, minLength: 1, maxLength: 500 }
destination: { type: string, maxLength: 255 }
destinationAddress: { type: string, nullable: true, maxLength: 500 }
destinationAddress: { type: string, minLength: 1, maxLength: 500 }
palletCount: { type: integer, minimum: 1, description: '下单预估托数' }
totalWeightKg: { type: number, minimum: 0 }
totalVolumeCbm: { type: number, minimum: 0 }
@@ -1,5 +1,5 @@
openapi: 3.0.3
info: { title: Overseas Business Fee Source API, version: 1.1.0, description: '首版除仓租外均人工登记审核;换标报价、外接运费及拆柜成本不自动收费;旧资金链同项目已锁款或收取时拒绝重复登记。' }
info: { title: Overseas Business Fee Source API, version: 1.1.0, description: '支持人工登记费用(含仓租)并审核;自动仓租继续按出库计租流程生成;换标报价、外接运费及拆柜成本不自动收费;旧资金链同项目已锁款或收取时拒绝重复登记。' }
paths:
/api/platform/v1/last-leg/finance-fee-sources/{sourceFeeId}/retries:
get:
@@ -184,6 +184,30 @@ components:
outboundAt: {type: string, format: date-time}
calculatedAmount: {type: number, description: 原快照计算金额,币种为originalCurrency}
chargedAmount: {type: number, nullable: true, description: 实际扣费CNY,未成功时为null}
calculations:
type: array
description: 逐原批次的实际计算过程;新费用取冻结快照,历史费用仅在原报价和计租基数完整时解释,不使用当前报价。
items:
type: object
properties:
sourceBusinessNo: {type: string, nullable: true}
batchNo: {type: string, nullable: true}
ruleCode: {type: string, enum: [TRANSIT, RETURN_PALLET, RETURN_SHARE], description: 中转体积、新退货整托、历史退货份额计价}
billingQuantity: {type: number, description: 实际用于乘单价的CBM或托数,区别于出库商品件数}
billingUnit: {type: string, enum: [CBM, PALLET]}
storageDays: {type: integer, format: int64, description: 原入库时刻起累计库龄}
previouslyChargedDays: {type: integer, format: int64, description: 本次计算前该原托已生成费用的截止库龄日,不重复收费}
calculatedAmount: {type: number, description: 原批次未按分取整的计算金额,费用合计统一按分取整}
tiers:
type: array
items:
type: object
properties:
startDay: {type: integer, format: int64}
endDay: {type: integer, format: int64}
days: {type: integer, format: int64}
unitPrice: {type: number, description: 原报价快照中每托或每CBM每天单价}
amount: {type: number, description: days乘billingQuantity乘unitPrice,保留计算精度}
lines:
type: array
items:
@@ -248,7 +272,7 @@ components:
inboundCode: { type: string, maxLength: 64, nullable: true }
feeItemCode:
type: string
description: 必须选择共享费用目录的有效编码,人工录费禁止自动仓租项目FEE_TYPE_077。OVERSEAS_CONTAINER时同时符合OverseasContainerFeeItem枚举。
description: 必须选择共享费用目录的有效编码,支持人工录入仓租项目FEE_TYPE_077并沿普通人工费用审核及收付流程处理。OVERSEAS_CONTAINER时同时符合OverseasContainerFeeItem枚举。
feeItemName: { type: string }
feeRemark: { type: string, maxLength: 500, nullable: true, description: 费用说明;同单同方向已有相同项目时必填,允许实际作业分次收费。已驳回原费用终结,只能重新新增。 }
direction: { type: string, enum: [RECEIVABLE, PAYABLE] }
@@ -3,10 +3,12 @@ info:
title: 海外仓租与出库资金预校验
version: 1.0.0
description: |
仅仓租自动计费。中转按CBM/天、退货按原托份额/天累进,首次或重建预校验读取客户当前仓租配置。
仅仓租自动计费。中转按CBM/天、退货按原托整托/天累进;原托只要剩余一箱仍计一托,不按件数分摊仓租。
退货部分出库生成该原托截至本计租日的未计费期间仓租,同一原托同一天不重复收费,清空后停止计租。
首次或重建预校验读取客户当前仓租配置,退货默认阶梯为第1–30天1.5、第31–60天2、第61–90天3、第91天起4 USD/托/天。
未配置客户使用仓库服务明确返回的两张默认报价表;网络、无效配置或不支持币种均阻断出库,不降级免费。
PlanJson保存配置ID、版本、币种和完整阶梯。有效预占重放与consume使用原快照及冻结金额,不受期间改价影响。
后续部分出库采用客户最新配置,原入库时间与原托份额保持不变。原币支持USD/CNY,结算币为CNY。
后续部分出库采用客户最新配置,原入库时间及阶梯库龄保持不变;退货只计尚未生成仓租的新增库龄。原币支持USD/CNY,结算币为CNY。
实际PDA入库开始计租,实际出库按本次数量生成待审核费用,审核通过后按确认金额扣款;所有海外仓租从余额及有效授信扣除。
头程同单同仓多次入库合并计租,统一沿用首次实际入库时间;其他业务按各批实际入库时间分别计龄。
每满24小时一天,不足24小时向上取整。公开时间均为ISO8601 UTC时间,携带Z,客户端按本地时区显示。
@@ -183,6 +185,8 @@ components:
currency: {type: string, enum: [USD, CNY]}
settlementAmount: {type: number, description: CNY结算金额}
currencyRate: {type: number, nullable: true}
billingQuantity: {type: number, nullable: true, description: 本次真实计租基数,来自原费用快照,整托退货不再按件数摊薄;历史未记录时为空}
billingUnit: {type: string, nullable: true, enum: [CBM, PALLET]}
status: {type: string, enum: [PENDING_REVIEW, REVIEW_FREEZE_PENDING, REVIEW_FREEZE_FAILED, REJECTED, CONSUMED, SETTLE_FAILED, SETTLED]}
createdAt: {type: string, format: date-time}
outboundAt: {type: string, format: date-time}