//! 账户域实体定义 use chrono::{DateTime, Utc}; use rust_decimal::Decimal; use serde::{Deserialize, Serialize}; /// 账户状态 #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum AccountStatus { /// 正常 Active, /// 冻结 Frozen, /// 已关闭 Closed, } impl Default for AccountStatus { fn default() -> Self { Self::Active } } impl std::fmt::Display for AccountStatus { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Active => write!(f, "active"), Self::Frozen => write!(f, "frozen"), Self::Closed => write!(f, "closed"), } } } impl std::str::FromStr for AccountStatus { type Err = String; fn from_str(s: &str) -> Result { match s.to_lowercase().as_str() { "active" => Ok(Self::Active), "frozen" => Ok(Self::Frozen), "closed" => Ok(Self::Closed), _ => Err(format!("未知账户状态: {}", s)), } } } /// 一致性模式 #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum ConsistencyMode { /// 强一致性 - 交易需等待银行确认 Strong, /// 最终一致性 - 先记账后对账 Eventual, } impl Default for ConsistencyMode { fn default() -> Self { Self::Eventual } } impl std::fmt::Display for ConsistencyMode { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Strong => write!(f, "strong"), Self::Eventual => write!(f, "eventual"), } } } /// 出金管控模式 #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum OutboundControl { /// 只收不付 ReceiveOnly, /// 网银控制 OnlineBank, /// 令牌控制 Token, } impl Default for OutboundControl { fn default() -> Self { Self::OnlineBank } } impl std::fmt::Display for OutboundControl { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::ReceiveOnly => write!(f, "receive_only"), Self::OnlineBank => write!(f, "online_bank"), Self::Token => write!(f, "token"), } } } /// 账户类型 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum AccountType { /// 实体账户 Physical, /// 虚拟账户 Virtual, } impl std::fmt::Display for AccountType { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Physical => write!(f, "physical"), Self::Virtual => write!(f, "virtual"), } } } /// 虚拟子账户类型 #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum SubAccountType { /// 结算子账户 Settlement, /// 管理子账户 Management, /// 临时子账户 Temporary, } impl Default for SubAccountType { fn default() -> Self { Self::Settlement } } impl std::fmt::Display for SubAccountType { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Settlement => write!(f, "settlement"), Self::Management => write!(f, "management"), Self::Temporary => write!(f, "temporary"), } } } /// 实体账户 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct PhysicalAccount { /// 账户ID pub id: i64, /// 银行账号 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, } impl PhysicalAccount { /// 检查账户是否可用 pub fn is_active(&self) -> bool { self.status == AccountStatus::Active } /// 检查是否允许出金 pub fn can_outbound(&self) -> bool { self.is_active() && self.outbound_control != OutboundControl::ReceiveOnly } } /// 虚拟子账户 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct VirtualSubAccount { /// 子账户ID pub id: i64, /// 所属实体账户ID pub physical_account_id: i64, /// 子账户编号 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, } impl VirtualSubAccount { /// 检查账户是否可用 pub fn is_active(&self) -> bool { if self.status != AccountStatus::Active { return false; } let now = Utc::now(); // 检查有效期 if let Some(valid_from) = self.valid_from { if now < valid_from { return false; } } if let Some(valid_to) = self.valid_to { if now > valid_to { return false; } } true } /// 检查是否为临时账户 pub fn is_temporary(&self) -> bool { self.account_type == SubAccountType::Temporary } /// 检查临时账户是否过期 pub fn is_expired(&self) -> bool { if !self.is_temporary() { return false; } if let Some(valid_to) = self.valid_to { return Utc::now() > valid_to; } false } } /// 账户控制配置 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct AccountControl { /// 控制ID pub id: i64, /// 实体账户ID pub physical_account_id: i64, /// 对账频率(分钟) pub reconciliation_interval: i32, /// 银企直连配置(JSON) pub direct_connect_config: Option, /// 第三方支付配置(JSON) pub third_party_config: Option, /// 创建时间 pub created_at: DateTime, /// 更新时间 pub updated_at: DateTime, } /// 临时账户池 #[derive(Debug, Clone, Serialize, Deserialize)] pub struct SubAccountPool { /// 池ID pub id: i64, /// 所属实体账户ID pub physical_account_id: i64, /// 池名称 pub name: String, /// 有效期开始 pub valid_from: DateTime, /// 有效期结束 pub valid_to: DateTime, /// 自动销户规则(JSON) pub auto_close_rule: Option, /// 创建时间 pub created_at: DateTime, } /// 创建实体账户请求 #[derive(Debug, Clone, Deserialize)] pub struct CreatePhysicalAccountRequest { pub account_no: String, pub bank_code: String, pub bank_name: Option, pub consistency_mode: Option, pub outbound_control: Option, } /// 创建虚拟子账户请求 #[derive(Debug, Clone, Deserialize)] pub struct CreateVirtualSubAccountRequest { pub physical_account_id: i64, pub account_code: String, pub account_type: SubAccountType, pub valid_from: Option>, pub valid_to: Option>, } /// 批量创建子账户请求 #[derive(Debug, Clone, Deserialize)] pub struct BatchCreateSubAccountRequest { pub physical_account_id: i64, pub account_type: SubAccountType, pub prefix: String, pub count: usize, pub valid_from: Option>, pub valid_to: Option>, }