1237 lines
62 KiB
YAML
1237 lines
62 KiB
YAML
openapi: 3.0.3
|
||
info:
|
||
title: 柏悦头程履约 API
|
||
description: 业务成功和失败均使用 HTTP 200;仅响应体 code 为字符串 "200" 时表示成功,其他 code 表示失败。
|
||
version: 1.1.0
|
||
security:
|
||
- bearerAuth: []
|
||
paths:
|
||
/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: 幂等补偿完成}
|
||
/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: 无编辑权限}
|
||
/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/unified-orders/query:
|
||
post:
|
||
summary: 按统一订单条件分页查询履约摘要(Order 内部)
|
||
description: >-
|
||
mainStatus 接受六态产品状态;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:
|
||
get:
|
||
summary: 分页查询平台货柜
|
||
description: 需要 platform:firstleg:container:list 权限;货柜为平台级数据,不传 tenant/account
|
||
parameters:
|
||
- {$ref: '#/components/parameters/Page'}
|
||
- {$ref: '#/components/parameters/Size'}
|
||
- {name: keyword, in: query, schema: {type: string, maxLength: 128}}
|
||
- {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, schema: {type: string, enum: [WAIT_LOADING, EDITING, LOADING, COMPLETED]}}
|
||
responses:
|
||
'200':
|
||
description: 成功或业务失败,按响应体 code 判断
|
||
content:
|
||
application/json:
|
||
schema: {$ref: '#/components/schemas/ContainerBookingPageEnvelope'}
|
||
'403': {description: 无货柜查询权限}
|
||
post:
|
||
summary: 新增平台货柜
|
||
description: 需要 platform:firstleg:container:create 权限;新增后聚合状态为 WAIT_LOADING(待装柜)
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema: {$ref: '#/components/schemas/ContainerSaveRequest'}
|
||
responses:
|
||
'200': {description: 成功或重复号、参数校验等业务失败}
|
||
'403': {description: 无新增按钮权限}
|
||
/api/platform/v1/containers/{id}:
|
||
get:
|
||
summary: 查询平台货柜详情
|
||
description: 需要 platform:firstleg:container:list 权限
|
||
parameters:
|
||
- {$ref: '#/components/parameters/ContainerBookingId'}
|
||
responses:
|
||
'200': {description: 成功或货柜不存在}
|
||
'403': {description: 无货柜查询权限}
|
||
put:
|
||
summary: 草稿阶段完整编辑货柜
|
||
description: 需要 platform:firstleg:container:edit 权限;仅待装柜或计划为 EDITING(预装柜中)时允许
|
||
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}/transport:
|
||
patch:
|
||
summary: 修改集装箱号和航次
|
||
description: 需要 platform:firstleg:container:edit 权限;LOADING 仅开放此白名单,COMPLETED 全部只读
|
||
parameters:
|
||
- {$ref: '#/components/parameters/ContainerBookingId'}
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema: {$ref: '#/components/schemas/ContainerTransportUpdateRequest'}
|
||
responses:
|
||
'200': {description: 成功或状态、版本、重复号冲突}
|
||
'403': {description: 无货柜编辑权限}
|
||
/api/platform/v1/containers/{id}/clearance:
|
||
get:
|
||
summary: 查询货柜目的港清关资料
|
||
description: 需要 platform:firstleg:customs:manage 权限
|
||
parameters: [{$ref: '#/components/parameters/ContainerBookingId'}]
|
||
responses: {'200': {description: 成功或货柜不存在}}
|
||
/api/platform/v1/containers/{id}/clearance/document:
|
||
post:
|
||
summary: 上传或替换货柜目的港清关资料
|
||
description: 需要 platform:firstleg:customs:manage 权限,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/upload:
|
||
post:
|
||
summary: 直接选择文件上传或替换货柜目的港清关资料
|
||
description: Firstleg 使用内部服务令牌上传 File,浏览器不得传递 fileId 或内部令牌;旧 JSON document 接口仅兼容存量调用。
|
||
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:customs:manage 权限
|
||
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/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: 无智能装柜查询权限}
|
||
/openapi/v1/inbound-measurements:
|
||
post:
|
||
summary: 提交一条第三方箱规测量结果和一张图片
|
||
description: >-
|
||
data 中的 inboundCode 匹配入库单,inboundDetailId 必须匹配该入库单关联订单中的已有货物明细;
|
||
每次只保存一条箱规明细和一张图片,不审核、不计费、不入库,也不改变入库单状态。
|
||
首轮联调可由服务端配置 signature-required=false:此时只强制固定 X-App-Key 和
|
||
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: 'RK-2085911321565003778#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}
|
||
weight: {type: number, format: decimal, minimum: 0.001, nullable: true}
|
||
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/v1/first-leg/inbounds/{inboundId}/measurement/carton-scans:
|
||
post:
|
||
summary: 平台模拟单箱设备扫描
|
||
description: >-
|
||
需要 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}
|
||
weight: {type: number, format: double, minimum: 0.001, nullable: true}
|
||
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}
|
||
weight: {type: number, format: double, minimum: 0.001, nullable: true}
|
||
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-results/{resultId}/confirm:
|
||
post:
|
||
summary: 确认 OCR 重量
|
||
description: >-
|
||
需要 platform:firstleg:inbound:weight:confirm 权限;携带人工修改字段时还需要
|
||
platform:firstleg:inbound:weight:edit 权限。修改与确认在同一事务内完成,保留 OCR 原值,
|
||
分别写入 CORRECT 和 CONFIRM 修订记录,并重算所有已确认图片的实际总毛重。
|
||
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 判断}
|
||
'403': {description: 无确认权限,或修改重量时无编辑权限}
|
||
/api/platform/v1/first-leg/inbounds/{inboundId}/weight-results/{resultId}:
|
||
delete:
|
||
summary: 删除称重图片及重量结果
|
||
description: >-
|
||
需要 platform:firstleg:inbound:weight:edit 权限;仅允许在可编辑的测量状态删除。
|
||
删除已确认图片后重新汇总剩余已确认图片的实际总毛重,删除最后一张时总毛重恢复为空。
|
||
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 权限;客服审核通过后自动计费、发布费用给客户并完成入库,客户无需确认。
|
||
parameters:
|
||
- {name: inboundId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
|
||
- {name: Idempotency-Key, in: header, required: true, schema: {type: string}}
|
||
responses:
|
||
'200': {description: 成功或业务失败}
|
||
/api/platform/v1/inbounds/{inboundId}/measurements/reject:
|
||
post:
|
||
summary: 驳回测量
|
||
description: 需要 firstleg:inbound:measurement-review 权限;只退回测量数据修改,已确认托盘和库位占用保持不动。
|
||
parameters:
|
||
- {name: inboundId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
|
||
- {name: Idempotency-Key, in: header, required: true, schema: {type: string}}
|
||
responses:
|
||
'200': {description: 成功或业务失败}
|
||
/api/platform/v1/inbounds/{inboundId}/measurements/submit:
|
||
post:
|
||
summary: 提交测量完成
|
||
description: 测量提交后立即按总体积拆分普通托盘、分配并确认占用库位,再进入客服待审核;无普通空闲位时共享 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]*$'}}
|
||
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_SPLIT + APPROVED + CONFIRMED 的二期终态可见。
|
||
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/platform/v1/inbounds/{inboundId}/measurements/exception-release:
|
||
post:
|
||
summary: 测量异常放行
|
||
description: 需要 firstleg:inbound:exception-release 权限
|
||
parameters:
|
||
- {name: inboundId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
|
||
- {name: Idempotency-Key, in: header, required: true, schema: {type: string}}
|
||
responses:
|
||
'200': {description: 成功或业务失败}
|
||
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:
|
||
UnifiedMainStatus:
|
||
type: string
|
||
enum: [PENDING_REVIEW, WAIT_MEASURE, WAIT_SPLIT, LOADING, LOADED, DELIVERED]
|
||
description: 六态产品主状态;WAIT_SPLIT 为入库完成后的唯一待分柜状态
|
||
UnifiedInboundQuery:
|
||
type: object
|
||
properties:
|
||
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_SPLIT, LOADING, LOADED, DELIVERED]
|
||
nullable: true
|
||
description: WAIT_SPLIT 为唯一待分柜筛选值
|
||
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}
|
||
containerNo: {type: string, maxLength: 64, 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: 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}
|
||
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
|
||
properties:
|
||
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}
|
||
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_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}
|
||
channelCode: {type: string, nullable: true}
|
||
channelName: {type: string, nullable: true}
|
||
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}
|
||
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}
|
||
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}
|
||
loadingStatus: {type: string, nullable: true}
|
||
containerNo: {type: string, nullable: true}
|
||
cabinetNo: {type: string, nullable: true}
|
||
vesselName: {type: string, nullable: true}
|
||
voyageNo: {type: string, nullable: true}
|
||
sailingAt: {type: string, format: date-time, nullable: true}
|
||
portArrivalAt: {type: string, format: date-time, nullable: true}
|
||
expressTrackingNo: {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'}
|
||
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: 箱规长、宽、高三个方向分别使用的每侧加宽厘米数
|
||
example: 2.000
|
||
remark: {type: string, maxLength: 500, nullable: true}
|
||
version: {type: integer, minimum: 0, description: 乐观锁版本号}
|
||
CustomerDimensionConfigGroupResponse:
|
||
type: object
|
||
required: [tenantId, rules]
|
||
properties:
|
||
tenantId: {type: string, pattern: '^[1-9][0-9]*$'}
|
||
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]
|
||
properties:
|
||
tenantId: {type: string, pattern: '^[1-9][0-9]*$'}
|
||
operatorId: {type: string, pattern: '^[0-9]+$'}
|
||
initializationKey: {type: string, minLength: 1, maxLength: 128}
|
||
CustomerDimensionConfigInitializeResponse:
|
||
type: object
|
||
required: [configId, createdByThisInitialization]
|
||
properties:
|
||
configId: {type: string, pattern: '^[1-9][0-9]*$'}
|
||
createdByThisInitialization: {type: boolean}
|
||
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]
|
||
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: RK-2085308606829346818}
|
||
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}
|
||
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}
|
||
ContainerBookingPageEnvelope:
|
||
type: object
|
||
properties:
|
||
code: {type: string, example: '200'}
|
||
message: {type: string}
|
||
data:
|
||
type: object
|
||
properties:
|
||
records: {type: array, items: {$ref: '#/components/schemas/ContainerBooking'}}
|
||
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]+$'}
|
||
ContainerBooking:
|
||
type: object
|
||
required: [id, bookingNo, cabinetNo, warehouseId, warehouseName, containerType, planStatus, version]
|
||
properties:
|
||
id: {type: string, pattern: '^[1-9][0-9]*$'}
|
||
planId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true, description: 关联智能装柜计划ID;未创建计划时为空}
|
||
bookingNo: {type: string, maxLength: 40}
|
||
containerNo: {type: string, maxLength: 64, nullable: true}
|
||
cabinetNo: {type: string, maxLength: 64}
|
||
channelCode: {type: string, maxLength: 64, nullable: true, description: Missing legacy snapshots are blocked from loading until explicitly backfilled}
|
||
channelName: {type: string, maxLength: 128, nullable: true}
|
||
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, maxLength: 32}
|
||
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, exclusiveMinimum: true, minimum: 0, nullable: true}
|
||
maxWeightKg: {type: number, exclusiveMinimum: true, minimum: 0, nullable: true}
|
||
terminalTruckingCompany: {type: string, maxLength: 128, nullable: true}
|
||
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}
|
||
planStatus: {type: string, enum: [WAIT_LOADING, EDITING, LOADING, COMPLETED]}
|
||
version: {type: integer, minimum: 0}
|
||
ContainerSaveRequest:
|
||
type: object
|
||
required: [cabinetNo, warehouseId, warehouseName, containerType]
|
||
properties:
|
||
containerNo: {type: string, maxLength: 64, nullable: true}
|
||
cabinetNo: {type: string, maxLength: 64}
|
||
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, maxLength: 32}
|
||
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, exclusiveMinimum: true, minimum: 0, nullable: true}
|
||
maxWeightKg: {type: number, exclusiveMinimum: true, minimum: 0, nullable: true}
|
||
terminalTruckingCompany: {type: string, maxLength: 128, nullable: true}
|
||
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'}
|
||
ContainerTransportUpdateRequest:
|
||
type: object
|
||
required: [version, reason]
|
||
properties:
|
||
containerNo: {type: string, maxLength: 64, nullable: true, description: 真实集装箱号;PDA任务创建前可空,任务创建后允许替换但禁止清空}
|
||
voyageNo: {type: string, maxLength: 64, nullable: true}
|
||
version: {type: integer, minimum: 0}
|
||
reason: {type: string, maxLength: 500}
|
||
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}
|
||
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}
|
||
settlementIncluded: {type: boolean, example: 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: 下单时选择的报价包税维度快照}
|
||
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: RK202608010001}
|
||
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}
|
||
unitWeightKg: {type: number, exclusiveMinimum: true, minimum: 0, nullable: true, example: 20}
|
||
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}
|