Files
baiyue-firstleg/lastleg-service/AGENTS.md
T

14 KiB
Raw Blame History

Lastleg Service 模块指引

职责与边界

  • 负责消费头程装柜完成事件,保存业务 Inbox,并按最终实装入仓单建立尾程订单、明细冻结快照和初始状态历史。
  • 负责尾程订单列表、详情、导出和目的仓调整,以及海外入仓计划、托盘分配与 PDA 入仓作业;PDA 卸柜完成后通过本地 Outbox 向国内头程回传货柜报空事实。
  • 不查询头程数据库,不调用头程接口补齐建单字段;事件快照缺失时应拒绝消费并保留可诊断错误。

快速索引

功能 入口
事件接收、平台订单列表/详情/导出、目的仓调整 src/main/java/com/baiyue/lastleg/controller/LastlegOrderController.java
客户尾程订单列表与详情 controller/MerchantLastlegOrderController.java;客户范围只取认证身份,稳定类型/状态见 model/LastlegOrderType.java、LastlegOrderStatus.java
装柜完成事件消费 service/LoadingCompletedConsumer.java;当前生产信封为 FIRST_LEG_LOADING_PLAN_COMPLETED V2,消费端冻结 destinationType:FBA 可按箱数且不生成逐箱作业账,OVERSEAS 必须逐箱校验并生成箱级事实;历史缺字段事件仅按明确 FBA 单号或目的仓与接柜仓一致性安全推断,歧义直接拒绝
尾程单号生成 service/LastlegOrderNoGenerator.java
订单查询与更新 service/LastlegOrderService.java
业务 Inbox entity/LastlegEventInbox.java、mapper/LastlegEventInboxMapper.java
尾程订单、明细、状态历史 entity/LastlegOrder.java、LastlegOrderDetail.java、LastlegOrderStatusHistory.java 及对应 Mapper
独立尾程入仓单快照 entity/LastlegInboundOrder.java、mapper/LastlegInboundOrderMapper.java;按客户与来源入仓标识冻结 inboundCode、来源/根订单及目的仓,不以尾程订单行代替入仓单聚合
内部令牌保护 security/InternalServiceTokenGuard.java
入仓计划分页、转换与详情 inboundplan/controller/InboundPlanController.java、inboundplan/dto/InboundPlanRequests.java、InboundPlanListResponse.java、inboundplan/mapper/InboundPlanQueryMapper.java、inboundplan/service/InboundPlanService.java
托盘分配算法 inboundplan/service/PalletAllocator.java
FBA 预约创建、详情与编辑 InboundPlanController.java 的 /fba-appointments/**、inboundplan/service/InboundFbaAppointmentService.java、BatchFbaAppointmentRequest.java、UpdateFbaAppointmentRequest.java
PDA 入仓、实收、上架、合托、完成 inboundplan/pda/controller/、inboundplan/pda/service/InboundPdaWorkflowService.java;入口固定为 /api/pda/v1/last-leg/**,不得挂入平台浏览器 API
PDA 卸柜照片文件上传与归属校验 InboundPdaController.java 的 /unload-photos/files、inboundplan/pda/gateway/UnloadPhotoFileGateway.java、HttpUnloadPhotoFileGateway.java;File 类型固定 OVERSEAS_UNLOAD_PHOTO
卸柜照片与海外卸柜完成 Outbox inboundplan/pda/controller/InboundPdaController.java、inboundplan/pda/service/InboundUnloadCompletedOutboxService.java、entity/LastlegEventOutbox.java、mapper/LastlegEventOutboxMapper.java;多计划同柜只能在全柜完成后调用 publishContainerCompleted,按来源柜预订 ID 幂等发布一次,完成时刻与拍照时刻分离;事件模型见 ../common-event-contract/AGENTS.md
入仓后 SKU 库存余额、库位和流水 inventory/;平台只读查询与非出库库存命令分别从 inventory/query/controller/InventoryQueryController.java、inventory/command/controller/InventoryCommandController.java 进入
平台排车列表/详情与智能预排 dispatch/controller/DispatchQueryController.java、SmartDispatchController.java、dispatch/mapper/DispatchCandidateMapper.java、dispatch/service/DispatchService.java;草稿柜 entity/DispatchDraftContainer.java、mapper/DispatchDraftContainerMapper.java,托盘锁 DispatchPalletLock.java;入口 /api/platform/v1/last-leg/dispatches,范围开关与禁用写操作见“四期开发范围路由”
仓储资源调用 inboundplan/pda/gateway/WarehouseResourceGateway.java、HttpWarehouseResourceGateway.java
仓储转运、历史订单/入仓绑定、可选换标联动 transfer/controller/WarehouseTransferController.java、transfer/service/WarehouseTransferService.java
一件代发接收、SKU/箱唛库存 dropship/service/DropshipOrderService.java、dropship/entity/、dropship/mapper/
货物废弃、待审锁箱、审批扣减 discard/controller/CargoDiscardController.java、discard/service/CargoDiscardService.java
海外采购、客户下单、采购审核、客户/采购仓候选与操作流水 procurement/controller/、procurement/service/OverseasProcurementService.java;OpenAPI src/main/resources/openapi/overseas-business-v1.yaml
美国/本土卡车订单 trucking/controller/PlatformUsTruckOrderController.java、MerchantUsTruckOrderController.java 及同子域 Service/DTO
本土散板订单 looseboard/controller/PlatformLocalLooseboardController.java 及同子域 Service/DTO/Entity/Mapper;OpenAPI src/main/resources/openapi/overseas-business-v1.yaml
海外仓报价、月度汇率、车辆主数据 masterdata/quote/、masterdata/exchange/、masterdata/vehicle/;OpenAPI src/main/resources/openapi/overseas-master-data-v1.yaml;车辆档案不含派送履约历史
数据库基线、表索引与中文注释契约 src/main/resources/db/lastleg.sql、src/test/java/com/baiyue/lastleg/schema/SchemaChineseCommentContractTest.java
测试 src/test/java/com/baiyue/lastleg/
真实事件消费验收 src/test/java/com/baiyue/lastleg/service/TaillegRealConsumerAcceptanceTest.java;覆盖真实 V2 建单、独立入仓单快照及下游转运/换标可消费性

四期开发范围路由

  • 四期在本服务内只进入尾程订单、入仓计划/PDA 入仓、换标、产品与箱唛快照、库存、海外采购和本土卡车;本土散板新增实现也归本服务的独立稳定子域。
  • dispatch/、delivery/、出库单、PDA 出库拣货、派送和其他库存离仓能力虽然已存在于服务代码或表结构中,但不属于当前四期开发与验收范围,不得因代码已存在而自动纳入。
  • 历史排车编辑/取消/出库、PDA 出库和 delivery/ Controller 默认不注册;只有后续阶段明确启用 lastleg.future-outbound-api.enabled=true 才可恢复。平台排车列表与详情由 lastleg.dispatch-query-api.enabled=true 独立启用;入库单智能排车候选、草稿锁定/解锁/释放和预排创建由 lastleg.smart-dispatch-api.enabled=true 独立启用。这些排车平台入口均不接收 customerId:排车列表跨客户分页,详情按全局排车单号定位后使用记录自身客户范围加载明细;智能排车候选未传计划 ID 时跨客户查询,传入时根据计划 ID 解析范围;托盘移入草稿时立即以操作人和随机草稿标识锁定,移除或关闭时释放,草稿锁超时失效;预排创建根据所选托盘 ID 在服务端解析并校验唯一客户范围,并将当前操作人的草稿锁原子转换为正式排车锁。预排只能创建待出库排车并锁定托盘,不得借此开放编辑、取消、depart、PDA 出库或派送。四期平台库存 Controller 不映射 allocate、unallocate、pick、ship。
  • 海外仓库、库位、实物托盘和资源锁归 warehouse-overseas-service/;浏览器 API 统一经 gateway-overseas/,本服务不得复制仓储资源主数据或另建公网认证入口。

数据库表索引与注释约束

业务域 表名 中文含义
核心订单与事件 ll_loading_*、ll_event_*、ll_order*、ll_inbound_order* 事件收件/发件、尾程订单、明细及状态历史
入仓计划与作业 ll_inbound_plan*、ll_inbound_pda*、ll_inbound_pallet_merge、ll_inbound_fba_appointment* 入仓计划、托盘分配、PDA 作业、合托及 FBA 预约
库存 ll_inventory_*、ll_inbound_stock_receipt 库存余额、仓位、流水、命令幂等及实收快照
派车与出库 ll_dispatch_*、ll_outbound_*、ll_delivery_order 派车、PDA 拣货、出库及派送
转仓与换标 ll_warehouse_transfer_*、ll_relabel_* 转仓单、库存转移、目标收货及换标
一件代发与废弃 ll_dropship_*、ll_cargo_discard_* 托盘/箱唛库存、流水和废弃审批
采购、卡车与本土散板 ll_overseas_procurement_*、ll_us_truck_*、ll_local_looseboard_* 海外采购、美国卡车运输及本土散板订单
通用资料 ll_overseas_quote*、ll_monthly_exchange_rate*、ll_vehicle 海外仓报价、月度汇率及车辆档案;不保存车辆派送履约历史
  • 新增或修改表时,表 COMMENT 和每个普通字段的 COMMENT 必须填写准确的中文业务含义,不得只写英文、字段名或类型名。
  • SchemaChineseCommentContractTest 自动扫描全部 ll_ 表,无需维护表名白名单;新增字段必须同步更新基线 SQL、建表增量和存量备注迁移,增量脚本的 ADD/MODIFY COLUMN 不得丢失中文备注。
  • 表备注、字段备注和索引变更必须可重复执行;存量库的备注修订通过统一增量脚本落地,不依赖基线建表语句。

事件建单规则

  • 只接受冻结契约支持的事件类型和版本;校验事件 ID、租户、区域、Payload 哈希及必要字段。
  • 同一实际集装箱 containerNo 生成一个共享业务尾程单号;payload.orders 每项按 sourceInboundId 独立落一条雪花 ID ll_order,并保存对应明细和初始状态历史。整柜操作不使用 cabinetNo。
  • ONE_CLICK_DROPSHIP 每个来源入仓单必须携带一个或多个不可变来源托盘快照;每托按 SKU 携带箱数、数量和箱唛。校验订单汇总一致、托盘号/SKU/箱唛唯一后,按托建立档案及 SKU 库存,并建立箱唛和流水。仓库实物托盘由 Warehouse API 分配,不得覆盖来源托盘快照。
  • 其他订单类型只建立入仓单维度的尾程订单与冻结明细,来源 palletCount 强制为 0;后续 PDA 托盘属于海外仓作业资源。
  • 整个事件消费在一个事务内完成;任意订单失败时不得留下部分订单。
  • 相同事件重复投递返回既有结果,不重新生成单号或插入明细。来源入仓单唯一约束是最终防线。
  • 内部接口先执行常量时间令牌校验;缺失或错误令牌不得进入消费事务。
  • PDA 入仓任务完成前必须先通过 /unload-photos 保存非空且不重复的卸柜照片文件 ID;照片上传时间由服务端记录,预计报空时间固定为照片上传时间加两天。完成入仓时,库存入账、计划/任务状态推进与 OVERSEAS_CONTAINER_UNLOADED V1 Outbox 必须处于同一事务;事件绑定来源头程货柜身份,不得从前端请求拼装或回查头程数据库。
  • 海外 PDA 柜号签收只允许平台 WAREHOUSE_PICKER 使用 lastleg:pda:operate;PDA 不接收 customerId,候选跨客户读取,选柜时从柜内计划唯一解析并冻结真实客户。未完成会话按平台操作账号和柜号分别全局唯一,后续照片、扫码、实收、库存与完成操作只使用会话客户范围;平台管理员和客户账号不得进入该作业入口。

查询与租户约束

  • 平台查询范围由可信身份/平台权限决定;商户查询只能使用认证身份中的客户 ID。
  • 尾程平台只读查询接口的 customerId 为可选筛选条件:平台身份省略时查询全部客户数据,传入时按指定客户过滤;商户身份忽略客户端传入值并始终按 Token 中的自身客户隔离。创建、编辑、审核等需要明确目标客户的写接口仍必须传入 customerId。
  • 常规入仓库存余额以客户、海外仓、目的仓和入仓单为唯一业务维度并汇总箱数;SKU 继续保存在箱唛、实收和流水快照中,余额 SKU 仅作单 SKU 展示或以 MIXED 标识多 SKU,不参与当前唯一维度。
  • 列表、详情、导出和更新必须使用同一租户边界,不能仅在列表过滤而让详情或更新越权。
  • 目的仓变更必须写状态/操作历史或审计证据,并使用版本控制防止并发覆盖。
  • 货物废弃只使用可核对 SKU 和箱唛的一件代发库存。创建申请只能将箱从 AVAILABLE 锁定为 DISCARD_PENDING,不得扣减 SKU 箱数;实际扣库存节点固定为具备 lastleg:cargo-discard:approve 权限的仓库/PDA 审核人确认废弃时,并且必须在审核事务内调用专用 discard adjustment。该 adjustment 必须将箱改为 DISCARDED、写逐箱业务流水及唯一幂等键,并校验 扣减前箱数 - 废弃箱数 = 扣减后箱数 且逐箱数等于申请总箱数;任一环节失败须整体回滚。拒绝申请只释放锁箱,不得扣库存。
  • 海外采购客户下单固定进入 PENDING_REVIEW;四期采购只维护采购订单、审核、入库数量、候选快照和操作流水,不提供采购出库端点、出库记录或出库数量。采购单据不得写入或冒充 available_packages;只有海外仓 PDA 完成实收后,InboundStockReceiptService 才能以 PDA_STOCK_IN:{taskId}:{allocationId} 幂等键调用库存 stockIn 转入可用库存。禁止通过通用平台接口绕过 PDA 入可用库存。
  • 派车状态只允许 PDA 拣货、完成和出库动作推进,普通派车编辑接口不得修改状态。PDA 写操作要求 lastleg:pda:operate;后台库存表单操作要求 lastleg:inventory:manage,盘点调整另要求 lastleg:inventory:adjust,转仓库存操作要求 lastleg:warehouse-transfer:manage。
  • ll_order.current_status 只保存尾程主流程状态;换标、转仓、出库和派送等子单精确状态保存到各自单据并汇总到 sub_order_status,不得再用子单状态覆盖主流程状态。PDA 入仓及库存落账完成后,主流程状态固定推进为 INBOUND_COMPLETED。

修改与验证

  • 表字段、注释和索引同步维护基线 SQL 与统一增量 SQL;生产/存量库只执行增量脚本。
  • 事件契约变化同时检查 common-event-contract 版本、Event Bridge 消费方和旧 Payload 哈希兼容。
  • 定向验证:mvn -pl lastleg -am test。
  • 事件链路变更至少覆盖重复事件、相同来源入仓单、事务回滚、并发单号、内部令牌和租户越权测试。