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}
184
185#[derive(Debug, Clone, Serialize, Deserialize)]
191pub struct LlmSchemaConfig {
192 #[serde(default)]
194 pub enabled: bool,
195 #[serde(default = "default_llm_provider")]
197 pub provider: String,
198 #[serde(default = "default_llm_model_name")]
200 pub model: String,
201 #[serde(default = "default_llm_batch_size")]
203 pub max_vendor_enrichments: usize,
204}
205
206fn default_llm_provider() -> String {
207 "mock".to_string()
208}
209
210fn default_llm_model_name() -> String {
211 "gpt-4o-mini".to_string()
212}
213
214fn default_llm_batch_size() -> usize {
215 50
216}
217
218impl Default for LlmSchemaConfig {
219 fn default() -> Self {
220 Self {
221 enabled: false,
222 provider: default_llm_provider(),
223 model: default_llm_model_name(),
224 max_vendor_enrichments: default_llm_batch_size(),
225 }
226 }
227}
228
229#[derive(Debug, Clone, Serialize, Deserialize)]
234pub struct DiffusionSchemaConfig {
235 #[serde(default)]
237 pub enabled: bool,
238 #[serde(default = "default_diffusion_steps")]
240 pub n_steps: usize,
241 #[serde(default = "default_diffusion_schedule")]
243 pub schedule: String,
244 #[serde(default = "default_diffusion_sample_size")]
246 pub sample_size: usize,
247}
248
249fn default_diffusion_steps() -> usize {
250 100
251}
252
253fn default_diffusion_schedule() -> String {
254 "linear".to_string()
255}
256
257fn default_diffusion_sample_size() -> usize {
258 100
259}
260
261impl Default for DiffusionSchemaConfig {
262 fn default() -> Self {
263 Self {
264 enabled: false,
265 n_steps: default_diffusion_steps(),
266 schedule: default_diffusion_schedule(),
267 sample_size: default_diffusion_sample_size(),
268 }
269 }
270}
271
272#[derive(Debug, Clone, Serialize, Deserialize)]
278pub struct CausalSchemaConfig {
279 #[serde(default)]
281 pub enabled: bool,
282 #[serde(default = "default_causal_template")]
284 pub template: String,
285 #[serde(default = "default_causal_sample_size")]
287 pub sample_size: usize,
288 #[serde(default = "default_true")]
290 pub validate: bool,
291}
292
293fn default_causal_template() -> String {
294 "fraud_detection".to_string()
295}
296
297fn default_causal_sample_size() -> usize {
298 500
299}
300
301impl Default for CausalSchemaConfig {
302 fn default() -> Self {
303 Self {
304 enabled: false,
305 template: default_causal_template(),
306 sample_size: default_causal_sample_size(),
307 validate: true,
308 }
309 }
310}
311
312#[derive(Debug, Clone, Serialize, Deserialize)]
319pub struct GraphExportConfig {
320 #[serde(default)]
322 pub enabled: bool,
323
324 #[serde(default = "default_graph_types")]
326 pub graph_types: Vec<GraphTypeConfig>,
327
328 #[serde(default = "default_graph_formats")]
330 pub formats: Vec<GraphExportFormat>,
331
332 #[serde(default = "default_train_ratio")]
334 pub train_ratio: f64,
335
336 #[serde(default = "default_val_ratio")]
338 pub validation_ratio: f64,
339
340 #[serde(default)]
342 pub split_seed: Option<u64>,
343
344 #[serde(default = "default_graph_subdir")]
346 pub output_subdirectory: String,
347
348 #[serde(default)]
350 pub hypergraph: HypergraphExportSettings,
351}
352
353fn default_graph_types() -> Vec<GraphTypeConfig> {
354 vec![GraphTypeConfig::default()]
355}
356
357fn default_graph_formats() -> Vec<GraphExportFormat> {
358 vec![GraphExportFormat::PytorchGeometric]
359}
360
361fn default_train_ratio() -> f64 {
362 0.7
363}
364
365fn default_val_ratio() -> f64 {
366 0.15
367}
368
369fn default_graph_subdir() -> String {
370 "graphs".to_string()
371}
372
373impl Default for GraphExportConfig {
374 fn default() -> Self {
375 Self {
376 enabled: false,
377 graph_types: default_graph_types(),
378 formats: default_graph_formats(),
379 train_ratio: 0.7,
380 validation_ratio: 0.15,
381 split_seed: None,
382 output_subdirectory: "graphs".to_string(),
383 hypergraph: HypergraphExportSettings::default(),
384 }
385 }
386}
387
388#[derive(Debug, Clone, Serialize, Deserialize)]
395pub struct HypergraphExportSettings {
396 #[serde(default)]
398 pub enabled: bool,
399
400 #[serde(default = "default_hypergraph_max_nodes")]
402 pub max_nodes: usize,
403
404 #[serde(default = "default_aggregation_strategy")]
406 pub aggregation_strategy: String,
407
408 #[serde(default)]
410 pub governance_layer: GovernanceLayerSettings,
411
412 #[serde(default)]
414 pub process_layer: ProcessLayerSettings,
415
416 #[serde(default)]
418 pub accounting_layer: AccountingLayerSettings,
419
420 #[serde(default)]
422 pub cross_layer: CrossLayerSettings,
423
424 #[serde(default = "default_hypergraph_subdir")]
426 pub output_subdirectory: String,
427
428 #[serde(default = "default_hypergraph_format")]
430 pub output_format: String,
431
432 #[serde(default)]
434 pub stream_target: Option<String>,
435
436 #[serde(default = "default_stream_batch_size")]
438 pub stream_batch_size: usize,
439}
440
441fn default_hypergraph_max_nodes() -> usize {
442 50_000
443}
444
445fn default_aggregation_strategy() -> String {
446 "pool_by_counterparty".to_string()
447}
448
449fn default_hypergraph_subdir() -> String {
450 "hypergraph".to_string()
451}
452
453fn default_hypergraph_format() -> String {
454 "native".to_string()
455}
456
457fn default_stream_batch_size() -> usize {
458 1000
459}
460
461impl Default for HypergraphExportSettings {
462 fn default() -> Self {
463 Self {
464 enabled: false,
465 max_nodes: 50_000,
466 aggregation_strategy: "pool_by_counterparty".to_string(),
467 governance_layer: GovernanceLayerSettings::default(),
468 process_layer: ProcessLayerSettings::default(),
469 accounting_layer: AccountingLayerSettings::default(),
470 cross_layer: CrossLayerSettings::default(),
471 output_subdirectory: "hypergraph".to_string(),
472 output_format: "native".to_string(),
473 stream_target: None,
474 stream_batch_size: 1000,
475 }
476 }
477}
478
479#[derive(Debug, Clone, Serialize, Deserialize)]
481pub struct GovernanceLayerSettings {
482 #[serde(default = "default_true")]
484 pub include_coso: bool,
485 #[serde(default = "default_true")]
487 pub include_controls: bool,
488 #[serde(default = "default_true")]
490 pub include_sox: bool,
491 #[serde(default = "default_true")]
493 pub include_vendors: bool,
494 #[serde(default = "default_true")]
496 pub include_customers: bool,
497 #[serde(default = "default_true")]
499 pub include_employees: bool,
500}
501
502impl Default for GovernanceLayerSettings {
503 fn default() -> Self {
504 Self {
505 include_coso: true,
506 include_controls: true,
507 include_sox: true,
508 include_vendors: true,
509 include_customers: true,
510 include_employees: true,
511 }
512 }
513}
514
515#[derive(Debug, Clone, Serialize, Deserialize)]
517pub struct ProcessLayerSettings {
518 #[serde(default = "default_true")]
520 pub include_p2p: bool,
521 #[serde(default = "default_true")]
523 pub include_o2c: bool,
524 #[serde(default = "default_true")]
526 pub include_s2c: bool,
527 #[serde(default = "default_true")]
529 pub include_h2r: bool,
530 #[serde(default = "default_true")]
532 pub include_mfg: bool,
533 #[serde(default = "default_true")]
535 pub include_bank: bool,
536 #[serde(default = "default_true")]
538 pub include_audit: bool,
539 #[serde(default = "default_true")]
541 pub include_r2r: bool,
542 #[serde(default = "default_true")]
544 pub events_as_hyperedges: bool,
545 #[serde(default = "default_docs_per_counterparty_threshold")]
547 pub docs_per_counterparty_threshold: usize,
548}
549
550fn default_docs_per_counterparty_threshold() -> usize {
551 20
552}
553
554impl Default for ProcessLayerSettings {
555 fn default() -> Self {
556 Self {
557 include_p2p: true,
558 include_o2c: true,
559 include_s2c: true,
560 include_h2r: true,
561 include_mfg: true,
562 include_bank: true,
563 include_audit: true,
564 include_r2r: true,
565 events_as_hyperedges: true,
566 docs_per_counterparty_threshold: 20,
567 }
568 }
569}
570
571#[derive(Debug, Clone, Serialize, Deserialize)]
573pub struct AccountingLayerSettings {
574 #[serde(default = "default_true")]
576 pub include_accounts: bool,
577 #[serde(default = "default_true")]
579 pub je_as_hyperedges: bool,
580}
581
582impl Default for AccountingLayerSettings {
583 fn default() -> Self {
584 Self {
585 include_accounts: true,
586 je_as_hyperedges: true,
587 }
588 }
589}
590
591#[derive(Debug, Clone, Serialize, Deserialize)]
593pub struct CrossLayerSettings {
594 #[serde(default = "default_true")]
596 pub enabled: bool,
597}
598
599impl Default for CrossLayerSettings {
600 fn default() -> Self {
601 Self { enabled: true }
602 }
603}
604
605#[derive(Debug, Clone, Serialize, Deserialize)]
607pub struct GraphTypeConfig {
608 #[serde(default = "default_graph_name")]
610 pub name: String,
611
612 #[serde(default)]
614 pub aggregate_edges: bool,
615
616 #[serde(default)]
618 pub min_edge_weight: f64,
619
620 #[serde(default)]
622 pub include_document_nodes: bool,
623}
624
625fn default_graph_name() -> String {
626 "accounting_network".to_string()
627}
628
629impl Default for GraphTypeConfig {
630 fn default() -> Self {
631 Self {
632 name: "accounting_network".to_string(),
633 aggregate_edges: false,
634 min_edge_weight: 0.0,
635 include_document_nodes: false,
636 }
637 }
638}
639
640#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
642#[serde(rename_all = "snake_case")]
643pub enum GraphExportFormat {
644 PytorchGeometric,
646 Neo4j,
648 Dgl,
650 RustGraph,
652 RustGraphHypergraph,
654}
655
656#[derive(Debug, Clone, Default, Serialize, Deserialize)]
660pub struct ScenarioConfig {
661 #[serde(default)]
664 pub tags: Vec<String>,
665
666 #[serde(default)]
671 pub profile: Option<String>,
672
673 #[serde(default)]
675 pub description: Option<String>,
676
677 #[serde(default)]
679 pub ml_training: bool,
680
681 #[serde(default)]
684 pub target_anomaly_ratio: Option<f64>,
685
686 #[serde(default)]
688 pub metadata: std::collections::HashMap<String, String>,
689}
690
691#[derive(Debug, Clone, Serialize, Deserialize)]
696pub struct TemporalDriftConfig {
697 #[serde(default)]
699 pub enabled: bool,
700
701 #[serde(default = "default_amount_drift")]
704 pub amount_mean_drift: f64,
705
706 #[serde(default)]
709 pub amount_variance_drift: f64,
710
711 #[serde(default)]
714 pub anomaly_rate_drift: f64,
715
716 #[serde(default = "default_concept_drift")]
719 pub concept_drift_rate: f64,
720
721 #[serde(default)]
723 pub sudden_drift_probability: f64,
724
725 #[serde(default = "default_sudden_drift_magnitude")]
727 pub sudden_drift_magnitude: f64,
728
729 #[serde(default)]
731 pub seasonal_drift: bool,
732
733 #[serde(default)]
735 pub drift_start_period: u32,
736
737 #[serde(default = "default_drift_type")]
739 pub drift_type: DriftType,
740}
741
742fn default_amount_drift() -> f64 {
743 0.02
744}
745
746fn default_concept_drift() -> f64 {
747 0.01
748}
749
750fn default_sudden_drift_magnitude() -> f64 {
751 2.0
752}
753
754fn default_drift_type() -> DriftType {
755 DriftType::Gradual
756}
757
758impl Default for TemporalDriftConfig {
759 fn default() -> Self {
760 Self {
761 enabled: false,
762 amount_mean_drift: 0.02,
763 amount_variance_drift: 0.0,
764 anomaly_rate_drift: 0.0,
765 concept_drift_rate: 0.01,
766 sudden_drift_probability: 0.0,
767 sudden_drift_magnitude: 2.0,
768 seasonal_drift: false,
769 drift_start_period: 0,
770 drift_type: DriftType::Gradual,
771 }
772 }
773}
774
775impl TemporalDriftConfig {
776 pub fn to_core_config(&self) -> datasynth_core::distributions::DriftConfig {
778 datasynth_core::distributions::DriftConfig {
779 enabled: self.enabled,
780 amount_mean_drift: self.amount_mean_drift,
781 amount_variance_drift: self.amount_variance_drift,
782 anomaly_rate_drift: self.anomaly_rate_drift,
783 concept_drift_rate: self.concept_drift_rate,
784 sudden_drift_probability: self.sudden_drift_probability,
785 sudden_drift_magnitude: self.sudden_drift_magnitude,
786 seasonal_drift: self.seasonal_drift,
787 drift_start_period: self.drift_start_period,
788 drift_type: match self.drift_type {
789 DriftType::Gradual => datasynth_core::distributions::DriftType::Gradual,
790 DriftType::Sudden => datasynth_core::distributions::DriftType::Sudden,
791 DriftType::Recurring => datasynth_core::distributions::DriftType::Recurring,
792 DriftType::Mixed => datasynth_core::distributions::DriftType::Mixed,
793 },
794 regime_changes: Vec::new(),
795 economic_cycle: Default::default(),
796 parameter_drifts: Vec::new(),
797 }
798 }
799}
800
801#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
803#[serde(rename_all = "snake_case")]
804pub enum DriftType {
805 #[default]
807 Gradual,
808 Sudden,
810 Recurring,
812 Mixed,
814}
815
816#[derive(Debug, Clone, Serialize, Deserialize)]
822pub struct StreamingSchemaConfig {
823 #[serde(default)]
825 pub enabled: bool,
826 #[serde(default = "default_buffer_size")]
828 pub buffer_size: usize,
829 #[serde(default = "default_true")]
831 pub enable_progress: bool,
832 #[serde(default = "default_progress_interval")]
834 pub progress_interval: u64,
835 #[serde(default)]
837 pub backpressure: BackpressureSchemaStrategy,
838}
839
840fn default_buffer_size() -> usize {
841 1000
842}
843
844fn default_progress_interval() -> u64 {
845 100
846}
847
848impl Default for StreamingSchemaConfig {
849 fn default() -> Self {
850 Self {
851 enabled: false,
852 buffer_size: 1000,
853 enable_progress: true,
854 progress_interval: 100,
855 backpressure: BackpressureSchemaStrategy::Block,
856 }
857 }
858}
859
860#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
862#[serde(rename_all = "snake_case")]
863pub enum BackpressureSchemaStrategy {
864 #[default]
866 Block,
867 DropOldest,
869 DropNewest,
871 Buffer,
873}
874
875#[derive(Debug, Clone, Serialize, Deserialize)]
881pub struct RateLimitSchemaConfig {
882 #[serde(default)]
884 pub enabled: bool,
885 #[serde(default = "default_entities_per_second")]
887 pub entities_per_second: f64,
888 #[serde(default = "default_burst_size")]
890 pub burst_size: u32,
891 #[serde(default)]
893 pub backpressure: RateLimitBackpressureSchema,
894}
895
896fn default_entities_per_second() -> f64 {
897 1000.0
898}
899
900fn default_burst_size() -> u32 {
901 100
902}
903
904impl Default for RateLimitSchemaConfig {
905 fn default() -> Self {
906 Self {
907 enabled: false,
908 entities_per_second: 1000.0,
909 burst_size: 100,
910 backpressure: RateLimitBackpressureSchema::Block,
911 }
912 }
913}
914
915#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
917#[serde(rename_all = "snake_case")]
918pub enum RateLimitBackpressureSchema {
919 #[default]
921 Block,
922 Drop,
924 Buffer,
926}
927
928#[derive(Debug, Clone, Serialize, Deserialize)]
934pub struct TemporalAttributeSchemaConfig {
935 #[serde(default)]
937 pub enabled: bool,
938 #[serde(default)]
940 pub valid_time: ValidTimeSchemaConfig,
941 #[serde(default)]
943 pub transaction_time: TransactionTimeSchemaConfig,
944 #[serde(default)]
946 pub generate_version_chains: bool,
947 #[serde(default = "default_avg_versions")]
949 pub avg_versions_per_entity: f64,
950}
951
952fn default_avg_versions() -> f64 {
953 1.5
954}
955
956impl Default for TemporalAttributeSchemaConfig {
957 fn default() -> Self {
958 Self {
959 enabled: false,
960 valid_time: ValidTimeSchemaConfig::default(),
961 transaction_time: TransactionTimeSchemaConfig::default(),
962 generate_version_chains: false,
963 avg_versions_per_entity: 1.5,
964 }
965 }
966}
967
968#[derive(Debug, Clone, Serialize, Deserialize)]
970pub struct ValidTimeSchemaConfig {
971 #[serde(default = "default_closed_probability")]
973 pub closed_probability: f64,
974 #[serde(default = "default_avg_validity_days")]
976 pub avg_validity_days: u32,
977 #[serde(default = "default_validity_stddev")]
979 pub validity_stddev_days: u32,
980}
981
982fn default_closed_probability() -> f64 {
983 0.1
984}
985
986fn default_avg_validity_days() -> u32 {
987 365
988}
989
990fn default_validity_stddev() -> u32 {
991 90
992}
993
994impl Default for ValidTimeSchemaConfig {
995 fn default() -> Self {
996 Self {
997 closed_probability: 0.1,
998 avg_validity_days: 365,
999 validity_stddev_days: 90,
1000 }
1001 }
1002}
1003
1004#[derive(Debug, Clone, Serialize, Deserialize)]
1006pub struct TransactionTimeSchemaConfig {
1007 #[serde(default)]
1009 pub avg_recording_delay_seconds: u32,
1010 #[serde(default)]
1012 pub allow_backdating: bool,
1013 #[serde(default = "default_backdating_probability")]
1015 pub backdating_probability: f64,
1016 #[serde(default = "default_max_backdate_days")]
1018 pub max_backdate_days: u32,
1019}
1020
1021fn default_backdating_probability() -> f64 {
1022 0.01
1023}
1024
1025fn default_max_backdate_days() -> u32 {
1026 30
1027}
1028
1029impl Default for TransactionTimeSchemaConfig {
1030 fn default() -> Self {
1031 Self {
1032 avg_recording_delay_seconds: 0,
1033 allow_backdating: false,
1034 backdating_probability: 0.01,
1035 max_backdate_days: 30,
1036 }
1037 }
1038}
1039
1040#[derive(Debug, Clone, Serialize, Deserialize)]
1046pub struct RelationshipSchemaConfig {
1047 #[serde(default)]
1049 pub relationship_types: Vec<RelationshipTypeSchemaConfig>,
1050 #[serde(default = "default_true")]
1052 pub allow_orphans: bool,
1053 #[serde(default = "default_orphan_probability")]
1055 pub orphan_probability: f64,
1056 #[serde(default)]
1058 pub allow_circular: bool,
1059 #[serde(default = "default_max_circular_depth")]
1061 pub max_circular_depth: u32,
1062}
1063
1064fn default_orphan_probability() -> f64 {
1065 0.01
1066}
1067
1068fn default_max_circular_depth() -> u32 {
1069 3
1070}
1071
1072impl Default for RelationshipSchemaConfig {
1073 fn default() -> Self {
1074 Self {
1075 relationship_types: Vec::new(),
1076 allow_orphans: true,
1077 orphan_probability: 0.01,
1078 allow_circular: false,
1079 max_circular_depth: 3,
1080 }
1081 }
1082}
1083
1084#[derive(Debug, Clone, Serialize, Deserialize)]
1086pub struct RelationshipTypeSchemaConfig {
1087 pub name: String,
1089 pub source_type: String,
1091 pub target_type: String,
1093 #[serde(default)]
1095 pub cardinality: CardinalitySchemaRule,
1096 #[serde(default = "default_relationship_weight")]
1098 pub weight: f64,
1099 #[serde(default)]
1101 pub required: bool,
1102 #[serde(default = "default_true")]
1104 pub directed: bool,
1105}
1106
1107fn default_relationship_weight() -> f64 {
1108 1.0
1109}
1110
1111impl Default for RelationshipTypeSchemaConfig {
1112 fn default() -> Self {
1113 Self {
1114 name: String::new(),
1115 source_type: String::new(),
1116 target_type: String::new(),
1117 cardinality: CardinalitySchemaRule::default(),
1118 weight: 1.0,
1119 required: false,
1120 directed: true,
1121 }
1122 }
1123}
1124
1125#[derive(Debug, Clone, Serialize, Deserialize)]
1127#[serde(rename_all = "snake_case")]
1128pub enum CardinalitySchemaRule {
1129 OneToOne,
1131 OneToMany {
1133 min: u32,
1135 max: u32,
1137 },
1138 ManyToOne {
1140 min: u32,
1142 max: u32,
1144 },
1145 ManyToMany {
1147 min_per_source: u32,
1149 max_per_source: u32,
1151 },
1152}
1153
1154impl Default for CardinalitySchemaRule {
1155 fn default() -> Self {
1156 Self::OneToMany { min: 1, max: 5 }
1157 }
1158}
1159
1160#[derive(Debug, Clone, Serialize, Deserialize)]
1162pub struct GlobalConfig {
1163 pub seed: Option<u64>,
1165 pub industry: IndustrySector,
1167 pub start_date: String,
1169 pub period_months: u32,
1171 #[serde(default = "default_currency")]
1173 pub group_currency: String,
1174 #[serde(default = "default_true")]
1176 pub parallel: bool,
1177 #[serde(default)]
1179 pub worker_threads: usize,
1180 #[serde(default)]
1182 pub memory_limit_mb: usize,
1183}
1184
1185fn default_currency() -> String {
1186 "USD".to_string()
1187}
1188fn default_true() -> bool {
1189 true
1190}
1191
1192#[derive(Debug, Clone, Serialize, Deserialize)]
1194pub struct CompanyConfig {
1195 pub code: String,
1197 pub name: String,
1199 pub currency: String,
1201 pub country: String,
1203 #[serde(default = "default_fiscal_variant")]
1205 pub fiscal_year_variant: String,
1206 pub annual_transaction_volume: TransactionVolume,
1208 #[serde(default = "default_weight")]
1210 pub volume_weight: f64,
1211}
1212
1213fn default_fiscal_variant() -> String {
1214 "K4".to_string()
1215}
1216fn default_weight() -> f64 {
1217 1.0
1218}
1219
1220#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1222#[serde(rename_all = "snake_case")]
1223pub enum TransactionVolume {
1224 TenK,
1226 HundredK,
1228 OneM,
1230 TenM,
1232 HundredM,
1234 Custom(u64),
1236}
1237
1238impl TransactionVolume {
1239 pub fn count(&self) -> u64 {
1241 match self {
1242 Self::TenK => 10_000,
1243 Self::HundredK => 100_000,
1244 Self::OneM => 1_000_000,
1245 Self::TenM => 10_000_000,
1246 Self::HundredM => 100_000_000,
1247 Self::Custom(n) => *n,
1248 }
1249 }
1250}
1251
1252#[derive(Debug, Clone, Serialize, Deserialize)]
1254pub struct ChartOfAccountsConfig {
1255 pub complexity: CoAComplexity,
1257 #[serde(default = "default_true")]
1259 pub industry_specific: bool,
1260 pub custom_accounts: Option<PathBuf>,
1262 #[serde(default = "default_min_depth")]
1264 pub min_hierarchy_depth: u8,
1265 #[serde(default = "default_max_depth")]
1267 pub max_hierarchy_depth: u8,
1268}
1269
1270fn default_min_depth() -> u8 {
1271 2
1272}
1273fn default_max_depth() -> u8 {
1274 5
1275}
1276
1277impl Default for ChartOfAccountsConfig {
1278 fn default() -> Self {
1279 Self {
1280 complexity: CoAComplexity::Small,
1281 industry_specific: true,
1282 custom_accounts: None,
1283 min_hierarchy_depth: default_min_depth(),
1284 max_hierarchy_depth: default_max_depth(),
1285 }
1286 }
1287}
1288
1289#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1291pub struct TransactionConfig {
1292 #[serde(default)]
1294 pub line_item_distribution: LineItemDistributionConfig,
1295 #[serde(default)]
1297 pub debit_credit_distribution: DebitCreditDistributionConfig,
1298 #[serde(default)]
1300 pub even_odd_distribution: EvenOddDistributionConfig,
1301 #[serde(default)]
1303 pub source_distribution: SourceDistribution,
1304 #[serde(default)]
1306 pub seasonality: SeasonalityConfig,
1307 #[serde(default)]
1309 pub amounts: AmountDistributionConfig,
1310 #[serde(default)]
1312 pub benford: BenfordConfig,
1313}
1314
1315#[derive(Debug, Clone, Serialize, Deserialize)]
1317pub struct BenfordConfig {
1318 #[serde(default = "default_true")]
1320 pub enabled: bool,
1321 #[serde(default = "default_benford_tolerance")]
1323 pub tolerance: f64,
1324 #[serde(default)]
1326 pub exempt_sources: Vec<BenfordExemption>,
1327}
1328
1329fn default_benford_tolerance() -> f64 {
1330 0.05
1331}
1332
1333impl Default for BenfordConfig {
1334 fn default() -> Self {
1335 Self {
1336 enabled: true,
1337 tolerance: default_benford_tolerance(),
1338 exempt_sources: vec![BenfordExemption::Recurring, BenfordExemption::Payroll],
1339 }
1340 }
1341}
1342
1343#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1345#[serde(rename_all = "snake_case")]
1346pub enum BenfordExemption {
1347 Recurring,
1349 Payroll,
1351 FixedFees,
1353 RoundAmounts,
1355}
1356
1357#[derive(Debug, Clone, Serialize, Deserialize)]
1359pub struct SourceDistribution {
1360 pub manual: f64,
1362 pub automated: f64,
1364 pub recurring: f64,
1366 pub adjustment: f64,
1368}
1369
1370impl Default for SourceDistribution {
1371 fn default() -> Self {
1372 Self {
1373 manual: 0.20,
1374 automated: 0.70,
1375 recurring: 0.07,
1376 adjustment: 0.03,
1377 }
1378 }
1379}
1380
1381#[derive(Debug, Clone, Serialize, Deserialize)]
1383pub struct OutputConfig {
1384 #[serde(default)]
1386 pub mode: OutputMode,
1387 pub output_directory: PathBuf,
1389 #[serde(default = "default_formats")]
1391 pub formats: Vec<FileFormat>,
1392 #[serde(default)]
1394 pub compression: CompressionConfig,
1395 #[serde(default = "default_batch_size")]
1397 pub batch_size: usize,
1398 #[serde(default = "default_true")]
1400 pub include_acdoca: bool,
1401 #[serde(default)]
1403 pub include_bseg: bool,
1404 #[serde(default = "default_true")]
1406 pub partition_by_period: bool,
1407 #[serde(default)]
1409 pub partition_by_company: bool,
1410}
1411
1412fn default_formats() -> Vec<FileFormat> {
1413 vec![FileFormat::Parquet]
1414}
1415fn default_batch_size() -> usize {
1416 100_000
1417}
1418
1419impl Default for OutputConfig {
1420 fn default() -> Self {
1421 Self {
1422 mode: OutputMode::FlatFile,
1423 output_directory: PathBuf::from("./output"),
1424 formats: default_formats(),
1425 compression: CompressionConfig::default(),
1426 batch_size: default_batch_size(),
1427 include_acdoca: true,
1428 include_bseg: false,
1429 partition_by_period: true,
1430 partition_by_company: false,
1431 }
1432 }
1433}
1434
1435#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
1437#[serde(rename_all = "snake_case")]
1438pub enum OutputMode {
1439 Streaming,
1441 #[default]
1443 FlatFile,
1444 Both,
1446}
1447
1448#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1450#[serde(rename_all = "snake_case")]
1451pub enum FileFormat {
1452 Csv,
1453 Parquet,
1454 Json,
1455 JsonLines,
1456}
1457
1458#[derive(Debug, Clone, Serialize, Deserialize)]
1460pub struct CompressionConfig {
1461 #[serde(default = "default_true")]
1463 pub enabled: bool,
1464 #[serde(default)]
1466 pub algorithm: CompressionAlgorithm,
1467 #[serde(default = "default_compression_level")]
1469 pub level: u8,
1470}
1471
1472fn default_compression_level() -> u8 {
1473 3
1474}
1475
1476impl Default for CompressionConfig {
1477 fn default() -> Self {
1478 Self {
1479 enabled: true,
1480 algorithm: CompressionAlgorithm::default(),
1481 level: default_compression_level(),
1482 }
1483 }
1484}
1485
1486#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
1488#[serde(rename_all = "snake_case")]
1489pub enum CompressionAlgorithm {
1490 Gzip,
1491 #[default]
1492 Zstd,
1493 Lz4,
1494 Snappy,
1495}
1496
1497#[derive(Debug, Clone, Serialize, Deserialize)]
1499pub struct FraudConfig {
1500 #[serde(default)]
1502 pub enabled: bool,
1503 #[serde(default = "default_fraud_rate")]
1505 pub fraud_rate: f64,
1506 #[serde(default)]
1508 pub fraud_type_distribution: FraudTypeDistribution,
1509 #[serde(default)]
1511 pub clustering_enabled: bool,
1512 #[serde(default = "default_clustering_factor")]
1514 pub clustering_factor: f64,
1515 #[serde(default = "default_approval_thresholds")]
1517 pub approval_thresholds: Vec<f64>,
1518}
1519
1520fn default_approval_thresholds() -> Vec<f64> {
1521 vec![1000.0, 5000.0, 10000.0, 25000.0, 50000.0, 100000.0]
1522}
1523
1524fn default_fraud_rate() -> f64 {
1525 0.005
1526}
1527fn default_clustering_factor() -> f64 {
1528 3.0
1529}
1530
1531impl Default for FraudConfig {
1532 fn default() -> Self {
1533 Self {
1534 enabled: false,
1535 fraud_rate: default_fraud_rate(),
1536 fraud_type_distribution: FraudTypeDistribution::default(),
1537 clustering_enabled: false,
1538 clustering_factor: default_clustering_factor(),
1539 approval_thresholds: default_approval_thresholds(),
1540 }
1541 }
1542}
1543
1544#[derive(Debug, Clone, Serialize, Deserialize)]
1546pub struct FraudTypeDistribution {
1547 pub suspense_account_abuse: f64,
1548 pub fictitious_transaction: f64,
1549 pub revenue_manipulation: f64,
1550 pub expense_capitalization: f64,
1551 pub split_transaction: f64,
1552 pub timing_anomaly: f64,
1553 pub unauthorized_access: f64,
1554 pub duplicate_payment: f64,
1555}
1556
1557impl Default for FraudTypeDistribution {
1558 fn default() -> Self {
1559 Self {
1560 suspense_account_abuse: 0.25,
1561 fictitious_transaction: 0.15,
1562 revenue_manipulation: 0.10,
1563 expense_capitalization: 0.10,
1564 split_transaction: 0.15,
1565 timing_anomaly: 0.10,
1566 unauthorized_access: 0.10,
1567 duplicate_payment: 0.05,
1568 }
1569 }
1570}
1571
1572#[derive(Debug, Clone, Serialize, Deserialize)]
1574pub struct InternalControlsConfig {
1575 #[serde(default)]
1577 pub enabled: bool,
1578 #[serde(default = "default_exception_rate")]
1580 pub exception_rate: f64,
1581 #[serde(default = "default_sod_violation_rate")]
1583 pub sod_violation_rate: f64,
1584 #[serde(default = "default_true")]
1586 pub export_control_master_data: bool,
1587 #[serde(default = "default_sox_materiality_threshold")]
1589 pub sox_materiality_threshold: f64,
1590 #[serde(default = "default_true")]
1592 pub coso_enabled: bool,
1593 #[serde(default)]
1595 pub include_entity_level_controls: bool,
1596 #[serde(default = "default_target_maturity_level")]
1599 pub target_maturity_level: String,
1600}
1601
1602fn default_exception_rate() -> f64 {
1603 0.02
1604}
1605
1606fn default_sod_violation_rate() -> f64 {
1607 0.01
1608}
1609
1610fn default_sox_materiality_threshold() -> f64 {
1611 10000.0
1612}
1613
1614fn default_target_maturity_level() -> String {
1615 "mixed".to_string()
1616}
1617
1618impl Default for InternalControlsConfig {
1619 fn default() -> Self {
1620 Self {
1621 enabled: false,
1622 exception_rate: default_exception_rate(),
1623 sod_violation_rate: default_sod_violation_rate(),
1624 export_control_master_data: true,
1625 sox_materiality_threshold: default_sox_materiality_threshold(),
1626 coso_enabled: true,
1627 include_entity_level_controls: false,
1628 target_maturity_level: default_target_maturity_level(),
1629 }
1630 }
1631}
1632
1633#[derive(Debug, Clone, Serialize, Deserialize)]
1635pub struct BusinessProcessConfig {
1636 #[serde(default = "default_o2c")]
1638 pub o2c_weight: f64,
1639 #[serde(default = "default_p2p")]
1641 pub p2p_weight: f64,
1642 #[serde(default = "default_r2r")]
1644 pub r2r_weight: f64,
1645 #[serde(default = "default_h2r")]
1647 pub h2r_weight: f64,
1648 #[serde(default = "default_a2r")]
1650 pub a2r_weight: f64,
1651}
1652
1653fn default_o2c() -> f64 {
1654 0.35
1655}
1656fn default_p2p() -> f64 {
1657 0.30
1658}
1659fn default_r2r() -> f64 {
1660 0.20
1661}
1662fn default_h2r() -> f64 {
1663 0.10
1664}
1665fn default_a2r() -> f64 {
1666 0.05
1667}
1668
1669impl Default for BusinessProcessConfig {
1670 fn default() -> Self {
1671 Self {
1672 o2c_weight: default_o2c(),
1673 p2p_weight: default_p2p(),
1674 r2r_weight: default_r2r(),
1675 h2r_weight: default_h2r(),
1676 a2r_weight: default_a2r(),
1677 }
1678 }
1679}
1680
1681#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1683pub struct UserPersonaConfig {
1684 #[serde(default)]
1686 pub persona_distribution: PersonaDistribution,
1687 #[serde(default)]
1689 pub users_per_persona: UsersPerPersona,
1690}
1691
1692#[derive(Debug, Clone, Serialize, Deserialize)]
1694pub struct PersonaDistribution {
1695 pub junior_accountant: f64,
1696 pub senior_accountant: f64,
1697 pub controller: f64,
1698 pub manager: f64,
1699 pub automated_system: f64,
1700}
1701
1702impl Default for PersonaDistribution {
1703 fn default() -> Self {
1704 Self {
1705 junior_accountant: 0.15,
1706 senior_accountant: 0.15,
1707 controller: 0.05,
1708 manager: 0.05,
1709 automated_system: 0.60,
1710 }
1711 }
1712}
1713
1714#[derive(Debug, Clone, Serialize, Deserialize)]
1716pub struct UsersPerPersona {
1717 pub junior_accountant: usize,
1718 pub senior_accountant: usize,
1719 pub controller: usize,
1720 pub manager: usize,
1721 pub automated_system: usize,
1722}
1723
1724impl Default for UsersPerPersona {
1725 fn default() -> Self {
1726 Self {
1727 junior_accountant: 10,
1728 senior_accountant: 5,
1729 controller: 2,
1730 manager: 3,
1731 automated_system: 20,
1732 }
1733 }
1734}
1735
1736#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1738pub struct TemplateConfig {
1739 #[serde(default)]
1741 pub names: NameTemplateConfig,
1742 #[serde(default)]
1744 pub descriptions: DescriptionTemplateConfig,
1745 #[serde(default)]
1747 pub references: ReferenceTemplateConfig,
1748}
1749
1750#[derive(Debug, Clone, Serialize, Deserialize)]
1752pub struct NameTemplateConfig {
1753 #[serde(default)]
1755 pub culture_distribution: CultureDistribution,
1756 #[serde(default = "default_email_domain")]
1758 pub email_domain: String,
1759 #[serde(default = "default_true")]
1761 pub generate_realistic_names: bool,
1762}
1763
1764fn default_email_domain() -> String {
1765 "company.com".to_string()
1766}
1767
1768impl Default for NameTemplateConfig {
1769 fn default() -> Self {
1770 Self {
1771 culture_distribution: CultureDistribution::default(),
1772 email_domain: default_email_domain(),
1773 generate_realistic_names: true,
1774 }
1775 }
1776}
1777
1778#[derive(Debug, Clone, Serialize, Deserialize)]
1780pub struct CultureDistribution {
1781 pub western_us: f64,
1782 pub hispanic: f64,
1783 pub german: f64,
1784 pub french: f64,
1785 pub chinese: f64,
1786 pub japanese: f64,
1787 pub indian: f64,
1788}
1789
1790impl Default for CultureDistribution {
1791 fn default() -> Self {
1792 Self {
1793 western_us: 0.40,
1794 hispanic: 0.20,
1795 german: 0.10,
1796 french: 0.05,
1797 chinese: 0.10,
1798 japanese: 0.05,
1799 indian: 0.10,
1800 }
1801 }
1802}
1803
1804#[derive(Debug, Clone, Serialize, Deserialize)]
1806pub struct DescriptionTemplateConfig {
1807 #[serde(default = "default_true")]
1809 pub generate_header_text: bool,
1810 #[serde(default = "default_true")]
1812 pub generate_line_text: bool,
1813}
1814
1815impl Default for DescriptionTemplateConfig {
1816 fn default() -> Self {
1817 Self {
1818 generate_header_text: true,
1819 generate_line_text: true,
1820 }
1821 }
1822}
1823
1824#[derive(Debug, Clone, Serialize, Deserialize)]
1826pub struct ReferenceTemplateConfig {
1827 #[serde(default = "default_true")]
1829 pub generate_references: bool,
1830 #[serde(default = "default_invoice_prefix")]
1832 pub invoice_prefix: String,
1833 #[serde(default = "default_po_prefix")]
1835 pub po_prefix: String,
1836 #[serde(default = "default_so_prefix")]
1838 pub so_prefix: String,
1839}
1840
1841fn default_invoice_prefix() -> String {
1842 "INV".to_string()
1843}
1844fn default_po_prefix() -> String {
1845 "PO".to_string()
1846}
1847fn default_so_prefix() -> String {
1848 "SO".to_string()
1849}
1850
1851impl Default for ReferenceTemplateConfig {
1852 fn default() -> Self {
1853 Self {
1854 generate_references: true,
1855 invoice_prefix: default_invoice_prefix(),
1856 po_prefix: default_po_prefix(),
1857 so_prefix: default_so_prefix(),
1858 }
1859 }
1860}
1861
1862#[derive(Debug, Clone, Serialize, Deserialize)]
1864pub struct ApprovalConfig {
1865 #[serde(default)]
1867 pub enabled: bool,
1868 #[serde(default = "default_auto_approve_threshold")]
1870 pub auto_approve_threshold: f64,
1871 #[serde(default = "default_rejection_rate")]
1873 pub rejection_rate: f64,
1874 #[serde(default = "default_revision_rate")]
1876 pub revision_rate: f64,
1877 #[serde(default = "default_approval_delay_hours")]
1879 pub average_approval_delay_hours: f64,
1880 #[serde(default)]
1882 pub thresholds: Vec<ApprovalThresholdConfig>,
1883}
1884
1885fn default_auto_approve_threshold() -> f64 {
1886 1000.0
1887}
1888fn default_rejection_rate() -> f64 {
1889 0.02
1890}
1891fn default_revision_rate() -> f64 {
1892 0.05
1893}
1894fn default_approval_delay_hours() -> f64 {
1895 4.0
1896}
1897
1898impl Default for ApprovalConfig {
1899 fn default() -> Self {
1900 Self {
1901 enabled: false,
1902 auto_approve_threshold: default_auto_approve_threshold(),
1903 rejection_rate: default_rejection_rate(),
1904 revision_rate: default_revision_rate(),
1905 average_approval_delay_hours: default_approval_delay_hours(),
1906 thresholds: vec![
1907 ApprovalThresholdConfig {
1908 amount: 1000.0,
1909 level: 1,
1910 roles: vec!["senior_accountant".to_string()],
1911 },
1912 ApprovalThresholdConfig {
1913 amount: 10000.0,
1914 level: 2,
1915 roles: vec!["senior_accountant".to_string(), "controller".to_string()],
1916 },
1917 ApprovalThresholdConfig {
1918 amount: 100000.0,
1919 level: 3,
1920 roles: vec![
1921 "senior_accountant".to_string(),
1922 "controller".to_string(),
1923 "manager".to_string(),
1924 ],
1925 },
1926 ApprovalThresholdConfig {
1927 amount: 500000.0,
1928 level: 4,
1929 roles: vec![
1930 "senior_accountant".to_string(),
1931 "controller".to_string(),
1932 "manager".to_string(),
1933 "executive".to_string(),
1934 ],
1935 },
1936 ],
1937 }
1938 }
1939}
1940
1941#[derive(Debug, Clone, Serialize, Deserialize)]
1943pub struct ApprovalThresholdConfig {
1944 pub amount: f64,
1946 pub level: u8,
1948 pub roles: Vec<String>,
1950}
1951
1952#[derive(Debug, Clone, Serialize, Deserialize)]
1954pub struct DepartmentConfig {
1955 #[serde(default)]
1957 pub enabled: bool,
1958 #[serde(default = "default_headcount_multiplier")]
1960 pub headcount_multiplier: f64,
1961 #[serde(default)]
1963 pub custom_departments: Vec<CustomDepartmentConfig>,
1964}
1965
1966fn default_headcount_multiplier() -> f64 {
1967 1.0
1968}
1969
1970impl Default for DepartmentConfig {
1971 fn default() -> Self {
1972 Self {
1973 enabled: false,
1974 headcount_multiplier: default_headcount_multiplier(),
1975 custom_departments: Vec::new(),
1976 }
1977 }
1978}
1979
1980#[derive(Debug, Clone, Serialize, Deserialize)]
1982pub struct CustomDepartmentConfig {
1983 pub code: String,
1985 pub name: String,
1987 #[serde(default)]
1989 pub cost_center: Option<String>,
1990 #[serde(default)]
1992 pub primary_processes: Vec<String>,
1993 #[serde(default)]
1995 pub parent_code: Option<String>,
1996}
1997
1998#[derive(Debug, Clone, Default, Serialize, Deserialize)]
2004pub struct MasterDataConfig {
2005 #[serde(default)]
2007 pub vendors: VendorMasterConfig,
2008 #[serde(default)]
2010 pub customers: CustomerMasterConfig,
2011 #[serde(default)]
2013 pub materials: MaterialMasterConfig,
2014 #[serde(default)]
2016 pub fixed_assets: FixedAssetMasterConfig,
2017 #[serde(default)]
2019 pub employees: EmployeeMasterConfig,
2020 #[serde(default)]
2022 pub cost_centers: CostCenterMasterConfig,
2023}
2024
2025#[derive(Debug, Clone, Serialize, Deserialize)]
2027pub struct VendorMasterConfig {
2028 #[serde(default = "default_vendor_count")]
2030 pub count: usize,
2031 #[serde(default = "default_intercompany_percent")]
2033 pub intercompany_percent: f64,
2034 #[serde(default)]
2036 pub payment_terms_distribution: PaymentTermsDistribution,
2037 #[serde(default)]
2039 pub behavior_distribution: VendorBehaviorDistribution,
2040 #[serde(default = "default_true")]
2042 pub generate_bank_accounts: bool,
2043 #[serde(default = "default_true")]
2045 pub generate_tax_ids: bool,
2046}
2047
2048fn default_vendor_count() -> usize {
2049 500
2050}
2051
2052fn default_intercompany_percent() -> f64 {
2053 0.05
2054}
2055
2056impl Default for VendorMasterConfig {
2057 fn default() -> Self {
2058 Self {
2059 count: default_vendor_count(),
2060 intercompany_percent: default_intercompany_percent(),
2061 payment_terms_distribution: PaymentTermsDistribution::default(),
2062 behavior_distribution: VendorBehaviorDistribution::default(),
2063 generate_bank_accounts: true,
2064 generate_tax_ids: true,
2065 }
2066 }
2067}
2068
2069#[derive(Debug, Clone, Serialize, Deserialize)]
2071pub struct PaymentTermsDistribution {
2072 pub net_30: f64,
2074 pub net_60: f64,
2076 pub net_90: f64,
2078 pub two_ten_net_30: f64,
2080 pub due_on_receipt: f64,
2082 pub end_of_month: f64,
2084}
2085
2086impl Default for PaymentTermsDistribution {
2087 fn default() -> Self {
2088 Self {
2089 net_30: 0.40,
2090 net_60: 0.20,
2091 net_90: 0.10,
2092 two_ten_net_30: 0.15,
2093 due_on_receipt: 0.05,
2094 end_of_month: 0.10,
2095 }
2096 }
2097}
2098
2099#[derive(Debug, Clone, Serialize, Deserialize)]
2101pub struct VendorBehaviorDistribution {
2102 pub reliable: f64,
2104 pub sometimes_late: f64,
2106 pub inconsistent_quality: f64,
2108 pub premium: f64,
2110 pub budget: f64,
2112}
2113
2114impl Default for VendorBehaviorDistribution {
2115 fn default() -> Self {
2116 Self {
2117 reliable: 0.50,
2118 sometimes_late: 0.20,
2119 inconsistent_quality: 0.10,
2120 premium: 0.10,
2121 budget: 0.10,
2122 }
2123 }
2124}
2125
2126#[derive(Debug, Clone, Serialize, Deserialize)]
2128pub struct CustomerMasterConfig {
2129 #[serde(default = "default_customer_count")]
2131 pub count: usize,
2132 #[serde(default = "default_intercompany_percent")]
2134 pub intercompany_percent: f64,
2135 #[serde(default)]
2137 pub credit_rating_distribution: CreditRatingDistribution,
2138 #[serde(default)]
2140 pub payment_behavior_distribution: PaymentBehaviorDistribution,
2141 #[serde(default = "default_true")]
2143 pub generate_credit_limits: bool,
2144}
2145
2146fn default_customer_count() -> usize {
2147 2000
2148}
2149
2150impl Default for CustomerMasterConfig {
2151 fn default() -> Self {
2152 Self {
2153 count: default_customer_count(),
2154 intercompany_percent: default_intercompany_percent(),
2155 credit_rating_distribution: CreditRatingDistribution::default(),
2156 payment_behavior_distribution: PaymentBehaviorDistribution::default(),
2157 generate_credit_limits: true,
2158 }
2159 }
2160}
2161
2162#[derive(Debug, Clone, Serialize, Deserialize)]
2164pub struct CreditRatingDistribution {
2165 pub aaa: f64,
2167 pub aa: f64,
2169 pub a: f64,
2171 pub bbb: f64,
2173 pub bb: f64,
2175 pub b: f64,
2177 pub below_b: f64,
2179}
2180
2181impl Default for CreditRatingDistribution {
2182 fn default() -> Self {
2183 Self {
2184 aaa: 0.05,
2185 aa: 0.10,
2186 a: 0.20,
2187 bbb: 0.30,
2188 bb: 0.20,
2189 b: 0.10,
2190 below_b: 0.05,
2191 }
2192 }
2193}
2194
2195#[derive(Debug, Clone, Serialize, Deserialize)]
2197pub struct PaymentBehaviorDistribution {
2198 pub early_payer: f64,
2200 pub on_time: f64,
2202 pub occasional_late: f64,
2204 pub frequent_late: f64,
2206 pub discount_taker: f64,
2208}
2209
2210impl Default for PaymentBehaviorDistribution {
2211 fn default() -> Self {
2212 Self {
2213 early_payer: 0.10,
2214 on_time: 0.50,
2215 occasional_late: 0.25,
2216 frequent_late: 0.10,
2217 discount_taker: 0.05,
2218 }
2219 }
2220}
2221
2222#[derive(Debug, Clone, Serialize, Deserialize)]
2224pub struct MaterialMasterConfig {
2225 #[serde(default = "default_material_count")]
2227 pub count: usize,
2228 #[serde(default)]
2230 pub type_distribution: MaterialTypeDistribution,
2231 #[serde(default)]
2233 pub valuation_distribution: ValuationMethodDistribution,
2234 #[serde(default = "default_bom_percent")]
2236 pub bom_percent: f64,
2237 #[serde(default = "default_max_bom_depth")]
2239 pub max_bom_depth: u8,
2240}
2241
2242fn default_material_count() -> usize {
2243 5000
2244}
2245
2246fn default_bom_percent() -> f64 {
2247 0.20
2248}
2249
2250fn default_max_bom_depth() -> u8 {
2251 3
2252}
2253
2254impl Default for MaterialMasterConfig {
2255 fn default() -> Self {
2256 Self {
2257 count: default_material_count(),
2258 type_distribution: MaterialTypeDistribution::default(),
2259 valuation_distribution: ValuationMethodDistribution::default(),
2260 bom_percent: default_bom_percent(),
2261 max_bom_depth: default_max_bom_depth(),
2262 }
2263 }
2264}
2265
2266#[derive(Debug, Clone, Serialize, Deserialize)]
2268pub struct MaterialTypeDistribution {
2269 pub raw_material: f64,
2271 pub semi_finished: f64,
2273 pub finished_good: f64,
2275 pub trading_good: f64,
2277 pub operating_supply: f64,
2279 pub service: f64,
2281}
2282
2283impl Default for MaterialTypeDistribution {
2284 fn default() -> Self {
2285 Self {
2286 raw_material: 0.30,
2287 semi_finished: 0.15,
2288 finished_good: 0.25,
2289 trading_good: 0.15,
2290 operating_supply: 0.10,
2291 service: 0.05,
2292 }
2293 }
2294}
2295
2296#[derive(Debug, Clone, Serialize, Deserialize)]
2298pub struct ValuationMethodDistribution {
2299 pub standard_cost: f64,
2301 pub moving_average: f64,
2303 pub fifo: f64,
2305 pub lifo: f64,
2307}
2308
2309impl Default for ValuationMethodDistribution {
2310 fn default() -> Self {
2311 Self {
2312 standard_cost: 0.50,
2313 moving_average: 0.30,
2314 fifo: 0.15,
2315 lifo: 0.05,
2316 }
2317 }
2318}
2319
2320#[derive(Debug, Clone, Serialize, Deserialize)]
2322pub struct FixedAssetMasterConfig {
2323 #[serde(default = "default_asset_count")]
2325 pub count: usize,
2326 #[serde(default)]
2328 pub class_distribution: AssetClassDistribution,
2329 #[serde(default)]
2331 pub depreciation_distribution: DepreciationMethodDistribution,
2332 #[serde(default = "default_fully_depreciated_percent")]
2334 pub fully_depreciated_percent: f64,
2335 #[serde(default = "default_true")]
2337 pub generate_acquisition_history: bool,
2338}
2339
2340fn default_asset_count() -> usize {
2341 800
2342}
2343
2344fn default_fully_depreciated_percent() -> f64 {
2345 0.15
2346}
2347
2348impl Default for FixedAssetMasterConfig {
2349 fn default() -> Self {
2350 Self {
2351 count: default_asset_count(),
2352 class_distribution: AssetClassDistribution::default(),
2353 depreciation_distribution: DepreciationMethodDistribution::default(),
2354 fully_depreciated_percent: default_fully_depreciated_percent(),
2355 generate_acquisition_history: true,
2356 }
2357 }
2358}
2359
2360#[derive(Debug, Clone, Serialize, Deserialize)]
2362pub struct AssetClassDistribution {
2363 pub buildings: f64,
2365 pub machinery: f64,
2367 pub vehicles: f64,
2369 pub it_equipment: f64,
2371 pub furniture: f64,
2373 pub land: f64,
2375 pub leasehold: f64,
2377}
2378
2379impl Default for AssetClassDistribution {
2380 fn default() -> Self {
2381 Self {
2382 buildings: 0.15,
2383 machinery: 0.30,
2384 vehicles: 0.15,
2385 it_equipment: 0.20,
2386 furniture: 0.10,
2387 land: 0.05,
2388 leasehold: 0.05,
2389 }
2390 }
2391}
2392
2393#[derive(Debug, Clone, Serialize, Deserialize)]
2395pub struct DepreciationMethodDistribution {
2396 pub straight_line: f64,
2398 pub declining_balance: f64,
2400 pub double_declining: f64,
2402 pub sum_of_years: f64,
2404 pub units_of_production: f64,
2406}
2407
2408impl Default for DepreciationMethodDistribution {
2409 fn default() -> Self {
2410 Self {
2411 straight_line: 0.60,
2412 declining_balance: 0.20,
2413 double_declining: 0.10,
2414 sum_of_years: 0.05,
2415 units_of_production: 0.05,
2416 }
2417 }
2418}
2419
2420#[derive(Debug, Clone, Serialize, Deserialize)]
2422pub struct EmployeeMasterConfig {
2423 #[serde(default = "default_employee_count")]
2425 pub count: usize,
2426 #[serde(default = "default_true")]
2428 pub generate_hierarchy: bool,
2429 #[serde(default = "default_hierarchy_depth")]
2431 pub max_hierarchy_depth: u8,
2432 #[serde(default = "default_span_of_control")]
2434 pub average_span_of_control: f64,
2435 #[serde(default)]
2437 pub approval_limits: ApprovalLimitDistribution,
2438 #[serde(default)]
2440 pub department_distribution: EmployeeDepartmentDistribution,
2441}
2442
2443fn default_employee_count() -> usize {
2444 1500
2445}
2446
2447fn default_hierarchy_depth() -> u8 {
2448 6
2449}
2450
2451fn default_span_of_control() -> f64 {
2452 5.0
2453}
2454
2455impl Default for EmployeeMasterConfig {
2456 fn default() -> Self {
2457 Self {
2458 count: default_employee_count(),
2459 generate_hierarchy: true,
2460 max_hierarchy_depth: default_hierarchy_depth(),
2461 average_span_of_control: default_span_of_control(),
2462 approval_limits: ApprovalLimitDistribution::default(),
2463 department_distribution: EmployeeDepartmentDistribution::default(),
2464 }
2465 }
2466}
2467
2468#[derive(Debug, Clone, Serialize, Deserialize)]
2470pub struct ApprovalLimitDistribution {
2471 #[serde(default = "default_staff_limit")]
2473 pub staff: f64,
2474 #[serde(default = "default_senior_limit")]
2476 pub senior: f64,
2477 #[serde(default = "default_manager_limit")]
2479 pub manager: f64,
2480 #[serde(default = "default_director_limit")]
2482 pub director: f64,
2483 #[serde(default = "default_vp_limit")]
2485 pub vp: f64,
2486 #[serde(default = "default_executive_limit")]
2488 pub executive: f64,
2489}
2490
2491fn default_staff_limit() -> f64 {
2492 1000.0
2493}
2494fn default_senior_limit() -> f64 {
2495 5000.0
2496}
2497fn default_manager_limit() -> f64 {
2498 25000.0
2499}
2500fn default_director_limit() -> f64 {
2501 100000.0
2502}
2503fn default_vp_limit() -> f64 {
2504 500000.0
2505}
2506fn default_executive_limit() -> f64 {
2507 f64::INFINITY
2508}
2509
2510impl Default for ApprovalLimitDistribution {
2511 fn default() -> Self {
2512 Self {
2513 staff: default_staff_limit(),
2514 senior: default_senior_limit(),
2515 manager: default_manager_limit(),
2516 director: default_director_limit(),
2517 vp: default_vp_limit(),
2518 executive: default_executive_limit(),
2519 }
2520 }
2521}
2522
2523#[derive(Debug, Clone, Serialize, Deserialize)]
2525pub struct EmployeeDepartmentDistribution {
2526 pub finance: f64,
2528 pub procurement: f64,
2530 pub sales: f64,
2532 pub warehouse: f64,
2534 pub it: f64,
2536 pub hr: f64,
2538 pub operations: f64,
2540 pub executive: f64,
2542}
2543
2544impl Default for EmployeeDepartmentDistribution {
2545 fn default() -> Self {
2546 Self {
2547 finance: 0.12,
2548 procurement: 0.10,
2549 sales: 0.25,
2550 warehouse: 0.15,
2551 it: 0.10,
2552 hr: 0.05,
2553 operations: 0.20,
2554 executive: 0.03,
2555 }
2556 }
2557}
2558
2559#[derive(Debug, Clone, Serialize, Deserialize)]
2561pub struct CostCenterMasterConfig {
2562 #[serde(default = "default_cost_center_count")]
2564 pub count: usize,
2565 #[serde(default = "default_true")]
2567 pub generate_hierarchy: bool,
2568 #[serde(default = "default_cc_hierarchy_depth")]
2570 pub max_hierarchy_depth: u8,
2571}
2572
2573fn default_cost_center_count() -> usize {
2574 50
2575}
2576
2577fn default_cc_hierarchy_depth() -> u8 {
2578 3
2579}
2580
2581impl Default for CostCenterMasterConfig {
2582 fn default() -> Self {
2583 Self {
2584 count: default_cost_center_count(),
2585 generate_hierarchy: true,
2586 max_hierarchy_depth: default_cc_hierarchy_depth(),
2587 }
2588 }
2589}
2590
2591#[derive(Debug, Clone, Serialize, Deserialize)]
2597pub struct DocumentFlowConfig {
2598 #[serde(default)]
2600 pub p2p: P2PFlowConfig,
2601 #[serde(default)]
2603 pub o2c: O2CFlowConfig,
2604 #[serde(default = "default_true")]
2606 pub generate_document_references: bool,
2607 #[serde(default)]
2609 pub export_flow_graph: bool,
2610}
2611
2612impl Default for DocumentFlowConfig {
2613 fn default() -> Self {
2614 Self {
2615 p2p: P2PFlowConfig::default(),
2616 o2c: O2CFlowConfig::default(),
2617 generate_document_references: true,
2618 export_flow_graph: false,
2619 }
2620 }
2621}
2622
2623#[derive(Debug, Clone, Serialize, Deserialize)]
2625pub struct P2PFlowConfig {
2626 #[serde(default = "default_true")]
2628 pub enabled: bool,
2629 #[serde(default = "default_three_way_match_rate")]
2631 pub three_way_match_rate: f64,
2632 #[serde(default = "default_partial_delivery_rate")]
2634 pub partial_delivery_rate: f64,
2635 #[serde(default = "default_price_variance_rate")]
2637 pub price_variance_rate: f64,
2638 #[serde(default = "default_max_price_variance")]
2640 pub max_price_variance_percent: f64,
2641 #[serde(default = "default_quantity_variance_rate")]
2643 pub quantity_variance_rate: f64,
2644 #[serde(default = "default_po_to_gr_days")]
2646 pub average_po_to_gr_days: u32,
2647 #[serde(default = "default_gr_to_invoice_days")]
2649 pub average_gr_to_invoice_days: u32,
2650 #[serde(default = "default_invoice_to_payment_days")]
2652 pub average_invoice_to_payment_days: u32,
2653 #[serde(default)]
2655 pub line_count_distribution: DocumentLineCountDistribution,
2656 #[serde(default)]
2658 pub payment_behavior: P2PPaymentBehaviorConfig,
2659}
2660
2661fn default_three_way_match_rate() -> f64 {
2662 0.95
2663}
2664
2665fn default_partial_delivery_rate() -> f64 {
2666 0.15
2667}
2668
2669fn default_price_variance_rate() -> f64 {
2670 0.08
2671}
2672
2673fn default_max_price_variance() -> f64 {
2674 0.05
2675}
2676
2677fn default_quantity_variance_rate() -> f64 {
2678 0.05
2679}
2680
2681fn default_po_to_gr_days() -> u32 {
2682 14
2683}
2684
2685fn default_gr_to_invoice_days() -> u32 {
2686 5
2687}
2688
2689fn default_invoice_to_payment_days() -> u32 {
2690 30
2691}
2692
2693impl Default for P2PFlowConfig {
2694 fn default() -> Self {
2695 Self {
2696 enabled: true,
2697 three_way_match_rate: default_three_way_match_rate(),
2698 partial_delivery_rate: default_partial_delivery_rate(),
2699 price_variance_rate: default_price_variance_rate(),
2700 max_price_variance_percent: default_max_price_variance(),
2701 quantity_variance_rate: default_quantity_variance_rate(),
2702 average_po_to_gr_days: default_po_to_gr_days(),
2703 average_gr_to_invoice_days: default_gr_to_invoice_days(),
2704 average_invoice_to_payment_days: default_invoice_to_payment_days(),
2705 line_count_distribution: DocumentLineCountDistribution::default(),
2706 payment_behavior: P2PPaymentBehaviorConfig::default(),
2707 }
2708 }
2709}
2710
2711#[derive(Debug, Clone, Serialize, Deserialize)]
2717pub struct P2PPaymentBehaviorConfig {
2718 #[serde(default = "default_p2p_late_payment_rate")]
2720 pub late_payment_rate: f64,
2721 #[serde(default)]
2723 pub late_payment_days_distribution: LatePaymentDaysDistribution,
2724 #[serde(default = "default_p2p_partial_payment_rate")]
2726 pub partial_payment_rate: f64,
2727 #[serde(default = "default_p2p_payment_correction_rate")]
2729 pub payment_correction_rate: f64,
2730}
2731
2732fn default_p2p_late_payment_rate() -> f64 {
2733 0.15
2734}
2735
2736fn default_p2p_partial_payment_rate() -> f64 {
2737 0.05
2738}
2739
2740fn default_p2p_payment_correction_rate() -> f64 {
2741 0.02
2742}
2743
2744impl Default for P2PPaymentBehaviorConfig {
2745 fn default() -> Self {
2746 Self {
2747 late_payment_rate: default_p2p_late_payment_rate(),
2748 late_payment_days_distribution: LatePaymentDaysDistribution::default(),
2749 partial_payment_rate: default_p2p_partial_payment_rate(),
2750 payment_correction_rate: default_p2p_payment_correction_rate(),
2751 }
2752 }
2753}
2754
2755#[derive(Debug, Clone, Serialize, Deserialize)]
2757pub struct LatePaymentDaysDistribution {
2758 #[serde(default = "default_slightly_late")]
2760 pub slightly_late_1_to_7: f64,
2761 #[serde(default = "default_late_8_14")]
2763 pub late_8_to_14: f64,
2764 #[serde(default = "default_very_late")]
2766 pub very_late_15_to_30: f64,
2767 #[serde(default = "default_severely_late")]
2769 pub severely_late_31_to_60: f64,
2770 #[serde(default = "default_extremely_late")]
2772 pub extremely_late_over_60: f64,
2773}
2774
2775fn default_slightly_late() -> f64 {
2776 0.50
2777}
2778
2779fn default_late_8_14() -> f64 {
2780 0.25
2781}
2782
2783fn default_very_late() -> f64 {
2784 0.15
2785}
2786
2787fn default_severely_late() -> f64 {
2788 0.07
2789}
2790
2791fn default_extremely_late() -> f64 {
2792 0.03
2793}
2794
2795impl Default for LatePaymentDaysDistribution {
2796 fn default() -> Self {
2797 Self {
2798 slightly_late_1_to_7: default_slightly_late(),
2799 late_8_to_14: default_late_8_14(),
2800 very_late_15_to_30: default_very_late(),
2801 severely_late_31_to_60: default_severely_late(),
2802 extremely_late_over_60: default_extremely_late(),
2803 }
2804 }
2805}
2806
2807#[derive(Debug, Clone, Serialize, Deserialize)]
2809pub struct O2CFlowConfig {
2810 #[serde(default = "default_true")]
2812 pub enabled: bool,
2813 #[serde(default = "default_credit_check_failure_rate")]
2815 pub credit_check_failure_rate: f64,
2816 #[serde(default = "default_partial_shipment_rate")]
2818 pub partial_shipment_rate: f64,
2819 #[serde(default = "default_return_rate")]
2821 pub return_rate: f64,
2822 #[serde(default = "default_bad_debt_rate")]
2824 pub bad_debt_rate: f64,
2825 #[serde(default = "default_so_to_delivery_days")]
2827 pub average_so_to_delivery_days: u32,
2828 #[serde(default = "default_delivery_to_invoice_days")]
2830 pub average_delivery_to_invoice_days: u32,
2831 #[serde(default = "default_invoice_to_receipt_days")]
2833 pub average_invoice_to_receipt_days: u32,
2834 #[serde(default)]
2836 pub line_count_distribution: DocumentLineCountDistribution,
2837 #[serde(default)]
2839 pub cash_discount: CashDiscountConfig,
2840 #[serde(default)]
2842 pub payment_behavior: O2CPaymentBehaviorConfig,
2843}
2844
2845fn default_credit_check_failure_rate() -> f64 {
2846 0.02
2847}
2848
2849fn default_partial_shipment_rate() -> f64 {
2850 0.10
2851}
2852
2853fn default_return_rate() -> f64 {
2854 0.03
2855}
2856
2857fn default_bad_debt_rate() -> f64 {
2858 0.01
2859}
2860
2861fn default_so_to_delivery_days() -> u32 {
2862 7
2863}
2864
2865fn default_delivery_to_invoice_days() -> u32 {
2866 1
2867}
2868
2869fn default_invoice_to_receipt_days() -> u32 {
2870 45
2871}
2872
2873impl Default for O2CFlowConfig {
2874 fn default() -> Self {
2875 Self {
2876 enabled: true,
2877 credit_check_failure_rate: default_credit_check_failure_rate(),
2878 partial_shipment_rate: default_partial_shipment_rate(),
2879 return_rate: default_return_rate(),
2880 bad_debt_rate: default_bad_debt_rate(),
2881 average_so_to_delivery_days: default_so_to_delivery_days(),
2882 average_delivery_to_invoice_days: default_delivery_to_invoice_days(),
2883 average_invoice_to_receipt_days: default_invoice_to_receipt_days(),
2884 line_count_distribution: DocumentLineCountDistribution::default(),
2885 cash_discount: CashDiscountConfig::default(),
2886 payment_behavior: O2CPaymentBehaviorConfig::default(),
2887 }
2888 }
2889}
2890
2891#[derive(Debug, Clone, Serialize, Deserialize, Default)]
2897pub struct O2CPaymentBehaviorConfig {
2898 #[serde(default)]
2900 pub dunning: DunningConfig,
2901 #[serde(default)]
2903 pub partial_payments: PartialPaymentConfig,
2904 #[serde(default)]
2906 pub short_payments: ShortPaymentConfig,
2907 #[serde(default)]
2909 pub on_account_payments: OnAccountPaymentConfig,
2910 #[serde(default)]
2912 pub payment_corrections: PaymentCorrectionConfig,
2913}
2914
2915#[derive(Debug, Clone, Serialize, Deserialize)]
2917pub struct DunningConfig {
2918 #[serde(default)]
2920 pub enabled: bool,
2921 #[serde(default = "default_dunning_level_1_days")]
2923 pub level_1_days_overdue: u32,
2924 #[serde(default = "default_dunning_level_2_days")]
2926 pub level_2_days_overdue: u32,
2927 #[serde(default = "default_dunning_level_3_days")]
2929 pub level_3_days_overdue: u32,
2930 #[serde(default = "default_collection_days")]
2932 pub collection_days_overdue: u32,
2933 #[serde(default)]
2935 pub payment_after_dunning_rates: DunningPaymentRates,
2936 #[serde(default = "default_dunning_block_rate")]
2938 pub dunning_block_rate: f64,
2939 #[serde(default = "default_dunning_interest_rate")]
2941 pub interest_rate_per_year: f64,
2942 #[serde(default = "default_dunning_charge")]
2944 pub dunning_charge: f64,
2945}
2946
2947fn default_dunning_level_1_days() -> u32 {
2948 14
2949}
2950
2951fn default_dunning_level_2_days() -> u32 {
2952 28
2953}
2954
2955fn default_dunning_level_3_days() -> u32 {
2956 42
2957}
2958
2959fn default_collection_days() -> u32 {
2960 60
2961}
2962
2963fn default_dunning_block_rate() -> f64 {
2964 0.05
2965}
2966
2967fn default_dunning_interest_rate() -> f64 {
2968 0.09
2969}
2970
2971fn default_dunning_charge() -> f64 {
2972 25.0
2973}
2974
2975impl Default for DunningConfig {
2976 fn default() -> Self {
2977 Self {
2978 enabled: false,
2979 level_1_days_overdue: default_dunning_level_1_days(),
2980 level_2_days_overdue: default_dunning_level_2_days(),
2981 level_3_days_overdue: default_dunning_level_3_days(),
2982 collection_days_overdue: default_collection_days(),
2983 payment_after_dunning_rates: DunningPaymentRates::default(),
2984 dunning_block_rate: default_dunning_block_rate(),
2985 interest_rate_per_year: default_dunning_interest_rate(),
2986 dunning_charge: default_dunning_charge(),
2987 }
2988 }
2989}
2990
2991#[derive(Debug, Clone, Serialize, Deserialize)]
2993pub struct DunningPaymentRates {
2994 #[serde(default = "default_after_level_1")]
2996 pub after_level_1: f64,
2997 #[serde(default = "default_after_level_2")]
2999 pub after_level_2: f64,
3000 #[serde(default = "default_after_level_3")]
3002 pub after_level_3: f64,
3003 #[serde(default = "default_during_collection")]
3005 pub during_collection: f64,
3006 #[serde(default = "default_never_pay")]
3008 pub never_pay: f64,
3009}
3010
3011fn default_after_level_1() -> f64 {
3012 0.40
3013}
3014
3015fn default_after_level_2() -> f64 {
3016 0.30
3017}
3018
3019fn default_after_level_3() -> f64 {
3020 0.15
3021}
3022
3023fn default_during_collection() -> f64 {
3024 0.05
3025}
3026
3027fn default_never_pay() -> f64 {
3028 0.10
3029}
3030
3031impl Default for DunningPaymentRates {
3032 fn default() -> Self {
3033 Self {
3034 after_level_1: default_after_level_1(),
3035 after_level_2: default_after_level_2(),
3036 after_level_3: default_after_level_3(),
3037 during_collection: default_during_collection(),
3038 never_pay: default_never_pay(),
3039 }
3040 }
3041}
3042
3043#[derive(Debug, Clone, Serialize, Deserialize)]
3045pub struct PartialPaymentConfig {
3046 #[serde(default = "default_partial_payment_rate")]
3048 pub rate: f64,
3049 #[serde(default)]
3051 pub percentage_distribution: PartialPaymentPercentageDistribution,
3052 #[serde(default = "default_avg_days_until_remainder")]
3054 pub avg_days_until_remainder: u32,
3055}
3056
3057fn default_partial_payment_rate() -> f64 {
3058 0.08
3059}
3060
3061fn default_avg_days_until_remainder() -> u32 {
3062 30
3063}
3064
3065impl Default for PartialPaymentConfig {
3066 fn default() -> Self {
3067 Self {
3068 rate: default_partial_payment_rate(),
3069 percentage_distribution: PartialPaymentPercentageDistribution::default(),
3070 avg_days_until_remainder: default_avg_days_until_remainder(),
3071 }
3072 }
3073}
3074
3075#[derive(Debug, Clone, Serialize, Deserialize)]
3077pub struct PartialPaymentPercentageDistribution {
3078 #[serde(default = "default_partial_25")]
3080 pub pay_25_percent: f64,
3081 #[serde(default = "default_partial_50")]
3083 pub pay_50_percent: f64,
3084 #[serde(default = "default_partial_75")]
3086 pub pay_75_percent: f64,
3087 #[serde(default = "default_partial_random")]
3089 pub pay_random_percent: f64,
3090}
3091
3092fn default_partial_25() -> f64 {
3093 0.15
3094}
3095
3096fn default_partial_50() -> f64 {
3097 0.50
3098}
3099
3100fn default_partial_75() -> f64 {
3101 0.25
3102}
3103
3104fn default_partial_random() -> f64 {
3105 0.10
3106}
3107
3108impl Default for PartialPaymentPercentageDistribution {
3109 fn default() -> Self {
3110 Self {
3111 pay_25_percent: default_partial_25(),
3112 pay_50_percent: default_partial_50(),
3113 pay_75_percent: default_partial_75(),
3114 pay_random_percent: default_partial_random(),
3115 }
3116 }
3117}
3118
3119#[derive(Debug, Clone, Serialize, Deserialize)]
3121pub struct ShortPaymentConfig {
3122 #[serde(default = "default_short_payment_rate")]
3124 pub rate: f64,
3125 #[serde(default)]
3127 pub reason_distribution: ShortPaymentReasonDistribution,
3128 #[serde(default = "default_max_short_percent")]
3130 pub max_short_percent: f64,
3131}
3132
3133fn default_short_payment_rate() -> f64 {
3134 0.03
3135}
3136
3137fn default_max_short_percent() -> f64 {
3138 0.10
3139}
3140
3141impl Default for ShortPaymentConfig {
3142 fn default() -> Self {
3143 Self {
3144 rate: default_short_payment_rate(),
3145 reason_distribution: ShortPaymentReasonDistribution::default(),
3146 max_short_percent: default_max_short_percent(),
3147 }
3148 }
3149}
3150
3151#[derive(Debug, Clone, Serialize, Deserialize)]
3153pub struct ShortPaymentReasonDistribution {
3154 #[serde(default = "default_pricing_dispute")]
3156 pub pricing_dispute: f64,
3157 #[serde(default = "default_quality_issue")]
3159 pub quality_issue: f64,
3160 #[serde(default = "default_quantity_discrepancy")]
3162 pub quantity_discrepancy: f64,
3163 #[serde(default = "default_unauthorized_deduction")]
3165 pub unauthorized_deduction: f64,
3166 #[serde(default = "default_incorrect_discount")]
3168 pub incorrect_discount: f64,
3169}
3170
3171fn default_pricing_dispute() -> f64 {
3172 0.30
3173}
3174
3175fn default_quality_issue() -> f64 {
3176 0.20
3177}
3178
3179fn default_quantity_discrepancy() -> f64 {
3180 0.20
3181}
3182
3183fn default_unauthorized_deduction() -> f64 {
3184 0.15
3185}
3186
3187fn default_incorrect_discount() -> f64 {
3188 0.15
3189}
3190
3191impl Default for ShortPaymentReasonDistribution {
3192 fn default() -> Self {
3193 Self {
3194 pricing_dispute: default_pricing_dispute(),
3195 quality_issue: default_quality_issue(),
3196 quantity_discrepancy: default_quantity_discrepancy(),
3197 unauthorized_deduction: default_unauthorized_deduction(),
3198 incorrect_discount: default_incorrect_discount(),
3199 }
3200 }
3201}
3202
3203#[derive(Debug, Clone, Serialize, Deserialize)]
3205pub struct OnAccountPaymentConfig {
3206 #[serde(default = "default_on_account_rate")]
3208 pub rate: f64,
3209 #[serde(default = "default_avg_days_until_applied")]
3211 pub avg_days_until_applied: u32,
3212}
3213
3214fn default_on_account_rate() -> f64 {
3215 0.02
3216}
3217
3218fn default_avg_days_until_applied() -> u32 {
3219 14
3220}
3221
3222impl Default for OnAccountPaymentConfig {
3223 fn default() -> Self {
3224 Self {
3225 rate: default_on_account_rate(),
3226 avg_days_until_applied: default_avg_days_until_applied(),
3227 }
3228 }
3229}
3230
3231#[derive(Debug, Clone, Serialize, Deserialize)]
3233pub struct PaymentCorrectionConfig {
3234 #[serde(default = "default_payment_correction_rate")]
3236 pub rate: f64,
3237 #[serde(default)]
3239 pub type_distribution: PaymentCorrectionTypeDistribution,
3240}
3241
3242fn default_payment_correction_rate() -> f64 {
3243 0.02
3244}
3245
3246impl Default for PaymentCorrectionConfig {
3247 fn default() -> Self {
3248 Self {
3249 rate: default_payment_correction_rate(),
3250 type_distribution: PaymentCorrectionTypeDistribution::default(),
3251 }
3252 }
3253}
3254
3255#[derive(Debug, Clone, Serialize, Deserialize)]
3257pub struct PaymentCorrectionTypeDistribution {
3258 #[serde(default = "default_nsf_rate")]
3260 pub nsf: f64,
3261 #[serde(default = "default_chargeback_rate")]
3263 pub chargeback: f64,
3264 #[serde(default = "default_wrong_amount_rate")]
3266 pub wrong_amount: f64,
3267 #[serde(default = "default_wrong_customer_rate")]
3269 pub wrong_customer: f64,
3270 #[serde(default = "default_duplicate_payment_rate")]
3272 pub duplicate_payment: f64,
3273}
3274
3275fn default_nsf_rate() -> f64 {
3276 0.30
3277}
3278
3279fn default_chargeback_rate() -> f64 {
3280 0.20
3281}
3282
3283fn default_wrong_amount_rate() -> f64 {
3284 0.20
3285}
3286
3287fn default_wrong_customer_rate() -> f64 {
3288 0.15
3289}
3290
3291fn default_duplicate_payment_rate() -> f64 {
3292 0.15
3293}
3294
3295impl Default for PaymentCorrectionTypeDistribution {
3296 fn default() -> Self {
3297 Self {
3298 nsf: default_nsf_rate(),
3299 chargeback: default_chargeback_rate(),
3300 wrong_amount: default_wrong_amount_rate(),
3301 wrong_customer: default_wrong_customer_rate(),
3302 duplicate_payment: default_duplicate_payment_rate(),
3303 }
3304 }
3305}
3306
3307#[derive(Debug, Clone, Serialize, Deserialize)]
3309pub struct DocumentLineCountDistribution {
3310 #[serde(default = "default_min_lines")]
3312 pub min_lines: u32,
3313 #[serde(default = "default_max_lines")]
3315 pub max_lines: u32,
3316 #[serde(default = "default_mode_lines")]
3318 pub mode_lines: u32,
3319}
3320
3321fn default_min_lines() -> u32 {
3322 1
3323}
3324
3325fn default_max_lines() -> u32 {
3326 20
3327}
3328
3329fn default_mode_lines() -> u32 {
3330 3
3331}
3332
3333impl Default for DocumentLineCountDistribution {
3334 fn default() -> Self {
3335 Self {
3336 min_lines: default_min_lines(),
3337 max_lines: default_max_lines(),
3338 mode_lines: default_mode_lines(),
3339 }
3340 }
3341}
3342
3343#[derive(Debug, Clone, Serialize, Deserialize)]
3345pub struct CashDiscountConfig {
3346 #[serde(default = "default_discount_eligible_rate")]
3348 pub eligible_rate: f64,
3349 #[serde(default = "default_discount_taken_rate")]
3351 pub taken_rate: f64,
3352 #[serde(default = "default_discount_percent")]
3354 pub discount_percent: f64,
3355 #[serde(default = "default_discount_days")]
3357 pub discount_days: u32,
3358}
3359
3360fn default_discount_eligible_rate() -> f64 {
3361 0.30
3362}
3363
3364fn default_discount_taken_rate() -> f64 {
3365 0.60
3366}
3367
3368fn default_discount_percent() -> f64 {
3369 0.02
3370}
3371
3372fn default_discount_days() -> u32 {
3373 10
3374}
3375
3376impl Default for CashDiscountConfig {
3377 fn default() -> Self {
3378 Self {
3379 eligible_rate: default_discount_eligible_rate(),
3380 taken_rate: default_discount_taken_rate(),
3381 discount_percent: default_discount_percent(),
3382 discount_days: default_discount_days(),
3383 }
3384 }
3385}
3386
3387#[derive(Debug, Clone, Serialize, Deserialize)]
3393pub struct IntercompanyConfig {
3394 #[serde(default)]
3396 pub enabled: bool,
3397 #[serde(default = "default_ic_transaction_rate")]
3399 pub ic_transaction_rate: f64,
3400 #[serde(default)]
3402 pub transfer_pricing_method: TransferPricingMethod,
3403 #[serde(default = "default_markup_percent")]
3405 pub markup_percent: f64,
3406 #[serde(default = "default_true")]
3408 pub generate_matched_pairs: bool,
3409 #[serde(default)]
3411 pub transaction_type_distribution: ICTransactionTypeDistribution,
3412 #[serde(default)]
3414 pub generate_eliminations: bool,
3415}
3416
3417fn default_ic_transaction_rate() -> f64 {
3418 0.15
3419}
3420
3421fn default_markup_percent() -> f64 {
3422 0.05
3423}
3424
3425impl Default for IntercompanyConfig {
3426 fn default() -> Self {
3427 Self {
3428 enabled: false,
3429 ic_transaction_rate: default_ic_transaction_rate(),
3430 transfer_pricing_method: TransferPricingMethod::default(),
3431 markup_percent: default_markup_percent(),
3432 generate_matched_pairs: true,
3433 transaction_type_distribution: ICTransactionTypeDistribution::default(),
3434 generate_eliminations: false,
3435 }
3436 }
3437}
3438
3439#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
3441#[serde(rename_all = "snake_case")]
3442pub enum TransferPricingMethod {
3443 #[default]
3445 CostPlus,
3446 ComparableUncontrolled,
3448 ResalePrice,
3450 TransactionalNetMargin,
3452 ProfitSplit,
3454}
3455
3456#[derive(Debug, Clone, Serialize, Deserialize)]
3458pub struct ICTransactionTypeDistribution {
3459 pub goods_sale: f64,
3461 pub service_provided: f64,
3463 pub loan: f64,
3465 pub dividend: f64,
3467 pub management_fee: f64,
3469 pub royalty: f64,
3471 pub cost_sharing: f64,
3473}
3474
3475impl Default for ICTransactionTypeDistribution {
3476 fn default() -> Self {
3477 Self {
3478 goods_sale: 0.35,
3479 service_provided: 0.20,
3480 loan: 0.10,
3481 dividend: 0.05,
3482 management_fee: 0.15,
3483 royalty: 0.10,
3484 cost_sharing: 0.05,
3485 }
3486 }
3487}
3488
3489#[derive(Debug, Clone, Serialize, Deserialize)]
3495pub struct BalanceConfig {
3496 #[serde(default)]
3498 pub generate_opening_balances: bool,
3499 #[serde(default = "default_true")]
3501 pub generate_trial_balances: bool,
3502 #[serde(default = "default_gross_margin")]
3504 pub target_gross_margin: f64,
3505 #[serde(default = "default_dso")]
3507 pub target_dso_days: u32,
3508 #[serde(default = "default_dpo")]
3510 pub target_dpo_days: u32,
3511 #[serde(default = "default_current_ratio")]
3513 pub target_current_ratio: f64,
3514 #[serde(default = "default_debt_equity")]
3516 pub target_debt_to_equity: f64,
3517 #[serde(default = "default_true")]
3519 pub validate_balance_equation: bool,
3520 #[serde(default = "default_true")]
3522 pub reconcile_subledgers: bool,
3523}
3524
3525fn default_gross_margin() -> f64 {
3526 0.35
3527}
3528
3529fn default_dso() -> u32 {
3530 45
3531}
3532
3533fn default_dpo() -> u32 {
3534 30
3535}
3536
3537fn default_current_ratio() -> f64 {
3538 1.5
3539}
3540
3541fn default_debt_equity() -> f64 {
3542 0.5
3543}
3544
3545impl Default for BalanceConfig {
3546 fn default() -> Self {
3547 Self {
3548 generate_opening_balances: false,
3549 generate_trial_balances: true,
3550 target_gross_margin: default_gross_margin(),
3551 target_dso_days: default_dso(),
3552 target_dpo_days: default_dpo(),
3553 target_current_ratio: default_current_ratio(),
3554 target_debt_to_equity: default_debt_equity(),
3555 validate_balance_equation: true,
3556 reconcile_subledgers: true,
3557 }
3558 }
3559}
3560
3561#[derive(Debug, Clone, Serialize, Deserialize)]
3570pub struct OcpmConfig {
3571 #[serde(default)]
3573 pub enabled: bool,
3574
3575 #[serde(default = "default_true")]
3577 pub generate_lifecycle_events: bool,
3578
3579 #[serde(default = "default_true")]
3581 pub include_object_relationships: bool,
3582
3583 #[serde(default = "default_true")]
3585 pub compute_variants: bool,
3586
3587 #[serde(default)]
3589 pub max_variants: usize,
3590
3591 #[serde(default)]
3593 pub p2p_process: OcpmProcessConfig,
3594
3595 #[serde(default)]
3597 pub o2c_process: OcpmProcessConfig,
3598
3599 #[serde(default)]
3601 pub output: OcpmOutputConfig,
3602}
3603
3604impl Default for OcpmConfig {
3605 fn default() -> Self {
3606 Self {
3607 enabled: false,
3608 generate_lifecycle_events: true,
3609 include_object_relationships: true,
3610 compute_variants: true,
3611 max_variants: 0,
3612 p2p_process: OcpmProcessConfig::default(),
3613 o2c_process: OcpmProcessConfig::default(),
3614 output: OcpmOutputConfig::default(),
3615 }
3616 }
3617}
3618
3619#[derive(Debug, Clone, Serialize, Deserialize)]
3621pub struct OcpmProcessConfig {
3622 #[serde(default = "default_rework_probability")]
3624 pub rework_probability: f64,
3625
3626 #[serde(default = "default_skip_probability")]
3628 pub skip_step_probability: f64,
3629
3630 #[serde(default = "default_out_of_order_probability")]
3632 pub out_of_order_probability: f64,
3633}
3634
3635fn default_rework_probability() -> f64 {
3636 0.05
3637}
3638
3639fn default_skip_probability() -> f64 {
3640 0.02
3641}
3642
3643fn default_out_of_order_probability() -> f64 {
3644 0.03
3645}
3646
3647impl Default for OcpmProcessConfig {
3648 fn default() -> Self {
3649 Self {
3650 rework_probability: default_rework_probability(),
3651 skip_step_probability: default_skip_probability(),
3652 out_of_order_probability: default_out_of_order_probability(),
3653 }
3654 }
3655}
3656
3657#[derive(Debug, Clone, Serialize, Deserialize)]
3659pub struct OcpmOutputConfig {
3660 #[serde(default = "default_true")]
3662 pub ocel_json: bool,
3663
3664 #[serde(default)]
3666 pub ocel_xml: bool,
3667
3668 #[serde(default)]
3670 pub xes: bool,
3671
3672 #[serde(default = "default_true")]
3674 pub xes_include_lifecycle: bool,
3675
3676 #[serde(default = "default_true")]
3678 pub xes_include_resources: bool,
3679
3680 #[serde(default = "default_true")]
3682 pub flattened_csv: bool,
3683
3684 #[serde(default = "default_true")]
3686 pub event_object_csv: bool,
3687
3688 #[serde(default = "default_true")]
3690 pub object_relationship_csv: bool,
3691
3692 #[serde(default = "default_true")]
3694 pub variants_csv: bool,
3695
3696 #[serde(default)]
3698 pub export_reference_models: bool,
3699}
3700
3701impl Default for OcpmOutputConfig {
3702 fn default() -> Self {
3703 Self {
3704 ocel_json: true,
3705 ocel_xml: false,
3706 xes: false,
3707 xes_include_lifecycle: true,
3708 xes_include_resources: true,
3709 flattened_csv: true,
3710 event_object_csv: true,
3711 object_relationship_csv: true,
3712 variants_csv: true,
3713 export_reference_models: false,
3714 }
3715 }
3716}
3717
3718#[derive(Debug, Clone, Serialize, Deserialize)]
3720pub struct AuditGenerationConfig {
3721 #[serde(default)]
3723 pub enabled: bool,
3724
3725 #[serde(default = "default_true")]
3727 pub generate_workpapers: bool,
3728
3729 #[serde(default)]
3731 pub engagement_types: AuditEngagementTypesConfig,
3732
3733 #[serde(default)]
3735 pub workpapers: WorkpaperConfig,
3736
3737 #[serde(default)]
3739 pub team: AuditTeamConfig,
3740
3741 #[serde(default)]
3743 pub review: ReviewWorkflowConfig,
3744}
3745
3746impl Default for AuditGenerationConfig {
3747 fn default() -> Self {
3748 Self {
3749 enabled: false,
3750 generate_workpapers: true,
3751 engagement_types: AuditEngagementTypesConfig::default(),
3752 workpapers: WorkpaperConfig::default(),
3753 team: AuditTeamConfig::default(),
3754 review: ReviewWorkflowConfig::default(),
3755 }
3756 }
3757}
3758
3759#[derive(Debug, Clone, Serialize, Deserialize)]
3761pub struct AuditEngagementTypesConfig {
3762 #[serde(default = "default_financial_audit_prob")]
3764 pub financial_statement: f64,
3765 #[serde(default = "default_sox_audit_prob")]
3767 pub sox_icfr: f64,
3768 #[serde(default = "default_integrated_audit_prob")]
3770 pub integrated: f64,
3771 #[serde(default = "default_review_prob")]
3773 pub review: f64,
3774 #[serde(default = "default_aup_prob")]
3776 pub agreed_upon_procedures: f64,
3777}
3778
3779fn default_financial_audit_prob() -> f64 {
3780 0.40
3781}
3782fn default_sox_audit_prob() -> f64 {
3783 0.20
3784}
3785fn default_integrated_audit_prob() -> f64 {
3786 0.25
3787}
3788fn default_review_prob() -> f64 {
3789 0.10
3790}
3791fn default_aup_prob() -> f64 {
3792 0.05
3793}
3794
3795impl Default for AuditEngagementTypesConfig {
3796 fn default() -> Self {
3797 Self {
3798 financial_statement: default_financial_audit_prob(),
3799 sox_icfr: default_sox_audit_prob(),
3800 integrated: default_integrated_audit_prob(),
3801 review: default_review_prob(),
3802 agreed_upon_procedures: default_aup_prob(),
3803 }
3804 }
3805}
3806
3807#[derive(Debug, Clone, Serialize, Deserialize)]
3809pub struct WorkpaperConfig {
3810 #[serde(default = "default_workpapers_per_phase")]
3812 pub average_per_phase: usize,
3813
3814 #[serde(default = "default_true")]
3816 pub include_isa_references: bool,
3817
3818 #[serde(default = "default_true")]
3820 pub include_sample_details: bool,
3821
3822 #[serde(default = "default_true")]
3824 pub include_cross_references: bool,
3825
3826 #[serde(default)]
3828 pub sampling: SamplingConfig,
3829}
3830
3831fn default_workpapers_per_phase() -> usize {
3832 5
3833}
3834
3835impl Default for WorkpaperConfig {
3836 fn default() -> Self {
3837 Self {
3838 average_per_phase: default_workpapers_per_phase(),
3839 include_isa_references: true,
3840 include_sample_details: true,
3841 include_cross_references: true,
3842 sampling: SamplingConfig::default(),
3843 }
3844 }
3845}
3846
3847#[derive(Debug, Clone, Serialize, Deserialize)]
3849pub struct SamplingConfig {
3850 #[serde(default = "default_statistical_rate")]
3852 pub statistical_rate: f64,
3853 #[serde(default = "default_judgmental_rate")]
3855 pub judgmental_rate: f64,
3856 #[serde(default = "default_haphazard_rate")]
3858 pub haphazard_rate: f64,
3859 #[serde(default = "default_complete_examination_rate")]
3861 pub complete_examination_rate: f64,
3862}
3863
3864fn default_statistical_rate() -> f64 {
3865 0.40
3866}
3867fn default_judgmental_rate() -> f64 {
3868 0.30
3869}
3870fn default_haphazard_rate() -> f64 {
3871 0.20
3872}
3873fn default_complete_examination_rate() -> f64 {
3874 0.10
3875}
3876
3877impl Default for SamplingConfig {
3878 fn default() -> Self {
3879 Self {
3880 statistical_rate: default_statistical_rate(),
3881 judgmental_rate: default_judgmental_rate(),
3882 haphazard_rate: default_haphazard_rate(),
3883 complete_examination_rate: default_complete_examination_rate(),
3884 }
3885 }
3886}
3887
3888#[derive(Debug, Clone, Serialize, Deserialize)]
3890pub struct AuditTeamConfig {
3891 #[serde(default = "default_min_team_size")]
3893 pub min_team_size: usize,
3894 #[serde(default = "default_max_team_size")]
3896 pub max_team_size: usize,
3897 #[serde(default = "default_specialist_probability")]
3899 pub specialist_probability: f64,
3900}
3901
3902fn default_min_team_size() -> usize {
3903 3
3904}
3905fn default_max_team_size() -> usize {
3906 8
3907}
3908fn default_specialist_probability() -> f64 {
3909 0.30
3910}
3911
3912impl Default for AuditTeamConfig {
3913 fn default() -> Self {
3914 Self {
3915 min_team_size: default_min_team_size(),
3916 max_team_size: default_max_team_size(),
3917 specialist_probability: default_specialist_probability(),
3918 }
3919 }
3920}
3921
3922#[derive(Debug, Clone, Serialize, Deserialize)]
3924pub struct ReviewWorkflowConfig {
3925 #[serde(default = "default_review_delay_days")]
3927 pub average_review_delay_days: u32,
3928 #[serde(default = "default_rework_probability_review")]
3930 pub rework_probability: f64,
3931 #[serde(default = "default_true")]
3933 pub require_partner_signoff: bool,
3934}
3935
3936fn default_review_delay_days() -> u32 {
3937 2
3938}
3939fn default_rework_probability_review() -> f64 {
3940 0.15
3941}
3942
3943impl Default for ReviewWorkflowConfig {
3944 fn default() -> Self {
3945 Self {
3946 average_review_delay_days: default_review_delay_days(),
3947 rework_probability: default_rework_probability_review(),
3948 require_partner_signoff: true,
3949 }
3950 }
3951}
3952
3953#[derive(Debug, Clone, Serialize, Deserialize)]
3959pub struct DataQualitySchemaConfig {
3960 #[serde(default)]
3962 pub enabled: bool,
3963 #[serde(default)]
3965 pub preset: DataQualityPreset,
3966 #[serde(default)]
3968 pub missing_values: MissingValuesSchemaConfig,
3969 #[serde(default)]
3971 pub typos: TypoSchemaConfig,
3972 #[serde(default)]
3974 pub format_variations: FormatVariationSchemaConfig,
3975 #[serde(default)]
3977 pub duplicates: DuplicateSchemaConfig,
3978 #[serde(default)]
3980 pub encoding_issues: EncodingIssueSchemaConfig,
3981 #[serde(default)]
3983 pub generate_labels: bool,
3984 #[serde(default)]
3986 pub sink_profiles: SinkQualityProfiles,
3987}
3988
3989impl Default for DataQualitySchemaConfig {
3990 fn default() -> Self {
3991 Self {
3992 enabled: false,
3993 preset: DataQualityPreset::None,
3994 missing_values: MissingValuesSchemaConfig::default(),
3995 typos: TypoSchemaConfig::default(),
3996 format_variations: FormatVariationSchemaConfig::default(),
3997 duplicates: DuplicateSchemaConfig::default(),
3998 encoding_issues: EncodingIssueSchemaConfig::default(),
3999 generate_labels: true,
4000 sink_profiles: SinkQualityProfiles::default(),
4001 }
4002 }
4003}
4004
4005impl DataQualitySchemaConfig {
4006 pub fn with_preset(preset: DataQualityPreset) -> Self {
4008 let mut config = Self {
4009 preset,
4010 ..Default::default()
4011 };
4012 config.apply_preset();
4013 config
4014 }
4015
4016 pub fn apply_preset(&mut self) {
4019 if !self.preset.overrides_settings() {
4020 return;
4021 }
4022
4023 self.enabled = true;
4024
4025 self.missing_values.enabled = self.preset.missing_rate() > 0.0;
4027 self.missing_values.rate = self.preset.missing_rate();
4028
4029 self.typos.enabled = self.preset.typo_rate() > 0.0;
4031 self.typos.char_error_rate = self.preset.typo_rate();
4032
4033 self.duplicates.enabled = self.preset.duplicate_rate() > 0.0;
4035 self.duplicates.exact_duplicate_ratio = self.preset.duplicate_rate() * 0.4;
4036 self.duplicates.near_duplicate_ratio = self.preset.duplicate_rate() * 0.4;
4037 self.duplicates.fuzzy_duplicate_ratio = self.preset.duplicate_rate() * 0.2;
4038
4039 self.format_variations.enabled = self.preset.format_variations_enabled();
4041
4042 self.encoding_issues.enabled = self.preset.encoding_issues_enabled();
4044 self.encoding_issues.rate = self.preset.encoding_issue_rate();
4045
4046 if self.preset.ocr_errors_enabled() {
4048 self.typos.type_weights.ocr_errors = 0.3;
4049 }
4050 }
4051
4052 pub fn effective_missing_rate(&self) -> f64 {
4054 if self.preset.overrides_settings() {
4055 self.preset.missing_rate()
4056 } else {
4057 self.missing_values.rate
4058 }
4059 }
4060
4061 pub fn effective_typo_rate(&self) -> f64 {
4063 if self.preset.overrides_settings() {
4064 self.preset.typo_rate()
4065 } else {
4066 self.typos.char_error_rate
4067 }
4068 }
4069
4070 pub fn effective_duplicate_rate(&self) -> f64 {
4072 if self.preset.overrides_settings() {
4073 self.preset.duplicate_rate()
4074 } else {
4075 self.duplicates.exact_duplicate_ratio
4076 + self.duplicates.near_duplicate_ratio
4077 + self.duplicates.fuzzy_duplicate_ratio
4078 }
4079 }
4080
4081 pub fn clean() -> Self {
4083 Self::with_preset(DataQualityPreset::Clean)
4084 }
4085
4086 pub fn noisy() -> Self {
4088 Self::with_preset(DataQualityPreset::Noisy)
4089 }
4090
4091 pub fn legacy() -> Self {
4093 Self::with_preset(DataQualityPreset::Legacy)
4094 }
4095}
4096
4097#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
4099#[serde(rename_all = "snake_case")]
4100pub enum DataQualityPreset {
4101 #[default]
4103 None,
4104 Minimal,
4106 Normal,
4108 High,
4110 Custom,
4112
4113 Clean,
4119 Noisy,
4122 Legacy,
4125}
4126
4127impl DataQualityPreset {
4128 pub fn missing_rate(&self) -> f64 {
4130 match self {
4131 DataQualityPreset::None => 0.0,
4132 DataQualityPreset::Minimal => 0.005,
4133 DataQualityPreset::Normal => 0.02,
4134 DataQualityPreset::High => 0.08,
4135 DataQualityPreset::Custom => 0.01, DataQualityPreset::Clean => 0.001,
4137 DataQualityPreset::Noisy => 0.05,
4138 DataQualityPreset::Legacy => 0.10,
4139 }
4140 }
4141
4142 pub fn typo_rate(&self) -> f64 {
4144 match self {
4145 DataQualityPreset::None => 0.0,
4146 DataQualityPreset::Minimal => 0.0005,
4147 DataQualityPreset::Normal => 0.002,
4148 DataQualityPreset::High => 0.01,
4149 DataQualityPreset::Custom => 0.001, DataQualityPreset::Clean => 0.0005,
4151 DataQualityPreset::Noisy => 0.02,
4152 DataQualityPreset::Legacy => 0.05,
4153 }
4154 }
4155
4156 pub fn duplicate_rate(&self) -> f64 {
4158 match self {
4159 DataQualityPreset::None => 0.0,
4160 DataQualityPreset::Minimal => 0.001,
4161 DataQualityPreset::Normal => 0.005,
4162 DataQualityPreset::High => 0.02,
4163 DataQualityPreset::Custom => 0.0, DataQualityPreset::Clean => 0.0,
4165 DataQualityPreset::Noisy => 0.01,
4166 DataQualityPreset::Legacy => 0.03,
4167 }
4168 }
4169
4170 pub fn format_variations_enabled(&self) -> bool {
4172 match self {
4173 DataQualityPreset::None | DataQualityPreset::Clean => false,
4174 DataQualityPreset::Minimal => true,
4175 DataQualityPreset::Normal => true,
4176 DataQualityPreset::High => true,
4177 DataQualityPreset::Custom => true,
4178 DataQualityPreset::Noisy => true,
4179 DataQualityPreset::Legacy => true,
4180 }
4181 }
4182
4183 pub fn ocr_errors_enabled(&self) -> bool {
4185 matches!(self, DataQualityPreset::Legacy | DataQualityPreset::High)
4186 }
4187
4188 pub fn encoding_issues_enabled(&self) -> bool {
4190 matches!(
4191 self,
4192 DataQualityPreset::Legacy | DataQualityPreset::High | DataQualityPreset::Noisy
4193 )
4194 }
4195
4196 pub fn encoding_issue_rate(&self) -> f64 {
4198 match self {
4199 DataQualityPreset::None | DataQualityPreset::Clean | DataQualityPreset::Minimal => 0.0,
4200 DataQualityPreset::Normal => 0.002,
4201 DataQualityPreset::High => 0.01,
4202 DataQualityPreset::Custom => 0.0,
4203 DataQualityPreset::Noisy => 0.005,
4204 DataQualityPreset::Legacy => 0.02,
4205 }
4206 }
4207
4208 pub fn overrides_settings(&self) -> bool {
4210 !matches!(self, DataQualityPreset::Custom | DataQualityPreset::None)
4211 }
4212
4213 pub fn description(&self) -> &'static str {
4215 match self {
4216 DataQualityPreset::None => "No data quality issues (pristine data)",
4217 DataQualityPreset::Minimal => "Very rare data quality issues",
4218 DataQualityPreset::Normal => "Realistic enterprise data quality",
4219 DataQualityPreset::High => "Messy data for stress testing",
4220 DataQualityPreset::Custom => "Custom settings from configuration",
4221 DataQualityPreset::Clean => "ML-ready clean data with minimal issues",
4222 DataQualityPreset::Noisy => "Typical production data with moderate issues",
4223 DataQualityPreset::Legacy => "Legacy/migrated data with heavy issues and OCR errors",
4224 }
4225 }
4226}
4227
4228#[derive(Debug, Clone, Serialize, Deserialize)]
4230pub struct MissingValuesSchemaConfig {
4231 #[serde(default)]
4233 pub enabled: bool,
4234 #[serde(default = "default_missing_rate")]
4236 pub rate: f64,
4237 #[serde(default)]
4239 pub strategy: MissingValueStrategy,
4240 #[serde(default)]
4242 pub field_rates: std::collections::HashMap<String, f64>,
4243 #[serde(default)]
4245 pub protected_fields: Vec<String>,
4246}
4247
4248fn default_missing_rate() -> f64 {
4249 0.01
4250}
4251
4252impl Default for MissingValuesSchemaConfig {
4253 fn default() -> Self {
4254 Self {
4255 enabled: false,
4256 rate: default_missing_rate(),
4257 strategy: MissingValueStrategy::Mcar,
4258 field_rates: std::collections::HashMap::new(),
4259 protected_fields: vec![
4260 "document_id".to_string(),
4261 "company_code".to_string(),
4262 "posting_date".to_string(),
4263 ],
4264 }
4265 }
4266}
4267
4268#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
4270#[serde(rename_all = "snake_case")]
4271pub enum MissingValueStrategy {
4272 #[default]
4274 Mcar,
4275 Mar,
4277 Mnar,
4279 Systematic,
4281}
4282
4283#[derive(Debug, Clone, Serialize, Deserialize)]
4285pub struct TypoSchemaConfig {
4286 #[serde(default)]
4288 pub enabled: bool,
4289 #[serde(default = "default_typo_rate")]
4291 pub char_error_rate: f64,
4292 #[serde(default)]
4294 pub type_weights: TypoTypeWeights,
4295 #[serde(default)]
4297 pub protected_fields: Vec<String>,
4298}
4299
4300fn default_typo_rate() -> f64 {
4301 0.001
4302}
4303
4304impl Default for TypoSchemaConfig {
4305 fn default() -> Self {
4306 Self {
4307 enabled: false,
4308 char_error_rate: default_typo_rate(),
4309 type_weights: TypoTypeWeights::default(),
4310 protected_fields: vec![
4311 "document_id".to_string(),
4312 "gl_account".to_string(),
4313 "company_code".to_string(),
4314 ],
4315 }
4316 }
4317}
4318
4319#[derive(Debug, Clone, Serialize, Deserialize)]
4321pub struct TypoTypeWeights {
4322 #[serde(default = "default_substitution_weight")]
4324 pub substitution: f64,
4325 #[serde(default = "default_transposition_weight")]
4327 pub transposition: f64,
4328 #[serde(default = "default_insertion_weight")]
4330 pub insertion: f64,
4331 #[serde(default = "default_deletion_weight")]
4333 pub deletion: f64,
4334 #[serde(default = "default_ocr_weight")]
4336 pub ocr_errors: f64,
4337 #[serde(default = "default_homophone_weight")]
4339 pub homophones: f64,
4340}
4341
4342fn default_substitution_weight() -> f64 {
4343 0.35
4344}
4345fn default_transposition_weight() -> f64 {
4346 0.25
4347}
4348fn default_insertion_weight() -> f64 {
4349 0.10
4350}
4351fn default_deletion_weight() -> f64 {
4352 0.15
4353}
4354fn default_ocr_weight() -> f64 {
4355 0.10
4356}
4357fn default_homophone_weight() -> f64 {
4358 0.05
4359}
4360
4361impl Default for TypoTypeWeights {
4362 fn default() -> Self {
4363 Self {
4364 substitution: default_substitution_weight(),
4365 transposition: default_transposition_weight(),
4366 insertion: default_insertion_weight(),
4367 deletion: default_deletion_weight(),
4368 ocr_errors: default_ocr_weight(),
4369 homophones: default_homophone_weight(),
4370 }
4371 }
4372}
4373
4374#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4376pub struct FormatVariationSchemaConfig {
4377 #[serde(default)]
4379 pub enabled: bool,
4380 #[serde(default)]
4382 pub dates: DateFormatVariationConfig,
4383 #[serde(default)]
4385 pub amounts: AmountFormatVariationConfig,
4386 #[serde(default)]
4388 pub identifiers: IdentifierFormatVariationConfig,
4389}
4390
4391#[derive(Debug, Clone, Serialize, Deserialize)]
4393pub struct DateFormatVariationConfig {
4394 #[serde(default)]
4396 pub enabled: bool,
4397 #[serde(default = "default_date_variation_rate")]
4399 pub rate: f64,
4400 #[serde(default = "default_true")]
4402 pub iso_format: bool,
4403 #[serde(default)]
4405 pub us_format: bool,
4406 #[serde(default)]
4408 pub eu_format: bool,
4409 #[serde(default)]
4411 pub long_format: bool,
4412}
4413
4414fn default_date_variation_rate() -> f64 {
4415 0.05
4416}
4417
4418impl Default for DateFormatVariationConfig {
4419 fn default() -> Self {
4420 Self {
4421 enabled: false,
4422 rate: default_date_variation_rate(),
4423 iso_format: true,
4424 us_format: false,
4425 eu_format: false,
4426 long_format: false,
4427 }
4428 }
4429}
4430
4431#[derive(Debug, Clone, Serialize, Deserialize)]
4433pub struct AmountFormatVariationConfig {
4434 #[serde(default)]
4436 pub enabled: bool,
4437 #[serde(default = "default_amount_variation_rate")]
4439 pub rate: f64,
4440 #[serde(default)]
4442 pub us_comma_format: bool,
4443 #[serde(default)]
4445 pub eu_format: bool,
4446 #[serde(default)]
4448 pub currency_prefix: bool,
4449 #[serde(default)]
4451 pub accounting_format: bool,
4452}
4453
4454fn default_amount_variation_rate() -> f64 {
4455 0.02
4456}
4457
4458impl Default for AmountFormatVariationConfig {
4459 fn default() -> Self {
4460 Self {
4461 enabled: false,
4462 rate: default_amount_variation_rate(),
4463 us_comma_format: false,
4464 eu_format: false,
4465 currency_prefix: false,
4466 accounting_format: false,
4467 }
4468 }
4469}
4470
4471#[derive(Debug, Clone, Serialize, Deserialize)]
4473pub struct IdentifierFormatVariationConfig {
4474 #[serde(default)]
4476 pub enabled: bool,
4477 #[serde(default = "default_identifier_variation_rate")]
4479 pub rate: f64,
4480 #[serde(default)]
4482 pub case_variations: bool,
4483 #[serde(default)]
4485 pub padding_variations: bool,
4486 #[serde(default)]
4488 pub separator_variations: bool,
4489}
4490
4491fn default_identifier_variation_rate() -> f64 {
4492 0.02
4493}
4494
4495impl Default for IdentifierFormatVariationConfig {
4496 fn default() -> Self {
4497 Self {
4498 enabled: false,
4499 rate: default_identifier_variation_rate(),
4500 case_variations: false,
4501 padding_variations: false,
4502 separator_variations: false,
4503 }
4504 }
4505}
4506
4507#[derive(Debug, Clone, Serialize, Deserialize)]
4509pub struct DuplicateSchemaConfig {
4510 #[serde(default)]
4512 pub enabled: bool,
4513 #[serde(default = "default_duplicate_rate")]
4515 pub rate: f64,
4516 #[serde(default = "default_exact_duplicate_ratio")]
4518 pub exact_duplicate_ratio: f64,
4519 #[serde(default = "default_near_duplicate_ratio")]
4521 pub near_duplicate_ratio: f64,
4522 #[serde(default = "default_fuzzy_duplicate_ratio")]
4524 pub fuzzy_duplicate_ratio: f64,
4525 #[serde(default = "default_max_date_offset")]
4527 pub max_date_offset_days: u32,
4528 #[serde(default = "default_max_amount_variance")]
4530 pub max_amount_variance: f64,
4531}
4532
4533fn default_duplicate_rate() -> f64 {
4534 0.005
4535}
4536fn default_exact_duplicate_ratio() -> f64 {
4537 0.4
4538}
4539fn default_near_duplicate_ratio() -> f64 {
4540 0.35
4541}
4542fn default_fuzzy_duplicate_ratio() -> f64 {
4543 0.25
4544}
4545fn default_max_date_offset() -> u32 {
4546 3
4547}
4548fn default_max_amount_variance() -> f64 {
4549 0.01
4550}
4551
4552impl Default for DuplicateSchemaConfig {
4553 fn default() -> Self {
4554 Self {
4555 enabled: false,
4556 rate: default_duplicate_rate(),
4557 exact_duplicate_ratio: default_exact_duplicate_ratio(),
4558 near_duplicate_ratio: default_near_duplicate_ratio(),
4559 fuzzy_duplicate_ratio: default_fuzzy_duplicate_ratio(),
4560 max_date_offset_days: default_max_date_offset(),
4561 max_amount_variance: default_max_amount_variance(),
4562 }
4563 }
4564}
4565
4566#[derive(Debug, Clone, Serialize, Deserialize)]
4568pub struct EncodingIssueSchemaConfig {
4569 #[serde(default)]
4571 pub enabled: bool,
4572 #[serde(default = "default_encoding_rate")]
4574 pub rate: f64,
4575 #[serde(default)]
4577 pub mojibake: bool,
4578 #[serde(default)]
4580 pub html_entities: bool,
4581 #[serde(default)]
4583 pub bom_issues: bool,
4584}
4585
4586fn default_encoding_rate() -> f64 {
4587 0.001
4588}
4589
4590impl Default for EncodingIssueSchemaConfig {
4591 fn default() -> Self {
4592 Self {
4593 enabled: false,
4594 rate: default_encoding_rate(),
4595 mojibake: false,
4596 html_entities: false,
4597 bom_issues: false,
4598 }
4599 }
4600}
4601
4602#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4604pub struct SinkQualityProfiles {
4605 #[serde(default)]
4607 pub csv: Option<SinkQualityOverride>,
4608 #[serde(default)]
4610 pub json: Option<SinkQualityOverride>,
4611 #[serde(default)]
4613 pub parquet: Option<SinkQualityOverride>,
4614}
4615
4616#[derive(Debug, Clone, Serialize, Deserialize)]
4618pub struct SinkQualityOverride {
4619 pub enabled: Option<bool>,
4621 pub missing_rate: Option<f64>,
4623 pub typo_rate: Option<f64>,
4625 pub format_variation_rate: Option<f64>,
4627 pub duplicate_rate: Option<f64>,
4629}
4630
4631#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4643pub struct AccountingStandardsConfig {
4644 #[serde(default)]
4646 pub enabled: bool,
4647
4648 #[serde(default)]
4650 pub framework: AccountingFrameworkConfig,
4651
4652 #[serde(default)]
4654 pub revenue_recognition: RevenueRecognitionConfig,
4655
4656 #[serde(default)]
4658 pub leases: LeaseAccountingConfig,
4659
4660 #[serde(default)]
4662 pub fair_value: FairValueConfig,
4663
4664 #[serde(default)]
4666 pub impairment: ImpairmentConfig,
4667
4668 #[serde(default)]
4670 pub generate_differences: bool,
4671}
4672
4673#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
4675#[serde(rename_all = "snake_case")]
4676pub enum AccountingFrameworkConfig {
4677 #[default]
4679 UsGaap,
4680 Ifrs,
4682 DualReporting,
4684}
4685
4686#[derive(Debug, Clone, Serialize, Deserialize)]
4688pub struct RevenueRecognitionConfig {
4689 #[serde(default)]
4691 pub enabled: bool,
4692
4693 #[serde(default = "default_true")]
4695 pub generate_contracts: bool,
4696
4697 #[serde(default = "default_avg_obligations")]
4699 pub avg_obligations_per_contract: f64,
4700
4701 #[serde(default = "default_variable_consideration_rate")]
4703 pub variable_consideration_rate: f64,
4704
4705 #[serde(default = "default_over_time_rate")]
4707 pub over_time_recognition_rate: f64,
4708
4709 #[serde(default = "default_contract_count")]
4711 pub contract_count: usize,
4712}
4713
4714fn default_avg_obligations() -> f64 {
4715 2.0
4716}
4717
4718fn default_variable_consideration_rate() -> f64 {
4719 0.15
4720}
4721
4722fn default_over_time_rate() -> f64 {
4723 0.30
4724}
4725
4726fn default_contract_count() -> usize {
4727 100
4728}
4729
4730impl Default for RevenueRecognitionConfig {
4731 fn default() -> Self {
4732 Self {
4733 enabled: false,
4734 generate_contracts: true,
4735 avg_obligations_per_contract: default_avg_obligations(),
4736 variable_consideration_rate: default_variable_consideration_rate(),
4737 over_time_recognition_rate: default_over_time_rate(),
4738 contract_count: default_contract_count(),
4739 }
4740 }
4741}
4742
4743#[derive(Debug, Clone, Serialize, Deserialize)]
4745pub struct LeaseAccountingConfig {
4746 #[serde(default)]
4748 pub enabled: bool,
4749
4750 #[serde(default = "default_lease_count")]
4752 pub lease_count: usize,
4753
4754 #[serde(default = "default_finance_lease_pct")]
4756 pub finance_lease_percent: f64,
4757
4758 #[serde(default = "default_avg_lease_term")]
4760 pub avg_lease_term_months: u32,
4761
4762 #[serde(default = "default_true")]
4764 pub generate_amortization: bool,
4765
4766 #[serde(default = "default_real_estate_pct")]
4768 pub real_estate_percent: f64,
4769}
4770
4771fn default_lease_count() -> usize {
4772 50
4773}
4774
4775fn default_finance_lease_pct() -> f64 {
4776 0.30
4777}
4778
4779fn default_avg_lease_term() -> u32 {
4780 60
4781}
4782
4783fn default_real_estate_pct() -> f64 {
4784 0.40
4785}
4786
4787impl Default for LeaseAccountingConfig {
4788 fn default() -> Self {
4789 Self {
4790 enabled: false,
4791 lease_count: default_lease_count(),
4792 finance_lease_percent: default_finance_lease_pct(),
4793 avg_lease_term_months: default_avg_lease_term(),
4794 generate_amortization: true,
4795 real_estate_percent: default_real_estate_pct(),
4796 }
4797 }
4798}
4799
4800#[derive(Debug, Clone, Serialize, Deserialize)]
4802pub struct FairValueConfig {
4803 #[serde(default)]
4805 pub enabled: bool,
4806
4807 #[serde(default = "default_fv_count")]
4809 pub measurement_count: usize,
4810
4811 #[serde(default = "default_level1_pct")]
4813 pub level1_percent: f64,
4814
4815 #[serde(default = "default_level2_pct")]
4817 pub level2_percent: f64,
4818
4819 #[serde(default = "default_level3_pct")]
4821 pub level3_percent: f64,
4822
4823 #[serde(default)]
4825 pub include_sensitivity_analysis: bool,
4826}
4827
4828fn default_fv_count() -> usize {
4829 25
4830}
4831
4832fn default_level1_pct() -> f64 {
4833 0.40
4834}
4835
4836fn default_level2_pct() -> f64 {
4837 0.35
4838}
4839
4840fn default_level3_pct() -> f64 {
4841 0.25
4842}
4843
4844impl Default for FairValueConfig {
4845 fn default() -> Self {
4846 Self {
4847 enabled: false,
4848 measurement_count: default_fv_count(),
4849 level1_percent: default_level1_pct(),
4850 level2_percent: default_level2_pct(),
4851 level3_percent: default_level3_pct(),
4852 include_sensitivity_analysis: false,
4853 }
4854 }
4855}
4856
4857#[derive(Debug, Clone, Serialize, Deserialize)]
4859pub struct ImpairmentConfig {
4860 #[serde(default)]
4862 pub enabled: bool,
4863
4864 #[serde(default = "default_impairment_count")]
4866 pub test_count: usize,
4867
4868 #[serde(default = "default_impairment_rate")]
4870 pub impairment_rate: f64,
4871
4872 #[serde(default = "default_true")]
4874 pub generate_projections: bool,
4875
4876 #[serde(default)]
4878 pub include_goodwill: bool,
4879}
4880
4881fn default_impairment_count() -> usize {
4882 15
4883}
4884
4885fn default_impairment_rate() -> f64 {
4886 0.10
4887}
4888
4889impl Default for ImpairmentConfig {
4890 fn default() -> Self {
4891 Self {
4892 enabled: false,
4893 test_count: default_impairment_count(),
4894 impairment_rate: default_impairment_rate(),
4895 generate_projections: true,
4896 include_goodwill: false,
4897 }
4898 }
4899}
4900
4901#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4914pub struct AuditStandardsConfig {
4915 #[serde(default)]
4917 pub enabled: bool,
4918
4919 #[serde(default)]
4921 pub isa_compliance: IsaComplianceConfig,
4922
4923 #[serde(default)]
4925 pub analytical_procedures: AnalyticalProceduresConfig,
4926
4927 #[serde(default)]
4929 pub confirmations: ConfirmationsConfig,
4930
4931 #[serde(default)]
4933 pub opinion: AuditOpinionConfig,
4934
4935 #[serde(default)]
4937 pub generate_audit_trail: bool,
4938
4939 #[serde(default)]
4941 pub sox: SoxComplianceConfig,
4942
4943 #[serde(default)]
4945 pub pcaob: PcaobConfig,
4946}
4947
4948#[derive(Debug, Clone, Serialize, Deserialize)]
4950pub struct IsaComplianceConfig {
4951 #[serde(default)]
4953 pub enabled: bool,
4954
4955 #[serde(default = "default_compliance_level")]
4957 pub compliance_level: String,
4958
4959 #[serde(default = "default_true")]
4961 pub generate_isa_mappings: bool,
4962
4963 #[serde(default = "default_true")]
4965 pub generate_coverage_summary: bool,
4966
4967 #[serde(default)]
4969 pub include_pcaob: bool,
4970
4971 #[serde(default = "default_audit_framework")]
4973 pub framework: String,
4974}
4975
4976fn default_compliance_level() -> String {
4977 "standard".to_string()
4978}
4979
4980fn default_audit_framework() -> String {
4981 "isa".to_string()
4982}
4983
4984impl Default for IsaComplianceConfig {
4985 fn default() -> Self {
4986 Self {
4987 enabled: false,
4988 compliance_level: default_compliance_level(),
4989 generate_isa_mappings: true,
4990 generate_coverage_summary: true,
4991 include_pcaob: false,
4992 framework: default_audit_framework(),
4993 }
4994 }
4995}
4996
4997#[derive(Debug, Clone, Serialize, Deserialize)]
4999pub struct AnalyticalProceduresConfig {
5000 #[serde(default)]
5002 pub enabled: bool,
5003
5004 #[serde(default = "default_procedures_per_account")]
5006 pub procedures_per_account: usize,
5007
5008 #[serde(default = "default_variance_probability")]
5010 pub variance_probability: f64,
5011
5012 #[serde(default = "default_true")]
5014 pub generate_investigations: bool,
5015
5016 #[serde(default = "default_true")]
5018 pub include_ratio_analysis: bool,
5019}
5020
5021fn default_procedures_per_account() -> usize {
5022 3
5023}
5024
5025fn default_variance_probability() -> f64 {
5026 0.20
5027}
5028
5029impl Default for AnalyticalProceduresConfig {
5030 fn default() -> Self {
5031 Self {
5032 enabled: false,
5033 procedures_per_account: default_procedures_per_account(),
5034 variance_probability: default_variance_probability(),
5035 generate_investigations: true,
5036 include_ratio_analysis: true,
5037 }
5038 }
5039}
5040
5041#[derive(Debug, Clone, Serialize, Deserialize)]
5043pub struct ConfirmationsConfig {
5044 #[serde(default)]
5046 pub enabled: bool,
5047
5048 #[serde(default = "default_confirmation_count")]
5050 pub confirmation_count: usize,
5051
5052 #[serde(default = "default_positive_response_rate")]
5054 pub positive_response_rate: f64,
5055
5056 #[serde(default = "default_exception_rate_confirm")]
5058 pub exception_rate: f64,
5059
5060 #[serde(default = "default_non_response_rate")]
5062 pub non_response_rate: f64,
5063
5064 #[serde(default = "default_true")]
5066 pub generate_alternative_procedures: bool,
5067}
5068
5069fn default_confirmation_count() -> usize {
5070 50
5071}
5072
5073fn default_positive_response_rate() -> f64 {
5074 0.85
5075}
5076
5077fn default_exception_rate_confirm() -> f64 {
5078 0.10
5079}
5080
5081fn default_non_response_rate() -> f64 {
5082 0.05
5083}
5084
5085impl Default for ConfirmationsConfig {
5086 fn default() -> Self {
5087 Self {
5088 enabled: false,
5089 confirmation_count: default_confirmation_count(),
5090 positive_response_rate: default_positive_response_rate(),
5091 exception_rate: default_exception_rate_confirm(),
5092 non_response_rate: default_non_response_rate(),
5093 generate_alternative_procedures: true,
5094 }
5095 }
5096}
5097
5098#[derive(Debug, Clone, Serialize, Deserialize)]
5100pub struct AuditOpinionConfig {
5101 #[serde(default)]
5103 pub enabled: bool,
5104
5105 #[serde(default = "default_true")]
5107 pub generate_kam: bool,
5108
5109 #[serde(default = "default_kam_count")]
5111 pub average_kam_count: usize,
5112
5113 #[serde(default = "default_modified_opinion_rate")]
5115 pub modified_opinion_rate: f64,
5116
5117 #[serde(default)]
5119 pub include_emphasis_of_matter: bool,
5120
5121 #[serde(default = "default_true")]
5123 pub include_going_concern: bool,
5124}
5125
5126fn default_kam_count() -> usize {
5127 3
5128}
5129
5130fn default_modified_opinion_rate() -> f64 {
5131 0.05
5132}
5133
5134impl Default for AuditOpinionConfig {
5135 fn default() -> Self {
5136 Self {
5137 enabled: false,
5138 generate_kam: true,
5139 average_kam_count: default_kam_count(),
5140 modified_opinion_rate: default_modified_opinion_rate(),
5141 include_emphasis_of_matter: false,
5142 include_going_concern: true,
5143 }
5144 }
5145}
5146
5147#[derive(Debug, Clone, Serialize, Deserialize)]
5149pub struct SoxComplianceConfig {
5150 #[serde(default)]
5152 pub enabled: bool,
5153
5154 #[serde(default = "default_true")]
5156 pub generate_302_certifications: bool,
5157
5158 #[serde(default = "default_true")]
5160 pub generate_404_assessments: bool,
5161
5162 #[serde(default = "default_sox_materiality_threshold")]
5164 pub materiality_threshold: f64,
5165
5166 #[serde(default = "default_material_weakness_rate")]
5168 pub material_weakness_rate: f64,
5169
5170 #[serde(default = "default_significant_deficiency_rate")]
5172 pub significant_deficiency_rate: f64,
5173}
5174
5175fn default_material_weakness_rate() -> f64 {
5176 0.02
5177}
5178
5179fn default_significant_deficiency_rate() -> f64 {
5180 0.08
5181}
5182
5183impl Default for SoxComplianceConfig {
5184 fn default() -> Self {
5185 Self {
5186 enabled: false,
5187 generate_302_certifications: true,
5188 generate_404_assessments: true,
5189 materiality_threshold: default_sox_materiality_threshold(),
5190 material_weakness_rate: default_material_weakness_rate(),
5191 significant_deficiency_rate: default_significant_deficiency_rate(),
5192 }
5193 }
5194}
5195
5196#[derive(Debug, Clone, Serialize, Deserialize)]
5198pub struct PcaobConfig {
5199 #[serde(default)]
5201 pub enabled: bool,
5202
5203 #[serde(default)]
5205 pub is_pcaob_audit: bool,
5206
5207 #[serde(default = "default_true")]
5209 pub generate_cam: bool,
5210
5211 #[serde(default)]
5213 pub include_icfr_opinion: bool,
5214
5215 #[serde(default)]
5217 pub generate_standard_mappings: bool,
5218}
5219
5220impl Default for PcaobConfig {
5221 fn default() -> Self {
5222 Self {
5223 enabled: false,
5224 is_pcaob_audit: false,
5225 generate_cam: true,
5226 include_icfr_opinion: false,
5227 generate_standard_mappings: false,
5228 }
5229 }
5230}
5231
5232#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5245pub struct AdvancedDistributionConfig {
5246 #[serde(default)]
5248 pub enabled: bool,
5249
5250 #[serde(default)]
5252 pub amounts: MixtureDistributionSchemaConfig,
5253
5254 #[serde(default)]
5256 pub correlations: CorrelationSchemaConfig,
5257
5258 #[serde(default)]
5260 pub conditional: Vec<ConditionalDistributionSchemaConfig>,
5261
5262 #[serde(default)]
5264 pub regime_changes: RegimeChangeSchemaConfig,
5265
5266 #[serde(default)]
5268 pub industry_profile: Option<IndustryProfileType>,
5269
5270 #[serde(default)]
5272 pub validation: StatisticalValidationSchemaConfig,
5273}
5274
5275#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
5277#[serde(rename_all = "snake_case")]
5278pub enum IndustryProfileType {
5279 Retail,
5281 Manufacturing,
5283 FinancialServices,
5285 Healthcare,
5287 Technology,
5289}
5290
5291#[derive(Debug, Clone, Serialize, Deserialize)]
5293pub struct MixtureDistributionSchemaConfig {
5294 #[serde(default)]
5296 pub enabled: bool,
5297
5298 #[serde(default = "default_mixture_type")]
5300 pub distribution_type: MixtureDistributionType,
5301
5302 #[serde(default)]
5304 pub components: Vec<MixtureComponentConfig>,
5305
5306 #[serde(default = "default_min_amount")]
5308 pub min_value: f64,
5309
5310 #[serde(default)]
5312 pub max_value: Option<f64>,
5313
5314 #[serde(default = "default_decimal_places")]
5316 pub decimal_places: u8,
5317}
5318
5319fn default_mixture_type() -> MixtureDistributionType {
5320 MixtureDistributionType::LogNormal
5321}
5322
5323fn default_min_amount() -> f64 {
5324 0.01
5325}
5326
5327fn default_decimal_places() -> u8 {
5328 2
5329}
5330
5331impl Default for MixtureDistributionSchemaConfig {
5332 fn default() -> Self {
5333 Self {
5334 enabled: false,
5335 distribution_type: MixtureDistributionType::LogNormal,
5336 components: Vec::new(),
5337 min_value: 0.01,
5338 max_value: None,
5339 decimal_places: 2,
5340 }
5341 }
5342}
5343
5344#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5346#[serde(rename_all = "snake_case")]
5347pub enum MixtureDistributionType {
5348 Gaussian,
5350 #[default]
5352 LogNormal,
5353}
5354
5355#[derive(Debug, Clone, Serialize, Deserialize)]
5357pub struct MixtureComponentConfig {
5358 pub weight: f64,
5360
5361 pub mu: f64,
5363
5364 pub sigma: f64,
5366
5367 #[serde(default)]
5369 pub label: Option<String>,
5370}
5371
5372#[derive(Debug, Clone, Serialize, Deserialize)]
5374pub struct CorrelationSchemaConfig {
5375 #[serde(default)]
5377 pub enabled: bool,
5378
5379 #[serde(default)]
5381 pub copula_type: CopulaSchemaType,
5382
5383 #[serde(default)]
5385 pub fields: Vec<CorrelatedFieldConfig>,
5386
5387 #[serde(default)]
5390 pub matrix: Vec<f64>,
5391
5392 #[serde(default)]
5394 pub expected_correlations: Vec<ExpectedCorrelationConfig>,
5395}
5396
5397impl Default for CorrelationSchemaConfig {
5398 fn default() -> Self {
5399 Self {
5400 enabled: false,
5401 copula_type: CopulaSchemaType::Gaussian,
5402 fields: Vec::new(),
5403 matrix: Vec::new(),
5404 expected_correlations: Vec::new(),
5405 }
5406 }
5407}
5408
5409#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5411#[serde(rename_all = "snake_case")]
5412pub enum CopulaSchemaType {
5413 #[default]
5415 Gaussian,
5416 Clayton,
5418 Gumbel,
5420 Frank,
5422 StudentT,
5424}
5425
5426#[derive(Debug, Clone, Serialize, Deserialize)]
5428pub struct CorrelatedFieldConfig {
5429 pub name: String,
5431
5432 #[serde(default)]
5434 pub distribution: MarginalDistributionConfig,
5435}
5436
5437#[derive(Debug, Clone, Serialize, Deserialize)]
5439#[serde(tag = "type", rename_all = "snake_case")]
5440pub enum MarginalDistributionConfig {
5441 Normal {
5443 mu: f64,
5445 sigma: f64,
5447 },
5448 LogNormal {
5450 mu: f64,
5452 sigma: f64,
5454 },
5455 Uniform {
5457 min: f64,
5459 max: f64,
5461 },
5462 DiscreteUniform {
5464 min: i32,
5466 max: i32,
5468 },
5469}
5470
5471impl Default for MarginalDistributionConfig {
5472 fn default() -> Self {
5473 Self::Normal {
5474 mu: 0.0,
5475 sigma: 1.0,
5476 }
5477 }
5478}
5479
5480#[derive(Debug, Clone, Serialize, Deserialize)]
5482pub struct ExpectedCorrelationConfig {
5483 pub field1: String,
5485 pub field2: String,
5487 pub expected_r: f64,
5489 #[serde(default = "default_correlation_tolerance")]
5491 pub tolerance: f64,
5492}
5493
5494fn default_correlation_tolerance() -> f64 {
5495 0.10
5496}
5497
5498#[derive(Debug, Clone, Serialize, Deserialize)]
5500pub struct ConditionalDistributionSchemaConfig {
5501 pub output_field: String,
5503
5504 pub input_field: String,
5506
5507 #[serde(default)]
5509 pub breakpoints: Vec<ConditionalBreakpointConfig>,
5510
5511 #[serde(default)]
5513 pub default_distribution: ConditionalDistributionParamsConfig,
5514
5515 #[serde(default)]
5517 pub min_value: Option<f64>,
5518
5519 #[serde(default)]
5521 pub max_value: Option<f64>,
5522
5523 #[serde(default = "default_decimal_places")]
5525 pub decimal_places: u8,
5526}
5527
5528#[derive(Debug, Clone, Serialize, Deserialize)]
5530pub struct ConditionalBreakpointConfig {
5531 pub threshold: f64,
5533
5534 pub distribution: ConditionalDistributionParamsConfig,
5536}
5537
5538#[derive(Debug, Clone, Serialize, Deserialize)]
5540#[serde(tag = "type", rename_all = "snake_case")]
5541pub enum ConditionalDistributionParamsConfig {
5542 Fixed {
5544 value: f64,
5546 },
5547 Normal {
5549 mu: f64,
5551 sigma: f64,
5553 },
5554 LogNormal {
5556 mu: f64,
5558 sigma: f64,
5560 },
5561 Uniform {
5563 min: f64,
5565 max: f64,
5567 },
5568 Beta {
5570 alpha: f64,
5572 beta: f64,
5574 min: f64,
5576 max: f64,
5578 },
5579 Discrete {
5581 values: Vec<f64>,
5583 weights: Vec<f64>,
5585 },
5586}
5587
5588impl Default for ConditionalDistributionParamsConfig {
5589 fn default() -> Self {
5590 Self::Normal {
5591 mu: 0.0,
5592 sigma: 1.0,
5593 }
5594 }
5595}
5596
5597#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5599pub struct RegimeChangeSchemaConfig {
5600 #[serde(default)]
5602 pub enabled: bool,
5603
5604 #[serde(default)]
5606 pub changes: Vec<RegimeChangeEventConfig>,
5607
5608 #[serde(default)]
5610 pub economic_cycle: Option<EconomicCycleSchemaConfig>,
5611
5612 #[serde(default)]
5614 pub parameter_drifts: Vec<ParameterDriftSchemaConfig>,
5615}
5616
5617#[derive(Debug, Clone, Serialize, Deserialize)]
5619pub struct RegimeChangeEventConfig {
5620 pub date: String,
5622
5623 pub change_type: RegimeChangeTypeConfig,
5625
5626 #[serde(default)]
5628 pub description: Option<String>,
5629
5630 #[serde(default)]
5632 pub effects: Vec<RegimeEffectConfig>,
5633}
5634
5635#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
5637#[serde(rename_all = "snake_case")]
5638pub enum RegimeChangeTypeConfig {
5639 Acquisition,
5641 Divestiture,
5643 PriceIncrease,
5645 PriceDecrease,
5647 ProductLaunch,
5649 ProductDiscontinuation,
5651 PolicyChange,
5653 CompetitorEntry,
5655 Custom,
5657}
5658
5659#[derive(Debug, Clone, Serialize, Deserialize)]
5661pub struct RegimeEffectConfig {
5662 pub field: String,
5664
5665 pub multiplier: f64,
5667}
5668
5669#[derive(Debug, Clone, Serialize, Deserialize)]
5671pub struct EconomicCycleSchemaConfig {
5672 #[serde(default)]
5674 pub enabled: bool,
5675
5676 #[serde(default = "default_cycle_period")]
5678 pub period_months: u32,
5679
5680 #[serde(default = "default_cycle_amplitude")]
5682 pub amplitude: f64,
5683
5684 #[serde(default)]
5686 pub phase_offset: u32,
5687
5688 #[serde(default)]
5690 pub recessions: Vec<RecessionPeriodConfig>,
5691}
5692
5693fn default_cycle_period() -> u32 {
5694 48
5695}
5696
5697fn default_cycle_amplitude() -> f64 {
5698 0.15
5699}
5700
5701impl Default for EconomicCycleSchemaConfig {
5702 fn default() -> Self {
5703 Self {
5704 enabled: false,
5705 period_months: 48,
5706 amplitude: 0.15,
5707 phase_offset: 0,
5708 recessions: Vec::new(),
5709 }
5710 }
5711}
5712
5713#[derive(Debug, Clone, Serialize, Deserialize)]
5715pub struct RecessionPeriodConfig {
5716 pub start_month: u32,
5718
5719 pub duration_months: u32,
5721
5722 #[serde(default = "default_recession_severity")]
5724 pub severity: f64,
5725}
5726
5727fn default_recession_severity() -> f64 {
5728 0.20
5729}
5730
5731#[derive(Debug, Clone, Serialize, Deserialize)]
5733pub struct ParameterDriftSchemaConfig {
5734 pub parameter: String,
5736
5737 pub drift_type: ParameterDriftTypeConfig,
5739
5740 pub start_value: f64,
5742
5743 pub end_value: f64,
5745
5746 #[serde(default)]
5748 pub start_period: u32,
5749
5750 #[serde(default)]
5752 pub end_period: Option<u32>,
5753}
5754
5755#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5757#[serde(rename_all = "snake_case")]
5758pub enum ParameterDriftTypeConfig {
5759 #[default]
5761 Linear,
5762 Exponential,
5764 Logistic,
5766 Step,
5768}
5769
5770#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5772pub struct StatisticalValidationSchemaConfig {
5773 #[serde(default)]
5775 pub enabled: bool,
5776
5777 #[serde(default)]
5779 pub tests: Vec<StatisticalTestConfig>,
5780
5781 #[serde(default)]
5783 pub reporting: ValidationReportingConfig,
5784}
5785
5786#[derive(Debug, Clone, Serialize, Deserialize)]
5788#[serde(tag = "type", rename_all = "snake_case")]
5789pub enum StatisticalTestConfig {
5790 BenfordFirstDigit {
5792 #[serde(default = "default_benford_threshold")]
5794 threshold_mad: f64,
5795 #[serde(default = "default_benford_warning")]
5797 warning_mad: f64,
5798 },
5799 DistributionFit {
5801 target: TargetDistributionConfig,
5803 #[serde(default = "default_ks_significance")]
5805 ks_significance: f64,
5806 #[serde(default)]
5808 method: DistributionFitMethod,
5809 },
5810 CorrelationCheck {
5812 expected_correlations: Vec<ExpectedCorrelationConfig>,
5814 },
5815 ChiSquared {
5817 #[serde(default = "default_chi_squared_bins")]
5819 bins: usize,
5820 #[serde(default = "default_chi_squared_significance")]
5822 significance: f64,
5823 },
5824 AndersonDarling {
5826 target: TargetDistributionConfig,
5828 #[serde(default = "default_ad_significance")]
5830 significance: f64,
5831 },
5832}
5833
5834fn default_benford_threshold() -> f64 {
5835 0.015
5836}
5837
5838fn default_benford_warning() -> f64 {
5839 0.010
5840}
5841
5842fn default_ks_significance() -> f64 {
5843 0.05
5844}
5845
5846fn default_chi_squared_bins() -> usize {
5847 10
5848}
5849
5850fn default_chi_squared_significance() -> f64 {
5851 0.05
5852}
5853
5854fn default_ad_significance() -> f64 {
5855 0.05
5856}
5857
5858#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5860#[serde(rename_all = "snake_case")]
5861pub enum TargetDistributionConfig {
5862 Normal,
5864 #[default]
5866 LogNormal,
5867 Exponential,
5869 Uniform,
5871}
5872
5873#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5875#[serde(rename_all = "snake_case")]
5876pub enum DistributionFitMethod {
5877 #[default]
5879 KolmogorovSmirnov,
5880 AndersonDarling,
5882 ChiSquared,
5884}
5885
5886#[derive(Debug, Clone, Serialize, Deserialize)]
5888pub struct ValidationReportingConfig {
5889 #[serde(default)]
5891 pub output_report: bool,
5892
5893 #[serde(default)]
5895 pub format: ValidationReportFormat,
5896
5897 #[serde(default)]
5899 pub fail_on_error: bool,
5900
5901 #[serde(default = "default_true")]
5903 pub include_details: bool,
5904}
5905
5906impl Default for ValidationReportingConfig {
5907 fn default() -> Self {
5908 Self {
5909 output_report: false,
5910 format: ValidationReportFormat::Json,
5911 fail_on_error: false,
5912 include_details: true,
5913 }
5914 }
5915}
5916
5917#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5919#[serde(rename_all = "snake_case")]
5920pub enum ValidationReportFormat {
5921 #[default]
5923 Json,
5924 Yaml,
5926 Html,
5928}
5929
5930#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5942pub struct TemporalPatternsConfig {
5943 #[serde(default)]
5945 pub enabled: bool,
5946
5947 #[serde(default)]
5949 pub business_days: BusinessDaySchemaConfig,
5950
5951 #[serde(default)]
5953 pub calendars: CalendarSchemaConfig,
5954
5955 #[serde(default)]
5957 pub period_end: PeriodEndSchemaConfig,
5958
5959 #[serde(default)]
5961 pub processing_lags: ProcessingLagSchemaConfig,
5962
5963 #[serde(default)]
5965 pub fiscal_calendar: FiscalCalendarSchemaConfig,
5966
5967 #[serde(default)]
5969 pub intraday: IntraDaySchemaConfig,
5970
5971 #[serde(default)]
5973 pub timezones: TimezoneSchemaConfig,
5974}
5975
5976#[derive(Debug, Clone, Serialize, Deserialize)]
5978pub struct BusinessDaySchemaConfig {
5979 #[serde(default = "default_true")]
5981 pub enabled: bool,
5982
5983 #[serde(default = "default_half_day_policy")]
5985 pub half_day_policy: String,
5986
5987 #[serde(default)]
5989 pub settlement_rules: SettlementRulesSchemaConfig,
5990
5991 #[serde(default = "default_month_end_convention")]
5993 pub month_end_convention: String,
5994
5995 #[serde(default)]
5997 pub weekend_days: Option<Vec<String>>,
5998}
5999
6000fn default_half_day_policy() -> String {
6001 "half_day".to_string()
6002}
6003
6004fn default_month_end_convention() -> String {
6005 "modified_following".to_string()
6006}
6007
6008impl Default for BusinessDaySchemaConfig {
6009 fn default() -> Self {
6010 Self {
6011 enabled: true,
6012 half_day_policy: "half_day".to_string(),
6013 settlement_rules: SettlementRulesSchemaConfig::default(),
6014 month_end_convention: "modified_following".to_string(),
6015 weekend_days: None,
6016 }
6017 }
6018}
6019
6020#[derive(Debug, Clone, Serialize, Deserialize)]
6022pub struct SettlementRulesSchemaConfig {
6023 #[serde(default = "default_settlement_2")]
6025 pub equity_days: i32,
6026
6027 #[serde(default = "default_settlement_1")]
6029 pub government_bonds_days: i32,
6030
6031 #[serde(default = "default_settlement_2")]
6033 pub fx_spot_days: i32,
6034
6035 #[serde(default = "default_settlement_2")]
6037 pub corporate_bonds_days: i32,
6038
6039 #[serde(default = "default_wire_cutoff")]
6041 pub wire_cutoff_time: String,
6042
6043 #[serde(default = "default_settlement_1")]
6045 pub wire_international_days: i32,
6046
6047 #[serde(default = "default_settlement_1")]
6049 pub ach_days: i32,
6050}
6051
6052fn default_settlement_1() -> i32 {
6053 1
6054}
6055
6056fn default_settlement_2() -> i32 {
6057 2
6058}
6059
6060fn default_wire_cutoff() -> String {
6061 "14:00".to_string()
6062}
6063
6064impl Default for SettlementRulesSchemaConfig {
6065 fn default() -> Self {
6066 Self {
6067 equity_days: 2,
6068 government_bonds_days: 1,
6069 fx_spot_days: 2,
6070 corporate_bonds_days: 2,
6071 wire_cutoff_time: "14:00".to_string(),
6072 wire_international_days: 1,
6073 ach_days: 1,
6074 }
6075 }
6076}
6077
6078#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6080pub struct CalendarSchemaConfig {
6081 #[serde(default)]
6083 pub regions: Vec<String>,
6084
6085 #[serde(default)]
6087 pub custom_holidays: Vec<CustomHolidaySchemaConfig>,
6088}
6089
6090#[derive(Debug, Clone, Serialize, Deserialize)]
6092pub struct CustomHolidaySchemaConfig {
6093 pub name: String,
6095 pub month: u8,
6097 pub day: u8,
6099 #[serde(default = "default_holiday_multiplier")]
6101 pub activity_multiplier: f64,
6102}
6103
6104fn default_holiday_multiplier() -> f64 {
6105 0.05
6106}
6107
6108#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6110pub struct PeriodEndSchemaConfig {
6111 #[serde(default)]
6113 pub model: Option<String>,
6114
6115 #[serde(default)]
6117 pub month_end: Option<PeriodEndModelSchemaConfig>,
6118
6119 #[serde(default)]
6121 pub quarter_end: Option<PeriodEndModelSchemaConfig>,
6122
6123 #[serde(default)]
6125 pub year_end: Option<PeriodEndModelSchemaConfig>,
6126}
6127
6128#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6130pub struct PeriodEndModelSchemaConfig {
6131 #[serde(default)]
6133 pub inherit_from: Option<String>,
6134
6135 #[serde(default)]
6137 pub additional_multiplier: Option<f64>,
6138
6139 #[serde(default)]
6141 pub start_day: Option<i32>,
6142
6143 #[serde(default)]
6145 pub base_multiplier: Option<f64>,
6146
6147 #[serde(default)]
6149 pub peak_multiplier: Option<f64>,
6150
6151 #[serde(default)]
6153 pub decay_rate: Option<f64>,
6154
6155 #[serde(default)]
6157 pub sustained_high_days: Option<i32>,
6158}
6159
6160#[derive(Debug, Clone, Serialize, Deserialize)]
6162pub struct ProcessingLagSchemaConfig {
6163 #[serde(default = "default_true")]
6165 pub enabled: bool,
6166
6167 #[serde(default)]
6169 pub sales_order_lag: Option<LagDistributionSchemaConfig>,
6170
6171 #[serde(default)]
6173 pub purchase_order_lag: Option<LagDistributionSchemaConfig>,
6174
6175 #[serde(default)]
6177 pub goods_receipt_lag: Option<LagDistributionSchemaConfig>,
6178
6179 #[serde(default)]
6181 pub invoice_receipt_lag: Option<LagDistributionSchemaConfig>,
6182
6183 #[serde(default)]
6185 pub invoice_issue_lag: Option<LagDistributionSchemaConfig>,
6186
6187 #[serde(default)]
6189 pub payment_lag: Option<LagDistributionSchemaConfig>,
6190
6191 #[serde(default)]
6193 pub journal_entry_lag: Option<LagDistributionSchemaConfig>,
6194
6195 #[serde(default)]
6197 pub cross_day_posting: Option<CrossDayPostingSchemaConfig>,
6198}
6199
6200impl Default for ProcessingLagSchemaConfig {
6201 fn default() -> Self {
6202 Self {
6203 enabled: true,
6204 sales_order_lag: None,
6205 purchase_order_lag: None,
6206 goods_receipt_lag: None,
6207 invoice_receipt_lag: None,
6208 invoice_issue_lag: None,
6209 payment_lag: None,
6210 journal_entry_lag: None,
6211 cross_day_posting: None,
6212 }
6213 }
6214}
6215
6216#[derive(Debug, Clone, Serialize, Deserialize)]
6218pub struct LagDistributionSchemaConfig {
6219 pub mu: f64,
6221 pub sigma: f64,
6223 #[serde(default)]
6225 pub min_hours: Option<f64>,
6226 #[serde(default)]
6228 pub max_hours: Option<f64>,
6229}
6230
6231#[derive(Debug, Clone, Serialize, Deserialize)]
6233pub struct CrossDayPostingSchemaConfig {
6234 #[serde(default = "default_true")]
6236 pub enabled: bool,
6237
6238 #[serde(default)]
6241 pub probability_by_hour: std::collections::HashMap<u8, f64>,
6242}
6243
6244impl Default for CrossDayPostingSchemaConfig {
6245 fn default() -> Self {
6246 let mut probability_by_hour = std::collections::HashMap::new();
6247 probability_by_hour.insert(17, 0.3);
6248 probability_by_hour.insert(18, 0.6);
6249 probability_by_hour.insert(19, 0.8);
6250 probability_by_hour.insert(20, 0.9);
6251 probability_by_hour.insert(21, 0.95);
6252 probability_by_hour.insert(22, 0.99);
6253
6254 Self {
6255 enabled: true,
6256 probability_by_hour,
6257 }
6258 }
6259}
6260
6261#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6270pub struct FiscalCalendarSchemaConfig {
6271 #[serde(default)]
6273 pub enabled: bool,
6274
6275 #[serde(default = "default_fiscal_calendar_type")]
6277 pub calendar_type: String,
6278
6279 #[serde(default)]
6281 pub year_start_month: Option<u8>,
6282
6283 #[serde(default)]
6285 pub year_start_day: Option<u8>,
6286
6287 #[serde(default)]
6289 pub four_four_five: Option<FourFourFiveSchemaConfig>,
6290}
6291
6292fn default_fiscal_calendar_type() -> String {
6293 "calendar_year".to_string()
6294}
6295
6296#[derive(Debug, Clone, Serialize, Deserialize)]
6298pub struct FourFourFiveSchemaConfig {
6299 #[serde(default = "default_week_pattern")]
6301 pub pattern: String,
6302
6303 #[serde(default = "default_anchor_type")]
6305 pub anchor_type: String,
6306
6307 #[serde(default = "default_anchor_month")]
6309 pub anchor_month: u8,
6310
6311 #[serde(default = "default_leap_week_placement")]
6313 pub leap_week_placement: String,
6314}
6315
6316fn default_week_pattern() -> String {
6317 "four_four_five".to_string()
6318}
6319
6320fn default_anchor_type() -> String {
6321 "last_saturday".to_string()
6322}
6323
6324fn default_anchor_month() -> u8 {
6325 1 }
6327
6328fn default_leap_week_placement() -> String {
6329 "q4_period3".to_string()
6330}
6331
6332impl Default for FourFourFiveSchemaConfig {
6333 fn default() -> Self {
6334 Self {
6335 pattern: "four_four_five".to_string(),
6336 anchor_type: "last_saturday".to_string(),
6337 anchor_month: 1,
6338 leap_week_placement: "q4_period3".to_string(),
6339 }
6340 }
6341}
6342
6343#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6352pub struct IntraDaySchemaConfig {
6353 #[serde(default)]
6355 pub enabled: bool,
6356
6357 #[serde(default)]
6359 pub segments: Vec<IntraDaySegmentSchemaConfig>,
6360}
6361
6362#[derive(Debug, Clone, Serialize, Deserialize)]
6364pub struct IntraDaySegmentSchemaConfig {
6365 pub name: String,
6367
6368 pub start: String,
6370
6371 pub end: String,
6373
6374 #[serde(default = "default_multiplier")]
6376 pub multiplier: f64,
6377
6378 #[serde(default = "default_posting_type")]
6380 pub posting_type: String,
6381}
6382
6383fn default_multiplier() -> f64 {
6384 1.0
6385}
6386
6387fn default_posting_type() -> String {
6388 "both".to_string()
6389}
6390
6391#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6397pub struct TimezoneSchemaConfig {
6398 #[serde(default)]
6400 pub enabled: bool,
6401
6402 #[serde(default = "default_timezone")]
6404 pub default_timezone: String,
6405
6406 #[serde(default = "default_consolidation_timezone")]
6408 pub consolidation_timezone: String,
6409
6410 #[serde(default)]
6413 pub entity_mappings: Vec<EntityTimezoneMapping>,
6414}
6415
6416fn default_timezone() -> String {
6417 "America/New_York".to_string()
6418}
6419
6420fn default_consolidation_timezone() -> String {
6421 "UTC".to_string()
6422}
6423
6424#[derive(Debug, Clone, Serialize, Deserialize)]
6426pub struct EntityTimezoneMapping {
6427 pub pattern: String,
6429
6430 pub timezone: String,
6432}
6433
6434#[derive(Debug, Clone, Serialize, Deserialize)]
6440pub struct VendorNetworkSchemaConfig {
6441 #[serde(default)]
6443 pub enabled: bool,
6444
6445 #[serde(default = "default_vendor_tier_depth")]
6447 pub depth: u8,
6448
6449 #[serde(default)]
6451 pub tier1: TierCountSchemaConfig,
6452
6453 #[serde(default)]
6455 pub tier2_per_parent: TierCountSchemaConfig,
6456
6457 #[serde(default)]
6459 pub tier3_per_parent: TierCountSchemaConfig,
6460
6461 #[serde(default)]
6463 pub clusters: VendorClusterSchemaConfig,
6464
6465 #[serde(default)]
6467 pub dependencies: DependencySchemaConfig,
6468}
6469
6470fn default_vendor_tier_depth() -> u8 {
6471 3
6472}
6473
6474impl Default for VendorNetworkSchemaConfig {
6475 fn default() -> Self {
6476 Self {
6477 enabled: false,
6478 depth: 3,
6479 tier1: TierCountSchemaConfig { min: 50, max: 100 },
6480 tier2_per_parent: TierCountSchemaConfig { min: 4, max: 10 },
6481 tier3_per_parent: TierCountSchemaConfig { min: 2, max: 5 },
6482 clusters: VendorClusterSchemaConfig::default(),
6483 dependencies: DependencySchemaConfig::default(),
6484 }
6485 }
6486}
6487
6488#[derive(Debug, Clone, Serialize, Deserialize)]
6490pub struct TierCountSchemaConfig {
6491 #[serde(default = "default_tier_min")]
6493 pub min: usize,
6494
6495 #[serde(default = "default_tier_max")]
6497 pub max: usize,
6498}
6499
6500fn default_tier_min() -> usize {
6501 5
6502}
6503
6504fn default_tier_max() -> usize {
6505 20
6506}
6507
6508impl Default for TierCountSchemaConfig {
6509 fn default() -> Self {
6510 Self {
6511 min: default_tier_min(),
6512 max: default_tier_max(),
6513 }
6514 }
6515}
6516
6517#[derive(Debug, Clone, Serialize, Deserialize)]
6519pub struct VendorClusterSchemaConfig {
6520 #[serde(default = "default_reliable_strategic")]
6522 pub reliable_strategic: f64,
6523
6524 #[serde(default = "default_standard_operational")]
6526 pub standard_operational: f64,
6527
6528 #[serde(default = "default_transactional")]
6530 pub transactional: f64,
6531
6532 #[serde(default = "default_problematic")]
6534 pub problematic: f64,
6535}
6536
6537fn default_reliable_strategic() -> f64 {
6538 0.20
6539}
6540
6541fn default_standard_operational() -> f64 {
6542 0.50
6543}
6544
6545fn default_transactional() -> f64 {
6546 0.25
6547}
6548
6549fn default_problematic() -> f64 {
6550 0.05
6551}
6552
6553impl Default for VendorClusterSchemaConfig {
6554 fn default() -> Self {
6555 Self {
6556 reliable_strategic: 0.20,
6557 standard_operational: 0.50,
6558 transactional: 0.25,
6559 problematic: 0.05,
6560 }
6561 }
6562}
6563
6564#[derive(Debug, Clone, Serialize, Deserialize)]
6566pub struct DependencySchemaConfig {
6567 #[serde(default = "default_max_single_vendor")]
6569 pub max_single_vendor_concentration: f64,
6570
6571 #[serde(default = "default_max_top5")]
6573 pub top_5_concentration: f64,
6574
6575 #[serde(default = "default_single_source_percent")]
6577 pub single_source_percent: f64,
6578}
6579
6580fn default_max_single_vendor() -> f64 {
6581 0.15
6582}
6583
6584fn default_max_top5() -> f64 {
6585 0.45
6586}
6587
6588fn default_single_source_percent() -> f64 {
6589 0.05
6590}
6591
6592impl Default for DependencySchemaConfig {
6593 fn default() -> Self {
6594 Self {
6595 max_single_vendor_concentration: 0.15,
6596 top_5_concentration: 0.45,
6597 single_source_percent: 0.05,
6598 }
6599 }
6600}
6601
6602#[derive(Debug, Clone, Default, Serialize, Deserialize)]
6608pub struct CustomerSegmentationSchemaConfig {
6609 #[serde(default)]
6611 pub enabled: bool,
6612
6613 #[serde(default)]
6615 pub value_segments: ValueSegmentsSchemaConfig,
6616
6617 #[serde(default)]
6619 pub lifecycle: LifecycleSchemaConfig,
6620
6621 #[serde(default)]
6623 pub networks: CustomerNetworksSchemaConfig,
6624}
6625
6626#[derive(Debug, Clone, Serialize, Deserialize)]
6628pub struct ValueSegmentsSchemaConfig {
6629 #[serde(default)]
6631 pub enterprise: SegmentDetailSchemaConfig,
6632
6633 #[serde(default)]
6635 pub mid_market: SegmentDetailSchemaConfig,
6636
6637 #[serde(default)]
6639 pub smb: SegmentDetailSchemaConfig,
6640
6641 #[serde(default)]
6643 pub consumer: SegmentDetailSchemaConfig,
6644}
6645
6646impl Default for ValueSegmentsSchemaConfig {
6647 fn default() -> Self {
6648 Self {
6649 enterprise: SegmentDetailSchemaConfig {
6650 revenue_share: 0.40,
6651 customer_share: 0.05,
6652 avg_order_value_range: "50000+".to_string(),
6653 },
6654 mid_market: SegmentDetailSchemaConfig {
6655 revenue_share: 0.35,
6656 customer_share: 0.20,
6657 avg_order_value_range: "5000-50000".to_string(),
6658 },
6659 smb: SegmentDetailSchemaConfig {
6660 revenue_share: 0.20,
6661 customer_share: 0.50,
6662 avg_order_value_range: "500-5000".to_string(),
6663 },
6664 consumer: SegmentDetailSchemaConfig {
6665 revenue_share: 0.05,
6666 customer_share: 0.25,
6667 avg_order_value_range: "50-500".to_string(),
6668 },
6669 }
6670 }
6671}
6672
6673#[derive(Debug, Clone, Serialize, Deserialize)]
6675pub struct SegmentDetailSchemaConfig {
6676 #[serde(default)]
6678 pub revenue_share: f64,
6679
6680 #[serde(default)]
6682 pub customer_share: f64,
6683
6684 #[serde(default)]
6686 pub avg_order_value_range: String,
6687}
6688
6689impl Default for SegmentDetailSchemaConfig {
6690 fn default() -> Self {
6691 Self {
6692 revenue_share: 0.25,
6693 customer_share: 0.25,
6694 avg_order_value_range: "1000-10000".to_string(),
6695 }
6696 }
6697}
6698
6699#[derive(Debug, Clone, Serialize, Deserialize)]
6701pub struct LifecycleSchemaConfig {
6702 #[serde(default)]
6704 pub prospect_rate: f64,
6705
6706 #[serde(default = "default_new_rate")]
6708 pub new_rate: f64,
6709
6710 #[serde(default = "default_growth_rate")]
6712 pub growth_rate: f64,
6713
6714 #[serde(default = "default_mature_rate")]
6716 pub mature_rate: f64,
6717
6718 #[serde(default = "default_at_risk_rate")]
6720 pub at_risk_rate: f64,
6721
6722 #[serde(default = "default_churned_rate")]
6724 pub churned_rate: f64,
6725}
6726
6727fn default_new_rate() -> f64 {
6728 0.10
6729}
6730
6731fn default_growth_rate() -> f64 {
6732 0.15
6733}
6734
6735fn default_mature_rate() -> f64 {
6736 0.60
6737}
6738
6739fn default_at_risk_rate() -> f64 {
6740 0.10
6741}
6742
6743fn default_churned_rate() -> f64 {
6744 0.05
6745}
6746
6747impl Default for LifecycleSchemaConfig {
6748 fn default() -> Self {
6749 Self {
6750 prospect_rate: 0.0,
6751 new_rate: 0.10,
6752 growth_rate: 0.15,
6753 mature_rate: 0.60,
6754 at_risk_rate: 0.10,
6755 churned_rate: 0.05,
6756 }
6757 }
6758}
6759
6760#[derive(Debug, Clone, Default, Serialize, Deserialize)]
6762pub struct CustomerNetworksSchemaConfig {
6763 #[serde(default)]
6765 pub referrals: ReferralSchemaConfig,
6766
6767 #[serde(default)]
6769 pub corporate_hierarchies: HierarchySchemaConfig,
6770}
6771
6772#[derive(Debug, Clone, Serialize, Deserialize)]
6774pub struct ReferralSchemaConfig {
6775 #[serde(default = "default_true")]
6777 pub enabled: bool,
6778
6779 #[serde(default = "default_referral_rate")]
6781 pub referral_rate: f64,
6782}
6783
6784fn default_referral_rate() -> f64 {
6785 0.15
6786}
6787
6788impl Default for ReferralSchemaConfig {
6789 fn default() -> Self {
6790 Self {
6791 enabled: true,
6792 referral_rate: 0.15,
6793 }
6794 }
6795}
6796
6797#[derive(Debug, Clone, Serialize, Deserialize)]
6799pub struct HierarchySchemaConfig {
6800 #[serde(default = "default_true")]
6802 pub enabled: bool,
6803
6804 #[serde(default = "default_hierarchy_rate")]
6806 pub probability: f64,
6807}
6808
6809fn default_hierarchy_rate() -> f64 {
6810 0.30
6811}
6812
6813impl Default for HierarchySchemaConfig {
6814 fn default() -> Self {
6815 Self {
6816 enabled: true,
6817 probability: 0.30,
6818 }
6819 }
6820}
6821
6822#[derive(Debug, Clone, Default, Serialize, Deserialize)]
6828pub struct RelationshipStrengthSchemaConfig {
6829 #[serde(default)]
6831 pub enabled: bool,
6832
6833 #[serde(default)]
6835 pub calculation: StrengthCalculationSchemaConfig,
6836
6837 #[serde(default)]
6839 pub thresholds: StrengthThresholdsSchemaConfig,
6840}
6841
6842#[derive(Debug, Clone, Serialize, Deserialize)]
6844pub struct StrengthCalculationSchemaConfig {
6845 #[serde(default = "default_volume_weight")]
6847 pub transaction_volume_weight: f64,
6848
6849 #[serde(default = "default_count_weight")]
6851 pub transaction_count_weight: f64,
6852
6853 #[serde(default = "default_duration_weight")]
6855 pub relationship_duration_weight: f64,
6856
6857 #[serde(default = "default_recency_weight")]
6859 pub recency_weight: f64,
6860
6861 #[serde(default = "default_mutual_weight")]
6863 pub mutual_connections_weight: f64,
6864
6865 #[serde(default = "default_recency_half_life")]
6867 pub recency_half_life_days: u32,
6868}
6869
6870fn default_volume_weight() -> f64 {
6871 0.30
6872}
6873
6874fn default_count_weight() -> f64 {
6875 0.25
6876}
6877
6878fn default_duration_weight() -> f64 {
6879 0.20
6880}
6881
6882fn default_recency_weight() -> f64 {
6883 0.15
6884}
6885
6886fn default_mutual_weight() -> f64 {
6887 0.10
6888}
6889
6890fn default_recency_half_life() -> u32 {
6891 90
6892}
6893
6894impl Default for StrengthCalculationSchemaConfig {
6895 fn default() -> Self {
6896 Self {
6897 transaction_volume_weight: 0.30,
6898 transaction_count_weight: 0.25,
6899 relationship_duration_weight: 0.20,
6900 recency_weight: 0.15,
6901 mutual_connections_weight: 0.10,
6902 recency_half_life_days: 90,
6903 }
6904 }
6905}
6906
6907#[derive(Debug, Clone, Serialize, Deserialize)]
6909pub struct StrengthThresholdsSchemaConfig {
6910 #[serde(default = "default_strong_threshold")]
6912 pub strong: f64,
6913
6914 #[serde(default = "default_moderate_threshold")]
6916 pub moderate: f64,
6917
6918 #[serde(default = "default_weak_threshold")]
6920 pub weak: f64,
6921}
6922
6923fn default_strong_threshold() -> f64 {
6924 0.7
6925}
6926
6927fn default_moderate_threshold() -> f64 {
6928 0.4
6929}
6930
6931fn default_weak_threshold() -> f64 {
6932 0.1
6933}
6934
6935impl Default for StrengthThresholdsSchemaConfig {
6936 fn default() -> Self {
6937 Self {
6938 strong: 0.7,
6939 moderate: 0.4,
6940 weak: 0.1,
6941 }
6942 }
6943}
6944
6945#[derive(Debug, Clone, Serialize, Deserialize)]
6951pub struct CrossProcessLinksSchemaConfig {
6952 #[serde(default)]
6954 pub enabled: bool,
6955
6956 #[serde(default = "default_true")]
6958 pub inventory_p2p_o2c: bool,
6959
6960 #[serde(default = "default_true")]
6962 pub payment_bank_reconciliation: bool,
6963
6964 #[serde(default = "default_true")]
6966 pub intercompany_bilateral: bool,
6967
6968 #[serde(default = "default_inventory_link_rate")]
6970 pub inventory_link_rate: f64,
6971}
6972
6973fn default_inventory_link_rate() -> f64 {
6974 0.30
6975}
6976
6977impl Default for CrossProcessLinksSchemaConfig {
6978 fn default() -> Self {
6979 Self {
6980 enabled: false,
6981 inventory_p2p_o2c: true,
6982 payment_bank_reconciliation: true,
6983 intercompany_bilateral: true,
6984 inventory_link_rate: 0.30,
6985 }
6986 }
6987}
6988
6989#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6995pub struct OrganizationalEventsSchemaConfig {
6996 #[serde(default)]
6998 pub enabled: bool,
6999
7000 #[serde(default)]
7002 pub effect_blending: EffectBlendingModeConfig,
7003
7004 #[serde(default)]
7006 pub events: Vec<OrganizationalEventSchemaConfig>,
7007
7008 #[serde(default)]
7010 pub process_evolution: Vec<ProcessEvolutionSchemaConfig>,
7011
7012 #[serde(default)]
7014 pub technology_transitions: Vec<TechnologyTransitionSchemaConfig>,
7015}
7016
7017#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
7019#[serde(rename_all = "snake_case")]
7020pub enum EffectBlendingModeConfig {
7021 #[default]
7023 Multiplicative,
7024 Additive,
7026 Maximum,
7028 Minimum,
7030}
7031
7032#[derive(Debug, Clone, Serialize, Deserialize)]
7034pub struct OrganizationalEventSchemaConfig {
7035 pub id: String,
7037
7038 pub event_type: OrganizationalEventTypeSchemaConfig,
7040
7041 pub effective_date: String,
7043
7044 #[serde(default = "default_org_transition_months")]
7046 pub transition_months: u32,
7047
7048 #[serde(default)]
7050 pub description: Option<String>,
7051}
7052
7053fn default_org_transition_months() -> u32 {
7054 6
7055}
7056
7057#[derive(Debug, Clone, Serialize, Deserialize)]
7059#[serde(tag = "type", rename_all = "snake_case")]
7060pub enum OrganizationalEventTypeSchemaConfig {
7061 Acquisition {
7063 acquired_entity: String,
7065 #[serde(default = "default_acquisition_volume")]
7067 volume_increase: f64,
7068 #[serde(default = "default_acquisition_error")]
7070 integration_error_rate: f64,
7071 #[serde(default = "default_parallel_days")]
7073 parallel_posting_days: u32,
7074 },
7075 Divestiture {
7077 divested_entity: String,
7079 #[serde(default = "default_divestiture_volume")]
7081 volume_reduction: f64,
7082 #[serde(default = "default_true_val")]
7084 remove_entity: bool,
7085 },
7086 Reorganization {
7088 #[serde(default)]
7090 cost_center_remapping: std::collections::HashMap<String, String>,
7091 #[serde(default = "default_reorg_error")]
7093 transition_error_rate: f64,
7094 },
7095 LeadershipChange {
7097 role: String,
7099 #[serde(default)]
7101 policy_changes: Vec<String>,
7102 },
7103 WorkforceReduction {
7105 #[serde(default = "default_workforce_reduction")]
7107 reduction_percent: f64,
7108 #[serde(default = "default_workforce_error")]
7110 error_rate_increase: f64,
7111 },
7112 Merger {
7114 merged_entity: String,
7116 #[serde(default = "default_merger_volume")]
7118 volume_increase: f64,
7119 },
7120}
7121
7122fn default_acquisition_volume() -> f64 {
7123 1.35
7124}
7125
7126fn default_acquisition_error() -> f64 {
7127 0.05
7128}
7129
7130fn default_parallel_days() -> u32 {
7131 30
7132}
7133
7134fn default_divestiture_volume() -> f64 {
7135 0.70
7136}
7137
7138fn default_true_val() -> bool {
7139 true
7140}
7141
7142fn default_reorg_error() -> f64 {
7143 0.04
7144}
7145
7146fn default_workforce_reduction() -> f64 {
7147 0.10
7148}
7149
7150fn default_workforce_error() -> f64 {
7151 0.05
7152}
7153
7154fn default_merger_volume() -> f64 {
7155 1.80
7156}
7157
7158#[derive(Debug, Clone, Serialize, Deserialize)]
7160pub struct ProcessEvolutionSchemaConfig {
7161 pub id: String,
7163
7164 pub event_type: ProcessEvolutionTypeSchemaConfig,
7166
7167 pub effective_date: String,
7169
7170 #[serde(default)]
7172 pub description: Option<String>,
7173}
7174
7175#[derive(Debug, Clone, Serialize, Deserialize)]
7177#[serde(tag = "type", rename_all = "snake_case")]
7178pub enum ProcessEvolutionTypeSchemaConfig {
7179 ProcessAutomation {
7181 process_name: String,
7183 #[serde(default = "default_manual_before")]
7185 manual_rate_before: f64,
7186 #[serde(default = "default_manual_after")]
7188 manual_rate_after: f64,
7189 },
7190 ApprovalWorkflowChange {
7192 description: String,
7194 },
7195 ControlEnhancement {
7197 control_id: String,
7199 #[serde(default = "default_error_reduction")]
7201 error_reduction: f64,
7202 },
7203}
7204
7205fn default_manual_before() -> f64 {
7206 0.80
7207}
7208
7209fn default_manual_after() -> f64 {
7210 0.15
7211}
7212
7213fn default_error_reduction() -> f64 {
7214 0.02
7215}
7216
7217#[derive(Debug, Clone, Serialize, Deserialize)]
7219pub struct TechnologyTransitionSchemaConfig {
7220 pub id: String,
7222
7223 pub event_type: TechnologyTransitionTypeSchemaConfig,
7225
7226 #[serde(default)]
7228 pub description: Option<String>,
7229}
7230
7231#[derive(Debug, Clone, Serialize, Deserialize)]
7233#[serde(tag = "type", rename_all = "snake_case")]
7234pub enum TechnologyTransitionTypeSchemaConfig {
7235 ErpMigration {
7237 source_system: String,
7239 target_system: String,
7241 cutover_date: String,
7243 stabilization_end: String,
7245 #[serde(default = "default_erp_duplicate_rate")]
7247 duplicate_rate: f64,
7248 #[serde(default = "default_format_mismatch")]
7250 format_mismatch_rate: f64,
7251 },
7252 ModuleImplementation {
7254 module_name: String,
7256 go_live_date: String,
7258 },
7259}
7260
7261fn default_erp_duplicate_rate() -> f64 {
7262 0.02
7263}
7264
7265fn default_format_mismatch() -> f64 {
7266 0.03
7267}
7268
7269#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7275pub struct BehavioralDriftSchemaConfig {
7276 #[serde(default)]
7278 pub enabled: bool,
7279
7280 #[serde(default)]
7282 pub vendor_behavior: VendorBehaviorSchemaConfig,
7283
7284 #[serde(default)]
7286 pub customer_behavior: CustomerBehaviorSchemaConfig,
7287
7288 #[serde(default)]
7290 pub employee_behavior: EmployeeBehaviorSchemaConfig,
7291
7292 #[serde(default)]
7294 pub collective: CollectiveBehaviorSchemaConfig,
7295}
7296
7297#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7299pub struct VendorBehaviorSchemaConfig {
7300 #[serde(default)]
7302 pub payment_terms_drift: PaymentTermsDriftSchemaConfig,
7303
7304 #[serde(default)]
7306 pub quality_drift: QualityDriftSchemaConfig,
7307}
7308
7309#[derive(Debug, Clone, Serialize, Deserialize)]
7311pub struct PaymentTermsDriftSchemaConfig {
7312 #[serde(default = "default_extension_rate")]
7314 pub extension_rate_per_year: f64,
7315
7316 #[serde(default = "default_economic_sensitivity")]
7318 pub economic_sensitivity: f64,
7319}
7320
7321fn default_extension_rate() -> f64 {
7322 2.5
7323}
7324
7325fn default_economic_sensitivity() -> f64 {
7326 1.0
7327}
7328
7329impl Default for PaymentTermsDriftSchemaConfig {
7330 fn default() -> Self {
7331 Self {
7332 extension_rate_per_year: 2.5,
7333 economic_sensitivity: 1.0,
7334 }
7335 }
7336}
7337
7338#[derive(Debug, Clone, Serialize, Deserialize)]
7340pub struct QualityDriftSchemaConfig {
7341 #[serde(default = "default_improvement_rate")]
7343 pub new_vendor_improvement_rate: f64,
7344
7345 #[serde(default = "default_decline_rate")]
7347 pub complacency_decline_rate: f64,
7348}
7349
7350fn default_improvement_rate() -> f64 {
7351 0.02
7352}
7353
7354fn default_decline_rate() -> f64 {
7355 0.01
7356}
7357
7358impl Default for QualityDriftSchemaConfig {
7359 fn default() -> Self {
7360 Self {
7361 new_vendor_improvement_rate: 0.02,
7362 complacency_decline_rate: 0.01,
7363 }
7364 }
7365}
7366
7367#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7369pub struct CustomerBehaviorSchemaConfig {
7370 #[serde(default)]
7372 pub payment_drift: CustomerPaymentDriftSchemaConfig,
7373
7374 #[serde(default)]
7376 pub order_drift: OrderDriftSchemaConfig,
7377}
7378
7379#[derive(Debug, Clone, Serialize, Deserialize)]
7381pub struct CustomerPaymentDriftSchemaConfig {
7382 #[serde(default = "default_downturn_extension")]
7384 pub downturn_days_extension: (u32, u32),
7385
7386 #[serde(default = "default_bad_debt_increase")]
7388 pub downturn_bad_debt_increase: f64,
7389}
7390
7391fn default_downturn_extension() -> (u32, u32) {
7392 (5, 15)
7393}
7394
7395fn default_bad_debt_increase() -> f64 {
7396 0.02
7397}
7398
7399impl Default for CustomerPaymentDriftSchemaConfig {
7400 fn default() -> Self {
7401 Self {
7402 downturn_days_extension: (5, 15),
7403 downturn_bad_debt_increase: 0.02,
7404 }
7405 }
7406}
7407
7408#[derive(Debug, Clone, Serialize, Deserialize)]
7410pub struct OrderDriftSchemaConfig {
7411 #[serde(default = "default_digital_shift")]
7413 pub digital_shift_rate: f64,
7414}
7415
7416fn default_digital_shift() -> f64 {
7417 0.05
7418}
7419
7420impl Default for OrderDriftSchemaConfig {
7421 fn default() -> Self {
7422 Self {
7423 digital_shift_rate: 0.05,
7424 }
7425 }
7426}
7427
7428#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7430pub struct EmployeeBehaviorSchemaConfig {
7431 #[serde(default)]
7433 pub approval_drift: ApprovalDriftSchemaConfig,
7434
7435 #[serde(default)]
7437 pub error_drift: ErrorDriftSchemaConfig,
7438}
7439
7440#[derive(Debug, Clone, Serialize, Deserialize)]
7442pub struct ApprovalDriftSchemaConfig {
7443 #[serde(default = "default_eom_intensity")]
7445 pub eom_intensity_increase_per_year: f64,
7446
7447 #[serde(default = "default_rubber_stamp")]
7449 pub rubber_stamp_volume_threshold: u32,
7450}
7451
7452fn default_eom_intensity() -> f64 {
7453 0.05
7454}
7455
7456fn default_rubber_stamp() -> u32 {
7457 50
7458}
7459
7460impl Default for ApprovalDriftSchemaConfig {
7461 fn default() -> Self {
7462 Self {
7463 eom_intensity_increase_per_year: 0.05,
7464 rubber_stamp_volume_threshold: 50,
7465 }
7466 }
7467}
7468
7469#[derive(Debug, Clone, Serialize, Deserialize)]
7471pub struct ErrorDriftSchemaConfig {
7472 #[serde(default = "default_new_error")]
7474 pub new_employee_error_rate: f64,
7475
7476 #[serde(default = "default_learning_months")]
7478 pub learning_curve_months: u32,
7479}
7480
7481fn default_new_error() -> f64 {
7482 0.08
7483}
7484
7485fn default_learning_months() -> u32 {
7486 6
7487}
7488
7489impl Default for ErrorDriftSchemaConfig {
7490 fn default() -> Self {
7491 Self {
7492 new_employee_error_rate: 0.08,
7493 learning_curve_months: 6,
7494 }
7495 }
7496}
7497
7498#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7500pub struct CollectiveBehaviorSchemaConfig {
7501 #[serde(default)]
7503 pub automation_adoption: AutomationAdoptionSchemaConfig,
7504}
7505
7506#[derive(Debug, Clone, Serialize, Deserialize)]
7508pub struct AutomationAdoptionSchemaConfig {
7509 #[serde(default)]
7511 pub s_curve_enabled: bool,
7512
7513 #[serde(default = "default_midpoint")]
7515 pub adoption_midpoint_months: u32,
7516
7517 #[serde(default = "default_steepness")]
7519 pub steepness: f64,
7520}
7521
7522fn default_midpoint() -> u32 {
7523 24
7524}
7525
7526fn default_steepness() -> f64 {
7527 0.15
7528}
7529
7530impl Default for AutomationAdoptionSchemaConfig {
7531 fn default() -> Self {
7532 Self {
7533 s_curve_enabled: false,
7534 adoption_midpoint_months: 24,
7535 steepness: 0.15,
7536 }
7537 }
7538}
7539
7540#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7546pub struct MarketDriftSchemaConfig {
7547 #[serde(default)]
7549 pub enabled: bool,
7550
7551 #[serde(default)]
7553 pub economic_cycle: MarketEconomicCycleSchemaConfig,
7554
7555 #[serde(default)]
7557 pub industry_cycles: std::collections::HashMap<String, IndustryCycleSchemaConfig>,
7558
7559 #[serde(default)]
7561 pub commodities: CommoditiesSchemaConfig,
7562}
7563
7564#[derive(Debug, Clone, Serialize, Deserialize)]
7566pub struct MarketEconomicCycleSchemaConfig {
7567 #[serde(default)]
7569 pub enabled: bool,
7570
7571 #[serde(default)]
7573 pub cycle_type: CycleTypeSchemaConfig,
7574
7575 #[serde(default = "default_market_cycle_period")]
7577 pub period_months: u32,
7578
7579 #[serde(default = "default_market_amplitude")]
7581 pub amplitude: f64,
7582
7583 #[serde(default)]
7585 pub recession: RecessionSchemaConfig,
7586}
7587
7588fn default_market_cycle_period() -> u32 {
7589 48
7590}
7591
7592fn default_market_amplitude() -> f64 {
7593 0.15
7594}
7595
7596impl Default for MarketEconomicCycleSchemaConfig {
7597 fn default() -> Self {
7598 Self {
7599 enabled: false,
7600 cycle_type: CycleTypeSchemaConfig::Sinusoidal,
7601 period_months: 48,
7602 amplitude: 0.15,
7603 recession: RecessionSchemaConfig::default(),
7604 }
7605 }
7606}
7607
7608#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
7610#[serde(rename_all = "snake_case")]
7611pub enum CycleTypeSchemaConfig {
7612 #[default]
7614 Sinusoidal,
7615 Asymmetric,
7617 MeanReverting,
7619}
7620
7621#[derive(Debug, Clone, Serialize, Deserialize)]
7623pub struct RecessionSchemaConfig {
7624 #[serde(default)]
7626 pub enabled: bool,
7627
7628 #[serde(default = "default_recession_prob")]
7630 pub probability_per_year: f64,
7631
7632 #[serde(default)]
7634 pub severity: RecessionSeveritySchemaConfig,
7635
7636 #[serde(default)]
7638 pub recession_periods: Vec<RecessionPeriodSchemaConfig>,
7639}
7640
7641fn default_recession_prob() -> f64 {
7642 0.10
7643}
7644
7645impl Default for RecessionSchemaConfig {
7646 fn default() -> Self {
7647 Self {
7648 enabled: false,
7649 probability_per_year: 0.10,
7650 severity: RecessionSeveritySchemaConfig::Moderate,
7651 recession_periods: Vec::new(),
7652 }
7653 }
7654}
7655
7656#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
7658#[serde(rename_all = "snake_case")]
7659pub enum RecessionSeveritySchemaConfig {
7660 Mild,
7662 #[default]
7664 Moderate,
7665 Severe,
7667}
7668
7669#[derive(Debug, Clone, Serialize, Deserialize)]
7671pub struct RecessionPeriodSchemaConfig {
7672 pub start_month: u32,
7674 pub duration_months: u32,
7676}
7677
7678#[derive(Debug, Clone, Serialize, Deserialize)]
7680pub struct IndustryCycleSchemaConfig {
7681 #[serde(default = "default_industry_period")]
7683 pub period_months: u32,
7684
7685 #[serde(default = "default_industry_amp")]
7687 pub amplitude: f64,
7688}
7689
7690fn default_industry_period() -> u32 {
7691 36
7692}
7693
7694fn default_industry_amp() -> f64 {
7695 0.20
7696}
7697
7698#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7700pub struct CommoditiesSchemaConfig {
7701 #[serde(default)]
7703 pub enabled: bool,
7704
7705 #[serde(default)]
7707 pub items: Vec<CommodityItemSchemaConfig>,
7708}
7709
7710#[derive(Debug, Clone, Serialize, Deserialize)]
7712pub struct CommodityItemSchemaConfig {
7713 pub name: String,
7715
7716 #[serde(default = "default_volatility")]
7718 pub volatility: f64,
7719
7720 #[serde(default)]
7722 pub cogs_pass_through: f64,
7723
7724 #[serde(default)]
7726 pub overhead_pass_through: f64,
7727}
7728
7729fn default_volatility() -> f64 {
7730 0.20
7731}
7732
7733#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7739pub struct DriftLabelingSchemaConfig {
7740 #[serde(default)]
7742 pub enabled: bool,
7743
7744 #[serde(default)]
7746 pub statistical: StatisticalDriftLabelingSchemaConfig,
7747
7748 #[serde(default)]
7750 pub categorical: CategoricalDriftLabelingSchemaConfig,
7751
7752 #[serde(default)]
7754 pub temporal: TemporalDriftLabelingSchemaConfig,
7755
7756 #[serde(default)]
7758 pub regulatory_calendar_preset: Option<String>,
7759}
7760
7761#[derive(Debug, Clone, Serialize, Deserialize)]
7763pub struct StatisticalDriftLabelingSchemaConfig {
7764 #[serde(default = "default_true_val")]
7766 pub enabled: bool,
7767
7768 #[serde(default = "default_min_magnitude")]
7770 pub min_magnitude_threshold: f64,
7771}
7772
7773fn default_min_magnitude() -> f64 {
7774 0.05
7775}
7776
7777impl Default for StatisticalDriftLabelingSchemaConfig {
7778 fn default() -> Self {
7779 Self {
7780 enabled: true,
7781 min_magnitude_threshold: 0.05,
7782 }
7783 }
7784}
7785
7786#[derive(Debug, Clone, Serialize, Deserialize)]
7788pub struct CategoricalDriftLabelingSchemaConfig {
7789 #[serde(default = "default_true_val")]
7791 pub enabled: bool,
7792}
7793
7794impl Default for CategoricalDriftLabelingSchemaConfig {
7795 fn default() -> Self {
7796 Self { enabled: true }
7797 }
7798}
7799
7800#[derive(Debug, Clone, Serialize, Deserialize)]
7802pub struct TemporalDriftLabelingSchemaConfig {
7803 #[serde(default = "default_true_val")]
7805 pub enabled: bool,
7806}
7807
7808impl Default for TemporalDriftLabelingSchemaConfig {
7809 fn default() -> Self {
7810 Self { enabled: true }
7811 }
7812}
7813
7814#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7827pub struct EnhancedAnomalyConfig {
7828 #[serde(default)]
7830 pub enabled: bool,
7831
7832 #[serde(default)]
7834 pub rates: AnomalyRateConfig,
7835
7836 #[serde(default)]
7838 pub multi_stage_schemes: MultiStageSchemeConfig,
7839
7840 #[serde(default)]
7842 pub correlated_injection: CorrelatedInjectionConfig,
7843
7844 #[serde(default)]
7846 pub near_miss: NearMissConfig,
7847
7848 #[serde(default)]
7850 pub difficulty_classification: DifficultyClassificationConfig,
7851
7852 #[serde(default)]
7854 pub context_aware: ContextAwareConfig,
7855
7856 #[serde(default)]
7858 pub labeling: EnhancedLabelingConfig,
7859}
7860
7861#[derive(Debug, Clone, Serialize, Deserialize)]
7863pub struct AnomalyRateConfig {
7864 #[serde(default = "default_total_anomaly_rate")]
7866 pub total_rate: f64,
7867
7868 #[serde(default = "default_fraud_anomaly_rate")]
7870 pub fraud_rate: f64,
7871
7872 #[serde(default = "default_error_anomaly_rate")]
7874 pub error_rate: f64,
7875
7876 #[serde(default = "default_process_anomaly_rate")]
7878 pub process_rate: f64,
7879}
7880
7881fn default_total_anomaly_rate() -> f64 {
7882 0.03
7883}
7884fn default_fraud_anomaly_rate() -> f64 {
7885 0.01
7886}
7887fn default_error_anomaly_rate() -> f64 {
7888 0.015
7889}
7890fn default_process_anomaly_rate() -> f64 {
7891 0.005
7892}
7893
7894impl Default for AnomalyRateConfig {
7895 fn default() -> Self {
7896 Self {
7897 total_rate: default_total_anomaly_rate(),
7898 fraud_rate: default_fraud_anomaly_rate(),
7899 error_rate: default_error_anomaly_rate(),
7900 process_rate: default_process_anomaly_rate(),
7901 }
7902 }
7903}
7904
7905#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7907pub struct MultiStageSchemeConfig {
7908 #[serde(default)]
7910 pub enabled: bool,
7911
7912 #[serde(default)]
7914 pub embezzlement: EmbezzlementSchemeConfig,
7915
7916 #[serde(default)]
7918 pub revenue_manipulation: RevenueManipulationSchemeConfig,
7919
7920 #[serde(default)]
7922 pub kickback: KickbackSchemeConfig,
7923}
7924
7925#[derive(Debug, Clone, Serialize, Deserialize)]
7927pub struct EmbezzlementSchemeConfig {
7928 #[serde(default = "default_embezzlement_probability")]
7930 pub probability: f64,
7931
7932 #[serde(default)]
7934 pub testing_stage: SchemeStageConfig,
7935
7936 #[serde(default)]
7938 pub escalation_stage: SchemeStageConfig,
7939
7940 #[serde(default)]
7942 pub acceleration_stage: SchemeStageConfig,
7943
7944 #[serde(default)]
7946 pub desperation_stage: SchemeStageConfig,
7947}
7948
7949fn default_embezzlement_probability() -> f64 {
7950 0.02
7951}
7952
7953impl Default for EmbezzlementSchemeConfig {
7954 fn default() -> Self {
7955 Self {
7956 probability: default_embezzlement_probability(),
7957 testing_stage: SchemeStageConfig {
7958 duration_months: 2,
7959 amount_min: 100.0,
7960 amount_max: 500.0,
7961 transaction_count_min: 2,
7962 transaction_count_max: 5,
7963 difficulty: "hard".to_string(),
7964 },
7965 escalation_stage: SchemeStageConfig {
7966 duration_months: 6,
7967 amount_min: 500.0,
7968 amount_max: 2000.0,
7969 transaction_count_min: 3,
7970 transaction_count_max: 8,
7971 difficulty: "moderate".to_string(),
7972 },
7973 acceleration_stage: SchemeStageConfig {
7974 duration_months: 3,
7975 amount_min: 2000.0,
7976 amount_max: 10000.0,
7977 transaction_count_min: 5,
7978 transaction_count_max: 12,
7979 difficulty: "easy".to_string(),
7980 },
7981 desperation_stage: SchemeStageConfig {
7982 duration_months: 1,
7983 amount_min: 10000.0,
7984 amount_max: 50000.0,
7985 transaction_count_min: 3,
7986 transaction_count_max: 6,
7987 difficulty: "trivial".to_string(),
7988 },
7989 }
7990 }
7991}
7992
7993#[derive(Debug, Clone, Serialize, Deserialize)]
7995pub struct RevenueManipulationSchemeConfig {
7996 #[serde(default = "default_revenue_manipulation_probability")]
7998 pub probability: f64,
7999
8000 #[serde(default = "default_early_recognition_target")]
8002 pub early_recognition_target: f64,
8003
8004 #[serde(default = "default_expense_deferral_target")]
8006 pub expense_deferral_target: f64,
8007
8008 #[serde(default = "default_reserve_release_target")]
8010 pub reserve_release_target: f64,
8011
8012 #[serde(default = "default_channel_stuffing_target")]
8014 pub channel_stuffing_target: f64,
8015}
8016
8017fn default_revenue_manipulation_probability() -> f64 {
8018 0.01
8019}
8020fn default_early_recognition_target() -> f64 {
8021 0.02
8022}
8023fn default_expense_deferral_target() -> f64 {
8024 0.03
8025}
8026fn default_reserve_release_target() -> f64 {
8027 0.02
8028}
8029fn default_channel_stuffing_target() -> f64 {
8030 0.05
8031}
8032
8033impl Default for RevenueManipulationSchemeConfig {
8034 fn default() -> Self {
8035 Self {
8036 probability: default_revenue_manipulation_probability(),
8037 early_recognition_target: default_early_recognition_target(),
8038 expense_deferral_target: default_expense_deferral_target(),
8039 reserve_release_target: default_reserve_release_target(),
8040 channel_stuffing_target: default_channel_stuffing_target(),
8041 }
8042 }
8043}
8044
8045#[derive(Debug, Clone, Serialize, Deserialize)]
8047pub struct KickbackSchemeConfig {
8048 #[serde(default = "default_kickback_probability")]
8050 pub probability: f64,
8051
8052 #[serde(default = "default_kickback_inflation_min")]
8054 pub inflation_min: f64,
8055
8056 #[serde(default = "default_kickback_inflation_max")]
8058 pub inflation_max: f64,
8059
8060 #[serde(default = "default_kickback_percent")]
8062 pub kickback_percent: f64,
8063
8064 #[serde(default = "default_kickback_setup_months")]
8066 pub setup_months: u32,
8067
8068 #[serde(default = "default_kickback_operation_months")]
8070 pub operation_months: u32,
8071}
8072
8073fn default_kickback_probability() -> f64 {
8074 0.01
8075}
8076fn default_kickback_inflation_min() -> f64 {
8077 0.10
8078}
8079fn default_kickback_inflation_max() -> f64 {
8080 0.25
8081}
8082fn default_kickback_percent() -> f64 {
8083 0.50
8084}
8085fn default_kickback_setup_months() -> u32 {
8086 3
8087}
8088fn default_kickback_operation_months() -> u32 {
8089 12
8090}
8091
8092impl Default for KickbackSchemeConfig {
8093 fn default() -> Self {
8094 Self {
8095 probability: default_kickback_probability(),
8096 inflation_min: default_kickback_inflation_min(),
8097 inflation_max: default_kickback_inflation_max(),
8098 kickback_percent: default_kickback_percent(),
8099 setup_months: default_kickback_setup_months(),
8100 operation_months: default_kickback_operation_months(),
8101 }
8102 }
8103}
8104
8105#[derive(Debug, Clone, Serialize, Deserialize)]
8107pub struct SchemeStageConfig {
8108 pub duration_months: u32,
8110
8111 pub amount_min: f64,
8113
8114 pub amount_max: f64,
8116
8117 pub transaction_count_min: u32,
8119
8120 pub transaction_count_max: u32,
8122
8123 pub difficulty: String,
8125}
8126
8127impl Default for SchemeStageConfig {
8128 fn default() -> Self {
8129 Self {
8130 duration_months: 3,
8131 amount_min: 100.0,
8132 amount_max: 1000.0,
8133 transaction_count_min: 2,
8134 transaction_count_max: 10,
8135 difficulty: "moderate".to_string(),
8136 }
8137 }
8138}
8139
8140#[derive(Debug, Clone, Serialize, Deserialize)]
8142pub struct CorrelatedInjectionConfig {
8143 #[serde(default)]
8145 pub enabled: bool,
8146
8147 #[serde(default = "default_true_val")]
8149 pub fraud_concealment: bool,
8150
8151 #[serde(default = "default_true_val")]
8153 pub error_cascade: bool,
8154
8155 #[serde(default = "default_true_val")]
8157 pub temporal_clustering: bool,
8158
8159 #[serde(default)]
8161 pub temporal_clustering_config: TemporalClusteringConfig,
8162
8163 #[serde(default)]
8165 pub co_occurrence_patterns: Vec<CoOccurrencePatternConfig>,
8166}
8167
8168impl Default for CorrelatedInjectionConfig {
8169 fn default() -> Self {
8170 Self {
8171 enabled: false,
8172 fraud_concealment: true,
8173 error_cascade: true,
8174 temporal_clustering: true,
8175 temporal_clustering_config: TemporalClusteringConfig::default(),
8176 co_occurrence_patterns: Vec::new(),
8177 }
8178 }
8179}
8180
8181#[derive(Debug, Clone, Serialize, Deserialize)]
8183pub struct TemporalClusteringConfig {
8184 #[serde(default = "default_period_end_multiplier")]
8186 pub period_end_multiplier: f64,
8187
8188 #[serde(default = "default_period_end_days")]
8190 pub period_end_days: u32,
8191
8192 #[serde(default = "default_quarter_end_multiplier")]
8194 pub quarter_end_multiplier: f64,
8195
8196 #[serde(default = "default_year_end_multiplier")]
8198 pub year_end_multiplier: f64,
8199}
8200
8201fn default_period_end_multiplier() -> f64 {
8202 2.5
8203}
8204fn default_period_end_days() -> u32 {
8205 5
8206}
8207fn default_quarter_end_multiplier() -> f64 {
8208 1.5
8209}
8210fn default_year_end_multiplier() -> f64 {
8211 2.0
8212}
8213
8214impl Default for TemporalClusteringConfig {
8215 fn default() -> Self {
8216 Self {
8217 period_end_multiplier: default_period_end_multiplier(),
8218 period_end_days: default_period_end_days(),
8219 quarter_end_multiplier: default_quarter_end_multiplier(),
8220 year_end_multiplier: default_year_end_multiplier(),
8221 }
8222 }
8223}
8224
8225#[derive(Debug, Clone, Serialize, Deserialize)]
8227pub struct CoOccurrencePatternConfig {
8228 pub name: String,
8230
8231 pub primary_type: String,
8233
8234 pub correlated: Vec<CorrelatedAnomalyConfig>,
8236}
8237
8238#[derive(Debug, Clone, Serialize, Deserialize)]
8240pub struct CorrelatedAnomalyConfig {
8241 pub anomaly_type: String,
8243
8244 pub probability: f64,
8246
8247 pub lag_days_min: i32,
8249
8250 pub lag_days_max: i32,
8252}
8253
8254#[derive(Debug, Clone, Serialize, Deserialize)]
8256pub struct NearMissConfig {
8257 #[serde(default)]
8259 pub enabled: bool,
8260
8261 #[serde(default = "default_near_miss_proportion")]
8263 pub proportion: f64,
8264
8265 #[serde(default = "default_true_val")]
8267 pub near_duplicate: bool,
8268
8269 #[serde(default)]
8271 pub near_duplicate_days: NearDuplicateDaysConfig,
8272
8273 #[serde(default = "default_true_val")]
8275 pub threshold_proximity: bool,
8276
8277 #[serde(default)]
8279 pub threshold_proximity_range: ThresholdProximityRangeConfig,
8280
8281 #[serde(default = "default_true_val")]
8283 pub unusual_legitimate: bool,
8284
8285 #[serde(default = "default_unusual_legitimate_types")]
8287 pub unusual_legitimate_types: Vec<String>,
8288
8289 #[serde(default = "default_true_val")]
8291 pub corrected_errors: bool,
8292
8293 #[serde(default)]
8295 pub corrected_error_lag: CorrectedErrorLagConfig,
8296}
8297
8298fn default_near_miss_proportion() -> f64 {
8299 0.30
8300}
8301
8302fn default_unusual_legitimate_types() -> Vec<String> {
8303 vec![
8304 "year_end_bonus".to_string(),
8305 "contract_prepayment".to_string(),
8306 "insurance_claim".to_string(),
8307 "settlement_payment".to_string(),
8308 ]
8309}
8310
8311impl Default for NearMissConfig {
8312 fn default() -> Self {
8313 Self {
8314 enabled: false,
8315 proportion: default_near_miss_proportion(),
8316 near_duplicate: true,
8317 near_duplicate_days: NearDuplicateDaysConfig::default(),
8318 threshold_proximity: true,
8319 threshold_proximity_range: ThresholdProximityRangeConfig::default(),
8320 unusual_legitimate: true,
8321 unusual_legitimate_types: default_unusual_legitimate_types(),
8322 corrected_errors: true,
8323 corrected_error_lag: CorrectedErrorLagConfig::default(),
8324 }
8325 }
8326}
8327
8328#[derive(Debug, Clone, Serialize, Deserialize)]
8330pub struct NearDuplicateDaysConfig {
8331 #[serde(default = "default_near_duplicate_min")]
8333 pub min: u32,
8334
8335 #[serde(default = "default_near_duplicate_max")]
8337 pub max: u32,
8338}
8339
8340fn default_near_duplicate_min() -> u32 {
8341 1
8342}
8343fn default_near_duplicate_max() -> u32 {
8344 3
8345}
8346
8347impl Default for NearDuplicateDaysConfig {
8348 fn default() -> Self {
8349 Self {
8350 min: default_near_duplicate_min(),
8351 max: default_near_duplicate_max(),
8352 }
8353 }
8354}
8355
8356#[derive(Debug, Clone, Serialize, Deserialize)]
8358pub struct ThresholdProximityRangeConfig {
8359 #[serde(default = "default_threshold_proximity_min")]
8361 pub min: f64,
8362
8363 #[serde(default = "default_threshold_proximity_max")]
8365 pub max: f64,
8366}
8367
8368fn default_threshold_proximity_min() -> f64 {
8369 0.90
8370}
8371fn default_threshold_proximity_max() -> f64 {
8372 0.99
8373}
8374
8375impl Default for ThresholdProximityRangeConfig {
8376 fn default() -> Self {
8377 Self {
8378 min: default_threshold_proximity_min(),
8379 max: default_threshold_proximity_max(),
8380 }
8381 }
8382}
8383
8384#[derive(Debug, Clone, Serialize, Deserialize)]
8386pub struct CorrectedErrorLagConfig {
8387 #[serde(default = "default_corrected_error_lag_min")]
8389 pub min: u32,
8390
8391 #[serde(default = "default_corrected_error_lag_max")]
8393 pub max: u32,
8394}
8395
8396fn default_corrected_error_lag_min() -> u32 {
8397 1
8398}
8399fn default_corrected_error_lag_max() -> u32 {
8400 5
8401}
8402
8403impl Default for CorrectedErrorLagConfig {
8404 fn default() -> Self {
8405 Self {
8406 min: default_corrected_error_lag_min(),
8407 max: default_corrected_error_lag_max(),
8408 }
8409 }
8410}
8411
8412#[derive(Debug, Clone, Serialize, Deserialize)]
8414pub struct DifficultyClassificationConfig {
8415 #[serde(default)]
8417 pub enabled: bool,
8418
8419 #[serde(default)]
8421 pub target_distribution: DifficultyDistributionConfig,
8422}
8423
8424impl Default for DifficultyClassificationConfig {
8425 fn default() -> Self {
8426 Self {
8427 enabled: true,
8428 target_distribution: DifficultyDistributionConfig::default(),
8429 }
8430 }
8431}
8432
8433#[derive(Debug, Clone, Serialize, Deserialize)]
8435pub struct DifficultyDistributionConfig {
8436 #[serde(default = "default_difficulty_trivial")]
8438 pub trivial: f64,
8439
8440 #[serde(default = "default_difficulty_easy")]
8442 pub easy: f64,
8443
8444 #[serde(default = "default_difficulty_moderate")]
8446 pub moderate: f64,
8447
8448 #[serde(default = "default_difficulty_hard")]
8450 pub hard: f64,
8451
8452 #[serde(default = "default_difficulty_expert")]
8454 pub expert: f64,
8455}
8456
8457fn default_difficulty_trivial() -> f64 {
8458 0.15
8459}
8460fn default_difficulty_easy() -> f64 {
8461 0.25
8462}
8463fn default_difficulty_moderate() -> f64 {
8464 0.30
8465}
8466fn default_difficulty_hard() -> f64 {
8467 0.20
8468}
8469fn default_difficulty_expert() -> f64 {
8470 0.10
8471}
8472
8473impl Default for DifficultyDistributionConfig {
8474 fn default() -> Self {
8475 Self {
8476 trivial: default_difficulty_trivial(),
8477 easy: default_difficulty_easy(),
8478 moderate: default_difficulty_moderate(),
8479 hard: default_difficulty_hard(),
8480 expert: default_difficulty_expert(),
8481 }
8482 }
8483}
8484
8485#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8487pub struct ContextAwareConfig {
8488 #[serde(default)]
8490 pub enabled: bool,
8491
8492 #[serde(default)]
8494 pub vendor_rules: VendorAnomalyRulesConfig,
8495
8496 #[serde(default)]
8498 pub employee_rules: EmployeeAnomalyRulesConfig,
8499
8500 #[serde(default)]
8502 pub account_rules: AccountAnomalyRulesConfig,
8503
8504 #[serde(default)]
8506 pub behavioral_baseline: BehavioralBaselineConfig,
8507}
8508
8509#[derive(Debug, Clone, Serialize, Deserialize)]
8511pub struct VendorAnomalyRulesConfig {
8512 #[serde(default = "default_new_vendor_multiplier")]
8514 pub new_vendor_error_multiplier: f64,
8515
8516 #[serde(default = "default_new_vendor_threshold")]
8518 pub new_vendor_threshold_days: u32,
8519
8520 #[serde(default = "default_international_multiplier")]
8522 pub international_error_multiplier: f64,
8523
8524 #[serde(default = "default_strategic_vendor_types")]
8526 pub strategic_vendor_anomaly_types: Vec<String>,
8527}
8528
8529fn default_new_vendor_multiplier() -> f64 {
8530 2.5
8531}
8532fn default_new_vendor_threshold() -> u32 {
8533 90
8534}
8535fn default_international_multiplier() -> f64 {
8536 1.5
8537}
8538fn default_strategic_vendor_types() -> Vec<String> {
8539 vec![
8540 "pricing_dispute".to_string(),
8541 "contract_violation".to_string(),
8542 ]
8543}
8544
8545impl Default for VendorAnomalyRulesConfig {
8546 fn default() -> Self {
8547 Self {
8548 new_vendor_error_multiplier: default_new_vendor_multiplier(),
8549 new_vendor_threshold_days: default_new_vendor_threshold(),
8550 international_error_multiplier: default_international_multiplier(),
8551 strategic_vendor_anomaly_types: default_strategic_vendor_types(),
8552 }
8553 }
8554}
8555
8556#[derive(Debug, Clone, Serialize, Deserialize)]
8558pub struct EmployeeAnomalyRulesConfig {
8559 #[serde(default = "default_new_employee_rate")]
8561 pub new_employee_error_rate: f64,
8562
8563 #[serde(default = "default_new_employee_threshold")]
8565 pub new_employee_threshold_days: u32,
8566
8567 #[serde(default = "default_volume_fatigue_threshold")]
8569 pub volume_fatigue_threshold: u32,
8570
8571 #[serde(default = "default_coverage_multiplier")]
8573 pub coverage_error_multiplier: f64,
8574}
8575
8576fn default_new_employee_rate() -> f64 {
8577 0.05
8578}
8579fn default_new_employee_threshold() -> u32 {
8580 180
8581}
8582fn default_volume_fatigue_threshold() -> u32 {
8583 50
8584}
8585fn default_coverage_multiplier() -> f64 {
8586 1.8
8587}
8588
8589impl Default for EmployeeAnomalyRulesConfig {
8590 fn default() -> Self {
8591 Self {
8592 new_employee_error_rate: default_new_employee_rate(),
8593 new_employee_threshold_days: default_new_employee_threshold(),
8594 volume_fatigue_threshold: default_volume_fatigue_threshold(),
8595 coverage_error_multiplier: default_coverage_multiplier(),
8596 }
8597 }
8598}
8599
8600#[derive(Debug, Clone, Serialize, Deserialize)]
8602pub struct AccountAnomalyRulesConfig {
8603 #[serde(default = "default_high_risk_multiplier")]
8605 pub high_risk_account_multiplier: f64,
8606
8607 #[serde(default = "default_high_risk_accounts")]
8609 pub high_risk_accounts: Vec<String>,
8610
8611 #[serde(default = "default_suspense_multiplier")]
8613 pub suspense_account_multiplier: f64,
8614
8615 #[serde(default = "default_suspense_accounts")]
8617 pub suspense_accounts: Vec<String>,
8618
8619 #[serde(default = "default_intercompany_multiplier")]
8621 pub intercompany_account_multiplier: f64,
8622}
8623
8624fn default_high_risk_multiplier() -> f64 {
8625 2.0
8626}
8627fn default_high_risk_accounts() -> Vec<String> {
8628 vec![
8629 "1100".to_string(), "2000".to_string(), "3000".to_string(), ]
8633}
8634fn default_suspense_multiplier() -> f64 {
8635 3.0
8636}
8637fn default_suspense_accounts() -> Vec<String> {
8638 vec!["9999".to_string(), "9998".to_string()]
8639}
8640fn default_intercompany_multiplier() -> f64 {
8641 1.5
8642}
8643
8644impl Default for AccountAnomalyRulesConfig {
8645 fn default() -> Self {
8646 Self {
8647 high_risk_account_multiplier: default_high_risk_multiplier(),
8648 high_risk_accounts: default_high_risk_accounts(),
8649 suspense_account_multiplier: default_suspense_multiplier(),
8650 suspense_accounts: default_suspense_accounts(),
8651 intercompany_account_multiplier: default_intercompany_multiplier(),
8652 }
8653 }
8654}
8655
8656#[derive(Debug, Clone, Serialize, Deserialize)]
8658pub struct BehavioralBaselineConfig {
8659 #[serde(default)]
8661 pub enabled: bool,
8662
8663 #[serde(default = "default_baseline_period")]
8665 pub baseline_period_days: u32,
8666
8667 #[serde(default = "default_deviation_threshold")]
8669 pub deviation_threshold_std: f64,
8670
8671 #[serde(default = "default_frequency_deviation")]
8673 pub frequency_deviation_threshold: f64,
8674}
8675
8676fn default_baseline_period() -> u32 {
8677 90
8678}
8679fn default_deviation_threshold() -> f64 {
8680 3.0
8681}
8682fn default_frequency_deviation() -> f64 {
8683 2.0
8684}
8685
8686impl Default for BehavioralBaselineConfig {
8687 fn default() -> Self {
8688 Self {
8689 enabled: false,
8690 baseline_period_days: default_baseline_period(),
8691 deviation_threshold_std: default_deviation_threshold(),
8692 frequency_deviation_threshold: default_frequency_deviation(),
8693 }
8694 }
8695}
8696
8697#[derive(Debug, Clone, Serialize, Deserialize)]
8699pub struct EnhancedLabelingConfig {
8700 #[serde(default = "default_true_val")]
8702 pub severity_scoring: bool,
8703
8704 #[serde(default = "default_true_val")]
8706 pub difficulty_classification: bool,
8707
8708 #[serde(default)]
8710 pub materiality_thresholds: MaterialityThresholdsConfig,
8711}
8712
8713impl Default for EnhancedLabelingConfig {
8714 fn default() -> Self {
8715 Self {
8716 severity_scoring: true,
8717 difficulty_classification: true,
8718 materiality_thresholds: MaterialityThresholdsConfig::default(),
8719 }
8720 }
8721}
8722
8723#[derive(Debug, Clone, Serialize, Deserialize)]
8725pub struct MaterialityThresholdsConfig {
8726 #[serde(default = "default_materiality_trivial")]
8728 pub trivial: f64,
8729
8730 #[serde(default = "default_materiality_immaterial")]
8732 pub immaterial: f64,
8733
8734 #[serde(default = "default_materiality_material")]
8736 pub material: f64,
8737
8738 #[serde(default = "default_materiality_highly_material")]
8740 pub highly_material: f64,
8741}
8742
8743fn default_materiality_trivial() -> f64 {
8744 0.001
8745}
8746fn default_materiality_immaterial() -> f64 {
8747 0.01
8748}
8749fn default_materiality_material() -> f64 {
8750 0.05
8751}
8752fn default_materiality_highly_material() -> f64 {
8753 0.10
8754}
8755
8756impl Default for MaterialityThresholdsConfig {
8757 fn default() -> Self {
8758 Self {
8759 trivial: default_materiality_trivial(),
8760 immaterial: default_materiality_immaterial(),
8761 material: default_materiality_material(),
8762 highly_material: default_materiality_highly_material(),
8763 }
8764 }
8765}
8766
8767#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8779pub struct IndustrySpecificConfig {
8780 #[serde(default)]
8782 pub enabled: bool,
8783
8784 #[serde(default)]
8786 pub manufacturing: ManufacturingConfig,
8787
8788 #[serde(default)]
8790 pub retail: RetailConfig,
8791
8792 #[serde(default)]
8794 pub healthcare: HealthcareConfig,
8795
8796 #[serde(default)]
8798 pub technology: TechnologyConfig,
8799
8800 #[serde(default)]
8802 pub financial_services: FinancialServicesConfig,
8803
8804 #[serde(default)]
8806 pub professional_services: ProfessionalServicesConfig,
8807}
8808
8809#[derive(Debug, Clone, Serialize, Deserialize)]
8811pub struct ManufacturingConfig {
8812 #[serde(default)]
8814 pub enabled: bool,
8815
8816 #[serde(default = "default_bom_depth")]
8818 pub bom_depth: u32,
8819
8820 #[serde(default)]
8822 pub just_in_time: bool,
8823
8824 #[serde(default = "default_production_order_types")]
8826 pub production_order_types: Vec<String>,
8827
8828 #[serde(default)]
8830 pub quality_framework: Option<String>,
8831
8832 #[serde(default = "default_supplier_tiers")]
8834 pub supplier_tiers: u32,
8835
8836 #[serde(default = "default_cost_frequency")]
8838 pub standard_cost_frequency: String,
8839
8840 #[serde(default = "default_yield_rate")]
8842 pub target_yield_rate: f64,
8843
8844 #[serde(default = "default_scrap_threshold")]
8846 pub scrap_alert_threshold: f64,
8847
8848 #[serde(default)]
8850 pub anomaly_rates: ManufacturingAnomalyRates,
8851}
8852
8853fn default_bom_depth() -> u32 {
8854 4
8855}
8856
8857fn default_production_order_types() -> Vec<String> {
8858 vec![
8859 "standard".to_string(),
8860 "rework".to_string(),
8861 "prototype".to_string(),
8862 ]
8863}
8864
8865fn default_supplier_tiers() -> u32 {
8866 2
8867}
8868
8869fn default_cost_frequency() -> String {
8870 "quarterly".to_string()
8871}
8872
8873fn default_yield_rate() -> f64 {
8874 0.97
8875}
8876
8877fn default_scrap_threshold() -> f64 {
8878 0.03
8879}
8880
8881impl Default for ManufacturingConfig {
8882 fn default() -> Self {
8883 Self {
8884 enabled: false,
8885 bom_depth: default_bom_depth(),
8886 just_in_time: false,
8887 production_order_types: default_production_order_types(),
8888 quality_framework: Some("ISO_9001".to_string()),
8889 supplier_tiers: default_supplier_tiers(),
8890 standard_cost_frequency: default_cost_frequency(),
8891 target_yield_rate: default_yield_rate(),
8892 scrap_alert_threshold: default_scrap_threshold(),
8893 anomaly_rates: ManufacturingAnomalyRates::default(),
8894 }
8895 }
8896}
8897
8898#[derive(Debug, Clone, Serialize, Deserialize)]
8900pub struct ManufacturingAnomalyRates {
8901 #[serde(default = "default_mfg_yield_rate")]
8903 pub yield_manipulation: f64,
8904
8905 #[serde(default = "default_mfg_labor_rate")]
8907 pub labor_misallocation: f64,
8908
8909 #[serde(default = "default_mfg_phantom_rate")]
8911 pub phantom_production: f64,
8912
8913 #[serde(default = "default_mfg_cost_rate")]
8915 pub standard_cost_manipulation: f64,
8916
8917 #[serde(default = "default_mfg_inventory_rate")]
8919 pub inventory_fraud: f64,
8920}
8921
8922fn default_mfg_yield_rate() -> f64 {
8923 0.015
8924}
8925
8926fn default_mfg_labor_rate() -> f64 {
8927 0.02
8928}
8929
8930fn default_mfg_phantom_rate() -> f64 {
8931 0.005
8932}
8933
8934fn default_mfg_cost_rate() -> f64 {
8935 0.01
8936}
8937
8938fn default_mfg_inventory_rate() -> f64 {
8939 0.008
8940}
8941
8942impl Default for ManufacturingAnomalyRates {
8943 fn default() -> Self {
8944 Self {
8945 yield_manipulation: default_mfg_yield_rate(),
8946 labor_misallocation: default_mfg_labor_rate(),
8947 phantom_production: default_mfg_phantom_rate(),
8948 standard_cost_manipulation: default_mfg_cost_rate(),
8949 inventory_fraud: default_mfg_inventory_rate(),
8950 }
8951 }
8952}
8953
8954#[derive(Debug, Clone, Serialize, Deserialize)]
8956pub struct RetailConfig {
8957 #[serde(default)]
8959 pub enabled: bool,
8960
8961 #[serde(default)]
8963 pub store_types: RetailStoreTypeConfig,
8964
8965 #[serde(default = "default_retail_daily_txns")]
8967 pub avg_daily_transactions: u32,
8968
8969 #[serde(default = "default_true")]
8971 pub loss_prevention: bool,
8972
8973 #[serde(default = "default_shrinkage_rate")]
8975 pub shrinkage_rate: f64,
8976
8977 #[serde(default)]
8979 pub anomaly_rates: RetailAnomalyRates,
8980}
8981
8982fn default_retail_daily_txns() -> u32 {
8983 500
8984}
8985
8986fn default_shrinkage_rate() -> f64 {
8987 0.015
8988}
8989
8990impl Default for RetailConfig {
8991 fn default() -> Self {
8992 Self {
8993 enabled: false,
8994 store_types: RetailStoreTypeConfig::default(),
8995 avg_daily_transactions: default_retail_daily_txns(),
8996 loss_prevention: true,
8997 shrinkage_rate: default_shrinkage_rate(),
8998 anomaly_rates: RetailAnomalyRates::default(),
8999 }
9000 }
9001}
9002
9003#[derive(Debug, Clone, Serialize, Deserialize)]
9005pub struct RetailStoreTypeConfig {
9006 #[serde(default = "default_flagship_pct")]
9008 pub flagship: f64,
9009
9010 #[serde(default = "default_regional_pct")]
9012 pub regional: f64,
9013
9014 #[serde(default = "default_outlet_pct")]
9016 pub outlet: f64,
9017
9018 #[serde(default = "default_ecommerce_pct")]
9020 pub ecommerce: f64,
9021}
9022
9023fn default_flagship_pct() -> f64 {
9024 0.10
9025}
9026
9027fn default_regional_pct() -> f64 {
9028 0.50
9029}
9030
9031fn default_outlet_pct() -> f64 {
9032 0.25
9033}
9034
9035fn default_ecommerce_pct() -> f64 {
9036 0.15
9037}
9038
9039impl Default for RetailStoreTypeConfig {
9040 fn default() -> Self {
9041 Self {
9042 flagship: default_flagship_pct(),
9043 regional: default_regional_pct(),
9044 outlet: default_outlet_pct(),
9045 ecommerce: default_ecommerce_pct(),
9046 }
9047 }
9048}
9049
9050#[derive(Debug, Clone, Serialize, Deserialize)]
9052pub struct RetailAnomalyRates {
9053 #[serde(default = "default_sweethearting_rate")]
9055 pub sweethearting: f64,
9056
9057 #[serde(default = "default_skimming_rate")]
9059 pub skimming: f64,
9060
9061 #[serde(default = "default_refund_fraud_rate")]
9063 pub refund_fraud: f64,
9064
9065 #[serde(default = "default_void_abuse_rate")]
9067 pub void_abuse: f64,
9068
9069 #[serde(default = "default_gift_card_rate")]
9071 pub gift_card_fraud: f64,
9072
9073 #[serde(default = "default_retail_kickback_rate")]
9075 pub vendor_kickback: f64,
9076}
9077
9078fn default_sweethearting_rate() -> f64 {
9079 0.02
9080}
9081
9082fn default_skimming_rate() -> f64 {
9083 0.005
9084}
9085
9086fn default_refund_fraud_rate() -> f64 {
9087 0.015
9088}
9089
9090fn default_void_abuse_rate() -> f64 {
9091 0.01
9092}
9093
9094fn default_gift_card_rate() -> f64 {
9095 0.008
9096}
9097
9098fn default_retail_kickback_rate() -> f64 {
9099 0.003
9100}
9101
9102impl Default for RetailAnomalyRates {
9103 fn default() -> Self {
9104 Self {
9105 sweethearting: default_sweethearting_rate(),
9106 skimming: default_skimming_rate(),
9107 refund_fraud: default_refund_fraud_rate(),
9108 void_abuse: default_void_abuse_rate(),
9109 gift_card_fraud: default_gift_card_rate(),
9110 vendor_kickback: default_retail_kickback_rate(),
9111 }
9112 }
9113}
9114
9115#[derive(Debug, Clone, Serialize, Deserialize)]
9117pub struct HealthcareConfig {
9118 #[serde(default)]
9120 pub enabled: bool,
9121
9122 #[serde(default = "default_facility_type")]
9124 pub facility_type: String,
9125
9126 #[serde(default)]
9128 pub payer_mix: HealthcarePayerMix,
9129
9130 #[serde(default)]
9132 pub coding_systems: HealthcareCodingSystems,
9133
9134 #[serde(default)]
9136 pub compliance: HealthcareComplianceConfig,
9137
9138 #[serde(default = "default_daily_encounters")]
9140 pub avg_daily_encounters: u32,
9141
9142 #[serde(default = "default_charges_per_encounter")]
9144 pub avg_charges_per_encounter: u32,
9145
9146 #[serde(default = "default_hc_denial_rate")]
9148 pub denial_rate: f64,
9149
9150 #[serde(default = "default_hc_bad_debt_rate")]
9152 pub bad_debt_rate: f64,
9153
9154 #[serde(default = "default_hc_charity_care_rate")]
9156 pub charity_care_rate: f64,
9157
9158 #[serde(default)]
9160 pub anomaly_rates: HealthcareAnomalyRates,
9161}
9162
9163fn default_facility_type() -> String {
9164 "hospital".to_string()
9165}
9166
9167fn default_daily_encounters() -> u32 {
9168 150
9169}
9170
9171fn default_charges_per_encounter() -> u32 {
9172 8
9173}
9174
9175fn default_hc_denial_rate() -> f64 {
9176 0.05
9177}
9178
9179fn default_hc_bad_debt_rate() -> f64 {
9180 0.03
9181}
9182
9183fn default_hc_charity_care_rate() -> f64 {
9184 0.02
9185}
9186
9187impl Default for HealthcareConfig {
9188 fn default() -> Self {
9189 Self {
9190 enabled: false,
9191 facility_type: default_facility_type(),
9192 payer_mix: HealthcarePayerMix::default(),
9193 coding_systems: HealthcareCodingSystems::default(),
9194 compliance: HealthcareComplianceConfig::default(),
9195 avg_daily_encounters: default_daily_encounters(),
9196 avg_charges_per_encounter: default_charges_per_encounter(),
9197 denial_rate: default_hc_denial_rate(),
9198 bad_debt_rate: default_hc_bad_debt_rate(),
9199 charity_care_rate: default_hc_charity_care_rate(),
9200 anomaly_rates: HealthcareAnomalyRates::default(),
9201 }
9202 }
9203}
9204
9205#[derive(Debug, Clone, Serialize, Deserialize)]
9207pub struct HealthcarePayerMix {
9208 #[serde(default = "default_medicare_pct")]
9210 pub medicare: f64,
9211
9212 #[serde(default = "default_medicaid_pct")]
9214 pub medicaid: f64,
9215
9216 #[serde(default = "default_commercial_pct")]
9218 pub commercial: f64,
9219
9220 #[serde(default = "default_self_pay_pct")]
9222 pub self_pay: f64,
9223}
9224
9225fn default_medicare_pct() -> f64 {
9226 0.40
9227}
9228
9229fn default_medicaid_pct() -> f64 {
9230 0.20
9231}
9232
9233fn default_commercial_pct() -> f64 {
9234 0.30
9235}
9236
9237fn default_self_pay_pct() -> f64 {
9238 0.10
9239}
9240
9241impl Default for HealthcarePayerMix {
9242 fn default() -> Self {
9243 Self {
9244 medicare: default_medicare_pct(),
9245 medicaid: default_medicaid_pct(),
9246 commercial: default_commercial_pct(),
9247 self_pay: default_self_pay_pct(),
9248 }
9249 }
9250}
9251
9252#[derive(Debug, Clone, Serialize, Deserialize)]
9254pub struct HealthcareCodingSystems {
9255 #[serde(default = "default_true")]
9257 pub icd10: bool,
9258
9259 #[serde(default = "default_true")]
9261 pub cpt: bool,
9262
9263 #[serde(default = "default_true")]
9265 pub drg: bool,
9266
9267 #[serde(default = "default_true")]
9269 pub hcpcs: bool,
9270
9271 #[serde(default = "default_true")]
9273 pub revenue_codes: bool,
9274}
9275
9276impl Default for HealthcareCodingSystems {
9277 fn default() -> Self {
9278 Self {
9279 icd10: true,
9280 cpt: true,
9281 drg: true,
9282 hcpcs: true,
9283 revenue_codes: true,
9284 }
9285 }
9286}
9287
9288#[derive(Debug, Clone, Serialize, Deserialize)]
9290pub struct HealthcareComplianceConfig {
9291 #[serde(default = "default_true")]
9293 pub hipaa: bool,
9294
9295 #[serde(default = "default_true")]
9297 pub stark_law: bool,
9298
9299 #[serde(default = "default_true")]
9301 pub anti_kickback: bool,
9302
9303 #[serde(default = "default_true")]
9305 pub false_claims_act: bool,
9306
9307 #[serde(default = "default_true")]
9309 pub emtala: bool,
9310}
9311
9312impl Default for HealthcareComplianceConfig {
9313 fn default() -> Self {
9314 Self {
9315 hipaa: true,
9316 stark_law: true,
9317 anti_kickback: true,
9318 false_claims_act: true,
9319 emtala: true,
9320 }
9321 }
9322}
9323
9324#[derive(Debug, Clone, Serialize, Deserialize)]
9326pub struct HealthcareAnomalyRates {
9327 #[serde(default = "default_upcoding_rate")]
9329 pub upcoding: f64,
9330
9331 #[serde(default = "default_unbundling_rate")]
9333 pub unbundling: f64,
9334
9335 #[serde(default = "default_phantom_billing_rate")]
9337 pub phantom_billing: f64,
9338
9339 #[serde(default = "default_healthcare_kickback_rate")]
9341 pub kickbacks: f64,
9342
9343 #[serde(default = "default_duplicate_billing_rate")]
9345 pub duplicate_billing: f64,
9346
9347 #[serde(default = "default_med_necessity_rate")]
9349 pub medical_necessity_abuse: f64,
9350}
9351
9352fn default_upcoding_rate() -> f64 {
9353 0.02
9354}
9355
9356fn default_unbundling_rate() -> f64 {
9357 0.015
9358}
9359
9360fn default_phantom_billing_rate() -> f64 {
9361 0.005
9362}
9363
9364fn default_healthcare_kickback_rate() -> f64 {
9365 0.003
9366}
9367
9368fn default_duplicate_billing_rate() -> f64 {
9369 0.008
9370}
9371
9372fn default_med_necessity_rate() -> f64 {
9373 0.01
9374}
9375
9376impl Default for HealthcareAnomalyRates {
9377 fn default() -> Self {
9378 Self {
9379 upcoding: default_upcoding_rate(),
9380 unbundling: default_unbundling_rate(),
9381 phantom_billing: default_phantom_billing_rate(),
9382 kickbacks: default_healthcare_kickback_rate(),
9383 duplicate_billing: default_duplicate_billing_rate(),
9384 medical_necessity_abuse: default_med_necessity_rate(),
9385 }
9386 }
9387}
9388
9389#[derive(Debug, Clone, Serialize, Deserialize)]
9391pub struct TechnologyConfig {
9392 #[serde(default)]
9394 pub enabled: bool,
9395
9396 #[serde(default = "default_revenue_model")]
9398 pub revenue_model: String,
9399
9400 #[serde(default = "default_subscription_pct")]
9402 pub subscription_revenue_pct: f64,
9403
9404 #[serde(default = "default_license_pct")]
9406 pub license_revenue_pct: f64,
9407
9408 #[serde(default = "default_services_pct")]
9410 pub services_revenue_pct: f64,
9411
9412 #[serde(default)]
9414 pub rd_capitalization: RdCapitalizationConfig,
9415
9416 #[serde(default)]
9418 pub anomaly_rates: TechnologyAnomalyRates,
9419}
9420
9421fn default_revenue_model() -> String {
9422 "saas".to_string()
9423}
9424
9425fn default_subscription_pct() -> f64 {
9426 0.60
9427}
9428
9429fn default_license_pct() -> f64 {
9430 0.25
9431}
9432
9433fn default_services_pct() -> f64 {
9434 0.15
9435}
9436
9437impl Default for TechnologyConfig {
9438 fn default() -> Self {
9439 Self {
9440 enabled: false,
9441 revenue_model: default_revenue_model(),
9442 subscription_revenue_pct: default_subscription_pct(),
9443 license_revenue_pct: default_license_pct(),
9444 services_revenue_pct: default_services_pct(),
9445 rd_capitalization: RdCapitalizationConfig::default(),
9446 anomaly_rates: TechnologyAnomalyRates::default(),
9447 }
9448 }
9449}
9450
9451#[derive(Debug, Clone, Serialize, Deserialize)]
9453pub struct RdCapitalizationConfig {
9454 #[serde(default = "default_true")]
9456 pub enabled: bool,
9457
9458 #[serde(default = "default_cap_rate")]
9460 pub capitalization_rate: f64,
9461
9462 #[serde(default = "default_useful_life")]
9464 pub useful_life_years: u32,
9465}
9466
9467fn default_cap_rate() -> f64 {
9468 0.30
9469}
9470
9471fn default_useful_life() -> u32 {
9472 3
9473}
9474
9475impl Default for RdCapitalizationConfig {
9476 fn default() -> Self {
9477 Self {
9478 enabled: true,
9479 capitalization_rate: default_cap_rate(),
9480 useful_life_years: default_useful_life(),
9481 }
9482 }
9483}
9484
9485#[derive(Debug, Clone, Serialize, Deserialize)]
9487pub struct TechnologyAnomalyRates {
9488 #[serde(default = "default_premature_rev_rate")]
9490 pub premature_revenue: f64,
9491
9492 #[serde(default = "default_side_letter_rate")]
9494 pub side_letter_abuse: f64,
9495
9496 #[serde(default = "default_channel_stuffing_rate")]
9498 pub channel_stuffing: f64,
9499
9500 #[serde(default = "default_improper_cap_rate")]
9502 pub improper_capitalization: f64,
9503}
9504
9505fn default_premature_rev_rate() -> f64 {
9506 0.015
9507}
9508
9509fn default_side_letter_rate() -> f64 {
9510 0.008
9511}
9512
9513fn default_channel_stuffing_rate() -> f64 {
9514 0.01
9515}
9516
9517fn default_improper_cap_rate() -> f64 {
9518 0.012
9519}
9520
9521impl Default for TechnologyAnomalyRates {
9522 fn default() -> Self {
9523 Self {
9524 premature_revenue: default_premature_rev_rate(),
9525 side_letter_abuse: default_side_letter_rate(),
9526 channel_stuffing: default_channel_stuffing_rate(),
9527 improper_capitalization: default_improper_cap_rate(),
9528 }
9529 }
9530}
9531
9532#[derive(Debug, Clone, Serialize, Deserialize)]
9534pub struct FinancialServicesConfig {
9535 #[serde(default)]
9537 pub enabled: bool,
9538
9539 #[serde(default = "default_fi_type")]
9541 pub institution_type: String,
9542
9543 #[serde(default = "default_fi_regulatory")]
9545 pub regulatory_framework: String,
9546
9547 #[serde(default)]
9549 pub anomaly_rates: FinancialServicesAnomalyRates,
9550}
9551
9552fn default_fi_type() -> String {
9553 "commercial_bank".to_string()
9554}
9555
9556fn default_fi_regulatory() -> String {
9557 "us_banking".to_string()
9558}
9559
9560impl Default for FinancialServicesConfig {
9561 fn default() -> Self {
9562 Self {
9563 enabled: false,
9564 institution_type: default_fi_type(),
9565 regulatory_framework: default_fi_regulatory(),
9566 anomaly_rates: FinancialServicesAnomalyRates::default(),
9567 }
9568 }
9569}
9570
9571#[derive(Debug, Clone, Serialize, Deserialize)]
9573pub struct FinancialServicesAnomalyRates {
9574 #[serde(default = "default_loan_fraud_rate")]
9576 pub loan_fraud: f64,
9577
9578 #[serde(default = "default_trading_fraud_rate")]
9580 pub trading_fraud: f64,
9581
9582 #[serde(default = "default_insurance_fraud_rate")]
9584 pub insurance_fraud: f64,
9585
9586 #[serde(default = "default_account_manip_rate")]
9588 pub account_manipulation: f64,
9589}
9590
9591fn default_loan_fraud_rate() -> f64 {
9592 0.01
9593}
9594
9595fn default_trading_fraud_rate() -> f64 {
9596 0.008
9597}
9598
9599fn default_insurance_fraud_rate() -> f64 {
9600 0.012
9601}
9602
9603fn default_account_manip_rate() -> f64 {
9604 0.005
9605}
9606
9607impl Default for FinancialServicesAnomalyRates {
9608 fn default() -> Self {
9609 Self {
9610 loan_fraud: default_loan_fraud_rate(),
9611 trading_fraud: default_trading_fraud_rate(),
9612 insurance_fraud: default_insurance_fraud_rate(),
9613 account_manipulation: default_account_manip_rate(),
9614 }
9615 }
9616}
9617
9618#[derive(Debug, Clone, Serialize, Deserialize)]
9620pub struct ProfessionalServicesConfig {
9621 #[serde(default)]
9623 pub enabled: bool,
9624
9625 #[serde(default = "default_firm_type")]
9627 pub firm_type: String,
9628
9629 #[serde(default = "default_billing_model")]
9631 pub billing_model: String,
9632
9633 #[serde(default = "default_hourly_rate")]
9635 pub avg_hourly_rate: f64,
9636
9637 #[serde(default)]
9639 pub trust_accounting: TrustAccountingConfig,
9640
9641 #[serde(default)]
9643 pub anomaly_rates: ProfessionalServicesAnomalyRates,
9644}
9645
9646fn default_firm_type() -> String {
9647 "consulting".to_string()
9648}
9649
9650fn default_billing_model() -> String {
9651 "time_and_materials".to_string()
9652}
9653
9654fn default_hourly_rate() -> f64 {
9655 250.0
9656}
9657
9658impl Default for ProfessionalServicesConfig {
9659 fn default() -> Self {
9660 Self {
9661 enabled: false,
9662 firm_type: default_firm_type(),
9663 billing_model: default_billing_model(),
9664 avg_hourly_rate: default_hourly_rate(),
9665 trust_accounting: TrustAccountingConfig::default(),
9666 anomaly_rates: ProfessionalServicesAnomalyRates::default(),
9667 }
9668 }
9669}
9670
9671#[derive(Debug, Clone, Serialize, Deserialize)]
9673pub struct TrustAccountingConfig {
9674 #[serde(default)]
9676 pub enabled: bool,
9677
9678 #[serde(default = "default_true")]
9680 pub require_three_way_reconciliation: bool,
9681}
9682
9683impl Default for TrustAccountingConfig {
9684 fn default() -> Self {
9685 Self {
9686 enabled: false,
9687 require_three_way_reconciliation: true,
9688 }
9689 }
9690}
9691
9692#[derive(Debug, Clone, Serialize, Deserialize)]
9694pub struct ProfessionalServicesAnomalyRates {
9695 #[serde(default = "default_time_fraud_rate")]
9697 pub time_billing_fraud: f64,
9698
9699 #[serde(default = "default_expense_fraud_rate")]
9701 pub expense_fraud: f64,
9702
9703 #[serde(default = "default_trust_misappropriation_rate")]
9705 pub trust_misappropriation: f64,
9706}
9707
9708fn default_time_fraud_rate() -> f64 {
9709 0.02
9710}
9711
9712fn default_expense_fraud_rate() -> f64 {
9713 0.015
9714}
9715
9716fn default_trust_misappropriation_rate() -> f64 {
9717 0.003
9718}
9719
9720impl Default for ProfessionalServicesAnomalyRates {
9721 fn default() -> Self {
9722 Self {
9723 time_billing_fraud: default_time_fraud_rate(),
9724 expense_fraud: default_expense_fraud_rate(),
9725 trust_misappropriation: default_trust_misappropriation_rate(),
9726 }
9727 }
9728}
9729
9730#[derive(Debug, Clone, Serialize, Deserialize)]
9744pub struct FingerprintPrivacyConfig {
9745 #[serde(default)]
9747 pub level: String,
9748 #[serde(default = "default_epsilon")]
9750 pub epsilon: f64,
9751 #[serde(default = "default_delta")]
9753 pub delta: f64,
9754 #[serde(default = "default_k_anonymity")]
9756 pub k_anonymity: u32,
9757 #[serde(default)]
9759 pub composition_method: String,
9760}
9761
9762fn default_epsilon() -> f64 {
9763 1.0
9764}
9765
9766fn default_delta() -> f64 {
9767 1e-5
9768}
9769
9770fn default_k_anonymity() -> u32 {
9771 5
9772}
9773
9774impl Default for FingerprintPrivacyConfig {
9775 fn default() -> Self {
9776 Self {
9777 level: "standard".to_string(),
9778 epsilon: default_epsilon(),
9779 delta: default_delta(),
9780 k_anonymity: default_k_anonymity(),
9781 composition_method: "naive".to_string(),
9782 }
9783 }
9784}
9785
9786#[derive(Debug, Clone, Serialize, Deserialize)]
9800pub struct QualityGatesSchemaConfig {
9801 #[serde(default)]
9803 pub enabled: bool,
9804 #[serde(default = "default_gate_profile_name")]
9806 pub profile: String,
9807 #[serde(default)]
9809 pub fail_on_violation: bool,
9810 #[serde(default)]
9812 pub custom_gates: Vec<QualityGateEntry>,
9813}
9814
9815fn default_gate_profile_name() -> String {
9816 "default".to_string()
9817}
9818
9819impl Default for QualityGatesSchemaConfig {
9820 fn default() -> Self {
9821 Self {
9822 enabled: false,
9823 profile: default_gate_profile_name(),
9824 fail_on_violation: false,
9825 custom_gates: Vec::new(),
9826 }
9827 }
9828}
9829
9830#[derive(Debug, Clone, Serialize, Deserialize)]
9832pub struct QualityGateEntry {
9833 pub name: String,
9835 pub metric: String,
9839 pub threshold: f64,
9841 #[serde(default)]
9843 pub upper_threshold: Option<f64>,
9844 #[serde(default = "default_gate_comparison")]
9846 pub comparison: String,
9847}
9848
9849fn default_gate_comparison() -> String {
9850 "gte".to_string()
9851}
9852
9853#[derive(Debug, Clone, Default, Serialize, Deserialize)]
9863pub struct ComplianceSchemaConfig {
9864 #[serde(default)]
9866 pub content_marking: ContentMarkingSchemaConfig,
9867 #[serde(default)]
9869 pub article10_report: bool,
9870 #[serde(default)]
9872 pub certificates: CertificateSchemaConfig,
9873}
9874
9875#[derive(Debug, Clone, Default, Serialize, Deserialize)]
9877pub struct CertificateSchemaConfig {
9878 #[serde(default)]
9880 pub enabled: bool,
9881 #[serde(default)]
9883 pub signing_key_env: Option<String>,
9884 #[serde(default)]
9886 pub include_quality_metrics: bool,
9887}
9888
9889#[derive(Debug, Clone, Serialize, Deserialize)]
9891pub struct ContentMarkingSchemaConfig {
9892 #[serde(default = "default_true")]
9894 pub enabled: bool,
9895 #[serde(default = "default_marking_format")]
9897 pub format: String,
9898}
9899
9900fn default_marking_format() -> String {
9901 "embedded".to_string()
9902}
9903
9904impl Default for ContentMarkingSchemaConfig {
9905 fn default() -> Self {
9906 Self {
9907 enabled: true,
9908 format: default_marking_format(),
9909 }
9910 }
9911}
9912
9913#[derive(Debug, Clone, Default, Serialize, Deserialize)]
9915pub struct WebhookSchemaConfig {
9916 #[serde(default)]
9918 pub enabled: bool,
9919 #[serde(default)]
9921 pub endpoints: Vec<WebhookEndpointConfig>,
9922}
9923
9924#[derive(Debug, Clone, Serialize, Deserialize)]
9926pub struct WebhookEndpointConfig {
9927 pub url: String,
9929 #[serde(default)]
9931 pub events: Vec<String>,
9932 #[serde(default)]
9934 pub secret: Option<String>,
9935 #[serde(default = "default_webhook_retries")]
9937 pub max_retries: u32,
9938 #[serde(default = "default_webhook_timeout")]
9940 pub timeout_secs: u64,
9941}
9942
9943fn default_webhook_retries() -> u32 {
9944 3
9945}
9946fn default_webhook_timeout() -> u64 {
9947 10
9948}
9949
9950#[derive(Debug, Clone, Default, Serialize, Deserialize)]
9956pub struct SourceToPayConfig {
9957 #[serde(default)]
9959 pub enabled: bool,
9960 #[serde(default)]
9962 pub spend_analysis: SpendAnalysisConfig,
9963 #[serde(default)]
9965 pub sourcing: SourcingConfig,
9966 #[serde(default)]
9968 pub qualification: QualificationConfig,
9969 #[serde(default)]
9971 pub rfx: RfxConfig,
9972 #[serde(default)]
9974 pub contracts: ContractConfig,
9975 #[serde(default)]
9977 pub catalog: CatalogConfig,
9978 #[serde(default)]
9980 pub scorecards: ScorecardConfig,
9981 #[serde(default)]
9983 pub p2p_integration: P2PIntegrationConfig,
9984}
9985
9986#[derive(Debug, Clone, Serialize, Deserialize)]
9988pub struct SpendAnalysisConfig {
9989 #[serde(default = "default_hhi_threshold")]
9991 pub hhi_threshold: f64,
9992 #[serde(default = "default_contract_coverage_target")]
9994 pub contract_coverage_target: f64,
9995}
9996
9997impl Default for SpendAnalysisConfig {
9998 fn default() -> Self {
9999 Self {
10000 hhi_threshold: default_hhi_threshold(),
10001 contract_coverage_target: default_contract_coverage_target(),
10002 }
10003 }
10004}
10005
10006fn default_hhi_threshold() -> f64 {
10007 2500.0
10008}
10009fn default_contract_coverage_target() -> f64 {
10010 0.80
10011}
10012
10013#[derive(Debug, Clone, Serialize, Deserialize)]
10015pub struct SourcingConfig {
10016 #[serde(default = "default_sourcing_projects_per_year")]
10018 pub projects_per_year: u32,
10019 #[serde(default = "default_renewal_horizon_months")]
10021 pub renewal_horizon_months: u32,
10022 #[serde(default = "default_project_duration_months")]
10024 pub project_duration_months: u32,
10025}
10026
10027impl Default for SourcingConfig {
10028 fn default() -> Self {
10029 Self {
10030 projects_per_year: default_sourcing_projects_per_year(),
10031 renewal_horizon_months: default_renewal_horizon_months(),
10032 project_duration_months: default_project_duration_months(),
10033 }
10034 }
10035}
10036
10037fn default_sourcing_projects_per_year() -> u32 {
10038 10
10039}
10040fn default_renewal_horizon_months() -> u32 {
10041 3
10042}
10043fn default_project_duration_months() -> u32 {
10044 4
10045}
10046
10047#[derive(Debug, Clone, Serialize, Deserialize)]
10049pub struct QualificationConfig {
10050 #[serde(default = "default_qualification_pass_rate")]
10052 pub pass_rate: f64,
10053 #[serde(default = "default_qualification_validity_days")]
10055 pub validity_days: u32,
10056 #[serde(default = "default_financial_weight")]
10058 pub financial_weight: f64,
10059 #[serde(default = "default_quality_weight")]
10061 pub quality_weight: f64,
10062 #[serde(default = "default_delivery_weight")]
10064 pub delivery_weight: f64,
10065 #[serde(default = "default_compliance_weight")]
10067 pub compliance_weight: f64,
10068}
10069
10070impl Default for QualificationConfig {
10071 fn default() -> Self {
10072 Self {
10073 pass_rate: default_qualification_pass_rate(),
10074 validity_days: default_qualification_validity_days(),
10075 financial_weight: default_financial_weight(),
10076 quality_weight: default_quality_weight(),
10077 delivery_weight: default_delivery_weight(),
10078 compliance_weight: default_compliance_weight(),
10079 }
10080 }
10081}
10082
10083fn default_qualification_pass_rate() -> f64 {
10084 0.75
10085}
10086fn default_qualification_validity_days() -> u32 {
10087 365
10088}
10089fn default_financial_weight() -> f64 {
10090 0.25
10091}
10092fn default_quality_weight() -> f64 {
10093 0.30
10094}
10095fn default_delivery_weight() -> f64 {
10096 0.25
10097}
10098fn default_compliance_weight() -> f64 {
10099 0.20
10100}
10101
10102#[derive(Debug, Clone, Serialize, Deserialize)]
10104pub struct RfxConfig {
10105 #[serde(default = "default_rfi_threshold")]
10107 pub rfi_threshold: f64,
10108 #[serde(default = "default_min_invited_vendors")]
10110 pub min_invited_vendors: u32,
10111 #[serde(default = "default_max_invited_vendors")]
10113 pub max_invited_vendors: u32,
10114 #[serde(default = "default_response_rate")]
10116 pub response_rate: f64,
10117 #[serde(default = "default_price_weight")]
10119 pub default_price_weight: f64,
10120 #[serde(default = "default_rfx_quality_weight")]
10122 pub default_quality_weight: f64,
10123 #[serde(default = "default_rfx_delivery_weight")]
10125 pub default_delivery_weight: f64,
10126}
10127
10128impl Default for RfxConfig {
10129 fn default() -> Self {
10130 Self {
10131 rfi_threshold: default_rfi_threshold(),
10132 min_invited_vendors: default_min_invited_vendors(),
10133 max_invited_vendors: default_max_invited_vendors(),
10134 response_rate: default_response_rate(),
10135 default_price_weight: default_price_weight(),
10136 default_quality_weight: default_rfx_quality_weight(),
10137 default_delivery_weight: default_rfx_delivery_weight(),
10138 }
10139 }
10140}
10141
10142fn default_rfi_threshold() -> f64 {
10143 100_000.0
10144}
10145fn default_min_invited_vendors() -> u32 {
10146 3
10147}
10148fn default_max_invited_vendors() -> u32 {
10149 8
10150}
10151fn default_response_rate() -> f64 {
10152 0.70
10153}
10154fn default_price_weight() -> f64 {
10155 0.40
10156}
10157fn default_rfx_quality_weight() -> f64 {
10158 0.35
10159}
10160fn default_rfx_delivery_weight() -> f64 {
10161 0.25
10162}
10163
10164#[derive(Debug, Clone, Serialize, Deserialize)]
10166pub struct ContractConfig {
10167 #[serde(default = "default_min_contract_months")]
10169 pub min_duration_months: u32,
10170 #[serde(default = "default_max_contract_months")]
10172 pub max_duration_months: u32,
10173 #[serde(default = "default_auto_renewal_rate")]
10175 pub auto_renewal_rate: f64,
10176 #[serde(default = "default_amendment_rate")]
10178 pub amendment_rate: f64,
10179 #[serde(default)]
10181 pub type_distribution: ContractTypeDistribution,
10182}
10183
10184impl Default for ContractConfig {
10185 fn default() -> Self {
10186 Self {
10187 min_duration_months: default_min_contract_months(),
10188 max_duration_months: default_max_contract_months(),
10189 auto_renewal_rate: default_auto_renewal_rate(),
10190 amendment_rate: default_amendment_rate(),
10191 type_distribution: ContractTypeDistribution::default(),
10192 }
10193 }
10194}
10195
10196fn default_min_contract_months() -> u32 {
10197 12
10198}
10199fn default_max_contract_months() -> u32 {
10200 36
10201}
10202fn default_auto_renewal_rate() -> f64 {
10203 0.40
10204}
10205fn default_amendment_rate() -> f64 {
10206 0.20
10207}
10208
10209#[derive(Debug, Clone, Serialize, Deserialize)]
10211pub struct ContractTypeDistribution {
10212 #[serde(default = "default_fixed_price_pct")]
10214 pub fixed_price: f64,
10215 #[serde(default = "default_blanket_pct")]
10217 pub blanket: f64,
10218 #[serde(default = "default_time_materials_pct")]
10220 pub time_and_materials: f64,
10221 #[serde(default = "default_service_agreement_pct")]
10223 pub service_agreement: f64,
10224}
10225
10226impl Default for ContractTypeDistribution {
10227 fn default() -> Self {
10228 Self {
10229 fixed_price: default_fixed_price_pct(),
10230 blanket: default_blanket_pct(),
10231 time_and_materials: default_time_materials_pct(),
10232 service_agreement: default_service_agreement_pct(),
10233 }
10234 }
10235}
10236
10237fn default_fixed_price_pct() -> f64 {
10238 0.40
10239}
10240fn default_blanket_pct() -> f64 {
10241 0.30
10242}
10243fn default_time_materials_pct() -> f64 {
10244 0.15
10245}
10246fn default_service_agreement_pct() -> f64 {
10247 0.15
10248}
10249
10250#[derive(Debug, Clone, Serialize, Deserialize)]
10252pub struct CatalogConfig {
10253 #[serde(default = "default_preferred_vendor_flag_rate")]
10255 pub preferred_vendor_flag_rate: f64,
10256 #[serde(default = "default_multi_source_rate")]
10258 pub multi_source_rate: f64,
10259}
10260
10261impl Default for CatalogConfig {
10262 fn default() -> Self {
10263 Self {
10264 preferred_vendor_flag_rate: default_preferred_vendor_flag_rate(),
10265 multi_source_rate: default_multi_source_rate(),
10266 }
10267 }
10268}
10269
10270fn default_preferred_vendor_flag_rate() -> f64 {
10271 0.70
10272}
10273fn default_multi_source_rate() -> f64 {
10274 0.25
10275}
10276
10277#[derive(Debug, Clone, Serialize, Deserialize)]
10279pub struct ScorecardConfig {
10280 #[serde(default = "default_scorecard_frequency")]
10282 pub frequency: String,
10283 #[serde(default = "default_otd_weight")]
10285 pub on_time_delivery_weight: f64,
10286 #[serde(default = "default_quality_score_weight")]
10288 pub quality_weight: f64,
10289 #[serde(default = "default_price_score_weight")]
10291 pub price_weight: f64,
10292 #[serde(default = "default_responsiveness_weight")]
10294 pub responsiveness_weight: f64,
10295 #[serde(default = "default_grade_a_threshold")]
10297 pub grade_a_threshold: f64,
10298 #[serde(default = "default_grade_b_threshold")]
10300 pub grade_b_threshold: f64,
10301 #[serde(default = "default_grade_c_threshold")]
10303 pub grade_c_threshold: f64,
10304}
10305
10306impl Default for ScorecardConfig {
10307 fn default() -> Self {
10308 Self {
10309 frequency: default_scorecard_frequency(),
10310 on_time_delivery_weight: default_otd_weight(),
10311 quality_weight: default_quality_score_weight(),
10312 price_weight: default_price_score_weight(),
10313 responsiveness_weight: default_responsiveness_weight(),
10314 grade_a_threshold: default_grade_a_threshold(),
10315 grade_b_threshold: default_grade_b_threshold(),
10316 grade_c_threshold: default_grade_c_threshold(),
10317 }
10318 }
10319}
10320
10321fn default_scorecard_frequency() -> String {
10322 "quarterly".to_string()
10323}
10324fn default_otd_weight() -> f64 {
10325 0.30
10326}
10327fn default_quality_score_weight() -> f64 {
10328 0.30
10329}
10330fn default_price_score_weight() -> f64 {
10331 0.25
10332}
10333fn default_responsiveness_weight() -> f64 {
10334 0.15
10335}
10336fn default_grade_a_threshold() -> f64 {
10337 90.0
10338}
10339fn default_grade_b_threshold() -> f64 {
10340 75.0
10341}
10342fn default_grade_c_threshold() -> f64 {
10343 60.0
10344}
10345
10346#[derive(Debug, Clone, Serialize, Deserialize)]
10348pub struct P2PIntegrationConfig {
10349 #[serde(default = "default_off_contract_rate")]
10351 pub off_contract_rate: f64,
10352 #[serde(default = "default_price_tolerance")]
10354 pub price_tolerance: f64,
10355 #[serde(default)]
10357 pub catalog_enforcement: bool,
10358}
10359
10360impl Default for P2PIntegrationConfig {
10361 fn default() -> Self {
10362 Self {
10363 off_contract_rate: default_off_contract_rate(),
10364 price_tolerance: default_price_tolerance(),
10365 catalog_enforcement: false,
10366 }
10367 }
10368}
10369
10370fn default_off_contract_rate() -> f64 {
10371 0.15
10372}
10373fn default_price_tolerance() -> f64 {
10374 0.02
10375}
10376
10377#[derive(Debug, Clone, Serialize, Deserialize)]
10381pub struct FinancialReportingConfig {
10382 #[serde(default)]
10384 pub enabled: bool,
10385 #[serde(default = "default_true")]
10387 pub generate_balance_sheet: bool,
10388 #[serde(default = "default_true")]
10390 pub generate_income_statement: bool,
10391 #[serde(default = "default_true")]
10393 pub generate_cash_flow: bool,
10394 #[serde(default = "default_true")]
10396 pub generate_changes_in_equity: bool,
10397 #[serde(default = "default_comparative_periods")]
10399 pub comparative_periods: u32,
10400 #[serde(default)]
10402 pub management_kpis: ManagementKpisConfig,
10403 #[serde(default)]
10405 pub budgets: BudgetConfig,
10406}
10407
10408impl Default for FinancialReportingConfig {
10409 fn default() -> Self {
10410 Self {
10411 enabled: false,
10412 generate_balance_sheet: true,
10413 generate_income_statement: true,
10414 generate_cash_flow: true,
10415 generate_changes_in_equity: true,
10416 comparative_periods: default_comparative_periods(),
10417 management_kpis: ManagementKpisConfig::default(),
10418 budgets: BudgetConfig::default(),
10419 }
10420 }
10421}
10422
10423fn default_comparative_periods() -> u32 {
10424 1
10425}
10426
10427#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10429pub struct ManagementKpisConfig {
10430 #[serde(default)]
10432 pub enabled: bool,
10433 #[serde(default = "default_kpi_frequency")]
10435 pub frequency: String,
10436}
10437
10438fn default_kpi_frequency() -> String {
10439 "monthly".to_string()
10440}
10441
10442#[derive(Debug, Clone, Serialize, Deserialize)]
10444pub struct BudgetConfig {
10445 #[serde(default)]
10447 pub enabled: bool,
10448 #[serde(default = "default_revenue_growth_rate")]
10450 pub revenue_growth_rate: f64,
10451 #[serde(default = "default_expense_inflation_rate")]
10453 pub expense_inflation_rate: f64,
10454 #[serde(default = "default_variance_noise")]
10456 pub variance_noise: f64,
10457}
10458
10459impl Default for BudgetConfig {
10460 fn default() -> Self {
10461 Self {
10462 enabled: false,
10463 revenue_growth_rate: default_revenue_growth_rate(),
10464 expense_inflation_rate: default_expense_inflation_rate(),
10465 variance_noise: default_variance_noise(),
10466 }
10467 }
10468}
10469
10470fn default_revenue_growth_rate() -> f64 {
10471 0.05
10472}
10473fn default_expense_inflation_rate() -> f64 {
10474 0.03
10475}
10476fn default_variance_noise() -> f64 {
10477 0.10
10478}
10479
10480#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10484pub struct HrConfig {
10485 #[serde(default)]
10487 pub enabled: bool,
10488 #[serde(default)]
10490 pub payroll: PayrollConfig,
10491 #[serde(default)]
10493 pub time_attendance: TimeAttendanceConfig,
10494 #[serde(default)]
10496 pub expenses: ExpenseConfig,
10497}
10498
10499#[derive(Debug, Clone, Serialize, Deserialize)]
10501pub struct PayrollConfig {
10502 #[serde(default = "default_true")]
10504 pub enabled: bool,
10505 #[serde(default = "default_pay_frequency")]
10507 pub pay_frequency: String,
10508 #[serde(default)]
10510 pub salary_ranges: PayrollSalaryRanges,
10511 #[serde(default)]
10513 pub tax_rates: PayrollTaxRates,
10514 #[serde(default = "default_benefits_enrollment_rate")]
10516 pub benefits_enrollment_rate: f64,
10517 #[serde(default = "default_retirement_participation_rate")]
10519 pub retirement_participation_rate: f64,
10520}
10521
10522impl Default for PayrollConfig {
10523 fn default() -> Self {
10524 Self {
10525 enabled: true,
10526 pay_frequency: default_pay_frequency(),
10527 salary_ranges: PayrollSalaryRanges::default(),
10528 tax_rates: PayrollTaxRates::default(),
10529 benefits_enrollment_rate: default_benefits_enrollment_rate(),
10530 retirement_participation_rate: default_retirement_participation_rate(),
10531 }
10532 }
10533}
10534
10535fn default_pay_frequency() -> String {
10536 "monthly".to_string()
10537}
10538fn default_benefits_enrollment_rate() -> f64 {
10539 0.60
10540}
10541fn default_retirement_participation_rate() -> f64 {
10542 0.45
10543}
10544
10545#[derive(Debug, Clone, Serialize, Deserialize)]
10547pub struct PayrollSalaryRanges {
10548 #[serde(default = "default_staff_min")]
10550 pub staff_min: f64,
10551 #[serde(default = "default_staff_max")]
10552 pub staff_max: f64,
10553 #[serde(default = "default_manager_min")]
10555 pub manager_min: f64,
10556 #[serde(default = "default_manager_max")]
10557 pub manager_max: f64,
10558 #[serde(default = "default_director_min")]
10560 pub director_min: f64,
10561 #[serde(default = "default_director_max")]
10562 pub director_max: f64,
10563 #[serde(default = "default_executive_min")]
10565 pub executive_min: f64,
10566 #[serde(default = "default_executive_max")]
10567 pub executive_max: f64,
10568}
10569
10570impl Default for PayrollSalaryRanges {
10571 fn default() -> Self {
10572 Self {
10573 staff_min: default_staff_min(),
10574 staff_max: default_staff_max(),
10575 manager_min: default_manager_min(),
10576 manager_max: default_manager_max(),
10577 director_min: default_director_min(),
10578 director_max: default_director_max(),
10579 executive_min: default_executive_min(),
10580 executive_max: default_executive_max(),
10581 }
10582 }
10583}
10584
10585fn default_staff_min() -> f64 {
10586 50_000.0
10587}
10588fn default_staff_max() -> f64 {
10589 70_000.0
10590}
10591fn default_manager_min() -> f64 {
10592 80_000.0
10593}
10594fn default_manager_max() -> f64 {
10595 120_000.0
10596}
10597fn default_director_min() -> f64 {
10598 120_000.0
10599}
10600fn default_director_max() -> f64 {
10601 180_000.0
10602}
10603fn default_executive_min() -> f64 {
10604 180_000.0
10605}
10606fn default_executive_max() -> f64 {
10607 350_000.0
10608}
10609
10610#[derive(Debug, Clone, Serialize, Deserialize)]
10612pub struct PayrollTaxRates {
10613 #[serde(default = "default_federal_rate")]
10615 pub federal_effective: f64,
10616 #[serde(default = "default_state_rate")]
10618 pub state_effective: f64,
10619 #[serde(default = "default_fica_rate")]
10621 pub fica: f64,
10622}
10623
10624impl Default for PayrollTaxRates {
10625 fn default() -> Self {
10626 Self {
10627 federal_effective: default_federal_rate(),
10628 state_effective: default_state_rate(),
10629 fica: default_fica_rate(),
10630 }
10631 }
10632}
10633
10634fn default_federal_rate() -> f64 {
10635 0.22
10636}
10637fn default_state_rate() -> f64 {
10638 0.05
10639}
10640fn default_fica_rate() -> f64 {
10641 0.0765
10642}
10643
10644#[derive(Debug, Clone, Serialize, Deserialize)]
10646pub struct TimeAttendanceConfig {
10647 #[serde(default = "default_true")]
10649 pub enabled: bool,
10650 #[serde(default = "default_overtime_rate")]
10652 pub overtime_rate: f64,
10653}
10654
10655impl Default for TimeAttendanceConfig {
10656 fn default() -> Self {
10657 Self {
10658 enabled: true,
10659 overtime_rate: default_overtime_rate(),
10660 }
10661 }
10662}
10663
10664fn default_overtime_rate() -> f64 {
10665 0.10
10666}
10667
10668#[derive(Debug, Clone, Serialize, Deserialize)]
10670pub struct ExpenseConfig {
10671 #[serde(default = "default_true")]
10673 pub enabled: bool,
10674 #[serde(default = "default_expense_submission_rate")]
10676 pub submission_rate: f64,
10677 #[serde(default = "default_policy_violation_rate")]
10679 pub policy_violation_rate: f64,
10680}
10681
10682impl Default for ExpenseConfig {
10683 fn default() -> Self {
10684 Self {
10685 enabled: true,
10686 submission_rate: default_expense_submission_rate(),
10687 policy_violation_rate: default_policy_violation_rate(),
10688 }
10689 }
10690}
10691
10692fn default_expense_submission_rate() -> f64 {
10693 0.30
10694}
10695fn default_policy_violation_rate() -> f64 {
10696 0.08
10697}
10698
10699#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10703pub struct ManufacturingProcessConfig {
10704 #[serde(default)]
10706 pub enabled: bool,
10707 #[serde(default)]
10709 pub production_orders: ProductionOrderConfig,
10710 #[serde(default)]
10712 pub costing: ManufacturingCostingConfig,
10713 #[serde(default)]
10715 pub routing: RoutingConfig,
10716}
10717
10718#[derive(Debug, Clone, Serialize, Deserialize)]
10720pub struct ProductionOrderConfig {
10721 #[serde(default = "default_prod_orders_per_month")]
10723 pub orders_per_month: u32,
10724 #[serde(default = "default_prod_avg_batch_size")]
10726 pub avg_batch_size: u32,
10727 #[serde(default = "default_prod_yield_rate")]
10729 pub yield_rate: f64,
10730 #[serde(default = "default_prod_make_to_order_rate")]
10732 pub make_to_order_rate: f64,
10733 #[serde(default = "default_prod_rework_rate")]
10735 pub rework_rate: f64,
10736}
10737
10738impl Default for ProductionOrderConfig {
10739 fn default() -> Self {
10740 Self {
10741 orders_per_month: default_prod_orders_per_month(),
10742 avg_batch_size: default_prod_avg_batch_size(),
10743 yield_rate: default_prod_yield_rate(),
10744 make_to_order_rate: default_prod_make_to_order_rate(),
10745 rework_rate: default_prod_rework_rate(),
10746 }
10747 }
10748}
10749
10750fn default_prod_orders_per_month() -> u32 {
10751 50
10752}
10753fn default_prod_avg_batch_size() -> u32 {
10754 100
10755}
10756fn default_prod_yield_rate() -> f64 {
10757 0.97
10758}
10759fn default_prod_make_to_order_rate() -> f64 {
10760 0.20
10761}
10762fn default_prod_rework_rate() -> f64 {
10763 0.03
10764}
10765
10766#[derive(Debug, Clone, Serialize, Deserialize)]
10768pub struct ManufacturingCostingConfig {
10769 #[serde(default = "default_labor_rate")]
10771 pub labor_rate_per_hour: f64,
10772 #[serde(default = "default_overhead_rate")]
10774 pub overhead_rate: f64,
10775 #[serde(default = "default_cost_update_frequency")]
10777 pub standard_cost_update_frequency: String,
10778}
10779
10780impl Default for ManufacturingCostingConfig {
10781 fn default() -> Self {
10782 Self {
10783 labor_rate_per_hour: default_labor_rate(),
10784 overhead_rate: default_overhead_rate(),
10785 standard_cost_update_frequency: default_cost_update_frequency(),
10786 }
10787 }
10788}
10789
10790fn default_labor_rate() -> f64 {
10791 35.0
10792}
10793fn default_overhead_rate() -> f64 {
10794 1.50
10795}
10796fn default_cost_update_frequency() -> String {
10797 "quarterly".to_string()
10798}
10799
10800#[derive(Debug, Clone, Serialize, Deserialize)]
10802pub struct RoutingConfig {
10803 #[serde(default = "default_avg_operations")]
10805 pub avg_operations: u32,
10806 #[serde(default = "default_setup_time")]
10808 pub setup_time_hours: f64,
10809 #[serde(default = "default_run_time_variation")]
10811 pub run_time_variation: f64,
10812}
10813
10814impl Default for RoutingConfig {
10815 fn default() -> Self {
10816 Self {
10817 avg_operations: default_avg_operations(),
10818 setup_time_hours: default_setup_time(),
10819 run_time_variation: default_run_time_variation(),
10820 }
10821 }
10822}
10823
10824fn default_avg_operations() -> u32 {
10825 4
10826}
10827fn default_setup_time() -> f64 {
10828 1.5
10829}
10830fn default_run_time_variation() -> f64 {
10831 0.15
10832}
10833
10834#[derive(Debug, Clone, Serialize, Deserialize)]
10838pub struct SalesQuoteConfig {
10839 #[serde(default)]
10841 pub enabled: bool,
10842 #[serde(default = "default_quotes_per_month")]
10844 pub quotes_per_month: u32,
10845 #[serde(default = "default_quote_win_rate")]
10847 pub win_rate: f64,
10848 #[serde(default = "default_quote_validity_days")]
10850 pub validity_days: u32,
10851}
10852
10853impl Default for SalesQuoteConfig {
10854 fn default() -> Self {
10855 Self {
10856 enabled: false,
10857 quotes_per_month: default_quotes_per_month(),
10858 win_rate: default_quote_win_rate(),
10859 validity_days: default_quote_validity_days(),
10860 }
10861 }
10862}
10863
10864fn default_quotes_per_month() -> u32 {
10865 30
10866}
10867fn default_quote_win_rate() -> f64 {
10868 0.35
10869}
10870fn default_quote_validity_days() -> u32 {
10871 30
10872}
10873
10874#[derive(Debug, Clone, Serialize, Deserialize)]
10883pub struct TaxConfig {
10884 #[serde(default)]
10886 pub enabled: bool,
10887 #[serde(default)]
10889 pub jurisdictions: TaxJurisdictionConfig,
10890 #[serde(default)]
10892 pub vat_gst: VatGstConfig,
10893 #[serde(default)]
10895 pub sales_tax: SalesTaxConfig,
10896 #[serde(default)]
10898 pub withholding: WithholdingTaxSchemaConfig,
10899 #[serde(default)]
10901 pub provisions: TaxProvisionSchemaConfig,
10902 #[serde(default)]
10904 pub payroll_tax: PayrollTaxSchemaConfig,
10905 #[serde(default = "default_tax_anomaly_rate")]
10907 pub anomaly_rate: f64,
10908}
10909
10910fn default_tax_anomaly_rate() -> f64 {
10911 0.03
10912}
10913
10914impl Default for TaxConfig {
10915 fn default() -> Self {
10916 Self {
10917 enabled: false,
10918 jurisdictions: TaxJurisdictionConfig::default(),
10919 vat_gst: VatGstConfig::default(),
10920 sales_tax: SalesTaxConfig::default(),
10921 withholding: WithholdingTaxSchemaConfig::default(),
10922 provisions: TaxProvisionSchemaConfig::default(),
10923 payroll_tax: PayrollTaxSchemaConfig::default(),
10924 anomaly_rate: default_tax_anomaly_rate(),
10925 }
10926 }
10927}
10928
10929#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10934pub struct TaxJurisdictionConfig {
10935 #[serde(default)]
10937 pub countries: Vec<String>,
10938 #[serde(default)]
10940 pub include_subnational: bool,
10941}
10942
10943#[derive(Debug, Clone, Serialize, Deserialize)]
10948pub struct VatGstConfig {
10949 #[serde(default)]
10951 pub enabled: bool,
10952 #[serde(default)]
10954 pub standard_rates: std::collections::HashMap<String, f64>,
10955 #[serde(default)]
10957 pub reduced_rates: std::collections::HashMap<String, f64>,
10958 #[serde(default)]
10960 pub exempt_categories: Vec<String>,
10961 #[serde(default = "default_true")]
10963 pub reverse_charge: bool,
10964}
10965
10966impl Default for VatGstConfig {
10967 fn default() -> Self {
10968 Self {
10969 enabled: false,
10970 standard_rates: std::collections::HashMap::new(),
10971 reduced_rates: std::collections::HashMap::new(),
10972 exempt_categories: Vec::new(),
10973 reverse_charge: true,
10974 }
10975 }
10976}
10977
10978#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10982pub struct SalesTaxConfig {
10983 #[serde(default)]
10985 pub enabled: bool,
10986 #[serde(default)]
10988 pub nexus_states: Vec<String>,
10989}
10990
10991#[derive(Debug, Clone, Serialize, Deserialize)]
10996pub struct WithholdingTaxSchemaConfig {
10997 #[serde(default)]
10999 pub enabled: bool,
11000 #[serde(default = "default_true")]
11002 pub treaty_network: bool,
11003 #[serde(default = "default_withholding_rate")]
11005 pub default_rate: f64,
11006 #[serde(default = "default_treaty_reduced_rate")]
11008 pub treaty_reduced_rate: f64,
11009}
11010
11011fn default_withholding_rate() -> f64 {
11012 0.30
11013}
11014
11015fn default_treaty_reduced_rate() -> f64 {
11016 0.15
11017}
11018
11019impl Default for WithholdingTaxSchemaConfig {
11020 fn default() -> Self {
11021 Self {
11022 enabled: false,
11023 treaty_network: true,
11024 default_rate: default_withholding_rate(),
11025 treaty_reduced_rate: default_treaty_reduced_rate(),
11026 }
11027 }
11028}
11029
11030#[derive(Debug, Clone, Serialize, Deserialize)]
11035pub struct TaxProvisionSchemaConfig {
11036 #[serde(default = "default_true")]
11039 pub enabled: bool,
11040 #[serde(default = "default_statutory_rate")]
11042 pub statutory_rate: f64,
11043 #[serde(default = "default_true")]
11045 pub uncertain_positions: bool,
11046}
11047
11048fn default_statutory_rate() -> f64 {
11049 0.21
11050}
11051
11052impl Default for TaxProvisionSchemaConfig {
11053 fn default() -> Self {
11054 Self {
11055 enabled: true,
11056 statutory_rate: default_statutory_rate(),
11057 uncertain_positions: true,
11058 }
11059 }
11060}
11061
11062#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11067pub struct PayrollTaxSchemaConfig {
11068 #[serde(default)]
11070 pub enabled: bool,
11071}
11072
11073#[derive(Debug, Clone, Serialize, Deserialize)]
11083pub struct TreasuryConfig {
11084 #[serde(default)]
11086 pub enabled: bool,
11087 #[serde(default)]
11089 pub cash_positioning: CashPositioningConfig,
11090 #[serde(default)]
11092 pub cash_forecasting: CashForecastingConfig,
11093 #[serde(default)]
11095 pub cash_pooling: CashPoolingConfig,
11096 #[serde(default)]
11098 pub hedging: HedgingSchemaConfig,
11099 #[serde(default)]
11101 pub debt: DebtSchemaConfig,
11102 #[serde(default)]
11104 pub netting: NettingSchemaConfig,
11105 #[serde(default)]
11107 pub bank_guarantees: BankGuaranteeSchemaConfig,
11108 #[serde(default = "default_treasury_anomaly_rate")]
11110 pub anomaly_rate: f64,
11111}
11112
11113fn default_treasury_anomaly_rate() -> f64 {
11114 0.02
11115}
11116
11117impl Default for TreasuryConfig {
11118 fn default() -> Self {
11119 Self {
11120 enabled: false,
11121 cash_positioning: CashPositioningConfig::default(),
11122 cash_forecasting: CashForecastingConfig::default(),
11123 cash_pooling: CashPoolingConfig::default(),
11124 hedging: HedgingSchemaConfig::default(),
11125 debt: DebtSchemaConfig::default(),
11126 netting: NettingSchemaConfig::default(),
11127 bank_guarantees: BankGuaranteeSchemaConfig::default(),
11128 anomaly_rate: default_treasury_anomaly_rate(),
11129 }
11130 }
11131}
11132
11133#[derive(Debug, Clone, Serialize, Deserialize)]
11137pub struct CashPositioningConfig {
11138 #[serde(default = "default_true")]
11140 pub enabled: bool,
11141 #[serde(default = "default_cash_frequency")]
11143 pub frequency: String,
11144 #[serde(default = "default_minimum_balance_policy")]
11146 pub minimum_balance_policy: f64,
11147}
11148
11149fn default_cash_frequency() -> String {
11150 "daily".to_string()
11151}
11152
11153fn default_minimum_balance_policy() -> f64 {
11154 100_000.0
11155}
11156
11157impl Default for CashPositioningConfig {
11158 fn default() -> Self {
11159 Self {
11160 enabled: true,
11161 frequency: default_cash_frequency(),
11162 minimum_balance_policy: default_minimum_balance_policy(),
11163 }
11164 }
11165}
11166
11167#[derive(Debug, Clone, Serialize, Deserialize)]
11171pub struct CashForecastingConfig {
11172 #[serde(default = "default_true")]
11174 pub enabled: bool,
11175 #[serde(default = "default_horizon_days")]
11177 pub horizon_days: u32,
11178 #[serde(default = "default_ar_probability_curve")]
11180 pub ar_collection_probability_curve: String,
11181 #[serde(default = "default_confidence_interval")]
11183 pub confidence_interval: f64,
11184}
11185
11186fn default_horizon_days() -> u32 {
11187 90
11188}
11189
11190fn default_ar_probability_curve() -> String {
11191 "aging".to_string()
11192}
11193
11194fn default_confidence_interval() -> f64 {
11195 0.90
11196}
11197
11198impl Default for CashForecastingConfig {
11199 fn default() -> Self {
11200 Self {
11201 enabled: true,
11202 horizon_days: default_horizon_days(),
11203 ar_collection_probability_curve: default_ar_probability_curve(),
11204 confidence_interval: default_confidence_interval(),
11205 }
11206 }
11207}
11208
11209#[derive(Debug, Clone, Serialize, Deserialize)]
11213pub struct CashPoolingConfig {
11214 #[serde(default)]
11216 pub enabled: bool,
11217 #[serde(default = "default_pool_type")]
11219 pub pool_type: String,
11220 #[serde(default = "default_sweep_time")]
11222 pub sweep_time: String,
11223}
11224
11225fn default_pool_type() -> String {
11226 "zero_balancing".to_string()
11227}
11228
11229fn default_sweep_time() -> String {
11230 "16:00".to_string()
11231}
11232
11233impl Default for CashPoolingConfig {
11234 fn default() -> Self {
11235 Self {
11236 enabled: false,
11237 pool_type: default_pool_type(),
11238 sweep_time: default_sweep_time(),
11239 }
11240 }
11241}
11242
11243#[derive(Debug, Clone, Serialize, Deserialize)]
11248pub struct HedgingSchemaConfig {
11249 #[serde(default)]
11251 pub enabled: bool,
11252 #[serde(default = "default_hedge_ratio")]
11254 pub hedge_ratio: f64,
11255 #[serde(default = "default_hedge_instruments")]
11257 pub instruments: Vec<String>,
11258 #[serde(default = "default_true")]
11260 pub hedge_accounting: bool,
11261 #[serde(default = "default_effectiveness_method")]
11263 pub effectiveness_method: String,
11264}
11265
11266fn default_hedge_ratio() -> f64 {
11267 0.75
11268}
11269
11270fn default_hedge_instruments() -> Vec<String> {
11271 vec!["fx_forward".to_string(), "interest_rate_swap".to_string()]
11272}
11273
11274fn default_effectiveness_method() -> String {
11275 "regression".to_string()
11276}
11277
11278impl Default for HedgingSchemaConfig {
11279 fn default() -> Self {
11280 Self {
11281 enabled: false,
11282 hedge_ratio: default_hedge_ratio(),
11283 instruments: default_hedge_instruments(),
11284 hedge_accounting: true,
11285 effectiveness_method: default_effectiveness_method(),
11286 }
11287 }
11288}
11289
11290#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11295pub struct DebtSchemaConfig {
11296 #[serde(default)]
11298 pub enabled: bool,
11299 #[serde(default)]
11301 pub instruments: Vec<DebtInstrumentDef>,
11302 #[serde(default)]
11304 pub covenants: Vec<CovenantDef>,
11305}
11306
11307#[derive(Debug, Clone, Serialize, Deserialize)]
11309pub struct DebtInstrumentDef {
11310 #[serde(rename = "type")]
11312 pub instrument_type: String,
11313 #[serde(default)]
11315 pub principal: Option<f64>,
11316 #[serde(default)]
11318 pub rate: Option<f64>,
11319 #[serde(default)]
11321 pub maturity_months: Option<u32>,
11322 #[serde(default)]
11324 pub facility: Option<f64>,
11325}
11326
11327#[derive(Debug, Clone, Serialize, Deserialize)]
11329pub struct CovenantDef {
11330 #[serde(rename = "type")]
11333 pub covenant_type: String,
11334 pub threshold: f64,
11336}
11337
11338#[derive(Debug, Clone, Serialize, Deserialize)]
11342pub struct NettingSchemaConfig {
11343 #[serde(default)]
11345 pub enabled: bool,
11346 #[serde(default = "default_netting_cycle")]
11348 pub cycle: String,
11349}
11350
11351fn default_netting_cycle() -> String {
11352 "monthly".to_string()
11353}
11354
11355impl Default for NettingSchemaConfig {
11356 fn default() -> Self {
11357 Self {
11358 enabled: false,
11359 cycle: default_netting_cycle(),
11360 }
11361 }
11362}
11363
11364#[derive(Debug, Clone, Serialize, Deserialize)]
11368pub struct BankGuaranteeSchemaConfig {
11369 #[serde(default)]
11371 pub enabled: bool,
11372 #[serde(default = "default_guarantee_count")]
11374 pub count: u32,
11375}
11376
11377fn default_guarantee_count() -> u32 {
11378 5
11379}
11380
11381impl Default for BankGuaranteeSchemaConfig {
11382 fn default() -> Self {
11383 Self {
11384 enabled: false,
11385 count: default_guarantee_count(),
11386 }
11387 }
11388}
11389
11390#[derive(Debug, Clone, Serialize, Deserialize)]
11399pub struct ProjectAccountingConfig {
11400 #[serde(default)]
11402 pub enabled: bool,
11403 #[serde(default = "default_project_count")]
11405 pub project_count: u32,
11406 #[serde(default)]
11408 pub project_types: ProjectTypeDistribution,
11409 #[serde(default)]
11411 pub wbs: WbsSchemaConfig,
11412 #[serde(default)]
11414 pub cost_allocation: CostAllocationConfig,
11415 #[serde(default)]
11417 pub revenue_recognition: ProjectRevenueRecognitionConfig,
11418 #[serde(default)]
11420 pub milestones: MilestoneSchemaConfig,
11421 #[serde(default)]
11423 pub change_orders: ChangeOrderSchemaConfig,
11424 #[serde(default)]
11426 pub retainage: RetainageSchemaConfig,
11427 #[serde(default)]
11429 pub earned_value: EarnedValueSchemaConfig,
11430 #[serde(default = "default_project_anomaly_rate")]
11432 pub anomaly_rate: f64,
11433}
11434
11435fn default_project_count() -> u32 {
11436 10
11437}
11438
11439fn default_project_anomaly_rate() -> f64 {
11440 0.03
11441}
11442
11443impl Default for ProjectAccountingConfig {
11444 fn default() -> Self {
11445 Self {
11446 enabled: false,
11447 project_count: default_project_count(),
11448 project_types: ProjectTypeDistribution::default(),
11449 wbs: WbsSchemaConfig::default(),
11450 cost_allocation: CostAllocationConfig::default(),
11451 revenue_recognition: ProjectRevenueRecognitionConfig::default(),
11452 milestones: MilestoneSchemaConfig::default(),
11453 change_orders: ChangeOrderSchemaConfig::default(),
11454 retainage: RetainageSchemaConfig::default(),
11455 earned_value: EarnedValueSchemaConfig::default(),
11456 anomaly_rate: default_project_anomaly_rate(),
11457 }
11458 }
11459}
11460
11461#[derive(Debug, Clone, Serialize, Deserialize)]
11463pub struct ProjectTypeDistribution {
11464 #[serde(default = "default_capital_weight")]
11466 pub capital: f64,
11467 #[serde(default = "default_internal_weight")]
11469 pub internal: f64,
11470 #[serde(default = "default_customer_weight")]
11472 pub customer: f64,
11473 #[serde(default = "default_rnd_weight")]
11475 pub r_and_d: f64,
11476 #[serde(default = "default_maintenance_weight")]
11478 pub maintenance: f64,
11479 #[serde(default = "default_technology_weight")]
11481 pub technology: f64,
11482}
11483
11484fn default_capital_weight() -> f64 {
11485 0.25
11486}
11487fn default_internal_weight() -> f64 {
11488 0.20
11489}
11490fn default_customer_weight() -> f64 {
11491 0.30
11492}
11493fn default_rnd_weight() -> f64 {
11494 0.10
11495}
11496fn default_maintenance_weight() -> f64 {
11497 0.10
11498}
11499fn default_technology_weight() -> f64 {
11500 0.05
11501}
11502
11503impl Default for ProjectTypeDistribution {
11504 fn default() -> Self {
11505 Self {
11506 capital: default_capital_weight(),
11507 internal: default_internal_weight(),
11508 customer: default_customer_weight(),
11509 r_and_d: default_rnd_weight(),
11510 maintenance: default_maintenance_weight(),
11511 technology: default_technology_weight(),
11512 }
11513 }
11514}
11515
11516#[derive(Debug, Clone, Serialize, Deserialize)]
11518pub struct WbsSchemaConfig {
11519 #[serde(default = "default_wbs_max_depth")]
11521 pub max_depth: u32,
11522 #[serde(default = "default_wbs_min_elements")]
11524 pub min_elements_per_level: u32,
11525 #[serde(default = "default_wbs_max_elements")]
11527 pub max_elements_per_level: u32,
11528}
11529
11530fn default_wbs_max_depth() -> u32 {
11531 3
11532}
11533fn default_wbs_min_elements() -> u32 {
11534 2
11535}
11536fn default_wbs_max_elements() -> u32 {
11537 6
11538}
11539
11540impl Default for WbsSchemaConfig {
11541 fn default() -> Self {
11542 Self {
11543 max_depth: default_wbs_max_depth(),
11544 min_elements_per_level: default_wbs_min_elements(),
11545 max_elements_per_level: default_wbs_max_elements(),
11546 }
11547 }
11548}
11549
11550#[derive(Debug, Clone, Serialize, Deserialize)]
11552pub struct CostAllocationConfig {
11553 #[serde(default = "default_time_entry_rate")]
11555 pub time_entry_project_rate: f64,
11556 #[serde(default = "default_expense_rate")]
11558 pub expense_project_rate: f64,
11559 #[serde(default = "default_po_rate")]
11561 pub purchase_order_project_rate: f64,
11562 #[serde(default = "default_vi_rate")]
11564 pub vendor_invoice_project_rate: f64,
11565}
11566
11567fn default_time_entry_rate() -> f64 {
11568 0.60
11569}
11570fn default_expense_rate() -> f64 {
11571 0.30
11572}
11573fn default_po_rate() -> f64 {
11574 0.40
11575}
11576fn default_vi_rate() -> f64 {
11577 0.35
11578}
11579
11580impl Default for CostAllocationConfig {
11581 fn default() -> Self {
11582 Self {
11583 time_entry_project_rate: default_time_entry_rate(),
11584 expense_project_rate: default_expense_rate(),
11585 purchase_order_project_rate: default_po_rate(),
11586 vendor_invoice_project_rate: default_vi_rate(),
11587 }
11588 }
11589}
11590
11591#[derive(Debug, Clone, Serialize, Deserialize)]
11593pub struct ProjectRevenueRecognitionConfig {
11594 #[serde(default = "default_true")]
11596 pub enabled: bool,
11597 #[serde(default = "default_revenue_method")]
11599 pub method: String,
11600 #[serde(default = "default_completion_measure")]
11602 pub completion_measure: String,
11603 #[serde(default = "default_avg_contract_value")]
11605 pub avg_contract_value: f64,
11606}
11607
11608fn default_revenue_method() -> String {
11609 "percentage_of_completion".to_string()
11610}
11611fn default_completion_measure() -> String {
11612 "cost_to_cost".to_string()
11613}
11614fn default_avg_contract_value() -> f64 {
11615 500_000.0
11616}
11617
11618impl Default for ProjectRevenueRecognitionConfig {
11619 fn default() -> Self {
11620 Self {
11621 enabled: true,
11622 method: default_revenue_method(),
11623 completion_measure: default_completion_measure(),
11624 avg_contract_value: default_avg_contract_value(),
11625 }
11626 }
11627}
11628
11629#[derive(Debug, Clone, Serialize, Deserialize)]
11631pub struct MilestoneSchemaConfig {
11632 #[serde(default = "default_true")]
11634 pub enabled: bool,
11635 #[serde(default = "default_milestones_per_project")]
11637 pub avg_per_project: u32,
11638 #[serde(default = "default_payment_milestone_rate")]
11640 pub payment_milestone_rate: f64,
11641}
11642
11643fn default_milestones_per_project() -> u32 {
11644 4
11645}
11646fn default_payment_milestone_rate() -> f64 {
11647 0.50
11648}
11649
11650impl Default for MilestoneSchemaConfig {
11651 fn default() -> Self {
11652 Self {
11653 enabled: true,
11654 avg_per_project: default_milestones_per_project(),
11655 payment_milestone_rate: default_payment_milestone_rate(),
11656 }
11657 }
11658}
11659
11660#[derive(Debug, Clone, Serialize, Deserialize)]
11662pub struct ChangeOrderSchemaConfig {
11663 #[serde(default = "default_true")]
11665 pub enabled: bool,
11666 #[serde(default = "default_change_order_probability")]
11668 pub probability: f64,
11669 #[serde(default = "default_max_change_orders")]
11671 pub max_per_project: u32,
11672 #[serde(default = "default_change_order_approval_rate")]
11674 pub approval_rate: f64,
11675}
11676
11677fn default_change_order_probability() -> f64 {
11678 0.40
11679}
11680fn default_max_change_orders() -> u32 {
11681 3
11682}
11683fn default_change_order_approval_rate() -> f64 {
11684 0.75
11685}
11686
11687impl Default for ChangeOrderSchemaConfig {
11688 fn default() -> Self {
11689 Self {
11690 enabled: true,
11691 probability: default_change_order_probability(),
11692 max_per_project: default_max_change_orders(),
11693 approval_rate: default_change_order_approval_rate(),
11694 }
11695 }
11696}
11697
11698#[derive(Debug, Clone, Serialize, Deserialize)]
11700pub struct RetainageSchemaConfig {
11701 #[serde(default)]
11703 pub enabled: bool,
11704 #[serde(default = "default_retainage_pct")]
11706 pub default_percentage: f64,
11707}
11708
11709fn default_retainage_pct() -> f64 {
11710 0.10
11711}
11712
11713impl Default for RetainageSchemaConfig {
11714 fn default() -> Self {
11715 Self {
11716 enabled: false,
11717 default_percentage: default_retainage_pct(),
11718 }
11719 }
11720}
11721
11722#[derive(Debug, Clone, Serialize, Deserialize)]
11724pub struct EarnedValueSchemaConfig {
11725 #[serde(default = "default_true")]
11727 pub enabled: bool,
11728 #[serde(default = "default_evm_frequency")]
11730 pub frequency: String,
11731}
11732
11733fn default_evm_frequency() -> String {
11734 "monthly".to_string()
11735}
11736
11737impl Default for EarnedValueSchemaConfig {
11738 fn default() -> Self {
11739 Self {
11740 enabled: true,
11741 frequency: default_evm_frequency(),
11742 }
11743 }
11744}
11745
11746#[derive(Debug, Clone, Serialize, Deserialize)]
11752pub struct EsgConfig {
11753 #[serde(default)]
11755 pub enabled: bool,
11756 #[serde(default)]
11758 pub environmental: EnvironmentalConfig,
11759 #[serde(default)]
11761 pub social: SocialConfig,
11762 #[serde(default)]
11764 pub governance: GovernanceSchemaConfig,
11765 #[serde(default)]
11767 pub supply_chain_esg: SupplyChainEsgConfig,
11768 #[serde(default)]
11770 pub reporting: EsgReportingConfig,
11771 #[serde(default)]
11773 pub climate_scenarios: ClimateScenarioConfig,
11774 #[serde(default = "default_esg_anomaly_rate")]
11776 pub anomaly_rate: f64,
11777}
11778
11779fn default_esg_anomaly_rate() -> f64 {
11780 0.02
11781}
11782
11783impl Default for EsgConfig {
11784 fn default() -> Self {
11785 Self {
11786 enabled: false,
11787 environmental: EnvironmentalConfig::default(),
11788 social: SocialConfig::default(),
11789 governance: GovernanceSchemaConfig::default(),
11790 supply_chain_esg: SupplyChainEsgConfig::default(),
11791 reporting: EsgReportingConfig::default(),
11792 climate_scenarios: ClimateScenarioConfig::default(),
11793 anomaly_rate: default_esg_anomaly_rate(),
11794 }
11795 }
11796}
11797
11798#[derive(Debug, Clone, Serialize, Deserialize)]
11800pub struct EnvironmentalConfig {
11801 #[serde(default = "default_true")]
11803 pub enabled: bool,
11804 #[serde(default)]
11806 pub scope1: EmissionScopeConfig,
11807 #[serde(default)]
11809 pub scope2: EmissionScopeConfig,
11810 #[serde(default)]
11812 pub scope3: Scope3Config,
11813 #[serde(default)]
11815 pub energy: EnergySchemaConfig,
11816 #[serde(default)]
11818 pub water: WaterSchemaConfig,
11819 #[serde(default)]
11821 pub waste: WasteSchemaConfig,
11822}
11823
11824impl Default for EnvironmentalConfig {
11825 fn default() -> Self {
11826 Self {
11827 enabled: true,
11828 scope1: EmissionScopeConfig::default(),
11829 scope2: EmissionScopeConfig::default(),
11830 scope3: Scope3Config::default(),
11831 energy: EnergySchemaConfig::default(),
11832 water: WaterSchemaConfig::default(),
11833 waste: WasteSchemaConfig::default(),
11834 }
11835 }
11836}
11837
11838#[derive(Debug, Clone, Serialize, Deserialize)]
11840pub struct EmissionScopeConfig {
11841 #[serde(default = "default_true")]
11843 pub enabled: bool,
11844 #[serde(default = "default_emission_region")]
11846 pub factor_region: String,
11847}
11848
11849fn default_emission_region() -> String {
11850 "US".to_string()
11851}
11852
11853impl Default for EmissionScopeConfig {
11854 fn default() -> Self {
11855 Self {
11856 enabled: true,
11857 factor_region: default_emission_region(),
11858 }
11859 }
11860}
11861
11862#[derive(Debug, Clone, Serialize, Deserialize)]
11864pub struct Scope3Config {
11865 #[serde(default = "default_true")]
11867 pub enabled: bool,
11868 #[serde(default = "default_scope3_categories")]
11870 pub categories: Vec<String>,
11871 #[serde(default = "default_spend_intensity")]
11873 pub default_spend_intensity_kg_per_usd: f64,
11874}
11875
11876fn default_scope3_categories() -> Vec<String> {
11877 vec![
11878 "purchased_goods".to_string(),
11879 "business_travel".to_string(),
11880 "employee_commuting".to_string(),
11881 ]
11882}
11883
11884fn default_spend_intensity() -> f64 {
11885 0.5
11886}
11887
11888impl Default for Scope3Config {
11889 fn default() -> Self {
11890 Self {
11891 enabled: true,
11892 categories: default_scope3_categories(),
11893 default_spend_intensity_kg_per_usd: default_spend_intensity(),
11894 }
11895 }
11896}
11897
11898#[derive(Debug, Clone, Serialize, Deserialize)]
11900pub struct EnergySchemaConfig {
11901 #[serde(default = "default_true")]
11903 pub enabled: bool,
11904 #[serde(default = "default_facility_count")]
11906 pub facility_count: u32,
11907 #[serde(default = "default_renewable_target")]
11909 pub renewable_target: f64,
11910}
11911
11912fn default_facility_count() -> u32 {
11913 5
11914}
11915
11916fn default_renewable_target() -> f64 {
11917 0.30
11918}
11919
11920impl Default for EnergySchemaConfig {
11921 fn default() -> Self {
11922 Self {
11923 enabled: true,
11924 facility_count: default_facility_count(),
11925 renewable_target: default_renewable_target(),
11926 }
11927 }
11928}
11929
11930#[derive(Debug, Clone, Serialize, Deserialize)]
11932pub struct WaterSchemaConfig {
11933 #[serde(default = "default_true")]
11935 pub enabled: bool,
11936 #[serde(default = "default_water_facility_count")]
11938 pub facility_count: u32,
11939}
11940
11941fn default_water_facility_count() -> u32 {
11942 3
11943}
11944
11945impl Default for WaterSchemaConfig {
11946 fn default() -> Self {
11947 Self {
11948 enabled: true,
11949 facility_count: default_water_facility_count(),
11950 }
11951 }
11952}
11953
11954#[derive(Debug, Clone, Serialize, Deserialize)]
11956pub struct WasteSchemaConfig {
11957 #[serde(default = "default_true")]
11959 pub enabled: bool,
11960 #[serde(default = "default_diversion_target")]
11962 pub diversion_target: f64,
11963}
11964
11965fn default_diversion_target() -> f64 {
11966 0.50
11967}
11968
11969impl Default for WasteSchemaConfig {
11970 fn default() -> Self {
11971 Self {
11972 enabled: true,
11973 diversion_target: default_diversion_target(),
11974 }
11975 }
11976}
11977
11978#[derive(Debug, Clone, Serialize, Deserialize)]
11980pub struct SocialConfig {
11981 #[serde(default = "default_true")]
11983 pub enabled: bool,
11984 #[serde(default)]
11986 pub diversity: DiversitySchemaConfig,
11987 #[serde(default)]
11989 pub pay_equity: PayEquitySchemaConfig,
11990 #[serde(default)]
11992 pub safety: SafetySchemaConfig,
11993}
11994
11995impl Default for SocialConfig {
11996 fn default() -> Self {
11997 Self {
11998 enabled: true,
11999 diversity: DiversitySchemaConfig::default(),
12000 pay_equity: PayEquitySchemaConfig::default(),
12001 safety: SafetySchemaConfig::default(),
12002 }
12003 }
12004}
12005
12006#[derive(Debug, Clone, Serialize, Deserialize)]
12008pub struct DiversitySchemaConfig {
12009 #[serde(default = "default_true")]
12011 pub enabled: bool,
12012 #[serde(default = "default_diversity_dimensions")]
12014 pub dimensions: Vec<String>,
12015}
12016
12017fn default_diversity_dimensions() -> Vec<String> {
12018 vec![
12019 "gender".to_string(),
12020 "ethnicity".to_string(),
12021 "age_group".to_string(),
12022 ]
12023}
12024
12025impl Default for DiversitySchemaConfig {
12026 fn default() -> Self {
12027 Self {
12028 enabled: true,
12029 dimensions: default_diversity_dimensions(),
12030 }
12031 }
12032}
12033
12034#[derive(Debug, Clone, Serialize, Deserialize)]
12036pub struct PayEquitySchemaConfig {
12037 #[serde(default = "default_true")]
12039 pub enabled: bool,
12040 #[serde(default = "default_pay_gap_threshold")]
12042 pub gap_threshold: f64,
12043}
12044
12045fn default_pay_gap_threshold() -> f64 {
12046 0.05
12047}
12048
12049impl Default for PayEquitySchemaConfig {
12050 fn default() -> Self {
12051 Self {
12052 enabled: true,
12053 gap_threshold: default_pay_gap_threshold(),
12054 }
12055 }
12056}
12057
12058#[derive(Debug, Clone, Serialize, Deserialize)]
12060pub struct SafetySchemaConfig {
12061 #[serde(default = "default_true")]
12063 pub enabled: bool,
12064 #[serde(default = "default_trir_target")]
12066 pub target_trir: f64,
12067 #[serde(default = "default_incident_count")]
12069 pub incident_count: u32,
12070}
12071
12072fn default_trir_target() -> f64 {
12073 2.5
12074}
12075
12076fn default_incident_count() -> u32 {
12077 20
12078}
12079
12080impl Default for SafetySchemaConfig {
12081 fn default() -> Self {
12082 Self {
12083 enabled: true,
12084 target_trir: default_trir_target(),
12085 incident_count: default_incident_count(),
12086 }
12087 }
12088}
12089
12090#[derive(Debug, Clone, Serialize, Deserialize)]
12092pub struct GovernanceSchemaConfig {
12093 #[serde(default = "default_true")]
12095 pub enabled: bool,
12096 #[serde(default = "default_board_size")]
12098 pub board_size: u32,
12099 #[serde(default = "default_independence_target")]
12101 pub independence_target: f64,
12102}
12103
12104fn default_board_size() -> u32 {
12105 11
12106}
12107
12108fn default_independence_target() -> f64 {
12109 0.67
12110}
12111
12112impl Default for GovernanceSchemaConfig {
12113 fn default() -> Self {
12114 Self {
12115 enabled: true,
12116 board_size: default_board_size(),
12117 independence_target: default_independence_target(),
12118 }
12119 }
12120}
12121
12122#[derive(Debug, Clone, Serialize, Deserialize)]
12124pub struct SupplyChainEsgConfig {
12125 #[serde(default = "default_true")]
12127 pub enabled: bool,
12128 #[serde(default = "default_assessment_coverage")]
12130 pub assessment_coverage: f64,
12131 #[serde(default = "default_high_risk_countries")]
12133 pub high_risk_countries: Vec<String>,
12134}
12135
12136fn default_assessment_coverage() -> f64 {
12137 0.80
12138}
12139
12140fn default_high_risk_countries() -> Vec<String> {
12141 vec!["CN".to_string(), "BD".to_string(), "MM".to_string()]
12142}
12143
12144impl Default for SupplyChainEsgConfig {
12145 fn default() -> Self {
12146 Self {
12147 enabled: true,
12148 assessment_coverage: default_assessment_coverage(),
12149 high_risk_countries: default_high_risk_countries(),
12150 }
12151 }
12152}
12153
12154#[derive(Debug, Clone, Serialize, Deserialize)]
12156pub struct EsgReportingConfig {
12157 #[serde(default = "default_true")]
12159 pub enabled: bool,
12160 #[serde(default = "default_esg_frameworks")]
12162 pub frameworks: Vec<String>,
12163 #[serde(default = "default_true")]
12165 pub materiality_assessment: bool,
12166 #[serde(default = "default_materiality_threshold")]
12168 pub impact_threshold: f64,
12169 #[serde(default = "default_materiality_threshold")]
12171 pub financial_threshold: f64,
12172}
12173
12174fn default_esg_frameworks() -> Vec<String> {
12175 vec!["GRI".to_string(), "ESRS".to_string()]
12176}
12177
12178fn default_materiality_threshold() -> f64 {
12179 0.6
12180}
12181
12182impl Default for EsgReportingConfig {
12183 fn default() -> Self {
12184 Self {
12185 enabled: true,
12186 frameworks: default_esg_frameworks(),
12187 materiality_assessment: true,
12188 impact_threshold: default_materiality_threshold(),
12189 financial_threshold: default_materiality_threshold(),
12190 }
12191 }
12192}
12193
12194#[derive(Debug, Clone, Serialize, Deserialize)]
12196pub struct ClimateScenarioConfig {
12197 #[serde(default)]
12199 pub enabled: bool,
12200 #[serde(default = "default_climate_scenarios")]
12202 pub scenarios: Vec<String>,
12203 #[serde(default = "default_time_horizons")]
12205 pub time_horizons: Vec<u32>,
12206}
12207
12208fn default_climate_scenarios() -> Vec<String> {
12209 vec![
12210 "net_zero_2050".to_string(),
12211 "stated_policies".to_string(),
12212 "current_trajectory".to_string(),
12213 ]
12214}
12215
12216fn default_time_horizons() -> Vec<u32> {
12217 vec![5, 10, 30]
12218}
12219
12220impl Default for ClimateScenarioConfig {
12221 fn default() -> Self {
12222 Self {
12223 enabled: false,
12224 scenarios: default_climate_scenarios(),
12225 time_horizons: default_time_horizons(),
12226 }
12227 }
12228}
12229
12230#[cfg(test)]
12231#[allow(clippy::unwrap_used)]
12232mod tests {
12233 use super::*;
12234 use crate::presets::demo_preset;
12235
12236 #[test]
12241 fn test_config_yaml_roundtrip() {
12242 let config = demo_preset();
12243 let yaml = serde_yaml::to_string(&config).expect("Failed to serialize to YAML");
12244 let deserialized: GeneratorConfig =
12245 serde_yaml::from_str(&yaml).expect("Failed to deserialize from YAML");
12246
12247 assert_eq!(
12248 config.global.period_months,
12249 deserialized.global.period_months
12250 );
12251 assert_eq!(config.global.industry, deserialized.global.industry);
12252 assert_eq!(config.companies.len(), deserialized.companies.len());
12253 assert_eq!(config.companies[0].code, deserialized.companies[0].code);
12254 }
12255
12256 #[test]
12257 fn test_config_json_roundtrip() {
12258 let mut config = demo_preset();
12260 config.master_data.employees.approval_limits.executive = 1e12;
12262
12263 let json = serde_json::to_string(&config).expect("Failed to serialize to JSON");
12264 let deserialized: GeneratorConfig =
12265 serde_json::from_str(&json).expect("Failed to deserialize from JSON");
12266
12267 assert_eq!(
12268 config.global.period_months,
12269 deserialized.global.period_months
12270 );
12271 assert_eq!(config.global.industry, deserialized.global.industry);
12272 assert_eq!(config.companies.len(), deserialized.companies.len());
12273 }
12274
12275 #[test]
12276 fn test_transaction_volume_serialization() {
12277 let volumes = vec![
12279 (TransactionVolume::TenK, "ten_k"),
12280 (TransactionVolume::HundredK, "hundred_k"),
12281 (TransactionVolume::OneM, "one_m"),
12282 (TransactionVolume::TenM, "ten_m"),
12283 (TransactionVolume::HundredM, "hundred_m"),
12284 ];
12285
12286 for (volume, expected_key) in volumes {
12287 let json = serde_json::to_string(&volume).expect("Failed to serialize");
12288 assert!(
12289 json.contains(expected_key),
12290 "Expected {} in JSON: {}",
12291 expected_key,
12292 json
12293 );
12294 }
12295 }
12296
12297 #[test]
12298 fn test_transaction_volume_custom_serialization() {
12299 let volume = TransactionVolume::Custom(12345);
12300 let json = serde_json::to_string(&volume).expect("Failed to serialize");
12301 let deserialized: TransactionVolume =
12302 serde_json::from_str(&json).expect("Failed to deserialize");
12303 assert_eq!(deserialized.count(), 12345);
12304 }
12305
12306 #[test]
12307 fn test_output_mode_serialization() {
12308 let modes = vec![
12309 OutputMode::Streaming,
12310 OutputMode::FlatFile,
12311 OutputMode::Both,
12312 ];
12313
12314 for mode in modes {
12315 let json = serde_json::to_string(&mode).expect("Failed to serialize");
12316 let deserialized: OutputMode =
12317 serde_json::from_str(&json).expect("Failed to deserialize");
12318 assert!(format!("{:?}", mode) == format!("{:?}", deserialized));
12319 }
12320 }
12321
12322 #[test]
12323 fn test_file_format_serialization() {
12324 let formats = vec![
12325 FileFormat::Csv,
12326 FileFormat::Parquet,
12327 FileFormat::Json,
12328 FileFormat::JsonLines,
12329 ];
12330
12331 for format in formats {
12332 let json = serde_json::to_string(&format).expect("Failed to serialize");
12333 let deserialized: FileFormat =
12334 serde_json::from_str(&json).expect("Failed to deserialize");
12335 assert!(format!("{:?}", format) == format!("{:?}", deserialized));
12336 }
12337 }
12338
12339 #[test]
12340 fn test_compression_algorithm_serialization() {
12341 let algos = vec![
12342 CompressionAlgorithm::Gzip,
12343 CompressionAlgorithm::Zstd,
12344 CompressionAlgorithm::Lz4,
12345 CompressionAlgorithm::Snappy,
12346 ];
12347
12348 for algo in algos {
12349 let json = serde_json::to_string(&algo).expect("Failed to serialize");
12350 let deserialized: CompressionAlgorithm =
12351 serde_json::from_str(&json).expect("Failed to deserialize");
12352 assert!(format!("{:?}", algo) == format!("{:?}", deserialized));
12353 }
12354 }
12355
12356 #[test]
12357 fn test_transfer_pricing_method_serialization() {
12358 let methods = vec![
12359 TransferPricingMethod::CostPlus,
12360 TransferPricingMethod::ComparableUncontrolled,
12361 TransferPricingMethod::ResalePrice,
12362 TransferPricingMethod::TransactionalNetMargin,
12363 TransferPricingMethod::ProfitSplit,
12364 ];
12365
12366 for method in methods {
12367 let json = serde_json::to_string(&method).expect("Failed to serialize");
12368 let deserialized: TransferPricingMethod =
12369 serde_json::from_str(&json).expect("Failed to deserialize");
12370 assert!(format!("{:?}", method) == format!("{:?}", deserialized));
12371 }
12372 }
12373
12374 #[test]
12375 fn test_benford_exemption_serialization() {
12376 let exemptions = vec![
12377 BenfordExemption::Recurring,
12378 BenfordExemption::Payroll,
12379 BenfordExemption::FixedFees,
12380 BenfordExemption::RoundAmounts,
12381 ];
12382
12383 for exemption in exemptions {
12384 let json = serde_json::to_string(&exemption).expect("Failed to serialize");
12385 let deserialized: BenfordExemption =
12386 serde_json::from_str(&json).expect("Failed to deserialize");
12387 assert!(format!("{:?}", exemption) == format!("{:?}", deserialized));
12388 }
12389 }
12390
12391 #[test]
12396 fn test_global_config_defaults() {
12397 let yaml = r#"
12398 industry: manufacturing
12399 start_date: "2024-01-01"
12400 period_months: 6
12401 "#;
12402 let config: GlobalConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12403 assert_eq!(config.group_currency, "USD");
12404 assert!(config.parallel);
12405 assert_eq!(config.worker_threads, 0);
12406 assert_eq!(config.memory_limit_mb, 0);
12407 }
12408
12409 #[test]
12410 fn test_fraud_config_defaults() {
12411 let config = FraudConfig::default();
12412 assert!(!config.enabled);
12413 assert_eq!(config.fraud_rate, 0.005);
12414 assert!(!config.clustering_enabled);
12415 }
12416
12417 #[test]
12418 fn test_internal_controls_config_defaults() {
12419 let config = InternalControlsConfig::default();
12420 assert!(!config.enabled);
12421 assert_eq!(config.exception_rate, 0.02);
12422 assert_eq!(config.sod_violation_rate, 0.01);
12423 assert!(config.export_control_master_data);
12424 assert_eq!(config.sox_materiality_threshold, 10000.0);
12425 assert!(config.coso_enabled);
12427 assert!(!config.include_entity_level_controls);
12428 assert_eq!(config.target_maturity_level, "mixed");
12429 }
12430
12431 #[test]
12432 fn test_output_config_defaults() {
12433 let config = OutputConfig::default();
12434 assert!(matches!(config.mode, OutputMode::FlatFile));
12435 assert_eq!(config.formats, vec![FileFormat::Parquet]);
12436 assert!(config.compression.enabled);
12437 assert!(matches!(
12438 config.compression.algorithm,
12439 CompressionAlgorithm::Zstd
12440 ));
12441 assert!(config.include_acdoca);
12442 assert!(!config.include_bseg);
12443 assert!(config.partition_by_period);
12444 assert!(!config.partition_by_company);
12445 }
12446
12447 #[test]
12448 fn test_approval_config_defaults() {
12449 let config = ApprovalConfig::default();
12450 assert!(!config.enabled);
12451 assert_eq!(config.auto_approve_threshold, 1000.0);
12452 assert_eq!(config.rejection_rate, 0.02);
12453 assert_eq!(config.revision_rate, 0.05);
12454 assert_eq!(config.average_approval_delay_hours, 4.0);
12455 assert_eq!(config.thresholds.len(), 4);
12456 }
12457
12458 #[test]
12459 fn test_p2p_flow_config_defaults() {
12460 let config = P2PFlowConfig::default();
12461 assert!(config.enabled);
12462 assert_eq!(config.three_way_match_rate, 0.95);
12463 assert_eq!(config.partial_delivery_rate, 0.15);
12464 assert_eq!(config.average_po_to_gr_days, 14);
12465 }
12466
12467 #[test]
12468 fn test_o2c_flow_config_defaults() {
12469 let config = O2CFlowConfig::default();
12470 assert!(config.enabled);
12471 assert_eq!(config.credit_check_failure_rate, 0.02);
12472 assert_eq!(config.return_rate, 0.03);
12473 assert_eq!(config.bad_debt_rate, 0.01);
12474 }
12475
12476 #[test]
12477 fn test_balance_config_defaults() {
12478 let config = BalanceConfig::default();
12479 assert!(!config.generate_opening_balances);
12480 assert!(config.generate_trial_balances);
12481 assert_eq!(config.target_gross_margin, 0.35);
12482 assert!(config.validate_balance_equation);
12483 assert!(config.reconcile_subledgers);
12484 }
12485
12486 #[test]
12491 fn test_partial_config_with_defaults() {
12492 let yaml = r#"
12494 global:
12495 industry: manufacturing
12496 start_date: "2024-01-01"
12497 period_months: 3
12498 companies:
12499 - code: "TEST"
12500 name: "Test Company"
12501 currency: "USD"
12502 country: "US"
12503 annual_transaction_volume: ten_k
12504 chart_of_accounts:
12505 complexity: small
12506 output:
12507 output_directory: "./output"
12508 "#;
12509
12510 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12511 assert_eq!(config.global.period_months, 3);
12512 assert_eq!(config.companies.len(), 1);
12513 assert!(!config.fraud.enabled); assert!(!config.internal_controls.enabled); }
12516
12517 #[test]
12518 fn test_config_with_fraud_enabled() {
12519 let yaml = r#"
12520 global:
12521 industry: retail
12522 start_date: "2024-01-01"
12523 period_months: 12
12524 companies:
12525 - code: "RETAIL"
12526 name: "Retail Co"
12527 currency: "USD"
12528 country: "US"
12529 annual_transaction_volume: hundred_k
12530 chart_of_accounts:
12531 complexity: medium
12532 output:
12533 output_directory: "./output"
12534 fraud:
12535 enabled: true
12536 fraud_rate: 0.05
12537 clustering_enabled: true
12538 "#;
12539
12540 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12541 assert!(config.fraud.enabled);
12542 assert_eq!(config.fraud.fraud_rate, 0.05);
12543 assert!(config.fraud.clustering_enabled);
12544 }
12545
12546 #[test]
12547 fn test_config_with_multiple_companies() {
12548 let yaml = r#"
12549 global:
12550 industry: manufacturing
12551 start_date: "2024-01-01"
12552 period_months: 6
12553 companies:
12554 - code: "HQ"
12555 name: "Headquarters"
12556 currency: "USD"
12557 country: "US"
12558 annual_transaction_volume: hundred_k
12559 volume_weight: 1.0
12560 - code: "EU"
12561 name: "European Subsidiary"
12562 currency: "EUR"
12563 country: "DE"
12564 annual_transaction_volume: hundred_k
12565 volume_weight: 0.5
12566 - code: "APAC"
12567 name: "Asia Pacific"
12568 currency: "JPY"
12569 country: "JP"
12570 annual_transaction_volume: ten_k
12571 volume_weight: 0.3
12572 chart_of_accounts:
12573 complexity: large
12574 output:
12575 output_directory: "./output"
12576 "#;
12577
12578 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12579 assert_eq!(config.companies.len(), 3);
12580 assert_eq!(config.companies[0].code, "HQ");
12581 assert_eq!(config.companies[1].currency, "EUR");
12582 assert_eq!(config.companies[2].volume_weight, 0.3);
12583 }
12584
12585 #[test]
12586 fn test_intercompany_config() {
12587 let yaml = r#"
12588 enabled: true
12589 ic_transaction_rate: 0.20
12590 transfer_pricing_method: cost_plus
12591 markup_percent: 0.08
12592 generate_matched_pairs: true
12593 generate_eliminations: true
12594 "#;
12595
12596 let config: IntercompanyConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12597 assert!(config.enabled);
12598 assert_eq!(config.ic_transaction_rate, 0.20);
12599 assert!(matches!(
12600 config.transfer_pricing_method,
12601 TransferPricingMethod::CostPlus
12602 ));
12603 assert_eq!(config.markup_percent, 0.08);
12604 assert!(config.generate_eliminations);
12605 }
12606
12607 #[test]
12612 fn test_company_config_defaults() {
12613 let yaml = r#"
12614 code: "TEST"
12615 name: "Test Company"
12616 currency: "USD"
12617 country: "US"
12618 annual_transaction_volume: ten_k
12619 "#;
12620
12621 let config: CompanyConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12622 assert_eq!(config.fiscal_year_variant, "K4"); assert_eq!(config.volume_weight, 1.0); }
12625
12626 #[test]
12631 fn test_coa_config_defaults() {
12632 let yaml = r#"
12633 complexity: medium
12634 "#;
12635
12636 let config: ChartOfAccountsConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12637 assert!(config.industry_specific); assert!(config.custom_accounts.is_none());
12639 assert_eq!(config.min_hierarchy_depth, 2); assert_eq!(config.max_hierarchy_depth, 5); }
12642
12643 #[test]
12648 fn test_accounting_standards_config_defaults() {
12649 let config = AccountingStandardsConfig::default();
12650 assert!(!config.enabled);
12651 assert!(matches!(
12652 config.framework,
12653 AccountingFrameworkConfig::UsGaap
12654 ));
12655 assert!(!config.revenue_recognition.enabled);
12656 assert!(!config.leases.enabled);
12657 assert!(!config.fair_value.enabled);
12658 assert!(!config.impairment.enabled);
12659 assert!(!config.generate_differences);
12660 }
12661
12662 #[test]
12663 fn test_accounting_standards_config_yaml() {
12664 let yaml = r#"
12665 enabled: true
12666 framework: ifrs
12667 revenue_recognition:
12668 enabled: true
12669 generate_contracts: true
12670 avg_obligations_per_contract: 2.5
12671 variable_consideration_rate: 0.20
12672 over_time_recognition_rate: 0.35
12673 contract_count: 150
12674 leases:
12675 enabled: true
12676 lease_count: 75
12677 finance_lease_percent: 0.25
12678 avg_lease_term_months: 48
12679 generate_differences: true
12680 "#;
12681
12682 let config: AccountingStandardsConfig =
12683 serde_yaml::from_str(yaml).expect("Failed to parse");
12684 assert!(config.enabled);
12685 assert!(matches!(config.framework, AccountingFrameworkConfig::Ifrs));
12686 assert!(config.revenue_recognition.enabled);
12687 assert_eq!(config.revenue_recognition.contract_count, 150);
12688 assert_eq!(config.revenue_recognition.avg_obligations_per_contract, 2.5);
12689 assert!(config.leases.enabled);
12690 assert_eq!(config.leases.lease_count, 75);
12691 assert_eq!(config.leases.finance_lease_percent, 0.25);
12692 assert!(config.generate_differences);
12693 }
12694
12695 #[test]
12696 fn test_accounting_framework_serialization() {
12697 let frameworks = [
12698 AccountingFrameworkConfig::UsGaap,
12699 AccountingFrameworkConfig::Ifrs,
12700 AccountingFrameworkConfig::DualReporting,
12701 ];
12702
12703 for framework in frameworks {
12704 let json = serde_json::to_string(&framework).expect("Failed to serialize");
12705 let deserialized: AccountingFrameworkConfig =
12706 serde_json::from_str(&json).expect("Failed to deserialize");
12707 assert!(format!("{:?}", framework) == format!("{:?}", deserialized));
12708 }
12709 }
12710
12711 #[test]
12712 fn test_revenue_recognition_config_defaults() {
12713 let config = RevenueRecognitionConfig::default();
12714 assert!(!config.enabled);
12715 assert!(config.generate_contracts);
12716 assert_eq!(config.avg_obligations_per_contract, 2.0);
12717 assert_eq!(config.variable_consideration_rate, 0.15);
12718 assert_eq!(config.over_time_recognition_rate, 0.30);
12719 assert_eq!(config.contract_count, 100);
12720 }
12721
12722 #[test]
12723 fn test_lease_accounting_config_defaults() {
12724 let config = LeaseAccountingConfig::default();
12725 assert!(!config.enabled);
12726 assert_eq!(config.lease_count, 50);
12727 assert_eq!(config.finance_lease_percent, 0.30);
12728 assert_eq!(config.avg_lease_term_months, 60);
12729 assert!(config.generate_amortization);
12730 assert_eq!(config.real_estate_percent, 0.40);
12731 }
12732
12733 #[test]
12734 fn test_fair_value_config_defaults() {
12735 let config = FairValueConfig::default();
12736 assert!(!config.enabled);
12737 assert_eq!(config.measurement_count, 25);
12738 assert_eq!(config.level1_percent, 0.40);
12739 assert_eq!(config.level2_percent, 0.35);
12740 assert_eq!(config.level3_percent, 0.25);
12741 assert!(!config.include_sensitivity_analysis);
12742 }
12743
12744 #[test]
12745 fn test_impairment_config_defaults() {
12746 let config = ImpairmentConfig::default();
12747 assert!(!config.enabled);
12748 assert_eq!(config.test_count, 15);
12749 assert_eq!(config.impairment_rate, 0.10);
12750 assert!(config.generate_projections);
12751 assert!(!config.include_goodwill);
12752 }
12753
12754 #[test]
12759 fn test_audit_standards_config_defaults() {
12760 let config = AuditStandardsConfig::default();
12761 assert!(!config.enabled);
12762 assert!(!config.isa_compliance.enabled);
12763 assert!(!config.analytical_procedures.enabled);
12764 assert!(!config.confirmations.enabled);
12765 assert!(!config.opinion.enabled);
12766 assert!(!config.generate_audit_trail);
12767 assert!(!config.sox.enabled);
12768 assert!(!config.pcaob.enabled);
12769 }
12770
12771 #[test]
12772 fn test_audit_standards_config_yaml() {
12773 let yaml = r#"
12774 enabled: true
12775 isa_compliance:
12776 enabled: true
12777 compliance_level: comprehensive
12778 generate_isa_mappings: true
12779 include_pcaob: true
12780 framework: dual
12781 analytical_procedures:
12782 enabled: true
12783 procedures_per_account: 5
12784 variance_probability: 0.25
12785 confirmations:
12786 enabled: true
12787 confirmation_count: 75
12788 positive_response_rate: 0.90
12789 exception_rate: 0.08
12790 opinion:
12791 enabled: true
12792 generate_kam: true
12793 average_kam_count: 4
12794 sox:
12795 enabled: true
12796 generate_302_certifications: true
12797 generate_404_assessments: true
12798 material_weakness_rate: 0.03
12799 pcaob:
12800 enabled: true
12801 is_pcaob_audit: true
12802 include_icfr_opinion: true
12803 generate_audit_trail: true
12804 "#;
12805
12806 let config: AuditStandardsConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12807 assert!(config.enabled);
12808 assert!(config.isa_compliance.enabled);
12809 assert_eq!(config.isa_compliance.compliance_level, "comprehensive");
12810 assert!(config.isa_compliance.include_pcaob);
12811 assert_eq!(config.isa_compliance.framework, "dual");
12812 assert!(config.analytical_procedures.enabled);
12813 assert_eq!(config.analytical_procedures.procedures_per_account, 5);
12814 assert!(config.confirmations.enabled);
12815 assert_eq!(config.confirmations.confirmation_count, 75);
12816 assert!(config.opinion.enabled);
12817 assert_eq!(config.opinion.average_kam_count, 4);
12818 assert!(config.sox.enabled);
12819 assert!(config.sox.generate_302_certifications);
12820 assert_eq!(config.sox.material_weakness_rate, 0.03);
12821 assert!(config.pcaob.enabled);
12822 assert!(config.pcaob.is_pcaob_audit);
12823 assert!(config.pcaob.include_icfr_opinion);
12824 assert!(config.generate_audit_trail);
12825 }
12826
12827 #[test]
12828 fn test_isa_compliance_config_defaults() {
12829 let config = IsaComplianceConfig::default();
12830 assert!(!config.enabled);
12831 assert_eq!(config.compliance_level, "standard");
12832 assert!(config.generate_isa_mappings);
12833 assert!(config.generate_coverage_summary);
12834 assert!(!config.include_pcaob);
12835 assert_eq!(config.framework, "isa");
12836 }
12837
12838 #[test]
12839 fn test_sox_compliance_config_defaults() {
12840 let config = SoxComplianceConfig::default();
12841 assert!(!config.enabled);
12842 assert!(config.generate_302_certifications);
12843 assert!(config.generate_404_assessments);
12844 assert_eq!(config.materiality_threshold, 10000.0);
12845 assert_eq!(config.material_weakness_rate, 0.02);
12846 assert_eq!(config.significant_deficiency_rate, 0.08);
12847 }
12848
12849 #[test]
12850 fn test_pcaob_config_defaults() {
12851 let config = PcaobConfig::default();
12852 assert!(!config.enabled);
12853 assert!(!config.is_pcaob_audit);
12854 assert!(config.generate_cam);
12855 assert!(!config.include_icfr_opinion);
12856 assert!(!config.generate_standard_mappings);
12857 }
12858
12859 #[test]
12860 fn test_config_with_standards_enabled() {
12861 let yaml = r#"
12862 global:
12863 industry: financial_services
12864 start_date: "2024-01-01"
12865 period_months: 12
12866 companies:
12867 - code: "BANK"
12868 name: "Test Bank"
12869 currency: "USD"
12870 country: "US"
12871 annual_transaction_volume: hundred_k
12872 chart_of_accounts:
12873 complexity: large
12874 output:
12875 output_directory: "./output"
12876 accounting_standards:
12877 enabled: true
12878 framework: us_gaap
12879 revenue_recognition:
12880 enabled: true
12881 leases:
12882 enabled: true
12883 audit_standards:
12884 enabled: true
12885 isa_compliance:
12886 enabled: true
12887 sox:
12888 enabled: true
12889 "#;
12890
12891 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12892 assert!(config.accounting_standards.enabled);
12893 assert!(matches!(
12894 config.accounting_standards.framework,
12895 AccountingFrameworkConfig::UsGaap
12896 ));
12897 assert!(config.accounting_standards.revenue_recognition.enabled);
12898 assert!(config.accounting_standards.leases.enabled);
12899 assert!(config.audit_standards.enabled);
12900 assert!(config.audit_standards.isa_compliance.enabled);
12901 assert!(config.audit_standards.sox.enabled);
12902 }
12903
12904 #[test]
12909 fn test_industry_specific_config_defaults() {
12910 let config = IndustrySpecificConfig::default();
12911 assert!(!config.enabled);
12912 assert!(!config.manufacturing.enabled);
12913 assert!(!config.retail.enabled);
12914 assert!(!config.healthcare.enabled);
12915 assert!(!config.technology.enabled);
12916 assert!(!config.financial_services.enabled);
12917 assert!(!config.professional_services.enabled);
12918 }
12919
12920 #[test]
12921 fn test_manufacturing_config_defaults() {
12922 let config = ManufacturingConfig::default();
12923 assert!(!config.enabled);
12924 assert_eq!(config.bom_depth, 4);
12925 assert!(!config.just_in_time);
12926 assert_eq!(config.supplier_tiers, 2);
12927 assert_eq!(config.target_yield_rate, 0.97);
12928 assert_eq!(config.scrap_alert_threshold, 0.03);
12929 }
12930
12931 #[test]
12932 fn test_retail_config_defaults() {
12933 let config = RetailConfig::default();
12934 assert!(!config.enabled);
12935 assert_eq!(config.avg_daily_transactions, 500);
12936 assert!(config.loss_prevention);
12937 assert_eq!(config.shrinkage_rate, 0.015);
12938 }
12939
12940 #[test]
12941 fn test_healthcare_config_defaults() {
12942 let config = HealthcareConfig::default();
12943 assert!(!config.enabled);
12944 assert_eq!(config.facility_type, "hospital");
12945 assert_eq!(config.avg_daily_encounters, 150);
12946 assert!(config.compliance.hipaa);
12947 assert!(config.compliance.stark_law);
12948 assert!(config.coding_systems.icd10);
12949 assert!(config.coding_systems.cpt);
12950 }
12951
12952 #[test]
12953 fn test_technology_config_defaults() {
12954 let config = TechnologyConfig::default();
12955 assert!(!config.enabled);
12956 assert_eq!(config.revenue_model, "saas");
12957 assert_eq!(config.subscription_revenue_pct, 0.60);
12958 assert!(config.rd_capitalization.enabled);
12959 }
12960
12961 #[test]
12962 fn test_config_with_industry_specific() {
12963 let yaml = r#"
12964 global:
12965 industry: healthcare
12966 start_date: "2024-01-01"
12967 period_months: 12
12968 companies:
12969 - code: "HOSP"
12970 name: "Test Hospital"
12971 currency: "USD"
12972 country: "US"
12973 annual_transaction_volume: hundred_k
12974 chart_of_accounts:
12975 complexity: medium
12976 output:
12977 output_directory: "./output"
12978 industry_specific:
12979 enabled: true
12980 healthcare:
12981 enabled: true
12982 facility_type: hospital
12983 payer_mix:
12984 medicare: 0.45
12985 medicaid: 0.15
12986 commercial: 0.35
12987 self_pay: 0.05
12988 coding_systems:
12989 icd10: true
12990 cpt: true
12991 drg: true
12992 compliance:
12993 hipaa: true
12994 stark_law: true
12995 anomaly_rates:
12996 upcoding: 0.03
12997 unbundling: 0.02
12998 "#;
12999
13000 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13001 assert!(config.industry_specific.enabled);
13002 assert!(config.industry_specific.healthcare.enabled);
13003 assert_eq!(
13004 config.industry_specific.healthcare.facility_type,
13005 "hospital"
13006 );
13007 assert_eq!(config.industry_specific.healthcare.payer_mix.medicare, 0.45);
13008 assert_eq!(config.industry_specific.healthcare.payer_mix.self_pay, 0.05);
13009 assert!(config.industry_specific.healthcare.coding_systems.icd10);
13010 assert!(config.industry_specific.healthcare.compliance.hipaa);
13011 assert_eq!(
13012 config.industry_specific.healthcare.anomaly_rates.upcoding,
13013 0.03
13014 );
13015 }
13016
13017 #[test]
13018 fn test_config_with_manufacturing_specific() {
13019 let yaml = r#"
13020 global:
13021 industry: manufacturing
13022 start_date: "2024-01-01"
13023 period_months: 12
13024 companies:
13025 - code: "MFG"
13026 name: "Test Manufacturing"
13027 currency: "USD"
13028 country: "US"
13029 annual_transaction_volume: hundred_k
13030 chart_of_accounts:
13031 complexity: medium
13032 output:
13033 output_directory: "./output"
13034 industry_specific:
13035 enabled: true
13036 manufacturing:
13037 enabled: true
13038 bom_depth: 5
13039 just_in_time: true
13040 supplier_tiers: 3
13041 target_yield_rate: 0.98
13042 anomaly_rates:
13043 yield_manipulation: 0.02
13044 phantom_production: 0.01
13045 "#;
13046
13047 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13048 assert!(config.industry_specific.enabled);
13049 assert!(config.industry_specific.manufacturing.enabled);
13050 assert_eq!(config.industry_specific.manufacturing.bom_depth, 5);
13051 assert!(config.industry_specific.manufacturing.just_in_time);
13052 assert_eq!(config.industry_specific.manufacturing.supplier_tiers, 3);
13053 assert_eq!(
13054 config.industry_specific.manufacturing.target_yield_rate,
13055 0.98
13056 );
13057 assert_eq!(
13058 config
13059 .industry_specific
13060 .manufacturing
13061 .anomaly_rates
13062 .yield_manipulation,
13063 0.02
13064 );
13065 }
13066
13067 #[test]
13072 fn test_tax_config_defaults() {
13073 let tax = TaxConfig::default();
13074 assert!(!tax.enabled);
13075 assert!(tax.jurisdictions.countries.is_empty());
13076 assert!(!tax.jurisdictions.include_subnational);
13077 assert!(!tax.vat_gst.enabled);
13078 assert!(tax.vat_gst.standard_rates.is_empty());
13079 assert!(tax.vat_gst.reduced_rates.is_empty());
13080 assert!(tax.vat_gst.exempt_categories.is_empty());
13081 assert!(tax.vat_gst.reverse_charge);
13082 assert!(!tax.sales_tax.enabled);
13083 assert!(tax.sales_tax.nexus_states.is_empty());
13084 assert!(!tax.withholding.enabled);
13085 assert!(tax.withholding.treaty_network);
13086 assert_eq!(tax.withholding.default_rate, 0.30);
13087 assert_eq!(tax.withholding.treaty_reduced_rate, 0.15);
13088 assert!(tax.provisions.enabled);
13089 assert_eq!(tax.provisions.statutory_rate, 0.21);
13090 assert!(tax.provisions.uncertain_positions);
13091 assert!(!tax.payroll_tax.enabled);
13092 assert_eq!(tax.anomaly_rate, 0.03);
13093 }
13094
13095 #[test]
13096 fn test_tax_config_from_yaml() {
13097 let yaml = r#"
13098 global:
13099 seed: 42
13100 start_date: "2024-01-01"
13101 period_months: 12
13102 industry: retail
13103 companies:
13104 - code: C001
13105 name: Test Corp
13106 currency: USD
13107 country: US
13108 annual_transaction_volume: ten_k
13109 chart_of_accounts:
13110 complexity: small
13111 output:
13112 output_directory: ./output
13113 tax:
13114 enabled: true
13115 anomaly_rate: 0.05
13116 jurisdictions:
13117 countries: ["US", "DE", "GB"]
13118 include_subnational: true
13119 vat_gst:
13120 enabled: true
13121 standard_rates:
13122 DE: 0.19
13123 GB: 0.20
13124 reduced_rates:
13125 DE: 0.07
13126 GB: 0.05
13127 exempt_categories:
13128 - financial_services
13129 - healthcare
13130 reverse_charge: false
13131 sales_tax:
13132 enabled: true
13133 nexus_states: ["CA", "NY", "TX"]
13134 withholding:
13135 enabled: true
13136 treaty_network: false
13137 default_rate: 0.25
13138 treaty_reduced_rate: 0.10
13139 provisions:
13140 enabled: false
13141 statutory_rate: 0.28
13142 uncertain_positions: false
13143 payroll_tax:
13144 enabled: true
13145 "#;
13146
13147 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13148 assert!(config.tax.enabled);
13149 assert_eq!(config.tax.anomaly_rate, 0.05);
13150
13151 assert_eq!(config.tax.jurisdictions.countries.len(), 3);
13153 assert!(config
13154 .tax
13155 .jurisdictions
13156 .countries
13157 .contains(&"DE".to_string()));
13158 assert!(config.tax.jurisdictions.include_subnational);
13159
13160 assert!(config.tax.vat_gst.enabled);
13162 assert_eq!(config.tax.vat_gst.standard_rates.get("DE"), Some(&0.19));
13163 assert_eq!(config.tax.vat_gst.standard_rates.get("GB"), Some(&0.20));
13164 assert_eq!(config.tax.vat_gst.reduced_rates.get("DE"), Some(&0.07));
13165 assert_eq!(config.tax.vat_gst.exempt_categories.len(), 2);
13166 assert!(!config.tax.vat_gst.reverse_charge);
13167
13168 assert!(config.tax.sales_tax.enabled);
13170 assert_eq!(config.tax.sales_tax.nexus_states.len(), 3);
13171 assert!(config
13172 .tax
13173 .sales_tax
13174 .nexus_states
13175 .contains(&"CA".to_string()));
13176
13177 assert!(config.tax.withholding.enabled);
13179 assert!(!config.tax.withholding.treaty_network);
13180 assert_eq!(config.tax.withholding.default_rate, 0.25);
13181 assert_eq!(config.tax.withholding.treaty_reduced_rate, 0.10);
13182
13183 assert!(!config.tax.provisions.enabled);
13185 assert_eq!(config.tax.provisions.statutory_rate, 0.28);
13186 assert!(!config.tax.provisions.uncertain_positions);
13187
13188 assert!(config.tax.payroll_tax.enabled);
13190 }
13191
13192 #[test]
13193 fn test_generator_config_with_tax_default() {
13194 let yaml = r#"
13195 global:
13196 seed: 42
13197 start_date: "2024-01-01"
13198 period_months: 12
13199 industry: retail
13200 companies:
13201 - code: C001
13202 name: Test Corp
13203 currency: USD
13204 country: US
13205 annual_transaction_volume: ten_k
13206 chart_of_accounts:
13207 complexity: small
13208 output:
13209 output_directory: ./output
13210 "#;
13211
13212 let config: GeneratorConfig =
13213 serde_yaml::from_str(yaml).expect("Failed to parse config without tax section");
13214 assert!(!config.tax.enabled);
13216 assert!(config.tax.jurisdictions.countries.is_empty());
13217 assert_eq!(config.tax.anomaly_rate, 0.03);
13218 assert!(config.tax.provisions.enabled); assert_eq!(config.tax.provisions.statutory_rate, 0.21);
13220 }
13221}