Commit Graph

9 Commits

Author SHA1 Message Date
yuming e47a399ad5 余额为 0 时改为发探针,不再无条件全部跳过
balance 只有前端上报这一条上升通道,没升级小程序的老用户在微信侧仍在
真实累积额度却永远不上报,记账会系统性低估。低估到 0 就一条不发,比
改造前更糟——改造前至少还会试。

改为:余额为 0 时仍发出优先级最高的那一条当探针。成功则证实微信侧有
额度,本轮继续发;43101 则立即中止(与原行为一致);非额度错误记 failed
且不再重复探。每用户每轮最多探一次。

探针成功仍走 quota.consume:内部 MAX(0, balance-1) 扣不出负数,净效果是
balance 保持 0、sentTotal +1。不趁机把 balance 调高——探针只证明「至少
还有 1 条」,凭空补猜出来的数字会让首页风险预告变成乐观的假话。

注:三个原有用例断言的是「余额 0 就一个请求都不发」这一被本次刻意推翻的
旧契约,已按新行为改写;改写后仍用变异测试确认能抓到探针被关掉。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-16 10:23:11 +08:00
yuming 12b146c2c9 两处提醒查询补 ORDER BY id,保证平局取舍可复现
reminder.js 扫全表和 index.js 的 getQuotaStatus 都没有 ORDER BY,
两边的 sort 又都是稳定排序,同一天、同 kind、同 importance 的条目
先后完全由 SQLite 返回顺序决定。一个走全表扫、一个可能走索引,
顺序一致纯属巧合——一旦不一致,首页预告的人名就和实际被跳过的人对不上。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-16 10:19:47 +08:00
yuming d8573359a2 修复首页风险预告与实际发送的排序不一致问题
atRisk.js 之前只按 fireInDays 排序,同一天内多条提醒的先后完全未定义,
和 reminder.js 实际发送时「当天>提前、重要程度降序」的规则对不上,导致
额度卡在中间时首页提示的风险人名和定时任务实际跳过的人不一致。

- 把 importanceRank 从 reminder.js 抽到共享的 src/importance.js,两处复用
- atRisk.js 的 computeAtRisk 排序改为三段式:fireInDays 升序 →
  同天内 kind(当天优先于提前)→ 同 kind 内重要程度降序
- 补充 atRisk.test.js 用例覆盖「同一天多条事件、额度只够一部分」场景
2026-08-16 09:21:09 +08:00
yuming 57470ade4f 补充发送侧分组与错误分支的测试覆盖,保留43101原始错误信息的修复
- reminder.js:43101 跳过日志改为记录微信原始错误信息,便于和「额度耗尽」的
  兜底文案区分排查(前一实施者已验证,此次原样带入提交)
- reminder.test.js:新增 runOnce 按 openid 分组结算用例,验证多用户额度互不
  串号;将「非额度类错误」用例扩到 2 条数据,证明该分支不会误中止后续发送
- 新建 wx.test.js:验证 sendSubscribeMessage 在微信返回非 0 errcode 时,
  抛出的 Error 对象确实带有正确的 errcode 属性

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-16 09:07:46 +08:00
yuming 6548577a98 定时任务改为按用户分组、按优先级发送,额度耗尽即停 2026-08-15 18:04:12 +08:00
yuming 68acbb3809 抽出日期计算纯函数模块,并搭建后端测试基建
- 新增 server/src/occurrence.js:startOfDay/getNextOccurrence/daysBetween,today 可注入
- reminder.js 改为调用新模块,删除内联的 getThisYearDate/daysBetween
- 引入 node:test 作为测试框架,加 npm test 脚本
- 新增 test/helper.js(临时库辅助,供后续任务用)和 test/occurrence.test.js(7 个用例,覆盖农历跨年等边界)
2026-08-15 17:30:42 +08:00
yuming 756d57d818 简化纪念日类型:去掉"农历生日"类型,公历/农历改由 isLunar 字段决定
部署到群晖 / deploy (push) Successful in 44s
- typeList 从 5 项简化到 4 项:生日 / 结婚纪念日 / 订婚纪念日 / 其他纪念日
- TYPE_NAMES / TYPE_ICONS 中 lunar_birthday 保留兼容映射(也映射到「生日」+ 🎂),
  让线上历史数据自然回显,无需数据库迁移(方案 A)
- getTypeIndex('lunar_birthday') = 0,老数据编辑时正确回显「生日」
- index.js 列表筛选和 wxml 图标判断本来已含 lunar_birthday 兼容,无需改

老数据自然淘汰:用户重新保存时新数据写 type='birthday',老数据 type 保留
直到下次编辑保存才升级。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-02 07:30:37 +08:00
yuming ddcfe3334e v2.1.0 流程改造 + 农历准确性修复 + 双向同步 + 闰月支持
部署到群晖 / deploy (push) Successful in 44s
- Phase 1: 添加纪念日合并人物创建流程(方案 B)
- Phase 2: 农历提醒按 lunarMonth/Day 计算每年公历
- Phase 3: 人员数据同步到后端(新增 /api/person)
- Phase 4: 新设备启动从云端恢复数据
- Phase 5: 工具函数收敛 utils/format.js
- Phase 6: 同步失败入队 + 启动重试
- Phase 7: 闰月生日完整支持(含 isLeapMonth + UI 警示)
- 修复 lunarInfo 数据表错位(替换为权威源 jjonline/calendar.js)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-02 05:51:17 +08:00
yuming 3965e542fc 接入自建后端 + Gitea CI/CD
部署到群晖 / deploy (push) Failing after 6m22s
- 新增 server/:Node + Express + SQLite + node-cron 实现登录、纪念日 CRUD 和定时订阅消息推送
- 新增 .gitea/workflows/deploy.yml:推送即触发群晖 Docker 部署,监听 15002
- utils/api.js:自动按 envVersion 切换本地/线上 BASE_URL
- app.js 与 add-anniversary.js 移除 wx.cloud 调用,改走自建后端
- cloudfunctions/ 暂保留以便回滚
- 一并提交此前未入库的首页 / 设置页 / 日历 / 万年历等改造

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 15:44:09 +08:00