12 KiB
运输计划创建日期 + 取货/送达默认 — 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: 为 pl_plan 增加业务字段「创建日期」(create_date/createDate),在新增/编辑弹窗中可编辑;新增时取货/送达时间若为空则默认等于计划日期。
Architecture: MySQL 增量迁移回填存量;SQLAlchemy 模型 + Pydantic Create/Update/Read 贯通;创建接口缺省时服务端用当天。前端仅改 pl-plan-form-dialog(及仍在用的 plan/form.vue),列表/查看暂不展示。
Tech Stack: FastAPI + SQLAlchemy + Pydantic v2;Vue 3 + Element Plus;MySQL 5.7
Spec: docs/superpowers/specs/2026-07-27-pl-plan-create-date-design.md
文件结构
| 文件 | 职责 |
|---|---|
backend/scripts/migrate_20260727_pl_plan_create_date.sql |
增量 DDL + 存量回填 |
docs/sql/shanxia2.0.sql |
pl_plan 建表定义同步加 create_date |
backend/app/models/pl_models.py |
PlPlan.create_date |
backend/app/schemas/pl/plan.py |
Create/Update/Read/CreateFromContractRequest 的 createDate |
backend/app/api/pl/plan.py |
create / create-full / create-from-contract / update 写入 |
backend/tests/test_pl_plan_create_date.py |
缺省日期解析纯函数单测(若抽 helper)或创建默认行为说明见 Task 3 |
web-admin/src/api/pl/index.ts |
Plan / PlanCreateFullPayload 增加 createDate |
web-admin/src/components/business/pl-plan-form-dialog/index.vue |
UI + 默认值 + 提交 |
web-admin/src/views/pl/plan/form.vue |
与弹窗对齐(路由仍挂载时) |
Task 1: 迁移 SQL + DDL 快照
Files:
-
Create:
backend/scripts/migrate_20260727_pl_plan_create_date.sql -
Modify:
docs/sql/shanxia2.0.sql(CREATE TABLE pl_plan中plan_date前插入create_date) -
Step 1: 写增量迁移脚本
-- backend/scripts/migrate_20260727_pl_plan_create_date.sql
-- 运输计划:业务创建日期 create_date(与系统 create_time 独立)
ALTER TABLE `pl_plan`
ADD COLUMN `create_date` date DEFAULT NULL COMMENT '创建日期' AFTER `plan_no`;
UPDATE `pl_plan`
SET `create_date` = DATE(`create_time`)
WHERE `create_date` IS NULL AND `create_time` IS NOT NULL;
UPDATE `pl_plan`
SET `create_date` = CURDATE()
WHERE `create_date` IS NULL;
ALTER TABLE `pl_plan`
MODIFY COLUMN `create_date` date NOT NULL COMMENT '创建日期';
- Step 2: 同步
docs/sql/shanxia2.0.sql
在 CREATE TABLE \pl_plan`中,于 ``plan_no`` 行之后、``plan_date` `` 行之前增加:
`create_date` date NOT NULL COMMENT '创建日期',
(不必改历史 INSERT 行;本地/环境以迁移脚本为准。若本机有库,执行 Step 1 脚本。)
- Step 3: Commit
git add backend/scripts/migrate_20260727_pl_plan_create_date.sql docs/sql/shanxia2.0.sql
git commit -m "$(cat <<'EOF'
chore(pl): add pl_plan.create_date migration and DDL snapshot
EOF
)"
Task 2: ORM + Schema
Files:
-
Modify:
backend/app/models/pl_models.py(PlPlan,约plan_no/plan_date附近) -
Modify:
backend/app/schemas/pl/plan.py -
Step 1: 模型增加列
在 plan_no 与 plan_date 之间:
plan_no = Column(String(32), nullable=False, unique=True, comment="计划订单编号 POYYYYMMDD###")
create_date = Column(Date, nullable=False, comment="创建日期")
plan_date = Column(Date, nullable=False, comment="计划日期")
- Step 2: Schema 贯通
PlanCreate(约 126 行)增加(紧挨 plan_date):
class PlanCreate(PlanBase):
create_date: Optional[date] = Field(
default=None, alias="createDate", description="创建日期;缺省则服务端用当天"
)
plan_date: date = Field(..., alias="planDate", description="计划日期")
products: Optional[list[PlanProductCreate]] = Field(default=None, description="产品明细列表")
model_config = {"populate_by_name": True}
PlanUpdate 增加:
create_date: Optional[date] = Field(default=None, alias="createDate")
plan_date: Optional[date] = Field(default=None, alias="planDate")
PlanRead 在 plan_date 旁增加:
create_date: date = Field(alias="createDate")
plan_date: date = Field(alias="planDate")
CreateFromContractRequest 增加可选:
create_date: Optional[date] = Field(
default=None, alias="createDate", description="创建日期;缺省当天"
)
plan_date: date = Field(..., alias="planDate", description="计划日期")
确保文件顶部已有 Optional、date 导入。
- Step 3: Commit
git add backend/app/models/pl_models.py backend/app/schemas/pl/plan.py
git commit -m "$(cat <<'EOF'
feat(pl): add create_date to PlPlan model and schemas
EOF
)"
Task 3: API 写入 create_date
Files:
- Modify:
backend/app/api/pl/plan.py(create_plan、create_plan_full、create_from_contract、update_plan)
说明:update_plan 已用 payload.model_dump(exclude_unset=True) + setattr,Schema 加字段后更新路径自动生效,无需改循环逻辑。
- Step 1: 抽一小段解析(同文件顶部附近或内联)
在 plan.py 模块级增加:
from datetime import date
def _resolve_create_date(value: date | None) -> date:
return value or date.today()
(若文件已 from datetime import date,勿重复导入。)
- Step 2: 三处创建赋值
在 PlPlan(...) 构造处,plan_date=payload.plan_date 旁增加:
create_date=_resolve_create_date(getattr(payload, "create_date", None)),
plan_date=payload.plan_date,
覆盖:
create_plan(约 396–400 行)create_plan_full(约 478–482 行)create_from_contract内PlPlan(...)(约 598–602 行)— 使用payload.create_date
- Step 3: 写纯函数单测
# backend/tests/test_pl_plan_create_date.py
from datetime import date
from app.api.pl.plan import _resolve_create_date
def test_resolve_create_date_uses_explicit():
assert _resolve_create_date(date(2026, 1, 15)) == date(2026, 1, 15)
def test_resolve_create_date_defaults_today():
assert _resolve_create_date(None) == date.today()
Run: cd backend && source venv/bin/activate && pytest tests/test_pl_plan_create_date.py -v
Expected: PASS
- Step 4: Commit
git add backend/app/api/pl/plan.py backend/tests/test_pl_plan_create_date.py
git commit -m "$(cat <<'EOF'
feat(pl): persist create_date on plan create APIs
EOF
)"
Task 4: 前端 API 类型
Files:
-
Modify:
web-admin/src/api/pl/index.ts -
Step 1: 类型增加
createDate
Plan 接口(约 planDate 旁):
planNo: string
createDate: string
planDate: string
PlanCreateFullPayload:
contractId: string
createDate: string
planDate: string
createFromContract 可选扩展(若合同入口会传):
createFromContract: (data: {
contractId: string
planDate: string
createDate?: string
followUserId?: string
followUserName?: string
}) =>
- Step 2: Commit
git add web-admin/src/api/pl/index.ts
git commit -m "$(cat <<'EOF'
feat(web-admin): add createDate to transport plan API types
EOF
)"
Task 5: 新增/编辑弹窗 UI 与默认值
Files:
-
Modify:
web-admin/src/components/business/pl-plan-form-dialog/index.vue -
Step 1: 模板 — 计划日期前加创建日期
在基础信息 form-grid-4 内,「计划日期」el-form-item 之前插入:
<el-form-item label="创建日期" prop="createDate">
<el-date-picker
v-model="formData.createDate"
type="date"
placeholder="选择日期"
value-format="YYYY-MM-DD"
style="width: 100%"
/>
</el-form-item>
- Step 2: formData / rules / reset / load / payload
辅助函数(script 内):
function todayYmd(): string {
return new Date().toISOString().split('T')[0]
}
formData 初始:
createDate: todayYmd(),
planDate: todayYmd(),
// ...
pickupTime: '', // reset 时再按计划日期填充
deliveryTime: '',
basicRules:
createDate: [{ required: true, message: '请选择创建日期', trigger: 'change' }],
planDate: [{ required: true, message: '请选择计划日期', trigger: 'change' }],
resetForm 的 Object.assign:
createDate: todayYmd(),
planDate: todayYmd(),
// ...其它字段同现有...
pickupTime: todayYmd(), // 与默认 planDate 相同;用户改后不再联动
deliveryTime: todayYmd(),
注意:resetForm 里先算一次 const d = todayYmd(),createDate/planDate/pickupTime/deliveryTime 都用同一个 d,避免跨日边界不一致。
loadPlanForEdit 的 Object.assign:
createDate: data.createDate || formatDate(data.createTime) || todayYmd(),
planDate: data.planDate,
// pickup/delivery 仍用接口值,空则保持空(不要用计划日期覆盖)
pickupTime: formatDate(data.pickupTime) || '',
deliveryTime: formatDate(data.deliveryTime) || '',
buildPlanCommonPayload:
createDate: formData.createDate,
planDate: formData.planDate,
确认 没有 对 planDate 的 watch 去改取货/送达。
- Step 3: 手工核对(开发者)
- 打开新增:创建日期、计划日期、取货、送达均为当天。
- 只改计划日期:取货/送达不变。
- 改取货后再改计划日期:取货仍为用户改过的值。
- 保存后再编辑:创建日期回填正确;
createTime未变。
- Step 4: Commit
git add web-admin/src/components/business/pl-plan-form-dialog/index.vue
git commit -m "$(cat <<'EOF'
feat(web-admin): add createDate and default pickup/delivery in plan form dialog
EOF
)"
Task 6: 对齐独立表单页(若仍使用)
Files:
-
Modify:
web-admin/src/views/pl/plan/form.vue -
Step 1: 与弹窗同构的最小改动
若该页仍可从路由 /pl/plan/form 打开:同样在计划日期前加「创建日期」,formData/rules/提交/reset 增加 createDate;新增时 pickupTime/deliveryTime 空则填 planDate。
若页面已废弃不用,可在 PR 说明中注明「未改 form.vue」,并跳过本 Task。
- Step 2: Commit(有改动时)
git add web-admin/src/views/pl/plan/form.vue
git commit -m "$(cat <<'EOF'
feat(web-admin): align plan form page with createDate field
EOF
)"
Task 7: 一致性检查与图谱
Files: 无强制新文件
- Step 1: 字段一致性(若脚本覆盖 pl)
cd backend && source venv/bin/activate && python scripts/check_field_consistency.py
若报 createDate/create_date 相关缺失,按脚本提示补齐后重跑至通过或确认脚本未覆盖 pl_plan。
- Step 2: 更新 graphify
./scripts/update-graph.sh all
或按仓库约定:graphify update .(根目录若配置)/ 仅 backend+web-admin。
- Step 3: Commit 图谱变更(若有)
git add backend/graphify-out web-admin/graphify-out graphify-out 2>/dev/null || true
git status
# 仅提交实际变更的 graph 文件
git commit -m "$(cat <<'EOF'
chore: update graphify after pl_plan create_date
EOF
)"
Spec 覆盖自检
| Spec 项 | Task |
|---|---|
D1 create_date 独立字段 |
1–3 |
| D2 存量回填 | 1 |
| D3 仅弹窗 UI | 5(列表/查看不改) |
| D4 新增取货/送达默认计划日期、不联动 | 5 |
| D5 计划日期默认当天不变 | 5 |
| D6 安排弹窗不改 | —(无 Task) |
| 后端缺省当天 | 3 |
| 验收:createTime 不被改写 | 3(未写 create_time)+ 5 手工 |
Placeholder 扫描
无 TBD/TODO;步骤含具体 SQL/代码/命令。
类型一致性
全程使用:DB create_date、API/前端 createDate、Python create_date / alias createDate。