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 = "default_buffer_size")]
859 pub buffer_size: usize,
860 #[serde(default = "default_true")]
862 pub enable_progress: bool,
863 #[serde(default = "default_progress_interval")]
865 pub progress_interval: u64,
866 #[serde(default)]
868 pub backpressure: BackpressureSchemaStrategy,
869}
870
871fn default_buffer_size() -> usize {
872 1000
873}
874
875fn default_progress_interval() -> u64 {
876 100
877}
878
879impl Default for StreamingSchemaConfig {
880 fn default() -> Self {
881 Self {
882 enabled: false,
883 buffer_size: 1000,
884 enable_progress: true,
885 progress_interval: 100,
886 backpressure: BackpressureSchemaStrategy::Block,
887 }
888 }
889}
890
891#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
893#[serde(rename_all = "snake_case")]
894pub enum BackpressureSchemaStrategy {
895 #[default]
897 Block,
898 DropOldest,
900 DropNewest,
902 Buffer,
904}
905
906#[derive(Debug, Clone, Serialize, Deserialize)]
912pub struct RateLimitSchemaConfig {
913 #[serde(default)]
915 pub enabled: bool,
916 #[serde(default = "default_entities_per_second")]
918 pub entities_per_second: f64,
919 #[serde(default = "default_burst_size")]
921 pub burst_size: u32,
922 #[serde(default)]
924 pub backpressure: RateLimitBackpressureSchema,
925}
926
927fn default_entities_per_second() -> f64 {
928 1000.0
929}
930
931fn default_burst_size() -> u32 {
932 100
933}
934
935impl Default for RateLimitSchemaConfig {
936 fn default() -> Self {
937 Self {
938 enabled: false,
939 entities_per_second: 1000.0,
940 burst_size: 100,
941 backpressure: RateLimitBackpressureSchema::Block,
942 }
943 }
944}
945
946#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
948#[serde(rename_all = "snake_case")]
949pub enum RateLimitBackpressureSchema {
950 #[default]
952 Block,
953 Drop,
955 Buffer,
957}
958
959#[derive(Debug, Clone, Serialize, Deserialize)]
965pub struct TemporalAttributeSchemaConfig {
966 #[serde(default)]
968 pub enabled: bool,
969 #[serde(default)]
971 pub valid_time: ValidTimeSchemaConfig,
972 #[serde(default)]
974 pub transaction_time: TransactionTimeSchemaConfig,
975 #[serde(default)]
977 pub generate_version_chains: bool,
978 #[serde(default = "default_avg_versions")]
980 pub avg_versions_per_entity: f64,
981}
982
983fn default_avg_versions() -> f64 {
984 1.5
985}
986
987impl Default for TemporalAttributeSchemaConfig {
988 fn default() -> Self {
989 Self {
990 enabled: false,
991 valid_time: ValidTimeSchemaConfig::default(),
992 transaction_time: TransactionTimeSchemaConfig::default(),
993 generate_version_chains: false,
994 avg_versions_per_entity: 1.5,
995 }
996 }
997}
998
999#[derive(Debug, Clone, Serialize, Deserialize)]
1001pub struct ValidTimeSchemaConfig {
1002 #[serde(default = "default_closed_probability")]
1004 pub closed_probability: f64,
1005 #[serde(default = "default_avg_validity_days")]
1007 pub avg_validity_days: u32,
1008 #[serde(default = "default_validity_stddev")]
1010 pub validity_stddev_days: u32,
1011}
1012
1013fn default_closed_probability() -> f64 {
1014 0.1
1015}
1016
1017fn default_avg_validity_days() -> u32 {
1018 365
1019}
1020
1021fn default_validity_stddev() -> u32 {
1022 90
1023}
1024
1025impl Default for ValidTimeSchemaConfig {
1026 fn default() -> Self {
1027 Self {
1028 closed_probability: 0.1,
1029 avg_validity_days: 365,
1030 validity_stddev_days: 90,
1031 }
1032 }
1033}
1034
1035#[derive(Debug, Clone, Serialize, Deserialize)]
1037pub struct TransactionTimeSchemaConfig {
1038 #[serde(default)]
1040 pub avg_recording_delay_seconds: u32,
1041 #[serde(default)]
1043 pub allow_backdating: bool,
1044 #[serde(default = "default_backdating_probability")]
1046 pub backdating_probability: f64,
1047 #[serde(default = "default_max_backdate_days")]
1049 pub max_backdate_days: u32,
1050}
1051
1052fn default_backdating_probability() -> f64 {
1053 0.01
1054}
1055
1056fn default_max_backdate_days() -> u32 {
1057 30
1058}
1059
1060impl Default for TransactionTimeSchemaConfig {
1061 fn default() -> Self {
1062 Self {
1063 avg_recording_delay_seconds: 0,
1064 allow_backdating: false,
1065 backdating_probability: 0.01,
1066 max_backdate_days: 30,
1067 }
1068 }
1069}
1070
1071#[derive(Debug, Clone, Serialize, Deserialize)]
1077pub struct RelationshipSchemaConfig {
1078 #[serde(default)]
1080 pub relationship_types: Vec<RelationshipTypeSchemaConfig>,
1081 #[serde(default = "default_true")]
1083 pub allow_orphans: bool,
1084 #[serde(default = "default_orphan_probability")]
1086 pub orphan_probability: f64,
1087 #[serde(default)]
1089 pub allow_circular: bool,
1090 #[serde(default = "default_max_circular_depth")]
1092 pub max_circular_depth: u32,
1093}
1094
1095fn default_orphan_probability() -> f64 {
1096 0.01
1097}
1098
1099fn default_max_circular_depth() -> u32 {
1100 3
1101}
1102
1103impl Default for RelationshipSchemaConfig {
1104 fn default() -> Self {
1105 Self {
1106 relationship_types: Vec::new(),
1107 allow_orphans: true,
1108 orphan_probability: 0.01,
1109 allow_circular: false,
1110 max_circular_depth: 3,
1111 }
1112 }
1113}
1114
1115#[derive(Debug, Clone, Serialize, Deserialize)]
1117pub struct RelationshipTypeSchemaConfig {
1118 pub name: String,
1120 pub source_type: String,
1122 pub target_type: String,
1124 #[serde(default)]
1126 pub cardinality: CardinalitySchemaRule,
1127 #[serde(default = "default_relationship_weight")]
1129 pub weight: f64,
1130 #[serde(default)]
1132 pub required: bool,
1133 #[serde(default = "default_true")]
1135 pub directed: bool,
1136}
1137
1138fn default_relationship_weight() -> f64 {
1139 1.0
1140}
1141
1142impl Default for RelationshipTypeSchemaConfig {
1143 fn default() -> Self {
1144 Self {
1145 name: String::new(),
1146 source_type: String::new(),
1147 target_type: String::new(),
1148 cardinality: CardinalitySchemaRule::default(),
1149 weight: 1.0,
1150 required: false,
1151 directed: true,
1152 }
1153 }
1154}
1155
1156#[derive(Debug, Clone, Serialize, Deserialize)]
1158#[serde(rename_all = "snake_case")]
1159pub enum CardinalitySchemaRule {
1160 OneToOne,
1162 OneToMany {
1164 min: u32,
1166 max: u32,
1168 },
1169 ManyToOne {
1171 min: u32,
1173 max: u32,
1175 },
1176 ManyToMany {
1178 min_per_source: u32,
1180 max_per_source: u32,
1182 },
1183}
1184
1185impl Default for CardinalitySchemaRule {
1186 fn default() -> Self {
1187 Self::OneToMany { min: 1, max: 5 }
1188 }
1189}
1190
1191#[derive(Debug, Clone, Serialize, Deserialize)]
1193pub struct GlobalConfig {
1194 pub seed: Option<u64>,
1196 pub industry: IndustrySector,
1198 pub start_date: String,
1200 pub period_months: u32,
1202 #[serde(default = "default_currency")]
1204 pub group_currency: String,
1205 #[serde(default)]
1208 pub presentation_currency: Option<String>,
1209 #[serde(default = "default_true")]
1211 pub parallel: bool,
1212 #[serde(default)]
1214 pub worker_threads: usize,
1215 #[serde(default)]
1217 pub memory_limit_mb: usize,
1218 #[serde(default)]
1221 pub fiscal_year_months: Option<u32>,
1222}
1223
1224fn default_currency() -> String {
1225 "USD".to_string()
1226}
1227fn default_true() -> bool {
1228 true
1229}
1230
1231#[derive(Debug, Clone, Serialize, Deserialize)]
1236pub struct SessionSchemaConfig {
1237 #[serde(default)]
1239 pub enabled: bool,
1240 #[serde(default)]
1242 pub checkpoint_path: Option<String>,
1243 #[serde(default = "default_true")]
1245 pub per_period_output: bool,
1246 #[serde(default = "default_true")]
1248 pub consolidated_output: bool,
1249}
1250
1251impl Default for SessionSchemaConfig {
1252 fn default() -> Self {
1253 Self {
1254 enabled: false,
1255 checkpoint_path: None,
1256 per_period_output: true,
1257 consolidated_output: true,
1258 }
1259 }
1260}
1261
1262#[derive(Debug, Clone, Serialize, Deserialize)]
1264pub struct CompanyConfig {
1265 pub code: String,
1267 pub name: String,
1269 pub currency: String,
1271 #[serde(default)]
1274 pub functional_currency: Option<String>,
1275 pub country: String,
1277 #[serde(default = "default_fiscal_variant")]
1279 pub fiscal_year_variant: String,
1280 pub annual_transaction_volume: TransactionVolume,
1282 #[serde(default = "default_weight")]
1284 pub volume_weight: f64,
1285}
1286
1287fn default_fiscal_variant() -> String {
1288 "K4".to_string()
1289}
1290fn default_weight() -> f64 {
1291 1.0
1292}
1293
1294#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1296#[serde(rename_all = "snake_case")]
1297pub enum TransactionVolume {
1298 TenK,
1300 HundredK,
1302 OneM,
1304 TenM,
1306 HundredM,
1308 Custom(u64),
1310}
1311
1312impl TransactionVolume {
1313 pub fn count(&self) -> u64 {
1315 match self {
1316 Self::TenK => 10_000,
1317 Self::HundredK => 100_000,
1318 Self::OneM => 1_000_000,
1319 Self::TenM => 10_000_000,
1320 Self::HundredM => 100_000_000,
1321 Self::Custom(n) => *n,
1322 }
1323 }
1324}
1325
1326#[derive(Debug, Clone, Serialize, Deserialize)]
1328pub struct ChartOfAccountsConfig {
1329 pub complexity: CoAComplexity,
1331 #[serde(default = "default_true")]
1333 pub industry_specific: bool,
1334 pub custom_accounts: Option<PathBuf>,
1336 #[serde(default = "default_min_depth")]
1338 pub min_hierarchy_depth: u8,
1339 #[serde(default = "default_max_depth")]
1341 pub max_hierarchy_depth: u8,
1342}
1343
1344fn default_min_depth() -> u8 {
1345 2
1346}
1347fn default_max_depth() -> u8 {
1348 5
1349}
1350
1351impl Default for ChartOfAccountsConfig {
1352 fn default() -> Self {
1353 Self {
1354 complexity: CoAComplexity::Small,
1355 industry_specific: true,
1356 custom_accounts: None,
1357 min_hierarchy_depth: default_min_depth(),
1358 max_hierarchy_depth: default_max_depth(),
1359 }
1360 }
1361}
1362
1363#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1365pub struct TransactionConfig {
1366 #[serde(default)]
1368 pub line_item_distribution: LineItemDistributionConfig,
1369 #[serde(default)]
1371 pub debit_credit_distribution: DebitCreditDistributionConfig,
1372 #[serde(default)]
1374 pub even_odd_distribution: EvenOddDistributionConfig,
1375 #[serde(default)]
1377 pub source_distribution: SourceDistribution,
1378 #[serde(default)]
1380 pub seasonality: SeasonalityConfig,
1381 #[serde(default)]
1383 pub amounts: AmountDistributionConfig,
1384 #[serde(default)]
1386 pub benford: BenfordConfig,
1387}
1388
1389#[derive(Debug, Clone, Serialize, Deserialize)]
1391pub struct BenfordConfig {
1392 #[serde(default = "default_true")]
1394 pub enabled: bool,
1395 #[serde(default = "default_benford_tolerance")]
1397 pub tolerance: f64,
1398 #[serde(default)]
1400 pub exempt_sources: Vec<BenfordExemption>,
1401}
1402
1403fn default_benford_tolerance() -> f64 {
1404 0.05
1405}
1406
1407impl Default for BenfordConfig {
1408 fn default() -> Self {
1409 Self {
1410 enabled: true,
1411 tolerance: default_benford_tolerance(),
1412 exempt_sources: vec![BenfordExemption::Recurring, BenfordExemption::Payroll],
1413 }
1414 }
1415}
1416
1417#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1419#[serde(rename_all = "snake_case")]
1420pub enum BenfordExemption {
1421 Recurring,
1423 Payroll,
1425 FixedFees,
1427 RoundAmounts,
1429}
1430
1431#[derive(Debug, Clone, Serialize, Deserialize)]
1433pub struct SourceDistribution {
1434 pub manual: f64,
1436 pub automated: f64,
1438 pub recurring: f64,
1440 pub adjustment: f64,
1442}
1443
1444impl Default for SourceDistribution {
1445 fn default() -> Self {
1446 Self {
1447 manual: 0.20,
1448 automated: 0.70,
1449 recurring: 0.07,
1450 adjustment: 0.03,
1451 }
1452 }
1453}
1454
1455#[derive(Debug, Clone, Serialize, Deserialize)]
1457pub struct OutputConfig {
1458 #[serde(default)]
1460 pub mode: OutputMode,
1461 pub output_directory: PathBuf,
1463 #[serde(default = "default_formats")]
1465 pub formats: Vec<FileFormat>,
1466 #[serde(default)]
1468 pub compression: CompressionConfig,
1469 #[serde(default = "default_batch_size")]
1471 pub batch_size: usize,
1472 #[serde(default = "default_true")]
1474 pub include_acdoca: bool,
1475 #[serde(default)]
1477 pub include_bseg: bool,
1478 #[serde(default = "default_true")]
1480 pub partition_by_period: bool,
1481 #[serde(default)]
1483 pub partition_by_company: bool,
1484}
1485
1486fn default_formats() -> Vec<FileFormat> {
1487 vec![FileFormat::Parquet]
1488}
1489fn default_batch_size() -> usize {
1490 100_000
1491}
1492
1493impl Default for OutputConfig {
1494 fn default() -> Self {
1495 Self {
1496 mode: OutputMode::FlatFile,
1497 output_directory: PathBuf::from("./output"),
1498 formats: default_formats(),
1499 compression: CompressionConfig::default(),
1500 batch_size: default_batch_size(),
1501 include_acdoca: true,
1502 include_bseg: false,
1503 partition_by_period: true,
1504 partition_by_company: false,
1505 }
1506 }
1507}
1508
1509#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
1511#[serde(rename_all = "snake_case")]
1512pub enum OutputMode {
1513 Streaming,
1515 #[default]
1517 FlatFile,
1518 Both,
1520}
1521
1522#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1524#[serde(rename_all = "snake_case")]
1525pub enum FileFormat {
1526 Csv,
1527 Parquet,
1528 Json,
1529 JsonLines,
1530}
1531
1532#[derive(Debug, Clone, Serialize, Deserialize)]
1534pub struct CompressionConfig {
1535 #[serde(default = "default_true")]
1537 pub enabled: bool,
1538 #[serde(default)]
1540 pub algorithm: CompressionAlgorithm,
1541 #[serde(default = "default_compression_level")]
1543 pub level: u8,
1544}
1545
1546fn default_compression_level() -> u8 {
1547 3
1548}
1549
1550impl Default for CompressionConfig {
1551 fn default() -> Self {
1552 Self {
1553 enabled: true,
1554 algorithm: CompressionAlgorithm::default(),
1555 level: default_compression_level(),
1556 }
1557 }
1558}
1559
1560#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
1562#[serde(rename_all = "snake_case")]
1563pub enum CompressionAlgorithm {
1564 Gzip,
1565 #[default]
1566 Zstd,
1567 Lz4,
1568 Snappy,
1569}
1570
1571#[derive(Debug, Clone, Serialize, Deserialize)]
1573pub struct FraudConfig {
1574 #[serde(default)]
1576 pub enabled: bool,
1577 #[serde(default = "default_fraud_rate")]
1579 pub fraud_rate: f64,
1580 #[serde(default)]
1582 pub fraud_type_distribution: FraudTypeDistribution,
1583 #[serde(default)]
1585 pub clustering_enabled: bool,
1586 #[serde(default = "default_clustering_factor")]
1588 pub clustering_factor: f64,
1589 #[serde(default = "default_approval_thresholds")]
1591 pub approval_thresholds: Vec<f64>,
1592}
1593
1594fn default_approval_thresholds() -> Vec<f64> {
1595 vec![1000.0, 5000.0, 10000.0, 25000.0, 50000.0, 100000.0]
1596}
1597
1598fn default_fraud_rate() -> f64 {
1599 0.005
1600}
1601fn default_clustering_factor() -> f64 {
1602 3.0
1603}
1604
1605impl Default for FraudConfig {
1606 fn default() -> Self {
1607 Self {
1608 enabled: false,
1609 fraud_rate: default_fraud_rate(),
1610 fraud_type_distribution: FraudTypeDistribution::default(),
1611 clustering_enabled: false,
1612 clustering_factor: default_clustering_factor(),
1613 approval_thresholds: default_approval_thresholds(),
1614 }
1615 }
1616}
1617
1618#[derive(Debug, Clone, Serialize, Deserialize)]
1620pub struct FraudTypeDistribution {
1621 pub suspense_account_abuse: f64,
1622 pub fictitious_transaction: f64,
1623 pub revenue_manipulation: f64,
1624 pub expense_capitalization: f64,
1625 pub split_transaction: f64,
1626 pub timing_anomaly: f64,
1627 pub unauthorized_access: f64,
1628 pub duplicate_payment: f64,
1629}
1630
1631impl Default for FraudTypeDistribution {
1632 fn default() -> Self {
1633 Self {
1634 suspense_account_abuse: 0.25,
1635 fictitious_transaction: 0.15,
1636 revenue_manipulation: 0.10,
1637 expense_capitalization: 0.10,
1638 split_transaction: 0.15,
1639 timing_anomaly: 0.10,
1640 unauthorized_access: 0.10,
1641 duplicate_payment: 0.05,
1642 }
1643 }
1644}
1645
1646#[derive(Debug, Clone, Serialize, Deserialize)]
1648pub struct InternalControlsConfig {
1649 #[serde(default)]
1651 pub enabled: bool,
1652 #[serde(default = "default_exception_rate")]
1654 pub exception_rate: f64,
1655 #[serde(default = "default_sod_violation_rate")]
1657 pub sod_violation_rate: f64,
1658 #[serde(default = "default_true")]
1660 pub export_control_master_data: bool,
1661 #[serde(default = "default_sox_materiality_threshold")]
1663 pub sox_materiality_threshold: f64,
1664 #[serde(default = "default_true")]
1666 pub coso_enabled: bool,
1667 #[serde(default)]
1669 pub include_entity_level_controls: bool,
1670 #[serde(default = "default_target_maturity_level")]
1673 pub target_maturity_level: String,
1674}
1675
1676fn default_exception_rate() -> f64 {
1677 0.02
1678}
1679
1680fn default_sod_violation_rate() -> f64 {
1681 0.01
1682}
1683
1684fn default_sox_materiality_threshold() -> f64 {
1685 10000.0
1686}
1687
1688fn default_target_maturity_level() -> String {
1689 "mixed".to_string()
1690}
1691
1692impl Default for InternalControlsConfig {
1693 fn default() -> Self {
1694 Self {
1695 enabled: false,
1696 exception_rate: default_exception_rate(),
1697 sod_violation_rate: default_sod_violation_rate(),
1698 export_control_master_data: true,
1699 sox_materiality_threshold: default_sox_materiality_threshold(),
1700 coso_enabled: true,
1701 include_entity_level_controls: false,
1702 target_maturity_level: default_target_maturity_level(),
1703 }
1704 }
1705}
1706
1707#[derive(Debug, Clone, Serialize, Deserialize)]
1709pub struct BusinessProcessConfig {
1710 #[serde(default = "default_o2c")]
1712 pub o2c_weight: f64,
1713 #[serde(default = "default_p2p")]
1715 pub p2p_weight: f64,
1716 #[serde(default = "default_r2r")]
1718 pub r2r_weight: f64,
1719 #[serde(default = "default_h2r")]
1721 pub h2r_weight: f64,
1722 #[serde(default = "default_a2r")]
1724 pub a2r_weight: f64,
1725}
1726
1727fn default_o2c() -> f64 {
1728 0.35
1729}
1730fn default_p2p() -> f64 {
1731 0.30
1732}
1733fn default_r2r() -> f64 {
1734 0.20
1735}
1736fn default_h2r() -> f64 {
1737 0.10
1738}
1739fn default_a2r() -> f64 {
1740 0.05
1741}
1742
1743impl Default for BusinessProcessConfig {
1744 fn default() -> Self {
1745 Self {
1746 o2c_weight: default_o2c(),
1747 p2p_weight: default_p2p(),
1748 r2r_weight: default_r2r(),
1749 h2r_weight: default_h2r(),
1750 a2r_weight: default_a2r(),
1751 }
1752 }
1753}
1754
1755#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1757pub struct UserPersonaConfig {
1758 #[serde(default)]
1760 pub persona_distribution: PersonaDistribution,
1761 #[serde(default)]
1763 pub users_per_persona: UsersPerPersona,
1764}
1765
1766#[derive(Debug, Clone, Serialize, Deserialize)]
1768pub struct PersonaDistribution {
1769 pub junior_accountant: f64,
1770 pub senior_accountant: f64,
1771 pub controller: f64,
1772 pub manager: f64,
1773 pub automated_system: f64,
1774}
1775
1776impl Default for PersonaDistribution {
1777 fn default() -> Self {
1778 Self {
1779 junior_accountant: 0.15,
1780 senior_accountant: 0.15,
1781 controller: 0.05,
1782 manager: 0.05,
1783 automated_system: 0.60,
1784 }
1785 }
1786}
1787
1788#[derive(Debug, Clone, Serialize, Deserialize)]
1790pub struct UsersPerPersona {
1791 pub junior_accountant: usize,
1792 pub senior_accountant: usize,
1793 pub controller: usize,
1794 pub manager: usize,
1795 pub automated_system: usize,
1796}
1797
1798impl Default for UsersPerPersona {
1799 fn default() -> Self {
1800 Self {
1801 junior_accountant: 10,
1802 senior_accountant: 5,
1803 controller: 2,
1804 manager: 3,
1805 automated_system: 20,
1806 }
1807 }
1808}
1809
1810#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1812pub struct TemplateConfig {
1813 #[serde(default)]
1815 pub names: NameTemplateConfig,
1816 #[serde(default)]
1818 pub descriptions: DescriptionTemplateConfig,
1819 #[serde(default)]
1821 pub references: ReferenceTemplateConfig,
1822}
1823
1824#[derive(Debug, Clone, Serialize, Deserialize)]
1826pub struct NameTemplateConfig {
1827 #[serde(default)]
1829 pub culture_distribution: CultureDistribution,
1830 #[serde(default = "default_email_domain")]
1832 pub email_domain: String,
1833 #[serde(default = "default_true")]
1835 pub generate_realistic_names: bool,
1836}
1837
1838fn default_email_domain() -> String {
1839 "company.com".to_string()
1840}
1841
1842impl Default for NameTemplateConfig {
1843 fn default() -> Self {
1844 Self {
1845 culture_distribution: CultureDistribution::default(),
1846 email_domain: default_email_domain(),
1847 generate_realistic_names: true,
1848 }
1849 }
1850}
1851
1852#[derive(Debug, Clone, Serialize, Deserialize)]
1854pub struct CultureDistribution {
1855 pub western_us: f64,
1856 pub hispanic: f64,
1857 pub german: f64,
1858 pub french: f64,
1859 pub chinese: f64,
1860 pub japanese: f64,
1861 pub indian: f64,
1862}
1863
1864impl Default for CultureDistribution {
1865 fn default() -> Self {
1866 Self {
1867 western_us: 0.40,
1868 hispanic: 0.20,
1869 german: 0.10,
1870 french: 0.05,
1871 chinese: 0.10,
1872 japanese: 0.05,
1873 indian: 0.10,
1874 }
1875 }
1876}
1877
1878#[derive(Debug, Clone, Serialize, Deserialize)]
1880pub struct DescriptionTemplateConfig {
1881 #[serde(default = "default_true")]
1883 pub generate_header_text: bool,
1884 #[serde(default = "default_true")]
1886 pub generate_line_text: bool,
1887}
1888
1889impl Default for DescriptionTemplateConfig {
1890 fn default() -> Self {
1891 Self {
1892 generate_header_text: true,
1893 generate_line_text: true,
1894 }
1895 }
1896}
1897
1898#[derive(Debug, Clone, Serialize, Deserialize)]
1900pub struct ReferenceTemplateConfig {
1901 #[serde(default = "default_true")]
1903 pub generate_references: bool,
1904 #[serde(default = "default_invoice_prefix")]
1906 pub invoice_prefix: String,
1907 #[serde(default = "default_po_prefix")]
1909 pub po_prefix: String,
1910 #[serde(default = "default_so_prefix")]
1912 pub so_prefix: String,
1913}
1914
1915fn default_invoice_prefix() -> String {
1916 "INV".to_string()
1917}
1918fn default_po_prefix() -> String {
1919 "PO".to_string()
1920}
1921fn default_so_prefix() -> String {
1922 "SO".to_string()
1923}
1924
1925impl Default for ReferenceTemplateConfig {
1926 fn default() -> Self {
1927 Self {
1928 generate_references: true,
1929 invoice_prefix: default_invoice_prefix(),
1930 po_prefix: default_po_prefix(),
1931 so_prefix: default_so_prefix(),
1932 }
1933 }
1934}
1935
1936#[derive(Debug, Clone, Serialize, Deserialize)]
1938pub struct ApprovalConfig {
1939 #[serde(default)]
1941 pub enabled: bool,
1942 #[serde(default = "default_auto_approve_threshold")]
1944 pub auto_approve_threshold: f64,
1945 #[serde(default = "default_rejection_rate")]
1947 pub rejection_rate: f64,
1948 #[serde(default = "default_revision_rate")]
1950 pub revision_rate: f64,
1951 #[serde(default = "default_approval_delay_hours")]
1953 pub average_approval_delay_hours: f64,
1954 #[serde(default)]
1956 pub thresholds: Vec<ApprovalThresholdConfig>,
1957}
1958
1959fn default_auto_approve_threshold() -> f64 {
1960 1000.0
1961}
1962fn default_rejection_rate() -> f64 {
1963 0.02
1964}
1965fn default_revision_rate() -> f64 {
1966 0.05
1967}
1968fn default_approval_delay_hours() -> f64 {
1969 4.0
1970}
1971
1972impl Default for ApprovalConfig {
1973 fn default() -> Self {
1974 Self {
1975 enabled: false,
1976 auto_approve_threshold: default_auto_approve_threshold(),
1977 rejection_rate: default_rejection_rate(),
1978 revision_rate: default_revision_rate(),
1979 average_approval_delay_hours: default_approval_delay_hours(),
1980 thresholds: vec![
1981 ApprovalThresholdConfig {
1982 amount: 1000.0,
1983 level: 1,
1984 roles: vec!["senior_accountant".to_string()],
1985 },
1986 ApprovalThresholdConfig {
1987 amount: 10000.0,
1988 level: 2,
1989 roles: vec!["senior_accountant".to_string(), "controller".to_string()],
1990 },
1991 ApprovalThresholdConfig {
1992 amount: 100000.0,
1993 level: 3,
1994 roles: vec![
1995 "senior_accountant".to_string(),
1996 "controller".to_string(),
1997 "manager".to_string(),
1998 ],
1999 },
2000 ApprovalThresholdConfig {
2001 amount: 500000.0,
2002 level: 4,
2003 roles: vec![
2004 "senior_accountant".to_string(),
2005 "controller".to_string(),
2006 "manager".to_string(),
2007 "executive".to_string(),
2008 ],
2009 },
2010 ],
2011 }
2012 }
2013}
2014
2015#[derive(Debug, Clone, Serialize, Deserialize)]
2017pub struct ApprovalThresholdConfig {
2018 pub amount: f64,
2020 pub level: u8,
2022 pub roles: Vec<String>,
2024}
2025
2026#[derive(Debug, Clone, Serialize, Deserialize)]
2028pub struct DepartmentConfig {
2029 #[serde(default)]
2031 pub enabled: bool,
2032 #[serde(default = "default_headcount_multiplier")]
2034 pub headcount_multiplier: f64,
2035 #[serde(default)]
2037 pub custom_departments: Vec<CustomDepartmentConfig>,
2038}
2039
2040fn default_headcount_multiplier() -> f64 {
2041 1.0
2042}
2043
2044impl Default for DepartmentConfig {
2045 fn default() -> Self {
2046 Self {
2047 enabled: false,
2048 headcount_multiplier: default_headcount_multiplier(),
2049 custom_departments: Vec::new(),
2050 }
2051 }
2052}
2053
2054#[derive(Debug, Clone, Serialize, Deserialize)]
2056pub struct CustomDepartmentConfig {
2057 pub code: String,
2059 pub name: String,
2061 #[serde(default)]
2063 pub cost_center: Option<String>,
2064 #[serde(default)]
2066 pub primary_processes: Vec<String>,
2067 #[serde(default)]
2069 pub parent_code: Option<String>,
2070}
2071
2072#[derive(Debug, Clone, Default, Serialize, Deserialize)]
2078pub struct MasterDataConfig {
2079 #[serde(default)]
2081 pub vendors: VendorMasterConfig,
2082 #[serde(default)]
2084 pub customers: CustomerMasterConfig,
2085 #[serde(default)]
2087 pub materials: MaterialMasterConfig,
2088 #[serde(default)]
2090 pub fixed_assets: FixedAssetMasterConfig,
2091 #[serde(default)]
2093 pub employees: EmployeeMasterConfig,
2094 #[serde(default)]
2096 pub cost_centers: CostCenterMasterConfig,
2097}
2098
2099#[derive(Debug, Clone, Serialize, Deserialize)]
2101pub struct VendorMasterConfig {
2102 #[serde(default = "default_vendor_count")]
2104 pub count: usize,
2105 #[serde(default = "default_intercompany_percent")]
2107 pub intercompany_percent: f64,
2108 #[serde(default)]
2110 pub payment_terms_distribution: PaymentTermsDistribution,
2111 #[serde(default)]
2113 pub behavior_distribution: VendorBehaviorDistribution,
2114 #[serde(default = "default_true")]
2116 pub generate_bank_accounts: bool,
2117 #[serde(default = "default_true")]
2119 pub generate_tax_ids: bool,
2120}
2121
2122fn default_vendor_count() -> usize {
2123 500
2124}
2125
2126fn default_intercompany_percent() -> f64 {
2127 0.05
2128}
2129
2130impl Default for VendorMasterConfig {
2131 fn default() -> Self {
2132 Self {
2133 count: default_vendor_count(),
2134 intercompany_percent: default_intercompany_percent(),
2135 payment_terms_distribution: PaymentTermsDistribution::default(),
2136 behavior_distribution: VendorBehaviorDistribution::default(),
2137 generate_bank_accounts: true,
2138 generate_tax_ids: true,
2139 }
2140 }
2141}
2142
2143#[derive(Debug, Clone, Serialize, Deserialize)]
2145pub struct PaymentTermsDistribution {
2146 pub net_30: f64,
2148 pub net_60: f64,
2150 pub net_90: f64,
2152 pub two_ten_net_30: f64,
2154 pub due_on_receipt: f64,
2156 pub end_of_month: f64,
2158}
2159
2160impl Default for PaymentTermsDistribution {
2161 fn default() -> Self {
2162 Self {
2163 net_30: 0.40,
2164 net_60: 0.20,
2165 net_90: 0.10,
2166 two_ten_net_30: 0.15,
2167 due_on_receipt: 0.05,
2168 end_of_month: 0.10,
2169 }
2170 }
2171}
2172
2173#[derive(Debug, Clone, Serialize, Deserialize)]
2175pub struct VendorBehaviorDistribution {
2176 pub reliable: f64,
2178 pub sometimes_late: f64,
2180 pub inconsistent_quality: f64,
2182 pub premium: f64,
2184 pub budget: f64,
2186}
2187
2188impl Default for VendorBehaviorDistribution {
2189 fn default() -> Self {
2190 Self {
2191 reliable: 0.50,
2192 sometimes_late: 0.20,
2193 inconsistent_quality: 0.10,
2194 premium: 0.10,
2195 budget: 0.10,
2196 }
2197 }
2198}
2199
2200#[derive(Debug, Clone, Serialize, Deserialize)]
2202pub struct CustomerMasterConfig {
2203 #[serde(default = "default_customer_count")]
2205 pub count: usize,
2206 #[serde(default = "default_intercompany_percent")]
2208 pub intercompany_percent: f64,
2209 #[serde(default)]
2211 pub credit_rating_distribution: CreditRatingDistribution,
2212 #[serde(default)]
2214 pub payment_behavior_distribution: PaymentBehaviorDistribution,
2215 #[serde(default = "default_true")]
2217 pub generate_credit_limits: bool,
2218}
2219
2220fn default_customer_count() -> usize {
2221 2000
2222}
2223
2224impl Default for CustomerMasterConfig {
2225 fn default() -> Self {
2226 Self {
2227 count: default_customer_count(),
2228 intercompany_percent: default_intercompany_percent(),
2229 credit_rating_distribution: CreditRatingDistribution::default(),
2230 payment_behavior_distribution: PaymentBehaviorDistribution::default(),
2231 generate_credit_limits: true,
2232 }
2233 }
2234}
2235
2236#[derive(Debug, Clone, Serialize, Deserialize)]
2238pub struct CreditRatingDistribution {
2239 pub aaa: f64,
2241 pub aa: f64,
2243 pub a: f64,
2245 pub bbb: f64,
2247 pub bb: f64,
2249 pub b: f64,
2251 pub below_b: f64,
2253}
2254
2255impl Default for CreditRatingDistribution {
2256 fn default() -> Self {
2257 Self {
2258 aaa: 0.05,
2259 aa: 0.10,
2260 a: 0.20,
2261 bbb: 0.30,
2262 bb: 0.20,
2263 b: 0.10,
2264 below_b: 0.05,
2265 }
2266 }
2267}
2268
2269#[derive(Debug, Clone, Serialize, Deserialize)]
2271pub struct PaymentBehaviorDistribution {
2272 pub early_payer: f64,
2274 pub on_time: f64,
2276 pub occasional_late: f64,
2278 pub frequent_late: f64,
2280 pub discount_taker: f64,
2282}
2283
2284impl Default for PaymentBehaviorDistribution {
2285 fn default() -> Self {
2286 Self {
2287 early_payer: 0.10,
2288 on_time: 0.50,
2289 occasional_late: 0.25,
2290 frequent_late: 0.10,
2291 discount_taker: 0.05,
2292 }
2293 }
2294}
2295
2296#[derive(Debug, Clone, Serialize, Deserialize)]
2298pub struct MaterialMasterConfig {
2299 #[serde(default = "default_material_count")]
2301 pub count: usize,
2302 #[serde(default)]
2304 pub type_distribution: MaterialTypeDistribution,
2305 #[serde(default)]
2307 pub valuation_distribution: ValuationMethodDistribution,
2308 #[serde(default = "default_bom_percent")]
2310 pub bom_percent: f64,
2311 #[serde(default = "default_max_bom_depth")]
2313 pub max_bom_depth: u8,
2314}
2315
2316fn default_material_count() -> usize {
2317 5000
2318}
2319
2320fn default_bom_percent() -> f64 {
2321 0.20
2322}
2323
2324fn default_max_bom_depth() -> u8 {
2325 3
2326}
2327
2328impl Default for MaterialMasterConfig {
2329 fn default() -> Self {
2330 Self {
2331 count: default_material_count(),
2332 type_distribution: MaterialTypeDistribution::default(),
2333 valuation_distribution: ValuationMethodDistribution::default(),
2334 bom_percent: default_bom_percent(),
2335 max_bom_depth: default_max_bom_depth(),
2336 }
2337 }
2338}
2339
2340#[derive(Debug, Clone, Serialize, Deserialize)]
2342pub struct MaterialTypeDistribution {
2343 pub raw_material: f64,
2345 pub semi_finished: f64,
2347 pub finished_good: f64,
2349 pub trading_good: f64,
2351 pub operating_supply: f64,
2353 pub service: f64,
2355}
2356
2357impl Default for MaterialTypeDistribution {
2358 fn default() -> Self {
2359 Self {
2360 raw_material: 0.30,
2361 semi_finished: 0.15,
2362 finished_good: 0.25,
2363 trading_good: 0.15,
2364 operating_supply: 0.10,
2365 service: 0.05,
2366 }
2367 }
2368}
2369
2370#[derive(Debug, Clone, Serialize, Deserialize)]
2372pub struct ValuationMethodDistribution {
2373 pub standard_cost: f64,
2375 pub moving_average: f64,
2377 pub fifo: f64,
2379 pub lifo: f64,
2381}
2382
2383impl Default for ValuationMethodDistribution {
2384 fn default() -> Self {
2385 Self {
2386 standard_cost: 0.50,
2387 moving_average: 0.30,
2388 fifo: 0.15,
2389 lifo: 0.05,
2390 }
2391 }
2392}
2393
2394#[derive(Debug, Clone, Serialize, Deserialize)]
2396pub struct FixedAssetMasterConfig {
2397 #[serde(default = "default_asset_count")]
2399 pub count: usize,
2400 #[serde(default)]
2402 pub class_distribution: AssetClassDistribution,
2403 #[serde(default)]
2405 pub depreciation_distribution: DepreciationMethodDistribution,
2406 #[serde(default = "default_fully_depreciated_percent")]
2408 pub fully_depreciated_percent: f64,
2409 #[serde(default = "default_true")]
2411 pub generate_acquisition_history: bool,
2412}
2413
2414fn default_asset_count() -> usize {
2415 800
2416}
2417
2418fn default_fully_depreciated_percent() -> f64 {
2419 0.15
2420}
2421
2422impl Default for FixedAssetMasterConfig {
2423 fn default() -> Self {
2424 Self {
2425 count: default_asset_count(),
2426 class_distribution: AssetClassDistribution::default(),
2427 depreciation_distribution: DepreciationMethodDistribution::default(),
2428 fully_depreciated_percent: default_fully_depreciated_percent(),
2429 generate_acquisition_history: true,
2430 }
2431 }
2432}
2433
2434#[derive(Debug, Clone, Serialize, Deserialize)]
2436pub struct AssetClassDistribution {
2437 pub buildings: f64,
2439 pub machinery: f64,
2441 pub vehicles: f64,
2443 pub it_equipment: f64,
2445 pub furniture: f64,
2447 pub land: f64,
2449 pub leasehold: f64,
2451}
2452
2453impl Default for AssetClassDistribution {
2454 fn default() -> Self {
2455 Self {
2456 buildings: 0.15,
2457 machinery: 0.30,
2458 vehicles: 0.15,
2459 it_equipment: 0.20,
2460 furniture: 0.10,
2461 land: 0.05,
2462 leasehold: 0.05,
2463 }
2464 }
2465}
2466
2467#[derive(Debug, Clone, Serialize, Deserialize)]
2469pub struct DepreciationMethodDistribution {
2470 pub straight_line: f64,
2472 pub declining_balance: f64,
2474 pub double_declining: f64,
2476 pub sum_of_years: f64,
2478 pub units_of_production: f64,
2480}
2481
2482impl Default for DepreciationMethodDistribution {
2483 fn default() -> Self {
2484 Self {
2485 straight_line: 0.60,
2486 declining_balance: 0.20,
2487 double_declining: 0.10,
2488 sum_of_years: 0.05,
2489 units_of_production: 0.05,
2490 }
2491 }
2492}
2493
2494#[derive(Debug, Clone, Serialize, Deserialize)]
2496pub struct EmployeeMasterConfig {
2497 #[serde(default = "default_employee_count")]
2499 pub count: usize,
2500 #[serde(default = "default_true")]
2502 pub generate_hierarchy: bool,
2503 #[serde(default = "default_hierarchy_depth")]
2505 pub max_hierarchy_depth: u8,
2506 #[serde(default = "default_span_of_control")]
2508 pub average_span_of_control: f64,
2509 #[serde(default)]
2511 pub approval_limits: ApprovalLimitDistribution,
2512 #[serde(default)]
2514 pub department_distribution: EmployeeDepartmentDistribution,
2515}
2516
2517fn default_employee_count() -> usize {
2518 1500
2519}
2520
2521fn default_hierarchy_depth() -> u8 {
2522 6
2523}
2524
2525fn default_span_of_control() -> f64 {
2526 5.0
2527}
2528
2529impl Default for EmployeeMasterConfig {
2530 fn default() -> Self {
2531 Self {
2532 count: default_employee_count(),
2533 generate_hierarchy: true,
2534 max_hierarchy_depth: default_hierarchy_depth(),
2535 average_span_of_control: default_span_of_control(),
2536 approval_limits: ApprovalLimitDistribution::default(),
2537 department_distribution: EmployeeDepartmentDistribution::default(),
2538 }
2539 }
2540}
2541
2542#[derive(Debug, Clone, Serialize, Deserialize)]
2544pub struct ApprovalLimitDistribution {
2545 #[serde(default = "default_staff_limit")]
2547 pub staff: f64,
2548 #[serde(default = "default_senior_limit")]
2550 pub senior: f64,
2551 #[serde(default = "default_manager_limit")]
2553 pub manager: f64,
2554 #[serde(default = "default_director_limit")]
2556 pub director: f64,
2557 #[serde(default = "default_vp_limit")]
2559 pub vp: f64,
2560 #[serde(default = "default_executive_limit")]
2562 pub executive: f64,
2563}
2564
2565fn default_staff_limit() -> f64 {
2566 1000.0
2567}
2568fn default_senior_limit() -> f64 {
2569 5000.0
2570}
2571fn default_manager_limit() -> f64 {
2572 25000.0
2573}
2574fn default_director_limit() -> f64 {
2575 100000.0
2576}
2577fn default_vp_limit() -> f64 {
2578 500000.0
2579}
2580fn default_executive_limit() -> f64 {
2581 f64::INFINITY
2582}
2583
2584impl Default for ApprovalLimitDistribution {
2585 fn default() -> Self {
2586 Self {
2587 staff: default_staff_limit(),
2588 senior: default_senior_limit(),
2589 manager: default_manager_limit(),
2590 director: default_director_limit(),
2591 vp: default_vp_limit(),
2592 executive: default_executive_limit(),
2593 }
2594 }
2595}
2596
2597#[derive(Debug, Clone, Serialize, Deserialize)]
2599pub struct EmployeeDepartmentDistribution {
2600 pub finance: f64,
2602 pub procurement: f64,
2604 pub sales: f64,
2606 pub warehouse: f64,
2608 pub it: f64,
2610 pub hr: f64,
2612 pub operations: f64,
2614 pub executive: f64,
2616}
2617
2618impl Default for EmployeeDepartmentDistribution {
2619 fn default() -> Self {
2620 Self {
2621 finance: 0.12,
2622 procurement: 0.10,
2623 sales: 0.25,
2624 warehouse: 0.15,
2625 it: 0.10,
2626 hr: 0.05,
2627 operations: 0.20,
2628 executive: 0.03,
2629 }
2630 }
2631}
2632
2633#[derive(Debug, Clone, Serialize, Deserialize)]
2635pub struct CostCenterMasterConfig {
2636 #[serde(default = "default_cost_center_count")]
2638 pub count: usize,
2639 #[serde(default = "default_true")]
2641 pub generate_hierarchy: bool,
2642 #[serde(default = "default_cc_hierarchy_depth")]
2644 pub max_hierarchy_depth: u8,
2645}
2646
2647fn default_cost_center_count() -> usize {
2648 50
2649}
2650
2651fn default_cc_hierarchy_depth() -> u8 {
2652 3
2653}
2654
2655impl Default for CostCenterMasterConfig {
2656 fn default() -> Self {
2657 Self {
2658 count: default_cost_center_count(),
2659 generate_hierarchy: true,
2660 max_hierarchy_depth: default_cc_hierarchy_depth(),
2661 }
2662 }
2663}
2664
2665#[derive(Debug, Clone, Serialize, Deserialize)]
2671pub struct DocumentFlowConfig {
2672 #[serde(default)]
2674 pub p2p: P2PFlowConfig,
2675 #[serde(default)]
2677 pub o2c: O2CFlowConfig,
2678 #[serde(default = "default_true")]
2680 pub generate_document_references: bool,
2681 #[serde(default)]
2683 pub export_flow_graph: bool,
2684}
2685
2686impl Default for DocumentFlowConfig {
2687 fn default() -> Self {
2688 Self {
2689 p2p: P2PFlowConfig::default(),
2690 o2c: O2CFlowConfig::default(),
2691 generate_document_references: true,
2692 export_flow_graph: false,
2693 }
2694 }
2695}
2696
2697#[derive(Debug, Clone, Serialize, Deserialize)]
2699pub struct P2PFlowConfig {
2700 #[serde(default = "default_true")]
2702 pub enabled: bool,
2703 #[serde(default = "default_three_way_match_rate")]
2705 pub three_way_match_rate: f64,
2706 #[serde(default = "default_partial_delivery_rate")]
2708 pub partial_delivery_rate: f64,
2709 #[serde(default = "default_price_variance_rate")]
2711 pub price_variance_rate: f64,
2712 #[serde(default = "default_max_price_variance")]
2714 pub max_price_variance_percent: f64,
2715 #[serde(default = "default_quantity_variance_rate")]
2717 pub quantity_variance_rate: f64,
2718 #[serde(default = "default_po_to_gr_days")]
2720 pub average_po_to_gr_days: u32,
2721 #[serde(default = "default_gr_to_invoice_days")]
2723 pub average_gr_to_invoice_days: u32,
2724 #[serde(default = "default_invoice_to_payment_days")]
2726 pub average_invoice_to_payment_days: u32,
2727 #[serde(default)]
2729 pub line_count_distribution: DocumentLineCountDistribution,
2730 #[serde(default)]
2732 pub payment_behavior: P2PPaymentBehaviorConfig,
2733 #[serde(default)]
2735 pub over_delivery_rate: Option<f64>,
2736 #[serde(default)]
2738 pub early_payment_discount_rate: Option<f64>,
2739}
2740
2741fn default_three_way_match_rate() -> f64 {
2742 0.95
2743}
2744
2745fn default_partial_delivery_rate() -> f64 {
2746 0.15
2747}
2748
2749fn default_price_variance_rate() -> f64 {
2750 0.08
2751}
2752
2753fn default_max_price_variance() -> f64 {
2754 0.05
2755}
2756
2757fn default_quantity_variance_rate() -> f64 {
2758 0.05
2759}
2760
2761fn default_po_to_gr_days() -> u32 {
2762 14
2763}
2764
2765fn default_gr_to_invoice_days() -> u32 {
2766 5
2767}
2768
2769fn default_invoice_to_payment_days() -> u32 {
2770 30
2771}
2772
2773impl Default for P2PFlowConfig {
2774 fn default() -> Self {
2775 Self {
2776 enabled: true,
2777 three_way_match_rate: default_three_way_match_rate(),
2778 partial_delivery_rate: default_partial_delivery_rate(),
2779 price_variance_rate: default_price_variance_rate(),
2780 max_price_variance_percent: default_max_price_variance(),
2781 quantity_variance_rate: default_quantity_variance_rate(),
2782 average_po_to_gr_days: default_po_to_gr_days(),
2783 average_gr_to_invoice_days: default_gr_to_invoice_days(),
2784 average_invoice_to_payment_days: default_invoice_to_payment_days(),
2785 line_count_distribution: DocumentLineCountDistribution::default(),
2786 payment_behavior: P2PPaymentBehaviorConfig::default(),
2787 over_delivery_rate: None,
2788 early_payment_discount_rate: None,
2789 }
2790 }
2791}
2792
2793#[derive(Debug, Clone, Serialize, Deserialize)]
2799pub struct P2PPaymentBehaviorConfig {
2800 #[serde(default = "default_p2p_late_payment_rate")]
2802 pub late_payment_rate: f64,
2803 #[serde(default)]
2805 pub late_payment_days_distribution: LatePaymentDaysDistribution,
2806 #[serde(default = "default_p2p_partial_payment_rate")]
2808 pub partial_payment_rate: f64,
2809 #[serde(default = "default_p2p_payment_correction_rate")]
2811 pub payment_correction_rate: f64,
2812 #[serde(default = "default_p2p_avg_days_until_remainder")]
2814 pub avg_days_until_remainder: u32,
2815}
2816
2817fn default_p2p_late_payment_rate() -> f64 {
2818 0.15
2819}
2820
2821fn default_p2p_partial_payment_rate() -> f64 {
2822 0.05
2823}
2824
2825fn default_p2p_payment_correction_rate() -> f64 {
2826 0.02
2827}
2828
2829fn default_p2p_avg_days_until_remainder() -> u32 {
2830 30
2831}
2832
2833impl Default for P2PPaymentBehaviorConfig {
2834 fn default() -> Self {
2835 Self {
2836 late_payment_rate: default_p2p_late_payment_rate(),
2837 late_payment_days_distribution: LatePaymentDaysDistribution::default(),
2838 partial_payment_rate: default_p2p_partial_payment_rate(),
2839 payment_correction_rate: default_p2p_payment_correction_rate(),
2840 avg_days_until_remainder: default_p2p_avg_days_until_remainder(),
2841 }
2842 }
2843}
2844
2845#[derive(Debug, Clone, Serialize, Deserialize)]
2847pub struct LatePaymentDaysDistribution {
2848 #[serde(default = "default_slightly_late")]
2850 pub slightly_late_1_to_7: f64,
2851 #[serde(default = "default_late_8_14")]
2853 pub late_8_to_14: f64,
2854 #[serde(default = "default_very_late")]
2856 pub very_late_15_to_30: f64,
2857 #[serde(default = "default_severely_late")]
2859 pub severely_late_31_to_60: f64,
2860 #[serde(default = "default_extremely_late")]
2862 pub extremely_late_over_60: f64,
2863}
2864
2865fn default_slightly_late() -> f64 {
2866 0.50
2867}
2868
2869fn default_late_8_14() -> f64 {
2870 0.25
2871}
2872
2873fn default_very_late() -> f64 {
2874 0.15
2875}
2876
2877fn default_severely_late() -> f64 {
2878 0.07
2879}
2880
2881fn default_extremely_late() -> f64 {
2882 0.03
2883}
2884
2885impl Default for LatePaymentDaysDistribution {
2886 fn default() -> Self {
2887 Self {
2888 slightly_late_1_to_7: default_slightly_late(),
2889 late_8_to_14: default_late_8_14(),
2890 very_late_15_to_30: default_very_late(),
2891 severely_late_31_to_60: default_severely_late(),
2892 extremely_late_over_60: default_extremely_late(),
2893 }
2894 }
2895}
2896
2897#[derive(Debug, Clone, Serialize, Deserialize)]
2899pub struct O2CFlowConfig {
2900 #[serde(default = "default_true")]
2902 pub enabled: bool,
2903 #[serde(default = "default_credit_check_failure_rate")]
2905 pub credit_check_failure_rate: f64,
2906 #[serde(default = "default_partial_shipment_rate")]
2908 pub partial_shipment_rate: f64,
2909 #[serde(default = "default_return_rate")]
2911 pub return_rate: f64,
2912 #[serde(default = "default_bad_debt_rate")]
2914 pub bad_debt_rate: f64,
2915 #[serde(default = "default_so_to_delivery_days")]
2917 pub average_so_to_delivery_days: u32,
2918 #[serde(default = "default_delivery_to_invoice_days")]
2920 pub average_delivery_to_invoice_days: u32,
2921 #[serde(default = "default_invoice_to_receipt_days")]
2923 pub average_invoice_to_receipt_days: u32,
2924 #[serde(default)]
2926 pub line_count_distribution: DocumentLineCountDistribution,
2927 #[serde(default)]
2929 pub cash_discount: CashDiscountConfig,
2930 #[serde(default)]
2932 pub payment_behavior: O2CPaymentBehaviorConfig,
2933 #[serde(default)]
2935 pub late_payment_rate: Option<f64>,
2936}
2937
2938fn default_credit_check_failure_rate() -> f64 {
2939 0.02
2940}
2941
2942fn default_partial_shipment_rate() -> f64 {
2943 0.10
2944}
2945
2946fn default_return_rate() -> f64 {
2947 0.03
2948}
2949
2950fn default_bad_debt_rate() -> f64 {
2951 0.01
2952}
2953
2954fn default_so_to_delivery_days() -> u32 {
2955 7
2956}
2957
2958fn default_delivery_to_invoice_days() -> u32 {
2959 1
2960}
2961
2962fn default_invoice_to_receipt_days() -> u32 {
2963 45
2964}
2965
2966impl Default for O2CFlowConfig {
2967 fn default() -> Self {
2968 Self {
2969 enabled: true,
2970 credit_check_failure_rate: default_credit_check_failure_rate(),
2971 partial_shipment_rate: default_partial_shipment_rate(),
2972 return_rate: default_return_rate(),
2973 bad_debt_rate: default_bad_debt_rate(),
2974 average_so_to_delivery_days: default_so_to_delivery_days(),
2975 average_delivery_to_invoice_days: default_delivery_to_invoice_days(),
2976 average_invoice_to_receipt_days: default_invoice_to_receipt_days(),
2977 line_count_distribution: DocumentLineCountDistribution::default(),
2978 cash_discount: CashDiscountConfig::default(),
2979 payment_behavior: O2CPaymentBehaviorConfig::default(),
2980 late_payment_rate: None,
2981 }
2982 }
2983}
2984
2985#[derive(Debug, Clone, Serialize, Deserialize, Default)]
2991pub struct O2CPaymentBehaviorConfig {
2992 #[serde(default)]
2994 pub dunning: DunningConfig,
2995 #[serde(default)]
2997 pub partial_payments: PartialPaymentConfig,
2998 #[serde(default)]
3000 pub short_payments: ShortPaymentConfig,
3001 #[serde(default)]
3003 pub on_account_payments: OnAccountPaymentConfig,
3004 #[serde(default)]
3006 pub payment_corrections: PaymentCorrectionConfig,
3007}
3008
3009#[derive(Debug, Clone, Serialize, Deserialize)]
3011pub struct DunningConfig {
3012 #[serde(default)]
3014 pub enabled: bool,
3015 #[serde(default = "default_dunning_level_1_days")]
3017 pub level_1_days_overdue: u32,
3018 #[serde(default = "default_dunning_level_2_days")]
3020 pub level_2_days_overdue: u32,
3021 #[serde(default = "default_dunning_level_3_days")]
3023 pub level_3_days_overdue: u32,
3024 #[serde(default = "default_collection_days")]
3026 pub collection_days_overdue: u32,
3027 #[serde(default)]
3029 pub payment_after_dunning_rates: DunningPaymentRates,
3030 #[serde(default = "default_dunning_block_rate")]
3032 pub dunning_block_rate: f64,
3033 #[serde(default = "default_dunning_interest_rate")]
3035 pub interest_rate_per_year: f64,
3036 #[serde(default = "default_dunning_charge")]
3038 pub dunning_charge: f64,
3039}
3040
3041fn default_dunning_level_1_days() -> u32 {
3042 14
3043}
3044
3045fn default_dunning_level_2_days() -> u32 {
3046 28
3047}
3048
3049fn default_dunning_level_3_days() -> u32 {
3050 42
3051}
3052
3053fn default_collection_days() -> u32 {
3054 60
3055}
3056
3057fn default_dunning_block_rate() -> f64 {
3058 0.05
3059}
3060
3061fn default_dunning_interest_rate() -> f64 {
3062 0.09
3063}
3064
3065fn default_dunning_charge() -> f64 {
3066 25.0
3067}
3068
3069impl Default for DunningConfig {
3070 fn default() -> Self {
3071 Self {
3072 enabled: false,
3073 level_1_days_overdue: default_dunning_level_1_days(),
3074 level_2_days_overdue: default_dunning_level_2_days(),
3075 level_3_days_overdue: default_dunning_level_3_days(),
3076 collection_days_overdue: default_collection_days(),
3077 payment_after_dunning_rates: DunningPaymentRates::default(),
3078 dunning_block_rate: default_dunning_block_rate(),
3079 interest_rate_per_year: default_dunning_interest_rate(),
3080 dunning_charge: default_dunning_charge(),
3081 }
3082 }
3083}
3084
3085#[derive(Debug, Clone, Serialize, Deserialize)]
3087pub struct DunningPaymentRates {
3088 #[serde(default = "default_after_level_1")]
3090 pub after_level_1: f64,
3091 #[serde(default = "default_after_level_2")]
3093 pub after_level_2: f64,
3094 #[serde(default = "default_after_level_3")]
3096 pub after_level_3: f64,
3097 #[serde(default = "default_during_collection")]
3099 pub during_collection: f64,
3100 #[serde(default = "default_never_pay")]
3102 pub never_pay: f64,
3103}
3104
3105fn default_after_level_1() -> f64 {
3106 0.40
3107}
3108
3109fn default_after_level_2() -> f64 {
3110 0.30
3111}
3112
3113fn default_after_level_3() -> f64 {
3114 0.15
3115}
3116
3117fn default_during_collection() -> f64 {
3118 0.05
3119}
3120
3121fn default_never_pay() -> f64 {
3122 0.10
3123}
3124
3125impl Default for DunningPaymentRates {
3126 fn default() -> Self {
3127 Self {
3128 after_level_1: default_after_level_1(),
3129 after_level_2: default_after_level_2(),
3130 after_level_3: default_after_level_3(),
3131 during_collection: default_during_collection(),
3132 never_pay: default_never_pay(),
3133 }
3134 }
3135}
3136
3137#[derive(Debug, Clone, Serialize, Deserialize)]
3139pub struct PartialPaymentConfig {
3140 #[serde(default = "default_partial_payment_rate")]
3142 pub rate: f64,
3143 #[serde(default)]
3145 pub percentage_distribution: PartialPaymentPercentageDistribution,
3146 #[serde(default = "default_avg_days_until_remainder")]
3148 pub avg_days_until_remainder: u32,
3149}
3150
3151fn default_partial_payment_rate() -> f64 {
3152 0.08
3153}
3154
3155fn default_avg_days_until_remainder() -> u32 {
3156 30
3157}
3158
3159impl Default for PartialPaymentConfig {
3160 fn default() -> Self {
3161 Self {
3162 rate: default_partial_payment_rate(),
3163 percentage_distribution: PartialPaymentPercentageDistribution::default(),
3164 avg_days_until_remainder: default_avg_days_until_remainder(),
3165 }
3166 }
3167}
3168
3169#[derive(Debug, Clone, Serialize, Deserialize)]
3171pub struct PartialPaymentPercentageDistribution {
3172 #[serde(default = "default_partial_25")]
3174 pub pay_25_percent: f64,
3175 #[serde(default = "default_partial_50")]
3177 pub pay_50_percent: f64,
3178 #[serde(default = "default_partial_75")]
3180 pub pay_75_percent: f64,
3181 #[serde(default = "default_partial_random")]
3183 pub pay_random_percent: f64,
3184}
3185
3186fn default_partial_25() -> f64 {
3187 0.15
3188}
3189
3190fn default_partial_50() -> f64 {
3191 0.50
3192}
3193
3194fn default_partial_75() -> f64 {
3195 0.25
3196}
3197
3198fn default_partial_random() -> f64 {
3199 0.10
3200}
3201
3202impl Default for PartialPaymentPercentageDistribution {
3203 fn default() -> Self {
3204 Self {
3205 pay_25_percent: default_partial_25(),
3206 pay_50_percent: default_partial_50(),
3207 pay_75_percent: default_partial_75(),
3208 pay_random_percent: default_partial_random(),
3209 }
3210 }
3211}
3212
3213#[derive(Debug, Clone, Serialize, Deserialize)]
3215pub struct ShortPaymentConfig {
3216 #[serde(default = "default_short_payment_rate")]
3218 pub rate: f64,
3219 #[serde(default)]
3221 pub reason_distribution: ShortPaymentReasonDistribution,
3222 #[serde(default = "default_max_short_percent")]
3224 pub max_short_percent: f64,
3225}
3226
3227fn default_short_payment_rate() -> f64 {
3228 0.03
3229}
3230
3231fn default_max_short_percent() -> f64 {
3232 0.10
3233}
3234
3235impl Default for ShortPaymentConfig {
3236 fn default() -> Self {
3237 Self {
3238 rate: default_short_payment_rate(),
3239 reason_distribution: ShortPaymentReasonDistribution::default(),
3240 max_short_percent: default_max_short_percent(),
3241 }
3242 }
3243}
3244
3245#[derive(Debug, Clone, Serialize, Deserialize)]
3247pub struct ShortPaymentReasonDistribution {
3248 #[serde(default = "default_pricing_dispute")]
3250 pub pricing_dispute: f64,
3251 #[serde(default = "default_quality_issue")]
3253 pub quality_issue: f64,
3254 #[serde(default = "default_quantity_discrepancy")]
3256 pub quantity_discrepancy: f64,
3257 #[serde(default = "default_unauthorized_deduction")]
3259 pub unauthorized_deduction: f64,
3260 #[serde(default = "default_incorrect_discount")]
3262 pub incorrect_discount: f64,
3263}
3264
3265fn default_pricing_dispute() -> f64 {
3266 0.30
3267}
3268
3269fn default_quality_issue() -> f64 {
3270 0.20
3271}
3272
3273fn default_quantity_discrepancy() -> f64 {
3274 0.20
3275}
3276
3277fn default_unauthorized_deduction() -> f64 {
3278 0.15
3279}
3280
3281fn default_incorrect_discount() -> f64 {
3282 0.15
3283}
3284
3285impl Default for ShortPaymentReasonDistribution {
3286 fn default() -> Self {
3287 Self {
3288 pricing_dispute: default_pricing_dispute(),
3289 quality_issue: default_quality_issue(),
3290 quantity_discrepancy: default_quantity_discrepancy(),
3291 unauthorized_deduction: default_unauthorized_deduction(),
3292 incorrect_discount: default_incorrect_discount(),
3293 }
3294 }
3295}
3296
3297#[derive(Debug, Clone, Serialize, Deserialize)]
3299pub struct OnAccountPaymentConfig {
3300 #[serde(default = "default_on_account_rate")]
3302 pub rate: f64,
3303 #[serde(default = "default_avg_days_until_applied")]
3305 pub avg_days_until_applied: u32,
3306}
3307
3308fn default_on_account_rate() -> f64 {
3309 0.02
3310}
3311
3312fn default_avg_days_until_applied() -> u32 {
3313 14
3314}
3315
3316impl Default for OnAccountPaymentConfig {
3317 fn default() -> Self {
3318 Self {
3319 rate: default_on_account_rate(),
3320 avg_days_until_applied: default_avg_days_until_applied(),
3321 }
3322 }
3323}
3324
3325#[derive(Debug, Clone, Serialize, Deserialize)]
3327pub struct PaymentCorrectionConfig {
3328 #[serde(default = "default_payment_correction_rate")]
3330 pub rate: f64,
3331 #[serde(default)]
3333 pub type_distribution: PaymentCorrectionTypeDistribution,
3334}
3335
3336fn default_payment_correction_rate() -> f64 {
3337 0.02
3338}
3339
3340impl Default for PaymentCorrectionConfig {
3341 fn default() -> Self {
3342 Self {
3343 rate: default_payment_correction_rate(),
3344 type_distribution: PaymentCorrectionTypeDistribution::default(),
3345 }
3346 }
3347}
3348
3349#[derive(Debug, Clone, Serialize, Deserialize)]
3351pub struct PaymentCorrectionTypeDistribution {
3352 #[serde(default = "default_nsf_rate")]
3354 pub nsf: f64,
3355 #[serde(default = "default_chargeback_rate")]
3357 pub chargeback: f64,
3358 #[serde(default = "default_wrong_amount_rate")]
3360 pub wrong_amount: f64,
3361 #[serde(default = "default_wrong_customer_rate")]
3363 pub wrong_customer: f64,
3364 #[serde(default = "default_duplicate_payment_rate")]
3366 pub duplicate_payment: f64,
3367}
3368
3369fn default_nsf_rate() -> f64 {
3370 0.30
3371}
3372
3373fn default_chargeback_rate() -> f64 {
3374 0.20
3375}
3376
3377fn default_wrong_amount_rate() -> f64 {
3378 0.20
3379}
3380
3381fn default_wrong_customer_rate() -> f64 {
3382 0.15
3383}
3384
3385fn default_duplicate_payment_rate() -> f64 {
3386 0.15
3387}
3388
3389impl Default for PaymentCorrectionTypeDistribution {
3390 fn default() -> Self {
3391 Self {
3392 nsf: default_nsf_rate(),
3393 chargeback: default_chargeback_rate(),
3394 wrong_amount: default_wrong_amount_rate(),
3395 wrong_customer: default_wrong_customer_rate(),
3396 duplicate_payment: default_duplicate_payment_rate(),
3397 }
3398 }
3399}
3400
3401#[derive(Debug, Clone, Serialize, Deserialize)]
3403pub struct DocumentLineCountDistribution {
3404 #[serde(default = "default_min_lines")]
3406 pub min_lines: u32,
3407 #[serde(default = "default_max_lines")]
3409 pub max_lines: u32,
3410 #[serde(default = "default_mode_lines")]
3412 pub mode_lines: u32,
3413}
3414
3415fn default_min_lines() -> u32 {
3416 1
3417}
3418
3419fn default_max_lines() -> u32 {
3420 20
3421}
3422
3423fn default_mode_lines() -> u32 {
3424 3
3425}
3426
3427impl Default for DocumentLineCountDistribution {
3428 fn default() -> Self {
3429 Self {
3430 min_lines: default_min_lines(),
3431 max_lines: default_max_lines(),
3432 mode_lines: default_mode_lines(),
3433 }
3434 }
3435}
3436
3437#[derive(Debug, Clone, Serialize, Deserialize)]
3439pub struct CashDiscountConfig {
3440 #[serde(default = "default_discount_eligible_rate")]
3442 pub eligible_rate: f64,
3443 #[serde(default = "default_discount_taken_rate")]
3445 pub taken_rate: f64,
3446 #[serde(default = "default_discount_percent")]
3448 pub discount_percent: f64,
3449 #[serde(default = "default_discount_days")]
3451 pub discount_days: u32,
3452}
3453
3454fn default_discount_eligible_rate() -> f64 {
3455 0.30
3456}
3457
3458fn default_discount_taken_rate() -> f64 {
3459 0.60
3460}
3461
3462fn default_discount_percent() -> f64 {
3463 0.02
3464}
3465
3466fn default_discount_days() -> u32 {
3467 10
3468}
3469
3470impl Default for CashDiscountConfig {
3471 fn default() -> Self {
3472 Self {
3473 eligible_rate: default_discount_eligible_rate(),
3474 taken_rate: default_discount_taken_rate(),
3475 discount_percent: default_discount_percent(),
3476 discount_days: default_discount_days(),
3477 }
3478 }
3479}
3480
3481#[derive(Debug, Clone, Serialize, Deserialize)]
3487pub struct IntercompanyConfig {
3488 #[serde(default)]
3490 pub enabled: bool,
3491 #[serde(default = "default_ic_transaction_rate")]
3493 pub ic_transaction_rate: f64,
3494 #[serde(default)]
3496 pub transfer_pricing_method: TransferPricingMethod,
3497 #[serde(default = "default_markup_percent")]
3499 pub markup_percent: f64,
3500 #[serde(default = "default_true")]
3502 pub generate_matched_pairs: bool,
3503 #[serde(default)]
3505 pub transaction_type_distribution: ICTransactionTypeDistribution,
3506 #[serde(default)]
3508 pub generate_eliminations: bool,
3509}
3510
3511fn default_ic_transaction_rate() -> f64 {
3512 0.15
3513}
3514
3515fn default_markup_percent() -> f64 {
3516 0.05
3517}
3518
3519impl Default for IntercompanyConfig {
3520 fn default() -> Self {
3521 Self {
3522 enabled: false,
3523 ic_transaction_rate: default_ic_transaction_rate(),
3524 transfer_pricing_method: TransferPricingMethod::default(),
3525 markup_percent: default_markup_percent(),
3526 generate_matched_pairs: true,
3527 transaction_type_distribution: ICTransactionTypeDistribution::default(),
3528 generate_eliminations: false,
3529 }
3530 }
3531}
3532
3533#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
3535#[serde(rename_all = "snake_case")]
3536pub enum TransferPricingMethod {
3537 #[default]
3539 CostPlus,
3540 ComparableUncontrolled,
3542 ResalePrice,
3544 TransactionalNetMargin,
3546 ProfitSplit,
3548}
3549
3550#[derive(Debug, Clone, Serialize, Deserialize)]
3552pub struct ICTransactionTypeDistribution {
3553 pub goods_sale: f64,
3555 pub service_provided: f64,
3557 pub loan: f64,
3559 pub dividend: f64,
3561 pub management_fee: f64,
3563 pub royalty: f64,
3565 pub cost_sharing: f64,
3567}
3568
3569impl Default for ICTransactionTypeDistribution {
3570 fn default() -> Self {
3571 Self {
3572 goods_sale: 0.35,
3573 service_provided: 0.20,
3574 loan: 0.10,
3575 dividend: 0.05,
3576 management_fee: 0.15,
3577 royalty: 0.10,
3578 cost_sharing: 0.05,
3579 }
3580 }
3581}
3582
3583#[derive(Debug, Clone, Serialize, Deserialize)]
3589pub struct BalanceConfig {
3590 #[serde(default)]
3592 pub generate_opening_balances: bool,
3593 #[serde(default = "default_true")]
3595 pub generate_trial_balances: bool,
3596 #[serde(default = "default_gross_margin")]
3598 pub target_gross_margin: f64,
3599 #[serde(default = "default_dso")]
3601 pub target_dso_days: u32,
3602 #[serde(default = "default_dpo")]
3604 pub target_dpo_days: u32,
3605 #[serde(default = "default_current_ratio")]
3607 pub target_current_ratio: f64,
3608 #[serde(default = "default_debt_equity")]
3610 pub target_debt_to_equity: f64,
3611 #[serde(default = "default_true")]
3613 pub validate_balance_equation: bool,
3614 #[serde(default = "default_true")]
3616 pub reconcile_subledgers: bool,
3617}
3618
3619fn default_gross_margin() -> f64 {
3620 0.35
3621}
3622
3623fn default_dso() -> u32 {
3624 45
3625}
3626
3627fn default_dpo() -> u32 {
3628 30
3629}
3630
3631fn default_current_ratio() -> f64 {
3632 1.5
3633}
3634
3635fn default_debt_equity() -> f64 {
3636 0.5
3637}
3638
3639impl Default for BalanceConfig {
3640 fn default() -> Self {
3641 Self {
3642 generate_opening_balances: false,
3643 generate_trial_balances: true,
3644 target_gross_margin: default_gross_margin(),
3645 target_dso_days: default_dso(),
3646 target_dpo_days: default_dpo(),
3647 target_current_ratio: default_current_ratio(),
3648 target_debt_to_equity: default_debt_equity(),
3649 validate_balance_equation: true,
3650 reconcile_subledgers: true,
3651 }
3652 }
3653}
3654
3655#[derive(Debug, Clone, Serialize, Deserialize)]
3664pub struct OcpmConfig {
3665 #[serde(default)]
3667 pub enabled: bool,
3668
3669 #[serde(default = "default_true")]
3671 pub generate_lifecycle_events: bool,
3672
3673 #[serde(default = "default_true")]
3675 pub include_object_relationships: bool,
3676
3677 #[serde(default = "default_true")]
3679 pub compute_variants: bool,
3680
3681 #[serde(default)]
3683 pub max_variants: usize,
3684
3685 #[serde(default)]
3687 pub p2p_process: OcpmProcessConfig,
3688
3689 #[serde(default)]
3691 pub o2c_process: OcpmProcessConfig,
3692
3693 #[serde(default)]
3695 pub output: OcpmOutputConfig,
3696}
3697
3698impl Default for OcpmConfig {
3699 fn default() -> Self {
3700 Self {
3701 enabled: false,
3702 generate_lifecycle_events: true,
3703 include_object_relationships: true,
3704 compute_variants: true,
3705 max_variants: 0,
3706 p2p_process: OcpmProcessConfig::default(),
3707 o2c_process: OcpmProcessConfig::default(),
3708 output: OcpmOutputConfig::default(),
3709 }
3710 }
3711}
3712
3713#[derive(Debug, Clone, Serialize, Deserialize)]
3715pub struct OcpmProcessConfig {
3716 #[serde(default = "default_rework_probability")]
3718 pub rework_probability: f64,
3719
3720 #[serde(default = "default_skip_probability")]
3722 pub skip_step_probability: f64,
3723
3724 #[serde(default = "default_out_of_order_probability")]
3726 pub out_of_order_probability: f64,
3727}
3728
3729fn default_rework_probability() -> f64 {
3730 0.05
3731}
3732
3733fn default_skip_probability() -> f64 {
3734 0.02
3735}
3736
3737fn default_out_of_order_probability() -> f64 {
3738 0.03
3739}
3740
3741impl Default for OcpmProcessConfig {
3742 fn default() -> Self {
3743 Self {
3744 rework_probability: default_rework_probability(),
3745 skip_step_probability: default_skip_probability(),
3746 out_of_order_probability: default_out_of_order_probability(),
3747 }
3748 }
3749}
3750
3751#[derive(Debug, Clone, Serialize, Deserialize)]
3753pub struct OcpmOutputConfig {
3754 #[serde(default = "default_true")]
3756 pub ocel_json: bool,
3757
3758 #[serde(default)]
3760 pub ocel_xml: bool,
3761
3762 #[serde(default)]
3764 pub xes: bool,
3765
3766 #[serde(default = "default_true")]
3768 pub xes_include_lifecycle: bool,
3769
3770 #[serde(default = "default_true")]
3772 pub xes_include_resources: bool,
3773
3774 #[serde(default = "default_true")]
3776 pub flattened_csv: bool,
3777
3778 #[serde(default = "default_true")]
3780 pub event_object_csv: bool,
3781
3782 #[serde(default = "default_true")]
3784 pub object_relationship_csv: bool,
3785
3786 #[serde(default = "default_true")]
3788 pub variants_csv: bool,
3789
3790 #[serde(default)]
3792 pub export_reference_models: bool,
3793}
3794
3795impl Default for OcpmOutputConfig {
3796 fn default() -> Self {
3797 Self {
3798 ocel_json: true,
3799 ocel_xml: false,
3800 xes: false,
3801 xes_include_lifecycle: true,
3802 xes_include_resources: true,
3803 flattened_csv: true,
3804 event_object_csv: true,
3805 object_relationship_csv: true,
3806 variants_csv: true,
3807 export_reference_models: false,
3808 }
3809 }
3810}
3811
3812#[derive(Debug, Clone, Serialize, Deserialize)]
3814pub struct AuditGenerationConfig {
3815 #[serde(default)]
3817 pub enabled: bool,
3818
3819 #[serde(default = "default_true")]
3822 pub generate_workpapers: bool,
3823
3824 #[serde(default)]
3827 pub engagement_types: AuditEngagementTypesConfig,
3828
3829 #[serde(default)]
3832 pub workpapers: WorkpaperConfig,
3833
3834 #[serde(default)]
3837 pub team: AuditTeamConfig,
3838
3839 #[serde(default)]
3842 pub review: ReviewWorkflowConfig,
3843
3844 #[serde(default)]
3846 pub fsm: Option<AuditFsmConfig>,
3847}
3848
3849impl Default for AuditGenerationConfig {
3850 fn default() -> Self {
3851 Self {
3852 enabled: false,
3853 generate_workpapers: true,
3854 engagement_types: AuditEngagementTypesConfig::default(),
3855 workpapers: WorkpaperConfig::default(),
3856 team: AuditTeamConfig::default(),
3857 review: ReviewWorkflowConfig::default(),
3858 fsm: None,
3859 }
3860 }
3861}
3862
3863#[derive(Debug, Clone, Serialize, Deserialize)]
3865pub struct AuditFsmConfig {
3866 #[serde(default)]
3868 pub enabled: bool,
3869
3870 #[serde(default = "default_audit_fsm_blueprint")]
3872 pub blueprint: String,
3873
3874 #[serde(default = "default_audit_fsm_overlay")]
3876 pub overlay: String,
3877
3878 #[serde(default)]
3880 pub depth: Option<String>,
3881
3882 #[serde(default)]
3884 pub discriminators: std::collections::HashMap<String, Vec<String>>,
3885
3886 #[serde(default)]
3888 pub event_trail: AuditEventTrailConfig,
3889
3890 #[serde(default)]
3892 pub seed: Option<u64>,
3893}
3894
3895impl Default for AuditFsmConfig {
3896 fn default() -> Self {
3897 Self {
3898 enabled: false,
3899 blueprint: default_audit_fsm_blueprint(),
3900 overlay: default_audit_fsm_overlay(),
3901 depth: None,
3902 discriminators: std::collections::HashMap::new(),
3903 event_trail: AuditEventTrailConfig::default(),
3904 seed: None,
3905 }
3906 }
3907}
3908
3909fn default_audit_fsm_blueprint() -> String {
3910 "builtin:fsa".to_string()
3911}
3912
3913fn default_audit_fsm_overlay() -> String {
3914 "builtin:default".to_string()
3915}
3916
3917#[derive(Debug, Clone, Serialize, Deserialize)]
3919pub struct AuditEventTrailConfig {
3920 #[serde(default = "default_true")]
3922 pub flat_log: bool,
3923 #[serde(default)]
3925 pub ocel_projection: bool,
3926}
3927
3928impl Default for AuditEventTrailConfig {
3929 fn default() -> Self {
3930 Self {
3931 flat_log: true,
3932 ocel_projection: false,
3933 }
3934 }
3935}
3936
3937#[derive(Debug, Clone, Serialize, Deserialize)]
3939pub struct AuditEngagementTypesConfig {
3940 #[serde(default = "default_financial_audit_prob")]
3942 pub financial_statement: f64,
3943 #[serde(default = "default_sox_audit_prob")]
3945 pub sox_icfr: f64,
3946 #[serde(default = "default_integrated_audit_prob")]
3948 pub integrated: f64,
3949 #[serde(default = "default_review_prob")]
3951 pub review: f64,
3952 #[serde(default = "default_aup_prob")]
3954 pub agreed_upon_procedures: f64,
3955}
3956
3957fn default_financial_audit_prob() -> f64 {
3958 0.40
3959}
3960fn default_sox_audit_prob() -> f64 {
3961 0.20
3962}
3963fn default_integrated_audit_prob() -> f64 {
3964 0.25
3965}
3966fn default_review_prob() -> f64 {
3967 0.10
3968}
3969fn default_aup_prob() -> f64 {
3970 0.05
3971}
3972
3973impl Default for AuditEngagementTypesConfig {
3974 fn default() -> Self {
3975 Self {
3976 financial_statement: default_financial_audit_prob(),
3977 sox_icfr: default_sox_audit_prob(),
3978 integrated: default_integrated_audit_prob(),
3979 review: default_review_prob(),
3980 agreed_upon_procedures: default_aup_prob(),
3981 }
3982 }
3983}
3984
3985#[derive(Debug, Clone, Serialize, Deserialize)]
3987pub struct WorkpaperConfig {
3988 #[serde(default = "default_workpapers_per_phase")]
3990 pub average_per_phase: usize,
3991
3992 #[serde(default = "default_true")]
3994 pub include_isa_references: bool,
3995
3996 #[serde(default = "default_true")]
3998 pub include_sample_details: bool,
3999
4000 #[serde(default = "default_true")]
4002 pub include_cross_references: bool,
4003
4004 #[serde(default)]
4006 pub sampling: SamplingConfig,
4007}
4008
4009fn default_workpapers_per_phase() -> usize {
4010 5
4011}
4012
4013impl Default for WorkpaperConfig {
4014 fn default() -> Self {
4015 Self {
4016 average_per_phase: default_workpapers_per_phase(),
4017 include_isa_references: true,
4018 include_sample_details: true,
4019 include_cross_references: true,
4020 sampling: SamplingConfig::default(),
4021 }
4022 }
4023}
4024
4025#[derive(Debug, Clone, Serialize, Deserialize)]
4027pub struct SamplingConfig {
4028 #[serde(default = "default_statistical_rate")]
4030 pub statistical_rate: f64,
4031 #[serde(default = "default_judgmental_rate")]
4033 pub judgmental_rate: f64,
4034 #[serde(default = "default_haphazard_rate")]
4036 pub haphazard_rate: f64,
4037 #[serde(default = "default_complete_examination_rate")]
4039 pub complete_examination_rate: f64,
4040}
4041
4042fn default_statistical_rate() -> f64 {
4043 0.40
4044}
4045fn default_judgmental_rate() -> f64 {
4046 0.30
4047}
4048fn default_haphazard_rate() -> f64 {
4049 0.20
4050}
4051fn default_complete_examination_rate() -> f64 {
4052 0.10
4053}
4054
4055impl Default for SamplingConfig {
4056 fn default() -> Self {
4057 Self {
4058 statistical_rate: default_statistical_rate(),
4059 judgmental_rate: default_judgmental_rate(),
4060 haphazard_rate: default_haphazard_rate(),
4061 complete_examination_rate: default_complete_examination_rate(),
4062 }
4063 }
4064}
4065
4066#[derive(Debug, Clone, Serialize, Deserialize)]
4068pub struct AuditTeamConfig {
4069 #[serde(default = "default_min_team_size")]
4071 pub min_team_size: usize,
4072 #[serde(default = "default_max_team_size")]
4074 pub max_team_size: usize,
4075 #[serde(default = "default_specialist_probability")]
4077 pub specialist_probability: f64,
4078}
4079
4080fn default_min_team_size() -> usize {
4081 3
4082}
4083fn default_max_team_size() -> usize {
4084 8
4085}
4086fn default_specialist_probability() -> f64 {
4087 0.30
4088}
4089
4090impl Default for AuditTeamConfig {
4091 fn default() -> Self {
4092 Self {
4093 min_team_size: default_min_team_size(),
4094 max_team_size: default_max_team_size(),
4095 specialist_probability: default_specialist_probability(),
4096 }
4097 }
4098}
4099
4100#[derive(Debug, Clone, Serialize, Deserialize)]
4102pub struct ReviewWorkflowConfig {
4103 #[serde(default = "default_review_delay_days")]
4105 pub average_review_delay_days: u32,
4106 #[serde(default = "default_rework_probability_review")]
4108 pub rework_probability: f64,
4109 #[serde(default = "default_true")]
4111 pub require_partner_signoff: bool,
4112}
4113
4114fn default_review_delay_days() -> u32 {
4115 2
4116}
4117fn default_rework_probability_review() -> f64 {
4118 0.15
4119}
4120
4121impl Default for ReviewWorkflowConfig {
4122 fn default() -> Self {
4123 Self {
4124 average_review_delay_days: default_review_delay_days(),
4125 rework_probability: default_rework_probability_review(),
4126 require_partner_signoff: true,
4127 }
4128 }
4129}
4130
4131#[derive(Debug, Clone, Serialize, Deserialize)]
4137pub struct DataQualitySchemaConfig {
4138 #[serde(default)]
4140 pub enabled: bool,
4141 #[serde(default)]
4143 pub preset: DataQualityPreset,
4144 #[serde(default)]
4146 pub missing_values: MissingValuesSchemaConfig,
4147 #[serde(default)]
4149 pub typos: TypoSchemaConfig,
4150 #[serde(default)]
4152 pub format_variations: FormatVariationSchemaConfig,
4153 #[serde(default)]
4155 pub duplicates: DuplicateSchemaConfig,
4156 #[serde(default)]
4158 pub encoding_issues: EncodingIssueSchemaConfig,
4159 #[serde(default)]
4161 pub generate_labels: bool,
4162 #[serde(default)]
4164 pub sink_profiles: SinkQualityProfiles,
4165}
4166
4167impl Default for DataQualitySchemaConfig {
4168 fn default() -> Self {
4169 Self {
4170 enabled: false,
4171 preset: DataQualityPreset::None,
4172 missing_values: MissingValuesSchemaConfig::default(),
4173 typos: TypoSchemaConfig::default(),
4174 format_variations: FormatVariationSchemaConfig::default(),
4175 duplicates: DuplicateSchemaConfig::default(),
4176 encoding_issues: EncodingIssueSchemaConfig::default(),
4177 generate_labels: true,
4178 sink_profiles: SinkQualityProfiles::default(),
4179 }
4180 }
4181}
4182
4183impl DataQualitySchemaConfig {
4184 pub fn with_preset(preset: DataQualityPreset) -> Self {
4186 let mut config = Self {
4187 preset,
4188 ..Default::default()
4189 };
4190 config.apply_preset();
4191 config
4192 }
4193
4194 pub fn apply_preset(&mut self) {
4197 if !self.preset.overrides_settings() {
4198 return;
4199 }
4200
4201 self.enabled = true;
4202
4203 self.missing_values.enabled = self.preset.missing_rate() > 0.0;
4205 self.missing_values.rate = self.preset.missing_rate();
4206
4207 self.typos.enabled = self.preset.typo_rate() > 0.0;
4209 self.typos.char_error_rate = self.preset.typo_rate();
4210
4211 self.duplicates.enabled = self.preset.duplicate_rate() > 0.0;
4213 self.duplicates.exact_duplicate_ratio = self.preset.duplicate_rate() * 0.4;
4214 self.duplicates.near_duplicate_ratio = self.preset.duplicate_rate() * 0.4;
4215 self.duplicates.fuzzy_duplicate_ratio = self.preset.duplicate_rate() * 0.2;
4216
4217 self.format_variations.enabled = self.preset.format_variations_enabled();
4219
4220 self.encoding_issues.enabled = self.preset.encoding_issues_enabled();
4222 self.encoding_issues.rate = self.preset.encoding_issue_rate();
4223
4224 if self.preset.ocr_errors_enabled() {
4226 self.typos.type_weights.ocr_errors = 0.3;
4227 }
4228 }
4229
4230 pub fn effective_missing_rate(&self) -> f64 {
4232 if self.preset.overrides_settings() {
4233 self.preset.missing_rate()
4234 } else {
4235 self.missing_values.rate
4236 }
4237 }
4238
4239 pub fn effective_typo_rate(&self) -> f64 {
4241 if self.preset.overrides_settings() {
4242 self.preset.typo_rate()
4243 } else {
4244 self.typos.char_error_rate
4245 }
4246 }
4247
4248 pub fn effective_duplicate_rate(&self) -> f64 {
4250 if self.preset.overrides_settings() {
4251 self.preset.duplicate_rate()
4252 } else {
4253 self.duplicates.exact_duplicate_ratio
4254 + self.duplicates.near_duplicate_ratio
4255 + self.duplicates.fuzzy_duplicate_ratio
4256 }
4257 }
4258
4259 pub fn clean() -> Self {
4261 Self::with_preset(DataQualityPreset::Clean)
4262 }
4263
4264 pub fn noisy() -> Self {
4266 Self::with_preset(DataQualityPreset::Noisy)
4267 }
4268
4269 pub fn legacy() -> Self {
4271 Self::with_preset(DataQualityPreset::Legacy)
4272 }
4273}
4274
4275#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
4277#[serde(rename_all = "snake_case")]
4278pub enum DataQualityPreset {
4279 #[default]
4281 None,
4282 Minimal,
4284 Normal,
4286 High,
4288 Custom,
4290
4291 Clean,
4297 Noisy,
4300 Legacy,
4303}
4304
4305impl DataQualityPreset {
4306 pub fn missing_rate(&self) -> f64 {
4308 match self {
4309 DataQualityPreset::None => 0.0,
4310 DataQualityPreset::Minimal => 0.005,
4311 DataQualityPreset::Normal => 0.02,
4312 DataQualityPreset::High => 0.08,
4313 DataQualityPreset::Custom => 0.01, DataQualityPreset::Clean => 0.001,
4315 DataQualityPreset::Noisy => 0.05,
4316 DataQualityPreset::Legacy => 0.10,
4317 }
4318 }
4319
4320 pub fn typo_rate(&self) -> f64 {
4322 match self {
4323 DataQualityPreset::None => 0.0,
4324 DataQualityPreset::Minimal => 0.0005,
4325 DataQualityPreset::Normal => 0.002,
4326 DataQualityPreset::High => 0.01,
4327 DataQualityPreset::Custom => 0.001, DataQualityPreset::Clean => 0.0005,
4329 DataQualityPreset::Noisy => 0.02,
4330 DataQualityPreset::Legacy => 0.05,
4331 }
4332 }
4333
4334 pub fn duplicate_rate(&self) -> f64 {
4336 match self {
4337 DataQualityPreset::None => 0.0,
4338 DataQualityPreset::Minimal => 0.001,
4339 DataQualityPreset::Normal => 0.005,
4340 DataQualityPreset::High => 0.02,
4341 DataQualityPreset::Custom => 0.0, DataQualityPreset::Clean => 0.0,
4343 DataQualityPreset::Noisy => 0.01,
4344 DataQualityPreset::Legacy => 0.03,
4345 }
4346 }
4347
4348 pub fn format_variations_enabled(&self) -> bool {
4350 match self {
4351 DataQualityPreset::None | DataQualityPreset::Clean => false,
4352 DataQualityPreset::Minimal => true,
4353 DataQualityPreset::Normal => true,
4354 DataQualityPreset::High => true,
4355 DataQualityPreset::Custom => true,
4356 DataQualityPreset::Noisy => true,
4357 DataQualityPreset::Legacy => true,
4358 }
4359 }
4360
4361 pub fn ocr_errors_enabled(&self) -> bool {
4363 matches!(self, DataQualityPreset::Legacy | DataQualityPreset::High)
4364 }
4365
4366 pub fn encoding_issues_enabled(&self) -> bool {
4368 matches!(
4369 self,
4370 DataQualityPreset::Legacy | DataQualityPreset::High | DataQualityPreset::Noisy
4371 )
4372 }
4373
4374 pub fn encoding_issue_rate(&self) -> f64 {
4376 match self {
4377 DataQualityPreset::None | DataQualityPreset::Clean | DataQualityPreset::Minimal => 0.0,
4378 DataQualityPreset::Normal => 0.002,
4379 DataQualityPreset::High => 0.01,
4380 DataQualityPreset::Custom => 0.0,
4381 DataQualityPreset::Noisy => 0.005,
4382 DataQualityPreset::Legacy => 0.02,
4383 }
4384 }
4385
4386 pub fn overrides_settings(&self) -> bool {
4388 !matches!(self, DataQualityPreset::Custom | DataQualityPreset::None)
4389 }
4390
4391 pub fn description(&self) -> &'static str {
4393 match self {
4394 DataQualityPreset::None => "No data quality issues (pristine data)",
4395 DataQualityPreset::Minimal => "Very rare data quality issues",
4396 DataQualityPreset::Normal => "Realistic enterprise data quality",
4397 DataQualityPreset::High => "Messy data for stress testing",
4398 DataQualityPreset::Custom => "Custom settings from configuration",
4399 DataQualityPreset::Clean => "ML-ready clean data with minimal issues",
4400 DataQualityPreset::Noisy => "Typical production data with moderate issues",
4401 DataQualityPreset::Legacy => "Legacy/migrated data with heavy issues and OCR errors",
4402 }
4403 }
4404}
4405
4406#[derive(Debug, Clone, Serialize, Deserialize)]
4408pub struct MissingValuesSchemaConfig {
4409 #[serde(default)]
4411 pub enabled: bool,
4412 #[serde(default = "default_missing_rate")]
4414 pub rate: f64,
4415 #[serde(default)]
4417 pub strategy: MissingValueStrategy,
4418 #[serde(default)]
4420 pub field_rates: std::collections::HashMap<String, f64>,
4421 #[serde(default)]
4423 pub protected_fields: Vec<String>,
4424}
4425
4426fn default_missing_rate() -> f64 {
4427 0.01
4428}
4429
4430impl Default for MissingValuesSchemaConfig {
4431 fn default() -> Self {
4432 Self {
4433 enabled: false,
4434 rate: default_missing_rate(),
4435 strategy: MissingValueStrategy::Mcar,
4436 field_rates: std::collections::HashMap::new(),
4437 protected_fields: vec![
4438 "document_id".to_string(),
4439 "company_code".to_string(),
4440 "posting_date".to_string(),
4441 ],
4442 }
4443 }
4444}
4445
4446#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
4448#[serde(rename_all = "snake_case")]
4449pub enum MissingValueStrategy {
4450 #[default]
4452 Mcar,
4453 Mar,
4455 Mnar,
4457 Systematic,
4459}
4460
4461#[derive(Debug, Clone, Serialize, Deserialize)]
4463pub struct TypoSchemaConfig {
4464 #[serde(default)]
4466 pub enabled: bool,
4467 #[serde(default = "default_typo_rate")]
4469 pub char_error_rate: f64,
4470 #[serde(default)]
4472 pub type_weights: TypoTypeWeights,
4473 #[serde(default)]
4475 pub protected_fields: Vec<String>,
4476}
4477
4478fn default_typo_rate() -> f64 {
4479 0.001
4480}
4481
4482impl Default for TypoSchemaConfig {
4483 fn default() -> Self {
4484 Self {
4485 enabled: false,
4486 char_error_rate: default_typo_rate(),
4487 type_weights: TypoTypeWeights::default(),
4488 protected_fields: vec![
4489 "document_id".to_string(),
4490 "gl_account".to_string(),
4491 "company_code".to_string(),
4492 ],
4493 }
4494 }
4495}
4496
4497#[derive(Debug, Clone, Serialize, Deserialize)]
4499pub struct TypoTypeWeights {
4500 #[serde(default = "default_substitution_weight")]
4502 pub substitution: f64,
4503 #[serde(default = "default_transposition_weight")]
4505 pub transposition: f64,
4506 #[serde(default = "default_insertion_weight")]
4508 pub insertion: f64,
4509 #[serde(default = "default_deletion_weight")]
4511 pub deletion: f64,
4512 #[serde(default = "default_ocr_weight")]
4514 pub ocr_errors: f64,
4515 #[serde(default = "default_homophone_weight")]
4517 pub homophones: f64,
4518}
4519
4520fn default_substitution_weight() -> f64 {
4521 0.35
4522}
4523fn default_transposition_weight() -> f64 {
4524 0.25
4525}
4526fn default_insertion_weight() -> f64 {
4527 0.10
4528}
4529fn default_deletion_weight() -> f64 {
4530 0.15
4531}
4532fn default_ocr_weight() -> f64 {
4533 0.10
4534}
4535fn default_homophone_weight() -> f64 {
4536 0.05
4537}
4538
4539impl Default for TypoTypeWeights {
4540 fn default() -> Self {
4541 Self {
4542 substitution: default_substitution_weight(),
4543 transposition: default_transposition_weight(),
4544 insertion: default_insertion_weight(),
4545 deletion: default_deletion_weight(),
4546 ocr_errors: default_ocr_weight(),
4547 homophones: default_homophone_weight(),
4548 }
4549 }
4550}
4551
4552#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4554pub struct FormatVariationSchemaConfig {
4555 #[serde(default)]
4557 pub enabled: bool,
4558 #[serde(default)]
4560 pub dates: DateFormatVariationConfig,
4561 #[serde(default)]
4563 pub amounts: AmountFormatVariationConfig,
4564 #[serde(default)]
4566 pub identifiers: IdentifierFormatVariationConfig,
4567}
4568
4569#[derive(Debug, Clone, Serialize, Deserialize)]
4571pub struct DateFormatVariationConfig {
4572 #[serde(default)]
4574 pub enabled: bool,
4575 #[serde(default = "default_date_variation_rate")]
4577 pub rate: f64,
4578 #[serde(default = "default_true")]
4580 pub iso_format: bool,
4581 #[serde(default)]
4583 pub us_format: bool,
4584 #[serde(default)]
4586 pub eu_format: bool,
4587 #[serde(default)]
4589 pub long_format: bool,
4590}
4591
4592fn default_date_variation_rate() -> f64 {
4593 0.05
4594}
4595
4596impl Default for DateFormatVariationConfig {
4597 fn default() -> Self {
4598 Self {
4599 enabled: false,
4600 rate: default_date_variation_rate(),
4601 iso_format: true,
4602 us_format: false,
4603 eu_format: false,
4604 long_format: false,
4605 }
4606 }
4607}
4608
4609#[derive(Debug, Clone, Serialize, Deserialize)]
4611pub struct AmountFormatVariationConfig {
4612 #[serde(default)]
4614 pub enabled: bool,
4615 #[serde(default = "default_amount_variation_rate")]
4617 pub rate: f64,
4618 #[serde(default)]
4620 pub us_comma_format: bool,
4621 #[serde(default)]
4623 pub eu_format: bool,
4624 #[serde(default)]
4626 pub currency_prefix: bool,
4627 #[serde(default)]
4629 pub accounting_format: bool,
4630}
4631
4632fn default_amount_variation_rate() -> f64 {
4633 0.02
4634}
4635
4636impl Default for AmountFormatVariationConfig {
4637 fn default() -> Self {
4638 Self {
4639 enabled: false,
4640 rate: default_amount_variation_rate(),
4641 us_comma_format: false,
4642 eu_format: false,
4643 currency_prefix: false,
4644 accounting_format: false,
4645 }
4646 }
4647}
4648
4649#[derive(Debug, Clone, Serialize, Deserialize)]
4651pub struct IdentifierFormatVariationConfig {
4652 #[serde(default)]
4654 pub enabled: bool,
4655 #[serde(default = "default_identifier_variation_rate")]
4657 pub rate: f64,
4658 #[serde(default)]
4660 pub case_variations: bool,
4661 #[serde(default)]
4663 pub padding_variations: bool,
4664 #[serde(default)]
4666 pub separator_variations: bool,
4667}
4668
4669fn default_identifier_variation_rate() -> f64 {
4670 0.02
4671}
4672
4673impl Default for IdentifierFormatVariationConfig {
4674 fn default() -> Self {
4675 Self {
4676 enabled: false,
4677 rate: default_identifier_variation_rate(),
4678 case_variations: false,
4679 padding_variations: false,
4680 separator_variations: false,
4681 }
4682 }
4683}
4684
4685#[derive(Debug, Clone, Serialize, Deserialize)]
4687pub struct DuplicateSchemaConfig {
4688 #[serde(default)]
4690 pub enabled: bool,
4691 #[serde(default = "default_duplicate_rate")]
4693 pub rate: f64,
4694 #[serde(default = "default_exact_duplicate_ratio")]
4696 pub exact_duplicate_ratio: f64,
4697 #[serde(default = "default_near_duplicate_ratio")]
4699 pub near_duplicate_ratio: f64,
4700 #[serde(default = "default_fuzzy_duplicate_ratio")]
4702 pub fuzzy_duplicate_ratio: f64,
4703 #[serde(default = "default_max_date_offset")]
4705 pub max_date_offset_days: u32,
4706 #[serde(default = "default_max_amount_variance")]
4708 pub max_amount_variance: f64,
4709}
4710
4711fn default_duplicate_rate() -> f64 {
4712 0.005
4713}
4714fn default_exact_duplicate_ratio() -> f64 {
4715 0.4
4716}
4717fn default_near_duplicate_ratio() -> f64 {
4718 0.35
4719}
4720fn default_fuzzy_duplicate_ratio() -> f64 {
4721 0.25
4722}
4723fn default_max_date_offset() -> u32 {
4724 3
4725}
4726fn default_max_amount_variance() -> f64 {
4727 0.01
4728}
4729
4730impl Default for DuplicateSchemaConfig {
4731 fn default() -> Self {
4732 Self {
4733 enabled: false,
4734 rate: default_duplicate_rate(),
4735 exact_duplicate_ratio: default_exact_duplicate_ratio(),
4736 near_duplicate_ratio: default_near_duplicate_ratio(),
4737 fuzzy_duplicate_ratio: default_fuzzy_duplicate_ratio(),
4738 max_date_offset_days: default_max_date_offset(),
4739 max_amount_variance: default_max_amount_variance(),
4740 }
4741 }
4742}
4743
4744#[derive(Debug, Clone, Serialize, Deserialize)]
4746pub struct EncodingIssueSchemaConfig {
4747 #[serde(default)]
4749 pub enabled: bool,
4750 #[serde(default = "default_encoding_rate")]
4752 pub rate: f64,
4753 #[serde(default)]
4755 pub mojibake: bool,
4756 #[serde(default)]
4758 pub html_entities: bool,
4759 #[serde(default)]
4761 pub bom_issues: bool,
4762}
4763
4764fn default_encoding_rate() -> f64 {
4765 0.001
4766}
4767
4768impl Default for EncodingIssueSchemaConfig {
4769 fn default() -> Self {
4770 Self {
4771 enabled: false,
4772 rate: default_encoding_rate(),
4773 mojibake: false,
4774 html_entities: false,
4775 bom_issues: false,
4776 }
4777 }
4778}
4779
4780#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4782pub struct SinkQualityProfiles {
4783 #[serde(default)]
4785 pub csv: Option<SinkQualityOverride>,
4786 #[serde(default)]
4788 pub json: Option<SinkQualityOverride>,
4789 #[serde(default)]
4791 pub parquet: Option<SinkQualityOverride>,
4792}
4793
4794#[derive(Debug, Clone, Serialize, Deserialize)]
4796pub struct SinkQualityOverride {
4797 pub enabled: Option<bool>,
4799 pub missing_rate: Option<f64>,
4801 pub typo_rate: Option<f64>,
4803 pub format_variation_rate: Option<f64>,
4805 pub duplicate_rate: Option<f64>,
4807}
4808
4809#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4821pub struct AccountingStandardsConfig {
4822 #[serde(default)]
4824 pub enabled: bool,
4825
4826 #[serde(default, skip_serializing_if = "Option::is_none")]
4830 pub framework: Option<AccountingFrameworkConfig>,
4831
4832 #[serde(default)]
4834 pub revenue_recognition: RevenueRecognitionConfig,
4835
4836 #[serde(default)]
4838 pub leases: LeaseAccountingConfig,
4839
4840 #[serde(default)]
4842 pub fair_value: FairValueConfig,
4843
4844 #[serde(default)]
4846 pub impairment: ImpairmentConfig,
4847
4848 #[serde(default)]
4850 pub business_combinations: BusinessCombinationsConfig,
4851
4852 #[serde(default)]
4854 pub expected_credit_loss: EclConfig,
4855
4856 #[serde(default)]
4858 pub generate_differences: bool,
4859}
4860
4861#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
4863#[serde(rename_all = "snake_case")]
4864pub enum AccountingFrameworkConfig {
4865 #[default]
4867 UsGaap,
4868 Ifrs,
4870 DualReporting,
4872 FrenchGaap,
4874 GermanGaap,
4876}
4877
4878#[derive(Debug, Clone, Serialize, Deserialize)]
4880pub struct RevenueRecognitionConfig {
4881 #[serde(default)]
4883 pub enabled: bool,
4884
4885 #[serde(default = "default_true")]
4887 pub generate_contracts: bool,
4888
4889 #[serde(default = "default_avg_obligations")]
4891 pub avg_obligations_per_contract: f64,
4892
4893 #[serde(default = "default_variable_consideration_rate")]
4895 pub variable_consideration_rate: f64,
4896
4897 #[serde(default = "default_over_time_rate")]
4899 pub over_time_recognition_rate: f64,
4900
4901 #[serde(default = "default_contract_count")]
4903 pub contract_count: usize,
4904}
4905
4906fn default_avg_obligations() -> f64 {
4907 2.0
4908}
4909
4910fn default_variable_consideration_rate() -> f64 {
4911 0.15
4912}
4913
4914fn default_over_time_rate() -> f64 {
4915 0.30
4916}
4917
4918fn default_contract_count() -> usize {
4919 100
4920}
4921
4922impl Default for RevenueRecognitionConfig {
4923 fn default() -> Self {
4924 Self {
4925 enabled: false,
4926 generate_contracts: true,
4927 avg_obligations_per_contract: default_avg_obligations(),
4928 variable_consideration_rate: default_variable_consideration_rate(),
4929 over_time_recognition_rate: default_over_time_rate(),
4930 contract_count: default_contract_count(),
4931 }
4932 }
4933}
4934
4935#[derive(Debug, Clone, Serialize, Deserialize)]
4937pub struct LeaseAccountingConfig {
4938 #[serde(default)]
4940 pub enabled: bool,
4941
4942 #[serde(default = "default_lease_count")]
4944 pub lease_count: usize,
4945
4946 #[serde(default = "default_finance_lease_pct")]
4948 pub finance_lease_percent: f64,
4949
4950 #[serde(default = "default_avg_lease_term")]
4952 pub avg_lease_term_months: u32,
4953
4954 #[serde(default = "default_true")]
4956 pub generate_amortization: bool,
4957
4958 #[serde(default = "default_real_estate_pct")]
4960 pub real_estate_percent: f64,
4961}
4962
4963fn default_lease_count() -> usize {
4964 50
4965}
4966
4967fn default_finance_lease_pct() -> f64 {
4968 0.30
4969}
4970
4971fn default_avg_lease_term() -> u32 {
4972 60
4973}
4974
4975fn default_real_estate_pct() -> f64 {
4976 0.40
4977}
4978
4979impl Default for LeaseAccountingConfig {
4980 fn default() -> Self {
4981 Self {
4982 enabled: false,
4983 lease_count: default_lease_count(),
4984 finance_lease_percent: default_finance_lease_pct(),
4985 avg_lease_term_months: default_avg_lease_term(),
4986 generate_amortization: true,
4987 real_estate_percent: default_real_estate_pct(),
4988 }
4989 }
4990}
4991
4992#[derive(Debug, Clone, Serialize, Deserialize)]
4994pub struct FairValueConfig {
4995 #[serde(default)]
4997 pub enabled: bool,
4998
4999 #[serde(default = "default_fv_count")]
5001 pub measurement_count: usize,
5002
5003 #[serde(default = "default_level1_pct")]
5005 pub level1_percent: f64,
5006
5007 #[serde(default = "default_level2_pct")]
5009 pub level2_percent: f64,
5010
5011 #[serde(default = "default_level3_pct")]
5013 pub level3_percent: f64,
5014
5015 #[serde(default)]
5017 pub include_sensitivity_analysis: bool,
5018}
5019
5020fn default_fv_count() -> usize {
5021 25
5022}
5023
5024fn default_level1_pct() -> f64 {
5025 0.40
5026}
5027
5028fn default_level2_pct() -> f64 {
5029 0.35
5030}
5031
5032fn default_level3_pct() -> f64 {
5033 0.25
5034}
5035
5036impl Default for FairValueConfig {
5037 fn default() -> Self {
5038 Self {
5039 enabled: false,
5040 measurement_count: default_fv_count(),
5041 level1_percent: default_level1_pct(),
5042 level2_percent: default_level2_pct(),
5043 level3_percent: default_level3_pct(),
5044 include_sensitivity_analysis: false,
5045 }
5046 }
5047}
5048
5049#[derive(Debug, Clone, Serialize, Deserialize)]
5051pub struct ImpairmentConfig {
5052 #[serde(default)]
5054 pub enabled: bool,
5055
5056 #[serde(default = "default_impairment_count")]
5058 pub test_count: usize,
5059
5060 #[serde(default = "default_impairment_rate")]
5062 pub impairment_rate: f64,
5063
5064 #[serde(default = "default_true")]
5066 pub generate_projections: bool,
5067
5068 #[serde(default)]
5070 pub include_goodwill: bool,
5071}
5072
5073fn default_impairment_count() -> usize {
5074 15
5075}
5076
5077fn default_impairment_rate() -> f64 {
5078 0.10
5079}
5080
5081impl Default for ImpairmentConfig {
5082 fn default() -> Self {
5083 Self {
5084 enabled: false,
5085 test_count: default_impairment_count(),
5086 impairment_rate: default_impairment_rate(),
5087 generate_projections: true,
5088 include_goodwill: false,
5089 }
5090 }
5091}
5092
5093#[derive(Debug, Clone, Serialize, Deserialize)]
5099pub struct BusinessCombinationsConfig {
5100 #[serde(default)]
5102 pub enabled: bool,
5103
5104 #[serde(default = "default_bc_acquisition_count")]
5106 pub acquisition_count: usize,
5107}
5108
5109fn default_bc_acquisition_count() -> usize {
5110 2
5111}
5112
5113impl Default for BusinessCombinationsConfig {
5114 fn default() -> Self {
5115 Self {
5116 enabled: false,
5117 acquisition_count: default_bc_acquisition_count(),
5118 }
5119 }
5120}
5121
5122#[derive(Debug, Clone, Serialize, Deserialize)]
5128pub struct EclConfig {
5129 #[serde(default)]
5131 pub enabled: bool,
5132
5133 #[serde(default = "default_ecl_base_weight")]
5135 pub base_scenario_weight: f64,
5136
5137 #[serde(default = "default_ecl_base_multiplier")]
5139 pub base_scenario_multiplier: f64,
5140
5141 #[serde(default = "default_ecl_optimistic_weight")]
5143 pub optimistic_scenario_weight: f64,
5144
5145 #[serde(default = "default_ecl_optimistic_multiplier")]
5147 pub optimistic_scenario_multiplier: f64,
5148
5149 #[serde(default = "default_ecl_pessimistic_weight")]
5151 pub pessimistic_scenario_weight: f64,
5152
5153 #[serde(default = "default_ecl_pessimistic_multiplier")]
5155 pub pessimistic_scenario_multiplier: f64,
5156}
5157
5158fn default_ecl_base_weight() -> f64 {
5159 0.50
5160}
5161fn default_ecl_base_multiplier() -> f64 {
5162 1.0
5163}
5164fn default_ecl_optimistic_weight() -> f64 {
5165 0.30
5166}
5167fn default_ecl_optimistic_multiplier() -> f64 {
5168 0.8
5169}
5170fn default_ecl_pessimistic_weight() -> f64 {
5171 0.20
5172}
5173fn default_ecl_pessimistic_multiplier() -> f64 {
5174 1.4
5175}
5176
5177impl Default for EclConfig {
5178 fn default() -> Self {
5179 Self {
5180 enabled: false,
5181 base_scenario_weight: default_ecl_base_weight(),
5182 base_scenario_multiplier: default_ecl_base_multiplier(),
5183 optimistic_scenario_weight: default_ecl_optimistic_weight(),
5184 optimistic_scenario_multiplier: default_ecl_optimistic_multiplier(),
5185 pessimistic_scenario_weight: default_ecl_pessimistic_weight(),
5186 pessimistic_scenario_multiplier: default_ecl_pessimistic_multiplier(),
5187 }
5188 }
5189}
5190
5191#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5204pub struct AuditStandardsConfig {
5205 #[serde(default)]
5207 pub enabled: bool,
5208
5209 #[serde(default)]
5211 pub isa_compliance: IsaComplianceConfig,
5212
5213 #[serde(default)]
5215 pub analytical_procedures: AnalyticalProceduresConfig,
5216
5217 #[serde(default)]
5219 pub confirmations: ConfirmationsConfig,
5220
5221 #[serde(default)]
5223 pub opinion: AuditOpinionConfig,
5224
5225 #[serde(default)]
5227 pub generate_audit_trail: bool,
5228
5229 #[serde(default)]
5231 pub sox: SoxComplianceConfig,
5232
5233 #[serde(default)]
5235 pub pcaob: PcaobConfig,
5236}
5237
5238#[derive(Debug, Clone, Serialize, Deserialize)]
5240pub struct IsaComplianceConfig {
5241 #[serde(default)]
5243 pub enabled: bool,
5244
5245 #[serde(default = "default_compliance_level")]
5247 pub compliance_level: String,
5248
5249 #[serde(default = "default_true")]
5251 pub generate_isa_mappings: bool,
5252
5253 #[serde(default = "default_true")]
5255 pub generate_coverage_summary: bool,
5256
5257 #[serde(default)]
5259 pub include_pcaob: bool,
5260
5261 #[serde(default = "default_audit_framework")]
5263 pub framework: String,
5264}
5265
5266fn default_compliance_level() -> String {
5267 "standard".to_string()
5268}
5269
5270fn default_audit_framework() -> String {
5271 "isa".to_string()
5272}
5273
5274impl Default for IsaComplianceConfig {
5275 fn default() -> Self {
5276 Self {
5277 enabled: false,
5278 compliance_level: default_compliance_level(),
5279 generate_isa_mappings: true,
5280 generate_coverage_summary: true,
5281 include_pcaob: false,
5282 framework: default_audit_framework(),
5283 }
5284 }
5285}
5286
5287#[derive(Debug, Clone, Serialize, Deserialize)]
5289pub struct AnalyticalProceduresConfig {
5290 #[serde(default)]
5292 pub enabled: bool,
5293
5294 #[serde(default = "default_procedures_per_account")]
5296 pub procedures_per_account: usize,
5297
5298 #[serde(default = "default_variance_probability")]
5300 pub variance_probability: f64,
5301
5302 #[serde(default = "default_true")]
5304 pub generate_investigations: bool,
5305
5306 #[serde(default = "default_true")]
5308 pub include_ratio_analysis: bool,
5309}
5310
5311fn default_procedures_per_account() -> usize {
5312 3
5313}
5314
5315fn default_variance_probability() -> f64 {
5316 0.20
5317}
5318
5319impl Default for AnalyticalProceduresConfig {
5320 fn default() -> Self {
5321 Self {
5322 enabled: false,
5323 procedures_per_account: default_procedures_per_account(),
5324 variance_probability: default_variance_probability(),
5325 generate_investigations: true,
5326 include_ratio_analysis: true,
5327 }
5328 }
5329}
5330
5331#[derive(Debug, Clone, Serialize, Deserialize)]
5333pub struct ConfirmationsConfig {
5334 #[serde(default)]
5336 pub enabled: bool,
5337
5338 #[serde(default = "default_confirmation_count")]
5340 pub confirmation_count: usize,
5341
5342 #[serde(default = "default_positive_response_rate")]
5344 pub positive_response_rate: f64,
5345
5346 #[serde(default = "default_exception_rate_confirm")]
5348 pub exception_rate: f64,
5349
5350 #[serde(default = "default_non_response_rate")]
5352 pub non_response_rate: f64,
5353
5354 #[serde(default = "default_true")]
5356 pub generate_alternative_procedures: bool,
5357}
5358
5359fn default_confirmation_count() -> usize {
5360 50
5361}
5362
5363fn default_positive_response_rate() -> f64 {
5364 0.85
5365}
5366
5367fn default_exception_rate_confirm() -> f64 {
5368 0.10
5369}
5370
5371fn default_non_response_rate() -> f64 {
5372 0.05
5373}
5374
5375impl Default for ConfirmationsConfig {
5376 fn default() -> Self {
5377 Self {
5378 enabled: false,
5379 confirmation_count: default_confirmation_count(),
5380 positive_response_rate: default_positive_response_rate(),
5381 exception_rate: default_exception_rate_confirm(),
5382 non_response_rate: default_non_response_rate(),
5383 generate_alternative_procedures: true,
5384 }
5385 }
5386}
5387
5388#[derive(Debug, Clone, Serialize, Deserialize)]
5390pub struct AuditOpinionConfig {
5391 #[serde(default)]
5393 pub enabled: bool,
5394
5395 #[serde(default = "default_true")]
5397 pub generate_kam: bool,
5398
5399 #[serde(default = "default_kam_count")]
5401 pub average_kam_count: usize,
5402
5403 #[serde(default = "default_modified_opinion_rate")]
5405 pub modified_opinion_rate: f64,
5406
5407 #[serde(default)]
5409 pub include_emphasis_of_matter: bool,
5410
5411 #[serde(default = "default_true")]
5413 pub include_going_concern: bool,
5414}
5415
5416fn default_kam_count() -> usize {
5417 3
5418}
5419
5420fn default_modified_opinion_rate() -> f64 {
5421 0.05
5422}
5423
5424impl Default for AuditOpinionConfig {
5425 fn default() -> Self {
5426 Self {
5427 enabled: false,
5428 generate_kam: true,
5429 average_kam_count: default_kam_count(),
5430 modified_opinion_rate: default_modified_opinion_rate(),
5431 include_emphasis_of_matter: false,
5432 include_going_concern: true,
5433 }
5434 }
5435}
5436
5437#[derive(Debug, Clone, Serialize, Deserialize)]
5439pub struct SoxComplianceConfig {
5440 #[serde(default)]
5442 pub enabled: bool,
5443
5444 #[serde(default = "default_true")]
5446 pub generate_302_certifications: bool,
5447
5448 #[serde(default = "default_true")]
5450 pub generate_404_assessments: bool,
5451
5452 #[serde(default = "default_sox_materiality_threshold")]
5454 pub materiality_threshold: f64,
5455
5456 #[serde(default = "default_material_weakness_rate")]
5458 pub material_weakness_rate: f64,
5459
5460 #[serde(default = "default_significant_deficiency_rate")]
5462 pub significant_deficiency_rate: f64,
5463}
5464
5465fn default_material_weakness_rate() -> f64 {
5466 0.02
5467}
5468
5469fn default_significant_deficiency_rate() -> f64 {
5470 0.08
5471}
5472
5473impl Default for SoxComplianceConfig {
5474 fn default() -> Self {
5475 Self {
5476 enabled: false,
5477 generate_302_certifications: true,
5478 generate_404_assessments: true,
5479 materiality_threshold: default_sox_materiality_threshold(),
5480 material_weakness_rate: default_material_weakness_rate(),
5481 significant_deficiency_rate: default_significant_deficiency_rate(),
5482 }
5483 }
5484}
5485
5486#[derive(Debug, Clone, Serialize, Deserialize)]
5488pub struct PcaobConfig {
5489 #[serde(default)]
5491 pub enabled: bool,
5492
5493 #[serde(default)]
5495 pub is_pcaob_audit: bool,
5496
5497 #[serde(default = "default_true")]
5499 pub generate_cam: bool,
5500
5501 #[serde(default)]
5503 pub include_icfr_opinion: bool,
5504
5505 #[serde(default)]
5507 pub generate_standard_mappings: bool,
5508}
5509
5510impl Default for PcaobConfig {
5511 fn default() -> Self {
5512 Self {
5513 enabled: false,
5514 is_pcaob_audit: false,
5515 generate_cam: true,
5516 include_icfr_opinion: false,
5517 generate_standard_mappings: false,
5518 }
5519 }
5520}
5521
5522#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5535pub struct AdvancedDistributionConfig {
5536 #[serde(default)]
5538 pub enabled: bool,
5539
5540 #[serde(default)]
5542 pub amounts: MixtureDistributionSchemaConfig,
5543
5544 #[serde(default)]
5546 pub correlations: CorrelationSchemaConfig,
5547
5548 #[serde(default)]
5550 pub conditional: Vec<ConditionalDistributionSchemaConfig>,
5551
5552 #[serde(default)]
5554 pub regime_changes: RegimeChangeSchemaConfig,
5555
5556 #[serde(default)]
5558 pub industry_profile: Option<IndustryProfileType>,
5559
5560 #[serde(default)]
5562 pub validation: StatisticalValidationSchemaConfig,
5563}
5564
5565#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
5567#[serde(rename_all = "snake_case")]
5568pub enum IndustryProfileType {
5569 Retail,
5571 Manufacturing,
5573 FinancialServices,
5575 Healthcare,
5577 Technology,
5579}
5580
5581#[derive(Debug, Clone, Serialize, Deserialize)]
5583pub struct MixtureDistributionSchemaConfig {
5584 #[serde(default)]
5586 pub enabled: bool,
5587
5588 #[serde(default = "default_mixture_type")]
5590 pub distribution_type: MixtureDistributionType,
5591
5592 #[serde(default)]
5594 pub components: Vec<MixtureComponentConfig>,
5595
5596 #[serde(default = "default_min_amount")]
5598 pub min_value: f64,
5599
5600 #[serde(default)]
5602 pub max_value: Option<f64>,
5603
5604 #[serde(default = "default_decimal_places")]
5606 pub decimal_places: u8,
5607}
5608
5609fn default_mixture_type() -> MixtureDistributionType {
5610 MixtureDistributionType::LogNormal
5611}
5612
5613fn default_min_amount() -> f64 {
5614 0.01
5615}
5616
5617fn default_decimal_places() -> u8 {
5618 2
5619}
5620
5621impl Default for MixtureDistributionSchemaConfig {
5622 fn default() -> Self {
5623 Self {
5624 enabled: false,
5625 distribution_type: MixtureDistributionType::LogNormal,
5626 components: Vec::new(),
5627 min_value: 0.01,
5628 max_value: None,
5629 decimal_places: 2,
5630 }
5631 }
5632}
5633
5634#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5636#[serde(rename_all = "snake_case")]
5637pub enum MixtureDistributionType {
5638 Gaussian,
5640 #[default]
5642 LogNormal,
5643}
5644
5645#[derive(Debug, Clone, Serialize, Deserialize)]
5647pub struct MixtureComponentConfig {
5648 pub weight: f64,
5650
5651 pub mu: f64,
5653
5654 pub sigma: f64,
5656
5657 #[serde(default)]
5659 pub label: Option<String>,
5660}
5661
5662#[derive(Debug, Clone, Serialize, Deserialize)]
5664pub struct CorrelationSchemaConfig {
5665 #[serde(default)]
5667 pub enabled: bool,
5668
5669 #[serde(default)]
5671 pub copula_type: CopulaSchemaType,
5672
5673 #[serde(default)]
5675 pub fields: Vec<CorrelatedFieldConfig>,
5676
5677 #[serde(default)]
5680 pub matrix: Vec<f64>,
5681
5682 #[serde(default)]
5684 pub expected_correlations: Vec<ExpectedCorrelationConfig>,
5685}
5686
5687impl Default for CorrelationSchemaConfig {
5688 fn default() -> Self {
5689 Self {
5690 enabled: false,
5691 copula_type: CopulaSchemaType::Gaussian,
5692 fields: Vec::new(),
5693 matrix: Vec::new(),
5694 expected_correlations: Vec::new(),
5695 }
5696 }
5697}
5698
5699#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5701#[serde(rename_all = "snake_case")]
5702pub enum CopulaSchemaType {
5703 #[default]
5705 Gaussian,
5706 Clayton,
5708 Gumbel,
5710 Frank,
5712 StudentT,
5714}
5715
5716#[derive(Debug, Clone, Serialize, Deserialize)]
5718pub struct CorrelatedFieldConfig {
5719 pub name: String,
5721
5722 #[serde(default)]
5724 pub distribution: MarginalDistributionConfig,
5725}
5726
5727#[derive(Debug, Clone, Serialize, Deserialize)]
5729#[serde(tag = "type", rename_all = "snake_case")]
5730pub enum MarginalDistributionConfig {
5731 Normal {
5733 mu: f64,
5735 sigma: f64,
5737 },
5738 LogNormal {
5740 mu: f64,
5742 sigma: f64,
5744 },
5745 Uniform {
5747 min: f64,
5749 max: f64,
5751 },
5752 DiscreteUniform {
5754 min: i32,
5756 max: i32,
5758 },
5759}
5760
5761impl Default for MarginalDistributionConfig {
5762 fn default() -> Self {
5763 Self::Normal {
5764 mu: 0.0,
5765 sigma: 1.0,
5766 }
5767 }
5768}
5769
5770#[derive(Debug, Clone, Serialize, Deserialize)]
5772pub struct ExpectedCorrelationConfig {
5773 pub field1: String,
5775 pub field2: String,
5777 pub expected_r: f64,
5779 #[serde(default = "default_correlation_tolerance")]
5781 pub tolerance: f64,
5782}
5783
5784fn default_correlation_tolerance() -> f64 {
5785 0.10
5786}
5787
5788#[derive(Debug, Clone, Serialize, Deserialize)]
5790pub struct ConditionalDistributionSchemaConfig {
5791 pub output_field: String,
5793
5794 pub input_field: String,
5796
5797 #[serde(default)]
5799 pub breakpoints: Vec<ConditionalBreakpointConfig>,
5800
5801 #[serde(default)]
5803 pub default_distribution: ConditionalDistributionParamsConfig,
5804
5805 #[serde(default)]
5807 pub min_value: Option<f64>,
5808
5809 #[serde(default)]
5811 pub max_value: Option<f64>,
5812
5813 #[serde(default = "default_decimal_places")]
5815 pub decimal_places: u8,
5816}
5817
5818#[derive(Debug, Clone, Serialize, Deserialize)]
5820pub struct ConditionalBreakpointConfig {
5821 pub threshold: f64,
5823
5824 pub distribution: ConditionalDistributionParamsConfig,
5826}
5827
5828#[derive(Debug, Clone, Serialize, Deserialize)]
5830#[serde(tag = "type", rename_all = "snake_case")]
5831pub enum ConditionalDistributionParamsConfig {
5832 Fixed {
5834 value: f64,
5836 },
5837 Normal {
5839 mu: f64,
5841 sigma: f64,
5843 },
5844 LogNormal {
5846 mu: f64,
5848 sigma: f64,
5850 },
5851 Uniform {
5853 min: f64,
5855 max: f64,
5857 },
5858 Beta {
5860 alpha: f64,
5862 beta: f64,
5864 min: f64,
5866 max: f64,
5868 },
5869 Discrete {
5871 values: Vec<f64>,
5873 weights: Vec<f64>,
5875 },
5876}
5877
5878impl Default for ConditionalDistributionParamsConfig {
5879 fn default() -> Self {
5880 Self::Normal {
5881 mu: 0.0,
5882 sigma: 1.0,
5883 }
5884 }
5885}
5886
5887#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5889pub struct RegimeChangeSchemaConfig {
5890 #[serde(default)]
5892 pub enabled: bool,
5893
5894 #[serde(default)]
5896 pub changes: Vec<RegimeChangeEventConfig>,
5897
5898 #[serde(default)]
5900 pub economic_cycle: Option<EconomicCycleSchemaConfig>,
5901
5902 #[serde(default)]
5904 pub parameter_drifts: Vec<ParameterDriftSchemaConfig>,
5905}
5906
5907#[derive(Debug, Clone, Serialize, Deserialize)]
5909pub struct RegimeChangeEventConfig {
5910 pub date: String,
5912
5913 pub change_type: RegimeChangeTypeConfig,
5915
5916 #[serde(default)]
5918 pub description: Option<String>,
5919
5920 #[serde(default)]
5922 pub effects: Vec<RegimeEffectConfig>,
5923}
5924
5925#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
5927#[serde(rename_all = "snake_case")]
5928pub enum RegimeChangeTypeConfig {
5929 Acquisition,
5931 Divestiture,
5933 PriceIncrease,
5935 PriceDecrease,
5937 ProductLaunch,
5939 ProductDiscontinuation,
5941 PolicyChange,
5943 CompetitorEntry,
5945 Custom,
5947}
5948
5949#[derive(Debug, Clone, Serialize, Deserialize)]
5951pub struct RegimeEffectConfig {
5952 pub field: String,
5954
5955 pub multiplier: f64,
5957}
5958
5959#[derive(Debug, Clone, Serialize, Deserialize)]
5961pub struct EconomicCycleSchemaConfig {
5962 #[serde(default)]
5964 pub enabled: bool,
5965
5966 #[serde(default = "default_cycle_period")]
5968 pub period_months: u32,
5969
5970 #[serde(default = "default_cycle_amplitude")]
5972 pub amplitude: f64,
5973
5974 #[serde(default)]
5976 pub phase_offset: u32,
5977
5978 #[serde(default)]
5980 pub recessions: Vec<RecessionPeriodConfig>,
5981}
5982
5983fn default_cycle_period() -> u32 {
5984 48
5985}
5986
5987fn default_cycle_amplitude() -> f64 {
5988 0.15
5989}
5990
5991impl Default for EconomicCycleSchemaConfig {
5992 fn default() -> Self {
5993 Self {
5994 enabled: false,
5995 period_months: 48,
5996 amplitude: 0.15,
5997 phase_offset: 0,
5998 recessions: Vec::new(),
5999 }
6000 }
6001}
6002
6003#[derive(Debug, Clone, Serialize, Deserialize)]
6005pub struct RecessionPeriodConfig {
6006 pub start_month: u32,
6008
6009 pub duration_months: u32,
6011
6012 #[serde(default = "default_recession_severity")]
6014 pub severity: f64,
6015}
6016
6017fn default_recession_severity() -> f64 {
6018 0.20
6019}
6020
6021#[derive(Debug, Clone, Serialize, Deserialize)]
6023pub struct ParameterDriftSchemaConfig {
6024 pub parameter: String,
6026
6027 pub drift_type: ParameterDriftTypeConfig,
6029
6030 pub start_value: f64,
6032
6033 pub end_value: f64,
6035
6036 #[serde(default)]
6038 pub start_period: u32,
6039
6040 #[serde(default)]
6042 pub end_period: Option<u32>,
6043}
6044
6045#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
6047#[serde(rename_all = "snake_case")]
6048pub enum ParameterDriftTypeConfig {
6049 #[default]
6051 Linear,
6052 Exponential,
6054 Logistic,
6056 Step,
6058}
6059
6060#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6062pub struct StatisticalValidationSchemaConfig {
6063 #[serde(default)]
6065 pub enabled: bool,
6066
6067 #[serde(default)]
6069 pub tests: Vec<StatisticalTestConfig>,
6070
6071 #[serde(default)]
6073 pub reporting: ValidationReportingConfig,
6074}
6075
6076#[derive(Debug, Clone, Serialize, Deserialize)]
6078#[serde(tag = "type", rename_all = "snake_case")]
6079pub enum StatisticalTestConfig {
6080 BenfordFirstDigit {
6082 #[serde(default = "default_benford_threshold")]
6084 threshold_mad: f64,
6085 #[serde(default = "default_benford_warning")]
6087 warning_mad: f64,
6088 },
6089 DistributionFit {
6091 target: TargetDistributionConfig,
6093 #[serde(default = "default_ks_significance")]
6095 ks_significance: f64,
6096 #[serde(default)]
6098 method: DistributionFitMethod,
6099 },
6100 CorrelationCheck {
6102 expected_correlations: Vec<ExpectedCorrelationConfig>,
6104 },
6105 ChiSquared {
6107 #[serde(default = "default_chi_squared_bins")]
6109 bins: usize,
6110 #[serde(default = "default_chi_squared_significance")]
6112 significance: f64,
6113 },
6114 AndersonDarling {
6116 target: TargetDistributionConfig,
6118 #[serde(default = "default_ad_significance")]
6120 significance: f64,
6121 },
6122}
6123
6124fn default_benford_threshold() -> f64 {
6125 0.015
6126}
6127
6128fn default_benford_warning() -> f64 {
6129 0.010
6130}
6131
6132fn default_ks_significance() -> f64 {
6133 0.05
6134}
6135
6136fn default_chi_squared_bins() -> usize {
6137 10
6138}
6139
6140fn default_chi_squared_significance() -> f64 {
6141 0.05
6142}
6143
6144fn default_ad_significance() -> f64 {
6145 0.05
6146}
6147
6148#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
6150#[serde(rename_all = "snake_case")]
6151pub enum TargetDistributionConfig {
6152 Normal,
6154 #[default]
6156 LogNormal,
6157 Exponential,
6159 Uniform,
6161}
6162
6163#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
6165#[serde(rename_all = "snake_case")]
6166pub enum DistributionFitMethod {
6167 #[default]
6169 KolmogorovSmirnov,
6170 AndersonDarling,
6172 ChiSquared,
6174}
6175
6176#[derive(Debug, Clone, Serialize, Deserialize)]
6178pub struct ValidationReportingConfig {
6179 #[serde(default)]
6181 pub output_report: bool,
6182
6183 #[serde(default)]
6185 pub format: ValidationReportFormat,
6186
6187 #[serde(default)]
6189 pub fail_on_error: bool,
6190
6191 #[serde(default = "default_true")]
6193 pub include_details: bool,
6194}
6195
6196impl Default for ValidationReportingConfig {
6197 fn default() -> Self {
6198 Self {
6199 output_report: false,
6200 format: ValidationReportFormat::Json,
6201 fail_on_error: false,
6202 include_details: true,
6203 }
6204 }
6205}
6206
6207#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
6209#[serde(rename_all = "snake_case")]
6210pub enum ValidationReportFormat {
6211 #[default]
6213 Json,
6214 Yaml,
6216 Html,
6218}
6219
6220#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6232pub struct TemporalPatternsConfig {
6233 #[serde(default)]
6235 pub enabled: bool,
6236
6237 #[serde(default)]
6239 pub business_days: BusinessDaySchemaConfig,
6240
6241 #[serde(default)]
6243 pub calendars: CalendarSchemaConfig,
6244
6245 #[serde(default)]
6247 pub period_end: PeriodEndSchemaConfig,
6248
6249 #[serde(default)]
6251 pub processing_lags: ProcessingLagSchemaConfig,
6252
6253 #[serde(default)]
6255 pub fiscal_calendar: FiscalCalendarSchemaConfig,
6256
6257 #[serde(default)]
6259 pub intraday: IntraDaySchemaConfig,
6260
6261 #[serde(default)]
6263 pub timezones: TimezoneSchemaConfig,
6264}
6265
6266#[derive(Debug, Clone, Serialize, Deserialize)]
6268pub struct BusinessDaySchemaConfig {
6269 #[serde(default = "default_true")]
6271 pub enabled: bool,
6272
6273 #[serde(default = "default_half_day_policy")]
6275 pub half_day_policy: String,
6276
6277 #[serde(default)]
6279 pub settlement_rules: SettlementRulesSchemaConfig,
6280
6281 #[serde(default = "default_month_end_convention")]
6283 pub month_end_convention: String,
6284
6285 #[serde(default)]
6287 pub weekend_days: Option<Vec<String>>,
6288}
6289
6290fn default_half_day_policy() -> String {
6291 "half_day".to_string()
6292}
6293
6294fn default_month_end_convention() -> String {
6295 "modified_following".to_string()
6296}
6297
6298impl Default for BusinessDaySchemaConfig {
6299 fn default() -> Self {
6300 Self {
6301 enabled: true,
6302 half_day_policy: "half_day".to_string(),
6303 settlement_rules: SettlementRulesSchemaConfig::default(),
6304 month_end_convention: "modified_following".to_string(),
6305 weekend_days: None,
6306 }
6307 }
6308}
6309
6310#[derive(Debug, Clone, Serialize, Deserialize)]
6312pub struct SettlementRulesSchemaConfig {
6313 #[serde(default = "default_settlement_2")]
6315 pub equity_days: i32,
6316
6317 #[serde(default = "default_settlement_1")]
6319 pub government_bonds_days: i32,
6320
6321 #[serde(default = "default_settlement_2")]
6323 pub fx_spot_days: i32,
6324
6325 #[serde(default = "default_settlement_2")]
6327 pub corporate_bonds_days: i32,
6328
6329 #[serde(default = "default_wire_cutoff")]
6331 pub wire_cutoff_time: String,
6332
6333 #[serde(default = "default_settlement_1")]
6335 pub wire_international_days: i32,
6336
6337 #[serde(default = "default_settlement_1")]
6339 pub ach_days: i32,
6340}
6341
6342fn default_settlement_1() -> i32 {
6343 1
6344}
6345
6346fn default_settlement_2() -> i32 {
6347 2
6348}
6349
6350fn default_wire_cutoff() -> String {
6351 "14:00".to_string()
6352}
6353
6354impl Default for SettlementRulesSchemaConfig {
6355 fn default() -> Self {
6356 Self {
6357 equity_days: 2,
6358 government_bonds_days: 1,
6359 fx_spot_days: 2,
6360 corporate_bonds_days: 2,
6361 wire_cutoff_time: "14:00".to_string(),
6362 wire_international_days: 1,
6363 ach_days: 1,
6364 }
6365 }
6366}
6367
6368#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6370pub struct CalendarSchemaConfig {
6371 #[serde(default)]
6373 pub regions: Vec<String>,
6374
6375 #[serde(default)]
6377 pub custom_holidays: Vec<CustomHolidaySchemaConfig>,
6378}
6379
6380#[derive(Debug, Clone, Serialize, Deserialize)]
6382pub struct CustomHolidaySchemaConfig {
6383 pub name: String,
6385 pub month: u8,
6387 pub day: u8,
6389 #[serde(default = "default_holiday_multiplier")]
6391 pub activity_multiplier: f64,
6392}
6393
6394fn default_holiday_multiplier() -> f64 {
6395 0.05
6396}
6397
6398#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6400pub struct PeriodEndSchemaConfig {
6401 #[serde(default)]
6403 pub model: Option<String>,
6404
6405 #[serde(default)]
6407 pub month_end: Option<PeriodEndModelSchemaConfig>,
6408
6409 #[serde(default)]
6411 pub quarter_end: Option<PeriodEndModelSchemaConfig>,
6412
6413 #[serde(default)]
6415 pub year_end: Option<PeriodEndModelSchemaConfig>,
6416}
6417
6418#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6420pub struct PeriodEndModelSchemaConfig {
6421 #[serde(default)]
6423 pub inherit_from: Option<String>,
6424
6425 #[serde(default)]
6427 pub additional_multiplier: Option<f64>,
6428
6429 #[serde(default)]
6431 pub start_day: Option<i32>,
6432
6433 #[serde(default)]
6435 pub base_multiplier: Option<f64>,
6436
6437 #[serde(default)]
6439 pub peak_multiplier: Option<f64>,
6440
6441 #[serde(default)]
6443 pub decay_rate: Option<f64>,
6444
6445 #[serde(default)]
6447 pub sustained_high_days: Option<i32>,
6448}
6449
6450#[derive(Debug, Clone, Serialize, Deserialize)]
6452pub struct ProcessingLagSchemaConfig {
6453 #[serde(default = "default_true")]
6455 pub enabled: bool,
6456
6457 #[serde(default)]
6459 pub sales_order_lag: Option<LagDistributionSchemaConfig>,
6460
6461 #[serde(default)]
6463 pub purchase_order_lag: Option<LagDistributionSchemaConfig>,
6464
6465 #[serde(default)]
6467 pub goods_receipt_lag: Option<LagDistributionSchemaConfig>,
6468
6469 #[serde(default)]
6471 pub invoice_receipt_lag: Option<LagDistributionSchemaConfig>,
6472
6473 #[serde(default)]
6475 pub invoice_issue_lag: Option<LagDistributionSchemaConfig>,
6476
6477 #[serde(default)]
6479 pub payment_lag: Option<LagDistributionSchemaConfig>,
6480
6481 #[serde(default)]
6483 pub journal_entry_lag: Option<LagDistributionSchemaConfig>,
6484
6485 #[serde(default)]
6487 pub cross_day_posting: Option<CrossDayPostingSchemaConfig>,
6488}
6489
6490impl Default for ProcessingLagSchemaConfig {
6491 fn default() -> Self {
6492 Self {
6493 enabled: true,
6494 sales_order_lag: None,
6495 purchase_order_lag: None,
6496 goods_receipt_lag: None,
6497 invoice_receipt_lag: None,
6498 invoice_issue_lag: None,
6499 payment_lag: None,
6500 journal_entry_lag: None,
6501 cross_day_posting: None,
6502 }
6503 }
6504}
6505
6506#[derive(Debug, Clone, Serialize, Deserialize)]
6508pub struct LagDistributionSchemaConfig {
6509 pub mu: f64,
6511 pub sigma: f64,
6513 #[serde(default)]
6515 pub min_hours: Option<f64>,
6516 #[serde(default)]
6518 pub max_hours: Option<f64>,
6519}
6520
6521#[derive(Debug, Clone, Serialize, Deserialize)]
6523pub struct CrossDayPostingSchemaConfig {
6524 #[serde(default = "default_true")]
6526 pub enabled: bool,
6527
6528 #[serde(default)]
6531 pub probability_by_hour: std::collections::HashMap<u8, f64>,
6532}
6533
6534impl Default for CrossDayPostingSchemaConfig {
6535 fn default() -> Self {
6536 let mut probability_by_hour = std::collections::HashMap::new();
6537 probability_by_hour.insert(17, 0.3);
6538 probability_by_hour.insert(18, 0.6);
6539 probability_by_hour.insert(19, 0.8);
6540 probability_by_hour.insert(20, 0.9);
6541 probability_by_hour.insert(21, 0.95);
6542 probability_by_hour.insert(22, 0.99);
6543
6544 Self {
6545 enabled: true,
6546 probability_by_hour,
6547 }
6548 }
6549}
6550
6551#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6560pub struct FiscalCalendarSchemaConfig {
6561 #[serde(default)]
6563 pub enabled: bool,
6564
6565 #[serde(default = "default_fiscal_calendar_type")]
6567 pub calendar_type: String,
6568
6569 #[serde(default)]
6571 pub year_start_month: Option<u8>,
6572
6573 #[serde(default)]
6575 pub year_start_day: Option<u8>,
6576
6577 #[serde(default)]
6579 pub four_four_five: Option<FourFourFiveSchemaConfig>,
6580}
6581
6582fn default_fiscal_calendar_type() -> String {
6583 "calendar_year".to_string()
6584}
6585
6586#[derive(Debug, Clone, Serialize, Deserialize)]
6588pub struct FourFourFiveSchemaConfig {
6589 #[serde(default = "default_week_pattern")]
6591 pub pattern: String,
6592
6593 #[serde(default = "default_anchor_type")]
6595 pub anchor_type: String,
6596
6597 #[serde(default = "default_anchor_month")]
6599 pub anchor_month: u8,
6600
6601 #[serde(default = "default_leap_week_placement")]
6603 pub leap_week_placement: String,
6604}
6605
6606fn default_week_pattern() -> String {
6607 "four_four_five".to_string()
6608}
6609
6610fn default_anchor_type() -> String {
6611 "last_saturday".to_string()
6612}
6613
6614fn default_anchor_month() -> u8 {
6615 1 }
6617
6618fn default_leap_week_placement() -> String {
6619 "q4_period3".to_string()
6620}
6621
6622impl Default for FourFourFiveSchemaConfig {
6623 fn default() -> Self {
6624 Self {
6625 pattern: "four_four_five".to_string(),
6626 anchor_type: "last_saturday".to_string(),
6627 anchor_month: 1,
6628 leap_week_placement: "q4_period3".to_string(),
6629 }
6630 }
6631}
6632
6633#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6642pub struct IntraDaySchemaConfig {
6643 #[serde(default)]
6645 pub enabled: bool,
6646
6647 #[serde(default)]
6649 pub segments: Vec<IntraDaySegmentSchemaConfig>,
6650}
6651
6652#[derive(Debug, Clone, Serialize, Deserialize)]
6654pub struct IntraDaySegmentSchemaConfig {
6655 pub name: String,
6657
6658 pub start: String,
6660
6661 pub end: String,
6663
6664 #[serde(default = "default_multiplier")]
6666 pub multiplier: f64,
6667
6668 #[serde(default = "default_posting_type")]
6670 pub posting_type: String,
6671}
6672
6673fn default_multiplier() -> f64 {
6674 1.0
6675}
6676
6677fn default_posting_type() -> String {
6678 "both".to_string()
6679}
6680
6681#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6687pub struct TimezoneSchemaConfig {
6688 #[serde(default)]
6690 pub enabled: bool,
6691
6692 #[serde(default = "default_timezone")]
6694 pub default_timezone: String,
6695
6696 #[serde(default = "default_consolidation_timezone")]
6698 pub consolidation_timezone: String,
6699
6700 #[serde(default)]
6703 pub entity_mappings: Vec<EntityTimezoneMapping>,
6704}
6705
6706fn default_timezone() -> String {
6707 "America/New_York".to_string()
6708}
6709
6710fn default_consolidation_timezone() -> String {
6711 "UTC".to_string()
6712}
6713
6714#[derive(Debug, Clone, Serialize, Deserialize)]
6716pub struct EntityTimezoneMapping {
6717 pub pattern: String,
6719
6720 pub timezone: String,
6722}
6723
6724#[derive(Debug, Clone, Serialize, Deserialize)]
6730pub struct VendorNetworkSchemaConfig {
6731 #[serde(default)]
6733 pub enabled: bool,
6734
6735 #[serde(default = "default_vendor_tier_depth")]
6737 pub depth: u8,
6738
6739 #[serde(default)]
6741 pub tier1: TierCountSchemaConfig,
6742
6743 #[serde(default)]
6745 pub tier2_per_parent: TierCountSchemaConfig,
6746
6747 #[serde(default)]
6749 pub tier3_per_parent: TierCountSchemaConfig,
6750
6751 #[serde(default)]
6753 pub clusters: VendorClusterSchemaConfig,
6754
6755 #[serde(default)]
6757 pub dependencies: DependencySchemaConfig,
6758}
6759
6760fn default_vendor_tier_depth() -> u8 {
6761 3
6762}
6763
6764impl Default for VendorNetworkSchemaConfig {
6765 fn default() -> Self {
6766 Self {
6767 enabled: false,
6768 depth: 3,
6769 tier1: TierCountSchemaConfig { min: 50, max: 100 },
6770 tier2_per_parent: TierCountSchemaConfig { min: 4, max: 10 },
6771 tier3_per_parent: TierCountSchemaConfig { min: 2, max: 5 },
6772 clusters: VendorClusterSchemaConfig::default(),
6773 dependencies: DependencySchemaConfig::default(),
6774 }
6775 }
6776}
6777
6778#[derive(Debug, Clone, Serialize, Deserialize)]
6780pub struct TierCountSchemaConfig {
6781 #[serde(default = "default_tier_min")]
6783 pub min: usize,
6784
6785 #[serde(default = "default_tier_max")]
6787 pub max: usize,
6788}
6789
6790fn default_tier_min() -> usize {
6791 5
6792}
6793
6794fn default_tier_max() -> usize {
6795 20
6796}
6797
6798impl Default for TierCountSchemaConfig {
6799 fn default() -> Self {
6800 Self {
6801 min: default_tier_min(),
6802 max: default_tier_max(),
6803 }
6804 }
6805}
6806
6807#[derive(Debug, Clone, Serialize, Deserialize)]
6809pub struct VendorClusterSchemaConfig {
6810 #[serde(default = "default_reliable_strategic")]
6812 pub reliable_strategic: f64,
6813
6814 #[serde(default = "default_standard_operational")]
6816 pub standard_operational: f64,
6817
6818 #[serde(default = "default_transactional")]
6820 pub transactional: f64,
6821
6822 #[serde(default = "default_problematic")]
6824 pub problematic: f64,
6825}
6826
6827fn default_reliable_strategic() -> f64 {
6828 0.20
6829}
6830
6831fn default_standard_operational() -> f64 {
6832 0.50
6833}
6834
6835fn default_transactional() -> f64 {
6836 0.25
6837}
6838
6839fn default_problematic() -> f64 {
6840 0.05
6841}
6842
6843impl Default for VendorClusterSchemaConfig {
6844 fn default() -> Self {
6845 Self {
6846 reliable_strategic: 0.20,
6847 standard_operational: 0.50,
6848 transactional: 0.25,
6849 problematic: 0.05,
6850 }
6851 }
6852}
6853
6854#[derive(Debug, Clone, Serialize, Deserialize)]
6856pub struct DependencySchemaConfig {
6857 #[serde(default = "default_max_single_vendor")]
6859 pub max_single_vendor_concentration: f64,
6860
6861 #[serde(default = "default_max_top5")]
6863 pub top_5_concentration: f64,
6864
6865 #[serde(default = "default_single_source_percent")]
6867 pub single_source_percent: f64,
6868}
6869
6870fn default_max_single_vendor() -> f64 {
6871 0.15
6872}
6873
6874fn default_max_top5() -> f64 {
6875 0.45
6876}
6877
6878fn default_single_source_percent() -> f64 {
6879 0.05
6880}
6881
6882impl Default for DependencySchemaConfig {
6883 fn default() -> Self {
6884 Self {
6885 max_single_vendor_concentration: 0.15,
6886 top_5_concentration: 0.45,
6887 single_source_percent: 0.05,
6888 }
6889 }
6890}
6891
6892#[derive(Debug, Clone, Default, Serialize, Deserialize)]
6898pub struct CustomerSegmentationSchemaConfig {
6899 #[serde(default)]
6901 pub enabled: bool,
6902
6903 #[serde(default)]
6905 pub value_segments: ValueSegmentsSchemaConfig,
6906
6907 #[serde(default)]
6909 pub lifecycle: LifecycleSchemaConfig,
6910
6911 #[serde(default)]
6913 pub networks: CustomerNetworksSchemaConfig,
6914}
6915
6916#[derive(Debug, Clone, Serialize, Deserialize)]
6918pub struct ValueSegmentsSchemaConfig {
6919 #[serde(default)]
6921 pub enterprise: SegmentDetailSchemaConfig,
6922
6923 #[serde(default)]
6925 pub mid_market: SegmentDetailSchemaConfig,
6926
6927 #[serde(default)]
6929 pub smb: SegmentDetailSchemaConfig,
6930
6931 #[serde(default)]
6933 pub consumer: SegmentDetailSchemaConfig,
6934}
6935
6936impl Default for ValueSegmentsSchemaConfig {
6937 fn default() -> Self {
6938 Self {
6939 enterprise: SegmentDetailSchemaConfig {
6940 revenue_share: 0.40,
6941 customer_share: 0.05,
6942 avg_order_value_range: "50000+".to_string(),
6943 },
6944 mid_market: SegmentDetailSchemaConfig {
6945 revenue_share: 0.35,
6946 customer_share: 0.20,
6947 avg_order_value_range: "5000-50000".to_string(),
6948 },
6949 smb: SegmentDetailSchemaConfig {
6950 revenue_share: 0.20,
6951 customer_share: 0.50,
6952 avg_order_value_range: "500-5000".to_string(),
6953 },
6954 consumer: SegmentDetailSchemaConfig {
6955 revenue_share: 0.05,
6956 customer_share: 0.25,
6957 avg_order_value_range: "50-500".to_string(),
6958 },
6959 }
6960 }
6961}
6962
6963#[derive(Debug, Clone, Serialize, Deserialize)]
6965pub struct SegmentDetailSchemaConfig {
6966 #[serde(default)]
6968 pub revenue_share: f64,
6969
6970 #[serde(default)]
6972 pub customer_share: f64,
6973
6974 #[serde(default)]
6976 pub avg_order_value_range: String,
6977}
6978
6979impl Default for SegmentDetailSchemaConfig {
6980 fn default() -> Self {
6981 Self {
6982 revenue_share: 0.25,
6983 customer_share: 0.25,
6984 avg_order_value_range: "1000-10000".to_string(),
6985 }
6986 }
6987}
6988
6989#[derive(Debug, Clone, Serialize, Deserialize)]
6991pub struct LifecycleSchemaConfig {
6992 #[serde(default)]
6994 pub prospect_rate: f64,
6995
6996 #[serde(default = "default_new_rate")]
6998 pub new_rate: f64,
6999
7000 #[serde(default = "default_growth_rate")]
7002 pub growth_rate: f64,
7003
7004 #[serde(default = "default_mature_rate")]
7006 pub mature_rate: f64,
7007
7008 #[serde(default = "default_at_risk_rate")]
7010 pub at_risk_rate: f64,
7011
7012 #[serde(default = "default_churned_rate")]
7014 pub churned_rate: f64,
7015
7016 #[serde(default)]
7018 pub won_back_rate: f64,
7019}
7020
7021fn default_new_rate() -> f64 {
7022 0.10
7023}
7024
7025fn default_growth_rate() -> f64 {
7026 0.15
7027}
7028
7029fn default_mature_rate() -> f64 {
7030 0.60
7031}
7032
7033fn default_at_risk_rate() -> f64 {
7034 0.10
7035}
7036
7037fn default_churned_rate() -> f64 {
7038 0.05
7039}
7040
7041impl Default for LifecycleSchemaConfig {
7042 fn default() -> Self {
7043 Self {
7044 prospect_rate: 0.0,
7045 new_rate: 0.10,
7046 growth_rate: 0.15,
7047 mature_rate: 0.60,
7048 at_risk_rate: 0.10,
7049 churned_rate: 0.05,
7050 won_back_rate: 0.0,
7051 }
7052 }
7053}
7054
7055#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7057pub struct CustomerNetworksSchemaConfig {
7058 #[serde(default)]
7060 pub referrals: ReferralSchemaConfig,
7061
7062 #[serde(default)]
7064 pub corporate_hierarchies: HierarchySchemaConfig,
7065}
7066
7067#[derive(Debug, Clone, Serialize, Deserialize)]
7069pub struct ReferralSchemaConfig {
7070 #[serde(default = "default_true")]
7072 pub enabled: bool,
7073
7074 #[serde(default = "default_referral_rate")]
7076 pub referral_rate: f64,
7077}
7078
7079fn default_referral_rate() -> f64 {
7080 0.15
7081}
7082
7083impl Default for ReferralSchemaConfig {
7084 fn default() -> Self {
7085 Self {
7086 enabled: true,
7087 referral_rate: 0.15,
7088 }
7089 }
7090}
7091
7092#[derive(Debug, Clone, Serialize, Deserialize)]
7094pub struct HierarchySchemaConfig {
7095 #[serde(default = "default_true")]
7097 pub enabled: bool,
7098
7099 #[serde(default = "default_hierarchy_rate")]
7101 pub probability: f64,
7102}
7103
7104fn default_hierarchy_rate() -> f64 {
7105 0.30
7106}
7107
7108impl Default for HierarchySchemaConfig {
7109 fn default() -> Self {
7110 Self {
7111 enabled: true,
7112 probability: 0.30,
7113 }
7114 }
7115}
7116
7117#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7123pub struct RelationshipStrengthSchemaConfig {
7124 #[serde(default)]
7126 pub enabled: bool,
7127
7128 #[serde(default)]
7130 pub calculation: StrengthCalculationSchemaConfig,
7131
7132 #[serde(default)]
7134 pub thresholds: StrengthThresholdsSchemaConfig,
7135}
7136
7137#[derive(Debug, Clone, Serialize, Deserialize)]
7139pub struct StrengthCalculationSchemaConfig {
7140 #[serde(default = "default_volume_weight")]
7142 pub transaction_volume_weight: f64,
7143
7144 #[serde(default = "default_count_weight")]
7146 pub transaction_count_weight: f64,
7147
7148 #[serde(default = "default_duration_weight")]
7150 pub relationship_duration_weight: f64,
7151
7152 #[serde(default = "default_recency_weight")]
7154 pub recency_weight: f64,
7155
7156 #[serde(default = "default_mutual_weight")]
7158 pub mutual_connections_weight: f64,
7159
7160 #[serde(default = "default_recency_half_life")]
7162 pub recency_half_life_days: u32,
7163}
7164
7165fn default_volume_weight() -> f64 {
7166 0.30
7167}
7168
7169fn default_count_weight() -> f64 {
7170 0.25
7171}
7172
7173fn default_duration_weight() -> f64 {
7174 0.20
7175}
7176
7177fn default_recency_weight() -> f64 {
7178 0.15
7179}
7180
7181fn default_mutual_weight() -> f64 {
7182 0.10
7183}
7184
7185fn default_recency_half_life() -> u32 {
7186 90
7187}
7188
7189impl Default for StrengthCalculationSchemaConfig {
7190 fn default() -> Self {
7191 Self {
7192 transaction_volume_weight: 0.30,
7193 transaction_count_weight: 0.25,
7194 relationship_duration_weight: 0.20,
7195 recency_weight: 0.15,
7196 mutual_connections_weight: 0.10,
7197 recency_half_life_days: 90,
7198 }
7199 }
7200}
7201
7202#[derive(Debug, Clone, Serialize, Deserialize)]
7204pub struct StrengthThresholdsSchemaConfig {
7205 #[serde(default = "default_strong_threshold")]
7207 pub strong: f64,
7208
7209 #[serde(default = "default_moderate_threshold")]
7211 pub moderate: f64,
7212
7213 #[serde(default = "default_weak_threshold")]
7215 pub weak: f64,
7216}
7217
7218fn default_strong_threshold() -> f64 {
7219 0.7
7220}
7221
7222fn default_moderate_threshold() -> f64 {
7223 0.4
7224}
7225
7226fn default_weak_threshold() -> f64 {
7227 0.1
7228}
7229
7230impl Default for StrengthThresholdsSchemaConfig {
7231 fn default() -> Self {
7232 Self {
7233 strong: 0.7,
7234 moderate: 0.4,
7235 weak: 0.1,
7236 }
7237 }
7238}
7239
7240#[derive(Debug, Clone, Serialize, Deserialize)]
7246pub struct CrossProcessLinksSchemaConfig {
7247 #[serde(default)]
7249 pub enabled: bool,
7250
7251 #[serde(default = "default_true")]
7253 pub inventory_p2p_o2c: bool,
7254
7255 #[serde(default = "default_true")]
7257 pub payment_bank_reconciliation: bool,
7258
7259 #[serde(default = "default_true")]
7261 pub intercompany_bilateral: bool,
7262
7263 #[serde(default = "default_inventory_link_rate")]
7265 pub inventory_link_rate: f64,
7266}
7267
7268fn default_inventory_link_rate() -> f64 {
7269 0.30
7270}
7271
7272impl Default for CrossProcessLinksSchemaConfig {
7273 fn default() -> Self {
7274 Self {
7275 enabled: false,
7276 inventory_p2p_o2c: true,
7277 payment_bank_reconciliation: true,
7278 intercompany_bilateral: true,
7279 inventory_link_rate: 0.30,
7280 }
7281 }
7282}
7283
7284#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7290pub struct OrganizationalEventsSchemaConfig {
7291 #[serde(default)]
7293 pub enabled: bool,
7294
7295 #[serde(default)]
7297 pub effect_blending: EffectBlendingModeConfig,
7298
7299 #[serde(default)]
7301 pub events: Vec<OrganizationalEventSchemaConfig>,
7302
7303 #[serde(default)]
7305 pub process_evolution: Vec<ProcessEvolutionSchemaConfig>,
7306
7307 #[serde(default)]
7309 pub technology_transitions: Vec<TechnologyTransitionSchemaConfig>,
7310}
7311
7312#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
7314#[serde(rename_all = "snake_case")]
7315pub enum EffectBlendingModeConfig {
7316 #[default]
7318 Multiplicative,
7319 Additive,
7321 Maximum,
7323 Minimum,
7325}
7326
7327#[derive(Debug, Clone, Serialize, Deserialize)]
7329pub struct OrganizationalEventSchemaConfig {
7330 pub id: String,
7332
7333 pub event_type: OrganizationalEventTypeSchemaConfig,
7335
7336 pub effective_date: String,
7338
7339 #[serde(default = "default_org_transition_months")]
7341 pub transition_months: u32,
7342
7343 #[serde(default)]
7345 pub description: Option<String>,
7346}
7347
7348fn default_org_transition_months() -> u32 {
7349 6
7350}
7351
7352#[derive(Debug, Clone, Serialize, Deserialize)]
7354#[serde(tag = "type", rename_all = "snake_case")]
7355pub enum OrganizationalEventTypeSchemaConfig {
7356 Acquisition {
7358 acquired_entity: String,
7360 #[serde(default = "default_acquisition_volume")]
7362 volume_increase: f64,
7363 #[serde(default = "default_acquisition_error")]
7365 integration_error_rate: f64,
7366 #[serde(default = "default_parallel_days")]
7368 parallel_posting_days: u32,
7369 },
7370 Divestiture {
7372 divested_entity: String,
7374 #[serde(default = "default_divestiture_volume")]
7376 volume_reduction: f64,
7377 #[serde(default = "default_true_val")]
7379 remove_entity: bool,
7380 },
7381 Reorganization {
7383 #[serde(default)]
7385 cost_center_remapping: std::collections::HashMap<String, String>,
7386 #[serde(default = "default_reorg_error")]
7388 transition_error_rate: f64,
7389 },
7390 LeadershipChange {
7392 role: String,
7394 #[serde(default)]
7396 policy_changes: Vec<String>,
7397 },
7398 WorkforceReduction {
7400 #[serde(default = "default_workforce_reduction")]
7402 reduction_percent: f64,
7403 #[serde(default = "default_workforce_error")]
7405 error_rate_increase: f64,
7406 },
7407 Merger {
7409 merged_entity: String,
7411 #[serde(default = "default_merger_volume")]
7413 volume_increase: f64,
7414 },
7415}
7416
7417fn default_acquisition_volume() -> f64 {
7418 1.35
7419}
7420
7421fn default_acquisition_error() -> f64 {
7422 0.05
7423}
7424
7425fn default_parallel_days() -> u32 {
7426 30
7427}
7428
7429fn default_divestiture_volume() -> f64 {
7430 0.70
7431}
7432
7433fn default_true_val() -> bool {
7434 true
7435}
7436
7437fn default_reorg_error() -> f64 {
7438 0.04
7439}
7440
7441fn default_workforce_reduction() -> f64 {
7442 0.10
7443}
7444
7445fn default_workforce_error() -> f64 {
7446 0.05
7447}
7448
7449fn default_merger_volume() -> f64 {
7450 1.80
7451}
7452
7453#[derive(Debug, Clone, Serialize, Deserialize)]
7455pub struct ProcessEvolutionSchemaConfig {
7456 pub id: String,
7458
7459 pub event_type: ProcessEvolutionTypeSchemaConfig,
7461
7462 pub effective_date: String,
7464
7465 #[serde(default)]
7467 pub description: Option<String>,
7468}
7469
7470#[derive(Debug, Clone, Serialize, Deserialize)]
7472#[serde(tag = "type", rename_all = "snake_case")]
7473pub enum ProcessEvolutionTypeSchemaConfig {
7474 ProcessAutomation {
7476 process_name: String,
7478 #[serde(default = "default_manual_before")]
7480 manual_rate_before: f64,
7481 #[serde(default = "default_manual_after")]
7483 manual_rate_after: f64,
7484 },
7485 ApprovalWorkflowChange {
7487 description: String,
7489 },
7490 ControlEnhancement {
7492 control_id: String,
7494 #[serde(default = "default_error_reduction")]
7496 error_reduction: f64,
7497 },
7498}
7499
7500fn default_manual_before() -> f64 {
7501 0.80
7502}
7503
7504fn default_manual_after() -> f64 {
7505 0.15
7506}
7507
7508fn default_error_reduction() -> f64 {
7509 0.02
7510}
7511
7512#[derive(Debug, Clone, Serialize, Deserialize)]
7514pub struct TechnologyTransitionSchemaConfig {
7515 pub id: String,
7517
7518 pub event_type: TechnologyTransitionTypeSchemaConfig,
7520
7521 #[serde(default)]
7523 pub description: Option<String>,
7524}
7525
7526#[derive(Debug, Clone, Serialize, Deserialize)]
7528#[serde(tag = "type", rename_all = "snake_case")]
7529pub enum TechnologyTransitionTypeSchemaConfig {
7530 ErpMigration {
7532 source_system: String,
7534 target_system: String,
7536 cutover_date: String,
7538 stabilization_end: String,
7540 #[serde(default = "default_erp_duplicate_rate")]
7542 duplicate_rate: f64,
7543 #[serde(default = "default_format_mismatch")]
7545 format_mismatch_rate: f64,
7546 },
7547 ModuleImplementation {
7549 module_name: String,
7551 go_live_date: String,
7553 },
7554}
7555
7556fn default_erp_duplicate_rate() -> f64 {
7557 0.02
7558}
7559
7560fn default_format_mismatch() -> f64 {
7561 0.03
7562}
7563
7564#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7570pub struct BehavioralDriftSchemaConfig {
7571 #[serde(default)]
7573 pub enabled: bool,
7574
7575 #[serde(default)]
7577 pub vendor_behavior: VendorBehaviorSchemaConfig,
7578
7579 #[serde(default)]
7581 pub customer_behavior: CustomerBehaviorSchemaConfig,
7582
7583 #[serde(default)]
7585 pub employee_behavior: EmployeeBehaviorSchemaConfig,
7586
7587 #[serde(default)]
7589 pub collective: CollectiveBehaviorSchemaConfig,
7590}
7591
7592#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7594pub struct VendorBehaviorSchemaConfig {
7595 #[serde(default)]
7597 pub payment_terms_drift: PaymentTermsDriftSchemaConfig,
7598
7599 #[serde(default)]
7601 pub quality_drift: QualityDriftSchemaConfig,
7602}
7603
7604#[derive(Debug, Clone, Serialize, Deserialize)]
7606pub struct PaymentTermsDriftSchemaConfig {
7607 #[serde(default = "default_extension_rate")]
7609 pub extension_rate_per_year: f64,
7610
7611 #[serde(default = "default_economic_sensitivity")]
7613 pub economic_sensitivity: f64,
7614}
7615
7616fn default_extension_rate() -> f64 {
7617 2.5
7618}
7619
7620fn default_economic_sensitivity() -> f64 {
7621 1.0
7622}
7623
7624impl Default for PaymentTermsDriftSchemaConfig {
7625 fn default() -> Self {
7626 Self {
7627 extension_rate_per_year: 2.5,
7628 economic_sensitivity: 1.0,
7629 }
7630 }
7631}
7632
7633#[derive(Debug, Clone, Serialize, Deserialize)]
7635pub struct QualityDriftSchemaConfig {
7636 #[serde(default = "default_improvement_rate")]
7638 pub new_vendor_improvement_rate: f64,
7639
7640 #[serde(default = "default_decline_rate")]
7642 pub complacency_decline_rate: f64,
7643}
7644
7645fn default_improvement_rate() -> f64 {
7646 0.02
7647}
7648
7649fn default_decline_rate() -> f64 {
7650 0.01
7651}
7652
7653impl Default for QualityDriftSchemaConfig {
7654 fn default() -> Self {
7655 Self {
7656 new_vendor_improvement_rate: 0.02,
7657 complacency_decline_rate: 0.01,
7658 }
7659 }
7660}
7661
7662#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7664pub struct CustomerBehaviorSchemaConfig {
7665 #[serde(default)]
7667 pub payment_drift: CustomerPaymentDriftSchemaConfig,
7668
7669 #[serde(default)]
7671 pub order_drift: OrderDriftSchemaConfig,
7672}
7673
7674#[derive(Debug, Clone, Serialize, Deserialize)]
7676pub struct CustomerPaymentDriftSchemaConfig {
7677 #[serde(default = "default_downturn_extension")]
7679 pub downturn_days_extension: (u32, u32),
7680
7681 #[serde(default = "default_bad_debt_increase")]
7683 pub downturn_bad_debt_increase: f64,
7684}
7685
7686fn default_downturn_extension() -> (u32, u32) {
7687 (5, 15)
7688}
7689
7690fn default_bad_debt_increase() -> f64 {
7691 0.02
7692}
7693
7694impl Default for CustomerPaymentDriftSchemaConfig {
7695 fn default() -> Self {
7696 Self {
7697 downturn_days_extension: (5, 15),
7698 downturn_bad_debt_increase: 0.02,
7699 }
7700 }
7701}
7702
7703#[derive(Debug, Clone, Serialize, Deserialize)]
7705pub struct OrderDriftSchemaConfig {
7706 #[serde(default = "default_digital_shift")]
7708 pub digital_shift_rate: f64,
7709}
7710
7711fn default_digital_shift() -> f64 {
7712 0.05
7713}
7714
7715impl Default for OrderDriftSchemaConfig {
7716 fn default() -> Self {
7717 Self {
7718 digital_shift_rate: 0.05,
7719 }
7720 }
7721}
7722
7723#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7725pub struct EmployeeBehaviorSchemaConfig {
7726 #[serde(default)]
7728 pub approval_drift: ApprovalDriftSchemaConfig,
7729
7730 #[serde(default)]
7732 pub error_drift: ErrorDriftSchemaConfig,
7733}
7734
7735#[derive(Debug, Clone, Serialize, Deserialize)]
7737pub struct ApprovalDriftSchemaConfig {
7738 #[serde(default = "default_eom_intensity")]
7740 pub eom_intensity_increase_per_year: f64,
7741
7742 #[serde(default = "default_rubber_stamp")]
7744 pub rubber_stamp_volume_threshold: u32,
7745}
7746
7747fn default_eom_intensity() -> f64 {
7748 0.05
7749}
7750
7751fn default_rubber_stamp() -> u32 {
7752 50
7753}
7754
7755impl Default for ApprovalDriftSchemaConfig {
7756 fn default() -> Self {
7757 Self {
7758 eom_intensity_increase_per_year: 0.05,
7759 rubber_stamp_volume_threshold: 50,
7760 }
7761 }
7762}
7763
7764#[derive(Debug, Clone, Serialize, Deserialize)]
7766pub struct ErrorDriftSchemaConfig {
7767 #[serde(default = "default_new_error")]
7769 pub new_employee_error_rate: f64,
7770
7771 #[serde(default = "default_learning_months")]
7773 pub learning_curve_months: u32,
7774}
7775
7776fn default_new_error() -> f64 {
7777 0.08
7778}
7779
7780fn default_learning_months() -> u32 {
7781 6
7782}
7783
7784impl Default for ErrorDriftSchemaConfig {
7785 fn default() -> Self {
7786 Self {
7787 new_employee_error_rate: 0.08,
7788 learning_curve_months: 6,
7789 }
7790 }
7791}
7792
7793#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7795pub struct CollectiveBehaviorSchemaConfig {
7796 #[serde(default)]
7798 pub automation_adoption: AutomationAdoptionSchemaConfig,
7799}
7800
7801#[derive(Debug, Clone, Serialize, Deserialize)]
7803pub struct AutomationAdoptionSchemaConfig {
7804 #[serde(default)]
7806 pub s_curve_enabled: bool,
7807
7808 #[serde(default = "default_midpoint")]
7810 pub adoption_midpoint_months: u32,
7811
7812 #[serde(default = "default_steepness")]
7814 pub steepness: f64,
7815}
7816
7817fn default_midpoint() -> u32 {
7818 24
7819}
7820
7821fn default_steepness() -> f64 {
7822 0.15
7823}
7824
7825impl Default for AutomationAdoptionSchemaConfig {
7826 fn default() -> Self {
7827 Self {
7828 s_curve_enabled: false,
7829 adoption_midpoint_months: 24,
7830 steepness: 0.15,
7831 }
7832 }
7833}
7834
7835#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7841pub struct MarketDriftSchemaConfig {
7842 #[serde(default)]
7844 pub enabled: bool,
7845
7846 #[serde(default)]
7848 pub economic_cycle: MarketEconomicCycleSchemaConfig,
7849
7850 #[serde(default)]
7852 pub industry_cycles: std::collections::HashMap<String, IndustryCycleSchemaConfig>,
7853
7854 #[serde(default)]
7856 pub commodities: CommoditiesSchemaConfig,
7857}
7858
7859#[derive(Debug, Clone, Serialize, Deserialize)]
7861pub struct MarketEconomicCycleSchemaConfig {
7862 #[serde(default)]
7864 pub enabled: bool,
7865
7866 #[serde(default)]
7868 pub cycle_type: CycleTypeSchemaConfig,
7869
7870 #[serde(default = "default_market_cycle_period")]
7872 pub period_months: u32,
7873
7874 #[serde(default = "default_market_amplitude")]
7876 pub amplitude: f64,
7877
7878 #[serde(default)]
7880 pub recession: RecessionSchemaConfig,
7881}
7882
7883fn default_market_cycle_period() -> u32 {
7884 48
7885}
7886
7887fn default_market_amplitude() -> f64 {
7888 0.15
7889}
7890
7891impl Default for MarketEconomicCycleSchemaConfig {
7892 fn default() -> Self {
7893 Self {
7894 enabled: false,
7895 cycle_type: CycleTypeSchemaConfig::Sinusoidal,
7896 period_months: 48,
7897 amplitude: 0.15,
7898 recession: RecessionSchemaConfig::default(),
7899 }
7900 }
7901}
7902
7903#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
7905#[serde(rename_all = "snake_case")]
7906pub enum CycleTypeSchemaConfig {
7907 #[default]
7909 Sinusoidal,
7910 Asymmetric,
7912 MeanReverting,
7914}
7915
7916#[derive(Debug, Clone, Serialize, Deserialize)]
7918pub struct RecessionSchemaConfig {
7919 #[serde(default)]
7921 pub enabled: bool,
7922
7923 #[serde(default = "default_recession_prob")]
7925 pub probability_per_year: f64,
7926
7927 #[serde(default)]
7929 pub severity: RecessionSeveritySchemaConfig,
7930
7931 #[serde(default)]
7933 pub recession_periods: Vec<RecessionPeriodSchemaConfig>,
7934}
7935
7936fn default_recession_prob() -> f64 {
7937 0.10
7938}
7939
7940impl Default for RecessionSchemaConfig {
7941 fn default() -> Self {
7942 Self {
7943 enabled: false,
7944 probability_per_year: 0.10,
7945 severity: RecessionSeveritySchemaConfig::Moderate,
7946 recession_periods: Vec::new(),
7947 }
7948 }
7949}
7950
7951#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
7953#[serde(rename_all = "snake_case")]
7954pub enum RecessionSeveritySchemaConfig {
7955 Mild,
7957 #[default]
7959 Moderate,
7960 Severe,
7962}
7963
7964#[derive(Debug, Clone, Serialize, Deserialize)]
7966pub struct RecessionPeriodSchemaConfig {
7967 pub start_month: u32,
7969 pub duration_months: u32,
7971}
7972
7973#[derive(Debug, Clone, Serialize, Deserialize)]
7975pub struct IndustryCycleSchemaConfig {
7976 #[serde(default = "default_industry_period")]
7978 pub period_months: u32,
7979
7980 #[serde(default = "default_industry_amp")]
7982 pub amplitude: f64,
7983}
7984
7985fn default_industry_period() -> u32 {
7986 36
7987}
7988
7989fn default_industry_amp() -> f64 {
7990 0.20
7991}
7992
7993#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7995pub struct CommoditiesSchemaConfig {
7996 #[serde(default)]
7998 pub enabled: bool,
7999
8000 #[serde(default)]
8002 pub items: Vec<CommodityItemSchemaConfig>,
8003}
8004
8005#[derive(Debug, Clone, Serialize, Deserialize)]
8007pub struct CommodityItemSchemaConfig {
8008 pub name: String,
8010
8011 #[serde(default = "default_volatility")]
8013 pub volatility: f64,
8014
8015 #[serde(default)]
8017 pub cogs_pass_through: f64,
8018
8019 #[serde(default)]
8021 pub overhead_pass_through: f64,
8022}
8023
8024fn default_volatility() -> f64 {
8025 0.20
8026}
8027
8028#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8034pub struct DriftLabelingSchemaConfig {
8035 #[serde(default)]
8037 pub enabled: bool,
8038
8039 #[serde(default)]
8041 pub statistical: StatisticalDriftLabelingSchemaConfig,
8042
8043 #[serde(default)]
8045 pub categorical: CategoricalDriftLabelingSchemaConfig,
8046
8047 #[serde(default)]
8049 pub temporal: TemporalDriftLabelingSchemaConfig,
8050
8051 #[serde(default)]
8053 pub regulatory_calendar_preset: Option<String>,
8054}
8055
8056#[derive(Debug, Clone, Serialize, Deserialize)]
8058pub struct StatisticalDriftLabelingSchemaConfig {
8059 #[serde(default = "default_true_val")]
8061 pub enabled: bool,
8062
8063 #[serde(default = "default_min_magnitude")]
8065 pub min_magnitude_threshold: f64,
8066}
8067
8068fn default_min_magnitude() -> f64 {
8069 0.05
8070}
8071
8072impl Default for StatisticalDriftLabelingSchemaConfig {
8073 fn default() -> Self {
8074 Self {
8075 enabled: true,
8076 min_magnitude_threshold: 0.05,
8077 }
8078 }
8079}
8080
8081#[derive(Debug, Clone, Serialize, Deserialize)]
8083pub struct CategoricalDriftLabelingSchemaConfig {
8084 #[serde(default = "default_true_val")]
8086 pub enabled: bool,
8087}
8088
8089impl Default for CategoricalDriftLabelingSchemaConfig {
8090 fn default() -> Self {
8091 Self { enabled: true }
8092 }
8093}
8094
8095#[derive(Debug, Clone, Serialize, Deserialize)]
8097pub struct TemporalDriftLabelingSchemaConfig {
8098 #[serde(default = "default_true_val")]
8100 pub enabled: bool,
8101}
8102
8103impl Default for TemporalDriftLabelingSchemaConfig {
8104 fn default() -> Self {
8105 Self { enabled: true }
8106 }
8107}
8108
8109#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8122pub struct EnhancedAnomalyConfig {
8123 #[serde(default)]
8125 pub enabled: bool,
8126
8127 #[serde(default)]
8129 pub rates: AnomalyRateConfig,
8130
8131 #[serde(default)]
8133 pub multi_stage_schemes: MultiStageSchemeConfig,
8134
8135 #[serde(default)]
8137 pub correlated_injection: CorrelatedInjectionConfig,
8138
8139 #[serde(default)]
8141 pub near_miss: NearMissConfig,
8142
8143 #[serde(default)]
8145 pub difficulty_classification: DifficultyClassificationConfig,
8146
8147 #[serde(default)]
8149 pub context_aware: ContextAwareConfig,
8150
8151 #[serde(default)]
8153 pub labeling: EnhancedLabelingConfig,
8154}
8155
8156#[derive(Debug, Clone, Serialize, Deserialize)]
8158pub struct AnomalyRateConfig {
8159 #[serde(default = "default_total_anomaly_rate")]
8161 pub total_rate: f64,
8162
8163 #[serde(default = "default_fraud_anomaly_rate")]
8165 pub fraud_rate: f64,
8166
8167 #[serde(default = "default_error_anomaly_rate")]
8169 pub error_rate: f64,
8170
8171 #[serde(default = "default_process_anomaly_rate")]
8173 pub process_rate: f64,
8174}
8175
8176fn default_total_anomaly_rate() -> f64 {
8177 0.03
8178}
8179fn default_fraud_anomaly_rate() -> f64 {
8180 0.01
8181}
8182fn default_error_anomaly_rate() -> f64 {
8183 0.015
8184}
8185fn default_process_anomaly_rate() -> f64 {
8186 0.005
8187}
8188
8189impl Default for AnomalyRateConfig {
8190 fn default() -> Self {
8191 Self {
8192 total_rate: default_total_anomaly_rate(),
8193 fraud_rate: default_fraud_anomaly_rate(),
8194 error_rate: default_error_anomaly_rate(),
8195 process_rate: default_process_anomaly_rate(),
8196 }
8197 }
8198}
8199
8200#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8202pub struct MultiStageSchemeConfig {
8203 #[serde(default)]
8205 pub enabled: bool,
8206
8207 #[serde(default)]
8209 pub embezzlement: EmbezzlementSchemeConfig,
8210
8211 #[serde(default)]
8213 pub revenue_manipulation: RevenueManipulationSchemeConfig,
8214
8215 #[serde(default)]
8217 pub kickback: KickbackSchemeConfig,
8218}
8219
8220#[derive(Debug, Clone, Serialize, Deserialize)]
8222pub struct EmbezzlementSchemeConfig {
8223 #[serde(default = "default_embezzlement_probability")]
8225 pub probability: f64,
8226
8227 #[serde(default)]
8229 pub testing_stage: SchemeStageConfig,
8230
8231 #[serde(default)]
8233 pub escalation_stage: SchemeStageConfig,
8234
8235 #[serde(default)]
8237 pub acceleration_stage: SchemeStageConfig,
8238
8239 #[serde(default)]
8241 pub desperation_stage: SchemeStageConfig,
8242}
8243
8244fn default_embezzlement_probability() -> f64 {
8245 0.02
8246}
8247
8248impl Default for EmbezzlementSchemeConfig {
8249 fn default() -> Self {
8250 Self {
8251 probability: default_embezzlement_probability(),
8252 testing_stage: SchemeStageConfig {
8253 duration_months: 2,
8254 amount_min: 100.0,
8255 amount_max: 500.0,
8256 transaction_count_min: 2,
8257 transaction_count_max: 5,
8258 difficulty: "hard".to_string(),
8259 },
8260 escalation_stage: SchemeStageConfig {
8261 duration_months: 6,
8262 amount_min: 500.0,
8263 amount_max: 2000.0,
8264 transaction_count_min: 3,
8265 transaction_count_max: 8,
8266 difficulty: "moderate".to_string(),
8267 },
8268 acceleration_stage: SchemeStageConfig {
8269 duration_months: 3,
8270 amount_min: 2000.0,
8271 amount_max: 10000.0,
8272 transaction_count_min: 5,
8273 transaction_count_max: 12,
8274 difficulty: "easy".to_string(),
8275 },
8276 desperation_stage: SchemeStageConfig {
8277 duration_months: 1,
8278 amount_min: 10000.0,
8279 amount_max: 50000.0,
8280 transaction_count_min: 3,
8281 transaction_count_max: 6,
8282 difficulty: "trivial".to_string(),
8283 },
8284 }
8285 }
8286}
8287
8288#[derive(Debug, Clone, Serialize, Deserialize)]
8290pub struct RevenueManipulationSchemeConfig {
8291 #[serde(default = "default_revenue_manipulation_probability")]
8293 pub probability: f64,
8294
8295 #[serde(default = "default_early_recognition_target")]
8297 pub early_recognition_target: f64,
8298
8299 #[serde(default = "default_expense_deferral_target")]
8301 pub expense_deferral_target: f64,
8302
8303 #[serde(default = "default_reserve_release_target")]
8305 pub reserve_release_target: f64,
8306
8307 #[serde(default = "default_channel_stuffing_target")]
8309 pub channel_stuffing_target: f64,
8310}
8311
8312fn default_revenue_manipulation_probability() -> f64 {
8313 0.01
8314}
8315fn default_early_recognition_target() -> f64 {
8316 0.02
8317}
8318fn default_expense_deferral_target() -> f64 {
8319 0.03
8320}
8321fn default_reserve_release_target() -> f64 {
8322 0.02
8323}
8324fn default_channel_stuffing_target() -> f64 {
8325 0.05
8326}
8327
8328impl Default for RevenueManipulationSchemeConfig {
8329 fn default() -> Self {
8330 Self {
8331 probability: default_revenue_manipulation_probability(),
8332 early_recognition_target: default_early_recognition_target(),
8333 expense_deferral_target: default_expense_deferral_target(),
8334 reserve_release_target: default_reserve_release_target(),
8335 channel_stuffing_target: default_channel_stuffing_target(),
8336 }
8337 }
8338}
8339
8340#[derive(Debug, Clone, Serialize, Deserialize)]
8342pub struct KickbackSchemeConfig {
8343 #[serde(default = "default_kickback_probability")]
8345 pub probability: f64,
8346
8347 #[serde(default = "default_kickback_inflation_min")]
8349 pub inflation_min: f64,
8350
8351 #[serde(default = "default_kickback_inflation_max")]
8353 pub inflation_max: f64,
8354
8355 #[serde(default = "default_kickback_percent")]
8357 pub kickback_percent: f64,
8358
8359 #[serde(default = "default_kickback_setup_months")]
8361 pub setup_months: u32,
8362
8363 #[serde(default = "default_kickback_operation_months")]
8365 pub operation_months: u32,
8366}
8367
8368fn default_kickback_probability() -> f64 {
8369 0.01
8370}
8371fn default_kickback_inflation_min() -> f64 {
8372 0.10
8373}
8374fn default_kickback_inflation_max() -> f64 {
8375 0.25
8376}
8377fn default_kickback_percent() -> f64 {
8378 0.50
8379}
8380fn default_kickback_setup_months() -> u32 {
8381 3
8382}
8383fn default_kickback_operation_months() -> u32 {
8384 12
8385}
8386
8387impl Default for KickbackSchemeConfig {
8388 fn default() -> Self {
8389 Self {
8390 probability: default_kickback_probability(),
8391 inflation_min: default_kickback_inflation_min(),
8392 inflation_max: default_kickback_inflation_max(),
8393 kickback_percent: default_kickback_percent(),
8394 setup_months: default_kickback_setup_months(),
8395 operation_months: default_kickback_operation_months(),
8396 }
8397 }
8398}
8399
8400#[derive(Debug, Clone, Serialize, Deserialize)]
8402pub struct SchemeStageConfig {
8403 pub duration_months: u32,
8405
8406 pub amount_min: f64,
8408
8409 pub amount_max: f64,
8411
8412 pub transaction_count_min: u32,
8414
8415 pub transaction_count_max: u32,
8417
8418 pub difficulty: String,
8420}
8421
8422impl Default for SchemeStageConfig {
8423 fn default() -> Self {
8424 Self {
8425 duration_months: 3,
8426 amount_min: 100.0,
8427 amount_max: 1000.0,
8428 transaction_count_min: 2,
8429 transaction_count_max: 10,
8430 difficulty: "moderate".to_string(),
8431 }
8432 }
8433}
8434
8435#[derive(Debug, Clone, Serialize, Deserialize)]
8437pub struct CorrelatedInjectionConfig {
8438 #[serde(default)]
8440 pub enabled: bool,
8441
8442 #[serde(default = "default_true_val")]
8444 pub fraud_concealment: bool,
8445
8446 #[serde(default = "default_true_val")]
8448 pub error_cascade: bool,
8449
8450 #[serde(default = "default_true_val")]
8452 pub temporal_clustering: bool,
8453
8454 #[serde(default)]
8456 pub temporal_clustering_config: TemporalClusteringConfig,
8457
8458 #[serde(default)]
8460 pub co_occurrence_patterns: Vec<CoOccurrencePatternConfig>,
8461}
8462
8463impl Default for CorrelatedInjectionConfig {
8464 fn default() -> Self {
8465 Self {
8466 enabled: false,
8467 fraud_concealment: true,
8468 error_cascade: true,
8469 temporal_clustering: true,
8470 temporal_clustering_config: TemporalClusteringConfig::default(),
8471 co_occurrence_patterns: Vec::new(),
8472 }
8473 }
8474}
8475
8476#[derive(Debug, Clone, Serialize, Deserialize)]
8478pub struct TemporalClusteringConfig {
8479 #[serde(default = "default_period_end_multiplier")]
8481 pub period_end_multiplier: f64,
8482
8483 #[serde(default = "default_period_end_days")]
8485 pub period_end_days: u32,
8486
8487 #[serde(default = "default_quarter_end_multiplier")]
8489 pub quarter_end_multiplier: f64,
8490
8491 #[serde(default = "default_year_end_multiplier")]
8493 pub year_end_multiplier: f64,
8494}
8495
8496fn default_period_end_multiplier() -> f64 {
8497 2.5
8498}
8499fn default_period_end_days() -> u32 {
8500 5
8501}
8502fn default_quarter_end_multiplier() -> f64 {
8503 1.5
8504}
8505fn default_year_end_multiplier() -> f64 {
8506 2.0
8507}
8508
8509impl Default for TemporalClusteringConfig {
8510 fn default() -> Self {
8511 Self {
8512 period_end_multiplier: default_period_end_multiplier(),
8513 period_end_days: default_period_end_days(),
8514 quarter_end_multiplier: default_quarter_end_multiplier(),
8515 year_end_multiplier: default_year_end_multiplier(),
8516 }
8517 }
8518}
8519
8520#[derive(Debug, Clone, Serialize, Deserialize)]
8522pub struct CoOccurrencePatternConfig {
8523 pub name: String,
8525
8526 pub primary_type: String,
8528
8529 pub correlated: Vec<CorrelatedAnomalyConfig>,
8531}
8532
8533#[derive(Debug, Clone, Serialize, Deserialize)]
8535pub struct CorrelatedAnomalyConfig {
8536 pub anomaly_type: String,
8538
8539 pub probability: f64,
8541
8542 pub lag_days_min: i32,
8544
8545 pub lag_days_max: i32,
8547}
8548
8549#[derive(Debug, Clone, Serialize, Deserialize)]
8551pub struct NearMissConfig {
8552 #[serde(default)]
8554 pub enabled: bool,
8555
8556 #[serde(default = "default_near_miss_proportion")]
8558 pub proportion: f64,
8559
8560 #[serde(default = "default_true_val")]
8562 pub near_duplicate: bool,
8563
8564 #[serde(default)]
8566 pub near_duplicate_days: NearDuplicateDaysConfig,
8567
8568 #[serde(default = "default_true_val")]
8570 pub threshold_proximity: bool,
8571
8572 #[serde(default)]
8574 pub threshold_proximity_range: ThresholdProximityRangeConfig,
8575
8576 #[serde(default = "default_true_val")]
8578 pub unusual_legitimate: bool,
8579
8580 #[serde(default = "default_unusual_legitimate_types")]
8582 pub unusual_legitimate_types: Vec<String>,
8583
8584 #[serde(default = "default_true_val")]
8586 pub corrected_errors: bool,
8587
8588 #[serde(default)]
8590 pub corrected_error_lag: CorrectedErrorLagConfig,
8591}
8592
8593fn default_near_miss_proportion() -> f64 {
8594 0.30
8595}
8596
8597fn default_unusual_legitimate_types() -> Vec<String> {
8598 vec![
8599 "year_end_bonus".to_string(),
8600 "contract_prepayment".to_string(),
8601 "insurance_claim".to_string(),
8602 "settlement_payment".to_string(),
8603 ]
8604}
8605
8606impl Default for NearMissConfig {
8607 fn default() -> Self {
8608 Self {
8609 enabled: false,
8610 proportion: default_near_miss_proportion(),
8611 near_duplicate: true,
8612 near_duplicate_days: NearDuplicateDaysConfig::default(),
8613 threshold_proximity: true,
8614 threshold_proximity_range: ThresholdProximityRangeConfig::default(),
8615 unusual_legitimate: true,
8616 unusual_legitimate_types: default_unusual_legitimate_types(),
8617 corrected_errors: true,
8618 corrected_error_lag: CorrectedErrorLagConfig::default(),
8619 }
8620 }
8621}
8622
8623#[derive(Debug, Clone, Serialize, Deserialize)]
8625pub struct NearDuplicateDaysConfig {
8626 #[serde(default = "default_near_duplicate_min")]
8628 pub min: u32,
8629
8630 #[serde(default = "default_near_duplicate_max")]
8632 pub max: u32,
8633}
8634
8635fn default_near_duplicate_min() -> u32 {
8636 1
8637}
8638fn default_near_duplicate_max() -> u32 {
8639 3
8640}
8641
8642impl Default for NearDuplicateDaysConfig {
8643 fn default() -> Self {
8644 Self {
8645 min: default_near_duplicate_min(),
8646 max: default_near_duplicate_max(),
8647 }
8648 }
8649}
8650
8651#[derive(Debug, Clone, Serialize, Deserialize)]
8653pub struct ThresholdProximityRangeConfig {
8654 #[serde(default = "default_threshold_proximity_min")]
8656 pub min: f64,
8657
8658 #[serde(default = "default_threshold_proximity_max")]
8660 pub max: f64,
8661}
8662
8663fn default_threshold_proximity_min() -> f64 {
8664 0.90
8665}
8666fn default_threshold_proximity_max() -> f64 {
8667 0.99
8668}
8669
8670impl Default for ThresholdProximityRangeConfig {
8671 fn default() -> Self {
8672 Self {
8673 min: default_threshold_proximity_min(),
8674 max: default_threshold_proximity_max(),
8675 }
8676 }
8677}
8678
8679#[derive(Debug, Clone, Serialize, Deserialize)]
8681pub struct CorrectedErrorLagConfig {
8682 #[serde(default = "default_corrected_error_lag_min")]
8684 pub min: u32,
8685
8686 #[serde(default = "default_corrected_error_lag_max")]
8688 pub max: u32,
8689}
8690
8691fn default_corrected_error_lag_min() -> u32 {
8692 1
8693}
8694fn default_corrected_error_lag_max() -> u32 {
8695 5
8696}
8697
8698impl Default for CorrectedErrorLagConfig {
8699 fn default() -> Self {
8700 Self {
8701 min: default_corrected_error_lag_min(),
8702 max: default_corrected_error_lag_max(),
8703 }
8704 }
8705}
8706
8707#[derive(Debug, Clone, Serialize, Deserialize)]
8709pub struct DifficultyClassificationConfig {
8710 #[serde(default)]
8712 pub enabled: bool,
8713
8714 #[serde(default)]
8716 pub target_distribution: DifficultyDistributionConfig,
8717}
8718
8719impl Default for DifficultyClassificationConfig {
8720 fn default() -> Self {
8721 Self {
8722 enabled: true,
8723 target_distribution: DifficultyDistributionConfig::default(),
8724 }
8725 }
8726}
8727
8728#[derive(Debug, Clone, Serialize, Deserialize)]
8730pub struct DifficultyDistributionConfig {
8731 #[serde(default = "default_difficulty_trivial")]
8733 pub trivial: f64,
8734
8735 #[serde(default = "default_difficulty_easy")]
8737 pub easy: f64,
8738
8739 #[serde(default = "default_difficulty_moderate")]
8741 pub moderate: f64,
8742
8743 #[serde(default = "default_difficulty_hard")]
8745 pub hard: f64,
8746
8747 #[serde(default = "default_difficulty_expert")]
8749 pub expert: f64,
8750}
8751
8752fn default_difficulty_trivial() -> f64 {
8753 0.15
8754}
8755fn default_difficulty_easy() -> f64 {
8756 0.25
8757}
8758fn default_difficulty_moderate() -> f64 {
8759 0.30
8760}
8761fn default_difficulty_hard() -> f64 {
8762 0.20
8763}
8764fn default_difficulty_expert() -> f64 {
8765 0.10
8766}
8767
8768impl Default for DifficultyDistributionConfig {
8769 fn default() -> Self {
8770 Self {
8771 trivial: default_difficulty_trivial(),
8772 easy: default_difficulty_easy(),
8773 moderate: default_difficulty_moderate(),
8774 hard: default_difficulty_hard(),
8775 expert: default_difficulty_expert(),
8776 }
8777 }
8778}
8779
8780#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8782pub struct ContextAwareConfig {
8783 #[serde(default)]
8785 pub enabled: bool,
8786
8787 #[serde(default)]
8789 pub vendor_rules: VendorAnomalyRulesConfig,
8790
8791 #[serde(default)]
8793 pub employee_rules: EmployeeAnomalyRulesConfig,
8794
8795 #[serde(default)]
8797 pub account_rules: AccountAnomalyRulesConfig,
8798
8799 #[serde(default)]
8801 pub behavioral_baseline: BehavioralBaselineConfig,
8802}
8803
8804#[derive(Debug, Clone, Serialize, Deserialize)]
8806pub struct VendorAnomalyRulesConfig {
8807 #[serde(default = "default_new_vendor_multiplier")]
8809 pub new_vendor_error_multiplier: f64,
8810
8811 #[serde(default = "default_new_vendor_threshold")]
8813 pub new_vendor_threshold_days: u32,
8814
8815 #[serde(default = "default_international_multiplier")]
8817 pub international_error_multiplier: f64,
8818
8819 #[serde(default = "default_strategic_vendor_types")]
8821 pub strategic_vendor_anomaly_types: Vec<String>,
8822}
8823
8824fn default_new_vendor_multiplier() -> f64 {
8825 2.5
8826}
8827fn default_new_vendor_threshold() -> u32 {
8828 90
8829}
8830fn default_international_multiplier() -> f64 {
8831 1.5
8832}
8833fn default_strategic_vendor_types() -> Vec<String> {
8834 vec![
8835 "pricing_dispute".to_string(),
8836 "contract_violation".to_string(),
8837 ]
8838}
8839
8840impl Default for VendorAnomalyRulesConfig {
8841 fn default() -> Self {
8842 Self {
8843 new_vendor_error_multiplier: default_new_vendor_multiplier(),
8844 new_vendor_threshold_days: default_new_vendor_threshold(),
8845 international_error_multiplier: default_international_multiplier(),
8846 strategic_vendor_anomaly_types: default_strategic_vendor_types(),
8847 }
8848 }
8849}
8850
8851#[derive(Debug, Clone, Serialize, Deserialize)]
8853pub struct EmployeeAnomalyRulesConfig {
8854 #[serde(default = "default_new_employee_rate")]
8856 pub new_employee_error_rate: f64,
8857
8858 #[serde(default = "default_new_employee_threshold")]
8860 pub new_employee_threshold_days: u32,
8861
8862 #[serde(default = "default_volume_fatigue_threshold")]
8864 pub volume_fatigue_threshold: u32,
8865
8866 #[serde(default = "default_coverage_multiplier")]
8868 pub coverage_error_multiplier: f64,
8869}
8870
8871fn default_new_employee_rate() -> f64 {
8872 0.05
8873}
8874fn default_new_employee_threshold() -> u32 {
8875 180
8876}
8877fn default_volume_fatigue_threshold() -> u32 {
8878 50
8879}
8880fn default_coverage_multiplier() -> f64 {
8881 1.8
8882}
8883
8884impl Default for EmployeeAnomalyRulesConfig {
8885 fn default() -> Self {
8886 Self {
8887 new_employee_error_rate: default_new_employee_rate(),
8888 new_employee_threshold_days: default_new_employee_threshold(),
8889 volume_fatigue_threshold: default_volume_fatigue_threshold(),
8890 coverage_error_multiplier: default_coverage_multiplier(),
8891 }
8892 }
8893}
8894
8895#[derive(Debug, Clone, Serialize, Deserialize)]
8897pub struct AccountAnomalyRulesConfig {
8898 #[serde(default = "default_high_risk_multiplier")]
8900 pub high_risk_account_multiplier: f64,
8901
8902 #[serde(default = "default_high_risk_accounts")]
8904 pub high_risk_accounts: Vec<String>,
8905
8906 #[serde(default = "default_suspense_multiplier")]
8908 pub suspense_account_multiplier: f64,
8909
8910 #[serde(default = "default_suspense_accounts")]
8912 pub suspense_accounts: Vec<String>,
8913
8914 #[serde(default = "default_intercompany_multiplier")]
8916 pub intercompany_account_multiplier: f64,
8917}
8918
8919fn default_high_risk_multiplier() -> f64 {
8920 2.0
8921}
8922fn default_high_risk_accounts() -> Vec<String> {
8923 vec![
8924 "1100".to_string(), "2000".to_string(), "3000".to_string(), ]
8928}
8929fn default_suspense_multiplier() -> f64 {
8930 3.0
8931}
8932fn default_suspense_accounts() -> Vec<String> {
8933 vec!["9999".to_string(), "9998".to_string()]
8934}
8935fn default_intercompany_multiplier() -> f64 {
8936 1.5
8937}
8938
8939impl Default for AccountAnomalyRulesConfig {
8940 fn default() -> Self {
8941 Self {
8942 high_risk_account_multiplier: default_high_risk_multiplier(),
8943 high_risk_accounts: default_high_risk_accounts(),
8944 suspense_account_multiplier: default_suspense_multiplier(),
8945 suspense_accounts: default_suspense_accounts(),
8946 intercompany_account_multiplier: default_intercompany_multiplier(),
8947 }
8948 }
8949}
8950
8951#[derive(Debug, Clone, Serialize, Deserialize)]
8953pub struct BehavioralBaselineConfig {
8954 #[serde(default)]
8956 pub enabled: bool,
8957
8958 #[serde(default = "default_baseline_period")]
8960 pub baseline_period_days: u32,
8961
8962 #[serde(default = "default_deviation_threshold")]
8964 pub deviation_threshold_std: f64,
8965
8966 #[serde(default = "default_frequency_deviation")]
8968 pub frequency_deviation_threshold: f64,
8969}
8970
8971fn default_baseline_period() -> u32 {
8972 90
8973}
8974fn default_deviation_threshold() -> f64 {
8975 3.0
8976}
8977fn default_frequency_deviation() -> f64 {
8978 2.0
8979}
8980
8981impl Default for BehavioralBaselineConfig {
8982 fn default() -> Self {
8983 Self {
8984 enabled: false,
8985 baseline_period_days: default_baseline_period(),
8986 deviation_threshold_std: default_deviation_threshold(),
8987 frequency_deviation_threshold: default_frequency_deviation(),
8988 }
8989 }
8990}
8991
8992#[derive(Debug, Clone, Serialize, Deserialize)]
8994pub struct EnhancedLabelingConfig {
8995 #[serde(default = "default_true_val")]
8997 pub severity_scoring: bool,
8998
8999 #[serde(default = "default_true_val")]
9001 pub difficulty_classification: bool,
9002
9003 #[serde(default)]
9005 pub materiality_thresholds: MaterialityThresholdsConfig,
9006}
9007
9008impl Default for EnhancedLabelingConfig {
9009 fn default() -> Self {
9010 Self {
9011 severity_scoring: true,
9012 difficulty_classification: true,
9013 materiality_thresholds: MaterialityThresholdsConfig::default(),
9014 }
9015 }
9016}
9017
9018#[derive(Debug, Clone, Serialize, Deserialize)]
9020pub struct MaterialityThresholdsConfig {
9021 #[serde(default = "default_materiality_trivial")]
9023 pub trivial: f64,
9024
9025 #[serde(default = "default_materiality_immaterial")]
9027 pub immaterial: f64,
9028
9029 #[serde(default = "default_materiality_material")]
9031 pub material: f64,
9032
9033 #[serde(default = "default_materiality_highly_material")]
9035 pub highly_material: f64,
9036}
9037
9038fn default_materiality_trivial() -> f64 {
9039 0.001
9040}
9041fn default_materiality_immaterial() -> f64 {
9042 0.01
9043}
9044fn default_materiality_material() -> f64 {
9045 0.05
9046}
9047fn default_materiality_highly_material() -> f64 {
9048 0.10
9049}
9050
9051impl Default for MaterialityThresholdsConfig {
9052 fn default() -> Self {
9053 Self {
9054 trivial: default_materiality_trivial(),
9055 immaterial: default_materiality_immaterial(),
9056 material: default_materiality_material(),
9057 highly_material: default_materiality_highly_material(),
9058 }
9059 }
9060}
9061
9062#[derive(Debug, Clone, Serialize, Deserialize, Default)]
9074pub struct IndustrySpecificConfig {
9075 #[serde(default)]
9077 pub enabled: bool,
9078
9079 #[serde(default)]
9081 pub manufacturing: ManufacturingConfig,
9082
9083 #[serde(default)]
9085 pub retail: RetailConfig,
9086
9087 #[serde(default)]
9089 pub healthcare: HealthcareConfig,
9090
9091 #[serde(default)]
9093 pub technology: TechnologyConfig,
9094
9095 #[serde(default)]
9097 pub financial_services: FinancialServicesConfig,
9098
9099 #[serde(default)]
9101 pub professional_services: ProfessionalServicesConfig,
9102}
9103
9104#[derive(Debug, Clone, Serialize, Deserialize)]
9106pub struct ManufacturingConfig {
9107 #[serde(default)]
9109 pub enabled: bool,
9110
9111 #[serde(default = "default_bom_depth")]
9113 pub bom_depth: u32,
9114
9115 #[serde(default)]
9117 pub just_in_time: bool,
9118
9119 #[serde(default = "default_production_order_types")]
9121 pub production_order_types: Vec<String>,
9122
9123 #[serde(default)]
9125 pub quality_framework: Option<String>,
9126
9127 #[serde(default = "default_supplier_tiers")]
9129 pub supplier_tiers: u32,
9130
9131 #[serde(default = "default_cost_frequency")]
9133 pub standard_cost_frequency: String,
9134
9135 #[serde(default = "default_yield_rate")]
9137 pub target_yield_rate: f64,
9138
9139 #[serde(default = "default_scrap_threshold")]
9141 pub scrap_alert_threshold: f64,
9142
9143 #[serde(default)]
9145 pub anomaly_rates: ManufacturingAnomalyRates,
9146
9147 #[serde(default)]
9149 pub cost_accounting: ManufacturingCostAccountingConfig,
9150}
9151
9152#[derive(Debug, Clone, Serialize, Deserialize)]
9154pub struct ManufacturingCostAccountingConfig {
9155 #[serde(default = "default_true")]
9157 pub enabled: bool,
9158
9159 #[serde(default = "default_true")]
9161 pub variance_accounts_enabled: bool,
9162
9163 #[serde(default = "default_true")]
9165 pub warranty_provisions_enabled: bool,
9166
9167 #[serde(default = "default_warranty_defect_threshold")]
9169 pub warranty_defect_threshold: f64,
9170}
9171
9172fn default_warranty_defect_threshold() -> f64 {
9173 0.01
9174}
9175
9176impl Default for ManufacturingCostAccountingConfig {
9177 fn default() -> Self {
9178 Self {
9179 enabled: true,
9180 variance_accounts_enabled: true,
9181 warranty_provisions_enabled: true,
9182 warranty_defect_threshold: 0.01,
9183 }
9184 }
9185}
9186
9187fn default_bom_depth() -> u32 {
9188 4
9189}
9190
9191fn default_production_order_types() -> Vec<String> {
9192 vec![
9193 "standard".to_string(),
9194 "rework".to_string(),
9195 "prototype".to_string(),
9196 ]
9197}
9198
9199fn default_supplier_tiers() -> u32 {
9200 2
9201}
9202
9203fn default_cost_frequency() -> String {
9204 "quarterly".to_string()
9205}
9206
9207fn default_yield_rate() -> f64 {
9208 0.97
9209}
9210
9211fn default_scrap_threshold() -> f64 {
9212 0.03
9213}
9214
9215impl Default for ManufacturingConfig {
9216 fn default() -> Self {
9217 Self {
9218 enabled: false,
9219 bom_depth: default_bom_depth(),
9220 just_in_time: false,
9221 production_order_types: default_production_order_types(),
9222 quality_framework: Some("ISO_9001".to_string()),
9223 supplier_tiers: default_supplier_tiers(),
9224 standard_cost_frequency: default_cost_frequency(),
9225 target_yield_rate: default_yield_rate(),
9226 scrap_alert_threshold: default_scrap_threshold(),
9227 anomaly_rates: ManufacturingAnomalyRates::default(),
9228 cost_accounting: ManufacturingCostAccountingConfig::default(),
9229 }
9230 }
9231}
9232
9233#[derive(Debug, Clone, Serialize, Deserialize)]
9235pub struct ManufacturingAnomalyRates {
9236 #[serde(default = "default_mfg_yield_rate")]
9238 pub yield_manipulation: f64,
9239
9240 #[serde(default = "default_mfg_labor_rate")]
9242 pub labor_misallocation: f64,
9243
9244 #[serde(default = "default_mfg_phantom_rate")]
9246 pub phantom_production: f64,
9247
9248 #[serde(default = "default_mfg_cost_rate")]
9250 pub standard_cost_manipulation: f64,
9251
9252 #[serde(default = "default_mfg_inventory_rate")]
9254 pub inventory_fraud: f64,
9255}
9256
9257fn default_mfg_yield_rate() -> f64 {
9258 0.015
9259}
9260
9261fn default_mfg_labor_rate() -> f64 {
9262 0.02
9263}
9264
9265fn default_mfg_phantom_rate() -> f64 {
9266 0.005
9267}
9268
9269fn default_mfg_cost_rate() -> f64 {
9270 0.01
9271}
9272
9273fn default_mfg_inventory_rate() -> f64 {
9274 0.008
9275}
9276
9277impl Default for ManufacturingAnomalyRates {
9278 fn default() -> Self {
9279 Self {
9280 yield_manipulation: default_mfg_yield_rate(),
9281 labor_misallocation: default_mfg_labor_rate(),
9282 phantom_production: default_mfg_phantom_rate(),
9283 standard_cost_manipulation: default_mfg_cost_rate(),
9284 inventory_fraud: default_mfg_inventory_rate(),
9285 }
9286 }
9287}
9288
9289#[derive(Debug, Clone, Serialize, Deserialize)]
9291pub struct RetailConfig {
9292 #[serde(default)]
9294 pub enabled: bool,
9295
9296 #[serde(default)]
9298 pub store_types: RetailStoreTypeConfig,
9299
9300 #[serde(default = "default_retail_daily_txns")]
9302 pub avg_daily_transactions: u32,
9303
9304 #[serde(default = "default_true")]
9306 pub loss_prevention: bool,
9307
9308 #[serde(default = "default_shrinkage_rate")]
9310 pub shrinkage_rate: f64,
9311
9312 #[serde(default)]
9314 pub anomaly_rates: RetailAnomalyRates,
9315}
9316
9317fn default_retail_daily_txns() -> u32 {
9318 500
9319}
9320
9321fn default_shrinkage_rate() -> f64 {
9322 0.015
9323}
9324
9325impl Default for RetailConfig {
9326 fn default() -> Self {
9327 Self {
9328 enabled: false,
9329 store_types: RetailStoreTypeConfig::default(),
9330 avg_daily_transactions: default_retail_daily_txns(),
9331 loss_prevention: true,
9332 shrinkage_rate: default_shrinkage_rate(),
9333 anomaly_rates: RetailAnomalyRates::default(),
9334 }
9335 }
9336}
9337
9338#[derive(Debug, Clone, Serialize, Deserialize)]
9340pub struct RetailStoreTypeConfig {
9341 #[serde(default = "default_flagship_pct")]
9343 pub flagship: f64,
9344
9345 #[serde(default = "default_regional_pct")]
9347 pub regional: f64,
9348
9349 #[serde(default = "default_outlet_pct")]
9351 pub outlet: f64,
9352
9353 #[serde(default = "default_ecommerce_pct")]
9355 pub ecommerce: f64,
9356}
9357
9358fn default_flagship_pct() -> f64 {
9359 0.10
9360}
9361
9362fn default_regional_pct() -> f64 {
9363 0.50
9364}
9365
9366fn default_outlet_pct() -> f64 {
9367 0.25
9368}
9369
9370fn default_ecommerce_pct() -> f64 {
9371 0.15
9372}
9373
9374impl Default for RetailStoreTypeConfig {
9375 fn default() -> Self {
9376 Self {
9377 flagship: default_flagship_pct(),
9378 regional: default_regional_pct(),
9379 outlet: default_outlet_pct(),
9380 ecommerce: default_ecommerce_pct(),
9381 }
9382 }
9383}
9384
9385#[derive(Debug, Clone, Serialize, Deserialize)]
9387pub struct RetailAnomalyRates {
9388 #[serde(default = "default_sweethearting_rate")]
9390 pub sweethearting: f64,
9391
9392 #[serde(default = "default_skimming_rate")]
9394 pub skimming: f64,
9395
9396 #[serde(default = "default_refund_fraud_rate")]
9398 pub refund_fraud: f64,
9399
9400 #[serde(default = "default_void_abuse_rate")]
9402 pub void_abuse: f64,
9403
9404 #[serde(default = "default_gift_card_rate")]
9406 pub gift_card_fraud: f64,
9407
9408 #[serde(default = "default_retail_kickback_rate")]
9410 pub vendor_kickback: f64,
9411}
9412
9413fn default_sweethearting_rate() -> f64 {
9414 0.02
9415}
9416
9417fn default_skimming_rate() -> f64 {
9418 0.005
9419}
9420
9421fn default_refund_fraud_rate() -> f64 {
9422 0.015
9423}
9424
9425fn default_void_abuse_rate() -> f64 {
9426 0.01
9427}
9428
9429fn default_gift_card_rate() -> f64 {
9430 0.008
9431}
9432
9433fn default_retail_kickback_rate() -> f64 {
9434 0.003
9435}
9436
9437impl Default for RetailAnomalyRates {
9438 fn default() -> Self {
9439 Self {
9440 sweethearting: default_sweethearting_rate(),
9441 skimming: default_skimming_rate(),
9442 refund_fraud: default_refund_fraud_rate(),
9443 void_abuse: default_void_abuse_rate(),
9444 gift_card_fraud: default_gift_card_rate(),
9445 vendor_kickback: default_retail_kickback_rate(),
9446 }
9447 }
9448}
9449
9450#[derive(Debug, Clone, Serialize, Deserialize)]
9452pub struct HealthcareConfig {
9453 #[serde(default)]
9455 pub enabled: bool,
9456
9457 #[serde(default = "default_facility_type")]
9459 pub facility_type: String,
9460
9461 #[serde(default)]
9463 pub payer_mix: HealthcarePayerMix,
9464
9465 #[serde(default)]
9467 pub coding_systems: HealthcareCodingSystems,
9468
9469 #[serde(default)]
9471 pub compliance: HealthcareComplianceConfig,
9472
9473 #[serde(default = "default_daily_encounters")]
9475 pub avg_daily_encounters: u32,
9476
9477 #[serde(default = "default_charges_per_encounter")]
9479 pub avg_charges_per_encounter: u32,
9480
9481 #[serde(default = "default_hc_denial_rate")]
9483 pub denial_rate: f64,
9484
9485 #[serde(default = "default_hc_bad_debt_rate")]
9487 pub bad_debt_rate: f64,
9488
9489 #[serde(default = "default_hc_charity_care_rate")]
9491 pub charity_care_rate: f64,
9492
9493 #[serde(default)]
9495 pub anomaly_rates: HealthcareAnomalyRates,
9496}
9497
9498fn default_facility_type() -> String {
9499 "hospital".to_string()
9500}
9501
9502fn default_daily_encounters() -> u32 {
9503 150
9504}
9505
9506fn default_charges_per_encounter() -> u32 {
9507 8
9508}
9509
9510fn default_hc_denial_rate() -> f64 {
9511 0.05
9512}
9513
9514fn default_hc_bad_debt_rate() -> f64 {
9515 0.03
9516}
9517
9518fn default_hc_charity_care_rate() -> f64 {
9519 0.02
9520}
9521
9522impl Default for HealthcareConfig {
9523 fn default() -> Self {
9524 Self {
9525 enabled: false,
9526 facility_type: default_facility_type(),
9527 payer_mix: HealthcarePayerMix::default(),
9528 coding_systems: HealthcareCodingSystems::default(),
9529 compliance: HealthcareComplianceConfig::default(),
9530 avg_daily_encounters: default_daily_encounters(),
9531 avg_charges_per_encounter: default_charges_per_encounter(),
9532 denial_rate: default_hc_denial_rate(),
9533 bad_debt_rate: default_hc_bad_debt_rate(),
9534 charity_care_rate: default_hc_charity_care_rate(),
9535 anomaly_rates: HealthcareAnomalyRates::default(),
9536 }
9537 }
9538}
9539
9540#[derive(Debug, Clone, Serialize, Deserialize)]
9542pub struct HealthcarePayerMix {
9543 #[serde(default = "default_medicare_pct")]
9545 pub medicare: f64,
9546
9547 #[serde(default = "default_medicaid_pct")]
9549 pub medicaid: f64,
9550
9551 #[serde(default = "default_commercial_pct")]
9553 pub commercial: f64,
9554
9555 #[serde(default = "default_self_pay_pct")]
9557 pub self_pay: f64,
9558}
9559
9560fn default_medicare_pct() -> f64 {
9561 0.40
9562}
9563
9564fn default_medicaid_pct() -> f64 {
9565 0.20
9566}
9567
9568fn default_commercial_pct() -> f64 {
9569 0.30
9570}
9571
9572fn default_self_pay_pct() -> f64 {
9573 0.10
9574}
9575
9576impl Default for HealthcarePayerMix {
9577 fn default() -> Self {
9578 Self {
9579 medicare: default_medicare_pct(),
9580 medicaid: default_medicaid_pct(),
9581 commercial: default_commercial_pct(),
9582 self_pay: default_self_pay_pct(),
9583 }
9584 }
9585}
9586
9587#[derive(Debug, Clone, Serialize, Deserialize)]
9589pub struct HealthcareCodingSystems {
9590 #[serde(default = "default_true")]
9592 pub icd10: bool,
9593
9594 #[serde(default = "default_true")]
9596 pub cpt: bool,
9597
9598 #[serde(default = "default_true")]
9600 pub drg: bool,
9601
9602 #[serde(default = "default_true")]
9604 pub hcpcs: bool,
9605
9606 #[serde(default = "default_true")]
9608 pub revenue_codes: bool,
9609}
9610
9611impl Default for HealthcareCodingSystems {
9612 fn default() -> Self {
9613 Self {
9614 icd10: true,
9615 cpt: true,
9616 drg: true,
9617 hcpcs: true,
9618 revenue_codes: true,
9619 }
9620 }
9621}
9622
9623#[derive(Debug, Clone, Serialize, Deserialize)]
9625pub struct HealthcareComplianceConfig {
9626 #[serde(default = "default_true")]
9628 pub hipaa: bool,
9629
9630 #[serde(default = "default_true")]
9632 pub stark_law: bool,
9633
9634 #[serde(default = "default_true")]
9636 pub anti_kickback: bool,
9637
9638 #[serde(default = "default_true")]
9640 pub false_claims_act: bool,
9641
9642 #[serde(default = "default_true")]
9644 pub emtala: bool,
9645}
9646
9647impl Default for HealthcareComplianceConfig {
9648 fn default() -> Self {
9649 Self {
9650 hipaa: true,
9651 stark_law: true,
9652 anti_kickback: true,
9653 false_claims_act: true,
9654 emtala: true,
9655 }
9656 }
9657}
9658
9659#[derive(Debug, Clone, Serialize, Deserialize)]
9661pub struct HealthcareAnomalyRates {
9662 #[serde(default = "default_upcoding_rate")]
9664 pub upcoding: f64,
9665
9666 #[serde(default = "default_unbundling_rate")]
9668 pub unbundling: f64,
9669
9670 #[serde(default = "default_phantom_billing_rate")]
9672 pub phantom_billing: f64,
9673
9674 #[serde(default = "default_healthcare_kickback_rate")]
9676 pub kickbacks: f64,
9677
9678 #[serde(default = "default_duplicate_billing_rate")]
9680 pub duplicate_billing: f64,
9681
9682 #[serde(default = "default_med_necessity_rate")]
9684 pub medical_necessity_abuse: f64,
9685}
9686
9687fn default_upcoding_rate() -> f64 {
9688 0.02
9689}
9690
9691fn default_unbundling_rate() -> f64 {
9692 0.015
9693}
9694
9695fn default_phantom_billing_rate() -> f64 {
9696 0.005
9697}
9698
9699fn default_healthcare_kickback_rate() -> f64 {
9700 0.003
9701}
9702
9703fn default_duplicate_billing_rate() -> f64 {
9704 0.008
9705}
9706
9707fn default_med_necessity_rate() -> f64 {
9708 0.01
9709}
9710
9711impl Default for HealthcareAnomalyRates {
9712 fn default() -> Self {
9713 Self {
9714 upcoding: default_upcoding_rate(),
9715 unbundling: default_unbundling_rate(),
9716 phantom_billing: default_phantom_billing_rate(),
9717 kickbacks: default_healthcare_kickback_rate(),
9718 duplicate_billing: default_duplicate_billing_rate(),
9719 medical_necessity_abuse: default_med_necessity_rate(),
9720 }
9721 }
9722}
9723
9724#[derive(Debug, Clone, Serialize, Deserialize)]
9726pub struct TechnologyConfig {
9727 #[serde(default)]
9729 pub enabled: bool,
9730
9731 #[serde(default = "default_revenue_model")]
9733 pub revenue_model: String,
9734
9735 #[serde(default = "default_subscription_pct")]
9737 pub subscription_revenue_pct: f64,
9738
9739 #[serde(default = "default_license_pct")]
9741 pub license_revenue_pct: f64,
9742
9743 #[serde(default = "default_services_pct")]
9745 pub services_revenue_pct: f64,
9746
9747 #[serde(default)]
9749 pub rd_capitalization: RdCapitalizationConfig,
9750
9751 #[serde(default)]
9753 pub anomaly_rates: TechnologyAnomalyRates,
9754}
9755
9756fn default_revenue_model() -> String {
9757 "saas".to_string()
9758}
9759
9760fn default_subscription_pct() -> f64 {
9761 0.60
9762}
9763
9764fn default_license_pct() -> f64 {
9765 0.25
9766}
9767
9768fn default_services_pct() -> f64 {
9769 0.15
9770}
9771
9772impl Default for TechnologyConfig {
9773 fn default() -> Self {
9774 Self {
9775 enabled: false,
9776 revenue_model: default_revenue_model(),
9777 subscription_revenue_pct: default_subscription_pct(),
9778 license_revenue_pct: default_license_pct(),
9779 services_revenue_pct: default_services_pct(),
9780 rd_capitalization: RdCapitalizationConfig::default(),
9781 anomaly_rates: TechnologyAnomalyRates::default(),
9782 }
9783 }
9784}
9785
9786#[derive(Debug, Clone, Serialize, Deserialize)]
9788pub struct RdCapitalizationConfig {
9789 #[serde(default = "default_true")]
9791 pub enabled: bool,
9792
9793 #[serde(default = "default_cap_rate")]
9795 pub capitalization_rate: f64,
9796
9797 #[serde(default = "default_useful_life")]
9799 pub useful_life_years: u32,
9800}
9801
9802fn default_cap_rate() -> f64 {
9803 0.30
9804}
9805
9806fn default_useful_life() -> u32 {
9807 3
9808}
9809
9810impl Default for RdCapitalizationConfig {
9811 fn default() -> Self {
9812 Self {
9813 enabled: true,
9814 capitalization_rate: default_cap_rate(),
9815 useful_life_years: default_useful_life(),
9816 }
9817 }
9818}
9819
9820#[derive(Debug, Clone, Serialize, Deserialize)]
9822pub struct TechnologyAnomalyRates {
9823 #[serde(default = "default_premature_rev_rate")]
9825 pub premature_revenue: f64,
9826
9827 #[serde(default = "default_side_letter_rate")]
9829 pub side_letter_abuse: f64,
9830
9831 #[serde(default = "default_channel_stuffing_rate")]
9833 pub channel_stuffing: f64,
9834
9835 #[serde(default = "default_improper_cap_rate")]
9837 pub improper_capitalization: f64,
9838}
9839
9840fn default_premature_rev_rate() -> f64 {
9841 0.015
9842}
9843
9844fn default_side_letter_rate() -> f64 {
9845 0.008
9846}
9847
9848fn default_channel_stuffing_rate() -> f64 {
9849 0.01
9850}
9851
9852fn default_improper_cap_rate() -> f64 {
9853 0.012
9854}
9855
9856impl Default for TechnologyAnomalyRates {
9857 fn default() -> Self {
9858 Self {
9859 premature_revenue: default_premature_rev_rate(),
9860 side_letter_abuse: default_side_letter_rate(),
9861 channel_stuffing: default_channel_stuffing_rate(),
9862 improper_capitalization: default_improper_cap_rate(),
9863 }
9864 }
9865}
9866
9867#[derive(Debug, Clone, Serialize, Deserialize)]
9869pub struct FinancialServicesConfig {
9870 #[serde(default)]
9872 pub enabled: bool,
9873
9874 #[serde(default = "default_fi_type")]
9876 pub institution_type: String,
9877
9878 #[serde(default = "default_fi_regulatory")]
9880 pub regulatory_framework: String,
9881
9882 #[serde(default)]
9884 pub anomaly_rates: FinancialServicesAnomalyRates,
9885}
9886
9887fn default_fi_type() -> String {
9888 "commercial_bank".to_string()
9889}
9890
9891fn default_fi_regulatory() -> String {
9892 "us_banking".to_string()
9893}
9894
9895impl Default for FinancialServicesConfig {
9896 fn default() -> Self {
9897 Self {
9898 enabled: false,
9899 institution_type: default_fi_type(),
9900 regulatory_framework: default_fi_regulatory(),
9901 anomaly_rates: FinancialServicesAnomalyRates::default(),
9902 }
9903 }
9904}
9905
9906#[derive(Debug, Clone, Serialize, Deserialize)]
9908pub struct FinancialServicesAnomalyRates {
9909 #[serde(default = "default_loan_fraud_rate")]
9911 pub loan_fraud: f64,
9912
9913 #[serde(default = "default_trading_fraud_rate")]
9915 pub trading_fraud: f64,
9916
9917 #[serde(default = "default_insurance_fraud_rate")]
9919 pub insurance_fraud: f64,
9920
9921 #[serde(default = "default_account_manip_rate")]
9923 pub account_manipulation: f64,
9924}
9925
9926fn default_loan_fraud_rate() -> f64 {
9927 0.01
9928}
9929
9930fn default_trading_fraud_rate() -> f64 {
9931 0.008
9932}
9933
9934fn default_insurance_fraud_rate() -> f64 {
9935 0.012
9936}
9937
9938fn default_account_manip_rate() -> f64 {
9939 0.005
9940}
9941
9942impl Default for FinancialServicesAnomalyRates {
9943 fn default() -> Self {
9944 Self {
9945 loan_fraud: default_loan_fraud_rate(),
9946 trading_fraud: default_trading_fraud_rate(),
9947 insurance_fraud: default_insurance_fraud_rate(),
9948 account_manipulation: default_account_manip_rate(),
9949 }
9950 }
9951}
9952
9953#[derive(Debug, Clone, Serialize, Deserialize)]
9955pub struct ProfessionalServicesConfig {
9956 #[serde(default)]
9958 pub enabled: bool,
9959
9960 #[serde(default = "default_firm_type")]
9962 pub firm_type: String,
9963
9964 #[serde(default = "default_billing_model")]
9966 pub billing_model: String,
9967
9968 #[serde(default = "default_hourly_rate")]
9970 pub avg_hourly_rate: f64,
9971
9972 #[serde(default)]
9974 pub trust_accounting: TrustAccountingConfig,
9975
9976 #[serde(default)]
9978 pub anomaly_rates: ProfessionalServicesAnomalyRates,
9979}
9980
9981fn default_firm_type() -> String {
9982 "consulting".to_string()
9983}
9984
9985fn default_billing_model() -> String {
9986 "time_and_materials".to_string()
9987}
9988
9989fn default_hourly_rate() -> f64 {
9990 250.0
9991}
9992
9993impl Default for ProfessionalServicesConfig {
9994 fn default() -> Self {
9995 Self {
9996 enabled: false,
9997 firm_type: default_firm_type(),
9998 billing_model: default_billing_model(),
9999 avg_hourly_rate: default_hourly_rate(),
10000 trust_accounting: TrustAccountingConfig::default(),
10001 anomaly_rates: ProfessionalServicesAnomalyRates::default(),
10002 }
10003 }
10004}
10005
10006#[derive(Debug, Clone, Serialize, Deserialize)]
10008pub struct TrustAccountingConfig {
10009 #[serde(default)]
10011 pub enabled: bool,
10012
10013 #[serde(default = "default_true")]
10015 pub require_three_way_reconciliation: bool,
10016}
10017
10018impl Default for TrustAccountingConfig {
10019 fn default() -> Self {
10020 Self {
10021 enabled: false,
10022 require_three_way_reconciliation: true,
10023 }
10024 }
10025}
10026
10027#[derive(Debug, Clone, Serialize, Deserialize)]
10029pub struct ProfessionalServicesAnomalyRates {
10030 #[serde(default = "default_time_fraud_rate")]
10032 pub time_billing_fraud: f64,
10033
10034 #[serde(default = "default_expense_fraud_rate")]
10036 pub expense_fraud: f64,
10037
10038 #[serde(default = "default_trust_misappropriation_rate")]
10040 pub trust_misappropriation: f64,
10041}
10042
10043fn default_time_fraud_rate() -> f64 {
10044 0.02
10045}
10046
10047fn default_expense_fraud_rate() -> f64 {
10048 0.015
10049}
10050
10051fn default_trust_misappropriation_rate() -> f64 {
10052 0.003
10053}
10054
10055impl Default for ProfessionalServicesAnomalyRates {
10056 fn default() -> Self {
10057 Self {
10058 time_billing_fraud: default_time_fraud_rate(),
10059 expense_fraud: default_expense_fraud_rate(),
10060 trust_misappropriation: default_trust_misappropriation_rate(),
10061 }
10062 }
10063}
10064
10065#[derive(Debug, Clone, Serialize, Deserialize)]
10079pub struct FingerprintPrivacyConfig {
10080 #[serde(default)]
10082 pub level: String,
10083 #[serde(default = "default_epsilon")]
10085 pub epsilon: f64,
10086 #[serde(default = "default_delta")]
10088 pub delta: f64,
10089 #[serde(default = "default_k_anonymity")]
10091 pub k_anonymity: u32,
10092 #[serde(default)]
10094 pub composition_method: String,
10095}
10096
10097fn default_epsilon() -> f64 {
10098 1.0
10099}
10100
10101fn default_delta() -> f64 {
10102 1e-5
10103}
10104
10105fn default_k_anonymity() -> u32 {
10106 5
10107}
10108
10109impl Default for FingerprintPrivacyConfig {
10110 fn default() -> Self {
10111 Self {
10112 level: "standard".to_string(),
10113 epsilon: default_epsilon(),
10114 delta: default_delta(),
10115 k_anonymity: default_k_anonymity(),
10116 composition_method: "naive".to_string(),
10117 }
10118 }
10119}
10120
10121#[derive(Debug, Clone, Serialize, Deserialize)]
10135pub struct QualityGatesSchemaConfig {
10136 #[serde(default)]
10138 pub enabled: bool,
10139 #[serde(default = "default_gate_profile_name")]
10141 pub profile: String,
10142 #[serde(default)]
10144 pub fail_on_violation: bool,
10145 #[serde(default)]
10147 pub custom_gates: Vec<QualityGateEntry>,
10148}
10149
10150fn default_gate_profile_name() -> String {
10151 "default".to_string()
10152}
10153
10154impl Default for QualityGatesSchemaConfig {
10155 fn default() -> Self {
10156 Self {
10157 enabled: false,
10158 profile: default_gate_profile_name(),
10159 fail_on_violation: false,
10160 custom_gates: Vec::new(),
10161 }
10162 }
10163}
10164
10165#[derive(Debug, Clone, Serialize, Deserialize)]
10167pub struct QualityGateEntry {
10168 pub name: String,
10170 pub metric: String,
10174 pub threshold: f64,
10176 #[serde(default)]
10178 pub upper_threshold: Option<f64>,
10179 #[serde(default = "default_gate_comparison")]
10181 pub comparison: String,
10182}
10183
10184fn default_gate_comparison() -> String {
10185 "gte".to_string()
10186}
10187
10188#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10198pub struct ComplianceSchemaConfig {
10199 #[serde(default)]
10201 pub content_marking: ContentMarkingSchemaConfig,
10202 #[serde(default)]
10204 pub article10_report: bool,
10205 #[serde(default)]
10207 pub certificates: CertificateSchemaConfig,
10208}
10209
10210#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10212pub struct CertificateSchemaConfig {
10213 #[serde(default)]
10215 pub enabled: bool,
10216 #[serde(default)]
10218 pub signing_key_env: Option<String>,
10219 #[serde(default)]
10221 pub include_quality_metrics: bool,
10222}
10223
10224#[derive(Debug, Clone, Serialize, Deserialize)]
10226pub struct ContentMarkingSchemaConfig {
10227 #[serde(default = "default_true")]
10229 pub enabled: bool,
10230 #[serde(default = "default_marking_format")]
10232 pub format: String,
10233}
10234
10235fn default_marking_format() -> String {
10236 "embedded".to_string()
10237}
10238
10239impl Default for ContentMarkingSchemaConfig {
10240 fn default() -> Self {
10241 Self {
10242 enabled: true,
10243 format: default_marking_format(),
10244 }
10245 }
10246}
10247
10248#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10250pub struct WebhookSchemaConfig {
10251 #[serde(default)]
10253 pub enabled: bool,
10254 #[serde(default)]
10256 pub endpoints: Vec<WebhookEndpointConfig>,
10257}
10258
10259#[derive(Debug, Clone, Serialize, Deserialize)]
10261pub struct WebhookEndpointConfig {
10262 pub url: String,
10264 #[serde(default)]
10266 pub events: Vec<String>,
10267 #[serde(default)]
10269 pub secret: Option<String>,
10270 #[serde(default = "default_webhook_retries")]
10272 pub max_retries: u32,
10273 #[serde(default = "default_webhook_timeout")]
10275 pub timeout_secs: u64,
10276}
10277
10278fn default_webhook_retries() -> u32 {
10279 3
10280}
10281fn default_webhook_timeout() -> u64 {
10282 10
10283}
10284
10285#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10291pub struct SourceToPayConfig {
10292 #[serde(default)]
10294 pub enabled: bool,
10295 #[serde(default)]
10297 pub spend_analysis: SpendAnalysisConfig,
10298 #[serde(default)]
10300 pub sourcing: SourcingConfig,
10301 #[serde(default)]
10303 pub qualification: QualificationConfig,
10304 #[serde(default)]
10306 pub rfx: RfxConfig,
10307 #[serde(default)]
10309 pub contracts: ContractConfig,
10310 #[serde(default)]
10312 pub catalog: CatalogConfig,
10313 #[serde(default)]
10315 pub scorecards: ScorecardConfig,
10316 #[serde(default)]
10318 pub p2p_integration: P2PIntegrationConfig,
10319}
10320
10321#[derive(Debug, Clone, Serialize, Deserialize)]
10323pub struct SpendAnalysisConfig {
10324 #[serde(default = "default_hhi_threshold")]
10326 pub hhi_threshold: f64,
10327 #[serde(default = "default_contract_coverage_target")]
10329 pub contract_coverage_target: f64,
10330}
10331
10332impl Default for SpendAnalysisConfig {
10333 fn default() -> Self {
10334 Self {
10335 hhi_threshold: default_hhi_threshold(),
10336 contract_coverage_target: default_contract_coverage_target(),
10337 }
10338 }
10339}
10340
10341fn default_hhi_threshold() -> f64 {
10342 2500.0
10343}
10344fn default_contract_coverage_target() -> f64 {
10345 0.80
10346}
10347
10348#[derive(Debug, Clone, Serialize, Deserialize)]
10350pub struct SourcingConfig {
10351 #[serde(default = "default_sourcing_projects_per_year")]
10353 pub projects_per_year: u32,
10354 #[serde(default = "default_renewal_horizon_months")]
10356 pub renewal_horizon_months: u32,
10357 #[serde(default = "default_project_duration_months")]
10359 pub project_duration_months: u32,
10360}
10361
10362impl Default for SourcingConfig {
10363 fn default() -> Self {
10364 Self {
10365 projects_per_year: default_sourcing_projects_per_year(),
10366 renewal_horizon_months: default_renewal_horizon_months(),
10367 project_duration_months: default_project_duration_months(),
10368 }
10369 }
10370}
10371
10372fn default_sourcing_projects_per_year() -> u32 {
10373 10
10374}
10375fn default_renewal_horizon_months() -> u32 {
10376 3
10377}
10378fn default_project_duration_months() -> u32 {
10379 4
10380}
10381
10382#[derive(Debug, Clone, Serialize, Deserialize)]
10384pub struct QualificationConfig {
10385 #[serde(default = "default_qualification_pass_rate")]
10387 pub pass_rate: f64,
10388 #[serde(default = "default_qualification_validity_days")]
10390 pub validity_days: u32,
10391 #[serde(default = "default_financial_weight")]
10393 pub financial_weight: f64,
10394 #[serde(default = "default_quality_weight")]
10396 pub quality_weight: f64,
10397 #[serde(default = "default_delivery_weight")]
10399 pub delivery_weight: f64,
10400 #[serde(default = "default_compliance_weight")]
10402 pub compliance_weight: f64,
10403}
10404
10405impl Default for QualificationConfig {
10406 fn default() -> Self {
10407 Self {
10408 pass_rate: default_qualification_pass_rate(),
10409 validity_days: default_qualification_validity_days(),
10410 financial_weight: default_financial_weight(),
10411 quality_weight: default_quality_weight(),
10412 delivery_weight: default_delivery_weight(),
10413 compliance_weight: default_compliance_weight(),
10414 }
10415 }
10416}
10417
10418fn default_qualification_pass_rate() -> f64 {
10419 0.75
10420}
10421fn default_qualification_validity_days() -> u32 {
10422 365
10423}
10424fn default_financial_weight() -> f64 {
10425 0.25
10426}
10427fn default_quality_weight() -> f64 {
10428 0.30
10429}
10430fn default_delivery_weight() -> f64 {
10431 0.25
10432}
10433fn default_compliance_weight() -> f64 {
10434 0.20
10435}
10436
10437#[derive(Debug, Clone, Serialize, Deserialize)]
10439pub struct RfxConfig {
10440 #[serde(default = "default_rfi_threshold")]
10442 pub rfi_threshold: f64,
10443 #[serde(default = "default_min_invited_vendors")]
10445 pub min_invited_vendors: u32,
10446 #[serde(default = "default_max_invited_vendors")]
10448 pub max_invited_vendors: u32,
10449 #[serde(default = "default_response_rate")]
10451 pub response_rate: f64,
10452 #[serde(default = "default_price_weight")]
10454 pub default_price_weight: f64,
10455 #[serde(default = "default_rfx_quality_weight")]
10457 pub default_quality_weight: f64,
10458 #[serde(default = "default_rfx_delivery_weight")]
10460 pub default_delivery_weight: f64,
10461}
10462
10463impl Default for RfxConfig {
10464 fn default() -> Self {
10465 Self {
10466 rfi_threshold: default_rfi_threshold(),
10467 min_invited_vendors: default_min_invited_vendors(),
10468 max_invited_vendors: default_max_invited_vendors(),
10469 response_rate: default_response_rate(),
10470 default_price_weight: default_price_weight(),
10471 default_quality_weight: default_rfx_quality_weight(),
10472 default_delivery_weight: default_rfx_delivery_weight(),
10473 }
10474 }
10475}
10476
10477fn default_rfi_threshold() -> f64 {
10478 100_000.0
10479}
10480fn default_min_invited_vendors() -> u32 {
10481 3
10482}
10483fn default_max_invited_vendors() -> u32 {
10484 8
10485}
10486fn default_response_rate() -> f64 {
10487 0.70
10488}
10489fn default_price_weight() -> f64 {
10490 0.40
10491}
10492fn default_rfx_quality_weight() -> f64 {
10493 0.35
10494}
10495fn default_rfx_delivery_weight() -> f64 {
10496 0.25
10497}
10498
10499#[derive(Debug, Clone, Serialize, Deserialize)]
10501pub struct ContractConfig {
10502 #[serde(default = "default_min_contract_months")]
10504 pub min_duration_months: u32,
10505 #[serde(default = "default_max_contract_months")]
10507 pub max_duration_months: u32,
10508 #[serde(default = "default_auto_renewal_rate")]
10510 pub auto_renewal_rate: f64,
10511 #[serde(default = "default_amendment_rate")]
10513 pub amendment_rate: f64,
10514 #[serde(default)]
10516 pub type_distribution: ContractTypeDistribution,
10517}
10518
10519impl Default for ContractConfig {
10520 fn default() -> Self {
10521 Self {
10522 min_duration_months: default_min_contract_months(),
10523 max_duration_months: default_max_contract_months(),
10524 auto_renewal_rate: default_auto_renewal_rate(),
10525 amendment_rate: default_amendment_rate(),
10526 type_distribution: ContractTypeDistribution::default(),
10527 }
10528 }
10529}
10530
10531fn default_min_contract_months() -> u32 {
10532 12
10533}
10534fn default_max_contract_months() -> u32 {
10535 36
10536}
10537fn default_auto_renewal_rate() -> f64 {
10538 0.40
10539}
10540fn default_amendment_rate() -> f64 {
10541 0.20
10542}
10543
10544#[derive(Debug, Clone, Serialize, Deserialize)]
10546pub struct ContractTypeDistribution {
10547 #[serde(default = "default_fixed_price_pct")]
10549 pub fixed_price: f64,
10550 #[serde(default = "default_blanket_pct")]
10552 pub blanket: f64,
10553 #[serde(default = "default_time_materials_pct")]
10555 pub time_and_materials: f64,
10556 #[serde(default = "default_service_agreement_pct")]
10558 pub service_agreement: f64,
10559}
10560
10561impl Default for ContractTypeDistribution {
10562 fn default() -> Self {
10563 Self {
10564 fixed_price: default_fixed_price_pct(),
10565 blanket: default_blanket_pct(),
10566 time_and_materials: default_time_materials_pct(),
10567 service_agreement: default_service_agreement_pct(),
10568 }
10569 }
10570}
10571
10572fn default_fixed_price_pct() -> f64 {
10573 0.40
10574}
10575fn default_blanket_pct() -> f64 {
10576 0.30
10577}
10578fn default_time_materials_pct() -> f64 {
10579 0.15
10580}
10581fn default_service_agreement_pct() -> f64 {
10582 0.15
10583}
10584
10585#[derive(Debug, Clone, Serialize, Deserialize)]
10587pub struct CatalogConfig {
10588 #[serde(default = "default_preferred_vendor_flag_rate")]
10590 pub preferred_vendor_flag_rate: f64,
10591 #[serde(default = "default_multi_source_rate")]
10593 pub multi_source_rate: f64,
10594}
10595
10596impl Default for CatalogConfig {
10597 fn default() -> Self {
10598 Self {
10599 preferred_vendor_flag_rate: default_preferred_vendor_flag_rate(),
10600 multi_source_rate: default_multi_source_rate(),
10601 }
10602 }
10603}
10604
10605fn default_preferred_vendor_flag_rate() -> f64 {
10606 0.70
10607}
10608fn default_multi_source_rate() -> f64 {
10609 0.25
10610}
10611
10612#[derive(Debug, Clone, Serialize, Deserialize)]
10614pub struct ScorecardConfig {
10615 #[serde(default = "default_scorecard_frequency")]
10617 pub frequency: String,
10618 #[serde(default = "default_otd_weight")]
10620 pub on_time_delivery_weight: f64,
10621 #[serde(default = "default_quality_score_weight")]
10623 pub quality_weight: f64,
10624 #[serde(default = "default_price_score_weight")]
10626 pub price_weight: f64,
10627 #[serde(default = "default_responsiveness_weight")]
10629 pub responsiveness_weight: f64,
10630 #[serde(default = "default_grade_a_threshold")]
10632 pub grade_a_threshold: f64,
10633 #[serde(default = "default_grade_b_threshold")]
10635 pub grade_b_threshold: f64,
10636 #[serde(default = "default_grade_c_threshold")]
10638 pub grade_c_threshold: f64,
10639}
10640
10641impl Default for ScorecardConfig {
10642 fn default() -> Self {
10643 Self {
10644 frequency: default_scorecard_frequency(),
10645 on_time_delivery_weight: default_otd_weight(),
10646 quality_weight: default_quality_score_weight(),
10647 price_weight: default_price_score_weight(),
10648 responsiveness_weight: default_responsiveness_weight(),
10649 grade_a_threshold: default_grade_a_threshold(),
10650 grade_b_threshold: default_grade_b_threshold(),
10651 grade_c_threshold: default_grade_c_threshold(),
10652 }
10653 }
10654}
10655
10656fn default_scorecard_frequency() -> String {
10657 "quarterly".to_string()
10658}
10659fn default_otd_weight() -> f64 {
10660 0.30
10661}
10662fn default_quality_score_weight() -> f64 {
10663 0.30
10664}
10665fn default_price_score_weight() -> f64 {
10666 0.25
10667}
10668fn default_responsiveness_weight() -> f64 {
10669 0.15
10670}
10671fn default_grade_a_threshold() -> f64 {
10672 90.0
10673}
10674fn default_grade_b_threshold() -> f64 {
10675 75.0
10676}
10677fn default_grade_c_threshold() -> f64 {
10678 60.0
10679}
10680
10681#[derive(Debug, Clone, Serialize, Deserialize)]
10683pub struct P2PIntegrationConfig {
10684 #[serde(default = "default_off_contract_rate")]
10686 pub off_contract_rate: f64,
10687 #[serde(default = "default_price_tolerance")]
10689 pub price_tolerance: f64,
10690 #[serde(default)]
10692 pub catalog_enforcement: bool,
10693}
10694
10695impl Default for P2PIntegrationConfig {
10696 fn default() -> Self {
10697 Self {
10698 off_contract_rate: default_off_contract_rate(),
10699 price_tolerance: default_price_tolerance(),
10700 catalog_enforcement: false,
10701 }
10702 }
10703}
10704
10705fn default_off_contract_rate() -> f64 {
10706 0.15
10707}
10708fn default_price_tolerance() -> f64 {
10709 0.02
10710}
10711
10712#[derive(Debug, Clone, Serialize, Deserialize)]
10716pub struct FinancialReportingConfig {
10717 #[serde(default)]
10719 pub enabled: bool,
10720 #[serde(default = "default_true")]
10722 pub generate_balance_sheet: bool,
10723 #[serde(default = "default_true")]
10725 pub generate_income_statement: bool,
10726 #[serde(default = "default_true")]
10728 pub generate_cash_flow: bool,
10729 #[serde(default = "default_true")]
10731 pub generate_changes_in_equity: bool,
10732 #[serde(default = "default_comparative_periods")]
10734 pub comparative_periods: u32,
10735 #[serde(default)]
10737 pub management_kpis: ManagementKpisConfig,
10738 #[serde(default)]
10740 pub budgets: BudgetConfig,
10741}
10742
10743impl Default for FinancialReportingConfig {
10744 fn default() -> Self {
10745 Self {
10746 enabled: false,
10747 generate_balance_sheet: true,
10748 generate_income_statement: true,
10749 generate_cash_flow: true,
10750 generate_changes_in_equity: true,
10751 comparative_periods: default_comparative_periods(),
10752 management_kpis: ManagementKpisConfig::default(),
10753 budgets: BudgetConfig::default(),
10754 }
10755 }
10756}
10757
10758fn default_comparative_periods() -> u32 {
10759 1
10760}
10761
10762#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10764pub struct ManagementKpisConfig {
10765 #[serde(default)]
10767 pub enabled: bool,
10768 #[serde(default = "default_kpi_frequency")]
10770 pub frequency: String,
10771}
10772
10773fn default_kpi_frequency() -> String {
10774 "monthly".to_string()
10775}
10776
10777#[derive(Debug, Clone, Serialize, Deserialize)]
10779pub struct BudgetConfig {
10780 #[serde(default)]
10782 pub enabled: bool,
10783 #[serde(default = "default_revenue_growth_rate")]
10785 pub revenue_growth_rate: f64,
10786 #[serde(default = "default_expense_inflation_rate")]
10788 pub expense_inflation_rate: f64,
10789 #[serde(default = "default_variance_noise")]
10791 pub variance_noise: f64,
10792}
10793
10794impl Default for BudgetConfig {
10795 fn default() -> Self {
10796 Self {
10797 enabled: false,
10798 revenue_growth_rate: default_revenue_growth_rate(),
10799 expense_inflation_rate: default_expense_inflation_rate(),
10800 variance_noise: default_variance_noise(),
10801 }
10802 }
10803}
10804
10805fn default_revenue_growth_rate() -> f64 {
10806 0.05
10807}
10808fn default_expense_inflation_rate() -> f64 {
10809 0.03
10810}
10811fn default_variance_noise() -> f64 {
10812 0.10
10813}
10814
10815#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10819pub struct HrConfig {
10820 #[serde(default)]
10822 pub enabled: bool,
10823 #[serde(default)]
10825 pub payroll: PayrollConfig,
10826 #[serde(default)]
10828 pub time_attendance: TimeAttendanceConfig,
10829 #[serde(default)]
10831 pub expenses: ExpenseConfig,
10832}
10833
10834#[derive(Debug, Clone, Serialize, Deserialize)]
10836pub struct PayrollConfig {
10837 #[serde(default = "default_true")]
10839 pub enabled: bool,
10840 #[serde(default = "default_pay_frequency")]
10842 pub pay_frequency: String,
10843 #[serde(default)]
10845 pub salary_ranges: PayrollSalaryRanges,
10846 #[serde(default)]
10848 pub tax_rates: PayrollTaxRates,
10849 #[serde(default = "default_benefits_enrollment_rate")]
10851 pub benefits_enrollment_rate: f64,
10852 #[serde(default = "default_retirement_participation_rate")]
10854 pub retirement_participation_rate: f64,
10855}
10856
10857impl Default for PayrollConfig {
10858 fn default() -> Self {
10859 Self {
10860 enabled: true,
10861 pay_frequency: default_pay_frequency(),
10862 salary_ranges: PayrollSalaryRanges::default(),
10863 tax_rates: PayrollTaxRates::default(),
10864 benefits_enrollment_rate: default_benefits_enrollment_rate(),
10865 retirement_participation_rate: default_retirement_participation_rate(),
10866 }
10867 }
10868}
10869
10870fn default_pay_frequency() -> String {
10871 "monthly".to_string()
10872}
10873fn default_benefits_enrollment_rate() -> f64 {
10874 0.60
10875}
10876fn default_retirement_participation_rate() -> f64 {
10877 0.45
10878}
10879
10880#[derive(Debug, Clone, Serialize, Deserialize)]
10882pub struct PayrollSalaryRanges {
10883 #[serde(default = "default_staff_min")]
10885 pub staff_min: f64,
10886 #[serde(default = "default_staff_max")]
10887 pub staff_max: f64,
10888 #[serde(default = "default_manager_min")]
10890 pub manager_min: f64,
10891 #[serde(default = "default_manager_max")]
10892 pub manager_max: f64,
10893 #[serde(default = "default_director_min")]
10895 pub director_min: f64,
10896 #[serde(default = "default_director_max")]
10897 pub director_max: f64,
10898 #[serde(default = "default_executive_min")]
10900 pub executive_min: f64,
10901 #[serde(default = "default_executive_max")]
10902 pub executive_max: f64,
10903}
10904
10905impl Default for PayrollSalaryRanges {
10906 fn default() -> Self {
10907 Self {
10908 staff_min: default_staff_min(),
10909 staff_max: default_staff_max(),
10910 manager_min: default_manager_min(),
10911 manager_max: default_manager_max(),
10912 director_min: default_director_min(),
10913 director_max: default_director_max(),
10914 executive_min: default_executive_min(),
10915 executive_max: default_executive_max(),
10916 }
10917 }
10918}
10919
10920fn default_staff_min() -> f64 {
10921 50_000.0
10922}
10923fn default_staff_max() -> f64 {
10924 70_000.0
10925}
10926fn default_manager_min() -> f64 {
10927 80_000.0
10928}
10929fn default_manager_max() -> f64 {
10930 120_000.0
10931}
10932fn default_director_min() -> f64 {
10933 120_000.0
10934}
10935fn default_director_max() -> f64 {
10936 180_000.0
10937}
10938fn default_executive_min() -> f64 {
10939 180_000.0
10940}
10941fn default_executive_max() -> f64 {
10942 350_000.0
10943}
10944
10945#[derive(Debug, Clone, Serialize, Deserialize)]
10947pub struct PayrollTaxRates {
10948 #[serde(default = "default_federal_rate")]
10950 pub federal_effective: f64,
10951 #[serde(default = "default_state_rate")]
10953 pub state_effective: f64,
10954 #[serde(default = "default_fica_rate")]
10956 pub fica: f64,
10957}
10958
10959impl Default for PayrollTaxRates {
10960 fn default() -> Self {
10961 Self {
10962 federal_effective: default_federal_rate(),
10963 state_effective: default_state_rate(),
10964 fica: default_fica_rate(),
10965 }
10966 }
10967}
10968
10969fn default_federal_rate() -> f64 {
10970 0.22
10971}
10972fn default_state_rate() -> f64 {
10973 0.05
10974}
10975fn default_fica_rate() -> f64 {
10976 0.0765
10977}
10978
10979#[derive(Debug, Clone, Serialize, Deserialize)]
10981pub struct TimeAttendanceConfig {
10982 #[serde(default = "default_true")]
10984 pub enabled: bool,
10985 #[serde(default = "default_overtime_rate")]
10987 pub overtime_rate: f64,
10988}
10989
10990impl Default for TimeAttendanceConfig {
10991 fn default() -> Self {
10992 Self {
10993 enabled: true,
10994 overtime_rate: default_overtime_rate(),
10995 }
10996 }
10997}
10998
10999fn default_overtime_rate() -> f64 {
11000 0.10
11001}
11002
11003#[derive(Debug, Clone, Serialize, Deserialize)]
11005pub struct ExpenseConfig {
11006 #[serde(default = "default_true")]
11008 pub enabled: bool,
11009 #[serde(default = "default_expense_submission_rate")]
11011 pub submission_rate: f64,
11012 #[serde(default = "default_policy_violation_rate")]
11014 pub policy_violation_rate: f64,
11015}
11016
11017impl Default for ExpenseConfig {
11018 fn default() -> Self {
11019 Self {
11020 enabled: true,
11021 submission_rate: default_expense_submission_rate(),
11022 policy_violation_rate: default_policy_violation_rate(),
11023 }
11024 }
11025}
11026
11027fn default_expense_submission_rate() -> f64 {
11028 0.30
11029}
11030fn default_policy_violation_rate() -> f64 {
11031 0.08
11032}
11033
11034#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11038pub struct ManufacturingProcessConfig {
11039 #[serde(default)]
11041 pub enabled: bool,
11042 #[serde(default)]
11044 pub production_orders: ProductionOrderConfig,
11045 #[serde(default)]
11047 pub costing: ManufacturingCostingConfig,
11048 #[serde(default)]
11050 pub routing: RoutingConfig,
11051}
11052
11053#[derive(Debug, Clone, Serialize, Deserialize)]
11055pub struct ProductionOrderConfig {
11056 #[serde(default = "default_prod_orders_per_month")]
11058 pub orders_per_month: u32,
11059 #[serde(default = "default_prod_avg_batch_size")]
11061 pub avg_batch_size: u32,
11062 #[serde(default = "default_prod_yield_rate")]
11064 pub yield_rate: f64,
11065 #[serde(default = "default_prod_make_to_order_rate")]
11067 pub make_to_order_rate: f64,
11068 #[serde(default = "default_prod_rework_rate")]
11070 pub rework_rate: f64,
11071}
11072
11073impl Default for ProductionOrderConfig {
11074 fn default() -> Self {
11075 Self {
11076 orders_per_month: default_prod_orders_per_month(),
11077 avg_batch_size: default_prod_avg_batch_size(),
11078 yield_rate: default_prod_yield_rate(),
11079 make_to_order_rate: default_prod_make_to_order_rate(),
11080 rework_rate: default_prod_rework_rate(),
11081 }
11082 }
11083}
11084
11085fn default_prod_orders_per_month() -> u32 {
11086 50
11087}
11088fn default_prod_avg_batch_size() -> u32 {
11089 100
11090}
11091fn default_prod_yield_rate() -> f64 {
11092 0.97
11093}
11094fn default_prod_make_to_order_rate() -> f64 {
11095 0.20
11096}
11097fn default_prod_rework_rate() -> f64 {
11098 0.03
11099}
11100
11101#[derive(Debug, Clone, Serialize, Deserialize)]
11103pub struct ManufacturingCostingConfig {
11104 #[serde(default = "default_labor_rate")]
11106 pub labor_rate_per_hour: f64,
11107 #[serde(default = "default_overhead_rate")]
11109 pub overhead_rate: f64,
11110 #[serde(default = "default_cost_update_frequency")]
11112 pub standard_cost_update_frequency: String,
11113}
11114
11115impl Default for ManufacturingCostingConfig {
11116 fn default() -> Self {
11117 Self {
11118 labor_rate_per_hour: default_labor_rate(),
11119 overhead_rate: default_overhead_rate(),
11120 standard_cost_update_frequency: default_cost_update_frequency(),
11121 }
11122 }
11123}
11124
11125fn default_labor_rate() -> f64 {
11126 35.0
11127}
11128fn default_overhead_rate() -> f64 {
11129 1.50
11130}
11131fn default_cost_update_frequency() -> String {
11132 "quarterly".to_string()
11133}
11134
11135#[derive(Debug, Clone, Serialize, Deserialize)]
11137pub struct RoutingConfig {
11138 #[serde(default = "default_avg_operations")]
11140 pub avg_operations: u32,
11141 #[serde(default = "default_setup_time")]
11143 pub setup_time_hours: f64,
11144 #[serde(default = "default_run_time_variation")]
11146 pub run_time_variation: f64,
11147}
11148
11149impl Default for RoutingConfig {
11150 fn default() -> Self {
11151 Self {
11152 avg_operations: default_avg_operations(),
11153 setup_time_hours: default_setup_time(),
11154 run_time_variation: default_run_time_variation(),
11155 }
11156 }
11157}
11158
11159fn default_avg_operations() -> u32 {
11160 4
11161}
11162fn default_setup_time() -> f64 {
11163 1.5
11164}
11165fn default_run_time_variation() -> f64 {
11166 0.15
11167}
11168
11169#[derive(Debug, Clone, Serialize, Deserialize)]
11173pub struct SalesQuoteConfig {
11174 #[serde(default)]
11176 pub enabled: bool,
11177 #[serde(default = "default_quotes_per_month")]
11179 pub quotes_per_month: u32,
11180 #[serde(default = "default_quote_win_rate")]
11182 pub win_rate: f64,
11183 #[serde(default = "default_quote_validity_days")]
11185 pub validity_days: u32,
11186}
11187
11188impl Default for SalesQuoteConfig {
11189 fn default() -> Self {
11190 Self {
11191 enabled: false,
11192 quotes_per_month: default_quotes_per_month(),
11193 win_rate: default_quote_win_rate(),
11194 validity_days: default_quote_validity_days(),
11195 }
11196 }
11197}
11198
11199fn default_quotes_per_month() -> u32 {
11200 30
11201}
11202fn default_quote_win_rate() -> f64 {
11203 0.35
11204}
11205fn default_quote_validity_days() -> u32 {
11206 30
11207}
11208
11209#[derive(Debug, Clone, Serialize, Deserialize)]
11218pub struct TaxConfig {
11219 #[serde(default)]
11221 pub enabled: bool,
11222 #[serde(default)]
11224 pub jurisdictions: TaxJurisdictionConfig,
11225 #[serde(default)]
11227 pub vat_gst: VatGstConfig,
11228 #[serde(default)]
11230 pub sales_tax: SalesTaxConfig,
11231 #[serde(default)]
11233 pub withholding: WithholdingTaxSchemaConfig,
11234 #[serde(default)]
11236 pub provisions: TaxProvisionSchemaConfig,
11237 #[serde(default)]
11239 pub payroll_tax: PayrollTaxSchemaConfig,
11240 #[serde(default = "default_tax_anomaly_rate")]
11242 pub anomaly_rate: f64,
11243}
11244
11245fn default_tax_anomaly_rate() -> f64 {
11246 0.03
11247}
11248
11249impl Default for TaxConfig {
11250 fn default() -> Self {
11251 Self {
11252 enabled: false,
11253 jurisdictions: TaxJurisdictionConfig::default(),
11254 vat_gst: VatGstConfig::default(),
11255 sales_tax: SalesTaxConfig::default(),
11256 withholding: WithholdingTaxSchemaConfig::default(),
11257 provisions: TaxProvisionSchemaConfig::default(),
11258 payroll_tax: PayrollTaxSchemaConfig::default(),
11259 anomaly_rate: default_tax_anomaly_rate(),
11260 }
11261 }
11262}
11263
11264#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11269pub struct TaxJurisdictionConfig {
11270 #[serde(default)]
11272 pub countries: Vec<String>,
11273 #[serde(default)]
11275 pub include_subnational: bool,
11276}
11277
11278#[derive(Debug, Clone, Serialize, Deserialize)]
11283pub struct VatGstConfig {
11284 #[serde(default)]
11286 pub enabled: bool,
11287 #[serde(default)]
11289 pub standard_rates: std::collections::HashMap<String, f64>,
11290 #[serde(default)]
11292 pub reduced_rates: std::collections::HashMap<String, f64>,
11293 #[serde(default)]
11295 pub exempt_categories: Vec<String>,
11296 #[serde(default = "default_true")]
11298 pub reverse_charge: bool,
11299}
11300
11301impl Default for VatGstConfig {
11302 fn default() -> Self {
11303 Self {
11304 enabled: false,
11305 standard_rates: std::collections::HashMap::new(),
11306 reduced_rates: std::collections::HashMap::new(),
11307 exempt_categories: Vec::new(),
11308 reverse_charge: true,
11309 }
11310 }
11311}
11312
11313#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11317pub struct SalesTaxConfig {
11318 #[serde(default)]
11320 pub enabled: bool,
11321 #[serde(default)]
11323 pub nexus_states: Vec<String>,
11324}
11325
11326#[derive(Debug, Clone, Serialize, Deserialize)]
11331pub struct WithholdingTaxSchemaConfig {
11332 #[serde(default)]
11334 pub enabled: bool,
11335 #[serde(default = "default_true")]
11337 pub treaty_network: bool,
11338 #[serde(default = "default_withholding_rate")]
11340 pub default_rate: f64,
11341 #[serde(default = "default_treaty_reduced_rate")]
11343 pub treaty_reduced_rate: f64,
11344}
11345
11346fn default_withholding_rate() -> f64 {
11347 0.30
11348}
11349
11350fn default_treaty_reduced_rate() -> f64 {
11351 0.15
11352}
11353
11354impl Default for WithholdingTaxSchemaConfig {
11355 fn default() -> Self {
11356 Self {
11357 enabled: false,
11358 treaty_network: true,
11359 default_rate: default_withholding_rate(),
11360 treaty_reduced_rate: default_treaty_reduced_rate(),
11361 }
11362 }
11363}
11364
11365#[derive(Debug, Clone, Serialize, Deserialize)]
11370pub struct TaxProvisionSchemaConfig {
11371 #[serde(default = "default_true")]
11374 pub enabled: bool,
11375 #[serde(default = "default_statutory_rate")]
11377 pub statutory_rate: f64,
11378 #[serde(default = "default_true")]
11380 pub uncertain_positions: bool,
11381}
11382
11383fn default_statutory_rate() -> f64 {
11384 0.21
11385}
11386
11387impl Default for TaxProvisionSchemaConfig {
11388 fn default() -> Self {
11389 Self {
11390 enabled: true,
11391 statutory_rate: default_statutory_rate(),
11392 uncertain_positions: true,
11393 }
11394 }
11395}
11396
11397#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11402pub struct PayrollTaxSchemaConfig {
11403 #[serde(default)]
11405 pub enabled: bool,
11406}
11407
11408#[derive(Debug, Clone, Serialize, Deserialize)]
11418pub struct TreasuryConfig {
11419 #[serde(default)]
11421 pub enabled: bool,
11422 #[serde(default)]
11424 pub cash_positioning: CashPositioningConfig,
11425 #[serde(default)]
11427 pub cash_forecasting: CashForecastingConfig,
11428 #[serde(default)]
11430 pub cash_pooling: CashPoolingConfig,
11431 #[serde(default)]
11433 pub hedging: HedgingSchemaConfig,
11434 #[serde(default)]
11436 pub debt: DebtSchemaConfig,
11437 #[serde(default)]
11439 pub netting: NettingSchemaConfig,
11440 #[serde(default)]
11442 pub bank_guarantees: BankGuaranteeSchemaConfig,
11443 #[serde(default = "default_treasury_anomaly_rate")]
11445 pub anomaly_rate: f64,
11446}
11447
11448fn default_treasury_anomaly_rate() -> f64 {
11449 0.02
11450}
11451
11452impl Default for TreasuryConfig {
11453 fn default() -> Self {
11454 Self {
11455 enabled: false,
11456 cash_positioning: CashPositioningConfig::default(),
11457 cash_forecasting: CashForecastingConfig::default(),
11458 cash_pooling: CashPoolingConfig::default(),
11459 hedging: HedgingSchemaConfig::default(),
11460 debt: DebtSchemaConfig::default(),
11461 netting: NettingSchemaConfig::default(),
11462 bank_guarantees: BankGuaranteeSchemaConfig::default(),
11463 anomaly_rate: default_treasury_anomaly_rate(),
11464 }
11465 }
11466}
11467
11468#[derive(Debug, Clone, Serialize, Deserialize)]
11472pub struct CashPositioningConfig {
11473 #[serde(default = "default_true")]
11475 pub enabled: bool,
11476 #[serde(default = "default_cash_frequency")]
11478 pub frequency: String,
11479 #[serde(default = "default_minimum_balance_policy")]
11481 pub minimum_balance_policy: f64,
11482}
11483
11484fn default_cash_frequency() -> String {
11485 "daily".to_string()
11486}
11487
11488fn default_minimum_balance_policy() -> f64 {
11489 100_000.0
11490}
11491
11492impl Default for CashPositioningConfig {
11493 fn default() -> Self {
11494 Self {
11495 enabled: true,
11496 frequency: default_cash_frequency(),
11497 minimum_balance_policy: default_minimum_balance_policy(),
11498 }
11499 }
11500}
11501
11502#[derive(Debug, Clone, Serialize, Deserialize)]
11506pub struct CashForecastingConfig {
11507 #[serde(default = "default_true")]
11509 pub enabled: bool,
11510 #[serde(default = "default_horizon_days")]
11512 pub horizon_days: u32,
11513 #[serde(default = "default_ar_probability_curve")]
11515 pub ar_collection_probability_curve: String,
11516 #[serde(default = "default_confidence_interval")]
11518 pub confidence_interval: f64,
11519}
11520
11521fn default_horizon_days() -> u32 {
11522 90
11523}
11524
11525fn default_ar_probability_curve() -> String {
11526 "aging".to_string()
11527}
11528
11529fn default_confidence_interval() -> f64 {
11530 0.90
11531}
11532
11533impl Default for CashForecastingConfig {
11534 fn default() -> Self {
11535 Self {
11536 enabled: true,
11537 horizon_days: default_horizon_days(),
11538 ar_collection_probability_curve: default_ar_probability_curve(),
11539 confidence_interval: default_confidence_interval(),
11540 }
11541 }
11542}
11543
11544#[derive(Debug, Clone, Serialize, Deserialize)]
11548pub struct CashPoolingConfig {
11549 #[serde(default)]
11551 pub enabled: bool,
11552 #[serde(default = "default_pool_type")]
11554 pub pool_type: String,
11555 #[serde(default = "default_sweep_time")]
11557 pub sweep_time: String,
11558}
11559
11560fn default_pool_type() -> String {
11561 "zero_balancing".to_string()
11562}
11563
11564fn default_sweep_time() -> String {
11565 "16:00".to_string()
11566}
11567
11568impl Default for CashPoolingConfig {
11569 fn default() -> Self {
11570 Self {
11571 enabled: false,
11572 pool_type: default_pool_type(),
11573 sweep_time: default_sweep_time(),
11574 }
11575 }
11576}
11577
11578#[derive(Debug, Clone, Serialize, Deserialize)]
11583pub struct HedgingSchemaConfig {
11584 #[serde(default)]
11586 pub enabled: bool,
11587 #[serde(default = "default_hedge_ratio")]
11589 pub hedge_ratio: f64,
11590 #[serde(default = "default_hedge_instruments")]
11592 pub instruments: Vec<String>,
11593 #[serde(default = "default_true")]
11595 pub hedge_accounting: bool,
11596 #[serde(default = "default_effectiveness_method")]
11598 pub effectiveness_method: String,
11599}
11600
11601fn default_hedge_ratio() -> f64 {
11602 0.75
11603}
11604
11605fn default_hedge_instruments() -> Vec<String> {
11606 vec!["fx_forward".to_string(), "interest_rate_swap".to_string()]
11607}
11608
11609fn default_effectiveness_method() -> String {
11610 "regression".to_string()
11611}
11612
11613impl Default for HedgingSchemaConfig {
11614 fn default() -> Self {
11615 Self {
11616 enabled: false,
11617 hedge_ratio: default_hedge_ratio(),
11618 instruments: default_hedge_instruments(),
11619 hedge_accounting: true,
11620 effectiveness_method: default_effectiveness_method(),
11621 }
11622 }
11623}
11624
11625#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11630pub struct DebtSchemaConfig {
11631 #[serde(default)]
11633 pub enabled: bool,
11634 #[serde(default)]
11636 pub instruments: Vec<DebtInstrumentDef>,
11637 #[serde(default)]
11639 pub covenants: Vec<CovenantDef>,
11640}
11641
11642#[derive(Debug, Clone, Serialize, Deserialize)]
11644pub struct DebtInstrumentDef {
11645 #[serde(rename = "type")]
11647 pub instrument_type: String,
11648 #[serde(default)]
11650 pub principal: Option<f64>,
11651 #[serde(default)]
11653 pub rate: Option<f64>,
11654 #[serde(default)]
11656 pub maturity_months: Option<u32>,
11657 #[serde(default)]
11659 pub facility: Option<f64>,
11660}
11661
11662#[derive(Debug, Clone, Serialize, Deserialize)]
11664pub struct CovenantDef {
11665 #[serde(rename = "type")]
11668 pub covenant_type: String,
11669 pub threshold: f64,
11671}
11672
11673#[derive(Debug, Clone, Serialize, Deserialize)]
11677pub struct NettingSchemaConfig {
11678 #[serde(default)]
11680 pub enabled: bool,
11681 #[serde(default = "default_netting_cycle")]
11683 pub cycle: String,
11684}
11685
11686fn default_netting_cycle() -> String {
11687 "monthly".to_string()
11688}
11689
11690impl Default for NettingSchemaConfig {
11691 fn default() -> Self {
11692 Self {
11693 enabled: false,
11694 cycle: default_netting_cycle(),
11695 }
11696 }
11697}
11698
11699#[derive(Debug, Clone, Serialize, Deserialize)]
11703pub struct BankGuaranteeSchemaConfig {
11704 #[serde(default)]
11706 pub enabled: bool,
11707 #[serde(default = "default_guarantee_count")]
11709 pub count: u32,
11710}
11711
11712fn default_guarantee_count() -> u32 {
11713 5
11714}
11715
11716impl Default for BankGuaranteeSchemaConfig {
11717 fn default() -> Self {
11718 Self {
11719 enabled: false,
11720 count: default_guarantee_count(),
11721 }
11722 }
11723}
11724
11725#[derive(Debug, Clone, Serialize, Deserialize)]
11734pub struct ProjectAccountingConfig {
11735 #[serde(default)]
11737 pub enabled: bool,
11738 #[serde(default = "default_project_count")]
11740 pub project_count: u32,
11741 #[serde(default)]
11743 pub project_types: ProjectTypeDistribution,
11744 #[serde(default)]
11746 pub wbs: WbsSchemaConfig,
11747 #[serde(default)]
11749 pub cost_allocation: CostAllocationConfig,
11750 #[serde(default)]
11752 pub revenue_recognition: ProjectRevenueRecognitionConfig,
11753 #[serde(default)]
11755 pub milestones: MilestoneSchemaConfig,
11756 #[serde(default)]
11758 pub change_orders: ChangeOrderSchemaConfig,
11759 #[serde(default)]
11761 pub retainage: RetainageSchemaConfig,
11762 #[serde(default)]
11764 pub earned_value: EarnedValueSchemaConfig,
11765 #[serde(default = "default_project_anomaly_rate")]
11767 pub anomaly_rate: f64,
11768}
11769
11770fn default_project_count() -> u32 {
11771 10
11772}
11773
11774fn default_project_anomaly_rate() -> f64 {
11775 0.03
11776}
11777
11778impl Default for ProjectAccountingConfig {
11779 fn default() -> Self {
11780 Self {
11781 enabled: false,
11782 project_count: default_project_count(),
11783 project_types: ProjectTypeDistribution::default(),
11784 wbs: WbsSchemaConfig::default(),
11785 cost_allocation: CostAllocationConfig::default(),
11786 revenue_recognition: ProjectRevenueRecognitionConfig::default(),
11787 milestones: MilestoneSchemaConfig::default(),
11788 change_orders: ChangeOrderSchemaConfig::default(),
11789 retainage: RetainageSchemaConfig::default(),
11790 earned_value: EarnedValueSchemaConfig::default(),
11791 anomaly_rate: default_project_anomaly_rate(),
11792 }
11793 }
11794}
11795
11796#[derive(Debug, Clone, Serialize, Deserialize)]
11798pub struct ProjectTypeDistribution {
11799 #[serde(default = "default_capital_weight")]
11801 pub capital: f64,
11802 #[serde(default = "default_internal_weight")]
11804 pub internal: f64,
11805 #[serde(default = "default_customer_weight")]
11807 pub customer: f64,
11808 #[serde(default = "default_rnd_weight")]
11810 pub r_and_d: f64,
11811 #[serde(default = "default_maintenance_weight")]
11813 pub maintenance: f64,
11814 #[serde(default = "default_technology_weight")]
11816 pub technology: f64,
11817}
11818
11819fn default_capital_weight() -> f64 {
11820 0.25
11821}
11822fn default_internal_weight() -> f64 {
11823 0.20
11824}
11825fn default_customer_weight() -> f64 {
11826 0.30
11827}
11828fn default_rnd_weight() -> f64 {
11829 0.10
11830}
11831fn default_maintenance_weight() -> f64 {
11832 0.10
11833}
11834fn default_technology_weight() -> f64 {
11835 0.05
11836}
11837
11838impl Default for ProjectTypeDistribution {
11839 fn default() -> Self {
11840 Self {
11841 capital: default_capital_weight(),
11842 internal: default_internal_weight(),
11843 customer: default_customer_weight(),
11844 r_and_d: default_rnd_weight(),
11845 maintenance: default_maintenance_weight(),
11846 technology: default_technology_weight(),
11847 }
11848 }
11849}
11850
11851#[derive(Debug, Clone, Serialize, Deserialize)]
11853pub struct WbsSchemaConfig {
11854 #[serde(default = "default_wbs_max_depth")]
11856 pub max_depth: u32,
11857 #[serde(default = "default_wbs_min_elements")]
11859 pub min_elements_per_level: u32,
11860 #[serde(default = "default_wbs_max_elements")]
11862 pub max_elements_per_level: u32,
11863}
11864
11865fn default_wbs_max_depth() -> u32 {
11866 3
11867}
11868fn default_wbs_min_elements() -> u32 {
11869 2
11870}
11871fn default_wbs_max_elements() -> u32 {
11872 6
11873}
11874
11875impl Default for WbsSchemaConfig {
11876 fn default() -> Self {
11877 Self {
11878 max_depth: default_wbs_max_depth(),
11879 min_elements_per_level: default_wbs_min_elements(),
11880 max_elements_per_level: default_wbs_max_elements(),
11881 }
11882 }
11883}
11884
11885#[derive(Debug, Clone, Serialize, Deserialize)]
11887pub struct CostAllocationConfig {
11888 #[serde(default = "default_time_entry_rate")]
11890 pub time_entry_project_rate: f64,
11891 #[serde(default = "default_expense_rate")]
11893 pub expense_project_rate: f64,
11894 #[serde(default = "default_po_rate")]
11896 pub purchase_order_project_rate: f64,
11897 #[serde(default = "default_vi_rate")]
11899 pub vendor_invoice_project_rate: f64,
11900}
11901
11902fn default_time_entry_rate() -> f64 {
11903 0.60
11904}
11905fn default_expense_rate() -> f64 {
11906 0.30
11907}
11908fn default_po_rate() -> f64 {
11909 0.40
11910}
11911fn default_vi_rate() -> f64 {
11912 0.35
11913}
11914
11915impl Default for CostAllocationConfig {
11916 fn default() -> Self {
11917 Self {
11918 time_entry_project_rate: default_time_entry_rate(),
11919 expense_project_rate: default_expense_rate(),
11920 purchase_order_project_rate: default_po_rate(),
11921 vendor_invoice_project_rate: default_vi_rate(),
11922 }
11923 }
11924}
11925
11926#[derive(Debug, Clone, Serialize, Deserialize)]
11928pub struct ProjectRevenueRecognitionConfig {
11929 #[serde(default = "default_true")]
11931 pub enabled: bool,
11932 #[serde(default = "default_revenue_method")]
11934 pub method: String,
11935 #[serde(default = "default_completion_measure")]
11937 pub completion_measure: String,
11938 #[serde(default = "default_avg_contract_value")]
11940 pub avg_contract_value: f64,
11941}
11942
11943fn default_revenue_method() -> String {
11944 "percentage_of_completion".to_string()
11945}
11946fn default_completion_measure() -> String {
11947 "cost_to_cost".to_string()
11948}
11949fn default_avg_contract_value() -> f64 {
11950 500_000.0
11951}
11952
11953impl Default for ProjectRevenueRecognitionConfig {
11954 fn default() -> Self {
11955 Self {
11956 enabled: true,
11957 method: default_revenue_method(),
11958 completion_measure: default_completion_measure(),
11959 avg_contract_value: default_avg_contract_value(),
11960 }
11961 }
11962}
11963
11964#[derive(Debug, Clone, Serialize, Deserialize)]
11966pub struct MilestoneSchemaConfig {
11967 #[serde(default = "default_true")]
11969 pub enabled: bool,
11970 #[serde(default = "default_milestones_per_project")]
11972 pub avg_per_project: u32,
11973 #[serde(default = "default_payment_milestone_rate")]
11975 pub payment_milestone_rate: f64,
11976}
11977
11978fn default_milestones_per_project() -> u32 {
11979 4
11980}
11981fn default_payment_milestone_rate() -> f64 {
11982 0.50
11983}
11984
11985impl Default for MilestoneSchemaConfig {
11986 fn default() -> Self {
11987 Self {
11988 enabled: true,
11989 avg_per_project: default_milestones_per_project(),
11990 payment_milestone_rate: default_payment_milestone_rate(),
11991 }
11992 }
11993}
11994
11995#[derive(Debug, Clone, Serialize, Deserialize)]
11997pub struct ChangeOrderSchemaConfig {
11998 #[serde(default = "default_true")]
12000 pub enabled: bool,
12001 #[serde(default = "default_change_order_probability")]
12003 pub probability: f64,
12004 #[serde(default = "default_max_change_orders")]
12006 pub max_per_project: u32,
12007 #[serde(default = "default_change_order_approval_rate")]
12009 pub approval_rate: f64,
12010}
12011
12012fn default_change_order_probability() -> f64 {
12013 0.40
12014}
12015fn default_max_change_orders() -> u32 {
12016 3
12017}
12018fn default_change_order_approval_rate() -> f64 {
12019 0.75
12020}
12021
12022impl Default for ChangeOrderSchemaConfig {
12023 fn default() -> Self {
12024 Self {
12025 enabled: true,
12026 probability: default_change_order_probability(),
12027 max_per_project: default_max_change_orders(),
12028 approval_rate: default_change_order_approval_rate(),
12029 }
12030 }
12031}
12032
12033#[derive(Debug, Clone, Serialize, Deserialize)]
12035pub struct RetainageSchemaConfig {
12036 #[serde(default)]
12038 pub enabled: bool,
12039 #[serde(default = "default_retainage_pct")]
12041 pub default_percentage: f64,
12042}
12043
12044fn default_retainage_pct() -> f64 {
12045 0.10
12046}
12047
12048impl Default for RetainageSchemaConfig {
12049 fn default() -> Self {
12050 Self {
12051 enabled: false,
12052 default_percentage: default_retainage_pct(),
12053 }
12054 }
12055}
12056
12057#[derive(Debug, Clone, Serialize, Deserialize)]
12059pub struct EarnedValueSchemaConfig {
12060 #[serde(default = "default_true")]
12062 pub enabled: bool,
12063 #[serde(default = "default_evm_frequency")]
12065 pub frequency: String,
12066}
12067
12068fn default_evm_frequency() -> String {
12069 "monthly".to_string()
12070}
12071
12072impl Default for EarnedValueSchemaConfig {
12073 fn default() -> Self {
12074 Self {
12075 enabled: true,
12076 frequency: default_evm_frequency(),
12077 }
12078 }
12079}
12080
12081#[derive(Debug, Clone, Serialize, Deserialize)]
12087pub struct EsgConfig {
12088 #[serde(default)]
12090 pub enabled: bool,
12091 #[serde(default)]
12093 pub environmental: EnvironmentalConfig,
12094 #[serde(default)]
12096 pub social: SocialConfig,
12097 #[serde(default)]
12099 pub governance: GovernanceSchemaConfig,
12100 #[serde(default)]
12102 pub supply_chain_esg: SupplyChainEsgConfig,
12103 #[serde(default)]
12105 pub reporting: EsgReportingConfig,
12106 #[serde(default)]
12108 pub climate_scenarios: ClimateScenarioConfig,
12109 #[serde(default = "default_esg_anomaly_rate")]
12111 pub anomaly_rate: f64,
12112}
12113
12114fn default_esg_anomaly_rate() -> f64 {
12115 0.02
12116}
12117
12118impl Default for EsgConfig {
12119 fn default() -> Self {
12120 Self {
12121 enabled: false,
12122 environmental: EnvironmentalConfig::default(),
12123 social: SocialConfig::default(),
12124 governance: GovernanceSchemaConfig::default(),
12125 supply_chain_esg: SupplyChainEsgConfig::default(),
12126 reporting: EsgReportingConfig::default(),
12127 climate_scenarios: ClimateScenarioConfig::default(),
12128 anomaly_rate: default_esg_anomaly_rate(),
12129 }
12130 }
12131}
12132
12133#[derive(Debug, Clone, Serialize, Deserialize, Default)]
12138pub struct CountryPacksSchemaConfig {
12139 #[serde(default)]
12141 pub external_dir: Option<PathBuf>,
12142 #[serde(default)]
12146 pub overrides: std::collections::HashMap<String, serde_json::Value>,
12147}
12148
12149#[derive(Debug, Clone, Serialize, Deserialize)]
12151pub struct EnvironmentalConfig {
12152 #[serde(default = "default_true")]
12154 pub enabled: bool,
12155 #[serde(default)]
12157 pub scope1: EmissionScopeConfig,
12158 #[serde(default)]
12160 pub scope2: EmissionScopeConfig,
12161 #[serde(default)]
12163 pub scope3: Scope3Config,
12164 #[serde(default)]
12166 pub energy: EnergySchemaConfig,
12167 #[serde(default)]
12169 pub water: WaterSchemaConfig,
12170 #[serde(default)]
12172 pub waste: WasteSchemaConfig,
12173}
12174
12175impl Default for EnvironmentalConfig {
12176 fn default() -> Self {
12177 Self {
12178 enabled: true,
12179 scope1: EmissionScopeConfig::default(),
12180 scope2: EmissionScopeConfig::default(),
12181 scope3: Scope3Config::default(),
12182 energy: EnergySchemaConfig::default(),
12183 water: WaterSchemaConfig::default(),
12184 waste: WasteSchemaConfig::default(),
12185 }
12186 }
12187}
12188
12189#[derive(Debug, Clone, Serialize, Deserialize)]
12191pub struct EmissionScopeConfig {
12192 #[serde(default = "default_true")]
12194 pub enabled: bool,
12195 #[serde(default = "default_emission_region")]
12197 pub factor_region: String,
12198}
12199
12200fn default_emission_region() -> String {
12201 "US".to_string()
12202}
12203
12204impl Default for EmissionScopeConfig {
12205 fn default() -> Self {
12206 Self {
12207 enabled: true,
12208 factor_region: default_emission_region(),
12209 }
12210 }
12211}
12212
12213#[derive(Debug, Clone, Serialize, Deserialize)]
12215pub struct Scope3Config {
12216 #[serde(default = "default_true")]
12218 pub enabled: bool,
12219 #[serde(default = "default_scope3_categories")]
12221 pub categories: Vec<String>,
12222 #[serde(default = "default_spend_intensity")]
12224 pub default_spend_intensity_kg_per_usd: f64,
12225}
12226
12227fn default_scope3_categories() -> Vec<String> {
12228 vec![
12229 "purchased_goods".to_string(),
12230 "business_travel".to_string(),
12231 "employee_commuting".to_string(),
12232 ]
12233}
12234
12235fn default_spend_intensity() -> f64 {
12236 0.5
12237}
12238
12239impl Default for Scope3Config {
12240 fn default() -> Self {
12241 Self {
12242 enabled: true,
12243 categories: default_scope3_categories(),
12244 default_spend_intensity_kg_per_usd: default_spend_intensity(),
12245 }
12246 }
12247}
12248
12249#[derive(Debug, Clone, Serialize, Deserialize)]
12251pub struct EnergySchemaConfig {
12252 #[serde(default = "default_true")]
12254 pub enabled: bool,
12255 #[serde(default = "default_facility_count")]
12257 pub facility_count: u32,
12258 #[serde(default = "default_renewable_target")]
12260 pub renewable_target: f64,
12261}
12262
12263fn default_facility_count() -> u32 {
12264 5
12265}
12266
12267fn default_renewable_target() -> f64 {
12268 0.30
12269}
12270
12271impl Default for EnergySchemaConfig {
12272 fn default() -> Self {
12273 Self {
12274 enabled: true,
12275 facility_count: default_facility_count(),
12276 renewable_target: default_renewable_target(),
12277 }
12278 }
12279}
12280
12281#[derive(Debug, Clone, Serialize, Deserialize)]
12283pub struct WaterSchemaConfig {
12284 #[serde(default = "default_true")]
12286 pub enabled: bool,
12287 #[serde(default = "default_water_facility_count")]
12289 pub facility_count: u32,
12290}
12291
12292fn default_water_facility_count() -> u32 {
12293 3
12294}
12295
12296impl Default for WaterSchemaConfig {
12297 fn default() -> Self {
12298 Self {
12299 enabled: true,
12300 facility_count: default_water_facility_count(),
12301 }
12302 }
12303}
12304
12305#[derive(Debug, Clone, Serialize, Deserialize)]
12307pub struct WasteSchemaConfig {
12308 #[serde(default = "default_true")]
12310 pub enabled: bool,
12311 #[serde(default = "default_diversion_target")]
12313 pub diversion_target: f64,
12314}
12315
12316fn default_diversion_target() -> f64 {
12317 0.50
12318}
12319
12320impl Default for WasteSchemaConfig {
12321 fn default() -> Self {
12322 Self {
12323 enabled: true,
12324 diversion_target: default_diversion_target(),
12325 }
12326 }
12327}
12328
12329#[derive(Debug, Clone, Serialize, Deserialize)]
12331pub struct SocialConfig {
12332 #[serde(default = "default_true")]
12334 pub enabled: bool,
12335 #[serde(default)]
12337 pub diversity: DiversitySchemaConfig,
12338 #[serde(default)]
12340 pub pay_equity: PayEquitySchemaConfig,
12341 #[serde(default)]
12343 pub safety: SafetySchemaConfig,
12344}
12345
12346impl Default for SocialConfig {
12347 fn default() -> Self {
12348 Self {
12349 enabled: true,
12350 diversity: DiversitySchemaConfig::default(),
12351 pay_equity: PayEquitySchemaConfig::default(),
12352 safety: SafetySchemaConfig::default(),
12353 }
12354 }
12355}
12356
12357#[derive(Debug, Clone, Serialize, Deserialize)]
12359pub struct DiversitySchemaConfig {
12360 #[serde(default = "default_true")]
12362 pub enabled: bool,
12363 #[serde(default = "default_diversity_dimensions")]
12365 pub dimensions: Vec<String>,
12366}
12367
12368fn default_diversity_dimensions() -> Vec<String> {
12369 vec![
12370 "gender".to_string(),
12371 "ethnicity".to_string(),
12372 "age_group".to_string(),
12373 ]
12374}
12375
12376impl Default for DiversitySchemaConfig {
12377 fn default() -> Self {
12378 Self {
12379 enabled: true,
12380 dimensions: default_diversity_dimensions(),
12381 }
12382 }
12383}
12384
12385#[derive(Debug, Clone, Serialize, Deserialize)]
12387pub struct PayEquitySchemaConfig {
12388 #[serde(default = "default_true")]
12390 pub enabled: bool,
12391 #[serde(default = "default_pay_gap_threshold")]
12393 pub gap_threshold: f64,
12394}
12395
12396fn default_pay_gap_threshold() -> f64 {
12397 0.05
12398}
12399
12400impl Default for PayEquitySchemaConfig {
12401 fn default() -> Self {
12402 Self {
12403 enabled: true,
12404 gap_threshold: default_pay_gap_threshold(),
12405 }
12406 }
12407}
12408
12409#[derive(Debug, Clone, Serialize, Deserialize)]
12411pub struct SafetySchemaConfig {
12412 #[serde(default = "default_true")]
12414 pub enabled: bool,
12415 #[serde(default = "default_trir_target")]
12417 pub target_trir: f64,
12418 #[serde(default = "default_incident_count")]
12420 pub incident_count: u32,
12421}
12422
12423fn default_trir_target() -> f64 {
12424 2.5
12425}
12426
12427fn default_incident_count() -> u32 {
12428 20
12429}
12430
12431impl Default for SafetySchemaConfig {
12432 fn default() -> Self {
12433 Self {
12434 enabled: true,
12435 target_trir: default_trir_target(),
12436 incident_count: default_incident_count(),
12437 }
12438 }
12439}
12440
12441#[derive(Debug, Clone, Serialize, Deserialize)]
12443pub struct GovernanceSchemaConfig {
12444 #[serde(default = "default_true")]
12446 pub enabled: bool,
12447 #[serde(default = "default_board_size")]
12449 pub board_size: u32,
12450 #[serde(default = "default_independence_target")]
12452 pub independence_target: f64,
12453}
12454
12455fn default_board_size() -> u32 {
12456 11
12457}
12458
12459fn default_independence_target() -> f64 {
12460 0.67
12461}
12462
12463impl Default for GovernanceSchemaConfig {
12464 fn default() -> Self {
12465 Self {
12466 enabled: true,
12467 board_size: default_board_size(),
12468 independence_target: default_independence_target(),
12469 }
12470 }
12471}
12472
12473#[derive(Debug, Clone, Serialize, Deserialize)]
12475pub struct SupplyChainEsgConfig {
12476 #[serde(default = "default_true")]
12478 pub enabled: bool,
12479 #[serde(default = "default_assessment_coverage")]
12481 pub assessment_coverage: f64,
12482 #[serde(default = "default_high_risk_countries")]
12484 pub high_risk_countries: Vec<String>,
12485}
12486
12487fn default_assessment_coverage() -> f64 {
12488 0.80
12489}
12490
12491fn default_high_risk_countries() -> Vec<String> {
12492 vec!["CN".to_string(), "BD".to_string(), "MM".to_string()]
12493}
12494
12495impl Default for SupplyChainEsgConfig {
12496 fn default() -> Self {
12497 Self {
12498 enabled: true,
12499 assessment_coverage: default_assessment_coverage(),
12500 high_risk_countries: default_high_risk_countries(),
12501 }
12502 }
12503}
12504
12505#[derive(Debug, Clone, Serialize, Deserialize)]
12507pub struct EsgReportingConfig {
12508 #[serde(default = "default_true")]
12510 pub enabled: bool,
12511 #[serde(default = "default_esg_frameworks")]
12513 pub frameworks: Vec<String>,
12514 #[serde(default = "default_true")]
12516 pub materiality_assessment: bool,
12517 #[serde(default = "default_materiality_threshold")]
12519 pub impact_threshold: f64,
12520 #[serde(default = "default_materiality_threshold")]
12522 pub financial_threshold: f64,
12523}
12524
12525fn default_esg_frameworks() -> Vec<String> {
12526 vec!["GRI".to_string(), "ESRS".to_string()]
12527}
12528
12529fn default_materiality_threshold() -> f64 {
12530 0.6
12531}
12532
12533impl Default for EsgReportingConfig {
12534 fn default() -> Self {
12535 Self {
12536 enabled: true,
12537 frameworks: default_esg_frameworks(),
12538 materiality_assessment: true,
12539 impact_threshold: default_materiality_threshold(),
12540 financial_threshold: default_materiality_threshold(),
12541 }
12542 }
12543}
12544
12545#[derive(Debug, Clone, Serialize, Deserialize)]
12547pub struct ClimateScenarioConfig {
12548 #[serde(default)]
12550 pub enabled: bool,
12551 #[serde(default = "default_climate_scenarios")]
12553 pub scenarios: Vec<String>,
12554 #[serde(default = "default_time_horizons")]
12556 pub time_horizons: Vec<u32>,
12557}
12558
12559fn default_climate_scenarios() -> Vec<String> {
12560 vec![
12561 "net_zero_2050".to_string(),
12562 "stated_policies".to_string(),
12563 "current_trajectory".to_string(),
12564 ]
12565}
12566
12567fn default_time_horizons() -> Vec<u32> {
12568 vec![5, 10, 30]
12569}
12570
12571impl Default for ClimateScenarioConfig {
12572 fn default() -> Self {
12573 Self {
12574 enabled: false,
12575 scenarios: default_climate_scenarios(),
12576 time_horizons: default_time_horizons(),
12577 }
12578 }
12579}
12580
12581#[derive(Debug, Clone, Serialize, Deserialize, Default)]
12585pub struct ScenariosConfig {
12586 #[serde(default)]
12588 pub enabled: bool,
12589 #[serde(default)]
12591 pub scenarios: Vec<ScenarioSchemaConfig>,
12592 #[serde(default)]
12594 pub causal_model: CausalModelSchemaConfig,
12595 #[serde(default)]
12597 pub defaults: ScenarioDefaultsConfig,
12598 #[serde(default)]
12601 pub generate_counterfactuals: bool,
12602}
12603
12604#[derive(Debug, Clone, Serialize, Deserialize)]
12606pub struct ScenarioSchemaConfig {
12607 pub name: String,
12609 #[serde(default)]
12611 pub description: String,
12612 #[serde(default)]
12614 pub tags: Vec<String>,
12615 pub base: Option<String>,
12617 pub probability_weight: Option<f64>,
12619 #[serde(default)]
12621 pub interventions: Vec<InterventionSchemaConfig>,
12622 #[serde(default)]
12624 pub constraints: ScenarioConstraintsSchemaConfig,
12625 #[serde(default)]
12627 pub output: ScenarioOutputSchemaConfig,
12628 #[serde(default)]
12630 pub metadata: std::collections::HashMap<String, String>,
12631}
12632
12633#[derive(Debug, Clone, Serialize, Deserialize)]
12635pub struct InterventionSchemaConfig {
12636 #[serde(flatten)]
12638 pub intervention_type: serde_json::Value,
12639 #[serde(default)]
12641 pub timing: InterventionTimingSchemaConfig,
12642 pub label: Option<String>,
12644 #[serde(default)]
12646 pub priority: u32,
12647}
12648
12649#[derive(Debug, Clone, Serialize, Deserialize)]
12651pub struct InterventionTimingSchemaConfig {
12652 #[serde(default = "default_start_month")]
12654 pub start_month: u32,
12655 pub duration_months: Option<u32>,
12657 #[serde(default = "default_onset")]
12659 pub onset: String,
12660 pub ramp_months: Option<u32>,
12662}
12663
12664fn default_start_month() -> u32 {
12665 1
12666}
12667
12668fn default_onset() -> String {
12669 "sudden".to_string()
12670}
12671
12672impl Default for InterventionTimingSchemaConfig {
12673 fn default() -> Self {
12674 Self {
12675 start_month: 1,
12676 duration_months: None,
12677 onset: "sudden".to_string(),
12678 ramp_months: None,
12679 }
12680 }
12681}
12682
12683#[derive(Debug, Clone, Serialize, Deserialize)]
12685pub struct ScenarioConstraintsSchemaConfig {
12686 #[serde(default = "default_true")]
12687 pub preserve_accounting_identity: bool,
12688 #[serde(default = "default_true")]
12689 pub preserve_document_chains: bool,
12690 #[serde(default = "default_true")]
12691 pub preserve_period_close: bool,
12692 #[serde(default = "default_true")]
12693 pub preserve_balance_coherence: bool,
12694 #[serde(default)]
12695 pub custom: Vec<CustomConstraintSchemaConfig>,
12696}
12697
12698impl Default for ScenarioConstraintsSchemaConfig {
12699 fn default() -> Self {
12700 Self {
12701 preserve_accounting_identity: true,
12702 preserve_document_chains: true,
12703 preserve_period_close: true,
12704 preserve_balance_coherence: true,
12705 custom: Vec::new(),
12706 }
12707 }
12708}
12709
12710#[derive(Debug, Clone, Serialize, Deserialize)]
12712pub struct CustomConstraintSchemaConfig {
12713 pub config_path: String,
12714 pub min: Option<f64>,
12715 pub max: Option<f64>,
12716 #[serde(default)]
12717 pub description: String,
12718}
12719
12720#[derive(Debug, Clone, Serialize, Deserialize)]
12722pub struct ScenarioOutputSchemaConfig {
12723 #[serde(default = "default_true")]
12724 pub paired: bool,
12725 #[serde(default = "default_diff_formats_schema")]
12726 pub diff_formats: Vec<String>,
12727 #[serde(default)]
12728 pub diff_scope: Vec<String>,
12729}
12730
12731fn default_diff_formats_schema() -> Vec<String> {
12732 vec!["summary".to_string(), "aggregate".to_string()]
12733}
12734
12735impl Default for ScenarioOutputSchemaConfig {
12736 fn default() -> Self {
12737 Self {
12738 paired: true,
12739 diff_formats: default_diff_formats_schema(),
12740 diff_scope: Vec::new(),
12741 }
12742 }
12743}
12744
12745#[derive(Debug, Clone, Serialize, Deserialize)]
12747pub struct CausalModelSchemaConfig {
12748 #[serde(default = "default_causal_preset")]
12750 pub preset: String,
12751 #[serde(default)]
12753 pub nodes: Vec<serde_json::Value>,
12754 #[serde(default)]
12756 pub edges: Vec<serde_json::Value>,
12757}
12758
12759fn default_causal_preset() -> String {
12760 "default".to_string()
12761}
12762
12763impl Default for CausalModelSchemaConfig {
12764 fn default() -> Self {
12765 Self {
12766 preset: "default".to_string(),
12767 nodes: Vec::new(),
12768 edges: Vec::new(),
12769 }
12770 }
12771}
12772
12773#[derive(Debug, Clone, Serialize, Deserialize, Default)]
12775pub struct ScenarioDefaultsConfig {
12776 #[serde(default)]
12777 pub constraints: ScenarioConstraintsSchemaConfig,
12778 #[serde(default)]
12779 pub output: ScenarioOutputSchemaConfig,
12780}
12781
12782#[derive(Debug, Clone, Default, Serialize, Deserialize)]
12815pub struct ComplianceRegulationsConfig {
12816 #[serde(default)]
12818 pub enabled: bool,
12819 #[serde(default)]
12822 pub jurisdictions: Vec<String>,
12823 #[serde(default)]
12826 pub reference_date: Option<String>,
12827 #[serde(default)]
12829 pub standards_selection: StandardsSelectionConfig,
12830 #[serde(default)]
12832 pub audit_procedures: AuditProcedureGenConfig,
12833 #[serde(default)]
12835 pub findings: ComplianceFindingGenConfig,
12836 #[serde(default)]
12838 pub filings: ComplianceFilingGenConfig,
12839 #[serde(default)]
12841 pub graph: ComplianceGraphConfig,
12842 #[serde(default)]
12844 pub output: ComplianceOutputConfig,
12845}
12846
12847#[derive(Debug, Clone, Default, Serialize, Deserialize)]
12849pub struct StandardsSelectionConfig {
12850 #[serde(default)]
12853 pub categories: Vec<String>,
12854 #[serde(default)]
12857 pub include: Vec<String>,
12858 #[serde(default)]
12860 pub exclude: Vec<String>,
12861 #[serde(default)]
12863 pub include_superseded: bool,
12864}
12865
12866#[derive(Debug, Clone, Serialize, Deserialize)]
12868pub struct AuditProcedureGenConfig {
12869 #[serde(default)]
12871 pub enabled: bool,
12872 #[serde(default = "default_procedures_per_standard")]
12874 pub procedures_per_standard: usize,
12875 #[serde(default = "default_sampling_method")]
12877 pub sampling_method: String,
12878 #[serde(default = "default_confidence_level")]
12880 pub confidence_level: f64,
12881 #[serde(default = "default_tolerable_misstatement")]
12883 pub tolerable_misstatement: f64,
12884}
12885
12886fn default_procedures_per_standard() -> usize {
12887 3
12888}
12889
12890fn default_sampling_method() -> String {
12891 "statistical".to_string()
12892}
12893
12894fn default_confidence_level() -> f64 {
12895 0.95
12896}
12897
12898fn default_tolerable_misstatement() -> f64 {
12899 0.05
12900}
12901
12902impl Default for AuditProcedureGenConfig {
12903 fn default() -> Self {
12904 Self {
12905 enabled: false,
12906 procedures_per_standard: default_procedures_per_standard(),
12907 sampling_method: default_sampling_method(),
12908 confidence_level: default_confidence_level(),
12909 tolerable_misstatement: default_tolerable_misstatement(),
12910 }
12911 }
12912}
12913
12914#[derive(Debug, Clone, Serialize, Deserialize)]
12916pub struct ComplianceFindingGenConfig {
12917 #[serde(default)]
12919 pub enabled: bool,
12920 #[serde(default = "default_finding_rate")]
12922 pub finding_rate: f64,
12923 #[serde(default = "default_cr_material_weakness_rate")]
12925 pub material_weakness_rate: f64,
12926 #[serde(default = "default_cr_significant_deficiency_rate")]
12928 pub significant_deficiency_rate: f64,
12929 #[serde(default = "default_true")]
12931 pub generate_remediation: bool,
12932}
12933
12934fn default_finding_rate() -> f64 {
12935 0.05
12936}
12937
12938fn default_cr_material_weakness_rate() -> f64 {
12939 0.02
12940}
12941
12942fn default_cr_significant_deficiency_rate() -> f64 {
12943 0.08
12944}
12945
12946impl Default for ComplianceFindingGenConfig {
12947 fn default() -> Self {
12948 Self {
12949 enabled: false,
12950 finding_rate: default_finding_rate(),
12951 material_weakness_rate: default_cr_material_weakness_rate(),
12952 significant_deficiency_rate: default_cr_significant_deficiency_rate(),
12953 generate_remediation: true,
12954 }
12955 }
12956}
12957
12958#[derive(Debug, Clone, Serialize, Deserialize)]
12960pub struct ComplianceFilingGenConfig {
12961 #[serde(default)]
12963 pub enabled: bool,
12964 #[serde(default)]
12967 pub filing_types: Vec<String>,
12968 #[serde(default = "default_true")]
12970 pub generate_status_progression: bool,
12971}
12972
12973impl Default for ComplianceFilingGenConfig {
12974 fn default() -> Self {
12975 Self {
12976 enabled: false,
12977 filing_types: Vec::new(),
12978 generate_status_progression: true,
12979 }
12980 }
12981}
12982
12983#[derive(Debug, Clone, Serialize, Deserialize)]
12985pub struct ComplianceGraphConfig {
12986 #[serde(default)]
12988 pub enabled: bool,
12989 #[serde(default = "default_true")]
12991 pub include_compliance_nodes: bool,
12992 #[serde(default = "default_true")]
12994 pub include_compliance_edges: bool,
12995 #[serde(default = "default_true")]
12997 pub include_cross_references: bool,
12998 #[serde(default)]
13000 pub include_supersession_edges: bool,
13001 #[serde(default = "default_true")]
13003 pub include_account_links: bool,
13004 #[serde(default = "default_true")]
13006 pub include_control_links: bool,
13007 #[serde(default = "default_true")]
13009 pub include_company_links: bool,
13010}
13011
13012impl Default for ComplianceGraphConfig {
13013 fn default() -> Self {
13014 Self {
13015 enabled: false,
13016 include_compliance_nodes: true,
13017 include_compliance_edges: true,
13018 include_cross_references: true,
13019 include_supersession_edges: false,
13020 include_account_links: true,
13021 include_control_links: true,
13022 include_company_links: true,
13023 }
13024 }
13025}
13026
13027#[derive(Debug, Clone, Serialize, Deserialize)]
13029pub struct ComplianceOutputConfig {
13030 #[serde(default = "default_true")]
13032 pub export_registry: bool,
13033 #[serde(default = "default_true")]
13035 pub export_jurisdictions: bool,
13036 #[serde(default = "default_true")]
13038 pub export_cross_references: bool,
13039 #[serde(default)]
13041 pub export_version_history: bool,
13042}
13043
13044impl Default for ComplianceOutputConfig {
13045 fn default() -> Self {
13046 Self {
13047 export_registry: true,
13048 export_jurisdictions: true,
13049 export_cross_references: true,
13050 export_version_history: false,
13051 }
13052 }
13053}
13054
13055#[cfg(test)]
13056#[allow(clippy::unwrap_used)]
13057mod tests {
13058 use super::*;
13059 use crate::presets::demo_preset;
13060
13061 #[test]
13066 fn test_config_yaml_roundtrip() {
13067 let config = demo_preset();
13068 let yaml = serde_yaml::to_string(&config).expect("Failed to serialize to YAML");
13069 let deserialized: GeneratorConfig =
13070 serde_yaml::from_str(&yaml).expect("Failed to deserialize from YAML");
13071
13072 assert_eq!(
13073 config.global.period_months,
13074 deserialized.global.period_months
13075 );
13076 assert_eq!(config.global.industry, deserialized.global.industry);
13077 assert_eq!(config.companies.len(), deserialized.companies.len());
13078 assert_eq!(config.companies[0].code, deserialized.companies[0].code);
13079 }
13080
13081 #[test]
13082 fn test_config_json_roundtrip() {
13083 let mut config = demo_preset();
13085 config.master_data.employees.approval_limits.executive = 1e12;
13087
13088 let json = serde_json::to_string(&config).expect("Failed to serialize to JSON");
13089 let deserialized: GeneratorConfig =
13090 serde_json::from_str(&json).expect("Failed to deserialize from JSON");
13091
13092 assert_eq!(
13093 config.global.period_months,
13094 deserialized.global.period_months
13095 );
13096 assert_eq!(config.global.industry, deserialized.global.industry);
13097 assert_eq!(config.companies.len(), deserialized.companies.len());
13098 }
13099
13100 #[test]
13101 fn test_transaction_volume_serialization() {
13102 let volumes = vec![
13104 (TransactionVolume::TenK, "ten_k"),
13105 (TransactionVolume::HundredK, "hundred_k"),
13106 (TransactionVolume::OneM, "one_m"),
13107 (TransactionVolume::TenM, "ten_m"),
13108 (TransactionVolume::HundredM, "hundred_m"),
13109 ];
13110
13111 for (volume, expected_key) in volumes {
13112 let json = serde_json::to_string(&volume).expect("Failed to serialize");
13113 assert!(
13114 json.contains(expected_key),
13115 "Expected {} in JSON: {}",
13116 expected_key,
13117 json
13118 );
13119 }
13120 }
13121
13122 #[test]
13123 fn test_transaction_volume_custom_serialization() {
13124 let volume = TransactionVolume::Custom(12345);
13125 let json = serde_json::to_string(&volume).expect("Failed to serialize");
13126 let deserialized: TransactionVolume =
13127 serde_json::from_str(&json).expect("Failed to deserialize");
13128 assert_eq!(deserialized.count(), 12345);
13129 }
13130
13131 #[test]
13132 fn test_output_mode_serialization() {
13133 let modes = vec![
13134 OutputMode::Streaming,
13135 OutputMode::FlatFile,
13136 OutputMode::Both,
13137 ];
13138
13139 for mode in modes {
13140 let json = serde_json::to_string(&mode).expect("Failed to serialize");
13141 let deserialized: OutputMode =
13142 serde_json::from_str(&json).expect("Failed to deserialize");
13143 assert!(format!("{:?}", mode) == format!("{:?}", deserialized));
13144 }
13145 }
13146
13147 #[test]
13148 fn test_file_format_serialization() {
13149 let formats = vec![
13150 FileFormat::Csv,
13151 FileFormat::Parquet,
13152 FileFormat::Json,
13153 FileFormat::JsonLines,
13154 ];
13155
13156 for format in formats {
13157 let json = serde_json::to_string(&format).expect("Failed to serialize");
13158 let deserialized: FileFormat =
13159 serde_json::from_str(&json).expect("Failed to deserialize");
13160 assert!(format!("{:?}", format) == format!("{:?}", deserialized));
13161 }
13162 }
13163
13164 #[test]
13165 fn test_compression_algorithm_serialization() {
13166 let algos = vec![
13167 CompressionAlgorithm::Gzip,
13168 CompressionAlgorithm::Zstd,
13169 CompressionAlgorithm::Lz4,
13170 CompressionAlgorithm::Snappy,
13171 ];
13172
13173 for algo in algos {
13174 let json = serde_json::to_string(&algo).expect("Failed to serialize");
13175 let deserialized: CompressionAlgorithm =
13176 serde_json::from_str(&json).expect("Failed to deserialize");
13177 assert!(format!("{:?}", algo) == format!("{:?}", deserialized));
13178 }
13179 }
13180
13181 #[test]
13182 fn test_transfer_pricing_method_serialization() {
13183 let methods = vec![
13184 TransferPricingMethod::CostPlus,
13185 TransferPricingMethod::ComparableUncontrolled,
13186 TransferPricingMethod::ResalePrice,
13187 TransferPricingMethod::TransactionalNetMargin,
13188 TransferPricingMethod::ProfitSplit,
13189 ];
13190
13191 for method in methods {
13192 let json = serde_json::to_string(&method).expect("Failed to serialize");
13193 let deserialized: TransferPricingMethod =
13194 serde_json::from_str(&json).expect("Failed to deserialize");
13195 assert!(format!("{:?}", method) == format!("{:?}", deserialized));
13196 }
13197 }
13198
13199 #[test]
13200 fn test_benford_exemption_serialization() {
13201 let exemptions = vec![
13202 BenfordExemption::Recurring,
13203 BenfordExemption::Payroll,
13204 BenfordExemption::FixedFees,
13205 BenfordExemption::RoundAmounts,
13206 ];
13207
13208 for exemption in exemptions {
13209 let json = serde_json::to_string(&exemption).expect("Failed to serialize");
13210 let deserialized: BenfordExemption =
13211 serde_json::from_str(&json).expect("Failed to deserialize");
13212 assert!(format!("{:?}", exemption) == format!("{:?}", deserialized));
13213 }
13214 }
13215
13216 #[test]
13221 fn test_global_config_defaults() {
13222 let yaml = r#"
13223 industry: manufacturing
13224 start_date: "2024-01-01"
13225 period_months: 6
13226 "#;
13227 let config: GlobalConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13228 assert_eq!(config.group_currency, "USD");
13229 assert!(config.parallel);
13230 assert_eq!(config.worker_threads, 0);
13231 assert_eq!(config.memory_limit_mb, 0);
13232 }
13233
13234 #[test]
13235 fn test_fraud_config_defaults() {
13236 let config = FraudConfig::default();
13237 assert!(!config.enabled);
13238 assert_eq!(config.fraud_rate, 0.005);
13239 assert!(!config.clustering_enabled);
13240 }
13241
13242 #[test]
13243 fn test_internal_controls_config_defaults() {
13244 let config = InternalControlsConfig::default();
13245 assert!(!config.enabled);
13246 assert_eq!(config.exception_rate, 0.02);
13247 assert_eq!(config.sod_violation_rate, 0.01);
13248 assert!(config.export_control_master_data);
13249 assert_eq!(config.sox_materiality_threshold, 10000.0);
13250 assert!(config.coso_enabled);
13252 assert!(!config.include_entity_level_controls);
13253 assert_eq!(config.target_maturity_level, "mixed");
13254 }
13255
13256 #[test]
13257 fn test_output_config_defaults() {
13258 let config = OutputConfig::default();
13259 assert!(matches!(config.mode, OutputMode::FlatFile));
13260 assert_eq!(config.formats, vec![FileFormat::Parquet]);
13261 assert!(config.compression.enabled);
13262 assert!(matches!(
13263 config.compression.algorithm,
13264 CompressionAlgorithm::Zstd
13265 ));
13266 assert!(config.include_acdoca);
13267 assert!(!config.include_bseg);
13268 assert!(config.partition_by_period);
13269 assert!(!config.partition_by_company);
13270 }
13271
13272 #[test]
13273 fn test_approval_config_defaults() {
13274 let config = ApprovalConfig::default();
13275 assert!(!config.enabled);
13276 assert_eq!(config.auto_approve_threshold, 1000.0);
13277 assert_eq!(config.rejection_rate, 0.02);
13278 assert_eq!(config.revision_rate, 0.05);
13279 assert_eq!(config.average_approval_delay_hours, 4.0);
13280 assert_eq!(config.thresholds.len(), 4);
13281 }
13282
13283 #[test]
13284 fn test_p2p_flow_config_defaults() {
13285 let config = P2PFlowConfig::default();
13286 assert!(config.enabled);
13287 assert_eq!(config.three_way_match_rate, 0.95);
13288 assert_eq!(config.partial_delivery_rate, 0.15);
13289 assert_eq!(config.average_po_to_gr_days, 14);
13290 }
13291
13292 #[test]
13293 fn test_o2c_flow_config_defaults() {
13294 let config = O2CFlowConfig::default();
13295 assert!(config.enabled);
13296 assert_eq!(config.credit_check_failure_rate, 0.02);
13297 assert_eq!(config.return_rate, 0.03);
13298 assert_eq!(config.bad_debt_rate, 0.01);
13299 }
13300
13301 #[test]
13302 fn test_balance_config_defaults() {
13303 let config = BalanceConfig::default();
13304 assert!(!config.generate_opening_balances);
13305 assert!(config.generate_trial_balances);
13306 assert_eq!(config.target_gross_margin, 0.35);
13307 assert!(config.validate_balance_equation);
13308 assert!(config.reconcile_subledgers);
13309 }
13310
13311 #[test]
13316 fn test_partial_config_with_defaults() {
13317 let yaml = r#"
13319 global:
13320 industry: manufacturing
13321 start_date: "2024-01-01"
13322 period_months: 3
13323 companies:
13324 - code: "TEST"
13325 name: "Test Company"
13326 currency: "USD"
13327 country: "US"
13328 annual_transaction_volume: ten_k
13329 chart_of_accounts:
13330 complexity: small
13331 output:
13332 output_directory: "./output"
13333 "#;
13334
13335 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13336 assert_eq!(config.global.period_months, 3);
13337 assert_eq!(config.companies.len(), 1);
13338 assert!(!config.fraud.enabled); assert!(!config.internal_controls.enabled); }
13341
13342 #[test]
13343 fn test_config_with_fraud_enabled() {
13344 let yaml = r#"
13345 global:
13346 industry: retail
13347 start_date: "2024-01-01"
13348 period_months: 12
13349 companies:
13350 - code: "RETAIL"
13351 name: "Retail Co"
13352 currency: "USD"
13353 country: "US"
13354 annual_transaction_volume: hundred_k
13355 chart_of_accounts:
13356 complexity: medium
13357 output:
13358 output_directory: "./output"
13359 fraud:
13360 enabled: true
13361 fraud_rate: 0.05
13362 clustering_enabled: true
13363 "#;
13364
13365 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13366 assert!(config.fraud.enabled);
13367 assert_eq!(config.fraud.fraud_rate, 0.05);
13368 assert!(config.fraud.clustering_enabled);
13369 }
13370
13371 #[test]
13372 fn test_config_with_multiple_companies() {
13373 let yaml = r#"
13374 global:
13375 industry: manufacturing
13376 start_date: "2024-01-01"
13377 period_months: 6
13378 companies:
13379 - code: "HQ"
13380 name: "Headquarters"
13381 currency: "USD"
13382 country: "US"
13383 annual_transaction_volume: hundred_k
13384 volume_weight: 1.0
13385 - code: "EU"
13386 name: "European Subsidiary"
13387 currency: "EUR"
13388 country: "DE"
13389 annual_transaction_volume: hundred_k
13390 volume_weight: 0.5
13391 - code: "APAC"
13392 name: "Asia Pacific"
13393 currency: "JPY"
13394 country: "JP"
13395 annual_transaction_volume: ten_k
13396 volume_weight: 0.3
13397 chart_of_accounts:
13398 complexity: large
13399 output:
13400 output_directory: "./output"
13401 "#;
13402
13403 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13404 assert_eq!(config.companies.len(), 3);
13405 assert_eq!(config.companies[0].code, "HQ");
13406 assert_eq!(config.companies[1].currency, "EUR");
13407 assert_eq!(config.companies[2].volume_weight, 0.3);
13408 }
13409
13410 #[test]
13411 fn test_intercompany_config() {
13412 let yaml = r#"
13413 enabled: true
13414 ic_transaction_rate: 0.20
13415 transfer_pricing_method: cost_plus
13416 markup_percent: 0.08
13417 generate_matched_pairs: true
13418 generate_eliminations: true
13419 "#;
13420
13421 let config: IntercompanyConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13422 assert!(config.enabled);
13423 assert_eq!(config.ic_transaction_rate, 0.20);
13424 assert!(matches!(
13425 config.transfer_pricing_method,
13426 TransferPricingMethod::CostPlus
13427 ));
13428 assert_eq!(config.markup_percent, 0.08);
13429 assert!(config.generate_eliminations);
13430 }
13431
13432 #[test]
13437 fn test_company_config_defaults() {
13438 let yaml = r#"
13439 code: "TEST"
13440 name: "Test Company"
13441 currency: "USD"
13442 country: "US"
13443 annual_transaction_volume: ten_k
13444 "#;
13445
13446 let config: CompanyConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13447 assert_eq!(config.fiscal_year_variant, "K4"); assert_eq!(config.volume_weight, 1.0); }
13450
13451 #[test]
13456 fn test_coa_config_defaults() {
13457 let yaml = r#"
13458 complexity: medium
13459 "#;
13460
13461 let config: ChartOfAccountsConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13462 assert!(config.industry_specific); assert!(config.custom_accounts.is_none());
13464 assert_eq!(config.min_hierarchy_depth, 2); assert_eq!(config.max_hierarchy_depth, 5); }
13467
13468 #[test]
13473 fn test_accounting_standards_config_defaults() {
13474 let config = AccountingStandardsConfig::default();
13475 assert!(!config.enabled);
13476 assert!(config.framework.is_none());
13477 assert!(!config.revenue_recognition.enabled);
13478 assert!(!config.leases.enabled);
13479 assert!(!config.fair_value.enabled);
13480 assert!(!config.impairment.enabled);
13481 assert!(!config.generate_differences);
13482 }
13483
13484 #[test]
13485 fn test_accounting_standards_config_yaml() {
13486 let yaml = r#"
13487 enabled: true
13488 framework: ifrs
13489 revenue_recognition:
13490 enabled: true
13491 generate_contracts: true
13492 avg_obligations_per_contract: 2.5
13493 variable_consideration_rate: 0.20
13494 over_time_recognition_rate: 0.35
13495 contract_count: 150
13496 leases:
13497 enabled: true
13498 lease_count: 75
13499 finance_lease_percent: 0.25
13500 avg_lease_term_months: 48
13501 generate_differences: true
13502 "#;
13503
13504 let config: AccountingStandardsConfig =
13505 serde_yaml::from_str(yaml).expect("Failed to parse");
13506 assert!(config.enabled);
13507 assert!(matches!(
13508 config.framework,
13509 Some(AccountingFrameworkConfig::Ifrs)
13510 ));
13511 assert!(config.revenue_recognition.enabled);
13512 assert_eq!(config.revenue_recognition.contract_count, 150);
13513 assert_eq!(config.revenue_recognition.avg_obligations_per_contract, 2.5);
13514 assert!(config.leases.enabled);
13515 assert_eq!(config.leases.lease_count, 75);
13516 assert_eq!(config.leases.finance_lease_percent, 0.25);
13517 assert!(config.generate_differences);
13518 }
13519
13520 #[test]
13521 fn test_accounting_framework_serialization() {
13522 let frameworks = [
13523 AccountingFrameworkConfig::UsGaap,
13524 AccountingFrameworkConfig::Ifrs,
13525 AccountingFrameworkConfig::DualReporting,
13526 AccountingFrameworkConfig::FrenchGaap,
13527 AccountingFrameworkConfig::GermanGaap,
13528 ];
13529
13530 for framework in frameworks {
13531 let json = serde_json::to_string(&framework).expect("Failed to serialize");
13532 let deserialized: AccountingFrameworkConfig =
13533 serde_json::from_str(&json).expect("Failed to deserialize");
13534 assert!(format!("{:?}", framework) == format!("{:?}", deserialized));
13535 }
13536 }
13537
13538 #[test]
13539 fn test_revenue_recognition_config_defaults() {
13540 let config = RevenueRecognitionConfig::default();
13541 assert!(!config.enabled);
13542 assert!(config.generate_contracts);
13543 assert_eq!(config.avg_obligations_per_contract, 2.0);
13544 assert_eq!(config.variable_consideration_rate, 0.15);
13545 assert_eq!(config.over_time_recognition_rate, 0.30);
13546 assert_eq!(config.contract_count, 100);
13547 }
13548
13549 #[test]
13550 fn test_lease_accounting_config_defaults() {
13551 let config = LeaseAccountingConfig::default();
13552 assert!(!config.enabled);
13553 assert_eq!(config.lease_count, 50);
13554 assert_eq!(config.finance_lease_percent, 0.30);
13555 assert_eq!(config.avg_lease_term_months, 60);
13556 assert!(config.generate_amortization);
13557 assert_eq!(config.real_estate_percent, 0.40);
13558 }
13559
13560 #[test]
13561 fn test_fair_value_config_defaults() {
13562 let config = FairValueConfig::default();
13563 assert!(!config.enabled);
13564 assert_eq!(config.measurement_count, 25);
13565 assert_eq!(config.level1_percent, 0.40);
13566 assert_eq!(config.level2_percent, 0.35);
13567 assert_eq!(config.level3_percent, 0.25);
13568 assert!(!config.include_sensitivity_analysis);
13569 }
13570
13571 #[test]
13572 fn test_impairment_config_defaults() {
13573 let config = ImpairmentConfig::default();
13574 assert!(!config.enabled);
13575 assert_eq!(config.test_count, 15);
13576 assert_eq!(config.impairment_rate, 0.10);
13577 assert!(config.generate_projections);
13578 assert!(!config.include_goodwill);
13579 }
13580
13581 #[test]
13586 fn test_audit_standards_config_defaults() {
13587 let config = AuditStandardsConfig::default();
13588 assert!(!config.enabled);
13589 assert!(!config.isa_compliance.enabled);
13590 assert!(!config.analytical_procedures.enabled);
13591 assert!(!config.confirmations.enabled);
13592 assert!(!config.opinion.enabled);
13593 assert!(!config.generate_audit_trail);
13594 assert!(!config.sox.enabled);
13595 assert!(!config.pcaob.enabled);
13596 }
13597
13598 #[test]
13599 fn test_audit_standards_config_yaml() {
13600 let yaml = r#"
13601 enabled: true
13602 isa_compliance:
13603 enabled: true
13604 compliance_level: comprehensive
13605 generate_isa_mappings: true
13606 include_pcaob: true
13607 framework: dual
13608 analytical_procedures:
13609 enabled: true
13610 procedures_per_account: 5
13611 variance_probability: 0.25
13612 confirmations:
13613 enabled: true
13614 confirmation_count: 75
13615 positive_response_rate: 0.90
13616 exception_rate: 0.08
13617 opinion:
13618 enabled: true
13619 generate_kam: true
13620 average_kam_count: 4
13621 sox:
13622 enabled: true
13623 generate_302_certifications: true
13624 generate_404_assessments: true
13625 material_weakness_rate: 0.03
13626 pcaob:
13627 enabled: true
13628 is_pcaob_audit: true
13629 include_icfr_opinion: true
13630 generate_audit_trail: true
13631 "#;
13632
13633 let config: AuditStandardsConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13634 assert!(config.enabled);
13635 assert!(config.isa_compliance.enabled);
13636 assert_eq!(config.isa_compliance.compliance_level, "comprehensive");
13637 assert!(config.isa_compliance.include_pcaob);
13638 assert_eq!(config.isa_compliance.framework, "dual");
13639 assert!(config.analytical_procedures.enabled);
13640 assert_eq!(config.analytical_procedures.procedures_per_account, 5);
13641 assert!(config.confirmations.enabled);
13642 assert_eq!(config.confirmations.confirmation_count, 75);
13643 assert!(config.opinion.enabled);
13644 assert_eq!(config.opinion.average_kam_count, 4);
13645 assert!(config.sox.enabled);
13646 assert!(config.sox.generate_302_certifications);
13647 assert_eq!(config.sox.material_weakness_rate, 0.03);
13648 assert!(config.pcaob.enabled);
13649 assert!(config.pcaob.is_pcaob_audit);
13650 assert!(config.pcaob.include_icfr_opinion);
13651 assert!(config.generate_audit_trail);
13652 }
13653
13654 #[test]
13655 fn test_isa_compliance_config_defaults() {
13656 let config = IsaComplianceConfig::default();
13657 assert!(!config.enabled);
13658 assert_eq!(config.compliance_level, "standard");
13659 assert!(config.generate_isa_mappings);
13660 assert!(config.generate_coverage_summary);
13661 assert!(!config.include_pcaob);
13662 assert_eq!(config.framework, "isa");
13663 }
13664
13665 #[test]
13666 fn test_sox_compliance_config_defaults() {
13667 let config = SoxComplianceConfig::default();
13668 assert!(!config.enabled);
13669 assert!(config.generate_302_certifications);
13670 assert!(config.generate_404_assessments);
13671 assert_eq!(config.materiality_threshold, 10000.0);
13672 assert_eq!(config.material_weakness_rate, 0.02);
13673 assert_eq!(config.significant_deficiency_rate, 0.08);
13674 }
13675
13676 #[test]
13677 fn test_pcaob_config_defaults() {
13678 let config = PcaobConfig::default();
13679 assert!(!config.enabled);
13680 assert!(!config.is_pcaob_audit);
13681 assert!(config.generate_cam);
13682 assert!(!config.include_icfr_opinion);
13683 assert!(!config.generate_standard_mappings);
13684 }
13685
13686 #[test]
13687 fn test_config_with_standards_enabled() {
13688 let yaml = r#"
13689 global:
13690 industry: financial_services
13691 start_date: "2024-01-01"
13692 period_months: 12
13693 companies:
13694 - code: "BANK"
13695 name: "Test Bank"
13696 currency: "USD"
13697 country: "US"
13698 annual_transaction_volume: hundred_k
13699 chart_of_accounts:
13700 complexity: large
13701 output:
13702 output_directory: "./output"
13703 accounting_standards:
13704 enabled: true
13705 framework: us_gaap
13706 revenue_recognition:
13707 enabled: true
13708 leases:
13709 enabled: true
13710 audit_standards:
13711 enabled: true
13712 isa_compliance:
13713 enabled: true
13714 sox:
13715 enabled: true
13716 "#;
13717
13718 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13719 assert!(config.accounting_standards.enabled);
13720 assert!(matches!(
13721 config.accounting_standards.framework,
13722 Some(AccountingFrameworkConfig::UsGaap)
13723 ));
13724 assert!(config.accounting_standards.revenue_recognition.enabled);
13725 assert!(config.accounting_standards.leases.enabled);
13726 assert!(config.audit_standards.enabled);
13727 assert!(config.audit_standards.isa_compliance.enabled);
13728 assert!(config.audit_standards.sox.enabled);
13729 }
13730
13731 #[test]
13736 fn test_industry_specific_config_defaults() {
13737 let config = IndustrySpecificConfig::default();
13738 assert!(!config.enabled);
13739 assert!(!config.manufacturing.enabled);
13740 assert!(!config.retail.enabled);
13741 assert!(!config.healthcare.enabled);
13742 assert!(!config.technology.enabled);
13743 assert!(!config.financial_services.enabled);
13744 assert!(!config.professional_services.enabled);
13745 }
13746
13747 #[test]
13748 fn test_manufacturing_config_defaults() {
13749 let config = ManufacturingConfig::default();
13750 assert!(!config.enabled);
13751 assert_eq!(config.bom_depth, 4);
13752 assert!(!config.just_in_time);
13753 assert_eq!(config.supplier_tiers, 2);
13754 assert_eq!(config.target_yield_rate, 0.97);
13755 assert_eq!(config.scrap_alert_threshold, 0.03);
13756 }
13757
13758 #[test]
13759 fn test_retail_config_defaults() {
13760 let config = RetailConfig::default();
13761 assert!(!config.enabled);
13762 assert_eq!(config.avg_daily_transactions, 500);
13763 assert!(config.loss_prevention);
13764 assert_eq!(config.shrinkage_rate, 0.015);
13765 }
13766
13767 #[test]
13768 fn test_healthcare_config_defaults() {
13769 let config = HealthcareConfig::default();
13770 assert!(!config.enabled);
13771 assert_eq!(config.facility_type, "hospital");
13772 assert_eq!(config.avg_daily_encounters, 150);
13773 assert!(config.compliance.hipaa);
13774 assert!(config.compliance.stark_law);
13775 assert!(config.coding_systems.icd10);
13776 assert!(config.coding_systems.cpt);
13777 }
13778
13779 #[test]
13780 fn test_technology_config_defaults() {
13781 let config = TechnologyConfig::default();
13782 assert!(!config.enabled);
13783 assert_eq!(config.revenue_model, "saas");
13784 assert_eq!(config.subscription_revenue_pct, 0.60);
13785 assert!(config.rd_capitalization.enabled);
13786 }
13787
13788 #[test]
13789 fn test_config_with_industry_specific() {
13790 let yaml = r#"
13791 global:
13792 industry: healthcare
13793 start_date: "2024-01-01"
13794 period_months: 12
13795 companies:
13796 - code: "HOSP"
13797 name: "Test Hospital"
13798 currency: "USD"
13799 country: "US"
13800 annual_transaction_volume: hundred_k
13801 chart_of_accounts:
13802 complexity: medium
13803 output:
13804 output_directory: "./output"
13805 industry_specific:
13806 enabled: true
13807 healthcare:
13808 enabled: true
13809 facility_type: hospital
13810 payer_mix:
13811 medicare: 0.45
13812 medicaid: 0.15
13813 commercial: 0.35
13814 self_pay: 0.05
13815 coding_systems:
13816 icd10: true
13817 cpt: true
13818 drg: true
13819 compliance:
13820 hipaa: true
13821 stark_law: true
13822 anomaly_rates:
13823 upcoding: 0.03
13824 unbundling: 0.02
13825 "#;
13826
13827 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13828 assert!(config.industry_specific.enabled);
13829 assert!(config.industry_specific.healthcare.enabled);
13830 assert_eq!(
13831 config.industry_specific.healthcare.facility_type,
13832 "hospital"
13833 );
13834 assert_eq!(config.industry_specific.healthcare.payer_mix.medicare, 0.45);
13835 assert_eq!(config.industry_specific.healthcare.payer_mix.self_pay, 0.05);
13836 assert!(config.industry_specific.healthcare.coding_systems.icd10);
13837 assert!(config.industry_specific.healthcare.compliance.hipaa);
13838 assert_eq!(
13839 config.industry_specific.healthcare.anomaly_rates.upcoding,
13840 0.03
13841 );
13842 }
13843
13844 #[test]
13845 fn test_config_with_manufacturing_specific() {
13846 let yaml = r#"
13847 global:
13848 industry: manufacturing
13849 start_date: "2024-01-01"
13850 period_months: 12
13851 companies:
13852 - code: "MFG"
13853 name: "Test Manufacturing"
13854 currency: "USD"
13855 country: "US"
13856 annual_transaction_volume: hundred_k
13857 chart_of_accounts:
13858 complexity: medium
13859 output:
13860 output_directory: "./output"
13861 industry_specific:
13862 enabled: true
13863 manufacturing:
13864 enabled: true
13865 bom_depth: 5
13866 just_in_time: true
13867 supplier_tiers: 3
13868 target_yield_rate: 0.98
13869 anomaly_rates:
13870 yield_manipulation: 0.02
13871 phantom_production: 0.01
13872 "#;
13873
13874 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13875 assert!(config.industry_specific.enabled);
13876 assert!(config.industry_specific.manufacturing.enabled);
13877 assert_eq!(config.industry_specific.manufacturing.bom_depth, 5);
13878 assert!(config.industry_specific.manufacturing.just_in_time);
13879 assert_eq!(config.industry_specific.manufacturing.supplier_tiers, 3);
13880 assert_eq!(
13881 config.industry_specific.manufacturing.target_yield_rate,
13882 0.98
13883 );
13884 assert_eq!(
13885 config
13886 .industry_specific
13887 .manufacturing
13888 .anomaly_rates
13889 .yield_manipulation,
13890 0.02
13891 );
13892 }
13893
13894 #[test]
13899 fn test_tax_config_defaults() {
13900 let tax = TaxConfig::default();
13901 assert!(!tax.enabled);
13902 assert!(tax.jurisdictions.countries.is_empty());
13903 assert!(!tax.jurisdictions.include_subnational);
13904 assert!(!tax.vat_gst.enabled);
13905 assert!(tax.vat_gst.standard_rates.is_empty());
13906 assert!(tax.vat_gst.reduced_rates.is_empty());
13907 assert!(tax.vat_gst.exempt_categories.is_empty());
13908 assert!(tax.vat_gst.reverse_charge);
13909 assert!(!tax.sales_tax.enabled);
13910 assert!(tax.sales_tax.nexus_states.is_empty());
13911 assert!(!tax.withholding.enabled);
13912 assert!(tax.withholding.treaty_network);
13913 assert_eq!(tax.withholding.default_rate, 0.30);
13914 assert_eq!(tax.withholding.treaty_reduced_rate, 0.15);
13915 assert!(tax.provisions.enabled);
13916 assert_eq!(tax.provisions.statutory_rate, 0.21);
13917 assert!(tax.provisions.uncertain_positions);
13918 assert!(!tax.payroll_tax.enabled);
13919 assert_eq!(tax.anomaly_rate, 0.03);
13920 }
13921
13922 #[test]
13923 fn test_tax_config_from_yaml() {
13924 let yaml = r#"
13925 global:
13926 seed: 42
13927 start_date: "2024-01-01"
13928 period_months: 12
13929 industry: retail
13930 companies:
13931 - code: C001
13932 name: Test Corp
13933 currency: USD
13934 country: US
13935 annual_transaction_volume: ten_k
13936 chart_of_accounts:
13937 complexity: small
13938 output:
13939 output_directory: ./output
13940 tax:
13941 enabled: true
13942 anomaly_rate: 0.05
13943 jurisdictions:
13944 countries: ["US", "DE", "GB"]
13945 include_subnational: true
13946 vat_gst:
13947 enabled: true
13948 standard_rates:
13949 DE: 0.19
13950 GB: 0.20
13951 reduced_rates:
13952 DE: 0.07
13953 GB: 0.05
13954 exempt_categories:
13955 - financial_services
13956 - healthcare
13957 reverse_charge: false
13958 sales_tax:
13959 enabled: true
13960 nexus_states: ["CA", "NY", "TX"]
13961 withholding:
13962 enabled: true
13963 treaty_network: false
13964 default_rate: 0.25
13965 treaty_reduced_rate: 0.10
13966 provisions:
13967 enabled: false
13968 statutory_rate: 0.28
13969 uncertain_positions: false
13970 payroll_tax:
13971 enabled: true
13972 "#;
13973
13974 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13975 assert!(config.tax.enabled);
13976 assert_eq!(config.tax.anomaly_rate, 0.05);
13977
13978 assert_eq!(config.tax.jurisdictions.countries.len(), 3);
13980 assert!(config
13981 .tax
13982 .jurisdictions
13983 .countries
13984 .contains(&"DE".to_string()));
13985 assert!(config.tax.jurisdictions.include_subnational);
13986
13987 assert!(config.tax.vat_gst.enabled);
13989 assert_eq!(config.tax.vat_gst.standard_rates.get("DE"), Some(&0.19));
13990 assert_eq!(config.tax.vat_gst.standard_rates.get("GB"), Some(&0.20));
13991 assert_eq!(config.tax.vat_gst.reduced_rates.get("DE"), Some(&0.07));
13992 assert_eq!(config.tax.vat_gst.exempt_categories.len(), 2);
13993 assert!(!config.tax.vat_gst.reverse_charge);
13994
13995 assert!(config.tax.sales_tax.enabled);
13997 assert_eq!(config.tax.sales_tax.nexus_states.len(), 3);
13998 assert!(config
13999 .tax
14000 .sales_tax
14001 .nexus_states
14002 .contains(&"CA".to_string()));
14003
14004 assert!(config.tax.withholding.enabled);
14006 assert!(!config.tax.withholding.treaty_network);
14007 assert_eq!(config.tax.withholding.default_rate, 0.25);
14008 assert_eq!(config.tax.withholding.treaty_reduced_rate, 0.10);
14009
14010 assert!(!config.tax.provisions.enabled);
14012 assert_eq!(config.tax.provisions.statutory_rate, 0.28);
14013 assert!(!config.tax.provisions.uncertain_positions);
14014
14015 assert!(config.tax.payroll_tax.enabled);
14017 }
14018
14019 #[test]
14020 fn test_generator_config_with_tax_default() {
14021 let yaml = r#"
14022 global:
14023 seed: 42
14024 start_date: "2024-01-01"
14025 period_months: 12
14026 industry: retail
14027 companies:
14028 - code: C001
14029 name: Test Corp
14030 currency: USD
14031 country: US
14032 annual_transaction_volume: ten_k
14033 chart_of_accounts:
14034 complexity: small
14035 output:
14036 output_directory: ./output
14037 "#;
14038
14039 let config: GeneratorConfig =
14040 serde_yaml::from_str(yaml).expect("Failed to parse config without tax section");
14041 assert!(!config.tax.enabled);
14043 assert!(config.tax.jurisdictions.countries.is_empty());
14044 assert_eq!(config.tax.anomaly_rate, 0.03);
14045 assert!(config.tax.provisions.enabled); assert_eq!(config.tax.provisions.statutory_rate, 0.21);
14047 }
14048
14049 #[test]
14054 fn test_session_config_default_disabled() {
14055 let yaml = "{}";
14056 let config: SessionSchemaConfig =
14057 serde_yaml::from_str(yaml).expect("Failed to parse empty session config");
14058 assert!(!config.enabled);
14059 assert!(config.checkpoint_path.is_none());
14060 assert!(config.per_period_output);
14061 assert!(config.consolidated_output);
14062 }
14063
14064 #[test]
14065 fn test_config_backward_compatible_without_session() {
14066 let yaml = r#"
14067 global:
14068 seed: 42
14069 start_date: "2024-01-01"
14070 period_months: 12
14071 industry: retail
14072 companies:
14073 - code: C001
14074 name: Test Corp
14075 currency: USD
14076 country: US
14077 annual_transaction_volume: ten_k
14078 chart_of_accounts:
14079 complexity: small
14080 output:
14081 output_directory: ./output
14082 "#;
14083
14084 let config: GeneratorConfig =
14085 serde_yaml::from_str(yaml).expect("Failed to parse config without session");
14086 assert!(!config.session.enabled);
14088 assert!(config.session.per_period_output);
14089 assert!(config.session.consolidated_output);
14090 assert!(config.global.fiscal_year_months.is_none());
14092 }
14093
14094 #[test]
14095 fn test_fiscal_year_months_parsed() {
14096 let yaml = r#"
14097 global:
14098 seed: 42
14099 start_date: "2024-01-01"
14100 period_months: 24
14101 industry: retail
14102 fiscal_year_months: 12
14103 companies:
14104 - code: C001
14105 name: Test Corp
14106 currency: USD
14107 country: US
14108 annual_transaction_volume: ten_k
14109 chart_of_accounts:
14110 complexity: small
14111 output:
14112 output_directory: ./output
14113 session:
14114 enabled: true
14115 checkpoint_path: /tmp/checkpoints
14116 per_period_output: true
14117 consolidated_output: false
14118 "#;
14119
14120 let config: GeneratorConfig =
14121 serde_yaml::from_str(yaml).expect("Failed to parse config with fiscal_year_months");
14122 assert_eq!(config.global.fiscal_year_months, Some(12));
14123 assert!(config.session.enabled);
14124 assert_eq!(
14125 config.session.checkpoint_path,
14126 Some("/tmp/checkpoints".to_string())
14127 );
14128 assert!(config.session.per_period_output);
14129 assert!(!config.session.consolidated_output);
14130 }
14131}