Skip to main content

ringkernel_accnet/fabric/
chart_of_accounts.rs

1//! Chart of Accounts templates for different industries.
2//!
3//! Each template provides a realistic account structure with
4//! typical account relationships and expected flow patterns.
5
6use super::{CompanyArchetype, Industry};
7use crate::models::{AccountMetadata, AccountNode, AccountSemantics, AccountType};
8use uuid::Uuid;
9
10/// A Chart of Accounts template.
11#[derive(Debug, Clone)]
12pub struct ChartOfAccountsTemplate {
13    /// Industry this template is designed for
14    pub industry: Industry,
15    /// Template name
16    pub name: String,
17    /// Account definitions
18    pub accounts: Vec<AccountDefinition>,
19    /// Expected flow patterns between accounts
20    pub expected_flows: Vec<ExpectedFlow>,
21}
22
23/// Definition of an account in the template.
24#[derive(Debug, Clone)]
25pub struct AccountDefinition {
26    /// Account code (e.g., "1100")
27    pub code: String,
28    /// Account name
29    pub name: String,
30    /// Account type
31    pub account_type: AccountType,
32    /// Account class (for grouping)
33    pub class_id: u8,
34    /// Account subclass
35    pub subclass_id: u8,
36    /// Parent account code (for hierarchy)
37    pub parent_code: Option<String>,
38    /// Semantic flags
39    pub semantics: u32,
40    /// Typical activity level (transactions per month)
41    pub typical_activity: f32,
42    /// Description
43    pub description: String,
44}
45
46impl AccountDefinition {
47    /// Create a new account definition.
48    pub fn new(
49        code: impl Into<String>,
50        name: impl Into<String>,
51        account_type: AccountType,
52    ) -> Self {
53        Self {
54            code: code.into(),
55            name: name.into(),
56            account_type,
57            class_id: 0,
58            subclass_id: 0,
59            parent_code: None,
60            semantics: 0,
61            typical_activity: 10.0,
62            description: String::new(),
63        }
64    }
65
66    /// Set the class and subclass.
67    pub fn with_class(mut self, class_id: u8, subclass_id: u8) -> Self {
68        self.class_id = class_id;
69        self.subclass_id = subclass_id;
70        self
71    }
72
73    /// Set the parent account.
74    pub fn with_parent(mut self, parent: impl Into<String>) -> Self {
75        self.parent_code = Some(parent.into());
76        self
77    }
78
79    /// Set semantic flags.
80    pub fn with_semantics(mut self, semantics: u32) -> Self {
81        self.semantics = semantics;
82        self
83    }
84
85    /// Set typical activity level.
86    pub fn with_activity(mut self, activity: f32) -> Self {
87        self.typical_activity = activity;
88        self
89    }
90
91    /// Set description.
92    pub fn with_description(mut self, desc: impl Into<String>) -> Self {
93        self.description = desc.into();
94        self
95    }
96
97    /// Convert to AccountNode and AccountMetadata.
98    pub fn to_account(&self, index: u16) -> (AccountNode, AccountMetadata) {
99        let mut node = AccountNode::new(Uuid::new_v4(), self.account_type, index);
100        node.class_id = self.class_id;
101        node.subclass_id = self.subclass_id;
102
103        let mut metadata = AccountMetadata::new(&self.code, &self.name);
104        metadata.description = self.description.clone();
105        metadata.semantics = AccountSemantics {
106            flags: self.semantics,
107            typical_frequency: self.typical_activity,
108            avg_amount_scale: 50.0, // Default mid-range
109        };
110
111        (node, metadata)
112    }
113}
114
115/// An expected flow pattern between accounts.
116#[derive(Debug, Clone)]
117pub struct ExpectedFlow {
118    /// Source account code
119    pub from_code: String,
120    /// Target account code
121    pub to_code: String,
122    /// Relative frequency (0.0 - 1.0)
123    pub frequency: f64,
124    /// Typical amount range
125    pub amount_range: (f64, f64),
126    /// Description of this flow
127    pub description: String,
128}
129
130impl ExpectedFlow {
131    /// Create a new expected flow.
132    pub fn new(
133        from: impl Into<String>,
134        to: impl Into<String>,
135        frequency: f64,
136        amount_range: (f64, f64),
137    ) -> Self {
138        Self {
139            from_code: from.into(),
140            to_code: to.into(),
141            frequency,
142            amount_range,
143            description: String::new(),
144        }
145    }
146
147    /// Add description.
148    pub fn with_description(mut self, desc: impl Into<String>) -> Self {
149        self.description = desc.into();
150        self
151    }
152}
153
154impl ChartOfAccountsTemplate {
155    /// Create a minimal GAAP-compliant template (for education).
156    pub fn gaap_minimal() -> Self {
157        Self {
158            industry: Industry::Retail,
159            name: "GAAP Minimal".to_string(),
160            accounts: vec![
161                // Assets (1xxx)
162                AccountDefinition::new("1000", "Assets", AccountType::Asset)
163                    .with_class(1, 0)
164                    .with_description("Total assets"),
165                AccountDefinition::new("1100", "Cash", AccountType::Asset)
166                    .with_class(1, 1)
167                    .with_parent("1000")
168                    .with_semantics(AccountSemantics::IS_CASH)
169                    .with_activity(100.0)
170                    .with_description("Cash and cash equivalents"),
171                AccountDefinition::new("1200", "Accounts Receivable", AccountType::Asset)
172                    .with_class(1, 2)
173                    .with_parent("1000")
174                    .with_semantics(AccountSemantics::IS_RECEIVABLE)
175                    .with_activity(50.0)
176                    .with_description("Amounts owed by customers"),
177                AccountDefinition::new("1300", "Inventory", AccountType::Asset)
178                    .with_class(1, 3)
179                    .with_parent("1000")
180                    .with_semantics(AccountSemantics::IS_INVENTORY)
181                    .with_activity(30.0)
182                    .with_description("Goods held for sale"),
183                AccountDefinition::new("1400", "Prepaid Expenses", AccountType::Asset)
184                    .with_class(1, 4)
185                    .with_parent("1000")
186                    .with_activity(5.0)
187                    .with_description("Expenses paid in advance"),
188                AccountDefinition::new("1500", "Fixed Assets", AccountType::Asset)
189                    .with_class(1, 5)
190                    .with_parent("1000")
191                    .with_activity(2.0)
192                    .with_description("Property, plant, and equipment"),
193                AccountDefinition::new("1510", "Accumulated Depreciation", AccountType::Contra)
194                    .with_class(1, 5)
195                    .with_parent("1500")
196                    .with_semantics(AccountSemantics::IS_DEPRECIATION)
197                    .with_activity(12.0)
198                    .with_description("Accumulated depreciation on fixed assets"),
199                // Liabilities (2xxx)
200                AccountDefinition::new("2000", "Liabilities", AccountType::Liability)
201                    .with_class(2, 0)
202                    .with_description("Total liabilities"),
203                AccountDefinition::new("2100", "Accounts Payable", AccountType::Liability)
204                    .with_class(2, 1)
205                    .with_parent("2000")
206                    .with_semantics(AccountSemantics::IS_PAYABLE)
207                    .with_activity(40.0)
208                    .with_description("Amounts owed to suppliers"),
209                AccountDefinition::new("2200", "Accrued Expenses", AccountType::Liability)
210                    .with_class(2, 2)
211                    .with_parent("2000")
212                    .with_activity(12.0)
213                    .with_description("Expenses incurred but not yet paid"),
214                AccountDefinition::new("2300", "Unearned Revenue", AccountType::Liability)
215                    .with_class(2, 3)
216                    .with_parent("2000")
217                    .with_activity(10.0)
218                    .with_description("Revenue received but not yet earned"),
219                AccountDefinition::new("2400", "Notes Payable", AccountType::Liability)
220                    .with_class(2, 4)
221                    .with_parent("2000")
222                    .with_activity(2.0)
223                    .with_description("Short-term loans"),
224                // Equity (3xxx)
225                AccountDefinition::new("3000", "Equity", AccountType::Equity)
226                    .with_class(3, 0)
227                    .with_description("Owner's equity"),
228                AccountDefinition::new("3100", "Common Stock", AccountType::Equity)
229                    .with_class(3, 1)
230                    .with_parent("3000")
231                    .with_activity(1.0)
232                    .with_description("Issued common shares"),
233                AccountDefinition::new("3200", "Retained Earnings", AccountType::Equity)
234                    .with_class(3, 2)
235                    .with_parent("3000")
236                    .with_activity(1.0)
237                    .with_description("Accumulated profits"),
238                // Revenue (4xxx)
239                AccountDefinition::new("4000", "Revenue", AccountType::Revenue)
240                    .with_class(4, 0)
241                    .with_semantics(AccountSemantics::IS_REVENUE)
242                    .with_description("Total revenue"),
243                AccountDefinition::new("4100", "Sales Revenue", AccountType::Revenue)
244                    .with_class(4, 1)
245                    .with_parent("4000")
246                    .with_semantics(AccountSemantics::IS_REVENUE)
247                    .with_activity(100.0)
248                    .with_description("Revenue from product sales"),
249                AccountDefinition::new("4200", "Service Revenue", AccountType::Revenue)
250                    .with_class(4, 2)
251                    .with_parent("4000")
252                    .with_semantics(AccountSemantics::IS_REVENUE)
253                    .with_activity(20.0)
254                    .with_description("Revenue from services"),
255                // Expenses (5xxx-6xxx)
256                AccountDefinition::new("5000", "Cost of Goods Sold", AccountType::Expense)
257                    .with_class(5, 0)
258                    .with_semantics(AccountSemantics::IS_COGS)
259                    .with_activity(80.0)
260                    .with_description("Direct cost of products sold"),
261                AccountDefinition::new("6000", "Operating Expenses", AccountType::Expense)
262                    .with_class(6, 0)
263                    .with_semantics(AccountSemantics::IS_EXPENSE)
264                    .with_description("General operating expenses"),
265                AccountDefinition::new("6100", "Salaries Expense", AccountType::Expense)
266                    .with_class(6, 1)
267                    .with_parent("6000")
268                    .with_semantics(AccountSemantics::IS_PAYROLL)
269                    .with_activity(24.0)
270                    .with_description("Employee salaries"),
271                AccountDefinition::new("6200", "Rent Expense", AccountType::Expense)
272                    .with_class(6, 2)
273                    .with_parent("6000")
274                    .with_activity(12.0)
275                    .with_description("Rent for facilities"),
276                AccountDefinition::new("6300", "Utilities Expense", AccountType::Expense)
277                    .with_class(6, 3)
278                    .with_parent("6000")
279                    .with_activity(12.0)
280                    .with_description("Electricity, water, gas"),
281                AccountDefinition::new("6400", "Depreciation Expense", AccountType::Expense)
282                    .with_class(6, 4)
283                    .with_parent("6000")
284                    .with_activity(12.0)
285                    .with_description("Depreciation of fixed assets"),
286                AccountDefinition::new("6500", "Marketing Expense", AccountType::Expense)
287                    .with_class(6, 5)
288                    .with_parent("6000")
289                    .with_activity(20.0)
290                    .with_description("Advertising and marketing"),
291                AccountDefinition::new("6900", "Other Expenses", AccountType::Expense)
292                    .with_class(6, 9)
293                    .with_parent("6000")
294                    .with_activity(15.0)
295                    .with_description("Miscellaneous expenses"),
296                // Suspense/Clearing (9xxx)
297                AccountDefinition::new("9100", "Clearing Account", AccountType::Asset)
298                    .with_class(9, 1)
299                    .with_semantics(AccountSemantics::IS_SUSPENSE)
300                    .with_activity(30.0)
301                    .with_description("Temporary clearing account"),
302            ],
303            expected_flows: vec![
304                // Sales cycle
305                ExpectedFlow::new("4100", "1200", 0.30, (50.0, 5000.0))
306                    .with_description("Credit sale: Revenue → A/R"),
307                ExpectedFlow::new("1200", "1100", 0.25, (50.0, 5000.0))
308                    .with_description("Collection: A/R → Cash"),
309                ExpectedFlow::new("4100", "1100", 0.10, (20.0, 500.0))
310                    .with_description("Cash sale: Revenue → Cash"),
311                // Purchasing cycle
312                ExpectedFlow::new("1300", "2100", 0.15, (100.0, 10000.0))
313                    .with_description("Purchase: Inventory → A/P"),
314                ExpectedFlow::new("2100", "1100", 0.15, (100.0, 10000.0))
315                    .with_description("Payment: A/P → Cash"),
316                ExpectedFlow::new("5000", "1300", 0.15, (50.0, 5000.0))
317                    .with_description("Cost of sale: COGS → Inventory"),
318                // Operating expenses
319                ExpectedFlow::new("6100", "1100", 0.08, (5000.0, 50000.0))
320                    .with_description("Payroll: Salaries → Cash"),
321                ExpectedFlow::new("6200", "1100", 0.04, (1000.0, 10000.0))
322                    .with_description("Rent payment"),
323                ExpectedFlow::new("6300", "1100", 0.04, (200.0, 2000.0))
324                    .with_description("Utilities payment"),
325                ExpectedFlow::new("6400", "1510", 0.04, (500.0, 5000.0))
326                    .with_description("Depreciation: Expense → Accum Depr"),
327            ],
328        }
329    }
330
331    /// Create a retail-specific template with ~150 accounts.
332    pub fn retail_standard() -> Self {
333        let mut template = Self::gaap_minimal();
334        template.industry = Industry::Retail;
335        template.name = "Retail Standard".to_string();
336
337        // Add retail-specific accounts
338        template.accounts.extend(vec![
339            // More detailed inventory
340            AccountDefinition::new("1310", "Merchandise Inventory", AccountType::Asset)
341                .with_class(1, 3)
342                .with_parent("1300")
343                .with_semantics(AccountSemantics::IS_INVENTORY)
344                .with_activity(50.0),
345            AccountDefinition::new("1320", "Inventory in Transit", AccountType::Asset)
346                .with_class(1, 3)
347                .with_parent("1300")
348                .with_activity(10.0),
349            // Point of Sale
350            AccountDefinition::new("1110", "Cash Registers", AccountType::Asset)
351                .with_class(1, 1)
352                .with_parent("1100")
353                .with_semantics(AccountSemantics::IS_CASH)
354                .with_activity(200.0),
355            AccountDefinition::new("1120", "Undeposited Funds", AccountType::Asset)
356                .with_class(1, 1)
357                .with_parent("1100")
358                .with_semantics(AccountSemantics::IS_SUSPENSE | AccountSemantics::IS_CASH)
359                .with_activity(100.0),
360            // Credit card processing
361            AccountDefinition::new("1130", "Credit Card Receivable", AccountType::Asset)
362                .with_class(1, 1)
363                .with_parent("1100")
364                .with_activity(80.0),
365            // Sales returns
366            AccountDefinition::new("4110", "Sales Returns", AccountType::Contra)
367                .with_class(4, 1)
368                .with_parent("4100")
369                .with_activity(20.0),
370            AccountDefinition::new("4120", "Sales Discounts", AccountType::Contra)
371                .with_class(4, 1)
372                .with_parent("4100")
373                .with_activity(15.0),
374            // Retail expenses
375            AccountDefinition::new("6510", "Store Supplies", AccountType::Expense)
376                .with_class(6, 5)
377                .with_parent("6500")
378                .with_activity(10.0),
379            AccountDefinition::new("6520", "Credit Card Fees", AccountType::Expense)
380                .with_class(6, 5)
381                .with_parent("6500")
382                .with_activity(30.0),
383            AccountDefinition::new("6530", "Shrinkage", AccountType::Expense)
384                .with_class(6, 5)
385                .with_parent("6500")
386                .with_activity(12.0),
387        ]);
388
389        // Add retail-specific flows
390        template.expected_flows.extend(vec![
391            ExpectedFlow::new("1110", "1120", 0.20, (100.0, 5000.0))
392                .with_description("Register → Undeposited"),
393            ExpectedFlow::new("1120", "1100", 0.15, (1000.0, 20000.0))
394                .with_description("Bank deposit"),
395            ExpectedFlow::new("4110", "1200", 0.05, (20.0, 500.0)).with_description("Sales return"),
396            ExpectedFlow::new("6520", "1130", 0.08, (50.0, 500.0))
397                .with_description("CC processing fees"),
398        ]);
399
400        template
401    }
402
403    /// Create a SaaS-specific template.
404    pub fn saas_standard() -> Self {
405        let mut template = Self::gaap_minimal();
406        template.industry = Industry::SaaS;
407        template.name = "SaaS Standard".to_string();
408
409        // Replace/add SaaS-specific accounts
410        template.accounts.extend(vec![
411            // Deferred revenue is big in SaaS
412            AccountDefinition::new("2310", "Deferred Revenue - Current", AccountType::Liability)
413                .with_class(2, 3)
414                .with_parent("2300")
415                .with_activity(100.0),
416            AccountDefinition::new(
417                "2320",
418                "Deferred Revenue - Long-term",
419                AccountType::Liability,
420            )
421            .with_class(2, 3)
422            .with_parent("2300")
423            .with_activity(20.0),
424            // Subscription metrics
425            AccountDefinition::new("4110", "Subscription Revenue", AccountType::Revenue)
426                .with_class(4, 1)
427                .with_parent("4100")
428                .with_semantics(AccountSemantics::IS_REVENUE)
429                .with_activity(200.0),
430            AccountDefinition::new("4120", "Professional Services", AccountType::Revenue)
431                .with_class(4, 2)
432                .with_parent("4200")
433                .with_activity(20.0),
434            // SaaS costs
435            AccountDefinition::new("5100", "Hosting Costs", AccountType::Expense)
436                .with_class(5, 1)
437                .with_parent("5000")
438                .with_activity(12.0),
439            AccountDefinition::new("5200", "Third-party Software", AccountType::Expense)
440                .with_class(5, 2)
441                .with_parent("5000")
442                .with_activity(24.0),
443            // Customer acquisition
444            AccountDefinition::new("6510", "Customer Acquisition Cost", AccountType::Expense)
445                .with_class(6, 5)
446                .with_parent("6500")
447                .with_activity(50.0),
448            AccountDefinition::new("1410", "Deferred Commission", AccountType::Asset)
449                .with_class(1, 4)
450                .with_parent("1400")
451                .with_activity(30.0),
452        ]);
453
454        // SaaS-specific flows
455        template.expected_flows = vec![
456            ExpectedFlow::new("1100", "2310", 0.25, (500.0, 50000.0))
457                .with_description("Annual subscription cash → Deferred revenue"),
458            ExpectedFlow::new("2310", "4110", 0.30, (50.0, 5000.0))
459                .with_description("Revenue recognition"),
460            ExpectedFlow::new("4110", "1200", 0.10, (100.0, 10000.0))
461                .with_description("Invoiced subscription"),
462            ExpectedFlow::new("1200", "1100", 0.15, (100.0, 10000.0))
463                .with_description("Collection"),
464            ExpectedFlow::new("5100", "2100", 0.08, (5000.0, 50000.0))
465                .with_description("Hosting invoice"),
466            ExpectedFlow::new("2100", "1100", 0.10, (1000.0, 50000.0))
467                .with_description("Vendor payment"),
468            ExpectedFlow::new("6510", "1100", 0.05, (1000.0, 20000.0))
469                .with_description("Marketing spend"),
470        ];
471
472        template
473    }
474
475    /// Create a manufacturing-specific template with inventory tracking.
476    ///
477    /// Includes accounts for:
478    /// - Raw materials, work-in-progress, and finished goods inventory
479    /// - Manufacturing overhead allocation
480    /// - Direct and indirect labor
481    /// - Factory equipment and depreciation
482    pub fn manufacturing_standard() -> Self {
483        let mut template = Self::gaap_minimal();
484        template.industry = Industry::Manufacturing;
485        template.name = "Manufacturing Standard".to_string();
486
487        // Manufacturing-specific accounts
488        template.accounts.extend(vec![
489            // Detailed inventory accounts
490            AccountDefinition::new("1310", "Raw Materials Inventory", AccountType::Asset)
491                .with_class(1, 3)
492                .with_parent("1300")
493                .with_semantics(AccountSemantics::IS_INVENTORY)
494                .with_activity(40.0)
495                .with_description("Materials awaiting production"),
496            AccountDefinition::new("1320", "Work in Progress", AccountType::Asset)
497                .with_class(1, 3)
498                .with_parent("1300")
499                .with_semantics(AccountSemantics::IS_INVENTORY)
500                .with_activity(60.0)
501                .with_description("Partially completed goods"),
502            AccountDefinition::new("1330", "Finished Goods Inventory", AccountType::Asset)
503                .with_class(1, 3)
504                .with_parent("1300")
505                .with_semantics(AccountSemantics::IS_INVENTORY)
506                .with_activity(50.0)
507                .with_description("Completed goods ready for sale"),
508            AccountDefinition::new("1340", "Factory Supplies", AccountType::Asset)
509                .with_class(1, 3)
510                .with_parent("1300")
511                .with_activity(15.0)
512                .with_description("Consumable manufacturing supplies"),
513            // Manufacturing equipment
514            AccountDefinition::new("1520", "Manufacturing Equipment", AccountType::Asset)
515                .with_class(1, 5)
516                .with_parent("1500")
517                .with_activity(5.0)
518                .with_description("Production machinery"),
519            AccountDefinition::new(
520                "1525",
521                "Accum Depreciation - Mfg Equipment",
522                AccountType::Contra,
523            )
524            .with_class(1, 5)
525            .with_parent("1520")
526            .with_semantics(AccountSemantics::IS_DEPRECIATION)
527            .with_activity(12.0)
528            .with_description("Accumulated depreciation on manufacturing equipment"),
529            // Manufacturing costs
530            AccountDefinition::new("5100", "Direct Materials", AccountType::Expense)
531                .with_class(5, 1)
532                .with_parent("5000")
533                .with_semantics(AccountSemantics::IS_COGS)
534                .with_activity(100.0)
535                .with_description("Raw materials used in production"),
536            AccountDefinition::new("5200", "Direct Labor", AccountType::Expense)
537                .with_class(5, 2)
538                .with_parent("5000")
539                .with_semantics(AccountSemantics::IS_COGS | AccountSemantics::IS_PAYROLL)
540                .with_activity(60.0)
541                .with_description("Labor directly applied to production"),
542            AccountDefinition::new("5300", "Manufacturing Overhead", AccountType::Expense)
543                .with_class(5, 3)
544                .with_parent("5000")
545                .with_activity(30.0)
546                .with_description("Indirect manufacturing costs"),
547            AccountDefinition::new("5310", "Factory Utilities", AccountType::Expense)
548                .with_class(5, 3)
549                .with_parent("5300")
550                .with_activity(12.0)
551                .with_description("Factory electricity, water, gas"),
552            AccountDefinition::new("5320", "Indirect Labor", AccountType::Expense)
553                .with_class(5, 3)
554                .with_parent("5300")
555                .with_semantics(AccountSemantics::IS_PAYROLL)
556                .with_activity(24.0)
557                .with_description("Supervisory and maintenance labor"),
558            AccountDefinition::new("5330", "Equipment Maintenance", AccountType::Expense)
559                .with_class(5, 3)
560                .with_parent("5300")
561                .with_activity(12.0)
562                .with_description("Machine repairs and maintenance"),
563            AccountDefinition::new("5340", "Factory Depreciation", AccountType::Expense)
564                .with_class(5, 3)
565                .with_parent("5300")
566                .with_activity(12.0)
567                .with_description("Depreciation on manufacturing assets"),
568            // Work order clearing
569            AccountDefinition::new("9110", "Work Order Clearing", AccountType::Asset)
570                .with_class(9, 1)
571                .with_parent("9100")
572                .with_semantics(AccountSemantics::IS_SUSPENSE)
573                .with_activity(80.0)
574                .with_description("Production job cost accumulation"),
575        ]);
576
577        // Manufacturing-specific flows
578        template.expected_flows = vec![
579            // Material purchasing
580            ExpectedFlow::new("1310", "2100", 0.20, (1000.0, 50000.0))
581                .with_description("Purchase raw materials on credit"),
582            ExpectedFlow::new("2100", "1100", 0.20, (1000.0, 50000.0))
583                .with_description("Pay supplier for materials"),
584            // Production flow
585            ExpectedFlow::new("5100", "1310", 0.25, (500.0, 20000.0))
586                .with_description("Issue materials to production"),
587            ExpectedFlow::new("1320", "5100", 0.15, (500.0, 20000.0))
588                .with_description("Accumulate direct materials in WIP"),
589            ExpectedFlow::new("1320", "5200", 0.15, (2000.0, 30000.0))
590                .with_description("Accumulate direct labor in WIP"),
591            ExpectedFlow::new("1320", "5300", 0.10, (1000.0, 15000.0))
592                .with_description("Allocate overhead to WIP"),
593            ExpectedFlow::new("1330", "1320", 0.20, (5000.0, 100000.0))
594                .with_description("Transfer completed goods from WIP"),
595            // Sales
596            ExpectedFlow::new("5000", "1330", 0.25, (3000.0, 80000.0))
597                .with_description("Cost of goods sold from finished goods"),
598            ExpectedFlow::new("4100", "1200", 0.30, (5000.0, 150000.0))
599                .with_description("Revenue recognized on sale"),
600            ExpectedFlow::new("1200", "1100", 0.25, (5000.0, 150000.0))
601                .with_description("Customer payment received"),
602            // Payroll
603            ExpectedFlow::new("5200", "1100", 0.08, (10000.0, 100000.0))
604                .with_description("Direct labor payroll"),
605            ExpectedFlow::new("5320", "1100", 0.05, (5000.0, 40000.0))
606                .with_description("Indirect labor payroll"),
607        ];
608
609        template
610    }
611
612    /// Create a professional services template.
613    ///
614    /// Includes accounts for:
615    /// - Billable and unbilled work in progress
616    /// - Client retainers and advances
617    /// - Professional fee revenue categories
618    /// - Reimbursable expenses
619    pub fn professional_services_standard() -> Self {
620        let mut template = Self::gaap_minimal();
621        template.industry = Industry::ProfessionalServices;
622        template.name = "Professional Services".to_string();
623
624        // Professional services-specific accounts
625        template.accounts.extend(vec![
626            // Unbilled work
627            AccountDefinition::new("1210", "Unbilled Receivables", AccountType::Asset)
628                .with_class(1, 2)
629                .with_parent("1200")
630                .with_semantics(AccountSemantics::IS_RECEIVABLE)
631                .with_activity(100.0)
632                .with_description("Work completed but not yet invoiced"),
633            AccountDefinition::new("1220", "Work in Progress - Billable", AccountType::Asset)
634                .with_class(1, 2)
635                .with_parent("1200")
636                .with_activity(150.0)
637                .with_description("Time and expenses in progress"),
638            AccountDefinition::new("1230", "Reimbursable Expenses", AccountType::Asset)
639                .with_class(1, 2)
640                .with_parent("1200")
641                .with_activity(40.0)
642                .with_description("Client-reimbursable expenses pending"),
643            // Client advances
644            AccountDefinition::new("2310", "Client Retainers", AccountType::Liability)
645                .with_class(2, 3)
646                .with_parent("2300")
647                .with_activity(30.0)
648                .with_description("Advance payments from clients"),
649            AccountDefinition::new("2320", "Client Deposits", AccountType::Liability)
650                .with_class(2, 3)
651                .with_parent("2300")
652                .with_activity(20.0)
653                .with_description("Project deposits held"),
654            // Revenue categories
655            AccountDefinition::new("4110", "Professional Fees - Hourly", AccountType::Revenue)
656                .with_class(4, 1)
657                .with_parent("4100")
658                .with_semantics(AccountSemantics::IS_REVENUE)
659                .with_activity(200.0)
660                .with_description("Revenue from billable hours"),
661            AccountDefinition::new("4120", "Professional Fees - Fixed", AccountType::Revenue)
662                .with_class(4, 1)
663                .with_parent("4100")
664                .with_semantics(AccountSemantics::IS_REVENUE)
665                .with_activity(50.0)
666                .with_description("Revenue from fixed-fee projects"),
667            AccountDefinition::new("4130", "Retainer Fees", AccountType::Revenue)
668                .with_class(4, 1)
669                .with_parent("4100")
670                .with_semantics(AccountSemantics::IS_REVENUE)
671                .with_activity(40.0)
672                .with_description("Monthly retainer revenue"),
673            AccountDefinition::new("4210", "Reimbursed Expenses", AccountType::Revenue)
674                .with_class(4, 2)
675                .with_parent("4200")
676                .with_activity(30.0)
677                .with_description("Client-reimbursed expenses"),
678            // Direct costs
679            AccountDefinition::new("5100", "Professional Labor Cost", AccountType::Expense)
680                .with_class(5, 1)
681                .with_parent("5000")
682                .with_semantics(AccountSemantics::IS_PAYROLL)
683                .with_activity(24.0)
684                .with_description("Cost of billable staff time"),
685            AccountDefinition::new("5200", "Subcontractor Fees", AccountType::Expense)
686                .with_class(5, 2)
687                .with_parent("5000")
688                .with_activity(20.0)
689                .with_description("Outside contractor costs"),
690            // Indirect expenses
691            AccountDefinition::new("6110", "Professional Development", AccountType::Expense)
692                .with_class(6, 1)
693                .with_parent("6100")
694                .with_activity(12.0)
695                .with_description("Training and certifications"),
696            AccountDefinition::new("6510", "Business Development", AccountType::Expense)
697                .with_class(6, 5)
698                .with_parent("6500")
699                .with_activity(25.0)
700                .with_description("Client acquisition and networking"),
701            AccountDefinition::new(
702                "6520",
703                "Professional Liability Insurance",
704                AccountType::Expense,
705            )
706            .with_class(6, 5)
707            .with_parent("6500")
708            .with_activity(12.0)
709            .with_description("E&O insurance premiums"),
710        ]);
711
712        // Professional services flows
713        template.expected_flows = vec![
714            // Time & expense billing
715            ExpectedFlow::new("1220", "5100", 0.30, (500.0, 20000.0))
716                .with_description("Record billable time as WIP"),
717            ExpectedFlow::new("1210", "1220", 0.25, (1000.0, 50000.0))
718                .with_description("Transfer completed WIP to unbilled"),
719            ExpectedFlow::new("1200", "1210", 0.25, (1000.0, 50000.0))
720                .with_description("Invoice unbilled work"),
721            ExpectedFlow::new("4110", "1200", 0.30, (1000.0, 50000.0))
722                .with_description("Recognize hourly fee revenue"),
723            ExpectedFlow::new("1200", "1100", 0.25, (1000.0, 50000.0))
724                .with_description("Client payment received"),
725            // Retainer flow
726            ExpectedFlow::new("1100", "2310", 0.10, (5000.0, 50000.0))
727                .with_description("Receive client retainer"),
728            ExpectedFlow::new("2310", "4130", 0.15, (1000.0, 10000.0))
729                .with_description("Apply retainer to revenue"),
730            // Reimbursables
731            ExpectedFlow::new("1230", "1100", 0.08, (100.0, 2000.0))
732                .with_description("Pay reimbursable expense"),
733            ExpectedFlow::new("4210", "1230", 0.08, (100.0, 2000.0))
734                .with_description("Bill reimbursable to client"),
735            // Payroll
736            ExpectedFlow::new("6100", "1100", 0.08, (10000.0, 100000.0))
737                .with_description("Staff payroll"),
738        ];
739
740        template
741    }
742
743    /// Create a financial services template.
744    ///
745    /// Includes accounts for:
746    /// - Trading and investment securities
747    /// - Customer custody and fiduciary accounts
748    /// - Regulatory capital requirements
749    /// - Interest income and expense
750    pub fn financial_services_standard() -> Self {
751        let mut template = Self::gaap_minimal();
752        template.industry = Industry::FinancialServices;
753        template.name = "Financial Services".to_string();
754
755        // Financial services-specific accounts
756        template.accounts.extend(vec![
757            // Trading and investment accounts
758            AccountDefinition::new("1110", "Trading Securities", AccountType::Asset)
759                .with_class(1, 1)
760                .with_parent("1100")
761                .with_activity(500.0)
762                .with_description("Securities held for trading"),
763            AccountDefinition::new("1120", "Available-for-Sale Securities", AccountType::Asset)
764                .with_class(1, 1)
765                .with_parent("1100")
766                .with_activity(100.0)
767                .with_description("Securities available for sale"),
768            AccountDefinition::new("1130", "Held-to-Maturity Securities", AccountType::Asset)
769                .with_class(1, 1)
770                .with_parent("1100")
771                .with_activity(20.0)
772                .with_description("Securities held to maturity"),
773            // Loan portfolio
774            AccountDefinition::new("1250", "Loans Receivable", AccountType::Asset)
775                .with_class(1, 2)
776                .with_parent("1200")
777                .with_semantics(AccountSemantics::IS_RECEIVABLE)
778                .with_activity(100.0)
779                .with_description("Outstanding loan portfolio"),
780            AccountDefinition::new("1255", "Allowance for Loan Losses", AccountType::Contra)
781                .with_class(1, 2)
782                .with_parent("1250")
783                .with_activity(24.0)
784                .with_description("Reserve for expected credit losses"),
785            AccountDefinition::new("1260", "Accrued Interest Receivable", AccountType::Asset)
786                .with_class(1, 2)
787                .with_parent("1200")
788                .with_activity(50.0)
789                .with_description("Interest earned but not yet received"),
790            // Fiduciary accounts (off-balance sheet tracking)
791            AccountDefinition::new("1610", "Customer Custody Assets", AccountType::Asset)
792                .with_class(1, 6)
793                .with_parent("1600")
794                .with_activity(200.0)
795                .with_description("Assets held in custody for clients"),
796            AccountDefinition::new(
797                "2610",
798                "Customer Custody Liabilities",
799                AccountType::Liability,
800            )
801            .with_class(2, 6)
802            .with_parent("2600")
803            .with_activity(200.0)
804            .with_description("Obligation to return custody assets"),
805            // Deposits
806            AccountDefinition::new("2110", "Customer Deposits - Demand", AccountType::Liability)
807                .with_class(2, 1)
808                .with_parent("2100")
809                .with_activity(300.0)
810                .with_description("Checking/demand deposit accounts"),
811            AccountDefinition::new(
812                "2120",
813                "Customer Deposits - Savings",
814                AccountType::Liability,
815            )
816            .with_class(2, 1)
817            .with_parent("2100")
818            .with_activity(100.0)
819            .with_description("Savings deposit accounts"),
820            AccountDefinition::new("2130", "Customer Deposits - Time", AccountType::Liability)
821                .with_class(2, 1)
822                .with_parent("2100")
823                .with_activity(50.0)
824                .with_description("CDs and time deposits"),
825            // Regulatory accounts
826            AccountDefinition::new("3110", "Regulatory Capital Reserve", AccountType::Equity)
827                .with_class(3, 1)
828                .with_parent("3100")
829                .with_activity(12.0)
830                .with_description("Capital held for regulatory requirements"),
831            AccountDefinition::new("2510", "Accrued Interest Payable", AccountType::Liability)
832                .with_class(2, 5)
833                .with_parent("2500")
834                .with_activity(50.0)
835                .with_description("Interest owed but not yet paid"),
836            // Revenue accounts
837            AccountDefinition::new("4110", "Interest Income - Loans", AccountType::Revenue)
838                .with_class(4, 1)
839                .with_parent("4100")
840                .with_semantics(AccountSemantics::IS_REVENUE)
841                .with_activity(100.0)
842                .with_description("Interest earned on loan portfolio"),
843            AccountDefinition::new("4120", "Interest Income - Securities", AccountType::Revenue)
844                .with_class(4, 1)
845                .with_parent("4100")
846                .with_semantics(AccountSemantics::IS_REVENUE)
847                .with_activity(80.0)
848                .with_description("Interest and dividends from investments"),
849            AccountDefinition::new("4130", "Trading Gains (Losses)", AccountType::Revenue)
850                .with_class(4, 1)
851                .with_parent("4100")
852                .with_activity(200.0)
853                .with_description("Net gains/losses from trading"),
854            AccountDefinition::new("4210", "Fee Income", AccountType::Revenue)
855                .with_class(4, 2)
856                .with_parent("4200")
857                .with_activity(150.0)
858                .with_description("Transaction and service fees"),
859            AccountDefinition::new("4220", "Custody Fees", AccountType::Revenue)
860                .with_class(4, 2)
861                .with_parent("4200")
862                .with_activity(50.0)
863                .with_description("Asset custody service fees"),
864            // Expense accounts
865            AccountDefinition::new("5100", "Interest Expense - Deposits", AccountType::Expense)
866                .with_class(5, 1)
867                .with_parent("5000")
868                .with_activity(100.0)
869                .with_description("Interest paid on customer deposits"),
870            AccountDefinition::new(
871                "5200",
872                "Interest Expense - Borrowings",
873                AccountType::Expense,
874            )
875            .with_class(5, 2)
876            .with_parent("5000")
877            .with_activity(50.0)
878            .with_description("Interest on wholesale borrowings"),
879            AccountDefinition::new("5300", "Provision for Loan Losses", AccountType::Expense)
880                .with_class(5, 3)
881                .with_parent("5000")
882                .with_activity(24.0)
883                .with_description("Additions to loan loss reserve"),
884            AccountDefinition::new("6110", "Compliance Costs", AccountType::Expense)
885                .with_class(6, 1)
886                .with_parent("6100")
887                .with_activity(24.0)
888                .with_description("Regulatory compliance expenses"),
889            AccountDefinition::new("6120", "Technology Infrastructure", AccountType::Expense)
890                .with_class(6, 1)
891                .with_parent("6100")
892                .with_activity(36.0)
893                .with_description("Trading systems and IT infrastructure"),
894        ]);
895
896        // Financial services flows
897        template.expected_flows = vec![
898            // Deposit flows
899            ExpectedFlow::new("1100", "2110", 0.20, (1000.0, 500000.0))
900                .with_description("Customer deposit received"),
901            ExpectedFlow::new("2110", "1100", 0.15, (500.0, 100000.0))
902                .with_description("Customer withdrawal"),
903            // Lending flows
904            ExpectedFlow::new("1250", "1100", 0.10, (10000.0, 1000000.0))
905                .with_description("Loan disbursement"),
906            ExpectedFlow::new("1100", "1250", 0.12, (1000.0, 100000.0))
907                .with_description("Loan repayment principal"),
908            ExpectedFlow::new("1100", "4110", 0.15, (100.0, 50000.0))
909                .with_description("Loan interest payment"),
910            // Trading flows
911            ExpectedFlow::new("1110", "1100", 0.25, (10000.0, 10000000.0))
912                .with_description("Security purchase"),
913            ExpectedFlow::new("1100", "1110", 0.25, (10000.0, 10000000.0))
914                .with_description("Security sale"),
915            ExpectedFlow::new("4130", "1110", 0.20, (100.0, 500000.0))
916                .with_description("Trading gain recognized"),
917            // Interest expense
918            ExpectedFlow::new("5100", "2510", 0.10, (100.0, 100000.0))
919                .with_description("Accrue interest on deposits"),
920            ExpectedFlow::new("2510", "1100", 0.08, (100.0, 100000.0))
921                .with_description("Pay accrued interest"),
922            // Fee income
923            ExpectedFlow::new("4210", "1100", 0.15, (10.0, 10000.0))
924                .with_description("Transaction fees collected"),
925            // Loan loss provision
926            ExpectedFlow::new("5300", "1255", 0.05, (1000.0, 100000.0))
927                .with_description("Provision for expected losses"),
928        ];
929
930        template
931    }
932
933    /// Get template for a company archetype.
934    pub fn for_archetype(archetype: &CompanyArchetype) -> Self {
935        match archetype.industry() {
936            Industry::Retail => Self::retail_standard(),
937            Industry::SaaS => Self::saas_standard(),
938            Industry::Manufacturing => Self::manufacturing_standard(),
939            Industry::ProfessionalServices => Self::professional_services_standard(),
940            Industry::FinancialServices => Self::financial_services_standard(),
941            _ => Self::gaap_minimal(),
942        }
943    }
944
945    /// Get account count.
946    pub fn account_count(&self) -> usize {
947        self.accounts.len()
948    }
949
950    /// Find account definition by code.
951    pub fn find_by_code(&self, code: &str) -> Option<&AccountDefinition> {
952        self.accounts.iter().find(|a| a.code == code)
953    }
954
955    /// Get accounts by type.
956    pub fn accounts_by_type(&self, account_type: AccountType) -> Vec<&AccountDefinition> {
957        self.accounts
958            .iter()
959            .filter(|a| a.account_type == account_type)
960            .collect()
961    }
962}
963
964#[cfg(test)]
965mod tests {
966    use super::*;
967
968    #[test]
969    fn test_gaap_minimal() {
970        let template = ChartOfAccountsTemplate::gaap_minimal();
971        assert!(template.account_count() > 20);
972
973        // Should have basic account types
974        assert!(!template.accounts_by_type(AccountType::Asset).is_empty());
975        assert!(!template.accounts_by_type(AccountType::Liability).is_empty());
976        assert!(!template.accounts_by_type(AccountType::Revenue).is_empty());
977        assert!(!template.accounts_by_type(AccountType::Expense).is_empty());
978    }
979
980    #[test]
981    fn test_retail_template() {
982        let template = ChartOfAccountsTemplate::retail_standard();
983        assert!(template.account_count() > 30);
984        assert_eq!(template.industry, Industry::Retail);
985
986        // Should have retail-specific accounts
987        assert!(template.find_by_code("1110").is_some()); // Cash Registers
988        assert!(template.find_by_code("1120").is_some()); // Undeposited Funds
989    }
990
991    #[test]
992    fn test_saas_template() {
993        let template = ChartOfAccountsTemplate::saas_standard();
994        assert_eq!(template.industry, Industry::SaaS);
995
996        // Should have SaaS-specific accounts
997        assert!(template.find_by_code("2310").is_some()); // Deferred Revenue
998        assert!(template.find_by_code("4110").is_some()); // Subscription Revenue
999    }
1000
1001    #[test]
1002    fn test_manufacturing_template() {
1003        let template = ChartOfAccountsTemplate::manufacturing_standard();
1004        assert_eq!(template.industry, Industry::Manufacturing);
1005        assert!(template.account_count() > 35);
1006
1007        // Should have manufacturing-specific inventory accounts
1008        assert!(template.find_by_code("1310").is_some()); // Raw Materials
1009        assert!(template.find_by_code("1320").is_some()); // Work in Progress
1010        assert!(template.find_by_code("1330").is_some()); // Finished Goods
1011
1012        // Should have manufacturing cost accounts
1013        assert!(template.find_by_code("5100").is_some()); // Direct Materials
1014        assert!(template.find_by_code("5200").is_some()); // Direct Labor
1015        assert!(template.find_by_code("5300").is_some()); // Manufacturing Overhead
1016
1017        // Should have manufacturing equipment
1018        assert!(template.find_by_code("1520").is_some()); // Manufacturing Equipment
1019
1020        // Should have expected flows
1021        assert!(!template.expected_flows.is_empty());
1022    }
1023
1024    #[test]
1025    fn test_professional_services_template() {
1026        let template = ChartOfAccountsTemplate::professional_services_standard();
1027        assert_eq!(template.industry, Industry::ProfessionalServices);
1028        assert!(template.account_count() > 35);
1029
1030        // Should have professional services-specific accounts
1031        assert!(template.find_by_code("1210").is_some()); // Unbilled Receivables
1032        assert!(template.find_by_code("1220").is_some()); // WIP - Billable
1033        assert!(template.find_by_code("2310").is_some()); // Client Retainers
1034
1035        // Should have fee revenue accounts
1036        assert!(template.find_by_code("4110").is_some()); // Professional Fees - Hourly
1037        assert!(template.find_by_code("4130").is_some()); // Retainer Fees
1038
1039        // Should have expected flows for billing cycle
1040        assert!(!template.expected_flows.is_empty());
1041    }
1042
1043    #[test]
1044    fn test_financial_services_template() {
1045        let template = ChartOfAccountsTemplate::financial_services_standard();
1046        assert_eq!(template.industry, Industry::FinancialServices);
1047        assert!(template.account_count() > 40);
1048
1049        // Should have securities accounts
1050        assert!(template.find_by_code("1110").is_some()); // Trading Securities
1051        assert!(template.find_by_code("1120").is_some()); // Available-for-Sale
1052        assert!(template.find_by_code("1130").is_some()); // Held-to-Maturity
1053
1054        // Should have loan portfolio accounts
1055        assert!(template.find_by_code("1250").is_some()); // Loans Receivable
1056        assert!(template.find_by_code("1255").is_some()); // Allowance for Loan Losses
1057
1058        // Should have deposit accounts
1059        assert!(template.find_by_code("2110").is_some()); // Customer Deposits - Demand
1060        assert!(template.find_by_code("2120").is_some()); // Customer Deposits - Savings
1061
1062        // Should have interest income/expense
1063        assert!(template.find_by_code("4110").is_some()); // Interest Income - Loans
1064        assert!(template.find_by_code("5100").is_some()); // Interest Expense - Deposits
1065
1066        // Should have custody accounts
1067        assert!(template.find_by_code("1610").is_some()); // Customer Custody Assets
1068        assert!(template.find_by_code("4220").is_some()); // Custody Fees
1069
1070        // Should have expected flows
1071        assert!(!template.expected_flows.is_empty());
1072    }
1073}