Files
shanxia2.0/docs/superpowers/plans/2026-08-26-pl-multi-stop-redesign.md
T
2026-08-27 14:23:18 +08:00

12 KiB
Raw Blame History

运输计划一车多卸重构 Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: 将运输计划从「1 供方 + 1 需方」升级为「1 装货段 + N 送货段」,并贯通归档、地磅、司机/现场链接、打印与历史迁移。

Architecture: 在 pl_plan 保留计划级主数据;新增 pl_plan_load / pl_plan_delivery 及段产品子表;链接与地磅按 stop_type+stop_id 关联;打印与归档按段规则聚合。详见 docs/superpowers/specs/2026-08-26-pl-multi-stop-redesign-design.md。

Tech Stack: FastAPI · SQLAlchemy · Pydantic v2 · Vue 3 · Element Plus · MySQL 5.7 · docs/sql/shanxia2.0.sql


文件结构(新建 / 主要修改)

职责 路径
装货/送货 ORM backend/app/models/pl_models.py
段 CRUD / 归档 backend/app/services/pl_plan_service.py(或拆 pl_plan_stop_service.py)
计划 API backend/app/api/pl/plan.py
安排/地磅 backend/app/services/pl_plan_service.py、backend/app/api/pl/transport.py
公网司机/现场 backend/app/api/public_site.py(或现有 public 路由)
DDL docs/sql/migrations/2026-08-26-pl-multi-stop.sql + 合并 docs/sql/shanxia2.0.sql
迁移脚本 backend/scripts/migrate_pl_plan_to_multi_stop.py
计划表单 web-admin/src/components/business/pl-plan-form-dialog/
送货段 UI 新建 pl-plan-load-section/、pl-plan-delivery-section/
选客户打印 新建 pl-plan-delivery-customer-select-dialog/
送提货/入库打印 pl-delivery-slip-print-dialog/、pl-inbound-slip-print-dialog/
归档弹窗 pl-plan-archive-dialog/、views/pl/plan-archive/index.vue
类型/API web-admin/src/api/pl/index.ts

Phase 1:数据库与模型

Task 1: DDL — 装货/送货段表

Files:

  • Create: docs/sql/migrations/2026-08-26-pl-multi-stop.sql

  • Modify: docs/sql/shanxia2.0.sql(归档后全量快照)

  • Step 1: 在 migration SQL 中创建 pl_plan_load、pl_plan_load_product、pl_plan_delivery、pl_plan_delivery_product

  • Step 2: pl_plan 增加 freight_remark VARCHAR(512) NULL

  • Step 3: pl_plan_contract 增加 stop_id VARCHAR(64) NULL;side 注释扩展 load/delivery

  • Step 4: pl_transport_db_link 增加 stop_type VARCHAR(20)、stop_id VARCHAR(64)(可空,兼容旧数据)

  • Step 5: 在本地库执行 migration 并验证表结构

Task 2: SQLAlchemy 模型

Files:

  • Modify: backend/app/models/pl_models.py

  • Modify: backend/app/schemas/pl/plan.py

  • Step 1: 新增 PlPlanLoad、PlPlanLoadProduct、PlPlanDelivery、PlPlanDeliveryProduct 类

  • Step 2: PlPlan 增加 freight_remark;PlPlanContract 增加 stop_id

  • Step 3: 新增 Pydantic:PlanLoadBody、PlanDeliveryBody、PlanStopProductBody、*Read 嵌套进 PlanWithProducts

  • Step 4: 运行 python -c "from app.models.pl_models import PlPlanLoad" 确认无导入错误

Task 3: 内部客户与地磅方向工具

Files:

  • Create: backend/app/services/pl_plan_stop_rules.py

  • Reuse: backend/app/services/pl_internal_customer.py

  • Step 1: 实现 resolve_stop_dibang_defaults(customer_name, stop_type) -> (generate_dibang, dibang_direction)

  • Step 2: 实现 warn_qty_imbalance(plan_products, load_products, delivery_products) -> list[str](仅返回警告文案)

  • Step 3: 单元测试(新建 backend/tests/test_pl_plan_stop_rules.py)覆盖山峡装货=出库、山峡送货=入库


Phase 2:计划 CRUD API

Task 4: 读取计划(含段)

