This commit is contained in:
2026-09-29 18:47:37 +08:00
parent 2c60a29e0f
commit c2927ab9a6
291 changed files with 4008 additions and 6298 deletions
+5 -7
View File
@@ -9,6 +9,8 @@
## 快速索引
事件人工重试:`controller/EventOperationsController.java` 提供内部 `/internal/lastleg/event-operations/{entryId}` 查询及 `/retry` 写入,只允许卸柜、派送、暂扣、资金指令与费用事件;独立 `EVENT_OPERATIONS_TOKEN` 保护。原事件不可修改,DEAD→PENDING 与 `event_delivery_retry_audit` 同事务提交,脚本见根 `scripts/event-outbox-operations.mjs`。
本表只保留定位入口;命中业务后必须用 `rg -n -F '关键词' docs/business-index.md` 读取对应行/段的详细约束,再沿代码引用追踪;不默认全文加载详细索引。已知目标文件时直接定位,并定向核对该业务约束。
退货预报、签收、库存、合箱与退货出库:`returnreceipt/`;人工计划自动生成托盘、柜级预览与头程来源托盘快照:`inboundplan/`。这两类入口的补充段落也在详细索引中,按对应短词查询。
@@ -26,7 +28,7 @@
| 尾程订单、明细、状态历史 | `entity/LastlegOrder.java` |
| 独立尾程入仓单快照 | `entity/LastlegInboundOrder.java` |
| 内部令牌保护 | `security/InternalServiceTokenGuard.java` |
| IAM 海外安全投影与实时校验 | `security/controller/LastlegSecurityController.java` |
| 统一会话校验 | 复用 `../common-security/` Redis会话与Auth权威状态校验;Lastleg不维护授权投影 |
| 入仓计划分页、柜级预览、转换与详情 | `inboundplan/controller/InboundPlanController.java` |
| 托盘分配算法 | `inboundplan/service/PalletAllocator.java` |
| FBA 预约创建、详情与编辑 | `InboundPlanController.java` |
@@ -69,7 +71,7 @@
- 平台一件代发出库候选由 `/outbound-orders/one-click-dropship/candidates` 统一返回已完成入库且仍有可用箱唛、SKU 汇总和库存仓位绑定的托盘明细;查询不强制先传 `customerId`,未传时跨客户展示供页面分页筛选,创建时必须从所选候选解析为唯一客户和唯一海外仓,禁止一张出库单跨客户或跨仓。创建后出库单按 `WAIT_PICK → PICKING → PICKED → OUTBOUNDED` 推进;海外 PDA 扫描托盘码时通过整托命令原子拣取该托盘在当前任务内全部剩余箱件和 SKU,任一库存明细失败须整托回滚,逐箱拣货入口继续保留。
- 排车转派送允许在 `PENDING_DEPARTURE`、`PICKING`、`READY_TO_DEPART` 阶段幂等生成一张 `WAIT_OUTBOUND` 出库单,并按目的FBA仓生成多张派送单,但必须早于发车;BOL和签收资料均绑定拆分后的单仓派送单,派送费用仍只发布一次。PDA 排车详情由 `DispatchPdaWorkflowService` 返回 `canDepart`、`departBlockReason`,只有车辆信息完整、拣货任务完成且箱数核平、排车为 `READY_TO_DEPART`、关联出库单仍为 `WAIT_OUTBOUND` 时才允许发车,PDA 不得自行推导该门禁。
- 排车执行与 `delivery/` Controller 和其他尾程业务接口一同注册,不受功能开关控制。平台排车列表与详情仍由 `lastleg.dispatch-query-api.enabled=true` 独立启用;入库单智能排车候选、草稿锁定/解锁/释放和预排创建仍由 `lastleg.smart-dispatch-api.enabled=true` 独立启用。这些排车平台入口均不接收 `customerId`:排车列表跨客户分页,详情按全局排车单号定位后使用记录自身客户范围加载明细;智能排车候选未传计划 ID 时跨客户查询,传入时根据计划 ID 解析范围;托盘移入草稿时立即以操作人和随机草稿标识锁定,移除或关闭时释放,草稿锁超时失效;预排创建根据所选托盘 ID 在服务端解析并校验唯一客户范围,并将当前操作人的草稿锁原子转换为正式排车锁。
- 仓库 ID、类型、状态、地址和能力唯一权威归国内 `warehouse-service`;海外库位、实物托盘和资源锁归 `warehouse-overseas-service/` 且只引用同一国内 `warehouseId`。Lastleg PDA 通过 Warehouse Overseas 内部资源入口校验该国内共享收货仓,不得要求海外数据库重复建仓;浏览器 API 统一经 `gateway-overseas/`。
- 仓库 ID、类型、状态、地址和能力唯一权威归国内 `warehouse-service`;海外库位、实物托盘和资源锁归 `warehouse-overseas-service/` 且只引用同一国内 `warehouseId`。Lastleg PDA 通过 Warehouse Overseas 内部资源入口校验该国内共享收货仓,不得要求海外数据库重复建仓;浏览器 API 统一经 `gateway/`。
## 数据库表索引与注释约束
@@ -83,7 +85,6 @@
| 一件代发与废弃 | `ll_dropship_*`、`ll_cargo_discard_*` | 托盘/箱唛库存、流水和废弃审批 |
| 采购、卡车与本土散板 | `ll_overseas_procurement_*`、`ll_us_truck_*`、`ll_local_looseboard_*` | 海外采购、美国卡车运输及本土散板订单 |
| 通用资料 | `ll_overseas_quote*`、`ll_monthly_exchange_rate*`、`ll_vehicle` | 海外仓报价、月度汇率及车辆档案;不保存车辆派送履约历史 |
| 海外安全投影 | `ll_security_event_inbox`、`ll_security_projection` | IAM 安全事件可靠收件箱与 Lastleg 本地授权投影;只允许内部服务入口访问,不作为 loading、shipping、inbound 等业务模型 |
- 新增或修改表时,表 `COMMENT` 和每个普通字段的 `COMMENT` 必须填写准确的中文业务含义,不得只写英文、字段名或类型名。
- `SchemaChineseCommentContractTest` 自动扫描全部 `ll_` 表,无需维护表名白名单;新增字段必须同步更新基线 SQL、建表增量和存量备注迁移,增量脚本的 `ADD/MODIFY COLUMN` 不得丢失中文备注。
@@ -99,9 +100,7 @@
- 相同事件重复投递返回既有结果,不重新生成单号或插入明细。来源入仓单唯一约束是最终防线。
- 装柜完成事件只把尾程订单建立为 `PENDING_ASSIGNMENT`。`FIRST_LEG` 在途库存使用不可变来源入仓码作为计划生成前的 `inbound_order_no` 展示快照;平台人工转换成功后,同一事务将订单推进为 `INBOUND_PLANNED`,并把对应库存余额的该快照收口为新 `planNo`。
- 内部接口先执行常量时间令牌校验;缺失或错误令牌不得进入消费事务。
- IAM 安全事件只能进入 `/internal/lastleg/security/v1/events`;通用 `/internal/lastleg/events` 只白名单接收装柜完成与实际船节点事件,禁止把 IAM 事件交给 `LoadingCompletedConsumer`。
- Lastleg 安全投影只接受 `ACTIVE`/`DISABLED` 两态安全语义;客户建档和审核的 `PROFILE_REQUIRED`/`PENDING`/`REJECTED`/`ARCHIVED` 由 IAM 在发布前统一折叠为 `DISABLED`,Lastleg 不兼容或解释国内工作流状态。
- 开发/测试空库基线只为国内固定 `authUserId=1000001`、`tenantId=0` 的 `platform_admin` 写 USER/AUTHORIZATION version=0 投影;AUTHORIZATION 必须携带当前 `PLATFORM_ADMIN` 角色及按 IAM 跨区前缀筛选的完整权限快照,统一 SQL 重放只修正仍处于固定 baseline version=0 的该行,后续 IAM version>=1 事件单调覆盖。不得扩大为其他历史账号运行时补齐或缺失投影默认放行。
- 通用 `/internal/lastleg/events` 只白名单接收装柜完成、实际船节点与资金结果事件;未知或IAM安全事件必须拒绝。
- PDA 入仓任务完成前必须先通过 `/unload-photos` 保存非空且不重复的卸柜照片文件 ID;照片上传时间由服务端记录,预计报空时间固定为照片上传时间加两天。完成入仓时,库存入账、计划/任务状态推进与 `OVERSEAS_CONTAINER_UNLOADED` V1 Outbox 必须处于同一事务;事件绑定来源头程货柜身份,不得从前端请求拼装或回查头程数据库。
- 海外 PDA 柜号签收只允许平台 `OVERSEAS_WAREHOUSE_PDA_OPERATOR` 使用 `lastleg:pda:operate`;国内头程 PDA 角色不得进入。PDA 不接收 `customerId`,候选按来源柜跨客户聚合,同柜允许多个客户;选柜会话、三类照片及整柜完成事实只绑定 `sourceContainerBookingId + containerNo`,文件与柜级跨区事件使用 `tenantId=0` 平台技术范围。签收后按每个入仓计划自身客户生成任务,扫码、SKU 实收、托盘和库存始终使用入仓码所属票的真实客户。未完成会话按平台操作账号和柜号分别全局唯一;平台管理员和客户账号不得进入该作业入口。
@@ -139,7 +138,6 @@
- 换标复核闭环:`PdaRelabelService.complete` 直接提交待客户确认,`RelabelApplicationService.confirmCompletion` 原子完成 PDA 复核;平台 `RelabelApplicationController` 的 `/review-task`、`/rework` 按状态权限提供带版本的退回。退回备注必填,上一轮事实及照片引用写入 `REWORK_ARCHIVE` 历史,原事实标记 `REWORK_ARCHIVED` 并释放扫描唯一键,当前计数归零;客户已确认不可退回。PDA 不再自行批准复核。
- 移动包、拆分端口/适配器或引入新的跨子域依赖时,先核对内部模块化基线并运行 `node --test scripts/analyze-lastleg-dependencies.test.mjs`;确需更新依赖基线时必须说明稳定边界变化,不能把临时循环依赖登记为长期豁免。
- 安全投影边界变更同时运行 `SecurityProjectionArchitectureTest` 与 `LastlegSecurityContractTest`;`security/controller|dto|service` 只允许依赖本子域和根 `InternalServiceTokenGuard`,其他 Lastleg 业务包不得直接依赖这些投影内部包。
- 表字段、注释和索引同步维护基线 SQL 与统一增量 SQL;生产/存量库只执行增量脚本。
- 事件契约变化同时检查 `common-event-contract` 版本、Event Bridge 消费方和旧 Payload 哈希兼容。
- 定向验证:从后端根执行 `mvn -pl lastleg-service -am test`。