- 系统架构文档 (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)
11 KiB
11 KiB
账户域 (Account Domain)
一、领域概述
账户域负责管理银行账户的完整生命周期,包括实体账户(对应真实银行账户)和虚拟子账户(在实体账户下创建的逻辑账户)。
二、核心实体
2.1 实体账户 (PhysicalAccount)
实体账户对应真实的银行账户,是资金管理的基础单元。
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)
虚拟子账户是在实体账户下创建的逻辑账户,用于资金隔离和管理。
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)
账户控制配置,用于设置对账频率和银行对接配置。
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)
管理临时子账户的池,支持批量创建和自动销户。
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)
pub enum AccountStatus {
Active, // 正常
Frozen, // 冻结
Closed, // 已关闭
}
状态转移规则:
Active ──► Frozen ──► Active
│ │
└──────► Closed ◄────┘
3.2 一致性模式 (ConsistencyMode)
pub enum ConsistencyMode {
Strong, // 强一致性 - 交易需等待银行确认
Eventual, // 最终一致性 - 先记账后对账
}
| 模式 | 特点 | 适用场景 |
|---|---|---|
| Strong | 实时确认,响应慢 | 大额转账 |
| Eventual | 异步确认,响应快 | 小额高频 |
3.3 出金管控模式 (OutboundControl)
pub enum OutboundControl {
ReceiveOnly, // 只收不付
OnlineBank, // 网银控制
Token, // 令牌控制
}
| 模式 | 说明 | 使用场景 |
|---|---|---|
| ReceiveOnly | 禁止出金 | 归集账户 |
| OnlineBank | 网银审批出金 | 常规账户 |
| Token | 令牌验证出金 | 高安全账户 |
3.4 账户类型 (AccountType)
pub enum AccountType {
Physical, // 实体账户
Virtual, // 虚拟账户
}
3.5 子账户类型 (SubAccountType)
pub enum SubAccountType {
Settlement, // 结算子账户
Management, // 管理子账户
Temporary, // 临时子账户
}
| 类型 | 说明 | 特点 |
|---|---|---|
| Settlement | 结算账户 | 长期使用,用于日常结算 |
| Management | 管理账户 | 内部管理,资金归集 |
| Temporary | 临时账户 | 有有效期,自动销户 |
四、领域服务
4.1 AccountService
账户域的核心服务,提供账户管理功能。
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
#[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
#[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 账户创建规则
- 银行账号必须唯一
- 实体账户必须关联有效的银行代码
- 子账户编号在同一实体账户下必须唯一
- 临时账户必须设置有效期
6.2 账户状态规则
- 只有
Active状态的账户可以进行交易 Frozen状态只影响出金,入金正常Closed状态不可进行任何交易- 账户关闭前必须余额为零
6.3 出金管控规则
ReceiveOnly模式禁止任何出金操作OnlineBank模式需要通过网银审批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 表
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 表
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 创建实体账户
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 创建子账户
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 批量创建临时账户
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?;