vault backup: 2026-05-26 01:03:15
This commit is contained in:
8
.obsidian/workspace.json
vendored
8
.obsidian/workspace.json
vendored
@@ -197,6 +197,10 @@
|
||||
},
|
||||
"active": "849c5ff8936a2b67",
|
||||
"lastOpenFiles": [
|
||||
"prop-acc/scenarios/billing/collect-via-prepaid-auto.md",
|
||||
"prop-acc/scenarios/billing/collect-payment-batch.md",
|
||||
"prop-acc/scenarios/billing/collect-payment-single.md",
|
||||
"prop-acc/scenarios/billing/create-single-bill-manual.md",
|
||||
"prop-acc/scenarios/billing/create-meter-bill-auto.md",
|
||||
"prop-acc/scenarios/billing/create-periodic-property-fee.md",
|
||||
"prop-acc/scenarios/billing",
|
||||
@@ -221,11 +225,7 @@
|
||||
"prop-acc/scenarios/meter/decommission-without-replacement.md",
|
||||
"prop-acc/scenarios/meter/replace-broken-meter.md",
|
||||
"prop-acc/scenarios/meter/register-single-meter.md",
|
||||
"prop-acc/scenarios/meter/init-new-community-batch.md",
|
||||
"prop-acc/scenarios/meter",
|
||||
"prop-acc/maps/meter-knowledge-map.md",
|
||||
"prop-acc/concepts/meter/decommission-and-locking.md",
|
||||
"prop-acc/concepts/meter/reading-source-and-photo-proof.md",
|
||||
"prop-acc/concepts/meter",
|
||||
"prop-acc/scenarios/prepaid",
|
||||
"prop-acc/concepts/prepaid",
|
||||
|
||||
257
prop-acc/scenarios/billing/collect-payment-batch.md
Normal file
257
prop-acc/scenarios/billing/collect-payment-batch.md
Normal file
@@ -0,0 +1,257 @@
|
||||
---
|
||||
title: prop-acc · billing · 场景 - 同业户多账单批量收款
|
||||
aliases:
|
||||
- 批量收款
|
||||
- BatchCollectPaymentAction
|
||||
- 一次付多张
|
||||
- collect-payment-batch
|
||||
- 场景-同业户批量收款
|
||||
tags:
|
||||
- 场景
|
||||
- prop-acc
|
||||
- 账单
|
||||
- 收款
|
||||
audience:
|
||||
- 业户
|
||||
- 业务人员
|
||||
status: 已发布
|
||||
sub_feature: billing
|
||||
last_review: 2026-05-26
|
||||
code_version: 2026-05-22
|
||||
---
|
||||
|
||||
# 场景:同业户多账单批量收款
|
||||
|
||||
业户**本月有多张账单**(物业费 + 水电气费 + 其他),想**一次性付清**。业务人员走 `BatchCollectPaymentAction`,**一笔 CollectionOrder 关联多张 Bill**(走 CollectionOrderBill 多对多)。
|
||||
|
||||
## 典型情境
|
||||
|
||||
> [!example] 真实情境
|
||||
> 张阿姨本月有 4 张账单:
|
||||
>
|
||||
> | 账单 | 金额 |
|
||||
> |---|---|
|
||||
> | 5 月物业费 | ¥800 |
|
||||
> | 5 月水费 | ¥54 |
|
||||
> | 5 月电费 | ¥168 |
|
||||
> | 5 月燃气 | ¥30 |
|
||||
> | **合计** | **¥1,052** |
|
||||
>
|
||||
> 张阿姨到前台:"4 张账单我一次性付清,微信扫码"。业务人员**1 笔操作**完成 4 张账单收款。
|
||||
|
||||
## 业户视角
|
||||
|
||||
### 第 1 步:告诉业务人员要付哪些
|
||||
|
||||
> "我把本月 4 张账单都付了,微信扫码"
|
||||
|
||||
### 第 2 步:确认金额
|
||||
|
||||
业务人员说:"4 张账单合计 ¥1,052,微信扫这个码"。
|
||||
|
||||
### 第 3 步:微信付
|
||||
|
||||
业户扫码 → 输密码 / 指纹 → 付 ¥1,052。
|
||||
|
||||
### 第 4 步:拿收据
|
||||
|
||||
可能是:
|
||||
|
||||
- 一张 Receipt 含 4 行明细(物业费 ¥800 / 水费 ¥54 / ...)
|
||||
- 或 4 张独立 Receipt(每张账单一张)
|
||||
|
||||
具体看实现。**业户体验上前者更好**(一张收据看全部)。
|
||||
|
||||
## 业务人员视角
|
||||
|
||||
### 第 1 步:找业户
|
||||
|
||||
后台 → 业户 → 找到张阿姨 → "她的账单"标签 → 看到 4 张 Unpaid。
|
||||
|
||||
或:后台 → 账单 → 列表 → 过滤业户=张阿姨 + 状态=Unpaid。
|
||||
|
||||
### 第 2 步:选中多张账单
|
||||
|
||||
Table 上勾选 4 张账单 → 顶部 **"批量收款"** 按钮(`BatchCollectPaymentAction`)。
|
||||
|
||||
或:后台 → 业户视图 → "批量收款"(若 UI 支持单业户聚合)。
|
||||
|
||||
### 第 3 步:Modal 表单
|
||||
|
||||
| 字段 | 填什么 |
|
||||
|---|---|
|
||||
| **选中账单数** | 4 张(显示)|
|
||||
| **合计金额** | ¥1,052(自动算)|
|
||||
| **支付方式** | 微信 |
|
||||
| **收款银行账户** | 物业微信账户 |
|
||||
| **备注** | 选填,如 "业户本月全套缴" |
|
||||
|
||||
### 第 4 步:提交
|
||||
|
||||
系统在**一个事务**内:
|
||||
|
||||
1. 校验每张 Bill 可付(`canBePaid()`)
|
||||
2. 建 **1 个 CollectionOrder**(`type=Bill`,`actual_amount=+1052`,`status=Completed`)
|
||||
3. 建 **4 个 CollectionOrderBill**(每张账单一个,各自 `allocated_amount` = 该账单金额)
|
||||
4. 4 张 Bill 各自 `paid_amount = amount`,`status = Paid`
|
||||
5. 触发 `CollectionOrderCompleted` 事件
|
||||
6. Listener 建 Receipt(可能含 4 个 line_items)
|
||||
|
||||
### 第 5 步:给收据
|
||||
|
||||
后台找到 Receipt → 打印 / 微信发。
|
||||
|
||||
## 系统流程
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant 业户
|
||||
participant 业务
|
||||
participant Filament
|
||||
participant Action[BatchCollectPaymentAction]
|
||||
participant DB
|
||||
|
||||
业务->>Filament: BillsList → 选 4 张 → 批量收款
|
||||
Filament->>Action: handle(bills, channel, bank)
|
||||
Action->>Action: 每张 Bill 校验 canBePaid
|
||||
|
||||
Action->>DB: 开启事务
|
||||
Action->>DB: 1. 建 CollectionOrder(+1052, Completed)
|
||||
|
||||
loop 每张 Bill
|
||||
Action->>DB: 2. 建 CollectionOrderBill(allocated=bill.amount)
|
||||
Action->>DB: 3. Bill.paid_amount = amount, status=Paid
|
||||
end
|
||||
|
||||
Action->>Listener: 4. 触发 CollectionOrderCompleted
|
||||
Listener->>DB: 5. 建 Receipt(line_items × 4)
|
||||
Action->>DB: 提交事务
|
||||
|
||||
Filament-->>业务: 成功通知
|
||||
业务-->>业户: 收据(含 4 项明细)
|
||||
```
|
||||
|
||||
## 数据示例
|
||||
|
||||
收款后:
|
||||
|
||||
### CollectionOrder(1 条)
|
||||
|
||||
```
|
||||
id: 67890
|
||||
collection_type: Bill
|
||||
actual_amount: +1052
|
||||
payment_channel: 微信
|
||||
status: Completed
|
||||
meta.fund_source: external
|
||||
```
|
||||
|
||||
### CollectionOrderBill(4 条)
|
||||
|
||||
| collection_order_id | bill_id | allocated_amount |
|
||||
|---|---|---|
|
||||
| 67890 | 物业费 Bill | 800 |
|
||||
| 67890 | 水费 Bill | 54 |
|
||||
| 67890 | 电费 Bill | 168 |
|
||||
| 67890 | 燃气 Bill | 30 |
|
||||
|
||||
### Bill(4 条更新)
|
||||
|
||||
每张 paid_amount = amount,status = Paid。
|
||||
|
||||
### Receipt(1 条,4 行明细)
|
||||
|
||||
```
|
||||
collection_order_id: 67890
|
||||
amount: +1052
|
||||
line_items: [
|
||||
{ 物业费(5月), 800 },
|
||||
{ 水费(5月), 54 },
|
||||
{ 电费(5月), 168 },
|
||||
{ 燃气(5月), 30 },
|
||||
]
|
||||
```
|
||||
|
||||
## 与单张收款的对比
|
||||
|
||||
| 维度 | [[collect-payment-single|单张]] | **批量(本场景)** |
|
||||
|---|---|---|
|
||||
| Modal 选账单 | 1 张(从 ViewBill 进入)| **多张**(Table 勾选)|
|
||||
| CollectionOrder | 1 个 | 1 个(共用)|
|
||||
| CollectionOrderBill | 1 个 | **N 个**(每张一个)|
|
||||
| 业务人员操作 | 单笔 | 一笔 |
|
||||
| 业户体验 | 一张一张付(慢)| 一次付清(快)|
|
||||
|
||||
**批量收款的好处**:业户体验更好(一次付),业务人员工作量更小。**唯一前提**:业户愿意一次付清。
|
||||
|
||||
## 不同支付方式的分摊
|
||||
|
||||
业户支付的钱**自动按账单原金额比例分摊** 到各 Bill。不需要业务人员手动分配。
|
||||
|
||||
例:¥1,052 微信付 → 4 个 CollectionOrderBill 各自 allocated_amount = 该账单 amount(全额分配)。
|
||||
|
||||
### 如果业户付不够(部分批量付)
|
||||
|
||||
业户只想付 ¥600(不够 ¥1,052)→ 业务人员有几种选择:
|
||||
|
||||
| 策略 | 操作 |
|
||||
|---|---|
|
||||
| **优先付物业费**(默认?)| ¥600 全部分配给物业费 Bill(部分付)|
|
||||
| **按比例分摊** | 600 × 800/1052 = 456 给物业费,600 × 54/1052 = 31 给水费, ... |
|
||||
| **业务人员手动决定** | 给业务人员选哪张账单付多少 |
|
||||
|
||||
当前实现的具体策略看代码。**业务上建议优先付到期早的**(避免逾期)。
|
||||
|
||||
> [!info] 批量收款的"部分付"复杂度
|
||||
> 上述场景比单张部分付更复杂。当前 `BatchCollectPaymentAction` 可能**只支持全额批量**(若金额够付所有选中账单 → 全付;不够 → 走单张部分付逐张操作)。看实现。
|
||||
|
||||
## 业务人员视角:Modal 的预检查
|
||||
|
||||
类似 [[smart-bulk-delete-design|智能批删]] 的预检查思路:
|
||||
|
||||
- 选中 4 张账单 → Modal 显示"总计 ¥1,052"
|
||||
- 选中包含已 Paid 的账单 → Modal 显示"4 选 + 1 已付跳过"
|
||||
- 选中包含 Suspended → Modal 提示 "该账单挂起,无法收款"
|
||||
|
||||
> [!info] 当前实现的成熟度
|
||||
> `BatchCollectPaymentAction` 的智能 Modal 程度看实现。可能比 `BulkDeleteBillsAction` 简单(批删有 issue.md Q6 详细设计,批收款未单独描述)。
|
||||
|
||||
## 常见问题
|
||||
|
||||
> [!question] 选中跨业户的多张账单能批量收款吗?
|
||||
> 业务上**不应该**(不同业户付的钱不能混)。系统层面应**校验同业户**,否则拒绝。
|
||||
>
|
||||
> 例外:**家属代付**场景(儿子来付父母账单)→ 业务上算同业户的钱。
|
||||
|
||||
> [!question] 批量收款失败一半怎么办?
|
||||
> 事务内**全成功或全失败**。任一 Bill 校验失败(例如某张已 Paid)→ 整笔回滚 → 业户的钱不被收。
|
||||
>
|
||||
> 实施上可能优化为"部分成功"(只失败的跳过),但破坏事务原子性,通常不推荐。
|
||||
|
||||
> [!question] 业户支付的钱比账单合计**多**?
|
||||
> Modal 守护应限制金额 ≤ 合计。如果业务上业户故意多给:
|
||||
>
|
||||
> - 找零给业户(系统层面只收账单的金额)
|
||||
> - **或转入业户预存款账户**(若有此自动逻辑)
|
||||
|
||||
> [!question] 不同期次的账单能一起付吗?
|
||||
> 可以(账单状态都是 Unpaid 即可)。例如付 4 月物业费 + 5 月物业费 + 5 月水电气。
|
||||
|
||||
> [!question] 批量收款的 activitylog 怎么记?
|
||||
> 一条 CollectionOrder 的 activitylog(event=created)+ 每张 Bill 状态变化的 log。可在 SQL 反查 affected_bill_ids。
|
||||
|
||||
## 异常分支
|
||||
|
||||
- 单张付 → [[collect-payment-single]]
|
||||
- 部分付 → [[exception-partial-payment]]
|
||||
- 预存款抵 → [[collect-via-prepaid-auto]]
|
||||
- 业户全付不起,挑某张付 → 走 [[collect-payment-single]] 逐张
|
||||
- 收错了想撤 → [[void-paid-bill]](已付作废 + 退款)
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [[bill-vs-collection-order]]
|
||||
- [[collect-payment-single]]
|
||||
- [[collect-via-prepaid-auto]]
|
||||
- [[exception-partial-payment]]
|
||||
- [[../prepaid/auto-deduction-design]]
|
||||
258
prop-acc/scenarios/billing/collect-payment-single.md
Normal file
258
prop-acc/scenarios/billing/collect-payment-single.md
Normal file
@@ -0,0 +1,258 @@
|
||||
---
|
||||
title: prop-acc · billing · 场景 - 单张账单收款
|
||||
aliases:
|
||||
- 单张收款
|
||||
- 收款
|
||||
- CollectPaymentAction
|
||||
- collect-payment-single
|
||||
- 场景-单张账单收款
|
||||
tags:
|
||||
- 场景
|
||||
- prop-acc
|
||||
- 账单
|
||||
- 收款
|
||||
audience:
|
||||
- 业户
|
||||
- 业务人员
|
||||
status: 已发布
|
||||
sub_feature: billing
|
||||
last_review: 2026-05-26
|
||||
code_version: 2026-05-22
|
||||
---
|
||||
|
||||
# 场景:单张账单收款
|
||||
|
||||
业户**单张账单付款**(物业费 / 水费 / 电费的某一张),业务人员后台触发 `CollectPaymentAction`。最基础高频的收款场景。
|
||||
|
||||
## 典型情境
|
||||
|
||||
> [!example] 真实情境
|
||||
> 张阿姨 5 月物业费 ¥800 账单已生成,她下午到物业前台:
|
||||
>
|
||||
> - "我交 5 月物业费"
|
||||
> - 业务人员小李打开张阿姨账户 → 找到 5 月物业费账单 → 收款
|
||||
|
||||
## 业户视角
|
||||
|
||||
### 第 1 步:到前台 / 小程序
|
||||
|
||||
带:
|
||||
|
||||
- 钱(现金 / 微信 / POS 卡)
|
||||
- 房号 / 姓名(身份证)
|
||||
|
||||
### 第 2 步:告诉业务人员要付哪张账单
|
||||
|
||||
> "我交 5 月物业费"
|
||||
|
||||
业务人员从系统找到对应账单。
|
||||
|
||||
### 第 3 步:确认金额 + 付款方式
|
||||
|
||||
业务人员告诉张阿姨:
|
||||
|
||||
> "您 5 月物业费 ¥800,请选付款方式"
|
||||
|
||||
| 付款方式 | 操作 |
|
||||
|---|---|
|
||||
| 现金 | 给钱 → 找零 |
|
||||
| 微信扫码 | 业务人员出示物业收款码 → 业户扫 |
|
||||
| POS 刷卡 | 业户给银行卡 → POS 机刷 |
|
||||
| 银行转账 | 业户给凭证(线下转账已到账)|
|
||||
|
||||
### 第 4 步:拿收据
|
||||
|
||||
- 纸质:**当场打印**
|
||||
- 电子:发到业户微信 / 邮箱
|
||||
|
||||
> [!success] 完成
|
||||
> 账单状态从 Unpaid → Paid。业户带收据离开,5 分钟内搞定。
|
||||
|
||||
## 业务人员视角
|
||||
|
||||
### 第 1 步:找账单
|
||||
|
||||
后台 → 账单 → 列表 → 按业户姓名 / 房号 / 期次过滤 → 找到张阿姨的 5 月物业费(Unpaid,¥800)→ 进 `ViewBill`。
|
||||
|
||||
或者:
|
||||
|
||||
- 后台 → 业户 → 找到张阿姨 → "她的账单"标签 → 看 Unpaid 列表 → 选
|
||||
|
||||
### 第 2 步:点击 `CollectPaymentAction`(标签"收款")
|
||||
|
||||
右上角状态管理组。
|
||||
|
||||
> [!warning] 按钮可见性
|
||||
> `CollectPaymentAction` 守护:`canBePaid()`(Unpaid / Partial)+ `->authorize('collect')`。Paid / Void / Suspended / Processing 灰化。
|
||||
|
||||
Modal 表单:
|
||||
|
||||
| 字段 | 填什么 |
|
||||
|---|---|
|
||||
| **收款金额** | ¥800(默认全额,可改为部分)|
|
||||
| **支付方式(`payment_channel_id`)** | 现金 / 微信 / POS / 银行转账 |
|
||||
| **收款银行账户(`bank_account_id`)** | 微信/POS/转账选对应银行账户;现金可空 |
|
||||
| **收款备注** | 选填,如"业户现场付款" |
|
||||
|
||||
### 第 3 步:提交
|
||||
|
||||
系统在**一个事务**内:
|
||||
|
||||
1. 校验 Bill 可付(`canBePaid` = Unpaid / Partial)
|
||||
2. 校验金额 ≤ Bill 剩余应付(`amount - paid_amount`)
|
||||
3. 建 `CollectionOrder`(`type=Bill`,`actual_amount=+800`,`status=Completed`,`payment_channel`,`meta.fund_source=external`)
|
||||
4. 建 `CollectionOrderBill`(`bill_id`,`collection_order_id`,`allocated_amount=800`)
|
||||
5. 更新 `Bill.paid_amount += 800`
|
||||
6. 更新 `Bill.status`:若 paid_amount = amount → `Paid`;若 < amount → `Partial`
|
||||
7. 触发 `CollectionOrderCompleted` 事件
|
||||
8. Listener 自动建 `Receipt` + `ReceiptItem`(文案"物业费 ¥800")
|
||||
9. 写 activitylog(可选,具体看实现)
|
||||
|
||||
### 第 4 步:给业户收据
|
||||
|
||||
后台找到新生成 Receipt → 打印 / 微信发。
|
||||
|
||||
## 系统流程
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant 业户
|
||||
participant 业务[业务人员]
|
||||
participant Filament
|
||||
participant Action[CollectPaymentAction]
|
||||
participant DB
|
||||
participant Listener
|
||||
|
||||
业户->>业务: 付物业费 800
|
||||
业务->>Filament: ViewBill → CollectPaymentAction(modal)
|
||||
Filament->>Action: handle(bill, 800, channel, bank)
|
||||
Action->>Action: canBePaid()? Unpaid=true
|
||||
Action->>Action: 800 ≤ remaining(800)? yes
|
||||
|
||||
Action->>DB: 开启事务
|
||||
Action->>DB: 1. 建 CollectionOrder(type=Bill, +800, Completed)
|
||||
Action->>DB: 2. 建 CollectionOrderBill(allocated=800)
|
||||
Action->>DB: 3. Bill.paid_amount=800
|
||||
Action->>DB: 4. Bill.status=Paid(800=800)
|
||||
Action->>Listener: 5. 触发 CollectionOrderCompleted
|
||||
Listener->>DB: 6. 建 Receipt("物业费 ¥800")
|
||||
Action->>DB: 提交事务
|
||||
|
||||
Filament-->>业务: 成功通知
|
||||
业务-->>业户: 收据
|
||||
```
|
||||
|
||||
## 部分付场景(business 上常见)
|
||||
|
||||
业户只想付 ¥300(全额 ¥800):
|
||||
|
||||
```
|
||||
Modal 表单:
|
||||
- 收款金额:300(手动改)
|
||||
- 支付方式:现金
|
||||
- 备注:"暂时只能付一部分"
|
||||
```
|
||||
|
||||
提交后:
|
||||
|
||||
- Bill.paid_amount = 300
|
||||
- Bill.status: Unpaid → **Partial**
|
||||
- 建 CollectionOrder(+300)+ CollectionOrderBill(allocated=300)
|
||||
|
||||
业户后续补付 ¥500 → 同样走 `CollectPaymentAction` → 第 2 笔 CollectionOrderBill → Bill 收齐 → Paid。
|
||||
|
||||
详见 [[exception-partial-payment]]。
|
||||
|
||||
## 数据示例(完整流水)
|
||||
|
||||
业户付 ¥800 后:
|
||||
|
||||
### Bill 表
|
||||
|
||||
| 字段 | 值 |
|
||||
|---|---|
|
||||
| `id` | 12345 |
|
||||
| `amount` | 800 |
|
||||
| `paid_amount` | 800 |
|
||||
| `status` | Paid |
|
||||
|
||||
### CollectionOrderBill 表
|
||||
|
||||
| 字段 | 值 |
|
||||
|---|---|
|
||||
| `bill_id` | 12345 |
|
||||
| `collection_order_id` | 67890 |
|
||||
| `allocated_amount` | 800 |
|
||||
|
||||
### CollectionOrder 表
|
||||
|
||||
| 字段 | 值 |
|
||||
|---|---|
|
||||
| `id` | 67890 |
|
||||
| `collection_type` | Bill |
|
||||
| `actual_amount` | +800 |
|
||||
| `payment_channel_id` | 微信 |
|
||||
| `status` | Completed |
|
||||
| `meta.fund_source` | external |
|
||||
|
||||
### Receipt 表
|
||||
|
||||
| 字段 | 值 |
|
||||
|---|---|
|
||||
| `collection_order_id` | 67890 |
|
||||
| `amount` | +800 |
|
||||
| line_items | [{ 物业费(5月), 800 }] |
|
||||
|
||||
## 常见问题
|
||||
|
||||
> [!question] 业户付的钱与账单金额不一致(多付 / 少付)?
|
||||
> | 情况 | 处置 |
|
||||
> |---|---|
|
||||
> | 少付 | 走部分付 Partial 状态;后续补付 |
|
||||
> | **多付** | **不应该**(Modal 守护 `amount ≤ remaining`)。如果业务上业户给的钱多,**找零给业户**(系统层面只收账单的金额) |
|
||||
|
||||
> [!question] 业户付错账单(本想付物业费,付到电费)?
|
||||
> 业务人员可:
|
||||
> - 立即作废这笔 CollectionOrder(走 [[void-paid-bill]] 类似流程)+ 重新对正确账单收款
|
||||
> - 或者**留这笔不动**(资金确实到账)+ 业务人员手工调整 CollectionOrderBill 的 allocated_amount(危险,会破坏审计)
|
||||
>
|
||||
> **推荐第一种**(走作废 + 重收)。
|
||||
|
||||
> [!question] Frozen Bill 能收款吗?
|
||||
> 不能。`canBePaid()` 只允许 Unpaid / Partial。Suspended 状态需先 [[resume-bill|恢复]]。
|
||||
|
||||
> [!question] 已付的 Bill 能再收款吗?
|
||||
> 不能。`canBePaid()` Paid 时返 false。理论上 Bill 已经付清。
|
||||
|
||||
> [!question] 业户预存款够付,业务人员怎么操作?
|
||||
> 看自动 / 手动:
|
||||
> - 自动(待补的 [[../prepaid/auto-deduction-design|预存款自动抵扣 job]]):业务人员不操作,系统自动
|
||||
> - 手动:业务人员在 `ViewBill` → 走 `CollectPaymentAction` 选"预存款抵扣"(或专用 Action)→ 详见 [[collect-via-prepaid-auto]]
|
||||
|
||||
> [!question] 收款时 PaymentChannel 写错(选了微信实际是现金)?
|
||||
> CollectionOrder 一经创建**通常不可改**字段。错了:
|
||||
> - 走作废(详见 [[void-paid-bill]])+ 重新建
|
||||
> - 或 tinker 改字段(运维 + 留审计)
|
||||
>
|
||||
> 预防:Modal 提交前再三确认。
|
||||
|
||||
> [!question] activitylog 记什么?
|
||||
> 详见 [[smart-bulk-delete-design]] activitylog 设计。CollectPayment 通常也记一条 activitylog:event=collected,properties 含 amount / payment_channel / receipt_id。
|
||||
|
||||
## 异常分支
|
||||
|
||||
- 部分付场景 → [[exception-partial-payment]]
|
||||
- 批量付(多张账单一起付)→ [[collect-payment-batch]]
|
||||
- 预存款抵 → [[collect-via-prepaid-auto]]
|
||||
- 收款错了想撤 → [[void-paid-bill]]
|
||||
- Bill 挂起中无法收 → [[resume-bill]]
|
||||
- 逾期账单催收 → [[exception-overdue-bills]]
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [[bill-six-state-machine]]
|
||||
- [[bill-vs-collection-order]]
|
||||
- [[exception-partial-payment]]
|
||||
- [[collect-payment-batch]]
|
||||
- [[collect-via-prepaid-auto]]
|
||||
- [[../adhoc/collection-order-and-receipt]]
|
||||
267
prop-acc/scenarios/billing/collect-via-prepaid-auto.md
Normal file
267
prop-acc/scenarios/billing/collect-via-prepaid-auto.md
Normal file
@@ -0,0 +1,267 @@
|
||||
---
|
||||
title: prop-acc · billing · 场景 - 预存款抵扣自动收款
|
||||
aliases:
|
||||
- 预存款抵账单
|
||||
- 自动抵扣收款
|
||||
- collect-via-prepaid-auto
|
||||
- 场景-预存款自动抵扣
|
||||
tags:
|
||||
- 场景
|
||||
- prop-acc
|
||||
- 账单
|
||||
- 收款
|
||||
- 跨子模块
|
||||
audience:
|
||||
- 业户
|
||||
- 业务人员
|
||||
- 财务
|
||||
status: 已发布
|
||||
sub_feature: billing
|
||||
last_review: 2026-05-26
|
||||
code_version: 2026-05-22
|
||||
---
|
||||
|
||||
# 场景:预存款抵扣自动收款
|
||||
|
||||
业户**预存款余额够付账单**,系统(理想是自动 job,当前是业务人员手动触发)走 `ConsumeFromPrepaidAccountAction` 抵扣账单。这是 billing × prepaid **两子模块联动**的核心场景。
|
||||
|
||||
> [!info] 本场景跨两个模块
|
||||
> - **billing 视角**:Bill 从 Unpaid → Paid,看似与普通收款一样
|
||||
> - **prepaid 视角**:PrepaidAccount.balance 减,走 consume 流水
|
||||
>
|
||||
> 详见 [[../prepaid/consume-monthly-property-bill]] 完整流程。本场景从 billing 角度补充。
|
||||
|
||||
## 典型情境
|
||||
|
||||
> [!example] 真实情境
|
||||
> 张阿姨预存款账户余额 ¥3,400,5 月物业费 ¥800。
|
||||
>
|
||||
> 手动模式:王主管在张阿姨预存款账户上点 `ConsumeAction`,选 5 月物业费 → 抵扣完成 → 账单 Paid。
|
||||
>
|
||||
> 自动模式(待补 [[../prepaid/auto-deduction-design]]):月初 1 日凌晨 job 自动跑 → 张阿姨账单当月自动扣 → 早晨业户收到推送"5 月物业费 ¥800 已抵扣,余额 ¥2,600"。
|
||||
|
||||
## billing 视角
|
||||
|
||||
### Bill 的变化
|
||||
|
||||
| 字段 | 变化前 | 变化后 |
|
||||
|---|---|---|
|
||||
| `status` | Unpaid | Paid |
|
||||
| `paid_amount` | 0 | 800 |
|
||||
| 关联的 CollectionOrderBill | 0 个 | 1 个(allocated=800)|
|
||||
| 关联的 CollectionOrder | 0 个 | 1 个(type=Bill, meta.fund_source=prepaid)|
|
||||
| 关联的 Receipt | 0 个 | 1 个("物业费 ¥800") |
|
||||
|
||||
**与普通收款的唯一差异**:CollectionOrder 的 `meta.fund_source = 'prepaid'`(而非默认 `external`)。
|
||||
|
||||
### CollectionOrder 的特殊性
|
||||
|
||||
```yaml
|
||||
id: 67890
|
||||
collection_type: Bill # 仍是 Bill 视角(不是 Prepaid)
|
||||
actual_amount: +800 # 正数
|
||||
payment_channel: null # 不走外部支付渠道
|
||||
status: Completed
|
||||
meta:
|
||||
fund_source: prepaid # 标资金来源
|
||||
prepaid_account_id: 123
|
||||
prepaid_transaction_id: 456
|
||||
```
|
||||
|
||||
详见 [[../prepaid/consume-via-bill-collection-type]]"CollectionOrder.type=Bill 设计"段。
|
||||
|
||||
### Receipt 文案
|
||||
|
||||
与现金 / 微信付的收据**长一样**:
|
||||
|
||||
```
|
||||
物业费(5月)¥800
|
||||
```
|
||||
|
||||
业户**感知不到**资金来源差异。这是有意设计 —— "业户付清账单"的统一感受。
|
||||
|
||||
## prepaid 视角(简述)
|
||||
|
||||
详见 [[../prepaid/consume-monthly-property-bill]] 完整流程。
|
||||
|
||||
- 校验账户 `canOperate()`(Active)
|
||||
- 校验余额够付(`balance >= 800`)
|
||||
- 校验跨社区(Bill 与 Account 同 community)
|
||||
- 建 `PrepaidTransaction(type=consume, amount=800, related_bill_id, balance 3400→2600)`
|
||||
- 更新 `PrepaidAccount.balance = 2600`
|
||||
- 同步 Bill 状态翻 Paid(通过 CollectionOrder + CollectionOrderBill)
|
||||
|
||||
## 业户视角
|
||||
|
||||
### 您会感受到什么
|
||||
|
||||
| 模式 | 感知 |
|
||||
|---|---|
|
||||
| **自动(待补)** | 月初推送"5 月物业费 ¥800 已自动从预存款扣,余额 ¥2,600" |
|
||||
| **手动** | 同上,只是触发时间不固定(看业务人员何时操作)|
|
||||
|
||||
### 与现金付的差异
|
||||
|
||||
| 维度 | 现金付 | **预存款抵** |
|
||||
|---|---|---|
|
||||
| 业户操作 | 到前台 + 给钱 | **无操作**(自动) |
|
||||
| 业户感知 | "我付了" | **"已抵扣"**(被动) |
|
||||
| Receipt | "物业费 ¥800" | **"物业费 ¥800"**(相同) |
|
||||
| 业务人员介入 | 多(收钱 + 录入) | **无**(自动 job)/ 中(手动) |
|
||||
| 时长 | 业户上门 + 5 分钟办理 | 0 秒(自动)/ 5 分钟(手动) |
|
||||
|
||||
## 业务人员视角
|
||||
|
||||
### 手动模式
|
||||
|
||||
业务人员在 `ViewPrepaidAccount`(预存款账户详情页):
|
||||
|
||||
1. 看到张阿姨账户余额 ¥3,400
|
||||
2. 点击 `ConsumeAction`(预存款上的)
|
||||
3. Modal 选 Bill = "5 月物业费 ¥800"
|
||||
4. 提交 → 系统自动跑完整链路
|
||||
|
||||
> [!info] 这个 Action 不在 billing 模块
|
||||
> `ConsumeAction` 是 prepaid 模块的 Filament Action,在 `PrepaidAccounts/Actions/`。billing 模块的 `CollectPaymentAction` 是普通收款用的(走外部 PaymentChannel)。两者**协作完成**预存款抵扣场景。
|
||||
>
|
||||
> 详见 [[../prepaid/consume-monthly-property-bill]]"业务人员视角"。
|
||||
|
||||
### 自动模式(待补)
|
||||
|
||||
业务人员**几乎不操作**(产品价值的最大体现)。月初看 dashboard 报告:
|
||||
|
||||
```
|
||||
2026 年 6 月 1 日 PrepaidAutoDeductionJob 报告
|
||||
- 候选账户:500
|
||||
- 全抵成功:380(76%)
|
||||
- 部分抵 / 跳过:80(16%)
|
||||
- 账户冻结跳过:8(2%)
|
||||
- 失败:0
|
||||
```
|
||||
|
||||
逐个跟进失败 / 跳过的(走 [[../prepaid/audit-low-balance-and-overdue|低余额预警]] 等)。
|
||||
|
||||
## 系统流程(手动)
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant 业务
|
||||
participant Filament
|
||||
participant ConsumeAction[Prepaid 的 ConsumeAction]
|
||||
participant ConsumeFromPrepaid[ConsumeFromPrepaidAccountAction]
|
||||
participant Bill
|
||||
participant PrepaidAccount
|
||||
participant DB
|
||||
participant Listener
|
||||
|
||||
业务->>Filament: ViewPrepaidAccount → ConsumeAction(选 Bill, 800)
|
||||
Filament->>ConsumeFromPrepaid: handle(account, bill, 800)
|
||||
ConsumeFromPrepaid->>PrepaidAccount: canOperate() ? Active=true
|
||||
ConsumeFromPrepaid->>PrepaidAccount: community_id match? yes
|
||||
ConsumeFromPrepaid->>PrepaidAccount: balance >= 800? yes
|
||||
|
||||
ConsumeFromPrepaid->>DB: 开启事务
|
||||
ConsumeFromPrepaid->>DB: 1. 建 CollectionOrder(type=Bill, +800, meta.fund_source=prepaid)
|
||||
ConsumeFromPrepaid->>DB: 2. 建 CollectionOrderBill(allocated=800)
|
||||
ConsumeFromPrepaid->>PrepaidAccount: 3. consume(bill, 800)
|
||||
PrepaidAccount->>DB: 建 PrepaidTransaction(consume, 3400→2600, related_bill_id)
|
||||
PrepaidAccount->>DB: 更新 balance=2600
|
||||
ConsumeFromPrepaid->>Bill: 4. recordPayment(800)
|
||||
Bill->>DB: paid_amount=800, status=Paid
|
||||
ConsumeFromPrepaid->>Listener: 5. 触发 CollectionOrderCompleted
|
||||
Listener->>DB: 6. 建 Receipt("物业费 ¥800")
|
||||
ConsumeFromPrepaid->>DB: 提交事务
|
||||
|
||||
Filament-->>业务: 成功
|
||||
```
|
||||
|
||||
## 自动 job 流程(待实现)
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Scheduler
|
||||
participant Job[PrepaidAutoDeductionJob]
|
||||
participant Bills
|
||||
participant Action[ConsumeFromPrepaidAccountAction]
|
||||
|
||||
Note over Scheduler: 2026-06-01 00:30
|
||||
|
||||
Scheduler->>Job: dispatch
|
||||
Job->>Bills: SELECT 未付账单(community_id, resident_id 匹配预存款)
|
||||
|
||||
loop 每户
|
||||
Job->>Bills: 按 due_at 升序查未付账单
|
||||
loop 每张账单
|
||||
alt 余额够
|
||||
Job->>Action: handle(account, bill, bill.amount)
|
||||
Note over Action: 同手动模式的链路
|
||||
else 余额不够
|
||||
Job->>Job: 跳过
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Job-->>Scheduler: 完成 + 报告
|
||||
```
|
||||
|
||||
详见 [[../prepaid/auto-deduction-design]] + [[../prepaid/consume-batch-auto-monthly]]。
|
||||
|
||||
## 与单张 / 批量收款的对比
|
||||
|
||||
| 维度 | [[collect-payment-single|单张]] | [[collect-payment-batch|批量]] | **预存款抵(本)** |
|
||||
|---|---|---|---|
|
||||
| 业务人员操作 | 单张点 CollectPayment | 多选 + BatchCollect | 手动 ConsumeAction / 自动 job |
|
||||
| 触发位置 | ViewBill | BillsList | **ViewPrepaidAccount** / 定时任务 |
|
||||
| 资金来源 | 现金 / 微信 / POS / 转账 | 同 | **预存款余额** |
|
||||
| CollectionOrder.meta.fund_source | external | external | **prepaid** |
|
||||
| 业户感知 | 主动付 | 主动付 | **被动收到通知** |
|
||||
| 频率 | 高 | 中 | **未来最高(自动 job)** |
|
||||
|
||||
## 常见问题
|
||||
|
||||
> [!question] 业户预存款不够付,但快有了(等到本月底)怎么办?
|
||||
> 业务上不应等。可:
|
||||
>
|
||||
> - 提示业户立即充值预存款([[../prepaid/deposit-additional-topup]])
|
||||
> - 业户用其他方式付(现金 / 微信)
|
||||
> - 部分抵(如果 Bill 支持部分付,见 [[exception-partial-payment]])
|
||||
|
||||
> [!question] 业户希望某些账单不要从预存款扣(例如不接受被自动扣电费)?
|
||||
> 当前自动 job 待实现,实施时**可加白名单 / 黑名单机制**:
|
||||
> - 业户可设置"只允许物业费自动扣"
|
||||
> - 其他费用(水电气)留给业户主动付
|
||||
>
|
||||
> issue.md 未明确需求,看业务方反馈。
|
||||
|
||||
> [!question] 预存款抵扣的 Bill 后续要作废怎么办?
|
||||
> 走 [[void-paid-bill|作废已付账单]] 流程,但**退款方向不同**:
|
||||
> - 不退现金 / 微信
|
||||
> - **退回预存款**(走 PrepaidAccount::deposit 反向充值)
|
||||
> - 详见 [[void-paid-bill]]"已付作废 + 预存款退还"段
|
||||
|
||||
> [!question] 业户跨社区,A 社区有预存款 ¥5000,B 社区欠物业费 ¥800,能跨社区抵吗?
|
||||
> **不能**。详见 [[../prepaid/exception-cross-community-consume]]"跨社区消费防御"段。
|
||||
|
||||
> [!question] 自动 job 跑的时候,业户同时去前台付现金,会重复收款吗?
|
||||
> 看时序 + 锁机制:
|
||||
> - 若 job 已锁 Bill(乐观锁)→ 前台收款失败(Bill 状态可能已变 Paid)
|
||||
> - 若 job 没锁 → 可能并发问题(罕见,需排查具体实现)
|
||||
>
|
||||
> **预防**:业务人员收款前看 Bill 当前状态,Paid 就不收。
|
||||
|
||||
## 异常分支
|
||||
|
||||
- 业户预存款不够 → 业务推 [[../prepaid/deposit-additional-topup]] 或走现金
|
||||
- 业户预存款冻结 → [[../prepaid/exception-refund-on-frozen|冻结无法抵]]
|
||||
- 跨社区抵企图 → [[../prepaid/exception-cross-community-consume|系统拦截]]
|
||||
- 抵后想撤 → [[void-paid-bill]] + 预存款回填
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [[bill-vs-collection-order]]
|
||||
- [[../prepaid/consume-via-bill-collection-type]]
|
||||
- [[../prepaid/consume-monthly-property-bill]]
|
||||
- [[../prepaid/auto-deduction-design]]
|
||||
- [[../prepaid/consume-batch-auto-monthly]]
|
||||
- [[collect-payment-single]]
|
||||
- [[void-paid-bill]]
|
||||
214
prop-acc/scenarios/billing/create-single-bill-manual.md
Normal file
214
prop-acc/scenarios/billing/create-single-bill-manual.md
Normal file
@@ -0,0 +1,214 @@
|
||||
---
|
||||
title: prop-acc · billing · 场景 - 手动建单(临时收费/调整账单)
|
||||
aliases:
|
||||
- 手动建账单
|
||||
- 临时账单
|
||||
- create-single-bill-manual
|
||||
- 场景-手动建账单
|
||||
tags:
|
||||
- 场景
|
||||
- prop-acc
|
||||
- 账单
|
||||
- 创建
|
||||
audience:
|
||||
- 业务人员
|
||||
- 财务
|
||||
status: 已发布
|
||||
sub_feature: billing
|
||||
last_review: 2026-05-26
|
||||
code_version: 2026-05-22
|
||||
---
|
||||
|
||||
# 场景:手动建单(临时收费/调整账单)
|
||||
|
||||
业务上**不属于周期任务、不属于抄表**的临时收费,通过 `CreateBill` 后台**手工建一张账单**。例如:维修费分摊、特别活动费、单次罚款、跨期补开账单。
|
||||
|
||||
## 典型情境
|
||||
|
||||
> [!example] 真实情境(一):公共维修费分摊
|
||||
> 嘉禾花园 3 单元电梯坏了维修,总成本 ¥15,000。物业公司决定**全单元 30 户业户分摊**(每户 ¥500)。这种"临时性的、不属周期 / 抄表"的费用,业务人员逐户手工建账单(或选定业户清单后批量手工)。
|
||||
|
||||
> [!example] 真实情境(二):个别业户的特别罚款
|
||||
> 张阿姨违反小区车位管理规定(占用应急车位 1 小时),物业罚款 ¥100。业务人员单独给张阿姨建一张账单。
|
||||
|
||||
> [!example] 真实情境(三):跨期补开账单
|
||||
> 业务人员发现陈先生 4 月物业费没生成(系统月初批量时陈先生数据有问题),5 月才发现。需补开 4 月账单。
|
||||
|
||||
## 业务人员视角
|
||||
|
||||
### 第 1 步:打开 CreateBill
|
||||
|
||||
后台 → 账单 → 列表 → 顶部 **"新建"** 按钮 → 进 `CreateBill` 页面。
|
||||
|
||||
### 第 2 步:填表单(`BillForm`)
|
||||
|
||||
| 字段 | 填什么 |
|
||||
|---|---|
|
||||
| **社区(community_id)** | 嘉禾花园(若多社区可选)|
|
||||
| **业户(resident_id)** | 张阿姨(下拉选)|
|
||||
| **房屋(asset_id)** | 12-3-501(自动带入或手选)|
|
||||
| **费用类型(fee_type_id)** | 选合适的 FeeType(物业费 / 杂费 / 罚款 / ...) |
|
||||
| **账单类型(bill_type)** | 通常选 `OneTime` 或 `Adjustment`(看 BillType 枚举)|
|
||||
| **金额(amount)** | ¥500(电梯维修分摊)|
|
||||
| **期次** | 选填(临时账单可不填,或填发生月)|
|
||||
| **到期日(due_at)** | 6 月 15 日 |
|
||||
| **备注(memo)** | **强烈推荐填**,说明缘由,如 "3 单元电梯维修分摊(2026-05),总成本 ¥15,000 ÷ 30 户" |
|
||||
|
||||
> [!warning] Policy 守护
|
||||
> `CreateBill` 需要 `bill.create` 权限。
|
||||
|
||||
### 第 3 步:提交
|
||||
|
||||
系统:
|
||||
|
||||
1. 校验字段(business / asset / fee_type 存在)
|
||||
2. 建 Bill(`status=Unpaid`,`sourceable_type=null` / 或自定义)
|
||||
3. 写 activitylog(单条 Bill 创建,subject=Bill)
|
||||
4. 跳到 `ViewBill` 页面
|
||||
|
||||
### 第 4 步:通知业户
|
||||
|
||||
通常需要业务人员**单独通知**(临时账单不在月度自动推送范围内):
|
||||
|
||||
- 微信 / 短信:"张阿姨,您本月有一笔电梯维修分摊费 ¥500,请于 6 月 15 日前付清"
|
||||
- 附备注说明
|
||||
|
||||
### 第 5 步:批量手工建(电梯维修分摊场景)
|
||||
|
||||
如果是分摊给 30 户业户,逐户建效率低。当前没有"批量手动建" UI,只能:
|
||||
|
||||
- 逐户走 `CreateBill`(30 次)
|
||||
- 或运维 tinker 脚本(SQL 批量 INSERT)
|
||||
- 或要求业务方加"批量手工建"功能
|
||||
|
||||
未来可加:`BulkCreateBillsAction`(给定业户清单 + 模板 → 批量建)。
|
||||
|
||||
## 系统流程
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant 业务[业务人员]
|
||||
participant Filament
|
||||
participant CreateBill
|
||||
participant Activity[activitylog]
|
||||
participant DB
|
||||
|
||||
业务->>Filament: ListBills → 新建 → CreateBill
|
||||
Filament->>CreateBill: 渲染 form
|
||||
业务->>CreateBill: 填业户 / 金额 / 备注 / 提交
|
||||
CreateBill->>DB: 校验 fields
|
||||
CreateBill->>DB: 建 Bill(status=Unpaid, bill_type=OneTime, sourceable=null)
|
||||
CreateBill->>Activity: log(event=created, subject=Bill)
|
||||
CreateBill-->>Filament: 跳转 ViewBill
|
||||
Filament-->>业务: 显示新账单
|
||||
```
|
||||
|
||||
## 业户视角
|
||||
|
||||
业户收到通知:
|
||||
|
||||
> 张阿姨您好,您本月有一笔账单:
|
||||
> - 电梯维修分摊费:¥500
|
||||
> - 备注:3 单元电梯维修分摊
|
||||
> - 到期日:6 月 15 日
|
||||
>
|
||||
> 请通过微信小程序 / 前台 / 预存款 任选方式付款。
|
||||
|
||||
业户:
|
||||
|
||||
- 看明白 → 付([[collect-payment-single]])
|
||||
- 不接受 → 投诉 / 走纠纷流程(可能 [[suspend-bill]] 挂起)
|
||||
|
||||
## 三种典型情境的不同处理
|
||||
|
||||
### 情境 1:电梯维修分摊
|
||||
|
||||
| 字段 | 值 |
|
||||
|---|---|
|
||||
| `bill_type` | `OneTime` |
|
||||
| `fee_type_id` | "维修分摊费"(若有此 FeeType,否则用通用"杂费")|
|
||||
| `amount` | ¥500 |
|
||||
| 备注 | 详细说明(分摊依据 + 总成本)|
|
||||
|
||||
业务上还要**备齐资料**:维修发票、户主同意决议(若有业主大会决议)、分摊依据。这些不在系统(物业备查)。
|
||||
|
||||
### 情境 2:违规罚款
|
||||
|
||||
| 字段 | 值 |
|
||||
|---|---|
|
||||
| `bill_type` | `OneTime` |
|
||||
| `fee_type_id` | "罚款"(若有此 FeeType)|
|
||||
| `amount` | ¥100 |
|
||||
| 备注 | 违规事由 + 处罚依据(管理规定第 X 条) |
|
||||
|
||||
业务上要 **业户书面确认**(违规事实),否则业户可能投诉 / 拒付。
|
||||
|
||||
### 情境 3:跨期补开
|
||||
|
||||
| 字段 | 值 |
|
||||
|---|---|
|
||||
| `bill_type` | `Periodic`(若是月物业费的补开)|
|
||||
| `period` | **填实际期次**(4 月)|
|
||||
| `amount` | 同正常月物业费 |
|
||||
| 备注 | "4 月物业费补开,原因 XXX" |
|
||||
|
||||
业务人员**需要**:
|
||||
|
||||
- 确认陈先生 4 月确实欠物业费(没有遗漏)
|
||||
- 与陈先生沟通(突然补开他可能困惑)
|
||||
|
||||
## 与周期账单 / 计量账单的对比
|
||||
|
||||
| 维度 | 周期账单([[create-periodic-property-fee]]) | 计量账单([[create-meter-bill-auto]]) | **手动账单(本场景)** |
|
||||
|---|---|---|---|
|
||||
| 触发 | 业务人员批量生成 | 抄表完成自动 | **业务人员单笔手工** |
|
||||
| 数量 | 一次 100-1000 张 | 一次 N 张(对应 reading 数)| **一次 1 张** |
|
||||
| 金额来源 | RatePlan + 房屋参数 | RatePlan + 用量计算 | **业务人员手填** |
|
||||
| 业务场景 | 月度固定收费 | 抄表后变动收费 | **临时收费 / 调整** |
|
||||
| sourceable | null / 周期任务 | MeterReading | **null** |
|
||||
| 频率 | 每月 1 次 | 每月 1 次 | **不定时** |
|
||||
|
||||
## 常见问题
|
||||
|
||||
> [!question] 手动建单和周期账单的 fee_type 重复怎么办?
|
||||
> 例如本月已经有"5 月物业费"账单,业务人员又手工建一张同 fee_type 同期次的 → 数据库 unique 约束可能拦截(若有),否则会有两张并存。
|
||||
>
|
||||
> **预防**:手动建单前确认是否已有同类账单。
|
||||
|
||||
> [!question] 手动建单金额没限制吗?
|
||||
> 系统层面无限制。**业务上**应有审核流程(高金额 > X 元 应主管审批,但当前系统不强制此审批流)。
|
||||
|
||||
> [!question] 跨期补开的账单影响月度报表吗?
|
||||
> 看报表的查询:
|
||||
>
|
||||
> - 按 `created_at`(账单创建时间)→ 影响 5 月报表(实际是 5 月创建)
|
||||
> - 按 `billing_period_start`(账单期次)→ 影响 4 月报表
|
||||
>
|
||||
> 不同报表用不同维度。月度对账通常按期次。
|
||||
|
||||
> [!question] 手动建单后业户拒付?
|
||||
> 走标准流程:
|
||||
>
|
||||
> - 沟通 → 协商
|
||||
> - 不接受 → [[suspend-bill|挂起]] 等争议解决
|
||||
> - 调解失败 → 物业法务介入(走线下,系统不参与司法)
|
||||
|
||||
> [!question] 业务人员误建一张账单怎么撤?
|
||||
> 若立即发现:[[delete-bill-unpaid|物理删除]](Unpaid 无付款)。
|
||||
> 若已发出:[[void-paid-bill|作废]](留状态留审计)。
|
||||
|
||||
## 异常分支
|
||||
|
||||
- 误建 → 立即删除 [[delete-bill-unpaid]]
|
||||
- 业户拒付 → [[suspend-bill]]
|
||||
- 已发现要修正金额 → 作废 + 新建 [[void-paid-bill]]
|
||||
- 批量手工建 → 待业务方提需求 + 加 BulkCreateBillsAction
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [[bill-types-and-sources]]
|
||||
- [[bill-six-state-machine]]
|
||||
- [[create-periodic-property-fee]]
|
||||
- [[create-meter-bill-auto]]
|
||||
- [[delete-bill-unpaid]]
|
||||
- [[suspend-bill]]
|
||||
Reference in New Issue
Block a user