feat(appointments): support scoped receiving and stable trip continuation

This commit is contained in:
2026-10-16 15:43:04 +08:00
parent 4e2ea89403
commit 30f48bd926
84 changed files with 4879 additions and 136 deletions
@@ -0,0 +1,49 @@
-- V13 receiving coverage and pending changes; baseline only, no test data migration.
CREATE TABLE IF NOT EXISTS ll_fba_receiving_agreement (
agreement_key VARCHAR(64) NOT NULL COMMENT '收货预约独立业务键',
version INT NOT NULL COMMENT '预约覆盖范围与确认资料版本',
status VARCHAR(24) NOT NULL COMMENT '有效、取消或已替代状态',
destination_key VARCHAR(128) NOT NULL COMMENT '权威目的仓关联键',
confirmation_no VARCHAR(128) NULL COMMENT '当前有效外部约号,失效后清空以释放覆盖',
snapshot_json LONGTEXT NOT NULL COMMENT '客户逐来源覆盖、确认时区及仓库依据快照',
PRIMARY KEY (agreement_key),
UNIQUE KEY uk_fba_receiving_confirmation (destination_key, confirmation_no)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='独立于送货批次的收货预约';
CREATE TABLE IF NOT EXISTS ll_fba_receiving_member (
agreement_key VARCHAR(64) NOT NULL COMMENT '所属收货预约业务键',
batch_key VARCHAR(128) NOT NULL COMMENT '稳定送货批次键',
customer_id VARCHAR(128) NOT NULL COMMENT '货物所属客户标识',
active_ref VARCHAR(260) NULL COMMENT '有效批次与客户唯一引用,退出后清空且历史保留',
PRIMARY KEY (agreement_key,batch_key,customer_id),
UNIQUE KEY uk_fba_receiving_active_member (active_ref),
KEY idx_fba_receiving_batch (batch_key,customer_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='收货预约当前覆盖关联及退出历史';
CREATE TABLE IF NOT EXISTS ll_fba_receiving_change (
change_key VARCHAR(64) NOT NULL COMMENT '客户预约变化业务键',
version INT NOT NULL COMMENT '变化续办版本',
status VARCHAR(24) NOT NULL COMMENT '待仓库确认、已应用或已撤回状态',
batch_key VARCHAR(128) NOT NULL COMMENT '受影响原送货批次键',
customer_id VARCHAR(128) NOT NULL COMMENT '本次变化所属客户',
snapshot_json LONGTEXT NOT NULL COMMENT '原覆盖快照、逐来源拟保留量、负责人及跟进资料',
result_json LONGTEXT NULL COMMENT '确认后的实际批次去向及逐步骤结果',
active_ref VARCHAR(260) NULL COMMENT '同批同客户唯一未解决变化引用',
PRIMARY KEY (change_key),
UNIQUE KEY uk_fba_receiving_pending (active_ref),
KEY idx_fba_receiving_pending_batch (batch_key,status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='保留原安排且阻止误发车的客户变化';
CREATE TABLE IF NOT EXISTS ll_fba_receiving_revision (
agreement_key VARCHAR(64) NOT NULL COMMENT '收货预约业务键',
version INT NOT NULL COMMENT '不可变覆盖与确认版本',
snapshot_json LONGTEXT NOT NULL COMMENT '该版本完整客户覆盖、确认时段及回复依据',
PRIMARY KEY (agreement_key,version)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='收货预约覆盖与确认不可变历史';
CREATE TABLE IF NOT EXISTS ll_fba_receiving_plan (
batch_key VARCHAR(128) NOT NULL COMMENT '稳定送货批次键',
customer_id VARCHAR(128) NOT NULL COMMENT '计划所属客户标识',
snapshot_json LONGTEXT NOT NULL COMMENT '本客户未确认计划、目标窗口及业务时区,不含有效预约确认',
PRIMARY KEY (batch_key,customer_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='按批次及客户保存的未确认收货计划';
@@ -1649,6 +1649,57 @@ CREATE TABLE IF NOT EXISTS ll_appointment_followup (
CONSTRAINT chk_appointment_followup_stage CHECK (stage IN ('DRAYAGE_CONTACT','TERMINAL_APPOINTMENT','WAREHOUSE_RECEIVING','FBA_RECEIVING'))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='真实在途货源的预约筹划联系记录,追加留痕';
-- V13 receiving coverage and pending changes; baseline only, no test data migration.
CREATE TABLE IF NOT EXISTS ll_fba_receiving_agreement (
agreement_key VARCHAR(64) NOT NULL COMMENT '收货预约独立业务键',
version INT NOT NULL COMMENT '预约覆盖范围与确认资料版本',
status VARCHAR(24) NOT NULL COMMENT '有效、取消或已替代状态',
destination_key VARCHAR(128) NOT NULL COMMENT '权威目的仓关联键',
confirmation_no VARCHAR(128) NULL COMMENT '当前有效外部约号,失效后清空以释放覆盖',
snapshot_json LONGTEXT NOT NULL COMMENT '客户逐来源覆盖、确认时区及仓库依据快照',
PRIMARY KEY (agreement_key),
UNIQUE KEY uk_fba_receiving_confirmation (destination_key, confirmation_no)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='独立于送货批次的收货预约';
CREATE TABLE IF NOT EXISTS ll_fba_receiving_member (
agreement_key VARCHAR(64) NOT NULL COMMENT '所属收货预约业务键',
batch_key VARCHAR(128) NOT NULL COMMENT '稳定送货批次键',
customer_id VARCHAR(128) NOT NULL COMMENT '货物所属客户标识',
active_ref VARCHAR(260) NULL COMMENT '有效批次与客户唯一引用,退出后清空且历史保留',
PRIMARY KEY (agreement_key,batch_key,customer_id),
UNIQUE KEY uk_fba_receiving_active_member (active_ref),
KEY idx_fba_receiving_batch (batch_key,customer_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='收货预约当前覆盖关联及退出历史';
CREATE TABLE IF NOT EXISTS ll_fba_receiving_change (
change_key VARCHAR(64) NOT NULL COMMENT '客户预约变化业务键',
version INT NOT NULL COMMENT '变化续办版本',
status VARCHAR(24) NOT NULL COMMENT '待仓库确认、已应用或已撤回状态',
batch_key VARCHAR(128) NOT NULL COMMENT '受影响原送货批次键',
customer_id VARCHAR(128) NOT NULL COMMENT '本次变化所属客户',
snapshot_json LONGTEXT NOT NULL COMMENT '原覆盖快照、逐来源拟保留量、负责人及跟进资料',
result_json LONGTEXT NULL COMMENT '确认后的实际批次去向及逐步骤结果',
active_ref VARCHAR(260) NULL COMMENT '同批同客户唯一未解决变化引用',
PRIMARY KEY (change_key),
UNIQUE KEY uk_fba_receiving_pending (active_ref),
KEY idx_fba_receiving_pending_batch (batch_key,status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='保留原安排且阻止误发车的客户变化';
CREATE TABLE IF NOT EXISTS ll_fba_receiving_revision (
agreement_key VARCHAR(64) NOT NULL COMMENT '收货预约业务键',
version INT NOT NULL COMMENT '不可变覆盖与确认版本',
snapshot_json LONGTEXT NOT NULL COMMENT '该版本完整客户覆盖、确认时段及回复依据',
PRIMARY KEY (agreement_key,version)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='收货预约覆盖与确认不可变历史';
CREATE TABLE IF NOT EXISTS ll_fba_receiving_plan (
batch_key VARCHAR(128) NOT NULL COMMENT '稳定送货批次键',
customer_id VARCHAR(128) NOT NULL COMMENT '计划所属客户标识',
snapshot_json LONGTEXT NOT NULL COMMENT '本客户未确认计划、目标窗口及业务时区,不含有效预约确认',
PRIMARY KEY (batch_key,customer_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='按批次及客户保存的未确认收货计划';
CREATE TABLE IF NOT EXISTS ll_inbound_fba_appointment (
id BIGINT NOT NULL COMMENT '主键ID',
appointment_no VARCHAR(64) NOT NULL COMMENT '系统预约业务单号,不是外部约号',
@@ -1675,7 +1726,6 @@ CREATE TABLE IF NOT EXISTS ll_inbound_fba_appointment (
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '更新UTC时间',
PRIMARY KEY (id),
UNIQUE KEY uk_ll_fba_appointment_no (appointment_no),
UNIQUE KEY uk_ll_fba_external_confirmation (fba_warehouse_code,confirmation_no),
KEY idx_ll_fba_appointment_list (appointment_at,appointment_status,fba_warehouse_code),
KEY idx_ll_fba_appointment_planned (planned_at,appointment_status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='FBA预约安排与正式确认唯一主记录';
@@ -1692,7 +1742,7 @@ CREATE TABLE IF NOT EXISTS ll_inbound_fba_appointment_item (
package_count INT NULL COMMENT '本批分配箱数,未知保持空;同一原来源总量守恒',
cargo_verification_version INT NULL COMMENT '采用的预约货物核实版本,未核实时为空',
shipment_references_json LONGTEXT NULL COMMENT '本次采用的货件或追踪号核实快照',
active TINYINT(1) NOT NULL DEFAULT 1 COMMENT '取消或失败后释放货源占用',
active TINYINT(1) NOT NULL DEFAULT 1 COMMENT '当前批次数量分配有效;取消、未约成和完成均保留,仅替代时释放',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建UTC时间',
PRIMARY KEY (id),
UNIQUE KEY uk_ll_fba_item_source (appointment_id,source_key),
@@ -12,7 +12,11 @@ paths:
summary: 按不可变批次键读取分批资料和操作条件
description: >-
仅平台,需预约列表及尾程订单列表权限。batchKey为FBA_APPOINTMENT加内部不可变主键,仅供关联,不作为展示编号。
返回appointment原快照、sources当前逐来源可用于重新分配的本批数量、allowedActions和blockReasons。
返回appointment原快照、sources当前逐来源可用于重新分配的本批数量、allowedActions、blockReasons及currentBatches全部当前去向。
currentBatches沿所有替代及客户后送分支读取到当前批次,按稳定键去重,并按原客户、来源、目的地排除无关分支。
originalSourceRefs是本批当前及已移出货物的客户/原来源/目的地范围,消费者用它过滤全部当前去向,不能用当前items漏掉已全部移出的客户;它不代表可重新分配的货量。
每项为当前批次完整权威快照(合并后可能含其他来源),不是旧批次逐箱归属拆账;消费者按所查看的客户和来源展示对应明细,不把整批合计当成本客户数量。
取消和未约成仍保留批次分配及当前去向;缺失关系、循环或超过1000节点明确报错,不返回截断成功或空货量。
原批次箱数未知且已独立核实总量时,本批数量由核实总量减其他活动批次分配量计算;不修改旧快照。
已替代、已确认或关联排车时不开放分批合并。原来源或核实事实读取失败明确报错,不以空列表冒充无货。
allowedActions表示业务资格,前端与FBA预约写权限取交集;实际写入仍在事务内重验。
@@ -31,6 +35,20 @@ paths:
type: object
properties:
appointment: {$ref: './fba-appointment-calendar-v1.yaml#/components/schemas/Appointment'}
currentBatches:
type: array
description: 全部当前批次快照,包含未约成、取消后仍需继续安排的批次,不仅返回第一个替代批次
items: {$ref: './fba-appointment-calendar-v1.yaml#/components/schemas/Appointment'}
originalSourceRefs:
type: array
description: 本批当前及历史移出来源,仅供当前去向过滤,不授予重新分配资格
items:
type: object
required: [customerId, sourceKey, destinationKey]
properties:
customerId: {type: string}
sourceKey: {type: string}
destinationKey: {type: string}
sources:
type: array
items:
@@ -59,7 +77,7 @@ paths:
仅平台,需platform:appointment:list、platform:overseas-warehouse:last-mile-order:list及platform:overseas-warehouse:inbound-order:fba-appointment。
originals为一条且batches多条表示分批;originals多条且batches一条表示合并,其他组合拒绝。
原批次必须同起运仓、同目的仓,尚未正式确认、未被替代且没有有效关联排车。
先按业务号有序锁原预约,再锁原BOOKING/订单;版本、来源资格、客户归属及数量均在锁内重新核对。
先按稳定批次键有序锁原预约,再锁原BOOKING/订单;版本、来源资格、客户归属及数量均在锁内重新核对。
按每个稳定来源分别比较调整前后总量,不能只比较合计箱数或跨客户挪量;逐来源预期版本及核实版本必须与最新资料一致。
原批次箱数未知时可采用刚保存的独立核实总量,无需先登记预约确认;仍未知则拒绝。
全部旧明细释放、新批次和来源明细建立、替代关系及幂等结果在同一事务内;任一失败全部回滚。
@@ -83,7 +83,7 @@ paths:
仅平台;同时需要platform:appointment:list、platform:overseas-warehouse:last-mile-order:list及platform:overseas-warehouse:inbound-order:fba-appointment。
与入仓明细入口共用同一FBA预约聚合;系统生成AP单号,不创建入仓计划、库存或车次。
PENDING允许日期、时段、外部约号及箱数暂缺。SUCCESS必须有权威目的仓时区、真实货件材料、确定箱数及外部约号和确认时段。
实际客户、起运仓、目的仓及原BOOKING由服务端核对;锁原来源后按剩余未分配箱数建立新安排,分批总量不能超过独立核实或原来源总量。取消只释放本批数量并保留历史。
实际客户、起运仓、目的仓及原BOOKING由服务端核对;锁原来源后按剩余未分配箱数建立新安排,分批总量不能超过独立核实或原来源总量。取消仅释放有效预约覆盖,仍需履约的本批分配保留,不重新作为整票余量;历史保留。
命令与主单、明细同事务;同键同操作人同内容重试返回原快照,不受后来编辑影响。异内容或来源占用冲突拒绝。
requestBody:
required: true
@@ -0,0 +1,852 @@
openapi: 3.0.3
info:
title: V13 收货预约覆盖、客户变化及重新预约
version: 1.0.0
description: 稳定批次与有效收货预约身份分离;Agreement.version覆盖资料和成员范围。新共约必须新agreementKey,不以约号相等推断成员。同一次移出为Lastleg本地事务:transport锁序车次→排车→出库/PDA→批次,任一步失败全部回滚,不返回批次部分成功。成功Result持久化且同键重放返回原快照;异内容冲突。后续约仓/配车独立续办使用成功batchKey,不重建已成功货物。WAITING保存原安排和数量,只有CONFIRM按原scope/source/verification及batch版本复验后应用;WITHDRAW保留原安排。实际发车另由原Dispatch/Fleet检查pending及有效收货范围。未知量、版本冲突、来源不可用均拒绝,不伪造0项。
负责人提交ownerId并由平台人员目录校验;后送及再次分批继承权威负责人和跟进资料。重约使用按客户核对的executionVersion,不让同批无关已完成客户阻断未完成员;已完成成员不得再次预约。WITHDRAW只撤回未生效变化,不改原货物/车辆,运输开始或版本变化不阻断撤回;仍须变化版本与幂等校验。
paths:
/api/platform/v1/last-leg/appointment-receiving/batches/{batchKey}:
get:
summary: 读取本批真实收货覆盖和待确认变化
description: '平台身份 tenantId=0。Required authority: platform:appointment:list'
security:
- bearerAuth: []
responses:
'200':
description: ApiResponse:成功code="200";业务错误按统一封装返回,不把HTTP 200当业务成功。
content:
application/json:
schema:
type: object
properties:
code: &id001
type: string
message: *id001
data:
$ref: '#/components/schemas/Context'
parameters:
- name: batchKey
in: path
required: true
schema: *id001
/api/platform/v1/last-leg/appointment-receiving/agreements/{agreementKey}:
get:
summary: 读取当前范围和取消组重约候选及排除原因
description: '平台身份 tenantId=0。Required authority: platform:appointment:list'
security:
- bearerAuth: []
responses:
'200':
description: ApiResponse:成功code="200";业务错误按统一封装返回,不把HTTP 200当业务成功。
content:
application/json:
schema:
type: object
properties:
code: *id001
message: *id001
data:
$ref: '#/components/schemas/GroupContext'
parameters:
- name: agreementKey
in: path
required: true
schema: *id001
/api/platform/v1/last-leg/appointment-receiving/changes:
post:
summary: 保存客户待确认变化,保留原安排并阻发
description: '平台身份 tenantId=0。Required authority: platform:overseas-warehouse:inbound-order:fba-appointment AND platform:appointment:delete'
security:
- bearerAuth: []
responses:
'200':
description: ApiResponse:成功code="200";业务错误按统一封装返回,不把HTTP 200当业务成功。
content:
application/json:
schema:
type: object
properties:
code: *id001
message: *id001
data:
$ref: '#/components/schemas/Result'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Propose'
/api/platform/v1/last-leg/appointment-receiving/changes/{changeKey}/resolve:
post:
summary: 确认并原子移出,或撤回本次变化
description: '平台身份 tenantId=0。Required authority: platform:overseas-warehouse:inbound-order:fba-appointment AND platform:appointment:delete'
security:
- bearerAuth: []
responses:
'200':
description: ApiResponse:成功code="200";业务错误按统一封装返回,不把HTTP 200当业务成功。
content:
application/json:
schema:
type: object
properties:
code: *id001
message: *id001
data:
$ref: '#/components/schemas/Result'
parameters:
- name: changeKey
in: path
required: true
schema: *id001
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Resolve'
/api/platform/v1/last-leg/appointment-receiving/bookings:
post:
summary: 沿用现有批次创建共同或独立收货预约
description: '平台身份 tenantId=0。Required authority: platform:overseas-warehouse:inbound-order:fba-appointment'
security:
- bearerAuth: []
responses:
'200':
description: ApiResponse:成功code="200";业务错误按统一封装返回,不把HTTP 200当业务成功。
content:
application/json:
schema:
type: object
properties:
code: *id001
message: *id001
data:
$ref: '#/components/schemas/Result'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Book'
/api/platform/v1/last-leg/appointment-receiving/agreements/{agreementKey}/reschedule:
post:
summary: 整份当前收货预约改期
description: '平台身份 tenantId=0。Required authority: platform:overseas-warehouse:inbound-order:fba-appointment'
security:
- bearerAuth: []
responses:
'200':
description: ApiResponse:成功code="200";业务错误按统一封装返回,不把HTTP 200当业务成功。
content:
application/json:
schema:
type: object
properties:
code: *id001
message: *id001
data:
$ref: '#/components/schemas/Result'
parameters:
- name: agreementKey
in: path
required: true
schema: *id001
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GroupChange'
/api/platform/v1/last-leg/appointment-receiving/agreements/{agreementKey}/cancel:
post:
summary: 整份当前收货预约取消并保留货量及车辆
description: '平台身份 tenantId=0。Required authority: platform:appointment:delete'
security:
- bearerAuth: []
responses:
'200':
description: ApiResponse:成功code="200";业务错误按统一封装返回,不把HTTP 200当业务成功。
content:
application/json:
schema:
type: object
properties:
code: *id001
message: *id001
data:
$ref: '#/components/schemas/Result'
parameters:
- name: agreementKey
in: path
required: true
schema: *id001
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GroupChange'
/api/platform/v1/last-leg/appointment-receiving/plans:
post:
summary: 只保存本客户未确认的送仓计划,不改变其他客户正式确认
description: '平台身份 tenantId=0。Required authority: platform:overseas-warehouse:inbound-order:fba-appointment。已正式确认、待变化确认或已执行客户不可直接改计划;清目标仍保留需求。计划不创建预约确认、不重新占量。'
security:
- bearerAuth: []
responses:
'200':
description: ApiResponse:成功code="200";业务错误按统一封装返回,不把HTTP 200当业务成功。
content:
application/json:
schema:
type: object
properties:
code: &id002
type: string
message: *id002
data:
$ref: '#/components/schemas/Result'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Plan'
/api/platform/v1/last-leg/appointment-receiving/execution-scope:
post:
summary: 按实际选择的客户批次只读核对执行资格和提交版本
description: '平台身份 tenantId=0。Required authority: platform:appointment:list。只读,不保存计划或预约。跨批次取消组只选部分成员时先读取本范围执行版本,前端重新确认选择;写入仍独立校验批次及取消组版本。'
security:
- bearerAuth: []
responses:
'200':
description: ApiResponse:成功code="200";业务错误按统一封装返回,不把HTTP 200当业务成功。
content:
application/json:
schema:
type: object
properties:
code: &id003
type: string
message: *id003
data:
$ref: '#/components/schemas/ExecutionScope'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ExecutionQuery'
/api/platform/v1/last-leg/appointment-receiving/cargo-refresh:
post:
summary: 明确核对并采用本客户最新货物资料
description: '平台身份 tenantId=0。Required authority: platform:overseas-warehouse:inbound-order:fba-appointment。仅未确认且未执行客户可采用,清晰核对本批量、最新核实总量及货件号;来源目的地或客户改变不得采用,不修改原订单。'
security:
- bearerAuth: []
responses:
'200':
description: ApiResponse:成功code="200";业务错误按统一封装返回,不把HTTP 200当业务成功。
content:
application/json:
schema:
type: object
properties:
code: &id004
type: string
message: *id004
data:
$ref: '#/components/schemas/Result'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/RefreshCargo'
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
schemas:
Source:
type: object
properties:
sourceKey: *id001
destinationKey: *id001
packageCount:
type: integer
minimum: 1
sourceVersion: *id001
verificationVersion:
type: integer
nullable: true
inboundCode:
type: string
nullable: true
description: 原来源入仓业务号;未知显示—
required:
- sourceKey
- destinationKey
- packageCount
- sourceVersion
- verificationVersion
Member:
type: object
properties:
batchKey: *id001
appointmentNo: *id001
batchVersion: &id005
type: integer
minimum: 0
customerId: *id001
sources:
type: array
items:
$ref: '#/components/schemas/Source'
customerName:
type: string
nullable: true
description: 原订单真实客户名称;未知显示—,不用内部标识回退
required:
- batchKey
- appointmentNo
- batchVersion
- customerId
- sources
Details:
type: object
properties:
plannedDate: &id006
type: string
format: date
nullable: true
plannedAt:
type: string
format: date-time
nullable: true
plannedEndAt:
type: string
format: date-time
nullable: true
confirmationNo: *id001
appointmentAt:
type: string
format: date-time
appointmentEndAt:
type: string
format: date-time
nullable: true
appointmentStatus:
type: string
enum:
- SUCCESS
appointmentRemark:
type: string
nullable: true
startOffset:
type: string
nullable: true
endOffset:
type: string
nullable: true
required:
- confirmationNo
- appointmentAt
- appointmentStatus
Agreement:
type: object
properties:
agreementKey: *id001
version: *id005
status:
type: string
enum:
- ACTIVE
- CANCELLED
- SUPERSEDED
destinationKey: *id001
details:
$ref: '#/components/schemas/Details'
timezone: *id001
members:
type: array
items:
$ref: '#/components/schemas/Member'
warehouseEvidence: *id001
required:
- agreementKey
- version
- status
- destinationKey
- details
- timezone
- members
- warehouseEvidence
Vehicle:
type: object
properties:
tripNo:
type: string
nullable: true
version:
type: integer
nullable: true
dispatchNo: *id001
customerId: *id001
batchKey: *id001
status: *id001
packageCount: *id005
required:
- tripNo
- version
- dispatchNo
- customerId
- batchKey
- status
- packageCount
Transport:
type: object
properties:
version: *id001
vehicles:
type: array
items:
$ref: '#/components/schemas/Vehicle'
blockReasons:
type: array
items: *id001
required:
- version
- vehicles
- blockReasons
Selection:
type: object
properties:
batchKey: *id001
batchVersion: *id005
customerId: *id001
required:
- batchKey
- batchVersion
- customerId
Quantity:
type: object
properties:
sourceKey: *id001
destinationKey: *id001
retainedPackages: *id005
expectedSourceVersion: *id001
expectedVerificationVersion:
type: integer
nullable: true
required:
- sourceKey
- destinationKey
- retainedPackages
- expectedSourceVersion
- expectedVerificationVersion
ChangeIntent:
type: object
properties:
batchKey: *id001
batchVersion: *id005
customerId: *id001
quantities:
type: array
items:
$ref: '#/components/schemas/Quantity'
laterDate: *id006
nextFollowupDate: *id006
reason: *id001
transportVersion: *id001
ownerId: *id001
required:
- batchKey
- batchVersion
- customerId
- quantities
- ownerId
- reason
- transportVersion
Pending:
type: object
properties:
changeKey: *id001
version: *id005
status:
type: string
enum:
- WAITING
- APPLIED
- WITHDRAWN
intent:
$ref: '#/components/schemas/ChangeIntent'
originalMembers:
type: array
items:
$ref: '#/components/schemas/Member'
originalAgreements:
type: array
items:
$ref: '#/components/schemas/Agreement'
followup:
$ref: '#/components/schemas/Followup'
required:
- changeKey
- version
- status
- intent
- originalMembers
- originalAgreements
- followup
Context:
type: object
properties:
batch:
$ref: ./fba-appointment-calendar-v1.yaml#/components/schemas/Appointment
agreements:
type: array
items:
$ref: '#/components/schemas/Agreement'
pendingChanges:
type: array
items:
$ref: '#/components/schemas/Pending'
transport:
$ref: '#/components/schemas/Transport'
allowedActions:
type: array
items:
type: string
enum:
- BOOK_RECEIVING
- PROPOSE_CUSTOMER_CHANGE
blockReasons:
type: array
items: *id001
executionScope:
$ref: '#/components/schemas/ExecutionScope'
plans:
type: array
items:
$ref: '#/components/schemas/CustomerPlan'
required:
- batch
- agreements
- pendingChanges
- transport
- allowedActions
- blockReasons
- executionScope
- plans
Excluded:
type: object
properties:
member:
$ref: '#/components/schemas/Member'
reason: *id001
currentAgreementKey:
type: string
nullable: true
required:
- member
- reason
- currentAgreementKey
GroupContext:
type: object
properties:
agreement:
$ref: '#/components/schemas/Agreement'
eligibleMembers:
type: array
items:
$ref: '#/components/schemas/Member'
excludedMembers:
type: array
items:
$ref: '#/components/schemas/Excluded'
transport:
$ref: '#/components/schemas/Transport'
executionScope:
$ref: '#/components/schemas/ExecutionScope'
required:
- agreement
- eligibleMembers
- excludedMembers
- transport
- executionScope
Propose:
type: object
properties:
idempotencyKey: *id001
intent:
$ref: '#/components/schemas/ChangeIntent'
required:
- idempotencyKey
- intent
Resolve:
type: object
properties:
idempotencyKey: *id001
version: *id005
decision:
type: string
enum:
- CONFIRM
- WITHDRAW
warehouseEvidence:
type: string
nullable: true
transportVersion: *id001
required:
- idempotencyKey
- version
- decision
- transportVersion
Booking:
type: object
properties:
members:
type: array
items:
$ref: '#/components/schemas/Selection'
details:
$ref: '#/components/schemas/Details'
warehouseEvidence: *id001
required:
- members
- details
- warehouseEvidence
Book:
type: object
properties:
idempotencyKey: *id001
bookings:
type: array
items:
$ref: '#/components/schemas/Booking'
cancelledAgreementKey:
type: string
nullable: true
cancelledAgreementVersion:
type: integer
nullable: true
executionVersion: *id001
required:
- idempotencyKey
- bookings
- executionVersion
GroupChange:
type: object
properties:
idempotencyKey: *id001
version: *id005
action:
type: string
enum:
- RESCHEDULE
- CANCEL
details:
$ref: '#/components/schemas/Details'
nullable: true
warehouseEvidence: *id001
transportVersion: *id001
required:
- idempotencyKey
- version
- action
- warehouseEvidence
- transportVersion
Step:
type: object
properties:
step: *id001
status:
type: string
enum:
- SUCCESS
targetKey: *id001
message: *id001
required:
- step
- status
- targetKey
- message
Result:
type: object
properties:
changeKey:
type: string
nullable: true
status:
type: string
enum:
- WAITING
- APPLIED
- WITHDRAWN
- UNCHANGED
batches:
type: array
items:
$ref: ./fba-appointment-calendar-v1.yaml#/components/schemas/Appointment
agreements:
type: array
items:
$ref: '#/components/schemas/Agreement'
steps:
type: array
items:
$ref: '#/components/schemas/Step'
nextActions:
type: array
items:
type: string
description: 主要下一步及原车辆业务返回的实际后续动作,沿Result中的稳定batchKey继续,不重复创建货物
required:
- changeKey
- status
- batches
- agreements
- steps
- nextActions
Followup:
type: object
properties:
ownerId:
type: string
ownerName:
type: string
nextFollowupDate:
type: string
format: date
nullable: true
required:
- ownerId
- ownerName
- nextFollowupDate
ExecutionMember:
type: object
properties:
batchKey:
type: string
customerId:
type: string
required:
- batchKey
- customerId
ExecutionEligibility:
type: object
properties:
member:
$ref: '#/components/schemas/ExecutionMember'
completed:
type: boolean
canRebook:
type: boolean
reason:
type: string
nullable: true
required:
- member
- completed
- canRebook
- reason
ExecutionScope:
type: object
description: 原业务按客户、批次及逐票履约事实核对;version绑定涉及批次的完整执行事实,资格仅针对所选客户。
properties:
version:
type: string
members:
type: array
items:
$ref: '#/components/schemas/ExecutionEligibility'
required:
- version
- members
CustomerPlan:
type: object
required:
- batchKey
- customerId
- details
properties:
batchKey:
type: string
customerId:
type: string
details:
$ref: ./fba-appointment-calendar-v1.yaml#/components/schemas/AppointmentDetails
timezone:
type: string
nullable: true
description: 按稳定批次及客户保存的未确认收货计划;仅PENDING/FAILED,目标可空,不包含有效确认或货物分配。
Plan:
type: object
required:
- idempotencyKey
- member
- details
- executionVersion
properties:
idempotencyKey:
type: string
maxLength: 64
member:
$ref: '#/components/schemas/Selection'
details:
$ref: ./fba-appointment-calendar-v1.yaml#/components/schemas/AppointmentDetails
executionVersion:
type: string
description: 仅PENDING/FAILED,confirmationNo、appointmentAt、appointmentEndAt必须为空;FAILED必须有原因。服务端校验客户实际执行资格、批次及来源/核实版本,同键幂等。 非空目标须目的仓有效IANA时区;计划时刻按DST与跨日规则校验。此命令中details.startOffset/endOffset对应计划窗口;仅日期或目标为空不携带offset。
ExecutionQuery:
type: object
required:
- members
properties:
members:
type: array
minItems: 1
maxItems: 200
uniqueItems: true
items:
$ref: '#/components/schemas/ExecutionMember'
CargoVersion:
type: object
required:
- sourceKey
- destinationKey
- expectedSourceVersion
properties:
sourceKey:
type: string
destinationKey:
type: string
expectedSourceVersion:
type: string
expectedVerificationVersion:
type: integer
minimum: 1
nullable: true
RefreshCargo:
type: object
required:
- idempotencyKey
- member
- sources
- executionVersion
properties:
idempotencyKey:
type: string
maxLength: 64
member:
$ref: '#/components/schemas/Selection'
sources:
type: array
minItems: 1
maxItems: 100
items:
$ref: '#/components/schemas/CargoVersion'
executionVersion:
type: string
description: 操作者先读取并核对本客户各原来源最新核实资料,再显式采用。只更新原批次本客户明细的源/核实版本和货件快照,原分配数量、来源身份和其他客户确认保持。已确认、待变化确认、已执行、源/核实版本变化或数量不守恒拒绝;同键幂等,不自动采用。
@@ -7,6 +7,43 @@ security:
-
bearerAuth: []
paths:
/api/platform/v1/last-leg/appointment-work/items/resolve:
get:
operationId: appointmentWorkResolveBatch
summary: 按当前权威批次精确进入送仓事项
description: "要求platform:appointment:list及原来源读取资格。batchKey使用原业务返回的完整稳定键;customerId来自所选客户货源。精确匹配返回detail,未传客户且存在多个客户时detail为空并返回candidates,必须选择后重新解析;不得选首项或回退已替代旧批次。需求关系未同步返回409,未生成返回404。"
parameters:
- name: batchKey
in: query
required: true
schema:
type: string
pattern: '^(FBA_APPOINTMENT|DISPATCH):[1-9][0-9]*$'
- name: customerId
in: query
required: false
schema: {type: string, minLength: 1}
responses:
200:
description: data为客户送仓精确解析结果或可见客户候选
content:
application/json:
schema:
type: object
required: [code, data]
properties:
code: {type: string}
message: {type: string, nullable: true}
data:
$ref: '#/components/schemas/BatchWorkResolution'
400:
description: 批次键无效
403:
description: 缺少平台或原来源读取资格
404:
description: 当前批次未生成活动送仓事项
409:
description: 需求关系尚未同步或存在不唯一的事项关系
/api/platform/v1/last-leg/appointment-work/calendar:
get:
operationId: "appointmentWorkCalendar"
@@ -874,12 +911,14 @@ components:
nextAction:
"$ref": "#/components/schemas/Action"
nullable: true
description: "按当前权限和白名单目标引导;已确认送仓预约可指向本批车辆安排或本车复核,不代表授权发车。取消预约沿原批次重新预约,不恢复旧确认。"
blockReasons:
type: "array"
items:
type: "string"
missingFields:
type: "array"
description: "未完成事项分别提示负责人、下次跟进日期和作业日期等缺口;跟进日期不能作为作业日历日期。"
items:
type: "string"
Review:
@@ -954,6 +993,25 @@ components:
type: "string"
summary:
type: "string"
BatchWorkResolution:
type: object
required: [batchKey, candidates]
properties:
batchKey: {type: string}
customerId: {type: string, nullable: true}
detail:
nullable: true
allOf:
- $ref: '#/components/schemas/WorkDetail'
candidates:
type: array
items:
type: object
required: [customerId, workItemKey]
properties:
customerId: {type: string}
workItemKey: {type: string}
batchNo: {type: string, nullable: true}
WorkDetail:
type: "object"
additionalProperties: false
@@ -1237,6 +1295,7 @@ components:
maxLength: 1000
RESOLVE_REVIEWRequest:
type: "object"
description: "须匹配当前影响版本,并核对本事项及关联安排的最新权威影响;需求关系未同步或出现新影响时拒绝清除。车次货物成员变化仅要求相关客户及车辆核对,未变化客户预约不连带复核;车辆、司机、时间变化影响当前关联预约。复核不恢复取消的确认、不修改原预约和车辆,也不制造新的业务影响。"
additionalProperties: false
required:
- "command"
@@ -33,8 +33,8 @@ paths:
required: true
schema: {type: string}
delete:
summary: 取消未关联有效排车的预约并释放占用
description: '平台专用,权限platform:appointment:delete。校验版本后保留主单、确认事实及明细历史,设置CANCELLED并释放货源占用;不删除客户货物或回退库存。已有关联有效排车时拒绝。取消原因必填,独立保存于取消命令历史,不覆盖原业务备注;按系统单号、版本、操作者及原因校验幂等,异内容拒绝。'
summary: 取消未关联有效排车的预约覆盖并保留本批货量
description: '平台专用,权限platform:appointment:delete。校验版本后设置CANCELLED,清除当前有效计划日期、确认号及时段;旧计划与确认保存在不可变取消命令历史。货物分配保持有效,不能再次从整票创建相同货量;不删除客户货物或回退库存。已有关联有效排车时拒绝。取消原因必填,独立保存于取消命令历史,不覆盖原业务备注;按系统单号、版本、操作者及原因校验幂等,异内容拒绝。'
requestBody:
required: true
content:
@@ -56,7 +56,7 @@ paths:
'403': {description: 无读取权限}
put:
summary: 按版本更新预约
description: '权限:platform:overseas-warehouse:inbound-order:fba-appointment。平台限定,版本及持久化幂等校验;已有有效排车时先处理运输安排。未约成必须写原因并保留原确认时间。禁止通过更新设置CANCELLED,取消必须调用DELETE并通过独立取消权限、实际原因和历史规则。恢复时重新核对来源、目的仓和占用;不能直接将SUCCESS退回PENDING。'
description: '权限:platform:overseas-warehouse:inbound-order:fba-appointment。平台限定,版本及持久化幂等校验;已有有效排车时先处理运输安排。未约成必须写原因,清除无效确认,但保留本批货物分配。禁止通过更新设置CANCELLED,取消必须调用DELETE并通过独立取消权限、实际原因和历史规则。重新安排时重新核对来源、目的仓和占用,沿原批次数量继续;不能直接将SUCCESS退回PENDING。'
requestBody:
required: true
content:
@@ -358,6 +358,14 @@ components:
properties:
trip: {$ref: '#/components/schemas/Trip'}
dispatches: {type: array, items: {$ref: '#/components/schemas/DispatchBinding'}}
previousDispatches:
type: array
description: 原绑定历史中已不在当前绑定的批次、客户及来源引用,按最新有效证据去重;历史数量不作为当前装载或可分配数量
items: {$ref: '#/components/schemas/PreviousDispatch'}
appointmentHistoryUnavailableReason:
type: string
nullable: true
description: 原绑定历史缺少引用证据或超过1000条读取上限时的明确原因;仅历史引用不可完整使用,当前车次和绑定仍可读
loadingReview: {$ref: '#/components/schemas/ReviewState'}
driverQualification:
type: object
@@ -681,13 +689,24 @@ components:
recordVersion: {type: integer, format: int64, nullable: true, description: 本次审核所核对的车次版本}
DispatchBinding:
type: object
required: [appointmentBatches]
properties:
appointmentBatches: {type: array, items: {$ref: 'overseas-business-v1.yaml#/components/schemas/DispatchBatchReference'}}
dispatchNo: {type: string}
customerId: {type: string, description: 排车单自身客户归属,由服务端解析}
packageCount: {type: integer, description: 关联时待发运箱数,不是实物托位数}
boundBy: {type: string}
boundAt: {type: string, format: date-time}
review: {$ref: '#/components/schemas/ReviewState'}
PreviousDispatch:
type: object
required: [dispatchNo, customerId, recordVersion, recordedAt, appointmentBatches]
properties:
dispatchNo: {type: string}
customerId: {type: string}
recordVersion: {type: integer, format: int64, description: 原绑定历史的车次版本}
recordedAt: {type: string, format: date-time}
appointmentBatches: {type: array, items: {$ref: 'overseas-business-v1.yaml#/components/schemas/DispatchBatchReference'}}
Envelope:
type: object
properties:
@@ -3048,6 +3048,7 @@ components:
properties: { reason: { type: string, minLength: 1, maxLength: 1000 } }
DispatchResponse:
type: object
required: [appointmentBatches]
properties:
id: { type: string }
dispatchNo: { type: string }
@@ -3060,6 +3061,10 @@ components:
overseasWarehouseId: { type: string }
overseasWarehouseName: { type: string }
departAt: { type: string, format: date-time, nullable: true }
appointmentBatches:
type: array
description: 当前排车分配中的全部原批次、客户及来源引用;无预约分配时为空,不通过旧预约号推导
items: { $ref: '#/components/schemas/DispatchBatchReference' }
fbaAppointmentNo: { type: string, nullable: true }
fbaAppointmentStatus: { type: string }
vehicleAppointmentStatus: { type: string }
@@ -3082,6 +3087,21 @@ components:
type: array
description: 仅详情接口返回的BOL打印聚合行;分页接口返回空数组,避免列表查询放大
items: { $ref: '#/components/schemas/DispatchBolLine' }
DispatchBatchSource:
type: object
required: [sourceKey, destinationKey, packageCount]
properties:
sourceKey: { type: string }
destinationKey: { type: string }
packageCount: { type: integer, minimum: 1 }
DispatchBatchReference:
type: object
required: [batchKey, batchNo, customerId, sources]
properties:
batchKey: { type: string, description: 原分配持久化的稳定批次键 }
batchNo: { type: string, nullable: true, description: 原批次业务号;缺失不以内码代替 }
customerId: { type: string }
sources: { type: array, items: { $ref: '#/components/schemas/DispatchBatchSource' } }
DispatchWorkflow:
type: object
required: [tripNo, dispatchReview, loadingReview]