Repository navigation
feat(store): 未付款订单催付(下单 24h 后一次,按计划时间戳扫描) - #41
Merged
Merged
Conversation
worable233
force-pushed
the
feat/unpaid-order-reminder
branch
from
October 25, 2026 09:25
8486a71 to
334209c
Compare
对标 #12.5 的最后一条业务口径:对方(ZJMF)有 `orderOverdue`「未付款订单提醒」, 我方完全没有 —— 未支付订单除了被取消,不会收到任何提示。 ## 做法 - 订单新增两列(无需迁移:12.1 加 `deletedAt`/`deletedAtMs` 时已验证插件模型是 schema 驱动): - `unpaidRemindAtMs`(索引,数值)= **计划催付时间**,下单时写 `now + 24h`; - `unpaidRemindedAt`(索引,字符串)= 已催付时间,非空即「已催过」。 - 新任务 `unpaid-order-reminder`(每小时):扫 `state = PENDING` + `unpaidRemindedAt IS NULL` + `unpaidRemindAtMs <= now`,认领(条件更新)→ 发通知 → 失败退回未催付。 - 三个条件都落在索引列上,不会退化成全表扫描;已催过的行不会反复占批次。 ## 三个刻意的选择 1. **按「计划时间戳」而不是「每天扫一遍创建时间」**:任务停两天,恢复后照样补发。 对方的每日等值窗口一旦那天没跑,这条提醒就永久丢了。 2. **每小时扫一次,不是每天一次**:代价只是一次索引查询,换来更小的补发延迟。 3. **认领后、发送前再查一次状态**:用户刚付完款就收到「请尽快支付」是最招投诉的 那种 bug,宁可多一次读。 ## 验证 `packages/plugins/store` **208 例全绿**(原 203 + 新增 5): 到点且未支付 → 发一条并标记;认领失败 → 不发;认领后已支付 → 不发; 通知失败 → 退回未催付等重试;催付窗口 = 24h。 `jobs-contract.test.ts` 的清单加入 `unpaid-order-reminder` 60min(改名/改频率即红); `tsc` 干净。 顺带:`toOrder` 把这两个内部列从接口返回里剥掉(与 `deletedAtMs` 同一处理), 避免内部标记泄漏到 API。
CI 的 `notification-type-coverage` 抓到:`unpaid-reminder.ts` 发 `order.unpaid`, 但通知目录里没有这个类型 —— 用户设置里看不到、也关不掉。 - `notifications.ts` 增加 `order.unpaid`(「订单待支付提醒」),与下单即发的 `order.pending` 分开:用户可以只关催付、保留下单回执。 - `apps/api` 的 `PLUGIN_EMITTERS` 加入 `unpaid-reminder.ts`,否则这个文件里的 发出点以后不受守门保护。 验证:`apps/api/tests/unit/notification-type-coverage.test.ts` 本地 3 例通过; 反向验证 —— 删掉 `service.overdue` 那行后测试转红并精确报出 `service.overdue (packages/plugins/store/src/expiry.ts)`,说明守门真的在跑。
worable233
force-pushed
the
feat/unpaid-order-reminder
branch
from
October 25, 2026 09:40
334209c to
2edd7fd
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
对标 #12.5 的最后一条业务口径:对方(ZJMF)有
orderOverdue「未付款订单提醒」,我方完全没有 —— 未支付订单除了被取消,不会收到任何提示。做法
订单新增两列(无需迁移:12.1 加
deletedAt/deletedAtMs时已验证插件模型是 schema 驱动):unpaidRemindAtMs(索引,数值)= 计划催付时间,下单时写now + 24hunpaidRemindedAt(索引,字符串)= 已催付时间,非空即「已催过」新任务
unpaid-order-reminder(每小时):扫state = PENDING+unpaidRemindedAt IS NULL+unpaidRemindAtMs <= now,认领(条件更新)→ 发通知 → 失败退回未催付。三个条件都落在索引列上,不会退化成全表扫描;已催过的行不会反复占批次。三个刻意的选择
验证
packages/plugins/store208 例全绿(原 203 + 新增 5):jobs-contract.test.ts的清单加入unpaid-order-reminder60min(改名/改频率即红);tsc干净。toOrder把这两个内部列从接口返回里剥掉(与deletedAtMs同一处理),避免内部标记泄漏到 API。