Files
uniprop-manual/prop-acc/一次性收费/场景-超时未付自动作废.md
2026-05-25 13:29:32 +08:00

143 lines
5.1 KiB
Markdown

---
title: 场景 - 超时未付自动作废
tags:
- prop-acc
- 一次性收费
- 业务场景
- 取消退款
audience:
- 业户
- 业务人员
status: stable
last_reviewed: 2026-05-25
code_version: 2026-05-22
---
# 场景:超时未付自动作废
业户在小程序下单后**没有及时付款**,系统在订单到期后**自动作废**。
> [!warning] 实现状态
> 后端 `VoidAdHocEventAction` 已就绪。**自动扫描 scheduled job 尚未实现**(预定与 payment-gateway webhook 同期上线)。本场景描述上线后体验。
## 典型情境
> [!example] 真实情境
> 周三下午,陈先生在小程序上下单一张游泳卡 ¥200。下单完接了个电话,把这事忘了。
>
> 30 分钟后他想起来,打开小程序"我的订单",订单已经变成 "已作废"。原因栏写着:**[订单超时作废] expires_at 已过**。
## 业户视角
### 您看到什么
下单后超时未付,小程序"我的订单"里:
```
游泳卡(月卡)
订单号:CO-20260525-XXX
金额:¥200
状态:❌ 已作废
作废原因:订单超时未付款
```
> [!info] 不影响后续
> 您可以**立即重新下一单**。新订单按当前价格冻结(如果项目涨价了,以新价为准)。
### 为什么要超时?
> [!tip] 业户视角:为什么超时设计?
> 假设您下单不付款占着这个金额很久,后台一直把项目库存(比如装修证只有 100 张)留给您 —— 不公平。**超时机制让资源可循环**。
## 业务人员视角
### 业务人员一般不需要管
> [!success] 完全自动化
> Scheduled job 每隔一段时间(比如每小时)扫描全表,自动处理超时单。**前台不用做任何事**。
### 业务人员能看到什么
每个超时作废的订单在 Filament 后台:
- 状态:`Voided`
- meta 字段记录:`voided_at` / `voided_reason: "[订单超时作废]"` / `voided_by: null`(系统自动,无操作员)
### 如果业户来问"我的订单怎么没了"
```
1. 在 Filament 后台搜业户姓名 / 订单号
2. 找到 Voided 记录
3. 告诉业户:"您的订单在 X 月 X 日下午 X 点超时作废了,原因是没在 30 分钟内完成支付。请重新下单。"
```
## 系统流程
```mermaid
sequenceDiagram
participant 业户
participant 小程序
participant 系统
participant Scheduled Job
业户->>小程序: 下单游泳卡 ¥200
小程序->>系统: CreatePendingAdHocEventAction
系统->>系统: 建 AdHocEvent + CO,expires_at = now + 30min
系统-->>业户: 返订单号,等待支付
Note over 业户: 业户忘了付钱
Note over Scheduled Job: 每小时扫描一次
Scheduled Job->>系统: 查询 CO where status=pending AND expires_at < now()
系统-->>Scheduled Job: 返回所有超时 Pending 单
loop 对每个超时单
Scheduled Job->>系统: VoidAdHocEventAction
系统->>系统: 级联废 AdHocEvent + CO
系统->>系统: 写 meta.voided_reason = "[订单超时作废]"
end
业户->>小程序: 想起来要付钱
小程序->>系统: 查询订单
系统-->>小程序: 状态 Voided
小程序-->>业户: 显示"订单已作废,请重新下单"
```
## 几个常见超时周期(可配置)
| 项目类型 | 推荐超时 | 理由 |
|---|---|---|
| **泳票 / 充电桩** | 30 分钟 | 业户高频下完即付 |
| **IC 卡** | 2 小时 | 业户可能要查档案、对房号 |
| **装修证(单张)** | 1 天 | 装修公司可能要走内部审批 |
| **装修证(批量)** | 7 天 | 大公司付款流程长 |
> [!warning] 跨渠道补缴场景请用长 expires_at
> 跨渠道补缴([[场景-跨渠道补缴]])时,儿女线上下单、老人现场付款 —— 中间可能隔几天。**这种场景建议 expires_at 设 7 天**,避免老人到前台时单子已废。具体配置看每个 RatePlan 的设置。
## 常见问题
> [!question] 我的订单超时了能恢复吗?
> **不能**。超时作废是终态。直接重新下单。
> [!question] 重新下单价格会不会涨?
> **可能**。系统按下单**当时的价格冻结**;如果上次下单到现在物业调价了,新订单按新价。
> [!question] 我付款的瞬间订单刚好超时,会重复扣款吗?
> **不会**。系统在 `MarkAdHocEventPaidAction` 内部有事务保护:如果订单已被作废,支付回调会失败,微信会原路退回。
> [!question] 物业前台能"延长有效期"吗?
> 当前**不支持**。要延长只能业户自己重新下单。是否要支持手动延长是个业务决策,等业务方反馈再加。
## 系统配置(技术细节,业务人员可跳过)
- 扫描 job 在 `app/Console/Kernel.php` 注册,每小时跑一次
- 查询语句:`SELECT * FROM acc_collection_orders WHERE status='pending' AND expires_at < NOW()`
- 调用 `VoidAdHocEventAction::handle($event, '[订单超时作废] expires_at < now()')`
## 相关概念
- [[概念-AdHocEvent状态机]] — Pending → Voided 流转
- [[概念-CollectionOrder与Receipt]] — `expires_at` 字段挂在 CollectionOrder 上的设计原因
- [[场景-B流-小程序下单+微信支付]] — 业户下单的正向流程
- [[场景-跨渠道补缴]] — 长 expires_at 的典型用例