Files
baiyue-firstleg/firstleg/src/main/resources/openapi/firstleg-v1.yaml
T

3024 lines
179 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
openapi: 3.0.3
info:
title: 柏悦头程履约 API
description: 业务成功和失败均使用 HTTP 200;仅响应体 code 为字符串 "200" 时表示成功,其他 code 表示失败。
version: 1.1.0
security:
- bearerAuth: []
paths:
/api/platform/inbounds/{inboundId}/hold:
get:
summary: 查询入库单当前扣货快照与不可变历史
description: 需要 platform:firstleg:inbound:list;canHold/canRelease 由服务端按实物作业事实计算,前端不得推导。
parameters:
- {name: inboundId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: tenantId, in: query, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
responses:
'200': {description: 成功时 data 为 InboundHoldDetail;客户归属不匹配时响应体 code=A0404}
post:
summary: 扣货入库单
description: 需要 platform:firstleg:inbound:hold;同事务写当前快照和不可变历史,不改变 Order 主状态。
parameters:
- {name: inboundId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: tenantId, in: query, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: Idempotency-Key, in: header, required: true, schema: {type: string, minLength: 1, maxLength: 128}}
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/InboundHoldCommand'}
responses:
'200': {description: 成功或完全同参幂等重放时 data 为 InboundHoldDetail;版本、状态、异参重放或实物作业冲突时响应体 code=A0409}
/api/platform/inbounds/{inboundId}/hold/release:
post:
summary: 解除入库单扣货
description: 需要 platform:firstleg:inbound:hold;解除原因进入不可变历史,当前原因快照清空,入库聚合 version 递增 1。
parameters:
- {name: inboundId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: tenantId, in: query, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: Idempotency-Key, in: header, required: true, schema: {type: string, minLength: 1, maxLength: 128}}
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/InboundHoldCommand'}
responses:
'200': {description: 成功或完全同参幂等重放时 data 为 InboundHoldDetail;版本、状态、异参重放或实物作业冲突时响应体 code=A0409}
/api/platform/inbounds/{inboundId}/hold/evidence:
post:
summary: 上传扣货或解除凭证
description: 需要 platform:firstleg:inbound:hold;文件按明确客户和入库单归属保存,单文件最大 10MiB。
parameters:
- {name: inboundId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: tenantId, 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: 成功时 data 为 InboundHoldEvidenceFile;入库单已发生实物作业时响应体 code=A0409}
/api/platform/inbounds/{inboundId}/hold/evidence/{fileId}/download:
get:
summary: 下载已关联扣货凭证
description: 需要 platform:firstleg:inbound:list;只允许下载已进入当前入库单不可变扣货历史的精确文件。
parameters:
- {name: inboundId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: fileId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: tenantId, in: query, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
responses:
'200': {description: 附件二进制;未关联当前入库单或归属不匹配时响应体 code=A0404}
/api/merchant/v1/first-leg/inbounds/{inboundId}/carton-label-pdf:
post:
summary: 客户端生成本客户入库单箱唛 PDF
parameters:
- {name: inboundId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: cartonIndex, in: query, required: false, schema: {type: array, items: {type: integer, minimum: 1}}}
responses:
'200': {description: PDF 文件}
'403': {description: 非客户端身份、无订单查看权限或入库单不属于当前客户}
/api/merchant/v1/first-leg/orders/{orderId}/carton-label-pdf:
post:
summary: 客户端按订单生成本客户草稿或正式订单箱唛 PDF
description: 后端按登录客户和 orderId 查找真实预入库单;不要求客户端先取得 inboundId。
parameters:
- {name: orderId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: cartonIndex, in: query, required: false, schema: {type: array, items: {type: integer, minimum: 1}}}
responses:
'200': {description: PDF 文件}
'403': {description: 非客户端身份、无订单查看权限或订单不属于当前客户}
'404': {description: 订单尚未生成预入库单}
/internal/firstleg/v1/customer-dimension-configs/defaults:
post:
summary: 幂等初始化客户四箱规默认配置
description: 原子创建 SMALL、MEDIUM、LARGE、EXTRA_LARGE 四行;同一客户和 initializationKey 重试稳定返回 createdByThisInitialization=true,configId 为 SMALL 行 ID。
security:
- internalServiceToken: []
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/CustomerDimensionConfigInitializeRequest'}
responses:
'200': {description: 成功或业务失败,data 返回 configId 和 createdByThisInitialization}
delete:
summary: 补偿删除本次新建且尚未修改的四箱规默认配置
description: 仅当四行均匹配 initializationKey、默认尺寸、默认2cm和version=0时整组物理删除,不会部分删除。
security:
- internalServiceToken: []
parameters:
- {name: tenantId, in: query, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: initializationKey, in: query, required: true, schema: {type: string, minLength: 1, maxLength: 128}}
responses:
'200': {description: 幂等补偿完成}
/internal/firstleg/v1/pricing/channels/validate:
post:
summary: 校验订单渠道并按需返回进仓编码前缀
description: 仅供订单服务调用;AUTO 模式要求并返回编码前缀,LEGACY_MANUAL 模式仅校验渠道可用性。
security:
- internalServiceToken: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [tenantId, originWarehouseId, channelCode, destinationType, requireInboundCodePrefix]
properties:
tenantId: {type: string, pattern: '^[1-9][0-9]*$'}
originWarehouseId: {type: string, pattern: '^[1-9][0-9]*$'}
channelCode: {type: string, minLength: 1, maxLength: 64}
destinationType: {type: string, enum: [FBA, OVERSEAS, PRIVATE]}
requireInboundCodePrefix: {type: boolean}
responses:
'200': {description: 成功时 data 返回 channelCode;requireInboundCodePrefix=true 时同时返回 inboundCodePrefix}
/internal/firstleg/v1/pricing/channels:
get:
summary: 查询指定客户和起运仓当前可用渠道
description: 仅供订单服务的旧系统导入解析使用,不经公网网关暴露。
security:
- internalServiceToken: []
parameters:
- {name: tenantId, in: query, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: originWarehouseId, in: query, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
responses:
'200': {description: 返回当前有效价格簿中的渠道编码和名称}
/internal/firstleg/v1/pricing/order-channel-changes/validate:
post:
summary: Order 提交渠道变更前校验 Firstleg 计价资格与费用可逆性
description: >-
按客户、订单、国内收货仓、目的仓类型/标识、报价包税方式和新渠道校验当前生效价格。
若已有 CONFIRMED/SENT 费用或 PUBLISHED 运费明细,返回冲突并明确要求先走费用作废流程;
CALCULATED 仅在响应中标记将失效,本接口不写数据。
security:
- internalServiceToken: []
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/OrderChannelChangePricingRequest'}
responses:
'200': {description: 成功时 data 返回价格版本、费用状态及是否需失效未确认预估}
/internal/firstleg/v1/pricing/order-channel-changes/apply:
post:
summary: 按订单版本幂等应用渠道变更并失效未确认价格预估
description: >-
仅供 Order 在渠道变更成功后调用。tenantId + orderId + orderVersion 构成幂等边界;
旧版本重放不会覆盖新版本。只将 CALCULATED 费用及草稿运费标记为 SUPERSEDED,
入库单恢复 UNPRICED 并可重新计价;实际净重、实际体积和测量审核事实保持不变。
已确认、已发送或已发布费用一律拒绝,不能由本命令覆盖;费用正式作废为 VOIDED 后可重新计价。
security:
- internalServiceToken: []
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/OrderChannelChangePricingRequest'}
responses:
'200': {description: 成功或同版本同请求幂等重放,data 返回应用版本和失效费用 ID}
/internal/firstleg/v1/inbounds/{inboundId}/fees/{feeId}/source-snapshot:
get:
summary: Finance 按入库费用来源版本精确回查不可变快照
description: sourceVersion 必填;只返回 sourceFeeId 与该版本精确匹配的已发布费用,不回退到其他版本。
security:
- internalServiceToken: []
parameters:
- {name: inboundId, in: path, required: true, schema: {type: integer, format: int64, minimum: 1}}
- {name: feeId, in: path, required: true, schema: {type: integer, format: int64, minimum: 1}}
- {name: sourceVersion, in: query, required: true, schema: {type: integer, minimum: 1}}
responses:
'200': {description: 成功时 data 为 FinanceFeeSourceSnapshot;不存在精确版本时返回业务错误}
/internal/firstleg/v1/containers/{containerId}/fees/{feeId}/source-snapshot:
get:
summary: Finance 按柜次费用来源版本精确回查不可变快照
description: sourceVersion 必填;containerId 固定为真实 containerBookingId,只返回 sourceFeeId 与该版本精确匹配的已发布费用,不接受 loadingPlanId 回退。
security:
- internalServiceToken: []
parameters:
- {name: containerId, in: path, required: true, schema: {type: integer, format: int64, minimum: 1}}
- {name: feeId, in: path, required: true, schema: {type: integer, format: int64, minimum: 1}}
- {name: sourceVersion, in: query, required: true, schema: {type: integer, minimum: 1}}
responses:
'200': {description: 成功时 data 为 FinanceFeeSourceSnapshot;不存在精确版本时返回业务错误}
/internal/firstleg/v1/fee-sources/commands/void:
post:
summary: Finance 发起 Firstleg 业务费用作废
description: >-
Finance 只发起命令,不修改或伪造业务费用状态。Firstleg 按 sourceType、sourceFeeId、sourceVersion、
customerId 和所属入库单/柜次精确校验,原子作废业务费用并写入 FIRSTLEG_FEE_VOIDED Outbox;
Finance 后续仅消费该事件同步本地费用池。相同幂等键与请求哈希安全重放,异参重放返回冲突。
security:
- internalServiceToken: []
parameters:
- {name: Idempotency-Key, in: header, required: true, schema: {type: string, minLength: 1, maxLength: 128}}
- {name: X-Request-Hash, in: header, required: true, schema: {type: string, pattern: '^[0-9a-f]{64}$'}}
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/FinanceFeeSourceVoidCommand'}
responses:
'200': {description: 成功时 data 为 FinanceFeeSourceCommandResult;业务失败仍按统一响应 code 返回}
/api/platform/v1/first-leg/customer-dimension-config:
get:
summary: 查询客户固定四箱规尺寸配置
description: 需要 firstleg:dimension-config:view 权限;按 SMALL、MEDIUM、LARGE、EXTRA_LARGE 固定顺序返回;规则用于实测尺寸归档和计费体积加权,不包含价格。
parameters:
- {name: tenantId, in: query, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
responses:
'200': {description: 成功时 data 为 CustomerDimensionConfigGroupResponse}
'403': {description: 无查询权限}
put:
summary: 整组编辑客户固定四箱规尺寸配置
description: 需要 firstleg:dimension-config:edit 权限;请求必须恰好包含四种固定 boxType,四行逐行乐观锁并在同一事务原子保存。
parameters:
- {name: tenantId, in: query, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/CustomerDimensionConfigUpdateRequest'}
responses:
'200': {description: 成功时 data 为更新后的 CustomerDimensionConfigGroupResponse}
'403': {description: 无编辑权限}
/api/platform/v1/first-leg/customer-dimension-config/default-calculation-mode:
put:
summary: 设置客户订单外箱规默认计算方式
description: 需要 firstleg:dimension-config:edit 权限;ADD 表示按箱规尺寸加宽,MULTIPLY 表示按默认权重系数计算。
parameters:
- {name: tenantId, in: query, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/CustomerDimensionDefaultCalculationModeUpdateRequest'}
responses:
'200': {description: 成功时 data 为更新后的 CustomerDimensionConfigGroupResponse}
'403': {description: 无编辑权限}
/internal/firstleg/v1/inbounds/order-approved:
post:
summary: 订单审核通过后幂等创建入库单
description: 仅供订单服务调用;入仓码由订单提交时生成,Firstleg 必须原样沿用。
security:
- internalServiceToken: []
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/OrderApprovedInboundCommand'}
responses:
'200': {description: 成功或业务失败;相同客户和订单重放返回已有入库单 ID}
/internal/firstleg/v1/inbounds/order-channel-changes/validate:
post:
summary: Order 审核后变更渠道的 Firstleg 履约只读门禁
description: >-
严格按客户和订单校验同柜组渠道兼容性、分柜、预装、PDA及装柜事实。
已存在不可逆履约事实时返回 A0409;不会拆组、删除计划或修改任何作业事实。
security:
- internalServiceToken: []
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/OrderChannelChangeValidationRequest'}
responses:
'200': {description: 成功时 data 返回订单版本、新渠道和当前统一履约状态;冲突时响应体 code=A0409}
/internal/firstleg/v1/inbounds/order-declaration-updated:
post:
summary: 按 eventId 幂等、按订单 version 单调消费客户申报快照
description: >-
只更新客户备注、预计到仓时间、渠道镜像和独立货物申报 JSON 快照;入仓码和唛头保持不变,
不覆盖箱码、实测重量体积、托盘、库位、PDA、装柜或已确认计费事实。
相同 eventId 同负载安全重放,旧版本不覆盖新版本,同版本异事件返回 A0409。
security:
- internalServiceToken: []
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/OrderDeclarationUpdatedEvent'}
responses:
'200': {description: 成功、幂等重放或旧版本已忽略;冲突时响应体 code=A0409}
/internal/firstleg/v1/inbounds/order-fulfillment-completed:
post:
summary: 接收 Order 履约最终完成并幂等同步入仓订单状态摘要
description: >-
由 Order 事务 Outbox 可靠投递,签收聚合和最后有效余量取消都使用同一正式完成事实。
按客户、来源订单号及入仓码核验全部有效入仓已为 DELIVERED 后更新摘要;重复调用不重复递增版本。
security:
- internalServiceToken: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [tenantId, orderId, orderNo, inboundCode, completedAt]
properties:
tenantId: {type: integer, format: int64, minimum: 1}
orderId: {type: integer, format: int64, minimum: 1}
orderNo: {type: string, minLength: 1}
inboundCode: {type: string, minLength: 1}
completedAt: {type: string, format: date-time}
responses:
'200': {description: data 返回实际更新入仓摘要数量,幂等重放为 0;未签收或来源不符时拒绝写入}
/internal/firstleg/v1/inbounds/order-remarks-updated:
post:
summary: 同步 Order 权威协作备注到未冻结预装明细
description: >-
仅接受内部服务令牌。按客户与订单关联全部 EDITING/LOADING 且未冻结的预装明细,
同步内部、仓库和客服备注并递增受影响计划与明细版本;已完成装柜的冻结快照不修改。
security:
- internalServiceToken: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [tenantId, orderId, operatorId]
properties:
tenantId: {type: integer, format: int64, minimum: 1}
orderId: {type: integer, format: int64, minimum: 1}
customerRemark: {type: string, nullable: true, maxLength: 1000}
internalRemark: {type: string, nullable: true, maxLength: 1000}
warehouseRemark: {type: string, nullable: true, maxLength: 1000}
customerServiceRemark: {type: string, nullable: true, maxLength: 1000}
operatorId: {type: integer, format: int64, minimum: 1}
operatorName: {type: string, nullable: true, maxLength: 128}
responses:
'200': {description: data 返回已同步的预装明细数量}
/internal/firstleg/v1/inbounds/unified-orders/workbench-filters:
post:
summary: 查询单一客户工作台履约筛选标识(Order内部)
description: 只读返回命中状态、待确认已推送费用及待上传报关资料的订单标识。feeOrderIds为最新已推送费用版本尚未由客户确认的订单,对应客户端“确认计费重”入口及费用明细弹窗。客户必须明确且为正数;不创建报关聚合,不跨Schema读取。传入orderIds为精确进度模式,仅计算progress,matchingStatusOrderIds为null,feeOrderIds和customsOrderIds为空;mainStatus在该模式不参与查询。
security: [{internalServiceToken: []}]
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [tenantId]
properties:
tenantId: {type: integer, format: int64, minimum: 1}
mainStatus: {type: string, nullable: true, enum: [WAIT_MEASURE, WAIT_PALLETIZE, WAIT_SPLIT, LOADING, LOADED, DELIVERED, WAIT_WEIGHT_CONFIRM, WEIGHT_CONFIRMED, WAIT_CUSTOMS_DOCS, EXPORT_CUSTOMS, SAILING_CLEARANCE, WAIT_UNLOAD, WAIT_DISPATCH, OUTBOUND_DOCUMENT, DELIVERING, SIGNED, MEASUREMENT_REVIEW]}
orderIds:
type: array
nullable: true
minItems: 1
maxItems: 200
items: {type: integer, format: int64, minimum: 1}
description: 省略或null查询当前客户全部进度;传入时仅在SQL内查询这些来源Order订单,空数组拒绝,不允许扩大到全客户。
responses:
'200':
description: 按响应code判断,标识只供Order在自身客户范围内过滤、计数和分页
content:
application/json:
schema:
type: object
properties:
code: {type: string}
data:
type: object
required: [feeOrderIds, customsOrderIds, progress]
properties:
matchingStatusOrderIds: {type: array, nullable: true, items: {type: integer, format: int64}}
feeOrderIds: {type: array, description: 待客户确认最新已推送费用版本的订单ID, items: {type: integer, format: int64}}
customsOrderIds: {type: array, items: {type: integer, format: int64}}
progress:
type: array
description: 实际装载片段投影;报关要求COMPLETED,目的港清关要求PICKUP_READY实际时间,缺失节点不推测。
items:
type: object
required: [orderId, stage, partial]
properties:
orderId: {type: integer, format: int64}
stage: {type: string, enum: [loaded, declared, cleared]}
partial: {type: boolean}
/internal/firstleg/v1/inbounds/unified-orders/status-summaries:
post:
summary: 当前页订单按原筛选读取履约摘要(Order 内部)
description: candidateOrderIds 必须提供且最多200项;保留统一筛选,避免读到不匹配的其他入库分片。
security: [{internalServiceToken: []}]
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/UnifiedInboundQuery'}
responses:
'200':
description: 标准 ApiResponse,data 为 UnifiedInboundSummary 数组
/internal/firstleg/v1/inbounds/unified-orders/status-rows:
post:
summary: 统一订单筛选后的轻量状态投影(Order 内部)
description: 非分页查询,共享统一履约筛选;按创建时间和ID降序排列,同一订单同一主状态去重,保留不同分片主状态,不查询逐票详情。调用方不传mainStatus。
security: [{internalServiceToken: []}]
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/UnifiedInboundQuery'}
responses:
'200':
description: 标准 ApiResponse;依赖失败不能返回空成功
content:
application/json:
schema:
type: object
properties:
code: {type: string}
data:
type: array
items:
type: object
required: [tenantId, orderId]
properties:
tenantId: {type: string}
orderId: {type: string}
mainStatus: {type: string, nullable: true}
/internal/firstleg/v1/inbounds/unified-orders/query:
post:
summary: 按统一订单条件分页查询履约摘要(Order 内部)
description: >-
mainStatus 接受七态产品状态;WAIT_PALLETIZE 为一件代发测量计费后的待清点组托状态,WAIT_SPLIT 为待分柜状态。
计费与入库处理中状态在完成前仍归并为 WAIT_MEASURE,不提前开放分柜。
security:
- internalServiceToken: []
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/UnifiedInboundQuery'}
responses:
'200':
description: 成功或业务失败,按响应体 code 判断
content:
application/json:
schema: {$ref: '#/components/schemas/UnifiedInboundPageEnvelope'}
/internal/firstleg/v1/inbounds/unified-orders/summaries:
post:
summary: 按订单 ID 批量查询统一履约摘要(Order 内部)
security:
- internalServiceToken: []
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/UnifiedInboundBatchRequest'}
responses:
'200':
description: 成功或业务失败,按响应体 code 判断
content:
application/json:
schema: {$ref: '#/components/schemas/UnifiedInboundListEnvelope'}
/internal/firstleg/v1/inbounds/unified-orders/detail:
post:
summary: 按订单 ID 查询统一履约详情(Order 内部)
description: 时间线保留 Firstleg 内部 fromStatus/toStatus;summary.mainStatus 使用六态产品状态。
security:
- internalServiceToken: []
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/UnifiedInboundDetailRequest'}
responses:
'200':
description: 成功或业务失败;找不到对应入库单时 data 为 null
content:
application/json:
schema: {$ref: '#/components/schemas/UnifiedInboundDetailEnvelope'}
/api/platform/v1/first-leg/tasks:
get:
summary: 分页查询履约任务
description: 需要 platform:firstleg:task:list 权限
parameters:
- $ref: '#/components/parameters/TenantId'
- $ref: '#/components/parameters/Page'
- $ref: '#/components/parameters/Size'
- {name: keyword, in: query, schema: {type: string, maxLength: 64}}
- {name: status, in: query, schema: {type: string, enum: [PENDING_ASSIGNMENT, ASSIGNED, PROCESSING, COMPLETED, CANCELLED]}}
- {name: assigneeId, in: query, schema: {type: integer, format: int64}}
responses:
'200': {description: 成功或业务失败,按响应体 code 判断}
'403': {description: 无查询权限}
/api/platform/v1/first-leg/tasks/{taskId}:
get:
summary: 查询履约任务详情
description: 需要 platform:firstleg:task:view 权限
parameters:
- $ref: '#/components/parameters/TenantId'
- $ref: '#/components/parameters/TaskId'
responses:
'200': {description: 成功或业务失败,按响应体 code 判断}
'403': {description: 无查看权限}
/api/platform/v1/first-leg/tasks/by-order/{orderId}:
get:
summary: 按订单查询履约任务
description: 需要 platform:firstleg:task:view 权限
parameters:
- $ref: '#/components/parameters/TenantId'
- {name: orderId, in: path, required: true, schema: {type: integer, format: int64}}
responses:
'200': {description: 成功或业务失败,按响应体 code 判断}
'403': {description: 无查看权限}
/api/platform/v1/first-leg/tasks/{taskId}/assignment-history:
get:
summary: 分页查询任务分配历史
description: 需要 platform:firstleg:assignment:history 权限
parameters:
- $ref: '#/components/parameters/TenantId'
- $ref: '#/components/parameters/TaskId'
- $ref: '#/components/parameters/Page'
- $ref: '#/components/parameters/Size'
responses:
'200': {description: 成功或业务失败,按响应体 code 判断}
'403': {description: 无历史查看权限}
/api/platform/v1/first-leg/tasks/{taskId}/assignment:
post:
summary: 分配或改派履约任务
description: 需要 platform:firstleg:assignment:assign 权限
parameters:
- $ref: '#/components/parameters/TenantId'
- $ref: '#/components/parameters/TaskId'
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/AssignRequest'}
responses:
'200': {description: 成功或业务失败,按响应体 code 判断}
'403': {description: 无分配权限}
/api/platform/v1/containers:
post:
summary: 新增内部模拟柜
description: 需要 platform:firstleg:container:create 权限;服务端生成稳定 containerBookingId/cabinetNo,不要求真实柜号或订舱
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/ContainerSimulationCreateRequest'}
responses:
'200': {description: 成功或重复号、参数校验等业务失败}
'403': {description: 无新增按钮权限}
/api/platform/v1/containers/domestic:
get:
summary: 分页查询国内货柜工作台
description: 需要 platform:firstleg:container:list;ACTIVE仅真实国内离仓前,HISTORY仅已真实离仓
parameters: &ContainerWorkbenchQueryParameters
- {$ref: '#/components/parameters/Page'}
- {$ref: '#/components/parameters/Size'}
- {name: scope, in: query, required: true, schema: {type: string, enum: [ACTIVE, HISTORY]}}
- {name: keyword, in: query, schema: {type: string, maxLength: 128}}
- {name: customerId, in: query, description: 仅返回包含该客户货物的柜次, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: containerNo, in: query, schema: {type: string, maxLength: 64}}
- {name: cabinetNo, in: query, schema: {type: string, maxLength: 64}}
- {name: warehouseId, in: query, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: status, in: query, description: 仅筛选装柜子状态,不作为出仓或船节点状态, schema: {type: string, enum: [WAIT_LOADING, EDITING, LOADING, COMPLETED]}}
responses:
'200': {description: 成功, content: {application/json: {schema: {$ref: '#/components/schemas/ContainerWorkbenchPageEnvelope'}}}}
'403': {description: 无国内货柜查询权限}
/api/platform/v1/containers/overseas:
get:
summary: 分页查询国外货柜工作台
description: 需要 platform:firstleg:terminal-drayage:list;ACTIVE从真实DEPARTED_WAREHOUSE至EMPTY_RETURNED前,HISTORY仅已还空柜
parameters: *ContainerWorkbenchQueryParameters
responses:
'200': {description: 成功, content: {application/json: {schema: {$ref: '#/components/schemas/ContainerWorkbenchPageEnvelope'}}}}
'403': {description: 无国外货柜查询权限}
/api/platform/v1/containers/domestic/{id}:
get:
summary: 查询国内货柜工作台详情
description: 需要 platform:firstleg:container:list;国内ACTIVE与HISTORY共用该只读详情,已真实离仓柜仍可打开;装柜清单只返回唯一loadingPlanId/planNo/planStatus关联
parameters: [{$ref: '#/components/parameters/ContainerBookingId'}]
responses: {'200': {description: 成功, content: {application/json: {schema: {$ref: '#/components/schemas/ContainerWorkbenchEnvelope'}}}}}
/api/platform/v1/containers/overseas/{id}:
get:
summary: 查询国外货柜工作台详情
description: 需要 platform:firstleg:terminal-drayage:list;同一containerBookingId只读聚合柜内组成和海外履约
parameters: [{$ref: '#/components/parameters/ContainerBookingId'}]
responses: {'200': {description: 成功, content: {application/json: {schema: {$ref: '#/components/schemas/ContainerWorkbenchEnvelope'}}}}}
/api/platform/v1/containers/{id}/ocean-booking-link:
post:
summary: 将内部模拟柜关联到已发布订舱需求
description: 需要 platform:firstleg:container:edit;请求指定 RELEASED oceanBookingId 和未满配 requirementId,containerNo 可空。首次关联允许 WAIT_LOADING 或已有预排货的 EDITING 模拟柜,保留原 containerBookingId/cabinetNo/loadingPlanId/items,原子写入订舱、运输和范围快照并创建 allocation;提柜后由拖车链调用柜次服务原子补录真实柜号。若关联请求已提供 containerNo,服务端仍规范化并校验 ISO 6346 结构、设备类别和校验位,并保证同一订舱内唯一;不同提单允许复用同一集装箱号。存在跨仓、跨渠道、柜型规格不一致、超量、同提单重复柜号、PDA、有效装柜证据、业务单证或 LOADING/COMPLETED 等事实时拒绝。
parameters: [{$ref: '#/components/parameters/ContainerBookingId'}]
requestBody: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/ContainerOceanBookingLinkRequest'}}}}
responses: {'200': {description: 关联后的同一模拟柜 containerBookingId/cabinetNo;列表仍只有这一条 ACTIVE 操作身份}}
/api/platform/v1/containers/{id}:
put:
summary: 草稿阶段编辑货柜基础资料
description: 需要 platform:firstleg:container:edit 权限;仅待装柜或计划为 EDITING 时允许;请求不包含 containerNo/cabinetNo,不形成真实柜号或内部柜次号写入口
parameters:
- {$ref: '#/components/parameters/ContainerBookingId'}
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/ContainerFullUpdateRequest'}
responses:
'200': {description: 成功或状态、版本、重复号冲突}
'403': {description: 无货柜编辑权限}
/api/platform/v1/containers/{id}/pickup-code:
put:
summary: 填写或更新PU码
description: 需要 platform:firstleg:terminal-drayage:document:edit 权限;仅国外工作台货柜;PU资料为1至64位数字码,按字符串保存以保留前导零
parameters: [{$ref: '#/components/parameters/ContainerBookingId'}]
requestBody: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/ContainerPickupCodeRequest'}}}}
responses: {'200': {description: 返回最新货柜履约概览}, '403': {description: 无货柜编辑权限}}
/api/platform/v1/containers/{id}/clearance:
get:
summary: 查询货柜目的港清关资料
description: 需要 platform:firstleg:terminal-drayage:list 权限;有效货柜已确认国内离仓,或已记录 DEPARTED_ORIGIN_PORT 且 actual_at 非空时可读取;人工与拉取节点使用相同事实
parameters: [{$ref: '#/components/parameters/ContainerBookingId'}]
responses: {'200': {description: 成功或货柜不存在}}
/api/platform/v1/containers/{id}/clearance/document:
post:
summary: 上传或替换货柜目的港清关资料
description: 需要 platform:firstleg:terminal-drayage:document:edit 权限;有效货柜已离仓或已实际开船,fileId 必须严格绑定当前货柜
parameters: [{$ref: '#/components/parameters/ContainerBookingId'}, {$ref: '#/components/parameters/IdempotencyKey'}]
requestBody:
required: true
content: {application/json: {schema: {$ref: '#/components/schemas/ContainerDocumentAttachRequest'}}}
responses: {'200': {description: 成功、文件归属不匹配或版本冲突}}
/api/platform/v1/containers/{id}/clearance/document/{fileId}/download:
get:
summary: 下载货柜目的港清关附件
description: 需要 platform:firstleg:terminal-drayage:list 权限;有效货柜已离仓或已实际开船;服务端校验当前 DESTINATION_CLEARANCE fileId 及 File 业务归属,完成态仍可下载,响应禁止缓存
parameters:
- {$ref: '#/components/parameters/ContainerBookingId'}
- {name: fileId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
responses:
'200': {description: 附件二进制内容,包含 Content-Disposition 与 Cache-Control no-store}
'404': {description: 当前附件不存在或归属不匹配}
/api/platform/v1/containers/{id}/clearance/document/upload:
post:
summary: 直接选择文件上传或替换货柜目的港清关资料
description: 需要 platform:firstleg:terminal-drayage:document:edit;有效货柜已离仓或已实际开船;Firstleg 使用内部服务令牌上传 File,浏览器不得传递 fileId 或内部令牌。上传成功即作为待拆柜的资料事实,不要求另行确认清关完成。
parameters: [{$ref: '#/components/parameters/ContainerBookingId'}, {$ref: '#/components/parameters/IdempotencyKey'}]
requestBody:
required: true
content:
multipart/form-data:
schema: {$ref: '#/components/schemas/ContainerDocumentUploadRequest'}
responses: {'200': {description: 成功、文件上传失败或版本冲突}}
/api/platform/v1/containers/{id}/clearance/complete:
post:
summary: 点击完成目的港清关
description: 需要 platform:firstleg:terminal-drayage:document:edit 权限;有效货柜已离仓或已实际开船;此完成动作不作为上传后进入待拆柜的附加条件
parameters: [{$ref: '#/components/parameters/ContainerBookingId'}, {$ref: '#/components/parameters/IdempotencyKey'}]
requestBody:
required: true
content: {application/json: {schema: {$ref: '#/components/schemas/ContainerDocumentCompleteRequest'}}}
responses: {'200': {description: 成功、未上传资料或版本冲突}}
/api/platform/v1/first-leg/smart-loading/plans/by-booking/{bookingId}:
get:
summary: 按货柜恢复智能装柜草稿
description: 需要 platform:firstleg:smart-loading:list 权限;仅返回 EDITING 草稿
parameters:
- {name: bookingId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
responses:
'200': {description: 成功、草稿不存在或计划已进入预装流程}
'403': {description: 无智能装柜查询权限}
/api/platform/v1/first-leg/smart-loading/candidates:
get:
summary: Query same-channel smart-loading candidates
parameters:
- {name: bookingId, in: query, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: warehouseId, in: query, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
responses: {'200': {description: Candidates filtered by the server to the booking channel}}
/api/platform/v1/first-leg/smart-loading/channels:
get:
summary: 查询当前仓库智能装柜渠道目录及统计
description: >-
需要 platform:firstleg:smart-loading:list 权限。渠道目录只来自平台当前唯一 ACTIVE 价格版本中
对该国内仓存在 ACTIVE 价格行的渠道;候选入仓码数、可用箱数及可编排柜次数由 Firstleg 当前事实聚合。
零候选或零可用柜次的有效渠道仍返回,Admin 可展示空态。渠道只约束智能推荐;人工加入允许跨渠道,
仍由服务端重新校验国内仓、货物原客户归属、占用、同柜组、箱数和容量资格。
平台柜次支持跨客户拼柜,关联订舱的客户快照不限制柜内成员客户。
parameters:
- {name: warehouseId, in: query, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
responses:
'200':
description: 成功;无 ACTIVE 价格版本时 data 为空数组
content:
application/json:
schema:
type: object
properties:
code: {type: string}
message: {type: string}
data: {type: array, items: {$ref: '#/components/schemas/SmartLoadingChannelSummary'}}
'403': {description: 无智能装柜查询权限}
/api/platform/v1/first-leg/smart-loading/inbound-candidates:
get:
summary: 全局分页查询智能装柜候选
description: >-
需要 platform:firstleg:smart-loading:list 权限。查询不绑定柜次;渠道、仓库、客户、入仓码、
订单创建日期、预计到货时间和订单状态共同作用于全局候选。每个普通入库单返回一行;同柜不可拆组作为一个
分页单元返回;一件代发每个已封托托盘仅返回一行,合托不按入仓码重复分页。
groupMembers 包含同柜组或托盘的完整成员,不会跨页或因单个成员命中搜索条件而拆散;托盘行箱数为整托箱数,成员箱数为本票在本托的实际箱数。
平均单箱毛重、净重按整票实测重量除以总箱数,平均单箱体积按剩余规格数量加权。
orderStatuses 可重复传参且最多四项;未传或空数组表示 PENDING_REVIEW、WAIT_MEASURE、WAIT_SPLIT、
LOADING 全部未完成状态,已完成装柜永不返回。状态映射为:Order SUBMITTED=PENDING_REVIEW;
Firstleg WAIT_MEASURE/MEASURING/MEASURE_PENDING/MEASURE_REJECTED/WAIT_PRICING/FEE_CONFIRMING/INBOUNDING
=WAIT_MEASURE;WAIT_SPLIT=WAIT_SPLIT;LOADING=LOADING。状态只用于搜索和展示,canAssign 由有效柜次占用、
剩余箱数、同柜组和容量等事实决定;容积和重量均允许达到柜型基准值的150%,超过即拒绝。
待审核及待测量可以先加入清单;确认预装/PDA 前
仍必须完成审核与测量并进入 WAIT_SPLIT。同柜不可拆组仅在全部成员命中当前状态集合时作为一个分页单位返回。
parameters:
- name: channelGroupCodes
in: query
required: true
description: >-
至少一项,可重复传参。分组到实际渠道:MATSON_CLX=[MATSON_CLX_TRUCK,MATSON_CLX_PARCEL];
MATSON_MAX=[MATSON_MAX_TRUCK,MATSON_MAX_PARCEL];EXX=[EXX_TRUCK,EXX_RAIL_NY];
HEDE=[HEDE_TRUCK,HEDE_PARCEL];OA_LA=[OA_LA_TRUCK,OA_LA_FULL_TRUCK,OA_PARCEL];
OA_CHICAGO=[OA_CHICAGO_RAIL];OA_HOUSTON=[OA_HOUSTON_TRUCK];
OA_SAVANNAH=[OA_SAVANNAH_TRUCK];OA_NEW_YORK_TRUCK=[OA_NEW_YORK_TRUCK]。
schema:
type: array
minItems: 1
maxItems: 9
uniqueItems: true
items: {type: string, enum: [MATSON_CLX, MATSON_MAX, EXX, HEDE, OA_LA, OA_CHICAGO, OA_HOUSTON, OA_SAVANNAH, OA_NEW_YORK_TRUCK]}
- {name: warehouseId, in: query, required: false, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: customerId, in: query, required: false, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: inboundCode, in: query, required: false, schema: {type: string, maxLength: 40}}
- {name: createdStart, in: query, required: false, schema: {type: string, format: date}}
- {name: createdEnd, in: query, required: false, schema: {type: string, format: date}}
- {name: expectedArrivalStart, in: query, required: false, schema: {type: string, format: date}}
- {name: expectedArrivalEnd, in: query, required: false, schema: {type: string, format: date}}
- name: orderStatuses
in: query
required: false
description: 可重复传参,未传或空数组表示全部四种未完成状态
schema:
type: array
maxItems: 4
uniqueItems: true
items: {type: string, enum: [PENDING_REVIEW, WAIT_MEASURE, WAIT_SPLIT, LOADING]}
- {name: page, in: query, required: false, schema: {type: integer, minimum: 1, default: 1}}
- {name: size, in: query, required: false, schema: {type: integer, minimum: 1, maximum: 200, default: 20}}
responses:
'200':
description: 成功,data 为标准分页;total/pages 按普通入库单或完整同柜组分页单元统计
content: {application/json: {schema: {$ref: '#/components/schemas/SmartLoadingInboundCandidatePageEnvelope'}}}
/api/platform/v1/first-leg/smart-loading/containers:
get:
summary: 分页查询智能装柜工作台柜次
description: >-
需要 platform:firstleg:smart-loading:list 权限。柜次查询只使用渠道、仓库、客户、入仓码及订单创建日期;
候选的 orderStatuses 不作用于柜次列表。客户及入仓事实以柜内任一有效装柜明细命中为准。
只返回 WAIT_LOADING、EDITING 或 LOADING 的 ACTIVE 柜次,COMPLETED 永不返回。
parameters:
- name: channelGroupCodes
in: query
required: true
schema:
type: array
minItems: 1
maxItems: 9
uniqueItems: true
items: {type: string, enum: [MATSON_CLX, MATSON_MAX, EXX, HEDE, OA_LA, OA_CHICAGO, OA_HOUSTON, OA_SAVANNAH, OA_NEW_YORK_TRUCK]}
- {name: warehouseId, in: query, required: false, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: customerId, in: query, required: false, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: inboundCode, in: query, required: false, schema: {type: string, maxLength: 40}}
- {name: createdStart, in: query, required: false, schema: {type: string, format: date}}
- {name: createdEnd, in: query, required: false, schema: {type: string, format: date}}
- {name: page, in: query, required: false, schema: {type: integer, minimum: 1, default: 1}}
- {name: size, in: query, required: false, schema: {type: integer, minimum: 1, maximum: 200, default: 20}}
responses:
'200':
description: 成功,柜次按更新时间、技术ID倒序稳定分页
content: {application/json: {schema: {$ref: '#/components/schemas/SmartLoadingWorkbenchContainerPageEnvelope'}}}
/api/platform/v1/first-leg/loading-associations/summary:
get:
summary: 查询入仓片段的装柜与国内PDA关联摘要
description: >-
需要 platform:firstleg:smart-loading:list 权限。inboundId 与 inboundCode 必须且只能提供一个;
inboundCode 是订单当前有效入仓片段业务号。响应优先提供 orderNo、loadingPlanNo、cabinetNo/containerNo、
loadingStatus、pdaTaskStatus 与 coLoadGroupNo 供页面展示;loadingPlanId、containerBookingId、taskId、
coLoadGroupId 和 items[].itemId 仅为技术关联,不得替代业务号作为UI主标识。
parameters:
- {name: inboundId, in: query, required: false, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: inboundCode, in: query, required: false, schema: {type: string, minLength: 1, maxLength: 40}}
responses:
'200':
description: 成功或业务失败;未进入装柜时仍返回 inboundId/inboundCode,其余关联字段为空
content:
application/json:
schema:
type: object
required: [code, message, data]
properties:
code: {type: string, example: '200'}
message: {type: string}
data: {$ref: '#/components/schemas/LoadingAssociationSummary'}
/api/platform/v1/first-leg/smart-loading/plans/{planId}:
get:
summary: 查询智能装柜草稿详情
description: 需要 platform:firstleg:smart-loading:list 权限;返回草稿及当前未删除明细
parameters:
- {name: planId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
responses:
'200': {description: 成功、计划不存在或计划已进入预装流程}
'403': {description: 无智能装柜查询权限}
/api/platform/v1/first-leg/smart-loading/plans/{planId}/recommend:
post:
summary: 按当前筛选范围执行智能装柜推荐
description: >-
需要 platform:firstleg:smart-loading:assign 权限。customerId 与 inboundCode 均为可选推荐范围;
传入时只推荐同时命中的候选,避免把同渠道历史候选批量加入当前柜。未传时按柜次渠道推荐全部可用候选。
关联订舱的客户快照不裁剪候选,未指定客户筛选时可推荐多个客户的货物。
一件代发仍按每个已封托托盘整体加入,不得按箱拆分;同一次推荐完成后按受影响客户统一重算费用。
parameters:
- {name: planId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
requestBody:
required: true
content: {application/json: {schema: {$ref: '#/components/schemas/SmartLoadingRecommendRequest'}}}
responses:
'200': {description: 成功或业务失败,data 为最新 SmartLoadingPlan}
/api/platform/v1/first-leg/smart-loading/plans/{planId}/assignments:
post:
summary: 向预装计划新增入库单明细
description: >-
EDITING 或 LOADING 且 PDA task 尚未完成时可用。服务端按 planId 锁定同一 PDA task,
校验货物原客户归属、可用箱数、容积和限重后原子新增/累加明细;平台允许跨客户拼柜,
不以关联订舱客户快照限定成员客户。人工加入允许订单国内仓及渠道与柜次不同,
智能推荐仍只选择柜次渠道。LOADING 时同步到原 taskId,
递增 planVersion、taskVersion,原 inventorySnapshotToken 随即失效。与 PDA batch/final complete 并发时,
锁顺序为 PDA task 行锁 -> plan 乐观锁;仅先取得任务锁且持有匹配版本的一方成功,另一方返回 A0409。
PDA 应重新 GET task detail 与 inventory snapshot,Admin 应重新 GET SmartLoadingPlan。新增项沿用原 taskId、
loadingPlanId、containerBookingId 和 inbound identity;已全拣任务会因新增 PENDING item 从 AWAITING_REVIEW
回到 IN_PROGRESS,已有证据不删除,但 final complete 门禁撤回。
parameters:
- {name: planId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
requestBody:
required: true
content: {application/json: {schema: {$ref: '#/components/schemas/SmartLoadingAssignRequest'}}}
responses:
'200': {description: 成功或业务失败,data 为最新 SmartLoadingPlan}
/api/platform/v1/first-leg/smart-loading/plans/{planId}/inbound-assignments:
post:
summary: 按入仓码分配计划装柜箱数
description: >-
需要 platform:firstleg:smart-loading:assign 权限。操作员只选择某个入仓码的本次计划箱数;
服务端在单一事务内按剩余规格箱数比例生成内部规格快照,用于体积估算及兼容 PDA/拆单;
人工分配不限制订单国内仓及渠道与柜次一致;智能推荐允许跨国内仓,但仍只选择柜次渠道;
占用、同柜组和容量门禁不变。
支持将不同客户的入仓码加入同一柜次,明细及费用仍保留各自原客户归属。
柜内总容积和总重量分别允许达到柜型基准值的150%,超过即拒绝。
只记录数量计划,具体实装箱号归属为 UNVERIFIED,不得将内部比例分摊宣称为现场箱号事实。
parameters:
- {name: planId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
requestBody:
required: true
content: {application/json: {schema: {$ref: '#/components/schemas/SmartLoadingInboundAssignRequest'}}}
responses:
'200': {description: 成功或业务失败,data 为最新 SmartLoadingPlan}
/api/platform/v1/first-leg/smart-loading/plans/{planId}/pending-review-assignments:
post:
summary: 将待审核订单加入装柜清单
description: >-
需要 platform:firstleg:smart-loading:assign 权限。订单审核状态不作为清单占位门禁;服务端以
customerId + orderId + inboundCode 重新核验 Order 权威待审核事实,幂等创建或复用 PREPARING
入仓投影,并按订单申报箱数、重量和体积建立柜次占位。人工分配允许订单渠道与柜次渠道不同;
不同客户可加入同一柜次,关联订舱客户快照不作为客户准入限制。
已被其他有效柜次占用、国内仓不一致、
超容量或订单事实变化返回业务冲突且事务零漂移。清单中存在 PREPARING/WAIT_MEASURE 订单时不得
确认预装或启动 PDA,审核测量完成并进入 WAIT_SPLIT 后才可继续物理装柜。
parameters:
- {name: planId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
requestBody:
required: true
content: {application/json: {schema: {$ref: '#/components/schemas/SmartLoadingPendingReviewAssignRequest'}}}
responses:
'200': {description: 成功或业务失败,data 为最新 SmartLoadingPlan}
/api/platform/v1/first-leg/smart-loading/plans/{planId}/items/{itemId}:
patch:
summary: 调整预装计划明细箱数
description: >-
EDITING/LOADING 均可;packageCount 不得小于已拣 pickedPackageCount。成功递增 plan、计划明细和现有 PDA task 版本,
原 inventorySnapshotToken 失效。PDA task 已完成或并发版本变化返回 A0409,事务零写入;调用方须刷新
SmartLoadingPlan,PDA 在下一次写入前须刷新 task detail 与 inventory snapshot。
parameters:
- {name: planId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: itemId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
requestBody:
required: true
content: {application/json: {schema: {$ref: '#/components/schemas/SmartLoadingAdjustRequest'}}}
responses:
'200': {description: 成功或业务失败,data 为最新 SmartLoadingPlan}
delete:
summary: 删除未拣预装计划明细
description: >-
仅 pickedPackageCount=0 且计划/PDA task 未最终完成时允许。成功递增 plan 和 task 版本并使原库存快照失效;
已拣、COMPLETED 或并发版本变化返回 A0409,事务零写入。PDA final complete 与本操作使用相同 task 行锁,
因而只允许一个事务成功;失败方刷新计划、task detail 与 inventory snapshot 后再决定后续操作。
parameters:
- {name: planId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: itemId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
requestBody:
required: true
content: {application/json: {schema: {$ref: '#/components/schemas/SmartLoadingDeleteRequest'}}}
responses:
'200': {description: 成功或业务失败,data 为最新 SmartLoadingPlan}
/api/platform/v1/first-leg/smart-loading/plans/{planId}/unpicked-items:
delete:
summary: 一次性移除当前计划全部未拣明细
description: >-
需要 platform:firstleg:smart-loading:delete 权限。单次请求、单事务锁定计划与 PDA task,移除全部
pickedPackageCount=0 的普通入仓码;同柜不可拆组只在组内所有明细均未拣时整组移除,任一成员已拣则整组保留。
planVersion 只递增一次;并发版本变化或任一步失败均整体回滚。同 operationId 重放返回既有结果。
parameters:
- {name: planId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
requestBody:
required: true
content: {application/json: {schema: {$ref: '#/components/schemas/SmartLoadingRemoveUnpickedRequest'}}}
responses:
'200': {description: 成功或业务失败,data 为最新 SmartLoadingPlan}
/api/platform/v1/first-leg/smart-loading/plans/{planId}/items/{itemId}/remarks:
patch:
summary: 修改装柜明细协作备注
description: >-
需要 platform:firstleg:preload:edit 权限。客户备注只读;EDITING/LOADING 可修改或清空
internalRemark、warehouseRemark 和 customerServiceRemark;
COMPLETED、计划/明细版本冲突返回 A0409 且事务零写入,写入历史且与 PDA final complete 使用同一并发门禁。
成功响应中的 version 是递增后的 planVersion,items[].version 是递增后的 itemVersion;调用方同时使用
canEdit、items[].canAdjust/canRemove 与自身权限决定操作可用性。数量调整或动态增量不会覆盖已有协作备注。
parameters:
- {name: planId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: itemId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
requestBody:
required: true
content: {application/json: {schema: {$ref: '#/components/schemas/SmartLoadingRemarksRequest'}}}
responses:
'200': {description: 成功或业务失败,data 为最新 SmartLoadingPlan}
/openapi/v1/inbound-measurements:
post:
summary: 提交一条第三方箱规测量结果和一张图片
description: >-
墨家 JSON 协议使用平台级 AppKey(tenant-id=0)和正数设备服务主体 ID;
按全平台唯一 boxCode 找到入库单真实客户,再校验 machineNo 绑定的仓库与入库单仓库一致。
匹配结果按真实客户保存,未匹配的联调收件按平台作用域保存;
每次只保存一条箱规明细和一张图片,不审核、不计费、不入库,也不改变入库单状态。
multipart 协议的 data 中则以 inboundCode 和 inboundDetailId 匹配指定客户的入库单及货物明细。
首轮联调可由服务端配置 signature-required=false:此时 JSON 协议只强制 X-App-Key,
multipart 协议还要求 Idempotency-Key;X-Timestamp、X-Nonce、X-Signature 可不传。
恢复签名后按下述规则计算。
签名串依次为 METHOD、原始 PATH、X-Timestamp、X-Nonce、Idempotency-Key、
签名body的 SHA-256 小写十六进制,六部分使用 LF(\n)连接且末尾不追加换行。
签名body = data原始UTF-8文本 + LF + image文件内容SHA-256小写十六进制。
三层语义:Nonce 防短时重放;Idempotency-Key 标识一次 HTTP 写操作;
appKey + eventNo 标识第三方业务事件。多台设备可共用同一 appKey/secret,
但 deviceCode、eventNo 和 Idempotency-Key 必须由调用方生成全局唯一值,
不得仅在单台设备内从 1 开始递增。
security:
- measurementAppKey: []
measurementTimestamp: []
measurementNonce: []
measurementSignature: []
parameters:
- {$ref: '#/components/parameters/XTimestamp'}
- {$ref: '#/components/parameters/XNonce'}
- {$ref: '#/components/parameters/IdempotencyKey'}
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [boxCode, length, width, height, machineNo, picture]
properties:
boxCode: {type: string, maxLength: 128, example: 'ZBYHK2608140001#4-1'}
shipment_id: {type: string, maxLength: 64, example: 'FBA19L5KMY2CU000002', description: '可选;设备从Amazon FBA箱标实际扫描得到,有则原样上传;系统只保存,不生成且不覆盖客户下单值'}
length: {type: number, format: decimal, minimum: 0.001}
width: {type: number, format: decimal, minimum: 0.001}
height: {type: number, format: decimal, minimum: 0.001}
machineNo: {type: string, maxLength: 64}
measuredAt: {type: string, format: date-time, nullable: true}
picture: {type: string, description: 'data:image/jpeg;base64,...'}
multipart/form-data:
schema:
type: object
required: [data, image]
properties:
data:
type: string
description: InboundMeasurementCallbackRequest 的原始UTF-8 JSON文本
image:
type: string
format: binary
description: 当前测量明细唯一对应图片,JPG/PNG/BMP且不超过5MB
responses:
'200':
description: JSON 墨家协议在正式箱码匹配或未匹配联调收件成功时均返回 code=200;data.matched 区分结果。其他业务失败按 code 判断。
content:
application/json:
schema: {$ref: '#/components/schemas/MojiaMeasurementUploadEnvelope'}
'413': {description: 请求体超过网关限制}
'415': {description: Content-Type 不支持}
/openapi/v1/inbound-measurements/events/{eventNo}:
get:
summary: 查询第三方测量事件状态
description: >-
signature-required=false 时只需固定 X-App-Key;恢复签名后,GET 签名串的
Idempotency-Key 行为空字符串,body 摘要为空字节 SHA-256。
security:
- measurementAppKey: []
measurementTimestamp: []
measurementNonce: []
measurementSignature: []
parameters:
- name: eventNo
in: path
required: true
schema: {type: string, pattern: '^[A-Za-z0-9._:-]{1,128}$'}
- {$ref: '#/components/parameters/XTimestamp'}
- {$ref: '#/components/parameters/XNonce'}
responses:
'200': {description: 成功或业务失败,按响应体字符串 code 判断}
/api/platform/inbounds:
get:
summary: 分页查询入库单
description: 需要 platform:firstleg:inbound:list 权限;默认查询全部企业,可选 tenantId 筛选;仅使用 V2 四个页签
parameters:
- {name: tenantId, in: query, required: false, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: tab, in: query, schema: {type: string, enum: [WAIT_MEASURE, WAIT_REVIEW, WAIT_FEE_SEND, WAIT_SPLIT]}}
responses:
'200':
description: 成功或业务失败,按响应体 code 判断;每条记录携带后续客户隔离操作所需的 tenantId,该字段当前表示客户 ID
content:
application/json:
schema: {$ref: '#/components/schemas/InboundOrderPageEnvelope'}
'403': {description: 无查询权限}
/api/platform/inbounds/{inboundId}:
get:
summary: 查询入库单详情
description: 需要 platform:firstleg:inbound:view 权限
parameters:
- {name: tenantId, in: query, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: inboundId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
responses:
'200': {description: 成功或业务失败,按响应体 code 判断}
'403': {description: 无查看权限}
/api/platform/inbounds/{inboundId}/carton-label-pdf:
post:
summary: 生成或补打入仓箱唛 PDF
description: 需要 platform:firstleg:inbound:view 权限;首次打印冻结整单箱号,重复打印和部分补打复用原映射。
parameters:
- {name: tenantId, in: query, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: inboundId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- name: cartonIndex
in: query
required: false
style: form
explode: true
schema: {type: array, items: {type: integer, minimum: 1}}
description: 不传时打印整单;可重复传入以部分补打指定箱下标。
responses:
'200':
description: 成功返回 PDF;业务失败返回统一 JSON 响应,调用方必须按 Content-Type 区分。
content:
application/pdf: {schema: {type: string, format: binary}}
application/json:
schema:
type: object
required: [code, message]
properties:
code: {type: string}
message: {type: string}
requestId: {type: string, nullable: true}
traceId: {type: string, nullable: true}
'403': {description: 无查看权限}
/api/platform/inbounds/carton-label-pdf:
post:
summary: 批量生成入仓箱唛 PDF
description: 需要 platform:firstleg:inbound:view 权限;可跨客户选择1至200个入库单,聚合生成一个 PDF,首次调用冻结各入库单整单箱号。
requestBody:
required: true
content:
application/json:
schema:
type: array
minItems: 1
maxItems: 200
items:
type: object
required: [tenantId, inboundId]
properties:
tenantId: {type: string, pattern: '^[1-9][0-9]*$'}
inboundId: {type: string, pattern: '^[1-9][0-9]*$'}
responses:
'200':
description: 成功返回聚合 PDF;业务失败返回统一 JSON 响应,调用方必须按 Content-Type 区分。
content:
application/pdf: {schema: {type: string, format: binary}}
application/json:
schema:
type: object
required: [code, message]
properties:
code: {type: string}
message: {type: string}
requestId: {type: string, nullable: true}
traceId: {type: string, nullable: true}
'403': {description: 无查看权限}
/api/platform/v1/first-leg/inbounds/{inboundId}/measurement:
get:
summary: 查询入库测量详情
description: >-
需要 platform:firstleg:inbound:measure:view 权限。尺寸测量图片只随 items 返回,
由稳定的 item.id(measurementItemId)与 intelligentImageFileId 关联;称重图片只随
weightResults 返回,由稳定的 weightResult.id 与 fileId 关联,并携带确认状态及服务端确认的
grossWeightKg/netWeightKg。两类证据不得合并为无明细归属的统一图片列表。
actualGrossWeightKg 是服务端确认后的实测毛重,actualNetWeightKg 是扣除托盘皮重后的货物净重;
两者语义独立,消费者不得互相回退,也不得根据图片或 OCR 值自行重算。
inboundCode 是当前入库详情唯一入仓码;每条 items 按 inboundDetailId 返回 Order 权威
fbaShipmentNo,并保留独立 scannedShipmentId,匹配失败返回空且禁止两者互相回退或覆盖。
parameters:
- {name: tenantId, in: query, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: inboundId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
responses:
'200':
description: 成功或业务失败,按响应体 code 判断
content:
application/json:
schema: {$ref: '#/components/schemas/InboundMeasurementDetailEnvelope'}
'403': {description: 无入库测量查看权限}
/api/platform/v1/first-leg/inbounds/{inboundId}/measurement/draft:
put:
summary: 保存测量草稿
description: >-
原单据号码、申报毛重和申报体积由服务端从客户订单生成快照,客户端不得提交覆盖;
actualGoodsName 默认使用客户货物品名汇总,但允许测量人员修正。仅允许 PREPARING(订单待审核但已到仓)、
WAIT_MEASURE、MEASURING 或 MEASURE_REJECTED 状态保存;进入 MEASURE_PENDING 后整批测量冻结,确认箱数修正使用
measurement/items/{itemId}/confirmed-package-count 明细专用接口。
parameters:
- {name: tenantId, in: query, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: inboundId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/InboundMeasurementSaveDraftRequest'}
responses:
'200': {description: 成功或业务失败,按响应体 code 判断}
'403': {description: 无测量编辑权限}
/api/platform/v1/first-leg/inbounds/{inboundId}/measurement/calculation-strategy:
put:
summary: 更新箱规计算规则
description: >-
独立更新当前测量批次全部明细的箱规计算规则并重算体积,不覆盖整批测量数据,
不改变测量提交或审核状态。仅当客户已确认费用且该票已装柜完成时冻结,不得再修改。
parameters:
- {name: tenantId, in: query, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: inboundId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/InboundMeasurementCalculationStrategyRequest'}
responses:
'200': {description: 成功或业务失败,按响应体 code 判断}
'403': {description: 无测量编辑权限}
/api/platform/v1/first-leg/inbounds/{inboundId}/measurement/items/{itemId}/outer-dimensions:
put:
summary: 更新仓库外箱长宽高
description: >-
独立更新当前测量批次指定明细的仓库外箱尺寸并重算体积,不覆盖整批测量数据,
不改变测量提交或审核状态。仅当客户已确认费用且该票已装柜完成时冻结,不得再修改。
parameters:
- {name: tenantId, in: query, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: inboundId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: itemId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/InboundMeasurementOuterDimensionsRequest'}
responses:
'200': {description: 成功或业务失败,按响应体 code 判断}
'403': {description: 无测量编辑权限}
/api/platform/v1/first-leg/inbounds/{inboundId}/measurement/carton-scans:
post:
summary: 平台模拟单箱设备扫描
description: >-
需要 platform:firstleg:inbound:warehouse-suggestion:edit 或兼容权限
platform:firstleg:inbound:measure:edit;仅用于平台联调和代设备录入,
复用正式单箱覆盖规则,不代表最终第三方设备协议或鉴权方式。
parameters:
- {name: tenantId, in: query, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: inboundId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
required: [data, image]
properties:
data:
type: object
required: [boxCode, length, width, height, machineNo, measuredAt]
properties:
boxCode: {type: string, maxLength: 128}
length: {type: number, format: double, minimum: 0.001}
width: {type: number, format: double, minimum: 0.001}
height: {type: number, format: double, minimum: 0.001}
machineNo: {type: string, maxLength: 64}
measuredAt: {type: string, format: date-time}
image: {type: string, format: binary}
responses:
'200': {description: 成功或业务失败,按响应体 code 判断}
'403': {description: 无测量编辑权限}
/api/platform/v1/first-leg/inbounds/{inboundId}/measurement/manual-cartons:
post:
summary: 平台人工录入单箱测量
description: >-
需要 platform:firstleg:inbound:measure:manual-entry 权限;人工录入独立记录为 MANUAL/PLATFORM,
复用正式单箱绑定、图片、计算和覆盖规则,不影响设备扫描入口。
parameters:
- {name: tenantId, in: query, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: inboundId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
required: [data, image]
properties:
data:
type: object
required: [boxCode, length, width, height, machineNo, measuredAt]
properties:
boxCode: {type: string, maxLength: 128}
length: {type: number, format: double, minimum: 0.001}
width: {type: number, format: double, minimum: 0.001}
height: {type: number, format: double, minimum: 0.001}
machineNo: {type: string, maxLength: 64}
measuredAt: {type: string, format: date-time}
image: {type: string, format: binary}
responses:
'200': {description: 成功或业务失败,按响应体 code 判断}
'403': {description: 无测量编辑权限}
/api/platform/v1/first-leg/inbounds/{inboundId}/weight-pallet-options:
get:
summary: 查询称重可选托盘快照
description: >-
需要入库测量查看或称重编辑权限。Firstleg 按入库单 warehouseId 分页查询 Warehouse 当前称重托盘候选;
Warehouse 校验平台公共作用域、启用国内仓、同仓归属和当前未删除资格。托盘可复用,不按预占或占用过滤,Admin 不需要 platform:pallet:list。
parameters:
- {name: tenantId, in: query, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: inboundId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: page, in: query, required: false, schema: {type: integer, format: int64, minimum: 1, default: 1}}
- {name: size, in: query, required: false, schema: {type: integer, format: int64, minimum: 1, maximum: 100, default: 20}}
- {name: keyword, in: query, required: false, description: 匹配托盘编码或类型, schema: {type: string, maxLength: 50}}
responses:
'200':
description: 成功或业务失败,按响应体 code 判断
content:
application/json:
schema:
type: object
properties:
code: {type: string}
message: {type: string}
data: {$ref: '#/components/schemas/WeightPalletOptionPage'}
'403': {description: 无入库测量查看或称重编辑权限}
/api/platform/v1/first-leg/inbounds/{inboundId}/weight-results:
post:
summary: 登记称重图片 OCR 毛重结果
description: >-
需要称重编辑权限。请求必须绑定 palletId;Firstleg 按入库单 warehouseId 读取 Warehouse
权威快照并固化托盘编码、类型、容量和皮重,不信任前端托盘快照。
parameters:
- {name: tenantId, in: query, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: inboundId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/CreateWeightResultRequest'}
responses:
'200':
description: 成功或业务失败,按响应体 code 判断
content:
application/json:
schema:
type: object
properties:
code: {type: string}
message: {type: string}
data: {$ref: '#/components/schemas/InboundWeightResult'}
'403': {description: 无称重编辑权限}
/api/platform/v1/first-leg/inbounds/{inboundId}/weight-results/{resultId}/confirm:
post:
summary: 确认 OCR 重量
description: >-
需要 platform:firstleg:inbound:weight:confirm 权限;携带人工修改字段时还需要
platform:firstleg:inbound:weight:edit 权限。修改与确认在同一事务内完成,保留 OCR 原值,
分别写入 CORRECT 和 CONFIRM 修订记录。输入表示含托盘毛重;服务端统一换算为 KG,
使用创建时固化的托盘皮重计算 netWeightKg,且毛重必须大于皮重。
入库单 actualGrossWeightKg 为实测毛重;actualNetWeightKg 为扣除托盘皮重后的货物净重,两者不得混用。
首张图片确认成功时优先按墨家/人工测量形成的实测体积建立并占用整票库位块;尚无实测体积时依次使用
测量批次冻结的申报体积、Order 最新客户申报体积,三者均无有效值才拒绝。后续图片绑定下一个空槽。
所需槽数增长时原子扩容原块,既有 blockId、slotNo、reservationId 和 locationId 保持不变,
普通连续位不足的新增槽使用同仓共享 A0。确认响应立即返回图片对应的权威块槽绑定。
parameters:
- {name: tenantId, in: query, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: inboundId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: resultId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/ConfirmWeightResultRequest'}
responses:
'200':
description: 成功或业务失败,按响应体 code 判断
content:
application/json:
schema:
type: object
properties:
code: {type: string}
message: {type: string}
data: {$ref: '#/components/schemas/InboundWeightResult'}
'403': {description: 无确认权限,或修改重量时无编辑权限}
/api/platform/v1/first-leg/inbounds/{inboundId}/weight-results/{resultId}:
put:
summary: 人工修正 OCR 毛重
description: >-
需要称重编辑权限。修正值仍表示含托盘毛重;保留 OCR 原值,已确认结果修正后立即移出净重汇总并回到待确认。
parameters:
- {name: tenantId, in: query, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: inboundId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: resultId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/CorrectWeightResultRequest'}
responses:
'200':
description: 成功或业务失败,按响应体 code 判断
content:
application/json:
schema:
type: object
properties:
code: {type: string}
message: {type: string}
data: {$ref: '#/components/schemas/InboundWeightResult'}
'403': {description: 无称重编辑权限}
delete:
summary: 删除称重图片及重量结果
description: >-
需要 platform:firstleg:inbound:weight:edit 权限;仅允许在可编辑的测量状态删除。
已绑定图片先将对应槽恢复为 RESERVED_EMPTY,整票块仍归当前入仓码;解绑或文件删除失败时事务失败。
删除已确认图片后由生产者分别重算剩余确认称重的毛重、净重;消费端不得用净重填充毛重。
parameters:
- {name: tenantId, in: query, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: version, in: query, required: true, schema: {type: integer, format: int32, minimum: 0}}
- {name: inboundId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: resultId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
responses:
'200': {description: 成功或业务失败,按响应体 code 判断}
'403': {description: 无重量编辑权限}
/api/platform/v1/inbounds/{inboundId}/measurements/approve:
post:
summary: 审核通过测量
description: 需要 firstleg:inbound:measurement-review 权限,且 Order 权威订单必须已审核通过。订单待审核期间可保留并提交到仓测量数据,但不能审核测量。审核通过前必须存在至少一张已确认的称重图片;历史异常数据若已提交但没有称重图片,必须先退回测量后补录。标准头程审核通过后进入 WAIT_SPLIT;一件代发进入 WAIT_PALLETIZE,完成逐箱清点和封托后再进入 WAIT_SPLIT。审核时按该次测量数据尽力生成 CALCULATED 初算费用;价格未覆盖或初算异常只返回非阻断提示,不影响审核结果和后续履约状态。
parameters:
- {name: inboundId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: tenantId, in: query, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: Idempotency-Key, in: header, required: true, schema: {type: string}}
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [measurementId, expectedVersion]
properties:
measurementId: {type: string, pattern: '^[1-9][0-9]*$'}
expectedVersion: {type: integer, minimum: 0}
reason: {type: string, maxLength: 1000}
responses:
'200': {description: 成功或业务失败,按响应体 code 判断;审核成功后标准头程 data.processStatus=WAIT_SPLIT,一件代发为 WAIT_PALLETIZE;initialPricingSucceeded 表示是否同时生成初算费用,未覆盖时 feeStatus=UNPRICED 且主流程仍成功}
/api/platform/v1/inbounds/{inboundId}/measurements/submit:
post:
summary: 提交测量完成
description: 即使只有一箱,也必须先上传并确认至少一张称重图片。提交只校验并复用称重图片确认阶段已经 OCCUPIED 且绑定完整的权威整票库位块,然后进入客服待审核;不会首次分配、重建或更换已显示槽位。Order 仍待审核时允许提交并冻结到仓测量证据,但不得继续审核测量或进入计费、分柜和装柜。
parameters:
- {name: tenantId, in: query, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: inboundId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
responses:
'200': {description: 成功时 processStatus=MEASURE_PENDING、measureReviewStatus=PENDING,且复用的整票库位块保持 OCCUPIED}
'403': {description: 无测量提交权限}
/api/merchant/v1/first-leg/orders/{orderId}/inbound-billing:
get:
summary: 客户查询已完成入库结果和最新已发布费用
description: 需要 merchant:order:view 权限;客户仅能按登录态客户范围查看。一件代发在 WAIT_PALLETIZE 清点组托阶段即可查看并确认已发布费用,之后在 WAIT_SPLIT、LOADING、LOADED、DELIVERED 持续可见;始终要求 measureReviewStatus=APPROVED、feeStatus=SENT 且存在 PUBLISHED 入库运费明细。
parameters:
- {name: orderId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
responses:
'200':
description: 成功;publishedFeeDetail 是后台和客户共同读取的同一条已发布入库运费明细,latestFee 仅为兼容保留的计费快照
content:
application/json:
schema: {$ref: '#/components/schemas/MerchantInboundBillingEnvelope'}
'403': {description: 非当前客户或无订单查看权限}
/api/merchant/v1/first-leg/orders/{orderId}/inbound-billing/confirm:
post:
summary: 客户确认已发布的入库费用
description: 需要 merchant:order:edit 权限;仅可确认当前客户 SENT 状态的最新费用版本。确认成功后记录当前成员与确认时间,并永久锁定该费用版本,平台不得再修改。
parameters:
- {name: orderId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {$ref: '#/components/parameters/IdempotencyKey'}
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [expectedFeeVersion]
properties:
expectedFeeVersion: {type: integer, minimum: 1}
responses:
'200': {description: 成功时返回 customerConfirmationStatus=CONFIRMED 的当前费用快照}
'403': {description: 非当前客户或无订单编辑权限}
'409': {description: 费用未发送、版本已变化或已经确认}
/api/platform/v1/loading-plans/{loadingPlanId}/fee-details/{feeId}/adjust:
post:
summary: 调整已审核柜次费用的日期和金额
description: >-
仅 ACTIVE、APPROVED 且 sourceVersion 匹配的费用可调整。成功后 sourceVersion 加一并重新进入
PENDING;费用方向、费用项目、供应商、结算方式、已付快照、币种和备注保持原快照。业务字段需要变化时,
必须作废原费用并新增。同一 expectedSourceVersion、businessDate、amount 的原样重试只读返回已生成的
PENDING 版本;旧版本异参、已作废或非已审核状态返回 A0409 且零写入。
parameters:
- {name: accountId, in: query, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: loadingPlanId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: feeId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/ContainerFeeAdjustRequest'}
responses:
'200': {description: 成功时 data 为调整后柜次费用;业务冲突通过响应体 A0409 返回}
'403': {description: 无 firstleg:inbound:fee-detail:edit 权限}
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
measurementAppKey:
type: apiKey
in: header
name: X-App-Key
description: 分配给测量服务商的应用标识
measurementTimestamp:
type: apiKey
in: header
name: X-Timestamp
description: Unix 毫秒时间戳
measurementNonce:
type: apiKey
in: header
name: X-Nonce
description: 每次请求唯一的随机串
measurementSignature:
type: apiKey
in: header
name: X-Signature
description: HMAC-SHA256 小写十六进制签名
internalServiceToken:
type: apiKey
in: header
name: X-Internal-Service-Token
parameters:
XTimestamp:
name: X-Timestamp
in: header
required: true
schema: {type: string, pattern: '^[0-9]{13}$', example: '1785551400000'}
XNonce:
name: X-Nonce
in: header
required: true
schema: {type: string, minLength: 1, maxLength: 128}
IdempotencyKey:
name: Idempotency-Key
in: header
required: true
schema: {type: string, minLength: 1, maxLength: 128}
TenantId:
name: tenantId
in: query
required: true
schema: {type: integer, format: int64, minimum: 1}
TaskId:
name: taskId
in: path
required: true
schema: {type: integer, format: int64}
Page:
name: page
in: query
schema: {type: integer, format: int64, minimum: 1, default: 1}
Size:
name: size
in: query
schema: {type: integer, format: int64, minimum: 1, maximum: 200, default: 20}
ContainerBookingId:
name: id
in: path
required: true
schema: {type: string, pattern: '^[1-9][0-9]*$'}
schemas:
CustomerTransportFragment:
type: object
required: [nodes]
properties:
inboundCode: {type: string, nullable: true}
cabinetNo: {type: string, nullable: true}
containerNo: {type: string, nullable: true}
nodes: {type: array, items: {$ref: '#/components/schemas/CustomerTransportNode'}}
CustomerTransportNode:
type: object
properties:
standardNode: {type: string, description: 标准船节点;进港为AT_ORIGIN_PORT,不表示开航}
nodeSequence: {type: integer}
providerCode: {type: string, nullable: true}
estimatedAt: {type: string, format: date-time, nullable: true}
actualAt: {type: string, format: date-time, nullable: true, description: 仅实际时间表示实际发生,不能用预计时间替代}
locationCode: {type: string, nullable: true}
locationName: {type: string, nullable: true}
InboundHoldCommand:
type: object
required: [expectedVersion, reason]
properties:
expectedVersion: {type: integer, minimum: 0, description: 当前入库聚合 version;成功后递增 1}
reason: {type: string, minLength: 1, maxLength: 1000}
evidenceFileId: {type: integer, format: int64, minimum: 1, nullable: true, description: 可选的 INBOUND_HOLD_EVIDENCE 文件引用,必须归属当前客户和入库单}
InboundHoldEvidenceFile:
type: object
required: [fileId, fileName, contentType, sizeBytes]
properties:
fileId: {type: integer, format: int64}
fileName: {type: string}
contentType: {type: string}
sizeBytes: {type: integer, format: int64, minimum: 0}
InboundHoldHistoryItem:
type: object
required: [id, action, reason, operatedAt]
properties:
id: {type: integer, format: int64}
action: {type: string, enum: [HOLD, RELEASE]}
reason: {type: string, maxLength: 1000}
evidenceFileId: {type: integer, format: int64, nullable: true}
operatorName: {type: string, nullable: true}
operatedAt: {type: string, format: date-time}
InboundHoldDetail:
type: object
required: [inboundId, tenantId, holdFlag, version, canHold, canRelease, history]
properties:
inboundId: {type: integer, format: int64}
tenantId: {type: integer, format: int64}
holdFlag: {type: boolean, description: 当前权威扣货状态}
currentHoldReason: {type: string, maxLength: 1000, nullable: true, description: 未扣货时固定为 null}
version: {type: integer, minimum: 0}
canHold: {type: boolean}
canRelease: {type: boolean}
actionBlockReason: {type: string, nullable: true}
history:
type: array
items: {$ref: '#/components/schemas/InboundHoldHistoryItem'}
OrderChannelChangeValidationRequest:
type: object
additionalProperties: false
required: [tenantId, orderId, orderVersion, channelCode]
properties:
tenantId: {type: integer, format: int64, minimum: 1}
orderId: {type: integer, format: int64, minimum: 1}
orderVersion: {type: integer, format: int64, minimum: 0}
channelCode: {type: string, minLength: 1, maxLength: 64}
OrderDeclarationUpdatedEvent:
type: object
additionalProperties: false
required: [schemaVersion, eventId, tenantId, orderId, orderNo, inboundCode, version, operatorId, occurredAt, channelCode, channelName, channelChanged, cargoes, changes]
properties:
schemaVersion: {type: integer, enum: [1]}
eventId: {type: string, minLength: 1, maxLength: 128}
tenantId: {type: integer, format: int64, minimum: 1}
orderId: {type: integer, format: int64, minimum: 1}
orderNo: {type: string, minLength: 1}
inboundCode: {type: string, minLength: 1, maxLength: 40, description: 仅作一致性校验,绝不修改 Firstleg 入仓码或唛头}
version: {type: integer, minimum: 0}
operatorId: {type: integer, format: int64, minimum: 1}
occurredAt: {type: string, format: date-time}
customerRemark: {type: string, nullable: true, maxLength: 1000}
expectedArrivalAt: {type: string, format: date-time, nullable: true}
channelCode: {type: string, minLength: 1, maxLength: 64}
channelName: {type: string, minLength: 1, maxLength: 128}
channelChanged: {type: boolean}
cargoes: {type: array, minItems: 1, maxItems: 500, items: {type: object, description: 与 OrderDeclarationDtos.Cargo 字段完全一致}}
changes: {type: array, items: {type: object, description: 与 OrderDeclarationDtos.FieldChange 字段完全一致}}
OrderChannelChangePricingRequest:
type: object
additionalProperties: false
required: [tenantId, orderId, orderVersion, originWarehouseId, channelCode, channelName, destinationType, pricingTaxMode]
properties:
tenantId: {type: integer, format: int64, minimum: 1}
orderId: {type: integer, format: int64, minimum: 1}
orderVersion: {type: integer, format: int64, minimum: 0, description: Order 渠道变更完成后的聚合版本;用于幂等与拒绝旧事件}
originWarehouseId: {type: integer, format: int64, minimum: 1}
channelCode: {type: string, minLength: 1, maxLength: 64}
channelName: {type: string, minLength: 1, maxLength: 128}
destinationType: {type: string, enum: [FBA, OVERSEAS]}
destinationWarehouseId: {type: integer, format: int64, minimum: 1, nullable: true}
destinationCode: {type: string, maxLength: 64, nullable: true}
pricingTaxMode: {type: string, enum: [TAX_INCLUDED, TAX_EXCLUDED]}
OrderChannelChangePricingResponse:
type: object
required: [inboundId, orderId, orderVersion, channelCode, feeStatus, calculatedFeeWillBeInvalidated]
properties:
inboundId: {type: integer, format: int64}
orderId: {type: integer, format: int64}
orderVersion: {type: integer, format: int64}
channelCode: {type: string}
priceBookVersionId: {type: integer, format: int64, nullable: true}
feeStatus: {type: string, enum: [UNPRICED, CALCULATED, VOIDED]}
calculatedFeeWillBeInvalidated: {type: boolean}
invalidatedFeeId: {type: integer, format: int64, nullable: true}
UnifiedMainStatus:
type: string
enum: [PENDING_REVIEW, WAIT_MEASURE, WAIT_PALLETIZE, WAIT_SPLIT, LOADING, LOADED, DELIVERED]
description: 七态产品主状态;WAIT_PALLETIZE 仅表示一件代发待清点组托
UnifiedInboundQuery:
type: object
properties:
taxMode: {type: string, enum: [TAX_REFUND, BUY_DECLARATION], nullable: true, description: 按税务模式在数据库计数和分页前过滤;未传不限制}
tenantId: {type: integer, format: int64, nullable: true}
keyword: {type: string, maxLength: 64, nullable: true}
orderNo: {type: string, maxLength: 64, nullable: true}
mainStatus:
type: string
enum: [PENDING_REVIEW, WAIT_MEASURE, WAIT_PALLETIZE, WAIT_SPLIT, LOADING, LOADED, DELIVERED, WAIT_WEIGHT_CONFIRM, WEIGHT_CONFIRMED, WAIT_CUSTOMS_DOCS, EXPORT_CUSTOMS, SAILING_CLEARANCE, WAIT_UNLOAD, WAIT_DISPATCH, OUTBOUND_DOCUMENT, DELIVERING, SIGNED, MEASUREMENT_REVIEW]
nullable: true
description: WAIT_SPLIT 为唯一待分柜筛选值;WAIT_CUSTOMS_DOCS 为实际装柜后缺少本票客户报关资料;EXPORT_CUSTOMS 按本票资料已上传且实际装柜完成汇总,买单无需客户退税资料,不依赖点击开始报关,实际开船后移出;SAILING_CLEARANCE 按手动或拉取的实际离港节点进入,清关资料上传后进入 WAIT_UNLOAD,实际卸柜完成后移出。
customerId: {type: integer, format: int64, nullable: true}
receivingWarehouseId: {type: integer, format: int64, nullable: true}
destinationWarehouseId: {type: integer, format: int64, nullable: true}
inboundCode: {type: string, maxLength: 64, nullable: true}
internalOrderStatus: {type: string, maxLength: 32, nullable: true}
expectedArrivalDate: {type: string, format: date, nullable: true}
feeReviewStatus: {type: string, maxLength: 32, nullable: true}
channelName: {type: string, maxLength: 128, nullable: true}
cabinetNo: {type: string, maxLength: 64, nullable: true}
sailingDate: {type: string, format: date, nullable: true}
loaded: {type: boolean, nullable: true}
fullContainer: {type: boolean, nullable: true}
measurementReviewStatus: {type: string, maxLength: 32, nullable: true}
candidateOrderIds: {type: array, nullable: true, items: {type: integer, format: int64}}
createdFrom: {type: string, format: date-time, nullable: true}
createdTo: {type: string, format: date-time, nullable: true}
page: {type: integer, format: int64, minimum: 1, default: 1}
size: {type: integer, format: int64, minimum: 1, maximum: 200, default: 20}
UnifiedInboundBatchRequest:
type: object
required: [orderIds]
properties:
tenantId: {type: integer, format: int64, nullable: true}
orderIds:
type: array
minItems: 1
maxItems: 200
items: {type: integer, format: int64, minimum: 1}
UnifiedInboundDetailRequest:
type: object
required: [tenantId, orderId]
properties:
tenantId: {type: integer, format: int64, minimum: 1}
orderId: {type: integer, format: int64, minimum: 1}
UnifiedInboundPageEnvelope:
type: object
properties:
code: {type: string, example: '200'}
message: {type: string}
data:
type: object
properties:
records: {type: array, items: {$ref: '#/components/schemas/UnifiedInboundSummary'}}
page: {type: string, pattern: '^[1-9][0-9]*$'}
size: {type: string, pattern: '^[1-9][0-9]*$'}
total: {type: string, pattern: '^[0-9]+$'}
pages: {type: string, pattern: '^[0-9]+$'}
UnifiedInboundListEnvelope:
type: object
properties:
code: {type: string, example: '200'}
message: {type: string}
data: {type: array, items: {$ref: '#/components/schemas/UnifiedInboundSummary'}}
UnifiedInboundDetailEnvelope:
type: object
properties:
code: {type: string, example: '200'}
message: {type: string}
data:
allOf: [{$ref: '#/components/schemas/UnifiedInboundDetail'}]
nullable: true
UnifiedInboundDetail:
type: object
required: [transportFragments]
properties:
transportFragments:
type: array
description: 仅当前客户当前订单已完成实装片段的柜级运输事实,按入仓码和柜次分别返回,不包含跳拣来源或其他客户
items: {$ref: '#/components/schemas/CustomerTransportFragment'}
summary: {$ref: '#/components/schemas/UnifiedInboundSummary'}
timeline:
type: array
items:
type: object
properties:
source: {type: string}
eventType: {type: string}
fromStatus: {type: string, nullable: true}
toStatus: {type: string, nullable: true}
action: {type: string, nullable: true}
remark: {type: string, nullable: true}
operatorId: {type: integer, format: int64, nullable: true}
operatorName: {type: string, nullable: true}
occurredAt: {type: string, format: date-time, nullable: true}
UnifiedInboundSummary:
type: object
properties:
inbound: {$ref: '#/components/schemas/UnifiedInboundOrderSummary'}
mainStatus: {$ref: '#/components/schemas/UnifiedMainStatus'}
nextAction: {type: string, nullable: true}
customerFeeConfirmationRequired: {type: boolean, description: 最新费用已发送给客户且尚未由客户确认}
preload: {$ref: '#/components/schemas/UnifiedPreloadSummary'}
loading: {$ref: '#/components/schemas/UnifiedLoadingSummary'}
delivery: {$ref: '#/components/schemas/UnifiedDeliverySummary'}
UnifiedInboundOrderSummary:
type: object
description: InboundOrderSummary 的内部统一订单投影
properties:
id: {type: integer, format: int64}
tenantId: {type: integer, format: int64}
orderId: {type: integer, format: int64, nullable: true}
orderNo: {type: string, nullable: true}
inboundCode: {type: string, nullable: true}
processStatus: {type: string, nullable: true, description: Firstleg 内部状态;一件代发测量后先进入 WAIT_PALLETIZE,合托完成再进入 WAIT_SPLIT}
orderStatusSnapshot: {type: string, nullable: true}
measureReviewStatus: {type: string, nullable: true}
feeStatus: {type: string, nullable: true}
feeReviewStatus: {type: string, nullable: true}
notificationStatus: {type: string, nullable: true}
version: {type: integer, nullable: true}
expectedArrivalAt: {type: string, format: date-time, nullable: true}
customerId: {type: integer, format: int64, nullable: true}
customerName: {type: string, nullable: true}
companyId: {type: integer, format: int64, nullable: true}
companyName: {type: string, nullable: true}
warehouseId: {type: integer, format: int64, nullable: true}
warehouseName: {type: string, nullable: true}
deliveryWarehouseId: {type: integer, format: int64, nullable: true}
deliveryWarehouseName: {type: string, nullable: true}
businessType: {type: string, nullable: true}
fulfillmentType: {type: string, enum: [STANDARD, ONE_CLICK_DROPSHIP], nullable: true}
lxCode: {type: string, nullable: true, description: 一件代发线路或履约产品编码快照}
channelCode: {type: string, nullable: true}
channelName: {type: string, nullable: true}
expectedPalletCount: {type: integer, minimum: 1, maximum: 1000, nullable: true, description: 一件代发预计托数;测量审核通过后按此数量预生成 DP 托盘码}
taxMode: {type: string, nullable: true}
pricingTaxMode: {type: string, nullable: true}
containerMode: {type: string, nullable: true}
customsInspection: {type: boolean, nullable: true}
destinationType: {type: string, nullable: true}
destinationWarehouseId: {type: integer, format: int64, nullable: true}
destinationCode: {type: string, nullable: true}
destinationName: {type: string, nullable: true}
holdFlag: {type: boolean, nullable: true}
currentHoldReason: {type: string, nullable: true}
totalPackageCount: {type: integer, nullable: true}
locationCodes: {type: string, nullable: true}
actualGrossWeightKg: {type: number, nullable: true, multipleOf: 0.001, description: 服务端确认后的实测毛重 KG;只读取 fl_inbound_order.actual_gross_weight_kg,不以净重回退}
actualNetWeightKg: {type: number, nullable: true, multipleOf: 0.001, description: 服务端确认后的货物净重 KG;只读取 fl_inbound_order.actual_net_weight_kg,不以毛重回退}
actualVolumeCbm: {type: number, nullable: true}
volumeWeightKg: {type: number, nullable: true}
chargeableWeightKg: {type: number, nullable: true}
chargeableVolumeCbm: {type: number, nullable: true}
palletCount: {type: integer, nullable: true}
measureCompletedAt: {type: string, format: date-time, nullable: true}
inboundedAt: {type: string, format: date-time, nullable: true}
expressCompanyCode: {type: string, nullable: true}
expressCompanyName: {type: string, nullable: true}
containerNo: {type: string, nullable: true}
cabinetNo: {type: string, nullable: true}
vesselName: {type: string, nullable: true}
voyageNo: {type: string, nullable: true}
estimatedSailingAt: {type: string, format: date-time, nullable: true, description: 当前关联柜次预计开船时间}
actualSailingAt: {type: string, format: date-time, nullable: true, description: 当前关联柜次实际开船时间}
estimatedPortArrivalAt: {type: string, format: date-time, nullable: true, description: 当前关联柜次预计到港时间}
actualPortArrivalAt: {type: string, format: date-time, nullable: true, description: 当前关联柜次实际到港时间}
expressTrackingNo: {type: string, nullable: true}
pickupMethod: {type: string, enum: [SELF_EXPRESS, PICKUP, SELF_TRUCK], nullable: true}
requestedPickupAt: {type: string, format: date-time, nullable: true, description: 客户要求平台上门提货的预约时间}
createdByName: {type: string, nullable: true}
createdAt: {type: string, format: date-time, nullable: true}
updatedAt: {type: string, format: date-time, nullable: true}
UnifiedPreloadSummary:
type: object
nullable: true
properties:
status: {type: string, nullable: true}
version: {type: integer, nullable: true}
itemCount: {type: integer, nullable: true}
updatedAt: {type: string, format: date-time, nullable: true}
UnifiedLoadingSummary:
type: object
nullable: true
properties:
status: {type: string, nullable: true}
loadingVersion: {type: integer, nullable: true, description: 当前为 pickingVersion 兼容别名}
pickingVersion: {type: integer, nullable: true}
expectedCount: {type: integer, nullable: true}
pickedCount: {type: integer, nullable: true}
evidenceCount: {type: integer, nullable: true}
sealNo: {type: string, nullable: true}
updatedAt: {type: string, format: date-time, nullable: true}
UnifiedDeliverySummary:
type: object
nullable: true
properties:
status: {type: string, nullable: true}
completedAt: {type: string, format: date-time, nullable: true}
trackingNo: {type: string, nullable: true}
MojiaMeasurementUploadEnvelope:
type: object
properties:
code: {type: string, example: '200'}
message: {type: string, example: success}
data: {$ref: '#/components/schemas/MojiaMeasurementUploadResponse'}
MojiaMeasurementUploadResponse:
type: object
required: [accepted, matched, boxCode, created]
properties:
accepted: {type: boolean, example: true}
matched: {type: boolean, description: true 表示已写入正式箱级测量;false 表示已写入联调收件箱等待排查}
receiptId: {type: string, nullable: true, description: matched=false 时返回的联调收件记录ID}
measurementId: {type: string, nullable: true}
itemId: {type: string, nullable: true}
boxCode: {type: string}
imageFileId: {type: string, nullable: true}
created: {type: boolean}
CustomerDimensionConfigUpdateRequest:
type: object
required: [rules]
properties:
rules:
type: array
minItems: 4
maxItems: 4
description: 必须恰好包含 SMALL、MEDIUM、LARGE、EXTRA_LARGE 各一行
items: {$ref: '#/components/schemas/CustomerDimensionConfigRuleUpdateRequest'}
CustomerDimensionDefaultCalculationModeUpdateRequest:
type: object
required: [defaultCalculationMode]
properties:
defaultCalculationMode: {type: string, enum: [ACTUAL, ADD, MULTIPLY]}
CustomerDimensionConfigRuleUpdateRequest:
type: object
required: [boxType, innerLengthCm, innerWidthCm, innerHeightCm, edgeAdditionCm, version]
properties:
boxType: {type: string, enum: [SMALL, MEDIUM, LARGE, EXTRA_LARGE]}
innerLengthCm: {type: number, minimum: 0.001, multipleOf: 0.001}
innerWidthCm: {type: number, minimum: 0.001, multipleOf: 0.001}
innerHeightCm: {type: number, minimum: 0.001, multipleOf: 0.001}
edgeAdditionCm:
type: number
minimum: 0.001
maximum: 100
multipleOf: 0.001
description: 箱规长、宽、高三个方向分别使用的每侧加宽厘米数;每个完整尺寸增加该值的2倍
example: 2.000
remark: {type: string, maxLength: 500, nullable: true}
version: {type: integer, minimum: 0, description: 乐观锁版本号}
CustomerDimensionConfigGroupResponse:
type: object
required: [tenantId, defaultCalculationMode, rules]
properties:
tenantId: {type: string, pattern: '^[1-9][0-9]*$'}
defaultCalculationMode: {type: string, enum: [ACTUAL, ADD, MULTIPLY]}
rules:
type: array
minItems: 4
maxItems: 4
items: {$ref: '#/components/schemas/CustomerDimensionConfigRuleResponse'}
CustomerDimensionConfigRuleResponse:
type: object
required: [id, boxType, boxTypeName, innerLengthCm, innerWidthCm, innerHeightCm, edgeAdditionCm, outerLengthCm, outerWidthCm, outerHeightCm, volumeCbm, version]
properties:
id: {type: string, pattern: '^[1-9][0-9]*$'}
boxType: {type: string, enum: [SMALL, MEDIUM, LARGE, EXTRA_LARGE]}
boxTypeName: {type: string, enum: [小箱, 中箱, 大箱, 特大箱]}
innerLengthCm: {type: number, minimum: 0.001, multipleOf: 0.001}
innerWidthCm: {type: number, minimum: 0.001, multipleOf: 0.001}
innerHeightCm: {type: number, minimum: 0.001, multipleOf: 0.001}
edgeAdditionCm: {type: number, minimum: 0.001, maximum: 100, example: 2.000}
outerLengthCm: {type: number, minimum: 0.001, description: innerLengthCm + edgeAdditionCm * 2}
outerWidthCm: {type: number, minimum: 0.001, description: innerWidthCm + edgeAdditionCm * 2}
outerHeightCm: {type: number, minimum: 0.001, description: innerHeightCm + edgeAdditionCm * 2}
volumeCbm: {type: number, multipleOf: 0.001, description: 使用未舍入外径完整计算后四舍五入保留3位}
remark: {type: string, nullable: true}
version: {type: integer, minimum: 0}
createdAt: {type: string, format: date-time, nullable: true}
updatedAt: {type: string, format: date-time, nullable: true}
CustomerDimensionConfigInitializeRequest:
type: object
required: [tenantId, operatorId, initializationKey, customerName]
properties:
tenantId: {type: string, pattern: '^[1-9][0-9]*$'}
operatorId: {type: string, pattern: '^[0-9]+$'}
initializationKey: {type: string, minLength: 1, maxLength: 128}
customerName: {type: string, minLength: 1, maxLength: 128}
CustomerDimensionConfigInitializeResponse:
type: object
required: [configId, chargeRuleId, createdByThisInitialization]
properties:
configId: {type: string, pattern: '^[1-9][0-9]*$'}
chargeRuleId: {type: string, pattern: '^[1-9][0-9]*$'}
createdByThisInitialization: {type: boolean}
WeightPalletSnapshot:
type: object
required: [palletId, palletCode, palletType, capacityCbm, tareWeightKg]
properties:
palletId: {type: string, pattern: '^[1-9][0-9]*$'}
palletCode: {type: string}
palletType: {type: string}
capacityCbm: {type: number, format: double, minimum: 0.0001}
tareWeightKg: {type: number, format: double, minimum: 0, multipleOf: 0.001}
WeightPalletOptionPage:
type: object
required: [records, page, size, total, pages]
properties:
records:
type: array
maxItems: 100
items: {$ref: '#/components/schemas/WeightPalletSnapshot'}
page: {oneOf: [{type: integer, format: int64, minimum: 1}, {type: string, pattern: '^[1-9][0-9]*$'}]}
size: {oneOf: [{type: integer, format: int64, minimum: 1, maximum: 100}, {type: string, pattern: '^(?:[1-9]|[1-9][0-9]|100)$'}]}
total: {oneOf: [{type: integer, format: int64, minimum: 0}, {type: string, pattern: '^(?:0|[1-9][0-9]*)$'}]}
pages: {oneOf: [{type: integer, format: int64, minimum: 0}, {type: string, pattern: '^(?:0|[1-9][0-9]*)$'}]}
CreateWeightResultRequest:
type: object
required: [fileId, palletId]
properties:
fileId: {type: string, pattern: '^[1-9][0-9]*$'}
palletId: {type: string, pattern: '^[1-9][0-9]*$'}
ocrProvider: {type: string, maxLength: 64, nullable: true}
ocrRawText: {type: string, maxLength: 1000, nullable: true}
ocrWeightValue: {type: number, format: double, minimum: 0, nullable: true, description: OCR 原始含托盘毛重}
ocrWeightUnit: {type: string, maxLength: 8, nullable: true}
confidence: {type: number, format: double, minimum: 0, maximum: 1, nullable: true}
CorrectWeightResultRequest:
type: object
required: [version, adjustedWeightValue, adjustedWeightUnit, adjustmentReason]
properties:
version: {type: integer, minimum: 0}
adjustedWeightValue: {type: number, format: double, minimum: 0.001, description: 人工修正后的含托盘毛重}
adjustedWeightUnit: {type: string, enum: [KG, LB]}
adjustmentReason: {type: string, minLength: 1, maxLength: 500}
InboundWeightResult:
type: object
required: [id, fileId, palletId, palletCode, palletType, palletCapacityCbm, palletTareWeightKg, recognitionStatus, version]
properties:
id: {type: string, pattern: '^[1-9][0-9]*$'}
fileId: {type: string, pattern: '^[1-9][0-9]*$'}
palletId: {type: string, pattern: '^[1-9][0-9]*$'}
palletCode: {type: string}
palletType: {type: string}
palletCapacityCbm: {type: number, format: double, minimum: 0.0001}
palletTareWeightKg: {type: number, format: double, minimum: 0, multipleOf: 0.001}
ocrProvider: {type: string, nullable: true}
ocrRawText: {type: string, nullable: true}
ocrWeightValue: {type: number, format: double, nullable: true, description: OCR 原始含托盘毛重}
ocrWeightUnit: {type: string, nullable: true}
confidence: {type: number, format: double, nullable: true}
grossWeightKg: {type: number, format: double, nullable: true, multipleOf: 0.001, description: 确认时标准化的含托盘毛重 KG}
adjustedWeightValue: {type: number, format: double, nullable: true, description: 人工修正后的含托盘毛重}
adjustedWeightUnit: {type: string, nullable: true}
netWeightKg: {type: number, format: double, nullable: true, multipleOf: 0.001, description: grossWeightKg - palletTareWeightKg}
recognitionStatus: {type: string, enum: [PENDING, PENDING_CONFIRM, NEEDS_MANUAL, CONFIRMED]}
adjustmentReason: {type: string, nullable: true}
adjustedBy: {type: string, nullable: true}
adjustedAt: {type: string, format: date-time, nullable: true}
confirmedBy: {type: string, nullable: true}
confirmedAt: {type: string, format: date-time, nullable: true}
palletSequence: {type: integer, minimum: 1, nullable: true, description: 已绑定称重托盘在整票内的稳定顺序;未绑定槽位时为空}
blockId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true, description: Warehouse 整票连续库位块标识}
slotNo: {type: integer, minimum: 1, nullable: true, description: 整票连续块内的稳定槽位序号}
reservationId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true, description: Warehouse 预占资源唯一标识;A0 共享时仍按此字段区分}
locationId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true, description: Warehouse 库位标识}
locationCode: {type: string, nullable: true, description: 库位业务编码,例如 A01 或 A0}
sharedOverflow: {type: boolean, nullable: true, description: 是否因普通连续位不足而使用共享 A0}
slotStatus: {type: string, enum: [RESERVED_EMPTY, BOUND, TRANSFERRED, RELEASED], nullable: true, description: 当前整票槽位状态}
version: {type: integer, minimum: 0}
InboundMeasurementItem:
type: object
description: >-
单条尺寸测量明细。id 是稳定 measurementItemId;intelligentImageFileId 仅表示该明细的
尺寸测量原图,不得与 weightResults.fileId 混用。fbaShipmentNo 是按 inboundDetailId
从 Order 货物明细实时读取的权威货件编号;scannedShipmentId 是独立设备实扫证据,二者不得回退或覆盖。
required: [id]
properties:
id: {type: string, pattern: '^[1-9][0-9]*$', description: 稳定 measurementItemId}
inboundCode: {type: string, nullable: true, description: 当前测量详情唯一权威入仓码,与根对象inboundCode一致}
inboundDetailId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true}
itemNo: {type: string, nullable: true}
boxSpecification: {type: string, nullable: true}
packageCount: {type: integer, nullable: true}
lengthCm: {type: number, format: double, nullable: true}
widthCm: {type: number, format: double, nullable: true}
heightCm: {type: number, format: double, nullable: true}
girthCm: {type: number, format: double, nullable: true}
unitVolumeCbm: {type: number, format: double, nullable: true}
totalVolumeCbm: {type: number, format: double, nullable: true}
volumeWeightKg: {type: number, format: double, nullable: true}
intelligentImageFileId:
type: string
pattern: '^[1-9][0-9]*$'
nullable: true
description: 当前尺寸测量明细的 File 文件 ID;图片类型固定为 DIMENSION
overLimitWarning: {type: string, nullable: true}
outerLengthCm: {type: number, format: double, nullable: true, description: 仓库手工保存的外箱长度;未保存人工修正时为空}
outerWidthCm: {type: number, format: double, nullable: true, description: 仓库手工保存的外箱宽度;未保存人工修正时为空}
outerHeightCm: {type: number, format: double, nullable: true, description: 仓库手工保存的外箱高度;未保存人工修正时为空}
calculatedOuterLengthCm: {type: number, format: double, nullable: true, description: 已落库的最终外箱规长度}
calculatedOuterWidthCm: {type: number, format: double, nullable: true, description: 已落库的最终外箱规宽度}
calculatedOuterHeightCm: {type: number, format: double, nullable: true, description: 已落库的最终外箱规高度}
calculationRuleVersion: {type: string, nullable: true, description: 当前外箱规所绑定的箱规或系数规则版本}
chargeRuleId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true}
coefficientMode: {type: string, enum: [ACTUAL, ADD, MULTIPLY], nullable: true}
remark: {type: string, nullable: true}
boxCode: {type: string, nullable: true}
fbaShipmentNo: {type: string, nullable: true, description: Order货物明细按inboundDetailId匹配的权威FBA货件编号;匹配失败为空}
scannedShipmentId: {type: string, nullable: true, description: 设备实扫Shipment ID;仅作现场证据,不覆盖或回退fbaShipmentNo}
confirmedPackageCount: {type: integer, nullable: true}
machineNo: {type: string, nullable: true}
deviceMeasuredAt: {type: string, format: date-time, nullable: true}
updatedAt: {type: string, format: date-time, nullable: true}
InboundMeasurementDetail:
type: object
description: >-
入库测量权威详情。尺寸证据天然归属 items,称重证据天然归属 weightResults,响应不提供统一 images。
required: [inboundId, inboundVersion, customerFeeConfirmed, items, weightResults]
properties:
inboundId: {type: string, pattern: '^[1-9][0-9]*$'}
inboundCode: {type: string, nullable: true, description: 当前测量详情唯一入仓码,UI业务主展示字段}
companyName: {type: string, nullable: true}
channelCode: {type: string, nullable: true}
channelName: {type: string, nullable: true}
processStatus: {type: string, nullable: true}
measureReviewStatus: {type: string, nullable: true}
customerFeeConfirmed: {type: boolean, description: 当前最新费用版本已由客户确认,确认后测量数据不可再修改}
recommendedPalletType: {type: string, nullable: true}
reviewReason: {type: string, nullable: true}
reviewerId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true}
reviewerName: {type: string, nullable: true}
measurementId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true}
sourceType: {type: string, nullable: true}
measurementStatus: {type: string, nullable: true}
inboundVersion: {type: integer, minimum: 0}
version: {type: integer, minimum: 0, nullable: true}
originalDocumentNo: {type: string, nullable: true, description: 测量批次开始时冻结的客户订单 referenceId;批次为空时才以最新申报回退}
originalGrossWeightKg: {type: number, format: double, nullable: true, description: 测量批次开始时冻结的客户申报毛重;不得被后续订单编辑覆盖}
originalVolumeCbm: {type: number, format: double, nullable: true, description: 测量批次开始时冻结的客户申报体积;不得被后续订单编辑覆盖}
originalPackageCount: {type: integer, nullable: true, description: 最新客户申报总箱数;仅用于与 actualPackageCount 对比}
actualPackageCount: {type: integer, nullable: true}
actualGrossWeightKg:
type: number
format: double
nullable: true
multipleOf: 0.001
description: 全部 CONFIRMED 称重结果 grossWeightKg 之和,含托盘毛重 KG;无确认结果时为空
actualNetWeightKg:
type: number
format: double
nullable: true
multipleOf: 0.001
description: 全部 CONFIRMED 称重结果 netWeightKg 之和,扣除托盘皮重后的货物净重 KG;无确认结果时为空,审核与计费以此为准
actualVolumeCbm: {type: number, format: double, nullable: true}
volumeWeightKg: {type: number, format: double, nullable: true}
actualGoodsName: {type: string, nullable: true, description: 默认由客户货物品名去重汇总,测量阶段允许人工修正}
latestDeclaration:
$ref: '#/components/schemas/InboundMeasurementLatestDeclaration'
items:
type: array
description: DIMENSION 尺寸测量明细及其图片证据
items: {$ref: '#/components/schemas/InboundMeasurementItem'}
weightResults:
type: array
description: WEIGHT 称重结果及其图片、确认状态和服务端重量事实
items: {$ref: '#/components/schemas/InboundWeightResult'}
palletLocationGuide:
allOf: [{$ref: '#/components/schemas/InboundPalletLocationGuide'}]
nullable: true
description: 服务端权威的整票上架引导;首张称重图片确认前为空,确认成功后立即返回并在后续确认时原位扩容,禁止由 weightResults 数量或数组下标推导
InboundPalletLocationGuide:
type: object
required: [blockId, reservedSlotCount, actualPalletCount, reservedEmptySlotCount, slots]
properties:
blockId: {type: string, pattern: '^[1-9][0-9]*$', description: Warehouse 整票连续库位块标识}
reservedSlotCount: {type: integer, minimum: 1, description: 整票当前预留槽位总数,等于 slots 长度}
actualPalletCount: {type: integer, minimum: 0, description: 已绑定称重结果的实际托数}
reservedEmptySlotCount: {type: integer, minimum: 0, description: slotStatus=RESERVED_EMPTY 的预留空位数}
slots:
type: array
minItems: 1
maxItems: 200
description: 严格按 slotNo 升序返回的整票槽位
items: {$ref: '#/components/schemas/InboundPalletLocationSlot'}
InboundPalletLocationSlot:
type: object
required: [slotNo, reservationId, locationId, locationCode, sharedOverflow, slotStatus]
properties:
slotNo: {type: integer, minimum: 1}
reservationId: {type: string, pattern: '^[1-9][0-9]*$'}
locationId: {type: string, pattern: '^[1-9][0-9]*$'}
locationCode: {type: string}
sharedOverflow: {type: boolean}
slotStatus: {type: string, enum: [RESERVED_EMPTY, BOUND, TRANSFERRED, RELEASED]}
boundWeightResultId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true}
palletSequence: {type: integer, minimum: 1, nullable: true}
palletId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true}
palletCode: {type: string, nullable: true}
InboundMeasurementLatestDeclaration:
type: object
description: Order 服务中的最新客户申报只读视图;订单编辑只能改变本对象,不得覆盖箱码、实测尺寸/重量或审核结果
required: [totalPackageCount, items]
properties:
referenceId: {type: string, nullable: true}
totalPackageCount: {type: integer, minimum: 0}
grossWeightKg: {type: number, format: double, nullable: true}
volumeCbm: {type: number, format: double, nullable: true}
goodsName: {type: string, nullable: true}
items:
type: array
items: {$ref: '#/components/schemas/InboundMeasurementDeclarationItem'}
InboundMeasurementDeclarationItem:
type: object
description: 最新订单货物申报行;inboundDetailId 仅用于与实测明细关联,不作为用户展示编号
required: [inboundDetailId, itemNo, packageCount]
properties:
inboundDetailId: {type: string, pattern: '^[1-9][0-9]*$'}
itemNo: {type: integer, minimum: 1}
cargoName: {type: string, nullable: true}
packageCount: {type: integer, minimum: 0}
lengthCm: {type: number, format: double, nullable: true}
widthCm: {type: number, format: double, nullable: true}
heightCm: {type: number, format: double, nullable: true}
InboundMeasurementSaveDraftRequest:
type: object
required: [version, items]
additionalProperties: false
properties:
measurementId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true}
version: {type: integer, minimum: 0}
actualGoodsName: {type: string, maxLength: 255, nullable: true}
expectedPalletCount: {type: integer, minimum: 1, maximum: 1000, nullable: true, description: 一件代发必填;普通入库可不传}
items:
type: array
minItems: 1
maxItems: 500
items: {$ref: '#/components/schemas/InboundMeasurementItemRequest'}
InboundMeasurementCalculationStrategyRequest:
type: object
required: [measurementId, version, coefficientMode]
additionalProperties: false
properties:
measurementId: {type: string, pattern: '^[1-9][0-9]*$'}
version: {type: integer, minimum: 0}
coefficientMode: {type: string, enum: [ACTUAL, ADD, MULTIPLY]}
chargeRuleId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true, description: MULTIPLY 模式必填}
InboundMeasurementOuterDimensionsRequest:
type: object
required: [measurementId, version]
additionalProperties: false
properties:
measurementId: {type: string, pattern: '^[1-9][0-9]*$'}
version: {type: integer, minimum: 0}
outerLengthCm: {type: number, minimum: 0.001, nullable: true}
outerWidthCm: {type: number, minimum: 0.001, nullable: true}
outerHeightCm: {type: number, minimum: 0.001, nullable: true}
InboundMeasurementItemRequest:
type: object
required: [inboundDetailId, itemNo, boxSpecification, packageCount, lengthCm, widthCm, heightCm]
additionalProperties: false
properties:
inboundDetailId: {type: string, pattern: '^[1-9][0-9]*$'}
itemNo: {type: string, minLength: 1, maxLength: 32}
boxSpecification: {type: string, minLength: 1, maxLength: 64}
packageCount: {type: integer, minimum: 1, maximum: 1000000}
lengthCm: {type: number, minimum: 0.001}
widthCm: {type: number, minimum: 0.001}
heightCm: {type: number, minimum: 0.001}
unitWeightKg: {type: number, minimum: 0, multipleOf: 0.0001, nullable: true, description: 实际总毛重按总箱数均分后的单箱毛重;用于系数挡位匹配}
intelligentImageFileId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true}
overLimitWarning: {type: string, maxLength: 500, nullable: true}
outerLengthCm: {type: number, minimum: 0, nullable: true, description: 可单独提交的仓库外箱长度修正;保存后参与联动计算}
outerWidthCm: {type: number, minimum: 0, nullable: true, description: 可单独提交的仓库外箱宽度修正;保存后参与联动计算}
outerHeightCm: {type: number, minimum: 0, nullable: true, description: 可单独提交的仓库外箱高度修正;保存后参与联动计算}
chargeRuleId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true}
coefficientMode: {type: string, enum: [ACTUAL, ADD, MULTIPLY], nullable: true}
remark: {type: string, maxLength: 500, nullable: true}
InboundMeasurementDetailEnvelope:
type: object
required: [code, message]
properties:
code: {type: string, example: '200'}
message: {type: string}
data: {$ref: '#/components/schemas/InboundMeasurementDetail'}
requestId: {type: string, nullable: true}
traceId: {type: string, nullable: true}
ConfirmWeightResultRequest:
type: object
required: [version]
description: 人工修改字段表示含托盘毛重且必须同时提供;全部省略时直接确认现有 OCR 或已修正毛重。
properties:
version: {type: integer, minimum: 0}
adjustedWeightValue: {type: number, format: double, minimum: 0.001, nullable: true}
adjustedWeightUnit: {type: string, enum: [KG, LB], nullable: true}
adjustmentReason: {type: string, minLength: 1, maxLength: 500, nullable: true}
OrderApprovedInboundCommand:
type: object
required: [tenantId, orderId, inboundCode, customerName, warehouseId, fulfillmentType]
properties:
tenantId: {type: string, pattern: '^[1-9][0-9]*$', description: 当前客户隔离 ID}
orderId: {type: string, pattern: '^[1-9][0-9]*$'}
orderNo: {type: string, nullable: true}
inboundCode: {type: string, minLength: 1, maxLength: 40, example: ZBYHK2608140001}
customerId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true}
customerName: {type: string, minLength: 1}
warehouseId: {type: string, pattern: '^[1-9][0-9]*$'}
warehouseName: {type: string, nullable: true}
deliveryWarehouseId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true}
deliveryWarehouseName: {type: string, nullable: true}
expectedArrivalAt: {type: string, format: date-time, nullable: true}
businessType: {type: string, nullable: true}
fulfillmentType: {type: string, enum: [STANDARD, ONE_CLICK_DROPSHIP], description: 独立履约类型;不得复用计费 businessType}
channelCode: {type: string, nullable: true}
channelName: {type: string, nullable: true}
carrierId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true, description: 历史兼容的内部运输供应商快照}
carrierName: {type: string, nullable: true}
taxMode: {type: string, nullable: true}
pricingTaxMode: {type: string, enum: [TAX_INCLUDED, TAX_EXCLUDED], nullable: true, description: 报价包税维度;独立于订单taxMode}
containerMode: {type: string, nullable: true}
customsInspection: {type: boolean, nullable: true}
destinationType: {type: string, nullable: true}
destinationWarehouseId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true}
destinationCode: {type: string, nullable: true}
destinationName: {type: string, nullable: true}
publicRemark: {type: string, nullable: true}
expressCompanyName: {type: string, nullable: true}
expressTrackingNo: {type: string, nullable: true}
ContainerWorkbenchPageEnvelope:
type: object
properties:
code: {type: string, example: '200'}
message: {type: string}
data:
type: object
properties:
records: {type: array, items: {$ref: '#/components/schemas/ContainerWorkbenchItem'}}
page: {type: string, pattern: '^[1-9][0-9]*$'}
size: {type: string, pattern: '^[1-9][0-9]*$'}
total: {type: string, pattern: '^[0-9]+$'}
pages: {type: string, pattern: '^[0-9]+$'}
ContainerWorkbenchEnvelope:
type: object
properties:
code: {type: string, example: '200'}
message: {type: string}
data: {$ref: '#/components/schemas/ContainerWorkbenchItem'}
ContainerWorkbenchItem:
type: object
required: [container, workbenchStage, statusSummary, allowedActions]
properties:
container: {$ref: '#/components/schemas/ContainerBooking'}
workbenchStage: {type: string, enum: [WAIT_LOADING, LOADING, WAIT_CUSTOMS, WAIT_OUTBOUND, DEPARTED_WAREHOUSE, IN_TRANSIT, ARRIVED_DESTINATION_PORT, PICKUP_READY, PICKED_UP, UNLOADED, EMPTY_RETURNED]}
statusSummary: {$ref: '#/components/schemas/ContainerWorkbenchStatusSummary'}
allowedActions:
type: array
description: 已同时按真实业务状态与当前用户权限裁剪
items: {type: string, enum: [EDIT_CONTAINER, MANAGE_CUSTOMS, CONFIRM_OUTBOUND, MANAGE_DESTINATION_DOCUMENTS, SELECT_FLEET, SCHEDULE_PICKUP, RECORD_EMPTY_RETURN, SEND_PICKUP_EMAIL]}
actualFacts: {$ref: '#/components/schemas/ContainerActualFacts'}
terminalDrayage: {$ref: '#/components/schemas/ContainerTerminalDrayage'}
ContainerWorkbenchStatusSummary:
type: object
properties:
loadingStatus: {type: string, nullable: true}
customsStatus: {type: string, nullable: true}
outboundStatus: {type: string, nullable: true}
destinationClearanceStatus: {$ref: '#/components/schemas/ContainerDocumentStatus'}
deliveryOrderStatus: {$ref: '#/components/schemas/ContainerDocumentStatus'}
pickupCodeStatus: {type: string, enum: [MISSING, UPLOADED]}
latestActualNode: {type: string, nullable: true}
latestActualAt: {type: string, format: date-time, nullable: true}
terminalDrayageStatus: {type: string, nullable: true}
emptyReturnWarningStatus: {type: string, enum: [NOT_APPLICABLE, PENDING, OVERDUE, RESOLVED], nullable: true}
ContainerActualFacts:
type: object
nullable: true
description: 仅来自最新船节点任务的actual_at;无任务时为null,不用预计时间推断
properties:
containerBookingId: {type: string, pattern: '^[1-9][0-9]*$'}
queryId: {type: string, pattern: '^[1-9][0-9]*$'}
queryVersion: {type: integer, minimum: 0}
queryStatus: {type: string}
latestActualNode: {type: string, nullable: true}
latestActualAt: {type: string, format: date-time, nullable: true}
departedWarehouseAt: {type: string, format: date-time, nullable: true}
departedOriginPortAt: {type: string, format: date-time, nullable: true}
arrivedDestinationPortAt: {type: string, format: date-time, nullable: true}
pickupReadyAt: {type: string, format: date-time, nullable: true}
pickedUpAt: {type: string, format: date-time, nullable: true}
emptyReturnedAt: {type: string, format: date-time, nullable: true}
ContainerTerminalDrayage:
type: object
nullable: true
properties:
status: {type: string, enum: [WAITING_FOR_ARRIVAL, ARRIVED, PICKUP_SCHEDULED, PICKED_UP, UNLOADED, EMPTY_RETURNED]}
version: {type: integer, minimum: 0}
fleetSupplierId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true}
fleetSupplierName: {type: string, nullable: true}
pickupAppointmentAt: {type: string, format: date-time, nullable: true}
actualPickupAt: {type: string, format: date-time, nullable: true, description: 优先使用实际船节点提柜时间;缺失时在海外PDA确认整柜拆柜完成后使用卸柜完成时间}
estimatedEmptyReturnAt: {type: string, format: date-time, nullable: true, description: unloadingCompletedAt加72小时}
actualEmptyReturnAt: {type: string, format: date-time, nullable: true}
unloadingCompletedAt: {type: string, format: date-time, nullable: true}
emptyReturnWarning: {type: object, nullable: true}
allowedActions: {type: array, items: {type: string, enum: [SELECT_FLEET, SCHEDULE_PICKUP, RECORD_EMPTY_RETURN, SEND_PICKUP_EMAIL]}}
ContainerBooking:
type: object
required: [id, cabinetNo, sourceType, recordStatus, warehouseId, warehouseName, channelGroupCode, containerType, capacityCbm, maxWeightKg, planStatus, exceptionActive, destinationClearanceDocumentStatus, customsDeclarationDocumentStatus, deliveryOrderDocumentStatus, version]
properties:
id: {type: string, pattern: '^[1-9][0-9]*$'}
currentPortScheduleId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true, readOnly: true, description: 当前运输读模型由 latestForDispatch 选中的船期记录 ID;无匹配时为空,仅用于定位关联船期,不作为业务编号展示}
planId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true, description: 关联智能装柜计划ID;未创建计划时为空}
planNo: {type: string, nullable: true, pattern: '^LP[0-9]{12}$', example: LP202608180001, description: 预装与确认装柜清单共用的稳定编号;未创建计划时为空}
containerNo: {type: string, maxLength: 64, nullable: true}
cabinetNo: {type: string, pattern: '^D[0-9]{4,}$', example: D0001, description: 平台全局连续且不按日期重置的稳定柜次号}
sourceType: {type: string, enum: [SIMULATION, OCEAN_BOOKING], description: SIMULATION 为内部模拟柜;OCEAN_BOOKING 为订舱登记直接生成的真实柜}
recordStatus: {type: string, enum: [ACTIVE, MERGED], description: 正常列表和详情仅返回 ACTIVE;真实订舱柜被模拟柜消费后变为 MERGED 且不再作为可操作柜返回}
mergedIntoContainerBookingId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true, description: MERGED 源真实柜指向保留的模拟柜稳定 containerBookingId;ACTIVE 时为空}
channelGroupCode: {type: string, maxLength: 64, enum: [MATSON_CLX, MATSON_MAX, EXX, HEDE, OA_LA, OA_CHICAGO, OA_HOUSTON, OA_SAVANNAH, OA_NEW_YORK_TRUCK], description: 模拟柜创建时确定的九类计划渠道分组,关联真实订舱后继续保留}
channelCode: {type: string, maxLength: 64, nullable: true, description: 关联真实订舱后冻结的实际物流渠道编码}
channelName: {type: string, maxLength: 128, nullable: true, description: 关联真实订舱后冻结的实际物流渠道名称}
oceanBookingId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true}
oceanBookingRequirementId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true}
warehouseId: {type: string, pattern: '^[1-9][0-9]*$'}
warehouseName: {type: string, maxLength: 128}
billOfLadingNo: {type: string, maxLength: 128, nullable: true}
vesselName: {type: string, maxLength: 128, nullable: true}
voyageNo: {type: string, maxLength: 64, nullable: true}
containerType: {type: string, enum: [40GP, 40HQ, 45HQ], description: 平台统一柜型;默认40HQ}
shippingCompanyId: {type: string, nullable: true}
shippingCompanyName: {type: string, maxLength: 128, nullable: true}
departurePortCode: {type: string, maxLength: 32, nullable: true}
departurePortName: {type: string, maxLength: 128, nullable: true}
destinationPortCode: {type: string, maxLength: 32, nullable: true}
destinationPortName: {type: string, maxLength: 128, nullable: true}
destinationWarehouseCode: {type: string, maxLength: 64, nullable: true}
destinationWarehouseName: {type: string, maxLength: 128, nullable: true}
capacityCbm: {type: number, enum: [58, 68, 86], description: 统一实装上限;40GP=58、40HQ=68、45HQ=86}
maxWeightKg: {type: number, enum: [19500], description: 统一货重上限}
terminalTruckingCompanyId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true, description: ACTIVE Warehouse Supplier ID validated as TRUCKING}
terminalTruckingCompany: {type: string, maxLength: 128, nullable: true, description: Server-frozen Warehouse supplier name snapshot}
loadingAt: {type: string, format: date-time, nullable: true}
estimatedSailingAt: {type: string, format: date-time, nullable: true}
actualSailingAt: {type: string, format: date-time, nullable: true}
estimatedPortArrivalAt: {type: string, format: date-time, nullable: true}
actualPortArrivalAt: {type: string, format: date-time, nullable: true}
estimatedWarehouseArrivalAt: {type: string, format: date-time, nullable: true}
actualWarehouseArrivalAt: {type: string, format: date-time, nullable: true}
unloadingCompletedAt: {type: string, format: date-time, nullable: true, description: 海外仓卸柜完成时间}
unloadingPhotoUploadedAt: {type: string, format: date-time, nullable: true, description: 海外仓卸柜照片上传成功时间}
estimatedEmptyReportedAt: {type: string, format: date-time, nullable: true, description: 预计还空时间,统一按卸柜完成时间加72小时计算}
actualEmptyReportedAt: {type: string, format: date-time, nullable: true, description: 实际报空时间}
emptyReportSourceVersion: {type: string, pattern: '^[1-9][0-9]*$', nullable: true, description: 海外货柜事件聚合版本}
planStatus: {type: string, enum: [WAIT_LOADING, EDITING, LOADING, COMPLETED]}
exceptionActive: {type: boolean, description: 最新异常历史动作是否为 MARK}
destinationClearanceDocumentStatus: {$ref: '#/components/schemas/ContainerDocumentStatus'}
customsDeclarationDocumentStatus: {$ref: '#/components/schemas/ContainerDocumentStatus'}
deliveryOrderDocumentStatus: {$ref: '#/components/schemas/ContainerDocumentStatus'}
outboundDispatchStatus: {type: string, nullable: true, description: 国内出仓聚合状态,不使用planStatus推断}
outboundConfirmedAt: {type: string, format: date-time, nullable: true, description: 真实国内离仓确认时间}
pickupCode: {type: string, pattern: '^[0-9]{1,64}$', nullable: true, description: PU数字码;字符串保存以保留前导零}
pickupCodeUpdatedBy: {type: string, pattern: '^[1-9][0-9]*$', nullable: true}
pickupCodeUpdatedByName: {type: string, nullable: true}
pickupCodeUpdatedAt: {type: string, format: date-time, nullable: true}
version: {type: integer, minimum: 0}
ContainerDocumentStatus:
type: string
enum: [MISSING, UPLOADED, COMPLETED]
description: 单证聚合状态;DO 无完成动作,因此只返回 MISSING 或 UPLOADED
ContainerSaveRequest:
type: object
required: [warehouseId, warehouseName, containerType, capacityCbm, maxWeightKg]
properties:
containerNo: {type: string, maxLength: 64, nullable: true}
warehouseId: {type: string, pattern: '^[1-9][0-9]*$'}
warehouseName: {type: string, maxLength: 128}
billOfLadingNo: {type: string, maxLength: 128, nullable: true}
vesselName: {type: string, maxLength: 128, nullable: true}
voyageNo: {type: string, maxLength: 64, nullable: true}
containerType: {type: string, enum: [40GP, 40HQ, 45HQ], description: 平台统一柜型;默认40HQ}
shippingCompanyId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true}
shippingCompanyName: {type: string, maxLength: 128, nullable: true}
departurePortCode: {type: string, maxLength: 32, nullable: true}
departurePortName: {type: string, maxLength: 128, nullable: true}
destinationPortCode: {type: string, maxLength: 32, nullable: true}
destinationPortName: {type: string, maxLength: 128, nullable: true}
destinationWarehouseCode: {type: string, maxLength: 64, nullable: true}
destinationWarehouseName: {type: string, maxLength: 128, nullable: true}
capacityCbm: {type: number, enum: [58, 68, 86], description: 统一实装上限;40GP=58、40HQ=68、45HQ=86}
maxWeightKg: {type: number, enum: [19500], description: 统一货重上限}
terminalTruckingCompanyId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true, description: ACTIVE Warehouse Supplier ID validated as TRUCKING}
terminalTruckingCompany: {type: string, maxLength: 128, nullable: true, description: Optional consistency hint; persisted name always comes from Warehouse and cannot replace the ID}
loadingAt: {type: string, format: date-time, nullable: true}
estimatedSailingAt: {type: string, format: date-time, nullable: true}
actualSailingAt: {type: string, format: date-time, nullable: true}
estimatedPortArrivalAt: {type: string, format: date-time, nullable: true}
actualPortArrivalAt: {type: string, format: date-time, nullable: true}
estimatedWarehouseArrivalAt: {type: string, format: date-time, nullable: true}
actualWarehouseArrivalAt: {type: string, format: date-time, nullable: true}
ContainerFullUpdateRequest:
type: object
required: [version, data]
properties:
version: {type: integer, minimum: 0}
data: {$ref: '#/components/schemas/ContainerSaveRequest'}
SmartLoadingAssignRequest:
type: object
required: [inboundId, inboundDetailId, packageCount, expectedVersion, operationId]
properties:
inboundId: {type: string, pattern: '^[1-9][0-9]*$'}
inboundDetailId: {type: string, pattern: '^[1-9][0-9]*$'}
packageCount: {type: integer, minimum: 1}
expectedVersion: {type: integer, minimum: 0, description: 当前 planVersion}
operationId: {type: string, minLength: 1, maxLength: 128}
SmartLoadingInboundAssignRequest:
type: object
required: [inboundId, packageCount, expectedVersion, operationId]
properties:
inboundId: {type: string, pattern: '^[1-9][0-9]*$'}
packageCount: {type: integer, minimum: 1, description: 该入仓码本次计划装柜总箱数}
expectedVersion: {type: integer, minimum: 0, description: 当前 planVersion}
operationId: {type: string, minLength: 1, maxLength: 128}
SmartLoadingPendingReviewAssignRequest:
type: object
required: [customerId, orderId, inboundCode, packageCount, expectedVersion, operationId]
properties:
customerId: {type: string, pattern: '^[1-9][0-9]*$'}
orderId: {type: string, pattern: '^[1-9][0-9]*$'}
inboundCode: {type: string, minLength: 1, maxLength: 40}
packageCount: {type: integer, minimum: 1, description: 待审核订单本次占用的申报箱数}
expectedVersion: {type: integer, minimum: 0, description: 当前 planVersion}
operationId: {type: string, minLength: 1, maxLength: 128}
SmartLoadingRecommendRequest:
type: object
required: [expectedVersion, operationId]
properties:
expectedVersion: {type: integer, minimum: 0, description: 当前 planVersion}
operationId: {type: string, minLength: 1, maxLength: 128}
customerId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true, description: 当前页面客户筛选;传入时限制推荐范围}
inboundCode: {type: string, minLength: 1, maxLength: 64, nullable: true, description: 当前页面入仓码筛选;传入时限制推荐范围}
SmartLoadingAdjustRequest:
type: object
required: [packageCount, expectedPlanVersion, expectedItemVersion, operationId]
properties:
packageCount: {type: integer, minimum: 1, description: 不得小于响应中的 minPackageCount}
expectedPlanVersion: {type: integer, minimum: 0}
expectedItemVersion: {type: integer, minimum: 0}
operationId: {type: string, minLength: 1, maxLength: 128}
SmartLoadingDeleteRequest:
type: object
required: [expectedPlanVersion, expectedItemVersion, operationId]
properties:
expectedPlanVersion: {type: integer, minimum: 0}
expectedItemVersion: {type: integer, minimum: 0}
operationId: {type: string, minLength: 1, maxLength: 128}
SmartLoadingRemoveUnpickedRequest:
type: object
required: [expectedPlanVersion, operationId]
properties:
expectedPlanVersion: {type: integer, minimum: 0}
operationId: {type: string, minLength: 1, maxLength: 128}
SmartLoadingRemarksRequest:
type: object
required: [expectedPlanVersion, expectedItemVersion, operationId]
properties:
internalRemark: {type: string, nullable: true, maxLength: 1000, description: 内部备注;null/空字符串均表示清空}
warehouseRemark: {type: string, nullable: true, maxLength: 1000, description: 仓库备注;null/空字符串均表示清空}
customerServiceRemark: {type: string, nullable: true, maxLength: 1000, description: 客服备注;null/空字符串均表示清空}
expectedPlanVersion: {type: integer, minimum: 0}
expectedItemVersion: {type: integer, minimum: 0}
operationId: {type: string, minLength: 1, maxLength: 128}
LoadingAssociationSummary:
type: object
required: [inboundId, inboundCode, orderNo, items]
properties:
inboundId: {type: string, pattern: '^[1-9][0-9]*$', description: 入仓片段内部技术ID}
inboundCode: {type: string, minLength: 1, maxLength: 40, description: 订单当前入仓片段业务号,UI主展示}
orderNo: {type: string, nullable: true, description: 订单业务号,UI主展示}
loadingPlanId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true, description: 装柜计划技术关联ID}
loadingPlanNo: {type: string, nullable: true, pattern: '^LP[0-9]{12}$', description: 装柜计划业务号,UI主展示}
containerBookingId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true, description: 柜次技术关联ID}
cabinetNo: {type: string, nullable: true, description: 稳定柜次业务号,UI主展示}
containerNo: {type: string, nullable: true, description: 真实集装箱号,UI主展示}
loadingStatus: {type: string, enum: [EDITING, LOADING, COMPLETED], nullable: true}
taskId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true, description: 国内PDA任务技术关联ID}
pdaTaskStatus: {type: string, enum: [UNASSIGNED, IN_PROGRESS, AWAITING_REVIEW, PROCESSING, COMPLETION_FAILED, COMPLETED], nullable: true, description: 国内PDA任务业务状态}
coLoadGroupId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true, description: 同柜不可拆组技术关联ID}
coLoadGroupNo: {type: string, nullable: true, description: 同柜不可拆组业务号,UI主展示}
items:
type: array
description: 装柜明细技术关联;不作为UI主展示
items:
type: object
required: [itemId]
properties:
itemId: {type: string, pattern: '^[1-9][0-9]*$'}
SmartLoadingChannelSummary:
type: object
additionalProperties: false
required: [channelCode, channelName, candidateInboundCount, availablePackageCount, availableContainerCount]
properties:
channelCode: {type: string, minLength: 1, maxLength: 64}
channelName: {type: string, minLength: 1, maxLength: 128}
candidateInboundCount: {type: integer, format: int64, minimum: 0, description: 当前可分配的唯一入仓码数量}
availablePackageCount: {type: integer, format: int64, minimum: 0, description: 当前候选规格剩余可分配箱数合计}
availableContainerCount: {type: integer, format: int64, minimum: 0, description: 当前 WAIT_LOADING、EDITING 或 LOADING 可编排柜次数量}
SmartLoadingInboundCandidatePageEnvelope:
type: object
required: [code, message, data]
properties:
code: {type: string, example: '200'}
message: {type: string}
data:
type: object
required: [records, page, size, total, pages]
properties:
records: {type: array, items: {$ref: '#/components/schemas/SmartLoadingInboundCandidate'}}
page: {type: integer, format: int64, minimum: 1}
size: {type: integer, format: int64, minimum: 1}
total: {type: integer, format: int64, minimum: 0}
pages: {type: integer, format: int64, minimum: 0}
SmartLoadingInboundCandidate:
type: object
required: [accountId, customerId, inboundId, orderId, orderNo, inboundCode, warehouseId, channelCode,
channelName, customerName, goodsSummary, availablePackageCount, unitGrossWeightKg,
unitNetWeightKg, averageUnitVolumeCbm, availableVolumeCbm, locked, canAssign, groupMembers]
properties:
accountId: {type: string, pattern: '^[1-9][0-9]*$'}
customerId: {type: string, pattern: '^[1-9][0-9]*$', description: 与 accountId 相同的客户技术关联ID}
inboundId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true, description: 待审核订单尚无入仓投影时为空;普通可装柜候选为入仓技术ID}
orderId: {type: string, pattern: '^[1-9][0-9]*$'}
orderNo: {type: string}
inboundCode: {type: string}
orderStatusSnapshot: {type: string, enum: [PENDING_REVIEW, WAIT_MEASURE, WAIT_SPLIT, LOADING]}
expectedArrivalAt: {type: string, format: date-time, nullable: true}
warehouseId: {type: string, pattern: '^[1-9][0-9]*$'}
channelCode: {type: string}
channelName: {type: string}
destinationWarehouseId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true}
destinationWarehouseCode: {type: string, nullable: true}
destinationWarehouseName: {type: string, nullable: true}
customerName: {type: string}
goodsSummary: {type: string, nullable: true}
availablePackageCount: {type: integer, minimum: 0, description: 普通行剩余箱数;组行完整成员箱数合计}
unitGrossWeightKg: {type: number, minimum: 0, nullable: true}
unitNetWeightKg: {type: number, minimum: 0, nullable: true}
averageUnitVolumeCbm: {type: number, minimum: 0, nullable: true}
availableVolumeCbm: {type: number, minimum: 0, nullable: true}
coLoadGroupId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true}
groupNo: {type: string, nullable: true}
memberCount: {type: integer, minimum: 2, nullable: true}
groupTotalBoxes: {type: integer, minimum: 1, nullable: true}
locked: {type: boolean}
canAssign: {type: boolean, description: 当前是否可加入柜次;与搜索状态解耦,以占用及业务约束事实计算}
blockReason: {type: string, nullable: true}
groupMembers:
type: array
description: 同柜组或封托托盘的完整入仓成员;SEALED_PALLET 行按托盘唯一分页,成员 availablePackageCount 为该入仓码在本托的箱数,行 availablePackageCount 为整托总箱数。搜索命中任一成员仍返回整托完整组成;普通箱件候选为空数组。
items: {$ref: '#/components/schemas/SmartLoadingCandidateGroupMember'}
SmartLoadingCandidateGroupMember:
type: object
required: [accountId, inboundId, orderId, orderNo, inboundCode, customerName, availablePackageCount]
properties:
accountId: {type: string, pattern: '^[1-9][0-9]*$'}
inboundId: {type: string, pattern: '^[1-9][0-9]*$'}
orderId: {type: string, pattern: '^[1-9][0-9]*$'}
orderNo: {type: string}
inboundCode: {type: string}
customerName: {type: string}
availablePackageCount: {type: integer, minimum: 0}
orderStatusSnapshot: {type: string, nullable: true}
expectedArrivalAt: {type: string, format: date-time, nullable: true}
SmartLoadingWorkbenchContainerPageEnvelope:
type: object
required: [code, message, data]
properties:
code: {type: string, example: '200'}
message: {type: string}
data:
type: object
required: [records, page, size, total, pages]
properties:
records: {type: array, items: {$ref: '#/components/schemas/SmartLoadingWorkbenchContainer'}}
page: {type: string, pattern: '^[1-9][0-9]*$'}
size: {type: string, pattern: '^[1-9][0-9]*$'}
total: {type: string, pattern: '^[0-9]+$'}
pages: {type: string, pattern: '^[0-9]+$'}
SmartLoadingWorkbenchContainer:
type: object
required: [bookingId, cabinetNo, warehouseId, warehouseName, channelGroupCode,
containerType, capacityCbm, maxWeightKg, planStatus, version]
properties:
bookingId: {type: string, pattern: '^[1-9][0-9]*$', description: containerBookingId 技术关联}
cabinetNo: {type: string, description: 稳定柜次业务号}
containerNo: {type: string, nullable: true, description: 真实集装箱号,允许在装柜前后补}
warehouseId: {type: string, pattern: '^[1-9][0-9]*$'}
warehouseName: {type: string}
channelGroupCode: {type: string, enum: [MATSON_CLX, MATSON_MAX, EXX, HEDE, OA_LA, OA_CHICAGO, OA_HOUSTON, OA_SAVANNAH, OA_NEW_YORK_TRUCK], description: 智能装柜匹配使用的计划渠道分组}
channelCode: {type: string, nullable: true, description: 关联真实订舱后冻结的实际物流渠道编码}
channelName: {type: string, nullable: true, description: 关联真实订舱后冻结的实际物流渠道名称}
containerType: {type: string}
capacityCbm: {type: number, nullable: true, description: 柜型基础容积;装柜上限按正式规则计算}
maxWeightKg: {type: number, nullable: true, description: 柜型基础载重;装柜上限按正式规则计算}
planId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true}
planNo: {type: string, nullable: true}
planStatus: {type: string, enum: [WAIT_LOADING, EDITING, LOADING]}
version: {type: integer, minimum: 0, description: 柜次版本}
SmartLoadingPlan:
type: object
required: [id, planNo, status, bookingId, version, canAssign, canEdit, finalCompletionStatus, coLoadGroups, palletMembers, items]
properties:
id: {type: string}
planNo: {type: string, pattern: '^LP[0-9]{12}$', example: LP202608180001, description: 预装与确认装柜清单共用的稳定编号}
status: {type: string, enum: [EDITING, LOADING, COMPLETED]}
bookingId: {type: string}
containerNo: {type: string, nullable: true}
voyageNo: {type: string, nullable: true}
version: {type: integer, minimum: 0, description: planVersion,写请求使用此值}
canAssign: {type: boolean}
canEdit: {type: boolean}
blockedReason: {type: string, nullable: true}
finalCompletionStatus: {type: string, enum: [NOT_STARTED, IN_PROGRESS, COMPLETED], description: IN_PROGRESS 表示 final complete 门禁尚未通过;增量新增 PENDING item 会保持或恢复此值,COMPLETED 后 canAssign/canEdit 均为 false}
pdaTaskId: {type: string, nullable: true}
pdaTaskStatus: {type: string, nullable: true, enum: [LOADING, COMPLETED], description: LOADING task 在增量后保持原 taskId;COMPLETED 永久拒绝增量}
pdaTaskVersion: {type: integer, minimum: 0, nullable: true, description: 服务端同步后最新 taskVersion;Admin 写操作不提交该值}
coLoadGroups:
type: array
description: 当前计划内同柜不可拆组的完整冻结快照;随计划一次返回,调用方不得按 inboundId 扇出重建
items: {$ref: '#/components/schemas/SmartLoadingPlanCoLoadGroup'}
palletMembers:
type: array
description: 当前计划内每个整托按入仓码汇总的实际装柜箱数;用于一托一行时展示完整组成
items: {$ref: '#/components/schemas/SmartLoadingPlanPalletMembers'}
items:
type: array
items: {$ref: '#/components/schemas/SmartLoadingPlanItem'}
SmartLoadingPlanCoLoadGroup:
type: object
required: [groupId, groupNo, lockedPlanId, memberOrderCount, inboundFragmentCount, fullPackageCount, memberInboundIds]
properties:
groupId: {type: string, pattern: '^[1-9][0-9]*$'}
groupNo: {type: string, minLength: 1}
lockedPlanId: {type: string, pattern: '^[1-9][0-9]*$'}
memberOrderCount: {type: integer, minimum: 1, description: 组内去重订单数}
inboundFragmentCount: {type: integer, minimum: 1, description: 组内去重当前有效入仓片段数}
fullPackageCount: {type: integer, minimum: 1, description: 全部成员冻结满箱数之和}
memberInboundIds:
type: array
minItems: 1
uniqueItems: true
items: {type: string, pattern: '^[1-9][0-9]*$'}
SmartLoadingPlanPalletMembers:
type: object
required: [palletId, members]
properties:
palletId: {type: string, pattern: '^[1-9][0-9]*$'}
members:
type: array
minItems: 1
items: {$ref: '#/components/schemas/SmartLoadingCandidateGroupMember'}
SmartLoadingPlanItem:
type: object
required: [id, packageCount, totalPackageCount, remainingPackageCount, version, pickedPackageCount, minPackageCount, canAdjust, canRemove]
properties:
id: {type: string}
inboundId: {type: string}
inboundDetailId: {type: string}
orderNo: {type: string, nullable: true}
inboundCode: {type: string, nullable: true}
customerName: {type: string, nullable: true}
customerRemark: {type: string, nullable: true, readOnly: true, description: 来源为订单 customerRemark}
internalRemark: {type: string, nullable: true, description: 内部备注;预装阶段可修改}
warehouseRemark: {type: string, nullable: true, description: 仓库人员逐条维护,可在 EDITING/LOADING 修改}
customerServiceRemark: {type: string, nullable: true, description: 客服备注;预装阶段可修改}
packageCount: {type: integer, minimum: 1}
totalPackageCount: {type: integer, minimum: 1, description: 当前入仓明细可在计划内分配的总箱数,包含已用与未用箱数}
remainingPackageCount: {type: integer, minimum: 0, description: 当前入仓明细尚未分配到本计划的箱数}
version: {type: integer, minimum: 0, description: itemVersion,调整/删除写请求使用此值}
pickedPackageCount: {type: integer, minimum: 0}
minPackageCount: {type: integer, minimum: 1}
canAdjust: {type: boolean}
canRemove: {type: boolean}
ContainerDocumentAttachRequest:
type: object
required: [fileId, expectedVersion]
properties:
fileId: {type: string, pattern: '^[1-9][0-9]*$'}
expectedVersion: {type: integer, minimum: 0}
operationReason: {type: string, maxLength: 500, nullable: true}
ContainerDocumentCompleteRequest:
type: object
required: [expectedVersion]
properties:
expectedVersion: {type: integer, minimum: 0}
operationReason: {type: string, maxLength: 500, nullable: true}
ContainerDocumentUploadRequest:
type: object
required: [file, expectedVersion]
additionalProperties: false
properties:
file: {type: string, format: binary, description: 用户直接选择的清关资料}
expectedVersion: {type: integer, minimum: 0, description: 当前文档乐观锁版本,首次上传为 0}
operationReason: {type: string, maxLength: 500, nullable: true}
ContainerPickupCodeRequest:
type: object
required: [pickupCode, expectedVersion]
properties:
pickupCode: {type: string, pattern: '^[0-9]{1,64}$'}
expectedVersion: {type: integer, minimum: 0}
MerchantInboundBillingEnvelope:
type: object
properties:
code: {type: string, example: '200'}
message: {type: string}
data:
type: object
properties:
inbound: {type: object, description: 入库单详情}
measurementSummary: {type: object, description: 测量汇总}
measurementItems: {type: array, items: {type: object}}
weightResults: {type: array, items: {type: object}}
measurementImages: {type: array, items: {type: object}}
weightImages: {type: array, items: {type: object}}
billingBasis: {type: object, description: 计费依据}
latestFee: {type: object, nullable: true, description: 兼容保留的最新计费快照}
publishedFeeDetail:
allOf:
- {$ref: '#/components/schemas/PublishedFreightFeeDetail'}
nullable: true
description: 后台与客户共用的已发布FBA头程运费应收明细
PublishedFreightFeeDetail:
type: object
description: 审核发布后绑定入库单的FBA头程运费应收明细
properties:
id: {type: integer, format: int64, description: 入库费用明细ID}
inboundId: {type: integer, format: int64}
inboundCode: {type: string}
sourceFeeId: {type: integer, format: int64, description: 来源计费快照ID}
sourceFeeVersion: {type: integer}
sourceFeeNo: {type: string}
direction: {type: string, enum: [RECEIVABLE]}
businessDate: {type: string, format: date}
customerId: {type: integer, format: int64}
customerName: {type: string}
invoiceTitle: {type: string, nullable: true}
channelCode: {type: string, nullable: true}
channelName: {type: string, nullable: true}
destinationCode: {type: string, nullable: true}
destinationName: {type: string, nullable: true}
packageCount: {type: integer, nullable: true}
actualGrossWeightKg: {type: number, format: double, nullable: true}
actualVolumeCbm: {type: number, format: double, nullable: true}
volumeWeightKg: {type: number, format: double, nullable: true}
chargeableWeightKg: {type: number, format: double, nullable: true}
chargeableVolumeCbm: {type: number, format: double, nullable: true}
chargeableQuantity: {type: number, format: double}
chargeUnit: {type: string, enum: [KG, CBM]}
feeTypeName: {type: string, example: FBA头程运费}
unitPrice: {type: number, format: double}
currency: {type: string, example: CNY}
amount: {type: number, format: double, description: 客户应收金额}
reviewStatus: {type: string, enum: [APPROVED]}
publicationStatus: {type: string, enum: [PUBLISHED]}
publishedAt: {type: string, format: date-time}
inboundedAt: {type: string, format: date-time, nullable: true}
InboundOrderPageEnvelope:
type: object
properties:
code: {type: string, example: '200'}
message: {type: string}
data: {$ref: '#/components/schemas/InboundOrderPage'}
InboundOrderPage:
type: object
properties:
records:
type: array
items: {$ref: '#/components/schemas/InboundOrderSummary'}
page: {type: integer, minimum: 1}
size: {type: integer, minimum: 1}
total: {type: integer, format: int64, minimum: 0}
pages: {type: integer, format: int64, minimum: 0}
InboundOrderSummary:
type: object
required: [id, tenantId]
properties:
id: {type: string, pattern: '^[1-9][0-9]*$'}
tenantId: {type: string, pattern: '^[1-9][0-9]*$', description: 记录所属客户 ID;字段名为历史兼容,用于详情和处理接口的客户隔离}
orderId: {type: string, nullable: true}
orderNo: {type: string, nullable: true}
inboundCode: {type: string, nullable: true}
processStatus: {type: string}
customerId: {type: string, nullable: true}
companyId: {type: string, nullable: true}
taxMode: {type: string, nullable: true, description: 订单报关方式快照}
pricingTaxMode: {type: string, enum: [TAX_INCLUDED, TAX_EXCLUDED], nullable: true, description: 下单时选择的报价包税维度快照}
expectedArrivalAt: {type: string, format: date-time, nullable: true}
customerName: {type: string, nullable: true}
companyName: {type: string, nullable: true}
warehouseId: {type: string, nullable: true}
warehouseName: {type: string, nullable: true}
deliveryWarehouseId: {type: string, nullable: true}
deliveryWarehouseName: {type: string, nullable: true}
businessType: {type: string, nullable: true}
fulfillmentType: {type: string, enum: [STANDARD, ONE_CLICK_DROPSHIP], nullable: true}
channelCode: {type: string, nullable: true}
channelName: {type: string, nullable: true}
containerMode: {type: string, nullable: true}
customsInspection: {type: boolean, nullable: true}
destinationType: {type: string, nullable: true}
destinationWarehouseId: {type: string, nullable: true}
destinationCode: {type: string, nullable: true}
destinationName: {type: string, nullable: true}
totalPackageCount: {type: integer, nullable: true}
actualGrossWeightKg: {type: number, nullable: true}
actualNetWeightKg: {type: number, nullable: true}
actualVolumeCbm: {type: number, nullable: true}
volumeWeightKg: {type: number, nullable: true}
chargeableWeightKg: {type: number, nullable: true}
chargeableVolumeCbm: {type: number, nullable: true}
palletCount: {type: integer, nullable: true}
locationCodes: {type: string, nullable: true}
measureCompletedAt: {type: string, format: date-time, nullable: true}
inboundedAt: {type: string, format: date-time, nullable: true}
expressCompanyName: {type: string, nullable: true}
expressTrackingNo: {type: string, nullable: true}
createdAt: {type: string, format: date-time, nullable: true}
updatedAt: {type: string, format: date-time, nullable: true}
InboundMeasurementCallbackRequest:
type: object
required: [eventNo, externalDetailNo, warehouseCode, inboundCode, inboundDetailId, deviceCode, measuredAt, boxSpecification, packageCount, lengthCm, widthCm, heightCm]
properties:
eventNo: {type: string, maxLength: 128, pattern: '^[A-Za-z0-9._:-]+$', example: M202608010001}
externalDetailNo: {type: string, maxLength: 128, pattern: '^[A-Za-z0-9._:-]+$', example: BOX-20260801-0001}
warehouseCode: {type: string, maxLength: 50, example: CN-YW-01}
inboundCode: {type: string, maxLength: 40, example: ZBYHK2608140001}
inboundDetailId: {type: string, example: '190000000000000001', description: 柏悦订单货物明细ID}
deviceCode: {type: string, maxLength: 64, example: DEVICE-01}
measuredAt: {type: string, format: date-time, example: '2026-08-01T10:30:00+08:00'}
boxSpecification: {type: string, maxLength: 64, example: '40x30x47cm'}
lengthCm: {type: number, exclusiveMinimum: true, minimum: 0, example: 50.20}
widthCm: {type: number, exclusiveMinimum: true, minimum: 0, example: 40.10}
heightCm: {type: number, exclusiveMinimum: true, minimum: 0, example: 30.00}
packageCount: {type: integer, minimum: 1, maximum: 1000000, example: 50}
remark: {type: string, maxLength: 500, nullable: true}
InboundMeasurementEventResponse:
type: object
properties:
eventNo: {type: string}
inboundCode: {type: string}
inboundDetailId: {type: string}
measurementId: {type: string}
measurementItemId: {type: string}
imageFileId: {type: string}
accepted: {type: boolean}
status: {type: string, enum: [RECEIVED]}
receivedAt: {type: string, format: date-time}
AssignRequest:
type: object
required: [assigneeId, assigneeName]
properties:
assigneeId: {type: integer, format: int64}
assigneeName: {type: string, maxLength: 64}
reason: {type: string, maxLength: 500}
ContainerSimulationCreateRequest:
type: object
required: [channelGroupCode, warehouseId, containerType, capacityCbm, maxWeightKg]
properties:
channelGroupCode: {type: string, maxLength: 64, enum: [MATSON_CLX, MATSON_MAX, EXX, HEDE, OA_LA, OA_CHICAGO, OA_HOUSTON, OA_SAVANNAH, OA_NEW_YORK_TRUCK], description: 智能装柜使用的九类计划渠道分组}
warehouseId: {type: integer, format: int64, minimum: 1}
containerType: {type: string, enum: [40GP, 40HQ, 45HQ], default: 40HQ, description: 与订舱共用的平台统一柜型}
capacityCbm: {type: number, enum: [58, 68, 86], description: 统一实装上限;40GP=58、40HQ=68、45HQ=86}
maxWeightKg: {type: number, enum: [19500], description: 统一货重上限}
ContainerOceanBookingLinkRequest:
type: object
required: [oceanBookingId, requirementId, expectedVersion]
properties:
oceanBookingId: {type: integer, format: int64, minimum: 1, description: RELEASED订舱ID}
requirementId: {type: integer, format: int64, minimum: 1, description: 未满配的订舱柜型需求ID}
containerNo: {type: string, nullable: true, maxLength: 64, description: 可选;港口提柜后可由拖车链另行原子补录。非空时服务端移除格式空白、转大写并校验ISO 6346结构、设备类别、校验位和同一订舱内唯一性}
expectedVersion: {type: integer, minimum: 0}
ContainerFeeAdjustRequest:
type: object
additionalProperties: false
required: [expectedSourceVersion, businessDate, amount]
properties:
expectedSourceVersion: {type: integer, minimum: 1}
businessDate: {type: string, format: date}
amount: {type: number, minimum: 0}
FinanceFeeSourceSnapshot:
type: object
description: Finance 消费的版本化费用来源快照;supplierCategory 为空表示仅约束供应商 ACTIVE,非空才约束明确类别。
required: [tenantId, sourceType, feeId, feeVersion, customerId, customerName, feeItemName, direction, businessDate, currency, totalAmount, reviewStatus, publicationStatus, sourceHash, snapshotVersion]
properties:
tenantId: {type: integer, format: int64}
sourceType: {type: string, enum: [INBOUND_FEE, CONTAINER_FEE]}
feeId: {type: integer, format: int64}
feeVersion: {type: integer, minimum: 1}
inboundId: {type: integer, format: int64, nullable: true}
inboundCode: {type: string, nullable: true}
orderId: {type: integer, format: int64, nullable: true}
containerId: {type: integer, format: int64, nullable: true, description: CONTAINER_FEE时固定为真实containerBookingId}
containerBookingId: {type: integer, format: int64, nullable: true, description: 真实containerBookingId;CONTAINER_FEE时与containerId一致}
containerNo: {type: string, nullable: true}
customerId: {type: integer, format: int64}
customerName: {type: string}
supplierId: {type: integer, format: int64, nullable: true}
supplierName: {type: string, nullable: true}
supplierCategory: {type: string, enum: [BOOKING, CUSTOMS, TRUCKING, CERTIFICATE], nullable: true, description: PAYABLE供应商类别约束;为空时仅要求供应商ACTIVE}
settlementMode: {type: string, enum: [ON_ACCOUNT, DIRECT_PAID], nullable: true, description: 仅PAYABLE;ON_ACCOUNT可进入AP,DIRECT_PAID仅计成本且禁止进入AP}
paidAt: {type: string, format: date-time, nullable: true}
paymentMethod: {type: string, enum: [ONLINE, BANK_TRANSFER, CASH, OTHER], nullable: true}
paymentReferenceNo: {type: string, nullable: true}
paymentVoucherFileIds: {type: array, nullable: true, items: {type: integer, format: int64}}
feeItemId: {type: integer, format: int64, nullable: true}
feeItemCode: {type: string, nullable: true}
feeItemName: {type: string}
direction: {type: string, enum: [RECEIVABLE, PAYABLE]}
businessDate: {type: string, format: date}
currency: {type: string, enum: [CNY]}
totalAmount: {type: number, minimum: 0}
reviewStatus: {type: string, enum: [APPROVED]}
publicationStatus: {type: string, enum: [PUBLISHED]}
publishedAt: {type: string, format: date-time, nullable: true}
chargeableQuantity: {type: number, nullable: true}
chargeUnit: {type: string, nullable: true}
actualGrossWeightKg: {type: number, nullable: true}
actualVolumeCbm: {type: number, nullable: true}
sourceHash: {type: string}
snapshotVersion: {type: integer, minimum: 1}
FinanceFeeSourceVoidCommand:
type: object
additionalProperties: false
required: [sourceType, sourceFeeId, sourceVersion, customerId, operatorId, operatorName, reason]
properties:
sourceType: {type: string, enum: [INBOUND_FEE, CONTAINER_FEE]}
sourceFeeId: {type: integer, format: int64, minimum: 1}
sourceVersion: {type: integer, minimum: 1}
customerId: {type: integer, format: int64, minimum: 1}
inboundId: {type: integer, format: int64, minimum: 1, nullable: true, description: INBOUND_FEE必填且containerId必须为空}
containerId: {type: integer, format: int64, minimum: 1, nullable: true, description: CONTAINER_FEE必填且inboundId必须为空}
operatorId: {type: integer, format: int64, minimum: 1}
operatorName: {type: string, minLength: 1, maxLength: 64}
reason: {type: string, minLength: 1, maxLength: 500}
FinanceFeeSourceCommandResult:
type: object
required: [sourceType, sourceFeeId, sourceVersion, status, replayed]
properties:
sourceType: {type: string, enum: [INBOUND_FEE, CONTAINER_FEE]}
sourceFeeId: {type: integer, format: int64}
sourceVersion: {type: integer}
status: {type: string, enum: [VOIDED]}
replayed: {type: boolean}