Files
docs/海外仓业务/预约工作日历开发协作契约.md
T
2026-10-19 10:40:53 +08:00

222 lines
31 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 预约工作日历开发协作契约
建立日期:2026-10-15;V13 确认同步日期:2026-10-16。用户已确认 V13 原型,正式业务变更见[预约工作日历 V13 变更说明](预约工作日历V13变更说明.md)。本文继续维护接口、数据归属和文件边界,不重复维护产品规则或作为已实现说明;当前部署与验收事实只维护环境主契约。
本文承接[预约优化方案](美国预约管理统一总览与优化方案.md),日历首屏、多客户共车、分批后送、改期取消、重新预约与完整待办的确认行为以 V13 正式变更说明为准;不扩展为拼车、车队或海外仓的全面重构。任务身份与唯一写者见[协作登记](../独立任务协作登记.md)。
当前开发总控为用户明确指定的 `01a13df2-c639-7560-a3e2-30bc23a579b3`,负责开发设计、任务调度、接口对齐、共享集成、开发检查点及验证收口;原型对话 `01a13a8d-e968-7962-906b-1a514792d921` 只负责业务梳理、原型和变更文档。用户再次明确:设计确认后交开发总控安排,不由原型对话继续派工或跟踪开发。本文“总控”均指当前开发总控。两个专项保留原范围,精确触点以第五节为准。
## 1. 输入与共同目标
原型只读入口:`C:/Users/BY-OY/.codex/visualizations/2026/10/14/01a13a8d-e968-7962-906b-1a514792d921/appointment-calendar-guided.html`,当前确认交接为 V13,确认指纹见正式变更说明第一节。它承载交互示例,不作为真实 API、数据总量或权限来源。
- 实际开船后,所有必需工作进入统一事项范围,未预约、未定日期也有记录与负责人跟进;不能等创建预约后才出现。
- 默认进入“预约工作日历”。月格固定高度,提柜、接仓卸柜、送仓/FBA、用车、还空五类勾选显示数量,点击数量进入明细。到港参考单独开关,不计工作量。
- 全部待办、今日需跟进、超期、未定日期、需复核独立于月历月份、流程和类型勾选;全局统计由服务端计算。明细明确显示其范围,不能把月历条件偷偷带入全局待办。
- 目标日期、对方确认时间、实际完成时间分别保存。按作业地点时区落日;无日期进入未定日期区,不伪造日期或 00:00/09:00。
- 主按钮直接给下一步,返回时保留原柜、批次、日期和筛选;查看当前项与跳到前置事项是两个明确入口。
## 2. 数据归属与两条流程
| 业务 | 本轮约束 | 唯一生产者 |
| --- | --- | --- |
| 来源/核实资料/数量分配 | 保留客户、原来源、目的地及核实版本;补箱数和各票货件号只写预约核实资料,不覆盖原订单;并发按原来源加锁,总分配量守恒 | 预约核心任务 |
| FBA 预约申请、确认、取消、分批合并 | 沿原预约写服务执行;取消预约保留工作需求、历史和后续跟进;分批不能只移除原整票唯一约束 | 预约核心任务 |
| 工作事项/路线/跟进/复核 | 工作关系、未安排需求、责任和操作入口由工作事项模块维护;已有业务计划和实际事实只关联,不另建第二份可编辑数量或预约结果 | 工作事项后端 |
| 提柜计划和实际提柜/还空 | 以 Firstleg 原业务命令及事实为准 | 预约核心任务协调原域最小适配 |
| 实际接仓卸柜 | 以真实海外仓/PDA 收货为准,不能由事项勾选完成代替 | 原海外仓业务;本轮只读消费 |
| 车辆计划、出车、完成 | 以 Fleet/Dispatch 原业务命令及事实为准 | 工作事项后端维护本轮 Lastleg 原域适配及直接消费者 |
| 客户仓无需预约、还空责任交接 | 保存明确收货要求、责任及交接历史,不生成假确认号、不改提柜承运历史;实际还空仍走 Firstleg | 工作事项后端保存要求和责任,核心任务适配实际执行入口 |
中转:同柜共用提柜、接仓卸柜、还空;每个送货批次独立关联收货预约与用车,可以一柜多批、多车,也允许同一真实车次覆盖多个批次。批次变更不能重复生成柜级工作。实际卸柜后即可按真实条件还空,不必等待全部尾程送货完成。
直送:没有海外仓接仓卸柜事项;提柜、目的仓收货/卸货、运输、还空形成关联,可同车执行,也可转交独立还空。不得调用会建立海外仓库存的 PDA 入库命令来证明直送卸货。现有 Firstleg 还空若只认可海外仓卸柜,核心任务必须补真实目的仓卸货依据及守卫,未补齐前保持明确阻断,不能把事项状态写成完成。
路线未确认:显示一条“确认路线”需求,确认后事务内幂等生成对应清单,并立即可查询。已执行的路线不能通过切换选项抹掉事实;有安排时必须先评估关联影响。
稳定身份:柜级事项用柜次内部标识与类型去重,送货/用车需求用不可变 requirementKey/batchKey 关联。原来源键沿用 `ORDER:` / `BOOKING:`;不得用柜号文本、目的仓名称或可变预约号作为唯一键。未分批阶段先有送货/运输需求;真正分批后以明确的替代关系衔接,旧需求不和新批次重复计数,也不能消失但未生成后续。批次、预约、车次的内部键仅用于关联,界面展示业务号,缺失显示“—”。
事项完整来源不能直接复用目前仅 FBA 的 cargo 查询或排除完成订单的 containers 查询。新后端负责独立覆盖核对:已开船无海外仓绑定、非 FBA 目的仓、未知路线、货已送完但柜未还空均须保留。不得靠前端翻完所有页拼全局统计;GET 不隐式写库。生成/同步须有可验证的服务端幂等入口,不能依赖用户先打开某个柜。新增 Firstleg 提供端触点先交总控确认精确文件后由核心任务实施。
## 3. 工作事项 HTTP 接口 v1
平台路径前缀:`/api/platform/v1/last-leg/appointment-work`。沿用项目 ApiResponse/PageResult、鉴权与分页约定;平台列表权限包含详情只读。新后端同时维护 `appointment-work-v1.yaml` 与 Controller/DTO,不通过多路径或别名兼容旧草案。
| 方法与路径 | 输入 | 输出与口径 |
| --- | --- | --- |
| GET `/calendar` | `from`、`to`(当地日期,均包含);可选 `flow`、重复 `types` | `CalendarResult`,整个区间的日聚合,不能按明细分页结果算数量;最大 62 天 |
| GET `/summary` | 无月历筛选参数 | `Summary`,当前权限可见的全部活动事项;跨月份、类型和路线 |
| GET `/items` | `view=ALL/FOLLOW_TODAY/OVERDUE/UNDATED/REVIEW`,`page`、`size`;明细可显式传 `date/flow/types/containerBookingId/bucket/keyword` | 项目分页结构的 `WorkItem`;全局卡片调用不传月历条件;无 date 的 ALL 为全部未完成事项,有 date 的 ALL 包含当日已完成事项;bucket 对应日历互斥统计桶 |
| GET `/items/{workItemKey}` | 稳定事项键 | `WorkDetail`,当前项、前置/后续、原业务引用和历史 |
| POST `/items/{workItemKey}/commands` | `command`、`expectedVersion`、`idempotencyKey`、判别式 `payload` | `{item, affectedWorkItemKeys}`;成功后刷新摘要与当前日历;版本冲突 409,刷新后保留用户输入 |
`flow` 枚举 `TRANSFER/DIRECT/UNKNOWN`,省略为全部。`types` 为 `PICKUP/WAREHOUSE_RECEIPT/DELIVERY/TRANSPORT/EMPTY_RETURN`;未知路线需求为 `ROUTE`,独立保留在全局待办中,不因五类勾选被遗漏。日历无条件命中时返回空聚合,数据源不可用不能返回伪造零值。
DTO 冻结的共同字段:
```text
WorkItem
workItemKey: string, version: integer
type, flow: 上述枚举
title: string, businessNo: string|null
containers: ContainerReference[]
requirementKey: string|null, batchKey: string|null, batchNo: string|null
originName: string|null, destinationName: string|null
planStatus: UNPLANNED|TARGET_SET|AWAITING_REPLY|CONFIRMED|NOT_REQUIRED
executionStatus: PENDING|IN_PROGRESS|COMPLETED
reviewRequired: boolean
target: Slot|null, confirmed: Slot|null
actual: Actual|null
calendarDate: YYYY-MM-DD|null
dateBasis: ACTUAL|CONFIRMED|TARGET|NONE
timezone: IANA zone|null
owner: {id: string, name: string}|null
followupDate: YYYY-MM-DD|null, overdueReasons: string[]
allowedActions: Action[], nextAction: Action|null
blockReasons: string[], missingFields: string[]
Actual = {occurredAt: Instant|null, localOccurredAt: LocalDateTime|null, timezone: IANA zone|null}
Slot = {date: YYYY-MM-DD, startTime: HH:mm|null, endDate: YYYY-MM-DD|null, endTime: HH:mm|null, timezone: IANA zone|null}
ContainerReference = {containerBookingId: string, bookingNo: string|null, containerNo: string|null}
SourceReference = {customerId: string, sourceKey: string, destinationKey: string|null}
Action = {code: ActionCode, label: string, targetWorkItemKey: string|null, target: ActionTarget}
ActionCode = VIEW_DETAIL|SAVE_PLAN|REQUEST_BOOKING|RECORD_CONFIRMATION|CHANGE_BOOKING|CANCEL_BOOKING|
VERIFY_CARGO|EDIT_BATCH|ARRANGE_TRANSPORT|RECORD_EXECUTION|CONFIRM_ROUTE|SAVE_FOLLOWUP|
RESOLVE_REVIEW|SAVE_REQUIREMENT|HANDOFF_RETURN|ACCEPT_RETURN|VIEW_HISTORY
ActionTarget 是按 kind 判别的联合:
WORK_COMMAND {command: 工作命令枚举}
CARGO_VERIFICATION {source: SourceReference}
FBA_APPOINTMENT {appointmentId: string|null, batchKey: string|null, sources: SourceReference[]}
FIRSTLEG_CONTAINER {containerBookingId: string}
FLEET_TRIP {tripId: string|null, batchKeys: string[]}
WAREHOUSE_RECEIPT {inboundPlanId: string|null, containerBookingId: string}
READ_ONLY {references: BusinessReference[]}
WorkDetail = {item: WorkItem, relatedItems: WorkItem[], references: BusinessReference[], history: HistoryEntry[],
review: {version: integer, reasons: string[]}|null,
requirement: {bookingRequired: boolean, receivingRequirements: string, reason: string|null}|null,
returnHandoff: {version: integer, from: Responsibility, to: Responsibility,
status: PENDING_ACCEPTANCE|ACCEPTED, reason: string}|null}
Responsibility = {kind: USER|SUPPLIER|EXTERNAL, id: string|null, name: string}
BusinessReference = {kind: string, key: string, businessNo: string|null, label: string}
HistoryEntry = {occurredAt: ISO instant, operatorName: string|null, action: string, summary: string}
Summary = {all: integer, followToday: integer, overdue: integer, undated: integer, review: integer}
CalendarResult = {from: YYYY-MM-DD, to: YYYY-MM-DD, total: integer,
counts: BucketCounts, days: DayAggregate[]}
DayAggregate = {date: YYYY-MM-DD, total: integer, typeCounts: Map<type,integer>, counts: BucketCounts}
BucketCounts = {pending: integer, confirmed: integer, noBookingRequired: integer, review: integer, completed: integer}
```
Slot 的 `date` 为开始日期;`endDate` 与 `endTime` 必须同时有值或同时为空。结束不能没有开始时间:填写结束日期/时间时,`startTime` 必填。完整结束时间必须严格晚于开始时间,不允许相等;跨日必须显式填写结束日期,不能因为结束钟点小于开始钟点就自动推断次日。只有日期、没有开始时间时,结束日期和结束时间都为空;前后端按同一规则校验。例如开始 `2026-10-15 23:00`、结束 `2026-10-16 01:00` 可以明确表达跨日;仅填写结束 `01:00` 而未填结束日期应拒绝。
时间事实扩充合同已冻结:`Actual` 非空时,`occurredAt` 与 `localOccurredAt` 至少一种有值。`occurredAt` 表示绝对时间(Instant),`localOccurredAt` 表示原业务保存的无偏移当地时间(LocalDateTime)。原业务只有 local 实际事实且没有时区时,直接保留其当地日期用于日历,`timezone=null`,并在事项 `missingFields` 中标记 `SOURCE_TIMEZONE`;不得给 local 时间附加 `Z` 或伪装成 UTC,也不得从服务器、浏览器或计划时区推导实际时间。缺少时区不能抹去真实完成事实或让事项回退为待完成;有 local 实际时间时继续按实际日期展示,不能退回目标/确认日期。
跨地点实际先后比较必须基于可确定的绝对时间。原提柜/还空只有无时区 `LocalDateTime` 时,不能直接与有 IANA 时区的直送目的仓当地钟面值比较先后,也不能擅自套用目的仓或其他时区。真实提柜存在、全来源真实卸货完成仍是直送还空的硬门槛;缺少源时区时,跨地点实际先后尚无法证明,不能把时序校验记为已通过,也不能因此跳过真实业务前置条件。
多目的地直送的完成时间选择各目的地真实完成时间中最晚的 `Instant`,不按当地钟面值取最大。72 小时提醒按基准 `Instant` 之后的绝对 72 小时时长计算,跨夏令时(DST)也保持相同时长,不能以当地日期加三天或当地钟面差值替代。
来自原业务的 `Slot.timezone` 允许为 null,并同样标记 `SOURCE_TIMEZONE`;保留原日期与时间,不擅自转换。新 `SAVE_REQUIREMENT` 的用户输入仍要求有效 IANA 时区:只要提交非空 `target`,`target.timezone` 就必填,不能用原业务读取允许空值的规则放宽新录入校验。合同冻结不代表实现、部署或验收已完成。
内部 `ContainerSource` 的时间字段扩充如下(其余既有字段不变):
```text
departedAt: Instant|null
departedLocalAt: LocalDateTime|null
sailedEvidenceLocalAt: LocalDateTime|null
```
三种时间至少一种有值。`departedAt` 或 `departedLocalAt` 是确切开船时间;`sailedEvidenceLocalAt` 仅证明存在实际发生且节点序号大于等于开船节点的事实,可用于确认已开船来源资格,不能显示为确切开船时间,也不能复制成 `departedAt`/`departedLocalAt`。仅有后续实际节点证据时,保留证据及其语义,不能把该节点发生时间冒充开船时间。
所有统计按稳定事项键去重;全局五项统计是不同集合,允许重叠,不能相加作为工作量。日历五个 BucketCounts 互斥,依次按已完成、需复核、已确认、无需预约、其余待安排归类,相加等于 total;无需预约单独表达,不能冒充已确认。同一真实车次在一天按一项运输工作计数,关联批次在明细中展示;批次送货工作仍各计一项。containers 保存全部关联柜,按任一关联柜筛选均能命中,共享车次仍只计一个事项。keyword 仅过滤当前明细,匹配业务号、柜号、批次号和地点,不影响全局摘要。`calendarDate` 优先实际、确认、目标;日期已过而未完成进入超期,不能从全局消失。事项无日期但有跟进日期仍属于未定日期;“今日跟进”按该事项作业当地今日判断,无地点时使用明确的业务默认时区并展示口径,不能取服务器默认时区。
Action 的 code/target 是白名单业务动作,不下发任意 URL 或 HTTP 方法。前端映射既有入口或工作命令表单;不能只凭 code 发车/完成,原业务命令仍复核权限、版本及前置事实。缺权限可以看详情和明确原因,不能以禁用按钮替代完整下一步说明。首屏一个主要下一步,其余放详情;若需要先处理其他事项,targetWorkItemKey 指向前置项,关闭后回原上下文。
工作命令只覆盖工作模块自身拥有的数据:
| command | payload 必需语义 | 边界 |
| --- | --- | --- |
| `CONFIRM_ROUTE` | `flow=TRANSFER/DIRECT`,`reason` 可选 | 核对业务事实、版本与已有安排,事务幂等生成清单 |
| `SAVE_FOLLOWUP` | `ownerId`、`followupDate`(可空)、`note` | 只写跟进;不能清除未接手、未预约或未完成需求 |
| `RESOLVE_REVIEW` | `reviewVersion`、`note` | 对已展示的影响版本复核;若原安排本身需改,先走原业务命令,不能用复核代替改期 |
| `SAVE_REQUIREMENT` | `target: Slot|null`、`bookingRequired: boolean`、`receivingRequirements`、`reason` | 非空 target 必须填写有效 IANA timezone;仅用于原业务尚无计划实体的接仓需求、客户仓收货要求及还空目标;FBA、提柜、车次计划仍写原模块;无需预约必须有明确收货要求依据 |
| `HANDOFF_RETURN` | `recipient: Responsibility`、`reason` | 保留原预约、原责任与交接记录;新接手未确认仍待办;重复提交不重复交接 |
| `ACCEPT_RETURN` | `handoffVersion`、`note` | 服务端核验当前责任与有效转交版本;用户本人可接手,外部承运方由具备写权限的运营记录明确反馈依据,保留真实操作人;只确认责任,不等于实际还空 |
服务端拒绝不支持的 command/payload,不提供通用“改状态/标为完成”。跟进、复核使用 `platform:appointment:followup`;路线、缺失计划要求及责任转交使用新写权限 `platform:appointment:manage-work`,接手操作还需身份约束;读取使用 `platform:appointment:list` 并核验关联来源的读取资格。权限种子/菜单绑定由总控集成,不通过移除鉴权让前端联调。
首次设置目标、首次同日落实和首次配车建立基线,不触发无意义复核。真正改期/货量或执行关系变化仅标记已有相关目标或已落实的下游;未定日期、尚未安排的项继续待安排。复核动作本身不再传播一轮复核;旧影响版本不能覆盖新变化。取消预约不取消工作需求。普通回复、复核、取消不能清除还空转交待接手提醒。
## 4. 预约核心向消费者提供的边界
已落源码的货物核实接口可据此并行消费,但仍须测试通过才能作为完成交付:
- GET `/api/platform/v1/last-leg/appointment-planning/sources/{sourceKey}/cargo-verification`,query 为 `customerId`,可选 `destinationKey`。返回 `Context{source, verification, allocatedPackages, unknownAllocationCount, effectivePackages, availablePackages, sourceChanged, allowedActions, blockReasons}`;可分配数无法确定时为 null,不得显示为 0。
- POST 同路径,query 为 `customerId`;body:`destinationKey, expectedSourceVersion, expectedVersion, packageCount, shipmentReferences[], remark, idempotencyKey`。返回 `Verification{version, sourceVersion, destinationKey, sourcePackages, packageCount, shipmentReferences[], remark, operatorName, verifiedAt}`。未知原箱数可保存经核实箱数,已知原箱数不能超出,已分配量不能被覆盖到更小;不改原订单。
- source 字段以 `AppointmentSourceService.Source` 和 `appointment-cargo-verification-v1.yaml` 为准;现有 `VERIFY_CARGO` 只代表核实能力,不代表分批已开放。
分批能力以实际 Controller/DTO/OpenAPI 和直接验证为准,不得以旧整票 preview/create 假定 V13 已全部具备。核心任务核对并冻结本轮新增或调整的合同,必须包含稳定 batchKey/version、每个 customerId/sourceKey/destinationKey 的分配量、核实版本、来源版本、幂等键、取消/替代关系,以及所影响的批次/事项引用;对同仓合并保留逐票来源,不把客户归属抹平。新工作模块通过单向只读适配获得批次身份和覆盖,不能回调形成包循环;原业务命令成功后按相关键重新读取/协调工作项,不建立第二本数量台账。
本轮 V13 接口补充按正式变更说明第十节核对:全部/部分分配去向、当前共同预约范围及版本、待重约和排除成员、失效预约与仍有效数量分配的边界、逐步骤结果及受影响事项。沿既有真实合同补齐,不照搬原型字段名,也不另建同功能端点。具体新增字段、动作和错误码由生产者先冻结并同步消费者。
V13 生产者与消费者使用下列明确边界;这是接口合同,不表示已部署验收:
- 批次上下文沿 `GET /appointment-planning/batches/{batchKey}`,`currentBatches` 返回全部当前去向;`originalSourceRefs` 保留当前和已移出货物的客户、原来源、目的地,仅用于过滤当前去向。可写分配量仍取 `sources` 及服务端资格,不能将历史来源重新作为可用余量。
- 收货范围命令归 `inboundplan/receiving/`,HTTP 根为 `/api/platform/v1/last-leg/appointment-receiving`;具体七个读写入口、字段与权限以 `appointment-receiving-v1.yaml` 为准。稳定批次、独立收货预约及真实车次是不同身份。共同或独立重约产生新的有效预约关系,旧取消范围保留历史。
- 待确认变化提交 `ownerId`,平台人员目录校验身份并给出姓名;响应 `Pending.followup` 保存权威姓名及可空跟进日期。后送批次与再次分批由工作域继承负责人和跟进记录,不将自由文本当账号,不将跟进日代替作业日。合批遇到同客户不同跟进安排时须先明确统一,不能猜选覆盖。
- `FbaAppointmentTransportPort` 负责真实移货;`FbaAppointmentExecutionPort` 按客户、批次及原履约证据给出重约资格。`Book.executionVersion` 绑定涉及批次的执行事实,写入只核对所选客户;同批已完成客户不阻断未完客户重约。锁顺序为车次、排车/执行、批次,取得批次锁后再次读取执行版本防止间隙新增关联。
- 确认变化同事务核平原量、后送量及运输关系;失败整体回滚。撤回未生效变化不改货量、原确认或车辆,不因运输开始而失去撤回入口,仍校验变化版本及幂等。保存后的独立约仓、配车失败只续办该步骤,不重复创建已成功批次。
新增或调整部分采用阶段门禁:生产者先产出真实合同与直接测试,消费者再接写入;现有已冻结能力及不依赖新增接口的工作继续并行。生产链不得用 Mock、空数组或成功兜底假装未交付能力;缺依赖在开发交接中列明,不向用户呈现不可用的假成功按钮。
- 同批部分客户已正式确认时,其余客户通过 `POST /api/platform/v1/last-leg/appointment-receiving/plans` 保存本客户未确认计划。请求 `Plan` 使用 `member(batchKey,batchVersion,customerId)`、`details`、`executionVersion` 和幂等键;只允许 `PENDING`/`FAILED`,正式确认字段必须为空,目标日期可空,未约成须说明原因。`Context.plans` / `BatchReceiving.plans` 返回权威客户计划,存在但目标为空表示真实清空,不回退其他客户日期。计划不占用新的货量、不形成有效收货确认、不修改其他客户确认。当前计划归核心 `ll_fba_receiving_plan`,工作域仅作投影;批量读取为三条有界查询。
- 整组重约允许明确选择本次客户子集。跨批次组只选部分批次时,通过只读 `POST /api/platform/v1/last-leg/appointment-receiving/execution-scope` 以 `ExecutionQuery.members` 获取实际所选范围的执行资格及版本;该入口使用列表权限,不建立预约。前端重新核对选择,写入继续校验原批次和取消组版本,不能自行合成 token 或静默刷新用户未核对的批次事实。
- 独立核实资料更新后,当前未确认客户通过 `POST /api/platform/v1/last-leg/appointment-receiving/cargo-refresh` 明确采用最新资料。请求 `RefreshCargo` 包含原 `member`、完整逐来源期望版本、`executionVersion` 和幂等键;先展示最新核实量与货件资料供操作者核对。只更新本客户原批次资料快照,不改分配量、客户/来源/目的地身份或其他客户确认。有效确认、待确认变化、已执行、来源身份改变或数量不守恒均拒绝;不以放松Plan/Book版控恢复,不在独立核实保存后自动采用。
## 5. 唯一文件写者与阶段交付
以下代码路径相对工作区 `C:/Users/BY-OY/Desktop/code/chongchong-global`。修改前读适用最近指引,保留已经存在的未提交更改。包级范围只覆盖预约工作本轮直接相关文件,不授权重写整包无关业务。
| 写者 | 独占文件/触点 | 不得写入 |
| --- | --- | --- |
| 开发总控兼预约核心 `01a13df2-c639-7560-a3e2-30bc23a579b3` | `baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/appointmentplanning/` 来源、核实、覆盖、批次与预约桥接,以及 `inboundplan/` 核心预约和直接消费者,排除下述本批交给后端专项的触点及直接测试;现有预约规划、核实、批次及 FBA OpenAPI;本轮全部 Firstleg 来源接口和直送卸货/还空守卫;既有检查点、共享 DDL/SQL、IAM/权限种子、根路由导航、Gateway/公共门禁集成及验证窗口 | 两个专项独占文件、原型及业务主文档;不能与专项并写 |
| 工作事项后端 `01a13e1c-9101-7a43-8445-771685ff315e` | 原 `baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/appointmentwork/`、同包测试、`src/main/resources/openapi/appointment-work-v1.yaml`、独立 DDL 提案 `src/main/resources/db/appointment-work.sql` 保留;增加下述 Lastleg 原域适配及精确同步触点 | Firstleg;未列入本批适配的预约核心和 PDA 写类;共享 SQL/配置/IAM/权限种子/架构门禁 |
| 预约页面前端 `01a13e1c-db36-73e3-a231-d6649c51664b` | `apps/admin-web/src/modules/appointment-calendar/` 全部页面、组件、API、直接测试与操作矩阵;共享 `overseas-warehouse/components/FbaAppointmentFields.vue`、`appointmentForm.ts`/直接测试;`api/inboundOrders.ts`/测试仅预约消费段;`index.ts` 仅相关导出;`pages/InboundOrdersView.vue`/测试仅预约弹窗衔接;增加下述跨页面工作流触点 | 后端、根路由/导航、本轮工作流之外的业务功能、原型与业务文档 |
| 原型与文档支持 `01a13a8d-e968-7962-906b-1a514792d921` | 业务梳理、原型、本文及必要业务正式文档/入口;设计确认后向开发总控交接 | 代码、共享 SQL、构建、开发检查点写入、开发派工及持续进度跟踪;接口对齐和验证安排由开发总控负责 |
模块 `lastleg-service/src/main/resources/db/lastleg.sql`、`deploy/sql/海外区域统一增量-MySQL8.sql` 与 `reset-test-fba-appointments.sql` 统一由当前开发总控 `01a13df2-c639-7560-a3e2-30bc23a579b3` 集成,保留各专项已有改动,新后端仅维护独立 DDL 提案,不并写共享文件;本轮只编辑文件,不执行 SQL。
本批工作事项后端新增写权,以下 Java 路径相对 `baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/`:
- 本轮 Lastleg 原业务域与工作事项间的真实读取/同步适配。
- `inboundplan/work/`:本轮原预约域的工作事项适配。`inboundplan/service/InboundFbaAppointmentService.java` 及核心预约/分批测试已由后端专项明确停止修改并交回开发总控,V13 核心调整由总控唯一写入;本条覆盖早期“专项增加最小同步钩子”的临时移交。
- `dispatch/service/DispatchService.java`、`dispatch/dto/DispatchRequests.java`、`fleet/trip/FleetTripExecutionService.java`,以及以上适配直接涉及的 Mapper、DTO 和对应测试;只为本轮工作流衔接修改,不扩展为原业务域整体重构。
上述保留给后端专项的触点及其直接测试由专项唯一写入;总控不同时编辑。已交回的预约核心服务及核心测试由总控唯一写入。再次调整写权时须明确移交后再写,不按同文件不同方法安排并写。后端专项仍不能改 Firstleg、共享 SQL/IAM/公共门禁。
本批预约页面前端新增以下最小工作流衔接写权,路径相对 `apps/admin-web/src/modules/`;可同步对应直接测试,不改页面中无关业务:
- `container-loading/pages/ContainerDetailView.vue`、`container-loading/api/terminalDrayages.ts`。
- `overseas-master-data/pages/TripsView.vue`、`overseas-master-data/pages/TripDetailView.vue`、`overseas-master-data/components/TripPlanDialog.vue`。
- `overseas-warehouse/pages/DispatchesView.vue`、`overseas-warehouse/components/SmartDispatchDialog.vue`、`overseas-warehouse/api/dispatches.ts`、`overseas-warehouse/pages/InboundOrderDetailView.vue`。
本轮全部 Firstleg 来源接口、直送实际卸货/还空守卫及相应原域事实适配由开发总控负责;工作事项后端消费和提出所需 DTO,不写 Firstleg。提柜后还空责任与原承运历史分离的业务约束不变。Firstleg 无时区 local 实际事实与开船证据按第三节已冻结时间合同衔接,不能把证据时间当作确切开船时间。共享 DDL、IAM、根公共权限常量及门禁仍归总控,不能借上述原域适配授权扩大写权。
1. 核心保持核实与数量分配开发;新后端按 v1 实现工作合同;前端接入已冻结的工作 v1 和核实接口。分批消费者等待真实分批合同,其他部分并行。
2. 每个任务在自己对话报告实际修改、接口偏差、缺口、测试证据与可集成基线。总控读取,不要求自动跨对话回信;不新增任务或递归派工。
3. Maven/共享构建输出按总控分配窗口串行;前端只运行本模块直接验证,完整测试/build 先核对其他专项的窗口。当前先开发和准备测试,由总控安排执行时段。
4. 原型由原型与文档支持对话统一维护;V13 已获用户确认并形成正式变更说明。实现偏差先报当前开发总控,必要时请求文档支持,不能各自改原型或偷偷改变 DTO。开发总控沿本节原分工推进,不新增任务或扩大文件写权。
## 6. 必须保留的验收场景
V13 本批新增及强化场景以[正式变更说明第十一节](预约工作日历V13变更说明.md#11-最小验收矩阵)为准;下列既有场景继续保留,不能用原型通过代替真实合同和实现验收。
- 已开船但未创建预约、未知路线、没有海外仓绑定的直送、非 FBA 客户仓、货已送完但未还空,全部能进入正确待办;跨月份、全关类型、只看单流程不能误清全局数量。
- 中转一柜分三批、两车运输,柜级不重复;部分取消/改期/合并后数量仍守恒、逐票客户和货件信息未丢失;并发或重复点击不超分、不中断剩余需求。
- 直送不生成海外仓入库,不伪造卸货事实;同车或转交还空均可追踪原预约、新责任、接手状态及真实完成前置条件。
- 未定日期仅补货物资料不自动预约;有跟进日仍未定作业日期;首次计划无多余复核,真实变更仅影响相关已安排项,复核不产生复核循环。
- 日期跨时区、实际发生时间晚于目标、改期/取消后的旧事实仍正确;同一车次多批不重复计车辆工作量;只读用户不能通过通用命令越权执行。
- 原业务无时区 local 实际事实保留当地日期与完成状态,并标记 `SOURCE_TIMEZONE`;原业务 Slot 可缺时区但新录入不可缺;仅有 `sailedEvidenceLocalAt` 时可证明已开船,不能展示为确切开船时间。
- 外部来源或权威事实读取失败有明确失败反馈,不能展示“0 项/全部完成”;生产接口不能返回原型 Fixture。
生产代码、离线检查、部署与真实验收分别交付。人工视觉验收仍按 1920×1080、100% 缩放,由用户截图确认;本轮不部署、不运行 SQL、不写测试环境数据、不启动本地后端、不自行提交或创建分支/worktree。