1use std::sync::Arc;
9
10use crate::accounts::AccountCategory;
11use crate::models::balance::AccountCategory as TrialBalanceCategory;
12use crate::models::balance::AccountType;
13
14#[derive(Debug, Clone, Default)]
16pub struct AuditExportConfig {
17 pub fec_enabled: bool,
19 pub gobd_enabled: bool,
22}
23
24#[derive(Clone)]
29pub struct FrameworkAccounts {
30 pub ar_control: String,
32 pub ap_control: String,
33 pub inventory: String,
34 pub fixed_assets: String,
35 pub accumulated_depreciation: String,
36 pub gr_ir_clearing: String,
37 pub ic_ar_clearing: String,
38 pub ic_ap_clearing: String,
39
40 pub operating_cash: String,
42 pub bank_account: String,
43 pub petty_cash: String,
44
45 pub product_revenue: String,
47 pub service_revenue: String,
48 pub ic_revenue: String,
49 pub purchase_discount_income: String,
50 pub other_revenue: String,
51 pub sales_discounts: String,
52 pub sales_returns: String,
53
54 pub cogs: String,
56 pub raw_materials: String,
57 pub depreciation_expense: String,
58 pub salaries_wages: String,
59 pub rent: String,
60 pub interest_expense: String,
61 pub purchase_discounts: String,
62 pub fx_gain_loss: String,
63 pub bad_debt: String,
64
65 pub sales_tax_payable: String,
67 pub vat_payable: String,
68 pub input_vat: String,
69 pub tax_receivable: String,
70 pub tax_expense: String,
71 pub deferred_tax_liability: String,
72 pub deferred_tax_asset: String,
73
74 pub accrued_expenses: String,
76 pub accrued_salaries: String,
77 pub unearned_revenue: String,
78 pub short_term_debt: String,
79 pub long_term_debt: String,
80 pub ic_payable: String,
81
82 pub common_stock: String,
84 pub retained_earnings: String,
85 pub current_year_earnings: String,
86 pub cta: String,
87 pub income_summary: String,
88 pub dividends_paid: String,
89
90 pub general_suspense: String,
92 pub payroll_clearing: String,
93 pub bank_reconciliation_suspense: String,
94
95 pub provisions: String,
97
98 pub audit_export: AuditExportConfig,
100
101 classifier: Arc<dyn Fn(&str) -> AccountCategory + Send + Sync>,
103}
104
105impl std::fmt::Debug for FrameworkAccounts {
106 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
107 f.debug_struct("FrameworkAccounts")
108 .field("ar_control", &self.ar_control)
109 .field("ap_control", &self.ap_control)
110 .field("audit_export", &self.audit_export)
111 .finish_non_exhaustive()
112 }
113}
114
115impl FrameworkAccounts {
116 pub fn classify(&self, account: &str) -> AccountCategory {
118 (self.classifier)(account)
119 }
120
121 pub fn classify_account_type(&self, account_code: &str) -> AccountType {
126 account_type_from_category(self.classify(account_code))
127 }
128
129 pub fn classify_trial_balance_category(&self, account_code: &str) -> TrialBalanceCategory {
135 trial_balance_category_from_category(self.classify(account_code))
136 }
137
138 pub fn us_gaap() -> Self {
140 use crate::accounts::*;
141 Self {
142 ar_control: control_accounts::AR_CONTROL.into(),
143 ap_control: control_accounts::AP_CONTROL.into(),
144 inventory: control_accounts::INVENTORY.into(),
145 fixed_assets: control_accounts::FIXED_ASSETS.into(),
146 accumulated_depreciation: control_accounts::ACCUMULATED_DEPRECIATION.into(),
147 gr_ir_clearing: control_accounts::GR_IR_CLEARING.into(),
148 ic_ar_clearing: control_accounts::IC_AR_CLEARING.into(),
149 ic_ap_clearing: control_accounts::IC_AP_CLEARING.into(),
150
151 operating_cash: cash_accounts::OPERATING_CASH.into(),
152 bank_account: cash_accounts::BANK_ACCOUNT.into(),
153 petty_cash: cash_accounts::PETTY_CASH.into(),
154
155 product_revenue: revenue_accounts::PRODUCT_REVENUE.into(),
156 service_revenue: revenue_accounts::SERVICE_REVENUE.into(),
157 ic_revenue: revenue_accounts::IC_REVENUE.into(),
158 purchase_discount_income: revenue_accounts::PURCHASE_DISCOUNT_INCOME.into(),
159 other_revenue: revenue_accounts::OTHER_REVENUE.into(),
160 sales_discounts: revenue_accounts::SALES_DISCOUNTS.into(),
161 sales_returns: revenue_accounts::SALES_RETURNS.into(),
162
163 cogs: expense_accounts::COGS.into(),
164 raw_materials: expense_accounts::RAW_MATERIALS.into(),
165 depreciation_expense: expense_accounts::DEPRECIATION.into(),
166 salaries_wages: expense_accounts::SALARIES_WAGES.into(),
167 rent: expense_accounts::RENT.into(),
168 interest_expense: expense_accounts::INTEREST_EXPENSE.into(),
169 purchase_discounts: expense_accounts::PURCHASE_DISCOUNTS.into(),
170 fx_gain_loss: expense_accounts::FX_GAIN_LOSS.into(),
171 bad_debt: expense_accounts::BAD_DEBT.into(),
172
173 sales_tax_payable: tax_accounts::SALES_TAX_PAYABLE.into(),
174 vat_payable: tax_accounts::VAT_PAYABLE.into(),
175 input_vat: tax_accounts::INPUT_VAT.into(),
176 tax_receivable: tax_accounts::TAX_RECEIVABLE.into(),
177 tax_expense: tax_accounts::TAX_EXPENSE.into(),
178 deferred_tax_liability: tax_accounts::DEFERRED_TAX_LIABILITY.into(),
179 deferred_tax_asset: tax_accounts::DEFERRED_TAX_ASSET.into(),
180
181 accrued_expenses: liability_accounts::ACCRUED_EXPENSES.into(),
182 accrued_salaries: liability_accounts::ACCRUED_SALARIES.into(),
183 unearned_revenue: liability_accounts::UNEARNED_REVENUE.into(),
184 short_term_debt: liability_accounts::SHORT_TERM_DEBT.into(),
185 long_term_debt: liability_accounts::LONG_TERM_DEBT.into(),
186 ic_payable: liability_accounts::IC_PAYABLE.into(),
187
188 common_stock: equity_accounts::COMMON_STOCK.into(),
189 retained_earnings: equity_accounts::RETAINED_EARNINGS.into(),
190 current_year_earnings: equity_accounts::CURRENT_YEAR_EARNINGS.into(),
191 cta: equity_accounts::CTA.into(),
192 income_summary: equity_accounts::INCOME_SUMMARY.into(),
193 dividends_paid: equity_accounts::DIVIDENDS_PAID.into(),
194
195 general_suspense: suspense_accounts::GENERAL_SUSPENSE.into(),
196 payroll_clearing: suspense_accounts::PAYROLL_CLEARING.into(),
197 bank_reconciliation_suspense: suspense_accounts::BANK_RECONCILIATION_SUSPENSE.into(),
198
199 provisions: liability_accounts::ACCRUED_EXPENSES.into(), audit_export: AuditExportConfig::default(),
202 classifier: Arc::new(us_gaap_classify),
203 }
204 }
205
206 pub fn ifrs() -> Self {
208 Self::us_gaap()
209 }
210
211 pub fn french_gaap() -> Self {
213 use crate::pcg::*;
214 Self {
215 ar_control: control_accounts::AR_CONTROL.into(),
216 ap_control: control_accounts::AP_CONTROL.into(),
217 inventory: control_accounts::INVENTORY.into(),
218 fixed_assets: control_accounts::FIXED_ASSETS.into(),
219 accumulated_depreciation: control_accounts::ACCUMULATED_DEPRECIATION.into(),
220 gr_ir_clearing: control_accounts::GR_IR_CLEARING.into(),
221 ic_ar_clearing: control_accounts::IC_AR_CLEARING.into(),
222 ic_ap_clearing: control_accounts::IC_AP_CLEARING.into(),
223
224 operating_cash: cash_accounts::OPERATING_CASH.into(),
225 bank_account: cash_accounts::BANK_ACCOUNT.into(),
226 petty_cash: cash_accounts::PETTY_CASH.into(),
227
228 product_revenue: revenue_accounts::PRODUCT_REVENUE.into(),
229 service_revenue: revenue_accounts::SERVICE_REVENUE.into(),
230 ic_revenue: additional_revenue::IC_REVENUE.into(),
231 purchase_discount_income: additional_revenue::PURCHASE_DISCOUNT_INCOME.into(),
232 other_revenue: revenue_accounts::OTHER_REVENUE.into(),
233 sales_discounts: revenue_accounts::SALES_DISCOUNTS.into(),
234 sales_returns: additional_revenue::SALES_RETURNS.into(),
235
236 cogs: expense_accounts::COGS.into(),
237 raw_materials: additional_expense::RAW_MATERIALS.into(),
238 depreciation_expense: expense_accounts::DEPRECIATION.into(),
239 salaries_wages: expense_accounts::SALARIES_WAGES.into(),
240 rent: expense_accounts::RENT.into(),
241 interest_expense: expense_accounts::INTEREST_EXPENSE.into(),
242 purchase_discounts: additional_expense::PURCHASE_DISCOUNTS.into(),
243 fx_gain_loss: additional_expense::FX_GAIN_LOSS.into(),
244 bad_debt: additional_expense::BAD_DEBT.into(),
245
246 sales_tax_payable: tax_accounts::OUTPUT_VAT.into(),
247 vat_payable: tax_accounts::OUTPUT_VAT.into(),
248 input_vat: tax_accounts::INPUT_VAT.into(),
249 tax_receivable: tax_accounts::TAX_RECEIVABLE.into(),
250 tax_expense: tax_accounts::TAX_EXPENSE.into(),
251 deferred_tax_liability: tax_accounts::DEFERRED_TAX_LIABILITY.into(),
252 deferred_tax_asset: tax_accounts::DEFERRED_TAX_ASSET.into(),
253
254 accrued_expenses: liability_accounts::ACCRUED_EXPENSES.into(),
255 accrued_salaries: liability_accounts::ACCRUED_SALARIES.into(),
256 unearned_revenue: liability_accounts::UNEARNED_REVENUE.into(),
257 short_term_debt: equity_liability_accounts::SHORT_TERM_DEBT.into(),
258 long_term_debt: equity_liability_accounts::LONG_TERM_DEBT.into(),
259 ic_payable: liability_accounts::IC_PAYABLE.into(),
260
261 common_stock: equity_liability_accounts::COMMON_STOCK.into(),
262 retained_earnings: equity_liability_accounts::RETAINED_EARNINGS.into(),
263 current_year_earnings: equity_accounts::CURRENT_YEAR_EARNINGS.into(),
264 cta: equity_accounts::CTA.into(),
265 income_summary: equity_accounts::INCOME_SUMMARY.into(),
266 dividends_paid: equity_accounts::DIVIDENDS_PAID.into(),
267
268 general_suspense: suspense_accounts::GENERAL_SUSPENSE.into(),
269 payroll_clearing: suspense_accounts::PAYROLL_CLEARING.into(),
270 bank_reconciliation_suspense: suspense_accounts::GENERAL_SUSPENSE.into(), provisions: equity_liability_accounts::PROVISIONS.into(),
273
274 audit_export: AuditExportConfig {
275 fec_enabled: true,
276 gobd_enabled: false,
277 },
278 classifier: Arc::new(pcg_classify),
279 }
280 }
281
282 pub fn german_gaap() -> Self {
284 use crate::skr::*;
285 Self {
286 ar_control: control_accounts::AR_CONTROL.into(),
287 ap_control: control_accounts::AP_CONTROL.into(),
288 inventory: control_accounts::INVENTORY.into(),
289 fixed_assets: control_accounts::FIXED_ASSETS.into(),
290 accumulated_depreciation: control_accounts::ACCUMULATED_DEPRECIATION.into(),
291 gr_ir_clearing: control_accounts::GR_IR_CLEARING.into(),
292 ic_ar_clearing: control_accounts::IC_AR_CLEARING.into(),
293 ic_ap_clearing: control_accounts::IC_AP_CLEARING.into(),
294
295 operating_cash: cash_accounts::OPERATING_CASH.into(),
296 bank_account: cash_accounts::BANK_ACCOUNT.into(),
297 petty_cash: cash_accounts::PETTY_CASH.into(),
298
299 product_revenue: revenue_accounts::PRODUCT_REVENUE.into(),
300 service_revenue: revenue_accounts::SERVICE_REVENUE.into(),
301 ic_revenue: revenue_accounts::IC_REVENUE.into(),
302 purchase_discount_income: revenue_accounts::PURCHASE_DISCOUNT_INCOME.into(),
303 other_revenue: revenue_accounts::OTHER_REVENUE.into(),
304 sales_discounts: revenue_accounts::SALES_DISCOUNTS.into(),
305 sales_returns: revenue_accounts::SALES_RETURNS.into(),
306
307 cogs: expense_accounts::COGS.into(),
308 raw_materials: expense_accounts::RAW_MATERIALS.into(),
309 depreciation_expense: expense_accounts::DEPRECIATION.into(),
310 salaries_wages: expense_accounts::SALARIES_WAGES.into(),
311 rent: expense_accounts::RENT.into(),
312 interest_expense: expense_accounts::INTEREST_EXPENSE.into(),
313 purchase_discounts: expense_accounts::PURCHASE_DISCOUNTS.into(),
314 fx_gain_loss: expense_accounts::FX_GAIN_LOSS.into(),
315 bad_debt: expense_accounts::BAD_DEBT.into(),
316
317 sales_tax_payable: tax_accounts::OUTPUT_VAT.into(),
318 vat_payable: tax_accounts::OUTPUT_VAT.into(),
319 input_vat: tax_accounts::INPUT_VAT.into(),
320 tax_receivable: tax_accounts::TAX_RECEIVABLE.into(),
321 tax_expense: tax_accounts::TAX_EXPENSE.into(),
322 deferred_tax_liability: tax_accounts::DEFERRED_TAX_LIABILITY.into(),
323 deferred_tax_asset: tax_accounts::DEFERRED_TAX_ASSET.into(),
324
325 accrued_expenses: liability_accounts::ACCRUED_EXPENSES.into(),
326 accrued_salaries: liability_accounts::ACCRUED_SALARIES.into(),
327 unearned_revenue: liability_accounts::UNEARNED_REVENUE.into(),
328 short_term_debt: liability_accounts::SHORT_TERM_DEBT.into(),
329 long_term_debt: liability_accounts::LONG_TERM_DEBT.into(),
330 ic_payable: liability_accounts::IC_PAYABLE.into(),
331
332 common_stock: equity_accounts::COMMON_STOCK.into(),
333 retained_earnings: equity_accounts::RETAINED_EARNINGS.into(),
334 current_year_earnings: equity_accounts::CURRENT_YEAR_EARNINGS.into(),
335 cta: equity_accounts::CTA.into(),
336 income_summary: equity_accounts::INCOME_SUMMARY.into(),
337 dividends_paid: equity_accounts::DIVIDENDS_PAID.into(),
338
339 general_suspense: suspense_accounts::GENERAL_SUSPENSE.into(),
340 payroll_clearing: suspense_accounts::PAYROLL_CLEARING.into(),
341 bank_reconciliation_suspense: suspense_accounts::BANK_RECONCILIATION_SUSPENSE.into(),
342
343 provisions: equity_accounts::PROVISIONS.into(),
344
345 audit_export: AuditExportConfig {
346 fec_enabled: false,
347 gobd_enabled: true,
348 },
349 classifier: Arc::new(skr04_classify),
350 }
351 }
352
353 pub fn for_framework(framework: &str) -> Self {
358 match framework {
359 "us_gaap" | "UsGaap" => Self::us_gaap(),
360 "ifrs" | "Ifrs" => Self::ifrs(),
361 "dual_reporting" | "DualReporting" => Self::us_gaap(),
362 "french_gaap" | "FrenchGaap" => Self::french_gaap(),
363 "german_gaap" | "GermanGaap" | "hgb" => Self::german_gaap(),
364 other => {
365 eprintln!(
366 "FrameworkAccounts::for_framework: unknown framework {:?}, defaulting to US GAAP",
367 other
368 );
369 Self::us_gaap()
370 }
371 }
372 }
373}
374
375fn account_type_from_category(cat: AccountCategory) -> AccountType {
379 match cat {
380 AccountCategory::Asset => AccountType::Asset,
381 AccountCategory::Liability => AccountType::Liability,
382 AccountCategory::Equity => AccountType::Equity,
383 AccountCategory::Revenue => AccountType::Revenue,
384 AccountCategory::Cogs
385 | AccountCategory::OperatingExpense
386 | AccountCategory::OtherIncomeExpense
387 | AccountCategory::Tax => AccountType::Expense,
388 AccountCategory::Suspense | AccountCategory::Unknown => AccountType::Asset,
389 }
390}
391
392fn trial_balance_category_from_category(cat: AccountCategory) -> TrialBalanceCategory {
394 match cat {
395 AccountCategory::Asset => TrialBalanceCategory::CurrentAssets,
396 AccountCategory::Liability => TrialBalanceCategory::CurrentLiabilities,
397 AccountCategory::Equity => TrialBalanceCategory::Equity,
398 AccountCategory::Revenue => TrialBalanceCategory::Revenue,
399 AccountCategory::Cogs => TrialBalanceCategory::CostOfGoodsSold,
400 AccountCategory::OperatingExpense => TrialBalanceCategory::OperatingExpenses,
401 AccountCategory::OtherIncomeExpense => TrialBalanceCategory::OtherExpenses,
402 AccountCategory::Tax => TrialBalanceCategory::OtherExpenses,
403 AccountCategory::Suspense | AccountCategory::Unknown => TrialBalanceCategory::OtherExpenses,
404 }
405}
406
407fn us_gaap_classify(account: &str) -> AccountCategory {
413 AccountCategory::from_account(account)
414}
415
416fn pcg_classify(account: &str) -> AccountCategory {
421 match account.chars().next().and_then(|c| c.to_digit(10)) {
422 Some(1) => {
423 let sub = account.get(1..2).and_then(|s| s.parse::<u8>().ok());
425 match sub {
426 Some(0..=4) => AccountCategory::Equity, Some(5) => AccountCategory::Liability, Some(6..=7) => AccountCategory::Liability, _ => AccountCategory::Liability,
430 }
431 }
432 Some(2) => AccountCategory::Asset, Some(3) => AccountCategory::Asset, Some(4) => {
435 let sub = account.get(1..2).and_then(|s| s.parse::<u8>().ok());
437 match sub {
438 Some(0) => AccountCategory::Liability, Some(1) => AccountCategory::Asset, Some(2) => AccountCategory::Liability, Some(3..=4) => AccountCategory::Liability, Some(5) => AccountCategory::Liability, _ => AccountCategory::Liability,
444 }
445 }
446 Some(5) => AccountCategory::Asset, Some(6) => AccountCategory::OperatingExpense, Some(7) => AccountCategory::Revenue, Some(8) => AccountCategory::Suspense, Some(9) => AccountCategory::Suspense, _ => AccountCategory::Unknown,
452 }
453}
454
455fn skr04_classify(account: &str) -> AccountCategory {
460 match account.chars().next().and_then(|c| c.to_digit(10)) {
461 Some(0) => AccountCategory::Asset, Some(1) => AccountCategory::Asset, Some(2) => AccountCategory::Equity, Some(3) => AccountCategory::Liability, Some(4) => AccountCategory::Revenue, Some(5) => AccountCategory::Cogs, Some(6) => AccountCategory::OperatingExpense, Some(7) => AccountCategory::OtherIncomeExpense, Some(8) => AccountCategory::Tax, Some(9) => AccountCategory::Suspense, _ => AccountCategory::Unknown,
472 }
473}
474
475#[cfg(test)]
476#[allow(clippy::unwrap_used)]
477mod tests {
478 use super::*;
479
480 #[test]
481 fn test_framework_accounts_us_gaap_defaults() {
482 use crate::accounts::*;
483 let fa = FrameworkAccounts::us_gaap();
484 assert_eq!(fa.ar_control, control_accounts::AR_CONTROL);
485 assert_eq!(fa.ap_control, control_accounts::AP_CONTROL);
486 assert_eq!(fa.inventory, control_accounts::INVENTORY);
487 assert_eq!(fa.cogs, expense_accounts::COGS);
488 assert_eq!(fa.product_revenue, revenue_accounts::PRODUCT_REVENUE);
489 assert_eq!(fa.retained_earnings, equity_accounts::RETAINED_EARNINGS);
490 assert_eq!(fa.general_suspense, suspense_accounts::GENERAL_SUSPENSE);
491 assert!(!fa.audit_export.fec_enabled);
492 assert!(!fa.audit_export.gobd_enabled);
493 }
494
495 #[test]
496 fn test_framework_accounts_french_gaap() {
497 use crate::pcg;
498 let fa = FrameworkAccounts::french_gaap();
499 assert_eq!(fa.ar_control, pcg::control_accounts::AR_CONTROL);
500 assert_eq!(fa.ap_control, pcg::control_accounts::AP_CONTROL);
501 assert_eq!(fa.inventory, pcg::control_accounts::INVENTORY);
502 assert_eq!(fa.cogs, pcg::expense_accounts::COGS);
503 assert_eq!(fa.product_revenue, pcg::revenue_accounts::PRODUCT_REVENUE);
504 assert!(fa.audit_export.fec_enabled);
505 assert!(!fa.audit_export.gobd_enabled);
506 }
507
508 #[test]
509 fn test_framework_accounts_german_gaap() {
510 use crate::skr;
511 let fa = FrameworkAccounts::german_gaap();
512 assert_eq!(fa.ar_control, skr::control_accounts::AR_CONTROL);
513 assert_eq!(fa.ap_control, skr::control_accounts::AP_CONTROL);
514 assert_eq!(fa.cogs, skr::expense_accounts::COGS);
515 assert!(!fa.audit_export.fec_enabled);
516 assert!(fa.audit_export.gobd_enabled);
517 }
518
519 #[test]
520 fn test_classify_us_gaap() {
521 let fa = FrameworkAccounts::us_gaap();
522 assert_eq!(fa.classify("1100"), AccountCategory::Asset);
523 assert_eq!(fa.classify("2000"), AccountCategory::Liability);
524 assert_eq!(fa.classify("3200"), AccountCategory::Equity);
525 assert_eq!(fa.classify("4000"), AccountCategory::Revenue);
526 assert_eq!(fa.classify("5000"), AccountCategory::Cogs);
527 assert_eq!(fa.classify("6100"), AccountCategory::OperatingExpense);
528 assert_eq!(fa.classify("9000"), AccountCategory::Suspense);
529 }
530
531 #[test]
532 fn test_classify_pcg() {
533 let fa = FrameworkAccounts::french_gaap();
534 assert_eq!(fa.classify("101000"), AccountCategory::Equity);
535 assert_eq!(fa.classify("151000"), AccountCategory::Liability);
536 assert_eq!(fa.classify("210000"), AccountCategory::Asset);
537 assert_eq!(fa.classify("310000"), AccountCategory::Asset);
538 assert_eq!(fa.classify("401000"), AccountCategory::Liability);
539 assert_eq!(fa.classify("411000"), AccountCategory::Asset);
540 assert_eq!(fa.classify("512000"), AccountCategory::Asset);
541 assert_eq!(fa.classify("603000"), AccountCategory::OperatingExpense);
542 assert_eq!(fa.classify("701000"), AccountCategory::Revenue);
543 }
544
545 #[test]
546 fn test_classify_skr04() {
547 let fa = FrameworkAccounts::german_gaap();
548 assert_eq!(fa.classify("0200"), AccountCategory::Asset);
549 assert_eq!(fa.classify("1200"), AccountCategory::Asset);
550 assert_eq!(fa.classify("2000"), AccountCategory::Equity);
551 assert_eq!(fa.classify("3300"), AccountCategory::Liability);
552 assert_eq!(fa.classify("4000"), AccountCategory::Revenue);
553 assert_eq!(fa.classify("5000"), AccountCategory::Cogs);
554 assert_eq!(fa.classify("6000"), AccountCategory::OperatingExpense);
555 assert_eq!(fa.classify("7300"), AccountCategory::OtherIncomeExpense);
556 }
557
558 #[test]
559 fn test_for_framework_dispatch() {
560 let us = FrameworkAccounts::for_framework("us_gaap");
561 assert_eq!(us.ar_control, "1100");
562
563 let fr = FrameworkAccounts::for_framework("french_gaap");
564 assert_eq!(fr.ar_control, "411000");
565
566 let de = FrameworkAccounts::for_framework("german_gaap");
567 assert_eq!(de.ar_control, "1200");
568
569 let hgb = FrameworkAccounts::for_framework("hgb");
570 assert_eq!(hgb.ar_control, "1200");
571
572 let ifrs = FrameworkAccounts::for_framework("ifrs");
574 assert_eq!(ifrs.ar_control, "1100");
575
576 let dual = FrameworkAccounts::for_framework("dual_reporting");
577 assert_eq!(dual.ar_control, "1100");
578
579 let unknown = FrameworkAccounts::for_framework("martian_gaap");
581 assert_eq!(unknown.ar_control, "1100");
582 }
583
584 #[test]
585 fn test_ifrs_constructor() {
586 let ifrs = FrameworkAccounts::ifrs();
587 let us = FrameworkAccounts::us_gaap();
588 assert_eq!(ifrs.ar_control, us.ar_control);
589 assert_eq!(ifrs.ap_control, us.ap_control);
590 assert_eq!(ifrs.cogs, us.cogs);
591 assert_eq!(ifrs.product_revenue, us.product_revenue);
592 assert_eq!(ifrs.classify("1100"), us.classify("1100"));
593 assert_eq!(ifrs.classify("4000"), us.classify("4000"));
594 }
595
596 #[test]
597 fn test_classify_account_type_us_gaap() {
598 let fa = FrameworkAccounts::us_gaap();
599 assert_eq!(fa.classify_account_type("1100"), AccountType::Asset);
600 assert_eq!(fa.classify_account_type("2000"), AccountType::Liability);
601 assert_eq!(fa.classify_account_type("3200"), AccountType::Equity);
602 assert_eq!(fa.classify_account_type("4000"), AccountType::Revenue);
603 assert_eq!(fa.classify_account_type("5000"), AccountType::Expense);
604 assert_eq!(fa.classify_account_type("6100"), AccountType::Expense);
605 }
606
607 #[test]
608 fn test_classify_account_type_french_gaap() {
609 let fa = FrameworkAccounts::french_gaap();
610 assert_eq!(fa.classify_account_type("101000"), AccountType::Equity);
611 assert_eq!(fa.classify_account_type("210000"), AccountType::Asset);
612 assert_eq!(fa.classify_account_type("401000"), AccountType::Liability);
613 assert_eq!(fa.classify_account_type("603000"), AccountType::Expense);
614 assert_eq!(fa.classify_account_type("701000"), AccountType::Revenue);
615 }
616
617 #[test]
618 fn test_classify_account_type_german_gaap() {
619 let fa = FrameworkAccounts::german_gaap();
620 assert_eq!(fa.classify_account_type("0200"), AccountType::Asset);
621 assert_eq!(fa.classify_account_type("2000"), AccountType::Equity);
622 assert_eq!(fa.classify_account_type("3300"), AccountType::Liability);
623 assert_eq!(fa.classify_account_type("4000"), AccountType::Revenue);
624 assert_eq!(fa.classify_account_type("5000"), AccountType::Expense);
625 assert_eq!(fa.classify_account_type("6000"), AccountType::Expense);
626 }
627
628 #[test]
629 fn test_classify_trial_balance_category_us_gaap() {
630 let fa = FrameworkAccounts::us_gaap();
631 assert_eq!(
632 fa.classify_trial_balance_category("1100"),
633 TrialBalanceCategory::CurrentAssets
634 );
635 assert_eq!(
636 fa.classify_trial_balance_category("2000"),
637 TrialBalanceCategory::CurrentLiabilities
638 );
639 assert_eq!(
640 fa.classify_trial_balance_category("3200"),
641 TrialBalanceCategory::Equity
642 );
643 assert_eq!(
644 fa.classify_trial_balance_category("4000"),
645 TrialBalanceCategory::Revenue
646 );
647 assert_eq!(
648 fa.classify_trial_balance_category("5000"),
649 TrialBalanceCategory::CostOfGoodsSold
650 );
651 assert_eq!(
652 fa.classify_trial_balance_category("6100"),
653 TrialBalanceCategory::OperatingExpenses
654 );
655 }
656
657 #[test]
658 fn test_classify_trial_balance_category_french_gaap() {
659 let fa = FrameworkAccounts::french_gaap();
660 assert_eq!(
661 fa.classify_trial_balance_category("101000"),
662 TrialBalanceCategory::Equity
663 );
664 assert_eq!(
665 fa.classify_trial_balance_category("210000"),
666 TrialBalanceCategory::CurrentAssets
667 );
668 assert_eq!(
669 fa.classify_trial_balance_category("603000"),
670 TrialBalanceCategory::OperatingExpenses
671 );
672 assert_eq!(
673 fa.classify_trial_balance_category("701000"),
674 TrialBalanceCategory::Revenue
675 );
676 }
677}