Files:

  • Modify: backend/app/api/pl/plan.py

  • Modify: backend/app/services/pl_plan_service.py

  • Step 1: _row_to_dict / get_plan_detail 联查 load、deliveries、段产品、合同(按 stop_id)

  • Step 2: GET /transport/plan/{id} 返回 load、deliveries[]

  • Step 3: 列表 planApi.list 增加摘要字段 loadCustomerName、deliveryCustomerSummary(后端聚合)

Task 5: 创建/更新计划(全量段)

Files:

  • Modify: backend/app/services/pl_plan_service.py

  • Modify: backend/app/api/pl/plan.py

  • Step 1: create_plan_full 接受 load + deliveries[];事务内写段表 + pl_plan_product

  • Step 2: 校验:必须有 1 条 load、≥1 条 delivery;外部段合同非空

  • Step 3: 数量不平衡调用 warn_qty_imbalance,响应 warnings: string[](HTTP 200)

  • Step 4: update_plan 全量替换段(软删旧段产品行)

  • Step 5: 跑 python scripts/check_field_consistency.py 并修复差异

Task 6: 历史数据迁移

Files:

  • Create: backend/scripts/migrate_pl_plan_to_multi_stop.py

  • Step 1: 对无 pl_plan_load 的计划:supplier→load,customer/destination→delivery seq=1

  • Step 2: 复制产品行到 load_product / delivery_product;迁移 pl_plan_contract.side

  • Step 3: 已归档计划:把 inbound_* 写入 load 产品行,outbound_* 写入 delivery 产品行

  • Step 4: 干跑模式 --dry-run + 日志统计;正式执行前备份库


Phase 3:前端计划表单

Task 7: API 类型与表单数据模型

Files:

  • Modify: web-admin/src/api/pl/index.ts

  • Step 1: 增加 PlanLoad、PlanDelivery、PlanStopProduct 类型

  • Step 2: createFull / update body 含 load、deliveries

  • Step 3: 处理响应 warnings,ElMessage.warning 展示

Task 8: 装货段组件(单段)

Files:

  • Create: web-admin/src/components/business/pl-plan-load-section/index.vue

  • Step 1: 客户选择 + 合同多选(内部禁用);产品表从计划产品带出

  • Step 2: 地址/时间/联系/注意事项(复用地址选择组件)

  • Step 3: generateDibang 随内部客户自动勾选(装货=出库)

Task 9: 送货段组件(多段)

Files:

  • Create: web-admin/src/components/business/pl-plan-delivery-section/index.vue

  • Step 1: v-for 送货段卡片;支持增删、排序

  • Step 2: 每段:客户、合同、产品行、地址信息、地磅勾选

  • Step 3: 「从计划产品同步」按钮(新增段时带出默认行)

Task 10: 接入 PlPlanFormDialog

Files:

  • Modify: web-admin/src/components/business/pl-plan-form-dialog/index.vue

  • Step 1: 移除供方/需方区块;接入 load + delivery 组件

  • Step 2: 保存/保存并安排:组装 payload;展示 warnings

  • Step 3: 编辑回填:API 返回的 load/deliveries 写入 formData

  • Step 4: 复制计划:深拷贝段数据

Task 11: 查看弹窗与列表摘要

Files:

  • Modify: web-admin/src/components/business/pl-plan-view-tabs/index.vue

  • Modify: web-admin/src/views/pl/plan/index.vue

  • Step 1: 查看 Tab 增加「装货/送货」分段展示

  • Step 2: 列表客户列改为装货/送货摘要


Phase 4:安排运输与地磅

Task 12: 安排弹窗按段地磅

Files:

  • Modify: web-admin/src/components/business/pl-plan-arrange-dialog/index.vue

  • Modify: backend/app/services/pl_plan_service.py(create_transport_for_plan)

  • Step 1: 安排弹窗列出各段 generateDibang 勾选(可改)

  • Step 2: 按段调用地磅生成;pl_transport_db_link.stop_id 写入

  • Step 3: 调整运输:revoke 逻辑按段处理(沿用现有不可作废则阻断)


Phase 5:司机 / 现场链接

Task 13: 司机公网页分段上传

