1use async_trait::async_trait;
4use bigdecimal::BigDecimal;
5use chrono::NaiveDate;
6use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8
9use crate::types::*;
10
11#[async_trait]
16pub trait LedgerStorage: Send + Sync {
17 async fn save_account(&mut self, account: &Account) -> LedgerResult<()>;
19
20 async fn get_account(&self, account_id: &str) -> LedgerResult<Option<Account>>;
22
23 async fn list_accounts(
25 &self,
26 account_type: Option<AccountType>,
27 pagination: PaginationOption,
28 ) -> LedgerResult<ListResponse<Account>>;
29
30 async fn update_account(&mut self, account: &Account) -> LedgerResult<()>;
32
33 async fn delete_account(&mut self, account_id: &str) -> LedgerResult<()>;
35
36 async fn save_transaction(&mut self, transaction: &Transaction) -> LedgerResult<()>;
38
39 async fn get_transaction(&self, transaction_id: &str) -> LedgerResult<Option<Transaction>>;
41
42 async fn get_account_transactions(
44 &self,
45 account_id: &str,
46 start_date: Option<NaiveDate>,
47 end_date: Option<NaiveDate>,
48 pagination: PaginationOption,
49 ) -> LedgerResult<ListResponse<Transaction>>;
50
51 async fn get_transactions(
53 &self,
54 start_date: Option<NaiveDate>,
55 end_date: Option<NaiveDate>,
56 pagination: PaginationOption,
57 ) -> LedgerResult<ListResponse<Transaction>>;
58
59 async fn update_transaction(&mut self, transaction: &Transaction) -> LedgerResult<()>;
61
62 async fn delete_transaction(&mut self, transaction_id: &str) -> LedgerResult<()>;
64
65 async fn get_account_balance(
67 &self,
68 account_id: &str,
69 as_of_date: Option<NaiveDate>,
70 ) -> LedgerResult<BigDecimal>;
71
72 async fn get_trial_balance(&self, as_of_date: NaiveDate) -> LedgerResult<TrialBalance>;
74
75 async fn get_account_balances_by_type(
77 &self,
78 as_of_date: NaiveDate,
79 ) -> LedgerResult<HashMap<AccountType, Vec<AccountBalance>>>;
80}
81
82pub trait AccountValidator: Send + Sync {
84 fn validate_account(&self, account: &Account) -> LedgerResult<()>;
86
87 fn validate_account_deletion(&self, account_id: &str) -> LedgerResult<()>;
89}
90
91pub trait TransactionValidator: Send + Sync {
93 fn validate_transaction(&self, transaction: &Transaction) -> LedgerResult<()>;
95
96 fn validate_account_references(&self, transaction: &Transaction) -> LedgerResult<()>;
98}
99
100pub struct DefaultAccountValidator;
102
103impl AccountValidator for DefaultAccountValidator {
104 fn validate_account(&self, account: &Account) -> LedgerResult<()> {
105 if account.id.trim().is_empty() {
106 return Err(LedgerError::Validation(
107 "Account ID cannot be empty".to_string(),
108 ));
109 }
110
111 if account.name.trim().is_empty() {
112 return Err(LedgerError::Validation(
113 "Account name cannot be empty".to_string(),
114 ));
115 }
116
117 Ok(())
118 }
119
120 fn validate_account_deletion(&self, _account_id: &str) -> LedgerResult<()> {
121 Ok(())
123 }
124}
125
126pub struct DefaultTransactionValidator;
128
129impl TransactionValidator for DefaultTransactionValidator {
130 fn validate_transaction(&self, transaction: &Transaction) -> LedgerResult<()> {
131 transaction.validate()
132 }
133
134 fn validate_account_references(&self, _transaction: &Transaction) -> LedgerResult<()> {
135 Ok(())
137 }
138}
139
140#[async_trait]
142pub trait ChartOfAccounts: Send + Sync {
143 async fn get_chart(&self) -> LedgerResult<Vec<Account>>;
145
146 async fn add_account(&mut self, account: Account) -> LedgerResult<()>;
148
149 async fn get_child_accounts(&self, parent_id: &str) -> LedgerResult<Vec<Account>>;
151
152 async fn get_account_path(&self, account_id: &str) -> LedgerResult<Vec<Account>>;
154}
155
156#[async_trait]
158pub trait ReportGenerator: Send + Sync {
159 async fn generate_balance_sheet(&self, as_of_date: NaiveDate) -> LedgerResult<BalanceSheet>;
161
162 async fn generate_income_statement(
164 &self,
165 start_date: NaiveDate,
166 end_date: NaiveDate,
167 ) -> LedgerResult<IncomeStatement>;
168
169 async fn generate_cash_flow(
171 &self,
172 start_date: NaiveDate,
173 end_date: NaiveDate,
174 ) -> LedgerResult<CashFlowStatement>;
175}
176
177#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
179pub struct BalanceSheet {
180 pub as_of_date: NaiveDate,
181 pub assets: Vec<AccountBalance>,
182 pub liabilities: Vec<AccountBalance>,
183 pub equity: Vec<AccountBalance>,
184 pub total_assets: BigDecimal,
185 pub total_liabilities: BigDecimal,
186 pub total_equity: BigDecimal,
187 pub is_balanced: bool,
188}
189
190#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
192pub struct IncomeStatement {
193 pub start_date: NaiveDate,
194 pub end_date: NaiveDate,
195 pub revenue: Vec<AccountBalance>,
196 pub expenses: Vec<AccountBalance>,
197 pub total_revenue: BigDecimal,
198 pub total_expenses: BigDecimal,
199 pub net_income: BigDecimal,
200}
201
202#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
204pub struct CashFlowStatement {
205 pub start_date: NaiveDate,
206 pub end_date: NaiveDate,
207 pub operating_activities: Vec<CashFlowItem>,
208 pub investing_activities: Vec<CashFlowItem>,
209 pub financing_activities: Vec<CashFlowItem>,
210 pub net_operating_cash_flow: BigDecimal,
211 pub net_investing_cash_flow: BigDecimal,
212 pub net_financing_cash_flow: BigDecimal,
213 pub net_cash_flow: BigDecimal,
214}
215
216#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
218pub struct CashFlowItem {
219 pub description: String,
220 pub amount: BigDecimal,
221}