1use std::ops::Range;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
10pub enum Industry {
11 Retail,
13 SaaS,
15 Manufacturing,
17 ProfessionalServices,
19 FinancialServices,
21 Healthcare,
23 Construction,
25 Education,
27}
28
29#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
31pub enum CompanySize {
32 Small,
34 Medium,
36 Large,
38 Enterprise,
40}
41
42impl CompanySize {
43 pub fn typical_account_count(&self) -> Range<usize> {
45 match self {
46 CompanySize::Small => 50..100,
47 CompanySize::Medium => 100..200,
48 CompanySize::Large => 200..400,
49 CompanySize::Enterprise => 400..800,
50 }
51 }
52
53 pub fn typical_daily_transactions(&self) -> Range<u32> {
55 match self {
56 CompanySize::Small => 10..100,
57 CompanySize::Medium => 100..500,
58 CompanySize::Large => 500..2000,
59 CompanySize::Enterprise => 2000..10000,
60 }
61 }
62}
63
64#[derive(Debug, Clone)]
66pub enum CompanyArchetype {
67 Retail(RetailConfig),
69
70 SaaS(SaaSConfig),
72
73 Manufacturing(ManufacturingConfig),
75
76 ProfessionalServices(ProfServicesConfig),
78
79 FinancialServices(FinServicesConfig),
81}
82
83#[derive(Debug, Clone)]
85pub struct RetailConfig {
86 pub store_count: u32,
88 pub avg_transaction: f64,
90 pub seasonal_peaks: Vec<u8>,
92 pub online_ratio: f64,
94 pub inventory_turnover: f64,
96 pub gross_margin: f64,
98 pub size: CompanySize,
100}
101
102impl Default for RetailConfig {
103 fn default() -> Self {
104 Self {
105 store_count: 5,
106 avg_transaction: 75.0,
107 seasonal_peaks: vec![11, 12], online_ratio: 0.3,
109 inventory_turnover: 6.0,
110 gross_margin: 0.35,
111 size: CompanySize::Medium,
112 }
113 }
114}
115
116#[derive(Debug, Clone)]
118pub struct SaaSConfig {
119 pub mrr: f64,
121 pub churn_rate: f64,
123 pub contract_length_months: u32,
125 pub annual_contract_ratio: f64,
127 pub deferred_revenue_ratio: f64,
129 pub size: CompanySize,
131}
132
133impl Default for SaaSConfig {
134 fn default() -> Self {
135 Self {
136 mrr: 500_000.0,
137 churn_rate: 0.05,
138 contract_length_months: 12,
139 annual_contract_ratio: 0.6,
140 deferred_revenue_ratio: 0.8,
141 size: CompanySize::Medium,
142 }
143 }
144}
145
146#[derive(Debug, Clone)]
148pub struct ManufacturingConfig {
149 pub product_lines: u32,
151 pub supplier_count: u32,
153 pub production_cycles_per_month: u32,
155 pub wip_ratio: f64,
157 pub lead_time_days: u32,
159 pub size: CompanySize,
161}
162
163impl Default for ManufacturingConfig {
164 fn default() -> Self {
165 Self {
166 product_lines: 3,
167 supplier_count: 25,
168 production_cycles_per_month: 4,
169 wip_ratio: 0.3,
170 lead_time_days: 30,
171 size: CompanySize::Large,
172 }
173 }
174}
175
176#[derive(Debug, Clone)]
178pub struct ProfServicesConfig {
179 pub billable_headcount: u32,
181 pub avg_hourly_rate: f64,
183 pub utilization_target: f64,
185 pub avg_project_duration: u32,
187 pub completion_billing_ratio: f64,
189 pub size: CompanySize,
191}
192
193impl Default for ProfServicesConfig {
194 fn default() -> Self {
195 Self {
196 billable_headcount: 50,
197 avg_hourly_rate: 200.0,
198 utilization_target: 0.75,
199 avg_project_duration: 45,
200 completion_billing_ratio: 0.4,
201 size: CompanySize::Medium,
202 }
203 }
204}
205
206#[derive(Debug, Clone)]
208pub struct FinServicesConfig {
209 pub aum: f64,
211 pub product_type_count: u32,
213 pub intercompany_ratio: f64,
215 pub capital_ratio: f64,
217 pub size: CompanySize,
219}
220
221impl Default for FinServicesConfig {
222 fn default() -> Self {
223 Self {
224 aum: 1_000_000_000.0,
225 product_type_count: 5,
226 intercompany_ratio: 0.15,
227 capital_ratio: 0.12,
228 size: CompanySize::Large,
229 }
230 }
231}
232
233impl CompanyArchetype {
234 pub fn retail_standard() -> Self {
236 Self::Retail(RetailConfig::default())
237 }
238
239 pub fn retail_small() -> Self {
241 Self::Retail(RetailConfig {
242 store_count: 1,
243 avg_transaction: 50.0,
244 size: CompanySize::Small,
245 ..Default::default()
246 })
247 }
248
249 pub fn saas_standard() -> Self {
251 Self::SaaS(SaaSConfig::default())
252 }
253
254 pub fn saas_startup() -> Self {
256 Self::SaaS(SaaSConfig {
257 mrr: 50_000.0,
258 churn_rate: 0.08,
259 size: CompanySize::Small,
260 ..Default::default()
261 })
262 }
263
264 pub fn manufacturing_standard() -> Self {
266 Self::Manufacturing(ManufacturingConfig::default())
267 }
268
269 pub fn professional_services_standard() -> Self {
271 Self::ProfessionalServices(ProfServicesConfig::default())
272 }
273
274 pub fn financial_services_standard() -> Self {
276 Self::FinancialServices(FinServicesConfig::default())
277 }
278
279 pub fn industry(&self) -> Industry {
281 match self {
282 CompanyArchetype::Retail(_) => Industry::Retail,
283 CompanyArchetype::SaaS(_) => Industry::SaaS,
284 CompanyArchetype::Manufacturing(_) => Industry::Manufacturing,
285 CompanyArchetype::ProfessionalServices(_) => Industry::ProfessionalServices,
286 CompanyArchetype::FinancialServices(_) => Industry::FinancialServices,
287 }
288 }
289
290 pub fn size(&self) -> CompanySize {
292 match self {
293 CompanyArchetype::Retail(c) => c.size,
294 CompanyArchetype::SaaS(c) => c.size,
295 CompanyArchetype::Manufacturing(c) => c.size,
296 CompanyArchetype::ProfessionalServices(c) => c.size,
297 CompanyArchetype::FinancialServices(c) => c.size,
298 }
299 }
300
301 pub fn display_name(&self) -> &'static str {
303 match self {
304 CompanyArchetype::Retail(_) => "Retail",
305 CompanyArchetype::SaaS(_) => "SaaS",
306 CompanyArchetype::Manufacturing(_) => "Manufacturing",
307 CompanyArchetype::ProfessionalServices(_) => "Professional Services",
308 CompanyArchetype::FinancialServices(_) => "Financial Services",
309 }
310 }
311
312 pub fn description(&self) -> &'static str {
314 match self {
315 CompanyArchetype::Retail(_) => {
316 "High-volume retail with inventory management and seasonal patterns"
317 }
318 CompanyArchetype::SaaS(_) => {
319 "Subscription software with deferred revenue and monthly billing cycles"
320 }
321 CompanyArchetype::Manufacturing(_) => {
322 "Manufacturing with supply chain, WIP inventory, and production cycles"
323 }
324 CompanyArchetype::ProfessionalServices(_) => {
325 "Time-based billing with utilization tracking and project accounting"
326 }
327 CompanyArchetype::FinancialServices(_) => {
328 "Complex financial instruments with intercompany transactions"
329 }
330 }
331 }
332
333 pub fn transaction_patterns(&self) -> Vec<TransactionPattern> {
335 match self {
336 CompanyArchetype::Retail(_) => vec![
337 TransactionPattern::new("Sales", 0.40, 50.0..500.0),
338 TransactionPattern::new("Inventory Purchase", 0.25, 500.0..10000.0),
339 TransactionPattern::new("Payroll", 0.10, 5000.0..50000.0),
340 TransactionPattern::new("Rent", 0.05, 2000.0..20000.0),
341 TransactionPattern::new("Utilities", 0.05, 200.0..2000.0),
342 TransactionPattern::new("Marketing", 0.05, 100.0..5000.0),
343 TransactionPattern::new("Returns", 0.05, 20.0..200.0),
344 TransactionPattern::new("Other", 0.05, 50.0..1000.0),
345 ],
346 CompanyArchetype::SaaS(_) => vec![
347 TransactionPattern::new("Subscription Revenue", 0.30, 50.0..5000.0),
348 TransactionPattern::new("Deferred Revenue Recog", 0.25, 100.0..10000.0),
349 TransactionPattern::new("Payroll", 0.20, 10000.0..100000.0),
350 TransactionPattern::new("Cloud Infrastructure", 0.10, 1000.0..50000.0),
351 TransactionPattern::new("Marketing", 0.08, 500.0..20000.0),
352 TransactionPattern::new("Refunds", 0.02, 50.0..500.0),
353 TransactionPattern::new("Other", 0.05, 100.0..2000.0),
354 ],
355 CompanyArchetype::Manufacturing(_) => vec![
356 TransactionPattern::new("Raw Materials", 0.30, 1000.0..100000.0),
357 TransactionPattern::new("WIP Transfer", 0.20, 500.0..50000.0),
358 TransactionPattern::new("Finished Goods Sale", 0.15, 1000.0..50000.0),
359 TransactionPattern::new("Payroll", 0.15, 20000.0..200000.0),
360 TransactionPattern::new("Equipment Depreciation", 0.05, 1000.0..20000.0),
361 TransactionPattern::new("Utilities", 0.05, 5000.0..30000.0),
362 TransactionPattern::new("Maintenance", 0.05, 500.0..10000.0),
363 TransactionPattern::new("Other", 0.05, 200.0..5000.0),
364 ],
365 CompanyArchetype::ProfessionalServices(_) => vec![
366 TransactionPattern::new("Time Billing", 0.35, 500.0..50000.0),
367 TransactionPattern::new("Expense Reimbursement", 0.15, 100.0..5000.0),
368 TransactionPattern::new("Payroll", 0.25, 15000.0..150000.0),
369 TransactionPattern::new("Rent", 0.08, 5000.0..50000.0),
370 TransactionPattern::new("Professional Development", 0.05, 200.0..5000.0),
371 TransactionPattern::new("Insurance", 0.05, 1000.0..10000.0),
372 TransactionPattern::new("Other", 0.07, 100.0..2000.0),
373 ],
374 CompanyArchetype::FinancialServices(_) => vec![
375 TransactionPattern::new("Investment Transaction", 0.25, 10000.0..1000000.0),
376 TransactionPattern::new("Fee Revenue", 0.15, 100.0..50000.0),
377 TransactionPattern::new("Interest Income", 0.15, 1000.0..100000.0),
378 TransactionPattern::new("Intercompany Transfer", 0.15, 50000.0..5000000.0),
379 TransactionPattern::new("Payroll", 0.10, 50000.0..500000.0),
380 TransactionPattern::new("Regulatory Reserve", 0.10, 10000.0..500000.0),
381 TransactionPattern::new("Other", 0.10, 500.0..10000.0),
382 ],
383 }
384 }
385
386 pub fn seasonal_multipliers(&self) -> [f64; 12] {
388 match self {
389 CompanyArchetype::Retail(config) => {
390 let mut mults = [1.0; 12];
391 for &peak_month in &config.seasonal_peaks {
393 if (1..=12).contains(&peak_month) {
394 mults[(peak_month - 1) as usize] = 2.5;
395 if peak_month > 1 {
397 mults[(peak_month - 2) as usize] *= 1.5;
398 }
399 }
400 }
401 mults[0] = 0.7;
403 mults
404 }
405 CompanyArchetype::SaaS(_) => {
406 [1.0, 1.0, 1.1, 1.0, 1.0, 1.1, 1.0, 1.0, 1.1, 1.0, 1.1, 1.3]
408 }
409 CompanyArchetype::Manufacturing(_) => {
410 [1.0, 1.1, 1.2, 1.1, 1.0, 0.9, 0.8, 0.8, 1.0, 1.1, 1.2, 1.0]
412 }
413 CompanyArchetype::ProfessionalServices(_) => {
414 [1.3, 1.2, 1.1, 1.0, 1.0, 0.9, 0.8, 0.8, 1.0, 1.0, 1.0, 0.9]
416 }
417 CompanyArchetype::FinancialServices(_) => {
418 [1.0, 1.0, 1.4, 1.0, 1.0, 1.4, 1.0, 1.0, 1.4, 1.0, 1.0, 1.5]
420 }
421 }
422 }
423}
424
425#[derive(Debug, Clone)]
427pub struct TransactionPattern {
428 pub name: String,
430 pub frequency: f64,
432 pub amount_range: Range<f64>,
434}
435
436impl TransactionPattern {
437 pub fn new(name: impl Into<String>, frequency: f64, amount_range: Range<f64>) -> Self {
439 Self {
440 name: name.into(),
441 frequency,
442 amount_range,
443 }
444 }
445}
446
447#[cfg(test)]
448mod tests {
449 use super::*;
450
451 #[test]
452 fn test_retail_archetype() {
453 let retail = CompanyArchetype::retail_standard();
454 assert_eq!(retail.industry(), Industry::Retail);
455 assert_eq!(retail.size(), CompanySize::Medium);
456
457 let patterns = retail.transaction_patterns();
458 let total_freq: f64 = patterns.iter().map(|p| p.frequency).sum();
459 assert!((total_freq - 1.0).abs() < 0.01);
460 }
461
462 #[test]
463 fn test_seasonal_multipliers() {
464 let retail = CompanyArchetype::retail_standard();
465 let mults = retail.seasonal_multipliers();
466
467 assert!(mults[10] > 1.5); assert!(mults[11] > 2.0); assert!(mults[0] < 1.0);
472 }
473
474 #[test]
475 fn test_company_sizes() {
476 assert!(CompanySize::Small.typical_account_count().start < 100);
477 assert!(CompanySize::Enterprise.typical_daily_transactions().end >= 10000);
478 }
479}