# 账户域 (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, // 银行名称 pub consistency_mode: ConsistencyMode, // 一致性模式 pub outbound_control: OutboundControl, // 出金管控模式 pub status: AccountStatus, // 账户状态 pub created_at: DateTime, // 创建时间 pub updated_at: DateTime, // 更新时间 } ``` **核心方法**: - `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>, // 有效期开始 pub valid_to: Option>, // 有效期结束 pub status: AccountStatus, // 账户状态 pub created_at: DateTime, // 创建时间 pub updated_at: DateTime, // 更新时间 } ``` **核心方法**: - `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, // 银企直连配置 pub third_party_config: Option, // 第三方支付配置 } ``` ### 2.4 临时账户池 (SubAccountPool) 管理临时子账户的池,支持批量创建和自动销户。 ```rust pub struct SubAccountPool { pub id: i64, pub physical_account_id: i64, pub name: String, pub valid_from: DateTime, pub valid_to: DateTime, pub auto_close_rule: Option, // 自动销户规则 } ``` ## 三、枚举类型 ### 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; // 获取实体账户 pub async fn get_physical_account(&self, id: i64) -> Result; // 获取实体账户列表(分页) pub async fn list_physical_accounts_paginated( &self, status: Option, keyword: Option, page: i32, page_size: i32 ) -> Result<(Vec, 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; // 批量创建子账户 pub async fn batch_create_sub_accounts(&self, req: BatchCreateSubAccountRequest) -> Result>; // 关闭子账户 pub async fn close_sub_account(&self, id: i64) -> Result<()>; // 获取实体账户下的子账户列表 pub async fn list_sub_accounts(&self, physical_account_id: i64) -> Result>; } ``` ## 五、仓储接口 ### 5.1 PhysicalAccountRepository ```rust #[async_trait] pub trait PhysicalAccountRepository: Send + Sync { async fn create(&self, account: &PhysicalAccount) -> Result; async fn find_by_id(&self, id: i64) -> Result>; async fn find_by_account_no(&self, account_no: &str) -> Result>; async fn find_all(&self) -> Result>; async fn find_paginated(&self, status: Option, keyword: Option, offset: i64, limit: i64) -> Result>; async fn count(&self, status: Option, keyword: Option) -> Result; 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; async fn find_by_id(&self, id: i64) -> Result>; async fn find_by_physical_account(&self, physical_account_id: i64) -> Result>; async fn find_expired_temporary(&self) -> Result>; async fn update_status(&self, id: i64, status: AccountStatus) -> Result<()>; async fn batch_create(&self, accounts: &[VirtualSubAccount]) -> Result>; } ``` ## 六、业务规则 ### 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?; ```