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

13 KiB
Raw Permalink Blame History

对账域 (Reconciliation Domain)

一、领域概述

对账域负责确保系统账务与银行账务的一致性,包括交易匹配、差异处理、手工补录、三账校验等功能。

二、核心概念

2.1 三账对账闭环

┌─────────────────────────────────────────────────────────┐
│                     三账校验公式                         │
│                                                         │
│     总账余额 = 银行账余额 + 在途净额                      │
│                                                         │
│     ledger_total = bank_balance + transit_net          │
└─────────────────────────────────────────────────────────┘

银行账: 银行实际余额(通过银行接口查询)
在途账: 已扣未确认的资金transit_amount
总账:   系统记账余额personal + labor + frozen

2.2 对账流程

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)

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>, // 三账是否平衡
}

核心方法

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)

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>,
}

核心方法

impl ReconciliationItem {
    // 检查是否需要手工处理
    pub fn needs_manual_handling(&self) -> bool {
        matches!(
            self.status,
            ReconciliationItemStatus::SystemUnreached
                | ReconciliationItemStatus::BankUnreached
                | ReconciliationItemStatus::AmountMismatch
        )
    }
}

3.3 手工补录 (ManualAdjustment)

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)

pub enum ReconciliationStatus {
    Processing, // 处理中
    Completed,  // 已完成
    NeedReview, // 需要审核
}

4.2 对账项状态 (ReconciliationItemStatus)

pub enum ReconciliationItemStatus {
    Matched,         // 已匹配
    SystemUnreached, // 系统未达(系统有银行无)
    BankUnreached,   // 银行未达(银行有系统无)
    AmountMismatch,  // 金额不匹配
    Adjusted,        // 已调整
}
状态 说明 处理方式
Matched 系统与银行完全匹配 无需处理
SystemUnreached 系统有记录但银行无 核实后补录或冲销
BankUnreached 银行有记录但系统无 核实后补录
AmountMismatch 金额不一致 核实后调整
Adjusted 已手工调整 已处理

4.3 补录类型 (AdjustmentType)

pub enum AdjustmentType {
    Add,     // 补录(新增)
    Reverse, // 冲销
    Modify,  // 修改
}

4.4 补录状态 (AdjustmentStatus)

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 校验结果

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

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 三账校验实现

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 表

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 表

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 表

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% 记录日志
严重 三账不平衡 通知运营
紧急 大额差异 升级处理