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
365fn default_graph_types() -> Vec<GraphTypeConfig> {
366 vec![GraphTypeConfig::default()]
367}
368
369fn default_graph_formats() -> Vec<GraphExportFormat> {
370 vec![GraphExportFormat::PytorchGeometric]
371}
372
373fn default_train_ratio() -> f64 {
374 0.7
375}
376
377fn default_val_ratio() -> f64 {
378 0.15
379}
380
381fn default_graph_subdir() -> String {
382 "graphs".to_string()
383}
384
385impl Default for GraphExportConfig {
386 fn default() -> Self {
387 Self {
388 enabled: false,
389 graph_types: default_graph_types(),
390 formats: default_graph_formats(),
391 train_ratio: 0.7,
392 validation_ratio: 0.15,
393 split_seed: None,
394 output_subdirectory: "graphs".to_string(),
395 hypergraph: HypergraphExportSettings::default(),
396 }
397 }
398}
399
400#[derive(Debug, Clone, Serialize, Deserialize)]
407pub struct HypergraphExportSettings {
408 #[serde(default)]
410 pub enabled: bool,
411
412 #[serde(default = "default_hypergraph_max_nodes")]
414 pub max_nodes: usize,
415
416 #[serde(default = "default_aggregation_strategy")]
418 pub aggregation_strategy: String,
419
420 #[serde(default)]
422 pub governance_layer: GovernanceLayerSettings,
423
424 #[serde(default)]
426 pub process_layer: ProcessLayerSettings,
427
428 #[serde(default)]
430 pub accounting_layer: AccountingLayerSettings,
431
432 #[serde(default)]
434 pub cross_layer: CrossLayerSettings,
435
436 #[serde(default = "default_hypergraph_subdir")]
438 pub output_subdirectory: String,
439
440 #[serde(default = "default_hypergraph_format")]
442 pub output_format: String,
443
444 #[serde(default)]
446 pub stream_target: Option<String>,
447
448 #[serde(default = "default_stream_batch_size")]
450 pub stream_batch_size: usize,
451}
452
453fn default_hypergraph_max_nodes() -> usize {
454 50_000
455}
456
457fn default_aggregation_strategy() -> String {
458 "pool_by_counterparty".to_string()
459}
460
461fn default_hypergraph_subdir() -> String {
462 "hypergraph".to_string()
463}
464
465fn default_hypergraph_format() -> String {
466 "native".to_string()
467}
468
469fn default_stream_batch_size() -> usize {
470 1000
471}
472
473impl Default for HypergraphExportSettings {
474 fn default() -> Self {
475 Self {
476 enabled: false,
477 max_nodes: 50_000,
478 aggregation_strategy: "pool_by_counterparty".to_string(),
479 governance_layer: GovernanceLayerSettings::default(),
480 process_layer: ProcessLayerSettings::default(),
481 accounting_layer: AccountingLayerSettings::default(),
482 cross_layer: CrossLayerSettings::default(),
483 output_subdirectory: "hypergraph".to_string(),
484 output_format: "native".to_string(),
485 stream_target: None,
486 stream_batch_size: 1000,
487 }
488 }
489}
490
491#[derive(Debug, Clone, Serialize, Deserialize)]
493pub struct GovernanceLayerSettings {
494 #[serde(default = "default_true")]
496 pub include_coso: bool,
497 #[serde(default = "default_true")]
499 pub include_controls: bool,
500 #[serde(default = "default_true")]
502 pub include_sox: bool,
503 #[serde(default = "default_true")]
505 pub include_vendors: bool,
506 #[serde(default = "default_true")]
508 pub include_customers: bool,
509 #[serde(default = "default_true")]
511 pub include_employees: bool,
512}
513
514impl Default for GovernanceLayerSettings {
515 fn default() -> Self {
516 Self {
517 include_coso: true,
518 include_controls: true,
519 include_sox: true,
520 include_vendors: true,
521 include_customers: true,
522 include_employees: true,
523 }
524 }
525}
526
527#[derive(Debug, Clone, Serialize, Deserialize)]
529pub struct ProcessLayerSettings {
530 #[serde(default = "default_true")]
532 pub include_p2p: bool,
533 #[serde(default = "default_true")]
535 pub include_o2c: bool,
536 #[serde(default = "default_true")]
538 pub include_s2c: bool,
539 #[serde(default = "default_true")]
541 pub include_h2r: bool,
542 #[serde(default = "default_true")]
544 pub include_mfg: bool,
545 #[serde(default = "default_true")]
547 pub include_bank: bool,
548 #[serde(default = "default_true")]
550 pub include_audit: bool,
551 #[serde(default = "default_true")]
553 pub include_r2r: bool,
554 #[serde(default = "default_true")]
556 pub events_as_hyperedges: bool,
557 #[serde(default = "default_docs_per_counterparty_threshold")]
559 pub docs_per_counterparty_threshold: usize,
560}
561
562fn default_docs_per_counterparty_threshold() -> usize {
563 20
564}
565
566impl Default for ProcessLayerSettings {
567 fn default() -> Self {
568 Self {
569 include_p2p: true,
570 include_o2c: true,
571 include_s2c: true,
572 include_h2r: true,
573 include_mfg: true,
574 include_bank: true,
575 include_audit: true,
576 include_r2r: true,
577 events_as_hyperedges: true,
578 docs_per_counterparty_threshold: 20,
579 }
580 }
581}
582
583#[derive(Debug, Clone, Serialize, Deserialize)]
585pub struct AccountingLayerSettings {
586 #[serde(default = "default_true")]
588 pub include_accounts: bool,
589 #[serde(default = "default_true")]
591 pub je_as_hyperedges: bool,
592}
593
594impl Default for AccountingLayerSettings {
595 fn default() -> Self {
596 Self {
597 include_accounts: true,
598 je_as_hyperedges: true,
599 }
600 }
601}
602
603#[derive(Debug, Clone, Serialize, Deserialize)]
605pub struct CrossLayerSettings {
606 #[serde(default = "default_true")]
608 pub enabled: bool,
609}
610
611impl Default for CrossLayerSettings {
612 fn default() -> Self {
613 Self { enabled: true }
614 }
615}
616
617#[derive(Debug, Clone, Serialize, Deserialize)]
619pub struct GraphTypeConfig {
620 #[serde(default = "default_graph_name")]
622 pub name: String,
623
624 #[serde(default)]
626 pub aggregate_edges: bool,
627
628 #[serde(default)]
630 pub min_edge_weight: f64,
631
632 #[serde(default)]
634 pub include_document_nodes: bool,
635}
636
637fn default_graph_name() -> String {
638 "accounting_network".to_string()
639}
640
641impl Default for GraphTypeConfig {
642 fn default() -> Self {
643 Self {
644 name: "accounting_network".to_string(),
645 aggregate_edges: false,
646 min_edge_weight: 0.0,
647 include_document_nodes: false,
648 }
649 }
650}
651
652#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
654#[serde(rename_all = "snake_case")]
655pub enum GraphExportFormat {
656 PytorchGeometric,
658 Neo4j,
660 Dgl,
662 RustGraph,
664 RustGraphHypergraph,
666}
667
668#[derive(Debug, Clone, Default, Serialize, Deserialize)]
672pub struct ScenarioConfig {
673 #[serde(default)]
676 pub tags: Vec<String>,
677
678 #[serde(default)]
683 pub profile: Option<String>,
684
685 #[serde(default)]
687 pub description: Option<String>,
688
689 #[serde(default)]
691 pub ml_training: bool,
692
693 #[serde(default)]
696 pub target_anomaly_ratio: Option<f64>,
697
698 #[serde(default)]
700 pub metadata: std::collections::HashMap<String, String>,
701}
702
703#[derive(Debug, Clone, Serialize, Deserialize)]
708pub struct TemporalDriftConfig {
709 #[serde(default)]
711 pub enabled: bool,
712
713 #[serde(default = "default_amount_drift")]
716 pub amount_mean_drift: f64,
717
718 #[serde(default)]
721 pub amount_variance_drift: f64,
722
723 #[serde(default)]
726 pub anomaly_rate_drift: f64,
727
728 #[serde(default = "default_concept_drift")]
731 pub concept_drift_rate: f64,
732
733 #[serde(default)]
735 pub sudden_drift_probability: f64,
736
737 #[serde(default = "default_sudden_drift_magnitude")]
739 pub sudden_drift_magnitude: f64,
740
741 #[serde(default)]
743 pub seasonal_drift: bool,
744
745 #[serde(default)]
747 pub drift_start_period: u32,
748
749 #[serde(default = "default_drift_type")]
751 pub drift_type: DriftType,
752}
753
754fn default_amount_drift() -> f64 {
755 0.02
756}
757
758fn default_concept_drift() -> f64 {
759 0.01
760}
761
762fn default_sudden_drift_magnitude() -> f64 {
763 2.0
764}
765
766fn default_drift_type() -> DriftType {
767 DriftType::Gradual
768}
769
770impl Default for TemporalDriftConfig {
771 fn default() -> Self {
772 Self {
773 enabled: false,
774 amount_mean_drift: 0.02,
775 amount_variance_drift: 0.0,
776 anomaly_rate_drift: 0.0,
777 concept_drift_rate: 0.01,
778 sudden_drift_probability: 0.0,
779 sudden_drift_magnitude: 2.0,
780 seasonal_drift: false,
781 drift_start_period: 0,
782 drift_type: DriftType::Gradual,
783 }
784 }
785}
786
787impl TemporalDriftConfig {
788 pub fn to_core_config(&self) -> datasynth_core::distributions::DriftConfig {
790 datasynth_core::distributions::DriftConfig {
791 enabled: self.enabled,
792 amount_mean_drift: self.amount_mean_drift,
793 amount_variance_drift: self.amount_variance_drift,
794 anomaly_rate_drift: self.anomaly_rate_drift,
795 concept_drift_rate: self.concept_drift_rate,
796 sudden_drift_probability: self.sudden_drift_probability,
797 sudden_drift_magnitude: self.sudden_drift_magnitude,
798 seasonal_drift: self.seasonal_drift,
799 drift_start_period: self.drift_start_period,
800 drift_type: match self.drift_type {
801 DriftType::Gradual => datasynth_core::distributions::DriftType::Gradual,
802 DriftType::Sudden => datasynth_core::distributions::DriftType::Sudden,
803 DriftType::Recurring => datasynth_core::distributions::DriftType::Recurring,
804 DriftType::Mixed => datasynth_core::distributions::DriftType::Mixed,
805 },
806 regime_changes: Vec::new(),
807 economic_cycle: Default::default(),
808 parameter_drifts: Vec::new(),
809 }
810 }
811}
812
813#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
815#[serde(rename_all = "snake_case")]
816pub enum DriftType {
817 #[default]
819 Gradual,
820 Sudden,
822 Recurring,
824 Mixed,
826}
827
828#[derive(Debug, Clone, Serialize, Deserialize)]
834pub struct StreamingSchemaConfig {
835 #[serde(default)]
837 pub enabled: bool,
838 #[serde(default = "default_buffer_size")]
840 pub buffer_size: usize,
841 #[serde(default = "default_true")]
843 pub enable_progress: bool,
844 #[serde(default = "default_progress_interval")]
846 pub progress_interval: u64,
847 #[serde(default)]
849 pub backpressure: BackpressureSchemaStrategy,
850}
851
852fn default_buffer_size() -> usize {
853 1000
854}
855
856fn default_progress_interval() -> u64 {
857 100
858}
859
860impl Default for StreamingSchemaConfig {
861 fn default() -> Self {
862 Self {
863 enabled: false,
864 buffer_size: 1000,
865 enable_progress: true,
866 progress_interval: 100,
867 backpressure: BackpressureSchemaStrategy::Block,
868 }
869 }
870}
871
872#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
874#[serde(rename_all = "snake_case")]
875pub enum BackpressureSchemaStrategy {
876 #[default]
878 Block,
879 DropOldest,
881 DropNewest,
883 Buffer,
885}
886
887#[derive(Debug, Clone, Serialize, Deserialize)]
893pub struct RateLimitSchemaConfig {
894 #[serde(default)]
896 pub enabled: bool,
897 #[serde(default = "default_entities_per_second")]
899 pub entities_per_second: f64,
900 #[serde(default = "default_burst_size")]
902 pub burst_size: u32,
903 #[serde(default)]
905 pub backpressure: RateLimitBackpressureSchema,
906}
907
908fn default_entities_per_second() -> f64 {
909 1000.0
910}
911
912fn default_burst_size() -> u32 {
913 100
914}
915
916impl Default for RateLimitSchemaConfig {
917 fn default() -> Self {
918 Self {
919 enabled: false,
920 entities_per_second: 1000.0,
921 burst_size: 100,
922 backpressure: RateLimitBackpressureSchema::Block,
923 }
924 }
925}
926
927#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
929#[serde(rename_all = "snake_case")]
930pub enum RateLimitBackpressureSchema {
931 #[default]
933 Block,
934 Drop,
936 Buffer,
938}
939
940#[derive(Debug, Clone, Serialize, Deserialize)]
946pub struct TemporalAttributeSchemaConfig {
947 #[serde(default)]
949 pub enabled: bool,
950 #[serde(default)]
952 pub valid_time: ValidTimeSchemaConfig,
953 #[serde(default)]
955 pub transaction_time: TransactionTimeSchemaConfig,
956 #[serde(default)]
958 pub generate_version_chains: bool,
959 #[serde(default = "default_avg_versions")]
961 pub avg_versions_per_entity: f64,
962}
963
964fn default_avg_versions() -> f64 {
965 1.5
966}
967
968impl Default for TemporalAttributeSchemaConfig {
969 fn default() -> Self {
970 Self {
971 enabled: false,
972 valid_time: ValidTimeSchemaConfig::default(),
973 transaction_time: TransactionTimeSchemaConfig::default(),
974 generate_version_chains: false,
975 avg_versions_per_entity: 1.5,
976 }
977 }
978}
979
980#[derive(Debug, Clone, Serialize, Deserialize)]
982pub struct ValidTimeSchemaConfig {
983 #[serde(default = "default_closed_probability")]
985 pub closed_probability: f64,
986 #[serde(default = "default_avg_validity_days")]
988 pub avg_validity_days: u32,
989 #[serde(default = "default_validity_stddev")]
991 pub validity_stddev_days: u32,
992}
993
994fn default_closed_probability() -> f64 {
995 0.1
996}
997
998fn default_avg_validity_days() -> u32 {
999 365
1000}
1001
1002fn default_validity_stddev() -> u32 {
1003 90
1004}
1005
1006impl Default for ValidTimeSchemaConfig {
1007 fn default() -> Self {
1008 Self {
1009 closed_probability: 0.1,
1010 avg_validity_days: 365,
1011 validity_stddev_days: 90,
1012 }
1013 }
1014}
1015
1016#[derive(Debug, Clone, Serialize, Deserialize)]
1018pub struct TransactionTimeSchemaConfig {
1019 #[serde(default)]
1021 pub avg_recording_delay_seconds: u32,
1022 #[serde(default)]
1024 pub allow_backdating: bool,
1025 #[serde(default = "default_backdating_probability")]
1027 pub backdating_probability: f64,
1028 #[serde(default = "default_max_backdate_days")]
1030 pub max_backdate_days: u32,
1031}
1032
1033fn default_backdating_probability() -> f64 {
1034 0.01
1035}
1036
1037fn default_max_backdate_days() -> u32 {
1038 30
1039}
1040
1041impl Default for TransactionTimeSchemaConfig {
1042 fn default() -> Self {
1043 Self {
1044 avg_recording_delay_seconds: 0,
1045 allow_backdating: false,
1046 backdating_probability: 0.01,
1047 max_backdate_days: 30,
1048 }
1049 }
1050}
1051
1052#[derive(Debug, Clone, Serialize, Deserialize)]
1058pub struct RelationshipSchemaConfig {
1059 #[serde(default)]
1061 pub relationship_types: Vec<RelationshipTypeSchemaConfig>,
1062 #[serde(default = "default_true")]
1064 pub allow_orphans: bool,
1065 #[serde(default = "default_orphan_probability")]
1067 pub orphan_probability: f64,
1068 #[serde(default)]
1070 pub allow_circular: bool,
1071 #[serde(default = "default_max_circular_depth")]
1073 pub max_circular_depth: u32,
1074}
1075
1076fn default_orphan_probability() -> f64 {
1077 0.01
1078}
1079
1080fn default_max_circular_depth() -> u32 {
1081 3
1082}
1083
1084impl Default for RelationshipSchemaConfig {
1085 fn default() -> Self {
1086 Self {
1087 relationship_types: Vec::new(),
1088 allow_orphans: true,
1089 orphan_probability: 0.01,
1090 allow_circular: false,
1091 max_circular_depth: 3,
1092 }
1093 }
1094}
1095
1096#[derive(Debug, Clone, Serialize, Deserialize)]
1098pub struct RelationshipTypeSchemaConfig {
1099 pub name: String,
1101 pub source_type: String,
1103 pub target_type: String,
1105 #[serde(default)]
1107 pub cardinality: CardinalitySchemaRule,
1108 #[serde(default = "default_relationship_weight")]
1110 pub weight: f64,
1111 #[serde(default)]
1113 pub required: bool,
1114 #[serde(default = "default_true")]
1116 pub directed: bool,
1117}
1118
1119fn default_relationship_weight() -> f64 {
1120 1.0
1121}
1122
1123impl Default for RelationshipTypeSchemaConfig {
1124 fn default() -> Self {
1125 Self {
1126 name: String::new(),
1127 source_type: String::new(),
1128 target_type: String::new(),
1129 cardinality: CardinalitySchemaRule::default(),
1130 weight: 1.0,
1131 required: false,
1132 directed: true,
1133 }
1134 }
1135}
1136
1137#[derive(Debug, Clone, Serialize, Deserialize)]
1139#[serde(rename_all = "snake_case")]
1140pub enum CardinalitySchemaRule {
1141 OneToOne,
1143 OneToMany {
1145 min: u32,
1147 max: u32,
1149 },
1150 ManyToOne {
1152 min: u32,
1154 max: u32,
1156 },
1157 ManyToMany {
1159 min_per_source: u32,
1161 max_per_source: u32,
1163 },
1164}
1165
1166impl Default for CardinalitySchemaRule {
1167 fn default() -> Self {
1168 Self::OneToMany { min: 1, max: 5 }
1169 }
1170}
1171
1172#[derive(Debug, Clone, Serialize, Deserialize)]
1174pub struct GlobalConfig {
1175 pub seed: Option<u64>,
1177 pub industry: IndustrySector,
1179 pub start_date: String,
1181 pub period_months: u32,
1183 #[serde(default = "default_currency")]
1185 pub group_currency: String,
1186 #[serde(default)]
1189 pub presentation_currency: Option<String>,
1190 #[serde(default = "default_true")]
1192 pub parallel: bool,
1193 #[serde(default)]
1195 pub worker_threads: usize,
1196 #[serde(default)]
1198 pub memory_limit_mb: usize,
1199 #[serde(default)]
1202 pub fiscal_year_months: Option<u32>,
1203}
1204
1205fn default_currency() -> String {
1206 "USD".to_string()
1207}
1208fn default_true() -> bool {
1209 true
1210}
1211
1212#[derive(Debug, Clone, Serialize, Deserialize)]
1217pub struct SessionSchemaConfig {
1218 #[serde(default)]
1220 pub enabled: bool,
1221 #[serde(default)]
1223 pub checkpoint_path: Option<String>,
1224 #[serde(default = "default_true")]
1226 pub per_period_output: bool,
1227 #[serde(default = "default_true")]
1229 pub consolidated_output: bool,
1230}
1231
1232impl Default for SessionSchemaConfig {
1233 fn default() -> Self {
1234 Self {
1235 enabled: false,
1236 checkpoint_path: None,
1237 per_period_output: true,
1238 consolidated_output: true,
1239 }
1240 }
1241}
1242
1243#[derive(Debug, Clone, Serialize, Deserialize)]
1245pub struct CompanyConfig {
1246 pub code: String,
1248 pub name: String,
1250 pub currency: String,
1252 #[serde(default)]
1255 pub functional_currency: Option<String>,
1256 pub country: String,
1258 #[serde(default = "default_fiscal_variant")]
1260 pub fiscal_year_variant: String,
1261 pub annual_transaction_volume: TransactionVolume,
1263 #[serde(default = "default_weight")]
1265 pub volume_weight: f64,
1266}
1267
1268fn default_fiscal_variant() -> String {
1269 "K4".to_string()
1270}
1271fn default_weight() -> f64 {
1272 1.0
1273}
1274
1275#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1277#[serde(rename_all = "snake_case")]
1278pub enum TransactionVolume {
1279 TenK,
1281 HundredK,
1283 OneM,
1285 TenM,
1287 HundredM,
1289 Custom(u64),
1291}
1292
1293impl TransactionVolume {
1294 pub fn count(&self) -> u64 {
1296 match self {
1297 Self::TenK => 10_000,
1298 Self::HundredK => 100_000,
1299 Self::OneM => 1_000_000,
1300 Self::TenM => 10_000_000,
1301 Self::HundredM => 100_000_000,
1302 Self::Custom(n) => *n,
1303 }
1304 }
1305}
1306
1307#[derive(Debug, Clone, Serialize, Deserialize)]
1309pub struct ChartOfAccountsConfig {
1310 pub complexity: CoAComplexity,
1312 #[serde(default = "default_true")]
1314 pub industry_specific: bool,
1315 pub custom_accounts: Option<PathBuf>,
1317 #[serde(default = "default_min_depth")]
1319 pub min_hierarchy_depth: u8,
1320 #[serde(default = "default_max_depth")]
1322 pub max_hierarchy_depth: u8,
1323}
1324
1325fn default_min_depth() -> u8 {
1326 2
1327}
1328fn default_max_depth() -> u8 {
1329 5
1330}
1331
1332impl Default for ChartOfAccountsConfig {
1333 fn default() -> Self {
1334 Self {
1335 complexity: CoAComplexity::Small,
1336 industry_specific: true,
1337 custom_accounts: None,
1338 min_hierarchy_depth: default_min_depth(),
1339 max_hierarchy_depth: default_max_depth(),
1340 }
1341 }
1342}
1343
1344#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1346pub struct TransactionConfig {
1347 #[serde(default)]
1349 pub line_item_distribution: LineItemDistributionConfig,
1350 #[serde(default)]
1352 pub debit_credit_distribution: DebitCreditDistributionConfig,
1353 #[serde(default)]
1355 pub even_odd_distribution: EvenOddDistributionConfig,
1356 #[serde(default)]
1358 pub source_distribution: SourceDistribution,
1359 #[serde(default)]
1361 pub seasonality: SeasonalityConfig,
1362 #[serde(default)]
1364 pub amounts: AmountDistributionConfig,
1365 #[serde(default)]
1367 pub benford: BenfordConfig,
1368}
1369
1370#[derive(Debug, Clone, Serialize, Deserialize)]
1372pub struct BenfordConfig {
1373 #[serde(default = "default_true")]
1375 pub enabled: bool,
1376 #[serde(default = "default_benford_tolerance")]
1378 pub tolerance: f64,
1379 #[serde(default)]
1381 pub exempt_sources: Vec<BenfordExemption>,
1382}
1383
1384fn default_benford_tolerance() -> f64 {
1385 0.05
1386}
1387
1388impl Default for BenfordConfig {
1389 fn default() -> Self {
1390 Self {
1391 enabled: true,
1392 tolerance: default_benford_tolerance(),
1393 exempt_sources: vec![BenfordExemption::Recurring, BenfordExemption::Payroll],
1394 }
1395 }
1396}
1397
1398#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1400#[serde(rename_all = "snake_case")]
1401pub enum BenfordExemption {
1402 Recurring,
1404 Payroll,
1406 FixedFees,
1408 RoundAmounts,
1410}
1411
1412#[derive(Debug, Clone, Serialize, Deserialize)]
1414pub struct SourceDistribution {
1415 pub manual: f64,
1417 pub automated: f64,
1419 pub recurring: f64,
1421 pub adjustment: f64,
1423}
1424
1425impl Default for SourceDistribution {
1426 fn default() -> Self {
1427 Self {
1428 manual: 0.20,
1429 automated: 0.70,
1430 recurring: 0.07,
1431 adjustment: 0.03,
1432 }
1433 }
1434}
1435
1436#[derive(Debug, Clone, Serialize, Deserialize)]
1438pub struct OutputConfig {
1439 #[serde(default)]
1441 pub mode: OutputMode,
1442 pub output_directory: PathBuf,
1444 #[serde(default = "default_formats")]
1446 pub formats: Vec<FileFormat>,
1447 #[serde(default)]
1449 pub compression: CompressionConfig,
1450 #[serde(default = "default_batch_size")]
1452 pub batch_size: usize,
1453 #[serde(default = "default_true")]
1455 pub include_acdoca: bool,
1456 #[serde(default)]
1458 pub include_bseg: bool,
1459 #[serde(default = "default_true")]
1461 pub partition_by_period: bool,
1462 #[serde(default)]
1464 pub partition_by_company: bool,
1465}
1466
1467fn default_formats() -> Vec<FileFormat> {
1468 vec![FileFormat::Parquet]
1469}
1470fn default_batch_size() -> usize {
1471 100_000
1472}
1473
1474impl Default for OutputConfig {
1475 fn default() -> Self {
1476 Self {
1477 mode: OutputMode::FlatFile,
1478 output_directory: PathBuf::from("./output"),
1479 formats: default_formats(),
1480 compression: CompressionConfig::default(),
1481 batch_size: default_batch_size(),
1482 include_acdoca: true,
1483 include_bseg: false,
1484 partition_by_period: true,
1485 partition_by_company: false,
1486 }
1487 }
1488}
1489
1490#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
1492#[serde(rename_all = "snake_case")]
1493pub enum OutputMode {
1494 Streaming,
1496 #[default]
1498 FlatFile,
1499 Both,
1501}
1502
1503#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1505#[serde(rename_all = "snake_case")]
1506pub enum FileFormat {
1507 Csv,
1508 Parquet,
1509 Json,
1510 JsonLines,
1511}
1512
1513#[derive(Debug, Clone, Serialize, Deserialize)]
1515pub struct CompressionConfig {
1516 #[serde(default = "default_true")]
1518 pub enabled: bool,
1519 #[serde(default)]
1521 pub algorithm: CompressionAlgorithm,
1522 #[serde(default = "default_compression_level")]
1524 pub level: u8,
1525}
1526
1527fn default_compression_level() -> u8 {
1528 3
1529}
1530
1531impl Default for CompressionConfig {
1532 fn default() -> Self {
1533 Self {
1534 enabled: true,
1535 algorithm: CompressionAlgorithm::default(),
1536 level: default_compression_level(),
1537 }
1538 }
1539}
1540
1541#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
1543#[serde(rename_all = "snake_case")]
1544pub enum CompressionAlgorithm {
1545 Gzip,
1546 #[default]
1547 Zstd,
1548 Lz4,
1549 Snappy,
1550}
1551
1552#[derive(Debug, Clone, Serialize, Deserialize)]
1554pub struct FraudConfig {
1555 #[serde(default)]
1557 pub enabled: bool,
1558 #[serde(default = "default_fraud_rate")]
1560 pub fraud_rate: f64,
1561 #[serde(default)]
1563 pub fraud_type_distribution: FraudTypeDistribution,
1564 #[serde(default)]
1566 pub clustering_enabled: bool,
1567 #[serde(default = "default_clustering_factor")]
1569 pub clustering_factor: f64,
1570 #[serde(default = "default_approval_thresholds")]
1572 pub approval_thresholds: Vec<f64>,
1573}
1574
1575fn default_approval_thresholds() -> Vec<f64> {
1576 vec![1000.0, 5000.0, 10000.0, 25000.0, 50000.0, 100000.0]
1577}
1578
1579fn default_fraud_rate() -> f64 {
1580 0.005
1581}
1582fn default_clustering_factor() -> f64 {
1583 3.0
1584}
1585
1586impl Default for FraudConfig {
1587 fn default() -> Self {
1588 Self {
1589 enabled: false,
1590 fraud_rate: default_fraud_rate(),
1591 fraud_type_distribution: FraudTypeDistribution::default(),
1592 clustering_enabled: false,
1593 clustering_factor: default_clustering_factor(),
1594 approval_thresholds: default_approval_thresholds(),
1595 }
1596 }
1597}
1598
1599#[derive(Debug, Clone, Serialize, Deserialize)]
1601pub struct FraudTypeDistribution {
1602 pub suspense_account_abuse: f64,
1603 pub fictitious_transaction: f64,
1604 pub revenue_manipulation: f64,
1605 pub expense_capitalization: f64,
1606 pub split_transaction: f64,
1607 pub timing_anomaly: f64,
1608 pub unauthorized_access: f64,
1609 pub duplicate_payment: f64,
1610}
1611
1612impl Default for FraudTypeDistribution {
1613 fn default() -> Self {
1614 Self {
1615 suspense_account_abuse: 0.25,
1616 fictitious_transaction: 0.15,
1617 revenue_manipulation: 0.10,
1618 expense_capitalization: 0.10,
1619 split_transaction: 0.15,
1620 timing_anomaly: 0.10,
1621 unauthorized_access: 0.10,
1622 duplicate_payment: 0.05,
1623 }
1624 }
1625}
1626
1627#[derive(Debug, Clone, Serialize, Deserialize)]
1629pub struct InternalControlsConfig {
1630 #[serde(default)]
1632 pub enabled: bool,
1633 #[serde(default = "default_exception_rate")]
1635 pub exception_rate: f64,
1636 #[serde(default = "default_sod_violation_rate")]
1638 pub sod_violation_rate: f64,
1639 #[serde(default = "default_true")]
1641 pub export_control_master_data: bool,
1642 #[serde(default = "default_sox_materiality_threshold")]
1644 pub sox_materiality_threshold: f64,
1645 #[serde(default = "default_true")]
1647 pub coso_enabled: bool,
1648 #[serde(default)]
1650 pub include_entity_level_controls: bool,
1651 #[serde(default = "default_target_maturity_level")]
1654 pub target_maturity_level: String,
1655}
1656
1657fn default_exception_rate() -> f64 {
1658 0.02
1659}
1660
1661fn default_sod_violation_rate() -> f64 {
1662 0.01
1663}
1664
1665fn default_sox_materiality_threshold() -> f64 {
1666 10000.0
1667}
1668
1669fn default_target_maturity_level() -> String {
1670 "mixed".to_string()
1671}
1672
1673impl Default for InternalControlsConfig {
1674 fn default() -> Self {
1675 Self {
1676 enabled: false,
1677 exception_rate: default_exception_rate(),
1678 sod_violation_rate: default_sod_violation_rate(),
1679 export_control_master_data: true,
1680 sox_materiality_threshold: default_sox_materiality_threshold(),
1681 coso_enabled: true,
1682 include_entity_level_controls: false,
1683 target_maturity_level: default_target_maturity_level(),
1684 }
1685 }
1686}
1687
1688#[derive(Debug, Clone, Serialize, Deserialize)]
1690pub struct BusinessProcessConfig {
1691 #[serde(default = "default_o2c")]
1693 pub o2c_weight: f64,
1694 #[serde(default = "default_p2p")]
1696 pub p2p_weight: f64,
1697 #[serde(default = "default_r2r")]
1699 pub r2r_weight: f64,
1700 #[serde(default = "default_h2r")]
1702 pub h2r_weight: f64,
1703 #[serde(default = "default_a2r")]
1705 pub a2r_weight: f64,
1706}
1707
1708fn default_o2c() -> f64 {
1709 0.35
1710}
1711fn default_p2p() -> f64 {
1712 0.30
1713}
1714fn default_r2r() -> f64 {
1715 0.20
1716}
1717fn default_h2r() -> f64 {
1718 0.10
1719}
1720fn default_a2r() -> f64 {
1721 0.05
1722}
1723
1724impl Default for BusinessProcessConfig {
1725 fn default() -> Self {
1726 Self {
1727 o2c_weight: default_o2c(),
1728 p2p_weight: default_p2p(),
1729 r2r_weight: default_r2r(),
1730 h2r_weight: default_h2r(),
1731 a2r_weight: default_a2r(),
1732 }
1733 }
1734}
1735
1736#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1738pub struct UserPersonaConfig {
1739 #[serde(default)]
1741 pub persona_distribution: PersonaDistribution,
1742 #[serde(default)]
1744 pub users_per_persona: UsersPerPersona,
1745}
1746
1747#[derive(Debug, Clone, Serialize, Deserialize)]
1749pub struct PersonaDistribution {
1750 pub junior_accountant: f64,
1751 pub senior_accountant: f64,
1752 pub controller: f64,
1753 pub manager: f64,
1754 pub automated_system: f64,
1755}
1756
1757impl Default for PersonaDistribution {
1758 fn default() -> Self {
1759 Self {
1760 junior_accountant: 0.15,
1761 senior_accountant: 0.15,
1762 controller: 0.05,
1763 manager: 0.05,
1764 automated_system: 0.60,
1765 }
1766 }
1767}
1768
1769#[derive(Debug, Clone, Serialize, Deserialize)]
1771pub struct UsersPerPersona {
1772 pub junior_accountant: usize,
1773 pub senior_accountant: usize,
1774 pub controller: usize,
1775 pub manager: usize,
1776 pub automated_system: usize,
1777}
1778
1779impl Default for UsersPerPersona {
1780 fn default() -> Self {
1781 Self {
1782 junior_accountant: 10,
1783 senior_accountant: 5,
1784 controller: 2,
1785 manager: 3,
1786 automated_system: 20,
1787 }
1788 }
1789}
1790
1791#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1793pub struct TemplateConfig {
1794 #[serde(default)]
1796 pub names: NameTemplateConfig,
1797 #[serde(default)]
1799 pub descriptions: DescriptionTemplateConfig,
1800 #[serde(default)]
1802 pub references: ReferenceTemplateConfig,
1803}
1804
1805#[derive(Debug, Clone, Serialize, Deserialize)]
1807pub struct NameTemplateConfig {
1808 #[serde(default)]
1810 pub culture_distribution: CultureDistribution,
1811 #[serde(default = "default_email_domain")]
1813 pub email_domain: String,
1814 #[serde(default = "default_true")]
1816 pub generate_realistic_names: bool,
1817}
1818
1819fn default_email_domain() -> String {
1820 "company.com".to_string()
1821}
1822
1823impl Default for NameTemplateConfig {
1824 fn default() -> Self {
1825 Self {
1826 culture_distribution: CultureDistribution::default(),
1827 email_domain: default_email_domain(),
1828 generate_realistic_names: true,
1829 }
1830 }
1831}
1832
1833#[derive(Debug, Clone, Serialize, Deserialize)]
1835pub struct CultureDistribution {
1836 pub western_us: f64,
1837 pub hispanic: f64,
1838 pub german: f64,
1839 pub french: f64,
1840 pub chinese: f64,
1841 pub japanese: f64,
1842 pub indian: f64,
1843}
1844
1845impl Default for CultureDistribution {
1846 fn default() -> Self {
1847 Self {
1848 western_us: 0.40,
1849 hispanic: 0.20,
1850 german: 0.10,
1851 french: 0.05,
1852 chinese: 0.10,
1853 japanese: 0.05,
1854 indian: 0.10,
1855 }
1856 }
1857}
1858
1859#[derive(Debug, Clone, Serialize, Deserialize)]
1861pub struct DescriptionTemplateConfig {
1862 #[serde(default = "default_true")]
1864 pub generate_header_text: bool,
1865 #[serde(default = "default_true")]
1867 pub generate_line_text: bool,
1868}
1869
1870impl Default for DescriptionTemplateConfig {
1871 fn default() -> Self {
1872 Self {
1873 generate_header_text: true,
1874 generate_line_text: true,
1875 }
1876 }
1877}
1878
1879#[derive(Debug, Clone, Serialize, Deserialize)]
1881pub struct ReferenceTemplateConfig {
1882 #[serde(default = "default_true")]
1884 pub generate_references: bool,
1885 #[serde(default = "default_invoice_prefix")]
1887 pub invoice_prefix: String,
1888 #[serde(default = "default_po_prefix")]
1890 pub po_prefix: String,
1891 #[serde(default = "default_so_prefix")]
1893 pub so_prefix: String,
1894}
1895
1896fn default_invoice_prefix() -> String {
1897 "INV".to_string()
1898}
1899fn default_po_prefix() -> String {
1900 "PO".to_string()
1901}
1902fn default_so_prefix() -> String {
1903 "SO".to_string()
1904}
1905
1906impl Default for ReferenceTemplateConfig {
1907 fn default() -> Self {
1908 Self {
1909 generate_references: true,
1910 invoice_prefix: default_invoice_prefix(),
1911 po_prefix: default_po_prefix(),
1912 so_prefix: default_so_prefix(),
1913 }
1914 }
1915}
1916
1917#[derive(Debug, Clone, Serialize, Deserialize)]
1919pub struct ApprovalConfig {
1920 #[serde(default)]
1922 pub enabled: bool,
1923 #[serde(default = "default_auto_approve_threshold")]
1925 pub auto_approve_threshold: f64,
1926 #[serde(default = "default_rejection_rate")]
1928 pub rejection_rate: f64,
1929 #[serde(default = "default_revision_rate")]
1931 pub revision_rate: f64,
1932 #[serde(default = "default_approval_delay_hours")]
1934 pub average_approval_delay_hours: f64,
1935 #[serde(default)]
1937 pub thresholds: Vec<ApprovalThresholdConfig>,
1938}
1939
1940fn default_auto_approve_threshold() -> f64 {
1941 1000.0
1942}
1943fn default_rejection_rate() -> f64 {
1944 0.02
1945}
1946fn default_revision_rate() -> f64 {
1947 0.05
1948}
1949fn default_approval_delay_hours() -> f64 {
1950 4.0
1951}
1952
1953impl Default for ApprovalConfig {
1954 fn default() -> Self {
1955 Self {
1956 enabled: false,
1957 auto_approve_threshold: default_auto_approve_threshold(),
1958 rejection_rate: default_rejection_rate(),
1959 revision_rate: default_revision_rate(),
1960 average_approval_delay_hours: default_approval_delay_hours(),
1961 thresholds: vec![
1962 ApprovalThresholdConfig {
1963 amount: 1000.0,
1964 level: 1,
1965 roles: vec!["senior_accountant".to_string()],
1966 },
1967 ApprovalThresholdConfig {
1968 amount: 10000.0,
1969 level: 2,
1970 roles: vec!["senior_accountant".to_string(), "controller".to_string()],
1971 },
1972 ApprovalThresholdConfig {
1973 amount: 100000.0,
1974 level: 3,
1975 roles: vec![
1976 "senior_accountant".to_string(),
1977 "controller".to_string(),
1978 "manager".to_string(),
1979 ],
1980 },
1981 ApprovalThresholdConfig {
1982 amount: 500000.0,
1983 level: 4,
1984 roles: vec![
1985 "senior_accountant".to_string(),
1986 "controller".to_string(),
1987 "manager".to_string(),
1988 "executive".to_string(),
1989 ],
1990 },
1991 ],
1992 }
1993 }
1994}
1995
1996#[derive(Debug, Clone, Serialize, Deserialize)]
1998pub struct ApprovalThresholdConfig {
1999 pub amount: f64,
2001 pub level: u8,
2003 pub roles: Vec<String>,
2005}
2006
2007#[derive(Debug, Clone, Serialize, Deserialize)]
2009pub struct DepartmentConfig {
2010 #[serde(default)]
2012 pub enabled: bool,
2013 #[serde(default = "default_headcount_multiplier")]
2015 pub headcount_multiplier: f64,
2016 #[serde(default)]
2018 pub custom_departments: Vec<CustomDepartmentConfig>,
2019}
2020
2021fn default_headcount_multiplier() -> f64 {
2022 1.0
2023}
2024
2025impl Default for DepartmentConfig {
2026 fn default() -> Self {
2027 Self {
2028 enabled: false,
2029 headcount_multiplier: default_headcount_multiplier(),
2030 custom_departments: Vec::new(),
2031 }
2032 }
2033}
2034
2035#[derive(Debug, Clone, Serialize, Deserialize)]
2037pub struct CustomDepartmentConfig {
2038 pub code: String,
2040 pub name: String,
2042 #[serde(default)]
2044 pub cost_center: Option<String>,
2045 #[serde(default)]
2047 pub primary_processes: Vec<String>,
2048 #[serde(default)]
2050 pub parent_code: Option<String>,
2051}
2052
2053#[derive(Debug, Clone, Default, Serialize, Deserialize)]
2059pub struct MasterDataConfig {
2060 #[serde(default)]
2062 pub vendors: VendorMasterConfig,
2063 #[serde(default)]
2065 pub customers: CustomerMasterConfig,
2066 #[serde(default)]
2068 pub materials: MaterialMasterConfig,
2069 #[serde(default)]
2071 pub fixed_assets: FixedAssetMasterConfig,
2072 #[serde(default)]
2074 pub employees: EmployeeMasterConfig,
2075 #[serde(default)]
2077 pub cost_centers: CostCenterMasterConfig,
2078}
2079
2080#[derive(Debug, Clone, Serialize, Deserialize)]
2082pub struct VendorMasterConfig {
2083 #[serde(default = "default_vendor_count")]
2085 pub count: usize,
2086 #[serde(default = "default_intercompany_percent")]
2088 pub intercompany_percent: f64,
2089 #[serde(default)]
2091 pub payment_terms_distribution: PaymentTermsDistribution,
2092 #[serde(default)]
2094 pub behavior_distribution: VendorBehaviorDistribution,
2095 #[serde(default = "default_true")]
2097 pub generate_bank_accounts: bool,
2098 #[serde(default = "default_true")]
2100 pub generate_tax_ids: bool,
2101}
2102
2103fn default_vendor_count() -> usize {
2104 500
2105}
2106
2107fn default_intercompany_percent() -> f64 {
2108 0.05
2109}
2110
2111impl Default for VendorMasterConfig {
2112 fn default() -> Self {
2113 Self {
2114 count: default_vendor_count(),
2115 intercompany_percent: default_intercompany_percent(),
2116 payment_terms_distribution: PaymentTermsDistribution::default(),
2117 behavior_distribution: VendorBehaviorDistribution::default(),
2118 generate_bank_accounts: true,
2119 generate_tax_ids: true,
2120 }
2121 }
2122}
2123
2124#[derive(Debug, Clone, Serialize, Deserialize)]
2126pub struct PaymentTermsDistribution {
2127 pub net_30: f64,
2129 pub net_60: f64,
2131 pub net_90: f64,
2133 pub two_ten_net_30: f64,
2135 pub due_on_receipt: f64,
2137 pub end_of_month: f64,
2139}
2140
2141impl Default for PaymentTermsDistribution {
2142 fn default() -> Self {
2143 Self {
2144 net_30: 0.40,
2145 net_60: 0.20,
2146 net_90: 0.10,
2147 two_ten_net_30: 0.15,
2148 due_on_receipt: 0.05,
2149 end_of_month: 0.10,
2150 }
2151 }
2152}
2153
2154#[derive(Debug, Clone, Serialize, Deserialize)]
2156pub struct VendorBehaviorDistribution {
2157 pub reliable: f64,
2159 pub sometimes_late: f64,
2161 pub inconsistent_quality: f64,
2163 pub premium: f64,
2165 pub budget: f64,
2167}
2168
2169impl Default for VendorBehaviorDistribution {
2170 fn default() -> Self {
2171 Self {
2172 reliable: 0.50,
2173 sometimes_late: 0.20,
2174 inconsistent_quality: 0.10,
2175 premium: 0.10,
2176 budget: 0.10,
2177 }
2178 }
2179}
2180
2181#[derive(Debug, Clone, Serialize, Deserialize)]
2183pub struct CustomerMasterConfig {
2184 #[serde(default = "default_customer_count")]
2186 pub count: usize,
2187 #[serde(default = "default_intercompany_percent")]
2189 pub intercompany_percent: f64,
2190 #[serde(default)]
2192 pub credit_rating_distribution: CreditRatingDistribution,
2193 #[serde(default)]
2195 pub payment_behavior_distribution: PaymentBehaviorDistribution,
2196 #[serde(default = "default_true")]
2198 pub generate_credit_limits: bool,
2199}
2200
2201fn default_customer_count() -> usize {
2202 2000
2203}
2204
2205impl Default for CustomerMasterConfig {
2206 fn default() -> Self {
2207 Self {
2208 count: default_customer_count(),
2209 intercompany_percent: default_intercompany_percent(),
2210 credit_rating_distribution: CreditRatingDistribution::default(),
2211 payment_behavior_distribution: PaymentBehaviorDistribution::default(),
2212 generate_credit_limits: true,
2213 }
2214 }
2215}
2216
2217#[derive(Debug, Clone, Serialize, Deserialize)]
2219pub struct CreditRatingDistribution {
2220 pub aaa: f64,
2222 pub aa: f64,
2224 pub a: f64,
2226 pub bbb: f64,
2228 pub bb: f64,
2230 pub b: f64,
2232 pub below_b: f64,
2234}
2235
2236impl Default for CreditRatingDistribution {
2237 fn default() -> Self {
2238 Self {
2239 aaa: 0.05,
2240 aa: 0.10,
2241 a: 0.20,
2242 bbb: 0.30,
2243 bb: 0.20,
2244 b: 0.10,
2245 below_b: 0.05,
2246 }
2247 }
2248}
2249
2250#[derive(Debug, Clone, Serialize, Deserialize)]
2252pub struct PaymentBehaviorDistribution {
2253 pub early_payer: f64,
2255 pub on_time: f64,
2257 pub occasional_late: f64,
2259 pub frequent_late: f64,
2261 pub discount_taker: f64,
2263}
2264
2265impl Default for PaymentBehaviorDistribution {
2266 fn default() -> Self {
2267 Self {
2268 early_payer: 0.10,
2269 on_time: 0.50,
2270 occasional_late: 0.25,
2271 frequent_late: 0.10,
2272 discount_taker: 0.05,
2273 }
2274 }
2275}
2276
2277#[derive(Debug, Clone, Serialize, Deserialize)]
2279pub struct MaterialMasterConfig {
2280 #[serde(default = "default_material_count")]
2282 pub count: usize,
2283 #[serde(default)]
2285 pub type_distribution: MaterialTypeDistribution,
2286 #[serde(default)]
2288 pub valuation_distribution: ValuationMethodDistribution,
2289 #[serde(default = "default_bom_percent")]
2291 pub bom_percent: f64,
2292 #[serde(default = "default_max_bom_depth")]
2294 pub max_bom_depth: u8,
2295}
2296
2297fn default_material_count() -> usize {
2298 5000
2299}
2300
2301fn default_bom_percent() -> f64 {
2302 0.20
2303}
2304
2305fn default_max_bom_depth() -> u8 {
2306 3
2307}
2308
2309impl Default for MaterialMasterConfig {
2310 fn default() -> Self {
2311 Self {
2312 count: default_material_count(),
2313 type_distribution: MaterialTypeDistribution::default(),
2314 valuation_distribution: ValuationMethodDistribution::default(),
2315 bom_percent: default_bom_percent(),
2316 max_bom_depth: default_max_bom_depth(),
2317 }
2318 }
2319}
2320
2321#[derive(Debug, Clone, Serialize, Deserialize)]
2323pub struct MaterialTypeDistribution {
2324 pub raw_material: f64,
2326 pub semi_finished: f64,
2328 pub finished_good: f64,
2330 pub trading_good: f64,
2332 pub operating_supply: f64,
2334 pub service: f64,
2336}
2337
2338impl Default for MaterialTypeDistribution {
2339 fn default() -> Self {
2340 Self {
2341 raw_material: 0.30,
2342 semi_finished: 0.15,
2343 finished_good: 0.25,
2344 trading_good: 0.15,
2345 operating_supply: 0.10,
2346 service: 0.05,
2347 }
2348 }
2349}
2350
2351#[derive(Debug, Clone, Serialize, Deserialize)]
2353pub struct ValuationMethodDistribution {
2354 pub standard_cost: f64,
2356 pub moving_average: f64,
2358 pub fifo: f64,
2360 pub lifo: f64,
2362}
2363
2364impl Default for ValuationMethodDistribution {
2365 fn default() -> Self {
2366 Self {
2367 standard_cost: 0.50,
2368 moving_average: 0.30,
2369 fifo: 0.15,
2370 lifo: 0.05,
2371 }
2372 }
2373}
2374
2375#[derive(Debug, Clone, Serialize, Deserialize)]
2377pub struct FixedAssetMasterConfig {
2378 #[serde(default = "default_asset_count")]
2380 pub count: usize,
2381 #[serde(default)]
2383 pub class_distribution: AssetClassDistribution,
2384 #[serde(default)]
2386 pub depreciation_distribution: DepreciationMethodDistribution,
2387 #[serde(default = "default_fully_depreciated_percent")]
2389 pub fully_depreciated_percent: f64,
2390 #[serde(default = "default_true")]
2392 pub generate_acquisition_history: bool,
2393}
2394
2395fn default_asset_count() -> usize {
2396 800
2397}
2398
2399fn default_fully_depreciated_percent() -> f64 {
2400 0.15
2401}
2402
2403impl Default for FixedAssetMasterConfig {
2404 fn default() -> Self {
2405 Self {
2406 count: default_asset_count(),
2407 class_distribution: AssetClassDistribution::default(),
2408 depreciation_distribution: DepreciationMethodDistribution::default(),
2409 fully_depreciated_percent: default_fully_depreciated_percent(),
2410 generate_acquisition_history: true,
2411 }
2412 }
2413}
2414
2415#[derive(Debug, Clone, Serialize, Deserialize)]
2417pub struct AssetClassDistribution {
2418 pub buildings: f64,
2420 pub machinery: f64,
2422 pub vehicles: f64,
2424 pub it_equipment: f64,
2426 pub furniture: f64,
2428 pub land: f64,
2430 pub leasehold: f64,
2432}
2433
2434impl Default for AssetClassDistribution {
2435 fn default() -> Self {
2436 Self {
2437 buildings: 0.15,
2438 machinery: 0.30,
2439 vehicles: 0.15,
2440 it_equipment: 0.20,
2441 furniture: 0.10,
2442 land: 0.05,
2443 leasehold: 0.05,
2444 }
2445 }
2446}
2447
2448#[derive(Debug, Clone, Serialize, Deserialize)]
2450pub struct DepreciationMethodDistribution {
2451 pub straight_line: f64,
2453 pub declining_balance: f64,
2455 pub double_declining: f64,
2457 pub sum_of_years: f64,
2459 pub units_of_production: f64,
2461}
2462
2463impl Default for DepreciationMethodDistribution {
2464 fn default() -> Self {
2465 Self {
2466 straight_line: 0.60,
2467 declining_balance: 0.20,
2468 double_declining: 0.10,
2469 sum_of_years: 0.05,
2470 units_of_production: 0.05,
2471 }
2472 }
2473}
2474
2475#[derive(Debug, Clone, Serialize, Deserialize)]
2477pub struct EmployeeMasterConfig {
2478 #[serde(default = "default_employee_count")]
2480 pub count: usize,
2481 #[serde(default = "default_true")]
2483 pub generate_hierarchy: bool,
2484 #[serde(default = "default_hierarchy_depth")]
2486 pub max_hierarchy_depth: u8,
2487 #[serde(default = "default_span_of_control")]
2489 pub average_span_of_control: f64,
2490 #[serde(default)]
2492 pub approval_limits: ApprovalLimitDistribution,
2493 #[serde(default)]
2495 pub department_distribution: EmployeeDepartmentDistribution,
2496}
2497
2498fn default_employee_count() -> usize {
2499 1500
2500}
2501
2502fn default_hierarchy_depth() -> u8 {
2503 6
2504}
2505
2506fn default_span_of_control() -> f64 {
2507 5.0
2508}
2509
2510impl Default for EmployeeMasterConfig {
2511 fn default() -> Self {
2512 Self {
2513 count: default_employee_count(),
2514 generate_hierarchy: true,
2515 max_hierarchy_depth: default_hierarchy_depth(),
2516 average_span_of_control: default_span_of_control(),
2517 approval_limits: ApprovalLimitDistribution::default(),
2518 department_distribution: EmployeeDepartmentDistribution::default(),
2519 }
2520 }
2521}
2522
2523#[derive(Debug, Clone, Serialize, Deserialize)]
2525pub struct ApprovalLimitDistribution {
2526 #[serde(default = "default_staff_limit")]
2528 pub staff: f64,
2529 #[serde(default = "default_senior_limit")]
2531 pub senior: f64,
2532 #[serde(default = "default_manager_limit")]
2534 pub manager: f64,
2535 #[serde(default = "default_director_limit")]
2537 pub director: f64,
2538 #[serde(default = "default_vp_limit")]
2540 pub vp: f64,
2541 #[serde(default = "default_executive_limit")]
2543 pub executive: f64,
2544}
2545
2546fn default_staff_limit() -> f64 {
2547 1000.0
2548}
2549fn default_senior_limit() -> f64 {
2550 5000.0
2551}
2552fn default_manager_limit() -> f64 {
2553 25000.0
2554}
2555fn default_director_limit() -> f64 {
2556 100000.0
2557}
2558fn default_vp_limit() -> f64 {
2559 500000.0
2560}
2561fn default_executive_limit() -> f64 {
2562 f64::INFINITY
2563}
2564
2565impl Default for ApprovalLimitDistribution {
2566 fn default() -> Self {
2567 Self {
2568 staff: default_staff_limit(),
2569 senior: default_senior_limit(),
2570 manager: default_manager_limit(),
2571 director: default_director_limit(),
2572 vp: default_vp_limit(),
2573 executive: default_executive_limit(),
2574 }
2575 }
2576}
2577
2578#[derive(Debug, Clone, Serialize, Deserialize)]
2580pub struct EmployeeDepartmentDistribution {
2581 pub finance: f64,
2583 pub procurement: f64,
2585 pub sales: f64,
2587 pub warehouse: f64,
2589 pub it: f64,
2591 pub hr: f64,
2593 pub operations: f64,
2595 pub executive: f64,
2597}
2598
2599impl Default for EmployeeDepartmentDistribution {
2600 fn default() -> Self {
2601 Self {
2602 finance: 0.12,
2603 procurement: 0.10,
2604 sales: 0.25,
2605 warehouse: 0.15,
2606 it: 0.10,
2607 hr: 0.05,
2608 operations: 0.20,
2609 executive: 0.03,
2610 }
2611 }
2612}
2613
2614#[derive(Debug, Clone, Serialize, Deserialize)]
2616pub struct CostCenterMasterConfig {
2617 #[serde(default = "default_cost_center_count")]
2619 pub count: usize,
2620 #[serde(default = "default_true")]
2622 pub generate_hierarchy: bool,
2623 #[serde(default = "default_cc_hierarchy_depth")]
2625 pub max_hierarchy_depth: u8,
2626}
2627
2628fn default_cost_center_count() -> usize {
2629 50
2630}
2631
2632fn default_cc_hierarchy_depth() -> u8 {
2633 3
2634}
2635
2636impl Default for CostCenterMasterConfig {
2637 fn default() -> Self {
2638 Self {
2639 count: default_cost_center_count(),
2640 generate_hierarchy: true,
2641 max_hierarchy_depth: default_cc_hierarchy_depth(),
2642 }
2643 }
2644}
2645
2646#[derive(Debug, Clone, Serialize, Deserialize)]
2652pub struct DocumentFlowConfig {
2653 #[serde(default)]
2655 pub p2p: P2PFlowConfig,
2656 #[serde(default)]
2658 pub o2c: O2CFlowConfig,
2659 #[serde(default = "default_true")]
2661 pub generate_document_references: bool,
2662 #[serde(default)]
2664 pub export_flow_graph: bool,
2665}
2666
2667impl Default for DocumentFlowConfig {
2668 fn default() -> Self {
2669 Self {
2670 p2p: P2PFlowConfig::default(),
2671 o2c: O2CFlowConfig::default(),
2672 generate_document_references: true,
2673 export_flow_graph: false,
2674 }
2675 }
2676}
2677
2678#[derive(Debug, Clone, Serialize, Deserialize)]
2680pub struct P2PFlowConfig {
2681 #[serde(default = "default_true")]
2683 pub enabled: bool,
2684 #[serde(default = "default_three_way_match_rate")]
2686 pub three_way_match_rate: f64,
2687 #[serde(default = "default_partial_delivery_rate")]
2689 pub partial_delivery_rate: f64,
2690 #[serde(default = "default_price_variance_rate")]
2692 pub price_variance_rate: f64,
2693 #[serde(default = "default_max_price_variance")]
2695 pub max_price_variance_percent: f64,
2696 #[serde(default = "default_quantity_variance_rate")]
2698 pub quantity_variance_rate: f64,
2699 #[serde(default = "default_po_to_gr_days")]
2701 pub average_po_to_gr_days: u32,
2702 #[serde(default = "default_gr_to_invoice_days")]
2704 pub average_gr_to_invoice_days: u32,
2705 #[serde(default = "default_invoice_to_payment_days")]
2707 pub average_invoice_to_payment_days: u32,
2708 #[serde(default)]
2710 pub line_count_distribution: DocumentLineCountDistribution,
2711 #[serde(default)]
2713 pub payment_behavior: P2PPaymentBehaviorConfig,
2714 #[serde(default)]
2716 pub over_delivery_rate: Option<f64>,
2717 #[serde(default)]
2719 pub early_payment_discount_rate: Option<f64>,
2720}
2721
2722fn default_three_way_match_rate() -> f64 {
2723 0.95
2724}
2725
2726fn default_partial_delivery_rate() -> f64 {
2727 0.15
2728}
2729
2730fn default_price_variance_rate() -> f64 {
2731 0.08
2732}
2733
2734fn default_max_price_variance() -> f64 {
2735 0.05
2736}
2737
2738fn default_quantity_variance_rate() -> f64 {
2739 0.05
2740}
2741
2742fn default_po_to_gr_days() -> u32 {
2743 14
2744}
2745
2746fn default_gr_to_invoice_days() -> u32 {
2747 5
2748}
2749
2750fn default_invoice_to_payment_days() -> u32 {
2751 30
2752}
2753
2754impl Default for P2PFlowConfig {
2755 fn default() -> Self {
2756 Self {
2757 enabled: true,
2758 three_way_match_rate: default_three_way_match_rate(),
2759 partial_delivery_rate: default_partial_delivery_rate(),
2760 price_variance_rate: default_price_variance_rate(),
2761 max_price_variance_percent: default_max_price_variance(),
2762 quantity_variance_rate: default_quantity_variance_rate(),
2763 average_po_to_gr_days: default_po_to_gr_days(),
2764 average_gr_to_invoice_days: default_gr_to_invoice_days(),
2765 average_invoice_to_payment_days: default_invoice_to_payment_days(),
2766 line_count_distribution: DocumentLineCountDistribution::default(),
2767 payment_behavior: P2PPaymentBehaviorConfig::default(),
2768 over_delivery_rate: None,
2769 early_payment_discount_rate: None,
2770 }
2771 }
2772}
2773
2774#[derive(Debug, Clone, Serialize, Deserialize)]
2780pub struct P2PPaymentBehaviorConfig {
2781 #[serde(default = "default_p2p_late_payment_rate")]
2783 pub late_payment_rate: f64,
2784 #[serde(default)]
2786 pub late_payment_days_distribution: LatePaymentDaysDistribution,
2787 #[serde(default = "default_p2p_partial_payment_rate")]
2789 pub partial_payment_rate: f64,
2790 #[serde(default = "default_p2p_payment_correction_rate")]
2792 pub payment_correction_rate: f64,
2793 #[serde(default = "default_p2p_avg_days_until_remainder")]
2795 pub avg_days_until_remainder: u32,
2796}
2797
2798fn default_p2p_late_payment_rate() -> f64 {
2799 0.15
2800}
2801
2802fn default_p2p_partial_payment_rate() -> f64 {
2803 0.05
2804}
2805
2806fn default_p2p_payment_correction_rate() -> f64 {
2807 0.02
2808}
2809
2810fn default_p2p_avg_days_until_remainder() -> u32 {
2811 30
2812}
2813
2814impl Default for P2PPaymentBehaviorConfig {
2815 fn default() -> Self {
2816 Self {
2817 late_payment_rate: default_p2p_late_payment_rate(),
2818 late_payment_days_distribution: LatePaymentDaysDistribution::default(),
2819 partial_payment_rate: default_p2p_partial_payment_rate(),
2820 payment_correction_rate: default_p2p_payment_correction_rate(),
2821 avg_days_until_remainder: default_p2p_avg_days_until_remainder(),
2822 }
2823 }
2824}
2825
2826#[derive(Debug, Clone, Serialize, Deserialize)]
2828pub struct LatePaymentDaysDistribution {
2829 #[serde(default = "default_slightly_late")]
2831 pub slightly_late_1_to_7: f64,
2832 #[serde(default = "default_late_8_14")]
2834 pub late_8_to_14: f64,
2835 #[serde(default = "default_very_late")]
2837 pub very_late_15_to_30: f64,
2838 #[serde(default = "default_severely_late")]
2840 pub severely_late_31_to_60: f64,
2841 #[serde(default = "default_extremely_late")]
2843 pub extremely_late_over_60: f64,
2844}
2845
2846fn default_slightly_late() -> f64 {
2847 0.50
2848}
2849
2850fn default_late_8_14() -> f64 {
2851 0.25
2852}
2853
2854fn default_very_late() -> f64 {
2855 0.15
2856}
2857
2858fn default_severely_late() -> f64 {
2859 0.07
2860}
2861
2862fn default_extremely_late() -> f64 {
2863 0.03
2864}
2865
2866impl Default for LatePaymentDaysDistribution {
2867 fn default() -> Self {
2868 Self {
2869 slightly_late_1_to_7: default_slightly_late(),
2870 late_8_to_14: default_late_8_14(),
2871 very_late_15_to_30: default_very_late(),
2872 severely_late_31_to_60: default_severely_late(),
2873 extremely_late_over_60: default_extremely_late(),
2874 }
2875 }
2876}
2877
2878#[derive(Debug, Clone, Serialize, Deserialize)]
2880pub struct O2CFlowConfig {
2881 #[serde(default = "default_true")]
2883 pub enabled: bool,
2884 #[serde(default = "default_credit_check_failure_rate")]
2886 pub credit_check_failure_rate: f64,
2887 #[serde(default = "default_partial_shipment_rate")]
2889 pub partial_shipment_rate: f64,
2890 #[serde(default = "default_return_rate")]
2892 pub return_rate: f64,
2893 #[serde(default = "default_bad_debt_rate")]
2895 pub bad_debt_rate: f64,
2896 #[serde(default = "default_so_to_delivery_days")]
2898 pub average_so_to_delivery_days: u32,
2899 #[serde(default = "default_delivery_to_invoice_days")]
2901 pub average_delivery_to_invoice_days: u32,
2902 #[serde(default = "default_invoice_to_receipt_days")]
2904 pub average_invoice_to_receipt_days: u32,
2905 #[serde(default)]
2907 pub line_count_distribution: DocumentLineCountDistribution,
2908 #[serde(default)]
2910 pub cash_discount: CashDiscountConfig,
2911 #[serde(default)]
2913 pub payment_behavior: O2CPaymentBehaviorConfig,
2914 #[serde(default)]
2916 pub late_payment_rate: Option<f64>,
2917}
2918
2919fn default_credit_check_failure_rate() -> f64 {
2920 0.02
2921}
2922
2923fn default_partial_shipment_rate() -> f64 {
2924 0.10
2925}
2926
2927fn default_return_rate() -> f64 {
2928 0.03
2929}
2930
2931fn default_bad_debt_rate() -> f64 {
2932 0.01
2933}
2934
2935fn default_so_to_delivery_days() -> u32 {
2936 7
2937}
2938
2939fn default_delivery_to_invoice_days() -> u32 {
2940 1
2941}
2942
2943fn default_invoice_to_receipt_days() -> u32 {
2944 45
2945}
2946
2947impl Default for O2CFlowConfig {
2948 fn default() -> Self {
2949 Self {
2950 enabled: true,
2951 credit_check_failure_rate: default_credit_check_failure_rate(),
2952 partial_shipment_rate: default_partial_shipment_rate(),
2953 return_rate: default_return_rate(),
2954 bad_debt_rate: default_bad_debt_rate(),
2955 average_so_to_delivery_days: default_so_to_delivery_days(),
2956 average_delivery_to_invoice_days: default_delivery_to_invoice_days(),
2957 average_invoice_to_receipt_days: default_invoice_to_receipt_days(),
2958 line_count_distribution: DocumentLineCountDistribution::default(),
2959 cash_discount: CashDiscountConfig::default(),
2960 payment_behavior: O2CPaymentBehaviorConfig::default(),
2961 late_payment_rate: None,
2962 }
2963 }
2964}
2965
2966#[derive(Debug, Clone, Serialize, Deserialize, Default)]
2972pub struct O2CPaymentBehaviorConfig {
2973 #[serde(default)]
2975 pub dunning: DunningConfig,
2976 #[serde(default)]
2978 pub partial_payments: PartialPaymentConfig,
2979 #[serde(default)]
2981 pub short_payments: ShortPaymentConfig,
2982 #[serde(default)]
2984 pub on_account_payments: OnAccountPaymentConfig,
2985 #[serde(default)]
2987 pub payment_corrections: PaymentCorrectionConfig,
2988}
2989
2990#[derive(Debug, Clone, Serialize, Deserialize)]
2992pub struct DunningConfig {
2993 #[serde(default)]
2995 pub enabled: bool,
2996 #[serde(default = "default_dunning_level_1_days")]
2998 pub level_1_days_overdue: u32,
2999 #[serde(default = "default_dunning_level_2_days")]
3001 pub level_2_days_overdue: u32,
3002 #[serde(default = "default_dunning_level_3_days")]
3004 pub level_3_days_overdue: u32,
3005 #[serde(default = "default_collection_days")]
3007 pub collection_days_overdue: u32,
3008 #[serde(default)]
3010 pub payment_after_dunning_rates: DunningPaymentRates,
3011 #[serde(default = "default_dunning_block_rate")]
3013 pub dunning_block_rate: f64,
3014 #[serde(default = "default_dunning_interest_rate")]
3016 pub interest_rate_per_year: f64,
3017 #[serde(default = "default_dunning_charge")]
3019 pub dunning_charge: f64,
3020}
3021
3022fn default_dunning_level_1_days() -> u32 {
3023 14
3024}
3025
3026fn default_dunning_level_2_days() -> u32 {
3027 28
3028}
3029
3030fn default_dunning_level_3_days() -> u32 {
3031 42
3032}
3033
3034fn default_collection_days() -> u32 {
3035 60
3036}
3037
3038fn default_dunning_block_rate() -> f64 {
3039 0.05
3040}
3041
3042fn default_dunning_interest_rate() -> f64 {
3043 0.09
3044}
3045
3046fn default_dunning_charge() -> f64 {
3047 25.0
3048}
3049
3050impl Default for DunningConfig {
3051 fn default() -> Self {
3052 Self {
3053 enabled: false,
3054 level_1_days_overdue: default_dunning_level_1_days(),
3055 level_2_days_overdue: default_dunning_level_2_days(),
3056 level_3_days_overdue: default_dunning_level_3_days(),
3057 collection_days_overdue: default_collection_days(),
3058 payment_after_dunning_rates: DunningPaymentRates::default(),
3059 dunning_block_rate: default_dunning_block_rate(),
3060 interest_rate_per_year: default_dunning_interest_rate(),
3061 dunning_charge: default_dunning_charge(),
3062 }
3063 }
3064}
3065
3066#[derive(Debug, Clone, Serialize, Deserialize)]
3068pub struct DunningPaymentRates {
3069 #[serde(default = "default_after_level_1")]
3071 pub after_level_1: f64,
3072 #[serde(default = "default_after_level_2")]
3074 pub after_level_2: f64,
3075 #[serde(default = "default_after_level_3")]
3077 pub after_level_3: f64,
3078 #[serde(default = "default_during_collection")]
3080 pub during_collection: f64,
3081 #[serde(default = "default_never_pay")]
3083 pub never_pay: f64,
3084}
3085
3086fn default_after_level_1() -> f64 {
3087 0.40
3088}
3089
3090fn default_after_level_2() -> f64 {
3091 0.30
3092}
3093
3094fn default_after_level_3() -> f64 {
3095 0.15
3096}
3097
3098fn default_during_collection() -> f64 {
3099 0.05
3100}
3101
3102fn default_never_pay() -> f64 {
3103 0.10
3104}
3105
3106impl Default for DunningPaymentRates {
3107 fn default() -> Self {
3108 Self {
3109 after_level_1: default_after_level_1(),
3110 after_level_2: default_after_level_2(),
3111 after_level_3: default_after_level_3(),
3112 during_collection: default_during_collection(),
3113 never_pay: default_never_pay(),
3114 }
3115 }
3116}
3117
3118#[derive(Debug, Clone, Serialize, Deserialize)]
3120pub struct PartialPaymentConfig {
3121 #[serde(default = "default_partial_payment_rate")]
3123 pub rate: f64,
3124 #[serde(default)]
3126 pub percentage_distribution: PartialPaymentPercentageDistribution,
3127 #[serde(default = "default_avg_days_until_remainder")]
3129 pub avg_days_until_remainder: u32,
3130}
3131
3132fn default_partial_payment_rate() -> f64 {
3133 0.08
3134}
3135
3136fn default_avg_days_until_remainder() -> u32 {
3137 30
3138}
3139
3140impl Default for PartialPaymentConfig {
3141 fn default() -> Self {
3142 Self {
3143 rate: default_partial_payment_rate(),
3144 percentage_distribution: PartialPaymentPercentageDistribution::default(),
3145 avg_days_until_remainder: default_avg_days_until_remainder(),
3146 }
3147 }
3148}
3149
3150#[derive(Debug, Clone, Serialize, Deserialize)]
3152pub struct PartialPaymentPercentageDistribution {
3153 #[serde(default = "default_partial_25")]
3155 pub pay_25_percent: f64,
3156 #[serde(default = "default_partial_50")]
3158 pub pay_50_percent: f64,
3159 #[serde(default = "default_partial_75")]
3161 pub pay_75_percent: f64,
3162 #[serde(default = "default_partial_random")]
3164 pub pay_random_percent: f64,
3165}
3166
3167fn default_partial_25() -> f64 {
3168 0.15
3169}
3170
3171fn default_partial_50() -> f64 {
3172 0.50
3173}
3174
3175fn default_partial_75() -> f64 {
3176 0.25
3177}
3178
3179fn default_partial_random() -> f64 {
3180 0.10
3181}
3182
3183impl Default for PartialPaymentPercentageDistribution {
3184 fn default() -> Self {
3185 Self {
3186 pay_25_percent: default_partial_25(),
3187 pay_50_percent: default_partial_50(),
3188 pay_75_percent: default_partial_75(),
3189 pay_random_percent: default_partial_random(),
3190 }
3191 }
3192}
3193
3194#[derive(Debug, Clone, Serialize, Deserialize)]
3196pub struct ShortPaymentConfig {
3197 #[serde(default = "default_short_payment_rate")]
3199 pub rate: f64,
3200 #[serde(default)]
3202 pub reason_distribution: ShortPaymentReasonDistribution,
3203 #[serde(default = "default_max_short_percent")]
3205 pub max_short_percent: f64,
3206}
3207
3208fn default_short_payment_rate() -> f64 {
3209 0.03
3210}
3211
3212fn default_max_short_percent() -> f64 {
3213 0.10
3214}
3215
3216impl Default for ShortPaymentConfig {
3217 fn default() -> Self {
3218 Self {
3219 rate: default_short_payment_rate(),
3220 reason_distribution: ShortPaymentReasonDistribution::default(),
3221 max_short_percent: default_max_short_percent(),
3222 }
3223 }
3224}
3225
3226#[derive(Debug, Clone, Serialize, Deserialize)]
3228pub struct ShortPaymentReasonDistribution {
3229 #[serde(default = "default_pricing_dispute")]
3231 pub pricing_dispute: f64,
3232 #[serde(default = "default_quality_issue")]
3234 pub quality_issue: f64,
3235 #[serde(default = "default_quantity_discrepancy")]
3237 pub quantity_discrepancy: f64,
3238 #[serde(default = "default_unauthorized_deduction")]
3240 pub unauthorized_deduction: f64,
3241 #[serde(default = "default_incorrect_discount")]
3243 pub incorrect_discount: f64,
3244}
3245
3246fn default_pricing_dispute() -> f64 {
3247 0.30
3248}
3249
3250fn default_quality_issue() -> f64 {
3251 0.20
3252}
3253
3254fn default_quantity_discrepancy() -> f64 {
3255 0.20
3256}
3257
3258fn default_unauthorized_deduction() -> f64 {
3259 0.15
3260}
3261
3262fn default_incorrect_discount() -> f64 {
3263 0.15
3264}
3265
3266impl Default for ShortPaymentReasonDistribution {
3267 fn default() -> Self {
3268 Self {
3269 pricing_dispute: default_pricing_dispute(),
3270 quality_issue: default_quality_issue(),
3271 quantity_discrepancy: default_quantity_discrepancy(),
3272 unauthorized_deduction: default_unauthorized_deduction(),
3273 incorrect_discount: default_incorrect_discount(),
3274 }
3275 }
3276}
3277
3278#[derive(Debug, Clone, Serialize, Deserialize)]
3280pub struct OnAccountPaymentConfig {
3281 #[serde(default = "default_on_account_rate")]
3283 pub rate: f64,
3284 #[serde(default = "default_avg_days_until_applied")]
3286 pub avg_days_until_applied: u32,
3287}
3288
3289fn default_on_account_rate() -> f64 {
3290 0.02
3291}
3292
3293fn default_avg_days_until_applied() -> u32 {
3294 14
3295}
3296
3297impl Default for OnAccountPaymentConfig {
3298 fn default() -> Self {
3299 Self {
3300 rate: default_on_account_rate(),
3301 avg_days_until_applied: default_avg_days_until_applied(),
3302 }
3303 }
3304}
3305
3306#[derive(Debug, Clone, Serialize, Deserialize)]
3308pub struct PaymentCorrectionConfig {
3309 #[serde(default = "default_payment_correction_rate")]
3311 pub rate: f64,
3312 #[serde(default)]
3314 pub type_distribution: PaymentCorrectionTypeDistribution,
3315}
3316
3317fn default_payment_correction_rate() -> f64 {
3318 0.02
3319}
3320
3321impl Default for PaymentCorrectionConfig {
3322 fn default() -> Self {
3323 Self {
3324 rate: default_payment_correction_rate(),
3325 type_distribution: PaymentCorrectionTypeDistribution::default(),
3326 }
3327 }
3328}
3329
3330#[derive(Debug, Clone, Serialize, Deserialize)]
3332pub struct PaymentCorrectionTypeDistribution {
3333 #[serde(default = "default_nsf_rate")]
3335 pub nsf: f64,
3336 #[serde(default = "default_chargeback_rate")]
3338 pub chargeback: f64,
3339 #[serde(default = "default_wrong_amount_rate")]
3341 pub wrong_amount: f64,
3342 #[serde(default = "default_wrong_customer_rate")]
3344 pub wrong_customer: f64,
3345 #[serde(default = "default_duplicate_payment_rate")]
3347 pub duplicate_payment: f64,
3348}
3349
3350fn default_nsf_rate() -> f64 {
3351 0.30
3352}
3353
3354fn default_chargeback_rate() -> f64 {
3355 0.20
3356}
3357
3358fn default_wrong_amount_rate() -> f64 {
3359 0.20
3360}
3361
3362fn default_wrong_customer_rate() -> f64 {
3363 0.15
3364}
3365
3366fn default_duplicate_payment_rate() -> f64 {
3367 0.15
3368}
3369
3370impl Default for PaymentCorrectionTypeDistribution {
3371 fn default() -> Self {
3372 Self {
3373 nsf: default_nsf_rate(),
3374 chargeback: default_chargeback_rate(),
3375 wrong_amount: default_wrong_amount_rate(),
3376 wrong_customer: default_wrong_customer_rate(),
3377 duplicate_payment: default_duplicate_payment_rate(),
3378 }
3379 }
3380}
3381
3382#[derive(Debug, Clone, Serialize, Deserialize)]
3384pub struct DocumentLineCountDistribution {
3385 #[serde(default = "default_min_lines")]
3387 pub min_lines: u32,
3388 #[serde(default = "default_max_lines")]
3390 pub max_lines: u32,
3391 #[serde(default = "default_mode_lines")]
3393 pub mode_lines: u32,
3394}
3395
3396fn default_min_lines() -> u32 {
3397 1
3398}
3399
3400fn default_max_lines() -> u32 {
3401 20
3402}
3403
3404fn default_mode_lines() -> u32 {
3405 3
3406}
3407
3408impl Default for DocumentLineCountDistribution {
3409 fn default() -> Self {
3410 Self {
3411 min_lines: default_min_lines(),
3412 max_lines: default_max_lines(),
3413 mode_lines: default_mode_lines(),
3414 }
3415 }
3416}
3417
3418#[derive(Debug, Clone, Serialize, Deserialize)]
3420pub struct CashDiscountConfig {
3421 #[serde(default = "default_discount_eligible_rate")]
3423 pub eligible_rate: f64,
3424 #[serde(default = "default_discount_taken_rate")]
3426 pub taken_rate: f64,
3427 #[serde(default = "default_discount_percent")]
3429 pub discount_percent: f64,
3430 #[serde(default = "default_discount_days")]
3432 pub discount_days: u32,
3433}
3434
3435fn default_discount_eligible_rate() -> f64 {
3436 0.30
3437}
3438
3439fn default_discount_taken_rate() -> f64 {
3440 0.60
3441}
3442
3443fn default_discount_percent() -> f64 {
3444 0.02
3445}
3446
3447fn default_discount_days() -> u32 {
3448 10
3449}
3450
3451impl Default for CashDiscountConfig {
3452 fn default() -> Self {
3453 Self {
3454 eligible_rate: default_discount_eligible_rate(),
3455 taken_rate: default_discount_taken_rate(),
3456 discount_percent: default_discount_percent(),
3457 discount_days: default_discount_days(),
3458 }
3459 }
3460}
3461
3462#[derive(Debug, Clone, Serialize, Deserialize)]
3468pub struct IntercompanyConfig {
3469 #[serde(default)]
3471 pub enabled: bool,
3472 #[serde(default = "default_ic_transaction_rate")]
3474 pub ic_transaction_rate: f64,
3475 #[serde(default)]
3477 pub transfer_pricing_method: TransferPricingMethod,
3478 #[serde(default = "default_markup_percent")]
3480 pub markup_percent: f64,
3481 #[serde(default = "default_true")]
3483 pub generate_matched_pairs: bool,
3484 #[serde(default)]
3486 pub transaction_type_distribution: ICTransactionTypeDistribution,
3487 #[serde(default)]
3489 pub generate_eliminations: bool,
3490}
3491
3492fn default_ic_transaction_rate() -> f64 {
3493 0.15
3494}
3495
3496fn default_markup_percent() -> f64 {
3497 0.05
3498}
3499
3500impl Default for IntercompanyConfig {
3501 fn default() -> Self {
3502 Self {
3503 enabled: false,
3504 ic_transaction_rate: default_ic_transaction_rate(),
3505 transfer_pricing_method: TransferPricingMethod::default(),
3506 markup_percent: default_markup_percent(),
3507 generate_matched_pairs: true,
3508 transaction_type_distribution: ICTransactionTypeDistribution::default(),
3509 generate_eliminations: false,
3510 }
3511 }
3512}
3513
3514#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
3516#[serde(rename_all = "snake_case")]
3517pub enum TransferPricingMethod {
3518 #[default]
3520 CostPlus,
3521 ComparableUncontrolled,
3523 ResalePrice,
3525 TransactionalNetMargin,
3527 ProfitSplit,
3529}
3530
3531#[derive(Debug, Clone, Serialize, Deserialize)]
3533pub struct ICTransactionTypeDistribution {
3534 pub goods_sale: f64,
3536 pub service_provided: f64,
3538 pub loan: f64,
3540 pub dividend: f64,
3542 pub management_fee: f64,
3544 pub royalty: f64,
3546 pub cost_sharing: f64,
3548}
3549
3550impl Default for ICTransactionTypeDistribution {
3551 fn default() -> Self {
3552 Self {
3553 goods_sale: 0.35,
3554 service_provided: 0.20,
3555 loan: 0.10,
3556 dividend: 0.05,
3557 management_fee: 0.15,
3558 royalty: 0.10,
3559 cost_sharing: 0.05,
3560 }
3561 }
3562}
3563
3564#[derive(Debug, Clone, Serialize, Deserialize)]
3570pub struct BalanceConfig {
3571 #[serde(default)]
3573 pub generate_opening_balances: bool,
3574 #[serde(default = "default_true")]
3576 pub generate_trial_balances: bool,
3577 #[serde(default = "default_gross_margin")]
3579 pub target_gross_margin: f64,
3580 #[serde(default = "default_dso")]
3582 pub target_dso_days: u32,
3583 #[serde(default = "default_dpo")]
3585 pub target_dpo_days: u32,
3586 #[serde(default = "default_current_ratio")]
3588 pub target_current_ratio: f64,
3589 #[serde(default = "default_debt_equity")]
3591 pub target_debt_to_equity: f64,
3592 #[serde(default = "default_true")]
3594 pub validate_balance_equation: bool,
3595 #[serde(default = "default_true")]
3597 pub reconcile_subledgers: bool,
3598}
3599
3600fn default_gross_margin() -> f64 {
3601 0.35
3602}
3603
3604fn default_dso() -> u32 {
3605 45
3606}
3607
3608fn default_dpo() -> u32 {
3609 30
3610}
3611
3612fn default_current_ratio() -> f64 {
3613 1.5
3614}
3615
3616fn default_debt_equity() -> f64 {
3617 0.5
3618}
3619
3620impl Default for BalanceConfig {
3621 fn default() -> Self {
3622 Self {
3623 generate_opening_balances: false,
3624 generate_trial_balances: true,
3625 target_gross_margin: default_gross_margin(),
3626 target_dso_days: default_dso(),
3627 target_dpo_days: default_dpo(),
3628 target_current_ratio: default_current_ratio(),
3629 target_debt_to_equity: default_debt_equity(),
3630 validate_balance_equation: true,
3631 reconcile_subledgers: true,
3632 }
3633 }
3634}
3635
3636#[derive(Debug, Clone, Serialize, Deserialize)]
3645pub struct OcpmConfig {
3646 #[serde(default)]
3648 pub enabled: bool,
3649
3650 #[serde(default = "default_true")]
3652 pub generate_lifecycle_events: bool,
3653
3654 #[serde(default = "default_true")]
3656 pub include_object_relationships: bool,
3657
3658 #[serde(default = "default_true")]
3660 pub compute_variants: bool,
3661
3662 #[serde(default)]
3664 pub max_variants: usize,
3665
3666 #[serde(default)]
3668 pub p2p_process: OcpmProcessConfig,
3669
3670 #[serde(default)]
3672 pub o2c_process: OcpmProcessConfig,
3673
3674 #[serde(default)]
3676 pub output: OcpmOutputConfig,
3677}
3678
3679impl Default for OcpmConfig {
3680 fn default() -> Self {
3681 Self {
3682 enabled: false,
3683 generate_lifecycle_events: true,
3684 include_object_relationships: true,
3685 compute_variants: true,
3686 max_variants: 0,
3687 p2p_process: OcpmProcessConfig::default(),
3688 o2c_process: OcpmProcessConfig::default(),
3689 output: OcpmOutputConfig::default(),
3690 }
3691 }
3692}
3693
3694#[derive(Debug, Clone, Serialize, Deserialize)]
3696pub struct OcpmProcessConfig {
3697 #[serde(default = "default_rework_probability")]
3699 pub rework_probability: f64,
3700
3701 #[serde(default = "default_skip_probability")]
3703 pub skip_step_probability: f64,
3704
3705 #[serde(default = "default_out_of_order_probability")]
3707 pub out_of_order_probability: f64,
3708}
3709
3710fn default_rework_probability() -> f64 {
3711 0.05
3712}
3713
3714fn default_skip_probability() -> f64 {
3715 0.02
3716}
3717
3718fn default_out_of_order_probability() -> f64 {
3719 0.03
3720}
3721
3722impl Default for OcpmProcessConfig {
3723 fn default() -> Self {
3724 Self {
3725 rework_probability: default_rework_probability(),
3726 skip_step_probability: default_skip_probability(),
3727 out_of_order_probability: default_out_of_order_probability(),
3728 }
3729 }
3730}
3731
3732#[derive(Debug, Clone, Serialize, Deserialize)]
3734pub struct OcpmOutputConfig {
3735 #[serde(default = "default_true")]
3737 pub ocel_json: bool,
3738
3739 #[serde(default)]
3741 pub ocel_xml: bool,
3742
3743 #[serde(default)]
3745 pub xes: bool,
3746
3747 #[serde(default = "default_true")]
3749 pub xes_include_lifecycle: bool,
3750
3751 #[serde(default = "default_true")]
3753 pub xes_include_resources: bool,
3754
3755 #[serde(default = "default_true")]
3757 pub flattened_csv: bool,
3758
3759 #[serde(default = "default_true")]
3761 pub event_object_csv: bool,
3762
3763 #[serde(default = "default_true")]
3765 pub object_relationship_csv: bool,
3766
3767 #[serde(default = "default_true")]
3769 pub variants_csv: bool,
3770
3771 #[serde(default)]
3773 pub export_reference_models: bool,
3774}
3775
3776impl Default for OcpmOutputConfig {
3777 fn default() -> Self {
3778 Self {
3779 ocel_json: true,
3780 ocel_xml: false,
3781 xes: false,
3782 xes_include_lifecycle: true,
3783 xes_include_resources: true,
3784 flattened_csv: true,
3785 event_object_csv: true,
3786 object_relationship_csv: true,
3787 variants_csv: true,
3788 export_reference_models: false,
3789 }
3790 }
3791}
3792
3793#[derive(Debug, Clone, Serialize, Deserialize)]
3795pub struct AuditGenerationConfig {
3796 #[serde(default)]
3798 pub enabled: bool,
3799
3800 #[serde(default = "default_true")]
3803 pub generate_workpapers: bool,
3804
3805 #[serde(default)]
3808 pub engagement_types: AuditEngagementTypesConfig,
3809
3810 #[serde(default)]
3813 pub workpapers: WorkpaperConfig,
3814
3815 #[serde(default)]
3818 pub team: AuditTeamConfig,
3819
3820 #[serde(default)]
3823 pub review: ReviewWorkflowConfig,
3824}
3825
3826impl Default for AuditGenerationConfig {
3827 fn default() -> Self {
3828 Self {
3829 enabled: false,
3830 generate_workpapers: true,
3831 engagement_types: AuditEngagementTypesConfig::default(),
3832 workpapers: WorkpaperConfig::default(),
3833 team: AuditTeamConfig::default(),
3834 review: ReviewWorkflowConfig::default(),
3835 }
3836 }
3837}
3838
3839#[derive(Debug, Clone, Serialize, Deserialize)]
3841pub struct AuditEngagementTypesConfig {
3842 #[serde(default = "default_financial_audit_prob")]
3844 pub financial_statement: f64,
3845 #[serde(default = "default_sox_audit_prob")]
3847 pub sox_icfr: f64,
3848 #[serde(default = "default_integrated_audit_prob")]
3850 pub integrated: f64,
3851 #[serde(default = "default_review_prob")]
3853 pub review: f64,
3854 #[serde(default = "default_aup_prob")]
3856 pub agreed_upon_procedures: f64,
3857}
3858
3859fn default_financial_audit_prob() -> f64 {
3860 0.40
3861}
3862fn default_sox_audit_prob() -> f64 {
3863 0.20
3864}
3865fn default_integrated_audit_prob() -> f64 {
3866 0.25
3867}
3868fn default_review_prob() -> f64 {
3869 0.10
3870}
3871fn default_aup_prob() -> f64 {
3872 0.05
3873}
3874
3875impl Default for AuditEngagementTypesConfig {
3876 fn default() -> Self {
3877 Self {
3878 financial_statement: default_financial_audit_prob(),
3879 sox_icfr: default_sox_audit_prob(),
3880 integrated: default_integrated_audit_prob(),
3881 review: default_review_prob(),
3882 agreed_upon_procedures: default_aup_prob(),
3883 }
3884 }
3885}
3886
3887#[derive(Debug, Clone, Serialize, Deserialize)]
3889pub struct WorkpaperConfig {
3890 #[serde(default = "default_workpapers_per_phase")]
3892 pub average_per_phase: usize,
3893
3894 #[serde(default = "default_true")]
3896 pub include_isa_references: bool,
3897
3898 #[serde(default = "default_true")]
3900 pub include_sample_details: bool,
3901
3902 #[serde(default = "default_true")]
3904 pub include_cross_references: bool,
3905
3906 #[serde(default)]
3908 pub sampling: SamplingConfig,
3909}
3910
3911fn default_workpapers_per_phase() -> usize {
3912 5
3913}
3914
3915impl Default for WorkpaperConfig {
3916 fn default() -> Self {
3917 Self {
3918 average_per_phase: default_workpapers_per_phase(),
3919 include_isa_references: true,
3920 include_sample_details: true,
3921 include_cross_references: true,
3922 sampling: SamplingConfig::default(),
3923 }
3924 }
3925}
3926
3927#[derive(Debug, Clone, Serialize, Deserialize)]
3929pub struct SamplingConfig {
3930 #[serde(default = "default_statistical_rate")]
3932 pub statistical_rate: f64,
3933 #[serde(default = "default_judgmental_rate")]
3935 pub judgmental_rate: f64,
3936 #[serde(default = "default_haphazard_rate")]
3938 pub haphazard_rate: f64,
3939 #[serde(default = "default_complete_examination_rate")]
3941 pub complete_examination_rate: f64,
3942}
3943
3944fn default_statistical_rate() -> f64 {
3945 0.40
3946}
3947fn default_judgmental_rate() -> f64 {
3948 0.30
3949}
3950fn default_haphazard_rate() -> f64 {
3951 0.20
3952}
3953fn default_complete_examination_rate() -> f64 {
3954 0.10
3955}
3956
3957impl Default for SamplingConfig {
3958 fn default() -> Self {
3959 Self {
3960 statistical_rate: default_statistical_rate(),
3961 judgmental_rate: default_judgmental_rate(),
3962 haphazard_rate: default_haphazard_rate(),
3963 complete_examination_rate: default_complete_examination_rate(),
3964 }
3965 }
3966}
3967
3968#[derive(Debug, Clone, Serialize, Deserialize)]
3970pub struct AuditTeamConfig {
3971 #[serde(default = "default_min_team_size")]
3973 pub min_team_size: usize,
3974 #[serde(default = "default_max_team_size")]
3976 pub max_team_size: usize,
3977 #[serde(default = "default_specialist_probability")]
3979 pub specialist_probability: f64,
3980}
3981
3982fn default_min_team_size() -> usize {
3983 3
3984}
3985fn default_max_team_size() -> usize {
3986 8
3987}
3988fn default_specialist_probability() -> f64 {
3989 0.30
3990}
3991
3992impl Default for AuditTeamConfig {
3993 fn default() -> Self {
3994 Self {
3995 min_team_size: default_min_team_size(),
3996 max_team_size: default_max_team_size(),
3997 specialist_probability: default_specialist_probability(),
3998 }
3999 }
4000}
4001
4002#[derive(Debug, Clone, Serialize, Deserialize)]
4004pub struct ReviewWorkflowConfig {
4005 #[serde(default = "default_review_delay_days")]
4007 pub average_review_delay_days: u32,
4008 #[serde(default = "default_rework_probability_review")]
4010 pub rework_probability: f64,
4011 #[serde(default = "default_true")]
4013 pub require_partner_signoff: bool,
4014}
4015
4016fn default_review_delay_days() -> u32 {
4017 2
4018}
4019fn default_rework_probability_review() -> f64 {
4020 0.15
4021}
4022
4023impl Default for ReviewWorkflowConfig {
4024 fn default() -> Self {
4025 Self {
4026 average_review_delay_days: default_review_delay_days(),
4027 rework_probability: default_rework_probability_review(),
4028 require_partner_signoff: true,
4029 }
4030 }
4031}
4032
4033#[derive(Debug, Clone, Serialize, Deserialize)]
4039pub struct DataQualitySchemaConfig {
4040 #[serde(default)]
4042 pub enabled: bool,
4043 #[serde(default)]
4045 pub preset: DataQualityPreset,
4046 #[serde(default)]
4048 pub missing_values: MissingValuesSchemaConfig,
4049 #[serde(default)]
4051 pub typos: TypoSchemaConfig,
4052 #[serde(default)]
4054 pub format_variations: FormatVariationSchemaConfig,
4055 #[serde(default)]
4057 pub duplicates: DuplicateSchemaConfig,
4058 #[serde(default)]
4060 pub encoding_issues: EncodingIssueSchemaConfig,
4061 #[serde(default)]
4063 pub generate_labels: bool,
4064 #[serde(default)]
4066 pub sink_profiles: SinkQualityProfiles,
4067}
4068
4069impl Default for DataQualitySchemaConfig {
4070 fn default() -> Self {
4071 Self {
4072 enabled: false,
4073 preset: DataQualityPreset::None,
4074 missing_values: MissingValuesSchemaConfig::default(),
4075 typos: TypoSchemaConfig::default(),
4076 format_variations: FormatVariationSchemaConfig::default(),
4077 duplicates: DuplicateSchemaConfig::default(),
4078 encoding_issues: EncodingIssueSchemaConfig::default(),
4079 generate_labels: true,
4080 sink_profiles: SinkQualityProfiles::default(),
4081 }
4082 }
4083}
4084
4085impl DataQualitySchemaConfig {
4086 pub fn with_preset(preset: DataQualityPreset) -> Self {
4088 let mut config = Self {
4089 preset,
4090 ..Default::default()
4091 };
4092 config.apply_preset();
4093 config
4094 }
4095
4096 pub fn apply_preset(&mut self) {
4099 if !self.preset.overrides_settings() {
4100 return;
4101 }
4102
4103 self.enabled = true;
4104
4105 self.missing_values.enabled = self.preset.missing_rate() > 0.0;
4107 self.missing_values.rate = self.preset.missing_rate();
4108
4109 self.typos.enabled = self.preset.typo_rate() > 0.0;
4111 self.typos.char_error_rate = self.preset.typo_rate();
4112
4113 self.duplicates.enabled = self.preset.duplicate_rate() > 0.0;
4115 self.duplicates.exact_duplicate_ratio = self.preset.duplicate_rate() * 0.4;
4116 self.duplicates.near_duplicate_ratio = self.preset.duplicate_rate() * 0.4;
4117 self.duplicates.fuzzy_duplicate_ratio = self.preset.duplicate_rate() * 0.2;
4118
4119 self.format_variations.enabled = self.preset.format_variations_enabled();
4121
4122 self.encoding_issues.enabled = self.preset.encoding_issues_enabled();
4124 self.encoding_issues.rate = self.preset.encoding_issue_rate();
4125
4126 if self.preset.ocr_errors_enabled() {
4128 self.typos.type_weights.ocr_errors = 0.3;
4129 }
4130 }
4131
4132 pub fn effective_missing_rate(&self) -> f64 {
4134 if self.preset.overrides_settings() {
4135 self.preset.missing_rate()
4136 } else {
4137 self.missing_values.rate
4138 }
4139 }
4140
4141 pub fn effective_typo_rate(&self) -> f64 {
4143 if self.preset.overrides_settings() {
4144 self.preset.typo_rate()
4145 } else {
4146 self.typos.char_error_rate
4147 }
4148 }
4149
4150 pub fn effective_duplicate_rate(&self) -> f64 {
4152 if self.preset.overrides_settings() {
4153 self.preset.duplicate_rate()
4154 } else {
4155 self.duplicates.exact_duplicate_ratio
4156 + self.duplicates.near_duplicate_ratio
4157 + self.duplicates.fuzzy_duplicate_ratio
4158 }
4159 }
4160
4161 pub fn clean() -> Self {
4163 Self::with_preset(DataQualityPreset::Clean)
4164 }
4165
4166 pub fn noisy() -> Self {
4168 Self::with_preset(DataQualityPreset::Noisy)
4169 }
4170
4171 pub fn legacy() -> Self {
4173 Self::with_preset(DataQualityPreset::Legacy)
4174 }
4175}
4176
4177#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
4179#[serde(rename_all = "snake_case")]
4180pub enum DataQualityPreset {
4181 #[default]
4183 None,
4184 Minimal,
4186 Normal,
4188 High,
4190 Custom,
4192
4193 Clean,
4199 Noisy,
4202 Legacy,
4205}
4206
4207impl DataQualityPreset {
4208 pub fn missing_rate(&self) -> f64 {
4210 match self {
4211 DataQualityPreset::None => 0.0,
4212 DataQualityPreset::Minimal => 0.005,
4213 DataQualityPreset::Normal => 0.02,
4214 DataQualityPreset::High => 0.08,
4215 DataQualityPreset::Custom => 0.01, DataQualityPreset::Clean => 0.001,
4217 DataQualityPreset::Noisy => 0.05,
4218 DataQualityPreset::Legacy => 0.10,
4219 }
4220 }
4221
4222 pub fn typo_rate(&self) -> f64 {
4224 match self {
4225 DataQualityPreset::None => 0.0,
4226 DataQualityPreset::Minimal => 0.0005,
4227 DataQualityPreset::Normal => 0.002,
4228 DataQualityPreset::High => 0.01,
4229 DataQualityPreset::Custom => 0.001, DataQualityPreset::Clean => 0.0005,
4231 DataQualityPreset::Noisy => 0.02,
4232 DataQualityPreset::Legacy => 0.05,
4233 }
4234 }
4235
4236 pub fn duplicate_rate(&self) -> f64 {
4238 match self {
4239 DataQualityPreset::None => 0.0,
4240 DataQualityPreset::Minimal => 0.001,
4241 DataQualityPreset::Normal => 0.005,
4242 DataQualityPreset::High => 0.02,
4243 DataQualityPreset::Custom => 0.0, DataQualityPreset::Clean => 0.0,
4245 DataQualityPreset::Noisy => 0.01,
4246 DataQualityPreset::Legacy => 0.03,
4247 }
4248 }
4249
4250 pub fn format_variations_enabled(&self) -> bool {
4252 match self {
4253 DataQualityPreset::None | DataQualityPreset::Clean => false,
4254 DataQualityPreset::Minimal => true,
4255 DataQualityPreset::Normal => true,
4256 DataQualityPreset::High => true,
4257 DataQualityPreset::Custom => true,
4258 DataQualityPreset::Noisy => true,
4259 DataQualityPreset::Legacy => true,
4260 }
4261 }
4262
4263 pub fn ocr_errors_enabled(&self) -> bool {
4265 matches!(self, DataQualityPreset::Legacy | DataQualityPreset::High)
4266 }
4267
4268 pub fn encoding_issues_enabled(&self) -> bool {
4270 matches!(
4271 self,
4272 DataQualityPreset::Legacy | DataQualityPreset::High | DataQualityPreset::Noisy
4273 )
4274 }
4275
4276 pub fn encoding_issue_rate(&self) -> f64 {
4278 match self {
4279 DataQualityPreset::None | DataQualityPreset::Clean | DataQualityPreset::Minimal => 0.0,
4280 DataQualityPreset::Normal => 0.002,
4281 DataQualityPreset::High => 0.01,
4282 DataQualityPreset::Custom => 0.0,
4283 DataQualityPreset::Noisy => 0.005,
4284 DataQualityPreset::Legacy => 0.02,
4285 }
4286 }
4287
4288 pub fn overrides_settings(&self) -> bool {
4290 !matches!(self, DataQualityPreset::Custom | DataQualityPreset::None)
4291 }
4292
4293 pub fn description(&self) -> &'static str {
4295 match self {
4296 DataQualityPreset::None => "No data quality issues (pristine data)",
4297 DataQualityPreset::Minimal => "Very rare data quality issues",
4298 DataQualityPreset::Normal => "Realistic enterprise data quality",
4299 DataQualityPreset::High => "Messy data for stress testing",
4300 DataQualityPreset::Custom => "Custom settings from configuration",
4301 DataQualityPreset::Clean => "ML-ready clean data with minimal issues",
4302 DataQualityPreset::Noisy => "Typical production data with moderate issues",
4303 DataQualityPreset::Legacy => "Legacy/migrated data with heavy issues and OCR errors",
4304 }
4305 }
4306}
4307
4308#[derive(Debug, Clone, Serialize, Deserialize)]
4310pub struct MissingValuesSchemaConfig {
4311 #[serde(default)]
4313 pub enabled: bool,
4314 #[serde(default = "default_missing_rate")]
4316 pub rate: f64,
4317 #[serde(default)]
4319 pub strategy: MissingValueStrategy,
4320 #[serde(default)]
4322 pub field_rates: std::collections::HashMap<String, f64>,
4323 #[serde(default)]
4325 pub protected_fields: Vec<String>,
4326}
4327
4328fn default_missing_rate() -> f64 {
4329 0.01
4330}
4331
4332impl Default for MissingValuesSchemaConfig {
4333 fn default() -> Self {
4334 Self {
4335 enabled: false,
4336 rate: default_missing_rate(),
4337 strategy: MissingValueStrategy::Mcar,
4338 field_rates: std::collections::HashMap::new(),
4339 protected_fields: vec![
4340 "document_id".to_string(),
4341 "company_code".to_string(),
4342 "posting_date".to_string(),
4343 ],
4344 }
4345 }
4346}
4347
4348#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
4350#[serde(rename_all = "snake_case")]
4351pub enum MissingValueStrategy {
4352 #[default]
4354 Mcar,
4355 Mar,
4357 Mnar,
4359 Systematic,
4361}
4362
4363#[derive(Debug, Clone, Serialize, Deserialize)]
4365pub struct TypoSchemaConfig {
4366 #[serde(default)]
4368 pub enabled: bool,
4369 #[serde(default = "default_typo_rate")]
4371 pub char_error_rate: f64,
4372 #[serde(default)]
4374 pub type_weights: TypoTypeWeights,
4375 #[serde(default)]
4377 pub protected_fields: Vec<String>,
4378}
4379
4380fn default_typo_rate() -> f64 {
4381 0.001
4382}
4383
4384impl Default for TypoSchemaConfig {
4385 fn default() -> Self {
4386 Self {
4387 enabled: false,
4388 char_error_rate: default_typo_rate(),
4389 type_weights: TypoTypeWeights::default(),
4390 protected_fields: vec![
4391 "document_id".to_string(),
4392 "gl_account".to_string(),
4393 "company_code".to_string(),
4394 ],
4395 }
4396 }
4397}
4398
4399#[derive(Debug, Clone, Serialize, Deserialize)]
4401pub struct TypoTypeWeights {
4402 #[serde(default = "default_substitution_weight")]
4404 pub substitution: f64,
4405 #[serde(default = "default_transposition_weight")]
4407 pub transposition: f64,
4408 #[serde(default = "default_insertion_weight")]
4410 pub insertion: f64,
4411 #[serde(default = "default_deletion_weight")]
4413 pub deletion: f64,
4414 #[serde(default = "default_ocr_weight")]
4416 pub ocr_errors: f64,
4417 #[serde(default = "default_homophone_weight")]
4419 pub homophones: f64,
4420}
4421
4422fn default_substitution_weight() -> f64 {
4423 0.35
4424}
4425fn default_transposition_weight() -> f64 {
4426 0.25
4427}
4428fn default_insertion_weight() -> f64 {
4429 0.10
4430}
4431fn default_deletion_weight() -> f64 {
4432 0.15
4433}
4434fn default_ocr_weight() -> f64 {
4435 0.10
4436}
4437fn default_homophone_weight() -> f64 {
4438 0.05
4439}
4440
4441impl Default for TypoTypeWeights {
4442 fn default() -> Self {
4443 Self {
4444 substitution: default_substitution_weight(),
4445 transposition: default_transposition_weight(),
4446 insertion: default_insertion_weight(),
4447 deletion: default_deletion_weight(),
4448 ocr_errors: default_ocr_weight(),
4449 homophones: default_homophone_weight(),
4450 }
4451 }
4452}
4453
4454#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4456pub struct FormatVariationSchemaConfig {
4457 #[serde(default)]
4459 pub enabled: bool,
4460 #[serde(default)]
4462 pub dates: DateFormatVariationConfig,
4463 #[serde(default)]
4465 pub amounts: AmountFormatVariationConfig,
4466 #[serde(default)]
4468 pub identifiers: IdentifierFormatVariationConfig,
4469}
4470
4471#[derive(Debug, Clone, Serialize, Deserialize)]
4473pub struct DateFormatVariationConfig {
4474 #[serde(default)]
4476 pub enabled: bool,
4477 #[serde(default = "default_date_variation_rate")]
4479 pub rate: f64,
4480 #[serde(default = "default_true")]
4482 pub iso_format: bool,
4483 #[serde(default)]
4485 pub us_format: bool,
4486 #[serde(default)]
4488 pub eu_format: bool,
4489 #[serde(default)]
4491 pub long_format: bool,
4492}
4493
4494fn default_date_variation_rate() -> f64 {
4495 0.05
4496}
4497
4498impl Default for DateFormatVariationConfig {
4499 fn default() -> Self {
4500 Self {
4501 enabled: false,
4502 rate: default_date_variation_rate(),
4503 iso_format: true,
4504 us_format: false,
4505 eu_format: false,
4506 long_format: false,
4507 }
4508 }
4509}
4510
4511#[derive(Debug, Clone, Serialize, Deserialize)]
4513pub struct AmountFormatVariationConfig {
4514 #[serde(default)]
4516 pub enabled: bool,
4517 #[serde(default = "default_amount_variation_rate")]
4519 pub rate: f64,
4520 #[serde(default)]
4522 pub us_comma_format: bool,
4523 #[serde(default)]
4525 pub eu_format: bool,
4526 #[serde(default)]
4528 pub currency_prefix: bool,
4529 #[serde(default)]
4531 pub accounting_format: bool,
4532}
4533
4534fn default_amount_variation_rate() -> f64 {
4535 0.02
4536}
4537
4538impl Default for AmountFormatVariationConfig {
4539 fn default() -> Self {
4540 Self {
4541 enabled: false,
4542 rate: default_amount_variation_rate(),
4543 us_comma_format: false,
4544 eu_format: false,
4545 currency_prefix: false,
4546 accounting_format: false,
4547 }
4548 }
4549}
4550
4551#[derive(Debug, Clone, Serialize, Deserialize)]
4553pub struct IdentifierFormatVariationConfig {
4554 #[serde(default)]
4556 pub enabled: bool,
4557 #[serde(default = "default_identifier_variation_rate")]
4559 pub rate: f64,
4560 #[serde(default)]
4562 pub case_variations: bool,
4563 #[serde(default)]
4565 pub padding_variations: bool,
4566 #[serde(default)]
4568 pub separator_variations: bool,
4569}
4570
4571fn default_identifier_variation_rate() -> f64 {
4572 0.02
4573}
4574
4575impl Default for IdentifierFormatVariationConfig {
4576 fn default() -> Self {
4577 Self {
4578 enabled: false,
4579 rate: default_identifier_variation_rate(),
4580 case_variations: false,
4581 padding_variations: false,
4582 separator_variations: false,
4583 }
4584 }
4585}
4586
4587#[derive(Debug, Clone, Serialize, Deserialize)]
4589pub struct DuplicateSchemaConfig {
4590 #[serde(default)]
4592 pub enabled: bool,
4593 #[serde(default = "default_duplicate_rate")]
4595 pub rate: f64,
4596 #[serde(default = "default_exact_duplicate_ratio")]
4598 pub exact_duplicate_ratio: f64,
4599 #[serde(default = "default_near_duplicate_ratio")]
4601 pub near_duplicate_ratio: f64,
4602 #[serde(default = "default_fuzzy_duplicate_ratio")]
4604 pub fuzzy_duplicate_ratio: f64,
4605 #[serde(default = "default_max_date_offset")]
4607 pub max_date_offset_days: u32,
4608 #[serde(default = "default_max_amount_variance")]
4610 pub max_amount_variance: f64,
4611}
4612
4613fn default_duplicate_rate() -> f64 {
4614 0.005
4615}
4616fn default_exact_duplicate_ratio() -> f64 {
4617 0.4
4618}
4619fn default_near_duplicate_ratio() -> f64 {
4620 0.35
4621}
4622fn default_fuzzy_duplicate_ratio() -> f64 {
4623 0.25
4624}
4625fn default_max_date_offset() -> u32 {
4626 3
4627}
4628fn default_max_amount_variance() -> f64 {
4629 0.01
4630}
4631
4632impl Default for DuplicateSchemaConfig {
4633 fn default() -> Self {
4634 Self {
4635 enabled: false,
4636 rate: default_duplicate_rate(),
4637 exact_duplicate_ratio: default_exact_duplicate_ratio(),
4638 near_duplicate_ratio: default_near_duplicate_ratio(),
4639 fuzzy_duplicate_ratio: default_fuzzy_duplicate_ratio(),
4640 max_date_offset_days: default_max_date_offset(),
4641 max_amount_variance: default_max_amount_variance(),
4642 }
4643 }
4644}
4645
4646#[derive(Debug, Clone, Serialize, Deserialize)]
4648pub struct EncodingIssueSchemaConfig {
4649 #[serde(default)]
4651 pub enabled: bool,
4652 #[serde(default = "default_encoding_rate")]
4654 pub rate: f64,
4655 #[serde(default)]
4657 pub mojibake: bool,
4658 #[serde(default)]
4660 pub html_entities: bool,
4661 #[serde(default)]
4663 pub bom_issues: bool,
4664}
4665
4666fn default_encoding_rate() -> f64 {
4667 0.001
4668}
4669
4670impl Default for EncodingIssueSchemaConfig {
4671 fn default() -> Self {
4672 Self {
4673 enabled: false,
4674 rate: default_encoding_rate(),
4675 mojibake: false,
4676 html_entities: false,
4677 bom_issues: false,
4678 }
4679 }
4680}
4681
4682#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4684pub struct SinkQualityProfiles {
4685 #[serde(default)]
4687 pub csv: Option<SinkQualityOverride>,
4688 #[serde(default)]
4690 pub json: Option<SinkQualityOverride>,
4691 #[serde(default)]
4693 pub parquet: Option<SinkQualityOverride>,
4694}
4695
4696#[derive(Debug, Clone, Serialize, Deserialize)]
4698pub struct SinkQualityOverride {
4699 pub enabled: Option<bool>,
4701 pub missing_rate: Option<f64>,
4703 pub typo_rate: Option<f64>,
4705 pub format_variation_rate: Option<f64>,
4707 pub duplicate_rate: Option<f64>,
4709}
4710
4711#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4723pub struct AccountingStandardsConfig {
4724 #[serde(default)]
4726 pub enabled: bool,
4727
4728 #[serde(default, skip_serializing_if = "Option::is_none")]
4732 pub framework: Option<AccountingFrameworkConfig>,
4733
4734 #[serde(default)]
4736 pub revenue_recognition: RevenueRecognitionConfig,
4737
4738 #[serde(default)]
4740 pub leases: LeaseAccountingConfig,
4741
4742 #[serde(default)]
4744 pub fair_value: FairValueConfig,
4745
4746 #[serde(default)]
4748 pub impairment: ImpairmentConfig,
4749
4750 #[serde(default)]
4752 pub business_combinations: BusinessCombinationsConfig,
4753
4754 #[serde(default)]
4756 pub expected_credit_loss: EclConfig,
4757
4758 #[serde(default)]
4760 pub generate_differences: bool,
4761}
4762
4763#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
4765#[serde(rename_all = "snake_case")]
4766pub enum AccountingFrameworkConfig {
4767 #[default]
4769 UsGaap,
4770 Ifrs,
4772 DualReporting,
4774 FrenchGaap,
4776 GermanGaap,
4778}
4779
4780#[derive(Debug, Clone, Serialize, Deserialize)]
4782pub struct RevenueRecognitionConfig {
4783 #[serde(default)]
4785 pub enabled: bool,
4786
4787 #[serde(default = "default_true")]
4789 pub generate_contracts: bool,
4790
4791 #[serde(default = "default_avg_obligations")]
4793 pub avg_obligations_per_contract: f64,
4794
4795 #[serde(default = "default_variable_consideration_rate")]
4797 pub variable_consideration_rate: f64,
4798
4799 #[serde(default = "default_over_time_rate")]
4801 pub over_time_recognition_rate: f64,
4802
4803 #[serde(default = "default_contract_count")]
4805 pub contract_count: usize,
4806}
4807
4808fn default_avg_obligations() -> f64 {
4809 2.0
4810}
4811
4812fn default_variable_consideration_rate() -> f64 {
4813 0.15
4814}
4815
4816fn default_over_time_rate() -> f64 {
4817 0.30
4818}
4819
4820fn default_contract_count() -> usize {
4821 100
4822}
4823
4824impl Default for RevenueRecognitionConfig {
4825 fn default() -> Self {
4826 Self {
4827 enabled: false,
4828 generate_contracts: true,
4829 avg_obligations_per_contract: default_avg_obligations(),
4830 variable_consideration_rate: default_variable_consideration_rate(),
4831 over_time_recognition_rate: default_over_time_rate(),
4832 contract_count: default_contract_count(),
4833 }
4834 }
4835}
4836
4837#[derive(Debug, Clone, Serialize, Deserialize)]
4839pub struct LeaseAccountingConfig {
4840 #[serde(default)]
4842 pub enabled: bool,
4843
4844 #[serde(default = "default_lease_count")]
4846 pub lease_count: usize,
4847
4848 #[serde(default = "default_finance_lease_pct")]
4850 pub finance_lease_percent: f64,
4851
4852 #[serde(default = "default_avg_lease_term")]
4854 pub avg_lease_term_months: u32,
4855
4856 #[serde(default = "default_true")]
4858 pub generate_amortization: bool,
4859
4860 #[serde(default = "default_real_estate_pct")]
4862 pub real_estate_percent: f64,
4863}
4864
4865fn default_lease_count() -> usize {
4866 50
4867}
4868
4869fn default_finance_lease_pct() -> f64 {
4870 0.30
4871}
4872
4873fn default_avg_lease_term() -> u32 {
4874 60
4875}
4876
4877fn default_real_estate_pct() -> f64 {
4878 0.40
4879}
4880
4881impl Default for LeaseAccountingConfig {
4882 fn default() -> Self {
4883 Self {
4884 enabled: false,
4885 lease_count: default_lease_count(),
4886 finance_lease_percent: default_finance_lease_pct(),
4887 avg_lease_term_months: default_avg_lease_term(),
4888 generate_amortization: true,
4889 real_estate_percent: default_real_estate_pct(),
4890 }
4891 }
4892}
4893
4894#[derive(Debug, Clone, Serialize, Deserialize)]
4896pub struct FairValueConfig {
4897 #[serde(default)]
4899 pub enabled: bool,
4900
4901 #[serde(default = "default_fv_count")]
4903 pub measurement_count: usize,
4904
4905 #[serde(default = "default_level1_pct")]
4907 pub level1_percent: f64,
4908
4909 #[serde(default = "default_level2_pct")]
4911 pub level2_percent: f64,
4912
4913 #[serde(default = "default_level3_pct")]
4915 pub level3_percent: f64,
4916
4917 #[serde(default)]
4919 pub include_sensitivity_analysis: bool,
4920}
4921
4922fn default_fv_count() -> usize {
4923 25
4924}
4925
4926fn default_level1_pct() -> f64 {
4927 0.40
4928}
4929
4930fn default_level2_pct() -> f64 {
4931 0.35
4932}
4933
4934fn default_level3_pct() -> f64 {
4935 0.25
4936}
4937
4938impl Default for FairValueConfig {
4939 fn default() -> Self {
4940 Self {
4941 enabled: false,
4942 measurement_count: default_fv_count(),
4943 level1_percent: default_level1_pct(),
4944 level2_percent: default_level2_pct(),
4945 level3_percent: default_level3_pct(),
4946 include_sensitivity_analysis: false,
4947 }
4948 }
4949}
4950
4951#[derive(Debug, Clone, Serialize, Deserialize)]
4953pub struct ImpairmentConfig {
4954 #[serde(default)]
4956 pub enabled: bool,
4957
4958 #[serde(default = "default_impairment_count")]
4960 pub test_count: usize,
4961
4962 #[serde(default = "default_impairment_rate")]
4964 pub impairment_rate: f64,
4965
4966 #[serde(default = "default_true")]
4968 pub generate_projections: bool,
4969
4970 #[serde(default)]
4972 pub include_goodwill: bool,
4973}
4974
4975fn default_impairment_count() -> usize {
4976 15
4977}
4978
4979fn default_impairment_rate() -> f64 {
4980 0.10
4981}
4982
4983impl Default for ImpairmentConfig {
4984 fn default() -> Self {
4985 Self {
4986 enabled: false,
4987 test_count: default_impairment_count(),
4988 impairment_rate: default_impairment_rate(),
4989 generate_projections: true,
4990 include_goodwill: false,
4991 }
4992 }
4993}
4994
4995#[derive(Debug, Clone, Serialize, Deserialize)]
5001pub struct BusinessCombinationsConfig {
5002 #[serde(default)]
5004 pub enabled: bool,
5005
5006 #[serde(default = "default_bc_acquisition_count")]
5008 pub acquisition_count: usize,
5009}
5010
5011fn default_bc_acquisition_count() -> usize {
5012 2
5013}
5014
5015impl Default for BusinessCombinationsConfig {
5016 fn default() -> Self {
5017 Self {
5018 enabled: false,
5019 acquisition_count: default_bc_acquisition_count(),
5020 }
5021 }
5022}
5023
5024#[derive(Debug, Clone, Serialize, Deserialize)]
5030pub struct EclConfig {
5031 #[serde(default)]
5033 pub enabled: bool,
5034
5035 #[serde(default = "default_ecl_base_weight")]
5037 pub base_scenario_weight: f64,
5038
5039 #[serde(default = "default_ecl_base_multiplier")]
5041 pub base_scenario_multiplier: f64,
5042
5043 #[serde(default = "default_ecl_optimistic_weight")]
5045 pub optimistic_scenario_weight: f64,
5046
5047 #[serde(default = "default_ecl_optimistic_multiplier")]
5049 pub optimistic_scenario_multiplier: f64,
5050
5051 #[serde(default = "default_ecl_pessimistic_weight")]
5053 pub pessimistic_scenario_weight: f64,
5054
5055 #[serde(default = "default_ecl_pessimistic_multiplier")]
5057 pub pessimistic_scenario_multiplier: f64,
5058}
5059
5060fn default_ecl_base_weight() -> f64 {
5061 0.50
5062}
5063fn default_ecl_base_multiplier() -> f64 {
5064 1.0
5065}
5066fn default_ecl_optimistic_weight() -> f64 {
5067 0.30
5068}
5069fn default_ecl_optimistic_multiplier() -> f64 {
5070 0.8
5071}
5072fn default_ecl_pessimistic_weight() -> f64 {
5073 0.20
5074}
5075fn default_ecl_pessimistic_multiplier() -> f64 {
5076 1.4
5077}
5078
5079impl Default for EclConfig {
5080 fn default() -> Self {
5081 Self {
5082 enabled: false,
5083 base_scenario_weight: default_ecl_base_weight(),
5084 base_scenario_multiplier: default_ecl_base_multiplier(),
5085 optimistic_scenario_weight: default_ecl_optimistic_weight(),
5086 optimistic_scenario_multiplier: default_ecl_optimistic_multiplier(),
5087 pessimistic_scenario_weight: default_ecl_pessimistic_weight(),
5088 pessimistic_scenario_multiplier: default_ecl_pessimistic_multiplier(),
5089 }
5090 }
5091}
5092
5093#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5106pub struct AuditStandardsConfig {
5107 #[serde(default)]
5109 pub enabled: bool,
5110
5111 #[serde(default)]
5113 pub isa_compliance: IsaComplianceConfig,
5114
5115 #[serde(default)]
5117 pub analytical_procedures: AnalyticalProceduresConfig,
5118
5119 #[serde(default)]
5121 pub confirmations: ConfirmationsConfig,
5122
5123 #[serde(default)]
5125 pub opinion: AuditOpinionConfig,
5126
5127 #[serde(default)]
5129 pub generate_audit_trail: bool,
5130
5131 #[serde(default)]
5133 pub sox: SoxComplianceConfig,
5134
5135 #[serde(default)]
5137 pub pcaob: PcaobConfig,
5138}
5139
5140#[derive(Debug, Clone, Serialize, Deserialize)]
5142pub struct IsaComplianceConfig {
5143 #[serde(default)]
5145 pub enabled: bool,
5146
5147 #[serde(default = "default_compliance_level")]
5149 pub compliance_level: String,
5150
5151 #[serde(default = "default_true")]
5153 pub generate_isa_mappings: bool,
5154
5155 #[serde(default = "default_true")]
5157 pub generate_coverage_summary: bool,
5158
5159 #[serde(default)]
5161 pub include_pcaob: bool,
5162
5163 #[serde(default = "default_audit_framework")]
5165 pub framework: String,
5166}
5167
5168fn default_compliance_level() -> String {
5169 "standard".to_string()
5170}
5171
5172fn default_audit_framework() -> String {
5173 "isa".to_string()
5174}
5175
5176impl Default for IsaComplianceConfig {
5177 fn default() -> Self {
5178 Self {
5179 enabled: false,
5180 compliance_level: default_compliance_level(),
5181 generate_isa_mappings: true,
5182 generate_coverage_summary: true,
5183 include_pcaob: false,
5184 framework: default_audit_framework(),
5185 }
5186 }
5187}
5188
5189#[derive(Debug, Clone, Serialize, Deserialize)]
5191pub struct AnalyticalProceduresConfig {
5192 #[serde(default)]
5194 pub enabled: bool,
5195
5196 #[serde(default = "default_procedures_per_account")]
5198 pub procedures_per_account: usize,
5199
5200 #[serde(default = "default_variance_probability")]
5202 pub variance_probability: f64,
5203
5204 #[serde(default = "default_true")]
5206 pub generate_investigations: bool,
5207
5208 #[serde(default = "default_true")]
5210 pub include_ratio_analysis: bool,
5211}
5212
5213fn default_procedures_per_account() -> usize {
5214 3
5215}
5216
5217fn default_variance_probability() -> f64 {
5218 0.20
5219}
5220
5221impl Default for AnalyticalProceduresConfig {
5222 fn default() -> Self {
5223 Self {
5224 enabled: false,
5225 procedures_per_account: default_procedures_per_account(),
5226 variance_probability: default_variance_probability(),
5227 generate_investigations: true,
5228 include_ratio_analysis: true,
5229 }
5230 }
5231}
5232
5233#[derive(Debug, Clone, Serialize, Deserialize)]
5235pub struct ConfirmationsConfig {
5236 #[serde(default)]
5238 pub enabled: bool,
5239
5240 #[serde(default = "default_confirmation_count")]
5242 pub confirmation_count: usize,
5243
5244 #[serde(default = "default_positive_response_rate")]
5246 pub positive_response_rate: f64,
5247
5248 #[serde(default = "default_exception_rate_confirm")]
5250 pub exception_rate: f64,
5251
5252 #[serde(default = "default_non_response_rate")]
5254 pub non_response_rate: f64,
5255
5256 #[serde(default = "default_true")]
5258 pub generate_alternative_procedures: bool,
5259}
5260
5261fn default_confirmation_count() -> usize {
5262 50
5263}
5264
5265fn default_positive_response_rate() -> f64 {
5266 0.85
5267}
5268
5269fn default_exception_rate_confirm() -> f64 {
5270 0.10
5271}
5272
5273fn default_non_response_rate() -> f64 {
5274 0.05
5275}
5276
5277impl Default for ConfirmationsConfig {
5278 fn default() -> Self {
5279 Self {
5280 enabled: false,
5281 confirmation_count: default_confirmation_count(),
5282 positive_response_rate: default_positive_response_rate(),
5283 exception_rate: default_exception_rate_confirm(),
5284 non_response_rate: default_non_response_rate(),
5285 generate_alternative_procedures: true,
5286 }
5287 }
5288}
5289
5290#[derive(Debug, Clone, Serialize, Deserialize)]
5292pub struct AuditOpinionConfig {
5293 #[serde(default)]
5295 pub enabled: bool,
5296
5297 #[serde(default = "default_true")]
5299 pub generate_kam: bool,
5300
5301 #[serde(default = "default_kam_count")]
5303 pub average_kam_count: usize,
5304
5305 #[serde(default = "default_modified_opinion_rate")]
5307 pub modified_opinion_rate: f64,
5308
5309 #[serde(default)]
5311 pub include_emphasis_of_matter: bool,
5312
5313 #[serde(default = "default_true")]
5315 pub include_going_concern: bool,
5316}
5317
5318fn default_kam_count() -> usize {
5319 3
5320}
5321
5322fn default_modified_opinion_rate() -> f64 {
5323 0.05
5324}
5325
5326impl Default for AuditOpinionConfig {
5327 fn default() -> Self {
5328 Self {
5329 enabled: false,
5330 generate_kam: true,
5331 average_kam_count: default_kam_count(),
5332 modified_opinion_rate: default_modified_opinion_rate(),
5333 include_emphasis_of_matter: false,
5334 include_going_concern: true,
5335 }
5336 }
5337}
5338
5339#[derive(Debug, Clone, Serialize, Deserialize)]
5341pub struct SoxComplianceConfig {
5342 #[serde(default)]
5344 pub enabled: bool,
5345
5346 #[serde(default = "default_true")]
5348 pub generate_302_certifications: bool,
5349
5350 #[serde(default = "default_true")]
5352 pub generate_404_assessments: bool,
5353
5354 #[serde(default = "default_sox_materiality_threshold")]
5356 pub materiality_threshold: f64,
5357
5358 #[serde(default = "default_material_weakness_rate")]
5360 pub material_weakness_rate: f64,
5361
5362 #[serde(default = "default_significant_deficiency_rate")]
5364 pub significant_deficiency_rate: f64,
5365}
5366
5367fn default_material_weakness_rate() -> f64 {
5368 0.02
5369}
5370
5371fn default_significant_deficiency_rate() -> f64 {
5372 0.08
5373}
5374
5375impl Default for SoxComplianceConfig {
5376 fn default() -> Self {
5377 Self {
5378 enabled: false,
5379 generate_302_certifications: true,
5380 generate_404_assessments: true,
5381 materiality_threshold: default_sox_materiality_threshold(),
5382 material_weakness_rate: default_material_weakness_rate(),
5383 significant_deficiency_rate: default_significant_deficiency_rate(),
5384 }
5385 }
5386}
5387
5388#[derive(Debug, Clone, Serialize, Deserialize)]
5390pub struct PcaobConfig {
5391 #[serde(default)]
5393 pub enabled: bool,
5394
5395 #[serde(default)]
5397 pub is_pcaob_audit: bool,
5398
5399 #[serde(default = "default_true")]
5401 pub generate_cam: bool,
5402
5403 #[serde(default)]
5405 pub include_icfr_opinion: bool,
5406
5407 #[serde(default)]
5409 pub generate_standard_mappings: bool,
5410}
5411
5412impl Default for PcaobConfig {
5413 fn default() -> Self {
5414 Self {
5415 enabled: false,
5416 is_pcaob_audit: false,
5417 generate_cam: true,
5418 include_icfr_opinion: false,
5419 generate_standard_mappings: false,
5420 }
5421 }
5422}
5423
5424#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5437pub struct AdvancedDistributionConfig {
5438 #[serde(default)]
5440 pub enabled: bool,
5441
5442 #[serde(default)]
5444 pub amounts: MixtureDistributionSchemaConfig,
5445
5446 #[serde(default)]
5448 pub correlations: CorrelationSchemaConfig,
5449
5450 #[serde(default)]
5452 pub conditional: Vec<ConditionalDistributionSchemaConfig>,
5453
5454 #[serde(default)]
5456 pub regime_changes: RegimeChangeSchemaConfig,
5457
5458 #[serde(default)]
5460 pub industry_profile: Option<IndustryProfileType>,
5461
5462 #[serde(default)]
5464 pub validation: StatisticalValidationSchemaConfig,
5465}
5466
5467#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
5469#[serde(rename_all = "snake_case")]
5470pub enum IndustryProfileType {
5471 Retail,
5473 Manufacturing,
5475 FinancialServices,
5477 Healthcare,
5479 Technology,
5481}
5482
5483#[derive(Debug, Clone, Serialize, Deserialize)]
5485pub struct MixtureDistributionSchemaConfig {
5486 #[serde(default)]
5488 pub enabled: bool,
5489
5490 #[serde(default = "default_mixture_type")]
5492 pub distribution_type: MixtureDistributionType,
5493
5494 #[serde(default)]
5496 pub components: Vec<MixtureComponentConfig>,
5497
5498 #[serde(default = "default_min_amount")]
5500 pub min_value: f64,
5501
5502 #[serde(default)]
5504 pub max_value: Option<f64>,
5505
5506 #[serde(default = "default_decimal_places")]
5508 pub decimal_places: u8,
5509}
5510
5511fn default_mixture_type() -> MixtureDistributionType {
5512 MixtureDistributionType::LogNormal
5513}
5514
5515fn default_min_amount() -> f64 {
5516 0.01
5517}
5518
5519fn default_decimal_places() -> u8 {
5520 2
5521}
5522
5523impl Default for MixtureDistributionSchemaConfig {
5524 fn default() -> Self {
5525 Self {
5526 enabled: false,
5527 distribution_type: MixtureDistributionType::LogNormal,
5528 components: Vec::new(),
5529 min_value: 0.01,
5530 max_value: None,
5531 decimal_places: 2,
5532 }
5533 }
5534}
5535
5536#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5538#[serde(rename_all = "snake_case")]
5539pub enum MixtureDistributionType {
5540 Gaussian,
5542 #[default]
5544 LogNormal,
5545}
5546
5547#[derive(Debug, Clone, Serialize, Deserialize)]
5549pub struct MixtureComponentConfig {
5550 pub weight: f64,
5552
5553 pub mu: f64,
5555
5556 pub sigma: f64,
5558
5559 #[serde(default)]
5561 pub label: Option<String>,
5562}
5563
5564#[derive(Debug, Clone, Serialize, Deserialize)]
5566pub struct CorrelationSchemaConfig {
5567 #[serde(default)]
5569 pub enabled: bool,
5570
5571 #[serde(default)]
5573 pub copula_type: CopulaSchemaType,
5574
5575 #[serde(default)]
5577 pub fields: Vec<CorrelatedFieldConfig>,
5578
5579 #[serde(default)]
5582 pub matrix: Vec<f64>,
5583
5584 #[serde(default)]
5586 pub expected_correlations: Vec<ExpectedCorrelationConfig>,
5587}
5588
5589impl Default for CorrelationSchemaConfig {
5590 fn default() -> Self {
5591 Self {
5592 enabled: false,
5593 copula_type: CopulaSchemaType::Gaussian,
5594 fields: Vec::new(),
5595 matrix: Vec::new(),
5596 expected_correlations: Vec::new(),
5597 }
5598 }
5599}
5600
5601#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5603#[serde(rename_all = "snake_case")]
5604pub enum CopulaSchemaType {
5605 #[default]
5607 Gaussian,
5608 Clayton,
5610 Gumbel,
5612 Frank,
5614 StudentT,
5616}
5617
5618#[derive(Debug, Clone, Serialize, Deserialize)]
5620pub struct CorrelatedFieldConfig {
5621 pub name: String,
5623
5624 #[serde(default)]
5626 pub distribution: MarginalDistributionConfig,
5627}
5628
5629#[derive(Debug, Clone, Serialize, Deserialize)]
5631#[serde(tag = "type", rename_all = "snake_case")]
5632pub enum MarginalDistributionConfig {
5633 Normal {
5635 mu: f64,
5637 sigma: f64,
5639 },
5640 LogNormal {
5642 mu: f64,
5644 sigma: f64,
5646 },
5647 Uniform {
5649 min: f64,
5651 max: f64,
5653 },
5654 DiscreteUniform {
5656 min: i32,
5658 max: i32,
5660 },
5661}
5662
5663impl Default for MarginalDistributionConfig {
5664 fn default() -> Self {
5665 Self::Normal {
5666 mu: 0.0,
5667 sigma: 1.0,
5668 }
5669 }
5670}
5671
5672#[derive(Debug, Clone, Serialize, Deserialize)]
5674pub struct ExpectedCorrelationConfig {
5675 pub field1: String,
5677 pub field2: String,
5679 pub expected_r: f64,
5681 #[serde(default = "default_correlation_tolerance")]
5683 pub tolerance: f64,
5684}
5685
5686fn default_correlation_tolerance() -> f64 {
5687 0.10
5688}
5689
5690#[derive(Debug, Clone, Serialize, Deserialize)]
5692pub struct ConditionalDistributionSchemaConfig {
5693 pub output_field: String,
5695
5696 pub input_field: String,
5698
5699 #[serde(default)]
5701 pub breakpoints: Vec<ConditionalBreakpointConfig>,
5702
5703 #[serde(default)]
5705 pub default_distribution: ConditionalDistributionParamsConfig,
5706
5707 #[serde(default)]
5709 pub min_value: Option<f64>,
5710
5711 #[serde(default)]
5713 pub max_value: Option<f64>,
5714
5715 #[serde(default = "default_decimal_places")]
5717 pub decimal_places: u8,
5718}
5719
5720#[derive(Debug, Clone, Serialize, Deserialize)]
5722pub struct ConditionalBreakpointConfig {
5723 pub threshold: f64,
5725
5726 pub distribution: ConditionalDistributionParamsConfig,
5728}
5729
5730#[derive(Debug, Clone, Serialize, Deserialize)]
5732#[serde(tag = "type", rename_all = "snake_case")]
5733pub enum ConditionalDistributionParamsConfig {
5734 Fixed {
5736 value: f64,
5738 },
5739 Normal {
5741 mu: f64,
5743 sigma: f64,
5745 },
5746 LogNormal {
5748 mu: f64,
5750 sigma: f64,
5752 },
5753 Uniform {
5755 min: f64,
5757 max: f64,
5759 },
5760 Beta {
5762 alpha: f64,
5764 beta: f64,
5766 min: f64,
5768 max: f64,
5770 },
5771 Discrete {
5773 values: Vec<f64>,
5775 weights: Vec<f64>,
5777 },
5778}
5779
5780impl Default for ConditionalDistributionParamsConfig {
5781 fn default() -> Self {
5782 Self::Normal {
5783 mu: 0.0,
5784 sigma: 1.0,
5785 }
5786 }
5787}
5788
5789#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5791pub struct RegimeChangeSchemaConfig {
5792 #[serde(default)]
5794 pub enabled: bool,
5795
5796 #[serde(default)]
5798 pub changes: Vec<RegimeChangeEventConfig>,
5799
5800 #[serde(default)]
5802 pub economic_cycle: Option<EconomicCycleSchemaConfig>,
5803
5804 #[serde(default)]
5806 pub parameter_drifts: Vec<ParameterDriftSchemaConfig>,
5807}
5808
5809#[derive(Debug, Clone, Serialize, Deserialize)]
5811pub struct RegimeChangeEventConfig {
5812 pub date: String,
5814
5815 pub change_type: RegimeChangeTypeConfig,
5817
5818 #[serde(default)]
5820 pub description: Option<String>,
5821
5822 #[serde(default)]
5824 pub effects: Vec<RegimeEffectConfig>,
5825}
5826
5827#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
5829#[serde(rename_all = "snake_case")]
5830pub enum RegimeChangeTypeConfig {
5831 Acquisition,
5833 Divestiture,
5835 PriceIncrease,
5837 PriceDecrease,
5839 ProductLaunch,
5841 ProductDiscontinuation,
5843 PolicyChange,
5845 CompetitorEntry,
5847 Custom,
5849}
5850
5851#[derive(Debug, Clone, Serialize, Deserialize)]
5853pub struct RegimeEffectConfig {
5854 pub field: String,
5856
5857 pub multiplier: f64,
5859}
5860
5861#[derive(Debug, Clone, Serialize, Deserialize)]
5863pub struct EconomicCycleSchemaConfig {
5864 #[serde(default)]
5866 pub enabled: bool,
5867
5868 #[serde(default = "default_cycle_period")]
5870 pub period_months: u32,
5871
5872 #[serde(default = "default_cycle_amplitude")]
5874 pub amplitude: f64,
5875
5876 #[serde(default)]
5878 pub phase_offset: u32,
5879
5880 #[serde(default)]
5882 pub recessions: Vec<RecessionPeriodConfig>,
5883}
5884
5885fn default_cycle_period() -> u32 {
5886 48
5887}
5888
5889fn default_cycle_amplitude() -> f64 {
5890 0.15
5891}
5892
5893impl Default for EconomicCycleSchemaConfig {
5894 fn default() -> Self {
5895 Self {
5896 enabled: false,
5897 period_months: 48,
5898 amplitude: 0.15,
5899 phase_offset: 0,
5900 recessions: Vec::new(),
5901 }
5902 }
5903}
5904
5905#[derive(Debug, Clone, Serialize, Deserialize)]
5907pub struct RecessionPeriodConfig {
5908 pub start_month: u32,
5910
5911 pub duration_months: u32,
5913
5914 #[serde(default = "default_recession_severity")]
5916 pub severity: f64,
5917}
5918
5919fn default_recession_severity() -> f64 {
5920 0.20
5921}
5922
5923#[derive(Debug, Clone, Serialize, Deserialize)]
5925pub struct ParameterDriftSchemaConfig {
5926 pub parameter: String,
5928
5929 pub drift_type: ParameterDriftTypeConfig,
5931
5932 pub start_value: f64,
5934
5935 pub end_value: f64,
5937
5938 #[serde(default)]
5940 pub start_period: u32,
5941
5942 #[serde(default)]
5944 pub end_period: Option<u32>,
5945}
5946
5947#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5949#[serde(rename_all = "snake_case")]
5950pub enum ParameterDriftTypeConfig {
5951 #[default]
5953 Linear,
5954 Exponential,
5956 Logistic,
5958 Step,
5960}
5961
5962#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5964pub struct StatisticalValidationSchemaConfig {
5965 #[serde(default)]
5967 pub enabled: bool,
5968
5969 #[serde(default)]
5971 pub tests: Vec<StatisticalTestConfig>,
5972
5973 #[serde(default)]
5975 pub reporting: ValidationReportingConfig,
5976}
5977
5978#[derive(Debug, Clone, Serialize, Deserialize)]
5980#[serde(tag = "type", rename_all = "snake_case")]
5981pub enum StatisticalTestConfig {
5982 BenfordFirstDigit {
5984 #[serde(default = "default_benford_threshold")]
5986 threshold_mad: f64,
5987 #[serde(default = "default_benford_warning")]
5989 warning_mad: f64,
5990 },
5991 DistributionFit {
5993 target: TargetDistributionConfig,
5995 #[serde(default = "default_ks_significance")]
5997 ks_significance: f64,
5998 #[serde(default)]
6000 method: DistributionFitMethod,
6001 },
6002 CorrelationCheck {
6004 expected_correlations: Vec<ExpectedCorrelationConfig>,
6006 },
6007 ChiSquared {
6009 #[serde(default = "default_chi_squared_bins")]
6011 bins: usize,
6012 #[serde(default = "default_chi_squared_significance")]
6014 significance: f64,
6015 },
6016 AndersonDarling {
6018 target: TargetDistributionConfig,
6020 #[serde(default = "default_ad_significance")]
6022 significance: f64,
6023 },
6024}
6025
6026fn default_benford_threshold() -> f64 {
6027 0.015
6028}
6029
6030fn default_benford_warning() -> f64 {
6031 0.010
6032}
6033
6034fn default_ks_significance() -> f64 {
6035 0.05
6036}
6037
6038fn default_chi_squared_bins() -> usize {
6039 10
6040}
6041
6042fn default_chi_squared_significance() -> f64 {
6043 0.05
6044}
6045
6046fn default_ad_significance() -> f64 {
6047 0.05
6048}
6049
6050#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
6052#[serde(rename_all = "snake_case")]
6053pub enum TargetDistributionConfig {
6054 Normal,
6056 #[default]
6058 LogNormal,
6059 Exponential,
6061 Uniform,
6063}
6064
6065#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
6067#[serde(rename_all = "snake_case")]
6068pub enum DistributionFitMethod {
6069 #[default]
6071 KolmogorovSmirnov,
6072 AndersonDarling,
6074 ChiSquared,
6076}
6077
6078#[derive(Debug, Clone, Serialize, Deserialize)]
6080pub struct ValidationReportingConfig {
6081 #[serde(default)]
6083 pub output_report: bool,
6084
6085 #[serde(default)]
6087 pub format: ValidationReportFormat,
6088
6089 #[serde(default)]
6091 pub fail_on_error: bool,
6092
6093 #[serde(default = "default_true")]
6095 pub include_details: bool,
6096}
6097
6098impl Default for ValidationReportingConfig {
6099 fn default() -> Self {
6100 Self {
6101 output_report: false,
6102 format: ValidationReportFormat::Json,
6103 fail_on_error: false,
6104 include_details: true,
6105 }
6106 }
6107}
6108
6109#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
6111#[serde(rename_all = "snake_case")]
6112pub enum ValidationReportFormat {
6113 #[default]
6115 Json,
6116 Yaml,
6118 Html,
6120}
6121
6122#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6134pub struct TemporalPatternsConfig {
6135 #[serde(default)]
6137 pub enabled: bool,
6138
6139 #[serde(default)]
6141 pub business_days: BusinessDaySchemaConfig,
6142
6143 #[serde(default)]
6145 pub calendars: CalendarSchemaConfig,
6146
6147 #[serde(default)]
6149 pub period_end: PeriodEndSchemaConfig,
6150
6151 #[serde(default)]
6153 pub processing_lags: ProcessingLagSchemaConfig,
6154
6155 #[serde(default)]
6157 pub fiscal_calendar: FiscalCalendarSchemaConfig,
6158
6159 #[serde(default)]
6161 pub intraday: IntraDaySchemaConfig,
6162
6163 #[serde(default)]
6165 pub timezones: TimezoneSchemaConfig,
6166}
6167
6168#[derive(Debug, Clone, Serialize, Deserialize)]
6170pub struct BusinessDaySchemaConfig {
6171 #[serde(default = "default_true")]
6173 pub enabled: bool,
6174
6175 #[serde(default = "default_half_day_policy")]
6177 pub half_day_policy: String,
6178
6179 #[serde(default)]
6181 pub settlement_rules: SettlementRulesSchemaConfig,
6182
6183 #[serde(default = "default_month_end_convention")]
6185 pub month_end_convention: String,
6186
6187 #[serde(default)]
6189 pub weekend_days: Option<Vec<String>>,
6190}
6191
6192fn default_half_day_policy() -> String {
6193 "half_day".to_string()
6194}
6195
6196fn default_month_end_convention() -> String {
6197 "modified_following".to_string()
6198}
6199
6200impl Default for BusinessDaySchemaConfig {
6201 fn default() -> Self {
6202 Self {
6203 enabled: true,
6204 half_day_policy: "half_day".to_string(),
6205 settlement_rules: SettlementRulesSchemaConfig::default(),
6206 month_end_convention: "modified_following".to_string(),
6207 weekend_days: None,
6208 }
6209 }
6210}
6211
6212#[derive(Debug, Clone, Serialize, Deserialize)]
6214pub struct SettlementRulesSchemaConfig {
6215 #[serde(default = "default_settlement_2")]
6217 pub equity_days: i32,
6218
6219 #[serde(default = "default_settlement_1")]
6221 pub government_bonds_days: i32,
6222
6223 #[serde(default = "default_settlement_2")]
6225 pub fx_spot_days: i32,
6226
6227 #[serde(default = "default_settlement_2")]
6229 pub corporate_bonds_days: i32,
6230
6231 #[serde(default = "default_wire_cutoff")]
6233 pub wire_cutoff_time: String,
6234
6235 #[serde(default = "default_settlement_1")]
6237 pub wire_international_days: i32,
6238
6239 #[serde(default = "default_settlement_1")]
6241 pub ach_days: i32,
6242}
6243
6244fn default_settlement_1() -> i32 {
6245 1
6246}
6247
6248fn default_settlement_2() -> i32 {
6249 2
6250}
6251
6252fn default_wire_cutoff() -> String {
6253 "14:00".to_string()
6254}
6255
6256impl Default for SettlementRulesSchemaConfig {
6257 fn default() -> Self {
6258 Self {
6259 equity_days: 2,
6260 government_bonds_days: 1,
6261 fx_spot_days: 2,
6262 corporate_bonds_days: 2,
6263 wire_cutoff_time: "14:00".to_string(),
6264 wire_international_days: 1,
6265 ach_days: 1,
6266 }
6267 }
6268}
6269
6270#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6272pub struct CalendarSchemaConfig {
6273 #[serde(default)]
6275 pub regions: Vec<String>,
6276
6277 #[serde(default)]
6279 pub custom_holidays: Vec<CustomHolidaySchemaConfig>,
6280}
6281
6282#[derive(Debug, Clone, Serialize, Deserialize)]
6284pub struct CustomHolidaySchemaConfig {
6285 pub name: String,
6287 pub month: u8,
6289 pub day: u8,
6291 #[serde(default = "default_holiday_multiplier")]
6293 pub activity_multiplier: f64,
6294}
6295
6296fn default_holiday_multiplier() -> f64 {
6297 0.05
6298}
6299
6300#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6302pub struct PeriodEndSchemaConfig {
6303 #[serde(default)]
6305 pub model: Option<String>,
6306
6307 #[serde(default)]
6309 pub month_end: Option<PeriodEndModelSchemaConfig>,
6310
6311 #[serde(default)]
6313 pub quarter_end: Option<PeriodEndModelSchemaConfig>,
6314
6315 #[serde(default)]
6317 pub year_end: Option<PeriodEndModelSchemaConfig>,
6318}
6319
6320#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6322pub struct PeriodEndModelSchemaConfig {
6323 #[serde(default)]
6325 pub inherit_from: Option<String>,
6326
6327 #[serde(default)]
6329 pub additional_multiplier: Option<f64>,
6330
6331 #[serde(default)]
6333 pub start_day: Option<i32>,
6334
6335 #[serde(default)]
6337 pub base_multiplier: Option<f64>,
6338
6339 #[serde(default)]
6341 pub peak_multiplier: Option<f64>,
6342
6343 #[serde(default)]
6345 pub decay_rate: Option<f64>,
6346
6347 #[serde(default)]
6349 pub sustained_high_days: Option<i32>,
6350}
6351
6352#[derive(Debug, Clone, Serialize, Deserialize)]
6354pub struct ProcessingLagSchemaConfig {
6355 #[serde(default = "default_true")]
6357 pub enabled: bool,
6358
6359 #[serde(default)]
6361 pub sales_order_lag: Option<LagDistributionSchemaConfig>,
6362
6363 #[serde(default)]
6365 pub purchase_order_lag: Option<LagDistributionSchemaConfig>,
6366
6367 #[serde(default)]
6369 pub goods_receipt_lag: Option<LagDistributionSchemaConfig>,
6370
6371 #[serde(default)]
6373 pub invoice_receipt_lag: Option<LagDistributionSchemaConfig>,
6374
6375 #[serde(default)]
6377 pub invoice_issue_lag: Option<LagDistributionSchemaConfig>,
6378
6379 #[serde(default)]
6381 pub payment_lag: Option<LagDistributionSchemaConfig>,
6382
6383 #[serde(default)]
6385 pub journal_entry_lag: Option<LagDistributionSchemaConfig>,
6386
6387 #[serde(default)]
6389 pub cross_day_posting: Option<CrossDayPostingSchemaConfig>,
6390}
6391
6392impl Default for ProcessingLagSchemaConfig {
6393 fn default() -> Self {
6394 Self {
6395 enabled: true,
6396 sales_order_lag: None,
6397 purchase_order_lag: None,
6398 goods_receipt_lag: None,
6399 invoice_receipt_lag: None,
6400 invoice_issue_lag: None,
6401 payment_lag: None,
6402 journal_entry_lag: None,
6403 cross_day_posting: None,
6404 }
6405 }
6406}
6407
6408#[derive(Debug, Clone, Serialize, Deserialize)]
6410pub struct LagDistributionSchemaConfig {
6411 pub mu: f64,
6413 pub sigma: f64,
6415 #[serde(default)]
6417 pub min_hours: Option<f64>,
6418 #[serde(default)]
6420 pub max_hours: Option<f64>,
6421}
6422
6423#[derive(Debug, Clone, Serialize, Deserialize)]
6425pub struct CrossDayPostingSchemaConfig {
6426 #[serde(default = "default_true")]
6428 pub enabled: bool,
6429
6430 #[serde(default)]
6433 pub probability_by_hour: std::collections::HashMap<u8, f64>,
6434}
6435
6436impl Default for CrossDayPostingSchemaConfig {
6437 fn default() -> Self {
6438 let mut probability_by_hour = std::collections::HashMap::new();
6439 probability_by_hour.insert(17, 0.3);
6440 probability_by_hour.insert(18, 0.6);
6441 probability_by_hour.insert(19, 0.8);
6442 probability_by_hour.insert(20, 0.9);
6443 probability_by_hour.insert(21, 0.95);
6444 probability_by_hour.insert(22, 0.99);
6445
6446 Self {
6447 enabled: true,
6448 probability_by_hour,
6449 }
6450 }
6451}
6452
6453#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6462pub struct FiscalCalendarSchemaConfig {
6463 #[serde(default)]
6465 pub enabled: bool,
6466
6467 #[serde(default = "default_fiscal_calendar_type")]
6469 pub calendar_type: String,
6470
6471 #[serde(default)]
6473 pub year_start_month: Option<u8>,
6474
6475 #[serde(default)]
6477 pub year_start_day: Option<u8>,
6478
6479 #[serde(default)]
6481 pub four_four_five: Option<FourFourFiveSchemaConfig>,
6482}
6483
6484fn default_fiscal_calendar_type() -> String {
6485 "calendar_year".to_string()
6486}
6487
6488#[derive(Debug, Clone, Serialize, Deserialize)]
6490pub struct FourFourFiveSchemaConfig {
6491 #[serde(default = "default_week_pattern")]
6493 pub pattern: String,
6494
6495 #[serde(default = "default_anchor_type")]
6497 pub anchor_type: String,
6498
6499 #[serde(default = "default_anchor_month")]
6501 pub anchor_month: u8,
6502
6503 #[serde(default = "default_leap_week_placement")]
6505 pub leap_week_placement: String,
6506}
6507
6508fn default_week_pattern() -> String {
6509 "four_four_five".to_string()
6510}
6511
6512fn default_anchor_type() -> String {
6513 "last_saturday".to_string()
6514}
6515
6516fn default_anchor_month() -> u8 {
6517 1 }
6519
6520fn default_leap_week_placement() -> String {
6521 "q4_period3".to_string()
6522}
6523
6524impl Default for FourFourFiveSchemaConfig {
6525 fn default() -> Self {
6526 Self {
6527 pattern: "four_four_five".to_string(),
6528 anchor_type: "last_saturday".to_string(),
6529 anchor_month: 1,
6530 leap_week_placement: "q4_period3".to_string(),
6531 }
6532 }
6533}
6534
6535#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6544pub struct IntraDaySchemaConfig {
6545 #[serde(default)]
6547 pub enabled: bool,
6548
6549 #[serde(default)]
6551 pub segments: Vec<IntraDaySegmentSchemaConfig>,
6552}
6553
6554#[derive(Debug, Clone, Serialize, Deserialize)]
6556pub struct IntraDaySegmentSchemaConfig {
6557 pub name: String,
6559
6560 pub start: String,
6562
6563 pub end: String,
6565
6566 #[serde(default = "default_multiplier")]
6568 pub multiplier: f64,
6569
6570 #[serde(default = "default_posting_type")]
6572 pub posting_type: String,
6573}
6574
6575fn default_multiplier() -> f64 {
6576 1.0
6577}
6578
6579fn default_posting_type() -> String {
6580 "both".to_string()
6581}
6582
6583#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6589pub struct TimezoneSchemaConfig {
6590 #[serde(default)]
6592 pub enabled: bool,
6593
6594 #[serde(default = "default_timezone")]
6596 pub default_timezone: String,
6597
6598 #[serde(default = "default_consolidation_timezone")]
6600 pub consolidation_timezone: String,
6601
6602 #[serde(default)]
6605 pub entity_mappings: Vec<EntityTimezoneMapping>,
6606}
6607
6608fn default_timezone() -> String {
6609 "America/New_York".to_string()
6610}
6611
6612fn default_consolidation_timezone() -> String {
6613 "UTC".to_string()
6614}
6615
6616#[derive(Debug, Clone, Serialize, Deserialize)]
6618pub struct EntityTimezoneMapping {
6619 pub pattern: String,
6621
6622 pub timezone: String,
6624}
6625
6626#[derive(Debug, Clone, Serialize, Deserialize)]
6632pub struct VendorNetworkSchemaConfig {
6633 #[serde(default)]
6635 pub enabled: bool,
6636
6637 #[serde(default = "default_vendor_tier_depth")]
6639 pub depth: u8,
6640
6641 #[serde(default)]
6643 pub tier1: TierCountSchemaConfig,
6644
6645 #[serde(default)]
6647 pub tier2_per_parent: TierCountSchemaConfig,
6648
6649 #[serde(default)]
6651 pub tier3_per_parent: TierCountSchemaConfig,
6652
6653 #[serde(default)]
6655 pub clusters: VendorClusterSchemaConfig,
6656
6657 #[serde(default)]
6659 pub dependencies: DependencySchemaConfig,
6660}
6661
6662fn default_vendor_tier_depth() -> u8 {
6663 3
6664}
6665
6666impl Default for VendorNetworkSchemaConfig {
6667 fn default() -> Self {
6668 Self {
6669 enabled: false,
6670 depth: 3,
6671 tier1: TierCountSchemaConfig { min: 50, max: 100 },
6672 tier2_per_parent: TierCountSchemaConfig { min: 4, max: 10 },
6673 tier3_per_parent: TierCountSchemaConfig { min: 2, max: 5 },
6674 clusters: VendorClusterSchemaConfig::default(),
6675 dependencies: DependencySchemaConfig::default(),
6676 }
6677 }
6678}
6679
6680#[derive(Debug, Clone, Serialize, Deserialize)]
6682pub struct TierCountSchemaConfig {
6683 #[serde(default = "default_tier_min")]
6685 pub min: usize,
6686
6687 #[serde(default = "default_tier_max")]
6689 pub max: usize,
6690}
6691
6692fn default_tier_min() -> usize {
6693 5
6694}
6695
6696fn default_tier_max() -> usize {
6697 20
6698}
6699
6700impl Default for TierCountSchemaConfig {
6701 fn default() -> Self {
6702 Self {
6703 min: default_tier_min(),
6704 max: default_tier_max(),
6705 }
6706 }
6707}
6708
6709#[derive(Debug, Clone, Serialize, Deserialize)]
6711pub struct VendorClusterSchemaConfig {
6712 #[serde(default = "default_reliable_strategic")]
6714 pub reliable_strategic: f64,
6715
6716 #[serde(default = "default_standard_operational")]
6718 pub standard_operational: f64,
6719
6720 #[serde(default = "default_transactional")]
6722 pub transactional: f64,
6723
6724 #[serde(default = "default_problematic")]
6726 pub problematic: f64,
6727}
6728
6729fn default_reliable_strategic() -> f64 {
6730 0.20
6731}
6732
6733fn default_standard_operational() -> f64 {
6734 0.50
6735}
6736
6737fn default_transactional() -> f64 {
6738 0.25
6739}
6740
6741fn default_problematic() -> f64 {
6742 0.05
6743}
6744
6745impl Default for VendorClusterSchemaConfig {
6746 fn default() -> Self {
6747 Self {
6748 reliable_strategic: 0.20,
6749 standard_operational: 0.50,
6750 transactional: 0.25,
6751 problematic: 0.05,
6752 }
6753 }
6754}
6755
6756#[derive(Debug, Clone, Serialize, Deserialize)]
6758pub struct DependencySchemaConfig {
6759 #[serde(default = "default_max_single_vendor")]
6761 pub max_single_vendor_concentration: f64,
6762
6763 #[serde(default = "default_max_top5")]
6765 pub top_5_concentration: f64,
6766
6767 #[serde(default = "default_single_source_percent")]
6769 pub single_source_percent: f64,
6770}
6771
6772fn default_max_single_vendor() -> f64 {
6773 0.15
6774}
6775
6776fn default_max_top5() -> f64 {
6777 0.45
6778}
6779
6780fn default_single_source_percent() -> f64 {
6781 0.05
6782}
6783
6784impl Default for DependencySchemaConfig {
6785 fn default() -> Self {
6786 Self {
6787 max_single_vendor_concentration: 0.15,
6788 top_5_concentration: 0.45,
6789 single_source_percent: 0.05,
6790 }
6791 }
6792}
6793
6794#[derive(Debug, Clone, Default, Serialize, Deserialize)]
6800pub struct CustomerSegmentationSchemaConfig {
6801 #[serde(default)]
6803 pub enabled: bool,
6804
6805 #[serde(default)]
6807 pub value_segments: ValueSegmentsSchemaConfig,
6808
6809 #[serde(default)]
6811 pub lifecycle: LifecycleSchemaConfig,
6812
6813 #[serde(default)]
6815 pub networks: CustomerNetworksSchemaConfig,
6816}
6817
6818#[derive(Debug, Clone, Serialize, Deserialize)]
6820pub struct ValueSegmentsSchemaConfig {
6821 #[serde(default)]
6823 pub enterprise: SegmentDetailSchemaConfig,
6824
6825 #[serde(default)]
6827 pub mid_market: SegmentDetailSchemaConfig,
6828
6829 #[serde(default)]
6831 pub smb: SegmentDetailSchemaConfig,
6832
6833 #[serde(default)]
6835 pub consumer: SegmentDetailSchemaConfig,
6836}
6837
6838impl Default for ValueSegmentsSchemaConfig {
6839 fn default() -> Self {
6840 Self {
6841 enterprise: SegmentDetailSchemaConfig {
6842 revenue_share: 0.40,
6843 customer_share: 0.05,
6844 avg_order_value_range: "50000+".to_string(),
6845 },
6846 mid_market: SegmentDetailSchemaConfig {
6847 revenue_share: 0.35,
6848 customer_share: 0.20,
6849 avg_order_value_range: "5000-50000".to_string(),
6850 },
6851 smb: SegmentDetailSchemaConfig {
6852 revenue_share: 0.20,
6853 customer_share: 0.50,
6854 avg_order_value_range: "500-5000".to_string(),
6855 },
6856 consumer: SegmentDetailSchemaConfig {
6857 revenue_share: 0.05,
6858 customer_share: 0.25,
6859 avg_order_value_range: "50-500".to_string(),
6860 },
6861 }
6862 }
6863}
6864
6865#[derive(Debug, Clone, Serialize, Deserialize)]
6867pub struct SegmentDetailSchemaConfig {
6868 #[serde(default)]
6870 pub revenue_share: f64,
6871
6872 #[serde(default)]
6874 pub customer_share: f64,
6875
6876 #[serde(default)]
6878 pub avg_order_value_range: String,
6879}
6880
6881impl Default for SegmentDetailSchemaConfig {
6882 fn default() -> Self {
6883 Self {
6884 revenue_share: 0.25,
6885 customer_share: 0.25,
6886 avg_order_value_range: "1000-10000".to_string(),
6887 }
6888 }
6889}
6890
6891#[derive(Debug, Clone, Serialize, Deserialize)]
6893pub struct LifecycleSchemaConfig {
6894 #[serde(default)]
6896 pub prospect_rate: f64,
6897
6898 #[serde(default = "default_new_rate")]
6900 pub new_rate: f64,
6901
6902 #[serde(default = "default_growth_rate")]
6904 pub growth_rate: f64,
6905
6906 #[serde(default = "default_mature_rate")]
6908 pub mature_rate: f64,
6909
6910 #[serde(default = "default_at_risk_rate")]
6912 pub at_risk_rate: f64,
6913
6914 #[serde(default = "default_churned_rate")]
6916 pub churned_rate: f64,
6917}
6918
6919fn default_new_rate() -> f64 {
6920 0.10
6921}
6922
6923fn default_growth_rate() -> f64 {
6924 0.15
6925}
6926
6927fn default_mature_rate() -> f64 {
6928 0.60
6929}
6930
6931fn default_at_risk_rate() -> f64 {
6932 0.10
6933}
6934
6935fn default_churned_rate() -> f64 {
6936 0.05
6937}
6938
6939impl Default for LifecycleSchemaConfig {
6940 fn default() -> Self {
6941 Self {
6942 prospect_rate: 0.0,
6943 new_rate: 0.10,
6944 growth_rate: 0.15,
6945 mature_rate: 0.60,
6946 at_risk_rate: 0.10,
6947 churned_rate: 0.05,
6948 }
6949 }
6950}
6951
6952#[derive(Debug, Clone, Default, Serialize, Deserialize)]
6954pub struct CustomerNetworksSchemaConfig {
6955 #[serde(default)]
6957 pub referrals: ReferralSchemaConfig,
6958
6959 #[serde(default)]
6961 pub corporate_hierarchies: HierarchySchemaConfig,
6962}
6963
6964#[derive(Debug, Clone, Serialize, Deserialize)]
6966pub struct ReferralSchemaConfig {
6967 #[serde(default = "default_true")]
6969 pub enabled: bool,
6970
6971 #[serde(default = "default_referral_rate")]
6973 pub referral_rate: f64,
6974}
6975
6976fn default_referral_rate() -> f64 {
6977 0.15
6978}
6979
6980impl Default for ReferralSchemaConfig {
6981 fn default() -> Self {
6982 Self {
6983 enabled: true,
6984 referral_rate: 0.15,
6985 }
6986 }
6987}
6988
6989#[derive(Debug, Clone, Serialize, Deserialize)]
6991pub struct HierarchySchemaConfig {
6992 #[serde(default = "default_true")]
6994 pub enabled: bool,
6995
6996 #[serde(default = "default_hierarchy_rate")]
6998 pub probability: f64,
6999}
7000
7001fn default_hierarchy_rate() -> f64 {
7002 0.30
7003}
7004
7005impl Default for HierarchySchemaConfig {
7006 fn default() -> Self {
7007 Self {
7008 enabled: true,
7009 probability: 0.30,
7010 }
7011 }
7012}
7013
7014#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7020pub struct RelationshipStrengthSchemaConfig {
7021 #[serde(default)]
7023 pub enabled: bool,
7024
7025 #[serde(default)]
7027 pub calculation: StrengthCalculationSchemaConfig,
7028
7029 #[serde(default)]
7031 pub thresholds: StrengthThresholdsSchemaConfig,
7032}
7033
7034#[derive(Debug, Clone, Serialize, Deserialize)]
7036pub struct StrengthCalculationSchemaConfig {
7037 #[serde(default = "default_volume_weight")]
7039 pub transaction_volume_weight: f64,
7040
7041 #[serde(default = "default_count_weight")]
7043 pub transaction_count_weight: f64,
7044
7045 #[serde(default = "default_duration_weight")]
7047 pub relationship_duration_weight: f64,
7048
7049 #[serde(default = "default_recency_weight")]
7051 pub recency_weight: f64,
7052
7053 #[serde(default = "default_mutual_weight")]
7055 pub mutual_connections_weight: f64,
7056
7057 #[serde(default = "default_recency_half_life")]
7059 pub recency_half_life_days: u32,
7060}
7061
7062fn default_volume_weight() -> f64 {
7063 0.30
7064}
7065
7066fn default_count_weight() -> f64 {
7067 0.25
7068}
7069
7070fn default_duration_weight() -> f64 {
7071 0.20
7072}
7073
7074fn default_recency_weight() -> f64 {
7075 0.15
7076}
7077
7078fn default_mutual_weight() -> f64 {
7079 0.10
7080}
7081
7082fn default_recency_half_life() -> u32 {
7083 90
7084}
7085
7086impl Default for StrengthCalculationSchemaConfig {
7087 fn default() -> Self {
7088 Self {
7089 transaction_volume_weight: 0.30,
7090 transaction_count_weight: 0.25,
7091 relationship_duration_weight: 0.20,
7092 recency_weight: 0.15,
7093 mutual_connections_weight: 0.10,
7094 recency_half_life_days: 90,
7095 }
7096 }
7097}
7098
7099#[derive(Debug, Clone, Serialize, Deserialize)]
7101pub struct StrengthThresholdsSchemaConfig {
7102 #[serde(default = "default_strong_threshold")]
7104 pub strong: f64,
7105
7106 #[serde(default = "default_moderate_threshold")]
7108 pub moderate: f64,
7109
7110 #[serde(default = "default_weak_threshold")]
7112 pub weak: f64,
7113}
7114
7115fn default_strong_threshold() -> f64 {
7116 0.7
7117}
7118
7119fn default_moderate_threshold() -> f64 {
7120 0.4
7121}
7122
7123fn default_weak_threshold() -> f64 {
7124 0.1
7125}
7126
7127impl Default for StrengthThresholdsSchemaConfig {
7128 fn default() -> Self {
7129 Self {
7130 strong: 0.7,
7131 moderate: 0.4,
7132 weak: 0.1,
7133 }
7134 }
7135}
7136
7137#[derive(Debug, Clone, Serialize, Deserialize)]
7143pub struct CrossProcessLinksSchemaConfig {
7144 #[serde(default)]
7146 pub enabled: bool,
7147
7148 #[serde(default = "default_true")]
7150 pub inventory_p2p_o2c: bool,
7151
7152 #[serde(default = "default_true")]
7154 pub payment_bank_reconciliation: bool,
7155
7156 #[serde(default = "default_true")]
7158 pub intercompany_bilateral: bool,
7159
7160 #[serde(default = "default_inventory_link_rate")]
7162 pub inventory_link_rate: f64,
7163}
7164
7165fn default_inventory_link_rate() -> f64 {
7166 0.30
7167}
7168
7169impl Default for CrossProcessLinksSchemaConfig {
7170 fn default() -> Self {
7171 Self {
7172 enabled: false,
7173 inventory_p2p_o2c: true,
7174 payment_bank_reconciliation: true,
7175 intercompany_bilateral: true,
7176 inventory_link_rate: 0.30,
7177 }
7178 }
7179}
7180
7181#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7187pub struct OrganizationalEventsSchemaConfig {
7188 #[serde(default)]
7190 pub enabled: bool,
7191
7192 #[serde(default)]
7194 pub effect_blending: EffectBlendingModeConfig,
7195
7196 #[serde(default)]
7198 pub events: Vec<OrganizationalEventSchemaConfig>,
7199
7200 #[serde(default)]
7202 pub process_evolution: Vec<ProcessEvolutionSchemaConfig>,
7203
7204 #[serde(default)]
7206 pub technology_transitions: Vec<TechnologyTransitionSchemaConfig>,
7207}
7208
7209#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
7211#[serde(rename_all = "snake_case")]
7212pub enum EffectBlendingModeConfig {
7213 #[default]
7215 Multiplicative,
7216 Additive,
7218 Maximum,
7220 Minimum,
7222}
7223
7224#[derive(Debug, Clone, Serialize, Deserialize)]
7226pub struct OrganizationalEventSchemaConfig {
7227 pub id: String,
7229
7230 pub event_type: OrganizationalEventTypeSchemaConfig,
7232
7233 pub effective_date: String,
7235
7236 #[serde(default = "default_org_transition_months")]
7238 pub transition_months: u32,
7239
7240 #[serde(default)]
7242 pub description: Option<String>,
7243}
7244
7245fn default_org_transition_months() -> u32 {
7246 6
7247}
7248
7249#[derive(Debug, Clone, Serialize, Deserialize)]
7251#[serde(tag = "type", rename_all = "snake_case")]
7252pub enum OrganizationalEventTypeSchemaConfig {
7253 Acquisition {
7255 acquired_entity: String,
7257 #[serde(default = "default_acquisition_volume")]
7259 volume_increase: f64,
7260 #[serde(default = "default_acquisition_error")]
7262 integration_error_rate: f64,
7263 #[serde(default = "default_parallel_days")]
7265 parallel_posting_days: u32,
7266 },
7267 Divestiture {
7269 divested_entity: String,
7271 #[serde(default = "default_divestiture_volume")]
7273 volume_reduction: f64,
7274 #[serde(default = "default_true_val")]
7276 remove_entity: bool,
7277 },
7278 Reorganization {
7280 #[serde(default)]
7282 cost_center_remapping: std::collections::HashMap<String, String>,
7283 #[serde(default = "default_reorg_error")]
7285 transition_error_rate: f64,
7286 },
7287 LeadershipChange {
7289 role: String,
7291 #[serde(default)]
7293 policy_changes: Vec<String>,
7294 },
7295 WorkforceReduction {
7297 #[serde(default = "default_workforce_reduction")]
7299 reduction_percent: f64,
7300 #[serde(default = "default_workforce_error")]
7302 error_rate_increase: f64,
7303 },
7304 Merger {
7306 merged_entity: String,
7308 #[serde(default = "default_merger_volume")]
7310 volume_increase: f64,
7311 },
7312}
7313
7314fn default_acquisition_volume() -> f64 {
7315 1.35
7316}
7317
7318fn default_acquisition_error() -> f64 {
7319 0.05
7320}
7321
7322fn default_parallel_days() -> u32 {
7323 30
7324}
7325
7326fn default_divestiture_volume() -> f64 {
7327 0.70
7328}
7329
7330fn default_true_val() -> bool {
7331 true
7332}
7333
7334fn default_reorg_error() -> f64 {
7335 0.04
7336}
7337
7338fn default_workforce_reduction() -> f64 {
7339 0.10
7340}
7341
7342fn default_workforce_error() -> f64 {
7343 0.05
7344}
7345
7346fn default_merger_volume() -> f64 {
7347 1.80
7348}
7349
7350#[derive(Debug, Clone, Serialize, Deserialize)]
7352pub struct ProcessEvolutionSchemaConfig {
7353 pub id: String,
7355
7356 pub event_type: ProcessEvolutionTypeSchemaConfig,
7358
7359 pub effective_date: String,
7361
7362 #[serde(default)]
7364 pub description: Option<String>,
7365}
7366
7367#[derive(Debug, Clone, Serialize, Deserialize)]
7369#[serde(tag = "type", rename_all = "snake_case")]
7370pub enum ProcessEvolutionTypeSchemaConfig {
7371 ProcessAutomation {
7373 process_name: String,
7375 #[serde(default = "default_manual_before")]
7377 manual_rate_before: f64,
7378 #[serde(default = "default_manual_after")]
7380 manual_rate_after: f64,
7381 },
7382 ApprovalWorkflowChange {
7384 description: String,
7386 },
7387 ControlEnhancement {
7389 control_id: String,
7391 #[serde(default = "default_error_reduction")]
7393 error_reduction: f64,
7394 },
7395}
7396
7397fn default_manual_before() -> f64 {
7398 0.80
7399}
7400
7401fn default_manual_after() -> f64 {
7402 0.15
7403}
7404
7405fn default_error_reduction() -> f64 {
7406 0.02
7407}
7408
7409#[derive(Debug, Clone, Serialize, Deserialize)]
7411pub struct TechnologyTransitionSchemaConfig {
7412 pub id: String,
7414
7415 pub event_type: TechnologyTransitionTypeSchemaConfig,
7417
7418 #[serde(default)]
7420 pub description: Option<String>,
7421}
7422
7423#[derive(Debug, Clone, Serialize, Deserialize)]
7425#[serde(tag = "type", rename_all = "snake_case")]
7426pub enum TechnologyTransitionTypeSchemaConfig {
7427 ErpMigration {
7429 source_system: String,
7431 target_system: String,
7433 cutover_date: String,
7435 stabilization_end: String,
7437 #[serde(default = "default_erp_duplicate_rate")]
7439 duplicate_rate: f64,
7440 #[serde(default = "default_format_mismatch")]
7442 format_mismatch_rate: f64,
7443 },
7444 ModuleImplementation {
7446 module_name: String,
7448 go_live_date: String,
7450 },
7451}
7452
7453fn default_erp_duplicate_rate() -> f64 {
7454 0.02
7455}
7456
7457fn default_format_mismatch() -> f64 {
7458 0.03
7459}
7460
7461#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7467pub struct BehavioralDriftSchemaConfig {
7468 #[serde(default)]
7470 pub enabled: bool,
7471
7472 #[serde(default)]
7474 pub vendor_behavior: VendorBehaviorSchemaConfig,
7475
7476 #[serde(default)]
7478 pub customer_behavior: CustomerBehaviorSchemaConfig,
7479
7480 #[serde(default)]
7482 pub employee_behavior: EmployeeBehaviorSchemaConfig,
7483
7484 #[serde(default)]
7486 pub collective: CollectiveBehaviorSchemaConfig,
7487}
7488
7489#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7491pub struct VendorBehaviorSchemaConfig {
7492 #[serde(default)]
7494 pub payment_terms_drift: PaymentTermsDriftSchemaConfig,
7495
7496 #[serde(default)]
7498 pub quality_drift: QualityDriftSchemaConfig,
7499}
7500
7501#[derive(Debug, Clone, Serialize, Deserialize)]
7503pub struct PaymentTermsDriftSchemaConfig {
7504 #[serde(default = "default_extension_rate")]
7506 pub extension_rate_per_year: f64,
7507
7508 #[serde(default = "default_economic_sensitivity")]
7510 pub economic_sensitivity: f64,
7511}
7512
7513fn default_extension_rate() -> f64 {
7514 2.5
7515}
7516
7517fn default_economic_sensitivity() -> f64 {
7518 1.0
7519}
7520
7521impl Default for PaymentTermsDriftSchemaConfig {
7522 fn default() -> Self {
7523 Self {
7524 extension_rate_per_year: 2.5,
7525 economic_sensitivity: 1.0,
7526 }
7527 }
7528}
7529
7530#[derive(Debug, Clone, Serialize, Deserialize)]
7532pub struct QualityDriftSchemaConfig {
7533 #[serde(default = "default_improvement_rate")]
7535 pub new_vendor_improvement_rate: f64,
7536
7537 #[serde(default = "default_decline_rate")]
7539 pub complacency_decline_rate: f64,
7540}
7541
7542fn default_improvement_rate() -> f64 {
7543 0.02
7544}
7545
7546fn default_decline_rate() -> f64 {
7547 0.01
7548}
7549
7550impl Default for QualityDriftSchemaConfig {
7551 fn default() -> Self {
7552 Self {
7553 new_vendor_improvement_rate: 0.02,
7554 complacency_decline_rate: 0.01,
7555 }
7556 }
7557}
7558
7559#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7561pub struct CustomerBehaviorSchemaConfig {
7562 #[serde(default)]
7564 pub payment_drift: CustomerPaymentDriftSchemaConfig,
7565
7566 #[serde(default)]
7568 pub order_drift: OrderDriftSchemaConfig,
7569}
7570
7571#[derive(Debug, Clone, Serialize, Deserialize)]
7573pub struct CustomerPaymentDriftSchemaConfig {
7574 #[serde(default = "default_downturn_extension")]
7576 pub downturn_days_extension: (u32, u32),
7577
7578 #[serde(default = "default_bad_debt_increase")]
7580 pub downturn_bad_debt_increase: f64,
7581}
7582
7583fn default_downturn_extension() -> (u32, u32) {
7584 (5, 15)
7585}
7586
7587fn default_bad_debt_increase() -> f64 {
7588 0.02
7589}
7590
7591impl Default for CustomerPaymentDriftSchemaConfig {
7592 fn default() -> Self {
7593 Self {
7594 downturn_days_extension: (5, 15),
7595 downturn_bad_debt_increase: 0.02,
7596 }
7597 }
7598}
7599
7600#[derive(Debug, Clone, Serialize, Deserialize)]
7602pub struct OrderDriftSchemaConfig {
7603 #[serde(default = "default_digital_shift")]
7605 pub digital_shift_rate: f64,
7606}
7607
7608fn default_digital_shift() -> f64 {
7609 0.05
7610}
7611
7612impl Default for OrderDriftSchemaConfig {
7613 fn default() -> Self {
7614 Self {
7615 digital_shift_rate: 0.05,
7616 }
7617 }
7618}
7619
7620#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7622pub struct EmployeeBehaviorSchemaConfig {
7623 #[serde(default)]
7625 pub approval_drift: ApprovalDriftSchemaConfig,
7626
7627 #[serde(default)]
7629 pub error_drift: ErrorDriftSchemaConfig,
7630}
7631
7632#[derive(Debug, Clone, Serialize, Deserialize)]
7634pub struct ApprovalDriftSchemaConfig {
7635 #[serde(default = "default_eom_intensity")]
7637 pub eom_intensity_increase_per_year: f64,
7638
7639 #[serde(default = "default_rubber_stamp")]
7641 pub rubber_stamp_volume_threshold: u32,
7642}
7643
7644fn default_eom_intensity() -> f64 {
7645 0.05
7646}
7647
7648fn default_rubber_stamp() -> u32 {
7649 50
7650}
7651
7652impl Default for ApprovalDriftSchemaConfig {
7653 fn default() -> Self {
7654 Self {
7655 eom_intensity_increase_per_year: 0.05,
7656 rubber_stamp_volume_threshold: 50,
7657 }
7658 }
7659}
7660
7661#[derive(Debug, Clone, Serialize, Deserialize)]
7663pub struct ErrorDriftSchemaConfig {
7664 #[serde(default = "default_new_error")]
7666 pub new_employee_error_rate: f64,
7667
7668 #[serde(default = "default_learning_months")]
7670 pub learning_curve_months: u32,
7671}
7672
7673fn default_new_error() -> f64 {
7674 0.08
7675}
7676
7677fn default_learning_months() -> u32 {
7678 6
7679}
7680
7681impl Default for ErrorDriftSchemaConfig {
7682 fn default() -> Self {
7683 Self {
7684 new_employee_error_rate: 0.08,
7685 learning_curve_months: 6,
7686 }
7687 }
7688}
7689
7690#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7692pub struct CollectiveBehaviorSchemaConfig {
7693 #[serde(default)]
7695 pub automation_adoption: AutomationAdoptionSchemaConfig,
7696}
7697
7698#[derive(Debug, Clone, Serialize, Deserialize)]
7700pub struct AutomationAdoptionSchemaConfig {
7701 #[serde(default)]
7703 pub s_curve_enabled: bool,
7704
7705 #[serde(default = "default_midpoint")]
7707 pub adoption_midpoint_months: u32,
7708
7709 #[serde(default = "default_steepness")]
7711 pub steepness: f64,
7712}
7713
7714fn default_midpoint() -> u32 {
7715 24
7716}
7717
7718fn default_steepness() -> f64 {
7719 0.15
7720}
7721
7722impl Default for AutomationAdoptionSchemaConfig {
7723 fn default() -> Self {
7724 Self {
7725 s_curve_enabled: false,
7726 adoption_midpoint_months: 24,
7727 steepness: 0.15,
7728 }
7729 }
7730}
7731
7732#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7738pub struct MarketDriftSchemaConfig {
7739 #[serde(default)]
7741 pub enabled: bool,
7742
7743 #[serde(default)]
7745 pub economic_cycle: MarketEconomicCycleSchemaConfig,
7746
7747 #[serde(default)]
7749 pub industry_cycles: std::collections::HashMap<String, IndustryCycleSchemaConfig>,
7750
7751 #[serde(default)]
7753 pub commodities: CommoditiesSchemaConfig,
7754}
7755
7756#[derive(Debug, Clone, Serialize, Deserialize)]
7758pub struct MarketEconomicCycleSchemaConfig {
7759 #[serde(default)]
7761 pub enabled: bool,
7762
7763 #[serde(default)]
7765 pub cycle_type: CycleTypeSchemaConfig,
7766
7767 #[serde(default = "default_market_cycle_period")]
7769 pub period_months: u32,
7770
7771 #[serde(default = "default_market_amplitude")]
7773 pub amplitude: f64,
7774
7775 #[serde(default)]
7777 pub recession: RecessionSchemaConfig,
7778}
7779
7780fn default_market_cycle_period() -> u32 {
7781 48
7782}
7783
7784fn default_market_amplitude() -> f64 {
7785 0.15
7786}
7787
7788impl Default for MarketEconomicCycleSchemaConfig {
7789 fn default() -> Self {
7790 Self {
7791 enabled: false,
7792 cycle_type: CycleTypeSchemaConfig::Sinusoidal,
7793 period_months: 48,
7794 amplitude: 0.15,
7795 recession: RecessionSchemaConfig::default(),
7796 }
7797 }
7798}
7799
7800#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
7802#[serde(rename_all = "snake_case")]
7803pub enum CycleTypeSchemaConfig {
7804 #[default]
7806 Sinusoidal,
7807 Asymmetric,
7809 MeanReverting,
7811}
7812
7813#[derive(Debug, Clone, Serialize, Deserialize)]
7815pub struct RecessionSchemaConfig {
7816 #[serde(default)]
7818 pub enabled: bool,
7819
7820 #[serde(default = "default_recession_prob")]
7822 pub probability_per_year: f64,
7823
7824 #[serde(default)]
7826 pub severity: RecessionSeveritySchemaConfig,
7827
7828 #[serde(default)]
7830 pub recession_periods: Vec<RecessionPeriodSchemaConfig>,
7831}
7832
7833fn default_recession_prob() -> f64 {
7834 0.10
7835}
7836
7837impl Default for RecessionSchemaConfig {
7838 fn default() -> Self {
7839 Self {
7840 enabled: false,
7841 probability_per_year: 0.10,
7842 severity: RecessionSeveritySchemaConfig::Moderate,
7843 recession_periods: Vec::new(),
7844 }
7845 }
7846}
7847
7848#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
7850#[serde(rename_all = "snake_case")]
7851pub enum RecessionSeveritySchemaConfig {
7852 Mild,
7854 #[default]
7856 Moderate,
7857 Severe,
7859}
7860
7861#[derive(Debug, Clone, Serialize, Deserialize)]
7863pub struct RecessionPeriodSchemaConfig {
7864 pub start_month: u32,
7866 pub duration_months: u32,
7868}
7869
7870#[derive(Debug, Clone, Serialize, Deserialize)]
7872pub struct IndustryCycleSchemaConfig {
7873 #[serde(default = "default_industry_period")]
7875 pub period_months: u32,
7876
7877 #[serde(default = "default_industry_amp")]
7879 pub amplitude: f64,
7880}
7881
7882fn default_industry_period() -> u32 {
7883 36
7884}
7885
7886fn default_industry_amp() -> f64 {
7887 0.20
7888}
7889
7890#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7892pub struct CommoditiesSchemaConfig {
7893 #[serde(default)]
7895 pub enabled: bool,
7896
7897 #[serde(default)]
7899 pub items: Vec<CommodityItemSchemaConfig>,
7900}
7901
7902#[derive(Debug, Clone, Serialize, Deserialize)]
7904pub struct CommodityItemSchemaConfig {
7905 pub name: String,
7907
7908 #[serde(default = "default_volatility")]
7910 pub volatility: f64,
7911
7912 #[serde(default)]
7914 pub cogs_pass_through: f64,
7915
7916 #[serde(default)]
7918 pub overhead_pass_through: f64,
7919}
7920
7921fn default_volatility() -> f64 {
7922 0.20
7923}
7924
7925#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7931pub struct DriftLabelingSchemaConfig {
7932 #[serde(default)]
7934 pub enabled: bool,
7935
7936 #[serde(default)]
7938 pub statistical: StatisticalDriftLabelingSchemaConfig,
7939
7940 #[serde(default)]
7942 pub categorical: CategoricalDriftLabelingSchemaConfig,
7943
7944 #[serde(default)]
7946 pub temporal: TemporalDriftLabelingSchemaConfig,
7947
7948 #[serde(default)]
7950 pub regulatory_calendar_preset: Option<String>,
7951}
7952
7953#[derive(Debug, Clone, Serialize, Deserialize)]
7955pub struct StatisticalDriftLabelingSchemaConfig {
7956 #[serde(default = "default_true_val")]
7958 pub enabled: bool,
7959
7960 #[serde(default = "default_min_magnitude")]
7962 pub min_magnitude_threshold: f64,
7963}
7964
7965fn default_min_magnitude() -> f64 {
7966 0.05
7967}
7968
7969impl Default for StatisticalDriftLabelingSchemaConfig {
7970 fn default() -> Self {
7971 Self {
7972 enabled: true,
7973 min_magnitude_threshold: 0.05,
7974 }
7975 }
7976}
7977
7978#[derive(Debug, Clone, Serialize, Deserialize)]
7980pub struct CategoricalDriftLabelingSchemaConfig {
7981 #[serde(default = "default_true_val")]
7983 pub enabled: bool,
7984}
7985
7986impl Default for CategoricalDriftLabelingSchemaConfig {
7987 fn default() -> Self {
7988 Self { enabled: true }
7989 }
7990}
7991
7992#[derive(Debug, Clone, Serialize, Deserialize)]
7994pub struct TemporalDriftLabelingSchemaConfig {
7995 #[serde(default = "default_true_val")]
7997 pub enabled: bool,
7998}
7999
8000impl Default for TemporalDriftLabelingSchemaConfig {
8001 fn default() -> Self {
8002 Self { enabled: true }
8003 }
8004}
8005
8006#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8019pub struct EnhancedAnomalyConfig {
8020 #[serde(default)]
8022 pub enabled: bool,
8023
8024 #[serde(default)]
8026 pub rates: AnomalyRateConfig,
8027
8028 #[serde(default)]
8030 pub multi_stage_schemes: MultiStageSchemeConfig,
8031
8032 #[serde(default)]
8034 pub correlated_injection: CorrelatedInjectionConfig,
8035
8036 #[serde(default)]
8038 pub near_miss: NearMissConfig,
8039
8040 #[serde(default)]
8042 pub difficulty_classification: DifficultyClassificationConfig,
8043
8044 #[serde(default)]
8046 pub context_aware: ContextAwareConfig,
8047
8048 #[serde(default)]
8050 pub labeling: EnhancedLabelingConfig,
8051}
8052
8053#[derive(Debug, Clone, Serialize, Deserialize)]
8055pub struct AnomalyRateConfig {
8056 #[serde(default = "default_total_anomaly_rate")]
8058 pub total_rate: f64,
8059
8060 #[serde(default = "default_fraud_anomaly_rate")]
8062 pub fraud_rate: f64,
8063
8064 #[serde(default = "default_error_anomaly_rate")]
8066 pub error_rate: f64,
8067
8068 #[serde(default = "default_process_anomaly_rate")]
8070 pub process_rate: f64,
8071}
8072
8073fn default_total_anomaly_rate() -> f64 {
8074 0.03
8075}
8076fn default_fraud_anomaly_rate() -> f64 {
8077 0.01
8078}
8079fn default_error_anomaly_rate() -> f64 {
8080 0.015
8081}
8082fn default_process_anomaly_rate() -> f64 {
8083 0.005
8084}
8085
8086impl Default for AnomalyRateConfig {
8087 fn default() -> Self {
8088 Self {
8089 total_rate: default_total_anomaly_rate(),
8090 fraud_rate: default_fraud_anomaly_rate(),
8091 error_rate: default_error_anomaly_rate(),
8092 process_rate: default_process_anomaly_rate(),
8093 }
8094 }
8095}
8096
8097#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8099pub struct MultiStageSchemeConfig {
8100 #[serde(default)]
8102 pub enabled: bool,
8103
8104 #[serde(default)]
8106 pub embezzlement: EmbezzlementSchemeConfig,
8107
8108 #[serde(default)]
8110 pub revenue_manipulation: RevenueManipulationSchemeConfig,
8111
8112 #[serde(default)]
8114 pub kickback: KickbackSchemeConfig,
8115}
8116
8117#[derive(Debug, Clone, Serialize, Deserialize)]
8119pub struct EmbezzlementSchemeConfig {
8120 #[serde(default = "default_embezzlement_probability")]
8122 pub probability: f64,
8123
8124 #[serde(default)]
8126 pub testing_stage: SchemeStageConfig,
8127
8128 #[serde(default)]
8130 pub escalation_stage: SchemeStageConfig,
8131
8132 #[serde(default)]
8134 pub acceleration_stage: SchemeStageConfig,
8135
8136 #[serde(default)]
8138 pub desperation_stage: SchemeStageConfig,
8139}
8140
8141fn default_embezzlement_probability() -> f64 {
8142 0.02
8143}
8144
8145impl Default for EmbezzlementSchemeConfig {
8146 fn default() -> Self {
8147 Self {
8148 probability: default_embezzlement_probability(),
8149 testing_stage: SchemeStageConfig {
8150 duration_months: 2,
8151 amount_min: 100.0,
8152 amount_max: 500.0,
8153 transaction_count_min: 2,
8154 transaction_count_max: 5,
8155 difficulty: "hard".to_string(),
8156 },
8157 escalation_stage: SchemeStageConfig {
8158 duration_months: 6,
8159 amount_min: 500.0,
8160 amount_max: 2000.0,
8161 transaction_count_min: 3,
8162 transaction_count_max: 8,
8163 difficulty: "moderate".to_string(),
8164 },
8165 acceleration_stage: SchemeStageConfig {
8166 duration_months: 3,
8167 amount_min: 2000.0,
8168 amount_max: 10000.0,
8169 transaction_count_min: 5,
8170 transaction_count_max: 12,
8171 difficulty: "easy".to_string(),
8172 },
8173 desperation_stage: SchemeStageConfig {
8174 duration_months: 1,
8175 amount_min: 10000.0,
8176 amount_max: 50000.0,
8177 transaction_count_min: 3,
8178 transaction_count_max: 6,
8179 difficulty: "trivial".to_string(),
8180 },
8181 }
8182 }
8183}
8184
8185#[derive(Debug, Clone, Serialize, Deserialize)]
8187pub struct RevenueManipulationSchemeConfig {
8188 #[serde(default = "default_revenue_manipulation_probability")]
8190 pub probability: f64,
8191
8192 #[serde(default = "default_early_recognition_target")]
8194 pub early_recognition_target: f64,
8195
8196 #[serde(default = "default_expense_deferral_target")]
8198 pub expense_deferral_target: f64,
8199
8200 #[serde(default = "default_reserve_release_target")]
8202 pub reserve_release_target: f64,
8203
8204 #[serde(default = "default_channel_stuffing_target")]
8206 pub channel_stuffing_target: f64,
8207}
8208
8209fn default_revenue_manipulation_probability() -> f64 {
8210 0.01
8211}
8212fn default_early_recognition_target() -> f64 {
8213 0.02
8214}
8215fn default_expense_deferral_target() -> f64 {
8216 0.03
8217}
8218fn default_reserve_release_target() -> f64 {
8219 0.02
8220}
8221fn default_channel_stuffing_target() -> f64 {
8222 0.05
8223}
8224
8225impl Default for RevenueManipulationSchemeConfig {
8226 fn default() -> Self {
8227 Self {
8228 probability: default_revenue_manipulation_probability(),
8229 early_recognition_target: default_early_recognition_target(),
8230 expense_deferral_target: default_expense_deferral_target(),
8231 reserve_release_target: default_reserve_release_target(),
8232 channel_stuffing_target: default_channel_stuffing_target(),
8233 }
8234 }
8235}
8236
8237#[derive(Debug, Clone, Serialize, Deserialize)]
8239pub struct KickbackSchemeConfig {
8240 #[serde(default = "default_kickback_probability")]
8242 pub probability: f64,
8243
8244 #[serde(default = "default_kickback_inflation_min")]
8246 pub inflation_min: f64,
8247
8248 #[serde(default = "default_kickback_inflation_max")]
8250 pub inflation_max: f64,
8251
8252 #[serde(default = "default_kickback_percent")]
8254 pub kickback_percent: f64,
8255
8256 #[serde(default = "default_kickback_setup_months")]
8258 pub setup_months: u32,
8259
8260 #[serde(default = "default_kickback_operation_months")]
8262 pub operation_months: u32,
8263}
8264
8265fn default_kickback_probability() -> f64 {
8266 0.01
8267}
8268fn default_kickback_inflation_min() -> f64 {
8269 0.10
8270}
8271fn default_kickback_inflation_max() -> f64 {
8272 0.25
8273}
8274fn default_kickback_percent() -> f64 {
8275 0.50
8276}
8277fn default_kickback_setup_months() -> u32 {
8278 3
8279}
8280fn default_kickback_operation_months() -> u32 {
8281 12
8282}
8283
8284impl Default for KickbackSchemeConfig {
8285 fn default() -> Self {
8286 Self {
8287 probability: default_kickback_probability(),
8288 inflation_min: default_kickback_inflation_min(),
8289 inflation_max: default_kickback_inflation_max(),
8290 kickback_percent: default_kickback_percent(),
8291 setup_months: default_kickback_setup_months(),
8292 operation_months: default_kickback_operation_months(),
8293 }
8294 }
8295}
8296
8297#[derive(Debug, Clone, Serialize, Deserialize)]
8299pub struct SchemeStageConfig {
8300 pub duration_months: u32,
8302
8303 pub amount_min: f64,
8305
8306 pub amount_max: f64,
8308
8309 pub transaction_count_min: u32,
8311
8312 pub transaction_count_max: u32,
8314
8315 pub difficulty: String,
8317}
8318
8319impl Default for SchemeStageConfig {
8320 fn default() -> Self {
8321 Self {
8322 duration_months: 3,
8323 amount_min: 100.0,
8324 amount_max: 1000.0,
8325 transaction_count_min: 2,
8326 transaction_count_max: 10,
8327 difficulty: "moderate".to_string(),
8328 }
8329 }
8330}
8331
8332#[derive(Debug, Clone, Serialize, Deserialize)]
8334pub struct CorrelatedInjectionConfig {
8335 #[serde(default)]
8337 pub enabled: bool,
8338
8339 #[serde(default = "default_true_val")]
8341 pub fraud_concealment: bool,
8342
8343 #[serde(default = "default_true_val")]
8345 pub error_cascade: bool,
8346
8347 #[serde(default = "default_true_val")]
8349 pub temporal_clustering: bool,
8350
8351 #[serde(default)]
8353 pub temporal_clustering_config: TemporalClusteringConfig,
8354
8355 #[serde(default)]
8357 pub co_occurrence_patterns: Vec<CoOccurrencePatternConfig>,
8358}
8359
8360impl Default for CorrelatedInjectionConfig {
8361 fn default() -> Self {
8362 Self {
8363 enabled: false,
8364 fraud_concealment: true,
8365 error_cascade: true,
8366 temporal_clustering: true,
8367 temporal_clustering_config: TemporalClusteringConfig::default(),
8368 co_occurrence_patterns: Vec::new(),
8369 }
8370 }
8371}
8372
8373#[derive(Debug, Clone, Serialize, Deserialize)]
8375pub struct TemporalClusteringConfig {
8376 #[serde(default = "default_period_end_multiplier")]
8378 pub period_end_multiplier: f64,
8379
8380 #[serde(default = "default_period_end_days")]
8382 pub period_end_days: u32,
8383
8384 #[serde(default = "default_quarter_end_multiplier")]
8386 pub quarter_end_multiplier: f64,
8387
8388 #[serde(default = "default_year_end_multiplier")]
8390 pub year_end_multiplier: f64,
8391}
8392
8393fn default_period_end_multiplier() -> f64 {
8394 2.5
8395}
8396fn default_period_end_days() -> u32 {
8397 5
8398}
8399fn default_quarter_end_multiplier() -> f64 {
8400 1.5
8401}
8402fn default_year_end_multiplier() -> f64 {
8403 2.0
8404}
8405
8406impl Default for TemporalClusteringConfig {
8407 fn default() -> Self {
8408 Self {
8409 period_end_multiplier: default_period_end_multiplier(),
8410 period_end_days: default_period_end_days(),
8411 quarter_end_multiplier: default_quarter_end_multiplier(),
8412 year_end_multiplier: default_year_end_multiplier(),
8413 }
8414 }
8415}
8416
8417#[derive(Debug, Clone, Serialize, Deserialize)]
8419pub struct CoOccurrencePatternConfig {
8420 pub name: String,
8422
8423 pub primary_type: String,
8425
8426 pub correlated: Vec<CorrelatedAnomalyConfig>,
8428}
8429
8430#[derive(Debug, Clone, Serialize, Deserialize)]
8432pub struct CorrelatedAnomalyConfig {
8433 pub anomaly_type: String,
8435
8436 pub probability: f64,
8438
8439 pub lag_days_min: i32,
8441
8442 pub lag_days_max: i32,
8444}
8445
8446#[derive(Debug, Clone, Serialize, Deserialize)]
8448pub struct NearMissConfig {
8449 #[serde(default)]
8451 pub enabled: bool,
8452
8453 #[serde(default = "default_near_miss_proportion")]
8455 pub proportion: f64,
8456
8457 #[serde(default = "default_true_val")]
8459 pub near_duplicate: bool,
8460
8461 #[serde(default)]
8463 pub near_duplicate_days: NearDuplicateDaysConfig,
8464
8465 #[serde(default = "default_true_val")]
8467 pub threshold_proximity: bool,
8468
8469 #[serde(default)]
8471 pub threshold_proximity_range: ThresholdProximityRangeConfig,
8472
8473 #[serde(default = "default_true_val")]
8475 pub unusual_legitimate: bool,
8476
8477 #[serde(default = "default_unusual_legitimate_types")]
8479 pub unusual_legitimate_types: Vec<String>,
8480
8481 #[serde(default = "default_true_val")]
8483 pub corrected_errors: bool,
8484
8485 #[serde(default)]
8487 pub corrected_error_lag: CorrectedErrorLagConfig,
8488}
8489
8490fn default_near_miss_proportion() -> f64 {
8491 0.30
8492}
8493
8494fn default_unusual_legitimate_types() -> Vec<String> {
8495 vec![
8496 "year_end_bonus".to_string(),
8497 "contract_prepayment".to_string(),
8498 "insurance_claim".to_string(),
8499 "settlement_payment".to_string(),
8500 ]
8501}
8502
8503impl Default for NearMissConfig {
8504 fn default() -> Self {
8505 Self {
8506 enabled: false,
8507 proportion: default_near_miss_proportion(),
8508 near_duplicate: true,
8509 near_duplicate_days: NearDuplicateDaysConfig::default(),
8510 threshold_proximity: true,
8511 threshold_proximity_range: ThresholdProximityRangeConfig::default(),
8512 unusual_legitimate: true,
8513 unusual_legitimate_types: default_unusual_legitimate_types(),
8514 corrected_errors: true,
8515 corrected_error_lag: CorrectedErrorLagConfig::default(),
8516 }
8517 }
8518}
8519
8520#[derive(Debug, Clone, Serialize, Deserialize)]
8522pub struct NearDuplicateDaysConfig {
8523 #[serde(default = "default_near_duplicate_min")]
8525 pub min: u32,
8526
8527 #[serde(default = "default_near_duplicate_max")]
8529 pub max: u32,
8530}
8531
8532fn default_near_duplicate_min() -> u32 {
8533 1
8534}
8535fn default_near_duplicate_max() -> u32 {
8536 3
8537}
8538
8539impl Default for NearDuplicateDaysConfig {
8540 fn default() -> Self {
8541 Self {
8542 min: default_near_duplicate_min(),
8543 max: default_near_duplicate_max(),
8544 }
8545 }
8546}
8547
8548#[derive(Debug, Clone, Serialize, Deserialize)]
8550pub struct ThresholdProximityRangeConfig {
8551 #[serde(default = "default_threshold_proximity_min")]
8553 pub min: f64,
8554
8555 #[serde(default = "default_threshold_proximity_max")]
8557 pub max: f64,
8558}
8559
8560fn default_threshold_proximity_min() -> f64 {
8561 0.90
8562}
8563fn default_threshold_proximity_max() -> f64 {
8564 0.99
8565}
8566
8567impl Default for ThresholdProximityRangeConfig {
8568 fn default() -> Self {
8569 Self {
8570 min: default_threshold_proximity_min(),
8571 max: default_threshold_proximity_max(),
8572 }
8573 }
8574}
8575
8576#[derive(Debug, Clone, Serialize, Deserialize)]
8578pub struct CorrectedErrorLagConfig {
8579 #[serde(default = "default_corrected_error_lag_min")]
8581 pub min: u32,
8582
8583 #[serde(default = "default_corrected_error_lag_max")]
8585 pub max: u32,
8586}
8587
8588fn default_corrected_error_lag_min() -> u32 {
8589 1
8590}
8591fn default_corrected_error_lag_max() -> u32 {
8592 5
8593}
8594
8595impl Default for CorrectedErrorLagConfig {
8596 fn default() -> Self {
8597 Self {
8598 min: default_corrected_error_lag_min(),
8599 max: default_corrected_error_lag_max(),
8600 }
8601 }
8602}
8603
8604#[derive(Debug, Clone, Serialize, Deserialize)]
8606pub struct DifficultyClassificationConfig {
8607 #[serde(default)]
8609 pub enabled: bool,
8610
8611 #[serde(default)]
8613 pub target_distribution: DifficultyDistributionConfig,
8614}
8615
8616impl Default for DifficultyClassificationConfig {
8617 fn default() -> Self {
8618 Self {
8619 enabled: true,
8620 target_distribution: DifficultyDistributionConfig::default(),
8621 }
8622 }
8623}
8624
8625#[derive(Debug, Clone, Serialize, Deserialize)]
8627pub struct DifficultyDistributionConfig {
8628 #[serde(default = "default_difficulty_trivial")]
8630 pub trivial: f64,
8631
8632 #[serde(default = "default_difficulty_easy")]
8634 pub easy: f64,
8635
8636 #[serde(default = "default_difficulty_moderate")]
8638 pub moderate: f64,
8639
8640 #[serde(default = "default_difficulty_hard")]
8642 pub hard: f64,
8643
8644 #[serde(default = "default_difficulty_expert")]
8646 pub expert: f64,
8647}
8648
8649fn default_difficulty_trivial() -> f64 {
8650 0.15
8651}
8652fn default_difficulty_easy() -> f64 {
8653 0.25
8654}
8655fn default_difficulty_moderate() -> f64 {
8656 0.30
8657}
8658fn default_difficulty_hard() -> f64 {
8659 0.20
8660}
8661fn default_difficulty_expert() -> f64 {
8662 0.10
8663}
8664
8665impl Default for DifficultyDistributionConfig {
8666 fn default() -> Self {
8667 Self {
8668 trivial: default_difficulty_trivial(),
8669 easy: default_difficulty_easy(),
8670 moderate: default_difficulty_moderate(),
8671 hard: default_difficulty_hard(),
8672 expert: default_difficulty_expert(),
8673 }
8674 }
8675}
8676
8677#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8679pub struct ContextAwareConfig {
8680 #[serde(default)]
8682 pub enabled: bool,
8683
8684 #[serde(default)]
8686 pub vendor_rules: VendorAnomalyRulesConfig,
8687
8688 #[serde(default)]
8690 pub employee_rules: EmployeeAnomalyRulesConfig,
8691
8692 #[serde(default)]
8694 pub account_rules: AccountAnomalyRulesConfig,
8695
8696 #[serde(default)]
8698 pub behavioral_baseline: BehavioralBaselineConfig,
8699}
8700
8701#[derive(Debug, Clone, Serialize, Deserialize)]
8703pub struct VendorAnomalyRulesConfig {
8704 #[serde(default = "default_new_vendor_multiplier")]
8706 pub new_vendor_error_multiplier: f64,
8707
8708 #[serde(default = "default_new_vendor_threshold")]
8710 pub new_vendor_threshold_days: u32,
8711
8712 #[serde(default = "default_international_multiplier")]
8714 pub international_error_multiplier: f64,
8715
8716 #[serde(default = "default_strategic_vendor_types")]
8718 pub strategic_vendor_anomaly_types: Vec<String>,
8719}
8720
8721fn default_new_vendor_multiplier() -> f64 {
8722 2.5
8723}
8724fn default_new_vendor_threshold() -> u32 {
8725 90
8726}
8727fn default_international_multiplier() -> f64 {
8728 1.5
8729}
8730fn default_strategic_vendor_types() -> Vec<String> {
8731 vec![
8732 "pricing_dispute".to_string(),
8733 "contract_violation".to_string(),
8734 ]
8735}
8736
8737impl Default for VendorAnomalyRulesConfig {
8738 fn default() -> Self {
8739 Self {
8740 new_vendor_error_multiplier: default_new_vendor_multiplier(),
8741 new_vendor_threshold_days: default_new_vendor_threshold(),
8742 international_error_multiplier: default_international_multiplier(),
8743 strategic_vendor_anomaly_types: default_strategic_vendor_types(),
8744 }
8745 }
8746}
8747
8748#[derive(Debug, Clone, Serialize, Deserialize)]
8750pub struct EmployeeAnomalyRulesConfig {
8751 #[serde(default = "default_new_employee_rate")]
8753 pub new_employee_error_rate: f64,
8754
8755 #[serde(default = "default_new_employee_threshold")]
8757 pub new_employee_threshold_days: u32,
8758
8759 #[serde(default = "default_volume_fatigue_threshold")]
8761 pub volume_fatigue_threshold: u32,
8762
8763 #[serde(default = "default_coverage_multiplier")]
8765 pub coverage_error_multiplier: f64,
8766}
8767
8768fn default_new_employee_rate() -> f64 {
8769 0.05
8770}
8771fn default_new_employee_threshold() -> u32 {
8772 180
8773}
8774fn default_volume_fatigue_threshold() -> u32 {
8775 50
8776}
8777fn default_coverage_multiplier() -> f64 {
8778 1.8
8779}
8780
8781impl Default for EmployeeAnomalyRulesConfig {
8782 fn default() -> Self {
8783 Self {
8784 new_employee_error_rate: default_new_employee_rate(),
8785 new_employee_threshold_days: default_new_employee_threshold(),
8786 volume_fatigue_threshold: default_volume_fatigue_threshold(),
8787 coverage_error_multiplier: default_coverage_multiplier(),
8788 }
8789 }
8790}
8791
8792#[derive(Debug, Clone, Serialize, Deserialize)]
8794pub struct AccountAnomalyRulesConfig {
8795 #[serde(default = "default_high_risk_multiplier")]
8797 pub high_risk_account_multiplier: f64,
8798
8799 #[serde(default = "default_high_risk_accounts")]
8801 pub high_risk_accounts: Vec<String>,
8802
8803 #[serde(default = "default_suspense_multiplier")]
8805 pub suspense_account_multiplier: f64,
8806
8807 #[serde(default = "default_suspense_accounts")]
8809 pub suspense_accounts: Vec<String>,
8810
8811 #[serde(default = "default_intercompany_multiplier")]
8813 pub intercompany_account_multiplier: f64,
8814}
8815
8816fn default_high_risk_multiplier() -> f64 {
8817 2.0
8818}
8819fn default_high_risk_accounts() -> Vec<String> {
8820 vec![
8821 "1100".to_string(), "2000".to_string(), "3000".to_string(), ]
8825}
8826fn default_suspense_multiplier() -> f64 {
8827 3.0
8828}
8829fn default_suspense_accounts() -> Vec<String> {
8830 vec!["9999".to_string(), "9998".to_string()]
8831}
8832fn default_intercompany_multiplier() -> f64 {
8833 1.5
8834}
8835
8836impl Default for AccountAnomalyRulesConfig {
8837 fn default() -> Self {
8838 Self {
8839 high_risk_account_multiplier: default_high_risk_multiplier(),
8840 high_risk_accounts: default_high_risk_accounts(),
8841 suspense_account_multiplier: default_suspense_multiplier(),
8842 suspense_accounts: default_suspense_accounts(),
8843 intercompany_account_multiplier: default_intercompany_multiplier(),
8844 }
8845 }
8846}
8847
8848#[derive(Debug, Clone, Serialize, Deserialize)]
8850pub struct BehavioralBaselineConfig {
8851 #[serde(default)]
8853 pub enabled: bool,
8854
8855 #[serde(default = "default_baseline_period")]
8857 pub baseline_period_days: u32,
8858
8859 #[serde(default = "default_deviation_threshold")]
8861 pub deviation_threshold_std: f64,
8862
8863 #[serde(default = "default_frequency_deviation")]
8865 pub frequency_deviation_threshold: f64,
8866}
8867
8868fn default_baseline_period() -> u32 {
8869 90
8870}
8871fn default_deviation_threshold() -> f64 {
8872 3.0
8873}
8874fn default_frequency_deviation() -> f64 {
8875 2.0
8876}
8877
8878impl Default for BehavioralBaselineConfig {
8879 fn default() -> Self {
8880 Self {
8881 enabled: false,
8882 baseline_period_days: default_baseline_period(),
8883 deviation_threshold_std: default_deviation_threshold(),
8884 frequency_deviation_threshold: default_frequency_deviation(),
8885 }
8886 }
8887}
8888
8889#[derive(Debug, Clone, Serialize, Deserialize)]
8891pub struct EnhancedLabelingConfig {
8892 #[serde(default = "default_true_val")]
8894 pub severity_scoring: bool,
8895
8896 #[serde(default = "default_true_val")]
8898 pub difficulty_classification: bool,
8899
8900 #[serde(default)]
8902 pub materiality_thresholds: MaterialityThresholdsConfig,
8903}
8904
8905impl Default for EnhancedLabelingConfig {
8906 fn default() -> Self {
8907 Self {
8908 severity_scoring: true,
8909 difficulty_classification: true,
8910 materiality_thresholds: MaterialityThresholdsConfig::default(),
8911 }
8912 }
8913}
8914
8915#[derive(Debug, Clone, Serialize, Deserialize)]
8917pub struct MaterialityThresholdsConfig {
8918 #[serde(default = "default_materiality_trivial")]
8920 pub trivial: f64,
8921
8922 #[serde(default = "default_materiality_immaterial")]
8924 pub immaterial: f64,
8925
8926 #[serde(default = "default_materiality_material")]
8928 pub material: f64,
8929
8930 #[serde(default = "default_materiality_highly_material")]
8932 pub highly_material: f64,
8933}
8934
8935fn default_materiality_trivial() -> f64 {
8936 0.001
8937}
8938fn default_materiality_immaterial() -> f64 {
8939 0.01
8940}
8941fn default_materiality_material() -> f64 {
8942 0.05
8943}
8944fn default_materiality_highly_material() -> f64 {
8945 0.10
8946}
8947
8948impl Default for MaterialityThresholdsConfig {
8949 fn default() -> Self {
8950 Self {
8951 trivial: default_materiality_trivial(),
8952 immaterial: default_materiality_immaterial(),
8953 material: default_materiality_material(),
8954 highly_material: default_materiality_highly_material(),
8955 }
8956 }
8957}
8958
8959#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8971pub struct IndustrySpecificConfig {
8972 #[serde(default)]
8974 pub enabled: bool,
8975
8976 #[serde(default)]
8978 pub manufacturing: ManufacturingConfig,
8979
8980 #[serde(default)]
8982 pub retail: RetailConfig,
8983
8984 #[serde(default)]
8986 pub healthcare: HealthcareConfig,
8987
8988 #[serde(default)]
8990 pub technology: TechnologyConfig,
8991
8992 #[serde(default)]
8994 pub financial_services: FinancialServicesConfig,
8995
8996 #[serde(default)]
8998 pub professional_services: ProfessionalServicesConfig,
8999}
9000
9001#[derive(Debug, Clone, Serialize, Deserialize)]
9003pub struct ManufacturingConfig {
9004 #[serde(default)]
9006 pub enabled: bool,
9007
9008 #[serde(default = "default_bom_depth")]
9010 pub bom_depth: u32,
9011
9012 #[serde(default)]
9014 pub just_in_time: bool,
9015
9016 #[serde(default = "default_production_order_types")]
9018 pub production_order_types: Vec<String>,
9019
9020 #[serde(default)]
9022 pub quality_framework: Option<String>,
9023
9024 #[serde(default = "default_supplier_tiers")]
9026 pub supplier_tiers: u32,
9027
9028 #[serde(default = "default_cost_frequency")]
9030 pub standard_cost_frequency: String,
9031
9032 #[serde(default = "default_yield_rate")]
9034 pub target_yield_rate: f64,
9035
9036 #[serde(default = "default_scrap_threshold")]
9038 pub scrap_alert_threshold: f64,
9039
9040 #[serde(default)]
9042 pub anomaly_rates: ManufacturingAnomalyRates,
9043}
9044
9045fn default_bom_depth() -> u32 {
9046 4
9047}
9048
9049fn default_production_order_types() -> Vec<String> {
9050 vec![
9051 "standard".to_string(),
9052 "rework".to_string(),
9053 "prototype".to_string(),
9054 ]
9055}
9056
9057fn default_supplier_tiers() -> u32 {
9058 2
9059}
9060
9061fn default_cost_frequency() -> String {
9062 "quarterly".to_string()
9063}
9064
9065fn default_yield_rate() -> f64 {
9066 0.97
9067}
9068
9069fn default_scrap_threshold() -> f64 {
9070 0.03
9071}
9072
9073impl Default for ManufacturingConfig {
9074 fn default() -> Self {
9075 Self {
9076 enabled: false,
9077 bom_depth: default_bom_depth(),
9078 just_in_time: false,
9079 production_order_types: default_production_order_types(),
9080 quality_framework: Some("ISO_9001".to_string()),
9081 supplier_tiers: default_supplier_tiers(),
9082 standard_cost_frequency: default_cost_frequency(),
9083 target_yield_rate: default_yield_rate(),
9084 scrap_alert_threshold: default_scrap_threshold(),
9085 anomaly_rates: ManufacturingAnomalyRates::default(),
9086 }
9087 }
9088}
9089
9090#[derive(Debug, Clone, Serialize, Deserialize)]
9092pub struct ManufacturingAnomalyRates {
9093 #[serde(default = "default_mfg_yield_rate")]
9095 pub yield_manipulation: f64,
9096
9097 #[serde(default = "default_mfg_labor_rate")]
9099 pub labor_misallocation: f64,
9100
9101 #[serde(default = "default_mfg_phantom_rate")]
9103 pub phantom_production: f64,
9104
9105 #[serde(default = "default_mfg_cost_rate")]
9107 pub standard_cost_manipulation: f64,
9108
9109 #[serde(default = "default_mfg_inventory_rate")]
9111 pub inventory_fraud: f64,
9112}
9113
9114fn default_mfg_yield_rate() -> f64 {
9115 0.015
9116}
9117
9118fn default_mfg_labor_rate() -> f64 {
9119 0.02
9120}
9121
9122fn default_mfg_phantom_rate() -> f64 {
9123 0.005
9124}
9125
9126fn default_mfg_cost_rate() -> f64 {
9127 0.01
9128}
9129
9130fn default_mfg_inventory_rate() -> f64 {
9131 0.008
9132}
9133
9134impl Default for ManufacturingAnomalyRates {
9135 fn default() -> Self {
9136 Self {
9137 yield_manipulation: default_mfg_yield_rate(),
9138 labor_misallocation: default_mfg_labor_rate(),
9139 phantom_production: default_mfg_phantom_rate(),
9140 standard_cost_manipulation: default_mfg_cost_rate(),
9141 inventory_fraud: default_mfg_inventory_rate(),
9142 }
9143 }
9144}
9145
9146#[derive(Debug, Clone, Serialize, Deserialize)]
9148pub struct RetailConfig {
9149 #[serde(default)]
9151 pub enabled: bool,
9152
9153 #[serde(default)]
9155 pub store_types: RetailStoreTypeConfig,
9156
9157 #[serde(default = "default_retail_daily_txns")]
9159 pub avg_daily_transactions: u32,
9160
9161 #[serde(default = "default_true")]
9163 pub loss_prevention: bool,
9164
9165 #[serde(default = "default_shrinkage_rate")]
9167 pub shrinkage_rate: f64,
9168
9169 #[serde(default)]
9171 pub anomaly_rates: RetailAnomalyRates,
9172}
9173
9174fn default_retail_daily_txns() -> u32 {
9175 500
9176}
9177
9178fn default_shrinkage_rate() -> f64 {
9179 0.015
9180}
9181
9182impl Default for RetailConfig {
9183 fn default() -> Self {
9184 Self {
9185 enabled: false,
9186 store_types: RetailStoreTypeConfig::default(),
9187 avg_daily_transactions: default_retail_daily_txns(),
9188 loss_prevention: true,
9189 shrinkage_rate: default_shrinkage_rate(),
9190 anomaly_rates: RetailAnomalyRates::default(),
9191 }
9192 }
9193}
9194
9195#[derive(Debug, Clone, Serialize, Deserialize)]
9197pub struct RetailStoreTypeConfig {
9198 #[serde(default = "default_flagship_pct")]
9200 pub flagship: f64,
9201
9202 #[serde(default = "default_regional_pct")]
9204 pub regional: f64,
9205
9206 #[serde(default = "default_outlet_pct")]
9208 pub outlet: f64,
9209
9210 #[serde(default = "default_ecommerce_pct")]
9212 pub ecommerce: f64,
9213}
9214
9215fn default_flagship_pct() -> f64 {
9216 0.10
9217}
9218
9219fn default_regional_pct() -> f64 {
9220 0.50
9221}
9222
9223fn default_outlet_pct() -> f64 {
9224 0.25
9225}
9226
9227fn default_ecommerce_pct() -> f64 {
9228 0.15
9229}
9230
9231impl Default for RetailStoreTypeConfig {
9232 fn default() -> Self {
9233 Self {
9234 flagship: default_flagship_pct(),
9235 regional: default_regional_pct(),
9236 outlet: default_outlet_pct(),
9237 ecommerce: default_ecommerce_pct(),
9238 }
9239 }
9240}
9241
9242#[derive(Debug, Clone, Serialize, Deserialize)]
9244pub struct RetailAnomalyRates {
9245 #[serde(default = "default_sweethearting_rate")]
9247 pub sweethearting: f64,
9248
9249 #[serde(default = "default_skimming_rate")]
9251 pub skimming: f64,
9252
9253 #[serde(default = "default_refund_fraud_rate")]
9255 pub refund_fraud: f64,
9256
9257 #[serde(default = "default_void_abuse_rate")]
9259 pub void_abuse: f64,
9260
9261 #[serde(default = "default_gift_card_rate")]
9263 pub gift_card_fraud: f64,
9264
9265 #[serde(default = "default_retail_kickback_rate")]
9267 pub vendor_kickback: f64,
9268}
9269
9270fn default_sweethearting_rate() -> f64 {
9271 0.02
9272}
9273
9274fn default_skimming_rate() -> f64 {
9275 0.005
9276}
9277
9278fn default_refund_fraud_rate() -> f64 {
9279 0.015
9280}
9281
9282fn default_void_abuse_rate() -> f64 {
9283 0.01
9284}
9285
9286fn default_gift_card_rate() -> f64 {
9287 0.008
9288}
9289
9290fn default_retail_kickback_rate() -> f64 {
9291 0.003
9292}
9293
9294impl Default for RetailAnomalyRates {
9295 fn default() -> Self {
9296 Self {
9297 sweethearting: default_sweethearting_rate(),
9298 skimming: default_skimming_rate(),
9299 refund_fraud: default_refund_fraud_rate(),
9300 void_abuse: default_void_abuse_rate(),
9301 gift_card_fraud: default_gift_card_rate(),
9302 vendor_kickback: default_retail_kickback_rate(),
9303 }
9304 }
9305}
9306
9307#[derive(Debug, Clone, Serialize, Deserialize)]
9309pub struct HealthcareConfig {
9310 #[serde(default)]
9312 pub enabled: bool,
9313
9314 #[serde(default = "default_facility_type")]
9316 pub facility_type: String,
9317
9318 #[serde(default)]
9320 pub payer_mix: HealthcarePayerMix,
9321
9322 #[serde(default)]
9324 pub coding_systems: HealthcareCodingSystems,
9325
9326 #[serde(default)]
9328 pub compliance: HealthcareComplianceConfig,
9329
9330 #[serde(default = "default_daily_encounters")]
9332 pub avg_daily_encounters: u32,
9333
9334 #[serde(default = "default_charges_per_encounter")]
9336 pub avg_charges_per_encounter: u32,
9337
9338 #[serde(default = "default_hc_denial_rate")]
9340 pub denial_rate: f64,
9341
9342 #[serde(default = "default_hc_bad_debt_rate")]
9344 pub bad_debt_rate: f64,
9345
9346 #[serde(default = "default_hc_charity_care_rate")]
9348 pub charity_care_rate: f64,
9349
9350 #[serde(default)]
9352 pub anomaly_rates: HealthcareAnomalyRates,
9353}
9354
9355fn default_facility_type() -> String {
9356 "hospital".to_string()
9357}
9358
9359fn default_daily_encounters() -> u32 {
9360 150
9361}
9362
9363fn default_charges_per_encounter() -> u32 {
9364 8
9365}
9366
9367fn default_hc_denial_rate() -> f64 {
9368 0.05
9369}
9370
9371fn default_hc_bad_debt_rate() -> f64 {
9372 0.03
9373}
9374
9375fn default_hc_charity_care_rate() -> f64 {
9376 0.02
9377}
9378
9379impl Default for HealthcareConfig {
9380 fn default() -> Self {
9381 Self {
9382 enabled: false,
9383 facility_type: default_facility_type(),
9384 payer_mix: HealthcarePayerMix::default(),
9385 coding_systems: HealthcareCodingSystems::default(),
9386 compliance: HealthcareComplianceConfig::default(),
9387 avg_daily_encounters: default_daily_encounters(),
9388 avg_charges_per_encounter: default_charges_per_encounter(),
9389 denial_rate: default_hc_denial_rate(),
9390 bad_debt_rate: default_hc_bad_debt_rate(),
9391 charity_care_rate: default_hc_charity_care_rate(),
9392 anomaly_rates: HealthcareAnomalyRates::default(),
9393 }
9394 }
9395}
9396
9397#[derive(Debug, Clone, Serialize, Deserialize)]
9399pub struct HealthcarePayerMix {
9400 #[serde(default = "default_medicare_pct")]
9402 pub medicare: f64,
9403
9404 #[serde(default = "default_medicaid_pct")]
9406 pub medicaid: f64,
9407
9408 #[serde(default = "default_commercial_pct")]
9410 pub commercial: f64,
9411
9412 #[serde(default = "default_self_pay_pct")]
9414 pub self_pay: f64,
9415}
9416
9417fn default_medicare_pct() -> f64 {
9418 0.40
9419}
9420
9421fn default_medicaid_pct() -> f64 {
9422 0.20
9423}
9424
9425fn default_commercial_pct() -> f64 {
9426 0.30
9427}
9428
9429fn default_self_pay_pct() -> f64 {
9430 0.10
9431}
9432
9433impl Default for HealthcarePayerMix {
9434 fn default() -> Self {
9435 Self {
9436 medicare: default_medicare_pct(),
9437 medicaid: default_medicaid_pct(),
9438 commercial: default_commercial_pct(),
9439 self_pay: default_self_pay_pct(),
9440 }
9441 }
9442}
9443
9444#[derive(Debug, Clone, Serialize, Deserialize)]
9446pub struct HealthcareCodingSystems {
9447 #[serde(default = "default_true")]
9449 pub icd10: bool,
9450
9451 #[serde(default = "default_true")]
9453 pub cpt: bool,
9454
9455 #[serde(default = "default_true")]
9457 pub drg: bool,
9458
9459 #[serde(default = "default_true")]
9461 pub hcpcs: bool,
9462
9463 #[serde(default = "default_true")]
9465 pub revenue_codes: bool,
9466}
9467
9468impl Default for HealthcareCodingSystems {
9469 fn default() -> Self {
9470 Self {
9471 icd10: true,
9472 cpt: true,
9473 drg: true,
9474 hcpcs: true,
9475 revenue_codes: true,
9476 }
9477 }
9478}
9479
9480#[derive(Debug, Clone, Serialize, Deserialize)]
9482pub struct HealthcareComplianceConfig {
9483 #[serde(default = "default_true")]
9485 pub hipaa: bool,
9486
9487 #[serde(default = "default_true")]
9489 pub stark_law: bool,
9490
9491 #[serde(default = "default_true")]
9493 pub anti_kickback: bool,
9494
9495 #[serde(default = "default_true")]
9497 pub false_claims_act: bool,
9498
9499 #[serde(default = "default_true")]
9501 pub emtala: bool,
9502}
9503
9504impl Default for HealthcareComplianceConfig {
9505 fn default() -> Self {
9506 Self {
9507 hipaa: true,
9508 stark_law: true,
9509 anti_kickback: true,
9510 false_claims_act: true,
9511 emtala: true,
9512 }
9513 }
9514}
9515
9516#[derive(Debug, Clone, Serialize, Deserialize)]
9518pub struct HealthcareAnomalyRates {
9519 #[serde(default = "default_upcoding_rate")]
9521 pub upcoding: f64,
9522
9523 #[serde(default = "default_unbundling_rate")]
9525 pub unbundling: f64,
9526
9527 #[serde(default = "default_phantom_billing_rate")]
9529 pub phantom_billing: f64,
9530
9531 #[serde(default = "default_healthcare_kickback_rate")]
9533 pub kickbacks: f64,
9534
9535 #[serde(default = "default_duplicate_billing_rate")]
9537 pub duplicate_billing: f64,
9538
9539 #[serde(default = "default_med_necessity_rate")]
9541 pub medical_necessity_abuse: f64,
9542}
9543
9544fn default_upcoding_rate() -> f64 {
9545 0.02
9546}
9547
9548fn default_unbundling_rate() -> f64 {
9549 0.015
9550}
9551
9552fn default_phantom_billing_rate() -> f64 {
9553 0.005
9554}
9555
9556fn default_healthcare_kickback_rate() -> f64 {
9557 0.003
9558}
9559
9560fn default_duplicate_billing_rate() -> f64 {
9561 0.008
9562}
9563
9564fn default_med_necessity_rate() -> f64 {
9565 0.01
9566}
9567
9568impl Default for HealthcareAnomalyRates {
9569 fn default() -> Self {
9570 Self {
9571 upcoding: default_upcoding_rate(),
9572 unbundling: default_unbundling_rate(),
9573 phantom_billing: default_phantom_billing_rate(),
9574 kickbacks: default_healthcare_kickback_rate(),
9575 duplicate_billing: default_duplicate_billing_rate(),
9576 medical_necessity_abuse: default_med_necessity_rate(),
9577 }
9578 }
9579}
9580
9581#[derive(Debug, Clone, Serialize, Deserialize)]
9583pub struct TechnologyConfig {
9584 #[serde(default)]
9586 pub enabled: bool,
9587
9588 #[serde(default = "default_revenue_model")]
9590 pub revenue_model: String,
9591
9592 #[serde(default = "default_subscription_pct")]
9594 pub subscription_revenue_pct: f64,
9595
9596 #[serde(default = "default_license_pct")]
9598 pub license_revenue_pct: f64,
9599
9600 #[serde(default = "default_services_pct")]
9602 pub services_revenue_pct: f64,
9603
9604 #[serde(default)]
9606 pub rd_capitalization: RdCapitalizationConfig,
9607
9608 #[serde(default)]
9610 pub anomaly_rates: TechnologyAnomalyRates,
9611}
9612
9613fn default_revenue_model() -> String {
9614 "saas".to_string()
9615}
9616
9617fn default_subscription_pct() -> f64 {
9618 0.60
9619}
9620
9621fn default_license_pct() -> f64 {
9622 0.25
9623}
9624
9625fn default_services_pct() -> f64 {
9626 0.15
9627}
9628
9629impl Default for TechnologyConfig {
9630 fn default() -> Self {
9631 Self {
9632 enabled: false,
9633 revenue_model: default_revenue_model(),
9634 subscription_revenue_pct: default_subscription_pct(),
9635 license_revenue_pct: default_license_pct(),
9636 services_revenue_pct: default_services_pct(),
9637 rd_capitalization: RdCapitalizationConfig::default(),
9638 anomaly_rates: TechnologyAnomalyRates::default(),
9639 }
9640 }
9641}
9642
9643#[derive(Debug, Clone, Serialize, Deserialize)]
9645pub struct RdCapitalizationConfig {
9646 #[serde(default = "default_true")]
9648 pub enabled: bool,
9649
9650 #[serde(default = "default_cap_rate")]
9652 pub capitalization_rate: f64,
9653
9654 #[serde(default = "default_useful_life")]
9656 pub useful_life_years: u32,
9657}
9658
9659fn default_cap_rate() -> f64 {
9660 0.30
9661}
9662
9663fn default_useful_life() -> u32 {
9664 3
9665}
9666
9667impl Default for RdCapitalizationConfig {
9668 fn default() -> Self {
9669 Self {
9670 enabled: true,
9671 capitalization_rate: default_cap_rate(),
9672 useful_life_years: default_useful_life(),
9673 }
9674 }
9675}
9676
9677#[derive(Debug, Clone, Serialize, Deserialize)]
9679pub struct TechnologyAnomalyRates {
9680 #[serde(default = "default_premature_rev_rate")]
9682 pub premature_revenue: f64,
9683
9684 #[serde(default = "default_side_letter_rate")]
9686 pub side_letter_abuse: f64,
9687
9688 #[serde(default = "default_channel_stuffing_rate")]
9690 pub channel_stuffing: f64,
9691
9692 #[serde(default = "default_improper_cap_rate")]
9694 pub improper_capitalization: f64,
9695}
9696
9697fn default_premature_rev_rate() -> f64 {
9698 0.015
9699}
9700
9701fn default_side_letter_rate() -> f64 {
9702 0.008
9703}
9704
9705fn default_channel_stuffing_rate() -> f64 {
9706 0.01
9707}
9708
9709fn default_improper_cap_rate() -> f64 {
9710 0.012
9711}
9712
9713impl Default for TechnologyAnomalyRates {
9714 fn default() -> Self {
9715 Self {
9716 premature_revenue: default_premature_rev_rate(),
9717 side_letter_abuse: default_side_letter_rate(),
9718 channel_stuffing: default_channel_stuffing_rate(),
9719 improper_capitalization: default_improper_cap_rate(),
9720 }
9721 }
9722}
9723
9724#[derive(Debug, Clone, Serialize, Deserialize)]
9726pub struct FinancialServicesConfig {
9727 #[serde(default)]
9729 pub enabled: bool,
9730
9731 #[serde(default = "default_fi_type")]
9733 pub institution_type: String,
9734
9735 #[serde(default = "default_fi_regulatory")]
9737 pub regulatory_framework: String,
9738
9739 #[serde(default)]
9741 pub anomaly_rates: FinancialServicesAnomalyRates,
9742}
9743
9744fn default_fi_type() -> String {
9745 "commercial_bank".to_string()
9746}
9747
9748fn default_fi_regulatory() -> String {
9749 "us_banking".to_string()
9750}
9751
9752impl Default for FinancialServicesConfig {
9753 fn default() -> Self {
9754 Self {
9755 enabled: false,
9756 institution_type: default_fi_type(),
9757 regulatory_framework: default_fi_regulatory(),
9758 anomaly_rates: FinancialServicesAnomalyRates::default(),
9759 }
9760 }
9761}
9762
9763#[derive(Debug, Clone, Serialize, Deserialize)]
9765pub struct FinancialServicesAnomalyRates {
9766 #[serde(default = "default_loan_fraud_rate")]
9768 pub loan_fraud: f64,
9769
9770 #[serde(default = "default_trading_fraud_rate")]
9772 pub trading_fraud: f64,
9773
9774 #[serde(default = "default_insurance_fraud_rate")]
9776 pub insurance_fraud: f64,
9777
9778 #[serde(default = "default_account_manip_rate")]
9780 pub account_manipulation: f64,
9781}
9782
9783fn default_loan_fraud_rate() -> f64 {
9784 0.01
9785}
9786
9787fn default_trading_fraud_rate() -> f64 {
9788 0.008
9789}
9790
9791fn default_insurance_fraud_rate() -> f64 {
9792 0.012
9793}
9794
9795fn default_account_manip_rate() -> f64 {
9796 0.005
9797}
9798
9799impl Default for FinancialServicesAnomalyRates {
9800 fn default() -> Self {
9801 Self {
9802 loan_fraud: default_loan_fraud_rate(),
9803 trading_fraud: default_trading_fraud_rate(),
9804 insurance_fraud: default_insurance_fraud_rate(),
9805 account_manipulation: default_account_manip_rate(),
9806 }
9807 }
9808}
9809
9810#[derive(Debug, Clone, Serialize, Deserialize)]
9812pub struct ProfessionalServicesConfig {
9813 #[serde(default)]
9815 pub enabled: bool,
9816
9817 #[serde(default = "default_firm_type")]
9819 pub firm_type: String,
9820
9821 #[serde(default = "default_billing_model")]
9823 pub billing_model: String,
9824
9825 #[serde(default = "default_hourly_rate")]
9827 pub avg_hourly_rate: f64,
9828
9829 #[serde(default)]
9831 pub trust_accounting: TrustAccountingConfig,
9832
9833 #[serde(default)]
9835 pub anomaly_rates: ProfessionalServicesAnomalyRates,
9836}
9837
9838fn default_firm_type() -> String {
9839 "consulting".to_string()
9840}
9841
9842fn default_billing_model() -> String {
9843 "time_and_materials".to_string()
9844}
9845
9846fn default_hourly_rate() -> f64 {
9847 250.0
9848}
9849
9850impl Default for ProfessionalServicesConfig {
9851 fn default() -> Self {
9852 Self {
9853 enabled: false,
9854 firm_type: default_firm_type(),
9855 billing_model: default_billing_model(),
9856 avg_hourly_rate: default_hourly_rate(),
9857 trust_accounting: TrustAccountingConfig::default(),
9858 anomaly_rates: ProfessionalServicesAnomalyRates::default(),
9859 }
9860 }
9861}
9862
9863#[derive(Debug, Clone, Serialize, Deserialize)]
9865pub struct TrustAccountingConfig {
9866 #[serde(default)]
9868 pub enabled: bool,
9869
9870 #[serde(default = "default_true")]
9872 pub require_three_way_reconciliation: bool,
9873}
9874
9875impl Default for TrustAccountingConfig {
9876 fn default() -> Self {
9877 Self {
9878 enabled: false,
9879 require_three_way_reconciliation: true,
9880 }
9881 }
9882}
9883
9884#[derive(Debug, Clone, Serialize, Deserialize)]
9886pub struct ProfessionalServicesAnomalyRates {
9887 #[serde(default = "default_time_fraud_rate")]
9889 pub time_billing_fraud: f64,
9890
9891 #[serde(default = "default_expense_fraud_rate")]
9893 pub expense_fraud: f64,
9894
9895 #[serde(default = "default_trust_misappropriation_rate")]
9897 pub trust_misappropriation: f64,
9898}
9899
9900fn default_time_fraud_rate() -> f64 {
9901 0.02
9902}
9903
9904fn default_expense_fraud_rate() -> f64 {
9905 0.015
9906}
9907
9908fn default_trust_misappropriation_rate() -> f64 {
9909 0.003
9910}
9911
9912impl Default for ProfessionalServicesAnomalyRates {
9913 fn default() -> Self {
9914 Self {
9915 time_billing_fraud: default_time_fraud_rate(),
9916 expense_fraud: default_expense_fraud_rate(),
9917 trust_misappropriation: default_trust_misappropriation_rate(),
9918 }
9919 }
9920}
9921
9922#[derive(Debug, Clone, Serialize, Deserialize)]
9936pub struct FingerprintPrivacyConfig {
9937 #[serde(default)]
9939 pub level: String,
9940 #[serde(default = "default_epsilon")]
9942 pub epsilon: f64,
9943 #[serde(default = "default_delta")]
9945 pub delta: f64,
9946 #[serde(default = "default_k_anonymity")]
9948 pub k_anonymity: u32,
9949 #[serde(default)]
9951 pub composition_method: String,
9952}
9953
9954fn default_epsilon() -> f64 {
9955 1.0
9956}
9957
9958fn default_delta() -> f64 {
9959 1e-5
9960}
9961
9962fn default_k_anonymity() -> u32 {
9963 5
9964}
9965
9966impl Default for FingerprintPrivacyConfig {
9967 fn default() -> Self {
9968 Self {
9969 level: "standard".to_string(),
9970 epsilon: default_epsilon(),
9971 delta: default_delta(),
9972 k_anonymity: default_k_anonymity(),
9973 composition_method: "naive".to_string(),
9974 }
9975 }
9976}
9977
9978#[derive(Debug, Clone, Serialize, Deserialize)]
9992pub struct QualityGatesSchemaConfig {
9993 #[serde(default)]
9995 pub enabled: bool,
9996 #[serde(default = "default_gate_profile_name")]
9998 pub profile: String,
9999 #[serde(default)]
10001 pub fail_on_violation: bool,
10002 #[serde(default)]
10004 pub custom_gates: Vec<QualityGateEntry>,
10005}
10006
10007fn default_gate_profile_name() -> String {
10008 "default".to_string()
10009}
10010
10011impl Default for QualityGatesSchemaConfig {
10012 fn default() -> Self {
10013 Self {
10014 enabled: false,
10015 profile: default_gate_profile_name(),
10016 fail_on_violation: false,
10017 custom_gates: Vec::new(),
10018 }
10019 }
10020}
10021
10022#[derive(Debug, Clone, Serialize, Deserialize)]
10024pub struct QualityGateEntry {
10025 pub name: String,
10027 pub metric: String,
10031 pub threshold: f64,
10033 #[serde(default)]
10035 pub upper_threshold: Option<f64>,
10036 #[serde(default = "default_gate_comparison")]
10038 pub comparison: String,
10039}
10040
10041fn default_gate_comparison() -> String {
10042 "gte".to_string()
10043}
10044
10045#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10055pub struct ComplianceSchemaConfig {
10056 #[serde(default)]
10058 pub content_marking: ContentMarkingSchemaConfig,
10059 #[serde(default)]
10061 pub article10_report: bool,
10062 #[serde(default)]
10064 pub certificates: CertificateSchemaConfig,
10065}
10066
10067#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10069pub struct CertificateSchemaConfig {
10070 #[serde(default)]
10072 pub enabled: bool,
10073 #[serde(default)]
10075 pub signing_key_env: Option<String>,
10076 #[serde(default)]
10078 pub include_quality_metrics: bool,
10079}
10080
10081#[derive(Debug, Clone, Serialize, Deserialize)]
10083pub struct ContentMarkingSchemaConfig {
10084 #[serde(default = "default_true")]
10086 pub enabled: bool,
10087 #[serde(default = "default_marking_format")]
10089 pub format: String,
10090}
10091
10092fn default_marking_format() -> String {
10093 "embedded".to_string()
10094}
10095
10096impl Default for ContentMarkingSchemaConfig {
10097 fn default() -> Self {
10098 Self {
10099 enabled: true,
10100 format: default_marking_format(),
10101 }
10102 }
10103}
10104
10105#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10107pub struct WebhookSchemaConfig {
10108 #[serde(default)]
10110 pub enabled: bool,
10111 #[serde(default)]
10113 pub endpoints: Vec<WebhookEndpointConfig>,
10114}
10115
10116#[derive(Debug, Clone, Serialize, Deserialize)]
10118pub struct WebhookEndpointConfig {
10119 pub url: String,
10121 #[serde(default)]
10123 pub events: Vec<String>,
10124 #[serde(default)]
10126 pub secret: Option<String>,
10127 #[serde(default = "default_webhook_retries")]
10129 pub max_retries: u32,
10130 #[serde(default = "default_webhook_timeout")]
10132 pub timeout_secs: u64,
10133}
10134
10135fn default_webhook_retries() -> u32 {
10136 3
10137}
10138fn default_webhook_timeout() -> u64 {
10139 10
10140}
10141
10142#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10148pub struct SourceToPayConfig {
10149 #[serde(default)]
10151 pub enabled: bool,
10152 #[serde(default)]
10154 pub spend_analysis: SpendAnalysisConfig,
10155 #[serde(default)]
10157 pub sourcing: SourcingConfig,
10158 #[serde(default)]
10160 pub qualification: QualificationConfig,
10161 #[serde(default)]
10163 pub rfx: RfxConfig,
10164 #[serde(default)]
10166 pub contracts: ContractConfig,
10167 #[serde(default)]
10169 pub catalog: CatalogConfig,
10170 #[serde(default)]
10172 pub scorecards: ScorecardConfig,
10173 #[serde(default)]
10175 pub p2p_integration: P2PIntegrationConfig,
10176}
10177
10178#[derive(Debug, Clone, Serialize, Deserialize)]
10180pub struct SpendAnalysisConfig {
10181 #[serde(default = "default_hhi_threshold")]
10183 pub hhi_threshold: f64,
10184 #[serde(default = "default_contract_coverage_target")]
10186 pub contract_coverage_target: f64,
10187}
10188
10189impl Default for SpendAnalysisConfig {
10190 fn default() -> Self {
10191 Self {
10192 hhi_threshold: default_hhi_threshold(),
10193 contract_coverage_target: default_contract_coverage_target(),
10194 }
10195 }
10196}
10197
10198fn default_hhi_threshold() -> f64 {
10199 2500.0
10200}
10201fn default_contract_coverage_target() -> f64 {
10202 0.80
10203}
10204
10205#[derive(Debug, Clone, Serialize, Deserialize)]
10207pub struct SourcingConfig {
10208 #[serde(default = "default_sourcing_projects_per_year")]
10210 pub projects_per_year: u32,
10211 #[serde(default = "default_renewal_horizon_months")]
10213 pub renewal_horizon_months: u32,
10214 #[serde(default = "default_project_duration_months")]
10216 pub project_duration_months: u32,
10217}
10218
10219impl Default for SourcingConfig {
10220 fn default() -> Self {
10221 Self {
10222 projects_per_year: default_sourcing_projects_per_year(),
10223 renewal_horizon_months: default_renewal_horizon_months(),
10224 project_duration_months: default_project_duration_months(),
10225 }
10226 }
10227}
10228
10229fn default_sourcing_projects_per_year() -> u32 {
10230 10
10231}
10232fn default_renewal_horizon_months() -> u32 {
10233 3
10234}
10235fn default_project_duration_months() -> u32 {
10236 4
10237}
10238
10239#[derive(Debug, Clone, Serialize, Deserialize)]
10241pub struct QualificationConfig {
10242 #[serde(default = "default_qualification_pass_rate")]
10244 pub pass_rate: f64,
10245 #[serde(default = "default_qualification_validity_days")]
10247 pub validity_days: u32,
10248 #[serde(default = "default_financial_weight")]
10250 pub financial_weight: f64,
10251 #[serde(default = "default_quality_weight")]
10253 pub quality_weight: f64,
10254 #[serde(default = "default_delivery_weight")]
10256 pub delivery_weight: f64,
10257 #[serde(default = "default_compliance_weight")]
10259 pub compliance_weight: f64,
10260}
10261
10262impl Default for QualificationConfig {
10263 fn default() -> Self {
10264 Self {
10265 pass_rate: default_qualification_pass_rate(),
10266 validity_days: default_qualification_validity_days(),
10267 financial_weight: default_financial_weight(),
10268 quality_weight: default_quality_weight(),
10269 delivery_weight: default_delivery_weight(),
10270 compliance_weight: default_compliance_weight(),
10271 }
10272 }
10273}
10274
10275fn default_qualification_pass_rate() -> f64 {
10276 0.75
10277}
10278fn default_qualification_validity_days() -> u32 {
10279 365
10280}
10281fn default_financial_weight() -> f64 {
10282 0.25
10283}
10284fn default_quality_weight() -> f64 {
10285 0.30
10286}
10287fn default_delivery_weight() -> f64 {
10288 0.25
10289}
10290fn default_compliance_weight() -> f64 {
10291 0.20
10292}
10293
10294#[derive(Debug, Clone, Serialize, Deserialize)]
10296pub struct RfxConfig {
10297 #[serde(default = "default_rfi_threshold")]
10299 pub rfi_threshold: f64,
10300 #[serde(default = "default_min_invited_vendors")]
10302 pub min_invited_vendors: u32,
10303 #[serde(default = "default_max_invited_vendors")]
10305 pub max_invited_vendors: u32,
10306 #[serde(default = "default_response_rate")]
10308 pub response_rate: f64,
10309 #[serde(default = "default_price_weight")]
10311 pub default_price_weight: f64,
10312 #[serde(default = "default_rfx_quality_weight")]
10314 pub default_quality_weight: f64,
10315 #[serde(default = "default_rfx_delivery_weight")]
10317 pub default_delivery_weight: f64,
10318}
10319
10320impl Default for RfxConfig {
10321 fn default() -> Self {
10322 Self {
10323 rfi_threshold: default_rfi_threshold(),
10324 min_invited_vendors: default_min_invited_vendors(),
10325 max_invited_vendors: default_max_invited_vendors(),
10326 response_rate: default_response_rate(),
10327 default_price_weight: default_price_weight(),
10328 default_quality_weight: default_rfx_quality_weight(),
10329 default_delivery_weight: default_rfx_delivery_weight(),
10330 }
10331 }
10332}
10333
10334fn default_rfi_threshold() -> f64 {
10335 100_000.0
10336}
10337fn default_min_invited_vendors() -> u32 {
10338 3
10339}
10340fn default_max_invited_vendors() -> u32 {
10341 8
10342}
10343fn default_response_rate() -> f64 {
10344 0.70
10345}
10346fn default_price_weight() -> f64 {
10347 0.40
10348}
10349fn default_rfx_quality_weight() -> f64 {
10350 0.35
10351}
10352fn default_rfx_delivery_weight() -> f64 {
10353 0.25
10354}
10355
10356#[derive(Debug, Clone, Serialize, Deserialize)]
10358pub struct ContractConfig {
10359 #[serde(default = "default_min_contract_months")]
10361 pub min_duration_months: u32,
10362 #[serde(default = "default_max_contract_months")]
10364 pub max_duration_months: u32,
10365 #[serde(default = "default_auto_renewal_rate")]
10367 pub auto_renewal_rate: f64,
10368 #[serde(default = "default_amendment_rate")]
10370 pub amendment_rate: f64,
10371 #[serde(default)]
10373 pub type_distribution: ContractTypeDistribution,
10374}
10375
10376impl Default for ContractConfig {
10377 fn default() -> Self {
10378 Self {
10379 min_duration_months: default_min_contract_months(),
10380 max_duration_months: default_max_contract_months(),
10381 auto_renewal_rate: default_auto_renewal_rate(),
10382 amendment_rate: default_amendment_rate(),
10383 type_distribution: ContractTypeDistribution::default(),
10384 }
10385 }
10386}
10387
10388fn default_min_contract_months() -> u32 {
10389 12
10390}
10391fn default_max_contract_months() -> u32 {
10392 36
10393}
10394fn default_auto_renewal_rate() -> f64 {
10395 0.40
10396}
10397fn default_amendment_rate() -> f64 {
10398 0.20
10399}
10400
10401#[derive(Debug, Clone, Serialize, Deserialize)]
10403pub struct ContractTypeDistribution {
10404 #[serde(default = "default_fixed_price_pct")]
10406 pub fixed_price: f64,
10407 #[serde(default = "default_blanket_pct")]
10409 pub blanket: f64,
10410 #[serde(default = "default_time_materials_pct")]
10412 pub time_and_materials: f64,
10413 #[serde(default = "default_service_agreement_pct")]
10415 pub service_agreement: f64,
10416}
10417
10418impl Default for ContractTypeDistribution {
10419 fn default() -> Self {
10420 Self {
10421 fixed_price: default_fixed_price_pct(),
10422 blanket: default_blanket_pct(),
10423 time_and_materials: default_time_materials_pct(),
10424 service_agreement: default_service_agreement_pct(),
10425 }
10426 }
10427}
10428
10429fn default_fixed_price_pct() -> f64 {
10430 0.40
10431}
10432fn default_blanket_pct() -> f64 {
10433 0.30
10434}
10435fn default_time_materials_pct() -> f64 {
10436 0.15
10437}
10438fn default_service_agreement_pct() -> f64 {
10439 0.15
10440}
10441
10442#[derive(Debug, Clone, Serialize, Deserialize)]
10444pub struct CatalogConfig {
10445 #[serde(default = "default_preferred_vendor_flag_rate")]
10447 pub preferred_vendor_flag_rate: f64,
10448 #[serde(default = "default_multi_source_rate")]
10450 pub multi_source_rate: f64,
10451}
10452
10453impl Default for CatalogConfig {
10454 fn default() -> Self {
10455 Self {
10456 preferred_vendor_flag_rate: default_preferred_vendor_flag_rate(),
10457 multi_source_rate: default_multi_source_rate(),
10458 }
10459 }
10460}
10461
10462fn default_preferred_vendor_flag_rate() -> f64 {
10463 0.70
10464}
10465fn default_multi_source_rate() -> f64 {
10466 0.25
10467}
10468
10469#[derive(Debug, Clone, Serialize, Deserialize)]
10471pub struct ScorecardConfig {
10472 #[serde(default = "default_scorecard_frequency")]
10474 pub frequency: String,
10475 #[serde(default = "default_otd_weight")]
10477 pub on_time_delivery_weight: f64,
10478 #[serde(default = "default_quality_score_weight")]
10480 pub quality_weight: f64,
10481 #[serde(default = "default_price_score_weight")]
10483 pub price_weight: f64,
10484 #[serde(default = "default_responsiveness_weight")]
10486 pub responsiveness_weight: f64,
10487 #[serde(default = "default_grade_a_threshold")]
10489 pub grade_a_threshold: f64,
10490 #[serde(default = "default_grade_b_threshold")]
10492 pub grade_b_threshold: f64,
10493 #[serde(default = "default_grade_c_threshold")]
10495 pub grade_c_threshold: f64,
10496}
10497
10498impl Default for ScorecardConfig {
10499 fn default() -> Self {
10500 Self {
10501 frequency: default_scorecard_frequency(),
10502 on_time_delivery_weight: default_otd_weight(),
10503 quality_weight: default_quality_score_weight(),
10504 price_weight: default_price_score_weight(),
10505 responsiveness_weight: default_responsiveness_weight(),
10506 grade_a_threshold: default_grade_a_threshold(),
10507 grade_b_threshold: default_grade_b_threshold(),
10508 grade_c_threshold: default_grade_c_threshold(),
10509 }
10510 }
10511}
10512
10513fn default_scorecard_frequency() -> String {
10514 "quarterly".to_string()
10515}
10516fn default_otd_weight() -> f64 {
10517 0.30
10518}
10519fn default_quality_score_weight() -> f64 {
10520 0.30
10521}
10522fn default_price_score_weight() -> f64 {
10523 0.25
10524}
10525fn default_responsiveness_weight() -> f64 {
10526 0.15
10527}
10528fn default_grade_a_threshold() -> f64 {
10529 90.0
10530}
10531fn default_grade_b_threshold() -> f64 {
10532 75.0
10533}
10534fn default_grade_c_threshold() -> f64 {
10535 60.0
10536}
10537
10538#[derive(Debug, Clone, Serialize, Deserialize)]
10540pub struct P2PIntegrationConfig {
10541 #[serde(default = "default_off_contract_rate")]
10543 pub off_contract_rate: f64,
10544 #[serde(default = "default_price_tolerance")]
10546 pub price_tolerance: f64,
10547 #[serde(default)]
10549 pub catalog_enforcement: bool,
10550}
10551
10552impl Default for P2PIntegrationConfig {
10553 fn default() -> Self {
10554 Self {
10555 off_contract_rate: default_off_contract_rate(),
10556 price_tolerance: default_price_tolerance(),
10557 catalog_enforcement: false,
10558 }
10559 }
10560}
10561
10562fn default_off_contract_rate() -> f64 {
10563 0.15
10564}
10565fn default_price_tolerance() -> f64 {
10566 0.02
10567}
10568
10569#[derive(Debug, Clone, Serialize, Deserialize)]
10573pub struct FinancialReportingConfig {
10574 #[serde(default)]
10576 pub enabled: bool,
10577 #[serde(default = "default_true")]
10579 pub generate_balance_sheet: bool,
10580 #[serde(default = "default_true")]
10582 pub generate_income_statement: bool,
10583 #[serde(default = "default_true")]
10585 pub generate_cash_flow: bool,
10586 #[serde(default = "default_true")]
10588 pub generate_changes_in_equity: bool,
10589 #[serde(default = "default_comparative_periods")]
10591 pub comparative_periods: u32,
10592 #[serde(default)]
10594 pub management_kpis: ManagementKpisConfig,
10595 #[serde(default)]
10597 pub budgets: BudgetConfig,
10598}
10599
10600impl Default for FinancialReportingConfig {
10601 fn default() -> Self {
10602 Self {
10603 enabled: false,
10604 generate_balance_sheet: true,
10605 generate_income_statement: true,
10606 generate_cash_flow: true,
10607 generate_changes_in_equity: true,
10608 comparative_periods: default_comparative_periods(),
10609 management_kpis: ManagementKpisConfig::default(),
10610 budgets: BudgetConfig::default(),
10611 }
10612 }
10613}
10614
10615fn default_comparative_periods() -> u32 {
10616 1
10617}
10618
10619#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10621pub struct ManagementKpisConfig {
10622 #[serde(default)]
10624 pub enabled: bool,
10625 #[serde(default = "default_kpi_frequency")]
10627 pub frequency: String,
10628}
10629
10630fn default_kpi_frequency() -> String {
10631 "monthly".to_string()
10632}
10633
10634#[derive(Debug, Clone, Serialize, Deserialize)]
10636pub struct BudgetConfig {
10637 #[serde(default)]
10639 pub enabled: bool,
10640 #[serde(default = "default_revenue_growth_rate")]
10642 pub revenue_growth_rate: f64,
10643 #[serde(default = "default_expense_inflation_rate")]
10645 pub expense_inflation_rate: f64,
10646 #[serde(default = "default_variance_noise")]
10648 pub variance_noise: f64,
10649}
10650
10651impl Default for BudgetConfig {
10652 fn default() -> Self {
10653 Self {
10654 enabled: false,
10655 revenue_growth_rate: default_revenue_growth_rate(),
10656 expense_inflation_rate: default_expense_inflation_rate(),
10657 variance_noise: default_variance_noise(),
10658 }
10659 }
10660}
10661
10662fn default_revenue_growth_rate() -> f64 {
10663 0.05
10664}
10665fn default_expense_inflation_rate() -> f64 {
10666 0.03
10667}
10668fn default_variance_noise() -> f64 {
10669 0.10
10670}
10671
10672#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10676pub struct HrConfig {
10677 #[serde(default)]
10679 pub enabled: bool,
10680 #[serde(default)]
10682 pub payroll: PayrollConfig,
10683 #[serde(default)]
10685 pub time_attendance: TimeAttendanceConfig,
10686 #[serde(default)]
10688 pub expenses: ExpenseConfig,
10689}
10690
10691#[derive(Debug, Clone, Serialize, Deserialize)]
10693pub struct PayrollConfig {
10694 #[serde(default = "default_true")]
10696 pub enabled: bool,
10697 #[serde(default = "default_pay_frequency")]
10699 pub pay_frequency: String,
10700 #[serde(default)]
10702 pub salary_ranges: PayrollSalaryRanges,
10703 #[serde(default)]
10705 pub tax_rates: PayrollTaxRates,
10706 #[serde(default = "default_benefits_enrollment_rate")]
10708 pub benefits_enrollment_rate: f64,
10709 #[serde(default = "default_retirement_participation_rate")]
10711 pub retirement_participation_rate: f64,
10712}
10713
10714impl Default for PayrollConfig {
10715 fn default() -> Self {
10716 Self {
10717 enabled: true,
10718 pay_frequency: default_pay_frequency(),
10719 salary_ranges: PayrollSalaryRanges::default(),
10720 tax_rates: PayrollTaxRates::default(),
10721 benefits_enrollment_rate: default_benefits_enrollment_rate(),
10722 retirement_participation_rate: default_retirement_participation_rate(),
10723 }
10724 }
10725}
10726
10727fn default_pay_frequency() -> String {
10728 "monthly".to_string()
10729}
10730fn default_benefits_enrollment_rate() -> f64 {
10731 0.60
10732}
10733fn default_retirement_participation_rate() -> f64 {
10734 0.45
10735}
10736
10737#[derive(Debug, Clone, Serialize, Deserialize)]
10739pub struct PayrollSalaryRanges {
10740 #[serde(default = "default_staff_min")]
10742 pub staff_min: f64,
10743 #[serde(default = "default_staff_max")]
10744 pub staff_max: f64,
10745 #[serde(default = "default_manager_min")]
10747 pub manager_min: f64,
10748 #[serde(default = "default_manager_max")]
10749 pub manager_max: f64,
10750 #[serde(default = "default_director_min")]
10752 pub director_min: f64,
10753 #[serde(default = "default_director_max")]
10754 pub director_max: f64,
10755 #[serde(default = "default_executive_min")]
10757 pub executive_min: f64,
10758 #[serde(default = "default_executive_max")]
10759 pub executive_max: f64,
10760}
10761
10762impl Default for PayrollSalaryRanges {
10763 fn default() -> Self {
10764 Self {
10765 staff_min: default_staff_min(),
10766 staff_max: default_staff_max(),
10767 manager_min: default_manager_min(),
10768 manager_max: default_manager_max(),
10769 director_min: default_director_min(),
10770 director_max: default_director_max(),
10771 executive_min: default_executive_min(),
10772 executive_max: default_executive_max(),
10773 }
10774 }
10775}
10776
10777fn default_staff_min() -> f64 {
10778 50_000.0
10779}
10780fn default_staff_max() -> f64 {
10781 70_000.0
10782}
10783fn default_manager_min() -> f64 {
10784 80_000.0
10785}
10786fn default_manager_max() -> f64 {
10787 120_000.0
10788}
10789fn default_director_min() -> f64 {
10790 120_000.0
10791}
10792fn default_director_max() -> f64 {
10793 180_000.0
10794}
10795fn default_executive_min() -> f64 {
10796 180_000.0
10797}
10798fn default_executive_max() -> f64 {
10799 350_000.0
10800}
10801
10802#[derive(Debug, Clone, Serialize, Deserialize)]
10804pub struct PayrollTaxRates {
10805 #[serde(default = "default_federal_rate")]
10807 pub federal_effective: f64,
10808 #[serde(default = "default_state_rate")]
10810 pub state_effective: f64,
10811 #[serde(default = "default_fica_rate")]
10813 pub fica: f64,
10814}
10815
10816impl Default for PayrollTaxRates {
10817 fn default() -> Self {
10818 Self {
10819 federal_effective: default_federal_rate(),
10820 state_effective: default_state_rate(),
10821 fica: default_fica_rate(),
10822 }
10823 }
10824}
10825
10826fn default_federal_rate() -> f64 {
10827 0.22
10828}
10829fn default_state_rate() -> f64 {
10830 0.05
10831}
10832fn default_fica_rate() -> f64 {
10833 0.0765
10834}
10835
10836#[derive(Debug, Clone, Serialize, Deserialize)]
10838pub struct TimeAttendanceConfig {
10839 #[serde(default = "default_true")]
10841 pub enabled: bool,
10842 #[serde(default = "default_overtime_rate")]
10844 pub overtime_rate: f64,
10845}
10846
10847impl Default for TimeAttendanceConfig {
10848 fn default() -> Self {
10849 Self {
10850 enabled: true,
10851 overtime_rate: default_overtime_rate(),
10852 }
10853 }
10854}
10855
10856fn default_overtime_rate() -> f64 {
10857 0.10
10858}
10859
10860#[derive(Debug, Clone, Serialize, Deserialize)]
10862pub struct ExpenseConfig {
10863 #[serde(default = "default_true")]
10865 pub enabled: bool,
10866 #[serde(default = "default_expense_submission_rate")]
10868 pub submission_rate: f64,
10869 #[serde(default = "default_policy_violation_rate")]
10871 pub policy_violation_rate: f64,
10872}
10873
10874impl Default for ExpenseConfig {
10875 fn default() -> Self {
10876 Self {
10877 enabled: true,
10878 submission_rate: default_expense_submission_rate(),
10879 policy_violation_rate: default_policy_violation_rate(),
10880 }
10881 }
10882}
10883
10884fn default_expense_submission_rate() -> f64 {
10885 0.30
10886}
10887fn default_policy_violation_rate() -> f64 {
10888 0.08
10889}
10890
10891#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10895pub struct ManufacturingProcessConfig {
10896 #[serde(default)]
10898 pub enabled: bool,
10899 #[serde(default)]
10901 pub production_orders: ProductionOrderConfig,
10902 #[serde(default)]
10904 pub costing: ManufacturingCostingConfig,
10905 #[serde(default)]
10907 pub routing: RoutingConfig,
10908}
10909
10910#[derive(Debug, Clone, Serialize, Deserialize)]
10912pub struct ProductionOrderConfig {
10913 #[serde(default = "default_prod_orders_per_month")]
10915 pub orders_per_month: u32,
10916 #[serde(default = "default_prod_avg_batch_size")]
10918 pub avg_batch_size: u32,
10919 #[serde(default = "default_prod_yield_rate")]
10921 pub yield_rate: f64,
10922 #[serde(default = "default_prod_make_to_order_rate")]
10924 pub make_to_order_rate: f64,
10925 #[serde(default = "default_prod_rework_rate")]
10927 pub rework_rate: f64,
10928}
10929
10930impl Default for ProductionOrderConfig {
10931 fn default() -> Self {
10932 Self {
10933 orders_per_month: default_prod_orders_per_month(),
10934 avg_batch_size: default_prod_avg_batch_size(),
10935 yield_rate: default_prod_yield_rate(),
10936 make_to_order_rate: default_prod_make_to_order_rate(),
10937 rework_rate: default_prod_rework_rate(),
10938 }
10939 }
10940}
10941
10942fn default_prod_orders_per_month() -> u32 {
10943 50
10944}
10945fn default_prod_avg_batch_size() -> u32 {
10946 100
10947}
10948fn default_prod_yield_rate() -> f64 {
10949 0.97
10950}
10951fn default_prod_make_to_order_rate() -> f64 {
10952 0.20
10953}
10954fn default_prod_rework_rate() -> f64 {
10955 0.03
10956}
10957
10958#[derive(Debug, Clone, Serialize, Deserialize)]
10960pub struct ManufacturingCostingConfig {
10961 #[serde(default = "default_labor_rate")]
10963 pub labor_rate_per_hour: f64,
10964 #[serde(default = "default_overhead_rate")]
10966 pub overhead_rate: f64,
10967 #[serde(default = "default_cost_update_frequency")]
10969 pub standard_cost_update_frequency: String,
10970}
10971
10972impl Default for ManufacturingCostingConfig {
10973 fn default() -> Self {
10974 Self {
10975 labor_rate_per_hour: default_labor_rate(),
10976 overhead_rate: default_overhead_rate(),
10977 standard_cost_update_frequency: default_cost_update_frequency(),
10978 }
10979 }
10980}
10981
10982fn default_labor_rate() -> f64 {
10983 35.0
10984}
10985fn default_overhead_rate() -> f64 {
10986 1.50
10987}
10988fn default_cost_update_frequency() -> String {
10989 "quarterly".to_string()
10990}
10991
10992#[derive(Debug, Clone, Serialize, Deserialize)]
10994pub struct RoutingConfig {
10995 #[serde(default = "default_avg_operations")]
10997 pub avg_operations: u32,
10998 #[serde(default = "default_setup_time")]
11000 pub setup_time_hours: f64,
11001 #[serde(default = "default_run_time_variation")]
11003 pub run_time_variation: f64,
11004}
11005
11006impl Default for RoutingConfig {
11007 fn default() -> Self {
11008 Self {
11009 avg_operations: default_avg_operations(),
11010 setup_time_hours: default_setup_time(),
11011 run_time_variation: default_run_time_variation(),
11012 }
11013 }
11014}
11015
11016fn default_avg_operations() -> u32 {
11017 4
11018}
11019fn default_setup_time() -> f64 {
11020 1.5
11021}
11022fn default_run_time_variation() -> f64 {
11023 0.15
11024}
11025
11026#[derive(Debug, Clone, Serialize, Deserialize)]
11030pub struct SalesQuoteConfig {
11031 #[serde(default)]
11033 pub enabled: bool,
11034 #[serde(default = "default_quotes_per_month")]
11036 pub quotes_per_month: u32,
11037 #[serde(default = "default_quote_win_rate")]
11039 pub win_rate: f64,
11040 #[serde(default = "default_quote_validity_days")]
11042 pub validity_days: u32,
11043}
11044
11045impl Default for SalesQuoteConfig {
11046 fn default() -> Self {
11047 Self {
11048 enabled: false,
11049 quotes_per_month: default_quotes_per_month(),
11050 win_rate: default_quote_win_rate(),
11051 validity_days: default_quote_validity_days(),
11052 }
11053 }
11054}
11055
11056fn default_quotes_per_month() -> u32 {
11057 30
11058}
11059fn default_quote_win_rate() -> f64 {
11060 0.35
11061}
11062fn default_quote_validity_days() -> u32 {
11063 30
11064}
11065
11066#[derive(Debug, Clone, Serialize, Deserialize)]
11075pub struct TaxConfig {
11076 #[serde(default)]
11078 pub enabled: bool,
11079 #[serde(default)]
11081 pub jurisdictions: TaxJurisdictionConfig,
11082 #[serde(default)]
11084 pub vat_gst: VatGstConfig,
11085 #[serde(default)]
11087 pub sales_tax: SalesTaxConfig,
11088 #[serde(default)]
11090 pub withholding: WithholdingTaxSchemaConfig,
11091 #[serde(default)]
11093 pub provisions: TaxProvisionSchemaConfig,
11094 #[serde(default)]
11096 pub payroll_tax: PayrollTaxSchemaConfig,
11097 #[serde(default = "default_tax_anomaly_rate")]
11099 pub anomaly_rate: f64,
11100}
11101
11102fn default_tax_anomaly_rate() -> f64 {
11103 0.03
11104}
11105
11106impl Default for TaxConfig {
11107 fn default() -> Self {
11108 Self {
11109 enabled: false,
11110 jurisdictions: TaxJurisdictionConfig::default(),
11111 vat_gst: VatGstConfig::default(),
11112 sales_tax: SalesTaxConfig::default(),
11113 withholding: WithholdingTaxSchemaConfig::default(),
11114 provisions: TaxProvisionSchemaConfig::default(),
11115 payroll_tax: PayrollTaxSchemaConfig::default(),
11116 anomaly_rate: default_tax_anomaly_rate(),
11117 }
11118 }
11119}
11120
11121#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11126pub struct TaxJurisdictionConfig {
11127 #[serde(default)]
11129 pub countries: Vec<String>,
11130 #[serde(default)]
11132 pub include_subnational: bool,
11133}
11134
11135#[derive(Debug, Clone, Serialize, Deserialize)]
11140pub struct VatGstConfig {
11141 #[serde(default)]
11143 pub enabled: bool,
11144 #[serde(default)]
11146 pub standard_rates: std::collections::HashMap<String, f64>,
11147 #[serde(default)]
11149 pub reduced_rates: std::collections::HashMap<String, f64>,
11150 #[serde(default)]
11152 pub exempt_categories: Vec<String>,
11153 #[serde(default = "default_true")]
11155 pub reverse_charge: bool,
11156}
11157
11158impl Default for VatGstConfig {
11159 fn default() -> Self {
11160 Self {
11161 enabled: false,
11162 standard_rates: std::collections::HashMap::new(),
11163 reduced_rates: std::collections::HashMap::new(),
11164 exempt_categories: Vec::new(),
11165 reverse_charge: true,
11166 }
11167 }
11168}
11169
11170#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11174pub struct SalesTaxConfig {
11175 #[serde(default)]
11177 pub enabled: bool,
11178 #[serde(default)]
11180 pub nexus_states: Vec<String>,
11181}
11182
11183#[derive(Debug, Clone, Serialize, Deserialize)]
11188pub struct WithholdingTaxSchemaConfig {
11189 #[serde(default)]
11191 pub enabled: bool,
11192 #[serde(default = "default_true")]
11194 pub treaty_network: bool,
11195 #[serde(default = "default_withholding_rate")]
11197 pub default_rate: f64,
11198 #[serde(default = "default_treaty_reduced_rate")]
11200 pub treaty_reduced_rate: f64,
11201}
11202
11203fn default_withholding_rate() -> f64 {
11204 0.30
11205}
11206
11207fn default_treaty_reduced_rate() -> f64 {
11208 0.15
11209}
11210
11211impl Default for WithholdingTaxSchemaConfig {
11212 fn default() -> Self {
11213 Self {
11214 enabled: false,
11215 treaty_network: true,
11216 default_rate: default_withholding_rate(),
11217 treaty_reduced_rate: default_treaty_reduced_rate(),
11218 }
11219 }
11220}
11221
11222#[derive(Debug, Clone, Serialize, Deserialize)]
11227pub struct TaxProvisionSchemaConfig {
11228 #[serde(default = "default_true")]
11231 pub enabled: bool,
11232 #[serde(default = "default_statutory_rate")]
11234 pub statutory_rate: f64,
11235 #[serde(default = "default_true")]
11237 pub uncertain_positions: bool,
11238}
11239
11240fn default_statutory_rate() -> f64 {
11241 0.21
11242}
11243
11244impl Default for TaxProvisionSchemaConfig {
11245 fn default() -> Self {
11246 Self {
11247 enabled: true,
11248 statutory_rate: default_statutory_rate(),
11249 uncertain_positions: true,
11250 }
11251 }
11252}
11253
11254#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11259pub struct PayrollTaxSchemaConfig {
11260 #[serde(default)]
11262 pub enabled: bool,
11263}
11264
11265#[derive(Debug, Clone, Serialize, Deserialize)]
11275pub struct TreasuryConfig {
11276 #[serde(default)]
11278 pub enabled: bool,
11279 #[serde(default)]
11281 pub cash_positioning: CashPositioningConfig,
11282 #[serde(default)]
11284 pub cash_forecasting: CashForecastingConfig,
11285 #[serde(default)]
11287 pub cash_pooling: CashPoolingConfig,
11288 #[serde(default)]
11290 pub hedging: HedgingSchemaConfig,
11291 #[serde(default)]
11293 pub debt: DebtSchemaConfig,
11294 #[serde(default)]
11296 pub netting: NettingSchemaConfig,
11297 #[serde(default)]
11299 pub bank_guarantees: BankGuaranteeSchemaConfig,
11300 #[serde(default = "default_treasury_anomaly_rate")]
11302 pub anomaly_rate: f64,
11303}
11304
11305fn default_treasury_anomaly_rate() -> f64 {
11306 0.02
11307}
11308
11309impl Default for TreasuryConfig {
11310 fn default() -> Self {
11311 Self {
11312 enabled: false,
11313 cash_positioning: CashPositioningConfig::default(),
11314 cash_forecasting: CashForecastingConfig::default(),
11315 cash_pooling: CashPoolingConfig::default(),
11316 hedging: HedgingSchemaConfig::default(),
11317 debt: DebtSchemaConfig::default(),
11318 netting: NettingSchemaConfig::default(),
11319 bank_guarantees: BankGuaranteeSchemaConfig::default(),
11320 anomaly_rate: default_treasury_anomaly_rate(),
11321 }
11322 }
11323}
11324
11325#[derive(Debug, Clone, Serialize, Deserialize)]
11329pub struct CashPositioningConfig {
11330 #[serde(default = "default_true")]
11332 pub enabled: bool,
11333 #[serde(default = "default_cash_frequency")]
11335 pub frequency: String,
11336 #[serde(default = "default_minimum_balance_policy")]
11338 pub minimum_balance_policy: f64,
11339}
11340
11341fn default_cash_frequency() -> String {
11342 "daily".to_string()
11343}
11344
11345fn default_minimum_balance_policy() -> f64 {
11346 100_000.0
11347}
11348
11349impl Default for CashPositioningConfig {
11350 fn default() -> Self {
11351 Self {
11352 enabled: true,
11353 frequency: default_cash_frequency(),
11354 minimum_balance_policy: default_minimum_balance_policy(),
11355 }
11356 }
11357}
11358
11359#[derive(Debug, Clone, Serialize, Deserialize)]
11363pub struct CashForecastingConfig {
11364 #[serde(default = "default_true")]
11366 pub enabled: bool,
11367 #[serde(default = "default_horizon_days")]
11369 pub horizon_days: u32,
11370 #[serde(default = "default_ar_probability_curve")]
11372 pub ar_collection_probability_curve: String,
11373 #[serde(default = "default_confidence_interval")]
11375 pub confidence_interval: f64,
11376}
11377
11378fn default_horizon_days() -> u32 {
11379 90
11380}
11381
11382fn default_ar_probability_curve() -> String {
11383 "aging".to_string()
11384}
11385
11386fn default_confidence_interval() -> f64 {
11387 0.90
11388}
11389
11390impl Default for CashForecastingConfig {
11391 fn default() -> Self {
11392 Self {
11393 enabled: true,
11394 horizon_days: default_horizon_days(),
11395 ar_collection_probability_curve: default_ar_probability_curve(),
11396 confidence_interval: default_confidence_interval(),
11397 }
11398 }
11399}
11400
11401#[derive(Debug, Clone, Serialize, Deserialize)]
11405pub struct CashPoolingConfig {
11406 #[serde(default)]
11408 pub enabled: bool,
11409 #[serde(default = "default_pool_type")]
11411 pub pool_type: String,
11412 #[serde(default = "default_sweep_time")]
11414 pub sweep_time: String,
11415}
11416
11417fn default_pool_type() -> String {
11418 "zero_balancing".to_string()
11419}
11420
11421fn default_sweep_time() -> String {
11422 "16:00".to_string()
11423}
11424
11425impl Default for CashPoolingConfig {
11426 fn default() -> Self {
11427 Self {
11428 enabled: false,
11429 pool_type: default_pool_type(),
11430 sweep_time: default_sweep_time(),
11431 }
11432 }
11433}
11434
11435#[derive(Debug, Clone, Serialize, Deserialize)]
11440pub struct HedgingSchemaConfig {
11441 #[serde(default)]
11443 pub enabled: bool,
11444 #[serde(default = "default_hedge_ratio")]
11446 pub hedge_ratio: f64,
11447 #[serde(default = "default_hedge_instruments")]
11449 pub instruments: Vec<String>,
11450 #[serde(default = "default_true")]
11452 pub hedge_accounting: bool,
11453 #[serde(default = "default_effectiveness_method")]
11455 pub effectiveness_method: String,
11456}
11457
11458fn default_hedge_ratio() -> f64 {
11459 0.75
11460}
11461
11462fn default_hedge_instruments() -> Vec<String> {
11463 vec!["fx_forward".to_string(), "interest_rate_swap".to_string()]
11464}
11465
11466fn default_effectiveness_method() -> String {
11467 "regression".to_string()
11468}
11469
11470impl Default for HedgingSchemaConfig {
11471 fn default() -> Self {
11472 Self {
11473 enabled: false,
11474 hedge_ratio: default_hedge_ratio(),
11475 instruments: default_hedge_instruments(),
11476 hedge_accounting: true,
11477 effectiveness_method: default_effectiveness_method(),
11478 }
11479 }
11480}
11481
11482#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11487pub struct DebtSchemaConfig {
11488 #[serde(default)]
11490 pub enabled: bool,
11491 #[serde(default)]
11493 pub instruments: Vec<DebtInstrumentDef>,
11494 #[serde(default)]
11496 pub covenants: Vec<CovenantDef>,
11497}
11498
11499#[derive(Debug, Clone, Serialize, Deserialize)]
11501pub struct DebtInstrumentDef {
11502 #[serde(rename = "type")]
11504 pub instrument_type: String,
11505 #[serde(default)]
11507 pub principal: Option<f64>,
11508 #[serde(default)]
11510 pub rate: Option<f64>,
11511 #[serde(default)]
11513 pub maturity_months: Option<u32>,
11514 #[serde(default)]
11516 pub facility: Option<f64>,
11517}
11518
11519#[derive(Debug, Clone, Serialize, Deserialize)]
11521pub struct CovenantDef {
11522 #[serde(rename = "type")]
11525 pub covenant_type: String,
11526 pub threshold: f64,
11528}
11529
11530#[derive(Debug, Clone, Serialize, Deserialize)]
11534pub struct NettingSchemaConfig {
11535 #[serde(default)]
11537 pub enabled: bool,
11538 #[serde(default = "default_netting_cycle")]
11540 pub cycle: String,
11541}
11542
11543fn default_netting_cycle() -> String {
11544 "monthly".to_string()
11545}
11546
11547impl Default for NettingSchemaConfig {
11548 fn default() -> Self {
11549 Self {
11550 enabled: false,
11551 cycle: default_netting_cycle(),
11552 }
11553 }
11554}
11555
11556#[derive(Debug, Clone, Serialize, Deserialize)]
11560pub struct BankGuaranteeSchemaConfig {
11561 #[serde(default)]
11563 pub enabled: bool,
11564 #[serde(default = "default_guarantee_count")]
11566 pub count: u32,
11567}
11568
11569fn default_guarantee_count() -> u32 {
11570 5
11571}
11572
11573impl Default for BankGuaranteeSchemaConfig {
11574 fn default() -> Self {
11575 Self {
11576 enabled: false,
11577 count: default_guarantee_count(),
11578 }
11579 }
11580}
11581
11582#[derive(Debug, Clone, Serialize, Deserialize)]
11591pub struct ProjectAccountingConfig {
11592 #[serde(default)]
11594 pub enabled: bool,
11595 #[serde(default = "default_project_count")]
11597 pub project_count: u32,
11598 #[serde(default)]
11600 pub project_types: ProjectTypeDistribution,
11601 #[serde(default)]
11603 pub wbs: WbsSchemaConfig,
11604 #[serde(default)]
11606 pub cost_allocation: CostAllocationConfig,
11607 #[serde(default)]
11609 pub revenue_recognition: ProjectRevenueRecognitionConfig,
11610 #[serde(default)]
11612 pub milestones: MilestoneSchemaConfig,
11613 #[serde(default)]
11615 pub change_orders: ChangeOrderSchemaConfig,
11616 #[serde(default)]
11618 pub retainage: RetainageSchemaConfig,
11619 #[serde(default)]
11621 pub earned_value: EarnedValueSchemaConfig,
11622 #[serde(default = "default_project_anomaly_rate")]
11624 pub anomaly_rate: f64,
11625}
11626
11627fn default_project_count() -> u32 {
11628 10
11629}
11630
11631fn default_project_anomaly_rate() -> f64 {
11632 0.03
11633}
11634
11635impl Default for ProjectAccountingConfig {
11636 fn default() -> Self {
11637 Self {
11638 enabled: false,
11639 project_count: default_project_count(),
11640 project_types: ProjectTypeDistribution::default(),
11641 wbs: WbsSchemaConfig::default(),
11642 cost_allocation: CostAllocationConfig::default(),
11643 revenue_recognition: ProjectRevenueRecognitionConfig::default(),
11644 milestones: MilestoneSchemaConfig::default(),
11645 change_orders: ChangeOrderSchemaConfig::default(),
11646 retainage: RetainageSchemaConfig::default(),
11647 earned_value: EarnedValueSchemaConfig::default(),
11648 anomaly_rate: default_project_anomaly_rate(),
11649 }
11650 }
11651}
11652
11653#[derive(Debug, Clone, Serialize, Deserialize)]
11655pub struct ProjectTypeDistribution {
11656 #[serde(default = "default_capital_weight")]
11658 pub capital: f64,
11659 #[serde(default = "default_internal_weight")]
11661 pub internal: f64,
11662 #[serde(default = "default_customer_weight")]
11664 pub customer: f64,
11665 #[serde(default = "default_rnd_weight")]
11667 pub r_and_d: f64,
11668 #[serde(default = "default_maintenance_weight")]
11670 pub maintenance: f64,
11671 #[serde(default = "default_technology_weight")]
11673 pub technology: f64,
11674}
11675
11676fn default_capital_weight() -> f64 {
11677 0.25
11678}
11679fn default_internal_weight() -> f64 {
11680 0.20
11681}
11682fn default_customer_weight() -> f64 {
11683 0.30
11684}
11685fn default_rnd_weight() -> f64 {
11686 0.10
11687}
11688fn default_maintenance_weight() -> f64 {
11689 0.10
11690}
11691fn default_technology_weight() -> f64 {
11692 0.05
11693}
11694
11695impl Default for ProjectTypeDistribution {
11696 fn default() -> Self {
11697 Self {
11698 capital: default_capital_weight(),
11699 internal: default_internal_weight(),
11700 customer: default_customer_weight(),
11701 r_and_d: default_rnd_weight(),
11702 maintenance: default_maintenance_weight(),
11703 technology: default_technology_weight(),
11704 }
11705 }
11706}
11707
11708#[derive(Debug, Clone, Serialize, Deserialize)]
11710pub struct WbsSchemaConfig {
11711 #[serde(default = "default_wbs_max_depth")]
11713 pub max_depth: u32,
11714 #[serde(default = "default_wbs_min_elements")]
11716 pub min_elements_per_level: u32,
11717 #[serde(default = "default_wbs_max_elements")]
11719 pub max_elements_per_level: u32,
11720}
11721
11722fn default_wbs_max_depth() -> u32 {
11723 3
11724}
11725fn default_wbs_min_elements() -> u32 {
11726 2
11727}
11728fn default_wbs_max_elements() -> u32 {
11729 6
11730}
11731
11732impl Default for WbsSchemaConfig {
11733 fn default() -> Self {
11734 Self {
11735 max_depth: default_wbs_max_depth(),
11736 min_elements_per_level: default_wbs_min_elements(),
11737 max_elements_per_level: default_wbs_max_elements(),
11738 }
11739 }
11740}
11741
11742#[derive(Debug, Clone, Serialize, Deserialize)]
11744pub struct CostAllocationConfig {
11745 #[serde(default = "default_time_entry_rate")]
11747 pub time_entry_project_rate: f64,
11748 #[serde(default = "default_expense_rate")]
11750 pub expense_project_rate: f64,
11751 #[serde(default = "default_po_rate")]
11753 pub purchase_order_project_rate: f64,
11754 #[serde(default = "default_vi_rate")]
11756 pub vendor_invoice_project_rate: f64,
11757}
11758
11759fn default_time_entry_rate() -> f64 {
11760 0.60
11761}
11762fn default_expense_rate() -> f64 {
11763 0.30
11764}
11765fn default_po_rate() -> f64 {
11766 0.40
11767}
11768fn default_vi_rate() -> f64 {
11769 0.35
11770}
11771
11772impl Default for CostAllocationConfig {
11773 fn default() -> Self {
11774 Self {
11775 time_entry_project_rate: default_time_entry_rate(),
11776 expense_project_rate: default_expense_rate(),
11777 purchase_order_project_rate: default_po_rate(),
11778 vendor_invoice_project_rate: default_vi_rate(),
11779 }
11780 }
11781}
11782
11783#[derive(Debug, Clone, Serialize, Deserialize)]
11785pub struct ProjectRevenueRecognitionConfig {
11786 #[serde(default = "default_true")]
11788 pub enabled: bool,
11789 #[serde(default = "default_revenue_method")]
11791 pub method: String,
11792 #[serde(default = "default_completion_measure")]
11794 pub completion_measure: String,
11795 #[serde(default = "default_avg_contract_value")]
11797 pub avg_contract_value: f64,
11798}
11799
11800fn default_revenue_method() -> String {
11801 "percentage_of_completion".to_string()
11802}
11803fn default_completion_measure() -> String {
11804 "cost_to_cost".to_string()
11805}
11806fn default_avg_contract_value() -> f64 {
11807 500_000.0
11808}
11809
11810impl Default for ProjectRevenueRecognitionConfig {
11811 fn default() -> Self {
11812 Self {
11813 enabled: true,
11814 method: default_revenue_method(),
11815 completion_measure: default_completion_measure(),
11816 avg_contract_value: default_avg_contract_value(),
11817 }
11818 }
11819}
11820
11821#[derive(Debug, Clone, Serialize, Deserialize)]
11823pub struct MilestoneSchemaConfig {
11824 #[serde(default = "default_true")]
11826 pub enabled: bool,
11827 #[serde(default = "default_milestones_per_project")]
11829 pub avg_per_project: u32,
11830 #[serde(default = "default_payment_milestone_rate")]
11832 pub payment_milestone_rate: f64,
11833}
11834
11835fn default_milestones_per_project() -> u32 {
11836 4
11837}
11838fn default_payment_milestone_rate() -> f64 {
11839 0.50
11840}
11841
11842impl Default for MilestoneSchemaConfig {
11843 fn default() -> Self {
11844 Self {
11845 enabled: true,
11846 avg_per_project: default_milestones_per_project(),
11847 payment_milestone_rate: default_payment_milestone_rate(),
11848 }
11849 }
11850}
11851
11852#[derive(Debug, Clone, Serialize, Deserialize)]
11854pub struct ChangeOrderSchemaConfig {
11855 #[serde(default = "default_true")]
11857 pub enabled: bool,
11858 #[serde(default = "default_change_order_probability")]
11860 pub probability: f64,
11861 #[serde(default = "default_max_change_orders")]
11863 pub max_per_project: u32,
11864 #[serde(default = "default_change_order_approval_rate")]
11866 pub approval_rate: f64,
11867}
11868
11869fn default_change_order_probability() -> f64 {
11870 0.40
11871}
11872fn default_max_change_orders() -> u32 {
11873 3
11874}
11875fn default_change_order_approval_rate() -> f64 {
11876 0.75
11877}
11878
11879impl Default for ChangeOrderSchemaConfig {
11880 fn default() -> Self {
11881 Self {
11882 enabled: true,
11883 probability: default_change_order_probability(),
11884 max_per_project: default_max_change_orders(),
11885 approval_rate: default_change_order_approval_rate(),
11886 }
11887 }
11888}
11889
11890#[derive(Debug, Clone, Serialize, Deserialize)]
11892pub struct RetainageSchemaConfig {
11893 #[serde(default)]
11895 pub enabled: bool,
11896 #[serde(default = "default_retainage_pct")]
11898 pub default_percentage: f64,
11899}
11900
11901fn default_retainage_pct() -> f64 {
11902 0.10
11903}
11904
11905impl Default for RetainageSchemaConfig {
11906 fn default() -> Self {
11907 Self {
11908 enabled: false,
11909 default_percentage: default_retainage_pct(),
11910 }
11911 }
11912}
11913
11914#[derive(Debug, Clone, Serialize, Deserialize)]
11916pub struct EarnedValueSchemaConfig {
11917 #[serde(default = "default_true")]
11919 pub enabled: bool,
11920 #[serde(default = "default_evm_frequency")]
11922 pub frequency: String,
11923}
11924
11925fn default_evm_frequency() -> String {
11926 "monthly".to_string()
11927}
11928
11929impl Default for EarnedValueSchemaConfig {
11930 fn default() -> Self {
11931 Self {
11932 enabled: true,
11933 frequency: default_evm_frequency(),
11934 }
11935 }
11936}
11937
11938#[derive(Debug, Clone, Serialize, Deserialize)]
11944pub struct EsgConfig {
11945 #[serde(default)]
11947 pub enabled: bool,
11948 #[serde(default)]
11950 pub environmental: EnvironmentalConfig,
11951 #[serde(default)]
11953 pub social: SocialConfig,
11954 #[serde(default)]
11956 pub governance: GovernanceSchemaConfig,
11957 #[serde(default)]
11959 pub supply_chain_esg: SupplyChainEsgConfig,
11960 #[serde(default)]
11962 pub reporting: EsgReportingConfig,
11963 #[serde(default)]
11965 pub climate_scenarios: ClimateScenarioConfig,
11966 #[serde(default = "default_esg_anomaly_rate")]
11968 pub anomaly_rate: f64,
11969}
11970
11971fn default_esg_anomaly_rate() -> f64 {
11972 0.02
11973}
11974
11975impl Default for EsgConfig {
11976 fn default() -> Self {
11977 Self {
11978 enabled: false,
11979 environmental: EnvironmentalConfig::default(),
11980 social: SocialConfig::default(),
11981 governance: GovernanceSchemaConfig::default(),
11982 supply_chain_esg: SupplyChainEsgConfig::default(),
11983 reporting: EsgReportingConfig::default(),
11984 climate_scenarios: ClimateScenarioConfig::default(),
11985 anomaly_rate: default_esg_anomaly_rate(),
11986 }
11987 }
11988}
11989
11990#[derive(Debug, Clone, Serialize, Deserialize, Default)]
11995pub struct CountryPacksSchemaConfig {
11996 #[serde(default)]
11998 pub external_dir: Option<PathBuf>,
11999 #[serde(default)]
12003 pub overrides: std::collections::HashMap<String, serde_json::Value>,
12004}
12005
12006#[derive(Debug, Clone, Serialize, Deserialize)]
12008pub struct EnvironmentalConfig {
12009 #[serde(default = "default_true")]
12011 pub enabled: bool,
12012 #[serde(default)]
12014 pub scope1: EmissionScopeConfig,
12015 #[serde(default)]
12017 pub scope2: EmissionScopeConfig,
12018 #[serde(default)]
12020 pub scope3: Scope3Config,
12021 #[serde(default)]
12023 pub energy: EnergySchemaConfig,
12024 #[serde(default)]
12026 pub water: WaterSchemaConfig,
12027 #[serde(default)]
12029 pub waste: WasteSchemaConfig,
12030}
12031
12032impl Default for EnvironmentalConfig {
12033 fn default() -> Self {
12034 Self {
12035 enabled: true,
12036 scope1: EmissionScopeConfig::default(),
12037 scope2: EmissionScopeConfig::default(),
12038 scope3: Scope3Config::default(),
12039 energy: EnergySchemaConfig::default(),
12040 water: WaterSchemaConfig::default(),
12041 waste: WasteSchemaConfig::default(),
12042 }
12043 }
12044}
12045
12046#[derive(Debug, Clone, Serialize, Deserialize)]
12048pub struct EmissionScopeConfig {
12049 #[serde(default = "default_true")]
12051 pub enabled: bool,
12052 #[serde(default = "default_emission_region")]
12054 pub factor_region: String,
12055}
12056
12057fn default_emission_region() -> String {
12058 "US".to_string()
12059}
12060
12061impl Default for EmissionScopeConfig {
12062 fn default() -> Self {
12063 Self {
12064 enabled: true,
12065 factor_region: default_emission_region(),
12066 }
12067 }
12068}
12069
12070#[derive(Debug, Clone, Serialize, Deserialize)]
12072pub struct Scope3Config {
12073 #[serde(default = "default_true")]
12075 pub enabled: bool,
12076 #[serde(default = "default_scope3_categories")]
12078 pub categories: Vec<String>,
12079 #[serde(default = "default_spend_intensity")]
12081 pub default_spend_intensity_kg_per_usd: f64,
12082}
12083
12084fn default_scope3_categories() -> Vec<String> {
12085 vec![
12086 "purchased_goods".to_string(),
12087 "business_travel".to_string(),
12088 "employee_commuting".to_string(),
12089 ]
12090}
12091
12092fn default_spend_intensity() -> f64 {
12093 0.5
12094}
12095
12096impl Default for Scope3Config {
12097 fn default() -> Self {
12098 Self {
12099 enabled: true,
12100 categories: default_scope3_categories(),
12101 default_spend_intensity_kg_per_usd: default_spend_intensity(),
12102 }
12103 }
12104}
12105
12106#[derive(Debug, Clone, Serialize, Deserialize)]
12108pub struct EnergySchemaConfig {
12109 #[serde(default = "default_true")]
12111 pub enabled: bool,
12112 #[serde(default = "default_facility_count")]
12114 pub facility_count: u32,
12115 #[serde(default = "default_renewable_target")]
12117 pub renewable_target: f64,
12118}
12119
12120fn default_facility_count() -> u32 {
12121 5
12122}
12123
12124fn default_renewable_target() -> f64 {
12125 0.30
12126}
12127
12128impl Default for EnergySchemaConfig {
12129 fn default() -> Self {
12130 Self {
12131 enabled: true,
12132 facility_count: default_facility_count(),
12133 renewable_target: default_renewable_target(),
12134 }
12135 }
12136}
12137
12138#[derive(Debug, Clone, Serialize, Deserialize)]
12140pub struct WaterSchemaConfig {
12141 #[serde(default = "default_true")]
12143 pub enabled: bool,
12144 #[serde(default = "default_water_facility_count")]
12146 pub facility_count: u32,
12147}
12148
12149fn default_water_facility_count() -> u32 {
12150 3
12151}
12152
12153impl Default for WaterSchemaConfig {
12154 fn default() -> Self {
12155 Self {
12156 enabled: true,
12157 facility_count: default_water_facility_count(),
12158 }
12159 }
12160}
12161
12162#[derive(Debug, Clone, Serialize, Deserialize)]
12164pub struct WasteSchemaConfig {
12165 #[serde(default = "default_true")]
12167 pub enabled: bool,
12168 #[serde(default = "default_diversion_target")]
12170 pub diversion_target: f64,
12171}
12172
12173fn default_diversion_target() -> f64 {
12174 0.50
12175}
12176
12177impl Default for WasteSchemaConfig {
12178 fn default() -> Self {
12179 Self {
12180 enabled: true,
12181 diversion_target: default_diversion_target(),
12182 }
12183 }
12184}
12185
12186#[derive(Debug, Clone, Serialize, Deserialize)]
12188pub struct SocialConfig {
12189 #[serde(default = "default_true")]
12191 pub enabled: bool,
12192 #[serde(default)]
12194 pub diversity: DiversitySchemaConfig,
12195 #[serde(default)]
12197 pub pay_equity: PayEquitySchemaConfig,
12198 #[serde(default)]
12200 pub safety: SafetySchemaConfig,
12201}
12202
12203impl Default for SocialConfig {
12204 fn default() -> Self {
12205 Self {
12206 enabled: true,
12207 diversity: DiversitySchemaConfig::default(),
12208 pay_equity: PayEquitySchemaConfig::default(),
12209 safety: SafetySchemaConfig::default(),
12210 }
12211 }
12212}
12213
12214#[derive(Debug, Clone, Serialize, Deserialize)]
12216pub struct DiversitySchemaConfig {
12217 #[serde(default = "default_true")]
12219 pub enabled: bool,
12220 #[serde(default = "default_diversity_dimensions")]
12222 pub dimensions: Vec<String>,
12223}
12224
12225fn default_diversity_dimensions() -> Vec<String> {
12226 vec![
12227 "gender".to_string(),
12228 "ethnicity".to_string(),
12229 "age_group".to_string(),
12230 ]
12231}
12232
12233impl Default for DiversitySchemaConfig {
12234 fn default() -> Self {
12235 Self {
12236 enabled: true,
12237 dimensions: default_diversity_dimensions(),
12238 }
12239 }
12240}
12241
12242#[derive(Debug, Clone, Serialize, Deserialize)]
12244pub struct PayEquitySchemaConfig {
12245 #[serde(default = "default_true")]
12247 pub enabled: bool,
12248 #[serde(default = "default_pay_gap_threshold")]
12250 pub gap_threshold: f64,
12251}
12252
12253fn default_pay_gap_threshold() -> f64 {
12254 0.05
12255}
12256
12257impl Default for PayEquitySchemaConfig {
12258 fn default() -> Self {
12259 Self {
12260 enabled: true,
12261 gap_threshold: default_pay_gap_threshold(),
12262 }
12263 }
12264}
12265
12266#[derive(Debug, Clone, Serialize, Deserialize)]
12268pub struct SafetySchemaConfig {
12269 #[serde(default = "default_true")]
12271 pub enabled: bool,
12272 #[serde(default = "default_trir_target")]
12274 pub target_trir: f64,
12275 #[serde(default = "default_incident_count")]
12277 pub incident_count: u32,
12278}
12279
12280fn default_trir_target() -> f64 {
12281 2.5
12282}
12283
12284fn default_incident_count() -> u32 {
12285 20
12286}
12287
12288impl Default for SafetySchemaConfig {
12289 fn default() -> Self {
12290 Self {
12291 enabled: true,
12292 target_trir: default_trir_target(),
12293 incident_count: default_incident_count(),
12294 }
12295 }
12296}
12297
12298#[derive(Debug, Clone, Serialize, Deserialize)]
12300pub struct GovernanceSchemaConfig {
12301 #[serde(default = "default_true")]
12303 pub enabled: bool,
12304 #[serde(default = "default_board_size")]
12306 pub board_size: u32,
12307 #[serde(default = "default_independence_target")]
12309 pub independence_target: f64,
12310}
12311
12312fn default_board_size() -> u32 {
12313 11
12314}
12315
12316fn default_independence_target() -> f64 {
12317 0.67
12318}
12319
12320impl Default for GovernanceSchemaConfig {
12321 fn default() -> Self {
12322 Self {
12323 enabled: true,
12324 board_size: default_board_size(),
12325 independence_target: default_independence_target(),
12326 }
12327 }
12328}
12329
12330#[derive(Debug, Clone, Serialize, Deserialize)]
12332pub struct SupplyChainEsgConfig {
12333 #[serde(default = "default_true")]
12335 pub enabled: bool,
12336 #[serde(default = "default_assessment_coverage")]
12338 pub assessment_coverage: f64,
12339 #[serde(default = "default_high_risk_countries")]
12341 pub high_risk_countries: Vec<String>,
12342}
12343
12344fn default_assessment_coverage() -> f64 {
12345 0.80
12346}
12347
12348fn default_high_risk_countries() -> Vec<String> {
12349 vec!["CN".to_string(), "BD".to_string(), "MM".to_string()]
12350}
12351
12352impl Default for SupplyChainEsgConfig {
12353 fn default() -> Self {
12354 Self {
12355 enabled: true,
12356 assessment_coverage: default_assessment_coverage(),
12357 high_risk_countries: default_high_risk_countries(),
12358 }
12359 }
12360}
12361
12362#[derive(Debug, Clone, Serialize, Deserialize)]
12364pub struct EsgReportingConfig {
12365 #[serde(default = "default_true")]
12367 pub enabled: bool,
12368 #[serde(default = "default_esg_frameworks")]
12370 pub frameworks: Vec<String>,
12371 #[serde(default = "default_true")]
12373 pub materiality_assessment: bool,
12374 #[serde(default = "default_materiality_threshold")]
12376 pub impact_threshold: f64,
12377 #[serde(default = "default_materiality_threshold")]
12379 pub financial_threshold: f64,
12380}
12381
12382fn default_esg_frameworks() -> Vec<String> {
12383 vec!["GRI".to_string(), "ESRS".to_string()]
12384}
12385
12386fn default_materiality_threshold() -> f64 {
12387 0.6
12388}
12389
12390impl Default for EsgReportingConfig {
12391 fn default() -> Self {
12392 Self {
12393 enabled: true,
12394 frameworks: default_esg_frameworks(),
12395 materiality_assessment: true,
12396 impact_threshold: default_materiality_threshold(),
12397 financial_threshold: default_materiality_threshold(),
12398 }
12399 }
12400}
12401
12402#[derive(Debug, Clone, Serialize, Deserialize)]
12404pub struct ClimateScenarioConfig {
12405 #[serde(default)]
12407 pub enabled: bool,
12408 #[serde(default = "default_climate_scenarios")]
12410 pub scenarios: Vec<String>,
12411 #[serde(default = "default_time_horizons")]
12413 pub time_horizons: Vec<u32>,
12414}
12415
12416fn default_climate_scenarios() -> Vec<String> {
12417 vec![
12418 "net_zero_2050".to_string(),
12419 "stated_policies".to_string(),
12420 "current_trajectory".to_string(),
12421 ]
12422}
12423
12424fn default_time_horizons() -> Vec<u32> {
12425 vec![5, 10, 30]
12426}
12427
12428impl Default for ClimateScenarioConfig {
12429 fn default() -> Self {
12430 Self {
12431 enabled: false,
12432 scenarios: default_climate_scenarios(),
12433 time_horizons: default_time_horizons(),
12434 }
12435 }
12436}
12437
12438#[derive(Debug, Clone, Serialize, Deserialize, Default)]
12442pub struct ScenariosConfig {
12443 #[serde(default)]
12445 pub enabled: bool,
12446 #[serde(default)]
12448 pub scenarios: Vec<ScenarioSchemaConfig>,
12449 #[serde(default)]
12451 pub causal_model: CausalModelSchemaConfig,
12452 #[serde(default)]
12454 pub defaults: ScenarioDefaultsConfig,
12455}
12456
12457#[derive(Debug, Clone, Serialize, Deserialize)]
12459pub struct ScenarioSchemaConfig {
12460 pub name: String,
12462 #[serde(default)]
12464 pub description: String,
12465 #[serde(default)]
12467 pub tags: Vec<String>,
12468 pub base: Option<String>,
12470 pub probability_weight: Option<f64>,
12472 #[serde(default)]
12474 pub interventions: Vec<InterventionSchemaConfig>,
12475 #[serde(default)]
12477 pub constraints: ScenarioConstraintsSchemaConfig,
12478 #[serde(default)]
12480 pub output: ScenarioOutputSchemaConfig,
12481 #[serde(default)]
12483 pub metadata: std::collections::HashMap<String, String>,
12484}
12485
12486#[derive(Debug, Clone, Serialize, Deserialize)]
12488pub struct InterventionSchemaConfig {
12489 #[serde(flatten)]
12491 pub intervention_type: serde_json::Value,
12492 #[serde(default)]
12494 pub timing: InterventionTimingSchemaConfig,
12495 pub label: Option<String>,
12497 #[serde(default)]
12499 pub priority: u32,
12500}
12501
12502#[derive(Debug, Clone, Serialize, Deserialize)]
12504pub struct InterventionTimingSchemaConfig {
12505 #[serde(default = "default_start_month")]
12507 pub start_month: u32,
12508 pub duration_months: Option<u32>,
12510 #[serde(default = "default_onset")]
12512 pub onset: String,
12513 pub ramp_months: Option<u32>,
12515}
12516
12517fn default_start_month() -> u32 {
12518 1
12519}
12520
12521fn default_onset() -> String {
12522 "sudden".to_string()
12523}
12524
12525impl Default for InterventionTimingSchemaConfig {
12526 fn default() -> Self {
12527 Self {
12528 start_month: 1,
12529 duration_months: None,
12530 onset: "sudden".to_string(),
12531 ramp_months: None,
12532 }
12533 }
12534}
12535
12536#[derive(Debug, Clone, Serialize, Deserialize)]
12538pub struct ScenarioConstraintsSchemaConfig {
12539 #[serde(default = "default_true")]
12540 pub preserve_accounting_identity: bool,
12541 #[serde(default = "default_true")]
12542 pub preserve_document_chains: bool,
12543 #[serde(default = "default_true")]
12544 pub preserve_period_close: bool,
12545 #[serde(default = "default_true")]
12546 pub preserve_balance_coherence: bool,
12547 #[serde(default)]
12548 pub custom: Vec<CustomConstraintSchemaConfig>,
12549}
12550
12551impl Default for ScenarioConstraintsSchemaConfig {
12552 fn default() -> Self {
12553 Self {
12554 preserve_accounting_identity: true,
12555 preserve_document_chains: true,
12556 preserve_period_close: true,
12557 preserve_balance_coherence: true,
12558 custom: Vec::new(),
12559 }
12560 }
12561}
12562
12563#[derive(Debug, Clone, Serialize, Deserialize)]
12565pub struct CustomConstraintSchemaConfig {
12566 pub config_path: String,
12567 pub min: Option<f64>,
12568 pub max: Option<f64>,
12569 #[serde(default)]
12570 pub description: String,
12571}
12572
12573#[derive(Debug, Clone, Serialize, Deserialize)]
12575pub struct ScenarioOutputSchemaConfig {
12576 #[serde(default = "default_true")]
12577 pub paired: bool,
12578 #[serde(default = "default_diff_formats_schema")]
12579 pub diff_formats: Vec<String>,
12580 #[serde(default)]
12581 pub diff_scope: Vec<String>,
12582}
12583
12584fn default_diff_formats_schema() -> Vec<String> {
12585 vec!["summary".to_string(), "aggregate".to_string()]
12586}
12587
12588impl Default for ScenarioOutputSchemaConfig {
12589 fn default() -> Self {
12590 Self {
12591 paired: true,
12592 diff_formats: default_diff_formats_schema(),
12593 diff_scope: Vec::new(),
12594 }
12595 }
12596}
12597
12598#[derive(Debug, Clone, Serialize, Deserialize)]
12600pub struct CausalModelSchemaConfig {
12601 #[serde(default = "default_causal_preset")]
12603 pub preset: String,
12604 #[serde(default)]
12606 pub nodes: Vec<serde_json::Value>,
12607 #[serde(default)]
12609 pub edges: Vec<serde_json::Value>,
12610}
12611
12612fn default_causal_preset() -> String {
12613 "default".to_string()
12614}
12615
12616impl Default for CausalModelSchemaConfig {
12617 fn default() -> Self {
12618 Self {
12619 preset: "default".to_string(),
12620 nodes: Vec::new(),
12621 edges: Vec::new(),
12622 }
12623 }
12624}
12625
12626#[derive(Debug, Clone, Serialize, Deserialize, Default)]
12628pub struct ScenarioDefaultsConfig {
12629 #[serde(default)]
12630 pub constraints: ScenarioConstraintsSchemaConfig,
12631 #[serde(default)]
12632 pub output: ScenarioOutputSchemaConfig,
12633}
12634
12635#[derive(Debug, Clone, Default, Serialize, Deserialize)]
12668pub struct ComplianceRegulationsConfig {
12669 #[serde(default)]
12671 pub enabled: bool,
12672 #[serde(default)]
12675 pub jurisdictions: Vec<String>,
12676 #[serde(default)]
12679 pub reference_date: Option<String>,
12680 #[serde(default)]
12682 pub standards_selection: StandardsSelectionConfig,
12683 #[serde(default)]
12685 pub audit_procedures: AuditProcedureGenConfig,
12686 #[serde(default)]
12688 pub findings: ComplianceFindingGenConfig,
12689 #[serde(default)]
12691 pub filings: ComplianceFilingGenConfig,
12692 #[serde(default)]
12694 pub graph: ComplianceGraphConfig,
12695 #[serde(default)]
12697 pub output: ComplianceOutputConfig,
12698}
12699
12700#[derive(Debug, Clone, Default, Serialize, Deserialize)]
12702pub struct StandardsSelectionConfig {
12703 #[serde(default)]
12706 pub categories: Vec<String>,
12707 #[serde(default)]
12710 pub include: Vec<String>,
12711 #[serde(default)]
12713 pub exclude: Vec<String>,
12714 #[serde(default)]
12716 pub include_superseded: bool,
12717}
12718
12719#[derive(Debug, Clone, Serialize, Deserialize)]
12721pub struct AuditProcedureGenConfig {
12722 #[serde(default)]
12724 pub enabled: bool,
12725 #[serde(default = "default_procedures_per_standard")]
12727 pub procedures_per_standard: usize,
12728 #[serde(default = "default_sampling_method")]
12730 pub sampling_method: String,
12731 #[serde(default = "default_confidence_level")]
12733 pub confidence_level: f64,
12734 #[serde(default = "default_tolerable_misstatement")]
12736 pub tolerable_misstatement: f64,
12737}
12738
12739fn default_procedures_per_standard() -> usize {
12740 3
12741}
12742
12743fn default_sampling_method() -> String {
12744 "statistical".to_string()
12745}
12746
12747fn default_confidence_level() -> f64 {
12748 0.95
12749}
12750
12751fn default_tolerable_misstatement() -> f64 {
12752 0.05
12753}
12754
12755impl Default for AuditProcedureGenConfig {
12756 fn default() -> Self {
12757 Self {
12758 enabled: false,
12759 procedures_per_standard: default_procedures_per_standard(),
12760 sampling_method: default_sampling_method(),
12761 confidence_level: default_confidence_level(),
12762 tolerable_misstatement: default_tolerable_misstatement(),
12763 }
12764 }
12765}
12766
12767#[derive(Debug, Clone, Serialize, Deserialize)]
12769pub struct ComplianceFindingGenConfig {
12770 #[serde(default)]
12772 pub enabled: bool,
12773 #[serde(default = "default_finding_rate")]
12775 pub finding_rate: f64,
12776 #[serde(default = "default_cr_material_weakness_rate")]
12778 pub material_weakness_rate: f64,
12779 #[serde(default = "default_cr_significant_deficiency_rate")]
12781 pub significant_deficiency_rate: f64,
12782 #[serde(default = "default_true")]
12784 pub generate_remediation: bool,
12785}
12786
12787fn default_finding_rate() -> f64 {
12788 0.05
12789}
12790
12791fn default_cr_material_weakness_rate() -> f64 {
12792 0.02
12793}
12794
12795fn default_cr_significant_deficiency_rate() -> f64 {
12796 0.08
12797}
12798
12799impl Default for ComplianceFindingGenConfig {
12800 fn default() -> Self {
12801 Self {
12802 enabled: false,
12803 finding_rate: default_finding_rate(),
12804 material_weakness_rate: default_cr_material_weakness_rate(),
12805 significant_deficiency_rate: default_cr_significant_deficiency_rate(),
12806 generate_remediation: true,
12807 }
12808 }
12809}
12810
12811#[derive(Debug, Clone, Serialize, Deserialize)]
12813pub struct ComplianceFilingGenConfig {
12814 #[serde(default)]
12816 pub enabled: bool,
12817 #[serde(default)]
12820 pub filing_types: Vec<String>,
12821 #[serde(default = "default_true")]
12823 pub generate_status_progression: bool,
12824}
12825
12826impl Default for ComplianceFilingGenConfig {
12827 fn default() -> Self {
12828 Self {
12829 enabled: false,
12830 filing_types: Vec::new(),
12831 generate_status_progression: true,
12832 }
12833 }
12834}
12835
12836#[derive(Debug, Clone, Serialize, Deserialize)]
12838pub struct ComplianceGraphConfig {
12839 #[serde(default)]
12841 pub enabled: bool,
12842 #[serde(default = "default_true")]
12844 pub include_compliance_nodes: bool,
12845 #[serde(default = "default_true")]
12847 pub include_compliance_edges: bool,
12848 #[serde(default = "default_true")]
12850 pub include_cross_references: bool,
12851 #[serde(default)]
12853 pub include_supersession_edges: bool,
12854 #[serde(default = "default_true")]
12856 pub include_account_links: bool,
12857 #[serde(default = "default_true")]
12859 pub include_control_links: bool,
12860 #[serde(default = "default_true")]
12862 pub include_company_links: bool,
12863}
12864
12865impl Default for ComplianceGraphConfig {
12866 fn default() -> Self {
12867 Self {
12868 enabled: false,
12869 include_compliance_nodes: true,
12870 include_compliance_edges: true,
12871 include_cross_references: true,
12872 include_supersession_edges: false,
12873 include_account_links: true,
12874 include_control_links: true,
12875 include_company_links: true,
12876 }
12877 }
12878}
12879
12880#[derive(Debug, Clone, Serialize, Deserialize)]
12882pub struct ComplianceOutputConfig {
12883 #[serde(default = "default_true")]
12885 pub export_registry: bool,
12886 #[serde(default = "default_true")]
12888 pub export_jurisdictions: bool,
12889 #[serde(default = "default_true")]
12891 pub export_cross_references: bool,
12892 #[serde(default)]
12894 pub export_version_history: bool,
12895}
12896
12897impl Default for ComplianceOutputConfig {
12898 fn default() -> Self {
12899 Self {
12900 export_registry: true,
12901 export_jurisdictions: true,
12902 export_cross_references: true,
12903 export_version_history: false,
12904 }
12905 }
12906}
12907
12908#[cfg(test)]
12909#[allow(clippy::unwrap_used)]
12910mod tests {
12911 use super::*;
12912 use crate::presets::demo_preset;
12913
12914 #[test]
12919 fn test_config_yaml_roundtrip() {
12920 let config = demo_preset();
12921 let yaml = serde_yaml::to_string(&config).expect("Failed to serialize to YAML");
12922 let deserialized: GeneratorConfig =
12923 serde_yaml::from_str(&yaml).expect("Failed to deserialize from YAML");
12924
12925 assert_eq!(
12926 config.global.period_months,
12927 deserialized.global.period_months
12928 );
12929 assert_eq!(config.global.industry, deserialized.global.industry);
12930 assert_eq!(config.companies.len(), deserialized.companies.len());
12931 assert_eq!(config.companies[0].code, deserialized.companies[0].code);
12932 }
12933
12934 #[test]
12935 fn test_config_json_roundtrip() {
12936 let mut config = demo_preset();
12938 config.master_data.employees.approval_limits.executive = 1e12;
12940
12941 let json = serde_json::to_string(&config).expect("Failed to serialize to JSON");
12942 let deserialized: GeneratorConfig =
12943 serde_json::from_str(&json).expect("Failed to deserialize from JSON");
12944
12945 assert_eq!(
12946 config.global.period_months,
12947 deserialized.global.period_months
12948 );
12949 assert_eq!(config.global.industry, deserialized.global.industry);
12950 assert_eq!(config.companies.len(), deserialized.companies.len());
12951 }
12952
12953 #[test]
12954 fn test_transaction_volume_serialization() {
12955 let volumes = vec![
12957 (TransactionVolume::TenK, "ten_k"),
12958 (TransactionVolume::HundredK, "hundred_k"),
12959 (TransactionVolume::OneM, "one_m"),
12960 (TransactionVolume::TenM, "ten_m"),
12961 (TransactionVolume::HundredM, "hundred_m"),
12962 ];
12963
12964 for (volume, expected_key) in volumes {
12965 let json = serde_json::to_string(&volume).expect("Failed to serialize");
12966 assert!(
12967 json.contains(expected_key),
12968 "Expected {} in JSON: {}",
12969 expected_key,
12970 json
12971 );
12972 }
12973 }
12974
12975 #[test]
12976 fn test_transaction_volume_custom_serialization() {
12977 let volume = TransactionVolume::Custom(12345);
12978 let json = serde_json::to_string(&volume).expect("Failed to serialize");
12979 let deserialized: TransactionVolume =
12980 serde_json::from_str(&json).expect("Failed to deserialize");
12981 assert_eq!(deserialized.count(), 12345);
12982 }
12983
12984 #[test]
12985 fn test_output_mode_serialization() {
12986 let modes = vec![
12987 OutputMode::Streaming,
12988 OutputMode::FlatFile,
12989 OutputMode::Both,
12990 ];
12991
12992 for mode in modes {
12993 let json = serde_json::to_string(&mode).expect("Failed to serialize");
12994 let deserialized: OutputMode =
12995 serde_json::from_str(&json).expect("Failed to deserialize");
12996 assert!(format!("{:?}", mode) == format!("{:?}", deserialized));
12997 }
12998 }
12999
13000 #[test]
13001 fn test_file_format_serialization() {
13002 let formats = vec![
13003 FileFormat::Csv,
13004 FileFormat::Parquet,
13005 FileFormat::Json,
13006 FileFormat::JsonLines,
13007 ];
13008
13009 for format in formats {
13010 let json = serde_json::to_string(&format).expect("Failed to serialize");
13011 let deserialized: FileFormat =
13012 serde_json::from_str(&json).expect("Failed to deserialize");
13013 assert!(format!("{:?}", format) == format!("{:?}", deserialized));
13014 }
13015 }
13016
13017 #[test]
13018 fn test_compression_algorithm_serialization() {
13019 let algos = vec![
13020 CompressionAlgorithm::Gzip,
13021 CompressionAlgorithm::Zstd,
13022 CompressionAlgorithm::Lz4,
13023 CompressionAlgorithm::Snappy,
13024 ];
13025
13026 for algo in algos {
13027 let json = serde_json::to_string(&algo).expect("Failed to serialize");
13028 let deserialized: CompressionAlgorithm =
13029 serde_json::from_str(&json).expect("Failed to deserialize");
13030 assert!(format!("{:?}", algo) == format!("{:?}", deserialized));
13031 }
13032 }
13033
13034 #[test]
13035 fn test_transfer_pricing_method_serialization() {
13036 let methods = vec![
13037 TransferPricingMethod::CostPlus,
13038 TransferPricingMethod::ComparableUncontrolled,
13039 TransferPricingMethod::ResalePrice,
13040 TransferPricingMethod::TransactionalNetMargin,
13041 TransferPricingMethod::ProfitSplit,
13042 ];
13043
13044 for method in methods {
13045 let json = serde_json::to_string(&method).expect("Failed to serialize");
13046 let deserialized: TransferPricingMethod =
13047 serde_json::from_str(&json).expect("Failed to deserialize");
13048 assert!(format!("{:?}", method) == format!("{:?}", deserialized));
13049 }
13050 }
13051
13052 #[test]
13053 fn test_benford_exemption_serialization() {
13054 let exemptions = vec![
13055 BenfordExemption::Recurring,
13056 BenfordExemption::Payroll,
13057 BenfordExemption::FixedFees,
13058 BenfordExemption::RoundAmounts,
13059 ];
13060
13061 for exemption in exemptions {
13062 let json = serde_json::to_string(&exemption).expect("Failed to serialize");
13063 let deserialized: BenfordExemption =
13064 serde_json::from_str(&json).expect("Failed to deserialize");
13065 assert!(format!("{:?}", exemption) == format!("{:?}", deserialized));
13066 }
13067 }
13068
13069 #[test]
13074 fn test_global_config_defaults() {
13075 let yaml = r#"
13076 industry: manufacturing
13077 start_date: "2024-01-01"
13078 period_months: 6
13079 "#;
13080 let config: GlobalConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13081 assert_eq!(config.group_currency, "USD");
13082 assert!(config.parallel);
13083 assert_eq!(config.worker_threads, 0);
13084 assert_eq!(config.memory_limit_mb, 0);
13085 }
13086
13087 #[test]
13088 fn test_fraud_config_defaults() {
13089 let config = FraudConfig::default();
13090 assert!(!config.enabled);
13091 assert_eq!(config.fraud_rate, 0.005);
13092 assert!(!config.clustering_enabled);
13093 }
13094
13095 #[test]
13096 fn test_internal_controls_config_defaults() {
13097 let config = InternalControlsConfig::default();
13098 assert!(!config.enabled);
13099 assert_eq!(config.exception_rate, 0.02);
13100 assert_eq!(config.sod_violation_rate, 0.01);
13101 assert!(config.export_control_master_data);
13102 assert_eq!(config.sox_materiality_threshold, 10000.0);
13103 assert!(config.coso_enabled);
13105 assert!(!config.include_entity_level_controls);
13106 assert_eq!(config.target_maturity_level, "mixed");
13107 }
13108
13109 #[test]
13110 fn test_output_config_defaults() {
13111 let config = OutputConfig::default();
13112 assert!(matches!(config.mode, OutputMode::FlatFile));
13113 assert_eq!(config.formats, vec![FileFormat::Parquet]);
13114 assert!(config.compression.enabled);
13115 assert!(matches!(
13116 config.compression.algorithm,
13117 CompressionAlgorithm::Zstd
13118 ));
13119 assert!(config.include_acdoca);
13120 assert!(!config.include_bseg);
13121 assert!(config.partition_by_period);
13122 assert!(!config.partition_by_company);
13123 }
13124
13125 #[test]
13126 fn test_approval_config_defaults() {
13127 let config = ApprovalConfig::default();
13128 assert!(!config.enabled);
13129 assert_eq!(config.auto_approve_threshold, 1000.0);
13130 assert_eq!(config.rejection_rate, 0.02);
13131 assert_eq!(config.revision_rate, 0.05);
13132 assert_eq!(config.average_approval_delay_hours, 4.0);
13133 assert_eq!(config.thresholds.len(), 4);
13134 }
13135
13136 #[test]
13137 fn test_p2p_flow_config_defaults() {
13138 let config = P2PFlowConfig::default();
13139 assert!(config.enabled);
13140 assert_eq!(config.three_way_match_rate, 0.95);
13141 assert_eq!(config.partial_delivery_rate, 0.15);
13142 assert_eq!(config.average_po_to_gr_days, 14);
13143 }
13144
13145 #[test]
13146 fn test_o2c_flow_config_defaults() {
13147 let config = O2CFlowConfig::default();
13148 assert!(config.enabled);
13149 assert_eq!(config.credit_check_failure_rate, 0.02);
13150 assert_eq!(config.return_rate, 0.03);
13151 assert_eq!(config.bad_debt_rate, 0.01);
13152 }
13153
13154 #[test]
13155 fn test_balance_config_defaults() {
13156 let config = BalanceConfig::default();
13157 assert!(!config.generate_opening_balances);
13158 assert!(config.generate_trial_balances);
13159 assert_eq!(config.target_gross_margin, 0.35);
13160 assert!(config.validate_balance_equation);
13161 assert!(config.reconcile_subledgers);
13162 }
13163
13164 #[test]
13169 fn test_partial_config_with_defaults() {
13170 let yaml = r#"
13172 global:
13173 industry: manufacturing
13174 start_date: "2024-01-01"
13175 period_months: 3
13176 companies:
13177 - code: "TEST"
13178 name: "Test Company"
13179 currency: "USD"
13180 country: "US"
13181 annual_transaction_volume: ten_k
13182 chart_of_accounts:
13183 complexity: small
13184 output:
13185 output_directory: "./output"
13186 "#;
13187
13188 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13189 assert_eq!(config.global.period_months, 3);
13190 assert_eq!(config.companies.len(), 1);
13191 assert!(!config.fraud.enabled); assert!(!config.internal_controls.enabled); }
13194
13195 #[test]
13196 fn test_config_with_fraud_enabled() {
13197 let yaml = r#"
13198 global:
13199 industry: retail
13200 start_date: "2024-01-01"
13201 period_months: 12
13202 companies:
13203 - code: "RETAIL"
13204 name: "Retail Co"
13205 currency: "USD"
13206 country: "US"
13207 annual_transaction_volume: hundred_k
13208 chart_of_accounts:
13209 complexity: medium
13210 output:
13211 output_directory: "./output"
13212 fraud:
13213 enabled: true
13214 fraud_rate: 0.05
13215 clustering_enabled: true
13216 "#;
13217
13218 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13219 assert!(config.fraud.enabled);
13220 assert_eq!(config.fraud.fraud_rate, 0.05);
13221 assert!(config.fraud.clustering_enabled);
13222 }
13223
13224 #[test]
13225 fn test_config_with_multiple_companies() {
13226 let yaml = r#"
13227 global:
13228 industry: manufacturing
13229 start_date: "2024-01-01"
13230 period_months: 6
13231 companies:
13232 - code: "HQ"
13233 name: "Headquarters"
13234 currency: "USD"
13235 country: "US"
13236 annual_transaction_volume: hundred_k
13237 volume_weight: 1.0
13238 - code: "EU"
13239 name: "European Subsidiary"
13240 currency: "EUR"
13241 country: "DE"
13242 annual_transaction_volume: hundred_k
13243 volume_weight: 0.5
13244 - code: "APAC"
13245 name: "Asia Pacific"
13246 currency: "JPY"
13247 country: "JP"
13248 annual_transaction_volume: ten_k
13249 volume_weight: 0.3
13250 chart_of_accounts:
13251 complexity: large
13252 output:
13253 output_directory: "./output"
13254 "#;
13255
13256 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13257 assert_eq!(config.companies.len(), 3);
13258 assert_eq!(config.companies[0].code, "HQ");
13259 assert_eq!(config.companies[1].currency, "EUR");
13260 assert_eq!(config.companies[2].volume_weight, 0.3);
13261 }
13262
13263 #[test]
13264 fn test_intercompany_config() {
13265 let yaml = r#"
13266 enabled: true
13267 ic_transaction_rate: 0.20
13268 transfer_pricing_method: cost_plus
13269 markup_percent: 0.08
13270 generate_matched_pairs: true
13271 generate_eliminations: true
13272 "#;
13273
13274 let config: IntercompanyConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13275 assert!(config.enabled);
13276 assert_eq!(config.ic_transaction_rate, 0.20);
13277 assert!(matches!(
13278 config.transfer_pricing_method,
13279 TransferPricingMethod::CostPlus
13280 ));
13281 assert_eq!(config.markup_percent, 0.08);
13282 assert!(config.generate_eliminations);
13283 }
13284
13285 #[test]
13290 fn test_company_config_defaults() {
13291 let yaml = r#"
13292 code: "TEST"
13293 name: "Test Company"
13294 currency: "USD"
13295 country: "US"
13296 annual_transaction_volume: ten_k
13297 "#;
13298
13299 let config: CompanyConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13300 assert_eq!(config.fiscal_year_variant, "K4"); assert_eq!(config.volume_weight, 1.0); }
13303
13304 #[test]
13309 fn test_coa_config_defaults() {
13310 let yaml = r#"
13311 complexity: medium
13312 "#;
13313
13314 let config: ChartOfAccountsConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13315 assert!(config.industry_specific); assert!(config.custom_accounts.is_none());
13317 assert_eq!(config.min_hierarchy_depth, 2); assert_eq!(config.max_hierarchy_depth, 5); }
13320
13321 #[test]
13326 fn test_accounting_standards_config_defaults() {
13327 let config = AccountingStandardsConfig::default();
13328 assert!(!config.enabled);
13329 assert!(config.framework.is_none());
13330 assert!(!config.revenue_recognition.enabled);
13331 assert!(!config.leases.enabled);
13332 assert!(!config.fair_value.enabled);
13333 assert!(!config.impairment.enabled);
13334 assert!(!config.generate_differences);
13335 }
13336
13337 #[test]
13338 fn test_accounting_standards_config_yaml() {
13339 let yaml = r#"
13340 enabled: true
13341 framework: ifrs
13342 revenue_recognition:
13343 enabled: true
13344 generate_contracts: true
13345 avg_obligations_per_contract: 2.5
13346 variable_consideration_rate: 0.20
13347 over_time_recognition_rate: 0.35
13348 contract_count: 150
13349 leases:
13350 enabled: true
13351 lease_count: 75
13352 finance_lease_percent: 0.25
13353 avg_lease_term_months: 48
13354 generate_differences: true
13355 "#;
13356
13357 let config: AccountingStandardsConfig =
13358 serde_yaml::from_str(yaml).expect("Failed to parse");
13359 assert!(config.enabled);
13360 assert!(matches!(
13361 config.framework,
13362 Some(AccountingFrameworkConfig::Ifrs)
13363 ));
13364 assert!(config.revenue_recognition.enabled);
13365 assert_eq!(config.revenue_recognition.contract_count, 150);
13366 assert_eq!(config.revenue_recognition.avg_obligations_per_contract, 2.5);
13367 assert!(config.leases.enabled);
13368 assert_eq!(config.leases.lease_count, 75);
13369 assert_eq!(config.leases.finance_lease_percent, 0.25);
13370 assert!(config.generate_differences);
13371 }
13372
13373 #[test]
13374 fn test_accounting_framework_serialization() {
13375 let frameworks = [
13376 AccountingFrameworkConfig::UsGaap,
13377 AccountingFrameworkConfig::Ifrs,
13378 AccountingFrameworkConfig::DualReporting,
13379 AccountingFrameworkConfig::FrenchGaap,
13380 AccountingFrameworkConfig::GermanGaap,
13381 ];
13382
13383 for framework in frameworks {
13384 let json = serde_json::to_string(&framework).expect("Failed to serialize");
13385 let deserialized: AccountingFrameworkConfig =
13386 serde_json::from_str(&json).expect("Failed to deserialize");
13387 assert!(format!("{:?}", framework) == format!("{:?}", deserialized));
13388 }
13389 }
13390
13391 #[test]
13392 fn test_revenue_recognition_config_defaults() {
13393 let config = RevenueRecognitionConfig::default();
13394 assert!(!config.enabled);
13395 assert!(config.generate_contracts);
13396 assert_eq!(config.avg_obligations_per_contract, 2.0);
13397 assert_eq!(config.variable_consideration_rate, 0.15);
13398 assert_eq!(config.over_time_recognition_rate, 0.30);
13399 assert_eq!(config.contract_count, 100);
13400 }
13401
13402 #[test]
13403 fn test_lease_accounting_config_defaults() {
13404 let config = LeaseAccountingConfig::default();
13405 assert!(!config.enabled);
13406 assert_eq!(config.lease_count, 50);
13407 assert_eq!(config.finance_lease_percent, 0.30);
13408 assert_eq!(config.avg_lease_term_months, 60);
13409 assert!(config.generate_amortization);
13410 assert_eq!(config.real_estate_percent, 0.40);
13411 }
13412
13413 #[test]
13414 fn test_fair_value_config_defaults() {
13415 let config = FairValueConfig::default();
13416 assert!(!config.enabled);
13417 assert_eq!(config.measurement_count, 25);
13418 assert_eq!(config.level1_percent, 0.40);
13419 assert_eq!(config.level2_percent, 0.35);
13420 assert_eq!(config.level3_percent, 0.25);
13421 assert!(!config.include_sensitivity_analysis);
13422 }
13423
13424 #[test]
13425 fn test_impairment_config_defaults() {
13426 let config = ImpairmentConfig::default();
13427 assert!(!config.enabled);
13428 assert_eq!(config.test_count, 15);
13429 assert_eq!(config.impairment_rate, 0.10);
13430 assert!(config.generate_projections);
13431 assert!(!config.include_goodwill);
13432 }
13433
13434 #[test]
13439 fn test_audit_standards_config_defaults() {
13440 let config = AuditStandardsConfig::default();
13441 assert!(!config.enabled);
13442 assert!(!config.isa_compliance.enabled);
13443 assert!(!config.analytical_procedures.enabled);
13444 assert!(!config.confirmations.enabled);
13445 assert!(!config.opinion.enabled);
13446 assert!(!config.generate_audit_trail);
13447 assert!(!config.sox.enabled);
13448 assert!(!config.pcaob.enabled);
13449 }
13450
13451 #[test]
13452 fn test_audit_standards_config_yaml() {
13453 let yaml = r#"
13454 enabled: true
13455 isa_compliance:
13456 enabled: true
13457 compliance_level: comprehensive
13458 generate_isa_mappings: true
13459 include_pcaob: true
13460 framework: dual
13461 analytical_procedures:
13462 enabled: true
13463 procedures_per_account: 5
13464 variance_probability: 0.25
13465 confirmations:
13466 enabled: true
13467 confirmation_count: 75
13468 positive_response_rate: 0.90
13469 exception_rate: 0.08
13470 opinion:
13471 enabled: true
13472 generate_kam: true
13473 average_kam_count: 4
13474 sox:
13475 enabled: true
13476 generate_302_certifications: true
13477 generate_404_assessments: true
13478 material_weakness_rate: 0.03
13479 pcaob:
13480 enabled: true
13481 is_pcaob_audit: true
13482 include_icfr_opinion: true
13483 generate_audit_trail: true
13484 "#;
13485
13486 let config: AuditStandardsConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13487 assert!(config.enabled);
13488 assert!(config.isa_compliance.enabled);
13489 assert_eq!(config.isa_compliance.compliance_level, "comprehensive");
13490 assert!(config.isa_compliance.include_pcaob);
13491 assert_eq!(config.isa_compliance.framework, "dual");
13492 assert!(config.analytical_procedures.enabled);
13493 assert_eq!(config.analytical_procedures.procedures_per_account, 5);
13494 assert!(config.confirmations.enabled);
13495 assert_eq!(config.confirmations.confirmation_count, 75);
13496 assert!(config.opinion.enabled);
13497 assert_eq!(config.opinion.average_kam_count, 4);
13498 assert!(config.sox.enabled);
13499 assert!(config.sox.generate_302_certifications);
13500 assert_eq!(config.sox.material_weakness_rate, 0.03);
13501 assert!(config.pcaob.enabled);
13502 assert!(config.pcaob.is_pcaob_audit);
13503 assert!(config.pcaob.include_icfr_opinion);
13504 assert!(config.generate_audit_trail);
13505 }
13506
13507 #[test]
13508 fn test_isa_compliance_config_defaults() {
13509 let config = IsaComplianceConfig::default();
13510 assert!(!config.enabled);
13511 assert_eq!(config.compliance_level, "standard");
13512 assert!(config.generate_isa_mappings);
13513 assert!(config.generate_coverage_summary);
13514 assert!(!config.include_pcaob);
13515 assert_eq!(config.framework, "isa");
13516 }
13517
13518 #[test]
13519 fn test_sox_compliance_config_defaults() {
13520 let config = SoxComplianceConfig::default();
13521 assert!(!config.enabled);
13522 assert!(config.generate_302_certifications);
13523 assert!(config.generate_404_assessments);
13524 assert_eq!(config.materiality_threshold, 10000.0);
13525 assert_eq!(config.material_weakness_rate, 0.02);
13526 assert_eq!(config.significant_deficiency_rate, 0.08);
13527 }
13528
13529 #[test]
13530 fn test_pcaob_config_defaults() {
13531 let config = PcaobConfig::default();
13532 assert!(!config.enabled);
13533 assert!(!config.is_pcaob_audit);
13534 assert!(config.generate_cam);
13535 assert!(!config.include_icfr_opinion);
13536 assert!(!config.generate_standard_mappings);
13537 }
13538
13539 #[test]
13540 fn test_config_with_standards_enabled() {
13541 let yaml = r#"
13542 global:
13543 industry: financial_services
13544 start_date: "2024-01-01"
13545 period_months: 12
13546 companies:
13547 - code: "BANK"
13548 name: "Test Bank"
13549 currency: "USD"
13550 country: "US"
13551 annual_transaction_volume: hundred_k
13552 chart_of_accounts:
13553 complexity: large
13554 output:
13555 output_directory: "./output"
13556 accounting_standards:
13557 enabled: true
13558 framework: us_gaap
13559 revenue_recognition:
13560 enabled: true
13561 leases:
13562 enabled: true
13563 audit_standards:
13564 enabled: true
13565 isa_compliance:
13566 enabled: true
13567 sox:
13568 enabled: true
13569 "#;
13570
13571 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13572 assert!(config.accounting_standards.enabled);
13573 assert!(matches!(
13574 config.accounting_standards.framework,
13575 Some(AccountingFrameworkConfig::UsGaap)
13576 ));
13577 assert!(config.accounting_standards.revenue_recognition.enabled);
13578 assert!(config.accounting_standards.leases.enabled);
13579 assert!(config.audit_standards.enabled);
13580 assert!(config.audit_standards.isa_compliance.enabled);
13581 assert!(config.audit_standards.sox.enabled);
13582 }
13583
13584 #[test]
13589 fn test_industry_specific_config_defaults() {
13590 let config = IndustrySpecificConfig::default();
13591 assert!(!config.enabled);
13592 assert!(!config.manufacturing.enabled);
13593 assert!(!config.retail.enabled);
13594 assert!(!config.healthcare.enabled);
13595 assert!(!config.technology.enabled);
13596 assert!(!config.financial_services.enabled);
13597 assert!(!config.professional_services.enabled);
13598 }
13599
13600 #[test]
13601 fn test_manufacturing_config_defaults() {
13602 let config = ManufacturingConfig::default();
13603 assert!(!config.enabled);
13604 assert_eq!(config.bom_depth, 4);
13605 assert!(!config.just_in_time);
13606 assert_eq!(config.supplier_tiers, 2);
13607 assert_eq!(config.target_yield_rate, 0.97);
13608 assert_eq!(config.scrap_alert_threshold, 0.03);
13609 }
13610
13611 #[test]
13612 fn test_retail_config_defaults() {
13613 let config = RetailConfig::default();
13614 assert!(!config.enabled);
13615 assert_eq!(config.avg_daily_transactions, 500);
13616 assert!(config.loss_prevention);
13617 assert_eq!(config.shrinkage_rate, 0.015);
13618 }
13619
13620 #[test]
13621 fn test_healthcare_config_defaults() {
13622 let config = HealthcareConfig::default();
13623 assert!(!config.enabled);
13624 assert_eq!(config.facility_type, "hospital");
13625 assert_eq!(config.avg_daily_encounters, 150);
13626 assert!(config.compliance.hipaa);
13627 assert!(config.compliance.stark_law);
13628 assert!(config.coding_systems.icd10);
13629 assert!(config.coding_systems.cpt);
13630 }
13631
13632 #[test]
13633 fn test_technology_config_defaults() {
13634 let config = TechnologyConfig::default();
13635 assert!(!config.enabled);
13636 assert_eq!(config.revenue_model, "saas");
13637 assert_eq!(config.subscription_revenue_pct, 0.60);
13638 assert!(config.rd_capitalization.enabled);
13639 }
13640
13641 #[test]
13642 fn test_config_with_industry_specific() {
13643 let yaml = r#"
13644 global:
13645 industry: healthcare
13646 start_date: "2024-01-01"
13647 period_months: 12
13648 companies:
13649 - code: "HOSP"
13650 name: "Test Hospital"
13651 currency: "USD"
13652 country: "US"
13653 annual_transaction_volume: hundred_k
13654 chart_of_accounts:
13655 complexity: medium
13656 output:
13657 output_directory: "./output"
13658 industry_specific:
13659 enabled: true
13660 healthcare:
13661 enabled: true
13662 facility_type: hospital
13663 payer_mix:
13664 medicare: 0.45
13665 medicaid: 0.15
13666 commercial: 0.35
13667 self_pay: 0.05
13668 coding_systems:
13669 icd10: true
13670 cpt: true
13671 drg: true
13672 compliance:
13673 hipaa: true
13674 stark_law: true
13675 anomaly_rates:
13676 upcoding: 0.03
13677 unbundling: 0.02
13678 "#;
13679
13680 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13681 assert!(config.industry_specific.enabled);
13682 assert!(config.industry_specific.healthcare.enabled);
13683 assert_eq!(
13684 config.industry_specific.healthcare.facility_type,
13685 "hospital"
13686 );
13687 assert_eq!(config.industry_specific.healthcare.payer_mix.medicare, 0.45);
13688 assert_eq!(config.industry_specific.healthcare.payer_mix.self_pay, 0.05);
13689 assert!(config.industry_specific.healthcare.coding_systems.icd10);
13690 assert!(config.industry_specific.healthcare.compliance.hipaa);
13691 assert_eq!(
13692 config.industry_specific.healthcare.anomaly_rates.upcoding,
13693 0.03
13694 );
13695 }
13696
13697 #[test]
13698 fn test_config_with_manufacturing_specific() {
13699 let yaml = r#"
13700 global:
13701 industry: manufacturing
13702 start_date: "2024-01-01"
13703 period_months: 12
13704 companies:
13705 - code: "MFG"
13706 name: "Test Manufacturing"
13707 currency: "USD"
13708 country: "US"
13709 annual_transaction_volume: hundred_k
13710 chart_of_accounts:
13711 complexity: medium
13712 output:
13713 output_directory: "./output"
13714 industry_specific:
13715 enabled: true
13716 manufacturing:
13717 enabled: true
13718 bom_depth: 5
13719 just_in_time: true
13720 supplier_tiers: 3
13721 target_yield_rate: 0.98
13722 anomaly_rates:
13723 yield_manipulation: 0.02
13724 phantom_production: 0.01
13725 "#;
13726
13727 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13728 assert!(config.industry_specific.enabled);
13729 assert!(config.industry_specific.manufacturing.enabled);
13730 assert_eq!(config.industry_specific.manufacturing.bom_depth, 5);
13731 assert!(config.industry_specific.manufacturing.just_in_time);
13732 assert_eq!(config.industry_specific.manufacturing.supplier_tiers, 3);
13733 assert_eq!(
13734 config.industry_specific.manufacturing.target_yield_rate,
13735 0.98
13736 );
13737 assert_eq!(
13738 config
13739 .industry_specific
13740 .manufacturing
13741 .anomaly_rates
13742 .yield_manipulation,
13743 0.02
13744 );
13745 }
13746
13747 #[test]
13752 fn test_tax_config_defaults() {
13753 let tax = TaxConfig::default();
13754 assert!(!tax.enabled);
13755 assert!(tax.jurisdictions.countries.is_empty());
13756 assert!(!tax.jurisdictions.include_subnational);
13757 assert!(!tax.vat_gst.enabled);
13758 assert!(tax.vat_gst.standard_rates.is_empty());
13759 assert!(tax.vat_gst.reduced_rates.is_empty());
13760 assert!(tax.vat_gst.exempt_categories.is_empty());
13761 assert!(tax.vat_gst.reverse_charge);
13762 assert!(!tax.sales_tax.enabled);
13763 assert!(tax.sales_tax.nexus_states.is_empty());
13764 assert!(!tax.withholding.enabled);
13765 assert!(tax.withholding.treaty_network);
13766 assert_eq!(tax.withholding.default_rate, 0.30);
13767 assert_eq!(tax.withholding.treaty_reduced_rate, 0.15);
13768 assert!(tax.provisions.enabled);
13769 assert_eq!(tax.provisions.statutory_rate, 0.21);
13770 assert!(tax.provisions.uncertain_positions);
13771 assert!(!tax.payroll_tax.enabled);
13772 assert_eq!(tax.anomaly_rate, 0.03);
13773 }
13774
13775 #[test]
13776 fn test_tax_config_from_yaml() {
13777 let yaml = r#"
13778 global:
13779 seed: 42
13780 start_date: "2024-01-01"
13781 period_months: 12
13782 industry: retail
13783 companies:
13784 - code: C001
13785 name: Test Corp
13786 currency: USD
13787 country: US
13788 annual_transaction_volume: ten_k
13789 chart_of_accounts:
13790 complexity: small
13791 output:
13792 output_directory: ./output
13793 tax:
13794 enabled: true
13795 anomaly_rate: 0.05
13796 jurisdictions:
13797 countries: ["US", "DE", "GB"]
13798 include_subnational: true
13799 vat_gst:
13800 enabled: true
13801 standard_rates:
13802 DE: 0.19
13803 GB: 0.20
13804 reduced_rates:
13805 DE: 0.07
13806 GB: 0.05
13807 exempt_categories:
13808 - financial_services
13809 - healthcare
13810 reverse_charge: false
13811 sales_tax:
13812 enabled: true
13813 nexus_states: ["CA", "NY", "TX"]
13814 withholding:
13815 enabled: true
13816 treaty_network: false
13817 default_rate: 0.25
13818 treaty_reduced_rate: 0.10
13819 provisions:
13820 enabled: false
13821 statutory_rate: 0.28
13822 uncertain_positions: false
13823 payroll_tax:
13824 enabled: true
13825 "#;
13826
13827 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13828 assert!(config.tax.enabled);
13829 assert_eq!(config.tax.anomaly_rate, 0.05);
13830
13831 assert_eq!(config.tax.jurisdictions.countries.len(), 3);
13833 assert!(config
13834 .tax
13835 .jurisdictions
13836 .countries
13837 .contains(&"DE".to_string()));
13838 assert!(config.tax.jurisdictions.include_subnational);
13839
13840 assert!(config.tax.vat_gst.enabled);
13842 assert_eq!(config.tax.vat_gst.standard_rates.get("DE"), Some(&0.19));
13843 assert_eq!(config.tax.vat_gst.standard_rates.get("GB"), Some(&0.20));
13844 assert_eq!(config.tax.vat_gst.reduced_rates.get("DE"), Some(&0.07));
13845 assert_eq!(config.tax.vat_gst.exempt_categories.len(), 2);
13846 assert!(!config.tax.vat_gst.reverse_charge);
13847
13848 assert!(config.tax.sales_tax.enabled);
13850 assert_eq!(config.tax.sales_tax.nexus_states.len(), 3);
13851 assert!(config
13852 .tax
13853 .sales_tax
13854 .nexus_states
13855 .contains(&"CA".to_string()));
13856
13857 assert!(config.tax.withholding.enabled);
13859 assert!(!config.tax.withholding.treaty_network);
13860 assert_eq!(config.tax.withholding.default_rate, 0.25);
13861 assert_eq!(config.tax.withholding.treaty_reduced_rate, 0.10);
13862
13863 assert!(!config.tax.provisions.enabled);
13865 assert_eq!(config.tax.provisions.statutory_rate, 0.28);
13866 assert!(!config.tax.provisions.uncertain_positions);
13867
13868 assert!(config.tax.payroll_tax.enabled);
13870 }
13871
13872 #[test]
13873 fn test_generator_config_with_tax_default() {
13874 let yaml = r#"
13875 global:
13876 seed: 42
13877 start_date: "2024-01-01"
13878 period_months: 12
13879 industry: retail
13880 companies:
13881 - code: C001
13882 name: Test Corp
13883 currency: USD
13884 country: US
13885 annual_transaction_volume: ten_k
13886 chart_of_accounts:
13887 complexity: small
13888 output:
13889 output_directory: ./output
13890 "#;
13891
13892 let config: GeneratorConfig =
13893 serde_yaml::from_str(yaml).expect("Failed to parse config without tax section");
13894 assert!(!config.tax.enabled);
13896 assert!(config.tax.jurisdictions.countries.is_empty());
13897 assert_eq!(config.tax.anomaly_rate, 0.03);
13898 assert!(config.tax.provisions.enabled); assert_eq!(config.tax.provisions.statutory_rate, 0.21);
13900 }
13901
13902 #[test]
13907 fn test_session_config_default_disabled() {
13908 let yaml = "{}";
13909 let config: SessionSchemaConfig =
13910 serde_yaml::from_str(yaml).expect("Failed to parse empty session config");
13911 assert!(!config.enabled);
13912 assert!(config.checkpoint_path.is_none());
13913 assert!(config.per_period_output);
13914 assert!(config.consolidated_output);
13915 }
13916
13917 #[test]
13918 fn test_config_backward_compatible_without_session() {
13919 let yaml = r#"
13920 global:
13921 seed: 42
13922 start_date: "2024-01-01"
13923 period_months: 12
13924 industry: retail
13925 companies:
13926 - code: C001
13927 name: Test Corp
13928 currency: USD
13929 country: US
13930 annual_transaction_volume: ten_k
13931 chart_of_accounts:
13932 complexity: small
13933 output:
13934 output_directory: ./output
13935 "#;
13936
13937 let config: GeneratorConfig =
13938 serde_yaml::from_str(yaml).expect("Failed to parse config without session");
13939 assert!(!config.session.enabled);
13941 assert!(config.session.per_period_output);
13942 assert!(config.session.consolidated_output);
13943 assert!(config.global.fiscal_year_months.is_none());
13945 }
13946
13947 #[test]
13948 fn test_fiscal_year_months_parsed() {
13949 let yaml = r#"
13950 global:
13951 seed: 42
13952 start_date: "2024-01-01"
13953 period_months: 24
13954 industry: retail
13955 fiscal_year_months: 12
13956 companies:
13957 - code: C001
13958 name: Test Corp
13959 currency: USD
13960 country: US
13961 annual_transaction_volume: ten_k
13962 chart_of_accounts:
13963 complexity: small
13964 output:
13965 output_directory: ./output
13966 session:
13967 enabled: true
13968 checkpoint_path: /tmp/checkpoints
13969 per_period_output: true
13970 consolidated_output: false
13971 "#;
13972
13973 let config: GeneratorConfig =
13974 serde_yaml::from_str(yaml).expect("Failed to parse config with fiscal_year_months");
13975 assert_eq!(config.global.fiscal_year_months, Some(12));
13976 assert!(config.session.enabled);
13977 assert_eq!(
13978 config.session.checkpoint_path,
13979 Some("/tmp/checkpoints".to_string())
13980 );
13981 assert!(config.session.per_period_output);
13982 assert!(!config.session.consolidated_output);
13983 }
13984}