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

7.1 KiB
Raw Permalink Blame History

title, aliases, tags, audience, status, sub_feature, last_review, code_version
title aliases tags audience status sub_feature last_review code_version
prop-acc · prepaid · 场景 - 月初批量自动抵扣 job(待补)
月初自动抵扣
批量预存款抵账单
consume-batch-auto-monthly
场景-月初自动抵扣
场景
prop-acc
预存款
消费
待补
业务人员
财务
产品
草稿 prepaid 2026-05-25 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 执行后

业务人员看汇总报告(后台 / 邮件):

# 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 排查

系统流程(目标态)

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 实现前)

相关文档