Files:

  • Modify: 公网司机页模板/Vue(miniprogram 或 web 公网页路径,按仓库现有 driver public 页定位)

  • Modify: backend/app/api/pl/plan.py 或 public 路由

  • Step 1: 司机页展示装货 + 全部送货段标题

  • Step 2: 每段独立附件上传 API:POST .../driver-feedback body { stopType, stopId, urls }

  • Step 3: 管理端 PlPlanViewTabs 运输信息 Tab 按段展示司机附件

Task 14: 现场公网页(仅内部段)

Files:

  • Modify: 现场公网页 + pl_transport_site_service.py

  • Step 1: 单 token 页面仅渲染 is_internal && generate_dibang 的段

  • Step 2: 每段:数量必填 → 附件;校验顺序

  • Step 3: 外部送货段不在现场页出现


Phase 6:打印

Task 15: 送提货单选客户

Files:

  • Create: web-admin/src/components/business/pl-plan-delivery-customer-select-dialog/index.vue

  • Modify: web-admin/src/views/pl/plan/index.vue(打印入口)

  • Step 1: 统计送货段去重 customer_id;仅 1 个客户时跳过弹窗

  • Step 2: ≥2 客户时弹窗单选;确认后带 customerId 打开 PlDeliverySlipPrintDialog

Task 16: 送提货单数据聚合

Files:

  • Modify: backend/app/api/pl/plan.py(或 print 专用 endpoint)

  • Modify: pl-delivery-slip-print-dialog/index.vue

  • Modify: web-admin/src/utils/pl-delivery-slip-template.ts

  • Step 1: 后端按 customerId 合并该客户所有送货段产品行

  • Step 2: 收货单位 = 客户名;地址/联系人 = seq 最小送货段

  • Step 3: 模板变量对齐新字段

Task 17: 入库单 / 分装单

Files:

  • Modify: pl-inbound-slip-print-dialog/index.vue

  • Modify: pl-subpack-slip-print-dialog/index.vue

  • Step 1: 入库单「送货单位」= load.customerName

  • Step 2: 分装单移除客户相关占位(若有)


Phase 7:归档与运费

Task 18: 归档弹窗分段

Files:

  • Modify: web-admin/src/components/business/pl-plan-archive-dialog/

  • Modify: backend/app/services/pl_plan_service.py(archive_plan)

  • Step 1: 上区:装货表(inbound_)+ 各送货表(outbound_)

  • Step 2: 运费区增加 freightRemark 输入

  • Step 3: 提交前校验全部段必填;一次 API 原子归档

  • Step 4: 库存同步改为按段汇总后写台账

Task 19: 运费结算展示备注

Files:

  • Modify: web-admin/src/views/pl/freight/components/UnsettledPlanPanel.vue

  • Modify: SettlementBillPanel.vue(结算详情弹窗)

  • Step 1: 列表/详情只读展示 freightRemark(计划级)


Phase 8:验收

Task 20: 端到端验收清单

  • Step 1: 场景 30=10+15+5 建单 → 安排 → 司机/现场 → 归档 → 运费结算(需联调环境手测)
  • Step 2: 送提货单 3 客户选择 + 同客户 2 段合并(单元测试覆盖)
  • Step 3: 迁移脚本在 staging 数据跑通;旧单打印/归档回归(--dry-run 可用,待连库)
  • Step 4: 相关 pytest 通过(vue-tsc 全仓既有错误,与本变更无关)
  • Step 5: ./scripts/update-graph.sh(backend/frontend 已更新)

Spec 覆盖自检

需求 Task
D1 装货 1 段 Task 5 校验、Task 8
D2 送货多段 Task 9
D3 数量告警 Task 3、5、10
D5/D6 内部地磅 Task 3、8、9、12
D7 归档字段 Task 18
D8 整单归档 Task 18
D9/D10 链接 Task 13、14
D11–D13 打印 Task 15–17
D14 运费备注 Task 1、18、19
D15 迁移 Task 6

建议实施顺序

  1. Phase 1–2(可并行前后端类型草案)
  2. Phase 3(表单可见进展)
  3. Phase 6 打印(业务方易验证)
  4. Phase 4–5 安排与链接
  5. Phase 7 归档
  6. Phase 8 + Task 6 生产迁移

预估规模: 大重构,建议分 2~3 个 PR(① 表+API+表单 ② 链接+地磅+打印 ③ 归档+迁移)。