1use datasynth_core::distributions::{
4 AmountDistributionConfig, DebitCreditDistributionConfig, EvenOddDistributionConfig,
5 LineItemDistributionConfig, SeasonalityConfig,
6};
7use datasynth_core::models::{CoAComplexity, IndustrySector};
8use serde::{Deserialize, Serialize};
9use std::path::PathBuf;
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct GeneratorConfig {
14 pub global: GlobalConfig,
16 pub companies: Vec<CompanyConfig>,
18 pub chart_of_accounts: ChartOfAccountsConfig,
20 #[serde(default)]
22 pub transactions: TransactionConfig,
23 pub output: OutputConfig,
25 #[serde(default)]
27 pub fraud: FraudConfig,
28 #[serde(default)]
30 pub data_quality: DataQualitySchemaConfig,
31 #[serde(default)]
33 pub internal_controls: InternalControlsConfig,
34 #[serde(default)]
36 pub business_processes: BusinessProcessConfig,
37 #[serde(default)]
39 pub user_personas: UserPersonaConfig,
40 #[serde(default)]
42 pub templates: TemplateConfig,
43 #[serde(default)]
45 pub approval: ApprovalConfig,
46 #[serde(default)]
48 pub departments: DepartmentConfig,
49 #[serde(default)]
51 pub master_data: MasterDataConfig,
52 #[serde(default)]
54 pub document_flows: DocumentFlowConfig,
55 #[serde(default)]
57 pub intercompany: IntercompanyConfig,
58 #[serde(default)]
60 pub balance: BalanceConfig,
61 #[serde(default)]
63 pub ocpm: OcpmConfig,
64 #[serde(default)]
66 pub audit: AuditGenerationConfig,
67 #[serde(default)]
69 pub banking: datasynth_banking::BankingConfig,
70 #[serde(default)]
72 pub scenario: ScenarioConfig,
73 #[serde(default)]
75 pub temporal: TemporalDriftConfig,
76 #[serde(default)]
78 pub graph_export: GraphExportConfig,
79 #[serde(default)]
81 pub streaming: StreamingSchemaConfig,
82 #[serde(default)]
84 pub rate_limit: RateLimitSchemaConfig,
85 #[serde(default)]
87 pub temporal_attributes: TemporalAttributeSchemaConfig,
88 #[serde(default)]
90 pub relationships: RelationshipSchemaConfig,
91 #[serde(default)]
93 pub accounting_standards: AccountingStandardsConfig,
94 #[serde(default)]
96 pub audit_standards: AuditStandardsConfig,
97 #[serde(default)]
99 pub distributions: AdvancedDistributionConfig,
100 #[serde(default)]
102 pub temporal_patterns: TemporalPatternsConfig,
103 #[serde(default)]
105 pub vendor_network: VendorNetworkSchemaConfig,
106 #[serde(default)]
108 pub customer_segmentation: CustomerSegmentationSchemaConfig,
109 #[serde(default)]
111 pub relationship_strength: RelationshipStrengthSchemaConfig,
112 #[serde(default)]
114 pub cross_process_links: CrossProcessLinksSchemaConfig,
115 #[serde(default)]
117 pub organizational_events: OrganizationalEventsSchemaConfig,
118 #[serde(default)]
120 pub behavioral_drift: BehavioralDriftSchemaConfig,
121 #[serde(default)]
123 pub market_drift: MarketDriftSchemaConfig,
124 #[serde(default)]
126 pub drift_labeling: DriftLabelingSchemaConfig,
127 #[serde(default)]
129 pub anomaly_injection: EnhancedAnomalyConfig,
130 #[serde(default)]
132 pub industry_specific: IndustrySpecificConfig,
133 #[serde(default)]
135 pub fingerprint_privacy: FingerprintPrivacyConfig,
136 #[serde(default)]
138 pub quality_gates: QualityGatesSchemaConfig,
139 #[serde(default)]
141 pub compliance: ComplianceSchemaConfig,
142 #[serde(default)]
144 pub webhooks: WebhookSchemaConfig,
145 #[serde(default)]
147 pub llm: LlmSchemaConfig,
148 #[serde(default)]
150 pub diffusion: DiffusionSchemaConfig,
151 #[serde(default)]
153 pub causal: CausalSchemaConfig,
154
155 #[serde(default)]
158 pub source_to_pay: SourceToPayConfig,
159 #[serde(default)]
161 pub financial_reporting: FinancialReportingConfig,
162 #[serde(default)]
164 pub hr: HrConfig,
165 #[serde(default)]
167 pub manufacturing: ManufacturingProcessConfig,
168 #[serde(default)]
170 pub sales_quotes: SalesQuoteConfig,
171 #[serde(default)]
173 pub tax: TaxConfig,
174 #[serde(default)]
176 pub treasury: TreasuryConfig,
177 #[serde(default)]
179 pub project_accounting: ProjectAccountingConfig,
180 #[serde(default)]
182 pub esg: EsgConfig,
183 #[serde(default)]
185 pub country_packs: Option<CountryPacksSchemaConfig>,
186 #[serde(default)]
188 pub scenarios: ScenariosConfig,
189 #[serde(default)]
191 pub session: SessionSchemaConfig,
192 #[serde(default)]
194 pub compliance_regulations: ComplianceRegulationsConfig,
195}
196
197#[derive(Debug, Clone, Serialize, Deserialize)]
203pub struct LlmSchemaConfig {
204 #[serde(default)]
206 pub enabled: bool,
207 #[serde(default = "default_llm_provider")]
209 pub provider: String,
210 #[serde(default = "default_llm_model_name")]
212 pub model: String,
213 #[serde(default = "default_llm_batch_size")]
215 pub max_vendor_enrichments: usize,
216}
217
218fn default_llm_provider() -> String {
219 "mock".to_string()
220}
221
222fn default_llm_model_name() -> String {
223 "gpt-4o-mini".to_string()
224}
225
226fn default_llm_batch_size() -> usize {
227 50
228}
229
230impl Default for LlmSchemaConfig {
231 fn default() -> Self {
232 Self {
233 enabled: false,
234 provider: default_llm_provider(),
235 model: default_llm_model_name(),
236 max_vendor_enrichments: default_llm_batch_size(),
237 }
238 }
239}
240
241#[derive(Debug, Clone, Serialize, Deserialize)]
246pub struct DiffusionSchemaConfig {
247 #[serde(default)]
249 pub enabled: bool,
250 #[serde(default = "default_diffusion_steps")]
252 pub n_steps: usize,
253 #[serde(default = "default_diffusion_schedule")]
255 pub schedule: String,
256 #[serde(default = "default_diffusion_sample_size")]
258 pub sample_size: usize,
259}
260
261fn default_diffusion_steps() -> usize {
262 100
263}
264
265fn default_diffusion_schedule() -> String {
266 "linear".to_string()
267}
268
269fn default_diffusion_sample_size() -> usize {
270 100
271}
272
273impl Default for DiffusionSchemaConfig {
274 fn default() -> Self {
275 Self {
276 enabled: false,
277 n_steps: default_diffusion_steps(),
278 schedule: default_diffusion_schedule(),
279 sample_size: default_diffusion_sample_size(),
280 }
281 }
282}
283
284#[derive(Debug, Clone, Serialize, Deserialize)]
290pub struct CausalSchemaConfig {
291 #[serde(default)]
293 pub enabled: bool,
294 #[serde(default = "default_causal_template")]
296 pub template: String,
297 #[serde(default = "default_causal_sample_size")]
299 pub sample_size: usize,
300 #[serde(default = "default_true")]
302 pub validate: bool,
303}
304
305fn default_causal_template() -> String {
306 "fraud_detection".to_string()
307}
308
309fn default_causal_sample_size() -> usize {
310 500
311}
312
313impl Default for CausalSchemaConfig {
314 fn default() -> Self {
315 Self {
316 enabled: false,
317 template: default_causal_template(),
318 sample_size: default_causal_sample_size(),
319 validate: true,
320 }
321 }
322}
323
324#[derive(Debug, Clone, Serialize, Deserialize)]
331pub struct GraphExportConfig {
332 #[serde(default)]
334 pub enabled: bool,
335
336 #[serde(default = "default_graph_types")]
338 pub graph_types: Vec<GraphTypeConfig>,
339
340 #[serde(default = "default_graph_formats")]
342 pub formats: Vec<GraphExportFormat>,
343
344 #[serde(default = "default_train_ratio")]
346 pub train_ratio: f64,
347
348 #[serde(default = "default_val_ratio")]
350 pub validation_ratio: f64,
351
352 #[serde(default)]
354 pub split_seed: Option<u64>,
355
356 #[serde(default = "default_graph_subdir")]
358 pub output_subdirectory: String,
359
360 #[serde(default)]
362 pub hypergraph: HypergraphExportSettings,
363
364 #[serde(default)]
366 pub dgl: DglExportConfig,
367}
368
369fn default_graph_types() -> Vec<GraphTypeConfig> {
370 vec![GraphTypeConfig::default()]
371}
372
373fn default_graph_formats() -> Vec<GraphExportFormat> {
374 vec![GraphExportFormat::PytorchGeometric]
375}
376
377fn default_train_ratio() -> f64 {
378 0.7
379}
380
381fn default_val_ratio() -> f64 {
382 0.15
383}
384
385fn default_graph_subdir() -> String {
386 "graphs".to_string()
387}
388
389impl Default for GraphExportConfig {
390 fn default() -> Self {
391 Self {
392 enabled: false,
393 graph_types: default_graph_types(),
394 formats: default_graph_formats(),
395 train_ratio: 0.7,
396 validation_ratio: 0.15,
397 split_seed: None,
398 output_subdirectory: "graphs".to_string(),
399 hypergraph: HypergraphExportSettings::default(),
400 dgl: DglExportConfig::default(),
401 }
402 }
403}
404
405#[derive(Debug, Clone, Default, Serialize, Deserialize)]
407pub struct DglExportConfig {
408 #[serde(default)]
414 pub heterogeneous: bool,
415}
416
417#[derive(Debug, Clone, Serialize, Deserialize)]
426pub struct HypergraphExportSettings {
427 #[serde(default)]
429 pub enabled: bool,
430
431 #[serde(default = "default_hypergraph_max_nodes")]
433 pub max_nodes: usize,
434
435 #[serde(default = "default_aggregation_strategy")]
437 pub aggregation_strategy: String,
438
439 #[serde(default)]
441 pub governance_layer: GovernanceLayerSettings,
442
443 #[serde(default)]
445 pub process_layer: ProcessLayerSettings,
446
447 #[serde(default)]
449 pub accounting_layer: AccountingLayerSettings,
450
451 #[serde(default)]
453 pub cross_layer: CrossLayerSettings,
454
455 #[serde(default = "default_hypergraph_subdir")]
457 pub output_subdirectory: String,
458
459 #[serde(default = "default_hypergraph_format")]
461 pub output_format: String,
462
463 #[serde(default)]
465 pub stream_target: Option<String>,
466
467 #[serde(default = "default_stream_batch_size")]
469 pub stream_batch_size: usize,
470}
471
472fn default_hypergraph_max_nodes() -> usize {
473 50_000
474}
475
476fn default_aggregation_strategy() -> String {
477 "pool_by_counterparty".to_string()
478}
479
480fn default_hypergraph_subdir() -> String {
481 "hypergraph".to_string()
482}
483
484fn default_hypergraph_format() -> String {
485 "native".to_string()
486}
487
488fn default_stream_batch_size() -> usize {
489 1000
490}
491
492impl Default for HypergraphExportSettings {
493 fn default() -> Self {
494 Self {
495 enabled: false,
496 max_nodes: 50_000,
497 aggregation_strategy: "pool_by_counterparty".to_string(),
498 governance_layer: GovernanceLayerSettings::default(),
499 process_layer: ProcessLayerSettings::default(),
500 accounting_layer: AccountingLayerSettings::default(),
501 cross_layer: CrossLayerSettings::default(),
502 output_subdirectory: "hypergraph".to_string(),
503 output_format: "native".to_string(),
504 stream_target: None,
505 stream_batch_size: 1000,
506 }
507 }
508}
509
510#[derive(Debug, Clone, Serialize, Deserialize)]
512pub struct GovernanceLayerSettings {
513 #[serde(default = "default_true")]
515 pub include_coso: bool,
516 #[serde(default = "default_true")]
518 pub include_controls: bool,
519 #[serde(default = "default_true")]
521 pub include_sox: bool,
522 #[serde(default = "default_true")]
524 pub include_vendors: bool,
525 #[serde(default = "default_true")]
527 pub include_customers: bool,
528 #[serde(default = "default_true")]
530 pub include_employees: bool,
531}
532
533impl Default for GovernanceLayerSettings {
534 fn default() -> Self {
535 Self {
536 include_coso: true,
537 include_controls: true,
538 include_sox: true,
539 include_vendors: true,
540 include_customers: true,
541 include_employees: true,
542 }
543 }
544}
545
546#[derive(Debug, Clone, Serialize, Deserialize)]
548pub struct ProcessLayerSettings {
549 #[serde(default = "default_true")]
551 pub include_p2p: bool,
552 #[serde(default = "default_true")]
554 pub include_o2c: bool,
555 #[serde(default = "default_true")]
557 pub include_s2c: bool,
558 #[serde(default = "default_true")]
560 pub include_h2r: bool,
561 #[serde(default = "default_true")]
563 pub include_mfg: bool,
564 #[serde(default = "default_true")]
566 pub include_bank: bool,
567 #[serde(default = "default_true")]
569 pub include_audit: bool,
570 #[serde(default = "default_true")]
572 pub include_r2r: bool,
573 #[serde(default = "default_true")]
575 pub events_as_hyperedges: bool,
576 #[serde(default = "default_docs_per_counterparty_threshold")]
578 pub docs_per_counterparty_threshold: usize,
579}
580
581fn default_docs_per_counterparty_threshold() -> usize {
582 20
583}
584
585impl Default for ProcessLayerSettings {
586 fn default() -> Self {
587 Self {
588 include_p2p: true,
589 include_o2c: true,
590 include_s2c: true,
591 include_h2r: true,
592 include_mfg: true,
593 include_bank: true,
594 include_audit: true,
595 include_r2r: true,
596 events_as_hyperedges: true,
597 docs_per_counterparty_threshold: 20,
598 }
599 }
600}
601
602#[derive(Debug, Clone, Serialize, Deserialize)]
604pub struct AccountingLayerSettings {
605 #[serde(default = "default_true")]
607 pub include_accounts: bool,
608 #[serde(default = "default_true")]
610 pub je_as_hyperedges: bool,
611}
612
613impl Default for AccountingLayerSettings {
614 fn default() -> Self {
615 Self {
616 include_accounts: true,
617 je_as_hyperedges: true,
618 }
619 }
620}
621
622#[derive(Debug, Clone, Serialize, Deserialize)]
624pub struct CrossLayerSettings {
625 #[serde(default = "default_true")]
627 pub enabled: bool,
628}
629
630impl Default for CrossLayerSettings {
631 fn default() -> Self {
632 Self { enabled: true }
633 }
634}
635
636#[derive(Debug, Clone, Serialize, Deserialize)]
638pub struct GraphTypeConfig {
639 #[serde(default = "default_graph_name")]
641 pub name: String,
642
643 #[serde(default)]
645 pub aggregate_edges: bool,
646
647 #[serde(default)]
649 pub min_edge_weight: f64,
650
651 #[serde(default)]
653 pub include_document_nodes: bool,
654}
655
656fn default_graph_name() -> String {
657 "accounting_network".to_string()
658}
659
660impl Default for GraphTypeConfig {
661 fn default() -> Self {
662 Self {
663 name: "accounting_network".to_string(),
664 aggregate_edges: false,
665 min_edge_weight: 0.0,
666 include_document_nodes: false,
667 }
668 }
669}
670
671#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
673#[serde(rename_all = "snake_case")]
674pub enum GraphExportFormat {
675 PytorchGeometric,
677 Neo4j,
679 Dgl,
681 RustGraph,
683 RustGraphHypergraph,
685}
686
687#[derive(Debug, Clone, Default, Serialize, Deserialize)]
691pub struct ScenarioConfig {
692 #[serde(default)]
695 pub tags: Vec<String>,
696
697 #[serde(default)]
702 pub profile: Option<String>,
703
704 #[serde(default)]
706 pub description: Option<String>,
707
708 #[serde(default)]
710 pub ml_training: bool,
711
712 #[serde(default)]
715 pub target_anomaly_ratio: Option<f64>,
716
717 #[serde(default)]
719 pub metadata: std::collections::HashMap<String, String>,
720}
721
722#[derive(Debug, Clone, Serialize, Deserialize)]
727pub struct TemporalDriftConfig {
728 #[serde(default)]
730 pub enabled: bool,
731
732 #[serde(default = "default_amount_drift")]
735 pub amount_mean_drift: f64,
736
737 #[serde(default)]
740 pub amount_variance_drift: f64,
741
742 #[serde(default)]
745 pub anomaly_rate_drift: f64,
746
747 #[serde(default = "default_concept_drift")]
750 pub concept_drift_rate: f64,
751
752 #[serde(default)]
754 pub sudden_drift_probability: f64,
755
756 #[serde(default = "default_sudden_drift_magnitude")]
758 pub sudden_drift_magnitude: f64,
759
760 #[serde(default)]
762 pub seasonal_drift: bool,
763
764 #[serde(default)]
766 pub drift_start_period: u32,
767
768 #[serde(default = "default_drift_type")]
770 pub drift_type: DriftType,
771}
772
773fn default_amount_drift() -> f64 {
774 0.02
775}
776
777fn default_concept_drift() -> f64 {
778 0.01
779}
780
781fn default_sudden_drift_magnitude() -> f64 {
782 2.0
783}
784
785fn default_drift_type() -> DriftType {
786 DriftType::Gradual
787}
788
789impl Default for TemporalDriftConfig {
790 fn default() -> Self {
791 Self {
792 enabled: false,
793 amount_mean_drift: 0.02,
794 amount_variance_drift: 0.0,
795 anomaly_rate_drift: 0.0,
796 concept_drift_rate: 0.01,
797 sudden_drift_probability: 0.0,
798 sudden_drift_magnitude: 2.0,
799 seasonal_drift: false,
800 drift_start_period: 0,
801 drift_type: DriftType::Gradual,
802 }
803 }
804}
805
806impl TemporalDriftConfig {
807 pub fn to_core_config(&self) -> datasynth_core::distributions::DriftConfig {
809 datasynth_core::distributions::DriftConfig {
810 enabled: self.enabled,
811 amount_mean_drift: self.amount_mean_drift,
812 amount_variance_drift: self.amount_variance_drift,
813 anomaly_rate_drift: self.anomaly_rate_drift,
814 concept_drift_rate: self.concept_drift_rate,
815 sudden_drift_probability: self.sudden_drift_probability,
816 sudden_drift_magnitude: self.sudden_drift_magnitude,
817 seasonal_drift: self.seasonal_drift,
818 drift_start_period: self.drift_start_period,
819 drift_type: match self.drift_type {
820 DriftType::Gradual => datasynth_core::distributions::DriftType::Gradual,
821 DriftType::Sudden => datasynth_core::distributions::DriftType::Sudden,
822 DriftType::Recurring => datasynth_core::distributions::DriftType::Recurring,
823 DriftType::Mixed => datasynth_core::distributions::DriftType::Mixed,
824 },
825 regime_changes: Vec::new(),
826 economic_cycle: Default::default(),
827 parameter_drifts: Vec::new(),
828 }
829 }
830}
831
832#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
834#[serde(rename_all = "snake_case")]
835pub enum DriftType {
836 #[default]
838 Gradual,
839 Sudden,
841 Recurring,
843 Mixed,
845}
846
847#[derive(Debug, Clone, Serialize, Deserialize)]
853pub struct StreamingSchemaConfig {
854 #[serde(default)]
856 pub enabled: bool,
857 #[serde(default)]
859 pub events_per_second: f64,
860 #[serde(default = "default_burst_size")]
862 pub burst_size: u32,
863 #[serde(default = "default_buffer_size")]
865 pub buffer_size: usize,
866 #[serde(default = "default_true")]
868 pub enable_progress: bool,
869 #[serde(default = "default_progress_interval")]
871 pub progress_interval: u64,
872 #[serde(default)]
874 pub backpressure: BackpressureSchemaStrategy,
875}
876
877fn default_buffer_size() -> usize {
878 1000
879}
880
881fn default_progress_interval() -> u64 {
882 100
883}
884
885impl Default for StreamingSchemaConfig {
886 fn default() -> Self {
887 Self {
888 enabled: false,
889 events_per_second: 0.0,
890 burst_size: 100,
891 buffer_size: 1000,
892 enable_progress: true,
893 progress_interval: 100,
894 backpressure: BackpressureSchemaStrategy::Block,
895 }
896 }
897}
898
899#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
901#[serde(rename_all = "snake_case")]
902pub enum BackpressureSchemaStrategy {
903 #[default]
905 Block,
906 DropOldest,
908 DropNewest,
910 Buffer,
912}
913
914#[derive(Debug, Clone, Serialize, Deserialize)]
920pub struct RateLimitSchemaConfig {
921 #[serde(default)]
923 pub enabled: bool,
924 #[serde(default = "default_entities_per_second")]
926 pub entities_per_second: f64,
927 #[serde(default = "default_burst_size")]
929 pub burst_size: u32,
930 #[serde(default)]
932 pub backpressure: RateLimitBackpressureSchema,
933}
934
935fn default_entities_per_second() -> f64 {
936 1000.0
937}
938
939fn default_burst_size() -> u32 {
940 100
941}
942
943impl Default for RateLimitSchemaConfig {
944 fn default() -> Self {
945 Self {
946 enabled: false,
947 entities_per_second: 1000.0,
948 burst_size: 100,
949 backpressure: RateLimitBackpressureSchema::Block,
950 }
951 }
952}
953
954#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
956#[serde(rename_all = "snake_case")]
957pub enum RateLimitBackpressureSchema {
958 #[default]
960 Block,
961 Drop,
963 Buffer,
965}
966
967#[derive(Debug, Clone, Serialize, Deserialize)]
973pub struct TemporalAttributeSchemaConfig {
974 #[serde(default)]
976 pub enabled: bool,
977 #[serde(default)]
979 pub valid_time: ValidTimeSchemaConfig,
980 #[serde(default)]
982 pub transaction_time: TransactionTimeSchemaConfig,
983 #[serde(default)]
985 pub generate_version_chains: bool,
986 #[serde(default = "default_avg_versions")]
988 pub avg_versions_per_entity: f64,
989}
990
991fn default_avg_versions() -> f64 {
992 1.5
993}
994
995impl Default for TemporalAttributeSchemaConfig {
996 fn default() -> Self {
997 Self {
998 enabled: false,
999 valid_time: ValidTimeSchemaConfig::default(),
1000 transaction_time: TransactionTimeSchemaConfig::default(),
1001 generate_version_chains: false,
1002 avg_versions_per_entity: 1.5,
1003 }
1004 }
1005}
1006
1007#[derive(Debug, Clone, Serialize, Deserialize)]
1009pub struct ValidTimeSchemaConfig {
1010 #[serde(default = "default_closed_probability")]
1012 pub closed_probability: f64,
1013 #[serde(default = "default_avg_validity_days")]
1015 pub avg_validity_days: u32,
1016 #[serde(default = "default_validity_stddev")]
1018 pub validity_stddev_days: u32,
1019}
1020
1021fn default_closed_probability() -> f64 {
1022 0.1
1023}
1024
1025fn default_avg_validity_days() -> u32 {
1026 365
1027}
1028
1029fn default_validity_stddev() -> u32 {
1030 90
1031}
1032
1033impl Default for ValidTimeSchemaConfig {
1034 fn default() -> Self {
1035 Self {
1036 closed_probability: 0.1,
1037 avg_validity_days: 365,
1038 validity_stddev_days: 90,
1039 }
1040 }
1041}
1042
1043#[derive(Debug, Clone, Serialize, Deserialize)]
1045pub struct TransactionTimeSchemaConfig {
1046 #[serde(default)]
1048 pub avg_recording_delay_seconds: u32,
1049 #[serde(default)]
1051 pub allow_backdating: bool,
1052 #[serde(default = "default_backdating_probability")]
1054 pub backdating_probability: f64,
1055 #[serde(default = "default_max_backdate_days")]
1057 pub max_backdate_days: u32,
1058}
1059
1060fn default_backdating_probability() -> f64 {
1061 0.01
1062}
1063
1064fn default_max_backdate_days() -> u32 {
1065 30
1066}
1067
1068impl Default for TransactionTimeSchemaConfig {
1069 fn default() -> Self {
1070 Self {
1071 avg_recording_delay_seconds: 0,
1072 allow_backdating: false,
1073 backdating_probability: 0.01,
1074 max_backdate_days: 30,
1075 }
1076 }
1077}
1078
1079#[derive(Debug, Clone, Serialize, Deserialize)]
1085pub struct RelationshipSchemaConfig {
1086 #[serde(default)]
1088 pub relationship_types: Vec<RelationshipTypeSchemaConfig>,
1089 #[serde(default = "default_true")]
1091 pub allow_orphans: bool,
1092 #[serde(default = "default_orphan_probability")]
1094 pub orphan_probability: f64,
1095 #[serde(default)]
1097 pub allow_circular: bool,
1098 #[serde(default = "default_max_circular_depth")]
1100 pub max_circular_depth: u32,
1101}
1102
1103fn default_orphan_probability() -> f64 {
1104 0.01
1105}
1106
1107fn default_max_circular_depth() -> u32 {
1108 3
1109}
1110
1111impl Default for RelationshipSchemaConfig {
1112 fn default() -> Self {
1113 Self {
1114 relationship_types: Vec::new(),
1115 allow_orphans: true,
1116 orphan_probability: 0.01,
1117 allow_circular: false,
1118 max_circular_depth: 3,
1119 }
1120 }
1121}
1122
1123#[derive(Debug, Clone, Serialize, Deserialize)]
1125pub struct RelationshipTypeSchemaConfig {
1126 pub name: String,
1128 pub source_type: String,
1130 pub target_type: String,
1132 #[serde(default)]
1134 pub cardinality: CardinalitySchemaRule,
1135 #[serde(default = "default_relationship_weight")]
1137 pub weight: f64,
1138 #[serde(default)]
1140 pub required: bool,
1141 #[serde(default = "default_true")]
1143 pub directed: bool,
1144}
1145
1146fn default_relationship_weight() -> f64 {
1147 1.0
1148}
1149
1150impl Default for RelationshipTypeSchemaConfig {
1151 fn default() -> Self {
1152 Self {
1153 name: String::new(),
1154 source_type: String::new(),
1155 target_type: String::new(),
1156 cardinality: CardinalitySchemaRule::default(),
1157 weight: 1.0,
1158 required: false,
1159 directed: true,
1160 }
1161 }
1162}
1163
1164#[derive(Debug, Clone, Serialize, Deserialize)]
1166#[serde(rename_all = "snake_case")]
1167pub enum CardinalitySchemaRule {
1168 OneToOne,
1170 OneToMany {
1172 min: u32,
1174 max: u32,
1176 },
1177 ManyToOne {
1179 min: u32,
1181 max: u32,
1183 },
1184 ManyToMany {
1186 min_per_source: u32,
1188 max_per_source: u32,
1190 },
1191}
1192
1193impl Default for CardinalitySchemaRule {
1194 fn default() -> Self {
1195 Self::OneToMany { min: 1, max: 5 }
1196 }
1197}
1198
1199#[derive(Debug, Clone, Serialize, Deserialize)]
1201pub struct GlobalConfig {
1202 pub seed: Option<u64>,
1204 pub industry: IndustrySector,
1206 pub start_date: String,
1208 pub period_months: u32,
1210 #[serde(default = "default_currency")]
1212 pub group_currency: String,
1213 #[serde(default)]
1216 pub presentation_currency: Option<String>,
1217 #[serde(default = "default_true")]
1219 pub parallel: bool,
1220 #[serde(default)]
1222 pub worker_threads: usize,
1223 #[serde(default)]
1225 pub memory_limit_mb: usize,
1226 #[serde(default)]
1229 pub fiscal_year_months: Option<u32>,
1230}
1231
1232fn default_currency() -> String {
1233 "USD".to_string()
1234}
1235fn default_true() -> bool {
1236 true
1237}
1238
1239#[derive(Debug, Clone, Serialize, Deserialize)]
1244pub struct SessionSchemaConfig {
1245 #[serde(default)]
1247 pub enabled: bool,
1248 #[serde(default)]
1250 pub checkpoint_path: Option<String>,
1251 #[serde(default = "default_true")]
1253 pub per_period_output: bool,
1254 #[serde(default = "default_true")]
1256 pub consolidated_output: bool,
1257}
1258
1259impl Default for SessionSchemaConfig {
1260 fn default() -> Self {
1261 Self {
1262 enabled: false,
1263 checkpoint_path: None,
1264 per_period_output: true,
1265 consolidated_output: true,
1266 }
1267 }
1268}
1269
1270#[derive(Debug, Clone, Serialize, Deserialize)]
1272pub struct CompanyConfig {
1273 pub code: String,
1275 pub name: String,
1277 pub currency: String,
1279 #[serde(default)]
1282 pub functional_currency: Option<String>,
1283 pub country: String,
1285 #[serde(default = "default_fiscal_variant")]
1287 pub fiscal_year_variant: String,
1288 pub annual_transaction_volume: TransactionVolume,
1290 #[serde(default = "default_weight")]
1292 pub volume_weight: f64,
1293}
1294
1295fn default_fiscal_variant() -> String {
1296 "K4".to_string()
1297}
1298fn default_weight() -> f64 {
1299 1.0
1300}
1301
1302#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1304#[serde(rename_all = "snake_case")]
1305pub enum TransactionVolume {
1306 TenK,
1308 HundredK,
1310 OneM,
1312 TenM,
1314 HundredM,
1316 Custom(u64),
1318}
1319
1320impl TransactionVolume {
1321 pub fn count(&self) -> u64 {
1323 match self {
1324 Self::TenK => 10_000,
1325 Self::HundredK => 100_000,
1326 Self::OneM => 1_000_000,
1327 Self::TenM => 10_000_000,
1328 Self::HundredM => 100_000_000,
1329 Self::Custom(n) => *n,
1330 }
1331 }
1332}
1333
1334#[derive(Debug, Clone, Serialize, Deserialize)]
1336pub struct ChartOfAccountsConfig {
1337 pub complexity: CoAComplexity,
1339 #[serde(default = "default_true")]
1341 pub industry_specific: bool,
1342 pub custom_accounts: Option<PathBuf>,
1344 #[serde(default = "default_min_depth")]
1346 pub min_hierarchy_depth: u8,
1347 #[serde(default = "default_max_depth")]
1349 pub max_hierarchy_depth: u8,
1350}
1351
1352fn default_min_depth() -> u8 {
1353 2
1354}
1355fn default_max_depth() -> u8 {
1356 5
1357}
1358
1359impl Default for ChartOfAccountsConfig {
1360 fn default() -> Self {
1361 Self {
1362 complexity: CoAComplexity::Small,
1363 industry_specific: true,
1364 custom_accounts: None,
1365 min_hierarchy_depth: default_min_depth(),
1366 max_hierarchy_depth: default_max_depth(),
1367 }
1368 }
1369}
1370
1371#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1373pub struct TransactionConfig {
1374 #[serde(default)]
1376 pub line_item_distribution: LineItemDistributionConfig,
1377 #[serde(default)]
1379 pub debit_credit_distribution: DebitCreditDistributionConfig,
1380 #[serde(default)]
1382 pub even_odd_distribution: EvenOddDistributionConfig,
1383 #[serde(default)]
1385 pub source_distribution: SourceDistribution,
1386 #[serde(default)]
1388 pub seasonality: SeasonalityConfig,
1389 #[serde(default)]
1391 pub amounts: AmountDistributionConfig,
1392 #[serde(default)]
1394 pub benford: BenfordConfig,
1395}
1396
1397#[derive(Debug, Clone, Serialize, Deserialize)]
1399pub struct BenfordConfig {
1400 #[serde(default = "default_true")]
1402 pub enabled: bool,
1403 #[serde(default = "default_benford_tolerance")]
1405 pub tolerance: f64,
1406 #[serde(default)]
1408 pub exempt_sources: Vec<BenfordExemption>,
1409}
1410
1411fn default_benford_tolerance() -> f64 {
1412 0.05
1413}
1414
1415impl Default for BenfordConfig {
1416 fn default() -> Self {
1417 Self {
1418 enabled: true,
1419 tolerance: default_benford_tolerance(),
1420 exempt_sources: vec![BenfordExemption::Recurring, BenfordExemption::Payroll],
1421 }
1422 }
1423}
1424
1425#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1427#[serde(rename_all = "snake_case")]
1428pub enum BenfordExemption {
1429 Recurring,
1431 Payroll,
1433 FixedFees,
1435 RoundAmounts,
1437}
1438
1439#[derive(Debug, Clone, Serialize, Deserialize)]
1441pub struct SourceDistribution {
1442 pub manual: f64,
1444 pub automated: f64,
1446 pub recurring: f64,
1448 pub adjustment: f64,
1450}
1451
1452impl Default for SourceDistribution {
1453 fn default() -> Self {
1454 Self {
1455 manual: 0.20,
1456 automated: 0.70,
1457 recurring: 0.07,
1458 adjustment: 0.03,
1459 }
1460 }
1461}
1462
1463#[derive(Debug, Clone, Serialize, Deserialize)]
1465pub struct OutputConfig {
1466 #[serde(default)]
1468 pub mode: OutputMode,
1469 pub output_directory: PathBuf,
1471 #[serde(default = "default_formats")]
1473 pub formats: Vec<FileFormat>,
1474 #[serde(default)]
1476 pub compression: CompressionConfig,
1477 #[serde(default = "default_batch_size")]
1479 pub batch_size: usize,
1480 #[serde(default = "default_true")]
1482 pub include_acdoca: bool,
1483 #[serde(default)]
1485 pub include_bseg: bool,
1486 #[serde(default = "default_true")]
1488 pub partition_by_period: bool,
1489 #[serde(default)]
1491 pub partition_by_company: bool,
1492 #[serde(default)]
1496 pub numeric_mode: NumericMode,
1497 #[serde(default)]
1501 pub export_layout: ExportLayout,
1502}
1503
1504fn default_formats() -> Vec<FileFormat> {
1505 vec![FileFormat::Parquet]
1506}
1507fn default_batch_size() -> usize {
1508 100_000
1509}
1510
1511impl Default for OutputConfig {
1512 fn default() -> Self {
1513 Self {
1514 mode: OutputMode::FlatFile,
1515 output_directory: PathBuf::from("./output"),
1516 formats: default_formats(),
1517 compression: CompressionConfig::default(),
1518 batch_size: default_batch_size(),
1519 include_acdoca: true,
1520 include_bseg: false,
1521 partition_by_period: true,
1522 partition_by_company: false,
1523 numeric_mode: NumericMode::default(),
1524 export_layout: ExportLayout::default(),
1525 }
1526 }
1527}
1528
1529#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
1531#[serde(rename_all = "snake_case")]
1532pub enum NumericMode {
1533 #[default]
1535 String,
1536 Native,
1538}
1539
1540#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
1542#[serde(rename_all = "snake_case")]
1543pub enum ExportLayout {
1544 #[default]
1546 Nested,
1547 Flat,
1549}
1550
1551#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
1553#[serde(rename_all = "snake_case")]
1554pub enum OutputMode {
1555 Streaming,
1557 #[default]
1559 FlatFile,
1560 Both,
1562}
1563
1564#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1566#[serde(rename_all = "snake_case")]
1567pub enum FileFormat {
1568 Csv,
1569 Parquet,
1570 Json,
1571 JsonLines,
1572}
1573
1574#[derive(Debug, Clone, Serialize, Deserialize)]
1576pub struct CompressionConfig {
1577 #[serde(default = "default_true")]
1579 pub enabled: bool,
1580 #[serde(default)]
1582 pub algorithm: CompressionAlgorithm,
1583 #[serde(default = "default_compression_level")]
1585 pub level: u8,
1586}
1587
1588fn default_compression_level() -> u8 {
1589 3
1590}
1591
1592impl Default for CompressionConfig {
1593 fn default() -> Self {
1594 Self {
1595 enabled: true,
1596 algorithm: CompressionAlgorithm::default(),
1597 level: default_compression_level(),
1598 }
1599 }
1600}
1601
1602#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
1604#[serde(rename_all = "snake_case")]
1605pub enum CompressionAlgorithm {
1606 Gzip,
1607 #[default]
1608 Zstd,
1609 Lz4,
1610 Snappy,
1611}
1612
1613#[derive(Debug, Clone, Serialize, Deserialize)]
1615pub struct FraudConfig {
1616 #[serde(default)]
1618 pub enabled: bool,
1619 #[serde(default = "default_fraud_rate")]
1621 pub fraud_rate: f64,
1622 #[serde(default)]
1624 pub fraud_type_distribution: FraudTypeDistribution,
1625 #[serde(default)]
1627 pub clustering_enabled: bool,
1628 #[serde(default = "default_clustering_factor")]
1630 pub clustering_factor: f64,
1631 #[serde(default = "default_approval_thresholds")]
1633 pub approval_thresholds: Vec<f64>,
1634}
1635
1636fn default_approval_thresholds() -> Vec<f64> {
1637 vec![1000.0, 5000.0, 10000.0, 25000.0, 50000.0, 100000.0]
1638}
1639
1640fn default_fraud_rate() -> f64 {
1641 0.005
1642}
1643fn default_clustering_factor() -> f64 {
1644 3.0
1645}
1646
1647impl Default for FraudConfig {
1648 fn default() -> Self {
1649 Self {
1650 enabled: false,
1651 fraud_rate: default_fraud_rate(),
1652 fraud_type_distribution: FraudTypeDistribution::default(),
1653 clustering_enabled: false,
1654 clustering_factor: default_clustering_factor(),
1655 approval_thresholds: default_approval_thresholds(),
1656 }
1657 }
1658}
1659
1660#[derive(Debug, Clone, Serialize, Deserialize)]
1662pub struct FraudTypeDistribution {
1663 pub suspense_account_abuse: f64,
1664 pub fictitious_transaction: f64,
1665 pub revenue_manipulation: f64,
1666 pub expense_capitalization: f64,
1667 pub split_transaction: f64,
1668 pub timing_anomaly: f64,
1669 pub unauthorized_access: f64,
1670 pub duplicate_payment: f64,
1671}
1672
1673impl Default for FraudTypeDistribution {
1674 fn default() -> Self {
1675 Self {
1676 suspense_account_abuse: 0.25,
1677 fictitious_transaction: 0.15,
1678 revenue_manipulation: 0.10,
1679 expense_capitalization: 0.10,
1680 split_transaction: 0.15,
1681 timing_anomaly: 0.10,
1682 unauthorized_access: 0.10,
1683 duplicate_payment: 0.05,
1684 }
1685 }
1686}
1687
1688#[derive(Debug, Clone, Serialize, Deserialize)]
1690pub struct InternalControlsConfig {
1691 #[serde(default)]
1693 pub enabled: bool,
1694 #[serde(default = "default_exception_rate")]
1696 pub exception_rate: f64,
1697 #[serde(default = "default_sod_violation_rate")]
1699 pub sod_violation_rate: f64,
1700 #[serde(default = "default_true")]
1702 pub export_control_master_data: bool,
1703 #[serde(default = "default_sox_materiality_threshold")]
1705 pub sox_materiality_threshold: f64,
1706 #[serde(default = "default_true")]
1708 pub coso_enabled: bool,
1709 #[serde(default)]
1711 pub include_entity_level_controls: bool,
1712 #[serde(default = "default_target_maturity_level")]
1715 pub target_maturity_level: String,
1716}
1717
1718fn default_exception_rate() -> f64 {
1719 0.02
1720}
1721
1722fn default_sod_violation_rate() -> f64 {
1723 0.01
1724}
1725
1726fn default_sox_materiality_threshold() -> f64 {
1727 10000.0
1728}
1729
1730fn default_target_maturity_level() -> String {
1731 "mixed".to_string()
1732}
1733
1734impl Default for InternalControlsConfig {
1735 fn default() -> Self {
1736 Self {
1737 enabled: false,
1738 exception_rate: default_exception_rate(),
1739 sod_violation_rate: default_sod_violation_rate(),
1740 export_control_master_data: true,
1741 sox_materiality_threshold: default_sox_materiality_threshold(),
1742 coso_enabled: true,
1743 include_entity_level_controls: false,
1744 target_maturity_level: default_target_maturity_level(),
1745 }
1746 }
1747}
1748
1749#[derive(Debug, Clone, Serialize, Deserialize)]
1751pub struct BusinessProcessConfig {
1752 #[serde(default = "default_o2c")]
1754 pub o2c_weight: f64,
1755 #[serde(default = "default_p2p")]
1757 pub p2p_weight: f64,
1758 #[serde(default = "default_r2r")]
1760 pub r2r_weight: f64,
1761 #[serde(default = "default_h2r")]
1763 pub h2r_weight: f64,
1764 #[serde(default = "default_a2r")]
1766 pub a2r_weight: f64,
1767}
1768
1769fn default_o2c() -> f64 {
1770 0.35
1771}
1772fn default_p2p() -> f64 {
1773 0.30
1774}
1775fn default_r2r() -> f64 {
1776 0.20
1777}
1778fn default_h2r() -> f64 {
1779 0.10
1780}
1781fn default_a2r() -> f64 {
1782 0.05
1783}
1784
1785impl Default for BusinessProcessConfig {
1786 fn default() -> Self {
1787 Self {
1788 o2c_weight: default_o2c(),
1789 p2p_weight: default_p2p(),
1790 r2r_weight: default_r2r(),
1791 h2r_weight: default_h2r(),
1792 a2r_weight: default_a2r(),
1793 }
1794 }
1795}
1796
1797#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1799pub struct UserPersonaConfig {
1800 #[serde(default)]
1802 pub persona_distribution: PersonaDistribution,
1803 #[serde(default)]
1805 pub users_per_persona: UsersPerPersona,
1806}
1807
1808#[derive(Debug, Clone, Serialize, Deserialize)]
1810pub struct PersonaDistribution {
1811 pub junior_accountant: f64,
1812 pub senior_accountant: f64,
1813 pub controller: f64,
1814 pub manager: f64,
1815 pub automated_system: f64,
1816}
1817
1818impl Default for PersonaDistribution {
1819 fn default() -> Self {
1820 Self {
1821 junior_accountant: 0.15,
1822 senior_accountant: 0.15,
1823 controller: 0.05,
1824 manager: 0.05,
1825 automated_system: 0.60,
1826 }
1827 }
1828}
1829
1830#[derive(Debug, Clone, Serialize, Deserialize)]
1832pub struct UsersPerPersona {
1833 pub junior_accountant: usize,
1834 pub senior_accountant: usize,
1835 pub controller: usize,
1836 pub manager: usize,
1837 pub automated_system: usize,
1838}
1839
1840impl Default for UsersPerPersona {
1841 fn default() -> Self {
1842 Self {
1843 junior_accountant: 10,
1844 senior_accountant: 5,
1845 controller: 2,
1846 manager: 3,
1847 automated_system: 20,
1848 }
1849 }
1850}
1851
1852#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1854pub struct TemplateConfig {
1855 #[serde(default)]
1857 pub names: NameTemplateConfig,
1858 #[serde(default)]
1860 pub descriptions: DescriptionTemplateConfig,
1861 #[serde(default)]
1863 pub references: ReferenceTemplateConfig,
1864}
1865
1866#[derive(Debug, Clone, Serialize, Deserialize)]
1868pub struct NameTemplateConfig {
1869 #[serde(default)]
1871 pub culture_distribution: CultureDistribution,
1872 #[serde(default = "default_email_domain")]
1874 pub email_domain: String,
1875 #[serde(default = "default_true")]
1877 pub generate_realistic_names: bool,
1878}
1879
1880fn default_email_domain() -> String {
1881 "company.com".to_string()
1882}
1883
1884impl Default for NameTemplateConfig {
1885 fn default() -> Self {
1886 Self {
1887 culture_distribution: CultureDistribution::default(),
1888 email_domain: default_email_domain(),
1889 generate_realistic_names: true,
1890 }
1891 }
1892}
1893
1894#[derive(Debug, Clone, Serialize, Deserialize)]
1896pub struct CultureDistribution {
1897 pub western_us: f64,
1898 pub hispanic: f64,
1899 pub german: f64,
1900 pub french: f64,
1901 pub chinese: f64,
1902 pub japanese: f64,
1903 pub indian: f64,
1904}
1905
1906impl Default for CultureDistribution {
1907 fn default() -> Self {
1908 Self {
1909 western_us: 0.40,
1910 hispanic: 0.20,
1911 german: 0.10,
1912 french: 0.05,
1913 chinese: 0.10,
1914 japanese: 0.05,
1915 indian: 0.10,
1916 }
1917 }
1918}
1919
1920#[derive(Debug, Clone, Serialize, Deserialize)]
1922pub struct DescriptionTemplateConfig {
1923 #[serde(default = "default_true")]
1925 pub generate_header_text: bool,
1926 #[serde(default = "default_true")]
1928 pub generate_line_text: bool,
1929}
1930
1931impl Default for DescriptionTemplateConfig {
1932 fn default() -> Self {
1933 Self {
1934 generate_header_text: true,
1935 generate_line_text: true,
1936 }
1937 }
1938}
1939
1940#[derive(Debug, Clone, Serialize, Deserialize)]
1942pub struct ReferenceTemplateConfig {
1943 #[serde(default = "default_true")]
1945 pub generate_references: bool,
1946 #[serde(default = "default_invoice_prefix")]
1948 pub invoice_prefix: String,
1949 #[serde(default = "default_po_prefix")]
1951 pub po_prefix: String,
1952 #[serde(default = "default_so_prefix")]
1954 pub so_prefix: String,
1955}
1956
1957fn default_invoice_prefix() -> String {
1958 "INV".to_string()
1959}
1960fn default_po_prefix() -> String {
1961 "PO".to_string()
1962}
1963fn default_so_prefix() -> String {
1964 "SO".to_string()
1965}
1966
1967impl Default for ReferenceTemplateConfig {
1968 fn default() -> Self {
1969 Self {
1970 generate_references: true,
1971 invoice_prefix: default_invoice_prefix(),
1972 po_prefix: default_po_prefix(),
1973 so_prefix: default_so_prefix(),
1974 }
1975 }
1976}
1977
1978#[derive(Debug, Clone, Serialize, Deserialize)]
1980pub struct ApprovalConfig {
1981 #[serde(default)]
1983 pub enabled: bool,
1984 #[serde(default = "default_auto_approve_threshold")]
1986 pub auto_approve_threshold: f64,
1987 #[serde(default = "default_rejection_rate")]
1989 pub rejection_rate: f64,
1990 #[serde(default = "default_revision_rate")]
1992 pub revision_rate: f64,
1993 #[serde(default = "default_approval_delay_hours")]
1995 pub average_approval_delay_hours: f64,
1996 #[serde(default)]
1998 pub thresholds: Vec<ApprovalThresholdConfig>,
1999}
2000
2001fn default_auto_approve_threshold() -> f64 {
2002 1000.0
2003}
2004fn default_rejection_rate() -> f64 {
2005 0.02
2006}
2007fn default_revision_rate() -> f64 {
2008 0.05
2009}
2010fn default_approval_delay_hours() -> f64 {
2011 4.0
2012}
2013
2014impl Default for ApprovalConfig {
2015 fn default() -> Self {
2016 Self {
2017 enabled: false,
2018 auto_approve_threshold: default_auto_approve_threshold(),
2019 rejection_rate: default_rejection_rate(),
2020 revision_rate: default_revision_rate(),
2021 average_approval_delay_hours: default_approval_delay_hours(),
2022 thresholds: vec![
2023 ApprovalThresholdConfig {
2024 amount: 1000.0,
2025 level: 1,
2026 roles: vec!["senior_accountant".to_string()],
2027 },
2028 ApprovalThresholdConfig {
2029 amount: 10000.0,
2030 level: 2,
2031 roles: vec!["senior_accountant".to_string(), "controller".to_string()],
2032 },
2033 ApprovalThresholdConfig {
2034 amount: 100000.0,
2035 level: 3,
2036 roles: vec![
2037 "senior_accountant".to_string(),
2038 "controller".to_string(),
2039 "manager".to_string(),
2040 ],
2041 },
2042 ApprovalThresholdConfig {
2043 amount: 500000.0,
2044 level: 4,
2045 roles: vec![
2046 "senior_accountant".to_string(),
2047 "controller".to_string(),
2048 "manager".to_string(),
2049 "executive".to_string(),
2050 ],
2051 },
2052 ],
2053 }
2054 }
2055}
2056
2057#[derive(Debug, Clone, Serialize, Deserialize)]
2059pub struct ApprovalThresholdConfig {
2060 pub amount: f64,
2062 pub level: u8,
2064 pub roles: Vec<String>,
2066}
2067
2068#[derive(Debug, Clone, Serialize, Deserialize)]
2070pub struct DepartmentConfig {
2071 #[serde(default)]
2073 pub enabled: bool,
2074 #[serde(default = "default_headcount_multiplier")]
2076 pub headcount_multiplier: f64,
2077 #[serde(default)]
2079 pub custom_departments: Vec<CustomDepartmentConfig>,
2080}
2081
2082fn default_headcount_multiplier() -> f64 {
2083 1.0
2084}
2085
2086impl Default for DepartmentConfig {
2087 fn default() -> Self {
2088 Self {
2089 enabled: false,
2090 headcount_multiplier: default_headcount_multiplier(),
2091 custom_departments: Vec::new(),
2092 }
2093 }
2094}
2095
2096#[derive(Debug, Clone, Serialize, Deserialize)]
2098pub struct CustomDepartmentConfig {
2099 pub code: String,
2101 pub name: String,
2103 #[serde(default)]
2105 pub cost_center: Option<String>,
2106 #[serde(default)]
2108 pub primary_processes: Vec<String>,
2109 #[serde(default)]
2111 pub parent_code: Option<String>,
2112}
2113
2114#[derive(Debug, Clone, Default, Serialize, Deserialize)]
2120pub struct MasterDataConfig {
2121 #[serde(default)]
2123 pub vendors: VendorMasterConfig,
2124 #[serde(default)]
2126 pub customers: CustomerMasterConfig,
2127 #[serde(default)]
2129 pub materials: MaterialMasterConfig,
2130 #[serde(default)]
2132 pub fixed_assets: FixedAssetMasterConfig,
2133 #[serde(default)]
2135 pub employees: EmployeeMasterConfig,
2136 #[serde(default)]
2138 pub cost_centers: CostCenterMasterConfig,
2139}
2140
2141#[derive(Debug, Clone, Serialize, Deserialize)]
2143pub struct VendorMasterConfig {
2144 #[serde(default = "default_vendor_count")]
2146 pub count: usize,
2147 #[serde(default = "default_intercompany_percent")]
2149 pub intercompany_percent: f64,
2150 #[serde(default)]
2152 pub payment_terms_distribution: PaymentTermsDistribution,
2153 #[serde(default)]
2155 pub behavior_distribution: VendorBehaviorDistribution,
2156 #[serde(default = "default_true")]
2158 pub generate_bank_accounts: bool,
2159 #[serde(default = "default_true")]
2161 pub generate_tax_ids: bool,
2162}
2163
2164fn default_vendor_count() -> usize {
2165 500
2166}
2167
2168fn default_intercompany_percent() -> f64 {
2169 0.05
2170}
2171
2172impl Default for VendorMasterConfig {
2173 fn default() -> Self {
2174 Self {
2175 count: default_vendor_count(),
2176 intercompany_percent: default_intercompany_percent(),
2177 payment_terms_distribution: PaymentTermsDistribution::default(),
2178 behavior_distribution: VendorBehaviorDistribution::default(),
2179 generate_bank_accounts: true,
2180 generate_tax_ids: true,
2181 }
2182 }
2183}
2184
2185#[derive(Debug, Clone, Serialize, Deserialize)]
2187pub struct PaymentTermsDistribution {
2188 pub net_30: f64,
2190 pub net_60: f64,
2192 pub net_90: f64,
2194 pub two_ten_net_30: f64,
2196 pub due_on_receipt: f64,
2198 pub end_of_month: f64,
2200}
2201
2202impl Default for PaymentTermsDistribution {
2203 fn default() -> Self {
2204 Self {
2205 net_30: 0.40,
2206 net_60: 0.20,
2207 net_90: 0.10,
2208 two_ten_net_30: 0.15,
2209 due_on_receipt: 0.05,
2210 end_of_month: 0.10,
2211 }
2212 }
2213}
2214
2215#[derive(Debug, Clone, Serialize, Deserialize)]
2217pub struct VendorBehaviorDistribution {
2218 pub reliable: f64,
2220 pub sometimes_late: f64,
2222 pub inconsistent_quality: f64,
2224 pub premium: f64,
2226 pub budget: f64,
2228}
2229
2230impl Default for VendorBehaviorDistribution {
2231 fn default() -> Self {
2232 Self {
2233 reliable: 0.50,
2234 sometimes_late: 0.20,
2235 inconsistent_quality: 0.10,
2236 premium: 0.10,
2237 budget: 0.10,
2238 }
2239 }
2240}
2241
2242#[derive(Debug, Clone, Serialize, Deserialize)]
2244pub struct CustomerMasterConfig {
2245 #[serde(default = "default_customer_count")]
2247 pub count: usize,
2248 #[serde(default = "default_intercompany_percent")]
2250 pub intercompany_percent: f64,
2251 #[serde(default)]
2253 pub credit_rating_distribution: CreditRatingDistribution,
2254 #[serde(default)]
2256 pub payment_behavior_distribution: PaymentBehaviorDistribution,
2257 #[serde(default = "default_true")]
2259 pub generate_credit_limits: bool,
2260}
2261
2262fn default_customer_count() -> usize {
2263 2000
2264}
2265
2266impl Default for CustomerMasterConfig {
2267 fn default() -> Self {
2268 Self {
2269 count: default_customer_count(),
2270 intercompany_percent: default_intercompany_percent(),
2271 credit_rating_distribution: CreditRatingDistribution::default(),
2272 payment_behavior_distribution: PaymentBehaviorDistribution::default(),
2273 generate_credit_limits: true,
2274 }
2275 }
2276}
2277
2278#[derive(Debug, Clone, Serialize, Deserialize)]
2280pub struct CreditRatingDistribution {
2281 pub aaa: f64,
2283 pub aa: f64,
2285 pub a: f64,
2287 pub bbb: f64,
2289 pub bb: f64,
2291 pub b: f64,
2293 pub below_b: f64,
2295}
2296
2297impl Default for CreditRatingDistribution {
2298 fn default() -> Self {
2299 Self {
2300 aaa: 0.05,
2301 aa: 0.10,
2302 a: 0.20,
2303 bbb: 0.30,
2304 bb: 0.20,
2305 b: 0.10,
2306 below_b: 0.05,
2307 }
2308 }
2309}
2310
2311#[derive(Debug, Clone, Serialize, Deserialize)]
2313pub struct PaymentBehaviorDistribution {
2314 pub early_payer: f64,
2316 pub on_time: f64,
2318 pub occasional_late: f64,
2320 pub frequent_late: f64,
2322 pub discount_taker: f64,
2324}
2325
2326impl Default for PaymentBehaviorDistribution {
2327 fn default() -> Self {
2328 Self {
2329 early_payer: 0.10,
2330 on_time: 0.50,
2331 occasional_late: 0.25,
2332 frequent_late: 0.10,
2333 discount_taker: 0.05,
2334 }
2335 }
2336}
2337
2338#[derive(Debug, Clone, Serialize, Deserialize)]
2340pub struct MaterialMasterConfig {
2341 #[serde(default = "default_material_count")]
2343 pub count: usize,
2344 #[serde(default)]
2346 pub type_distribution: MaterialTypeDistribution,
2347 #[serde(default)]
2349 pub valuation_distribution: ValuationMethodDistribution,
2350 #[serde(default = "default_bom_percent")]
2352 pub bom_percent: f64,
2353 #[serde(default = "default_max_bom_depth")]
2355 pub max_bom_depth: u8,
2356}
2357
2358fn default_material_count() -> usize {
2359 5000
2360}
2361
2362fn default_bom_percent() -> f64 {
2363 0.20
2364}
2365
2366fn default_max_bom_depth() -> u8 {
2367 3
2368}
2369
2370impl Default for MaterialMasterConfig {
2371 fn default() -> Self {
2372 Self {
2373 count: default_material_count(),
2374 type_distribution: MaterialTypeDistribution::default(),
2375 valuation_distribution: ValuationMethodDistribution::default(),
2376 bom_percent: default_bom_percent(),
2377 max_bom_depth: default_max_bom_depth(),
2378 }
2379 }
2380}
2381
2382#[derive(Debug, Clone, Serialize, Deserialize)]
2384pub struct MaterialTypeDistribution {
2385 pub raw_material: f64,
2387 pub semi_finished: f64,
2389 pub finished_good: f64,
2391 pub trading_good: f64,
2393 pub operating_supply: f64,
2395 pub service: f64,
2397}
2398
2399impl Default for MaterialTypeDistribution {
2400 fn default() -> Self {
2401 Self {
2402 raw_material: 0.30,
2403 semi_finished: 0.15,
2404 finished_good: 0.25,
2405 trading_good: 0.15,
2406 operating_supply: 0.10,
2407 service: 0.05,
2408 }
2409 }
2410}
2411
2412#[derive(Debug, Clone, Serialize, Deserialize)]
2414pub struct ValuationMethodDistribution {
2415 pub standard_cost: f64,
2417 pub moving_average: f64,
2419 pub fifo: f64,
2421 pub lifo: f64,
2423}
2424
2425impl Default for ValuationMethodDistribution {
2426 fn default() -> Self {
2427 Self {
2428 standard_cost: 0.50,
2429 moving_average: 0.30,
2430 fifo: 0.15,
2431 lifo: 0.05,
2432 }
2433 }
2434}
2435
2436#[derive(Debug, Clone, Serialize, Deserialize)]
2438pub struct FixedAssetMasterConfig {
2439 #[serde(default = "default_asset_count")]
2441 pub count: usize,
2442 #[serde(default)]
2444 pub class_distribution: AssetClassDistribution,
2445 #[serde(default)]
2447 pub depreciation_distribution: DepreciationMethodDistribution,
2448 #[serde(default = "default_fully_depreciated_percent")]
2450 pub fully_depreciated_percent: f64,
2451 #[serde(default = "default_true")]
2453 pub generate_acquisition_history: bool,
2454}
2455
2456fn default_asset_count() -> usize {
2457 800
2458}
2459
2460fn default_fully_depreciated_percent() -> f64 {
2461 0.15
2462}
2463
2464impl Default for FixedAssetMasterConfig {
2465 fn default() -> Self {
2466 Self {
2467 count: default_asset_count(),
2468 class_distribution: AssetClassDistribution::default(),
2469 depreciation_distribution: DepreciationMethodDistribution::default(),
2470 fully_depreciated_percent: default_fully_depreciated_percent(),
2471 generate_acquisition_history: true,
2472 }
2473 }
2474}
2475
2476#[derive(Debug, Clone, Serialize, Deserialize)]
2478pub struct AssetClassDistribution {
2479 pub buildings: f64,
2481 pub machinery: f64,
2483 pub vehicles: f64,
2485 pub it_equipment: f64,
2487 pub furniture: f64,
2489 pub land: f64,
2491 pub leasehold: f64,
2493}
2494
2495impl Default for AssetClassDistribution {
2496 fn default() -> Self {
2497 Self {
2498 buildings: 0.15,
2499 machinery: 0.30,
2500 vehicles: 0.15,
2501 it_equipment: 0.20,
2502 furniture: 0.10,
2503 land: 0.05,
2504 leasehold: 0.05,
2505 }
2506 }
2507}
2508
2509#[derive(Debug, Clone, Serialize, Deserialize)]
2511pub struct DepreciationMethodDistribution {
2512 pub straight_line: f64,
2514 pub declining_balance: f64,
2516 pub double_declining: f64,
2518 pub sum_of_years: f64,
2520 pub units_of_production: f64,
2522}
2523
2524impl Default for DepreciationMethodDistribution {
2525 fn default() -> Self {
2526 Self {
2527 straight_line: 0.60,
2528 declining_balance: 0.20,
2529 double_declining: 0.10,
2530 sum_of_years: 0.05,
2531 units_of_production: 0.05,
2532 }
2533 }
2534}
2535
2536#[derive(Debug, Clone, Serialize, Deserialize)]
2538pub struct EmployeeMasterConfig {
2539 #[serde(default = "default_employee_count")]
2541 pub count: usize,
2542 #[serde(default = "default_true")]
2544 pub generate_hierarchy: bool,
2545 #[serde(default = "default_hierarchy_depth")]
2547 pub max_hierarchy_depth: u8,
2548 #[serde(default = "default_span_of_control")]
2550 pub average_span_of_control: f64,
2551 #[serde(default)]
2553 pub approval_limits: ApprovalLimitDistribution,
2554 #[serde(default)]
2556 pub department_distribution: EmployeeDepartmentDistribution,
2557}
2558
2559fn default_employee_count() -> usize {
2560 1500
2561}
2562
2563fn default_hierarchy_depth() -> u8 {
2564 6
2565}
2566
2567fn default_span_of_control() -> f64 {
2568 5.0
2569}
2570
2571impl Default for EmployeeMasterConfig {
2572 fn default() -> Self {
2573 Self {
2574 count: default_employee_count(),
2575 generate_hierarchy: true,
2576 max_hierarchy_depth: default_hierarchy_depth(),
2577 average_span_of_control: default_span_of_control(),
2578 approval_limits: ApprovalLimitDistribution::default(),
2579 department_distribution: EmployeeDepartmentDistribution::default(),
2580 }
2581 }
2582}
2583
2584#[derive(Debug, Clone, Serialize, Deserialize)]
2586pub struct ApprovalLimitDistribution {
2587 #[serde(default = "default_staff_limit")]
2589 pub staff: f64,
2590 #[serde(default = "default_senior_limit")]
2592 pub senior: f64,
2593 #[serde(default = "default_manager_limit")]
2595 pub manager: f64,
2596 #[serde(default = "default_director_limit")]
2598 pub director: f64,
2599 #[serde(default = "default_vp_limit")]
2601 pub vp: f64,
2602 #[serde(default = "default_executive_limit")]
2604 pub executive: f64,
2605}
2606
2607fn default_staff_limit() -> f64 {
2608 1000.0
2609}
2610fn default_senior_limit() -> f64 {
2611 5000.0
2612}
2613fn default_manager_limit() -> f64 {
2614 25000.0
2615}
2616fn default_director_limit() -> f64 {
2617 100000.0
2618}
2619fn default_vp_limit() -> f64 {
2620 500000.0
2621}
2622fn default_executive_limit() -> f64 {
2623 f64::INFINITY
2624}
2625
2626impl Default for ApprovalLimitDistribution {
2627 fn default() -> Self {
2628 Self {
2629 staff: default_staff_limit(),
2630 senior: default_senior_limit(),
2631 manager: default_manager_limit(),
2632 director: default_director_limit(),
2633 vp: default_vp_limit(),
2634 executive: default_executive_limit(),
2635 }
2636 }
2637}
2638
2639#[derive(Debug, Clone, Serialize, Deserialize)]
2641pub struct EmployeeDepartmentDistribution {
2642 pub finance: f64,
2644 pub procurement: f64,
2646 pub sales: f64,
2648 pub warehouse: f64,
2650 pub it: f64,
2652 pub hr: f64,
2654 pub operations: f64,
2656 pub executive: f64,
2658}
2659
2660impl Default for EmployeeDepartmentDistribution {
2661 fn default() -> Self {
2662 Self {
2663 finance: 0.12,
2664 procurement: 0.10,
2665 sales: 0.25,
2666 warehouse: 0.15,
2667 it: 0.10,
2668 hr: 0.05,
2669 operations: 0.20,
2670 executive: 0.03,
2671 }
2672 }
2673}
2674
2675#[derive(Debug, Clone, Serialize, Deserialize)]
2677pub struct CostCenterMasterConfig {
2678 #[serde(default = "default_cost_center_count")]
2680 pub count: usize,
2681 #[serde(default = "default_true")]
2683 pub generate_hierarchy: bool,
2684 #[serde(default = "default_cc_hierarchy_depth")]
2686 pub max_hierarchy_depth: u8,
2687}
2688
2689fn default_cost_center_count() -> usize {
2690 50
2691}
2692
2693fn default_cc_hierarchy_depth() -> u8 {
2694 3
2695}
2696
2697impl Default for CostCenterMasterConfig {
2698 fn default() -> Self {
2699 Self {
2700 count: default_cost_center_count(),
2701 generate_hierarchy: true,
2702 max_hierarchy_depth: default_cc_hierarchy_depth(),
2703 }
2704 }
2705}
2706
2707#[derive(Debug, Clone, Serialize, Deserialize)]
2713pub struct DocumentFlowConfig {
2714 #[serde(default)]
2716 pub p2p: P2PFlowConfig,
2717 #[serde(default)]
2719 pub o2c: O2CFlowConfig,
2720 #[serde(default = "default_true")]
2722 pub generate_document_references: bool,
2723 #[serde(default)]
2725 pub export_flow_graph: bool,
2726}
2727
2728impl Default for DocumentFlowConfig {
2729 fn default() -> Self {
2730 Self {
2731 p2p: P2PFlowConfig::default(),
2732 o2c: O2CFlowConfig::default(),
2733 generate_document_references: true,
2734 export_flow_graph: false,
2735 }
2736 }
2737}
2738
2739#[derive(Debug, Clone, Serialize, Deserialize)]
2741pub struct P2PFlowConfig {
2742 #[serde(default = "default_true")]
2744 pub enabled: bool,
2745 #[serde(default = "default_three_way_match_rate")]
2747 pub three_way_match_rate: f64,
2748 #[serde(default = "default_partial_delivery_rate")]
2750 pub partial_delivery_rate: f64,
2751 #[serde(default = "default_price_variance_rate")]
2753 pub price_variance_rate: f64,
2754 #[serde(default = "default_max_price_variance")]
2756 pub max_price_variance_percent: f64,
2757 #[serde(default = "default_quantity_variance_rate")]
2759 pub quantity_variance_rate: f64,
2760 #[serde(default = "default_po_to_gr_days")]
2762 pub average_po_to_gr_days: u32,
2763 #[serde(default = "default_gr_to_invoice_days")]
2765 pub average_gr_to_invoice_days: u32,
2766 #[serde(default = "default_invoice_to_payment_days")]
2768 pub average_invoice_to_payment_days: u32,
2769 #[serde(default)]
2771 pub line_count_distribution: DocumentLineCountDistribution,
2772 #[serde(default)]
2774 pub payment_behavior: P2PPaymentBehaviorConfig,
2775 #[serde(default)]
2777 pub over_delivery_rate: Option<f64>,
2778 #[serde(default)]
2780 pub early_payment_discount_rate: Option<f64>,
2781}
2782
2783fn default_three_way_match_rate() -> f64 {
2784 0.95
2785}
2786
2787fn default_partial_delivery_rate() -> f64 {
2788 0.15
2789}
2790
2791fn default_price_variance_rate() -> f64 {
2792 0.08
2793}
2794
2795fn default_max_price_variance() -> f64 {
2796 0.05
2797}
2798
2799fn default_quantity_variance_rate() -> f64 {
2800 0.05
2801}
2802
2803fn default_po_to_gr_days() -> u32 {
2804 14
2805}
2806
2807fn default_gr_to_invoice_days() -> u32 {
2808 5
2809}
2810
2811fn default_invoice_to_payment_days() -> u32 {
2812 30
2813}
2814
2815impl Default for P2PFlowConfig {
2816 fn default() -> Self {
2817 Self {
2818 enabled: true,
2819 three_way_match_rate: default_three_way_match_rate(),
2820 partial_delivery_rate: default_partial_delivery_rate(),
2821 price_variance_rate: default_price_variance_rate(),
2822 max_price_variance_percent: default_max_price_variance(),
2823 quantity_variance_rate: default_quantity_variance_rate(),
2824 average_po_to_gr_days: default_po_to_gr_days(),
2825 average_gr_to_invoice_days: default_gr_to_invoice_days(),
2826 average_invoice_to_payment_days: default_invoice_to_payment_days(),
2827 line_count_distribution: DocumentLineCountDistribution::default(),
2828 payment_behavior: P2PPaymentBehaviorConfig::default(),
2829 over_delivery_rate: None,
2830 early_payment_discount_rate: None,
2831 }
2832 }
2833}
2834
2835#[derive(Debug, Clone, Serialize, Deserialize)]
2841pub struct P2PPaymentBehaviorConfig {
2842 #[serde(default = "default_p2p_late_payment_rate")]
2844 pub late_payment_rate: f64,
2845 #[serde(default)]
2847 pub late_payment_days_distribution: LatePaymentDaysDistribution,
2848 #[serde(default = "default_p2p_partial_payment_rate")]
2850 pub partial_payment_rate: f64,
2851 #[serde(default = "default_p2p_payment_correction_rate")]
2853 pub payment_correction_rate: f64,
2854 #[serde(default = "default_p2p_avg_days_until_remainder")]
2856 pub avg_days_until_remainder: u32,
2857}
2858
2859fn default_p2p_late_payment_rate() -> f64 {
2860 0.15
2861}
2862
2863fn default_p2p_partial_payment_rate() -> f64 {
2864 0.05
2865}
2866
2867fn default_p2p_payment_correction_rate() -> f64 {
2868 0.02
2869}
2870
2871fn default_p2p_avg_days_until_remainder() -> u32 {
2872 30
2873}
2874
2875impl Default for P2PPaymentBehaviorConfig {
2876 fn default() -> Self {
2877 Self {
2878 late_payment_rate: default_p2p_late_payment_rate(),
2879 late_payment_days_distribution: LatePaymentDaysDistribution::default(),
2880 partial_payment_rate: default_p2p_partial_payment_rate(),
2881 payment_correction_rate: default_p2p_payment_correction_rate(),
2882 avg_days_until_remainder: default_p2p_avg_days_until_remainder(),
2883 }
2884 }
2885}
2886
2887#[derive(Debug, Clone, Serialize, Deserialize)]
2889pub struct LatePaymentDaysDistribution {
2890 #[serde(default = "default_slightly_late")]
2892 pub slightly_late_1_to_7: f64,
2893 #[serde(default = "default_late_8_14")]
2895 pub late_8_to_14: f64,
2896 #[serde(default = "default_very_late")]
2898 pub very_late_15_to_30: f64,
2899 #[serde(default = "default_severely_late")]
2901 pub severely_late_31_to_60: f64,
2902 #[serde(default = "default_extremely_late")]
2904 pub extremely_late_over_60: f64,
2905}
2906
2907fn default_slightly_late() -> f64 {
2908 0.50
2909}
2910
2911fn default_late_8_14() -> f64 {
2912 0.25
2913}
2914
2915fn default_very_late() -> f64 {
2916 0.15
2917}
2918
2919fn default_severely_late() -> f64 {
2920 0.07
2921}
2922
2923fn default_extremely_late() -> f64 {
2924 0.03
2925}
2926
2927impl Default for LatePaymentDaysDistribution {
2928 fn default() -> Self {
2929 Self {
2930 slightly_late_1_to_7: default_slightly_late(),
2931 late_8_to_14: default_late_8_14(),
2932 very_late_15_to_30: default_very_late(),
2933 severely_late_31_to_60: default_severely_late(),
2934 extremely_late_over_60: default_extremely_late(),
2935 }
2936 }
2937}
2938
2939#[derive(Debug, Clone, Serialize, Deserialize)]
2941pub struct O2CFlowConfig {
2942 #[serde(default = "default_true")]
2944 pub enabled: bool,
2945 #[serde(default = "default_credit_check_failure_rate")]
2947 pub credit_check_failure_rate: f64,
2948 #[serde(default = "default_partial_shipment_rate")]
2950 pub partial_shipment_rate: f64,
2951 #[serde(default = "default_return_rate")]
2953 pub return_rate: f64,
2954 #[serde(default = "default_bad_debt_rate")]
2956 pub bad_debt_rate: f64,
2957 #[serde(default = "default_so_to_delivery_days")]
2959 pub average_so_to_delivery_days: u32,
2960 #[serde(default = "default_delivery_to_invoice_days")]
2962 pub average_delivery_to_invoice_days: u32,
2963 #[serde(default = "default_invoice_to_receipt_days")]
2965 pub average_invoice_to_receipt_days: u32,
2966 #[serde(default)]
2968 pub line_count_distribution: DocumentLineCountDistribution,
2969 #[serde(default)]
2971 pub cash_discount: CashDiscountConfig,
2972 #[serde(default)]
2974 pub payment_behavior: O2CPaymentBehaviorConfig,
2975 #[serde(default)]
2977 pub late_payment_rate: Option<f64>,
2978}
2979
2980fn default_credit_check_failure_rate() -> f64 {
2981 0.02
2982}
2983
2984fn default_partial_shipment_rate() -> f64 {
2985 0.10
2986}
2987
2988fn default_return_rate() -> f64 {
2989 0.03
2990}
2991
2992fn default_bad_debt_rate() -> f64 {
2993 0.01
2994}
2995
2996fn default_so_to_delivery_days() -> u32 {
2997 7
2998}
2999
3000fn default_delivery_to_invoice_days() -> u32 {
3001 1
3002}
3003
3004fn default_invoice_to_receipt_days() -> u32 {
3005 45
3006}
3007
3008impl Default for O2CFlowConfig {
3009 fn default() -> Self {
3010 Self {
3011 enabled: true,
3012 credit_check_failure_rate: default_credit_check_failure_rate(),
3013 partial_shipment_rate: default_partial_shipment_rate(),
3014 return_rate: default_return_rate(),
3015 bad_debt_rate: default_bad_debt_rate(),
3016 average_so_to_delivery_days: default_so_to_delivery_days(),
3017 average_delivery_to_invoice_days: default_delivery_to_invoice_days(),
3018 average_invoice_to_receipt_days: default_invoice_to_receipt_days(),
3019 line_count_distribution: DocumentLineCountDistribution::default(),
3020 cash_discount: CashDiscountConfig::default(),
3021 payment_behavior: O2CPaymentBehaviorConfig::default(),
3022 late_payment_rate: None,
3023 }
3024 }
3025}
3026
3027#[derive(Debug, Clone, Serialize, Deserialize, Default)]
3033pub struct O2CPaymentBehaviorConfig {
3034 #[serde(default)]
3036 pub dunning: DunningConfig,
3037 #[serde(default)]
3039 pub partial_payments: PartialPaymentConfig,
3040 #[serde(default)]
3042 pub short_payments: ShortPaymentConfig,
3043 #[serde(default)]
3045 pub on_account_payments: OnAccountPaymentConfig,
3046 #[serde(default)]
3048 pub payment_corrections: PaymentCorrectionConfig,
3049}
3050
3051#[derive(Debug, Clone, Serialize, Deserialize)]
3053pub struct DunningConfig {
3054 #[serde(default)]
3056 pub enabled: bool,
3057 #[serde(default = "default_dunning_level_1_days")]
3059 pub level_1_days_overdue: u32,
3060 #[serde(default = "default_dunning_level_2_days")]
3062 pub level_2_days_overdue: u32,
3063 #[serde(default = "default_dunning_level_3_days")]
3065 pub level_3_days_overdue: u32,
3066 #[serde(default = "default_collection_days")]
3068 pub collection_days_overdue: u32,
3069 #[serde(default)]
3071 pub payment_after_dunning_rates: DunningPaymentRates,
3072 #[serde(default = "default_dunning_block_rate")]
3074 pub dunning_block_rate: f64,
3075 #[serde(default = "default_dunning_interest_rate")]
3077 pub interest_rate_per_year: f64,
3078 #[serde(default = "default_dunning_charge")]
3080 pub dunning_charge: f64,
3081}
3082
3083fn default_dunning_level_1_days() -> u32 {
3084 14
3085}
3086
3087fn default_dunning_level_2_days() -> u32 {
3088 28
3089}
3090
3091fn default_dunning_level_3_days() -> u32 {
3092 42
3093}
3094
3095fn default_collection_days() -> u32 {
3096 60
3097}
3098
3099fn default_dunning_block_rate() -> f64 {
3100 0.05
3101}
3102
3103fn default_dunning_interest_rate() -> f64 {
3104 0.09
3105}
3106
3107fn default_dunning_charge() -> f64 {
3108 25.0
3109}
3110
3111impl Default for DunningConfig {
3112 fn default() -> Self {
3113 Self {
3114 enabled: false,
3115 level_1_days_overdue: default_dunning_level_1_days(),
3116 level_2_days_overdue: default_dunning_level_2_days(),
3117 level_3_days_overdue: default_dunning_level_3_days(),
3118 collection_days_overdue: default_collection_days(),
3119 payment_after_dunning_rates: DunningPaymentRates::default(),
3120 dunning_block_rate: default_dunning_block_rate(),
3121 interest_rate_per_year: default_dunning_interest_rate(),
3122 dunning_charge: default_dunning_charge(),
3123 }
3124 }
3125}
3126
3127#[derive(Debug, Clone, Serialize, Deserialize)]
3129pub struct DunningPaymentRates {
3130 #[serde(default = "default_after_level_1")]
3132 pub after_level_1: f64,
3133 #[serde(default = "default_after_level_2")]
3135 pub after_level_2: f64,
3136 #[serde(default = "default_after_level_3")]
3138 pub after_level_3: f64,
3139 #[serde(default = "default_during_collection")]
3141 pub during_collection: f64,
3142 #[serde(default = "default_never_pay")]
3144 pub never_pay: f64,
3145}
3146
3147fn default_after_level_1() -> f64 {
3148 0.40
3149}
3150
3151fn default_after_level_2() -> f64 {
3152 0.30
3153}
3154
3155fn default_after_level_3() -> f64 {
3156 0.15
3157}
3158
3159fn default_during_collection() -> f64 {
3160 0.05
3161}
3162
3163fn default_never_pay() -> f64 {
3164 0.10
3165}
3166
3167impl Default for DunningPaymentRates {
3168 fn default() -> Self {
3169 Self {
3170 after_level_1: default_after_level_1(),
3171 after_level_2: default_after_level_2(),
3172 after_level_3: default_after_level_3(),
3173 during_collection: default_during_collection(),
3174 never_pay: default_never_pay(),
3175 }
3176 }
3177}
3178
3179#[derive(Debug, Clone, Serialize, Deserialize)]
3181pub struct PartialPaymentConfig {
3182 #[serde(default = "default_partial_payment_rate")]
3184 pub rate: f64,
3185 #[serde(default)]
3187 pub percentage_distribution: PartialPaymentPercentageDistribution,
3188 #[serde(default = "default_avg_days_until_remainder")]
3190 pub avg_days_until_remainder: u32,
3191}
3192
3193fn default_partial_payment_rate() -> f64 {
3194 0.08
3195}
3196
3197fn default_avg_days_until_remainder() -> u32 {
3198 30
3199}
3200
3201impl Default for PartialPaymentConfig {
3202 fn default() -> Self {
3203 Self {
3204 rate: default_partial_payment_rate(),
3205 percentage_distribution: PartialPaymentPercentageDistribution::default(),
3206 avg_days_until_remainder: default_avg_days_until_remainder(),
3207 }
3208 }
3209}
3210
3211#[derive(Debug, Clone, Serialize, Deserialize)]
3213pub struct PartialPaymentPercentageDistribution {
3214 #[serde(default = "default_partial_25")]
3216 pub pay_25_percent: f64,
3217 #[serde(default = "default_partial_50")]
3219 pub pay_50_percent: f64,
3220 #[serde(default = "default_partial_75")]
3222 pub pay_75_percent: f64,
3223 #[serde(default = "default_partial_random")]
3225 pub pay_random_percent: f64,
3226}
3227
3228fn default_partial_25() -> f64 {
3229 0.15
3230}
3231
3232fn default_partial_50() -> f64 {
3233 0.50
3234}
3235
3236fn default_partial_75() -> f64 {
3237 0.25
3238}
3239
3240fn default_partial_random() -> f64 {
3241 0.10
3242}
3243
3244impl Default for PartialPaymentPercentageDistribution {
3245 fn default() -> Self {
3246 Self {
3247 pay_25_percent: default_partial_25(),
3248 pay_50_percent: default_partial_50(),
3249 pay_75_percent: default_partial_75(),
3250 pay_random_percent: default_partial_random(),
3251 }
3252 }
3253}
3254
3255#[derive(Debug, Clone, Serialize, Deserialize)]
3257pub struct ShortPaymentConfig {
3258 #[serde(default = "default_short_payment_rate")]
3260 pub rate: f64,
3261 #[serde(default)]
3263 pub reason_distribution: ShortPaymentReasonDistribution,
3264 #[serde(default = "default_max_short_percent")]
3266 pub max_short_percent: f64,
3267}
3268
3269fn default_short_payment_rate() -> f64 {
3270 0.03
3271}
3272
3273fn default_max_short_percent() -> f64 {
3274 0.10
3275}
3276
3277impl Default for ShortPaymentConfig {
3278 fn default() -> Self {
3279 Self {
3280 rate: default_short_payment_rate(),
3281 reason_distribution: ShortPaymentReasonDistribution::default(),
3282 max_short_percent: default_max_short_percent(),
3283 }
3284 }
3285}
3286
3287#[derive(Debug, Clone, Serialize, Deserialize)]
3289pub struct ShortPaymentReasonDistribution {
3290 #[serde(default = "default_pricing_dispute")]
3292 pub pricing_dispute: f64,
3293 #[serde(default = "default_quality_issue")]
3295 pub quality_issue: f64,
3296 #[serde(default = "default_quantity_discrepancy")]
3298 pub quantity_discrepancy: f64,
3299 #[serde(default = "default_unauthorized_deduction")]
3301 pub unauthorized_deduction: f64,
3302 #[serde(default = "default_incorrect_discount")]
3304 pub incorrect_discount: f64,
3305}
3306
3307fn default_pricing_dispute() -> f64 {
3308 0.30
3309}
3310
3311fn default_quality_issue() -> f64 {
3312 0.20
3313}
3314
3315fn default_quantity_discrepancy() -> f64 {
3316 0.20
3317}
3318
3319fn default_unauthorized_deduction() -> f64 {
3320 0.15
3321}
3322
3323fn default_incorrect_discount() -> f64 {
3324 0.15
3325}
3326
3327impl Default for ShortPaymentReasonDistribution {
3328 fn default() -> Self {
3329 Self {
3330 pricing_dispute: default_pricing_dispute(),
3331 quality_issue: default_quality_issue(),
3332 quantity_discrepancy: default_quantity_discrepancy(),
3333 unauthorized_deduction: default_unauthorized_deduction(),
3334 incorrect_discount: default_incorrect_discount(),
3335 }
3336 }
3337}
3338
3339#[derive(Debug, Clone, Serialize, Deserialize)]
3341pub struct OnAccountPaymentConfig {
3342 #[serde(default = "default_on_account_rate")]
3344 pub rate: f64,
3345 #[serde(default = "default_avg_days_until_applied")]
3347 pub avg_days_until_applied: u32,
3348}
3349
3350fn default_on_account_rate() -> f64 {
3351 0.02
3352}
3353
3354fn default_avg_days_until_applied() -> u32 {
3355 14
3356}
3357
3358impl Default for OnAccountPaymentConfig {
3359 fn default() -> Self {
3360 Self {
3361 rate: default_on_account_rate(),
3362 avg_days_until_applied: default_avg_days_until_applied(),
3363 }
3364 }
3365}
3366
3367#[derive(Debug, Clone, Serialize, Deserialize)]
3369pub struct PaymentCorrectionConfig {
3370 #[serde(default = "default_payment_correction_rate")]
3372 pub rate: f64,
3373 #[serde(default)]
3375 pub type_distribution: PaymentCorrectionTypeDistribution,
3376}
3377
3378fn default_payment_correction_rate() -> f64 {
3379 0.02
3380}
3381
3382impl Default for PaymentCorrectionConfig {
3383 fn default() -> Self {
3384 Self {
3385 rate: default_payment_correction_rate(),
3386 type_distribution: PaymentCorrectionTypeDistribution::default(),
3387 }
3388 }
3389}
3390
3391#[derive(Debug, Clone, Serialize, Deserialize)]
3393pub struct PaymentCorrectionTypeDistribution {
3394 #[serde(default = "default_nsf_rate")]
3396 pub nsf: f64,
3397 #[serde(default = "default_chargeback_rate")]
3399 pub chargeback: f64,
3400 #[serde(default = "default_wrong_amount_rate")]
3402 pub wrong_amount: f64,
3403 #[serde(default = "default_wrong_customer_rate")]
3405 pub wrong_customer: f64,
3406 #[serde(default = "default_duplicate_payment_rate")]
3408 pub duplicate_payment: f64,
3409}
3410
3411fn default_nsf_rate() -> f64 {
3412 0.30
3413}
3414
3415fn default_chargeback_rate() -> f64 {
3416 0.20
3417}
3418
3419fn default_wrong_amount_rate() -> f64 {
3420 0.20
3421}
3422
3423fn default_wrong_customer_rate() -> f64 {
3424 0.15
3425}
3426
3427fn default_duplicate_payment_rate() -> f64 {
3428 0.15
3429}
3430
3431impl Default for PaymentCorrectionTypeDistribution {
3432 fn default() -> Self {
3433 Self {
3434 nsf: default_nsf_rate(),
3435 chargeback: default_chargeback_rate(),
3436 wrong_amount: default_wrong_amount_rate(),
3437 wrong_customer: default_wrong_customer_rate(),
3438 duplicate_payment: default_duplicate_payment_rate(),
3439 }
3440 }
3441}
3442
3443#[derive(Debug, Clone, Serialize, Deserialize)]
3445pub struct DocumentLineCountDistribution {
3446 #[serde(default = "default_min_lines")]
3448 pub min_lines: u32,
3449 #[serde(default = "default_max_lines")]
3451 pub max_lines: u32,
3452 #[serde(default = "default_mode_lines")]
3454 pub mode_lines: u32,
3455}
3456
3457fn default_min_lines() -> u32 {
3458 1
3459}
3460
3461fn default_max_lines() -> u32 {
3462 20
3463}
3464
3465fn default_mode_lines() -> u32 {
3466 3
3467}
3468
3469impl Default for DocumentLineCountDistribution {
3470 fn default() -> Self {
3471 Self {
3472 min_lines: default_min_lines(),
3473 max_lines: default_max_lines(),
3474 mode_lines: default_mode_lines(),
3475 }
3476 }
3477}
3478
3479#[derive(Debug, Clone, Serialize, Deserialize)]
3481pub struct CashDiscountConfig {
3482 #[serde(default = "default_discount_eligible_rate")]
3484 pub eligible_rate: f64,
3485 #[serde(default = "default_discount_taken_rate")]
3487 pub taken_rate: f64,
3488 #[serde(default = "default_discount_percent")]
3490 pub discount_percent: f64,
3491 #[serde(default = "default_discount_days")]
3493 pub discount_days: u32,
3494}
3495
3496fn default_discount_eligible_rate() -> f64 {
3497 0.30
3498}
3499
3500fn default_discount_taken_rate() -> f64 {
3501 0.60
3502}
3503
3504fn default_discount_percent() -> f64 {
3505 0.02
3506}
3507
3508fn default_discount_days() -> u32 {
3509 10
3510}
3511
3512impl Default for CashDiscountConfig {
3513 fn default() -> Self {
3514 Self {
3515 eligible_rate: default_discount_eligible_rate(),
3516 taken_rate: default_discount_taken_rate(),
3517 discount_percent: default_discount_percent(),
3518 discount_days: default_discount_days(),
3519 }
3520 }
3521}
3522
3523#[derive(Debug, Clone, Serialize, Deserialize)]
3529pub struct IntercompanyConfig {
3530 #[serde(default)]
3532 pub enabled: bool,
3533 #[serde(default = "default_ic_transaction_rate")]
3535 pub ic_transaction_rate: f64,
3536 #[serde(default)]
3538 pub transfer_pricing_method: TransferPricingMethod,
3539 #[serde(default = "default_markup_percent")]
3541 pub markup_percent: f64,
3542 #[serde(default = "default_true")]
3544 pub generate_matched_pairs: bool,
3545 #[serde(default)]
3547 pub transaction_type_distribution: ICTransactionTypeDistribution,
3548 #[serde(default)]
3550 pub generate_eliminations: bool,
3551}
3552
3553fn default_ic_transaction_rate() -> f64 {
3554 0.15
3555}
3556
3557fn default_markup_percent() -> f64 {
3558 0.05
3559}
3560
3561impl Default for IntercompanyConfig {
3562 fn default() -> Self {
3563 Self {
3564 enabled: false,
3565 ic_transaction_rate: default_ic_transaction_rate(),
3566 transfer_pricing_method: TransferPricingMethod::default(),
3567 markup_percent: default_markup_percent(),
3568 generate_matched_pairs: true,
3569 transaction_type_distribution: ICTransactionTypeDistribution::default(),
3570 generate_eliminations: false,
3571 }
3572 }
3573}
3574
3575#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
3577#[serde(rename_all = "snake_case")]
3578pub enum TransferPricingMethod {
3579 #[default]
3581 CostPlus,
3582 ComparableUncontrolled,
3584 ResalePrice,
3586 TransactionalNetMargin,
3588 ProfitSplit,
3590}
3591
3592#[derive(Debug, Clone, Serialize, Deserialize)]
3594pub struct ICTransactionTypeDistribution {
3595 pub goods_sale: f64,
3597 pub service_provided: f64,
3599 pub loan: f64,
3601 pub dividend: f64,
3603 pub management_fee: f64,
3605 pub royalty: f64,
3607 pub cost_sharing: f64,
3609}
3610
3611impl Default for ICTransactionTypeDistribution {
3612 fn default() -> Self {
3613 Self {
3614 goods_sale: 0.35,
3615 service_provided: 0.20,
3616 loan: 0.10,
3617 dividend: 0.05,
3618 management_fee: 0.15,
3619 royalty: 0.10,
3620 cost_sharing: 0.05,
3621 }
3622 }
3623}
3624
3625#[derive(Debug, Clone, Serialize, Deserialize)]
3631pub struct BalanceConfig {
3632 #[serde(default)]
3634 pub generate_opening_balances: bool,
3635 #[serde(default = "default_true")]
3637 pub generate_trial_balances: bool,
3638 #[serde(default = "default_gross_margin")]
3640 pub target_gross_margin: f64,
3641 #[serde(default = "default_dso")]
3643 pub target_dso_days: u32,
3644 #[serde(default = "default_dpo")]
3646 pub target_dpo_days: u32,
3647 #[serde(default = "default_current_ratio")]
3649 pub target_current_ratio: f64,
3650 #[serde(default = "default_debt_equity")]
3652 pub target_debt_to_equity: f64,
3653 #[serde(default = "default_true")]
3655 pub validate_balance_equation: bool,
3656 #[serde(default = "default_true")]
3658 pub reconcile_subledgers: bool,
3659}
3660
3661fn default_gross_margin() -> f64 {
3662 0.35
3663}
3664
3665fn default_dso() -> u32 {
3666 45
3667}
3668
3669fn default_dpo() -> u32 {
3670 30
3671}
3672
3673fn default_current_ratio() -> f64 {
3674 1.5
3675}
3676
3677fn default_debt_equity() -> f64 {
3678 0.5
3679}
3680
3681impl Default for BalanceConfig {
3682 fn default() -> Self {
3683 Self {
3684 generate_opening_balances: false,
3685 generate_trial_balances: true,
3686 target_gross_margin: default_gross_margin(),
3687 target_dso_days: default_dso(),
3688 target_dpo_days: default_dpo(),
3689 target_current_ratio: default_current_ratio(),
3690 target_debt_to_equity: default_debt_equity(),
3691 validate_balance_equation: true,
3692 reconcile_subledgers: true,
3693 }
3694 }
3695}
3696
3697#[derive(Debug, Clone, Serialize, Deserialize)]
3706pub struct OcpmConfig {
3707 #[serde(default)]
3709 pub enabled: bool,
3710
3711 #[serde(default = "default_true")]
3713 pub generate_lifecycle_events: bool,
3714
3715 #[serde(default = "default_true")]
3717 pub include_object_relationships: bool,
3718
3719 #[serde(default = "default_true")]
3721 pub compute_variants: bool,
3722
3723 #[serde(default)]
3725 pub max_variants: usize,
3726
3727 #[serde(default)]
3729 pub p2p_process: OcpmProcessConfig,
3730
3731 #[serde(default)]
3733 pub o2c_process: OcpmProcessConfig,
3734
3735 #[serde(default)]
3737 pub output: OcpmOutputConfig,
3738}
3739
3740impl Default for OcpmConfig {
3741 fn default() -> Self {
3742 Self {
3743 enabled: false,
3744 generate_lifecycle_events: true,
3745 include_object_relationships: true,
3746 compute_variants: true,
3747 max_variants: 0,
3748 p2p_process: OcpmProcessConfig::default(),
3749 o2c_process: OcpmProcessConfig::default(),
3750 output: OcpmOutputConfig::default(),
3751 }
3752 }
3753}
3754
3755#[derive(Debug, Clone, Serialize, Deserialize)]
3757pub struct OcpmProcessConfig {
3758 #[serde(default = "default_rework_probability")]
3760 pub rework_probability: f64,
3761
3762 #[serde(default = "default_skip_probability")]
3764 pub skip_step_probability: f64,
3765
3766 #[serde(default = "default_out_of_order_probability")]
3768 pub out_of_order_probability: f64,
3769}
3770
3771fn default_rework_probability() -> f64 {
3772 0.05
3773}
3774
3775fn default_skip_probability() -> f64 {
3776 0.02
3777}
3778
3779fn default_out_of_order_probability() -> f64 {
3780 0.03
3781}
3782
3783impl Default for OcpmProcessConfig {
3784 fn default() -> Self {
3785 Self {
3786 rework_probability: default_rework_probability(),
3787 skip_step_probability: default_skip_probability(),
3788 out_of_order_probability: default_out_of_order_probability(),
3789 }
3790 }
3791}
3792
3793#[derive(Debug, Clone, Serialize, Deserialize)]
3795pub struct OcpmOutputConfig {
3796 #[serde(default = "default_true")]
3798 pub ocel_json: bool,
3799
3800 #[serde(default)]
3802 pub ocel_xml: bool,
3803
3804 #[serde(default)]
3806 pub xes: bool,
3807
3808 #[serde(default = "default_true")]
3810 pub xes_include_lifecycle: bool,
3811
3812 #[serde(default = "default_true")]
3814 pub xes_include_resources: bool,
3815
3816 #[serde(default = "default_true")]
3818 pub flattened_csv: bool,
3819
3820 #[serde(default = "default_true")]
3822 pub event_object_csv: bool,
3823
3824 #[serde(default = "default_true")]
3826 pub object_relationship_csv: bool,
3827
3828 #[serde(default = "default_true")]
3830 pub variants_csv: bool,
3831
3832 #[serde(default)]
3834 pub export_reference_models: bool,
3835}
3836
3837impl Default for OcpmOutputConfig {
3838 fn default() -> Self {
3839 Self {
3840 ocel_json: true,
3841 ocel_xml: false,
3842 xes: false,
3843 xes_include_lifecycle: true,
3844 xes_include_resources: true,
3845 flattened_csv: true,
3846 event_object_csv: true,
3847 object_relationship_csv: true,
3848 variants_csv: true,
3849 export_reference_models: false,
3850 }
3851 }
3852}
3853
3854#[derive(Debug, Clone, Serialize, Deserialize)]
3856pub struct AuditGenerationConfig {
3857 #[serde(default)]
3859 pub enabled: bool,
3860
3861 #[serde(default = "default_true")]
3864 pub generate_workpapers: bool,
3865
3866 #[serde(default)]
3869 pub engagement_types: AuditEngagementTypesConfig,
3870
3871 #[serde(default)]
3874 pub workpapers: WorkpaperConfig,
3875
3876 #[serde(default)]
3879 pub team: AuditTeamConfig,
3880
3881 #[serde(default)]
3884 pub review: ReviewWorkflowConfig,
3885
3886 #[serde(default)]
3888 pub fsm: Option<AuditFsmConfig>,
3889}
3890
3891impl Default for AuditGenerationConfig {
3892 fn default() -> Self {
3893 Self {
3894 enabled: false,
3895 generate_workpapers: true,
3896 engagement_types: AuditEngagementTypesConfig::default(),
3897 workpapers: WorkpaperConfig::default(),
3898 team: AuditTeamConfig::default(),
3899 review: ReviewWorkflowConfig::default(),
3900 fsm: None,
3901 }
3902 }
3903}
3904
3905#[derive(Debug, Clone, Serialize, Deserialize)]
3907pub struct AuditFsmConfig {
3908 #[serde(default)]
3910 pub enabled: bool,
3911
3912 #[serde(default = "default_audit_fsm_blueprint")]
3914 pub blueprint: String,
3915
3916 #[serde(default = "default_audit_fsm_overlay")]
3918 pub overlay: String,
3919
3920 #[serde(default)]
3922 pub depth: Option<String>,
3923
3924 #[serde(default)]
3926 pub discriminators: std::collections::HashMap<String, Vec<String>>,
3927
3928 #[serde(default)]
3930 pub event_trail: AuditEventTrailConfig,
3931
3932 #[serde(default)]
3934 pub seed: Option<u64>,
3935}
3936
3937impl Default for AuditFsmConfig {
3938 fn default() -> Self {
3939 Self {
3940 enabled: false,
3941 blueprint: default_audit_fsm_blueprint(),
3942 overlay: default_audit_fsm_overlay(),
3943 depth: None,
3944 discriminators: std::collections::HashMap::new(),
3945 event_trail: AuditEventTrailConfig::default(),
3946 seed: None,
3947 }
3948 }
3949}
3950
3951fn default_audit_fsm_blueprint() -> String {
3952 "builtin:fsa".to_string()
3953}
3954
3955fn default_audit_fsm_overlay() -> String {
3956 "builtin:default".to_string()
3957}
3958
3959#[derive(Debug, Clone, Serialize, Deserialize)]
3961pub struct AuditEventTrailConfig {
3962 #[serde(default = "default_true")]
3964 pub flat_log: bool,
3965 #[serde(default)]
3967 pub ocel_projection: bool,
3968}
3969
3970impl Default for AuditEventTrailConfig {
3971 fn default() -> Self {
3972 Self {
3973 flat_log: true,
3974 ocel_projection: false,
3975 }
3976 }
3977}
3978
3979#[derive(Debug, Clone, Serialize, Deserialize)]
3981pub struct AuditEngagementTypesConfig {
3982 #[serde(default = "default_financial_audit_prob")]
3984 pub financial_statement: f64,
3985 #[serde(default = "default_sox_audit_prob")]
3987 pub sox_icfr: f64,
3988 #[serde(default = "default_integrated_audit_prob")]
3990 pub integrated: f64,
3991 #[serde(default = "default_review_prob")]
3993 pub review: f64,
3994 #[serde(default = "default_aup_prob")]
3996 pub agreed_upon_procedures: f64,
3997}
3998
3999fn default_financial_audit_prob() -> f64 {
4000 0.40
4001}
4002fn default_sox_audit_prob() -> f64 {
4003 0.20
4004}
4005fn default_integrated_audit_prob() -> f64 {
4006 0.25
4007}
4008fn default_review_prob() -> f64 {
4009 0.10
4010}
4011fn default_aup_prob() -> f64 {
4012 0.05
4013}
4014
4015impl Default for AuditEngagementTypesConfig {
4016 fn default() -> Self {
4017 Self {
4018 financial_statement: default_financial_audit_prob(),
4019 sox_icfr: default_sox_audit_prob(),
4020 integrated: default_integrated_audit_prob(),
4021 review: default_review_prob(),
4022 agreed_upon_procedures: default_aup_prob(),
4023 }
4024 }
4025}
4026
4027#[derive(Debug, Clone, Serialize, Deserialize)]
4029pub struct WorkpaperConfig {
4030 #[serde(default = "default_workpapers_per_phase")]
4032 pub average_per_phase: usize,
4033
4034 #[serde(default = "default_true")]
4036 pub include_isa_references: bool,
4037
4038 #[serde(default = "default_true")]
4040 pub include_sample_details: bool,
4041
4042 #[serde(default = "default_true")]
4044 pub include_cross_references: bool,
4045
4046 #[serde(default)]
4048 pub sampling: SamplingConfig,
4049}
4050
4051fn default_workpapers_per_phase() -> usize {
4052 5
4053}
4054
4055impl Default for WorkpaperConfig {
4056 fn default() -> Self {
4057 Self {
4058 average_per_phase: default_workpapers_per_phase(),
4059 include_isa_references: true,
4060 include_sample_details: true,
4061 include_cross_references: true,
4062 sampling: SamplingConfig::default(),
4063 }
4064 }
4065}
4066
4067#[derive(Debug, Clone, Serialize, Deserialize)]
4069pub struct SamplingConfig {
4070 #[serde(default = "default_statistical_rate")]
4072 pub statistical_rate: f64,
4073 #[serde(default = "default_judgmental_rate")]
4075 pub judgmental_rate: f64,
4076 #[serde(default = "default_haphazard_rate")]
4078 pub haphazard_rate: f64,
4079 #[serde(default = "default_complete_examination_rate")]
4081 pub complete_examination_rate: f64,
4082}
4083
4084fn default_statistical_rate() -> f64 {
4085 0.40
4086}
4087fn default_judgmental_rate() -> f64 {
4088 0.30
4089}
4090fn default_haphazard_rate() -> f64 {
4091 0.20
4092}
4093fn default_complete_examination_rate() -> f64 {
4094 0.10
4095}
4096
4097impl Default for SamplingConfig {
4098 fn default() -> Self {
4099 Self {
4100 statistical_rate: default_statistical_rate(),
4101 judgmental_rate: default_judgmental_rate(),
4102 haphazard_rate: default_haphazard_rate(),
4103 complete_examination_rate: default_complete_examination_rate(),
4104 }
4105 }
4106}
4107
4108#[derive(Debug, Clone, Serialize, Deserialize)]
4110pub struct AuditTeamConfig {
4111 #[serde(default = "default_min_team_size")]
4113 pub min_team_size: usize,
4114 #[serde(default = "default_max_team_size")]
4116 pub max_team_size: usize,
4117 #[serde(default = "default_specialist_probability")]
4119 pub specialist_probability: f64,
4120}
4121
4122fn default_min_team_size() -> usize {
4123 3
4124}
4125fn default_max_team_size() -> usize {
4126 8
4127}
4128fn default_specialist_probability() -> f64 {
4129 0.30
4130}
4131
4132impl Default for AuditTeamConfig {
4133 fn default() -> Self {
4134 Self {
4135 min_team_size: default_min_team_size(),
4136 max_team_size: default_max_team_size(),
4137 specialist_probability: default_specialist_probability(),
4138 }
4139 }
4140}
4141
4142#[derive(Debug, Clone, Serialize, Deserialize)]
4144pub struct ReviewWorkflowConfig {
4145 #[serde(default = "default_review_delay_days")]
4147 pub average_review_delay_days: u32,
4148 #[serde(default = "default_rework_probability_review")]
4150 pub rework_probability: f64,
4151 #[serde(default = "default_true")]
4153 pub require_partner_signoff: bool,
4154}
4155
4156fn default_review_delay_days() -> u32 {
4157 2
4158}
4159fn default_rework_probability_review() -> f64 {
4160 0.15
4161}
4162
4163impl Default for ReviewWorkflowConfig {
4164 fn default() -> Self {
4165 Self {
4166 average_review_delay_days: default_review_delay_days(),
4167 rework_probability: default_rework_probability_review(),
4168 require_partner_signoff: true,
4169 }
4170 }
4171}
4172
4173#[derive(Debug, Clone, Serialize, Deserialize)]
4179pub struct DataQualitySchemaConfig {
4180 #[serde(default)]
4182 pub enabled: bool,
4183 #[serde(default)]
4185 pub preset: DataQualityPreset,
4186 #[serde(default)]
4188 pub missing_values: MissingValuesSchemaConfig,
4189 #[serde(default)]
4191 pub typos: TypoSchemaConfig,
4192 #[serde(default)]
4194 pub format_variations: FormatVariationSchemaConfig,
4195 #[serde(default)]
4197 pub duplicates: DuplicateSchemaConfig,
4198 #[serde(default)]
4200 pub encoding_issues: EncodingIssueSchemaConfig,
4201 #[serde(default)]
4203 pub generate_labels: bool,
4204 #[serde(default)]
4206 pub sink_profiles: SinkQualityProfiles,
4207}
4208
4209impl Default for DataQualitySchemaConfig {
4210 fn default() -> Self {
4211 Self {
4212 enabled: false,
4213 preset: DataQualityPreset::None,
4214 missing_values: MissingValuesSchemaConfig::default(),
4215 typos: TypoSchemaConfig::default(),
4216 format_variations: FormatVariationSchemaConfig::default(),
4217 duplicates: DuplicateSchemaConfig::default(),
4218 encoding_issues: EncodingIssueSchemaConfig::default(),
4219 generate_labels: true,
4220 sink_profiles: SinkQualityProfiles::default(),
4221 }
4222 }
4223}
4224
4225impl DataQualitySchemaConfig {
4226 pub fn with_preset(preset: DataQualityPreset) -> Self {
4228 let mut config = Self {
4229 preset,
4230 ..Default::default()
4231 };
4232 config.apply_preset();
4233 config
4234 }
4235
4236 pub fn apply_preset(&mut self) {
4239 if !self.preset.overrides_settings() {
4240 return;
4241 }
4242
4243 self.enabled = true;
4244
4245 self.missing_values.enabled = self.preset.missing_rate() > 0.0;
4247 self.missing_values.rate = self.preset.missing_rate();
4248
4249 self.typos.enabled = self.preset.typo_rate() > 0.0;
4251 self.typos.char_error_rate = self.preset.typo_rate();
4252
4253 self.duplicates.enabled = self.preset.duplicate_rate() > 0.0;
4255 self.duplicates.exact_duplicate_ratio = self.preset.duplicate_rate() * 0.4;
4256 self.duplicates.near_duplicate_ratio = self.preset.duplicate_rate() * 0.4;
4257 self.duplicates.fuzzy_duplicate_ratio = self.preset.duplicate_rate() * 0.2;
4258
4259 self.format_variations.enabled = self.preset.format_variations_enabled();
4261
4262 self.encoding_issues.enabled = self.preset.encoding_issues_enabled();
4264 self.encoding_issues.rate = self.preset.encoding_issue_rate();
4265
4266 if self.preset.ocr_errors_enabled() {
4268 self.typos.type_weights.ocr_errors = 0.3;
4269 }
4270 }
4271
4272 pub fn effective_missing_rate(&self) -> f64 {
4274 if self.preset.overrides_settings() {
4275 self.preset.missing_rate()
4276 } else {
4277 self.missing_values.rate
4278 }
4279 }
4280
4281 pub fn effective_typo_rate(&self) -> f64 {
4283 if self.preset.overrides_settings() {
4284 self.preset.typo_rate()
4285 } else {
4286 self.typos.char_error_rate
4287 }
4288 }
4289
4290 pub fn effective_duplicate_rate(&self) -> f64 {
4292 if self.preset.overrides_settings() {
4293 self.preset.duplicate_rate()
4294 } else {
4295 self.duplicates.exact_duplicate_ratio
4296 + self.duplicates.near_duplicate_ratio
4297 + self.duplicates.fuzzy_duplicate_ratio
4298 }
4299 }
4300
4301 pub fn clean() -> Self {
4303 Self::with_preset(DataQualityPreset::Clean)
4304 }
4305
4306 pub fn noisy() -> Self {
4308 Self::with_preset(DataQualityPreset::Noisy)
4309 }
4310
4311 pub fn legacy() -> Self {
4313 Self::with_preset(DataQualityPreset::Legacy)
4314 }
4315}
4316
4317#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
4319#[serde(rename_all = "snake_case")]
4320pub enum DataQualityPreset {
4321 #[default]
4323 None,
4324 Minimal,
4326 Normal,
4328 High,
4330 Custom,
4332
4333 Clean,
4339 Noisy,
4342 Legacy,
4345}
4346
4347impl DataQualityPreset {
4348 pub fn missing_rate(&self) -> f64 {
4350 match self {
4351 DataQualityPreset::None => 0.0,
4352 DataQualityPreset::Minimal => 0.005,
4353 DataQualityPreset::Normal => 0.02,
4354 DataQualityPreset::High => 0.08,
4355 DataQualityPreset::Custom => 0.01, DataQualityPreset::Clean => 0.001,
4357 DataQualityPreset::Noisy => 0.05,
4358 DataQualityPreset::Legacy => 0.10,
4359 }
4360 }
4361
4362 pub fn typo_rate(&self) -> f64 {
4364 match self {
4365 DataQualityPreset::None => 0.0,
4366 DataQualityPreset::Minimal => 0.0005,
4367 DataQualityPreset::Normal => 0.002,
4368 DataQualityPreset::High => 0.01,
4369 DataQualityPreset::Custom => 0.001, DataQualityPreset::Clean => 0.0005,
4371 DataQualityPreset::Noisy => 0.02,
4372 DataQualityPreset::Legacy => 0.05,
4373 }
4374 }
4375
4376 pub fn duplicate_rate(&self) -> f64 {
4378 match self {
4379 DataQualityPreset::None => 0.0,
4380 DataQualityPreset::Minimal => 0.001,
4381 DataQualityPreset::Normal => 0.005,
4382 DataQualityPreset::High => 0.02,
4383 DataQualityPreset::Custom => 0.0, DataQualityPreset::Clean => 0.0,
4385 DataQualityPreset::Noisy => 0.01,
4386 DataQualityPreset::Legacy => 0.03,
4387 }
4388 }
4389
4390 pub fn format_variations_enabled(&self) -> bool {
4392 match self {
4393 DataQualityPreset::None | DataQualityPreset::Clean => false,
4394 DataQualityPreset::Minimal => true,
4395 DataQualityPreset::Normal => true,
4396 DataQualityPreset::High => true,
4397 DataQualityPreset::Custom => true,
4398 DataQualityPreset::Noisy => true,
4399 DataQualityPreset::Legacy => true,
4400 }
4401 }
4402
4403 pub fn ocr_errors_enabled(&self) -> bool {
4405 matches!(self, DataQualityPreset::Legacy | DataQualityPreset::High)
4406 }
4407
4408 pub fn encoding_issues_enabled(&self) -> bool {
4410 matches!(
4411 self,
4412 DataQualityPreset::Legacy | DataQualityPreset::High | DataQualityPreset::Noisy
4413 )
4414 }
4415
4416 pub fn encoding_issue_rate(&self) -> f64 {
4418 match self {
4419 DataQualityPreset::None | DataQualityPreset::Clean | DataQualityPreset::Minimal => 0.0,
4420 DataQualityPreset::Normal => 0.002,
4421 DataQualityPreset::High => 0.01,
4422 DataQualityPreset::Custom => 0.0,
4423 DataQualityPreset::Noisy => 0.005,
4424 DataQualityPreset::Legacy => 0.02,
4425 }
4426 }
4427
4428 pub fn overrides_settings(&self) -> bool {
4430 !matches!(self, DataQualityPreset::Custom | DataQualityPreset::None)
4431 }
4432
4433 pub fn description(&self) -> &'static str {
4435 match self {
4436 DataQualityPreset::None => "No data quality issues (pristine data)",
4437 DataQualityPreset::Minimal => "Very rare data quality issues",
4438 DataQualityPreset::Normal => "Realistic enterprise data quality",
4439 DataQualityPreset::High => "Messy data for stress testing",
4440 DataQualityPreset::Custom => "Custom settings from configuration",
4441 DataQualityPreset::Clean => "ML-ready clean data with minimal issues",
4442 DataQualityPreset::Noisy => "Typical production data with moderate issues",
4443 DataQualityPreset::Legacy => "Legacy/migrated data with heavy issues and OCR errors",
4444 }
4445 }
4446}
4447
4448#[derive(Debug, Clone, Serialize, Deserialize)]
4450pub struct MissingValuesSchemaConfig {
4451 #[serde(default)]
4453 pub enabled: bool,
4454 #[serde(default = "default_missing_rate")]
4456 pub rate: f64,
4457 #[serde(default)]
4459 pub strategy: MissingValueStrategy,
4460 #[serde(default)]
4462 pub field_rates: std::collections::HashMap<String, f64>,
4463 #[serde(default)]
4465 pub protected_fields: Vec<String>,
4466}
4467
4468fn default_missing_rate() -> f64 {
4469 0.01
4470}
4471
4472impl Default for MissingValuesSchemaConfig {
4473 fn default() -> Self {
4474 Self {
4475 enabled: false,
4476 rate: default_missing_rate(),
4477 strategy: MissingValueStrategy::Mcar,
4478 field_rates: std::collections::HashMap::new(),
4479 protected_fields: vec![
4480 "document_id".to_string(),
4481 "company_code".to_string(),
4482 "posting_date".to_string(),
4483 ],
4484 }
4485 }
4486}
4487
4488#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
4490#[serde(rename_all = "snake_case")]
4491pub enum MissingValueStrategy {
4492 #[default]
4494 Mcar,
4495 Mar,
4497 Mnar,
4499 Systematic,
4501}
4502
4503#[derive(Debug, Clone, Serialize, Deserialize)]
4505pub struct TypoSchemaConfig {
4506 #[serde(default)]
4508 pub enabled: bool,
4509 #[serde(default = "default_typo_rate")]
4511 pub char_error_rate: f64,
4512 #[serde(default)]
4514 pub type_weights: TypoTypeWeights,
4515 #[serde(default)]
4517 pub protected_fields: Vec<String>,
4518}
4519
4520fn default_typo_rate() -> f64 {
4521 0.001
4522}
4523
4524impl Default for TypoSchemaConfig {
4525 fn default() -> Self {
4526 Self {
4527 enabled: false,
4528 char_error_rate: default_typo_rate(),
4529 type_weights: TypoTypeWeights::default(),
4530 protected_fields: vec![
4531 "document_id".to_string(),
4532 "gl_account".to_string(),
4533 "company_code".to_string(),
4534 ],
4535 }
4536 }
4537}
4538
4539#[derive(Debug, Clone, Serialize, Deserialize)]
4541pub struct TypoTypeWeights {
4542 #[serde(default = "default_substitution_weight")]
4544 pub substitution: f64,
4545 #[serde(default = "default_transposition_weight")]
4547 pub transposition: f64,
4548 #[serde(default = "default_insertion_weight")]
4550 pub insertion: f64,
4551 #[serde(default = "default_deletion_weight")]
4553 pub deletion: f64,
4554 #[serde(default = "default_ocr_weight")]
4556 pub ocr_errors: f64,
4557 #[serde(default = "default_homophone_weight")]
4559 pub homophones: f64,
4560}
4561
4562fn default_substitution_weight() -> f64 {
4563 0.35
4564}
4565fn default_transposition_weight() -> f64 {
4566 0.25
4567}
4568fn default_insertion_weight() -> f64 {
4569 0.10
4570}
4571fn default_deletion_weight() -> f64 {
4572 0.15
4573}
4574fn default_ocr_weight() -> f64 {
4575 0.10
4576}
4577fn default_homophone_weight() -> f64 {
4578 0.05
4579}
4580
4581impl Default for TypoTypeWeights {
4582 fn default() -> Self {
4583 Self {
4584 substitution: default_substitution_weight(),
4585 transposition: default_transposition_weight(),
4586 insertion: default_insertion_weight(),
4587 deletion: default_deletion_weight(),
4588 ocr_errors: default_ocr_weight(),
4589 homophones: default_homophone_weight(),
4590 }
4591 }
4592}
4593
4594#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4596pub struct FormatVariationSchemaConfig {
4597 #[serde(default)]
4599 pub enabled: bool,
4600 #[serde(default)]
4602 pub dates: DateFormatVariationConfig,
4603 #[serde(default)]
4605 pub amounts: AmountFormatVariationConfig,
4606 #[serde(default)]
4608 pub identifiers: IdentifierFormatVariationConfig,
4609}
4610
4611#[derive(Debug, Clone, Serialize, Deserialize)]
4613pub struct DateFormatVariationConfig {
4614 #[serde(default)]
4616 pub enabled: bool,
4617 #[serde(default = "default_date_variation_rate")]
4619 pub rate: f64,
4620 #[serde(default = "default_true")]
4622 pub iso_format: bool,
4623 #[serde(default)]
4625 pub us_format: bool,
4626 #[serde(default)]
4628 pub eu_format: bool,
4629 #[serde(default)]
4631 pub long_format: bool,
4632}
4633
4634fn default_date_variation_rate() -> f64 {
4635 0.05
4636}
4637
4638impl Default for DateFormatVariationConfig {
4639 fn default() -> Self {
4640 Self {
4641 enabled: false,
4642 rate: default_date_variation_rate(),
4643 iso_format: true,
4644 us_format: false,
4645 eu_format: false,
4646 long_format: false,
4647 }
4648 }
4649}
4650
4651#[derive(Debug, Clone, Serialize, Deserialize)]
4653pub struct AmountFormatVariationConfig {
4654 #[serde(default)]
4656 pub enabled: bool,
4657 #[serde(default = "default_amount_variation_rate")]
4659 pub rate: f64,
4660 #[serde(default)]
4662 pub us_comma_format: bool,
4663 #[serde(default)]
4665 pub eu_format: bool,
4666 #[serde(default)]
4668 pub currency_prefix: bool,
4669 #[serde(default)]
4671 pub accounting_format: bool,
4672}
4673
4674fn default_amount_variation_rate() -> f64 {
4675 0.02
4676}
4677
4678impl Default for AmountFormatVariationConfig {
4679 fn default() -> Self {
4680 Self {
4681 enabled: false,
4682 rate: default_amount_variation_rate(),
4683 us_comma_format: false,
4684 eu_format: false,
4685 currency_prefix: false,
4686 accounting_format: false,
4687 }
4688 }
4689}
4690
4691#[derive(Debug, Clone, Serialize, Deserialize)]
4693pub struct IdentifierFormatVariationConfig {
4694 #[serde(default)]
4696 pub enabled: bool,
4697 #[serde(default = "default_identifier_variation_rate")]
4699 pub rate: f64,
4700 #[serde(default)]
4702 pub case_variations: bool,
4703 #[serde(default)]
4705 pub padding_variations: bool,
4706 #[serde(default)]
4708 pub separator_variations: bool,
4709}
4710
4711fn default_identifier_variation_rate() -> f64 {
4712 0.02
4713}
4714
4715impl Default for IdentifierFormatVariationConfig {
4716 fn default() -> Self {
4717 Self {
4718 enabled: false,
4719 rate: default_identifier_variation_rate(),
4720 case_variations: false,
4721 padding_variations: false,
4722 separator_variations: false,
4723 }
4724 }
4725}
4726
4727#[derive(Debug, Clone, Serialize, Deserialize)]
4729pub struct DuplicateSchemaConfig {
4730 #[serde(default)]
4732 pub enabled: bool,
4733 #[serde(default = "default_duplicate_rate")]
4735 pub rate: f64,
4736 #[serde(default = "default_exact_duplicate_ratio")]
4738 pub exact_duplicate_ratio: f64,
4739 #[serde(default = "default_near_duplicate_ratio")]
4741 pub near_duplicate_ratio: f64,
4742 #[serde(default = "default_fuzzy_duplicate_ratio")]
4744 pub fuzzy_duplicate_ratio: f64,
4745 #[serde(default = "default_max_date_offset")]
4747 pub max_date_offset_days: u32,
4748 #[serde(default = "default_max_amount_variance")]
4750 pub max_amount_variance: f64,
4751}
4752
4753fn default_duplicate_rate() -> f64 {
4754 0.005
4755}
4756fn default_exact_duplicate_ratio() -> f64 {
4757 0.4
4758}
4759fn default_near_duplicate_ratio() -> f64 {
4760 0.35
4761}
4762fn default_fuzzy_duplicate_ratio() -> f64 {
4763 0.25
4764}
4765fn default_max_date_offset() -> u32 {
4766 3
4767}
4768fn default_max_amount_variance() -> f64 {
4769 0.01
4770}
4771
4772impl Default for DuplicateSchemaConfig {
4773 fn default() -> Self {
4774 Self {
4775 enabled: false,
4776 rate: default_duplicate_rate(),
4777 exact_duplicate_ratio: default_exact_duplicate_ratio(),
4778 near_duplicate_ratio: default_near_duplicate_ratio(),
4779 fuzzy_duplicate_ratio: default_fuzzy_duplicate_ratio(),
4780 max_date_offset_days: default_max_date_offset(),
4781 max_amount_variance: default_max_amount_variance(),
4782 }
4783 }
4784}
4785
4786#[derive(Debug, Clone, Serialize, Deserialize)]
4788pub struct EncodingIssueSchemaConfig {
4789 #[serde(default)]
4791 pub enabled: bool,
4792 #[serde(default = "default_encoding_rate")]
4794 pub rate: f64,
4795 #[serde(default)]
4797 pub mojibake: bool,
4798 #[serde(default)]
4800 pub html_entities: bool,
4801 #[serde(default)]
4803 pub bom_issues: bool,
4804}
4805
4806fn default_encoding_rate() -> f64 {
4807 0.001
4808}
4809
4810impl Default for EncodingIssueSchemaConfig {
4811 fn default() -> Self {
4812 Self {
4813 enabled: false,
4814 rate: default_encoding_rate(),
4815 mojibake: false,
4816 html_entities: false,
4817 bom_issues: false,
4818 }
4819 }
4820}
4821
4822#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4824pub struct SinkQualityProfiles {
4825 #[serde(default)]
4827 pub csv: Option<SinkQualityOverride>,
4828 #[serde(default)]
4830 pub json: Option<SinkQualityOverride>,
4831 #[serde(default)]
4833 pub parquet: Option<SinkQualityOverride>,
4834}
4835
4836#[derive(Debug, Clone, Serialize, Deserialize)]
4838pub struct SinkQualityOverride {
4839 pub enabled: Option<bool>,
4841 pub missing_rate: Option<f64>,
4843 pub typo_rate: Option<f64>,
4845 pub format_variation_rate: Option<f64>,
4847 pub duplicate_rate: Option<f64>,
4849}
4850
4851#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4863pub struct AccountingStandardsConfig {
4864 #[serde(default)]
4866 pub enabled: bool,
4867
4868 #[serde(default, skip_serializing_if = "Option::is_none")]
4872 pub framework: Option<AccountingFrameworkConfig>,
4873
4874 #[serde(default)]
4876 pub revenue_recognition: RevenueRecognitionConfig,
4877
4878 #[serde(default)]
4880 pub leases: LeaseAccountingConfig,
4881
4882 #[serde(default)]
4884 pub fair_value: FairValueConfig,
4885
4886 #[serde(default)]
4888 pub impairment: ImpairmentConfig,
4889
4890 #[serde(default)]
4892 pub business_combinations: BusinessCombinationsConfig,
4893
4894 #[serde(default)]
4896 pub expected_credit_loss: EclConfig,
4897
4898 #[serde(default)]
4900 pub generate_differences: bool,
4901}
4902
4903#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
4905#[serde(rename_all = "snake_case")]
4906pub enum AccountingFrameworkConfig {
4907 #[default]
4909 UsGaap,
4910 Ifrs,
4912 DualReporting,
4914 FrenchGaap,
4916 GermanGaap,
4918}
4919
4920#[derive(Debug, Clone, Serialize, Deserialize)]
4922pub struct RevenueRecognitionConfig {
4923 #[serde(default)]
4925 pub enabled: bool,
4926
4927 #[serde(default = "default_true")]
4929 pub generate_contracts: bool,
4930
4931 #[serde(default = "default_avg_obligations")]
4933 pub avg_obligations_per_contract: f64,
4934
4935 #[serde(default = "default_variable_consideration_rate")]
4937 pub variable_consideration_rate: f64,
4938
4939 #[serde(default = "default_over_time_rate")]
4941 pub over_time_recognition_rate: f64,
4942
4943 #[serde(default = "default_contract_count")]
4945 pub contract_count: usize,
4946}
4947
4948fn default_avg_obligations() -> f64 {
4949 2.0
4950}
4951
4952fn default_variable_consideration_rate() -> f64 {
4953 0.15
4954}
4955
4956fn default_over_time_rate() -> f64 {
4957 0.30
4958}
4959
4960fn default_contract_count() -> usize {
4961 100
4962}
4963
4964impl Default for RevenueRecognitionConfig {
4965 fn default() -> Self {
4966 Self {
4967 enabled: false,
4968 generate_contracts: true,
4969 avg_obligations_per_contract: default_avg_obligations(),
4970 variable_consideration_rate: default_variable_consideration_rate(),
4971 over_time_recognition_rate: default_over_time_rate(),
4972 contract_count: default_contract_count(),
4973 }
4974 }
4975}
4976
4977#[derive(Debug, Clone, Serialize, Deserialize)]
4979pub struct LeaseAccountingConfig {
4980 #[serde(default)]
4982 pub enabled: bool,
4983
4984 #[serde(default = "default_lease_count")]
4986 pub lease_count: usize,
4987
4988 #[serde(default = "default_finance_lease_pct")]
4990 pub finance_lease_percent: f64,
4991
4992 #[serde(default = "default_avg_lease_term")]
4994 pub avg_lease_term_months: u32,
4995
4996 #[serde(default = "default_true")]
4998 pub generate_amortization: bool,
4999
5000 #[serde(default = "default_real_estate_pct")]
5002 pub real_estate_percent: f64,
5003}
5004
5005fn default_lease_count() -> usize {
5006 50
5007}
5008
5009fn default_finance_lease_pct() -> f64 {
5010 0.30
5011}
5012
5013fn default_avg_lease_term() -> u32 {
5014 60
5015}
5016
5017fn default_real_estate_pct() -> f64 {
5018 0.40
5019}
5020
5021impl Default for LeaseAccountingConfig {
5022 fn default() -> Self {
5023 Self {
5024 enabled: false,
5025 lease_count: default_lease_count(),
5026 finance_lease_percent: default_finance_lease_pct(),
5027 avg_lease_term_months: default_avg_lease_term(),
5028 generate_amortization: true,
5029 real_estate_percent: default_real_estate_pct(),
5030 }
5031 }
5032}
5033
5034#[derive(Debug, Clone, Serialize, Deserialize)]
5036pub struct FairValueConfig {
5037 #[serde(default)]
5039 pub enabled: bool,
5040
5041 #[serde(default = "default_fv_count")]
5043 pub measurement_count: usize,
5044
5045 #[serde(default = "default_level1_pct")]
5047 pub level1_percent: f64,
5048
5049 #[serde(default = "default_level2_pct")]
5051 pub level2_percent: f64,
5052
5053 #[serde(default = "default_level3_pct")]
5055 pub level3_percent: f64,
5056
5057 #[serde(default)]
5059 pub include_sensitivity_analysis: bool,
5060}
5061
5062fn default_fv_count() -> usize {
5063 25
5064}
5065
5066fn default_level1_pct() -> f64 {
5067 0.40
5068}
5069
5070fn default_level2_pct() -> f64 {
5071 0.35
5072}
5073
5074fn default_level3_pct() -> f64 {
5075 0.25
5076}
5077
5078impl Default for FairValueConfig {
5079 fn default() -> Self {
5080 Self {
5081 enabled: false,
5082 measurement_count: default_fv_count(),
5083 level1_percent: default_level1_pct(),
5084 level2_percent: default_level2_pct(),
5085 level3_percent: default_level3_pct(),
5086 include_sensitivity_analysis: false,
5087 }
5088 }
5089}
5090
5091#[derive(Debug, Clone, Serialize, Deserialize)]
5093pub struct ImpairmentConfig {
5094 #[serde(default)]
5096 pub enabled: bool,
5097
5098 #[serde(default = "default_impairment_count")]
5100 pub test_count: usize,
5101
5102 #[serde(default = "default_impairment_rate")]
5104 pub impairment_rate: f64,
5105
5106 #[serde(default = "default_true")]
5108 pub generate_projections: bool,
5109
5110 #[serde(default)]
5112 pub include_goodwill: bool,
5113}
5114
5115fn default_impairment_count() -> usize {
5116 15
5117}
5118
5119fn default_impairment_rate() -> f64 {
5120 0.10
5121}
5122
5123impl Default for ImpairmentConfig {
5124 fn default() -> Self {
5125 Self {
5126 enabled: false,
5127 test_count: default_impairment_count(),
5128 impairment_rate: default_impairment_rate(),
5129 generate_projections: true,
5130 include_goodwill: false,
5131 }
5132 }
5133}
5134
5135#[derive(Debug, Clone, Serialize, Deserialize)]
5141pub struct BusinessCombinationsConfig {
5142 #[serde(default)]
5144 pub enabled: bool,
5145
5146 #[serde(default = "default_bc_acquisition_count")]
5148 pub acquisition_count: usize,
5149}
5150
5151fn default_bc_acquisition_count() -> usize {
5152 2
5153}
5154
5155impl Default for BusinessCombinationsConfig {
5156 fn default() -> Self {
5157 Self {
5158 enabled: false,
5159 acquisition_count: default_bc_acquisition_count(),
5160 }
5161 }
5162}
5163
5164#[derive(Debug, Clone, Serialize, Deserialize)]
5170pub struct EclConfig {
5171 #[serde(default)]
5173 pub enabled: bool,
5174
5175 #[serde(default = "default_ecl_base_weight")]
5177 pub base_scenario_weight: f64,
5178
5179 #[serde(default = "default_ecl_base_multiplier")]
5181 pub base_scenario_multiplier: f64,
5182
5183 #[serde(default = "default_ecl_optimistic_weight")]
5185 pub optimistic_scenario_weight: f64,
5186
5187 #[serde(default = "default_ecl_optimistic_multiplier")]
5189 pub optimistic_scenario_multiplier: f64,
5190
5191 #[serde(default = "default_ecl_pessimistic_weight")]
5193 pub pessimistic_scenario_weight: f64,
5194
5195 #[serde(default = "default_ecl_pessimistic_multiplier")]
5197 pub pessimistic_scenario_multiplier: f64,
5198}
5199
5200fn default_ecl_base_weight() -> f64 {
5201 0.50
5202}
5203fn default_ecl_base_multiplier() -> f64 {
5204 1.0
5205}
5206fn default_ecl_optimistic_weight() -> f64 {
5207 0.30
5208}
5209fn default_ecl_optimistic_multiplier() -> f64 {
5210 0.8
5211}
5212fn default_ecl_pessimistic_weight() -> f64 {
5213 0.20
5214}
5215fn default_ecl_pessimistic_multiplier() -> f64 {
5216 1.4
5217}
5218
5219impl Default for EclConfig {
5220 fn default() -> Self {
5221 Self {
5222 enabled: false,
5223 base_scenario_weight: default_ecl_base_weight(),
5224 base_scenario_multiplier: default_ecl_base_multiplier(),
5225 optimistic_scenario_weight: default_ecl_optimistic_weight(),
5226 optimistic_scenario_multiplier: default_ecl_optimistic_multiplier(),
5227 pessimistic_scenario_weight: default_ecl_pessimistic_weight(),
5228 pessimistic_scenario_multiplier: default_ecl_pessimistic_multiplier(),
5229 }
5230 }
5231}
5232
5233#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5246pub struct AuditStandardsConfig {
5247 #[serde(default)]
5249 pub enabled: bool,
5250
5251 #[serde(default)]
5253 pub isa_compliance: IsaComplianceConfig,
5254
5255 #[serde(default)]
5257 pub analytical_procedures: AnalyticalProceduresConfig,
5258
5259 #[serde(default)]
5261 pub confirmations: ConfirmationsConfig,
5262
5263 #[serde(default)]
5265 pub opinion: AuditOpinionConfig,
5266
5267 #[serde(default)]
5269 pub generate_audit_trail: bool,
5270
5271 #[serde(default)]
5273 pub sox: SoxComplianceConfig,
5274
5275 #[serde(default)]
5277 pub pcaob: PcaobConfig,
5278}
5279
5280#[derive(Debug, Clone, Serialize, Deserialize)]
5282pub struct IsaComplianceConfig {
5283 #[serde(default)]
5285 pub enabled: bool,
5286
5287 #[serde(default = "default_compliance_level")]
5289 pub compliance_level: String,
5290
5291 #[serde(default = "default_true")]
5293 pub generate_isa_mappings: bool,
5294
5295 #[serde(default = "default_true")]
5297 pub generate_coverage_summary: bool,
5298
5299 #[serde(default)]
5301 pub include_pcaob: bool,
5302
5303 #[serde(default = "default_audit_framework")]
5305 pub framework: String,
5306}
5307
5308fn default_compliance_level() -> String {
5309 "standard".to_string()
5310}
5311
5312fn default_audit_framework() -> String {
5313 "isa".to_string()
5314}
5315
5316impl Default for IsaComplianceConfig {
5317 fn default() -> Self {
5318 Self {
5319 enabled: false,
5320 compliance_level: default_compliance_level(),
5321 generate_isa_mappings: true,
5322 generate_coverage_summary: true,
5323 include_pcaob: false,
5324 framework: default_audit_framework(),
5325 }
5326 }
5327}
5328
5329#[derive(Debug, Clone, Serialize, Deserialize)]
5331pub struct AnalyticalProceduresConfig {
5332 #[serde(default)]
5334 pub enabled: bool,
5335
5336 #[serde(default = "default_procedures_per_account")]
5338 pub procedures_per_account: usize,
5339
5340 #[serde(default = "default_variance_probability")]
5342 pub variance_probability: f64,
5343
5344 #[serde(default = "default_true")]
5346 pub generate_investigations: bool,
5347
5348 #[serde(default = "default_true")]
5350 pub include_ratio_analysis: bool,
5351}
5352
5353fn default_procedures_per_account() -> usize {
5354 3
5355}
5356
5357fn default_variance_probability() -> f64 {
5358 0.20
5359}
5360
5361impl Default for AnalyticalProceduresConfig {
5362 fn default() -> Self {
5363 Self {
5364 enabled: false,
5365 procedures_per_account: default_procedures_per_account(),
5366 variance_probability: default_variance_probability(),
5367 generate_investigations: true,
5368 include_ratio_analysis: true,
5369 }
5370 }
5371}
5372
5373#[derive(Debug, Clone, Serialize, Deserialize)]
5375pub struct ConfirmationsConfig {
5376 #[serde(default)]
5378 pub enabled: bool,
5379
5380 #[serde(default = "default_confirmation_count")]
5382 pub confirmation_count: usize,
5383
5384 #[serde(default = "default_positive_response_rate")]
5386 pub positive_response_rate: f64,
5387
5388 #[serde(default = "default_exception_rate_confirm")]
5390 pub exception_rate: f64,
5391
5392 #[serde(default = "default_non_response_rate")]
5394 pub non_response_rate: f64,
5395
5396 #[serde(default = "default_true")]
5398 pub generate_alternative_procedures: bool,
5399}
5400
5401fn default_confirmation_count() -> usize {
5402 50
5403}
5404
5405fn default_positive_response_rate() -> f64 {
5406 0.85
5407}
5408
5409fn default_exception_rate_confirm() -> f64 {
5410 0.10
5411}
5412
5413fn default_non_response_rate() -> f64 {
5414 0.05
5415}
5416
5417impl Default for ConfirmationsConfig {
5418 fn default() -> Self {
5419 Self {
5420 enabled: false,
5421 confirmation_count: default_confirmation_count(),
5422 positive_response_rate: default_positive_response_rate(),
5423 exception_rate: default_exception_rate_confirm(),
5424 non_response_rate: default_non_response_rate(),
5425 generate_alternative_procedures: true,
5426 }
5427 }
5428}
5429
5430#[derive(Debug, Clone, Serialize, Deserialize)]
5432pub struct AuditOpinionConfig {
5433 #[serde(default)]
5435 pub enabled: bool,
5436
5437 #[serde(default = "default_true")]
5439 pub generate_kam: bool,
5440
5441 #[serde(default = "default_kam_count")]
5443 pub average_kam_count: usize,
5444
5445 #[serde(default = "default_modified_opinion_rate")]
5447 pub modified_opinion_rate: f64,
5448
5449 #[serde(default)]
5451 pub include_emphasis_of_matter: bool,
5452
5453 #[serde(default = "default_true")]
5455 pub include_going_concern: bool,
5456}
5457
5458fn default_kam_count() -> usize {
5459 3
5460}
5461
5462fn default_modified_opinion_rate() -> f64 {
5463 0.05
5464}
5465
5466impl Default for AuditOpinionConfig {
5467 fn default() -> Self {
5468 Self {
5469 enabled: false,
5470 generate_kam: true,
5471 average_kam_count: default_kam_count(),
5472 modified_opinion_rate: default_modified_opinion_rate(),
5473 include_emphasis_of_matter: false,
5474 include_going_concern: true,
5475 }
5476 }
5477}
5478
5479#[derive(Debug, Clone, Serialize, Deserialize)]
5481pub struct SoxComplianceConfig {
5482 #[serde(default)]
5484 pub enabled: bool,
5485
5486 #[serde(default = "default_true")]
5488 pub generate_302_certifications: bool,
5489
5490 #[serde(default = "default_true")]
5492 pub generate_404_assessments: bool,
5493
5494 #[serde(default = "default_sox_materiality_threshold")]
5496 pub materiality_threshold: f64,
5497
5498 #[serde(default = "default_material_weakness_rate")]
5500 pub material_weakness_rate: f64,
5501
5502 #[serde(default = "default_significant_deficiency_rate")]
5504 pub significant_deficiency_rate: f64,
5505}
5506
5507fn default_material_weakness_rate() -> f64 {
5508 0.02
5509}
5510
5511fn default_significant_deficiency_rate() -> f64 {
5512 0.08
5513}
5514
5515impl Default for SoxComplianceConfig {
5516 fn default() -> Self {
5517 Self {
5518 enabled: false,
5519 generate_302_certifications: true,
5520 generate_404_assessments: true,
5521 materiality_threshold: default_sox_materiality_threshold(),
5522 material_weakness_rate: default_material_weakness_rate(),
5523 significant_deficiency_rate: default_significant_deficiency_rate(),
5524 }
5525 }
5526}
5527
5528#[derive(Debug, Clone, Serialize, Deserialize)]
5530pub struct PcaobConfig {
5531 #[serde(default)]
5533 pub enabled: bool,
5534
5535 #[serde(default)]
5537 pub is_pcaob_audit: bool,
5538
5539 #[serde(default = "default_true")]
5541 pub generate_cam: bool,
5542
5543 #[serde(default)]
5545 pub include_icfr_opinion: bool,
5546
5547 #[serde(default)]
5549 pub generate_standard_mappings: bool,
5550}
5551
5552impl Default for PcaobConfig {
5553 fn default() -> Self {
5554 Self {
5555 enabled: false,
5556 is_pcaob_audit: false,
5557 generate_cam: true,
5558 include_icfr_opinion: false,
5559 generate_standard_mappings: false,
5560 }
5561 }
5562}
5563
5564#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5577pub struct AdvancedDistributionConfig {
5578 #[serde(default)]
5580 pub enabled: bool,
5581
5582 #[serde(default)]
5584 pub amounts: MixtureDistributionSchemaConfig,
5585
5586 #[serde(default)]
5588 pub correlations: CorrelationSchemaConfig,
5589
5590 #[serde(default)]
5592 pub conditional: Vec<ConditionalDistributionSchemaConfig>,
5593
5594 #[serde(default)]
5596 pub regime_changes: RegimeChangeSchemaConfig,
5597
5598 #[serde(default)]
5600 pub industry_profile: Option<IndustryProfileType>,
5601
5602 #[serde(default)]
5604 pub validation: StatisticalValidationSchemaConfig,
5605}
5606
5607#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
5609#[serde(rename_all = "snake_case")]
5610pub enum IndustryProfileType {
5611 Retail,
5613 Manufacturing,
5615 FinancialServices,
5617 Healthcare,
5619 Technology,
5621}
5622
5623#[derive(Debug, Clone, Serialize, Deserialize)]
5625pub struct MixtureDistributionSchemaConfig {
5626 #[serde(default)]
5628 pub enabled: bool,
5629
5630 #[serde(default = "default_mixture_type")]
5632 pub distribution_type: MixtureDistributionType,
5633
5634 #[serde(default)]
5636 pub components: Vec<MixtureComponentConfig>,
5637
5638 #[serde(default = "default_min_amount")]
5640 pub min_value: f64,
5641
5642 #[serde(default)]
5644 pub max_value: Option<f64>,
5645
5646 #[serde(default = "default_decimal_places")]
5648 pub decimal_places: u8,
5649}
5650
5651fn default_mixture_type() -> MixtureDistributionType {
5652 MixtureDistributionType::LogNormal
5653}
5654
5655fn default_min_amount() -> f64 {
5656 0.01
5657}
5658
5659fn default_decimal_places() -> u8 {
5660 2
5661}
5662
5663impl Default for MixtureDistributionSchemaConfig {
5664 fn default() -> Self {
5665 Self {
5666 enabled: false,
5667 distribution_type: MixtureDistributionType::LogNormal,
5668 components: Vec::new(),
5669 min_value: 0.01,
5670 max_value: None,
5671 decimal_places: 2,
5672 }
5673 }
5674}
5675
5676#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5678#[serde(rename_all = "snake_case")]
5679pub enum MixtureDistributionType {
5680 Gaussian,
5682 #[default]
5684 LogNormal,
5685}
5686
5687#[derive(Debug, Clone, Serialize, Deserialize)]
5689pub struct MixtureComponentConfig {
5690 pub weight: f64,
5692
5693 pub mu: f64,
5695
5696 pub sigma: f64,
5698
5699 #[serde(default)]
5701 pub label: Option<String>,
5702}
5703
5704#[derive(Debug, Clone, Serialize, Deserialize)]
5706pub struct CorrelationSchemaConfig {
5707 #[serde(default)]
5709 pub enabled: bool,
5710
5711 #[serde(default)]
5713 pub copula_type: CopulaSchemaType,
5714
5715 #[serde(default)]
5717 pub fields: Vec<CorrelatedFieldConfig>,
5718
5719 #[serde(default)]
5722 pub matrix: Vec<f64>,
5723
5724 #[serde(default)]
5726 pub expected_correlations: Vec<ExpectedCorrelationConfig>,
5727}
5728
5729impl Default for CorrelationSchemaConfig {
5730 fn default() -> Self {
5731 Self {
5732 enabled: false,
5733 copula_type: CopulaSchemaType::Gaussian,
5734 fields: Vec::new(),
5735 matrix: Vec::new(),
5736 expected_correlations: Vec::new(),
5737 }
5738 }
5739}
5740
5741#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5743#[serde(rename_all = "snake_case")]
5744pub enum CopulaSchemaType {
5745 #[default]
5747 Gaussian,
5748 Clayton,
5750 Gumbel,
5752 Frank,
5754 StudentT,
5756}
5757
5758#[derive(Debug, Clone, Serialize, Deserialize)]
5760pub struct CorrelatedFieldConfig {
5761 pub name: String,
5763
5764 #[serde(default)]
5766 pub distribution: MarginalDistributionConfig,
5767}
5768
5769#[derive(Debug, Clone, Serialize, Deserialize)]
5771#[serde(tag = "type", rename_all = "snake_case")]
5772pub enum MarginalDistributionConfig {
5773 Normal {
5775 mu: f64,
5777 sigma: f64,
5779 },
5780 LogNormal {
5782 mu: f64,
5784 sigma: f64,
5786 },
5787 Uniform {
5789 min: f64,
5791 max: f64,
5793 },
5794 DiscreteUniform {
5796 min: i32,
5798 max: i32,
5800 },
5801}
5802
5803impl Default for MarginalDistributionConfig {
5804 fn default() -> Self {
5805 Self::Normal {
5806 mu: 0.0,
5807 sigma: 1.0,
5808 }
5809 }
5810}
5811
5812#[derive(Debug, Clone, Serialize, Deserialize)]
5814pub struct ExpectedCorrelationConfig {
5815 pub field1: String,
5817 pub field2: String,
5819 pub expected_r: f64,
5821 #[serde(default = "default_correlation_tolerance")]
5823 pub tolerance: f64,
5824}
5825
5826fn default_correlation_tolerance() -> f64 {
5827 0.10
5828}
5829
5830#[derive(Debug, Clone, Serialize, Deserialize)]
5832pub struct ConditionalDistributionSchemaConfig {
5833 pub output_field: String,
5835
5836 pub input_field: String,
5838
5839 #[serde(default)]
5841 pub breakpoints: Vec<ConditionalBreakpointConfig>,
5842
5843 #[serde(default)]
5845 pub default_distribution: ConditionalDistributionParamsConfig,
5846
5847 #[serde(default)]
5849 pub min_value: Option<f64>,
5850
5851 #[serde(default)]
5853 pub max_value: Option<f64>,
5854
5855 #[serde(default = "default_decimal_places")]
5857 pub decimal_places: u8,
5858}
5859
5860#[derive(Debug, Clone, Serialize, Deserialize)]
5862pub struct ConditionalBreakpointConfig {
5863 pub threshold: f64,
5865
5866 pub distribution: ConditionalDistributionParamsConfig,
5868}
5869
5870#[derive(Debug, Clone, Serialize, Deserialize)]
5872#[serde(tag = "type", rename_all = "snake_case")]
5873pub enum ConditionalDistributionParamsConfig {
5874 Fixed {
5876 value: f64,
5878 },
5879 Normal {
5881 mu: f64,
5883 sigma: f64,
5885 },
5886 LogNormal {
5888 mu: f64,
5890 sigma: f64,
5892 },
5893 Uniform {
5895 min: f64,
5897 max: f64,
5899 },
5900 Beta {
5902 alpha: f64,
5904 beta: f64,
5906 min: f64,
5908 max: f64,
5910 },
5911 Discrete {
5913 values: Vec<f64>,
5915 weights: Vec<f64>,
5917 },
5918}
5919
5920impl Default for ConditionalDistributionParamsConfig {
5921 fn default() -> Self {
5922 Self::Normal {
5923 mu: 0.0,
5924 sigma: 1.0,
5925 }
5926 }
5927}
5928
5929#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5931pub struct RegimeChangeSchemaConfig {
5932 #[serde(default)]
5934 pub enabled: bool,
5935
5936 #[serde(default)]
5938 pub changes: Vec<RegimeChangeEventConfig>,
5939
5940 #[serde(default)]
5942 pub economic_cycle: Option<EconomicCycleSchemaConfig>,
5943
5944 #[serde(default)]
5946 pub parameter_drifts: Vec<ParameterDriftSchemaConfig>,
5947}
5948
5949#[derive(Debug, Clone, Serialize, Deserialize)]
5951pub struct RegimeChangeEventConfig {
5952 pub date: String,
5954
5955 pub change_type: RegimeChangeTypeConfig,
5957
5958 #[serde(default)]
5960 pub description: Option<String>,
5961
5962 #[serde(default)]
5964 pub effects: Vec<RegimeEffectConfig>,
5965}
5966
5967#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
5969#[serde(rename_all = "snake_case")]
5970pub enum RegimeChangeTypeConfig {
5971 Acquisition,
5973 Divestiture,
5975 PriceIncrease,
5977 PriceDecrease,
5979 ProductLaunch,
5981 ProductDiscontinuation,
5983 PolicyChange,
5985 CompetitorEntry,
5987 Custom,
5989}
5990
5991#[derive(Debug, Clone, Serialize, Deserialize)]
5993pub struct RegimeEffectConfig {
5994 pub field: String,
5996
5997 pub multiplier: f64,
5999}
6000
6001#[derive(Debug, Clone, Serialize, Deserialize)]
6003pub struct EconomicCycleSchemaConfig {
6004 #[serde(default)]
6006 pub enabled: bool,
6007
6008 #[serde(default = "default_cycle_period")]
6010 pub period_months: u32,
6011
6012 #[serde(default = "default_cycle_amplitude")]
6014 pub amplitude: f64,
6015
6016 #[serde(default)]
6018 pub phase_offset: u32,
6019
6020 #[serde(default)]
6022 pub recessions: Vec<RecessionPeriodConfig>,
6023}
6024
6025fn default_cycle_period() -> u32 {
6026 48
6027}
6028
6029fn default_cycle_amplitude() -> f64 {
6030 0.15
6031}
6032
6033impl Default for EconomicCycleSchemaConfig {
6034 fn default() -> Self {
6035 Self {
6036 enabled: false,
6037 period_months: 48,
6038 amplitude: 0.15,
6039 phase_offset: 0,
6040 recessions: Vec::new(),
6041 }
6042 }
6043}
6044
6045#[derive(Debug, Clone, Serialize, Deserialize)]
6047pub struct RecessionPeriodConfig {
6048 pub start_month: u32,
6050
6051 pub duration_months: u32,
6053
6054 #[serde(default = "default_recession_severity")]
6056 pub severity: f64,
6057}
6058
6059fn default_recession_severity() -> f64 {
6060 0.20
6061}
6062
6063#[derive(Debug, Clone, Serialize, Deserialize)]
6065pub struct ParameterDriftSchemaConfig {
6066 pub parameter: String,
6068
6069 pub drift_type: ParameterDriftTypeConfig,
6071
6072 pub start_value: f64,
6074
6075 pub end_value: f64,
6077
6078 #[serde(default)]
6080 pub start_period: u32,
6081
6082 #[serde(default)]
6084 pub end_period: Option<u32>,
6085}
6086
6087#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
6089#[serde(rename_all = "snake_case")]
6090pub enum ParameterDriftTypeConfig {
6091 #[default]
6093 Linear,
6094 Exponential,
6096 Logistic,
6098 Step,
6100}
6101
6102#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6104pub struct StatisticalValidationSchemaConfig {
6105 #[serde(default)]
6107 pub enabled: bool,
6108
6109 #[serde(default)]
6111 pub tests: Vec<StatisticalTestConfig>,
6112
6113 #[serde(default)]
6115 pub reporting: ValidationReportingConfig,
6116}
6117
6118#[derive(Debug, Clone, Serialize, Deserialize)]
6120#[serde(tag = "type", rename_all = "snake_case")]
6121pub enum StatisticalTestConfig {
6122 BenfordFirstDigit {
6124 #[serde(default = "default_benford_threshold")]
6126 threshold_mad: f64,
6127 #[serde(default = "default_benford_warning")]
6129 warning_mad: f64,
6130 },
6131 DistributionFit {
6133 target: TargetDistributionConfig,
6135 #[serde(default = "default_ks_significance")]
6137 ks_significance: f64,
6138 #[serde(default)]
6140 method: DistributionFitMethod,
6141 },
6142 CorrelationCheck {
6144 expected_correlations: Vec<ExpectedCorrelationConfig>,
6146 },
6147 ChiSquared {
6149 #[serde(default = "default_chi_squared_bins")]
6151 bins: usize,
6152 #[serde(default = "default_chi_squared_significance")]
6154 significance: f64,
6155 },
6156 AndersonDarling {
6158 target: TargetDistributionConfig,
6160 #[serde(default = "default_ad_significance")]
6162 significance: f64,
6163 },
6164}
6165
6166fn default_benford_threshold() -> f64 {
6167 0.015
6168}
6169
6170fn default_benford_warning() -> f64 {
6171 0.010
6172}
6173
6174fn default_ks_significance() -> f64 {
6175 0.05
6176}
6177
6178fn default_chi_squared_bins() -> usize {
6179 10
6180}
6181
6182fn default_chi_squared_significance() -> f64 {
6183 0.05
6184}
6185
6186fn default_ad_significance() -> f64 {
6187 0.05
6188}
6189
6190#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
6192#[serde(rename_all = "snake_case")]
6193pub enum TargetDistributionConfig {
6194 Normal,
6196 #[default]
6198 LogNormal,
6199 Exponential,
6201 Uniform,
6203}
6204
6205#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
6207#[serde(rename_all = "snake_case")]
6208pub enum DistributionFitMethod {
6209 #[default]
6211 KolmogorovSmirnov,
6212 AndersonDarling,
6214 ChiSquared,
6216}
6217
6218#[derive(Debug, Clone, Serialize, Deserialize)]
6220pub struct ValidationReportingConfig {
6221 #[serde(default)]
6223 pub output_report: bool,
6224
6225 #[serde(default)]
6227 pub format: ValidationReportFormat,
6228
6229 #[serde(default)]
6231 pub fail_on_error: bool,
6232
6233 #[serde(default = "default_true")]
6235 pub include_details: bool,
6236}
6237
6238impl Default for ValidationReportingConfig {
6239 fn default() -> Self {
6240 Self {
6241 output_report: false,
6242 format: ValidationReportFormat::Json,
6243 fail_on_error: false,
6244 include_details: true,
6245 }
6246 }
6247}
6248
6249#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
6251#[serde(rename_all = "snake_case")]
6252pub enum ValidationReportFormat {
6253 #[default]
6255 Json,
6256 Yaml,
6258 Html,
6260}
6261
6262#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6274pub struct TemporalPatternsConfig {
6275 #[serde(default)]
6277 pub enabled: bool,
6278
6279 #[serde(default)]
6281 pub business_days: BusinessDaySchemaConfig,
6282
6283 #[serde(default)]
6285 pub calendars: CalendarSchemaConfig,
6286
6287 #[serde(default)]
6289 pub period_end: PeriodEndSchemaConfig,
6290
6291 #[serde(default)]
6293 pub processing_lags: ProcessingLagSchemaConfig,
6294
6295 #[serde(default)]
6297 pub fiscal_calendar: FiscalCalendarSchemaConfig,
6298
6299 #[serde(default)]
6301 pub intraday: IntraDaySchemaConfig,
6302
6303 #[serde(default)]
6305 pub timezones: TimezoneSchemaConfig,
6306}
6307
6308#[derive(Debug, Clone, Serialize, Deserialize)]
6310pub struct BusinessDaySchemaConfig {
6311 #[serde(default = "default_true")]
6313 pub enabled: bool,
6314
6315 #[serde(default = "default_half_day_policy")]
6317 pub half_day_policy: String,
6318
6319 #[serde(default)]
6321 pub settlement_rules: SettlementRulesSchemaConfig,
6322
6323 #[serde(default = "default_month_end_convention")]
6325 pub month_end_convention: String,
6326
6327 #[serde(default)]
6329 pub weekend_days: Option<Vec<String>>,
6330}
6331
6332fn default_half_day_policy() -> String {
6333 "half_day".to_string()
6334}
6335
6336fn default_month_end_convention() -> String {
6337 "modified_following".to_string()
6338}
6339
6340impl Default for BusinessDaySchemaConfig {
6341 fn default() -> Self {
6342 Self {
6343 enabled: true,
6344 half_day_policy: "half_day".to_string(),
6345 settlement_rules: SettlementRulesSchemaConfig::default(),
6346 month_end_convention: "modified_following".to_string(),
6347 weekend_days: None,
6348 }
6349 }
6350}
6351
6352#[derive(Debug, Clone, Serialize, Deserialize)]
6354pub struct SettlementRulesSchemaConfig {
6355 #[serde(default = "default_settlement_2")]
6357 pub equity_days: i32,
6358
6359 #[serde(default = "default_settlement_1")]
6361 pub government_bonds_days: i32,
6362
6363 #[serde(default = "default_settlement_2")]
6365 pub fx_spot_days: i32,
6366
6367 #[serde(default = "default_settlement_2")]
6369 pub corporate_bonds_days: i32,
6370
6371 #[serde(default = "default_wire_cutoff")]
6373 pub wire_cutoff_time: String,
6374
6375 #[serde(default = "default_settlement_1")]
6377 pub wire_international_days: i32,
6378
6379 #[serde(default = "default_settlement_1")]
6381 pub ach_days: i32,
6382}
6383
6384fn default_settlement_1() -> i32 {
6385 1
6386}
6387
6388fn default_settlement_2() -> i32 {
6389 2
6390}
6391
6392fn default_wire_cutoff() -> String {
6393 "14:00".to_string()
6394}
6395
6396impl Default for SettlementRulesSchemaConfig {
6397 fn default() -> Self {
6398 Self {
6399 equity_days: 2,
6400 government_bonds_days: 1,
6401 fx_spot_days: 2,
6402 corporate_bonds_days: 2,
6403 wire_cutoff_time: "14:00".to_string(),
6404 wire_international_days: 1,
6405 ach_days: 1,
6406 }
6407 }
6408}
6409
6410#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6412pub struct CalendarSchemaConfig {
6413 #[serde(default)]
6415 pub regions: Vec<String>,
6416
6417 #[serde(default)]
6419 pub custom_holidays: Vec<CustomHolidaySchemaConfig>,
6420}
6421
6422#[derive(Debug, Clone, Serialize, Deserialize)]
6424pub struct CustomHolidaySchemaConfig {
6425 pub name: String,
6427 pub month: u8,
6429 pub day: u8,
6431 #[serde(default = "default_holiday_multiplier")]
6433 pub activity_multiplier: f64,
6434}
6435
6436fn default_holiday_multiplier() -> f64 {
6437 0.05
6438}
6439
6440#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6442pub struct PeriodEndSchemaConfig {
6443 #[serde(default)]
6445 pub model: Option<String>,
6446
6447 #[serde(default)]
6449 pub month_end: Option<PeriodEndModelSchemaConfig>,
6450
6451 #[serde(default)]
6453 pub quarter_end: Option<PeriodEndModelSchemaConfig>,
6454
6455 #[serde(default)]
6457 pub year_end: Option<PeriodEndModelSchemaConfig>,
6458}
6459
6460#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6462pub struct PeriodEndModelSchemaConfig {
6463 #[serde(default)]
6465 pub inherit_from: Option<String>,
6466
6467 #[serde(default)]
6469 pub additional_multiplier: Option<f64>,
6470
6471 #[serde(default)]
6473 pub start_day: Option<i32>,
6474
6475 #[serde(default)]
6477 pub base_multiplier: Option<f64>,
6478
6479 #[serde(default)]
6481 pub peak_multiplier: Option<f64>,
6482
6483 #[serde(default)]
6485 pub decay_rate: Option<f64>,
6486
6487 #[serde(default)]
6489 pub sustained_high_days: Option<i32>,
6490}
6491
6492#[derive(Debug, Clone, Serialize, Deserialize)]
6494pub struct ProcessingLagSchemaConfig {
6495 #[serde(default = "default_true")]
6497 pub enabled: bool,
6498
6499 #[serde(default)]
6501 pub sales_order_lag: Option<LagDistributionSchemaConfig>,
6502
6503 #[serde(default)]
6505 pub purchase_order_lag: Option<LagDistributionSchemaConfig>,
6506
6507 #[serde(default)]
6509 pub goods_receipt_lag: Option<LagDistributionSchemaConfig>,
6510
6511 #[serde(default)]
6513 pub invoice_receipt_lag: Option<LagDistributionSchemaConfig>,
6514
6515 #[serde(default)]
6517 pub invoice_issue_lag: Option<LagDistributionSchemaConfig>,
6518
6519 #[serde(default)]
6521 pub payment_lag: Option<LagDistributionSchemaConfig>,
6522
6523 #[serde(default)]
6525 pub journal_entry_lag: Option<LagDistributionSchemaConfig>,
6526
6527 #[serde(default)]
6529 pub cross_day_posting: Option<CrossDayPostingSchemaConfig>,
6530}
6531
6532impl Default for ProcessingLagSchemaConfig {
6533 fn default() -> Self {
6534 Self {
6535 enabled: true,
6536 sales_order_lag: None,
6537 purchase_order_lag: None,
6538 goods_receipt_lag: None,
6539 invoice_receipt_lag: None,
6540 invoice_issue_lag: None,
6541 payment_lag: None,
6542 journal_entry_lag: None,
6543 cross_day_posting: None,
6544 }
6545 }
6546}
6547
6548#[derive(Debug, Clone, Serialize, Deserialize)]
6550pub struct LagDistributionSchemaConfig {
6551 pub mu: f64,
6553 pub sigma: f64,
6555 #[serde(default)]
6557 pub min_hours: Option<f64>,
6558 #[serde(default)]
6560 pub max_hours: Option<f64>,
6561}
6562
6563#[derive(Debug, Clone, Serialize, Deserialize)]
6565pub struct CrossDayPostingSchemaConfig {
6566 #[serde(default = "default_true")]
6568 pub enabled: bool,
6569
6570 #[serde(default)]
6573 pub probability_by_hour: std::collections::HashMap<u8, f64>,
6574}
6575
6576impl Default for CrossDayPostingSchemaConfig {
6577 fn default() -> Self {
6578 let mut probability_by_hour = std::collections::HashMap::new();
6579 probability_by_hour.insert(17, 0.3);
6580 probability_by_hour.insert(18, 0.6);
6581 probability_by_hour.insert(19, 0.8);
6582 probability_by_hour.insert(20, 0.9);
6583 probability_by_hour.insert(21, 0.95);
6584 probability_by_hour.insert(22, 0.99);
6585
6586 Self {
6587 enabled: true,
6588 probability_by_hour,
6589 }
6590 }
6591}
6592
6593#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6602pub struct FiscalCalendarSchemaConfig {
6603 #[serde(default)]
6605 pub enabled: bool,
6606
6607 #[serde(default = "default_fiscal_calendar_type")]
6609 pub calendar_type: String,
6610
6611 #[serde(default)]
6613 pub year_start_month: Option<u8>,
6614
6615 #[serde(default)]
6617 pub year_start_day: Option<u8>,
6618
6619 #[serde(default)]
6621 pub four_four_five: Option<FourFourFiveSchemaConfig>,
6622}
6623
6624fn default_fiscal_calendar_type() -> String {
6625 "calendar_year".to_string()
6626}
6627
6628#[derive(Debug, Clone, Serialize, Deserialize)]
6630pub struct FourFourFiveSchemaConfig {
6631 #[serde(default = "default_week_pattern")]
6633 pub pattern: String,
6634
6635 #[serde(default = "default_anchor_type")]
6637 pub anchor_type: String,
6638
6639 #[serde(default = "default_anchor_month")]
6641 pub anchor_month: u8,
6642
6643 #[serde(default = "default_leap_week_placement")]
6645 pub leap_week_placement: String,
6646}
6647
6648fn default_week_pattern() -> String {
6649 "four_four_five".to_string()
6650}
6651
6652fn default_anchor_type() -> String {
6653 "last_saturday".to_string()
6654}
6655
6656fn default_anchor_month() -> u8 {
6657 1 }
6659
6660fn default_leap_week_placement() -> String {
6661 "q4_period3".to_string()
6662}
6663
6664impl Default for FourFourFiveSchemaConfig {
6665 fn default() -> Self {
6666 Self {
6667 pattern: "four_four_five".to_string(),
6668 anchor_type: "last_saturday".to_string(),
6669 anchor_month: 1,
6670 leap_week_placement: "q4_period3".to_string(),
6671 }
6672 }
6673}
6674
6675#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6684pub struct IntraDaySchemaConfig {
6685 #[serde(default)]
6687 pub enabled: bool,
6688
6689 #[serde(default)]
6691 pub segments: Vec<IntraDaySegmentSchemaConfig>,
6692}
6693
6694#[derive(Debug, Clone, Serialize, Deserialize)]
6696pub struct IntraDaySegmentSchemaConfig {
6697 pub name: String,
6699
6700 pub start: String,
6702
6703 pub end: String,
6705
6706 #[serde(default = "default_multiplier")]
6708 pub multiplier: f64,
6709
6710 #[serde(default = "default_posting_type")]
6712 pub posting_type: String,
6713}
6714
6715fn default_multiplier() -> f64 {
6716 1.0
6717}
6718
6719fn default_posting_type() -> String {
6720 "both".to_string()
6721}
6722
6723#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6729pub struct TimezoneSchemaConfig {
6730 #[serde(default)]
6732 pub enabled: bool,
6733
6734 #[serde(default = "default_timezone")]
6736 pub default_timezone: String,
6737
6738 #[serde(default = "default_consolidation_timezone")]
6740 pub consolidation_timezone: String,
6741
6742 #[serde(default)]
6745 pub entity_mappings: Vec<EntityTimezoneMapping>,
6746}
6747
6748fn default_timezone() -> String {
6749 "America/New_York".to_string()
6750}
6751
6752fn default_consolidation_timezone() -> String {
6753 "UTC".to_string()
6754}
6755
6756#[derive(Debug, Clone, Serialize, Deserialize)]
6758pub struct EntityTimezoneMapping {
6759 pub pattern: String,
6761
6762 pub timezone: String,
6764}
6765
6766#[derive(Debug, Clone, Serialize, Deserialize)]
6772pub struct VendorNetworkSchemaConfig {
6773 #[serde(default)]
6775 pub enabled: bool,
6776
6777 #[serde(default = "default_vendor_tier_depth")]
6779 pub depth: u8,
6780
6781 #[serde(default)]
6783 pub tier1: TierCountSchemaConfig,
6784
6785 #[serde(default)]
6787 pub tier2_per_parent: TierCountSchemaConfig,
6788
6789 #[serde(default)]
6791 pub tier3_per_parent: TierCountSchemaConfig,
6792
6793 #[serde(default)]
6795 pub clusters: VendorClusterSchemaConfig,
6796
6797 #[serde(default)]
6799 pub dependencies: DependencySchemaConfig,
6800}
6801
6802fn default_vendor_tier_depth() -> u8 {
6803 3
6804}
6805
6806impl Default for VendorNetworkSchemaConfig {
6807 fn default() -> Self {
6808 Self {
6809 enabled: false,
6810 depth: 3,
6811 tier1: TierCountSchemaConfig { min: 50, max: 100 },
6812 tier2_per_parent: TierCountSchemaConfig { min: 4, max: 10 },
6813 tier3_per_parent: TierCountSchemaConfig { min: 2, max: 5 },
6814 clusters: VendorClusterSchemaConfig::default(),
6815 dependencies: DependencySchemaConfig::default(),
6816 }
6817 }
6818}
6819
6820#[derive(Debug, Clone, Serialize, Deserialize)]
6822pub struct TierCountSchemaConfig {
6823 #[serde(default = "default_tier_min")]
6825 pub min: usize,
6826
6827 #[serde(default = "default_tier_max")]
6829 pub max: usize,
6830}
6831
6832fn default_tier_min() -> usize {
6833 5
6834}
6835
6836fn default_tier_max() -> usize {
6837 20
6838}
6839
6840impl Default for TierCountSchemaConfig {
6841 fn default() -> Self {
6842 Self {
6843 min: default_tier_min(),
6844 max: default_tier_max(),
6845 }
6846 }
6847}
6848
6849#[derive(Debug, Clone, Serialize, Deserialize)]
6851pub struct VendorClusterSchemaConfig {
6852 #[serde(default = "default_reliable_strategic")]
6854 pub reliable_strategic: f64,
6855
6856 #[serde(default = "default_standard_operational")]
6858 pub standard_operational: f64,
6859
6860 #[serde(default = "default_transactional")]
6862 pub transactional: f64,
6863
6864 #[serde(default = "default_problematic")]
6866 pub problematic: f64,
6867}
6868
6869fn default_reliable_strategic() -> f64 {
6870 0.20
6871}
6872
6873fn default_standard_operational() -> f64 {
6874 0.50
6875}
6876
6877fn default_transactional() -> f64 {
6878 0.25
6879}
6880
6881fn default_problematic() -> f64 {
6882 0.05
6883}
6884
6885impl Default for VendorClusterSchemaConfig {
6886 fn default() -> Self {
6887 Self {
6888 reliable_strategic: 0.20,
6889 standard_operational: 0.50,
6890 transactional: 0.25,
6891 problematic: 0.05,
6892 }
6893 }
6894}
6895
6896#[derive(Debug, Clone, Serialize, Deserialize)]
6898pub struct DependencySchemaConfig {
6899 #[serde(default = "default_max_single_vendor")]
6901 pub max_single_vendor_concentration: f64,
6902
6903 #[serde(default = "default_max_top5")]
6905 pub top_5_concentration: f64,
6906
6907 #[serde(default = "default_single_source_percent")]
6909 pub single_source_percent: f64,
6910}
6911
6912fn default_max_single_vendor() -> f64 {
6913 0.15
6914}
6915
6916fn default_max_top5() -> f64 {
6917 0.45
6918}
6919
6920fn default_single_source_percent() -> f64 {
6921 0.05
6922}
6923
6924impl Default for DependencySchemaConfig {
6925 fn default() -> Self {
6926 Self {
6927 max_single_vendor_concentration: 0.15,
6928 top_5_concentration: 0.45,
6929 single_source_percent: 0.05,
6930 }
6931 }
6932}
6933
6934#[derive(Debug, Clone, Default, Serialize, Deserialize)]
6940pub struct CustomerSegmentationSchemaConfig {
6941 #[serde(default)]
6943 pub enabled: bool,
6944
6945 #[serde(default)]
6947 pub value_segments: ValueSegmentsSchemaConfig,
6948
6949 #[serde(default)]
6951 pub lifecycle: LifecycleSchemaConfig,
6952
6953 #[serde(default)]
6955 pub networks: CustomerNetworksSchemaConfig,
6956}
6957
6958#[derive(Debug, Clone, Serialize, Deserialize)]
6960pub struct ValueSegmentsSchemaConfig {
6961 #[serde(default)]
6963 pub enterprise: SegmentDetailSchemaConfig,
6964
6965 #[serde(default)]
6967 pub mid_market: SegmentDetailSchemaConfig,
6968
6969 #[serde(default)]
6971 pub smb: SegmentDetailSchemaConfig,
6972
6973 #[serde(default)]
6975 pub consumer: SegmentDetailSchemaConfig,
6976}
6977
6978impl Default for ValueSegmentsSchemaConfig {
6979 fn default() -> Self {
6980 Self {
6981 enterprise: SegmentDetailSchemaConfig {
6982 revenue_share: 0.40,
6983 customer_share: 0.05,
6984 avg_order_value_range: "50000+".to_string(),
6985 },
6986 mid_market: SegmentDetailSchemaConfig {
6987 revenue_share: 0.35,
6988 customer_share: 0.20,
6989 avg_order_value_range: "5000-50000".to_string(),
6990 },
6991 smb: SegmentDetailSchemaConfig {
6992 revenue_share: 0.20,
6993 customer_share: 0.50,
6994 avg_order_value_range: "500-5000".to_string(),
6995 },
6996 consumer: SegmentDetailSchemaConfig {
6997 revenue_share: 0.05,
6998 customer_share: 0.25,
6999 avg_order_value_range: "50-500".to_string(),
7000 },
7001 }
7002 }
7003}
7004
7005#[derive(Debug, Clone, Serialize, Deserialize)]
7007pub struct SegmentDetailSchemaConfig {
7008 #[serde(default)]
7010 pub revenue_share: f64,
7011
7012 #[serde(default)]
7014 pub customer_share: f64,
7015
7016 #[serde(default)]
7018 pub avg_order_value_range: String,
7019}
7020
7021impl Default for SegmentDetailSchemaConfig {
7022 fn default() -> Self {
7023 Self {
7024 revenue_share: 0.25,
7025 customer_share: 0.25,
7026 avg_order_value_range: "1000-10000".to_string(),
7027 }
7028 }
7029}
7030
7031#[derive(Debug, Clone, Serialize, Deserialize)]
7033pub struct LifecycleSchemaConfig {
7034 #[serde(default)]
7036 pub prospect_rate: f64,
7037
7038 #[serde(default = "default_new_rate")]
7040 pub new_rate: f64,
7041
7042 #[serde(default = "default_growth_rate")]
7044 pub growth_rate: f64,
7045
7046 #[serde(default = "default_mature_rate")]
7048 pub mature_rate: f64,
7049
7050 #[serde(default = "default_at_risk_rate")]
7052 pub at_risk_rate: f64,
7053
7054 #[serde(default = "default_churned_rate")]
7056 pub churned_rate: f64,
7057
7058 #[serde(default)]
7060 pub won_back_rate: f64,
7061}
7062
7063fn default_new_rate() -> f64 {
7064 0.10
7065}
7066
7067fn default_growth_rate() -> f64 {
7068 0.15
7069}
7070
7071fn default_mature_rate() -> f64 {
7072 0.60
7073}
7074
7075fn default_at_risk_rate() -> f64 {
7076 0.10
7077}
7078
7079fn default_churned_rate() -> f64 {
7080 0.05
7081}
7082
7083impl Default for LifecycleSchemaConfig {
7084 fn default() -> Self {
7085 Self {
7086 prospect_rate: 0.0,
7087 new_rate: 0.10,
7088 growth_rate: 0.15,
7089 mature_rate: 0.60,
7090 at_risk_rate: 0.10,
7091 churned_rate: 0.05,
7092 won_back_rate: 0.0,
7093 }
7094 }
7095}
7096
7097#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7099pub struct CustomerNetworksSchemaConfig {
7100 #[serde(default)]
7102 pub referrals: ReferralSchemaConfig,
7103
7104 #[serde(default)]
7106 pub corporate_hierarchies: HierarchySchemaConfig,
7107}
7108
7109#[derive(Debug, Clone, Serialize, Deserialize)]
7111pub struct ReferralSchemaConfig {
7112 #[serde(default = "default_true")]
7114 pub enabled: bool,
7115
7116 #[serde(default = "default_referral_rate")]
7118 pub referral_rate: f64,
7119}
7120
7121fn default_referral_rate() -> f64 {
7122 0.15
7123}
7124
7125impl Default for ReferralSchemaConfig {
7126 fn default() -> Self {
7127 Self {
7128 enabled: true,
7129 referral_rate: 0.15,
7130 }
7131 }
7132}
7133
7134#[derive(Debug, Clone, Serialize, Deserialize)]
7136pub struct HierarchySchemaConfig {
7137 #[serde(default = "default_true")]
7139 pub enabled: bool,
7140
7141 #[serde(default = "default_hierarchy_rate")]
7143 pub probability: f64,
7144}
7145
7146fn default_hierarchy_rate() -> f64 {
7147 0.30
7148}
7149
7150impl Default for HierarchySchemaConfig {
7151 fn default() -> Self {
7152 Self {
7153 enabled: true,
7154 probability: 0.30,
7155 }
7156 }
7157}
7158
7159#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7165pub struct RelationshipStrengthSchemaConfig {
7166 #[serde(default)]
7168 pub enabled: bool,
7169
7170 #[serde(default)]
7172 pub calculation: StrengthCalculationSchemaConfig,
7173
7174 #[serde(default)]
7176 pub thresholds: StrengthThresholdsSchemaConfig,
7177}
7178
7179#[derive(Debug, Clone, Serialize, Deserialize)]
7181pub struct StrengthCalculationSchemaConfig {
7182 #[serde(default = "default_volume_weight")]
7184 pub transaction_volume_weight: f64,
7185
7186 #[serde(default = "default_count_weight")]
7188 pub transaction_count_weight: f64,
7189
7190 #[serde(default = "default_duration_weight")]
7192 pub relationship_duration_weight: f64,
7193
7194 #[serde(default = "default_recency_weight")]
7196 pub recency_weight: f64,
7197
7198 #[serde(default = "default_mutual_weight")]
7200 pub mutual_connections_weight: f64,
7201
7202 #[serde(default = "default_recency_half_life")]
7204 pub recency_half_life_days: u32,
7205}
7206
7207fn default_volume_weight() -> f64 {
7208 0.30
7209}
7210
7211fn default_count_weight() -> f64 {
7212 0.25
7213}
7214
7215fn default_duration_weight() -> f64 {
7216 0.20
7217}
7218
7219fn default_recency_weight() -> f64 {
7220 0.15
7221}
7222
7223fn default_mutual_weight() -> f64 {
7224 0.10
7225}
7226
7227fn default_recency_half_life() -> u32 {
7228 90
7229}
7230
7231impl Default for StrengthCalculationSchemaConfig {
7232 fn default() -> Self {
7233 Self {
7234 transaction_volume_weight: 0.30,
7235 transaction_count_weight: 0.25,
7236 relationship_duration_weight: 0.20,
7237 recency_weight: 0.15,
7238 mutual_connections_weight: 0.10,
7239 recency_half_life_days: 90,
7240 }
7241 }
7242}
7243
7244#[derive(Debug, Clone, Serialize, Deserialize)]
7246pub struct StrengthThresholdsSchemaConfig {
7247 #[serde(default = "default_strong_threshold")]
7249 pub strong: f64,
7250
7251 #[serde(default = "default_moderate_threshold")]
7253 pub moderate: f64,
7254
7255 #[serde(default = "default_weak_threshold")]
7257 pub weak: f64,
7258}
7259
7260fn default_strong_threshold() -> f64 {
7261 0.7
7262}
7263
7264fn default_moderate_threshold() -> f64 {
7265 0.4
7266}
7267
7268fn default_weak_threshold() -> f64 {
7269 0.1
7270}
7271
7272impl Default for StrengthThresholdsSchemaConfig {
7273 fn default() -> Self {
7274 Self {
7275 strong: 0.7,
7276 moderate: 0.4,
7277 weak: 0.1,
7278 }
7279 }
7280}
7281
7282#[derive(Debug, Clone, Serialize, Deserialize)]
7288pub struct CrossProcessLinksSchemaConfig {
7289 #[serde(default)]
7291 pub enabled: bool,
7292
7293 #[serde(default = "default_true")]
7295 pub inventory_p2p_o2c: bool,
7296
7297 #[serde(default = "default_true")]
7299 pub payment_bank_reconciliation: bool,
7300
7301 #[serde(default = "default_true")]
7303 pub intercompany_bilateral: bool,
7304
7305 #[serde(default = "default_inventory_link_rate")]
7307 pub inventory_link_rate: f64,
7308}
7309
7310fn default_inventory_link_rate() -> f64 {
7311 0.30
7312}
7313
7314impl Default for CrossProcessLinksSchemaConfig {
7315 fn default() -> Self {
7316 Self {
7317 enabled: false,
7318 inventory_p2p_o2c: true,
7319 payment_bank_reconciliation: true,
7320 intercompany_bilateral: true,
7321 inventory_link_rate: 0.30,
7322 }
7323 }
7324}
7325
7326#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7332pub struct OrganizationalEventsSchemaConfig {
7333 #[serde(default)]
7335 pub enabled: bool,
7336
7337 #[serde(default)]
7339 pub effect_blending: EffectBlendingModeConfig,
7340
7341 #[serde(default)]
7343 pub events: Vec<OrganizationalEventSchemaConfig>,
7344
7345 #[serde(default)]
7347 pub process_evolution: Vec<ProcessEvolutionSchemaConfig>,
7348
7349 #[serde(default)]
7351 pub technology_transitions: Vec<TechnologyTransitionSchemaConfig>,
7352}
7353
7354#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
7356#[serde(rename_all = "snake_case")]
7357pub enum EffectBlendingModeConfig {
7358 #[default]
7360 Multiplicative,
7361 Additive,
7363 Maximum,
7365 Minimum,
7367}
7368
7369#[derive(Debug, Clone, Serialize, Deserialize)]
7371pub struct OrganizationalEventSchemaConfig {
7372 pub id: String,
7374
7375 pub event_type: OrganizationalEventTypeSchemaConfig,
7377
7378 pub effective_date: String,
7380
7381 #[serde(default = "default_org_transition_months")]
7383 pub transition_months: u32,
7384
7385 #[serde(default)]
7387 pub description: Option<String>,
7388}
7389
7390fn default_org_transition_months() -> u32 {
7391 6
7392}
7393
7394#[derive(Debug, Clone, Serialize, Deserialize)]
7396#[serde(tag = "type", rename_all = "snake_case")]
7397pub enum OrganizationalEventTypeSchemaConfig {
7398 Acquisition {
7400 acquired_entity: String,
7402 #[serde(default = "default_acquisition_volume")]
7404 volume_increase: f64,
7405 #[serde(default = "default_acquisition_error")]
7407 integration_error_rate: f64,
7408 #[serde(default = "default_parallel_days")]
7410 parallel_posting_days: u32,
7411 },
7412 Divestiture {
7414 divested_entity: String,
7416 #[serde(default = "default_divestiture_volume")]
7418 volume_reduction: f64,
7419 #[serde(default = "default_true_val")]
7421 remove_entity: bool,
7422 },
7423 Reorganization {
7425 #[serde(default)]
7427 cost_center_remapping: std::collections::HashMap<String, String>,
7428 #[serde(default = "default_reorg_error")]
7430 transition_error_rate: f64,
7431 },
7432 LeadershipChange {
7434 role: String,
7436 #[serde(default)]
7438 policy_changes: Vec<String>,
7439 },
7440 WorkforceReduction {
7442 #[serde(default = "default_workforce_reduction")]
7444 reduction_percent: f64,
7445 #[serde(default = "default_workforce_error")]
7447 error_rate_increase: f64,
7448 },
7449 Merger {
7451 merged_entity: String,
7453 #[serde(default = "default_merger_volume")]
7455 volume_increase: f64,
7456 },
7457}
7458
7459fn default_acquisition_volume() -> f64 {
7460 1.35
7461}
7462
7463fn default_acquisition_error() -> f64 {
7464 0.05
7465}
7466
7467fn default_parallel_days() -> u32 {
7468 30
7469}
7470
7471fn default_divestiture_volume() -> f64 {
7472 0.70
7473}
7474
7475fn default_true_val() -> bool {
7476 true
7477}
7478
7479fn default_reorg_error() -> f64 {
7480 0.04
7481}
7482
7483fn default_workforce_reduction() -> f64 {
7484 0.10
7485}
7486
7487fn default_workforce_error() -> f64 {
7488 0.05
7489}
7490
7491fn default_merger_volume() -> f64 {
7492 1.80
7493}
7494
7495#[derive(Debug, Clone, Serialize, Deserialize)]
7497pub struct ProcessEvolutionSchemaConfig {
7498 pub id: String,
7500
7501 pub event_type: ProcessEvolutionTypeSchemaConfig,
7503
7504 pub effective_date: String,
7506
7507 #[serde(default)]
7509 pub description: Option<String>,
7510}
7511
7512#[derive(Debug, Clone, Serialize, Deserialize)]
7514#[serde(tag = "type", rename_all = "snake_case")]
7515pub enum ProcessEvolutionTypeSchemaConfig {
7516 ProcessAutomation {
7518 process_name: String,
7520 #[serde(default = "default_manual_before")]
7522 manual_rate_before: f64,
7523 #[serde(default = "default_manual_after")]
7525 manual_rate_after: f64,
7526 },
7527 ApprovalWorkflowChange {
7529 description: String,
7531 },
7532 ControlEnhancement {
7534 control_id: String,
7536 #[serde(default = "default_error_reduction")]
7538 error_reduction: f64,
7539 },
7540}
7541
7542fn default_manual_before() -> f64 {
7543 0.80
7544}
7545
7546fn default_manual_after() -> f64 {
7547 0.15
7548}
7549
7550fn default_error_reduction() -> f64 {
7551 0.02
7552}
7553
7554#[derive(Debug, Clone, Serialize, Deserialize)]
7556pub struct TechnologyTransitionSchemaConfig {
7557 pub id: String,
7559
7560 pub event_type: TechnologyTransitionTypeSchemaConfig,
7562
7563 #[serde(default)]
7565 pub description: Option<String>,
7566}
7567
7568#[derive(Debug, Clone, Serialize, Deserialize)]
7570#[serde(tag = "type", rename_all = "snake_case")]
7571pub enum TechnologyTransitionTypeSchemaConfig {
7572 ErpMigration {
7574 source_system: String,
7576 target_system: String,
7578 cutover_date: String,
7580 stabilization_end: String,
7582 #[serde(default = "default_erp_duplicate_rate")]
7584 duplicate_rate: f64,
7585 #[serde(default = "default_format_mismatch")]
7587 format_mismatch_rate: f64,
7588 },
7589 ModuleImplementation {
7591 module_name: String,
7593 go_live_date: String,
7595 },
7596}
7597
7598fn default_erp_duplicate_rate() -> f64 {
7599 0.02
7600}
7601
7602fn default_format_mismatch() -> f64 {
7603 0.03
7604}
7605
7606#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7612pub struct BehavioralDriftSchemaConfig {
7613 #[serde(default)]
7615 pub enabled: bool,
7616
7617 #[serde(default)]
7619 pub vendor_behavior: VendorBehaviorSchemaConfig,
7620
7621 #[serde(default)]
7623 pub customer_behavior: CustomerBehaviorSchemaConfig,
7624
7625 #[serde(default)]
7627 pub employee_behavior: EmployeeBehaviorSchemaConfig,
7628
7629 #[serde(default)]
7631 pub collective: CollectiveBehaviorSchemaConfig,
7632}
7633
7634#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7636pub struct VendorBehaviorSchemaConfig {
7637 #[serde(default)]
7639 pub payment_terms_drift: PaymentTermsDriftSchemaConfig,
7640
7641 #[serde(default)]
7643 pub quality_drift: QualityDriftSchemaConfig,
7644}
7645
7646#[derive(Debug, Clone, Serialize, Deserialize)]
7648pub struct PaymentTermsDriftSchemaConfig {
7649 #[serde(default = "default_extension_rate")]
7651 pub extension_rate_per_year: f64,
7652
7653 #[serde(default = "default_economic_sensitivity")]
7655 pub economic_sensitivity: f64,
7656}
7657
7658fn default_extension_rate() -> f64 {
7659 2.5
7660}
7661
7662fn default_economic_sensitivity() -> f64 {
7663 1.0
7664}
7665
7666impl Default for PaymentTermsDriftSchemaConfig {
7667 fn default() -> Self {
7668 Self {
7669 extension_rate_per_year: 2.5,
7670 economic_sensitivity: 1.0,
7671 }
7672 }
7673}
7674
7675#[derive(Debug, Clone, Serialize, Deserialize)]
7677pub struct QualityDriftSchemaConfig {
7678 #[serde(default = "default_improvement_rate")]
7680 pub new_vendor_improvement_rate: f64,
7681
7682 #[serde(default = "default_decline_rate")]
7684 pub complacency_decline_rate: f64,
7685}
7686
7687fn default_improvement_rate() -> f64 {
7688 0.02
7689}
7690
7691fn default_decline_rate() -> f64 {
7692 0.01
7693}
7694
7695impl Default for QualityDriftSchemaConfig {
7696 fn default() -> Self {
7697 Self {
7698 new_vendor_improvement_rate: 0.02,
7699 complacency_decline_rate: 0.01,
7700 }
7701 }
7702}
7703
7704#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7706pub struct CustomerBehaviorSchemaConfig {
7707 #[serde(default)]
7709 pub payment_drift: CustomerPaymentDriftSchemaConfig,
7710
7711 #[serde(default)]
7713 pub order_drift: OrderDriftSchemaConfig,
7714}
7715
7716#[derive(Debug, Clone, Serialize, Deserialize)]
7718pub struct CustomerPaymentDriftSchemaConfig {
7719 #[serde(default = "default_downturn_extension")]
7721 pub downturn_days_extension: (u32, u32),
7722
7723 #[serde(default = "default_bad_debt_increase")]
7725 pub downturn_bad_debt_increase: f64,
7726}
7727
7728fn default_downturn_extension() -> (u32, u32) {
7729 (5, 15)
7730}
7731
7732fn default_bad_debt_increase() -> f64 {
7733 0.02
7734}
7735
7736impl Default for CustomerPaymentDriftSchemaConfig {
7737 fn default() -> Self {
7738 Self {
7739 downturn_days_extension: (5, 15),
7740 downturn_bad_debt_increase: 0.02,
7741 }
7742 }
7743}
7744
7745#[derive(Debug, Clone, Serialize, Deserialize)]
7747pub struct OrderDriftSchemaConfig {
7748 #[serde(default = "default_digital_shift")]
7750 pub digital_shift_rate: f64,
7751}
7752
7753fn default_digital_shift() -> f64 {
7754 0.05
7755}
7756
7757impl Default for OrderDriftSchemaConfig {
7758 fn default() -> Self {
7759 Self {
7760 digital_shift_rate: 0.05,
7761 }
7762 }
7763}
7764
7765#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7767pub struct EmployeeBehaviorSchemaConfig {
7768 #[serde(default)]
7770 pub approval_drift: ApprovalDriftSchemaConfig,
7771
7772 #[serde(default)]
7774 pub error_drift: ErrorDriftSchemaConfig,
7775}
7776
7777#[derive(Debug, Clone, Serialize, Deserialize)]
7779pub struct ApprovalDriftSchemaConfig {
7780 #[serde(default = "default_eom_intensity")]
7782 pub eom_intensity_increase_per_year: f64,
7783
7784 #[serde(default = "default_rubber_stamp")]
7786 pub rubber_stamp_volume_threshold: u32,
7787}
7788
7789fn default_eom_intensity() -> f64 {
7790 0.05
7791}
7792
7793fn default_rubber_stamp() -> u32 {
7794 50
7795}
7796
7797impl Default for ApprovalDriftSchemaConfig {
7798 fn default() -> Self {
7799 Self {
7800 eom_intensity_increase_per_year: 0.05,
7801 rubber_stamp_volume_threshold: 50,
7802 }
7803 }
7804}
7805
7806#[derive(Debug, Clone, Serialize, Deserialize)]
7808pub struct ErrorDriftSchemaConfig {
7809 #[serde(default = "default_new_error")]
7811 pub new_employee_error_rate: f64,
7812
7813 #[serde(default = "default_learning_months")]
7815 pub learning_curve_months: u32,
7816}
7817
7818fn default_new_error() -> f64 {
7819 0.08
7820}
7821
7822fn default_learning_months() -> u32 {
7823 6
7824}
7825
7826impl Default for ErrorDriftSchemaConfig {
7827 fn default() -> Self {
7828 Self {
7829 new_employee_error_rate: 0.08,
7830 learning_curve_months: 6,
7831 }
7832 }
7833}
7834
7835#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7837pub struct CollectiveBehaviorSchemaConfig {
7838 #[serde(default)]
7840 pub automation_adoption: AutomationAdoptionSchemaConfig,
7841}
7842
7843#[derive(Debug, Clone, Serialize, Deserialize)]
7845pub struct AutomationAdoptionSchemaConfig {
7846 #[serde(default)]
7848 pub s_curve_enabled: bool,
7849
7850 #[serde(default = "default_midpoint")]
7852 pub adoption_midpoint_months: u32,
7853
7854 #[serde(default = "default_steepness")]
7856 pub steepness: f64,
7857}
7858
7859fn default_midpoint() -> u32 {
7860 24
7861}
7862
7863fn default_steepness() -> f64 {
7864 0.15
7865}
7866
7867impl Default for AutomationAdoptionSchemaConfig {
7868 fn default() -> Self {
7869 Self {
7870 s_curve_enabled: false,
7871 adoption_midpoint_months: 24,
7872 steepness: 0.15,
7873 }
7874 }
7875}
7876
7877#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7883pub struct MarketDriftSchemaConfig {
7884 #[serde(default)]
7886 pub enabled: bool,
7887
7888 #[serde(default)]
7890 pub economic_cycle: MarketEconomicCycleSchemaConfig,
7891
7892 #[serde(default)]
7894 pub industry_cycles: std::collections::HashMap<String, IndustryCycleSchemaConfig>,
7895
7896 #[serde(default)]
7898 pub commodities: CommoditiesSchemaConfig,
7899}
7900
7901#[derive(Debug, Clone, Serialize, Deserialize)]
7903pub struct MarketEconomicCycleSchemaConfig {
7904 #[serde(default)]
7906 pub enabled: bool,
7907
7908 #[serde(default)]
7910 pub cycle_type: CycleTypeSchemaConfig,
7911
7912 #[serde(default = "default_market_cycle_period")]
7914 pub period_months: u32,
7915
7916 #[serde(default = "default_market_amplitude")]
7918 pub amplitude: f64,
7919
7920 #[serde(default)]
7922 pub recession: RecessionSchemaConfig,
7923}
7924
7925fn default_market_cycle_period() -> u32 {
7926 48
7927}
7928
7929fn default_market_amplitude() -> f64 {
7930 0.15
7931}
7932
7933impl Default for MarketEconomicCycleSchemaConfig {
7934 fn default() -> Self {
7935 Self {
7936 enabled: false,
7937 cycle_type: CycleTypeSchemaConfig::Sinusoidal,
7938 period_months: 48,
7939 amplitude: 0.15,
7940 recession: RecessionSchemaConfig::default(),
7941 }
7942 }
7943}
7944
7945#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
7947#[serde(rename_all = "snake_case")]
7948pub enum CycleTypeSchemaConfig {
7949 #[default]
7951 Sinusoidal,
7952 Asymmetric,
7954 MeanReverting,
7956}
7957
7958#[derive(Debug, Clone, Serialize, Deserialize)]
7960pub struct RecessionSchemaConfig {
7961 #[serde(default)]
7963 pub enabled: bool,
7964
7965 #[serde(default = "default_recession_prob")]
7967 pub probability_per_year: f64,
7968
7969 #[serde(default)]
7971 pub severity: RecessionSeveritySchemaConfig,
7972
7973 #[serde(default)]
7975 pub recession_periods: Vec<RecessionPeriodSchemaConfig>,
7976}
7977
7978fn default_recession_prob() -> f64 {
7979 0.10
7980}
7981
7982impl Default for RecessionSchemaConfig {
7983 fn default() -> Self {
7984 Self {
7985 enabled: false,
7986 probability_per_year: 0.10,
7987 severity: RecessionSeveritySchemaConfig::Moderate,
7988 recession_periods: Vec::new(),
7989 }
7990 }
7991}
7992
7993#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
7995#[serde(rename_all = "snake_case")]
7996pub enum RecessionSeveritySchemaConfig {
7997 Mild,
7999 #[default]
8001 Moderate,
8002 Severe,
8004}
8005
8006#[derive(Debug, Clone, Serialize, Deserialize)]
8008pub struct RecessionPeriodSchemaConfig {
8009 pub start_month: u32,
8011 pub duration_months: u32,
8013}
8014
8015#[derive(Debug, Clone, Serialize, Deserialize)]
8017pub struct IndustryCycleSchemaConfig {
8018 #[serde(default = "default_industry_period")]
8020 pub period_months: u32,
8021
8022 #[serde(default = "default_industry_amp")]
8024 pub amplitude: f64,
8025}
8026
8027fn default_industry_period() -> u32 {
8028 36
8029}
8030
8031fn default_industry_amp() -> f64 {
8032 0.20
8033}
8034
8035#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8037pub struct CommoditiesSchemaConfig {
8038 #[serde(default)]
8040 pub enabled: bool,
8041
8042 #[serde(default)]
8044 pub items: Vec<CommodityItemSchemaConfig>,
8045}
8046
8047#[derive(Debug, Clone, Serialize, Deserialize)]
8049pub struct CommodityItemSchemaConfig {
8050 pub name: String,
8052
8053 #[serde(default = "default_volatility")]
8055 pub volatility: f64,
8056
8057 #[serde(default)]
8059 pub cogs_pass_through: f64,
8060
8061 #[serde(default)]
8063 pub overhead_pass_through: f64,
8064}
8065
8066fn default_volatility() -> f64 {
8067 0.20
8068}
8069
8070#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8076pub struct DriftLabelingSchemaConfig {
8077 #[serde(default)]
8079 pub enabled: bool,
8080
8081 #[serde(default)]
8083 pub statistical: StatisticalDriftLabelingSchemaConfig,
8084
8085 #[serde(default)]
8087 pub categorical: CategoricalDriftLabelingSchemaConfig,
8088
8089 #[serde(default)]
8091 pub temporal: TemporalDriftLabelingSchemaConfig,
8092
8093 #[serde(default)]
8095 pub regulatory_calendar_preset: Option<String>,
8096}
8097
8098#[derive(Debug, Clone, Serialize, Deserialize)]
8100pub struct StatisticalDriftLabelingSchemaConfig {
8101 #[serde(default = "default_true_val")]
8103 pub enabled: bool,
8104
8105 #[serde(default = "default_min_magnitude")]
8107 pub min_magnitude_threshold: f64,
8108}
8109
8110fn default_min_magnitude() -> f64 {
8111 0.05
8112}
8113
8114impl Default for StatisticalDriftLabelingSchemaConfig {
8115 fn default() -> Self {
8116 Self {
8117 enabled: true,
8118 min_magnitude_threshold: 0.05,
8119 }
8120 }
8121}
8122
8123#[derive(Debug, Clone, Serialize, Deserialize)]
8125pub struct CategoricalDriftLabelingSchemaConfig {
8126 #[serde(default = "default_true_val")]
8128 pub enabled: bool,
8129}
8130
8131impl Default for CategoricalDriftLabelingSchemaConfig {
8132 fn default() -> Self {
8133 Self { enabled: true }
8134 }
8135}
8136
8137#[derive(Debug, Clone, Serialize, Deserialize)]
8139pub struct TemporalDriftLabelingSchemaConfig {
8140 #[serde(default = "default_true_val")]
8142 pub enabled: bool,
8143}
8144
8145impl Default for TemporalDriftLabelingSchemaConfig {
8146 fn default() -> Self {
8147 Self { enabled: true }
8148 }
8149}
8150
8151#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8164pub struct EnhancedAnomalyConfig {
8165 #[serde(default)]
8167 pub enabled: bool,
8168
8169 #[serde(default)]
8171 pub rates: AnomalyRateConfig,
8172
8173 #[serde(default)]
8175 pub multi_stage_schemes: MultiStageSchemeConfig,
8176
8177 #[serde(default)]
8179 pub correlated_injection: CorrelatedInjectionConfig,
8180
8181 #[serde(default)]
8183 pub near_miss: NearMissConfig,
8184
8185 #[serde(default)]
8187 pub difficulty_classification: DifficultyClassificationConfig,
8188
8189 #[serde(default)]
8191 pub context_aware: ContextAwareConfig,
8192
8193 #[serde(default)]
8195 pub labeling: EnhancedLabelingConfig,
8196}
8197
8198#[derive(Debug, Clone, Serialize, Deserialize)]
8200pub struct AnomalyRateConfig {
8201 #[serde(default = "default_total_anomaly_rate")]
8203 pub total_rate: f64,
8204
8205 #[serde(default = "default_fraud_anomaly_rate")]
8207 pub fraud_rate: f64,
8208
8209 #[serde(default = "default_error_anomaly_rate")]
8211 pub error_rate: f64,
8212
8213 #[serde(default = "default_process_anomaly_rate")]
8215 pub process_rate: f64,
8216}
8217
8218fn default_total_anomaly_rate() -> f64 {
8219 0.03
8220}
8221fn default_fraud_anomaly_rate() -> f64 {
8222 0.01
8223}
8224fn default_error_anomaly_rate() -> f64 {
8225 0.015
8226}
8227fn default_process_anomaly_rate() -> f64 {
8228 0.005
8229}
8230
8231impl Default for AnomalyRateConfig {
8232 fn default() -> Self {
8233 Self {
8234 total_rate: default_total_anomaly_rate(),
8235 fraud_rate: default_fraud_anomaly_rate(),
8236 error_rate: default_error_anomaly_rate(),
8237 process_rate: default_process_anomaly_rate(),
8238 }
8239 }
8240}
8241
8242#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8244pub struct MultiStageSchemeConfig {
8245 #[serde(default)]
8247 pub enabled: bool,
8248
8249 #[serde(default)]
8251 pub embezzlement: EmbezzlementSchemeConfig,
8252
8253 #[serde(default)]
8255 pub revenue_manipulation: RevenueManipulationSchemeConfig,
8256
8257 #[serde(default)]
8259 pub kickback: KickbackSchemeConfig,
8260}
8261
8262#[derive(Debug, Clone, Serialize, Deserialize)]
8264pub struct EmbezzlementSchemeConfig {
8265 #[serde(default = "default_embezzlement_probability")]
8267 pub probability: f64,
8268
8269 #[serde(default)]
8271 pub testing_stage: SchemeStageConfig,
8272
8273 #[serde(default)]
8275 pub escalation_stage: SchemeStageConfig,
8276
8277 #[serde(default)]
8279 pub acceleration_stage: SchemeStageConfig,
8280
8281 #[serde(default)]
8283 pub desperation_stage: SchemeStageConfig,
8284}
8285
8286fn default_embezzlement_probability() -> f64 {
8287 0.02
8288}
8289
8290impl Default for EmbezzlementSchemeConfig {
8291 fn default() -> Self {
8292 Self {
8293 probability: default_embezzlement_probability(),
8294 testing_stage: SchemeStageConfig {
8295 duration_months: 2,
8296 amount_min: 100.0,
8297 amount_max: 500.0,
8298 transaction_count_min: 2,
8299 transaction_count_max: 5,
8300 difficulty: "hard".to_string(),
8301 },
8302 escalation_stage: SchemeStageConfig {
8303 duration_months: 6,
8304 amount_min: 500.0,
8305 amount_max: 2000.0,
8306 transaction_count_min: 3,
8307 transaction_count_max: 8,
8308 difficulty: "moderate".to_string(),
8309 },
8310 acceleration_stage: SchemeStageConfig {
8311 duration_months: 3,
8312 amount_min: 2000.0,
8313 amount_max: 10000.0,
8314 transaction_count_min: 5,
8315 transaction_count_max: 12,
8316 difficulty: "easy".to_string(),
8317 },
8318 desperation_stage: SchemeStageConfig {
8319 duration_months: 1,
8320 amount_min: 10000.0,
8321 amount_max: 50000.0,
8322 transaction_count_min: 3,
8323 transaction_count_max: 6,
8324 difficulty: "trivial".to_string(),
8325 },
8326 }
8327 }
8328}
8329
8330#[derive(Debug, Clone, Serialize, Deserialize)]
8332pub struct RevenueManipulationSchemeConfig {
8333 #[serde(default = "default_revenue_manipulation_probability")]
8335 pub probability: f64,
8336
8337 #[serde(default = "default_early_recognition_target")]
8339 pub early_recognition_target: f64,
8340
8341 #[serde(default = "default_expense_deferral_target")]
8343 pub expense_deferral_target: f64,
8344
8345 #[serde(default = "default_reserve_release_target")]
8347 pub reserve_release_target: f64,
8348
8349 #[serde(default = "default_channel_stuffing_target")]
8351 pub channel_stuffing_target: f64,
8352}
8353
8354fn default_revenue_manipulation_probability() -> f64 {
8355 0.01
8356}
8357fn default_early_recognition_target() -> f64 {
8358 0.02
8359}
8360fn default_expense_deferral_target() -> f64 {
8361 0.03
8362}
8363fn default_reserve_release_target() -> f64 {
8364 0.02
8365}
8366fn default_channel_stuffing_target() -> f64 {
8367 0.05
8368}
8369
8370impl Default for RevenueManipulationSchemeConfig {
8371 fn default() -> Self {
8372 Self {
8373 probability: default_revenue_manipulation_probability(),
8374 early_recognition_target: default_early_recognition_target(),
8375 expense_deferral_target: default_expense_deferral_target(),
8376 reserve_release_target: default_reserve_release_target(),
8377 channel_stuffing_target: default_channel_stuffing_target(),
8378 }
8379 }
8380}
8381
8382#[derive(Debug, Clone, Serialize, Deserialize)]
8384pub struct KickbackSchemeConfig {
8385 #[serde(default = "default_kickback_probability")]
8387 pub probability: f64,
8388
8389 #[serde(default = "default_kickback_inflation_min")]
8391 pub inflation_min: f64,
8392
8393 #[serde(default = "default_kickback_inflation_max")]
8395 pub inflation_max: f64,
8396
8397 #[serde(default = "default_kickback_percent")]
8399 pub kickback_percent: f64,
8400
8401 #[serde(default = "default_kickback_setup_months")]
8403 pub setup_months: u32,
8404
8405 #[serde(default = "default_kickback_operation_months")]
8407 pub operation_months: u32,
8408}
8409
8410fn default_kickback_probability() -> f64 {
8411 0.01
8412}
8413fn default_kickback_inflation_min() -> f64 {
8414 0.10
8415}
8416fn default_kickback_inflation_max() -> f64 {
8417 0.25
8418}
8419fn default_kickback_percent() -> f64 {
8420 0.50
8421}
8422fn default_kickback_setup_months() -> u32 {
8423 3
8424}
8425fn default_kickback_operation_months() -> u32 {
8426 12
8427}
8428
8429impl Default for KickbackSchemeConfig {
8430 fn default() -> Self {
8431 Self {
8432 probability: default_kickback_probability(),
8433 inflation_min: default_kickback_inflation_min(),
8434 inflation_max: default_kickback_inflation_max(),
8435 kickback_percent: default_kickback_percent(),
8436 setup_months: default_kickback_setup_months(),
8437 operation_months: default_kickback_operation_months(),
8438 }
8439 }
8440}
8441
8442#[derive(Debug, Clone, Serialize, Deserialize)]
8444pub struct SchemeStageConfig {
8445 pub duration_months: u32,
8447
8448 pub amount_min: f64,
8450
8451 pub amount_max: f64,
8453
8454 pub transaction_count_min: u32,
8456
8457 pub transaction_count_max: u32,
8459
8460 pub difficulty: String,
8462}
8463
8464impl Default for SchemeStageConfig {
8465 fn default() -> Self {
8466 Self {
8467 duration_months: 3,
8468 amount_min: 100.0,
8469 amount_max: 1000.0,
8470 transaction_count_min: 2,
8471 transaction_count_max: 10,
8472 difficulty: "moderate".to_string(),
8473 }
8474 }
8475}
8476
8477#[derive(Debug, Clone, Serialize, Deserialize)]
8479pub struct CorrelatedInjectionConfig {
8480 #[serde(default)]
8482 pub enabled: bool,
8483
8484 #[serde(default = "default_true_val")]
8486 pub fraud_concealment: bool,
8487
8488 #[serde(default = "default_true_val")]
8490 pub error_cascade: bool,
8491
8492 #[serde(default = "default_true_val")]
8494 pub temporal_clustering: bool,
8495
8496 #[serde(default)]
8498 pub temporal_clustering_config: TemporalClusteringConfig,
8499
8500 #[serde(default)]
8502 pub co_occurrence_patterns: Vec<CoOccurrencePatternConfig>,
8503}
8504
8505impl Default for CorrelatedInjectionConfig {
8506 fn default() -> Self {
8507 Self {
8508 enabled: false,
8509 fraud_concealment: true,
8510 error_cascade: true,
8511 temporal_clustering: true,
8512 temporal_clustering_config: TemporalClusteringConfig::default(),
8513 co_occurrence_patterns: Vec::new(),
8514 }
8515 }
8516}
8517
8518#[derive(Debug, Clone, Serialize, Deserialize)]
8520pub struct TemporalClusteringConfig {
8521 #[serde(default = "default_period_end_multiplier")]
8523 pub period_end_multiplier: f64,
8524
8525 #[serde(default = "default_period_end_days")]
8527 pub period_end_days: u32,
8528
8529 #[serde(default = "default_quarter_end_multiplier")]
8531 pub quarter_end_multiplier: f64,
8532
8533 #[serde(default = "default_year_end_multiplier")]
8535 pub year_end_multiplier: f64,
8536}
8537
8538fn default_period_end_multiplier() -> f64 {
8539 2.5
8540}
8541fn default_period_end_days() -> u32 {
8542 5
8543}
8544fn default_quarter_end_multiplier() -> f64 {
8545 1.5
8546}
8547fn default_year_end_multiplier() -> f64 {
8548 2.0
8549}
8550
8551impl Default for TemporalClusteringConfig {
8552 fn default() -> Self {
8553 Self {
8554 period_end_multiplier: default_period_end_multiplier(),
8555 period_end_days: default_period_end_days(),
8556 quarter_end_multiplier: default_quarter_end_multiplier(),
8557 year_end_multiplier: default_year_end_multiplier(),
8558 }
8559 }
8560}
8561
8562#[derive(Debug, Clone, Serialize, Deserialize)]
8564pub struct CoOccurrencePatternConfig {
8565 pub name: String,
8567
8568 pub primary_type: String,
8570
8571 pub correlated: Vec<CorrelatedAnomalyConfig>,
8573}
8574
8575#[derive(Debug, Clone, Serialize, Deserialize)]
8577pub struct CorrelatedAnomalyConfig {
8578 pub anomaly_type: String,
8580
8581 pub probability: f64,
8583
8584 pub lag_days_min: i32,
8586
8587 pub lag_days_max: i32,
8589}
8590
8591#[derive(Debug, Clone, Serialize, Deserialize)]
8593pub struct NearMissConfig {
8594 #[serde(default)]
8596 pub enabled: bool,
8597
8598 #[serde(default = "default_near_miss_proportion")]
8600 pub proportion: f64,
8601
8602 #[serde(default = "default_true_val")]
8604 pub near_duplicate: bool,
8605
8606 #[serde(default)]
8608 pub near_duplicate_days: NearDuplicateDaysConfig,
8609
8610 #[serde(default = "default_true_val")]
8612 pub threshold_proximity: bool,
8613
8614 #[serde(default)]
8616 pub threshold_proximity_range: ThresholdProximityRangeConfig,
8617
8618 #[serde(default = "default_true_val")]
8620 pub unusual_legitimate: bool,
8621
8622 #[serde(default = "default_unusual_legitimate_types")]
8624 pub unusual_legitimate_types: Vec<String>,
8625
8626 #[serde(default = "default_true_val")]
8628 pub corrected_errors: bool,
8629
8630 #[serde(default)]
8632 pub corrected_error_lag: CorrectedErrorLagConfig,
8633}
8634
8635fn default_near_miss_proportion() -> f64 {
8636 0.30
8637}
8638
8639fn default_unusual_legitimate_types() -> Vec<String> {
8640 vec![
8641 "year_end_bonus".to_string(),
8642 "contract_prepayment".to_string(),
8643 "insurance_claim".to_string(),
8644 "settlement_payment".to_string(),
8645 ]
8646}
8647
8648impl Default for NearMissConfig {
8649 fn default() -> Self {
8650 Self {
8651 enabled: false,
8652 proportion: default_near_miss_proportion(),
8653 near_duplicate: true,
8654 near_duplicate_days: NearDuplicateDaysConfig::default(),
8655 threshold_proximity: true,
8656 threshold_proximity_range: ThresholdProximityRangeConfig::default(),
8657 unusual_legitimate: true,
8658 unusual_legitimate_types: default_unusual_legitimate_types(),
8659 corrected_errors: true,
8660 corrected_error_lag: CorrectedErrorLagConfig::default(),
8661 }
8662 }
8663}
8664
8665#[derive(Debug, Clone, Serialize, Deserialize)]
8667pub struct NearDuplicateDaysConfig {
8668 #[serde(default = "default_near_duplicate_min")]
8670 pub min: u32,
8671
8672 #[serde(default = "default_near_duplicate_max")]
8674 pub max: u32,
8675}
8676
8677fn default_near_duplicate_min() -> u32 {
8678 1
8679}
8680fn default_near_duplicate_max() -> u32 {
8681 3
8682}
8683
8684impl Default for NearDuplicateDaysConfig {
8685 fn default() -> Self {
8686 Self {
8687 min: default_near_duplicate_min(),
8688 max: default_near_duplicate_max(),
8689 }
8690 }
8691}
8692
8693#[derive(Debug, Clone, Serialize, Deserialize)]
8695pub struct ThresholdProximityRangeConfig {
8696 #[serde(default = "default_threshold_proximity_min")]
8698 pub min: f64,
8699
8700 #[serde(default = "default_threshold_proximity_max")]
8702 pub max: f64,
8703}
8704
8705fn default_threshold_proximity_min() -> f64 {
8706 0.90
8707}
8708fn default_threshold_proximity_max() -> f64 {
8709 0.99
8710}
8711
8712impl Default for ThresholdProximityRangeConfig {
8713 fn default() -> Self {
8714 Self {
8715 min: default_threshold_proximity_min(),
8716 max: default_threshold_proximity_max(),
8717 }
8718 }
8719}
8720
8721#[derive(Debug, Clone, Serialize, Deserialize)]
8723pub struct CorrectedErrorLagConfig {
8724 #[serde(default = "default_corrected_error_lag_min")]
8726 pub min: u32,
8727
8728 #[serde(default = "default_corrected_error_lag_max")]
8730 pub max: u32,
8731}
8732
8733fn default_corrected_error_lag_min() -> u32 {
8734 1
8735}
8736fn default_corrected_error_lag_max() -> u32 {
8737 5
8738}
8739
8740impl Default for CorrectedErrorLagConfig {
8741 fn default() -> Self {
8742 Self {
8743 min: default_corrected_error_lag_min(),
8744 max: default_corrected_error_lag_max(),
8745 }
8746 }
8747}
8748
8749#[derive(Debug, Clone, Serialize, Deserialize)]
8751pub struct DifficultyClassificationConfig {
8752 #[serde(default)]
8754 pub enabled: bool,
8755
8756 #[serde(default)]
8758 pub target_distribution: DifficultyDistributionConfig,
8759}
8760
8761impl Default for DifficultyClassificationConfig {
8762 fn default() -> Self {
8763 Self {
8764 enabled: true,
8765 target_distribution: DifficultyDistributionConfig::default(),
8766 }
8767 }
8768}
8769
8770#[derive(Debug, Clone, Serialize, Deserialize)]
8772pub struct DifficultyDistributionConfig {
8773 #[serde(default = "default_difficulty_trivial")]
8775 pub trivial: f64,
8776
8777 #[serde(default = "default_difficulty_easy")]
8779 pub easy: f64,
8780
8781 #[serde(default = "default_difficulty_moderate")]
8783 pub moderate: f64,
8784
8785 #[serde(default = "default_difficulty_hard")]
8787 pub hard: f64,
8788
8789 #[serde(default = "default_difficulty_expert")]
8791 pub expert: f64,
8792}
8793
8794fn default_difficulty_trivial() -> f64 {
8795 0.15
8796}
8797fn default_difficulty_easy() -> f64 {
8798 0.25
8799}
8800fn default_difficulty_moderate() -> f64 {
8801 0.30
8802}
8803fn default_difficulty_hard() -> f64 {
8804 0.20
8805}
8806fn default_difficulty_expert() -> f64 {
8807 0.10
8808}
8809
8810impl Default for DifficultyDistributionConfig {
8811 fn default() -> Self {
8812 Self {
8813 trivial: default_difficulty_trivial(),
8814 easy: default_difficulty_easy(),
8815 moderate: default_difficulty_moderate(),
8816 hard: default_difficulty_hard(),
8817 expert: default_difficulty_expert(),
8818 }
8819 }
8820}
8821
8822#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8824pub struct ContextAwareConfig {
8825 #[serde(default)]
8827 pub enabled: bool,
8828
8829 #[serde(default)]
8831 pub vendor_rules: VendorAnomalyRulesConfig,
8832
8833 #[serde(default)]
8835 pub employee_rules: EmployeeAnomalyRulesConfig,
8836
8837 #[serde(default)]
8839 pub account_rules: AccountAnomalyRulesConfig,
8840
8841 #[serde(default)]
8843 pub behavioral_baseline: BehavioralBaselineConfig,
8844}
8845
8846#[derive(Debug, Clone, Serialize, Deserialize)]
8848pub struct VendorAnomalyRulesConfig {
8849 #[serde(default = "default_new_vendor_multiplier")]
8851 pub new_vendor_error_multiplier: f64,
8852
8853 #[serde(default = "default_new_vendor_threshold")]
8855 pub new_vendor_threshold_days: u32,
8856
8857 #[serde(default = "default_international_multiplier")]
8859 pub international_error_multiplier: f64,
8860
8861 #[serde(default = "default_strategic_vendor_types")]
8863 pub strategic_vendor_anomaly_types: Vec<String>,
8864}
8865
8866fn default_new_vendor_multiplier() -> f64 {
8867 2.5
8868}
8869fn default_new_vendor_threshold() -> u32 {
8870 90
8871}
8872fn default_international_multiplier() -> f64 {
8873 1.5
8874}
8875fn default_strategic_vendor_types() -> Vec<String> {
8876 vec![
8877 "pricing_dispute".to_string(),
8878 "contract_violation".to_string(),
8879 ]
8880}
8881
8882impl Default for VendorAnomalyRulesConfig {
8883 fn default() -> Self {
8884 Self {
8885 new_vendor_error_multiplier: default_new_vendor_multiplier(),
8886 new_vendor_threshold_days: default_new_vendor_threshold(),
8887 international_error_multiplier: default_international_multiplier(),
8888 strategic_vendor_anomaly_types: default_strategic_vendor_types(),
8889 }
8890 }
8891}
8892
8893#[derive(Debug, Clone, Serialize, Deserialize)]
8895pub struct EmployeeAnomalyRulesConfig {
8896 #[serde(default = "default_new_employee_rate")]
8898 pub new_employee_error_rate: f64,
8899
8900 #[serde(default = "default_new_employee_threshold")]
8902 pub new_employee_threshold_days: u32,
8903
8904 #[serde(default = "default_volume_fatigue_threshold")]
8906 pub volume_fatigue_threshold: u32,
8907
8908 #[serde(default = "default_coverage_multiplier")]
8910 pub coverage_error_multiplier: f64,
8911}
8912
8913fn default_new_employee_rate() -> f64 {
8914 0.05
8915}
8916fn default_new_employee_threshold() -> u32 {
8917 180
8918}
8919fn default_volume_fatigue_threshold() -> u32 {
8920 50
8921}
8922fn default_coverage_multiplier() -> f64 {
8923 1.8
8924}
8925
8926impl Default for EmployeeAnomalyRulesConfig {
8927 fn default() -> Self {
8928 Self {
8929 new_employee_error_rate: default_new_employee_rate(),
8930 new_employee_threshold_days: default_new_employee_threshold(),
8931 volume_fatigue_threshold: default_volume_fatigue_threshold(),
8932 coverage_error_multiplier: default_coverage_multiplier(),
8933 }
8934 }
8935}
8936
8937#[derive(Debug, Clone, Serialize, Deserialize)]
8939pub struct AccountAnomalyRulesConfig {
8940 #[serde(default = "default_high_risk_multiplier")]
8942 pub high_risk_account_multiplier: f64,
8943
8944 #[serde(default = "default_high_risk_accounts")]
8946 pub high_risk_accounts: Vec<String>,
8947
8948 #[serde(default = "default_suspense_multiplier")]
8950 pub suspense_account_multiplier: f64,
8951
8952 #[serde(default = "default_suspense_accounts")]
8954 pub suspense_accounts: Vec<String>,
8955
8956 #[serde(default = "default_intercompany_multiplier")]
8958 pub intercompany_account_multiplier: f64,
8959}
8960
8961fn default_high_risk_multiplier() -> f64 {
8962 2.0
8963}
8964fn default_high_risk_accounts() -> Vec<String> {
8965 vec![
8966 "1100".to_string(), "2000".to_string(), "3000".to_string(), ]
8970}
8971fn default_suspense_multiplier() -> f64 {
8972 3.0
8973}
8974fn default_suspense_accounts() -> Vec<String> {
8975 vec!["9999".to_string(), "9998".to_string()]
8976}
8977fn default_intercompany_multiplier() -> f64 {
8978 1.5
8979}
8980
8981impl Default for AccountAnomalyRulesConfig {
8982 fn default() -> Self {
8983 Self {
8984 high_risk_account_multiplier: default_high_risk_multiplier(),
8985 high_risk_accounts: default_high_risk_accounts(),
8986 suspense_account_multiplier: default_suspense_multiplier(),
8987 suspense_accounts: default_suspense_accounts(),
8988 intercompany_account_multiplier: default_intercompany_multiplier(),
8989 }
8990 }
8991}
8992
8993#[derive(Debug, Clone, Serialize, Deserialize)]
8995pub struct BehavioralBaselineConfig {
8996 #[serde(default)]
8998 pub enabled: bool,
8999
9000 #[serde(default = "default_baseline_period")]
9002 pub baseline_period_days: u32,
9003
9004 #[serde(default = "default_deviation_threshold")]
9006 pub deviation_threshold_std: f64,
9007
9008 #[serde(default = "default_frequency_deviation")]
9010 pub frequency_deviation_threshold: f64,
9011}
9012
9013fn default_baseline_period() -> u32 {
9014 90
9015}
9016fn default_deviation_threshold() -> f64 {
9017 3.0
9018}
9019fn default_frequency_deviation() -> f64 {
9020 2.0
9021}
9022
9023impl Default for BehavioralBaselineConfig {
9024 fn default() -> Self {
9025 Self {
9026 enabled: false,
9027 baseline_period_days: default_baseline_period(),
9028 deviation_threshold_std: default_deviation_threshold(),
9029 frequency_deviation_threshold: default_frequency_deviation(),
9030 }
9031 }
9032}
9033
9034#[derive(Debug, Clone, Serialize, Deserialize)]
9036pub struct EnhancedLabelingConfig {
9037 #[serde(default = "default_true_val")]
9039 pub severity_scoring: bool,
9040
9041 #[serde(default = "default_true_val")]
9043 pub difficulty_classification: bool,
9044
9045 #[serde(default)]
9047 pub materiality_thresholds: MaterialityThresholdsConfig,
9048}
9049
9050impl Default for EnhancedLabelingConfig {
9051 fn default() -> Self {
9052 Self {
9053 severity_scoring: true,
9054 difficulty_classification: true,
9055 materiality_thresholds: MaterialityThresholdsConfig::default(),
9056 }
9057 }
9058}
9059
9060#[derive(Debug, Clone, Serialize, Deserialize)]
9062pub struct MaterialityThresholdsConfig {
9063 #[serde(default = "default_materiality_trivial")]
9065 pub trivial: f64,
9066
9067 #[serde(default = "default_materiality_immaterial")]
9069 pub immaterial: f64,
9070
9071 #[serde(default = "default_materiality_material")]
9073 pub material: f64,
9074
9075 #[serde(default = "default_materiality_highly_material")]
9077 pub highly_material: f64,
9078}
9079
9080fn default_materiality_trivial() -> f64 {
9081 0.001
9082}
9083fn default_materiality_immaterial() -> f64 {
9084 0.01
9085}
9086fn default_materiality_material() -> f64 {
9087 0.05
9088}
9089fn default_materiality_highly_material() -> f64 {
9090 0.10
9091}
9092
9093impl Default for MaterialityThresholdsConfig {
9094 fn default() -> Self {
9095 Self {
9096 trivial: default_materiality_trivial(),
9097 immaterial: default_materiality_immaterial(),
9098 material: default_materiality_material(),
9099 highly_material: default_materiality_highly_material(),
9100 }
9101 }
9102}
9103
9104#[derive(Debug, Clone, Serialize, Deserialize, Default)]
9116pub struct IndustrySpecificConfig {
9117 #[serde(default)]
9119 pub enabled: bool,
9120
9121 #[serde(default)]
9123 pub manufacturing: ManufacturingConfig,
9124
9125 #[serde(default)]
9127 pub retail: RetailConfig,
9128
9129 #[serde(default)]
9131 pub healthcare: HealthcareConfig,
9132
9133 #[serde(default)]
9135 pub technology: TechnologyConfig,
9136
9137 #[serde(default)]
9139 pub financial_services: FinancialServicesConfig,
9140
9141 #[serde(default)]
9143 pub professional_services: ProfessionalServicesConfig,
9144}
9145
9146#[derive(Debug, Clone, Serialize, Deserialize)]
9148pub struct ManufacturingConfig {
9149 #[serde(default)]
9151 pub enabled: bool,
9152
9153 #[serde(default = "default_bom_depth")]
9155 pub bom_depth: u32,
9156
9157 #[serde(default)]
9159 pub just_in_time: bool,
9160
9161 #[serde(default = "default_production_order_types")]
9163 pub production_order_types: Vec<String>,
9164
9165 #[serde(default)]
9167 pub quality_framework: Option<String>,
9168
9169 #[serde(default = "default_supplier_tiers")]
9171 pub supplier_tiers: u32,
9172
9173 #[serde(default = "default_cost_frequency")]
9175 pub standard_cost_frequency: String,
9176
9177 #[serde(default = "default_yield_rate")]
9179 pub target_yield_rate: f64,
9180
9181 #[serde(default = "default_scrap_threshold")]
9183 pub scrap_alert_threshold: f64,
9184
9185 #[serde(default)]
9187 pub anomaly_rates: ManufacturingAnomalyRates,
9188
9189 #[serde(default)]
9191 pub cost_accounting: ManufacturingCostAccountingConfig,
9192}
9193
9194#[derive(Debug, Clone, Serialize, Deserialize)]
9196pub struct ManufacturingCostAccountingConfig {
9197 #[serde(default = "default_true")]
9199 pub enabled: bool,
9200
9201 #[serde(default = "default_true")]
9203 pub variance_accounts_enabled: bool,
9204
9205 #[serde(default = "default_true")]
9207 pub warranty_provisions_enabled: bool,
9208
9209 #[serde(default = "default_warranty_defect_threshold")]
9211 pub warranty_defect_threshold: f64,
9212}
9213
9214fn default_warranty_defect_threshold() -> f64 {
9215 0.01
9216}
9217
9218impl Default for ManufacturingCostAccountingConfig {
9219 fn default() -> Self {
9220 Self {
9221 enabled: true,
9222 variance_accounts_enabled: true,
9223 warranty_provisions_enabled: true,
9224 warranty_defect_threshold: 0.01,
9225 }
9226 }
9227}
9228
9229fn default_bom_depth() -> u32 {
9230 4
9231}
9232
9233fn default_production_order_types() -> Vec<String> {
9234 vec![
9235 "standard".to_string(),
9236 "rework".to_string(),
9237 "prototype".to_string(),
9238 ]
9239}
9240
9241fn default_supplier_tiers() -> u32 {
9242 2
9243}
9244
9245fn default_cost_frequency() -> String {
9246 "quarterly".to_string()
9247}
9248
9249fn default_yield_rate() -> f64 {
9250 0.97
9251}
9252
9253fn default_scrap_threshold() -> f64 {
9254 0.03
9255}
9256
9257impl Default for ManufacturingConfig {
9258 fn default() -> Self {
9259 Self {
9260 enabled: false,
9261 bom_depth: default_bom_depth(),
9262 just_in_time: false,
9263 production_order_types: default_production_order_types(),
9264 quality_framework: Some("ISO_9001".to_string()),
9265 supplier_tiers: default_supplier_tiers(),
9266 standard_cost_frequency: default_cost_frequency(),
9267 target_yield_rate: default_yield_rate(),
9268 scrap_alert_threshold: default_scrap_threshold(),
9269 anomaly_rates: ManufacturingAnomalyRates::default(),
9270 cost_accounting: ManufacturingCostAccountingConfig::default(),
9271 }
9272 }
9273}
9274
9275#[derive(Debug, Clone, Serialize, Deserialize)]
9277pub struct ManufacturingAnomalyRates {
9278 #[serde(default = "default_mfg_yield_rate")]
9280 pub yield_manipulation: f64,
9281
9282 #[serde(default = "default_mfg_labor_rate")]
9284 pub labor_misallocation: f64,
9285
9286 #[serde(default = "default_mfg_phantom_rate")]
9288 pub phantom_production: f64,
9289
9290 #[serde(default = "default_mfg_cost_rate")]
9292 pub standard_cost_manipulation: f64,
9293
9294 #[serde(default = "default_mfg_inventory_rate")]
9296 pub inventory_fraud: f64,
9297}
9298
9299fn default_mfg_yield_rate() -> f64 {
9300 0.015
9301}
9302
9303fn default_mfg_labor_rate() -> f64 {
9304 0.02
9305}
9306
9307fn default_mfg_phantom_rate() -> f64 {
9308 0.005
9309}
9310
9311fn default_mfg_cost_rate() -> f64 {
9312 0.01
9313}
9314
9315fn default_mfg_inventory_rate() -> f64 {
9316 0.008
9317}
9318
9319impl Default for ManufacturingAnomalyRates {
9320 fn default() -> Self {
9321 Self {
9322 yield_manipulation: default_mfg_yield_rate(),
9323 labor_misallocation: default_mfg_labor_rate(),
9324 phantom_production: default_mfg_phantom_rate(),
9325 standard_cost_manipulation: default_mfg_cost_rate(),
9326 inventory_fraud: default_mfg_inventory_rate(),
9327 }
9328 }
9329}
9330
9331#[derive(Debug, Clone, Serialize, Deserialize)]
9333pub struct RetailConfig {
9334 #[serde(default)]
9336 pub enabled: bool,
9337
9338 #[serde(default)]
9340 pub store_types: RetailStoreTypeConfig,
9341
9342 #[serde(default = "default_retail_daily_txns")]
9344 pub avg_daily_transactions: u32,
9345
9346 #[serde(default = "default_true")]
9348 pub loss_prevention: bool,
9349
9350 #[serde(default = "default_shrinkage_rate")]
9352 pub shrinkage_rate: f64,
9353
9354 #[serde(default)]
9356 pub anomaly_rates: RetailAnomalyRates,
9357}
9358
9359fn default_retail_daily_txns() -> u32 {
9360 500
9361}
9362
9363fn default_shrinkage_rate() -> f64 {
9364 0.015
9365}
9366
9367impl Default for RetailConfig {
9368 fn default() -> Self {
9369 Self {
9370 enabled: false,
9371 store_types: RetailStoreTypeConfig::default(),
9372 avg_daily_transactions: default_retail_daily_txns(),
9373 loss_prevention: true,
9374 shrinkage_rate: default_shrinkage_rate(),
9375 anomaly_rates: RetailAnomalyRates::default(),
9376 }
9377 }
9378}
9379
9380#[derive(Debug, Clone, Serialize, Deserialize)]
9382pub struct RetailStoreTypeConfig {
9383 #[serde(default = "default_flagship_pct")]
9385 pub flagship: f64,
9386
9387 #[serde(default = "default_regional_pct")]
9389 pub regional: f64,
9390
9391 #[serde(default = "default_outlet_pct")]
9393 pub outlet: f64,
9394
9395 #[serde(default = "default_ecommerce_pct")]
9397 pub ecommerce: f64,
9398}
9399
9400fn default_flagship_pct() -> f64 {
9401 0.10
9402}
9403
9404fn default_regional_pct() -> f64 {
9405 0.50
9406}
9407
9408fn default_outlet_pct() -> f64 {
9409 0.25
9410}
9411
9412fn default_ecommerce_pct() -> f64 {
9413 0.15
9414}
9415
9416impl Default for RetailStoreTypeConfig {
9417 fn default() -> Self {
9418 Self {
9419 flagship: default_flagship_pct(),
9420 regional: default_regional_pct(),
9421 outlet: default_outlet_pct(),
9422 ecommerce: default_ecommerce_pct(),
9423 }
9424 }
9425}
9426
9427#[derive(Debug, Clone, Serialize, Deserialize)]
9429pub struct RetailAnomalyRates {
9430 #[serde(default = "default_sweethearting_rate")]
9432 pub sweethearting: f64,
9433
9434 #[serde(default = "default_skimming_rate")]
9436 pub skimming: f64,
9437
9438 #[serde(default = "default_refund_fraud_rate")]
9440 pub refund_fraud: f64,
9441
9442 #[serde(default = "default_void_abuse_rate")]
9444 pub void_abuse: f64,
9445
9446 #[serde(default = "default_gift_card_rate")]
9448 pub gift_card_fraud: f64,
9449
9450 #[serde(default = "default_retail_kickback_rate")]
9452 pub vendor_kickback: f64,
9453}
9454
9455fn default_sweethearting_rate() -> f64 {
9456 0.02
9457}
9458
9459fn default_skimming_rate() -> f64 {
9460 0.005
9461}
9462
9463fn default_refund_fraud_rate() -> f64 {
9464 0.015
9465}
9466
9467fn default_void_abuse_rate() -> f64 {
9468 0.01
9469}
9470
9471fn default_gift_card_rate() -> f64 {
9472 0.008
9473}
9474
9475fn default_retail_kickback_rate() -> f64 {
9476 0.003
9477}
9478
9479impl Default for RetailAnomalyRates {
9480 fn default() -> Self {
9481 Self {
9482 sweethearting: default_sweethearting_rate(),
9483 skimming: default_skimming_rate(),
9484 refund_fraud: default_refund_fraud_rate(),
9485 void_abuse: default_void_abuse_rate(),
9486 gift_card_fraud: default_gift_card_rate(),
9487 vendor_kickback: default_retail_kickback_rate(),
9488 }
9489 }
9490}
9491
9492#[derive(Debug, Clone, Serialize, Deserialize)]
9494pub struct HealthcareConfig {
9495 #[serde(default)]
9497 pub enabled: bool,
9498
9499 #[serde(default = "default_facility_type")]
9501 pub facility_type: String,
9502
9503 #[serde(default)]
9505 pub payer_mix: HealthcarePayerMix,
9506
9507 #[serde(default)]
9509 pub coding_systems: HealthcareCodingSystems,
9510
9511 #[serde(default)]
9513 pub compliance: HealthcareComplianceConfig,
9514
9515 #[serde(default = "default_daily_encounters")]
9517 pub avg_daily_encounters: u32,
9518
9519 #[serde(default = "default_charges_per_encounter")]
9521 pub avg_charges_per_encounter: u32,
9522
9523 #[serde(default = "default_hc_denial_rate")]
9525 pub denial_rate: f64,
9526
9527 #[serde(default = "default_hc_bad_debt_rate")]
9529 pub bad_debt_rate: f64,
9530
9531 #[serde(default = "default_hc_charity_care_rate")]
9533 pub charity_care_rate: f64,
9534
9535 #[serde(default)]
9537 pub anomaly_rates: HealthcareAnomalyRates,
9538}
9539
9540fn default_facility_type() -> String {
9541 "hospital".to_string()
9542}
9543
9544fn default_daily_encounters() -> u32 {
9545 150
9546}
9547
9548fn default_charges_per_encounter() -> u32 {
9549 8
9550}
9551
9552fn default_hc_denial_rate() -> f64 {
9553 0.05
9554}
9555
9556fn default_hc_bad_debt_rate() -> f64 {
9557 0.03
9558}
9559
9560fn default_hc_charity_care_rate() -> f64 {
9561 0.02
9562}
9563
9564impl Default for HealthcareConfig {
9565 fn default() -> Self {
9566 Self {
9567 enabled: false,
9568 facility_type: default_facility_type(),
9569 payer_mix: HealthcarePayerMix::default(),
9570 coding_systems: HealthcareCodingSystems::default(),
9571 compliance: HealthcareComplianceConfig::default(),
9572 avg_daily_encounters: default_daily_encounters(),
9573 avg_charges_per_encounter: default_charges_per_encounter(),
9574 denial_rate: default_hc_denial_rate(),
9575 bad_debt_rate: default_hc_bad_debt_rate(),
9576 charity_care_rate: default_hc_charity_care_rate(),
9577 anomaly_rates: HealthcareAnomalyRates::default(),
9578 }
9579 }
9580}
9581
9582#[derive(Debug, Clone, Serialize, Deserialize)]
9584pub struct HealthcarePayerMix {
9585 #[serde(default = "default_medicare_pct")]
9587 pub medicare: f64,
9588
9589 #[serde(default = "default_medicaid_pct")]
9591 pub medicaid: f64,
9592
9593 #[serde(default = "default_commercial_pct")]
9595 pub commercial: f64,
9596
9597 #[serde(default = "default_self_pay_pct")]
9599 pub self_pay: f64,
9600}
9601
9602fn default_medicare_pct() -> f64 {
9603 0.40
9604}
9605
9606fn default_medicaid_pct() -> f64 {
9607 0.20
9608}
9609
9610fn default_commercial_pct() -> f64 {
9611 0.30
9612}
9613
9614fn default_self_pay_pct() -> f64 {
9615 0.10
9616}
9617
9618impl Default for HealthcarePayerMix {
9619 fn default() -> Self {
9620 Self {
9621 medicare: default_medicare_pct(),
9622 medicaid: default_medicaid_pct(),
9623 commercial: default_commercial_pct(),
9624 self_pay: default_self_pay_pct(),
9625 }
9626 }
9627}
9628
9629#[derive(Debug, Clone, Serialize, Deserialize)]
9631pub struct HealthcareCodingSystems {
9632 #[serde(default = "default_true")]
9634 pub icd10: bool,
9635
9636 #[serde(default = "default_true")]
9638 pub cpt: bool,
9639
9640 #[serde(default = "default_true")]
9642 pub drg: bool,
9643
9644 #[serde(default = "default_true")]
9646 pub hcpcs: bool,
9647
9648 #[serde(default = "default_true")]
9650 pub revenue_codes: bool,
9651}
9652
9653impl Default for HealthcareCodingSystems {
9654 fn default() -> Self {
9655 Self {
9656 icd10: true,
9657 cpt: true,
9658 drg: true,
9659 hcpcs: true,
9660 revenue_codes: true,
9661 }
9662 }
9663}
9664
9665#[derive(Debug, Clone, Serialize, Deserialize)]
9667pub struct HealthcareComplianceConfig {
9668 #[serde(default = "default_true")]
9670 pub hipaa: bool,
9671
9672 #[serde(default = "default_true")]
9674 pub stark_law: bool,
9675
9676 #[serde(default = "default_true")]
9678 pub anti_kickback: bool,
9679
9680 #[serde(default = "default_true")]
9682 pub false_claims_act: bool,
9683
9684 #[serde(default = "default_true")]
9686 pub emtala: bool,
9687}
9688
9689impl Default for HealthcareComplianceConfig {
9690 fn default() -> Self {
9691 Self {
9692 hipaa: true,
9693 stark_law: true,
9694 anti_kickback: true,
9695 false_claims_act: true,
9696 emtala: true,
9697 }
9698 }
9699}
9700
9701#[derive(Debug, Clone, Serialize, Deserialize)]
9703pub struct HealthcareAnomalyRates {
9704 #[serde(default = "default_upcoding_rate")]
9706 pub upcoding: f64,
9707
9708 #[serde(default = "default_unbundling_rate")]
9710 pub unbundling: f64,
9711
9712 #[serde(default = "default_phantom_billing_rate")]
9714 pub phantom_billing: f64,
9715
9716 #[serde(default = "default_healthcare_kickback_rate")]
9718 pub kickbacks: f64,
9719
9720 #[serde(default = "default_duplicate_billing_rate")]
9722 pub duplicate_billing: f64,
9723
9724 #[serde(default = "default_med_necessity_rate")]
9726 pub medical_necessity_abuse: f64,
9727}
9728
9729fn default_upcoding_rate() -> f64 {
9730 0.02
9731}
9732
9733fn default_unbundling_rate() -> f64 {
9734 0.015
9735}
9736
9737fn default_phantom_billing_rate() -> f64 {
9738 0.005
9739}
9740
9741fn default_healthcare_kickback_rate() -> f64 {
9742 0.003
9743}
9744
9745fn default_duplicate_billing_rate() -> f64 {
9746 0.008
9747}
9748
9749fn default_med_necessity_rate() -> f64 {
9750 0.01
9751}
9752
9753impl Default for HealthcareAnomalyRates {
9754 fn default() -> Self {
9755 Self {
9756 upcoding: default_upcoding_rate(),
9757 unbundling: default_unbundling_rate(),
9758 phantom_billing: default_phantom_billing_rate(),
9759 kickbacks: default_healthcare_kickback_rate(),
9760 duplicate_billing: default_duplicate_billing_rate(),
9761 medical_necessity_abuse: default_med_necessity_rate(),
9762 }
9763 }
9764}
9765
9766#[derive(Debug, Clone, Serialize, Deserialize)]
9768pub struct TechnologyConfig {
9769 #[serde(default)]
9771 pub enabled: bool,
9772
9773 #[serde(default = "default_revenue_model")]
9775 pub revenue_model: String,
9776
9777 #[serde(default = "default_subscription_pct")]
9779 pub subscription_revenue_pct: f64,
9780
9781 #[serde(default = "default_license_pct")]
9783 pub license_revenue_pct: f64,
9784
9785 #[serde(default = "default_services_pct")]
9787 pub services_revenue_pct: f64,
9788
9789 #[serde(default)]
9791 pub rd_capitalization: RdCapitalizationConfig,
9792
9793 #[serde(default)]
9795 pub anomaly_rates: TechnologyAnomalyRates,
9796}
9797
9798fn default_revenue_model() -> String {
9799 "saas".to_string()
9800}
9801
9802fn default_subscription_pct() -> f64 {
9803 0.60
9804}
9805
9806fn default_license_pct() -> f64 {
9807 0.25
9808}
9809
9810fn default_services_pct() -> f64 {
9811 0.15
9812}
9813
9814impl Default for TechnologyConfig {
9815 fn default() -> Self {
9816 Self {
9817 enabled: false,
9818 revenue_model: default_revenue_model(),
9819 subscription_revenue_pct: default_subscription_pct(),
9820 license_revenue_pct: default_license_pct(),
9821 services_revenue_pct: default_services_pct(),
9822 rd_capitalization: RdCapitalizationConfig::default(),
9823 anomaly_rates: TechnologyAnomalyRates::default(),
9824 }
9825 }
9826}
9827
9828#[derive(Debug, Clone, Serialize, Deserialize)]
9830pub struct RdCapitalizationConfig {
9831 #[serde(default = "default_true")]
9833 pub enabled: bool,
9834
9835 #[serde(default = "default_cap_rate")]
9837 pub capitalization_rate: f64,
9838
9839 #[serde(default = "default_useful_life")]
9841 pub useful_life_years: u32,
9842}
9843
9844fn default_cap_rate() -> f64 {
9845 0.30
9846}
9847
9848fn default_useful_life() -> u32 {
9849 3
9850}
9851
9852impl Default for RdCapitalizationConfig {
9853 fn default() -> Self {
9854 Self {
9855 enabled: true,
9856 capitalization_rate: default_cap_rate(),
9857 useful_life_years: default_useful_life(),
9858 }
9859 }
9860}
9861
9862#[derive(Debug, Clone, Serialize, Deserialize)]
9864pub struct TechnologyAnomalyRates {
9865 #[serde(default = "default_premature_rev_rate")]
9867 pub premature_revenue: f64,
9868
9869 #[serde(default = "default_side_letter_rate")]
9871 pub side_letter_abuse: f64,
9872
9873 #[serde(default = "default_channel_stuffing_rate")]
9875 pub channel_stuffing: f64,
9876
9877 #[serde(default = "default_improper_cap_rate")]
9879 pub improper_capitalization: f64,
9880}
9881
9882fn default_premature_rev_rate() -> f64 {
9883 0.015
9884}
9885
9886fn default_side_letter_rate() -> f64 {
9887 0.008
9888}
9889
9890fn default_channel_stuffing_rate() -> f64 {
9891 0.01
9892}
9893
9894fn default_improper_cap_rate() -> f64 {
9895 0.012
9896}
9897
9898impl Default for TechnologyAnomalyRates {
9899 fn default() -> Self {
9900 Self {
9901 premature_revenue: default_premature_rev_rate(),
9902 side_letter_abuse: default_side_letter_rate(),
9903 channel_stuffing: default_channel_stuffing_rate(),
9904 improper_capitalization: default_improper_cap_rate(),
9905 }
9906 }
9907}
9908
9909#[derive(Debug, Clone, Serialize, Deserialize)]
9911pub struct FinancialServicesConfig {
9912 #[serde(default)]
9914 pub enabled: bool,
9915
9916 #[serde(default = "default_fi_type")]
9918 pub institution_type: String,
9919
9920 #[serde(default = "default_fi_regulatory")]
9922 pub regulatory_framework: String,
9923
9924 #[serde(default)]
9926 pub anomaly_rates: FinancialServicesAnomalyRates,
9927}
9928
9929fn default_fi_type() -> String {
9930 "commercial_bank".to_string()
9931}
9932
9933fn default_fi_regulatory() -> String {
9934 "us_banking".to_string()
9935}
9936
9937impl Default for FinancialServicesConfig {
9938 fn default() -> Self {
9939 Self {
9940 enabled: false,
9941 institution_type: default_fi_type(),
9942 regulatory_framework: default_fi_regulatory(),
9943 anomaly_rates: FinancialServicesAnomalyRates::default(),
9944 }
9945 }
9946}
9947
9948#[derive(Debug, Clone, Serialize, Deserialize)]
9950pub struct FinancialServicesAnomalyRates {
9951 #[serde(default = "default_loan_fraud_rate")]
9953 pub loan_fraud: f64,
9954
9955 #[serde(default = "default_trading_fraud_rate")]
9957 pub trading_fraud: f64,
9958
9959 #[serde(default = "default_insurance_fraud_rate")]
9961 pub insurance_fraud: f64,
9962
9963 #[serde(default = "default_account_manip_rate")]
9965 pub account_manipulation: f64,
9966}
9967
9968fn default_loan_fraud_rate() -> f64 {
9969 0.01
9970}
9971
9972fn default_trading_fraud_rate() -> f64 {
9973 0.008
9974}
9975
9976fn default_insurance_fraud_rate() -> f64 {
9977 0.012
9978}
9979
9980fn default_account_manip_rate() -> f64 {
9981 0.005
9982}
9983
9984impl Default for FinancialServicesAnomalyRates {
9985 fn default() -> Self {
9986 Self {
9987 loan_fraud: default_loan_fraud_rate(),
9988 trading_fraud: default_trading_fraud_rate(),
9989 insurance_fraud: default_insurance_fraud_rate(),
9990 account_manipulation: default_account_manip_rate(),
9991 }
9992 }
9993}
9994
9995#[derive(Debug, Clone, Serialize, Deserialize)]
9997pub struct ProfessionalServicesConfig {
9998 #[serde(default)]
10000 pub enabled: bool,
10001
10002 #[serde(default = "default_firm_type")]
10004 pub firm_type: String,
10005
10006 #[serde(default = "default_billing_model")]
10008 pub billing_model: String,
10009
10010 #[serde(default = "default_hourly_rate")]
10012 pub avg_hourly_rate: f64,
10013
10014 #[serde(default)]
10016 pub trust_accounting: TrustAccountingConfig,
10017
10018 #[serde(default)]
10020 pub anomaly_rates: ProfessionalServicesAnomalyRates,
10021}
10022
10023fn default_firm_type() -> String {
10024 "consulting".to_string()
10025}
10026
10027fn default_billing_model() -> String {
10028 "time_and_materials".to_string()
10029}
10030
10031fn default_hourly_rate() -> f64 {
10032 250.0
10033}
10034
10035impl Default for ProfessionalServicesConfig {
10036 fn default() -> Self {
10037 Self {
10038 enabled: false,
10039 firm_type: default_firm_type(),
10040 billing_model: default_billing_model(),
10041 avg_hourly_rate: default_hourly_rate(),
10042 trust_accounting: TrustAccountingConfig::default(),
10043 anomaly_rates: ProfessionalServicesAnomalyRates::default(),
10044 }
10045 }
10046}
10047
10048#[derive(Debug, Clone, Serialize, Deserialize)]
10050pub struct TrustAccountingConfig {
10051 #[serde(default)]
10053 pub enabled: bool,
10054
10055 #[serde(default = "default_true")]
10057 pub require_three_way_reconciliation: bool,
10058}
10059
10060impl Default for TrustAccountingConfig {
10061 fn default() -> Self {
10062 Self {
10063 enabled: false,
10064 require_three_way_reconciliation: true,
10065 }
10066 }
10067}
10068
10069#[derive(Debug, Clone, Serialize, Deserialize)]
10071pub struct ProfessionalServicesAnomalyRates {
10072 #[serde(default = "default_time_fraud_rate")]
10074 pub time_billing_fraud: f64,
10075
10076 #[serde(default = "default_expense_fraud_rate")]
10078 pub expense_fraud: f64,
10079
10080 #[serde(default = "default_trust_misappropriation_rate")]
10082 pub trust_misappropriation: f64,
10083}
10084
10085fn default_time_fraud_rate() -> f64 {
10086 0.02
10087}
10088
10089fn default_expense_fraud_rate() -> f64 {
10090 0.015
10091}
10092
10093fn default_trust_misappropriation_rate() -> f64 {
10094 0.003
10095}
10096
10097impl Default for ProfessionalServicesAnomalyRates {
10098 fn default() -> Self {
10099 Self {
10100 time_billing_fraud: default_time_fraud_rate(),
10101 expense_fraud: default_expense_fraud_rate(),
10102 trust_misappropriation: default_trust_misappropriation_rate(),
10103 }
10104 }
10105}
10106
10107#[derive(Debug, Clone, Serialize, Deserialize)]
10121pub struct FingerprintPrivacyConfig {
10122 #[serde(default)]
10124 pub level: String,
10125 #[serde(default = "default_epsilon")]
10127 pub epsilon: f64,
10128 #[serde(default = "default_delta")]
10130 pub delta: f64,
10131 #[serde(default = "default_k_anonymity")]
10133 pub k_anonymity: u32,
10134 #[serde(default)]
10136 pub composition_method: String,
10137}
10138
10139fn default_epsilon() -> f64 {
10140 1.0
10141}
10142
10143fn default_delta() -> f64 {
10144 1e-5
10145}
10146
10147fn default_k_anonymity() -> u32 {
10148 5
10149}
10150
10151impl Default for FingerprintPrivacyConfig {
10152 fn default() -> Self {
10153 Self {
10154 level: "standard".to_string(),
10155 epsilon: default_epsilon(),
10156 delta: default_delta(),
10157 k_anonymity: default_k_anonymity(),
10158 composition_method: "naive".to_string(),
10159 }
10160 }
10161}
10162
10163#[derive(Debug, Clone, Serialize, Deserialize)]
10177pub struct QualityGatesSchemaConfig {
10178 #[serde(default)]
10180 pub enabled: bool,
10181 #[serde(default = "default_gate_profile_name")]
10183 pub profile: String,
10184 #[serde(default)]
10186 pub fail_on_violation: bool,
10187 #[serde(default)]
10189 pub custom_gates: Vec<QualityGateEntry>,
10190}
10191
10192fn default_gate_profile_name() -> String {
10193 "default".to_string()
10194}
10195
10196impl Default for QualityGatesSchemaConfig {
10197 fn default() -> Self {
10198 Self {
10199 enabled: false,
10200 profile: default_gate_profile_name(),
10201 fail_on_violation: false,
10202 custom_gates: Vec::new(),
10203 }
10204 }
10205}
10206
10207#[derive(Debug, Clone, Serialize, Deserialize)]
10209pub struct QualityGateEntry {
10210 pub name: String,
10212 pub metric: String,
10216 pub threshold: f64,
10218 #[serde(default)]
10220 pub upper_threshold: Option<f64>,
10221 #[serde(default = "default_gate_comparison")]
10223 pub comparison: String,
10224}
10225
10226fn default_gate_comparison() -> String {
10227 "gte".to_string()
10228}
10229
10230#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10240pub struct ComplianceSchemaConfig {
10241 #[serde(default)]
10243 pub content_marking: ContentMarkingSchemaConfig,
10244 #[serde(default)]
10246 pub article10_report: bool,
10247 #[serde(default)]
10249 pub certificates: CertificateSchemaConfig,
10250}
10251
10252#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10254pub struct CertificateSchemaConfig {
10255 #[serde(default)]
10257 pub enabled: bool,
10258 #[serde(default)]
10260 pub signing_key_env: Option<String>,
10261 #[serde(default)]
10263 pub include_quality_metrics: bool,
10264}
10265
10266#[derive(Debug, Clone, Serialize, Deserialize)]
10268pub struct ContentMarkingSchemaConfig {
10269 #[serde(default = "default_true")]
10271 pub enabled: bool,
10272 #[serde(default = "default_marking_format")]
10274 pub format: String,
10275}
10276
10277fn default_marking_format() -> String {
10278 "embedded".to_string()
10279}
10280
10281impl Default for ContentMarkingSchemaConfig {
10282 fn default() -> Self {
10283 Self {
10284 enabled: true,
10285 format: default_marking_format(),
10286 }
10287 }
10288}
10289
10290#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10292pub struct WebhookSchemaConfig {
10293 #[serde(default)]
10295 pub enabled: bool,
10296 #[serde(default)]
10298 pub endpoints: Vec<WebhookEndpointConfig>,
10299}
10300
10301#[derive(Debug, Clone, Serialize, Deserialize)]
10303pub struct WebhookEndpointConfig {
10304 pub url: String,
10306 #[serde(default)]
10308 pub events: Vec<String>,
10309 #[serde(default)]
10311 pub secret: Option<String>,
10312 #[serde(default = "default_webhook_retries")]
10314 pub max_retries: u32,
10315 #[serde(default = "default_webhook_timeout")]
10317 pub timeout_secs: u64,
10318}
10319
10320fn default_webhook_retries() -> u32 {
10321 3
10322}
10323fn default_webhook_timeout() -> u64 {
10324 10
10325}
10326
10327#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10333pub struct SourceToPayConfig {
10334 #[serde(default)]
10336 pub enabled: bool,
10337 #[serde(default)]
10339 pub spend_analysis: SpendAnalysisConfig,
10340 #[serde(default)]
10342 pub sourcing: SourcingConfig,
10343 #[serde(default)]
10345 pub qualification: QualificationConfig,
10346 #[serde(default)]
10348 pub rfx: RfxConfig,
10349 #[serde(default)]
10351 pub contracts: ContractConfig,
10352 #[serde(default)]
10354 pub catalog: CatalogConfig,
10355 #[serde(default)]
10357 pub scorecards: ScorecardConfig,
10358 #[serde(default)]
10360 pub p2p_integration: P2PIntegrationConfig,
10361}
10362
10363#[derive(Debug, Clone, Serialize, Deserialize)]
10365pub struct SpendAnalysisConfig {
10366 #[serde(default = "default_hhi_threshold")]
10368 pub hhi_threshold: f64,
10369 #[serde(default = "default_contract_coverage_target")]
10371 pub contract_coverage_target: f64,
10372}
10373
10374impl Default for SpendAnalysisConfig {
10375 fn default() -> Self {
10376 Self {
10377 hhi_threshold: default_hhi_threshold(),
10378 contract_coverage_target: default_contract_coverage_target(),
10379 }
10380 }
10381}
10382
10383fn default_hhi_threshold() -> f64 {
10384 2500.0
10385}
10386fn default_contract_coverage_target() -> f64 {
10387 0.80
10388}
10389
10390#[derive(Debug, Clone, Serialize, Deserialize)]
10392pub struct SourcingConfig {
10393 #[serde(default = "default_sourcing_projects_per_year")]
10395 pub projects_per_year: u32,
10396 #[serde(default = "default_renewal_horizon_months")]
10398 pub renewal_horizon_months: u32,
10399 #[serde(default = "default_project_duration_months")]
10401 pub project_duration_months: u32,
10402}
10403
10404impl Default for SourcingConfig {
10405 fn default() -> Self {
10406 Self {
10407 projects_per_year: default_sourcing_projects_per_year(),
10408 renewal_horizon_months: default_renewal_horizon_months(),
10409 project_duration_months: default_project_duration_months(),
10410 }
10411 }
10412}
10413
10414fn default_sourcing_projects_per_year() -> u32 {
10415 10
10416}
10417fn default_renewal_horizon_months() -> u32 {
10418 3
10419}
10420fn default_project_duration_months() -> u32 {
10421 4
10422}
10423
10424#[derive(Debug, Clone, Serialize, Deserialize)]
10426pub struct QualificationConfig {
10427 #[serde(default = "default_qualification_pass_rate")]
10429 pub pass_rate: f64,
10430 #[serde(default = "default_qualification_validity_days")]
10432 pub validity_days: u32,
10433 #[serde(default = "default_financial_weight")]
10435 pub financial_weight: f64,
10436 #[serde(default = "default_quality_weight")]
10438 pub quality_weight: f64,
10439 #[serde(default = "default_delivery_weight")]
10441 pub delivery_weight: f64,
10442 #[serde(default = "default_compliance_weight")]
10444 pub compliance_weight: f64,
10445}
10446
10447impl Default for QualificationConfig {
10448 fn default() -> Self {
10449 Self {
10450 pass_rate: default_qualification_pass_rate(),
10451 validity_days: default_qualification_validity_days(),
10452 financial_weight: default_financial_weight(),
10453 quality_weight: default_quality_weight(),
10454 delivery_weight: default_delivery_weight(),
10455 compliance_weight: default_compliance_weight(),
10456 }
10457 }
10458}
10459
10460fn default_qualification_pass_rate() -> f64 {
10461 0.75
10462}
10463fn default_qualification_validity_days() -> u32 {
10464 365
10465}
10466fn default_financial_weight() -> f64 {
10467 0.25
10468}
10469fn default_quality_weight() -> f64 {
10470 0.30
10471}
10472fn default_delivery_weight() -> f64 {
10473 0.25
10474}
10475fn default_compliance_weight() -> f64 {
10476 0.20
10477}
10478
10479#[derive(Debug, Clone, Serialize, Deserialize)]
10481pub struct RfxConfig {
10482 #[serde(default = "default_rfi_threshold")]
10484 pub rfi_threshold: f64,
10485 #[serde(default = "default_min_invited_vendors")]
10487 pub min_invited_vendors: u32,
10488 #[serde(default = "default_max_invited_vendors")]
10490 pub max_invited_vendors: u32,
10491 #[serde(default = "default_response_rate")]
10493 pub response_rate: f64,
10494 #[serde(default = "default_price_weight")]
10496 pub default_price_weight: f64,
10497 #[serde(default = "default_rfx_quality_weight")]
10499 pub default_quality_weight: f64,
10500 #[serde(default = "default_rfx_delivery_weight")]
10502 pub default_delivery_weight: f64,
10503}
10504
10505impl Default for RfxConfig {
10506 fn default() -> Self {
10507 Self {
10508 rfi_threshold: default_rfi_threshold(),
10509 min_invited_vendors: default_min_invited_vendors(),
10510 max_invited_vendors: default_max_invited_vendors(),
10511 response_rate: default_response_rate(),
10512 default_price_weight: default_price_weight(),
10513 default_quality_weight: default_rfx_quality_weight(),
10514 default_delivery_weight: default_rfx_delivery_weight(),
10515 }
10516 }
10517}
10518
10519fn default_rfi_threshold() -> f64 {
10520 100_000.0
10521}
10522fn default_min_invited_vendors() -> u32 {
10523 3
10524}
10525fn default_max_invited_vendors() -> u32 {
10526 8
10527}
10528fn default_response_rate() -> f64 {
10529 0.70
10530}
10531fn default_price_weight() -> f64 {
10532 0.40
10533}
10534fn default_rfx_quality_weight() -> f64 {
10535 0.35
10536}
10537fn default_rfx_delivery_weight() -> f64 {
10538 0.25
10539}
10540
10541#[derive(Debug, Clone, Serialize, Deserialize)]
10543pub struct ContractConfig {
10544 #[serde(default = "default_min_contract_months")]
10546 pub min_duration_months: u32,
10547 #[serde(default = "default_max_contract_months")]
10549 pub max_duration_months: u32,
10550 #[serde(default = "default_auto_renewal_rate")]
10552 pub auto_renewal_rate: f64,
10553 #[serde(default = "default_amendment_rate")]
10555 pub amendment_rate: f64,
10556 #[serde(default)]
10558 pub type_distribution: ContractTypeDistribution,
10559}
10560
10561impl Default for ContractConfig {
10562 fn default() -> Self {
10563 Self {
10564 min_duration_months: default_min_contract_months(),
10565 max_duration_months: default_max_contract_months(),
10566 auto_renewal_rate: default_auto_renewal_rate(),
10567 amendment_rate: default_amendment_rate(),
10568 type_distribution: ContractTypeDistribution::default(),
10569 }
10570 }
10571}
10572
10573fn default_min_contract_months() -> u32 {
10574 12
10575}
10576fn default_max_contract_months() -> u32 {
10577 36
10578}
10579fn default_auto_renewal_rate() -> f64 {
10580 0.40
10581}
10582fn default_amendment_rate() -> f64 {
10583 0.20
10584}
10585
10586#[derive(Debug, Clone, Serialize, Deserialize)]
10588pub struct ContractTypeDistribution {
10589 #[serde(default = "default_fixed_price_pct")]
10591 pub fixed_price: f64,
10592 #[serde(default = "default_blanket_pct")]
10594 pub blanket: f64,
10595 #[serde(default = "default_time_materials_pct")]
10597 pub time_and_materials: f64,
10598 #[serde(default = "default_service_agreement_pct")]
10600 pub service_agreement: f64,
10601}
10602
10603impl Default for ContractTypeDistribution {
10604 fn default() -> Self {
10605 Self {
10606 fixed_price: default_fixed_price_pct(),
10607 blanket: default_blanket_pct(),
10608 time_and_materials: default_time_materials_pct(),
10609 service_agreement: default_service_agreement_pct(),
10610 }
10611 }
10612}
10613
10614fn default_fixed_price_pct() -> f64 {
10615 0.40
10616}
10617fn default_blanket_pct() -> f64 {
10618 0.30
10619}
10620fn default_time_materials_pct() -> f64 {
10621 0.15
10622}
10623fn default_service_agreement_pct() -> f64 {
10624 0.15
10625}
10626
10627#[derive(Debug, Clone, Serialize, Deserialize)]
10629pub struct CatalogConfig {
10630 #[serde(default = "default_preferred_vendor_flag_rate")]
10632 pub preferred_vendor_flag_rate: f64,
10633 #[serde(default = "default_multi_source_rate")]
10635 pub multi_source_rate: f64,
10636}
10637
10638impl Default for CatalogConfig {
10639 fn default() -> Self {
10640 Self {
10641 preferred_vendor_flag_rate: default_preferred_vendor_flag_rate(),
10642 multi_source_rate: default_multi_source_rate(),
10643 }
10644 }
10645}
10646
10647fn default_preferred_vendor_flag_rate() -> f64 {
10648 0.70
10649}
10650fn default_multi_source_rate() -> f64 {
10651 0.25
10652}
10653
10654#[derive(Debug, Clone, Serialize, Deserialize)]
10656pub struct ScorecardConfig {
10657 #[serde(default = "default_scorecard_frequency")]
10659 pub frequency: String,
10660 #[serde(default = "default_otd_weight")]
10662 pub on_time_delivery_weight: f64,
10663 #[serde(default = "default_quality_score_weight")]
10665 pub quality_weight: f64,
10666 #[serde(default = "default_price_score_weight")]
10668 pub price_weight: f64,
10669 #[serde(default = "default_responsiveness_weight")]
10671 pub responsiveness_weight: f64,
10672 #[serde(default = "default_grade_a_threshold")]
10674 pub grade_a_threshold: f64,
10675 #[serde(default = "default_grade_b_threshold")]
10677 pub grade_b_threshold: f64,
10678 #[serde(default = "default_grade_c_threshold")]
10680 pub grade_c_threshold: f64,
10681}
10682
10683impl Default for ScorecardConfig {
10684 fn default() -> Self {
10685 Self {
10686 frequency: default_scorecard_frequency(),
10687 on_time_delivery_weight: default_otd_weight(),
10688 quality_weight: default_quality_score_weight(),
10689 price_weight: default_price_score_weight(),
10690 responsiveness_weight: default_responsiveness_weight(),
10691 grade_a_threshold: default_grade_a_threshold(),
10692 grade_b_threshold: default_grade_b_threshold(),
10693 grade_c_threshold: default_grade_c_threshold(),
10694 }
10695 }
10696}
10697
10698fn default_scorecard_frequency() -> String {
10699 "quarterly".to_string()
10700}
10701fn default_otd_weight() -> f64 {
10702 0.30
10703}
10704fn default_quality_score_weight() -> f64 {
10705 0.30
10706}
10707fn default_price_score_weight() -> f64 {
10708 0.25
10709}
10710fn default_responsiveness_weight() -> f64 {
10711 0.15
10712}
10713fn default_grade_a_threshold() -> f64 {
10714 90.0
10715}
10716fn default_grade_b_threshold() -> f64 {
10717 75.0
10718}
10719fn default_grade_c_threshold() -> f64 {
10720 60.0
10721}
10722
10723#[derive(Debug, Clone, Serialize, Deserialize)]
10725pub struct P2PIntegrationConfig {
10726 #[serde(default = "default_off_contract_rate")]
10728 pub off_contract_rate: f64,
10729 #[serde(default = "default_price_tolerance")]
10731 pub price_tolerance: f64,
10732 #[serde(default)]
10734 pub catalog_enforcement: bool,
10735}
10736
10737impl Default for P2PIntegrationConfig {
10738 fn default() -> Self {
10739 Self {
10740 off_contract_rate: default_off_contract_rate(),
10741 price_tolerance: default_price_tolerance(),
10742 catalog_enforcement: false,
10743 }
10744 }
10745}
10746
10747fn default_off_contract_rate() -> f64 {
10748 0.15
10749}
10750fn default_price_tolerance() -> f64 {
10751 0.02
10752}
10753
10754#[derive(Debug, Clone, Serialize, Deserialize)]
10758pub struct FinancialReportingConfig {
10759 #[serde(default)]
10761 pub enabled: bool,
10762 #[serde(default = "default_true")]
10764 pub generate_balance_sheet: bool,
10765 #[serde(default = "default_true")]
10767 pub generate_income_statement: bool,
10768 #[serde(default = "default_true")]
10770 pub generate_cash_flow: bool,
10771 #[serde(default = "default_true")]
10773 pub generate_changes_in_equity: bool,
10774 #[serde(default = "default_comparative_periods")]
10776 pub comparative_periods: u32,
10777 #[serde(default)]
10779 pub management_kpis: ManagementKpisConfig,
10780 #[serde(default)]
10782 pub budgets: BudgetConfig,
10783}
10784
10785impl Default for FinancialReportingConfig {
10786 fn default() -> Self {
10787 Self {
10788 enabled: false,
10789 generate_balance_sheet: true,
10790 generate_income_statement: true,
10791 generate_cash_flow: true,
10792 generate_changes_in_equity: true,
10793 comparative_periods: default_comparative_periods(),
10794 management_kpis: ManagementKpisConfig::default(),
10795 budgets: BudgetConfig::default(),
10796 }
10797 }
10798}
10799
10800fn default_comparative_periods() -> u32 {
10801 1
10802}
10803
10804#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10806pub struct ManagementKpisConfig {
10807 #[serde(default)]
10809 pub enabled: bool,
10810 #[serde(default = "default_kpi_frequency")]
10812 pub frequency: String,
10813}
10814
10815fn default_kpi_frequency() -> String {
10816 "monthly".to_string()
10817}
10818
10819#[derive(Debug, Clone, Serialize, Deserialize)]
10821pub struct BudgetConfig {
10822 #[serde(default)]
10824 pub enabled: bool,
10825 #[serde(default = "default_revenue_growth_rate")]
10827 pub revenue_growth_rate: f64,
10828 #[serde(default = "default_expense_inflation_rate")]
10830 pub expense_inflation_rate: f64,
10831 #[serde(default = "default_variance_noise")]
10833 pub variance_noise: f64,
10834}
10835
10836impl Default for BudgetConfig {
10837 fn default() -> Self {
10838 Self {
10839 enabled: false,
10840 revenue_growth_rate: default_revenue_growth_rate(),
10841 expense_inflation_rate: default_expense_inflation_rate(),
10842 variance_noise: default_variance_noise(),
10843 }
10844 }
10845}
10846
10847fn default_revenue_growth_rate() -> f64 {
10848 0.05
10849}
10850fn default_expense_inflation_rate() -> f64 {
10851 0.03
10852}
10853fn default_variance_noise() -> f64 {
10854 0.10
10855}
10856
10857#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10861pub struct HrConfig {
10862 #[serde(default)]
10864 pub enabled: bool,
10865 #[serde(default)]
10867 pub payroll: PayrollConfig,
10868 #[serde(default)]
10870 pub time_attendance: TimeAttendanceConfig,
10871 #[serde(default)]
10873 pub expenses: ExpenseConfig,
10874}
10875
10876#[derive(Debug, Clone, Serialize, Deserialize)]
10878pub struct PayrollConfig {
10879 #[serde(default = "default_true")]
10881 pub enabled: bool,
10882 #[serde(default = "default_pay_frequency")]
10884 pub pay_frequency: String,
10885 #[serde(default)]
10887 pub salary_ranges: PayrollSalaryRanges,
10888 #[serde(default)]
10890 pub tax_rates: PayrollTaxRates,
10891 #[serde(default = "default_benefits_enrollment_rate")]
10893 pub benefits_enrollment_rate: f64,
10894 #[serde(default = "default_retirement_participation_rate")]
10896 pub retirement_participation_rate: f64,
10897}
10898
10899impl Default for PayrollConfig {
10900 fn default() -> Self {
10901 Self {
10902 enabled: true,
10903 pay_frequency: default_pay_frequency(),
10904 salary_ranges: PayrollSalaryRanges::default(),
10905 tax_rates: PayrollTaxRates::default(),
10906 benefits_enrollment_rate: default_benefits_enrollment_rate(),
10907 retirement_participation_rate: default_retirement_participation_rate(),
10908 }
10909 }
10910}
10911
10912fn default_pay_frequency() -> String {
10913 "monthly".to_string()
10914}
10915fn default_benefits_enrollment_rate() -> f64 {
10916 0.60
10917}
10918fn default_retirement_participation_rate() -> f64 {
10919 0.45
10920}
10921
10922#[derive(Debug, Clone, Serialize, Deserialize)]
10924pub struct PayrollSalaryRanges {
10925 #[serde(default = "default_staff_min")]
10927 pub staff_min: f64,
10928 #[serde(default = "default_staff_max")]
10929 pub staff_max: f64,
10930 #[serde(default = "default_manager_min")]
10932 pub manager_min: f64,
10933 #[serde(default = "default_manager_max")]
10934 pub manager_max: f64,
10935 #[serde(default = "default_director_min")]
10937 pub director_min: f64,
10938 #[serde(default = "default_director_max")]
10939 pub director_max: f64,
10940 #[serde(default = "default_executive_min")]
10942 pub executive_min: f64,
10943 #[serde(default = "default_executive_max")]
10944 pub executive_max: f64,
10945}
10946
10947impl Default for PayrollSalaryRanges {
10948 fn default() -> Self {
10949 Self {
10950 staff_min: default_staff_min(),
10951 staff_max: default_staff_max(),
10952 manager_min: default_manager_min(),
10953 manager_max: default_manager_max(),
10954 director_min: default_director_min(),
10955 director_max: default_director_max(),
10956 executive_min: default_executive_min(),
10957 executive_max: default_executive_max(),
10958 }
10959 }
10960}
10961
10962fn default_staff_min() -> f64 {
10963 50_000.0
10964}
10965fn default_staff_max() -> f64 {
10966 70_000.0
10967}
10968fn default_manager_min() -> f64 {
10969 80_000.0
10970}
10971fn default_manager_max() -> f64 {
10972 120_000.0
10973}
10974fn default_director_min() -> f64 {
10975 120_000.0
10976}
10977fn default_director_max() -> f64 {
10978 180_000.0
10979}
10980fn default_executive_min() -> f64 {
10981 180_000.0
10982}
10983fn default_executive_max() -> f64 {
10984 350_000.0
10985}
10986
10987#[derive(Debug, Clone, Serialize, Deserialize)]
10989pub struct PayrollTaxRates {
10990 #[serde(default = "default_federal_rate")]
10992 pub federal_effective: f64,
10993 #[serde(default = "default_state_rate")]
10995 pub state_effective: f64,
10996 #[serde(default = "default_fica_rate")]
10998 pub fica: f64,
10999}
11000
11001impl Default for PayrollTaxRates {
11002 fn default() -> Self {
11003 Self {
11004 federal_effective: default_federal_rate(),
11005 state_effective: default_state_rate(),
11006 fica: default_fica_rate(),
11007 }
11008 }
11009}
11010
11011fn default_federal_rate() -> f64 {
11012 0.22
11013}
11014fn default_state_rate() -> f64 {
11015 0.05
11016}
11017fn default_fica_rate() -> f64 {
11018 0.0765
11019}
11020
11021#[derive(Debug, Clone, Serialize, Deserialize)]
11023pub struct TimeAttendanceConfig {
11024 #[serde(default = "default_true")]
11026 pub enabled: bool,
11027 #[serde(default = "default_overtime_rate")]
11029 pub overtime_rate: f64,
11030}
11031
11032impl Default for TimeAttendanceConfig {
11033 fn default() -> Self {
11034 Self {
11035 enabled: true,
11036 overtime_rate: default_overtime_rate(),
11037 }
11038 }
11039}
11040
11041fn default_overtime_rate() -> f64 {
11042 0.10
11043}
11044
11045#[derive(Debug, Clone, Serialize, Deserialize)]
11047pub struct ExpenseConfig {
11048 #[serde(default = "default_true")]
11050 pub enabled: bool,
11051 #[serde(default = "default_expense_submission_rate")]
11053 pub submission_rate: f64,
11054 #[serde(default = "default_policy_violation_rate")]
11056 pub policy_violation_rate: f64,
11057}
11058
11059impl Default for ExpenseConfig {
11060 fn default() -> Self {
11061 Self {
11062 enabled: true,
11063 submission_rate: default_expense_submission_rate(),
11064 policy_violation_rate: default_policy_violation_rate(),
11065 }
11066 }
11067}
11068
11069fn default_expense_submission_rate() -> f64 {
11070 0.30
11071}
11072fn default_policy_violation_rate() -> f64 {
11073 0.08
11074}
11075
11076#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11080pub struct ManufacturingProcessConfig {
11081 #[serde(default)]
11083 pub enabled: bool,
11084 #[serde(default)]
11086 pub production_orders: ProductionOrderConfig,
11087 #[serde(default)]
11089 pub costing: ManufacturingCostingConfig,
11090 #[serde(default)]
11092 pub routing: RoutingConfig,
11093}
11094
11095#[derive(Debug, Clone, Serialize, Deserialize)]
11097pub struct ProductionOrderConfig {
11098 #[serde(default = "default_prod_orders_per_month")]
11100 pub orders_per_month: u32,
11101 #[serde(default = "default_prod_avg_batch_size")]
11103 pub avg_batch_size: u32,
11104 #[serde(default = "default_prod_yield_rate")]
11106 pub yield_rate: f64,
11107 #[serde(default = "default_prod_make_to_order_rate")]
11109 pub make_to_order_rate: f64,
11110 #[serde(default = "default_prod_rework_rate")]
11112 pub rework_rate: f64,
11113}
11114
11115impl Default for ProductionOrderConfig {
11116 fn default() -> Self {
11117 Self {
11118 orders_per_month: default_prod_orders_per_month(),
11119 avg_batch_size: default_prod_avg_batch_size(),
11120 yield_rate: default_prod_yield_rate(),
11121 make_to_order_rate: default_prod_make_to_order_rate(),
11122 rework_rate: default_prod_rework_rate(),
11123 }
11124 }
11125}
11126
11127fn default_prod_orders_per_month() -> u32 {
11128 50
11129}
11130fn default_prod_avg_batch_size() -> u32 {
11131 100
11132}
11133fn default_prod_yield_rate() -> f64 {
11134 0.97
11135}
11136fn default_prod_make_to_order_rate() -> f64 {
11137 0.20
11138}
11139fn default_prod_rework_rate() -> f64 {
11140 0.03
11141}
11142
11143#[derive(Debug, Clone, Serialize, Deserialize)]
11145pub struct ManufacturingCostingConfig {
11146 #[serde(default = "default_labor_rate")]
11148 pub labor_rate_per_hour: f64,
11149 #[serde(default = "default_overhead_rate")]
11151 pub overhead_rate: f64,
11152 #[serde(default = "default_cost_update_frequency")]
11154 pub standard_cost_update_frequency: String,
11155}
11156
11157impl Default for ManufacturingCostingConfig {
11158 fn default() -> Self {
11159 Self {
11160 labor_rate_per_hour: default_labor_rate(),
11161 overhead_rate: default_overhead_rate(),
11162 standard_cost_update_frequency: default_cost_update_frequency(),
11163 }
11164 }
11165}
11166
11167fn default_labor_rate() -> f64 {
11168 35.0
11169}
11170fn default_overhead_rate() -> f64 {
11171 1.50
11172}
11173fn default_cost_update_frequency() -> String {
11174 "quarterly".to_string()
11175}
11176
11177#[derive(Debug, Clone, Serialize, Deserialize)]
11179pub struct RoutingConfig {
11180 #[serde(default = "default_avg_operations")]
11182 pub avg_operations: u32,
11183 #[serde(default = "default_setup_time")]
11185 pub setup_time_hours: f64,
11186 #[serde(default = "default_run_time_variation")]
11188 pub run_time_variation: f64,
11189}
11190
11191impl Default for RoutingConfig {
11192 fn default() -> Self {
11193 Self {
11194 avg_operations: default_avg_operations(),
11195 setup_time_hours: default_setup_time(),
11196 run_time_variation: default_run_time_variation(),
11197 }
11198 }
11199}
11200
11201fn default_avg_operations() -> u32 {
11202 4
11203}
11204fn default_setup_time() -> f64 {
11205 1.5
11206}
11207fn default_run_time_variation() -> f64 {
11208 0.15
11209}
11210
11211#[derive(Debug, Clone, Serialize, Deserialize)]
11215pub struct SalesQuoteConfig {
11216 #[serde(default)]
11218 pub enabled: bool,
11219 #[serde(default = "default_quotes_per_month")]
11221 pub quotes_per_month: u32,
11222 #[serde(default = "default_quote_win_rate")]
11224 pub win_rate: f64,
11225 #[serde(default = "default_quote_validity_days")]
11227 pub validity_days: u32,
11228}
11229
11230impl Default for SalesQuoteConfig {
11231 fn default() -> Self {
11232 Self {
11233 enabled: false,
11234 quotes_per_month: default_quotes_per_month(),
11235 win_rate: default_quote_win_rate(),
11236 validity_days: default_quote_validity_days(),
11237 }
11238 }
11239}
11240
11241fn default_quotes_per_month() -> u32 {
11242 30
11243}
11244fn default_quote_win_rate() -> f64 {
11245 0.35
11246}
11247fn default_quote_validity_days() -> u32 {
11248 30
11249}
11250
11251#[derive(Debug, Clone, Serialize, Deserialize)]
11260pub struct TaxConfig {
11261 #[serde(default)]
11263 pub enabled: bool,
11264 #[serde(default)]
11266 pub jurisdictions: TaxJurisdictionConfig,
11267 #[serde(default)]
11269 pub vat_gst: VatGstConfig,
11270 #[serde(default)]
11272 pub sales_tax: SalesTaxConfig,
11273 #[serde(default)]
11275 pub withholding: WithholdingTaxSchemaConfig,
11276 #[serde(default)]
11278 pub provisions: TaxProvisionSchemaConfig,
11279 #[serde(default)]
11281 pub payroll_tax: PayrollTaxSchemaConfig,
11282 #[serde(default = "default_tax_anomaly_rate")]
11284 pub anomaly_rate: f64,
11285}
11286
11287fn default_tax_anomaly_rate() -> f64 {
11288 0.03
11289}
11290
11291impl Default for TaxConfig {
11292 fn default() -> Self {
11293 Self {
11294 enabled: false,
11295 jurisdictions: TaxJurisdictionConfig::default(),
11296 vat_gst: VatGstConfig::default(),
11297 sales_tax: SalesTaxConfig::default(),
11298 withholding: WithholdingTaxSchemaConfig::default(),
11299 provisions: TaxProvisionSchemaConfig::default(),
11300 payroll_tax: PayrollTaxSchemaConfig::default(),
11301 anomaly_rate: default_tax_anomaly_rate(),
11302 }
11303 }
11304}
11305
11306#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11311pub struct TaxJurisdictionConfig {
11312 #[serde(default)]
11314 pub countries: Vec<String>,
11315 #[serde(default)]
11317 pub include_subnational: bool,
11318}
11319
11320#[derive(Debug, Clone, Serialize, Deserialize)]
11325pub struct VatGstConfig {
11326 #[serde(default)]
11328 pub enabled: bool,
11329 #[serde(default)]
11331 pub standard_rates: std::collections::HashMap<String, f64>,
11332 #[serde(default)]
11334 pub reduced_rates: std::collections::HashMap<String, f64>,
11335 #[serde(default)]
11337 pub exempt_categories: Vec<String>,
11338 #[serde(default = "default_true")]
11340 pub reverse_charge: bool,
11341}
11342
11343impl Default for VatGstConfig {
11344 fn default() -> Self {
11345 Self {
11346 enabled: false,
11347 standard_rates: std::collections::HashMap::new(),
11348 reduced_rates: std::collections::HashMap::new(),
11349 exempt_categories: Vec::new(),
11350 reverse_charge: true,
11351 }
11352 }
11353}
11354
11355#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11359pub struct SalesTaxConfig {
11360 #[serde(default)]
11362 pub enabled: bool,
11363 #[serde(default)]
11365 pub nexus_states: Vec<String>,
11366}
11367
11368#[derive(Debug, Clone, Serialize, Deserialize)]
11373pub struct WithholdingTaxSchemaConfig {
11374 #[serde(default)]
11376 pub enabled: bool,
11377 #[serde(default = "default_true")]
11379 pub treaty_network: bool,
11380 #[serde(default = "default_withholding_rate")]
11382 pub default_rate: f64,
11383 #[serde(default = "default_treaty_reduced_rate")]
11385 pub treaty_reduced_rate: f64,
11386}
11387
11388fn default_withholding_rate() -> f64 {
11389 0.30
11390}
11391
11392fn default_treaty_reduced_rate() -> f64 {
11393 0.15
11394}
11395
11396impl Default for WithholdingTaxSchemaConfig {
11397 fn default() -> Self {
11398 Self {
11399 enabled: false,
11400 treaty_network: true,
11401 default_rate: default_withholding_rate(),
11402 treaty_reduced_rate: default_treaty_reduced_rate(),
11403 }
11404 }
11405}
11406
11407#[derive(Debug, Clone, Serialize, Deserialize)]
11412pub struct TaxProvisionSchemaConfig {
11413 #[serde(default = "default_true")]
11416 pub enabled: bool,
11417 #[serde(default = "default_statutory_rate")]
11419 pub statutory_rate: f64,
11420 #[serde(default = "default_true")]
11422 pub uncertain_positions: bool,
11423}
11424
11425fn default_statutory_rate() -> f64 {
11426 0.21
11427}
11428
11429impl Default for TaxProvisionSchemaConfig {
11430 fn default() -> Self {
11431 Self {
11432 enabled: true,
11433 statutory_rate: default_statutory_rate(),
11434 uncertain_positions: true,
11435 }
11436 }
11437}
11438
11439#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11444pub struct PayrollTaxSchemaConfig {
11445 #[serde(default)]
11447 pub enabled: bool,
11448}
11449
11450#[derive(Debug, Clone, Serialize, Deserialize)]
11460pub struct TreasuryConfig {
11461 #[serde(default)]
11463 pub enabled: bool,
11464 #[serde(default)]
11466 pub cash_positioning: CashPositioningConfig,
11467 #[serde(default)]
11469 pub cash_forecasting: CashForecastingConfig,
11470 #[serde(default)]
11472 pub cash_pooling: CashPoolingConfig,
11473 #[serde(default)]
11475 pub hedging: HedgingSchemaConfig,
11476 #[serde(default)]
11478 pub debt: DebtSchemaConfig,
11479 #[serde(default)]
11481 pub netting: NettingSchemaConfig,
11482 #[serde(default)]
11484 pub bank_guarantees: BankGuaranteeSchemaConfig,
11485 #[serde(default = "default_treasury_anomaly_rate")]
11487 pub anomaly_rate: f64,
11488}
11489
11490fn default_treasury_anomaly_rate() -> f64 {
11491 0.02
11492}
11493
11494impl Default for TreasuryConfig {
11495 fn default() -> Self {
11496 Self {
11497 enabled: false,
11498 cash_positioning: CashPositioningConfig::default(),
11499 cash_forecasting: CashForecastingConfig::default(),
11500 cash_pooling: CashPoolingConfig::default(),
11501 hedging: HedgingSchemaConfig::default(),
11502 debt: DebtSchemaConfig::default(),
11503 netting: NettingSchemaConfig::default(),
11504 bank_guarantees: BankGuaranteeSchemaConfig::default(),
11505 anomaly_rate: default_treasury_anomaly_rate(),
11506 }
11507 }
11508}
11509
11510#[derive(Debug, Clone, Serialize, Deserialize)]
11514pub struct CashPositioningConfig {
11515 #[serde(default = "default_true")]
11517 pub enabled: bool,
11518 #[serde(default = "default_cash_frequency")]
11520 pub frequency: String,
11521 #[serde(default = "default_minimum_balance_policy")]
11523 pub minimum_balance_policy: f64,
11524}
11525
11526fn default_cash_frequency() -> String {
11527 "daily".to_string()
11528}
11529
11530fn default_minimum_balance_policy() -> f64 {
11531 100_000.0
11532}
11533
11534impl Default for CashPositioningConfig {
11535 fn default() -> Self {
11536 Self {
11537 enabled: true,
11538 frequency: default_cash_frequency(),
11539 minimum_balance_policy: default_minimum_balance_policy(),
11540 }
11541 }
11542}
11543
11544#[derive(Debug, Clone, Serialize, Deserialize)]
11548pub struct CashForecastingConfig {
11549 #[serde(default = "default_true")]
11551 pub enabled: bool,
11552 #[serde(default = "default_horizon_days")]
11554 pub horizon_days: u32,
11555 #[serde(default = "default_ar_probability_curve")]
11557 pub ar_collection_probability_curve: String,
11558 #[serde(default = "default_confidence_interval")]
11560 pub confidence_interval: f64,
11561}
11562
11563fn default_horizon_days() -> u32 {
11564 90
11565}
11566
11567fn default_ar_probability_curve() -> String {
11568 "aging".to_string()
11569}
11570
11571fn default_confidence_interval() -> f64 {
11572 0.90
11573}
11574
11575impl Default for CashForecastingConfig {
11576 fn default() -> Self {
11577 Self {
11578 enabled: true,
11579 horizon_days: default_horizon_days(),
11580 ar_collection_probability_curve: default_ar_probability_curve(),
11581 confidence_interval: default_confidence_interval(),
11582 }
11583 }
11584}
11585
11586#[derive(Debug, Clone, Serialize, Deserialize)]
11590pub struct CashPoolingConfig {
11591 #[serde(default)]
11593 pub enabled: bool,
11594 #[serde(default = "default_pool_type")]
11596 pub pool_type: String,
11597 #[serde(default = "default_sweep_time")]
11599 pub sweep_time: String,
11600}
11601
11602fn default_pool_type() -> String {
11603 "zero_balancing".to_string()
11604}
11605
11606fn default_sweep_time() -> String {
11607 "16:00".to_string()
11608}
11609
11610impl Default for CashPoolingConfig {
11611 fn default() -> Self {
11612 Self {
11613 enabled: false,
11614 pool_type: default_pool_type(),
11615 sweep_time: default_sweep_time(),
11616 }
11617 }
11618}
11619
11620#[derive(Debug, Clone, Serialize, Deserialize)]
11625pub struct HedgingSchemaConfig {
11626 #[serde(default)]
11628 pub enabled: bool,
11629 #[serde(default = "default_hedge_ratio")]
11631 pub hedge_ratio: f64,
11632 #[serde(default = "default_hedge_instruments")]
11634 pub instruments: Vec<String>,
11635 #[serde(default = "default_true")]
11637 pub hedge_accounting: bool,
11638 #[serde(default = "default_effectiveness_method")]
11640 pub effectiveness_method: String,
11641}
11642
11643fn default_hedge_ratio() -> f64 {
11644 0.75
11645}
11646
11647fn default_hedge_instruments() -> Vec<String> {
11648 vec!["fx_forward".to_string(), "interest_rate_swap".to_string()]
11649}
11650
11651fn default_effectiveness_method() -> String {
11652 "regression".to_string()
11653}
11654
11655impl Default for HedgingSchemaConfig {
11656 fn default() -> Self {
11657 Self {
11658 enabled: false,
11659 hedge_ratio: default_hedge_ratio(),
11660 instruments: default_hedge_instruments(),
11661 hedge_accounting: true,
11662 effectiveness_method: default_effectiveness_method(),
11663 }
11664 }
11665}
11666
11667#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11672pub struct DebtSchemaConfig {
11673 #[serde(default)]
11675 pub enabled: bool,
11676 #[serde(default)]
11678 pub instruments: Vec<DebtInstrumentDef>,
11679 #[serde(default)]
11681 pub covenants: Vec<CovenantDef>,
11682}
11683
11684#[derive(Debug, Clone, Serialize, Deserialize)]
11686pub struct DebtInstrumentDef {
11687 #[serde(rename = "type")]
11689 pub instrument_type: String,
11690 #[serde(default)]
11692 pub principal: Option<f64>,
11693 #[serde(default)]
11695 pub rate: Option<f64>,
11696 #[serde(default)]
11698 pub maturity_months: Option<u32>,
11699 #[serde(default)]
11701 pub facility: Option<f64>,
11702}
11703
11704#[derive(Debug, Clone, Serialize, Deserialize)]
11706pub struct CovenantDef {
11707 #[serde(rename = "type")]
11710 pub covenant_type: String,
11711 pub threshold: f64,
11713}
11714
11715#[derive(Debug, Clone, Serialize, Deserialize)]
11719pub struct NettingSchemaConfig {
11720 #[serde(default)]
11722 pub enabled: bool,
11723 #[serde(default = "default_netting_cycle")]
11725 pub cycle: String,
11726}
11727
11728fn default_netting_cycle() -> String {
11729 "monthly".to_string()
11730}
11731
11732impl Default for NettingSchemaConfig {
11733 fn default() -> Self {
11734 Self {
11735 enabled: false,
11736 cycle: default_netting_cycle(),
11737 }
11738 }
11739}
11740
11741#[derive(Debug, Clone, Serialize, Deserialize)]
11745pub struct BankGuaranteeSchemaConfig {
11746 #[serde(default)]
11748 pub enabled: bool,
11749 #[serde(default = "default_guarantee_count")]
11751 pub count: u32,
11752}
11753
11754fn default_guarantee_count() -> u32 {
11755 5
11756}
11757
11758impl Default for BankGuaranteeSchemaConfig {
11759 fn default() -> Self {
11760 Self {
11761 enabled: false,
11762 count: default_guarantee_count(),
11763 }
11764 }
11765}
11766
11767#[derive(Debug, Clone, Serialize, Deserialize)]
11776pub struct ProjectAccountingConfig {
11777 #[serde(default)]
11779 pub enabled: bool,
11780 #[serde(default = "default_project_count")]
11782 pub project_count: u32,
11783 #[serde(default)]
11785 pub project_types: ProjectTypeDistribution,
11786 #[serde(default)]
11788 pub wbs: WbsSchemaConfig,
11789 #[serde(default)]
11791 pub cost_allocation: CostAllocationConfig,
11792 #[serde(default)]
11794 pub revenue_recognition: ProjectRevenueRecognitionConfig,
11795 #[serde(default)]
11797 pub milestones: MilestoneSchemaConfig,
11798 #[serde(default)]
11800 pub change_orders: ChangeOrderSchemaConfig,
11801 #[serde(default)]
11803 pub retainage: RetainageSchemaConfig,
11804 #[serde(default)]
11806 pub earned_value: EarnedValueSchemaConfig,
11807 #[serde(default = "default_project_anomaly_rate")]
11809 pub anomaly_rate: f64,
11810}
11811
11812fn default_project_count() -> u32 {
11813 10
11814}
11815
11816fn default_project_anomaly_rate() -> f64 {
11817 0.03
11818}
11819
11820impl Default for ProjectAccountingConfig {
11821 fn default() -> Self {
11822 Self {
11823 enabled: false,
11824 project_count: default_project_count(),
11825 project_types: ProjectTypeDistribution::default(),
11826 wbs: WbsSchemaConfig::default(),
11827 cost_allocation: CostAllocationConfig::default(),
11828 revenue_recognition: ProjectRevenueRecognitionConfig::default(),
11829 milestones: MilestoneSchemaConfig::default(),
11830 change_orders: ChangeOrderSchemaConfig::default(),
11831 retainage: RetainageSchemaConfig::default(),
11832 earned_value: EarnedValueSchemaConfig::default(),
11833 anomaly_rate: default_project_anomaly_rate(),
11834 }
11835 }
11836}
11837
11838#[derive(Debug, Clone, Serialize, Deserialize)]
11840pub struct ProjectTypeDistribution {
11841 #[serde(default = "default_capital_weight")]
11843 pub capital: f64,
11844 #[serde(default = "default_internal_weight")]
11846 pub internal: f64,
11847 #[serde(default = "default_customer_weight")]
11849 pub customer: f64,
11850 #[serde(default = "default_rnd_weight")]
11852 pub r_and_d: f64,
11853 #[serde(default = "default_maintenance_weight")]
11855 pub maintenance: f64,
11856 #[serde(default = "default_technology_weight")]
11858 pub technology: f64,
11859}
11860
11861fn default_capital_weight() -> f64 {
11862 0.25
11863}
11864fn default_internal_weight() -> f64 {
11865 0.20
11866}
11867fn default_customer_weight() -> f64 {
11868 0.30
11869}
11870fn default_rnd_weight() -> f64 {
11871 0.10
11872}
11873fn default_maintenance_weight() -> f64 {
11874 0.10
11875}
11876fn default_technology_weight() -> f64 {
11877 0.05
11878}
11879
11880impl Default for ProjectTypeDistribution {
11881 fn default() -> Self {
11882 Self {
11883 capital: default_capital_weight(),
11884 internal: default_internal_weight(),
11885 customer: default_customer_weight(),
11886 r_and_d: default_rnd_weight(),
11887 maintenance: default_maintenance_weight(),
11888 technology: default_technology_weight(),
11889 }
11890 }
11891}
11892
11893#[derive(Debug, Clone, Serialize, Deserialize)]
11895pub struct WbsSchemaConfig {
11896 #[serde(default = "default_wbs_max_depth")]
11898 pub max_depth: u32,
11899 #[serde(default = "default_wbs_min_elements")]
11901 pub min_elements_per_level: u32,
11902 #[serde(default = "default_wbs_max_elements")]
11904 pub max_elements_per_level: u32,
11905}
11906
11907fn default_wbs_max_depth() -> u32 {
11908 3
11909}
11910fn default_wbs_min_elements() -> u32 {
11911 2
11912}
11913fn default_wbs_max_elements() -> u32 {
11914 6
11915}
11916
11917impl Default for WbsSchemaConfig {
11918 fn default() -> Self {
11919 Self {
11920 max_depth: default_wbs_max_depth(),
11921 min_elements_per_level: default_wbs_min_elements(),
11922 max_elements_per_level: default_wbs_max_elements(),
11923 }
11924 }
11925}
11926
11927#[derive(Debug, Clone, Serialize, Deserialize)]
11929pub struct CostAllocationConfig {
11930 #[serde(default = "default_time_entry_rate")]
11932 pub time_entry_project_rate: f64,
11933 #[serde(default = "default_expense_rate")]
11935 pub expense_project_rate: f64,
11936 #[serde(default = "default_po_rate")]
11938 pub purchase_order_project_rate: f64,
11939 #[serde(default = "default_vi_rate")]
11941 pub vendor_invoice_project_rate: f64,
11942}
11943
11944fn default_time_entry_rate() -> f64 {
11945 0.60
11946}
11947fn default_expense_rate() -> f64 {
11948 0.30
11949}
11950fn default_po_rate() -> f64 {
11951 0.40
11952}
11953fn default_vi_rate() -> f64 {
11954 0.35
11955}
11956
11957impl Default for CostAllocationConfig {
11958 fn default() -> Self {
11959 Self {
11960 time_entry_project_rate: default_time_entry_rate(),
11961 expense_project_rate: default_expense_rate(),
11962 purchase_order_project_rate: default_po_rate(),
11963 vendor_invoice_project_rate: default_vi_rate(),
11964 }
11965 }
11966}
11967
11968#[derive(Debug, Clone, Serialize, Deserialize)]
11970pub struct ProjectRevenueRecognitionConfig {
11971 #[serde(default = "default_true")]
11973 pub enabled: bool,
11974 #[serde(default = "default_revenue_method")]
11976 pub method: String,
11977 #[serde(default = "default_completion_measure")]
11979 pub completion_measure: String,
11980 #[serde(default = "default_avg_contract_value")]
11982 pub avg_contract_value: f64,
11983}
11984
11985fn default_revenue_method() -> String {
11986 "percentage_of_completion".to_string()
11987}
11988fn default_completion_measure() -> String {
11989 "cost_to_cost".to_string()
11990}
11991fn default_avg_contract_value() -> f64 {
11992 500_000.0
11993}
11994
11995impl Default for ProjectRevenueRecognitionConfig {
11996 fn default() -> Self {
11997 Self {
11998 enabled: true,
11999 method: default_revenue_method(),
12000 completion_measure: default_completion_measure(),
12001 avg_contract_value: default_avg_contract_value(),
12002 }
12003 }
12004}
12005
12006#[derive(Debug, Clone, Serialize, Deserialize)]
12008pub struct MilestoneSchemaConfig {
12009 #[serde(default = "default_true")]
12011 pub enabled: bool,
12012 #[serde(default = "default_milestones_per_project")]
12014 pub avg_per_project: u32,
12015 #[serde(default = "default_payment_milestone_rate")]
12017 pub payment_milestone_rate: f64,
12018}
12019
12020fn default_milestones_per_project() -> u32 {
12021 4
12022}
12023fn default_payment_milestone_rate() -> f64 {
12024 0.50
12025}
12026
12027impl Default for MilestoneSchemaConfig {
12028 fn default() -> Self {
12029 Self {
12030 enabled: true,
12031 avg_per_project: default_milestones_per_project(),
12032 payment_milestone_rate: default_payment_milestone_rate(),
12033 }
12034 }
12035}
12036
12037#[derive(Debug, Clone, Serialize, Deserialize)]
12039pub struct ChangeOrderSchemaConfig {
12040 #[serde(default = "default_true")]
12042 pub enabled: bool,
12043 #[serde(default = "default_change_order_probability")]
12045 pub probability: f64,
12046 #[serde(default = "default_max_change_orders")]
12048 pub max_per_project: u32,
12049 #[serde(default = "default_change_order_approval_rate")]
12051 pub approval_rate: f64,
12052}
12053
12054fn default_change_order_probability() -> f64 {
12055 0.40
12056}
12057fn default_max_change_orders() -> u32 {
12058 3
12059}
12060fn default_change_order_approval_rate() -> f64 {
12061 0.75
12062}
12063
12064impl Default for ChangeOrderSchemaConfig {
12065 fn default() -> Self {
12066 Self {
12067 enabled: true,
12068 probability: default_change_order_probability(),
12069 max_per_project: default_max_change_orders(),
12070 approval_rate: default_change_order_approval_rate(),
12071 }
12072 }
12073}
12074
12075#[derive(Debug, Clone, Serialize, Deserialize)]
12077pub struct RetainageSchemaConfig {
12078 #[serde(default)]
12080 pub enabled: bool,
12081 #[serde(default = "default_retainage_pct")]
12083 pub default_percentage: f64,
12084}
12085
12086fn default_retainage_pct() -> f64 {
12087 0.10
12088}
12089
12090impl Default for RetainageSchemaConfig {
12091 fn default() -> Self {
12092 Self {
12093 enabled: false,
12094 default_percentage: default_retainage_pct(),
12095 }
12096 }
12097}
12098
12099#[derive(Debug, Clone, Serialize, Deserialize)]
12101pub struct EarnedValueSchemaConfig {
12102 #[serde(default = "default_true")]
12104 pub enabled: bool,
12105 #[serde(default = "default_evm_frequency")]
12107 pub frequency: String,
12108}
12109
12110fn default_evm_frequency() -> String {
12111 "monthly".to_string()
12112}
12113
12114impl Default for EarnedValueSchemaConfig {
12115 fn default() -> Self {
12116 Self {
12117 enabled: true,
12118 frequency: default_evm_frequency(),
12119 }
12120 }
12121}
12122
12123#[derive(Debug, Clone, Serialize, Deserialize)]
12129pub struct EsgConfig {
12130 #[serde(default)]
12132 pub enabled: bool,
12133 #[serde(default)]
12135 pub environmental: EnvironmentalConfig,
12136 #[serde(default)]
12138 pub social: SocialConfig,
12139 #[serde(default)]
12141 pub governance: GovernanceSchemaConfig,
12142 #[serde(default)]
12144 pub supply_chain_esg: SupplyChainEsgConfig,
12145 #[serde(default)]
12147 pub reporting: EsgReportingConfig,
12148 #[serde(default)]
12150 pub climate_scenarios: ClimateScenarioConfig,
12151 #[serde(default = "default_esg_anomaly_rate")]
12153 pub anomaly_rate: f64,
12154}
12155
12156fn default_esg_anomaly_rate() -> f64 {
12157 0.02
12158}
12159
12160impl Default for EsgConfig {
12161 fn default() -> Self {
12162 Self {
12163 enabled: false,
12164 environmental: EnvironmentalConfig::default(),
12165 social: SocialConfig::default(),
12166 governance: GovernanceSchemaConfig::default(),
12167 supply_chain_esg: SupplyChainEsgConfig::default(),
12168 reporting: EsgReportingConfig::default(),
12169 climate_scenarios: ClimateScenarioConfig::default(),
12170 anomaly_rate: default_esg_anomaly_rate(),
12171 }
12172 }
12173}
12174
12175#[derive(Debug, Clone, Serialize, Deserialize, Default)]
12180pub struct CountryPacksSchemaConfig {
12181 #[serde(default)]
12183 pub external_dir: Option<PathBuf>,
12184 #[serde(default)]
12188 pub overrides: std::collections::HashMap<String, serde_json::Value>,
12189}
12190
12191#[derive(Debug, Clone, Serialize, Deserialize)]
12193pub struct EnvironmentalConfig {
12194 #[serde(default = "default_true")]
12196 pub enabled: bool,
12197 #[serde(default)]
12199 pub scope1: EmissionScopeConfig,
12200 #[serde(default)]
12202 pub scope2: EmissionScopeConfig,
12203 #[serde(default)]
12205 pub scope3: Scope3Config,
12206 #[serde(default)]
12208 pub energy: EnergySchemaConfig,
12209 #[serde(default)]
12211 pub water: WaterSchemaConfig,
12212 #[serde(default)]
12214 pub waste: WasteSchemaConfig,
12215}
12216
12217impl Default for EnvironmentalConfig {
12218 fn default() -> Self {
12219 Self {
12220 enabled: true,
12221 scope1: EmissionScopeConfig::default(),
12222 scope2: EmissionScopeConfig::default(),
12223 scope3: Scope3Config::default(),
12224 energy: EnergySchemaConfig::default(),
12225 water: WaterSchemaConfig::default(),
12226 waste: WasteSchemaConfig::default(),
12227 }
12228 }
12229}
12230
12231#[derive(Debug, Clone, Serialize, Deserialize)]
12233pub struct EmissionScopeConfig {
12234 #[serde(default = "default_true")]
12236 pub enabled: bool,
12237 #[serde(default = "default_emission_region")]
12239 pub factor_region: String,
12240}
12241
12242fn default_emission_region() -> String {
12243 "US".to_string()
12244}
12245
12246impl Default for EmissionScopeConfig {
12247 fn default() -> Self {
12248 Self {
12249 enabled: true,
12250 factor_region: default_emission_region(),
12251 }
12252 }
12253}
12254
12255#[derive(Debug, Clone, Serialize, Deserialize)]
12257pub struct Scope3Config {
12258 #[serde(default = "default_true")]
12260 pub enabled: bool,
12261 #[serde(default = "default_scope3_categories")]
12263 pub categories: Vec<String>,
12264 #[serde(default = "default_spend_intensity")]
12266 pub default_spend_intensity_kg_per_usd: f64,
12267}
12268
12269fn default_scope3_categories() -> Vec<String> {
12270 vec![
12271 "purchased_goods".to_string(),
12272 "business_travel".to_string(),
12273 "employee_commuting".to_string(),
12274 ]
12275}
12276
12277fn default_spend_intensity() -> f64 {
12278 0.5
12279}
12280
12281impl Default for Scope3Config {
12282 fn default() -> Self {
12283 Self {
12284 enabled: true,
12285 categories: default_scope3_categories(),
12286 default_spend_intensity_kg_per_usd: default_spend_intensity(),
12287 }
12288 }
12289}
12290
12291#[derive(Debug, Clone, Serialize, Deserialize)]
12293pub struct EnergySchemaConfig {
12294 #[serde(default = "default_true")]
12296 pub enabled: bool,
12297 #[serde(default = "default_facility_count")]
12299 pub facility_count: u32,
12300 #[serde(default = "default_renewable_target")]
12302 pub renewable_target: f64,
12303}
12304
12305fn default_facility_count() -> u32 {
12306 5
12307}
12308
12309fn default_renewable_target() -> f64 {
12310 0.30
12311}
12312
12313impl Default for EnergySchemaConfig {
12314 fn default() -> Self {
12315 Self {
12316 enabled: true,
12317 facility_count: default_facility_count(),
12318 renewable_target: default_renewable_target(),
12319 }
12320 }
12321}
12322
12323#[derive(Debug, Clone, Serialize, Deserialize)]
12325pub struct WaterSchemaConfig {
12326 #[serde(default = "default_true")]
12328 pub enabled: bool,
12329 #[serde(default = "default_water_facility_count")]
12331 pub facility_count: u32,
12332}
12333
12334fn default_water_facility_count() -> u32 {
12335 3
12336}
12337
12338impl Default for WaterSchemaConfig {
12339 fn default() -> Self {
12340 Self {
12341 enabled: true,
12342 facility_count: default_water_facility_count(),
12343 }
12344 }
12345}
12346
12347#[derive(Debug, Clone, Serialize, Deserialize)]
12349pub struct WasteSchemaConfig {
12350 #[serde(default = "default_true")]
12352 pub enabled: bool,
12353 #[serde(default = "default_diversion_target")]
12355 pub diversion_target: f64,
12356}
12357
12358fn default_diversion_target() -> f64 {
12359 0.50
12360}
12361
12362impl Default for WasteSchemaConfig {
12363 fn default() -> Self {
12364 Self {
12365 enabled: true,
12366 diversion_target: default_diversion_target(),
12367 }
12368 }
12369}
12370
12371#[derive(Debug, Clone, Serialize, Deserialize)]
12373pub struct SocialConfig {
12374 #[serde(default = "default_true")]
12376 pub enabled: bool,
12377 #[serde(default)]
12379 pub diversity: DiversitySchemaConfig,
12380 #[serde(default)]
12382 pub pay_equity: PayEquitySchemaConfig,
12383 #[serde(default)]
12385 pub safety: SafetySchemaConfig,
12386}
12387
12388impl Default for SocialConfig {
12389 fn default() -> Self {
12390 Self {
12391 enabled: true,
12392 diversity: DiversitySchemaConfig::default(),
12393 pay_equity: PayEquitySchemaConfig::default(),
12394 safety: SafetySchemaConfig::default(),
12395 }
12396 }
12397}
12398
12399#[derive(Debug, Clone, Serialize, Deserialize)]
12401pub struct DiversitySchemaConfig {
12402 #[serde(default = "default_true")]
12404 pub enabled: bool,
12405 #[serde(default = "default_diversity_dimensions")]
12407 pub dimensions: Vec<String>,
12408}
12409
12410fn default_diversity_dimensions() -> Vec<String> {
12411 vec![
12412 "gender".to_string(),
12413 "ethnicity".to_string(),
12414 "age_group".to_string(),
12415 ]
12416}
12417
12418impl Default for DiversitySchemaConfig {
12419 fn default() -> Self {
12420 Self {
12421 enabled: true,
12422 dimensions: default_diversity_dimensions(),
12423 }
12424 }
12425}
12426
12427#[derive(Debug, Clone, Serialize, Deserialize)]
12429pub struct PayEquitySchemaConfig {
12430 #[serde(default = "default_true")]
12432 pub enabled: bool,
12433 #[serde(default = "default_pay_gap_threshold")]
12435 pub gap_threshold: f64,
12436}
12437
12438fn default_pay_gap_threshold() -> f64 {
12439 0.05
12440}
12441
12442impl Default for PayEquitySchemaConfig {
12443 fn default() -> Self {
12444 Self {
12445 enabled: true,
12446 gap_threshold: default_pay_gap_threshold(),
12447 }
12448 }
12449}
12450
12451#[derive(Debug, Clone, Serialize, Deserialize)]
12453pub struct SafetySchemaConfig {
12454 #[serde(default = "default_true")]
12456 pub enabled: bool,
12457 #[serde(default = "default_trir_target")]
12459 pub target_trir: f64,
12460 #[serde(default = "default_incident_count")]
12462 pub incident_count: u32,
12463}
12464
12465fn default_trir_target() -> f64 {
12466 2.5
12467}
12468
12469fn default_incident_count() -> u32 {
12470 20
12471}
12472
12473impl Default for SafetySchemaConfig {
12474 fn default() -> Self {
12475 Self {
12476 enabled: true,
12477 target_trir: default_trir_target(),
12478 incident_count: default_incident_count(),
12479 }
12480 }
12481}
12482
12483#[derive(Debug, Clone, Serialize, Deserialize)]
12485pub struct GovernanceSchemaConfig {
12486 #[serde(default = "default_true")]
12488 pub enabled: bool,
12489 #[serde(default = "default_board_size")]
12491 pub board_size: u32,
12492 #[serde(default = "default_independence_target")]
12494 pub independence_target: f64,
12495}
12496
12497fn default_board_size() -> u32 {
12498 11
12499}
12500
12501fn default_independence_target() -> f64 {
12502 0.67
12503}
12504
12505impl Default for GovernanceSchemaConfig {
12506 fn default() -> Self {
12507 Self {
12508 enabled: true,
12509 board_size: default_board_size(),
12510 independence_target: default_independence_target(),
12511 }
12512 }
12513}
12514
12515#[derive(Debug, Clone, Serialize, Deserialize)]
12517pub struct SupplyChainEsgConfig {
12518 #[serde(default = "default_true")]
12520 pub enabled: bool,
12521 #[serde(default = "default_assessment_coverage")]
12523 pub assessment_coverage: f64,
12524 #[serde(default = "default_high_risk_countries")]
12526 pub high_risk_countries: Vec<String>,
12527}
12528
12529fn default_assessment_coverage() -> f64 {
12530 0.80
12531}
12532
12533fn default_high_risk_countries() -> Vec<String> {
12534 vec!["CN".to_string(), "BD".to_string(), "MM".to_string()]
12535}
12536
12537impl Default for SupplyChainEsgConfig {
12538 fn default() -> Self {
12539 Self {
12540 enabled: true,
12541 assessment_coverage: default_assessment_coverage(),
12542 high_risk_countries: default_high_risk_countries(),
12543 }
12544 }
12545}
12546
12547#[derive(Debug, Clone, Serialize, Deserialize)]
12549pub struct EsgReportingConfig {
12550 #[serde(default = "default_true")]
12552 pub enabled: bool,
12553 #[serde(default = "default_esg_frameworks")]
12555 pub frameworks: Vec<String>,
12556 #[serde(default = "default_true")]
12558 pub materiality_assessment: bool,
12559 #[serde(default = "default_materiality_threshold")]
12561 pub impact_threshold: f64,
12562 #[serde(default = "default_materiality_threshold")]
12564 pub financial_threshold: f64,
12565}
12566
12567fn default_esg_frameworks() -> Vec<String> {
12568 vec!["GRI".to_string(), "ESRS".to_string()]
12569}
12570
12571fn default_materiality_threshold() -> f64 {
12572 0.6
12573}
12574
12575impl Default for EsgReportingConfig {
12576 fn default() -> Self {
12577 Self {
12578 enabled: true,
12579 frameworks: default_esg_frameworks(),
12580 materiality_assessment: true,
12581 impact_threshold: default_materiality_threshold(),
12582 financial_threshold: default_materiality_threshold(),
12583 }
12584 }
12585}
12586
12587#[derive(Debug, Clone, Serialize, Deserialize)]
12589pub struct ClimateScenarioConfig {
12590 #[serde(default)]
12592 pub enabled: bool,
12593 #[serde(default = "default_climate_scenarios")]
12595 pub scenarios: Vec<String>,
12596 #[serde(default = "default_time_horizons")]
12598 pub time_horizons: Vec<u32>,
12599}
12600
12601fn default_climate_scenarios() -> Vec<String> {
12602 vec![
12603 "net_zero_2050".to_string(),
12604 "stated_policies".to_string(),
12605 "current_trajectory".to_string(),
12606 ]
12607}
12608
12609fn default_time_horizons() -> Vec<u32> {
12610 vec![5, 10, 30]
12611}
12612
12613impl Default for ClimateScenarioConfig {
12614 fn default() -> Self {
12615 Self {
12616 enabled: false,
12617 scenarios: default_climate_scenarios(),
12618 time_horizons: default_time_horizons(),
12619 }
12620 }
12621}
12622
12623#[derive(Debug, Clone, Serialize, Deserialize, Default)]
12627pub struct ScenariosConfig {
12628 #[serde(default)]
12630 pub enabled: bool,
12631 #[serde(default)]
12633 pub scenarios: Vec<ScenarioSchemaConfig>,
12634 #[serde(default)]
12636 pub causal_model: CausalModelSchemaConfig,
12637 #[serde(default)]
12639 pub defaults: ScenarioDefaultsConfig,
12640 #[serde(default)]
12643 pub generate_counterfactuals: bool,
12644}
12645
12646#[derive(Debug, Clone, Serialize, Deserialize)]
12648pub struct ScenarioSchemaConfig {
12649 pub name: String,
12651 #[serde(default)]
12653 pub description: String,
12654 #[serde(default)]
12656 pub tags: Vec<String>,
12657 pub base: Option<String>,
12659 pub probability_weight: Option<f64>,
12661 #[serde(default)]
12663 pub interventions: Vec<InterventionSchemaConfig>,
12664 #[serde(default)]
12666 pub constraints: ScenarioConstraintsSchemaConfig,
12667 #[serde(default)]
12669 pub output: ScenarioOutputSchemaConfig,
12670 #[serde(default)]
12672 pub metadata: std::collections::HashMap<String, String>,
12673}
12674
12675#[derive(Debug, Clone, Serialize, Deserialize)]
12677pub struct InterventionSchemaConfig {
12678 #[serde(flatten)]
12680 pub intervention_type: serde_json::Value,
12681 #[serde(default)]
12683 pub timing: InterventionTimingSchemaConfig,
12684 pub label: Option<String>,
12686 #[serde(default)]
12688 pub priority: u32,
12689}
12690
12691#[derive(Debug, Clone, Serialize, Deserialize)]
12693pub struct InterventionTimingSchemaConfig {
12694 #[serde(default = "default_start_month")]
12696 pub start_month: u32,
12697 pub duration_months: Option<u32>,
12699 #[serde(default = "default_onset")]
12701 pub onset: String,
12702 pub ramp_months: Option<u32>,
12704}
12705
12706fn default_start_month() -> u32 {
12707 1
12708}
12709
12710fn default_onset() -> String {
12711 "sudden".to_string()
12712}
12713
12714impl Default for InterventionTimingSchemaConfig {
12715 fn default() -> Self {
12716 Self {
12717 start_month: 1,
12718 duration_months: None,
12719 onset: "sudden".to_string(),
12720 ramp_months: None,
12721 }
12722 }
12723}
12724
12725#[derive(Debug, Clone, Serialize, Deserialize)]
12727pub struct ScenarioConstraintsSchemaConfig {
12728 #[serde(default = "default_true")]
12729 pub preserve_accounting_identity: bool,
12730 #[serde(default = "default_true")]
12731 pub preserve_document_chains: bool,
12732 #[serde(default = "default_true")]
12733 pub preserve_period_close: bool,
12734 #[serde(default = "default_true")]
12735 pub preserve_balance_coherence: bool,
12736 #[serde(default)]
12737 pub custom: Vec<CustomConstraintSchemaConfig>,
12738}
12739
12740impl Default for ScenarioConstraintsSchemaConfig {
12741 fn default() -> Self {
12742 Self {
12743 preserve_accounting_identity: true,
12744 preserve_document_chains: true,
12745 preserve_period_close: true,
12746 preserve_balance_coherence: true,
12747 custom: Vec::new(),
12748 }
12749 }
12750}
12751
12752#[derive(Debug, Clone, Serialize, Deserialize)]
12754pub struct CustomConstraintSchemaConfig {
12755 pub config_path: String,
12756 pub min: Option<f64>,
12757 pub max: Option<f64>,
12758 #[serde(default)]
12759 pub description: String,
12760}
12761
12762#[derive(Debug, Clone, Serialize, Deserialize)]
12764pub struct ScenarioOutputSchemaConfig {
12765 #[serde(default = "default_true")]
12766 pub paired: bool,
12767 #[serde(default = "default_diff_formats_schema")]
12768 pub diff_formats: Vec<String>,
12769 #[serde(default)]
12770 pub diff_scope: Vec<String>,
12771}
12772
12773fn default_diff_formats_schema() -> Vec<String> {
12774 vec!["summary".to_string(), "aggregate".to_string()]
12775}
12776
12777impl Default for ScenarioOutputSchemaConfig {
12778 fn default() -> Self {
12779 Self {
12780 paired: true,
12781 diff_formats: default_diff_formats_schema(),
12782 diff_scope: Vec::new(),
12783 }
12784 }
12785}
12786
12787#[derive(Debug, Clone, Serialize, Deserialize)]
12789pub struct CausalModelSchemaConfig {
12790 #[serde(default = "default_causal_preset")]
12792 pub preset: String,
12793 #[serde(default)]
12795 pub nodes: Vec<serde_json::Value>,
12796 #[serde(default)]
12798 pub edges: Vec<serde_json::Value>,
12799}
12800
12801fn default_causal_preset() -> String {
12802 "default".to_string()
12803}
12804
12805impl Default for CausalModelSchemaConfig {
12806 fn default() -> Self {
12807 Self {
12808 preset: "default".to_string(),
12809 nodes: Vec::new(),
12810 edges: Vec::new(),
12811 }
12812 }
12813}
12814
12815#[derive(Debug, Clone, Serialize, Deserialize, Default)]
12817pub struct ScenarioDefaultsConfig {
12818 #[serde(default)]
12819 pub constraints: ScenarioConstraintsSchemaConfig,
12820 #[serde(default)]
12821 pub output: ScenarioOutputSchemaConfig,
12822}
12823
12824#[derive(Debug, Clone, Default, Serialize, Deserialize)]
12857pub struct ComplianceRegulationsConfig {
12858 #[serde(default)]
12860 pub enabled: bool,
12861 #[serde(default)]
12864 pub jurisdictions: Vec<String>,
12865 #[serde(default)]
12868 pub reference_date: Option<String>,
12869 #[serde(default)]
12871 pub standards_selection: StandardsSelectionConfig,
12872 #[serde(default)]
12874 pub audit_procedures: AuditProcedureGenConfig,
12875 #[serde(default)]
12877 pub findings: ComplianceFindingGenConfig,
12878 #[serde(default)]
12880 pub filings: ComplianceFilingGenConfig,
12881 #[serde(default)]
12883 pub graph: ComplianceGraphConfig,
12884 #[serde(default)]
12886 pub output: ComplianceOutputConfig,
12887}
12888
12889#[derive(Debug, Clone, Default, Serialize, Deserialize)]
12891pub struct StandardsSelectionConfig {
12892 #[serde(default)]
12895 pub categories: Vec<String>,
12896 #[serde(default)]
12899 pub include: Vec<String>,
12900 #[serde(default)]
12902 pub exclude: Vec<String>,
12903 #[serde(default)]
12905 pub include_superseded: bool,
12906}
12907
12908#[derive(Debug, Clone, Serialize, Deserialize)]
12910pub struct AuditProcedureGenConfig {
12911 #[serde(default)]
12913 pub enabled: bool,
12914 #[serde(default = "default_procedures_per_standard")]
12916 pub procedures_per_standard: usize,
12917 #[serde(default = "default_sampling_method")]
12919 pub sampling_method: String,
12920 #[serde(default = "default_confidence_level")]
12922 pub confidence_level: f64,
12923 #[serde(default = "default_tolerable_misstatement")]
12925 pub tolerable_misstatement: f64,
12926}
12927
12928fn default_procedures_per_standard() -> usize {
12929 3
12930}
12931
12932fn default_sampling_method() -> String {
12933 "statistical".to_string()
12934}
12935
12936fn default_confidence_level() -> f64 {
12937 0.95
12938}
12939
12940fn default_tolerable_misstatement() -> f64 {
12941 0.05
12942}
12943
12944impl Default for AuditProcedureGenConfig {
12945 fn default() -> Self {
12946 Self {
12947 enabled: false,
12948 procedures_per_standard: default_procedures_per_standard(),
12949 sampling_method: default_sampling_method(),
12950 confidence_level: default_confidence_level(),
12951 tolerable_misstatement: default_tolerable_misstatement(),
12952 }
12953 }
12954}
12955
12956#[derive(Debug, Clone, Serialize, Deserialize)]
12958pub struct ComplianceFindingGenConfig {
12959 #[serde(default)]
12961 pub enabled: bool,
12962 #[serde(default = "default_finding_rate")]
12964 pub finding_rate: f64,
12965 #[serde(default = "default_cr_material_weakness_rate")]
12967 pub material_weakness_rate: f64,
12968 #[serde(default = "default_cr_significant_deficiency_rate")]
12970 pub significant_deficiency_rate: f64,
12971 #[serde(default = "default_true")]
12973 pub generate_remediation: bool,
12974}
12975
12976fn default_finding_rate() -> f64 {
12977 0.05
12978}
12979
12980fn default_cr_material_weakness_rate() -> f64 {
12981 0.02
12982}
12983
12984fn default_cr_significant_deficiency_rate() -> f64 {
12985 0.08
12986}
12987
12988impl Default for ComplianceFindingGenConfig {
12989 fn default() -> Self {
12990 Self {
12991 enabled: false,
12992 finding_rate: default_finding_rate(),
12993 material_weakness_rate: default_cr_material_weakness_rate(),
12994 significant_deficiency_rate: default_cr_significant_deficiency_rate(),
12995 generate_remediation: true,
12996 }
12997 }
12998}
12999
13000#[derive(Debug, Clone, Serialize, Deserialize)]
13002pub struct ComplianceFilingGenConfig {
13003 #[serde(default)]
13005 pub enabled: bool,
13006 #[serde(default)]
13009 pub filing_types: Vec<String>,
13010 #[serde(default = "default_true")]
13012 pub generate_status_progression: bool,
13013}
13014
13015impl Default for ComplianceFilingGenConfig {
13016 fn default() -> Self {
13017 Self {
13018 enabled: false,
13019 filing_types: Vec::new(),
13020 generate_status_progression: true,
13021 }
13022 }
13023}
13024
13025#[derive(Debug, Clone, Serialize, Deserialize)]
13027pub struct ComplianceGraphConfig {
13028 #[serde(default)]
13030 pub enabled: bool,
13031 #[serde(default = "default_true")]
13033 pub include_compliance_nodes: bool,
13034 #[serde(default = "default_true")]
13036 pub include_compliance_edges: bool,
13037 #[serde(default = "default_true")]
13039 pub include_cross_references: bool,
13040 #[serde(default)]
13042 pub include_supersession_edges: bool,
13043 #[serde(default = "default_true")]
13045 pub include_account_links: bool,
13046 #[serde(default = "default_true")]
13048 pub include_control_links: bool,
13049 #[serde(default = "default_true")]
13051 pub include_company_links: bool,
13052}
13053
13054impl Default for ComplianceGraphConfig {
13055 fn default() -> Self {
13056 Self {
13057 enabled: false,
13058 include_compliance_nodes: true,
13059 include_compliance_edges: true,
13060 include_cross_references: true,
13061 include_supersession_edges: false,
13062 include_account_links: true,
13063 include_control_links: true,
13064 include_company_links: true,
13065 }
13066 }
13067}
13068
13069#[derive(Debug, Clone, Serialize, Deserialize)]
13071pub struct ComplianceOutputConfig {
13072 #[serde(default = "default_true")]
13074 pub export_registry: bool,
13075 #[serde(default = "default_true")]
13077 pub export_jurisdictions: bool,
13078 #[serde(default = "default_true")]
13080 pub export_cross_references: bool,
13081 #[serde(default)]
13083 pub export_version_history: bool,
13084}
13085
13086impl Default for ComplianceOutputConfig {
13087 fn default() -> Self {
13088 Self {
13089 export_registry: true,
13090 export_jurisdictions: true,
13091 export_cross_references: true,
13092 export_version_history: false,
13093 }
13094 }
13095}
13096
13097#[cfg(test)]
13098#[allow(clippy::unwrap_used)]
13099mod tests {
13100 use super::*;
13101 use crate::presets::demo_preset;
13102
13103 #[test]
13108 fn test_config_yaml_roundtrip() {
13109 let config = demo_preset();
13110 let yaml = serde_yaml::to_string(&config).expect("Failed to serialize to YAML");
13111 let deserialized: GeneratorConfig =
13112 serde_yaml::from_str(&yaml).expect("Failed to deserialize from YAML");
13113
13114 assert_eq!(
13115 config.global.period_months,
13116 deserialized.global.period_months
13117 );
13118 assert_eq!(config.global.industry, deserialized.global.industry);
13119 assert_eq!(config.companies.len(), deserialized.companies.len());
13120 assert_eq!(config.companies[0].code, deserialized.companies[0].code);
13121 }
13122
13123 #[test]
13124 fn test_config_json_roundtrip() {
13125 let mut config = demo_preset();
13127 config.master_data.employees.approval_limits.executive = 1e12;
13129
13130 let json = serde_json::to_string(&config).expect("Failed to serialize to JSON");
13131 let deserialized: GeneratorConfig =
13132 serde_json::from_str(&json).expect("Failed to deserialize from JSON");
13133
13134 assert_eq!(
13135 config.global.period_months,
13136 deserialized.global.period_months
13137 );
13138 assert_eq!(config.global.industry, deserialized.global.industry);
13139 assert_eq!(config.companies.len(), deserialized.companies.len());
13140 }
13141
13142 #[test]
13143 fn test_transaction_volume_serialization() {
13144 let volumes = vec![
13146 (TransactionVolume::TenK, "ten_k"),
13147 (TransactionVolume::HundredK, "hundred_k"),
13148 (TransactionVolume::OneM, "one_m"),
13149 (TransactionVolume::TenM, "ten_m"),
13150 (TransactionVolume::HundredM, "hundred_m"),
13151 ];
13152
13153 for (volume, expected_key) in volumes {
13154 let json = serde_json::to_string(&volume).expect("Failed to serialize");
13155 assert!(
13156 json.contains(expected_key),
13157 "Expected {} in JSON: {}",
13158 expected_key,
13159 json
13160 );
13161 }
13162 }
13163
13164 #[test]
13165 fn test_transaction_volume_custom_serialization() {
13166 let volume = TransactionVolume::Custom(12345);
13167 let json = serde_json::to_string(&volume).expect("Failed to serialize");
13168 let deserialized: TransactionVolume =
13169 serde_json::from_str(&json).expect("Failed to deserialize");
13170 assert_eq!(deserialized.count(), 12345);
13171 }
13172
13173 #[test]
13174 fn test_output_mode_serialization() {
13175 let modes = vec![
13176 OutputMode::Streaming,
13177 OutputMode::FlatFile,
13178 OutputMode::Both,
13179 ];
13180
13181 for mode in modes {
13182 let json = serde_json::to_string(&mode).expect("Failed to serialize");
13183 let deserialized: OutputMode =
13184 serde_json::from_str(&json).expect("Failed to deserialize");
13185 assert!(format!("{:?}", mode) == format!("{:?}", deserialized));
13186 }
13187 }
13188
13189 #[test]
13190 fn test_file_format_serialization() {
13191 let formats = vec![
13192 FileFormat::Csv,
13193 FileFormat::Parquet,
13194 FileFormat::Json,
13195 FileFormat::JsonLines,
13196 ];
13197
13198 for format in formats {
13199 let json = serde_json::to_string(&format).expect("Failed to serialize");
13200 let deserialized: FileFormat =
13201 serde_json::from_str(&json).expect("Failed to deserialize");
13202 assert!(format!("{:?}", format) == format!("{:?}", deserialized));
13203 }
13204 }
13205
13206 #[test]
13207 fn test_compression_algorithm_serialization() {
13208 let algos = vec![
13209 CompressionAlgorithm::Gzip,
13210 CompressionAlgorithm::Zstd,
13211 CompressionAlgorithm::Lz4,
13212 CompressionAlgorithm::Snappy,
13213 ];
13214
13215 for algo in algos {
13216 let json = serde_json::to_string(&algo).expect("Failed to serialize");
13217 let deserialized: CompressionAlgorithm =
13218 serde_json::from_str(&json).expect("Failed to deserialize");
13219 assert!(format!("{:?}", algo) == format!("{:?}", deserialized));
13220 }
13221 }
13222
13223 #[test]
13224 fn test_transfer_pricing_method_serialization() {
13225 let methods = vec![
13226 TransferPricingMethod::CostPlus,
13227 TransferPricingMethod::ComparableUncontrolled,
13228 TransferPricingMethod::ResalePrice,
13229 TransferPricingMethod::TransactionalNetMargin,
13230 TransferPricingMethod::ProfitSplit,
13231 ];
13232
13233 for method in methods {
13234 let json = serde_json::to_string(&method).expect("Failed to serialize");
13235 let deserialized: TransferPricingMethod =
13236 serde_json::from_str(&json).expect("Failed to deserialize");
13237 assert!(format!("{:?}", method) == format!("{:?}", deserialized));
13238 }
13239 }
13240
13241 #[test]
13242 fn test_benford_exemption_serialization() {
13243 let exemptions = vec![
13244 BenfordExemption::Recurring,
13245 BenfordExemption::Payroll,
13246 BenfordExemption::FixedFees,
13247 BenfordExemption::RoundAmounts,
13248 ];
13249
13250 for exemption in exemptions {
13251 let json = serde_json::to_string(&exemption).expect("Failed to serialize");
13252 let deserialized: BenfordExemption =
13253 serde_json::from_str(&json).expect("Failed to deserialize");
13254 assert!(format!("{:?}", exemption) == format!("{:?}", deserialized));
13255 }
13256 }
13257
13258 #[test]
13263 fn test_global_config_defaults() {
13264 let yaml = r#"
13265 industry: manufacturing
13266 start_date: "2024-01-01"
13267 period_months: 6
13268 "#;
13269 let config: GlobalConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13270 assert_eq!(config.group_currency, "USD");
13271 assert!(config.parallel);
13272 assert_eq!(config.worker_threads, 0);
13273 assert_eq!(config.memory_limit_mb, 0);
13274 }
13275
13276 #[test]
13277 fn test_fraud_config_defaults() {
13278 let config = FraudConfig::default();
13279 assert!(!config.enabled);
13280 assert_eq!(config.fraud_rate, 0.005);
13281 assert!(!config.clustering_enabled);
13282 }
13283
13284 #[test]
13285 fn test_internal_controls_config_defaults() {
13286 let config = InternalControlsConfig::default();
13287 assert!(!config.enabled);
13288 assert_eq!(config.exception_rate, 0.02);
13289 assert_eq!(config.sod_violation_rate, 0.01);
13290 assert!(config.export_control_master_data);
13291 assert_eq!(config.sox_materiality_threshold, 10000.0);
13292 assert!(config.coso_enabled);
13294 assert!(!config.include_entity_level_controls);
13295 assert_eq!(config.target_maturity_level, "mixed");
13296 }
13297
13298 #[test]
13299 fn test_output_config_defaults() {
13300 let config = OutputConfig::default();
13301 assert!(matches!(config.mode, OutputMode::FlatFile));
13302 assert_eq!(config.formats, vec![FileFormat::Parquet]);
13303 assert!(config.compression.enabled);
13304 assert!(matches!(
13305 config.compression.algorithm,
13306 CompressionAlgorithm::Zstd
13307 ));
13308 assert!(config.include_acdoca);
13309 assert!(!config.include_bseg);
13310 assert!(config.partition_by_period);
13311 assert!(!config.partition_by_company);
13312 }
13313
13314 #[test]
13315 fn test_approval_config_defaults() {
13316 let config = ApprovalConfig::default();
13317 assert!(!config.enabled);
13318 assert_eq!(config.auto_approve_threshold, 1000.0);
13319 assert_eq!(config.rejection_rate, 0.02);
13320 assert_eq!(config.revision_rate, 0.05);
13321 assert_eq!(config.average_approval_delay_hours, 4.0);
13322 assert_eq!(config.thresholds.len(), 4);
13323 }
13324
13325 #[test]
13326 fn test_p2p_flow_config_defaults() {
13327 let config = P2PFlowConfig::default();
13328 assert!(config.enabled);
13329 assert_eq!(config.three_way_match_rate, 0.95);
13330 assert_eq!(config.partial_delivery_rate, 0.15);
13331 assert_eq!(config.average_po_to_gr_days, 14);
13332 }
13333
13334 #[test]
13335 fn test_o2c_flow_config_defaults() {
13336 let config = O2CFlowConfig::default();
13337 assert!(config.enabled);
13338 assert_eq!(config.credit_check_failure_rate, 0.02);
13339 assert_eq!(config.return_rate, 0.03);
13340 assert_eq!(config.bad_debt_rate, 0.01);
13341 }
13342
13343 #[test]
13344 fn test_balance_config_defaults() {
13345 let config = BalanceConfig::default();
13346 assert!(!config.generate_opening_balances);
13347 assert!(config.generate_trial_balances);
13348 assert_eq!(config.target_gross_margin, 0.35);
13349 assert!(config.validate_balance_equation);
13350 assert!(config.reconcile_subledgers);
13351 }
13352
13353 #[test]
13358 fn test_partial_config_with_defaults() {
13359 let yaml = r#"
13361 global:
13362 industry: manufacturing
13363 start_date: "2024-01-01"
13364 period_months: 3
13365 companies:
13366 - code: "TEST"
13367 name: "Test Company"
13368 currency: "USD"
13369 country: "US"
13370 annual_transaction_volume: ten_k
13371 chart_of_accounts:
13372 complexity: small
13373 output:
13374 output_directory: "./output"
13375 "#;
13376
13377 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13378 assert_eq!(config.global.period_months, 3);
13379 assert_eq!(config.companies.len(), 1);
13380 assert!(!config.fraud.enabled); assert!(!config.internal_controls.enabled); }
13383
13384 #[test]
13385 fn test_config_with_fraud_enabled() {
13386 let yaml = r#"
13387 global:
13388 industry: retail
13389 start_date: "2024-01-01"
13390 period_months: 12
13391 companies:
13392 - code: "RETAIL"
13393 name: "Retail Co"
13394 currency: "USD"
13395 country: "US"
13396 annual_transaction_volume: hundred_k
13397 chart_of_accounts:
13398 complexity: medium
13399 output:
13400 output_directory: "./output"
13401 fraud:
13402 enabled: true
13403 fraud_rate: 0.05
13404 clustering_enabled: true
13405 "#;
13406
13407 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13408 assert!(config.fraud.enabled);
13409 assert_eq!(config.fraud.fraud_rate, 0.05);
13410 assert!(config.fraud.clustering_enabled);
13411 }
13412
13413 #[test]
13414 fn test_config_with_multiple_companies() {
13415 let yaml = r#"
13416 global:
13417 industry: manufacturing
13418 start_date: "2024-01-01"
13419 period_months: 6
13420 companies:
13421 - code: "HQ"
13422 name: "Headquarters"
13423 currency: "USD"
13424 country: "US"
13425 annual_transaction_volume: hundred_k
13426 volume_weight: 1.0
13427 - code: "EU"
13428 name: "European Subsidiary"
13429 currency: "EUR"
13430 country: "DE"
13431 annual_transaction_volume: hundred_k
13432 volume_weight: 0.5
13433 - code: "APAC"
13434 name: "Asia Pacific"
13435 currency: "JPY"
13436 country: "JP"
13437 annual_transaction_volume: ten_k
13438 volume_weight: 0.3
13439 chart_of_accounts:
13440 complexity: large
13441 output:
13442 output_directory: "./output"
13443 "#;
13444
13445 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13446 assert_eq!(config.companies.len(), 3);
13447 assert_eq!(config.companies[0].code, "HQ");
13448 assert_eq!(config.companies[1].currency, "EUR");
13449 assert_eq!(config.companies[2].volume_weight, 0.3);
13450 }
13451
13452 #[test]
13453 fn test_intercompany_config() {
13454 let yaml = r#"
13455 enabled: true
13456 ic_transaction_rate: 0.20
13457 transfer_pricing_method: cost_plus
13458 markup_percent: 0.08
13459 generate_matched_pairs: true
13460 generate_eliminations: true
13461 "#;
13462
13463 let config: IntercompanyConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13464 assert!(config.enabled);
13465 assert_eq!(config.ic_transaction_rate, 0.20);
13466 assert!(matches!(
13467 config.transfer_pricing_method,
13468 TransferPricingMethod::CostPlus
13469 ));
13470 assert_eq!(config.markup_percent, 0.08);
13471 assert!(config.generate_eliminations);
13472 }
13473
13474 #[test]
13479 fn test_company_config_defaults() {
13480 let yaml = r#"
13481 code: "TEST"
13482 name: "Test Company"
13483 currency: "USD"
13484 country: "US"
13485 annual_transaction_volume: ten_k
13486 "#;
13487
13488 let config: CompanyConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13489 assert_eq!(config.fiscal_year_variant, "K4"); assert_eq!(config.volume_weight, 1.0); }
13492
13493 #[test]
13498 fn test_coa_config_defaults() {
13499 let yaml = r#"
13500 complexity: medium
13501 "#;
13502
13503 let config: ChartOfAccountsConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13504 assert!(config.industry_specific); assert!(config.custom_accounts.is_none());
13506 assert_eq!(config.min_hierarchy_depth, 2); assert_eq!(config.max_hierarchy_depth, 5); }
13509
13510 #[test]
13515 fn test_accounting_standards_config_defaults() {
13516 let config = AccountingStandardsConfig::default();
13517 assert!(!config.enabled);
13518 assert!(config.framework.is_none());
13519 assert!(!config.revenue_recognition.enabled);
13520 assert!(!config.leases.enabled);
13521 assert!(!config.fair_value.enabled);
13522 assert!(!config.impairment.enabled);
13523 assert!(!config.generate_differences);
13524 }
13525
13526 #[test]
13527 fn test_accounting_standards_config_yaml() {
13528 let yaml = r#"
13529 enabled: true
13530 framework: ifrs
13531 revenue_recognition:
13532 enabled: true
13533 generate_contracts: true
13534 avg_obligations_per_contract: 2.5
13535 variable_consideration_rate: 0.20
13536 over_time_recognition_rate: 0.35
13537 contract_count: 150
13538 leases:
13539 enabled: true
13540 lease_count: 75
13541 finance_lease_percent: 0.25
13542 avg_lease_term_months: 48
13543 generate_differences: true
13544 "#;
13545
13546 let config: AccountingStandardsConfig =
13547 serde_yaml::from_str(yaml).expect("Failed to parse");
13548 assert!(config.enabled);
13549 assert!(matches!(
13550 config.framework,
13551 Some(AccountingFrameworkConfig::Ifrs)
13552 ));
13553 assert!(config.revenue_recognition.enabled);
13554 assert_eq!(config.revenue_recognition.contract_count, 150);
13555 assert_eq!(config.revenue_recognition.avg_obligations_per_contract, 2.5);
13556 assert!(config.leases.enabled);
13557 assert_eq!(config.leases.lease_count, 75);
13558 assert_eq!(config.leases.finance_lease_percent, 0.25);
13559 assert!(config.generate_differences);
13560 }
13561
13562 #[test]
13563 fn test_accounting_framework_serialization() {
13564 let frameworks = [
13565 AccountingFrameworkConfig::UsGaap,
13566 AccountingFrameworkConfig::Ifrs,
13567 AccountingFrameworkConfig::DualReporting,
13568 AccountingFrameworkConfig::FrenchGaap,
13569 AccountingFrameworkConfig::GermanGaap,
13570 ];
13571
13572 for framework in frameworks {
13573 let json = serde_json::to_string(&framework).expect("Failed to serialize");
13574 let deserialized: AccountingFrameworkConfig =
13575 serde_json::from_str(&json).expect("Failed to deserialize");
13576 assert!(format!("{:?}", framework) == format!("{:?}", deserialized));
13577 }
13578 }
13579
13580 #[test]
13581 fn test_revenue_recognition_config_defaults() {
13582 let config = RevenueRecognitionConfig::default();
13583 assert!(!config.enabled);
13584 assert!(config.generate_contracts);
13585 assert_eq!(config.avg_obligations_per_contract, 2.0);
13586 assert_eq!(config.variable_consideration_rate, 0.15);
13587 assert_eq!(config.over_time_recognition_rate, 0.30);
13588 assert_eq!(config.contract_count, 100);
13589 }
13590
13591 #[test]
13592 fn test_lease_accounting_config_defaults() {
13593 let config = LeaseAccountingConfig::default();
13594 assert!(!config.enabled);
13595 assert_eq!(config.lease_count, 50);
13596 assert_eq!(config.finance_lease_percent, 0.30);
13597 assert_eq!(config.avg_lease_term_months, 60);
13598 assert!(config.generate_amortization);
13599 assert_eq!(config.real_estate_percent, 0.40);
13600 }
13601
13602 #[test]
13603 fn test_fair_value_config_defaults() {
13604 let config = FairValueConfig::default();
13605 assert!(!config.enabled);
13606 assert_eq!(config.measurement_count, 25);
13607 assert_eq!(config.level1_percent, 0.40);
13608 assert_eq!(config.level2_percent, 0.35);
13609 assert_eq!(config.level3_percent, 0.25);
13610 assert!(!config.include_sensitivity_analysis);
13611 }
13612
13613 #[test]
13614 fn test_impairment_config_defaults() {
13615 let config = ImpairmentConfig::default();
13616 assert!(!config.enabled);
13617 assert_eq!(config.test_count, 15);
13618 assert_eq!(config.impairment_rate, 0.10);
13619 assert!(config.generate_projections);
13620 assert!(!config.include_goodwill);
13621 }
13622
13623 #[test]
13628 fn test_audit_standards_config_defaults() {
13629 let config = AuditStandardsConfig::default();
13630 assert!(!config.enabled);
13631 assert!(!config.isa_compliance.enabled);
13632 assert!(!config.analytical_procedures.enabled);
13633 assert!(!config.confirmations.enabled);
13634 assert!(!config.opinion.enabled);
13635 assert!(!config.generate_audit_trail);
13636 assert!(!config.sox.enabled);
13637 assert!(!config.pcaob.enabled);
13638 }
13639
13640 #[test]
13641 fn test_audit_standards_config_yaml() {
13642 let yaml = r#"
13643 enabled: true
13644 isa_compliance:
13645 enabled: true
13646 compliance_level: comprehensive
13647 generate_isa_mappings: true
13648 include_pcaob: true
13649 framework: dual
13650 analytical_procedures:
13651 enabled: true
13652 procedures_per_account: 5
13653 variance_probability: 0.25
13654 confirmations:
13655 enabled: true
13656 confirmation_count: 75
13657 positive_response_rate: 0.90
13658 exception_rate: 0.08
13659 opinion:
13660 enabled: true
13661 generate_kam: true
13662 average_kam_count: 4
13663 sox:
13664 enabled: true
13665 generate_302_certifications: true
13666 generate_404_assessments: true
13667 material_weakness_rate: 0.03
13668 pcaob:
13669 enabled: true
13670 is_pcaob_audit: true
13671 include_icfr_opinion: true
13672 generate_audit_trail: true
13673 "#;
13674
13675 let config: AuditStandardsConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13676 assert!(config.enabled);
13677 assert!(config.isa_compliance.enabled);
13678 assert_eq!(config.isa_compliance.compliance_level, "comprehensive");
13679 assert!(config.isa_compliance.include_pcaob);
13680 assert_eq!(config.isa_compliance.framework, "dual");
13681 assert!(config.analytical_procedures.enabled);
13682 assert_eq!(config.analytical_procedures.procedures_per_account, 5);
13683 assert!(config.confirmations.enabled);
13684 assert_eq!(config.confirmations.confirmation_count, 75);
13685 assert!(config.opinion.enabled);
13686 assert_eq!(config.opinion.average_kam_count, 4);
13687 assert!(config.sox.enabled);
13688 assert!(config.sox.generate_302_certifications);
13689 assert_eq!(config.sox.material_weakness_rate, 0.03);
13690 assert!(config.pcaob.enabled);
13691 assert!(config.pcaob.is_pcaob_audit);
13692 assert!(config.pcaob.include_icfr_opinion);
13693 assert!(config.generate_audit_trail);
13694 }
13695
13696 #[test]
13697 fn test_isa_compliance_config_defaults() {
13698 let config = IsaComplianceConfig::default();
13699 assert!(!config.enabled);
13700 assert_eq!(config.compliance_level, "standard");
13701 assert!(config.generate_isa_mappings);
13702 assert!(config.generate_coverage_summary);
13703 assert!(!config.include_pcaob);
13704 assert_eq!(config.framework, "isa");
13705 }
13706
13707 #[test]
13708 fn test_sox_compliance_config_defaults() {
13709 let config = SoxComplianceConfig::default();
13710 assert!(!config.enabled);
13711 assert!(config.generate_302_certifications);
13712 assert!(config.generate_404_assessments);
13713 assert_eq!(config.materiality_threshold, 10000.0);
13714 assert_eq!(config.material_weakness_rate, 0.02);
13715 assert_eq!(config.significant_deficiency_rate, 0.08);
13716 }
13717
13718 #[test]
13719 fn test_pcaob_config_defaults() {
13720 let config = PcaobConfig::default();
13721 assert!(!config.enabled);
13722 assert!(!config.is_pcaob_audit);
13723 assert!(config.generate_cam);
13724 assert!(!config.include_icfr_opinion);
13725 assert!(!config.generate_standard_mappings);
13726 }
13727
13728 #[test]
13729 fn test_config_with_standards_enabled() {
13730 let yaml = r#"
13731 global:
13732 industry: financial_services
13733 start_date: "2024-01-01"
13734 period_months: 12
13735 companies:
13736 - code: "BANK"
13737 name: "Test Bank"
13738 currency: "USD"
13739 country: "US"
13740 annual_transaction_volume: hundred_k
13741 chart_of_accounts:
13742 complexity: large
13743 output:
13744 output_directory: "./output"
13745 accounting_standards:
13746 enabled: true
13747 framework: us_gaap
13748 revenue_recognition:
13749 enabled: true
13750 leases:
13751 enabled: true
13752 audit_standards:
13753 enabled: true
13754 isa_compliance:
13755 enabled: true
13756 sox:
13757 enabled: true
13758 "#;
13759
13760 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13761 assert!(config.accounting_standards.enabled);
13762 assert!(matches!(
13763 config.accounting_standards.framework,
13764 Some(AccountingFrameworkConfig::UsGaap)
13765 ));
13766 assert!(config.accounting_standards.revenue_recognition.enabled);
13767 assert!(config.accounting_standards.leases.enabled);
13768 assert!(config.audit_standards.enabled);
13769 assert!(config.audit_standards.isa_compliance.enabled);
13770 assert!(config.audit_standards.sox.enabled);
13771 }
13772
13773 #[test]
13778 fn test_industry_specific_config_defaults() {
13779 let config = IndustrySpecificConfig::default();
13780 assert!(!config.enabled);
13781 assert!(!config.manufacturing.enabled);
13782 assert!(!config.retail.enabled);
13783 assert!(!config.healthcare.enabled);
13784 assert!(!config.technology.enabled);
13785 assert!(!config.financial_services.enabled);
13786 assert!(!config.professional_services.enabled);
13787 }
13788
13789 #[test]
13790 fn test_manufacturing_config_defaults() {
13791 let config = ManufacturingConfig::default();
13792 assert!(!config.enabled);
13793 assert_eq!(config.bom_depth, 4);
13794 assert!(!config.just_in_time);
13795 assert_eq!(config.supplier_tiers, 2);
13796 assert_eq!(config.target_yield_rate, 0.97);
13797 assert_eq!(config.scrap_alert_threshold, 0.03);
13798 }
13799
13800 #[test]
13801 fn test_retail_config_defaults() {
13802 let config = RetailConfig::default();
13803 assert!(!config.enabled);
13804 assert_eq!(config.avg_daily_transactions, 500);
13805 assert!(config.loss_prevention);
13806 assert_eq!(config.shrinkage_rate, 0.015);
13807 }
13808
13809 #[test]
13810 fn test_healthcare_config_defaults() {
13811 let config = HealthcareConfig::default();
13812 assert!(!config.enabled);
13813 assert_eq!(config.facility_type, "hospital");
13814 assert_eq!(config.avg_daily_encounters, 150);
13815 assert!(config.compliance.hipaa);
13816 assert!(config.compliance.stark_law);
13817 assert!(config.coding_systems.icd10);
13818 assert!(config.coding_systems.cpt);
13819 }
13820
13821 #[test]
13822 fn test_technology_config_defaults() {
13823 let config = TechnologyConfig::default();
13824 assert!(!config.enabled);
13825 assert_eq!(config.revenue_model, "saas");
13826 assert_eq!(config.subscription_revenue_pct, 0.60);
13827 assert!(config.rd_capitalization.enabled);
13828 }
13829
13830 #[test]
13831 fn test_config_with_industry_specific() {
13832 let yaml = r#"
13833 global:
13834 industry: healthcare
13835 start_date: "2024-01-01"
13836 period_months: 12
13837 companies:
13838 - code: "HOSP"
13839 name: "Test Hospital"
13840 currency: "USD"
13841 country: "US"
13842 annual_transaction_volume: hundred_k
13843 chart_of_accounts:
13844 complexity: medium
13845 output:
13846 output_directory: "./output"
13847 industry_specific:
13848 enabled: true
13849 healthcare:
13850 enabled: true
13851 facility_type: hospital
13852 payer_mix:
13853 medicare: 0.45
13854 medicaid: 0.15
13855 commercial: 0.35
13856 self_pay: 0.05
13857 coding_systems:
13858 icd10: true
13859 cpt: true
13860 drg: true
13861 compliance:
13862 hipaa: true
13863 stark_law: true
13864 anomaly_rates:
13865 upcoding: 0.03
13866 unbundling: 0.02
13867 "#;
13868
13869 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13870 assert!(config.industry_specific.enabled);
13871 assert!(config.industry_specific.healthcare.enabled);
13872 assert_eq!(
13873 config.industry_specific.healthcare.facility_type,
13874 "hospital"
13875 );
13876 assert_eq!(config.industry_specific.healthcare.payer_mix.medicare, 0.45);
13877 assert_eq!(config.industry_specific.healthcare.payer_mix.self_pay, 0.05);
13878 assert!(config.industry_specific.healthcare.coding_systems.icd10);
13879 assert!(config.industry_specific.healthcare.compliance.hipaa);
13880 assert_eq!(
13881 config.industry_specific.healthcare.anomaly_rates.upcoding,
13882 0.03
13883 );
13884 }
13885
13886 #[test]
13887 fn test_config_with_manufacturing_specific() {
13888 let yaml = r#"
13889 global:
13890 industry: manufacturing
13891 start_date: "2024-01-01"
13892 period_months: 12
13893 companies:
13894 - code: "MFG"
13895 name: "Test Manufacturing"
13896 currency: "USD"
13897 country: "US"
13898 annual_transaction_volume: hundred_k
13899 chart_of_accounts:
13900 complexity: medium
13901 output:
13902 output_directory: "./output"
13903 industry_specific:
13904 enabled: true
13905 manufacturing:
13906 enabled: true
13907 bom_depth: 5
13908 just_in_time: true
13909 supplier_tiers: 3
13910 target_yield_rate: 0.98
13911 anomaly_rates:
13912 yield_manipulation: 0.02
13913 phantom_production: 0.01
13914 "#;
13915
13916 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13917 assert!(config.industry_specific.enabled);
13918 assert!(config.industry_specific.manufacturing.enabled);
13919 assert_eq!(config.industry_specific.manufacturing.bom_depth, 5);
13920 assert!(config.industry_specific.manufacturing.just_in_time);
13921 assert_eq!(config.industry_specific.manufacturing.supplier_tiers, 3);
13922 assert_eq!(
13923 config.industry_specific.manufacturing.target_yield_rate,
13924 0.98
13925 );
13926 assert_eq!(
13927 config
13928 .industry_specific
13929 .manufacturing
13930 .anomaly_rates
13931 .yield_manipulation,
13932 0.02
13933 );
13934 }
13935
13936 #[test]
13941 fn test_tax_config_defaults() {
13942 let tax = TaxConfig::default();
13943 assert!(!tax.enabled);
13944 assert!(tax.jurisdictions.countries.is_empty());
13945 assert!(!tax.jurisdictions.include_subnational);
13946 assert!(!tax.vat_gst.enabled);
13947 assert!(tax.vat_gst.standard_rates.is_empty());
13948 assert!(tax.vat_gst.reduced_rates.is_empty());
13949 assert!(tax.vat_gst.exempt_categories.is_empty());
13950 assert!(tax.vat_gst.reverse_charge);
13951 assert!(!tax.sales_tax.enabled);
13952 assert!(tax.sales_tax.nexus_states.is_empty());
13953 assert!(!tax.withholding.enabled);
13954 assert!(tax.withholding.treaty_network);
13955 assert_eq!(tax.withholding.default_rate, 0.30);
13956 assert_eq!(tax.withholding.treaty_reduced_rate, 0.15);
13957 assert!(tax.provisions.enabled);
13958 assert_eq!(tax.provisions.statutory_rate, 0.21);
13959 assert!(tax.provisions.uncertain_positions);
13960 assert!(!tax.payroll_tax.enabled);
13961 assert_eq!(tax.anomaly_rate, 0.03);
13962 }
13963
13964 #[test]
13965 fn test_tax_config_from_yaml() {
13966 let yaml = r#"
13967 global:
13968 seed: 42
13969 start_date: "2024-01-01"
13970 period_months: 12
13971 industry: retail
13972 companies:
13973 - code: C001
13974 name: Test Corp
13975 currency: USD
13976 country: US
13977 annual_transaction_volume: ten_k
13978 chart_of_accounts:
13979 complexity: small
13980 output:
13981 output_directory: ./output
13982 tax:
13983 enabled: true
13984 anomaly_rate: 0.05
13985 jurisdictions:
13986 countries: ["US", "DE", "GB"]
13987 include_subnational: true
13988 vat_gst:
13989 enabled: true
13990 standard_rates:
13991 DE: 0.19
13992 GB: 0.20
13993 reduced_rates:
13994 DE: 0.07
13995 GB: 0.05
13996 exempt_categories:
13997 - financial_services
13998 - healthcare
13999 reverse_charge: false
14000 sales_tax:
14001 enabled: true
14002 nexus_states: ["CA", "NY", "TX"]
14003 withholding:
14004 enabled: true
14005 treaty_network: false
14006 default_rate: 0.25
14007 treaty_reduced_rate: 0.10
14008 provisions:
14009 enabled: false
14010 statutory_rate: 0.28
14011 uncertain_positions: false
14012 payroll_tax:
14013 enabled: true
14014 "#;
14015
14016 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
14017 assert!(config.tax.enabled);
14018 assert_eq!(config.tax.anomaly_rate, 0.05);
14019
14020 assert_eq!(config.tax.jurisdictions.countries.len(), 3);
14022 assert!(config
14023 .tax
14024 .jurisdictions
14025 .countries
14026 .contains(&"DE".to_string()));
14027 assert!(config.tax.jurisdictions.include_subnational);
14028
14029 assert!(config.tax.vat_gst.enabled);
14031 assert_eq!(config.tax.vat_gst.standard_rates.get("DE"), Some(&0.19));
14032 assert_eq!(config.tax.vat_gst.standard_rates.get("GB"), Some(&0.20));
14033 assert_eq!(config.tax.vat_gst.reduced_rates.get("DE"), Some(&0.07));
14034 assert_eq!(config.tax.vat_gst.exempt_categories.len(), 2);
14035 assert!(!config.tax.vat_gst.reverse_charge);
14036
14037 assert!(config.tax.sales_tax.enabled);
14039 assert_eq!(config.tax.sales_tax.nexus_states.len(), 3);
14040 assert!(config
14041 .tax
14042 .sales_tax
14043 .nexus_states
14044 .contains(&"CA".to_string()));
14045
14046 assert!(config.tax.withholding.enabled);
14048 assert!(!config.tax.withholding.treaty_network);
14049 assert_eq!(config.tax.withholding.default_rate, 0.25);
14050 assert_eq!(config.tax.withholding.treaty_reduced_rate, 0.10);
14051
14052 assert!(!config.tax.provisions.enabled);
14054 assert_eq!(config.tax.provisions.statutory_rate, 0.28);
14055 assert!(!config.tax.provisions.uncertain_positions);
14056
14057 assert!(config.tax.payroll_tax.enabled);
14059 }
14060
14061 #[test]
14062 fn test_generator_config_with_tax_default() {
14063 let yaml = r#"
14064 global:
14065 seed: 42
14066 start_date: "2024-01-01"
14067 period_months: 12
14068 industry: retail
14069 companies:
14070 - code: C001
14071 name: Test Corp
14072 currency: USD
14073 country: US
14074 annual_transaction_volume: ten_k
14075 chart_of_accounts:
14076 complexity: small
14077 output:
14078 output_directory: ./output
14079 "#;
14080
14081 let config: GeneratorConfig =
14082 serde_yaml::from_str(yaml).expect("Failed to parse config without tax section");
14083 assert!(!config.tax.enabled);
14085 assert!(config.tax.jurisdictions.countries.is_empty());
14086 assert_eq!(config.tax.anomaly_rate, 0.03);
14087 assert!(config.tax.provisions.enabled); assert_eq!(config.tax.provisions.statutory_rate, 0.21);
14089 }
14090
14091 #[test]
14096 fn test_session_config_default_disabled() {
14097 let yaml = "{}";
14098 let config: SessionSchemaConfig =
14099 serde_yaml::from_str(yaml).expect("Failed to parse empty session config");
14100 assert!(!config.enabled);
14101 assert!(config.checkpoint_path.is_none());
14102 assert!(config.per_period_output);
14103 assert!(config.consolidated_output);
14104 }
14105
14106 #[test]
14107 fn test_config_backward_compatible_without_session() {
14108 let yaml = r#"
14109 global:
14110 seed: 42
14111 start_date: "2024-01-01"
14112 period_months: 12
14113 industry: retail
14114 companies:
14115 - code: C001
14116 name: Test Corp
14117 currency: USD
14118 country: US
14119 annual_transaction_volume: ten_k
14120 chart_of_accounts:
14121 complexity: small
14122 output:
14123 output_directory: ./output
14124 "#;
14125
14126 let config: GeneratorConfig =
14127 serde_yaml::from_str(yaml).expect("Failed to parse config without session");
14128 assert!(!config.session.enabled);
14130 assert!(config.session.per_period_output);
14131 assert!(config.session.consolidated_output);
14132 assert!(config.global.fiscal_year_months.is_none());
14134 }
14135
14136 #[test]
14137 fn test_fiscal_year_months_parsed() {
14138 let yaml = r#"
14139 global:
14140 seed: 42
14141 start_date: "2024-01-01"
14142 period_months: 24
14143 industry: retail
14144 fiscal_year_months: 12
14145 companies:
14146 - code: C001
14147 name: Test Corp
14148 currency: USD
14149 country: US
14150 annual_transaction_volume: ten_k
14151 chart_of_accounts:
14152 complexity: small
14153 output:
14154 output_directory: ./output
14155 session:
14156 enabled: true
14157 checkpoint_path: /tmp/checkpoints
14158 per_period_output: true
14159 consolidated_output: false
14160 "#;
14161
14162 let config: GeneratorConfig =
14163 serde_yaml::from_str(yaml).expect("Failed to parse config with fiscal_year_months");
14164 assert_eq!(config.global.fiscal_year_months, Some(12));
14165 assert!(config.session.enabled);
14166 assert_eq!(
14167 config.session.checkpoint_path,
14168 Some("/tmp/checkpoints".to_string())
14169 );
14170 assert!(config.session.per_period_output);
14171 assert!(!config.session.consolidated_output);
14172 }
14173}