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/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/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: 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 权限;仅国外工作台货柜 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}/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}/warehouse-remark: patch: summary: 修改装柜明细仓库备注 description: >- 需要 platform:firstleg:preload:edit 权限。EDITING/LOADING 可修改或清空 warehouseRemark; COMPLETED、计划/明细版本冲突返回 A0409 且事务零写入,写入历史且与 PDA final complete 使用同一并发门禁。 成功响应中的 version 是递增后的 planVersion,items[].version 是递增后的 itemVersion;调用方同时使用 canEdit、items[].canAdjust/canRemove 与自身权限决定操作可用性。数量调整或动态增量不会覆盖已有 warehouseRemark。 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/SmartLoadingWarehouseRemarkRequest'}}} responses: '200': {description: 成功或业务失败,data 为最新 SmartLoadingPlan} /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: '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,并按该次测量数据尽力生成 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,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_SPLIT 后,费用在 LOADING、LOADED、DELIVERED 仍持续可见;始终要求 measureReviewStatus=APPROVED、feeStatus=SENT 且存在 PUBLISHED 入库运费明细。latestFee.customerConfirmationStatus 表示客户是否已确认当前费用版本。 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: 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_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} 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 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_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} 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, 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] 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} 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, 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} 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} 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_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} 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_PICKUP, RECORD_EMPTY_RETURN, SEND_PICKUP_EMAIL]}} ContainerBooking: type: object required: [id, bookingNo, cabinetNo, sourceType, recordStatus, warehouseId, warehouseName, containerType, capacityCbm, maxWeightKg, planStatus, exceptionActive, destinationClearanceDocumentStatus, customsDeclarationDocumentStatus, deliveryOrderDocumentStatus, version] properties: id: {type: string, pattern: '^[1-9][0-9]*$'} planId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true, description: 关联智能装柜计划ID;未创建计划时为空} planNo: {type: string, nullable: true, pattern: '^LP-[0-9]{6}-[0-9]{4}$', example: LP-260818-0001, description: 预装与确认装柜清单共用的稳定编号;未创建计划时为空} bookingNo: {type: string, pattern: '^CB-[0-9]{6}-[0-9]{4}$', example: CB-260818-0001, description: 平台内部货柜登记号} containerNo: {type: string, maxLength: 64, nullable: true} cabinetNo: {type: string, pattern: '^CAB-[0-9]{6}-[0-9]{4}$', example: CAB-260818-0001, 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 时为空} 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, enum: [20GP, 40GP, 40HC, 40NR, 45HC], description: 平台固定柜型} 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, description: 必须等于柜型固定容量} maxWeightKg: {type: number, exclusiveMinimum: true, minimum: 0, 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: [20GP, 40GP, 40HC, 40NR, 45HC], description: 平台固定柜型} 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, description: 必须等于柜型固定容量} maxWeightKg: {type: number, exclusiveMinimum: true, minimum: 0, 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} 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} SmartLoadingWarehouseRemarkRequest: type: object required: [expectedPlanVersion, expectedItemVersion, operationId] properties: warehouseRemark: {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]{6}-[0-9]{4}$', 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: 同柜组聚合行的完整成员;普通候选为空数组 items: 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, bookingNo, cabinetNo, warehouseId, warehouseName, channelCode, channelName, containerType, capacityCbm, maxWeightKg, planStatus, version] properties: bookingId: {type: string, pattern: '^[1-9][0-9]*$', description: containerBookingId 技术关联} bookingNo: {type: string, description: 货柜登记业务号} cabinetNo: {type: string, description: 稳定柜次业务号} containerNo: {type: string, nullable: true, description: 真实集装箱号,允许在装柜前后补} warehouseId: {type: string, pattern: '^[1-9][0-9]*$'} warehouseName: {type: string} channelCode: {type: string} channelName: {type: string} 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, items] properties: id: {type: string} planNo: {type: string, pattern: '^LP-[0-9]{6}-[0-9]{4}$', example: LP-260818-0001, 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'} 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]*$'} 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, readOnly: true, description: 来源为订单最新内部备注,不使用 cargoRemark} warehouseRemark: {type: string, nullable: true, description: 仓库人员逐条维护,可在 EDITING/LOADING 修改} 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: [channelCode, warehouseId, containerType, capacityCbm, maxWeightKg] properties: channelCode: {type: string, maxLength: 64, description: 当前 ACTIVE 价格簿中的真实物流渠道} warehouseId: {type: integer, format: int64, minimum: 1} containerType: {type: string, enum: [20GP, 40GP, 40HC, 40NR, 45HC], description: 与订舱共用的平台固定柜型} capacityCbm: {type: number, minimum: 0, exclusiveMinimum: true, description: 必须等于柜型固定容量} maxWeightKg: {type: number, minimum: 0, exclusiveMinimum: true, 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}