Files
docs/头程到尾程分阶段流程/阶段五-海外接柜库存与库内服务.md

408 lines
19 KiB
Markdown
Raw Permalink 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.
# 阶段五:海外接柜、库存与库内服务
> 对应全景流程:F28~F33。
> 阶段起点:实际船节点达到 `PICKUP_READY`,整柜尾程计划和海外托盘/库位资源已经就绪。
> 主链终点:整柜收货完成,库存同事务入账,尾程主状态为 `INBOUND_COMPLETED`。
> 并行范围:库存查询、托盘作业、暂扣、换标、仓储转运和货物废弃。
## 1. 阶段目标和边界
本阶段把海运在途货物转化为海外仓可核对库存:
1. 海外 PDA 操作员按真实柜号认领待卸货柜;
2. 核对国内装柜证据并拍摄海外签收三类照片;
3. 按 FBA 散货、OVERSEAS 逐箱和一件代发整托三种模式实收;
4. 整柜核平后一次完成计划、任务、库存和卸柜事件;
5. 提供库存、位置、流水、托盘以及已开放的库内作业;
6. 对单票执行暂扣/解除;
7. 处理换标、仓储转运和一件代发货物废弃。
本阶段不负责海外配送排车、出库发车和最终派送。入仓完成只是后续履约资格之一;有效暂扣、换标未完成或库存被其他子单锁定时仍不能出库。
## 2. 角色、终端和权限
| 角色 | 终端 | 主要操作 | 边界 |
|---|---|---|---|
| 海外仓 PDA 操作员 | 海外 PDA | 认领柜、拍照签收、实收、完成整柜、库内作业 | 需 `OVERSEAS_WAREHOUSE_PDA_OPERATOR` 和 `lastleg:pda:operate`,仓库由 Token 固定 |
| 海外仓主管 | Admin | 查询入仓、库存、托盘、异常,处理授权的库存/暂扣操作 | 不用内部 ID 修改他仓资源 |
| 企业操作员 | Client | 查看本企业库存,发起换标、转运、废弃等自助服务 | 不查看其他客户或直接改实物托盘 |
| 换标作业员 | 海外 PDA | 认领、扫描旧/新标、拍照、提交复核 | 不自行批准复核或客户确认 |
| 换标复核员 | Admin | 退回返工、核对作业事实 | 已由客户确认后不能退回 |
| 废弃审核员 | Admin/PDA | 审批一件代发废弃并触发实际扣减 | 创建申请时不得直接扣库存 |
| Lastleg | 后端 | 入仓作业、库存业务、子单、状态和事件权威 | 不拥有物理仓/托盘主档 |
| Warehouse Overseas | 后端 | 海外库位、实物托盘、资源锁和物理状态 | 不拥有库存客户归属和尾程订单 |
平台管理员和普通客户账号不能进入海外 PDA 柜号签收入口。PDA 请求不接收 `customerId` 或可切换的 `warehouseId`;客户和仓库范围由柜内计划、入仓码和登录 Token 解析。
## 3. 作业前检查
- 操作员账号已绑定唯一 `ACTIVE + OVERSEAS + RECEIVING` 海外仓;
- 换仓或清空绑定后旧 Token 已失效;
- 实际节点达到 `PICKUP_READY` 或更晚;
- 柜内每票订单为 `INBOUND_PLANNED`;
- 所有计划已经绑定真实托盘、库位和资源锁;
- `resourcePendingPlanCount=0`;
- 真实柜号、来源柜聚合键、预计到仓和入仓码完整;
- 普通货计划箱数、一件代发来源托盘/SKU/箱唛快照可核对;
- PDA 网络、相机和扫码能力正常。
只要任一计划仍缺真实资源,就不能准备、签收或开始该柜。PDA 首次扫码只确认计划阶段已预留资源,不在现场重新分配托盘或库位。
## 4. F28 海外 PDA 柜号签收
### 4.1 查看待卸货柜
入口:海外 PDA → 拆柜收货。
候选按物理柜跨客户聚合,仅返回达到 `PICKUP_READY` 且计划资源完整的柜。列表使用真实集装箱号、预计到仓和接柜仓,不显示内部柜次 ID。
操作员选择柜后:
1. 系统按平台账号和柜号创建/恢复唯一未完成会话;
2. 柜被原子认领到当前 Token 固定仓库;
3. PDA 锁定当前柜,不允许随意切换;
4. 展开查看柜内全部入仓码、客户隔离任务、目的仓、计划托数和箱数;
5. 核对当前仓库与现场一致。
柜级认领允许同柜多客户,但后续每票任务、扫码、库存和流水仍使用入仓码所属的真实客户。
### 4.2 查看国内装柜照片
签收前展开国内五类只读证据:空柜、装载过程、接近完成、满柜/关门前、带铅封号照片。
- 证据仅用于现场对照,不允许 PDA 修改;
- 单张图片加载失败时提供重试;
- 单图失败不阻断拆柜,但应保留加载异常;
- 现场发现柜号、铅封或外观明显不符时,应先走异常处理而不是盲目签收。
### 4.3 拍摄三类签收照片
依次现场拍摄并上传:
1. `LICENSE_PLATE`:承运车辆车牌;
2. `CONTAINER_SEAL`:开封前柜门和铅封;
3. `DOOR_OPEN`:开柜现场。
每类固定一张当前有效照片,允许在上传成功后更换。更换失败保留原照片;预览走鉴权下载,不持久化设备临时路径。三类照片全部齐全后才能确认签收。
### 4.4 确认签收
点击确认后,服务端复核柜号、仓库、会话、照片和版本,记录签收人和时间并进入收货。首次开始收货的 `receiving_at` 是整柜唯一实际到仓时间,回传 Admin 清关提柜列表;不能用预约或预计时间代替。
## 5. F29 三类实收操作
### 5.1 通用规则
每次实收都必须:
- 使用当前柜会话;
- 由业务箱码、入仓码或来源托盘定位唯一计划;
- 扫描计划已绑定的实物托盘码;
- 使用稳定幂等键和当前版本;
- 不超过该计划待收数量;
- 写入当前客户、仓库、目的仓和库存来源;
- 返回最新已收、待收和异常信息。
`assigned/mergeAllowed/urgent/mergeHint` 只消费服务端结果。可合托只是现场选择,不改变收货资格,也不是整柜完成门禁。
### 5.2 FBA 散货批量收货
1. 在柜内选择目标入仓码/目的仓分组;
2. 扫描冻结 SKU 或用于定位分组的业务码;
3. 扫描计划绑定的实物托盘码;
4. 输入本次放入托盘的箱数;
5. 核对本次、累计和剩余箱数;
6. 提交 bulk 收货;
7. 继续下一托或下一入仓码。
FBA bulk 不提交 `skuCode` 作为库存归属,服务端按计划明细分配。首次扫业务码只选择分组,不自动多收一箱。超收返回冲突且库存不变化。
### 5.3 OVERSEAS 逐箱收货
1. 扫描国内最终实装的稳定箱唛;
2. 服务端自动解析唯一入仓码和计划;
3. 扫描目标实物托盘;
4. 核对箱码、目的模式和托盘兼容性;
5. 确认单箱收货;
6. 已收箱再次扫描必须冲突,不重复入账。
OVERSEAS 必须使用跨区冻结的逐箱事实,禁止改为手工输入批量箱数。
### 5.4 一件代发整托收货
1. 选择柜内一件代发计划;
2. 扫描国内冻结的来源 `DP` 托盘码;
3. 查看该托盘所属入仓码、箱数、SKU 和箱唛;
4. 扫描海外计划绑定的实物托盘;
5. 使用 `/current/receipts/pallet` 整托确认;
6. 服务端按来源托盘原子核平全部箱件和 SKU。
禁止逐箱拆收、改写国内托盘成员或按商品名称猜配。一个国内来源托盘失败时整托不落账。
### 5.5 独立收货与合托
- 独立收货:扫描计划分配的新托盘;
- 合托:仅在 `mergeAllowed=true` 时,扫描同目的仓已使用托盘;
- 合托后同一实物托盘可以包含多张入仓单,但每票组成数量独立保存;
- 单票全部收完不要求因“可合托”再执行一次合托动作。
## 6. F30 整柜完成、库存入账与国内回写
### 6.1 完成前检查
点击完成整柜前核对:
- 柜内所有计划 `pendingPackages=0`;
- FBA 汇总数量、OVERSEAS 箱码和一件代发来源托盘均核平;
- 每个库存组成已绑定真实托盘和库位;
- 三类签收照片存在;
- 通过 `/unload-photos` 保存了非空且不重复的卸柜照片文件 ID;
- 没有结果不确定的在途命令或版本冲突。
### 6.2 原子完成
服务端在同一事务内:
1. 完成每票 PDA 任务和入仓计划;
2. 将尾程主状态推进为 `INBOUND_COMPLETED`;
3. 将 `FIRST_LEG` 在途数量转为海外仓可用/对应状态库存;
4. 写库存余额;
5. 写按托盘和入仓单拆分的库存位置;
6. 写进销存流水和实收快照;
7. 更新托盘组成;
8. 创建唯一 `OVERSEAS_CONTAINER_UNLOADED` V1 Outbox。
任一步失败时不能只完成状态、不入库存,或只入库存、不完成任务。相同完成请求重放返回既有结果,不重复增加库存。
### 6.3 国内回写
事件绑定来源头程柜次身份,由服务端冻结,不接受 PDA 拼装。Firstleg 消费后:
- 记录卸柜完成时间;
- 记录照片上传/完成事实;
- 计算预计还空时间;正式业务以卸柜完成后 72 小时为准;
- 更新目的港码头拖车的还空预警;
- 以事件 ID、哈希和聚合版本防重与防乱序。
此事件不代表已经还柜;实际还柜另行推进 `EMPTY_RETURNED`。
## 7. F31 库存、盘点、移库和托盘
### 7.1 Admin 库存查询
入口:Admin → 海外仓 → 库存管理。
核对维度:客户、实际海外仓、目的仓、入仓单、可用/冻结/占用箱数、SKU 展示、实物托盘和库位。余额唯一业务维度不以托盘为归属;多 SKU 可显示 `MIXED`,完整 SKU 保存在箱唛、实收和流水快照。
列表、详情、汇总和 CSV 必须使用同一权限范围,并默认排除所有数量桶均为零的维度。
### 7.2 托盘与位置
入口:Admin → 海外仓 → 托盘管理。
- 实物托盘和库位是平台公共资源,`customer_id=0`;
- 资源锁保存真实业务客户范围;
- 同一托盘可包含多票,每票箱数保存在库存位置组成;
- 托盘是 PDA 出库作业单位,不是库存所有权单位;
- 普通入仓只证明某票有多少箱在该托盘,不证明每个箱唛精确位于哪个托盘;
- 标签只按真实托盘编码补打,不重新生成编号。
### 7.3 PDA 现场查询
入口:海外 PDA → 库存/库位/托盘查询。
扫描稳定业务码后查看服务端最新事实,只展示箱码、托盘码、库位码、仓库名称等业务标识,不以内建 ID 回退。
### 7.4 商品移库
入口:海外 PDA → 商品移库。
1. 扫描来源托盘;
2. 查看组成和当前版本;
3. 扫描同仓目标库位;
4. 核对目标可用;
5. 提交整托移库;
6. 服务端原子释放源真实库位并占用目标库位;
7. 409 冲突后重新扫描,不能用旧版本重试覆盖。
虚拟库位保持 `ACTIVE`;真实库位与托盘同步 `IDLE/OCCUPIED`。
### 7.5 托盘组、拆、换、解绑
PDA 扫描托盘后按服务端返回的 `palletVersion`、`positionVersion` 执行。每次操作必须核对库存组成并使用稳定幂等键;跨服务业务失败走显式补偿,Lastleg 不直接修改 Warehouse Overseas 的 `wh_` 表。
### 7.6 库存盘点
盘点底层支持创建、恢复、计数、提交、幂等和版本冲突处理;当前海外 PDA 工作台不开放入口,因此不能宣称已完成现场页面验收。需要盘点时以正式开放入口、权限 `lastleg:inventory:adjust` 和最终库存流水为准。
## 8. F32 暂扣与解除
### 8.1 新增暂扣
只允许尾程订单已经 `INBOUND_COMPLETED` 且尚未进入出库流程时新增:
1. Admin 打开尾程订单;
2. 核对当前库存和后续占用;
3. 填写暂扣原因和必要凭证;
4. 携带订单版本和幂等键提交;
5. 写不可变历史并发布暂扣事件。
暂扣只作用于本票,阻断该票排车和出库;不影响同柜其他客户/订单,也不回退入仓计划、实收、库存或主状态。
### 8.2 解除暂扣
风险解除后填写原因并提交当前版本。解除不受“尚未进入出库”这一新增条件限制,但不能抹掉已发生的历史或释放其他子单仍合法持有的库存锁。
## 9. F33 换标、仓储转运和废弃
### 9.1 换标申请
入口:Client → 海外仓服务 → 换标。
1. 客户从本企业可用库存选择目标箱/数量;
2. 选择换标类型:SKU、箱唛或混合;
3. 填写旧标、新标和数量;
4. 提交后系统冻结对应库存,防止重复申请和出库占用;
5. 生成换标子单,精确状态保存在子单和 `sub_order_status`。
普通入仓没有逐箱唛到托盘的精确快照时,客户填写的我方箱唛是换标作业主键;库存位置只是冻结记账锚点和现场大概位置,不能据此声称箱唛一定在某托。
### 9.2 PDA 换标作业
入口:海外 PDA → 换标收货/执行。
1. 认领任务并进入处理中;
2. SKU 类型逐条核对旧 SKU、新 SKU 和批准件数;
3. 箱唛类型扫描仓库唛头和新 FBA 箱唛;
4. 混合类型分别完成 `MIXED_CARTON`、`MIXED_SKU`,两项齐全才计一箱完成;
5. 拍摄并上传作业照片;
6. 必要时按实际来源拆托、换托并记录 `PALLET_BIND`;
7. 提交后任务进入 `WAIT_REVIEW`,申请进入 `CUSTOMER_CONFIRM_PENDING`。
换标移动只能移动本申请 `hold_packages`,不得解冻为普通可用库存。已生成出库单或开始拣货后禁止随意改绑。
### 9.3 返工与客户确认
平台复核发现问题时,使用专用返工接口携带任务版本、幂等键和必填备注退回。上一轮事实和照片归档,当前轮计数清零;客户已确认后不能退回。
客户核对结果后确认,服务端原子完成复核并释放后续资格。换标主流程相关单据进入 `WAIT_OUTBOUND`;客户确认前不得出库。
### 9.4 仓储转运
入口:Client → 海外仓服务 → 仓储转运。
1. 客户选择本企业可用库存和目标仓/运输要求;
2. 提交转运申请;
3. 平台审核通过或驳回;
4. 通过后冻结对应库存并进入转运出库;
5. 实际移出和目标收货按转运单、库存流水和资源操作闭环。
转运状态保存在子单,不覆盖尾程主状态 `INBOUND_COMPLETED`。
### 9.5 一件代发货物废弃
废弃只使用能够核对 SKU 和箱唛的一件代发库存:
1. 客户选择箱唛并创建申请;
2. 箱从 `AVAILABLE` 锁定为 `DISCARD_PENDING`,此时不扣 SKU 箱数;
3. 有 `lastleg:cargo-discard:approve` 权限的仓库/PDA 人员现场审核;
4. 拒绝时只释放锁,不扣库存;
5. 通过时在同一事务调用专用 discard adjustment;
6. 箱进入 `DISCARDED`,写逐箱流水和唯一幂等键;
7. 校验扣减前箱数减废弃箱数等于扣减后箱数,且逐箱合计等于申请总数;
8. 任一失败整体回滚。
## 10. 状态与数据归属
| 维度 | 关键状态 | 说明 |
|---|---|---|
| 柜级收货会话 | 待签收/收货中/完成 | 绑定平台账号、柜和实际仓 |
| 入仓计划/PDA 任务 | 已计划→作业中→完成 | 每票按真实客户隔离 |
| 尾程主状态 | `INBOUND_PLANNED → INBOUND_COMPLETED` | 子单不能覆盖 |
| 库存 | `FIRST_LEG` 在途→海外仓库存各数量桶 | 入账必须与状态同事务 |
| 暂扣 | 有效/解除 | 正交阻断排车出库 |
| 换标/转运/废弃 | 各自子状态 | 汇总到 `sub_order_status` |
| 物理资源 | 托盘、库位、锁和版本 | Warehouse Overseas 权威 |
## 11. 异常与恢复
| 场景 | 处理方式 |
|---|---|
| `PICKUP_READY` 前看不到柜 | 等待真实节点,不手工绕过候选门禁 |
| 操作员仓库绑定错误 | 重新绑定并重新登录,旧 Token 失效 |
| 三类照片上传失败 | 保留旧图/现场重试,不伪造签收 |
| FBA 超收 | 冲突且库存不变,核对累计/剩余数 |
| OVERSEAS 重复箱码 | 冲突且不重复入账 |
| 一件代发来源托盘不符 | 整托拒绝,核对国内冻结快照 |
| 实收命令超时 | 查询当前实收记录,复用原幂等键 |
| 任一计划未清零 | 禁止完成整柜,定位具体入仓码 |
| 完成事务失败 | 状态和库存整体回滚后重试原命令 |
| 移库/托盘版本冲突 | 重新扫描获取最新版本 |
| 暂扣票参与排车 | 服务端拒绝,先按权限解除 |
| 换标一项未完成 | 混合单不计整箱完成 |
| 换标被退回 | 展示备注,清理设备草稿后按新轮返工 |
| 废弃审批失败 | 锁定和扣减整体回滚,不产生半套流水 |
## 12. 阶段完成判定
测试环境综合证据 `baiyue-firstleg/reports/admin-full-postdeploy-66c2651b.json` 已覆盖海外 PDA、收货、库存、库内服务和 `phase5-overseas-fulfillment`;上述模块失败数均为 0。这里的清单继续保留为逐票验收条件,不能用综合报告替代具体柜次的业务核对。
主链完成必须满足:
- [ ] 柜号由正确仓库操作员认领
- [ ] 国内五类证据可对照,海外三类签收照片齐全
- [ ] 实际到仓时间来自首次收货会话
- [ ] FBA、OVERSEAS、一件代发均按对应模式实收
- [ ] 每票 `pendingPackages=0`
- [ ] 库存余额、位置、流水和托盘组成数量一致
- [ ] 入仓计划和 PDA 任务完成
- [ ] 尾程主状态为 `INBOUND_COMPLETED`
- [ ] 卸柜 Outbox 唯一且国内幂等回写成功或可重试
- [ ] 重放任何实收/完成命令不会重复库存
库内服务完成以各子单独立判断;它们不改变已经成立的 `INBOUND_COMPLETED`,但未完成的冻结、暂扣或占用必须继续阻断阶段六相应库存。
## 13. 易用性与数据流评审问题
1. 柜级认领前是否需要把计划/资源缺口直接展示为可操作诊断?
2. 国内五类照片与海外三类照片是否应提供左右对照和异常快捷登记?
3. 三类收货模式是否需要在页面用颜色/图标强提示,防止操作员走错批量或逐箱入口?
4. FBA 首次扫码只选分组、不计数的规则是否足够直观?
5. 合托提示是否应同时展示托盘已有客户、入仓单组成和容量风险?
6. 整柜完成前是否需要按入仓码显示“剩余几箱/哪几个来源托盘”?
7. 卸柜完成后 72 小时还空预警应由谁接收、何时升级?
8. 库存余额、库存位置、托盘组成和箱唛明细是否需要统一钻取入口?
9. 当前盘点入口隐藏,正式业务发生账实差异时由哪个可见流程处理?
10. 暂扣原因、换标冻结、转运占用和废弃锁箱是否应统一显示“不可用数量来源”?
11. 换标混合任务双 Tab 的完成条件是否需要总进度和缺项提示?
12. 废弃从“申请锁定”到“现场实际扣减”的状态文案是否足够清楚?
## 14. 阶段六交接包
交给阶段六“海外排车、出库、派送与回写”的输入包括:
- `INBOUND_COMPLETED` 尾程订单和实际海外仓;
- 客户、入仓单、目的仓和可用库存余额;
- 每个实物托盘的多票组成、库位和版本;
- 一件代发来源托盘、SKU 和箱唛可用状态;
- 有效暂扣、换标、转运、废弃及其他库存锁;
- 可出库数量、已占用数量和相应库存流水;
- 客户/平台要求的派送地址、FBA 仓和服务属性。
## 15. 事实来源
- `docs/海外仓业务/README.md`
- `docs/海外仓业务/虫虫出海全流程人工验收手册.md`
- `apps/pda-overseas-uniapp/AGENTS.md`
- `apps/pda-overseas-uniapp/src/pages/operation/operation.vue`
- `apps/pda-overseas-uniapp/src/pages/pallet/pallet.vue`
- `apps/pda-overseas-uniapp/src/pages/move/move.vue`
- `apps/pda-overseas-uniapp/src/pages/relabel/relabel.vue`
- `baiyue-firstleg/lastleg-service/AGENTS.md`
- `baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/pda/`
- `baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/pda/`
- `baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/relabel/`
- `baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/transfer/`
- `baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/discard/`
- `baiyue-firstleg/warehouse-overseas-service/AGENTS.md`