feat(lastleg): connect appointment followups and fleet intake
This commit is contained in:
@@ -0,0 +1,230 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
title: 美国预约筹划货源
|
||||
version: 1.0.0
|
||||
description: 读取真实已开船头程货物,不要求预先创建入仓计划,不生成库存、车次或对外确认。
|
||||
security:
|
||||
- bearerAuth: []
|
||||
paths:
|
||||
/api/platform/v1/last-leg/appointment-planning/cargo:
|
||||
get:
|
||||
operationId: appointmentPlanningCargo
|
||||
summary: 分页读取美国FBA筹划货源
|
||||
description: >-
|
||||
仅平台身份;同时要求platform:appointment:list与platform:overseas-warehouse:last-mile-order:list。
|
||||
从公共仓库目录核对美国接仓点与美国FBA目的仓;目录失败返回错误,不冒充空结果。
|
||||
当前读取FIRST_LEG货物与已确认开船或更晚的实际船节点,未建计划可见;已有计划不重复计数。
|
||||
预计时间来自尾程订单保存的来源快照,不代表实时船司ETA;shippingObservedAt仅是实际节点观察时间。
|
||||
sourcePalletCount是头程预报托数,不是海外实测托位。其他货源由后续正式合同接入,不能从本接口推断已支持。
|
||||
parameters:
|
||||
- {name: page, in: query, schema: {type: integer, minimum: 1, default: 1}}
|
||||
- {name: size, in: query, schema: {type: integer, minimum: 1, maximum: 100, default: 20}}
|
||||
- {name: warehouseId, in: query, schema: {type: string}, description: 美国接仓点主档ID,仅用于关联}
|
||||
- {name: destination, in: query, schema: {type: string}, description: 美国FBA仓编码}
|
||||
- {name: keyword, in: query, schema: {type: string, maxLength: 128}, description: 入仓码、柜号或客户名称}
|
||||
responses:
|
||||
'200':
|
||||
description: 业务响应,必须核对code
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
code: {type: string}
|
||||
message: {type: string}
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
records: {type: array, items: {$ref: '#/components/schemas/Cargo'}}
|
||||
page: {type: integer}
|
||||
size: {type: integer}
|
||||
total: {type: integer}
|
||||
pages: {type: integer}
|
||||
'400': {description: 查询参数或美国范围无效}
|
||||
'403': {description: 无来源读取权限或非平台身份}
|
||||
'503': {description: 仓库目录暂不可用,不能证明美国货源范围}
|
||||
/api/platform/v1/last-leg/appointment-planning/sources/resolve:
|
||||
get:
|
||||
operationId: resolveAppointmentPlanningSource
|
||||
summary: 核对深链来源并读取预约覆盖
|
||||
description: >-
|
||||
仅平台;同时要求platform:appointment:list与platform:overseas-warehouse:last-mile-order:list。
|
||||
依据真实客户、货源与美国仓目录核对来源,URL参数不能授予预约资格。
|
||||
ORDER仅接受已开船头程FBA货;BOOKING保留原登记身份,确认承运后尚未生成入仓单也能跟进。
|
||||
此查询不建单、不确认预约。当前覆盖读取已有FBA预约,尚未生成货物时返回SOURCE_NOT_MATERIALIZED。
|
||||
parameters:
|
||||
- {name: sourceKey, in: query, required: true, schema: {type: string, maxLength: 160}, description: 'ORDER:<内部关联ID>或BOOKING:<登记号>,非用户展示编号'}
|
||||
- {name: customerId, in: query, required: true, schema: {type: string, maxLength: 128}}
|
||||
- {name: destinationKey, in: query, schema: {type: string}, description: 'FBA:<仓编码>,传入后必须与真实来源一致'}
|
||||
responses:
|
||||
'200':
|
||||
description: code=200时data包含已核实来源和预约覆盖
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
code: {type: string}
|
||||
message: {type: string}
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
source: {$ref: '#/components/schemas/PlanningSource'}
|
||||
coverage: {$ref: '#/components/schemas/Coverage'}
|
||||
'400': {description: 非美国FBA来源、尚未开船或目的地变化}
|
||||
'403': {description: 无读取权限或非平台身份}
|
||||
'404': {description: 客户与来源不匹配或来源不存在}
|
||||
'503': {description: 仓库目录不可用}
|
||||
/api/platform/v1/last-leg/appointment-planning/sources/{sourceKey}/follow-ups:
|
||||
parameters:
|
||||
- {name: sourceKey, in: path, required: true, schema: {type: string, maxLength: 160}, description: 'ORDER或BOOKING稳定来源键,路径须URL编码'}
|
||||
- {name: customerId, in: query, required: true, schema: {type: string, maxLength: 128}}
|
||||
get:
|
||||
summary: 分页读取分事项跟进历史与最新版本
|
||||
description: 仅平台;同时要求platform:appointment:list与platform:overseas-warehouse:last-mile-order:list。已有跟进历史在货物完成后仍可读取。
|
||||
parameters:
|
||||
- {name: page, in: query, schema: {type: integer, minimum: 1, default: 1}}
|
||||
- {name: size, in: query, schema: {type: integer, minimum: 1, maximum: 100, default: 20}}
|
||||
responses:
|
||||
'200':
|
||||
description: code=200时data含history分页和按stage排列的versions;createdAt为UTC时间点,followupDate为业务地点当地日期。
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
code: {type: string}
|
||||
message: {type: string}
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
history:
|
||||
type: object
|
||||
properties:
|
||||
records: {type: array, items: {$ref: '#/components/schemas/FollowupRecord'}}
|
||||
page: {type: integer}
|
||||
size: {type: integer}
|
||||
total: {type: integer}
|
||||
pages: {type: integer}
|
||||
versions: {type: object, additionalProperties: {type: integer, minimum: 0}, description: 四个事项各自的最新版本}
|
||||
'403': {description: 无读取权限或非平台身份}
|
||||
'404': {description: 无历史且来源不具备美国筹划资格}
|
||||
post:
|
||||
summary: 追加人工联系结果与下次跟进
|
||||
description: >-
|
||||
仅平台;除读取权限外要求platform:appointment:followup。
|
||||
跟进人来自登录主体,不接受客户端操作者ID。核实来源后按stage版本追加,以持久化唯一约束防止并发覆盖;幂等键持久化,同键同操作者同内容返回原记录,异内容拒绝。
|
||||
不要求已创建入仓计划、外部预约号或司机,不更新正式预约、库存和车次。设置followupDate时nextAction必填。
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [stage, expectedVersion, idempotencyKey, result]
|
||||
properties:
|
||||
stage: {type: string, enum: [DRAYAGE_CONTACT, TERMINAL_APPOINTMENT, WAREHOUSE_RECEIVING, FBA_RECEIVING]}
|
||||
expectedVersion: {type: integer, minimum: 0, description: 初次为0,后续取history.versions中对应事项版本}
|
||||
idempotencyKey: {type: string, maxLength: 64}
|
||||
contactedParty: {type: string, maxLength: 200, nullable: true}
|
||||
result: {type: string, minLength: 1, maxLength: 1000}
|
||||
nextAction: {type: string, maxLength: 500, nullable: true}
|
||||
followupDate: {type: string, format: date, nullable: true}
|
||||
responses:
|
||||
'200':
|
||||
description: data为原记录或新增记录
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
code: {type: string}
|
||||
message: {type: string}
|
||||
data: {$ref: '#/components/schemas/FollowupRecord'}
|
||||
'400': {description: 无效事项或缺少下一步安排}
|
||||
'403': {description: 无写权限或非平台身份}
|
||||
'404': {description: 来源不存在或不可筹划}
|
||||
'409': {description: 版本冲突或同键异内容}
|
||||
components:
|
||||
securitySchemes:
|
||||
bearerAuth: {type: http, scheme: bearer, bearerFormat: JWT}
|
||||
schemas:
|
||||
FollowupRecord:
|
||||
type: object
|
||||
properties:
|
||||
stage: {type: string, enum: [DRAYAGE_CONTACT, TERMINAL_APPOINTMENT, WAREHOUSE_RECEIVING, FBA_RECEIVING]}
|
||||
version: {type: integer, minimum: 1}
|
||||
contactedParty: {type: string, nullable: true}
|
||||
result: {type: string}
|
||||
nextAction: {type: string, nullable: true}
|
||||
followupDate: {type: string, format: date, nullable: true}
|
||||
operatorName: {type: string, nullable: true}
|
||||
createdAt: {type: string, format: date-time, description: UTC时间点}
|
||||
PlanningSource:
|
||||
type: object
|
||||
properties:
|
||||
sourceKey: {type: string}
|
||||
customerId: {type: string}
|
||||
orderId: {type: string, nullable: true}
|
||||
inboundCode: {type: string, nullable: true}
|
||||
bookingNo: {type: string, nullable: true}
|
||||
containerNo: {type: string, nullable: true}
|
||||
originWarehouseId: {type: string}
|
||||
originWarehouseName: {type: string}
|
||||
destinationKey: {type: string}
|
||||
destinationWarehouseCode: {type: string}
|
||||
packages: {type: integer, nullable: true, description: 未知数量保持空值,不能替换为0}
|
||||
sourceVersion: {type: string, nullable: true}
|
||||
canFollowup: {type: boolean}
|
||||
blockReasons: {type: array, items: {type: string}}
|
||||
Coverage:
|
||||
type: object
|
||||
properties:
|
||||
customerId: {type: string}
|
||||
sourceKey: {type: string}
|
||||
destinationKey: {type: string}
|
||||
status: {type: string, enum: [SOURCE_NOT_FOUND, SOURCE_NOT_MATERIALIZED, SOURCE_NOT_READY, DESTINATION_MISMATCH, UNASSIGNED, PARTIAL, PENDING, CONFIRMED, REVIEW_REQUIRED]}
|
||||
sourceVersion: {type: string, nullable: true}
|
||||
changeReviewRequired: {type: boolean}
|
||||
missingFields: {type: array, items: {type: string}, description: 缺项或待核实原因代码,客户端需显示业务文案}
|
||||
appointments:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
appointmentNo: {type: string}
|
||||
confirmationNo: {type: string, nullable: true}
|
||||
status: {type: string}
|
||||
confirmedAt: {type: string, nullable: true}
|
||||
confirmedEndAt: {type: string, nullable: true}
|
||||
timezone: {type: string, nullable: true, description: 旧预约未记录时区时为空并返回缺项,不能按浏览器时区推定}
|
||||
Cargo:
|
||||
type: object
|
||||
properties:
|
||||
sourceKey: {type: string, description: 稳定ORDER来源键,不因生成入仓计划而变化;非展示编号}
|
||||
orderId: {type: string}
|
||||
customerId: {type: string}
|
||||
customerName: {type: string, nullable: true}
|
||||
inboundCode: {type: string, nullable: true}
|
||||
containerBookingId: {type: string}
|
||||
containerNo: {type: string, nullable: true}
|
||||
originWarehouseId: {type: string}
|
||||
originWarehouseCode: {type: string}
|
||||
originWarehouseName: {type: string}
|
||||
destinationWarehouseCode: {type: string}
|
||||
packages: {type: integer, nullable: true}
|
||||
receivedPackages: {type: integer, nullable: true}
|
||||
shippedPackages: {type: integer, nullable: true}
|
||||
sourcePalletCount: {type: integer, nullable: true}
|
||||
volumeCbm: {type: number, nullable: true}
|
||||
estimatedArrivalAt: {type: string, nullable: true, description: 来源预计到港快照,保留原业务当地时间;不得按浏览器时区转换}
|
||||
estimatedWarehouseAt: {type: string, nullable: true, description: 已保存预计到仓,不因本查询改变}
|
||||
orderVersion: {type: integer}
|
||||
standardNode: {type: string}
|
||||
shippingVersion: {type: string, nullable: true}
|
||||
shippingObservedAt: {type: string, nullable: true}
|
||||
shippingProvider: {type: string, nullable: true}
|
||||
hasInboundPlan: {type: boolean}
|
||||
hasActiveAppointment: {type: boolean}
|
||||
detained: {type: boolean}
|
||||
mixedDestinations: {type: boolean, description: 存在其他目的地明细时,不能按整票默认为同仓货物}
|
||||
@@ -376,7 +376,7 @@ paths:
|
||||
/api/platform/v1/last-leg/fleet/capacity-offers/inquiries:
|
||||
get:
|
||||
summary: 分页查询本人或获准的全部意向
|
||||
description: 权限:platform:fleet:capacity-offer:list 或 platform:fleet:capacity-offer:manage。ALL只允许manage;销售负责人由登录身份过滤,历史不依赖发布仍OPEN。
|
||||
description: 权限:platform:fleet:capacity-offer:list 或 platform:fleet:capacity-offer:manage。ALL和TODO只允许manage;TODO按服务端负责角色筛选调度待办,基础候选超过100条要求按客户或登记号缩小范围,过滤后精确分页,不按当前页伪造总数;销售负责人由登录身份过滤,历史不依赖发布仍OPEN。
|
||||
responses:
|
||||
'200':
|
||||
description: 统一业务响应;code=200成功,冲突或资格拒绝不得当成功
|
||||
@@ -440,6 +440,7 @@ paths:
|
||||
enum:
|
||||
- MINE
|
||||
- ALL
|
||||
- TODO
|
||||
default: MINE
|
||||
/api/platform/v1/last-leg/fleet/capacity-offers/inquiries/{bookingNo}:
|
||||
get:
|
||||
@@ -985,8 +986,41 @@ components:
|
||||
actions:
|
||||
$ref: '#/components/schemas/OfferActions'
|
||||
Inquiry:
|
||||
description: 登记返回服务端资料缺项与处理进度;canConfirm同时核对本票完整性和目的地三维余位,最终写命令仍复验。
|
||||
type: object
|
||||
properties:
|
||||
appointmentCoverage:
|
||||
type: object
|
||||
nullable: true
|
||||
description: FBA来源通过AppointmentCoverageService按客户和BOOKING稳定来源批量读取;无订单保留待形成货件资料,私人目的地为null。不把保位当收货预约,不推算未知时区。
|
||||
properties:
|
||||
status: {type: string}
|
||||
sourceVersion: {type: string, nullable: true}
|
||||
changeReviewRequired: {type: boolean}
|
||||
missingFields: {type: array, items: {type: string}}
|
||||
appointments:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
appointmentNo: {type: string}
|
||||
confirmationNo: {type: string, nullable: true}
|
||||
status: {type: string}
|
||||
confirmedAt: {type: string, nullable: true}
|
||||
confirmedEndAt: {type: string, nullable: true}
|
||||
timezone: {type: string, nullable: true}
|
||||
progress:
|
||||
type: object
|
||||
description: 只读派生处理提示,不是可写状态;负责人及动作按资料完整性、承运/来货/实收事实返回;保存不保位。
|
||||
required: [stage, label, reservation, owner, primaryAction, message, missingFields]
|
||||
properties:
|
||||
stage: {type: string}
|
||||
label: {type: string}
|
||||
reservation: {type: string}
|
||||
owner: {type: string}
|
||||
primaryAction: {type: string, enum: [VIEW, EDIT, CONFIRM, INCOMING, RECEIPT, BIND]}
|
||||
message: {type: string}
|
||||
missingFields: {type: array, items: {type: string}}
|
||||
bookingNo:
|
||||
type: string
|
||||
offerNo:
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
title: 共用车次准备与拼车连续处理
|
||||
version: 1.0.0
|
||||
security:
|
||||
- bearerAuth: []
|
||||
paths:
|
||||
/api/platform/v1/last-leg/fleet/trips/prepare:
|
||||
post:
|
||||
summary: 原子新建或加入车次并关联所选排车单
|
||||
description: '权限:platform:fleet:trip:edit;新建另需platform:fleet:trip:create和platform:fleet:trip:assign。新建、资源分配和全部关联在同一事务,失败回滚;幂等键同载荷重放原结果,异载荷拒绝。同仓、未执行、未绑定其他车次;不确认容量、不审批、不发车。'
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/Prepare'}
|
||||
responses:
|
||||
'200': {description: '统一ApiResponse,data为FleetTripModels.Detail;code=200才成功'}
|
||||
/api/platform/v1/last-leg/fleet/trips/{tripNo}/dispatch-candidates:
|
||||
parameters: [{$ref: './fleet-trips-v1.yaml#/components/parameters/TripNo'}]
|
||||
get:
|
||||
summary: 本仓未关联且未开始执行的排车候选
|
||||
description: '权限:platform:fleet:trip:list。数据库筛选后分页,绑定时重新锁定校验。候选不代表预约、装载或审核已完成。'
|
||||
parameters:
|
||||
- {name: keyword, in: query, schema: {type: string}}
|
||||
- {name: page, in: query, schema: {type: integer, minimum: 1, default: 1}}
|
||||
- {name: size, in: query, schema: {type: integer, minimum: 1, maximum: 100, default: 20}}
|
||||
responses:
|
||||
'200': {description: '统一分页data:records含dispatchNo、customerId、warehouseId、packageCount、route及total/page/size/pages;内部身份不作为用户业务编号'}
|
||||
/api/platform/v1/last-leg/fleet/capacity-offers/inquiries/{bookingNo}/save-and-confirm:
|
||||
parameters: [{$ref: './fleet-trips-v1.yaml#/components/parameters/BookingNo'}]
|
||||
post:
|
||||
summary: 同窗补齐登记资料并原子确认承运
|
||||
description: '权限:platform:fleet:capacity-offer:manage。复用InquiryWrite,更新资料、创建唯一商业订单及占位同事务;任何阶段失败全部回滚,不把保存当成交。同键同载荷返回原结果。'
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: './fleet-capacity-offers-v1.yaml#/components/schemas/InquiryWrite'}
|
||||
responses:
|
||||
'200': {description: '统一ApiResponse,data为InquiryResult'}
|
||||
/api/platform/v1/last-leg/fleet/capacity-offers/inquiries/{bookingNo}/fulfillment:
|
||||
parameters: [{$ref: './fleet-trips-v1.yaml#/components/parameters/BookingNo'}]
|
||||
get:
|
||||
summary: 从原登记查看本票履约进度
|
||||
description: '权限:platform:fleet:capacity-offer:list或platform:fleet:capacity-offer:manage。销售仅本人;返回本票booking、preview及plannedDepartureAt,不返回整车司机或他人货物。preview含tripRecordVersion、recordVersion、incoming,未安排时incoming为null。'
|
||||
responses:
|
||||
'200': {description: '统一ApiResponse,data为Fulfillment'}
|
||||
/api/platform/v1/last-leg/fleet/capacity-offers/inquiries/{bookingNo}/incoming:
|
||||
parameters: [{$ref: './fleet-trips-v1.yaml#/components/parameters/BookingNo'}]
|
||||
post:
|
||||
summary: 从原登记明确安排来货
|
||||
description: '权限:platform:fleet:capacity-offer:manage和platform:fleet:trip:booking-edit。复用版本及幂等门禁,未填时间时沿用登记预计到仓,仍缺失则拒绝,不自动减两小时猜测。承运确认不自动调用此命令。'
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: './fleet-trips-v1.yaml#/components/schemas/BookingIncoming'}
|
||||
responses:
|
||||
'200': {$ref: './fleet-trips-v1.yaml#/components/responses/BookingResult'}
|
||||
/api/platform/v1/last-leg/fleet/capacity-offers/inquiries/{bookingNo}/receipt-confirmation:
|
||||
parameters: [{$ref: './fleet-trips-v1.yaml#/components/parameters/BookingNo'}]
|
||||
post:
|
||||
summary: 原登记核对真实实收与约定运费
|
||||
description: '权限:platform:fleet:capacity-offer:manage和platform:fleet:trip:booking-confirm。沿实际receiptHash/托盘和三维容量校验;不以预报覆盖实收。'
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: './fleet-trips-v1.yaml#/components/schemas/BookingAcceptReceipt'}
|
||||
responses:
|
||||
'200': {$ref: './fleet-trips-v1.yaml#/components/responses/BookingResult'}
|
||||
/api/platform/v1/last-leg/fleet/capacity-offers/inquiries/{bookingNo}/arrange-dispatch:
|
||||
parameters: [{$ref: './fleet-trips-v1.yaml#/components/parameters/BookingNo'}]
|
||||
post:
|
||||
summary: 实收后复用或生成排车并原子排入本车
|
||||
description: '权限:platform:fleet:capacity-offer:manage、platform:fleet:trip:booking-edit、platform:fleet:trip:edit和platform:overseas-warehouse:inbound-order:smart-dispatch。锁原车次和本票来货,先校验实收快照、车辆、有效容量;来源有多张排车或不完整时拒绝,不另建。无排车时复用真实预排命令;任何校验或绑定失败整体回滚。同键重放不重复建单。成功将预留替换为BOUND,旧计划失效待核对,仍需审核和现场作业。'
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: './fleet-trips-v1.yaml#/components/schemas/BookingCommand'}
|
||||
responses:
|
||||
'200': {$ref: './fleet-trips-v1.yaml#/components/responses/BookingResult'}
|
||||
components:
|
||||
securitySchemes:
|
||||
bearerAuth: {type: http, scheme: bearer, bearerFormat: JWT}
|
||||
schemas:
|
||||
Prepare:
|
||||
type: object
|
||||
required: [dispatchNos, idempotencyKey]
|
||||
properties:
|
||||
tripNo: {type: string, nullable: true, maxLength: 64}
|
||||
recordVersion: {type: integer, format: int64, nullable: true, minimum: 0}
|
||||
plan:
|
||||
allOf:
|
||||
- {$ref: './fleet-trips-v1.yaml#/components/schemas/Create'}
|
||||
nullable: true
|
||||
description: 仅新建提交,实际创建幂等键使用外层idempotencyKey。
|
||||
vehicleId: {type: string, nullable: true}
|
||||
driverId: {type: string, nullable: true}
|
||||
dispatchNos: {type: array, minItems: 1, maxItems: 100, uniqueItems: true, items: {type: string, maxLength: 64}}
|
||||
idempotencyKey: {type: string, minLength: 8, maxLength: 128}
|
||||
Reference in New Issue
Block a user