Files
uniprop-manual/prop-acc/scenarios/prepaid/consume-batch-auto-monthly.md
2026-05-25 23:27:56 +08:00

225 lines
7.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: prop-acc · prepaid · 场景 - 月初批量自动抵扣 job(待补)
aliases:
- 月初自动抵扣
- 批量预存款抵账单
- consume-batch-auto-monthly
- 场景-月初自动抵扣
tags:
- 场景
- prop-acc
- 预存款
- 消费
- 待补
audience:
- 业务人员
- 财务
- 产品
status: 草稿
sub_feature: prepaid
last_review: 2026-05-25
code_version: 2026-05-22
---
# 场景:月初批量自动抵扣 job(待补)
> [!warning] 本场景**代码未实现**
> 当前所有 consume 操作都需要业务人员**手动后台触发**。本文档描述自动 job 落地后的目标态。设计意图详见 [[auto-deduction-design]]。
预存款的**产品价值核心**。月初 1 日凌晨,Scheduled job 扫所有 Active + 余额>0 的预存款账户,对每个账户找未付账单,按优先级 ([[consume-multiple-bills-priority]]) 自动抵扣。
## 典型情境(目标态)
> [!example] 真实情境(目标态)
> 2026 年 6 月 1 日 00:30,系统自动跑 `PrepaidAutoDeductionJob`:
>
> - 扫描全平台 5 个社区,共 500 个 Active 预存款账户(余额 > 0)
> - 对每个账户找该业户的未付账单(物业费 + 水电费 + ...)
> - 按 due_at 升序抵扣
> - 全部完成耗时 ~5 分钟
>
> 早上 8 点,500 个业户陆续收到推送:
>
> | 业户场景 | 推送内容 |
> |---|---|
> | 余额充足,全抵 | "5 月账单已自动抵扣 ¥1,000,余额 ¥4,000" |
> | 余额部分够 | "已抵 ¥800,水电费 ¥200 余额不足,请充值" |
> | 账户冻结 | (不推送)|
## 业户视角(目标态)
### 您会感受到什么
- 月初某个早晨突然收到推送
- 小程序"我的账单"批量翻为 ✅ Paid
- 小程序"我的预存款"流水里多几笔 consume
- 收到对应数量的 Receipt(每张账单一张)
- **完全无感**(理想状态),不需要任何操作
### 您要做什么
只在以下情况要做:
| 推送内容 | 您要做 |
|---|---|
| "余额不足,X 账单未付" | 充值 → 业务人员手动补抵 / 等下月自动 job |
| "账户冻结无法抵" | 联系物业了解冻结原因 |
| "所有账单已抵,余额还剩 ¥X" | 不用做 |
## 业务人员视角
### Job 执行前
业务人员**不需要任何操作**。Scheduled 配置在系统层,运行无需介入。
### Job 执行过程
后台监控面板(待开发):
- 实时进度:已处理 N / 总共 M 账户
- 实时统计:已抵账单数、抵扣总额、失败数、跳过数
- 失败告警:任何异常立即推送给 ops
### Job 执行后
业务人员看汇总报告(后台 / 邮件):
```markdown
# 2026 年 6 月 1 日 PrepaidAutoDeductionJob 报告
## 统计
- 候选账户:500
- 全抵成功:380(76%)
- 部分抵 / 跳过:80(16%)
- 跨社区拦截:0
- 账户冻结跳过:8(2%)
- 失败(异常):0(0%)
- 其余(余额=0、无未付账单):32(6%)
## 资金动作
- 抵扣总额:¥412,300
- 涉及账单数:835(平均每户 1.6 张)
- 平均抵扣金额:¥513
- 最大单户抵扣:¥3,200(陈先生家,水电+物业+电梯)
## 失败明细
(无)
## 跳过明细(需关注)
- 80 户余额不足,合计欠款 ¥45,000
- 已发推送
- 业务人员可后续手动追缴
## 冻结跳过
- 8 户冻结中
- 需业务人员核实是否解冻
```
### 异常介入
| 场景 | 业务人员动作 |
|---|---|
| 跳过的余额不足业户 | 联系业户充值 + 后续手动 ConsumeAction |
| 冻结跳过业户 | 核实纠纷 / 风控状态 → [[unfreeze-after-verification|解冻]] |
| Job 失败(系统异常) | 立即联系运维查日志 |
| 某账户重复抵扣(理论上不应该) | 查 transactions 表是否有同一 Bill 被抵两次 → 立即停 job 排查 |
## 系统流程(目标态)
```mermaid
sequenceDiagram
participant Scheduler
participant Job[PrepaidAutoDeductionJob]
participant Account[PrepaidAccount]
participant Bill
participant Consume[ConsumeFromPrepaidAccountAction]
participant 监听器
participant 数据库
participant 业户
Note over Scheduler: 2026-06-01 00:30 触发
Scheduler->>Job: dispatch
Job->>数据库: SELECT prepaid_accounts WHERE status=Active AND balance>0
loop 每个 account
Job->>数据库: SELECT bills WHERE community_id=? AND resident_id=? AND status='unpaid' ORDER BY due_at, amount
loop 每个 bill
alt balance >= bill.amount
Job->>Consume: handle(account, bill, bill.amount)
Consume->>Account: consume()
Consume->>Bill: recordPayment() → Paid
Consume->>监听器: 触发 CollectionOrderCompleted
监听器->>数据库: 建 Receipt
Consume->>数据库: 提交事务
else 余额不够
Job->>Job: 跳过,记日志
end
end
end
Job->>数据库: 写汇总报告
Job-->>Scheduler: 完成
Job->>业户: 批量推送通知
```
## Job 的安全设计(目标态)
| 风险 | 防御 |
|---|---|
| 同一账户被抵两次(job 重跑) | 每笔 consume 关联 Bill,Bill.status=Paid 后跳过 |
| 跨社区误抵 | `ConsumeFromPrepaidAccountAction` 内置守护(consume 模型方法层) |
| Frozen 账户被抵 | `canOperate()` 守护(模型层) |
| 余额为负 | 事务回滚 + amount ≤ balance 守护 |
| Job 长时间运行影响业务 | 分批 chunk(100 / 批);限制最大并发 |
| Job 半夜失败无人发现 | 失败告警(Slack / 钉钉 / 短信)|
| 业户充值后想立即抵(月中)| 业务人员手动 ConsumeAction(不等下月 job)|
## 与手动 ConsumeAction 的关系
| 维度 | 手动 ConsumeAction | 自动 Job |
|---|---|---|
| 触发 | 业务人员后台点击 | Scheduled(月初)|
| 单次范围 | 1 账户 × 1 账单 | 全平台 × 全部账户 × 全部账单 |
| 业务场景 | 个案、运维、补抵 | 月度默认流程 |
| 通知 | 单笔 Receipt | 批量 Receipt + 汇总推送 |
| 复用代码 | `ConsumeFromPrepaidAccountAction` | **同上**(复用,不重写)|
## 实施前已记录的待讨论项
详见 [[auto-deduction-design]] "待讨论 / 决策" 段。简略列表:
- 触发频率(月度 / 周度 / 实时)
- 触发时点(月初固定 / 账单生成事件触发)
- 优先级排序(due_at / amount / bill_type 组合)
- 部分抵扣支持
- 失败通知策略
- 监控指标
## 未来扩展
job 落地后,后续可演化:
| 演化方向 | 价值 |
|---|---|
| **小程序"我的账单"显示"将于 X 月 1 日自动扣"** | 业户预期管理,避免临时余额不足惊讶 |
| **预扣预警**:月底前 7 天扫描"下月账单 > 当前余额"的业户 → 主动提醒充值 | 减少跳过率,提升用户体验 |
| **零余额自动通知**:月初 job 后,余额 = 0 的账户主动推送"请充值" | 提升复购率 |
| **跨账户均衡**(若同业户多社区):未来若放开跨社区抵扣 | 提升资金利用率 |
## 当前替代(job 实现前)
- 业务人员**月初批量手动**逐户处理(见 [[consume-monthly-property-bill]] + [[consume-multiple-bills-priority]])
- 工作量大,容易遗漏 / 顺序错乱
- **这就是 job 紧迫性的来源**
## 相关文档
- [[auto-deduction-design]]
- [[consume-monthly-property-bill]]
- [[consume-multiple-bills-priority]]
- [[consume-meter-bill]]
- [[consume-via-bill-collection-type]]
- [[audit-low-balance-and-overdue]]