From 071281150d9dbdfca6f00ea6d7a86832476a67c1 Mon Sep 17 00:00:00 2001 From: zlwu <704541015@qq.com> Date: Mon, 17 Aug 2026 15:45:27 +0800 Subject: [PATCH] docs: add design for optional reimburse detail occur date Capture the agreed plan to add nullable occur_date (YYYY-MM-DD) on bx_reimburse_detail across backend, web-admin, and bx-mobile. Co-authored-by: Cursor --- ...8-17-reimburse-detail-occur-date-design.md | 142 ++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 docs/superpowers/specs/2026-08-17-reimburse-detail-occur-date-design.md diff --git a/docs/superpowers/specs/2026-08-17-reimburse-detail-occur-date-design.md b/docs/superpowers/specs/2026-08-17-reimburse-detail-occur-date-design.md new file mode 100644 index 000000000..aec38aa4a --- /dev/null +++ b/docs/superpowers/specs/2026-08-17-reimburse-detail-occur-date-design.md @@ -0,0 +1,142 @@ +# 报销明细「发生时间」字段 — 设计文档 + +> **日期**: 2026-08-17 +> **状态**: 已确认设计(待实现) +> **仓库**: shanxia2.0(`backend/` + `web-admin/` + `bx-mobile/`) +> **入口页**: `http://localhost:3006/#/bx/reimburse/apply` + +## 背景与问题 + +报销申请「新增 / 编辑」弹窗的报销明细当前列为:序号、费用项目、金额、报销事由、操作。 +客户希望在「报销事由」后增加可选字段「发生时间」,可填可不填;精度为年月日。 + +## 已确认决策 + +| # | 决策 | 说明 | +|---|------|------| +| D1 | **独立字段** | 表 `bx_reimburse_detail` 新增可空 `occur_date`(DATE),不用拼进 `remark` | +| D2 | **仅年月日** | API / 前端统一 `YYYY-MM-DD`;不做时分秒 | +| D3 | **可选** | 不校验必填;空串 / null → 库 `NULL` | +| D4 | **只读空值** | 始终展示该列/字段,空显示为 `—` | +| D5 | **三端一致** | backend + web-admin + bx-mobile 同步读写与展示 | +| D6 | **不做** | 列表筛选、导出、未来日期限制、主表列、列表卡片摘要 | + +--- + +## 一、目标与范围 + +### 目标 + +每条报销明细可记录可选的费用发生日期,并在申请录入与各只读明细场景一致展示。 + +### 范围内 + +- 库表 / Model / Schema / API 写入与回读 +- Web:申请弹窗录入 + 查看弹窗;审批页与 view(mine/todo/all)明细表 +- Mobile:申请页录入;详情页与审批页明细展示 + +### 范围外 + +- 列表筛选 / 导出 / 打印 +- `ApprovalDetailPage`(当前未展示报销明细分列,不改) +- 历史数据回填(存量保持 `NULL`) + +--- + +## 二、数据模型与 API + +### 2.1 表字段 + +`bx_reimburse_detail` 新增: + +| 列名 | 类型 | 可空 | 位置 | 注释 | +|------|------|------|------|------| +| `occur_date` | `date` | YES | `amount` 之后、`tenant_no` 之前 | 费用发生日期 | + +存量行:`occur_date = NULL`。 + +### 2.2 DDL 与快照 + +- 迁移脚本:`backend/scripts/migrate_20260817_bx_reimburse_detail_occur_date.sql` +- 同步更新:`docs/sql/shanxia2.0.sql` 中 `bx_reimburse_detail` 表定义 + +### 2.3 Model / Schema + +- Model:`BxReimburseDetail.occur_date`(nullable Date) +- `ReimburseDetailCreate.occur_date: Optional[str] = None` +- `ReimburseDetailOut.occur_date: OptDateToStr = None`(序列化为 `YYYY-MM-DD` 或 null) +- JSON 驼峰别名:`occurDate` + +### 2.4 写入链路 + +1. `api/bx/reimburse.py` → `_build_details_data` 透传 `occur_date` +2. `services/bx/reimburse.py` → `create_with_details` / `update_with_details` 写入明细 +3. 解析:空 → `NULL`;非空按与 `reimburse_date` 同类的日期解析(`YYYY-MM-DD`) +4. 出参:`ReimburseDetailOut.model_validate` 自然带出(字段挂在 Model 上即可) + +--- + +## 三、前端交互 + +### 3.1 列 / 字段顺序 + +费用项目 → 金额 → 报销事由 → **发生时间** →(操作列,仅编辑表) + +### 3.2 web-admin + +**录入** — `views/bx/reimburse/apply/index.vue` + +- 明细表新增「发生时间」列(无必填星号) +- `el-date-picker`:`type="date"`,`value-format="YYYY-MM-DD"`,可清空 +- `DetailLine`、提交 payload、编辑回填增加 `occurDate` +- 不做必填校验 + +**只读**(始终显示列,空为 `—`) + +- 同页查看弹窗明细表 +- `views/bx/reimburse/approve/index.vue` +- `views/bx/view/mine|todo|all/index.vue` + +### 3.3 bx-mobile + +**录入** — `ReimburseApplyPage.vue`:报销事由后增加发生时间日期选择(可清空);提交/回填带 `occurDate`。 + +**只读**(始终显示,空为 `—`) + +- `ReimburseDetailPage.vue` +- `ReimburseApprovePage.vue` + +--- + +## 四、改动文件清单 + +| 层 | 文件 | +|----|------| +| DB | `backend/scripts/migrate_20260817_bx_reimburse_detail_occur_date.sql` | +| DB 快照 | `docs/sql/shanxia2.0.sql` | +| Model | `backend/app/models/bx_models.py` | +| Schema | `backend/app/schemas/bx/reimburse.py` | +| API | `backend/app/api/bx/reimburse.py` | +| Service | `backend/app/services/bx/reimburse.py` | +| Web | `web-admin/src/views/bx/reimburse/apply/index.vue` | +| Web | `web-admin/src/views/bx/reimburse/approve/index.vue` | +| Web | `web-admin/src/views/bx/view/mine/index.vue` | +| Web | `web-admin/src/views/bx/view/todo/index.vue` | +| Web | `web-admin/src/views/bx/view/all/index.vue` | +| Mobile | `bx-mobile/src/views/reimburse/ReimburseApplyPage.vue` | +| Mobile | `bx-mobile/src/views/reimburse/ReimburseDetailPage.vue` | +| Mobile | `bx-mobile/src/views/reimburse/ReimburseApprovePage.vue` | + +--- + +## 五、验收要点 + +1. 新增/编辑:可填、可清空发生时间;不填可保存与提交。 +2. 各只读明细场景:有值显示 `YYYY-MM-DD`,无值显示 `—`。 +3. Web 与 bx-mobile 行为一致。 +4. 旧单据明细为空时展示 `—`,编辑其他字段不受影响。 + +## 六、错误处理 + +- 非法日期格式:后端解析失败时返回 400(与现有报销日期解析策略一致)。 +- 前端 date-picker 正常情况下只产出合法 `YYYY-MM-DD` 或空。