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

356 lines
11 KiB
Markdown
Raw Permalink 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.

# 账户域 (Account Domain)
## 一、领域概述
账户域负责管理银行账户的完整生命周期,包括实体账户(对应真实银行账户)和虚拟子账户(在实体账户下创建的逻辑账户)。
## 二、核心实体
### 2.1 实体账户 (PhysicalAccount)
实体账户对应真实的银行账户,是资金管理的基础单元。
```rust
pub struct PhysicalAccount {
pub id: i64, // 账户ID
pub account_no: String, // 银行账号
pub bank_code: String, // 银行代码
pub bank_name: Option<String>, // 银行名称
pub consistency_mode: ConsistencyMode, // 一致性模式
pub outbound_control: OutboundControl, // 出金管控模式
pub status: AccountStatus, // 账户状态
pub created_at: DateTime<Utc>, // 创建时间
pub updated_at: DateTime<Utc>, // 更新时间
}
```
**核心方法**
- `is_active()` - 检查账户是否可用
- `can_outbound()` - 检查是否允许出金
### 2.2 虚拟子账户 (VirtualSubAccount)
虚拟子账户是在实体账户下创建的逻辑账户,用于资金隔离和管理。
```rust
pub struct VirtualSubAccount {
pub id: i64, // 子账户ID
pub physical_account_id: i64, // 所属实体账户ID
pub account_code: String, // 子账户编号
pub account_type: SubAccountType, // 子账户类型
pub valid_from: Option<DateTime<Utc>>, // 有效期开始
pub valid_to: Option<DateTime<Utc>>, // 有效期结束
pub status: AccountStatus, // 账户状态
pub created_at: DateTime<Utc>, // 创建时间
pub updated_at: DateTime<Utc>, // 更新时间
}
```
**核心方法**
- `is_active()` - 检查账户是否可用(考虑有效期)
- `is_temporary()` - 是否为临时账户
- `is_expired()` - 临时账户是否过期
### 2.3 账户控制 (AccountControl)
账户控制配置,用于设置对账频率和银行对接配置。
```rust
pub struct AccountControl {
pub id: i64,
pub physical_account_id: i64,
pub reconciliation_interval: i32, // 对账频率(分钟)
pub direct_connect_config: Option<Value>, // 银企直连配置
pub third_party_config: Option<Value>, // 第三方支付配置
}
```
### 2.4 临时账户池 (SubAccountPool)
管理临时子账户的池,支持批量创建和自动销户。
```rust
pub struct SubAccountPool {
pub id: i64,
pub physical_account_id: i64,
pub name: String,
pub valid_from: DateTime<Utc>,
pub valid_to: DateTime<Utc>,
pub auto_close_rule: Option<Value>, // 自动销户规则
}
```
## 三、枚举类型
### 3.1 账户状态 (AccountStatus)
```rust
pub enum AccountStatus {
Active, // 正常
Frozen, // 冻结
Closed, // 已关闭
}
```
**状态转移规则**
```
Active ──► Frozen ──► Active
│ │
└──────► Closed ◄────┘
```
### 3.2 一致性模式 (ConsistencyMode)
```rust
pub enum ConsistencyMode {
Strong, // 强一致性 - 交易需等待银行确认
Eventual, // 最终一致性 - 先记账后对账
}
```
| 模式 | 特点 | 适用场景 |
|------|------|----------|
| Strong | 实时确认,响应慢 | 大额转账 |
| Eventual | 异步确认,响应快 | 小额高频 |
### 3.3 出金管控模式 (OutboundControl)
```rust
pub enum OutboundControl {
ReceiveOnly, // 只收不付
OnlineBank, // 网银控制
Token, // 令牌控制
}
```
| 模式 | 说明 | 使用场景 |
|------|------|----------|
| ReceiveOnly | 禁止出金 | 归集账户 |
| OnlineBank | 网银审批出金 | 常规账户 |
| Token | 令牌验证出金 | 高安全账户 |
### 3.4 账户类型 (AccountType)
```rust
pub enum AccountType {
Physical, // 实体账户
Virtual, // 虚拟账户
}
```
### 3.5 子账户类型 (SubAccountType)
```rust
pub enum SubAccountType {
Settlement, // 结算子账户
Management, // 管理子账户
Temporary, // 临时子账户
}
```
| 类型 | 说明 | 特点 |
|------|------|------|
| Settlement | 结算账户 | 长期使用,用于日常结算 |
| Management | 管理账户 | 内部管理,资金归集 |
| Temporary | 临时账户 | 有有效期,自动销户 |
## 四、领域服务
### 4.1 AccountService
账户域的核心服务,提供账户管理功能。
```rust
impl AccountService {
// 创建实体账户
pub async fn create_physical_account(&self, req: CreatePhysicalAccountRequest) -> Result<PhysicalAccount>;
// 获取实体账户
pub async fn get_physical_account(&self, id: i64) -> Result<PhysicalAccount>;
// 获取实体账户列表(分页)
pub async fn list_physical_accounts_paginated(
&self,
status: Option<AccountStatus>,
keyword: Option<String>,
page: i32,
page_size: i32
) -> Result<(Vec<PhysicalAccount>, i64)>;
// 冻结实体账户
pub async fn freeze_physical_account(&self, id: i64) -> Result<()>;
// 解冻实体账户
pub async fn unfreeze_physical_account(&self, id: i64) -> Result<()>;
// 创建虚拟子账户
pub async fn create_sub_account(&self, req: CreateVirtualSubAccountRequest) -> Result<VirtualSubAccount>;
// 批量创建子账户
pub async fn batch_create_sub_accounts(&self, req: BatchCreateSubAccountRequest) -> Result<Vec<VirtualSubAccount>>;
// 关闭子账户
pub async fn close_sub_account(&self, id: i64) -> Result<()>;
// 获取实体账户下的子账户列表
pub async fn list_sub_accounts(&self, physical_account_id: i64) -> Result<Vec<VirtualSubAccount>>;
}
```
## 五、仓储接口
### 5.1 PhysicalAccountRepository
```rust
#[async_trait]
pub trait PhysicalAccountRepository: Send + Sync {
async fn create(&self, account: &PhysicalAccount) -> Result<i64>;
async fn find_by_id(&self, id: i64) -> Result<Option<PhysicalAccount>>;
async fn find_by_account_no(&self, account_no: &str) -> Result<Option<PhysicalAccount>>;
async fn find_all(&self) -> Result<Vec<PhysicalAccount>>;
async fn find_paginated(&self, status: Option<AccountStatus>, keyword: Option<String>, offset: i64, limit: i64) -> Result<Vec<PhysicalAccount>>;
async fn count(&self, status: Option<AccountStatus>, keyword: Option<String>) -> Result<i64>;
async fn update_status(&self, id: i64, status: AccountStatus) -> Result<()>;
}
```
### 5.2 VirtualSubAccountRepository
```rust
#[async_trait]
pub trait VirtualSubAccountRepository: Send + Sync {
async fn create(&self, account: &VirtualSubAccount) -> Result<i64>;
async fn find_by_id(&self, id: i64) -> Result<Option<VirtualSubAccount>>;
async fn find_by_physical_account(&self, physical_account_id: i64) -> Result<Vec<VirtualSubAccount>>;
async fn find_expired_temporary(&self) -> Result<Vec<VirtualSubAccount>>;
async fn update_status(&self, id: i64, status: AccountStatus) -> Result<()>;
async fn batch_create(&self, accounts: &[VirtualSubAccount]) -> Result<Vec<i64>>;
}
```
## 六、业务规则
### 6.1 账户创建规则
1. 银行账号必须唯一
2. 实体账户必须关联有效的银行代码
3. 子账户编号在同一实体账户下必须唯一
4. 临时账户必须设置有效期
### 6.2 账户状态规则
1. 只有 `Active` 状态的账户可以进行交易
2. `Frozen` 状态只影响出金,入金正常
3. `Closed` 状态不可进行任何交易
4. 账户关闭前必须余额为零
### 6.3 出金管控规则
1. `ReceiveOnly` 模式禁止任何出金操作
2. `OnlineBank` 模式需要通过网银审批
3. `Token` 模式需要提供有效令牌
## 七、API 接口
| 方法 | 路径 | 说明 |
|------|------|------|
| POST | /api/v1/physical-accounts | 创建实体账户 |
| GET | /api/v1/physical-accounts | 获取实体账户列表 |
| GET | /api/v1/physical-accounts/:id | 获取实体账户详情 |
| POST | /api/v1/physical-accounts/:id/freeze | 冻结实体账户资金 |
| POST | /api/v1/physical-accounts/:id/unfreeze | 解冻实体账户资金 |
| POST | /api/v1/sub-accounts | 创建虚拟子账户 |
| GET | /api/v1/sub-accounts/:id | 获取子账户详情 |
| GET | /api/v1/sub-accounts/:id/balance | 获取子账户余额 |
| POST | /api/v1/sub-accounts/:id/freeze | 冻结子账户资金 |
| POST | /api/v1/sub-accounts/:id/unfreeze | 解冻子账户资金 |
| POST | /api/v1/sub-accounts/:id/close | 关闭子账户 |
| GET | /api/v1/physical-accounts/:id/sub-accounts | 获取实体账户下的子账户列表 |
## 八、数据库表结构
### 8.1 physical_account 表
```sql
CREATE TABLE physical_account (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
account_no VARCHAR(64) NOT NULL UNIQUE,
account_name VARCHAR(128),
bank_code VARCHAR(32) NOT NULL,
bank_name VARCHAR(128),
consistency_mode VARCHAR(32) DEFAULT 'eventual',
outbound_control VARCHAR(32) DEFAULT 'online_bank',
status VARCHAR(32) DEFAULT 'active',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_bank_code (bank_code),
INDEX idx_status (status)
);
```
### 8.2 virtual_sub_account 表
```sql
CREATE TABLE virtual_sub_account (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
physical_account_id BIGINT NOT NULL,
account_code VARCHAR(64) NOT NULL,
account_type VARCHAR(32) DEFAULT 'settlement',
valid_from TIMESTAMP NULL,
valid_to TIMESTAMP NULL,
status VARCHAR(32) DEFAULT 'active',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (physical_account_id) REFERENCES physical_account(id),
UNIQUE INDEX idx_account_code (physical_account_id, account_code),
INDEX idx_status (status),
INDEX idx_valid_to (valid_to)
);
```
## 九、使用示例
### 9.1 创建实体账户
```rust
let req = CreatePhysicalAccountRequest {
account_no: "6222021234567890123".to_string(),
bank_code: "ICBC".to_string(),
bank_name: Some("中国工商银行".to_string()),
consistency_mode: Some(ConsistencyMode::Eventual),
outbound_control: Some(OutboundControl::OnlineBank),
};
let account = account_service.create_physical_account(req).await?;
```
### 9.2 创建子账户
```rust
let req = CreateVirtualSubAccountRequest {
physical_account_id: 1,
account_code: "SUB001".to_string(),
account_type: SubAccountType::Settlement,
valid_from: None,
valid_to: None,
};
let sub_account = account_service.create_sub_account(req).await?;
```
### 9.3 批量创建临时账户
```rust
let req = BatchCreateSubAccountRequest {
physical_account_id: 1,
account_type: SubAccountType::Temporary,
prefix: "TEMP".to_string(),
count: 100,
valid_from: Some(Utc::now()),
valid_to: Some(Utc::now() + Duration::days(30)),
};
let accounts = account_service.batch_create_sub_accounts(req).await?;
```