**发现并已修复的文档滞后**(后期代码先于文档,审计时补齐): | 滞后点 | 修复 | |---|---| | `24.附录` users 表缺 `wechat_openid` 列(二期微信登录加的) | ✅ 已补 | | `24.附录` 缺 `refuel_records` 表(三期记账) | ✅ 已补 | | `24.附录` 错误码缺 `1012/1013`(三期) | ✅ 已补 | | `34.附录` 小程序页面目录缺 `calc/refuels`(三期) | ✅ 已补 | **核对一致项**: - API 路由 **A1-A23 + `/api/auth/wechat`** 全部注册,与 22/33/43 文档逐项对应 - `schema.sql` 11 表 = 24 附录(10 + refuel)+ 45 附录 - 小程序 8 页文件齐全(js/wxml/wxss/json × 8),`refuels.wxml` 数据绑定与 js 匹配 - H5 8 页面全部可访问 ## 2️⃣ 后期变更对前期的影响 ✅ 无破坏 综合回归 **20 项全 PASS**: - **一期**:账号密码登录 / Cookie 会话 / dashboard / provinces(31省) / history ✅ - **二期**:Bearer token 认证(与 Cookie **双通道共存**,互不冲突)✅ - **三期**:refuel 首条保存 / 区间油耗 8.25 / 统计 / 预填 ✅ - **前端**:9 个资源(8 页 + 静态 JS)全部 200 ✅ 关键:二期的 `users` 加列是**幂等增量迁移**(ALTER),未动一期任何表结构;一期 API 与前端全部正常。 ## 3️⃣ 整体可行性 ✅ 在可控范围 | 维度 | 状态 | |---|---| | 构建/静态检查 | `go build / vet` 全绿 | | 单元测试 | 6 包 17 单测全过(auth/crawler/cron/db/push/service) | | 规模 | 11 表 · 23+ 接口 · 8 H5 页面 · 8 小程序页面 · 17 份文档 · ~90 代码文件 | | 三阶段功能 | 监控预测提醒 → 微信小程序 → 加油记账/真实油耗,全部落地 | **非阻塞小项**(可后续优化,不影响运行): 1. `refuels.wxml` 第 11 行 `wx:for` 与 `wx:if` 同节点——功能正常,写法可规范 2. api 包 handler 层无独立单测——由端到端回归覆盖(service 层已有单测) --- **结论:项目整体健康、文档与代码对齐、三阶段功能完整可用。** 4 处文档滞后已修复,无功能性问题。可以进入部署/上线阶段。
5.9 KiB
5.9 KiB
⛽ 三期 · 记账功能 — 附录
上游:
docs/40.记账概要设计.md、docs/24.附录.md(全系统通用规则) 数据表 DDL / 公式 / 漏记规则 / 级联重算 / 错误码
一、数据表设计
1.1 加油记录表 refuel_records
CREATE TABLE IF NOT EXISTS refuel_records (
id INTEGER PRIMARY KEY AUTOINCREMENT, -- 记录 id
user_id INTEGER NOT NULL REFERENCES users(id), -- 归属用户(私有数据)
vehicle_id INTEGER NOT NULL REFERENCES vehicles(id), -- 归属车辆(油耗按车独立计算)
refuel_at TEXT NOT NULL, -- 加油时间(默认当前,可改)
odometer REAL NOT NULL, -- 当前码表里程(km)
price_per_liter REAL NOT NULL, -- 油价(元/升)
amount REAL NOT NULL, -- 支付金额(元)
discount REAL NOT NULL DEFAULT 0, -- 优惠金额(元)
net_amount REAL NOT NULL, -- 实付金额 = amount - discount
liters REAL NOT NULL, -- 加油量 = net_amount / price
fuel_type TEXT, -- 油号(92/95/98/0,可空,缺省取该车油号)
full_tank INTEGER NOT NULL DEFAULT 1, -- 是否加满:1=是(仅标签展示,不参与计算)
note TEXT, -- 备注
calc_distance_km REAL, -- 区间行驶里程(距上次,可空)
calc_l_per_100km REAL, -- 区间油耗 L/100km(可空)
calc_yuan_per_km REAL, -- 区间成本 元/km(可空)
anomaly TEXT, -- 异常标记:NULL/odometer(里程回退)
created_at TEXT DEFAULT (datetime('now','localtime')),-- 创建时间
updated_at TEXT DEFAULT (datetime('now','localtime')) -- 更新时间
);
CREATE INDEX IF NOT EXISTS idx_refuel_veh ON refuel_records(vehicle_id, refuel_at);
CREATE INDEX IF NOT EXISTS idx_refuel_user ON refuel_records(user_id);
1.2 数据库迁移
schema.sql增加上述表(新库直接建)。db.Open的migrate函数增加幂等CREATE TABLE IF NOT EXISTS refuel_records(旧库自动建)。
二、公式与计算规则
2.1 基本公式
| 量 | 公式 | 精度 |
|---|---|---|
实付金额 net |
net = amount - discount |
2 位 |
加油量 liters |
liters = net / price |
2 位 |
区间里程 distance |
distance = odometer_now - last_odometer |
整数 km |
区间油耗 L/100km |
l_per_100km = liters / distance × 100 |
1 位 |
区间成本 元/km |
yuan_per_km = net / distance |
2 位 |
2.2 计算生效条件
| 条件 | 行为 |
|---|---|
| 该车无上次记录(首条) | calc_* 全 NULL("无基准") |
distance <= 0(里程未前进/回退) |
calc_* NULL,anomaly=odometer |
price <= 0 或 net <= 0 |
拒绝保存(400+1012) |
full_tank仅作标签(历史记录展示"加满"徽标),不参与油耗计算。
2.3 异常检测规则(漏记提示)
对本次记录(相比该车历史平均;无历史平均则跳过):
异常判定(满足任一):
a) 本次油价 price > 历史平均 price × 2
b) 本次油耗 calc_l_per_100km > 历史平均 L/100km × 2
→ possible_missing = true("耗油量异常,是否有漏记?")
三、漏记处理与级联重算
3.1 漏记/异常处理
| 场景 | 处理 |
|---|---|
| 漏记一次加油 | 下次记录自动以最近有效记录为基准(平均油耗);possible_missing 提示补录 |
| 用户补录 | 历史列表"补一笔",填漏记那次里程/金额/油价 → 按 refuel_at 排序落位 → 级联重算 |
| 里程回退 | odometer_now <= last_odometer → 该条油耗 NULL + anomaly=odometer,标黄提示 |
| 加满标签 | full_tank 复选框仅作标签展示,不参与油耗计算;历史记录显示"加满"徽标 |
| 删除记录 | 其后一条的基准变为被删记录的上一条,级联重算 |
3.2 级联重算规则
操作 影响范围 重算动作
─────────────────────────────────────────────────────────────────
新增 R3 R3(与上次 R2) 重算 R3
编辑 R2 R2(与上次 R1)、R3(与 R2) 重算 R2、R3
删除 R2 R3(上次基准改为 R1) 重算 R3
补录 R2 R2(与 R1)、R3(与 R2) 重算 R2、R3
3.3 重算实现
func recalc(conn, vehicleID, fromRefuelID):
// 取该车按时间排序的记录,从 fromRefuelID 开始逐条重算
// 每条的上次基准 = 前一条有效记录
重算在同一事务内完成,保证一致性。
四、错误码扩展
| code | HTTP | 含义 |
|---|---|---|
| 1012 | 400 | 加油记录参数非法(金额/油价/里程/车辆归属) |
| 1013 | 409 | 加油记录冲突(同一车同一时间重复记录) |
其余复用 docs/24.附录.md 错误码表(0/1001-1011/5000)。
五、与通用规则衔接
- 时间:
refuel_at用 Asia/Shanghai 本地时间(YYYY-MM-DD HH:MM:SS)。 - 权限:
/api/refuels*挂authGuard;按user_id归属,vehicle_id归属校验。 - 金额精度:元保留 2 位;油耗 L/100km 保留 1 位。
- 数据分层:
refuel_records为用户私有数据(含user_id),按用户隔离。