refactor(stage10): ele / feedback 拆出 repository + model,并补契约测试
背景
- 这两个域把 SQL 与处理器放在同一文件,是全仓仅有的两个零接口测试的后端域。
直接拆会改动 SQL 与参数顺序,而硬约束要求不得变更统计口径 —— 因此按
"可注入化 -> 补契约测试 -> 再提取" 的顺序做。
改动
- ele:拆为 routes.ts(校验与组装)/ repository.ts(全部 SQL)/ model.ts(xlsx 解析、
取值清洗、筛选片段、插入值组装等纯逻辑),并改为 registerEleRoutes(app, deps) 可注入。
- feedback:拆为 routes.ts / repository.ts,同样可注入;建表与截图上传也作为依赖注入。
- 两域各补测试:ele 7 个接口契约 + 6 个模型用例,feedback 9 个接口契约。
mock pool 逐条断言 SQL 文本与参数顺序(含分页、状态白名单、批量插入的 30 列顺序)。
- 架构测试新增一条:已完整分层的三个域(vehicles / ele / feedback)必须有 repository.ts
且 routes.ts 不得出现 SQL。
等价性验证(关键)
- 把改造前的实现从 git 取出,与改造后的实现跑同一批请求(含真实 xlsx 解析路径),
对比每一步落库 SQL、参数、HTTP 状态与响应体:
feedback:6 个场景,SQL + 参数 + 状态完全一致(差异仅 DDL 已移交 db/schema 层)
ele :5 个场景,SQL + 参数 + 状态 + 响应体完全一致(仅随机 batchId/时间戳做掩码)
- 期间的修正:曾把 /mine 与 /list 的列集合统一,二者实际不同(管理列表多 user_id/user_name),
已按原样保留;测试同时锁定了这一差异。
lint / test(161) / build 全绿,可达性 0 未引用文件。
This commit is contained in:
+14
-8
@@ -91,12 +91,17 @@ server/
|
||||
|
||||
| 域 | 文件 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `vehicles/` | `routes.ts` `repository.ts` `model.ts` `utils.ts` `types.ts` | 唯一已完整分层到 repository 的域,SQL 有指纹测试 |
|
||||
| `mileage/` | `index.ts`(聚合)+ `monitoring.ts` `targets.ts` `trend.ts` `daily-report.ts` `vehicle-recent.ts` + `*-model.ts` + `cache.ts` `oneos-api.ts` `daily-report-{service,store,scheduler}.ts` | 路由 / 模型 / 服务已分开 |
|
||||
| `energy/` | `index.ts`(聚合)+ `hydrogen-bi-v2.ts` `hydrogen-station-board.ts` `electric.ts` `etc.ts` + `query-model.ts` `cache.ts` `constants.ts` | 路由 / 模型已分开,SQL 仍在路由内 |
|
||||
| `vehicles/` | `routes.ts` `repository.ts` `model.ts` `utils.ts` `types.ts` | ✅ 完整分层;SQL 有契约测试 |
|
||||
| `ele/` | `routes.ts` `repository.ts` `model.ts`(+ `model.test.ts` `routes.test.ts`) | ✅ 完整分层;改造前后 SQL/参数/响应体已做等价性验证 |
|
||||
| `feedback/` | `routes.ts` `repository.ts` `oss.ts`(+ `routes.test.ts`) | ✅ 完整分层;同上 |
|
||||
| `mileage/` | `index.ts`(聚合)+ `monitoring.ts` `targets.ts` `trend.ts` `daily-report.ts` `vehicle-recent.ts` + `*-model.ts` + `cache.ts` `oneos-api.ts` `daily-report-{service,store,scheduler}.ts` | 路由 / 模型 / 服务已分开,**SQL 仍在各路由文件内** |
|
||||
| `energy/` | `index.ts`(聚合)+ `hydrogen-bi-v2.ts` `hydrogen-station-board.ts` `electric.ts` `etc.ts` + `query-model.ts` `cache.ts` `constants.ts` | 路由 / 模型已分开,**SQL 仍在路由内** |
|
||||
| `scheduling/` | `index.ts`(聚合)+ `suggestions.ts` `notify.ts` + `algorithm.ts` `notification-model.ts` | 同上 |
|
||||
| `hydrogen-heatmap/`、`vehicle-heatmap/` | `routes.ts` + `model.ts` | 路由 / 模型已分开 |
|
||||
| `ele/`、`feedback/` | `routes.ts`(+ `oss.ts`) | **尚未拆出 repository**,SQL 与处理器在同一文件 |
|
||||
| `hydrogen-heatmap/`、`vehicle-heatmap/` | `routes.ts` + `model.ts` | 纯模型已抽出,**SQL 仍在 `routes.ts`** |
|
||||
|
||||
已完整分层的三个域(`vehicles` / `ele` / `feedback`)由架构测试守护:`routes.ts` 不得出现 SQL,
|
||||
且必须存在 `repository.ts`。其余域尚未拆出 repository——拆分时**不要改变 SQL 与参数顺序**,
|
||||
并建议先按 `ele/routes.test.ts` 的方式补契约测试再动。
|
||||
|
||||
|
||||
### 中间件顺序(在 `app.ts` 中显式体现)
|
||||
@@ -132,9 +137,10 @@ cors → read-only → /api/auth(公开) → authMiddleware → 各业务域
|
||||
|
||||
诚实记录,避免后来者以为已经做完:
|
||||
|
||||
- **后端仍有两个域没拆出 repository**:`ele/routes.ts` 与 `feedback/routes.ts` 仍把 SQL
|
||||
与处理器放在同一文件(形状见上表)。拆分时**不要改变 SQL 与参数顺序**——这两个域目前
|
||||
没有 SQL 指纹测试,建议先补契约测试再动。
|
||||
- **后端仍有域没拆出 repository**:`mileage` / `energy` / `scheduling` / 两个热力图的 SQL 仍在
|
||||
各自的 `routes.ts`(或平级模块)里(形状见上表)。`vehicles` / `ele` / `feedback` 已完成,
|
||||
可作为模板:路由只做校验与组装,SQL 进 `repository.ts`,纯逻辑进 `model.ts`,
|
||||
并用 mock pool 的契约测试锁定 SQL 与参数。
|
||||
- **运行时建表已集中到 `server/db/schema/`**,并在 `DB_READ_ONLY=1` 时整体跳过(由架构测试守护,
|
||||
已实测不触碰数据库)。它仍由业务接口在首次调用时触发,而不是只由 `bootstrap.ts` 调用——
|
||||
要彻底改成显式迁移,需要先建立数据库变更脚本流程,避免"代码里偷偷建表"。
|
||||
|
||||
Reference in New Issue
Block a user