| name | fbo-fill-boxes |
| description | Ozon FBO 填装箱 + 箱唛 PDF + 对照表 (fill_boxes_labels.py). 当用户说"填箱"、"申报装箱"、"拉箱唛"、"拉 PDF 标签"、"箱唛打印"、"已建单要填箱"、"补上装箱明细"、"跑 skip-fill 后的下一步"、"单个 order 填箱" 时触发。支持 (a) 单 order_id 填; (b) 批量按 plan-result.json 填. |
FBO 填装箱 + 箱唛 PDF + 对照表
输入已建好的 supply_order → 查实际 items → 切箱 → /v1/cargoes/create → 拉箱唛 PDF → 写 Excel 对照表.
脚本: /Users/mac/Documents/ozns/丝绸生活/海外仓发货表/2026-04-23海外仓发货/fill_boxes_labels.py (~405 行)
触发场景
- "已经建好 order 100452984, 帮我填箱 + 拉箱唛"
- "
create_fbo_plan.py --skip-fill 跑完了, 现在要填"
- "restock_planner 建的一批 order, 批量填装箱"
- "重新拉箱唛 PDF"
- "对照表没导出, 补一份"
工作原理
- 从
/v3/supply-order/get 拿 order detail + supply_id
- 从
/v1/supply-order/bundle 拿 Ozon 实际接受的 items (很关键 — 任何模式都可能过滤 SKU)
- 按实际 items 切箱 (件/box_size, 最后一箱余数)
- 调
/flow/upload-cargoes: cargoes/create → cargoes/create/info 轮询 → cargoes-label/create → cargoes-label/get → PDF 保存到 LABEL_DOWNLOAD_DIR
- 写 Excel 对照表 (22 列和
/fbo-plan 产物同结构)
前置
- 4182 服务健康 (
/fbo-service-up)
- order_id 已存在 + supply 状态
DATA_FILLING (未申报过箱) — 否则会报错
两种模式
模式 A: 单 order 填 (用户直接报 order_id)
cd /Users/mac/Documents/ozns/丝绸生活/海外仓发货表/2026-04-23海外仓发货
python3 fill_boxes_labels.py \
--order-id 100452984 \
--offer-id Q_MeiGongDao-HeiSe-Free \
--sku 3214793665 \
--qty 4200 \
--cluster Москва \
--box-size 300 \
--account 丝绸生活
必填 (单 order 模式): --order-id + --offer-id + --sku + --qty + --box-size.
可选: --cluster (写进对照表), --account (默认 丝绸生活), --fbo-service (默认 127.0.0.1:4182), --out-xlsx, --dry-run.
模式 B: 批量按 plan-result.json 填
plan-result.json 是 restock_planner.py --execute 产出的 fbo_plan_*.result.json, 里面有已建好的 order_ids.
python3 fill_boxes_labels.py \
--plan-result /path/to/fbo_plan_Q_MeiGongDao-HeiSe-Free_20260422.result.json \
--box-size 300 \
--account 丝绸生活
脚本会逐行读 result.json, 对每条有 order_ids 的记录, 逐 order 申报.
关键参数
--order-id 或 --plan-result (二选一, 互斥必填)
--box-size (必填): 单箱装箱率
--offer-id / --sku / --qty: 单 order 模式必填
--cluster: 对照表列用, 单 order 模式可选
--account: 账号名 (默认 丝绸生活)
--fbo-service: 默认 http://127.0.0.1:4182
--out-xlsx: 默认 fbo_mapping_<date>.xlsx
--dry-run: 只切箱 + 打表, 不调 Ozon (保护已建好的单, 看切箱计划是否合理)
产出物
- Excel 对照表:
fbo_mapping_<YYYYMMDD_HHMMSS>.xlsx (22 列)
- 箱唛 PDF: 落到
LABEL_DOWNLOAD_DIR (容器 /app/labels → 宿主 /Users/mac/Documents/ozns/github/ozon_fbo_shipment_service/labels/); 每 supply_id 一个 PDF
常见问题
Q1: 报 SUPPLY_ITEM_NOT_FOUND
原计划件数 ≠ supply 实际接受件数. 脚本已默认调 /supply-order/bundle, 所以不会发. 若还出, 说明 supply 后来被改过 (时段 update 可能引发), 重看 /supply-order/get 对一下数.
Q2: DATA_FILLING 之外的状态也想填
不行. Ozon 的 cargoes/create 只接受 DATA_FILLING 状态. SHIPPING_PREPARED 之后只能用 /supply-order/content/update 改.
Q3: PDF 下不下来, file_url 返 S3 URL
正常. /v1/cargoes-label/get 返的 file_url 是 presigned S3 (1h 过期), 脚本已自动下并落本地. /v1/cargoes-label/file/{guid} 这个路径是 404, 不要用.
Q4: 对照表少列 / 有空列
脚本沿用 create_fbo_plan.py 的 22 列 schema, 空集群/cargo_ids 就是空. 检查 order 是不是多 SKU 但只填了一个.
Q5: --dry-run 和真实跑差别?
dry-run 不会调 cargoes/create, 只 print 切箱方案 + 写 xlsx. 真实跑会建箱 + 拉 PDF.
实测 (2026-04-24)
- order 100452984 (Moscow, 4200 Q_MeiGongDao, CROSSDOCK) ✓ 单 order 模式跑通
- order 100532100 (NSK, 600 Q_ChongQiZui, CROSSDOCK) ✓ 跟在
create_fbo_plan.py 里 fill 阶段跑的
label 失败恢复 (cargo recovery)
/cargoes/create 已成功 (cargoes READY_TO_SUPPLY) 但 label/create 返 500/429 时, 不要重跑 /flow/upload-cargoes (会建重复 cargoes). 直接走恢复:
cargoes = post("/v1/cargoes/get", {"supply_id": supply_id})
cargo_ids = [c["cargo_id"] for c in cargoes["supply"][0]["cargoes"]]
post("/v1/cargoes-label/create", {"cargo_ids": cargo_ids})
post("/v1/cargoes-label/get", {"task_id": task_id})
curl -o supply_X.pdf "$file_url"
相关 memory: feedback_cargo_label_recovery.md
同步本 skill 的 .py 文件
bash /Users/mac/.claude/skills/sync_fbo_scripts.sh
相关 skill / memory
/fbo-service-up — 4182 服务运维
/fbo-plan — 建 plan + 自动 fill (默认行为, 不需要再单独 fill, 除非 --skip-fill)
/restock-to-fbo — 批量建 order, 产 plan-result.json 直接喂模式 B
- memory
reference_fill_boxes_labels.md — 脚本契约
- memory
feedback_always_verify_supply_actual_items.md — 必须 bundle 再切箱的原因
- memory
reference_ozon_fbo_api.md — cargoes-label PDF URL 细节