rustjr-account-management/docs/domains/04-reconciliation.md
tangweijie 1460187516 docs: 添加完整技术文档体系
- 系统架构文档 (architecture/README.md)
- 6个领域文档:
  - 账户域 (01-account.md)
  - 账务域 (02-ledger.md)
  - 交易域 (03-transaction.md)
  - 对账域 (04-reconciliation.md)
  - 补偿域 (05-compensation.md)
  - 积分域 (06-points.md)
- API 参考文档 (api/README.md)
- 前后端对接清单 (integration/frontend-backend.md)
2026-01-05 18:12:37 +08:00

455 lines
13 KiB
Markdown
Raw 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.

# 对账域 (Reconciliation Domain)
## 一、领域概述
对账域负责确保系统账务与银行账务的一致性,包括交易匹配、差异处理、手工补录、三账校验等功能。
## 二、核心概念
### 2.1 三账对账闭环
```
┌─────────────────────────────────────────────────────────┐
│ 三账校验公式 │
│ │
│ 总账余额 = 银行账余额 + 在途净额 │
│ │
│ ledger_total = bank_balance + transit_net │
└─────────────────────────────────────────────────────────┘
银行账: 银行实际余额(通过银行接口查询)
在途账: 已扣未确认的资金transit_amount
总账: 系统记账余额personal + labor + frozen
```
### 2.2 对账流程
```mermaid
graph TD
A[获取银行流水] --> B[获取系统交易]
B --> C[交易匹配]
C --> D{匹配结果}
D -->|匹配| E[标记已匹配]
D -->|系统未达| F[创建系统未达项]
D -->|银行未达| G[创建银行未达项]
D -->|金额不匹配| H[创建差异项]
E --> I[三账校验]
F --> I
G --> I
H --> I
I --> J{是否平衡}
J -->|是| K[对账完成]
J -->|否| L[需要审核]
```
## 三、核心实体
### 3.1 对账批次 (ReconciliationBatch)
```rust
pub struct ReconciliationBatch {
pub id: i64,
pub batch_no: String, // 批次编号
pub physical_account_id: i64, // 实体账户ID
pub recon_date: NaiveDate, // 对账日期
pub total_count: i32, // 总记录数
pub matched_count: i32, // 匹配数
pub mismatch_count: i32, // 不匹配数
pub status: ReconciliationStatus, // 状态
pub created_at: DateTime<Utc>, // 创建时间
pub completed_at: Option<DateTime<Utc>>, // 完成时间
// 三账对账结果
pub bank_total: Option<Decimal>, // 银行账汇总
pub transit_net: Option<Decimal>, // 在途净额
pub ledger_total: Option<Decimal>, // 总账汇总
pub three_account_balanced: Option<bool>, // 三账是否平衡
}
```
**核心方法**
```rust
impl ReconciliationBatch {
// 计算匹配率
pub fn match_rate(&self) -> f64 {
if self.total_count == 0 {
return 100.0;
}
(self.matched_count as f64 / self.total_count as f64) * 100.0
}
// 是否全部匹配
pub fn is_all_matched(&self) -> bool {
self.mismatch_count == 0
}
// 是否已完成三账对账
pub fn has_three_account_result(&self) -> bool {
self.three_account_balanced.is_some()
}
// 三账差异金额
pub fn three_account_difference(&self) -> Option<Decimal> {
match (self.ledger_total, self.bank_total, self.transit_net) {
(Some(ledger), Some(bank), Some(transit)) => {
Some(ledger - (bank + transit))
}
_ => None,
}
}
}
```
### 3.2 对账明细项 (ReconciliationItem)
```rust
pub struct ReconciliationItem {
pub id: i64,
pub batch_id: i64, // 批次ID
pub system_txn_no: Option<String>, // 系统交易号
pub bank_ref_no: Option<String>, // 银行参考号
pub system_amount: Option<Decimal>, // 系统金额
pub bank_amount: Option<Decimal>, // 银行金额
pub diff_amount: Decimal, // 差异金额
pub status: ReconciliationItemStatus, // 状态
pub remark: Option<String>, // 处理备注
pub created_at: DateTime<Utc>,
}
```
**核心方法**
```rust
impl ReconciliationItem {
// 检查是否需要手工处理
pub fn needs_manual_handling(&self) -> bool {
matches!(
self.status,
ReconciliationItemStatus::SystemUnreached
| ReconciliationItemStatus::BankUnreached
| ReconciliationItemStatus::AmountMismatch
)
}
}
```
### 3.3 手工补录 (ManualAdjustment)
```rust
pub struct ManualAdjustment {
pub id: i64,
pub adjustment_no: String, // 补录编号
pub related_txn_no: Option<String>, // 关联交易号
pub reconciliation_item_id: Option<i64>,// 关联对账项ID
pub adjustment_type: AdjustmentType, // 补录类型
pub account_id: i64, // 账户ID
pub amount: Decimal, // 金额
pub reason: String, // 原因说明
pub operator: String, // 操作人
pub approver: Option<String>, // 审批人
pub status: AdjustmentStatus, // 状态
pub created_at: DateTime<Utc>,
pub approved_at: Option<DateTime<Utc>>, // 审批时间
}
```
## 四、枚举类型
### 4.1 对账批次状态 (ReconciliationStatus)
```rust
pub enum ReconciliationStatus {
Processing, // 处理中
Completed, // 已完成
NeedReview, // 需要审核
}
```
### 4.2 对账项状态 (ReconciliationItemStatus)
```rust
pub enum ReconciliationItemStatus {
Matched, // 已匹配
SystemUnreached, // 系统未达(系统有银行无)
BankUnreached, // 银行未达(银行有系统无)
AmountMismatch, // 金额不匹配
Adjusted, // 已调整
}
```
| 状态 | 说明 | 处理方式 |
|------|------|----------|
| Matched | 系统与银行完全匹配 | 无需处理 |
| SystemUnreached | 系统有记录但银行无 | 核实后补录或冲销 |
| BankUnreached | 银行有记录但系统无 | 核实后补录 |
| AmountMismatch | 金额不一致 | 核实后调整 |
| Adjusted | 已手工调整 | 已处理 |
### 4.3 补录类型 (AdjustmentType)
```rust
pub enum AdjustmentType {
Add, // 补录(新增)
Reverse, // 冲销
Modify, // 修改
}
```
### 4.4 补录状态 (AdjustmentStatus)
```rust
pub enum AdjustmentStatus {
Pending, // 待审批
Approved, // 已审批
Rejected, // 已拒绝
}
```
## 五、对账匹配规则
### 5.1 匹配策略
1. **精确匹配**:银行交易号 = 系统银行参考号
2. **金额匹配**:金额完全一致
3. **时间匹配**:交易时间在允许范围内
4. **方向匹配**:入账/出账方向一致
### 5.2 匹配优先级
```
1. 按银行交易号精确匹配
2. 按金额 + 时间 + 方向模糊匹配
3. 按 SourceKey 匹配(入账)
4. 无法匹配则标记为未达
```
### 5.3 差异处理
| 差异类型 | 处理方式 |
|----------|----------|
| 金额差异 < 1分 | 自动调平 |
| 金额差异 < 100元 | 人工审核 |
| 金额差异 >= 100元 | 升级处理 |
## 六、三账校验
### 6.1 校验结果
```rust
pub struct ThreeAccountResult {
pub bank_balance: Decimal, // 银行账余额
pub transit_net: Decimal, // 在途净额
pub ledger_total: Decimal, // 总账余额
pub is_balanced: bool, // 是否平衡
pub difference: Decimal, // 差异金额
}
```
### 6.2 校验公式
```
期望总账 = 银行余额 + 在途净额
差异 = 实际总账 - 期望总账
平衡 = (差异 == 0)
```
### 6.3 不平衡原因分析
| 原因 | 说明 | 处理 |
|------|------|------|
| 银行延迟 | 银行入账延迟 | 等待银行同步 |
| 系统错误 | 记账错误 | 查找并修正 |
| 在途异常 | 在途状态不正确 | 核实在途交易 |
| 并发问题 | 对账期间有新交易 | 锁定后重新对账 |
## 七、领域服务
### 7.1 ReconciliationService
```rust
impl ReconciliationService {
// ========== 对账批次管理 ==========
// 执行对账
pub async fn run_reconciliation(&self, req: CreateReconciliationBatchRequest) -> Result<ReconciliationBatch>;
// 获取对账批次
pub async fn get_batch(&self, id: i64) -> Result<ReconciliationBatch>;
// 获取对账明细
pub async fn get_batch_items(&self, batch_id: i64) -> Result<Vec<ReconciliationItem>>;
// ========== 三账校验 ==========
// 执行三账校验
pub async fn verify_three_accounts(&self, physical_account_id: i64) -> Result<ThreeAccountVerificationResult>;
// 更新批次三账结果
pub async fn update_three_account_result(&self, batch_id: i64, result: &ThreeAccountResult) -> Result<()>;
// ========== 手工补录 ==========
// 创建手工补录
pub async fn create_adjustment(&self, req: CreateManualAdjustmentRequest) -> Result<ManualAdjustment>;
// 审批补录
pub async fn approve_adjustment(&self, id: i64, approver: &str) -> Result<()>;
// 拒绝补录
pub async fn reject_adjustment(&self, id: i64, approver: &str, reason: &str) -> Result<()>;
// 获取待审批补录
pub async fn list_pending_adjustments(&self) -> Result<Vec<ManualAdjustment>>;
// ========== 统计查询 ==========
// 获取对账统计
pub async fn get_stats(&self, batch_id: i64) -> Result<ReconciliationStats>;
}
```
### 7.2 三账校验实现
```rust
pub async fn verify_three_accounts(&self, physical_account_id: i64) -> Result<ThreeAccountVerificationResult> {
// 1. 获取银行余额
let bank_balance = self.bank_client.query_balance(physical_account_id).await?;
// 2. 计算在途净额
let transit_net = self.ledger_service.get_transit_total(physical_account_id).await?;
// 3. 计算总账余额
let ledger_total = self.ledger_service.get_ledger_total(physical_account_id).await?;
// 4. 校验
let expected_total = bank_balance + transit_net;
let difference = ledger_total - expected_total;
let is_balanced = difference.abs() < Decimal::new(1, 2); // 允许1分误差
Ok(ThreeAccountVerificationResult {
physical_account_id,
bank_balance,
transit_net,
ledger_total,
expected_total,
difference,
is_balanced,
verified_at: Utc::now(),
})
}
```
## 八、API 接口
| 方法 | 路径 | 说明 |
|------|------|------|
| POST | /api/v1/reconciliation/run | 执行对账 |
| GET | /api/v1/reconciliation/batches/:id | 获取对账批次 |
| GET | /api/v1/reconciliation/batches/:id/items | 获取对账明细 |
| GET | /api/v1/reconciliation/three-account/:id | 三账校验 |
| POST | /api/v1/reconciliation/adjustments | 创建手工补录 |
| POST | /api/v1/reconciliation/adjustments/:id/approve | 审批补录 |
| POST | /api/v1/reconciliation/adjustments/:id/reject | 拒绝补录 |
| GET | /api/v1/reconciliation/adjustments/pending | 获取待审批补录 |
## 九、数据库表结构
### 9.1 reconciliation_batch 表
```sql
CREATE TABLE reconciliation_batch (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
batch_no VARCHAR(64) NOT NULL UNIQUE,
physical_account_id BIGINT NOT NULL,
recon_date DATE NOT NULL,
total_count INT DEFAULT 0,
matched_count INT DEFAULT 0,
mismatch_count INT DEFAULT 0,
status VARCHAR(32) DEFAULT 'processing',
bank_total DECIMAL(20, 2),
transit_net DECIMAL(20, 2),
ledger_total DECIMAL(20, 2),
three_account_balanced BOOLEAN,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
completed_at TIMESTAMP NULL,
INDEX idx_physical_account (physical_account_id),
INDEX idx_recon_date (recon_date),
INDEX idx_status (status)
);
```
### 9.2 reconciliation_item 表
```sql
CREATE TABLE reconciliation_item (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
batch_id BIGINT NOT NULL,
system_txn_no VARCHAR(64),
bank_ref_no VARCHAR(64),
system_amount DECIMAL(20, 2),
bank_amount DECIMAL(20, 2),
diff_amount DECIMAL(20, 2) DEFAULT 0.00,
status VARCHAR(32) NOT NULL,
remark TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (batch_id) REFERENCES reconciliation_batch(id),
INDEX idx_batch (batch_id),
INDEX idx_status (status)
);
```
### 9.3 manual_adjustment 表
```sql
CREATE TABLE manual_adjustment (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
adjustment_no VARCHAR(64) NOT NULL UNIQUE,
related_txn_no VARCHAR(64),
reconciliation_item_id BIGINT,
adjustment_type VARCHAR(32) NOT NULL,
account_id BIGINT NOT NULL,
amount DECIMAL(20, 2) NOT NULL,
reason TEXT NOT NULL,
operator VARCHAR(64) NOT NULL,
approver VARCHAR(64),
status VARCHAR(32) DEFAULT 'pending',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
approved_at TIMESTAMP NULL,
INDEX idx_status (status),
INDEX idx_operator (operator)
);
```
## 十、对账时机
### 10.1 自动对账
- 每日定时对账T+1
- 配置对账频率(按账户)
- 批量处理
### 10.2 手动对账
- 运营人员触发
- 指定日期范围
- 单账户或多账户
### 10.3 实时对账
- 大额交易实时校验
- 异常交易即时告警
- 关键节点检查
## 十一、告警机制
| 告警级别 | 触发条件 | 处理方式 |
|----------|----------|----------|
| 警告 | 匹配率 < 99% | 记录日志 |
| 严重 | 三账不平衡 | 通知运营 |
| 紧急 | 大额差异 | 升级处理 |