1use datasynth_core::distributions::{
4 AmountDistributionConfig, DebitCreditDistributionConfig, EvenOddDistributionConfig,
5 LineItemDistributionConfig, SeasonalityConfig,
6};
7use datasynth_core::models::{CoAComplexity, IndustrySector};
8use serde::{Deserialize, Serialize};
9use std::path::PathBuf;
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct GeneratorConfig {
14 pub global: GlobalConfig,
16 pub companies: Vec<CompanyConfig>,
18 pub chart_of_accounts: ChartOfAccountsConfig,
20 #[serde(default)]
22 pub transactions: TransactionConfig,
23 pub output: OutputConfig,
25 #[serde(default)]
27 pub fraud: FraudConfig,
28 #[serde(default)]
30 pub data_quality: DataQualitySchemaConfig,
31 #[serde(default)]
33 pub internal_controls: InternalControlsConfig,
34 #[serde(default)]
36 pub business_processes: BusinessProcessConfig,
37 #[serde(default)]
39 pub user_personas: UserPersonaConfig,
40 #[serde(default)]
42 pub templates: TemplateConfig,
43 #[serde(default)]
45 pub approval: ApprovalConfig,
46 #[serde(default)]
48 pub departments: DepartmentConfig,
49 #[serde(default)]
51 pub master_data: MasterDataConfig,
52 #[serde(default)]
54 pub document_flows: DocumentFlowConfig,
55 #[serde(default)]
57 pub intercompany: IntercompanyConfig,
58 #[serde(default)]
60 pub balance: BalanceConfig,
61 #[serde(default)]
63 pub ocpm: OcpmConfig,
64 #[serde(default)]
66 pub audit: AuditGenerationConfig,
67 #[serde(default)]
69 pub banking: datasynth_banking::BankingConfig,
70 #[serde(default)]
72 pub scenario: ScenarioConfig,
73 #[serde(default)]
75 pub temporal: TemporalDriftConfig,
76 #[serde(default)]
78 pub graph_export: GraphExportConfig,
79 #[serde(default)]
81 pub streaming: StreamingSchemaConfig,
82 #[serde(default)]
84 pub rate_limit: RateLimitSchemaConfig,
85 #[serde(default)]
87 pub temporal_attributes: TemporalAttributeSchemaConfig,
88 #[serde(default)]
90 pub relationships: RelationshipSchemaConfig,
91 #[serde(default)]
93 pub accounting_standards: AccountingStandardsConfig,
94 #[serde(default)]
96 pub audit_standards: AuditStandardsConfig,
97 #[serde(default)]
99 pub distributions: AdvancedDistributionConfig,
100 #[serde(default)]
102 pub temporal_patterns: TemporalPatternsConfig,
103 #[serde(default)]
105 pub vendor_network: VendorNetworkSchemaConfig,
106 #[serde(default)]
108 pub customer_segmentation: CustomerSegmentationSchemaConfig,
109 #[serde(default)]
111 pub relationship_strength: RelationshipStrengthSchemaConfig,
112 #[serde(default)]
114 pub cross_process_links: CrossProcessLinksSchemaConfig,
115 #[serde(default)]
117 pub organizational_events: OrganizationalEventsSchemaConfig,
118 #[serde(default)]
120 pub behavioral_drift: BehavioralDriftSchemaConfig,
121 #[serde(default)]
123 pub market_drift: MarketDriftSchemaConfig,
124 #[serde(default)]
126 pub drift_labeling: DriftLabelingSchemaConfig,
127 #[serde(default)]
129 pub anomaly_injection: EnhancedAnomalyConfig,
130 #[serde(default)]
132 pub industry_specific: IndustrySpecificConfig,
133 #[serde(default)]
135 pub fingerprint_privacy: FingerprintPrivacyConfig,
136 #[serde(default)]
138 pub quality_gates: QualityGatesSchemaConfig,
139 #[serde(default)]
141 pub compliance: ComplianceSchemaConfig,
142 #[serde(default)]
144 pub webhooks: WebhookSchemaConfig,
145 #[serde(default)]
147 pub llm: LlmSchemaConfig,
148 #[serde(default)]
150 pub diffusion: DiffusionSchemaConfig,
151 #[serde(default)]
153 pub causal: CausalSchemaConfig,
154
155 #[serde(default)]
158 pub source_to_pay: SourceToPayConfig,
159 #[serde(default)]
161 pub financial_reporting: FinancialReportingConfig,
162 #[serde(default)]
164 pub hr: HrConfig,
165 #[serde(default)]
167 pub manufacturing: ManufacturingProcessConfig,
168 #[serde(default)]
170 pub sales_quotes: SalesQuoteConfig,
171 #[serde(default)]
173 pub tax: TaxConfig,
174 #[serde(default)]
176 pub treasury: TreasuryConfig,
177 #[serde(default)]
179 pub project_accounting: ProjectAccountingConfig,
180 #[serde(default)]
182 pub esg: EsgConfig,
183 #[serde(default)]
185 pub country_packs: Option<CountryPacksSchemaConfig>,
186 #[serde(default)]
188 pub scenarios: ScenariosConfig,
189 #[serde(default)]
191 pub session: SessionSchemaConfig,
192 #[serde(default)]
194 pub compliance_regulations: ComplianceRegulationsConfig,
195}
196
197#[derive(Debug, Clone, Serialize, Deserialize)]
203pub struct LlmSchemaConfig {
204 #[serde(default)]
206 pub enabled: bool,
207 #[serde(default = "default_llm_provider")]
209 pub provider: String,
210 #[serde(default = "default_llm_model_name")]
212 pub model: String,
213 #[serde(default = "default_llm_batch_size")]
215 pub max_vendor_enrichments: usize,
216}
217
218fn default_llm_provider() -> String {
219 "mock".to_string()
220}
221
222fn default_llm_model_name() -> String {
223 "gpt-4o-mini".to_string()
224}
225
226fn default_llm_batch_size() -> usize {
227 50
228}
229
230impl Default for LlmSchemaConfig {
231 fn default() -> Self {
232 Self {
233 enabled: false,
234 provider: default_llm_provider(),
235 model: default_llm_model_name(),
236 max_vendor_enrichments: default_llm_batch_size(),
237 }
238 }
239}
240
241#[derive(Debug, Clone, Serialize, Deserialize)]
246pub struct DiffusionSchemaConfig {
247 #[serde(default)]
249 pub enabled: bool,
250 #[serde(default = "default_diffusion_steps")]
252 pub n_steps: usize,
253 #[serde(default = "default_diffusion_schedule")]
255 pub schedule: String,
256 #[serde(default = "default_diffusion_sample_size")]
258 pub sample_size: usize,
259}
260
261fn default_diffusion_steps() -> usize {
262 100
263}
264
265fn default_diffusion_schedule() -> String {
266 "linear".to_string()
267}
268
269fn default_diffusion_sample_size() -> usize {
270 100
271}
272
273impl Default for DiffusionSchemaConfig {
274 fn default() -> Self {
275 Self {
276 enabled: false,
277 n_steps: default_diffusion_steps(),
278 schedule: default_diffusion_schedule(),
279 sample_size: default_diffusion_sample_size(),
280 }
281 }
282}
283
284#[derive(Debug, Clone, Serialize, Deserialize)]
290pub struct CausalSchemaConfig {
291 #[serde(default)]
293 pub enabled: bool,
294 #[serde(default = "default_causal_template")]
296 pub template: String,
297 #[serde(default = "default_causal_sample_size")]
299 pub sample_size: usize,
300 #[serde(default = "default_true")]
302 pub validate: bool,
303}
304
305fn default_causal_template() -> String {
306 "fraud_detection".to_string()
307}
308
309fn default_causal_sample_size() -> usize {
310 500
311}
312
313impl Default for CausalSchemaConfig {
314 fn default() -> Self {
315 Self {
316 enabled: false,
317 template: default_causal_template(),
318 sample_size: default_causal_sample_size(),
319 validate: true,
320 }
321 }
322}
323
324#[derive(Debug, Clone, Serialize, Deserialize)]
331pub struct GraphExportConfig {
332 #[serde(default)]
334 pub enabled: bool,
335
336 #[serde(default = "default_graph_types")]
338 pub graph_types: Vec<GraphTypeConfig>,
339
340 #[serde(default = "default_graph_formats")]
342 pub formats: Vec<GraphExportFormat>,
343
344 #[serde(default = "default_train_ratio")]
346 pub train_ratio: f64,
347
348 #[serde(default = "default_val_ratio")]
350 pub validation_ratio: f64,
351
352 #[serde(default)]
354 pub split_seed: Option<u64>,
355
356 #[serde(default = "default_graph_subdir")]
358 pub output_subdirectory: String,
359
360 #[serde(default)]
362 pub hypergraph: HypergraphExportSettings,
363}
364
365fn default_graph_types() -> Vec<GraphTypeConfig> {
366 vec![GraphTypeConfig::default()]
367}
368
369fn default_graph_formats() -> Vec<GraphExportFormat> {
370 vec![GraphExportFormat::PytorchGeometric]
371}
372
373fn default_train_ratio() -> f64 {
374 0.7
375}
376
377fn default_val_ratio() -> f64 {
378 0.15
379}
380
381fn default_graph_subdir() -> String {
382 "graphs".to_string()
383}
384
385impl Default for GraphExportConfig {
386 fn default() -> Self {
387 Self {
388 enabled: false,
389 graph_types: default_graph_types(),
390 formats: default_graph_formats(),
391 train_ratio: 0.7,
392 validation_ratio: 0.15,
393 split_seed: None,
394 output_subdirectory: "graphs".to_string(),
395 hypergraph: HypergraphExportSettings::default(),
396 }
397 }
398}
399
400#[derive(Debug, Clone, Serialize, Deserialize)]
407pub struct HypergraphExportSettings {
408 #[serde(default)]
410 pub enabled: bool,
411
412 #[serde(default = "default_hypergraph_max_nodes")]
414 pub max_nodes: usize,
415
416 #[serde(default = "default_aggregation_strategy")]
418 pub aggregation_strategy: String,
419
420 #[serde(default)]
422 pub governance_layer: GovernanceLayerSettings,
423
424 #[serde(default)]
426 pub process_layer: ProcessLayerSettings,
427
428 #[serde(default)]
430 pub accounting_layer: AccountingLayerSettings,
431
432 #[serde(default)]
434 pub cross_layer: CrossLayerSettings,
435
436 #[serde(default = "default_hypergraph_subdir")]
438 pub output_subdirectory: String,
439
440 #[serde(default = "default_hypergraph_format")]
442 pub output_format: String,
443
444 #[serde(default)]
446 pub stream_target: Option<String>,
447
448 #[serde(default = "default_stream_batch_size")]
450 pub stream_batch_size: usize,
451}
452
453fn default_hypergraph_max_nodes() -> usize {
454 50_000
455}
456
457fn default_aggregation_strategy() -> String {
458 "pool_by_counterparty".to_string()
459}
460
461fn default_hypergraph_subdir() -> String {
462 "hypergraph".to_string()
463}
464
465fn default_hypergraph_format() -> String {
466 "native".to_string()
467}
468
469fn default_stream_batch_size() -> usize {
470 1000
471}
472
473impl Default for HypergraphExportSettings {
474 fn default() -> Self {
475 Self {
476 enabled: false,
477 max_nodes: 50_000,
478 aggregation_strategy: "pool_by_counterparty".to_string(),
479 governance_layer: GovernanceLayerSettings::default(),
480 process_layer: ProcessLayerSettings::default(),
481 accounting_layer: AccountingLayerSettings::default(),
482 cross_layer: CrossLayerSettings::default(),
483 output_subdirectory: "hypergraph".to_string(),
484 output_format: "native".to_string(),
485 stream_target: None,
486 stream_batch_size: 1000,
487 }
488 }
489}
490
491#[derive(Debug, Clone, Serialize, Deserialize)]
493pub struct GovernanceLayerSettings {
494 #[serde(default = "default_true")]
496 pub include_coso: bool,
497 #[serde(default = "default_true")]
499 pub include_controls: bool,
500 #[serde(default = "default_true")]
502 pub include_sox: bool,
503 #[serde(default = "default_true")]
505 pub include_vendors: bool,
506 #[serde(default = "default_true")]
508 pub include_customers: bool,
509 #[serde(default = "default_true")]
511 pub include_employees: bool,
512}
513
514impl Default for GovernanceLayerSettings {
515 fn default() -> Self {
516 Self {
517 include_coso: true,
518 include_controls: true,
519 include_sox: true,
520 include_vendors: true,
521 include_customers: true,
522 include_employees: true,
523 }
524 }
525}
526
527#[derive(Debug, Clone, Serialize, Deserialize)]
529pub struct ProcessLayerSettings {
530 #[serde(default = "default_true")]
532 pub include_p2p: bool,
533 #[serde(default = "default_true")]
535 pub include_o2c: bool,
536 #[serde(default = "default_true")]
538 pub include_s2c: bool,
539 #[serde(default = "default_true")]
541 pub include_h2r: bool,
542 #[serde(default = "default_true")]
544 pub include_mfg: bool,
545 #[serde(default = "default_true")]
547 pub include_bank: bool,
548 #[serde(default = "default_true")]
550 pub include_audit: bool,
551 #[serde(default = "default_true")]
553 pub include_r2r: bool,
554 #[serde(default = "default_true")]
556 pub events_as_hyperedges: bool,
557 #[serde(default = "default_docs_per_counterparty_threshold")]
559 pub docs_per_counterparty_threshold: usize,
560}
561
562fn default_docs_per_counterparty_threshold() -> usize {
563 20
564}
565
566impl Default for ProcessLayerSettings {
567 fn default() -> Self {
568 Self {
569 include_p2p: true,
570 include_o2c: true,
571 include_s2c: true,
572 include_h2r: true,
573 include_mfg: true,
574 include_bank: true,
575 include_audit: true,
576 include_r2r: true,
577 events_as_hyperedges: true,
578 docs_per_counterparty_threshold: 20,
579 }
580 }
581}
582
583#[derive(Debug, Clone, Serialize, Deserialize)]
585pub struct AccountingLayerSettings {
586 #[serde(default = "default_true")]
588 pub include_accounts: bool,
589 #[serde(default = "default_true")]
591 pub je_as_hyperedges: bool,
592}
593
594impl Default for AccountingLayerSettings {
595 fn default() -> Self {
596 Self {
597 include_accounts: true,
598 je_as_hyperedges: true,
599 }
600 }
601}
602
603#[derive(Debug, Clone, Serialize, Deserialize)]
605pub struct CrossLayerSettings {
606 #[serde(default = "default_true")]
608 pub enabled: bool,
609}
610
611impl Default for CrossLayerSettings {
612 fn default() -> Self {
613 Self { enabled: true }
614 }
615}
616
617#[derive(Debug, Clone, Serialize, Deserialize)]
619pub struct GraphTypeConfig {
620 #[serde(default = "default_graph_name")]
622 pub name: String,
623
624 #[serde(default)]
626 pub aggregate_edges: bool,
627
628 #[serde(default)]
630 pub min_edge_weight: f64,
631
632 #[serde(default)]
634 pub include_document_nodes: bool,
635}
636
637fn default_graph_name() -> String {
638 "accounting_network".to_string()
639}
640
641impl Default for GraphTypeConfig {
642 fn default() -> Self {
643 Self {
644 name: "accounting_network".to_string(),
645 aggregate_edges: false,
646 min_edge_weight: 0.0,
647 include_document_nodes: false,
648 }
649 }
650}
651
652#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
654#[serde(rename_all = "snake_case")]
655pub enum GraphExportFormat {
656 PytorchGeometric,
658 Neo4j,
660 Dgl,
662 RustGraph,
664 RustGraphHypergraph,
666}
667
668#[derive(Debug, Clone, Default, Serialize, Deserialize)]
672pub struct ScenarioConfig {
673 #[serde(default)]
676 pub tags: Vec<String>,
677
678 #[serde(default)]
683 pub profile: Option<String>,
684
685 #[serde(default)]
687 pub description: Option<String>,
688
689 #[serde(default)]
691 pub ml_training: bool,
692
693 #[serde(default)]
696 pub target_anomaly_ratio: Option<f64>,
697
698 #[serde(default)]
700 pub metadata: std::collections::HashMap<String, String>,
701}
702
703#[derive(Debug, Clone, Serialize, Deserialize)]
708pub struct TemporalDriftConfig {
709 #[serde(default)]
711 pub enabled: bool,
712
713 #[serde(default = "default_amount_drift")]
716 pub amount_mean_drift: f64,
717
718 #[serde(default)]
721 pub amount_variance_drift: f64,
722
723 #[serde(default)]
726 pub anomaly_rate_drift: f64,
727
728 #[serde(default = "default_concept_drift")]
731 pub concept_drift_rate: f64,
732
733 #[serde(default)]
735 pub sudden_drift_probability: f64,
736
737 #[serde(default = "default_sudden_drift_magnitude")]
739 pub sudden_drift_magnitude: f64,
740
741 #[serde(default)]
743 pub seasonal_drift: bool,
744
745 #[serde(default)]
747 pub drift_start_period: u32,
748
749 #[serde(default = "default_drift_type")]
751 pub drift_type: DriftType,
752}
753
754fn default_amount_drift() -> f64 {
755 0.02
756}
757
758fn default_concept_drift() -> f64 {
759 0.01
760}
761
762fn default_sudden_drift_magnitude() -> f64 {
763 2.0
764}
765
766fn default_drift_type() -> DriftType {
767 DriftType::Gradual
768}
769
770impl Default for TemporalDriftConfig {
771 fn default() -> Self {
772 Self {
773 enabled: false,
774 amount_mean_drift: 0.02,
775 amount_variance_drift: 0.0,
776 anomaly_rate_drift: 0.0,
777 concept_drift_rate: 0.01,
778 sudden_drift_probability: 0.0,
779 sudden_drift_magnitude: 2.0,
780 seasonal_drift: false,
781 drift_start_period: 0,
782 drift_type: DriftType::Gradual,
783 }
784 }
785}
786
787impl TemporalDriftConfig {
788 pub fn to_core_config(&self) -> datasynth_core::distributions::DriftConfig {
790 datasynth_core::distributions::DriftConfig {
791 enabled: self.enabled,
792 amount_mean_drift: self.amount_mean_drift,
793 amount_variance_drift: self.amount_variance_drift,
794 anomaly_rate_drift: self.anomaly_rate_drift,
795 concept_drift_rate: self.concept_drift_rate,
796 sudden_drift_probability: self.sudden_drift_probability,
797 sudden_drift_magnitude: self.sudden_drift_magnitude,
798 seasonal_drift: self.seasonal_drift,
799 drift_start_period: self.drift_start_period,
800 drift_type: match self.drift_type {
801 DriftType::Gradual => datasynth_core::distributions::DriftType::Gradual,
802 DriftType::Sudden => datasynth_core::distributions::DriftType::Sudden,
803 DriftType::Recurring => datasynth_core::distributions::DriftType::Recurring,
804 DriftType::Mixed => datasynth_core::distributions::DriftType::Mixed,
805 },
806 regime_changes: Vec::new(),
807 economic_cycle: Default::default(),
808 parameter_drifts: Vec::new(),
809 }
810 }
811}
812
813#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
815#[serde(rename_all = "snake_case")]
816pub enum DriftType {
817 #[default]
819 Gradual,
820 Sudden,
822 Recurring,
824 Mixed,
826}
827
828#[derive(Debug, Clone, Serialize, Deserialize)]
834pub struct StreamingSchemaConfig {
835 #[serde(default)]
837 pub enabled: bool,
838 #[serde(default = "default_buffer_size")]
840 pub buffer_size: usize,
841 #[serde(default = "default_true")]
843 pub enable_progress: bool,
844 #[serde(default = "default_progress_interval")]
846 pub progress_interval: u64,
847 #[serde(default)]
849 pub backpressure: BackpressureSchemaStrategy,
850}
851
852fn default_buffer_size() -> usize {
853 1000
854}
855
856fn default_progress_interval() -> u64 {
857 100
858}
859
860impl Default for StreamingSchemaConfig {
861 fn default() -> Self {
862 Self {
863 enabled: false,
864 buffer_size: 1000,
865 enable_progress: true,
866 progress_interval: 100,
867 backpressure: BackpressureSchemaStrategy::Block,
868 }
869 }
870}
871
872#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
874#[serde(rename_all = "snake_case")]
875pub enum BackpressureSchemaStrategy {
876 #[default]
878 Block,
879 DropOldest,
881 DropNewest,
883 Buffer,
885}
886
887#[derive(Debug, Clone, Serialize, Deserialize)]
893pub struct RateLimitSchemaConfig {
894 #[serde(default)]
896 pub enabled: bool,
897 #[serde(default = "default_entities_per_second")]
899 pub entities_per_second: f64,
900 #[serde(default = "default_burst_size")]
902 pub burst_size: u32,
903 #[serde(default)]
905 pub backpressure: RateLimitBackpressureSchema,
906}
907
908fn default_entities_per_second() -> f64 {
909 1000.0
910}
911
912fn default_burst_size() -> u32 {
913 100
914}
915
916impl Default for RateLimitSchemaConfig {
917 fn default() -> Self {
918 Self {
919 enabled: false,
920 entities_per_second: 1000.0,
921 burst_size: 100,
922 backpressure: RateLimitBackpressureSchema::Block,
923 }
924 }
925}
926
927#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
929#[serde(rename_all = "snake_case")]
930pub enum RateLimitBackpressureSchema {
931 #[default]
933 Block,
934 Drop,
936 Buffer,
938}
939
940#[derive(Debug, Clone, Serialize, Deserialize)]
946pub struct TemporalAttributeSchemaConfig {
947 #[serde(default)]
949 pub enabled: bool,
950 #[serde(default)]
952 pub valid_time: ValidTimeSchemaConfig,
953 #[serde(default)]
955 pub transaction_time: TransactionTimeSchemaConfig,
956 #[serde(default)]
958 pub generate_version_chains: bool,
959 #[serde(default = "default_avg_versions")]
961 pub avg_versions_per_entity: f64,
962}
963
964fn default_avg_versions() -> f64 {
965 1.5
966}
967
968impl Default for TemporalAttributeSchemaConfig {
969 fn default() -> Self {
970 Self {
971 enabled: false,
972 valid_time: ValidTimeSchemaConfig::default(),
973 transaction_time: TransactionTimeSchemaConfig::default(),
974 generate_version_chains: false,
975 avg_versions_per_entity: 1.5,
976 }
977 }
978}
979
980#[derive(Debug, Clone, Serialize, Deserialize)]
982pub struct ValidTimeSchemaConfig {
983 #[serde(default = "default_closed_probability")]
985 pub closed_probability: f64,
986 #[serde(default = "default_avg_validity_days")]
988 pub avg_validity_days: u32,
989 #[serde(default = "default_validity_stddev")]
991 pub validity_stddev_days: u32,
992}
993
994fn default_closed_probability() -> f64 {
995 0.1
996}
997
998fn default_avg_validity_days() -> u32 {
999 365
1000}
1001
1002fn default_validity_stddev() -> u32 {
1003 90
1004}
1005
1006impl Default for ValidTimeSchemaConfig {
1007 fn default() -> Self {
1008 Self {
1009 closed_probability: 0.1,
1010 avg_validity_days: 365,
1011 validity_stddev_days: 90,
1012 }
1013 }
1014}
1015
1016#[derive(Debug, Clone, Serialize, Deserialize)]
1018pub struct TransactionTimeSchemaConfig {
1019 #[serde(default)]
1021 pub avg_recording_delay_seconds: u32,
1022 #[serde(default)]
1024 pub allow_backdating: bool,
1025 #[serde(default = "default_backdating_probability")]
1027 pub backdating_probability: f64,
1028 #[serde(default = "default_max_backdate_days")]
1030 pub max_backdate_days: u32,
1031}
1032
1033fn default_backdating_probability() -> f64 {
1034 0.01
1035}
1036
1037fn default_max_backdate_days() -> u32 {
1038 30
1039}
1040
1041impl Default for TransactionTimeSchemaConfig {
1042 fn default() -> Self {
1043 Self {
1044 avg_recording_delay_seconds: 0,
1045 allow_backdating: false,
1046 backdating_probability: 0.01,
1047 max_backdate_days: 30,
1048 }
1049 }
1050}
1051
1052#[derive(Debug, Clone, Serialize, Deserialize)]
1058pub struct RelationshipSchemaConfig {
1059 #[serde(default)]
1061 pub relationship_types: Vec<RelationshipTypeSchemaConfig>,
1062 #[serde(default = "default_true")]
1064 pub allow_orphans: bool,
1065 #[serde(default = "default_orphan_probability")]
1067 pub orphan_probability: f64,
1068 #[serde(default)]
1070 pub allow_circular: bool,
1071 #[serde(default = "default_max_circular_depth")]
1073 pub max_circular_depth: u32,
1074}
1075
1076fn default_orphan_probability() -> f64 {
1077 0.01
1078}
1079
1080fn default_max_circular_depth() -> u32 {
1081 3
1082}
1083
1084impl Default for RelationshipSchemaConfig {
1085 fn default() -> Self {
1086 Self {
1087 relationship_types: Vec::new(),
1088 allow_orphans: true,
1089 orphan_probability: 0.01,
1090 allow_circular: false,
1091 max_circular_depth: 3,
1092 }
1093 }
1094}
1095
1096#[derive(Debug, Clone, Serialize, Deserialize)]
1098pub struct RelationshipTypeSchemaConfig {
1099 pub name: String,
1101 pub source_type: String,
1103 pub target_type: String,
1105 #[serde(default)]
1107 pub cardinality: CardinalitySchemaRule,
1108 #[serde(default = "default_relationship_weight")]
1110 pub weight: f64,
1111 #[serde(default)]
1113 pub required: bool,
1114 #[serde(default = "default_true")]
1116 pub directed: bool,
1117}
1118
1119fn default_relationship_weight() -> f64 {
1120 1.0
1121}
1122
1123impl Default for RelationshipTypeSchemaConfig {
1124 fn default() -> Self {
1125 Self {
1126 name: String::new(),
1127 source_type: String::new(),
1128 target_type: String::new(),
1129 cardinality: CardinalitySchemaRule::default(),
1130 weight: 1.0,
1131 required: false,
1132 directed: true,
1133 }
1134 }
1135}
1136
1137#[derive(Debug, Clone, Serialize, Deserialize)]
1139#[serde(rename_all = "snake_case")]
1140pub enum CardinalitySchemaRule {
1141 OneToOne,
1143 OneToMany {
1145 min: u32,
1147 max: u32,
1149 },
1150 ManyToOne {
1152 min: u32,
1154 max: u32,
1156 },
1157 ManyToMany {
1159 min_per_source: u32,
1161 max_per_source: u32,
1163 },
1164}
1165
1166impl Default for CardinalitySchemaRule {
1167 fn default() -> Self {
1168 Self::OneToMany { min: 1, max: 5 }
1169 }
1170}
1171
1172#[derive(Debug, Clone, Serialize, Deserialize)]
1174pub struct GlobalConfig {
1175 pub seed: Option<u64>,
1177 pub industry: IndustrySector,
1179 pub start_date: String,
1181 pub period_months: u32,
1183 #[serde(default = "default_currency")]
1185 pub group_currency: String,
1186 #[serde(default = "default_true")]
1188 pub parallel: bool,
1189 #[serde(default)]
1191 pub worker_threads: usize,
1192 #[serde(default)]
1194 pub memory_limit_mb: usize,
1195 #[serde(default)]
1198 pub fiscal_year_months: Option<u32>,
1199}
1200
1201fn default_currency() -> String {
1202 "USD".to_string()
1203}
1204fn default_true() -> bool {
1205 true
1206}
1207
1208#[derive(Debug, Clone, Serialize, Deserialize)]
1213pub struct SessionSchemaConfig {
1214 #[serde(default)]
1216 pub enabled: bool,
1217 #[serde(default)]
1219 pub checkpoint_path: Option<String>,
1220 #[serde(default = "default_true")]
1222 pub per_period_output: bool,
1223 #[serde(default = "default_true")]
1225 pub consolidated_output: bool,
1226}
1227
1228impl Default for SessionSchemaConfig {
1229 fn default() -> Self {
1230 Self {
1231 enabled: false,
1232 checkpoint_path: None,
1233 per_period_output: true,
1234 consolidated_output: true,
1235 }
1236 }
1237}
1238
1239#[derive(Debug, Clone, Serialize, Deserialize)]
1241pub struct CompanyConfig {
1242 pub code: String,
1244 pub name: String,
1246 pub currency: String,
1248 pub country: String,
1250 #[serde(default = "default_fiscal_variant")]
1252 pub fiscal_year_variant: String,
1253 pub annual_transaction_volume: TransactionVolume,
1255 #[serde(default = "default_weight")]
1257 pub volume_weight: f64,
1258}
1259
1260fn default_fiscal_variant() -> String {
1261 "K4".to_string()
1262}
1263fn default_weight() -> f64 {
1264 1.0
1265}
1266
1267#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1269#[serde(rename_all = "snake_case")]
1270pub enum TransactionVolume {
1271 TenK,
1273 HundredK,
1275 OneM,
1277 TenM,
1279 HundredM,
1281 Custom(u64),
1283}
1284
1285impl TransactionVolume {
1286 pub fn count(&self) -> u64 {
1288 match self {
1289 Self::TenK => 10_000,
1290 Self::HundredK => 100_000,
1291 Self::OneM => 1_000_000,
1292 Self::TenM => 10_000_000,
1293 Self::HundredM => 100_000_000,
1294 Self::Custom(n) => *n,
1295 }
1296 }
1297}
1298
1299#[derive(Debug, Clone, Serialize, Deserialize)]
1301pub struct ChartOfAccountsConfig {
1302 pub complexity: CoAComplexity,
1304 #[serde(default = "default_true")]
1306 pub industry_specific: bool,
1307 pub custom_accounts: Option<PathBuf>,
1309 #[serde(default = "default_min_depth")]
1311 pub min_hierarchy_depth: u8,
1312 #[serde(default = "default_max_depth")]
1314 pub max_hierarchy_depth: u8,
1315}
1316
1317fn default_min_depth() -> u8 {
1318 2
1319}
1320fn default_max_depth() -> u8 {
1321 5
1322}
1323
1324impl Default for ChartOfAccountsConfig {
1325 fn default() -> Self {
1326 Self {
1327 complexity: CoAComplexity::Small,
1328 industry_specific: true,
1329 custom_accounts: None,
1330 min_hierarchy_depth: default_min_depth(),
1331 max_hierarchy_depth: default_max_depth(),
1332 }
1333 }
1334}
1335
1336#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1338pub struct TransactionConfig {
1339 #[serde(default)]
1341 pub line_item_distribution: LineItemDistributionConfig,
1342 #[serde(default)]
1344 pub debit_credit_distribution: DebitCreditDistributionConfig,
1345 #[serde(default)]
1347 pub even_odd_distribution: EvenOddDistributionConfig,
1348 #[serde(default)]
1350 pub source_distribution: SourceDistribution,
1351 #[serde(default)]
1353 pub seasonality: SeasonalityConfig,
1354 #[serde(default)]
1356 pub amounts: AmountDistributionConfig,
1357 #[serde(default)]
1359 pub benford: BenfordConfig,
1360}
1361
1362#[derive(Debug, Clone, Serialize, Deserialize)]
1364pub struct BenfordConfig {
1365 #[serde(default = "default_true")]
1367 pub enabled: bool,
1368 #[serde(default = "default_benford_tolerance")]
1370 pub tolerance: f64,
1371 #[serde(default)]
1373 pub exempt_sources: Vec<BenfordExemption>,
1374}
1375
1376fn default_benford_tolerance() -> f64 {
1377 0.05
1378}
1379
1380impl Default for BenfordConfig {
1381 fn default() -> Self {
1382 Self {
1383 enabled: true,
1384 tolerance: default_benford_tolerance(),
1385 exempt_sources: vec![BenfordExemption::Recurring, BenfordExemption::Payroll],
1386 }
1387 }
1388}
1389
1390#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1392#[serde(rename_all = "snake_case")]
1393pub enum BenfordExemption {
1394 Recurring,
1396 Payroll,
1398 FixedFees,
1400 RoundAmounts,
1402}
1403
1404#[derive(Debug, Clone, Serialize, Deserialize)]
1406pub struct SourceDistribution {
1407 pub manual: f64,
1409 pub automated: f64,
1411 pub recurring: f64,
1413 pub adjustment: f64,
1415}
1416
1417impl Default for SourceDistribution {
1418 fn default() -> Self {
1419 Self {
1420 manual: 0.20,
1421 automated: 0.70,
1422 recurring: 0.07,
1423 adjustment: 0.03,
1424 }
1425 }
1426}
1427
1428#[derive(Debug, Clone, Serialize, Deserialize)]
1430pub struct OutputConfig {
1431 #[serde(default)]
1433 pub mode: OutputMode,
1434 pub output_directory: PathBuf,
1436 #[serde(default = "default_formats")]
1438 pub formats: Vec<FileFormat>,
1439 #[serde(default)]
1441 pub compression: CompressionConfig,
1442 #[serde(default = "default_batch_size")]
1444 pub batch_size: usize,
1445 #[serde(default = "default_true")]
1447 pub include_acdoca: bool,
1448 #[serde(default)]
1450 pub include_bseg: bool,
1451 #[serde(default = "default_true")]
1453 pub partition_by_period: bool,
1454 #[serde(default)]
1456 pub partition_by_company: bool,
1457}
1458
1459fn default_formats() -> Vec<FileFormat> {
1460 vec![FileFormat::Parquet]
1461}
1462fn default_batch_size() -> usize {
1463 100_000
1464}
1465
1466impl Default for OutputConfig {
1467 fn default() -> Self {
1468 Self {
1469 mode: OutputMode::FlatFile,
1470 output_directory: PathBuf::from("./output"),
1471 formats: default_formats(),
1472 compression: CompressionConfig::default(),
1473 batch_size: default_batch_size(),
1474 include_acdoca: true,
1475 include_bseg: false,
1476 partition_by_period: true,
1477 partition_by_company: false,
1478 }
1479 }
1480}
1481
1482#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
1484#[serde(rename_all = "snake_case")]
1485pub enum OutputMode {
1486 Streaming,
1488 #[default]
1490 FlatFile,
1491 Both,
1493}
1494
1495#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1497#[serde(rename_all = "snake_case")]
1498pub enum FileFormat {
1499 Csv,
1500 Parquet,
1501 Json,
1502 JsonLines,
1503}
1504
1505#[derive(Debug, Clone, Serialize, Deserialize)]
1507pub struct CompressionConfig {
1508 #[serde(default = "default_true")]
1510 pub enabled: bool,
1511 #[serde(default)]
1513 pub algorithm: CompressionAlgorithm,
1514 #[serde(default = "default_compression_level")]
1516 pub level: u8,
1517}
1518
1519fn default_compression_level() -> u8 {
1520 3
1521}
1522
1523impl Default for CompressionConfig {
1524 fn default() -> Self {
1525 Self {
1526 enabled: true,
1527 algorithm: CompressionAlgorithm::default(),
1528 level: default_compression_level(),
1529 }
1530 }
1531}
1532
1533#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
1535#[serde(rename_all = "snake_case")]
1536pub enum CompressionAlgorithm {
1537 Gzip,
1538 #[default]
1539 Zstd,
1540 Lz4,
1541 Snappy,
1542}
1543
1544#[derive(Debug, Clone, Serialize, Deserialize)]
1546pub struct FraudConfig {
1547 #[serde(default)]
1549 pub enabled: bool,
1550 #[serde(default = "default_fraud_rate")]
1552 pub fraud_rate: f64,
1553 #[serde(default)]
1555 pub fraud_type_distribution: FraudTypeDistribution,
1556 #[serde(default)]
1558 pub clustering_enabled: bool,
1559 #[serde(default = "default_clustering_factor")]
1561 pub clustering_factor: f64,
1562 #[serde(default = "default_approval_thresholds")]
1564 pub approval_thresholds: Vec<f64>,
1565}
1566
1567fn default_approval_thresholds() -> Vec<f64> {
1568 vec![1000.0, 5000.0, 10000.0, 25000.0, 50000.0, 100000.0]
1569}
1570
1571fn default_fraud_rate() -> f64 {
1572 0.005
1573}
1574fn default_clustering_factor() -> f64 {
1575 3.0
1576}
1577
1578impl Default for FraudConfig {
1579 fn default() -> Self {
1580 Self {
1581 enabled: false,
1582 fraud_rate: default_fraud_rate(),
1583 fraud_type_distribution: FraudTypeDistribution::default(),
1584 clustering_enabled: false,
1585 clustering_factor: default_clustering_factor(),
1586 approval_thresholds: default_approval_thresholds(),
1587 }
1588 }
1589}
1590
1591#[derive(Debug, Clone, Serialize, Deserialize)]
1593pub struct FraudTypeDistribution {
1594 pub suspense_account_abuse: f64,
1595 pub fictitious_transaction: f64,
1596 pub revenue_manipulation: f64,
1597 pub expense_capitalization: f64,
1598 pub split_transaction: f64,
1599 pub timing_anomaly: f64,
1600 pub unauthorized_access: f64,
1601 pub duplicate_payment: f64,
1602}
1603
1604impl Default for FraudTypeDistribution {
1605 fn default() -> Self {
1606 Self {
1607 suspense_account_abuse: 0.25,
1608 fictitious_transaction: 0.15,
1609 revenue_manipulation: 0.10,
1610 expense_capitalization: 0.10,
1611 split_transaction: 0.15,
1612 timing_anomaly: 0.10,
1613 unauthorized_access: 0.10,
1614 duplicate_payment: 0.05,
1615 }
1616 }
1617}
1618
1619#[derive(Debug, Clone, Serialize, Deserialize)]
1621pub struct InternalControlsConfig {
1622 #[serde(default)]
1624 pub enabled: bool,
1625 #[serde(default = "default_exception_rate")]
1627 pub exception_rate: f64,
1628 #[serde(default = "default_sod_violation_rate")]
1630 pub sod_violation_rate: f64,
1631 #[serde(default = "default_true")]
1633 pub export_control_master_data: bool,
1634 #[serde(default = "default_sox_materiality_threshold")]
1636 pub sox_materiality_threshold: f64,
1637 #[serde(default = "default_true")]
1639 pub coso_enabled: bool,
1640 #[serde(default)]
1642 pub include_entity_level_controls: bool,
1643 #[serde(default = "default_target_maturity_level")]
1646 pub target_maturity_level: String,
1647}
1648
1649fn default_exception_rate() -> f64 {
1650 0.02
1651}
1652
1653fn default_sod_violation_rate() -> f64 {
1654 0.01
1655}
1656
1657fn default_sox_materiality_threshold() -> f64 {
1658 10000.0
1659}
1660
1661fn default_target_maturity_level() -> String {
1662 "mixed".to_string()
1663}
1664
1665impl Default for InternalControlsConfig {
1666 fn default() -> Self {
1667 Self {
1668 enabled: false,
1669 exception_rate: default_exception_rate(),
1670 sod_violation_rate: default_sod_violation_rate(),
1671 export_control_master_data: true,
1672 sox_materiality_threshold: default_sox_materiality_threshold(),
1673 coso_enabled: true,
1674 include_entity_level_controls: false,
1675 target_maturity_level: default_target_maturity_level(),
1676 }
1677 }
1678}
1679
1680#[derive(Debug, Clone, Serialize, Deserialize)]
1682pub struct BusinessProcessConfig {
1683 #[serde(default = "default_o2c")]
1685 pub o2c_weight: f64,
1686 #[serde(default = "default_p2p")]
1688 pub p2p_weight: f64,
1689 #[serde(default = "default_r2r")]
1691 pub r2r_weight: f64,
1692 #[serde(default = "default_h2r")]
1694 pub h2r_weight: f64,
1695 #[serde(default = "default_a2r")]
1697 pub a2r_weight: f64,
1698}
1699
1700fn default_o2c() -> f64 {
1701 0.35
1702}
1703fn default_p2p() -> f64 {
1704 0.30
1705}
1706fn default_r2r() -> f64 {
1707 0.20
1708}
1709fn default_h2r() -> f64 {
1710 0.10
1711}
1712fn default_a2r() -> f64 {
1713 0.05
1714}
1715
1716impl Default for BusinessProcessConfig {
1717 fn default() -> Self {
1718 Self {
1719 o2c_weight: default_o2c(),
1720 p2p_weight: default_p2p(),
1721 r2r_weight: default_r2r(),
1722 h2r_weight: default_h2r(),
1723 a2r_weight: default_a2r(),
1724 }
1725 }
1726}
1727
1728#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1730pub struct UserPersonaConfig {
1731 #[serde(default)]
1733 pub persona_distribution: PersonaDistribution,
1734 #[serde(default)]
1736 pub users_per_persona: UsersPerPersona,
1737}
1738
1739#[derive(Debug, Clone, Serialize, Deserialize)]
1741pub struct PersonaDistribution {
1742 pub junior_accountant: f64,
1743 pub senior_accountant: f64,
1744 pub controller: f64,
1745 pub manager: f64,
1746 pub automated_system: f64,
1747}
1748
1749impl Default for PersonaDistribution {
1750 fn default() -> Self {
1751 Self {
1752 junior_accountant: 0.15,
1753 senior_accountant: 0.15,
1754 controller: 0.05,
1755 manager: 0.05,
1756 automated_system: 0.60,
1757 }
1758 }
1759}
1760
1761#[derive(Debug, Clone, Serialize, Deserialize)]
1763pub struct UsersPerPersona {
1764 pub junior_accountant: usize,
1765 pub senior_accountant: usize,
1766 pub controller: usize,
1767 pub manager: usize,
1768 pub automated_system: usize,
1769}
1770
1771impl Default for UsersPerPersona {
1772 fn default() -> Self {
1773 Self {
1774 junior_accountant: 10,
1775 senior_accountant: 5,
1776 controller: 2,
1777 manager: 3,
1778 automated_system: 20,
1779 }
1780 }
1781}
1782
1783#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1785pub struct TemplateConfig {
1786 #[serde(default)]
1788 pub names: NameTemplateConfig,
1789 #[serde(default)]
1791 pub descriptions: DescriptionTemplateConfig,
1792 #[serde(default)]
1794 pub references: ReferenceTemplateConfig,
1795}
1796
1797#[derive(Debug, Clone, Serialize, Deserialize)]
1799pub struct NameTemplateConfig {
1800 #[serde(default)]
1802 pub culture_distribution: CultureDistribution,
1803 #[serde(default = "default_email_domain")]
1805 pub email_domain: String,
1806 #[serde(default = "default_true")]
1808 pub generate_realistic_names: bool,
1809}
1810
1811fn default_email_domain() -> String {
1812 "company.com".to_string()
1813}
1814
1815impl Default for NameTemplateConfig {
1816 fn default() -> Self {
1817 Self {
1818 culture_distribution: CultureDistribution::default(),
1819 email_domain: default_email_domain(),
1820 generate_realistic_names: true,
1821 }
1822 }
1823}
1824
1825#[derive(Debug, Clone, Serialize, Deserialize)]
1827pub struct CultureDistribution {
1828 pub western_us: f64,
1829 pub hispanic: f64,
1830 pub german: f64,
1831 pub french: f64,
1832 pub chinese: f64,
1833 pub japanese: f64,
1834 pub indian: f64,
1835}
1836
1837impl Default for CultureDistribution {
1838 fn default() -> Self {
1839 Self {
1840 western_us: 0.40,
1841 hispanic: 0.20,
1842 german: 0.10,
1843 french: 0.05,
1844 chinese: 0.10,
1845 japanese: 0.05,
1846 indian: 0.10,
1847 }
1848 }
1849}
1850
1851#[derive(Debug, Clone, Serialize, Deserialize)]
1853pub struct DescriptionTemplateConfig {
1854 #[serde(default = "default_true")]
1856 pub generate_header_text: bool,
1857 #[serde(default = "default_true")]
1859 pub generate_line_text: bool,
1860}
1861
1862impl Default for DescriptionTemplateConfig {
1863 fn default() -> Self {
1864 Self {
1865 generate_header_text: true,
1866 generate_line_text: true,
1867 }
1868 }
1869}
1870
1871#[derive(Debug, Clone, Serialize, Deserialize)]
1873pub struct ReferenceTemplateConfig {
1874 #[serde(default = "default_true")]
1876 pub generate_references: bool,
1877 #[serde(default = "default_invoice_prefix")]
1879 pub invoice_prefix: String,
1880 #[serde(default = "default_po_prefix")]
1882 pub po_prefix: String,
1883 #[serde(default = "default_so_prefix")]
1885 pub so_prefix: String,
1886}
1887
1888fn default_invoice_prefix() -> String {
1889 "INV".to_string()
1890}
1891fn default_po_prefix() -> String {
1892 "PO".to_string()
1893}
1894fn default_so_prefix() -> String {
1895 "SO".to_string()
1896}
1897
1898impl Default for ReferenceTemplateConfig {
1899 fn default() -> Self {
1900 Self {
1901 generate_references: true,
1902 invoice_prefix: default_invoice_prefix(),
1903 po_prefix: default_po_prefix(),
1904 so_prefix: default_so_prefix(),
1905 }
1906 }
1907}
1908
1909#[derive(Debug, Clone, Serialize, Deserialize)]
1911pub struct ApprovalConfig {
1912 #[serde(default)]
1914 pub enabled: bool,
1915 #[serde(default = "default_auto_approve_threshold")]
1917 pub auto_approve_threshold: f64,
1918 #[serde(default = "default_rejection_rate")]
1920 pub rejection_rate: f64,
1921 #[serde(default = "default_revision_rate")]
1923 pub revision_rate: f64,
1924 #[serde(default = "default_approval_delay_hours")]
1926 pub average_approval_delay_hours: f64,
1927 #[serde(default)]
1929 pub thresholds: Vec<ApprovalThresholdConfig>,
1930}
1931
1932fn default_auto_approve_threshold() -> f64 {
1933 1000.0
1934}
1935fn default_rejection_rate() -> f64 {
1936 0.02
1937}
1938fn default_revision_rate() -> f64 {
1939 0.05
1940}
1941fn default_approval_delay_hours() -> f64 {
1942 4.0
1943}
1944
1945impl Default for ApprovalConfig {
1946 fn default() -> Self {
1947 Self {
1948 enabled: false,
1949 auto_approve_threshold: default_auto_approve_threshold(),
1950 rejection_rate: default_rejection_rate(),
1951 revision_rate: default_revision_rate(),
1952 average_approval_delay_hours: default_approval_delay_hours(),
1953 thresholds: vec![
1954 ApprovalThresholdConfig {
1955 amount: 1000.0,
1956 level: 1,
1957 roles: vec!["senior_accountant".to_string()],
1958 },
1959 ApprovalThresholdConfig {
1960 amount: 10000.0,
1961 level: 2,
1962 roles: vec!["senior_accountant".to_string(), "controller".to_string()],
1963 },
1964 ApprovalThresholdConfig {
1965 amount: 100000.0,
1966 level: 3,
1967 roles: vec![
1968 "senior_accountant".to_string(),
1969 "controller".to_string(),
1970 "manager".to_string(),
1971 ],
1972 },
1973 ApprovalThresholdConfig {
1974 amount: 500000.0,
1975 level: 4,
1976 roles: vec![
1977 "senior_accountant".to_string(),
1978 "controller".to_string(),
1979 "manager".to_string(),
1980 "executive".to_string(),
1981 ],
1982 },
1983 ],
1984 }
1985 }
1986}
1987
1988#[derive(Debug, Clone, Serialize, Deserialize)]
1990pub struct ApprovalThresholdConfig {
1991 pub amount: f64,
1993 pub level: u8,
1995 pub roles: Vec<String>,
1997}
1998
1999#[derive(Debug, Clone, Serialize, Deserialize)]
2001pub struct DepartmentConfig {
2002 #[serde(default)]
2004 pub enabled: bool,
2005 #[serde(default = "default_headcount_multiplier")]
2007 pub headcount_multiplier: f64,
2008 #[serde(default)]
2010 pub custom_departments: Vec<CustomDepartmentConfig>,
2011}
2012
2013fn default_headcount_multiplier() -> f64 {
2014 1.0
2015}
2016
2017impl Default for DepartmentConfig {
2018 fn default() -> Self {
2019 Self {
2020 enabled: false,
2021 headcount_multiplier: default_headcount_multiplier(),
2022 custom_departments: Vec::new(),
2023 }
2024 }
2025}
2026
2027#[derive(Debug, Clone, Serialize, Deserialize)]
2029pub struct CustomDepartmentConfig {
2030 pub code: String,
2032 pub name: String,
2034 #[serde(default)]
2036 pub cost_center: Option<String>,
2037 #[serde(default)]
2039 pub primary_processes: Vec<String>,
2040 #[serde(default)]
2042 pub parent_code: Option<String>,
2043}
2044
2045#[derive(Debug, Clone, Default, Serialize, Deserialize)]
2051pub struct MasterDataConfig {
2052 #[serde(default)]
2054 pub vendors: VendorMasterConfig,
2055 #[serde(default)]
2057 pub customers: CustomerMasterConfig,
2058 #[serde(default)]
2060 pub materials: MaterialMasterConfig,
2061 #[serde(default)]
2063 pub fixed_assets: FixedAssetMasterConfig,
2064 #[serde(default)]
2066 pub employees: EmployeeMasterConfig,
2067 #[serde(default)]
2069 pub cost_centers: CostCenterMasterConfig,
2070}
2071
2072#[derive(Debug, Clone, Serialize, Deserialize)]
2074pub struct VendorMasterConfig {
2075 #[serde(default = "default_vendor_count")]
2077 pub count: usize,
2078 #[serde(default = "default_intercompany_percent")]
2080 pub intercompany_percent: f64,
2081 #[serde(default)]
2083 pub payment_terms_distribution: PaymentTermsDistribution,
2084 #[serde(default)]
2086 pub behavior_distribution: VendorBehaviorDistribution,
2087 #[serde(default = "default_true")]
2089 pub generate_bank_accounts: bool,
2090 #[serde(default = "default_true")]
2092 pub generate_tax_ids: bool,
2093}
2094
2095fn default_vendor_count() -> usize {
2096 500
2097}
2098
2099fn default_intercompany_percent() -> f64 {
2100 0.05
2101}
2102
2103impl Default for VendorMasterConfig {
2104 fn default() -> Self {
2105 Self {
2106 count: default_vendor_count(),
2107 intercompany_percent: default_intercompany_percent(),
2108 payment_terms_distribution: PaymentTermsDistribution::default(),
2109 behavior_distribution: VendorBehaviorDistribution::default(),
2110 generate_bank_accounts: true,
2111 generate_tax_ids: true,
2112 }
2113 }
2114}
2115
2116#[derive(Debug, Clone, Serialize, Deserialize)]
2118pub struct PaymentTermsDistribution {
2119 pub net_30: f64,
2121 pub net_60: f64,
2123 pub net_90: f64,
2125 pub two_ten_net_30: f64,
2127 pub due_on_receipt: f64,
2129 pub end_of_month: f64,
2131}
2132
2133impl Default for PaymentTermsDistribution {
2134 fn default() -> Self {
2135 Self {
2136 net_30: 0.40,
2137 net_60: 0.20,
2138 net_90: 0.10,
2139 two_ten_net_30: 0.15,
2140 due_on_receipt: 0.05,
2141 end_of_month: 0.10,
2142 }
2143 }
2144}
2145
2146#[derive(Debug, Clone, Serialize, Deserialize)]
2148pub struct VendorBehaviorDistribution {
2149 pub reliable: f64,
2151 pub sometimes_late: f64,
2153 pub inconsistent_quality: f64,
2155 pub premium: f64,
2157 pub budget: f64,
2159}
2160
2161impl Default for VendorBehaviorDistribution {
2162 fn default() -> Self {
2163 Self {
2164 reliable: 0.50,
2165 sometimes_late: 0.20,
2166 inconsistent_quality: 0.10,
2167 premium: 0.10,
2168 budget: 0.10,
2169 }
2170 }
2171}
2172
2173#[derive(Debug, Clone, Serialize, Deserialize)]
2175pub struct CustomerMasterConfig {
2176 #[serde(default = "default_customer_count")]
2178 pub count: usize,
2179 #[serde(default = "default_intercompany_percent")]
2181 pub intercompany_percent: f64,
2182 #[serde(default)]
2184 pub credit_rating_distribution: CreditRatingDistribution,
2185 #[serde(default)]
2187 pub payment_behavior_distribution: PaymentBehaviorDistribution,
2188 #[serde(default = "default_true")]
2190 pub generate_credit_limits: bool,
2191}
2192
2193fn default_customer_count() -> usize {
2194 2000
2195}
2196
2197impl Default for CustomerMasterConfig {
2198 fn default() -> Self {
2199 Self {
2200 count: default_customer_count(),
2201 intercompany_percent: default_intercompany_percent(),
2202 credit_rating_distribution: CreditRatingDistribution::default(),
2203 payment_behavior_distribution: PaymentBehaviorDistribution::default(),
2204 generate_credit_limits: true,
2205 }
2206 }
2207}
2208
2209#[derive(Debug, Clone, Serialize, Deserialize)]
2211pub struct CreditRatingDistribution {
2212 pub aaa: f64,
2214 pub aa: f64,
2216 pub a: f64,
2218 pub bbb: f64,
2220 pub bb: f64,
2222 pub b: f64,
2224 pub below_b: f64,
2226}
2227
2228impl Default for CreditRatingDistribution {
2229 fn default() -> Self {
2230 Self {
2231 aaa: 0.05,
2232 aa: 0.10,
2233 a: 0.20,
2234 bbb: 0.30,
2235 bb: 0.20,
2236 b: 0.10,
2237 below_b: 0.05,
2238 }
2239 }
2240}
2241
2242#[derive(Debug, Clone, Serialize, Deserialize)]
2244pub struct PaymentBehaviorDistribution {
2245 pub early_payer: f64,
2247 pub on_time: f64,
2249 pub occasional_late: f64,
2251 pub frequent_late: f64,
2253 pub discount_taker: f64,
2255}
2256
2257impl Default for PaymentBehaviorDistribution {
2258 fn default() -> Self {
2259 Self {
2260 early_payer: 0.10,
2261 on_time: 0.50,
2262 occasional_late: 0.25,
2263 frequent_late: 0.10,
2264 discount_taker: 0.05,
2265 }
2266 }
2267}
2268
2269#[derive(Debug, Clone, Serialize, Deserialize)]
2271pub struct MaterialMasterConfig {
2272 #[serde(default = "default_material_count")]
2274 pub count: usize,
2275 #[serde(default)]
2277 pub type_distribution: MaterialTypeDistribution,
2278 #[serde(default)]
2280 pub valuation_distribution: ValuationMethodDistribution,
2281 #[serde(default = "default_bom_percent")]
2283 pub bom_percent: f64,
2284 #[serde(default = "default_max_bom_depth")]
2286 pub max_bom_depth: u8,
2287}
2288
2289fn default_material_count() -> usize {
2290 5000
2291}
2292
2293fn default_bom_percent() -> f64 {
2294 0.20
2295}
2296
2297fn default_max_bom_depth() -> u8 {
2298 3
2299}
2300
2301impl Default for MaterialMasterConfig {
2302 fn default() -> Self {
2303 Self {
2304 count: default_material_count(),
2305 type_distribution: MaterialTypeDistribution::default(),
2306 valuation_distribution: ValuationMethodDistribution::default(),
2307 bom_percent: default_bom_percent(),
2308 max_bom_depth: default_max_bom_depth(),
2309 }
2310 }
2311}
2312
2313#[derive(Debug, Clone, Serialize, Deserialize)]
2315pub struct MaterialTypeDistribution {
2316 pub raw_material: f64,
2318 pub semi_finished: f64,
2320 pub finished_good: f64,
2322 pub trading_good: f64,
2324 pub operating_supply: f64,
2326 pub service: f64,
2328}
2329
2330impl Default for MaterialTypeDistribution {
2331 fn default() -> Self {
2332 Self {
2333 raw_material: 0.30,
2334 semi_finished: 0.15,
2335 finished_good: 0.25,
2336 trading_good: 0.15,
2337 operating_supply: 0.10,
2338 service: 0.05,
2339 }
2340 }
2341}
2342
2343#[derive(Debug, Clone, Serialize, Deserialize)]
2345pub struct ValuationMethodDistribution {
2346 pub standard_cost: f64,
2348 pub moving_average: f64,
2350 pub fifo: f64,
2352 pub lifo: f64,
2354}
2355
2356impl Default for ValuationMethodDistribution {
2357 fn default() -> Self {
2358 Self {
2359 standard_cost: 0.50,
2360 moving_average: 0.30,
2361 fifo: 0.15,
2362 lifo: 0.05,
2363 }
2364 }
2365}
2366
2367#[derive(Debug, Clone, Serialize, Deserialize)]
2369pub struct FixedAssetMasterConfig {
2370 #[serde(default = "default_asset_count")]
2372 pub count: usize,
2373 #[serde(default)]
2375 pub class_distribution: AssetClassDistribution,
2376 #[serde(default)]
2378 pub depreciation_distribution: DepreciationMethodDistribution,
2379 #[serde(default = "default_fully_depreciated_percent")]
2381 pub fully_depreciated_percent: f64,
2382 #[serde(default = "default_true")]
2384 pub generate_acquisition_history: bool,
2385}
2386
2387fn default_asset_count() -> usize {
2388 800
2389}
2390
2391fn default_fully_depreciated_percent() -> f64 {
2392 0.15
2393}
2394
2395impl Default for FixedAssetMasterConfig {
2396 fn default() -> Self {
2397 Self {
2398 count: default_asset_count(),
2399 class_distribution: AssetClassDistribution::default(),
2400 depreciation_distribution: DepreciationMethodDistribution::default(),
2401 fully_depreciated_percent: default_fully_depreciated_percent(),
2402 generate_acquisition_history: true,
2403 }
2404 }
2405}
2406
2407#[derive(Debug, Clone, Serialize, Deserialize)]
2409pub struct AssetClassDistribution {
2410 pub buildings: f64,
2412 pub machinery: f64,
2414 pub vehicles: f64,
2416 pub it_equipment: f64,
2418 pub furniture: f64,
2420 pub land: f64,
2422 pub leasehold: f64,
2424}
2425
2426impl Default for AssetClassDistribution {
2427 fn default() -> Self {
2428 Self {
2429 buildings: 0.15,
2430 machinery: 0.30,
2431 vehicles: 0.15,
2432 it_equipment: 0.20,
2433 furniture: 0.10,
2434 land: 0.05,
2435 leasehold: 0.05,
2436 }
2437 }
2438}
2439
2440#[derive(Debug, Clone, Serialize, Deserialize)]
2442pub struct DepreciationMethodDistribution {
2443 pub straight_line: f64,
2445 pub declining_balance: f64,
2447 pub double_declining: f64,
2449 pub sum_of_years: f64,
2451 pub units_of_production: f64,
2453}
2454
2455impl Default for DepreciationMethodDistribution {
2456 fn default() -> Self {
2457 Self {
2458 straight_line: 0.60,
2459 declining_balance: 0.20,
2460 double_declining: 0.10,
2461 sum_of_years: 0.05,
2462 units_of_production: 0.05,
2463 }
2464 }
2465}
2466
2467#[derive(Debug, Clone, Serialize, Deserialize)]
2469pub struct EmployeeMasterConfig {
2470 #[serde(default = "default_employee_count")]
2472 pub count: usize,
2473 #[serde(default = "default_true")]
2475 pub generate_hierarchy: bool,
2476 #[serde(default = "default_hierarchy_depth")]
2478 pub max_hierarchy_depth: u8,
2479 #[serde(default = "default_span_of_control")]
2481 pub average_span_of_control: f64,
2482 #[serde(default)]
2484 pub approval_limits: ApprovalLimitDistribution,
2485 #[serde(default)]
2487 pub department_distribution: EmployeeDepartmentDistribution,
2488}
2489
2490fn default_employee_count() -> usize {
2491 1500
2492}
2493
2494fn default_hierarchy_depth() -> u8 {
2495 6
2496}
2497
2498fn default_span_of_control() -> f64 {
2499 5.0
2500}
2501
2502impl Default for EmployeeMasterConfig {
2503 fn default() -> Self {
2504 Self {
2505 count: default_employee_count(),
2506 generate_hierarchy: true,
2507 max_hierarchy_depth: default_hierarchy_depth(),
2508 average_span_of_control: default_span_of_control(),
2509 approval_limits: ApprovalLimitDistribution::default(),
2510 department_distribution: EmployeeDepartmentDistribution::default(),
2511 }
2512 }
2513}
2514
2515#[derive(Debug, Clone, Serialize, Deserialize)]
2517pub struct ApprovalLimitDistribution {
2518 #[serde(default = "default_staff_limit")]
2520 pub staff: f64,
2521 #[serde(default = "default_senior_limit")]
2523 pub senior: f64,
2524 #[serde(default = "default_manager_limit")]
2526 pub manager: f64,
2527 #[serde(default = "default_director_limit")]
2529 pub director: f64,
2530 #[serde(default = "default_vp_limit")]
2532 pub vp: f64,
2533 #[serde(default = "default_executive_limit")]
2535 pub executive: f64,
2536}
2537
2538fn default_staff_limit() -> f64 {
2539 1000.0
2540}
2541fn default_senior_limit() -> f64 {
2542 5000.0
2543}
2544fn default_manager_limit() -> f64 {
2545 25000.0
2546}
2547fn default_director_limit() -> f64 {
2548 100000.0
2549}
2550fn default_vp_limit() -> f64 {
2551 500000.0
2552}
2553fn default_executive_limit() -> f64 {
2554 f64::INFINITY
2555}
2556
2557impl Default for ApprovalLimitDistribution {
2558 fn default() -> Self {
2559 Self {
2560 staff: default_staff_limit(),
2561 senior: default_senior_limit(),
2562 manager: default_manager_limit(),
2563 director: default_director_limit(),
2564 vp: default_vp_limit(),
2565 executive: default_executive_limit(),
2566 }
2567 }
2568}
2569
2570#[derive(Debug, Clone, Serialize, Deserialize)]
2572pub struct EmployeeDepartmentDistribution {
2573 pub finance: f64,
2575 pub procurement: f64,
2577 pub sales: f64,
2579 pub warehouse: f64,
2581 pub it: f64,
2583 pub hr: f64,
2585 pub operations: f64,
2587 pub executive: f64,
2589}
2590
2591impl Default for EmployeeDepartmentDistribution {
2592 fn default() -> Self {
2593 Self {
2594 finance: 0.12,
2595 procurement: 0.10,
2596 sales: 0.25,
2597 warehouse: 0.15,
2598 it: 0.10,
2599 hr: 0.05,
2600 operations: 0.20,
2601 executive: 0.03,
2602 }
2603 }
2604}
2605
2606#[derive(Debug, Clone, Serialize, Deserialize)]
2608pub struct CostCenterMasterConfig {
2609 #[serde(default = "default_cost_center_count")]
2611 pub count: usize,
2612 #[serde(default = "default_true")]
2614 pub generate_hierarchy: bool,
2615 #[serde(default = "default_cc_hierarchy_depth")]
2617 pub max_hierarchy_depth: u8,
2618}
2619
2620fn default_cost_center_count() -> usize {
2621 50
2622}
2623
2624fn default_cc_hierarchy_depth() -> u8 {
2625 3
2626}
2627
2628impl Default for CostCenterMasterConfig {
2629 fn default() -> Self {
2630 Self {
2631 count: default_cost_center_count(),
2632 generate_hierarchy: true,
2633 max_hierarchy_depth: default_cc_hierarchy_depth(),
2634 }
2635 }
2636}
2637
2638#[derive(Debug, Clone, Serialize, Deserialize)]
2644pub struct DocumentFlowConfig {
2645 #[serde(default)]
2647 pub p2p: P2PFlowConfig,
2648 #[serde(default)]
2650 pub o2c: O2CFlowConfig,
2651 #[serde(default = "default_true")]
2653 pub generate_document_references: bool,
2654 #[serde(default)]
2656 pub export_flow_graph: bool,
2657}
2658
2659impl Default for DocumentFlowConfig {
2660 fn default() -> Self {
2661 Self {
2662 p2p: P2PFlowConfig::default(),
2663 o2c: O2CFlowConfig::default(),
2664 generate_document_references: true,
2665 export_flow_graph: false,
2666 }
2667 }
2668}
2669
2670#[derive(Debug, Clone, Serialize, Deserialize)]
2672pub struct P2PFlowConfig {
2673 #[serde(default = "default_true")]
2675 pub enabled: bool,
2676 #[serde(default = "default_three_way_match_rate")]
2678 pub three_way_match_rate: f64,
2679 #[serde(default = "default_partial_delivery_rate")]
2681 pub partial_delivery_rate: f64,
2682 #[serde(default = "default_price_variance_rate")]
2684 pub price_variance_rate: f64,
2685 #[serde(default = "default_max_price_variance")]
2687 pub max_price_variance_percent: f64,
2688 #[serde(default = "default_quantity_variance_rate")]
2690 pub quantity_variance_rate: f64,
2691 #[serde(default = "default_po_to_gr_days")]
2693 pub average_po_to_gr_days: u32,
2694 #[serde(default = "default_gr_to_invoice_days")]
2696 pub average_gr_to_invoice_days: u32,
2697 #[serde(default = "default_invoice_to_payment_days")]
2699 pub average_invoice_to_payment_days: u32,
2700 #[serde(default)]
2702 pub line_count_distribution: DocumentLineCountDistribution,
2703 #[serde(default)]
2705 pub payment_behavior: P2PPaymentBehaviorConfig,
2706 #[serde(default)]
2708 pub over_delivery_rate: Option<f64>,
2709 #[serde(default)]
2711 pub early_payment_discount_rate: Option<f64>,
2712}
2713
2714fn default_three_way_match_rate() -> f64 {
2715 0.95
2716}
2717
2718fn default_partial_delivery_rate() -> f64 {
2719 0.15
2720}
2721
2722fn default_price_variance_rate() -> f64 {
2723 0.08
2724}
2725
2726fn default_max_price_variance() -> f64 {
2727 0.05
2728}
2729
2730fn default_quantity_variance_rate() -> f64 {
2731 0.05
2732}
2733
2734fn default_po_to_gr_days() -> u32 {
2735 14
2736}
2737
2738fn default_gr_to_invoice_days() -> u32 {
2739 5
2740}
2741
2742fn default_invoice_to_payment_days() -> u32 {
2743 30
2744}
2745
2746impl Default for P2PFlowConfig {
2747 fn default() -> Self {
2748 Self {
2749 enabled: true,
2750 three_way_match_rate: default_three_way_match_rate(),
2751 partial_delivery_rate: default_partial_delivery_rate(),
2752 price_variance_rate: default_price_variance_rate(),
2753 max_price_variance_percent: default_max_price_variance(),
2754 quantity_variance_rate: default_quantity_variance_rate(),
2755 average_po_to_gr_days: default_po_to_gr_days(),
2756 average_gr_to_invoice_days: default_gr_to_invoice_days(),
2757 average_invoice_to_payment_days: default_invoice_to_payment_days(),
2758 line_count_distribution: DocumentLineCountDistribution::default(),
2759 payment_behavior: P2PPaymentBehaviorConfig::default(),
2760 over_delivery_rate: None,
2761 early_payment_discount_rate: None,
2762 }
2763 }
2764}
2765
2766#[derive(Debug, Clone, Serialize, Deserialize)]
2772pub struct P2PPaymentBehaviorConfig {
2773 #[serde(default = "default_p2p_late_payment_rate")]
2775 pub late_payment_rate: f64,
2776 #[serde(default)]
2778 pub late_payment_days_distribution: LatePaymentDaysDistribution,
2779 #[serde(default = "default_p2p_partial_payment_rate")]
2781 pub partial_payment_rate: f64,
2782 #[serde(default = "default_p2p_payment_correction_rate")]
2784 pub payment_correction_rate: f64,
2785 #[serde(default = "default_p2p_avg_days_until_remainder")]
2787 pub avg_days_until_remainder: u32,
2788}
2789
2790fn default_p2p_late_payment_rate() -> f64 {
2791 0.15
2792}
2793
2794fn default_p2p_partial_payment_rate() -> f64 {
2795 0.05
2796}
2797
2798fn default_p2p_payment_correction_rate() -> f64 {
2799 0.02
2800}
2801
2802fn default_p2p_avg_days_until_remainder() -> u32 {
2803 30
2804}
2805
2806impl Default for P2PPaymentBehaviorConfig {
2807 fn default() -> Self {
2808 Self {
2809 late_payment_rate: default_p2p_late_payment_rate(),
2810 late_payment_days_distribution: LatePaymentDaysDistribution::default(),
2811 partial_payment_rate: default_p2p_partial_payment_rate(),
2812 payment_correction_rate: default_p2p_payment_correction_rate(),
2813 avg_days_until_remainder: default_p2p_avg_days_until_remainder(),
2814 }
2815 }
2816}
2817
2818#[derive(Debug, Clone, Serialize, Deserialize)]
2820pub struct LatePaymentDaysDistribution {
2821 #[serde(default = "default_slightly_late")]
2823 pub slightly_late_1_to_7: f64,
2824 #[serde(default = "default_late_8_14")]
2826 pub late_8_to_14: f64,
2827 #[serde(default = "default_very_late")]
2829 pub very_late_15_to_30: f64,
2830 #[serde(default = "default_severely_late")]
2832 pub severely_late_31_to_60: f64,
2833 #[serde(default = "default_extremely_late")]
2835 pub extremely_late_over_60: f64,
2836}
2837
2838fn default_slightly_late() -> f64 {
2839 0.50
2840}
2841
2842fn default_late_8_14() -> f64 {
2843 0.25
2844}
2845
2846fn default_very_late() -> f64 {
2847 0.15
2848}
2849
2850fn default_severely_late() -> f64 {
2851 0.07
2852}
2853
2854fn default_extremely_late() -> f64 {
2855 0.03
2856}
2857
2858impl Default for LatePaymentDaysDistribution {
2859 fn default() -> Self {
2860 Self {
2861 slightly_late_1_to_7: default_slightly_late(),
2862 late_8_to_14: default_late_8_14(),
2863 very_late_15_to_30: default_very_late(),
2864 severely_late_31_to_60: default_severely_late(),
2865 extremely_late_over_60: default_extremely_late(),
2866 }
2867 }
2868}
2869
2870#[derive(Debug, Clone, Serialize, Deserialize)]
2872pub struct O2CFlowConfig {
2873 #[serde(default = "default_true")]
2875 pub enabled: bool,
2876 #[serde(default = "default_credit_check_failure_rate")]
2878 pub credit_check_failure_rate: f64,
2879 #[serde(default = "default_partial_shipment_rate")]
2881 pub partial_shipment_rate: f64,
2882 #[serde(default = "default_return_rate")]
2884 pub return_rate: f64,
2885 #[serde(default = "default_bad_debt_rate")]
2887 pub bad_debt_rate: f64,
2888 #[serde(default = "default_so_to_delivery_days")]
2890 pub average_so_to_delivery_days: u32,
2891 #[serde(default = "default_delivery_to_invoice_days")]
2893 pub average_delivery_to_invoice_days: u32,
2894 #[serde(default = "default_invoice_to_receipt_days")]
2896 pub average_invoice_to_receipt_days: u32,
2897 #[serde(default)]
2899 pub line_count_distribution: DocumentLineCountDistribution,
2900 #[serde(default)]
2902 pub cash_discount: CashDiscountConfig,
2903 #[serde(default)]
2905 pub payment_behavior: O2CPaymentBehaviorConfig,
2906 #[serde(default)]
2908 pub late_payment_rate: Option<f64>,
2909}
2910
2911fn default_credit_check_failure_rate() -> f64 {
2912 0.02
2913}
2914
2915fn default_partial_shipment_rate() -> f64 {
2916 0.10
2917}
2918
2919fn default_return_rate() -> f64 {
2920 0.03
2921}
2922
2923fn default_bad_debt_rate() -> f64 {
2924 0.01
2925}
2926
2927fn default_so_to_delivery_days() -> u32 {
2928 7
2929}
2930
2931fn default_delivery_to_invoice_days() -> u32 {
2932 1
2933}
2934
2935fn default_invoice_to_receipt_days() -> u32 {
2936 45
2937}
2938
2939impl Default for O2CFlowConfig {
2940 fn default() -> Self {
2941 Self {
2942 enabled: true,
2943 credit_check_failure_rate: default_credit_check_failure_rate(),
2944 partial_shipment_rate: default_partial_shipment_rate(),
2945 return_rate: default_return_rate(),
2946 bad_debt_rate: default_bad_debt_rate(),
2947 average_so_to_delivery_days: default_so_to_delivery_days(),
2948 average_delivery_to_invoice_days: default_delivery_to_invoice_days(),
2949 average_invoice_to_receipt_days: default_invoice_to_receipt_days(),
2950 line_count_distribution: DocumentLineCountDistribution::default(),
2951 cash_discount: CashDiscountConfig::default(),
2952 payment_behavior: O2CPaymentBehaviorConfig::default(),
2953 late_payment_rate: None,
2954 }
2955 }
2956}
2957
2958#[derive(Debug, Clone, Serialize, Deserialize, Default)]
2964pub struct O2CPaymentBehaviorConfig {
2965 #[serde(default)]
2967 pub dunning: DunningConfig,
2968 #[serde(default)]
2970 pub partial_payments: PartialPaymentConfig,
2971 #[serde(default)]
2973 pub short_payments: ShortPaymentConfig,
2974 #[serde(default)]
2976 pub on_account_payments: OnAccountPaymentConfig,
2977 #[serde(default)]
2979 pub payment_corrections: PaymentCorrectionConfig,
2980}
2981
2982#[derive(Debug, Clone, Serialize, Deserialize)]
2984pub struct DunningConfig {
2985 #[serde(default)]
2987 pub enabled: bool,
2988 #[serde(default = "default_dunning_level_1_days")]
2990 pub level_1_days_overdue: u32,
2991 #[serde(default = "default_dunning_level_2_days")]
2993 pub level_2_days_overdue: u32,
2994 #[serde(default = "default_dunning_level_3_days")]
2996 pub level_3_days_overdue: u32,
2997 #[serde(default = "default_collection_days")]
2999 pub collection_days_overdue: u32,
3000 #[serde(default)]
3002 pub payment_after_dunning_rates: DunningPaymentRates,
3003 #[serde(default = "default_dunning_block_rate")]
3005 pub dunning_block_rate: f64,
3006 #[serde(default = "default_dunning_interest_rate")]
3008 pub interest_rate_per_year: f64,
3009 #[serde(default = "default_dunning_charge")]
3011 pub dunning_charge: f64,
3012}
3013
3014fn default_dunning_level_1_days() -> u32 {
3015 14
3016}
3017
3018fn default_dunning_level_2_days() -> u32 {
3019 28
3020}
3021
3022fn default_dunning_level_3_days() -> u32 {
3023 42
3024}
3025
3026fn default_collection_days() -> u32 {
3027 60
3028}
3029
3030fn default_dunning_block_rate() -> f64 {
3031 0.05
3032}
3033
3034fn default_dunning_interest_rate() -> f64 {
3035 0.09
3036}
3037
3038fn default_dunning_charge() -> f64 {
3039 25.0
3040}
3041
3042impl Default for DunningConfig {
3043 fn default() -> Self {
3044 Self {
3045 enabled: false,
3046 level_1_days_overdue: default_dunning_level_1_days(),
3047 level_2_days_overdue: default_dunning_level_2_days(),
3048 level_3_days_overdue: default_dunning_level_3_days(),
3049 collection_days_overdue: default_collection_days(),
3050 payment_after_dunning_rates: DunningPaymentRates::default(),
3051 dunning_block_rate: default_dunning_block_rate(),
3052 interest_rate_per_year: default_dunning_interest_rate(),
3053 dunning_charge: default_dunning_charge(),
3054 }
3055 }
3056}
3057
3058#[derive(Debug, Clone, Serialize, Deserialize)]
3060pub struct DunningPaymentRates {
3061 #[serde(default = "default_after_level_1")]
3063 pub after_level_1: f64,
3064 #[serde(default = "default_after_level_2")]
3066 pub after_level_2: f64,
3067 #[serde(default = "default_after_level_3")]
3069 pub after_level_3: f64,
3070 #[serde(default = "default_during_collection")]
3072 pub during_collection: f64,
3073 #[serde(default = "default_never_pay")]
3075 pub never_pay: f64,
3076}
3077
3078fn default_after_level_1() -> f64 {
3079 0.40
3080}
3081
3082fn default_after_level_2() -> f64 {
3083 0.30
3084}
3085
3086fn default_after_level_3() -> f64 {
3087 0.15
3088}
3089
3090fn default_during_collection() -> f64 {
3091 0.05
3092}
3093
3094fn default_never_pay() -> f64 {
3095 0.10
3096}
3097
3098impl Default for DunningPaymentRates {
3099 fn default() -> Self {
3100 Self {
3101 after_level_1: default_after_level_1(),
3102 after_level_2: default_after_level_2(),
3103 after_level_3: default_after_level_3(),
3104 during_collection: default_during_collection(),
3105 never_pay: default_never_pay(),
3106 }
3107 }
3108}
3109
3110#[derive(Debug, Clone, Serialize, Deserialize)]
3112pub struct PartialPaymentConfig {
3113 #[serde(default = "default_partial_payment_rate")]
3115 pub rate: f64,
3116 #[serde(default)]
3118 pub percentage_distribution: PartialPaymentPercentageDistribution,
3119 #[serde(default = "default_avg_days_until_remainder")]
3121 pub avg_days_until_remainder: u32,
3122}
3123
3124fn default_partial_payment_rate() -> f64 {
3125 0.08
3126}
3127
3128fn default_avg_days_until_remainder() -> u32 {
3129 30
3130}
3131
3132impl Default for PartialPaymentConfig {
3133 fn default() -> Self {
3134 Self {
3135 rate: default_partial_payment_rate(),
3136 percentage_distribution: PartialPaymentPercentageDistribution::default(),
3137 avg_days_until_remainder: default_avg_days_until_remainder(),
3138 }
3139 }
3140}
3141
3142#[derive(Debug, Clone, Serialize, Deserialize)]
3144pub struct PartialPaymentPercentageDistribution {
3145 #[serde(default = "default_partial_25")]
3147 pub pay_25_percent: f64,
3148 #[serde(default = "default_partial_50")]
3150 pub pay_50_percent: f64,
3151 #[serde(default = "default_partial_75")]
3153 pub pay_75_percent: f64,
3154 #[serde(default = "default_partial_random")]
3156 pub pay_random_percent: f64,
3157}
3158
3159fn default_partial_25() -> f64 {
3160 0.15
3161}
3162
3163fn default_partial_50() -> f64 {
3164 0.50
3165}
3166
3167fn default_partial_75() -> f64 {
3168 0.25
3169}
3170
3171fn default_partial_random() -> f64 {
3172 0.10
3173}
3174
3175impl Default for PartialPaymentPercentageDistribution {
3176 fn default() -> Self {
3177 Self {
3178 pay_25_percent: default_partial_25(),
3179 pay_50_percent: default_partial_50(),
3180 pay_75_percent: default_partial_75(),
3181 pay_random_percent: default_partial_random(),
3182 }
3183 }
3184}
3185
3186#[derive(Debug, Clone, Serialize, Deserialize)]
3188pub struct ShortPaymentConfig {
3189 #[serde(default = "default_short_payment_rate")]
3191 pub rate: f64,
3192 #[serde(default)]
3194 pub reason_distribution: ShortPaymentReasonDistribution,
3195 #[serde(default = "default_max_short_percent")]
3197 pub max_short_percent: f64,
3198}
3199
3200fn default_short_payment_rate() -> f64 {
3201 0.03
3202}
3203
3204fn default_max_short_percent() -> f64 {
3205 0.10
3206}
3207
3208impl Default for ShortPaymentConfig {
3209 fn default() -> Self {
3210 Self {
3211 rate: default_short_payment_rate(),
3212 reason_distribution: ShortPaymentReasonDistribution::default(),
3213 max_short_percent: default_max_short_percent(),
3214 }
3215 }
3216}
3217
3218#[derive(Debug, Clone, Serialize, Deserialize)]
3220pub struct ShortPaymentReasonDistribution {
3221 #[serde(default = "default_pricing_dispute")]
3223 pub pricing_dispute: f64,
3224 #[serde(default = "default_quality_issue")]
3226 pub quality_issue: f64,
3227 #[serde(default = "default_quantity_discrepancy")]
3229 pub quantity_discrepancy: f64,
3230 #[serde(default = "default_unauthorized_deduction")]
3232 pub unauthorized_deduction: f64,
3233 #[serde(default = "default_incorrect_discount")]
3235 pub incorrect_discount: f64,
3236}
3237
3238fn default_pricing_dispute() -> f64 {
3239 0.30
3240}
3241
3242fn default_quality_issue() -> f64 {
3243 0.20
3244}
3245
3246fn default_quantity_discrepancy() -> f64 {
3247 0.20
3248}
3249
3250fn default_unauthorized_deduction() -> f64 {
3251 0.15
3252}
3253
3254fn default_incorrect_discount() -> f64 {
3255 0.15
3256}
3257
3258impl Default for ShortPaymentReasonDistribution {
3259 fn default() -> Self {
3260 Self {
3261 pricing_dispute: default_pricing_dispute(),
3262 quality_issue: default_quality_issue(),
3263 quantity_discrepancy: default_quantity_discrepancy(),
3264 unauthorized_deduction: default_unauthorized_deduction(),
3265 incorrect_discount: default_incorrect_discount(),
3266 }
3267 }
3268}
3269
3270#[derive(Debug, Clone, Serialize, Deserialize)]
3272pub struct OnAccountPaymentConfig {
3273 #[serde(default = "default_on_account_rate")]
3275 pub rate: f64,
3276 #[serde(default = "default_avg_days_until_applied")]
3278 pub avg_days_until_applied: u32,
3279}
3280
3281fn default_on_account_rate() -> f64 {
3282 0.02
3283}
3284
3285fn default_avg_days_until_applied() -> u32 {
3286 14
3287}
3288
3289impl Default for OnAccountPaymentConfig {
3290 fn default() -> Self {
3291 Self {
3292 rate: default_on_account_rate(),
3293 avg_days_until_applied: default_avg_days_until_applied(),
3294 }
3295 }
3296}
3297
3298#[derive(Debug, Clone, Serialize, Deserialize)]
3300pub struct PaymentCorrectionConfig {
3301 #[serde(default = "default_payment_correction_rate")]
3303 pub rate: f64,
3304 #[serde(default)]
3306 pub type_distribution: PaymentCorrectionTypeDistribution,
3307}
3308
3309fn default_payment_correction_rate() -> f64 {
3310 0.02
3311}
3312
3313impl Default for PaymentCorrectionConfig {
3314 fn default() -> Self {
3315 Self {
3316 rate: default_payment_correction_rate(),
3317 type_distribution: PaymentCorrectionTypeDistribution::default(),
3318 }
3319 }
3320}
3321
3322#[derive(Debug, Clone, Serialize, Deserialize)]
3324pub struct PaymentCorrectionTypeDistribution {
3325 #[serde(default = "default_nsf_rate")]
3327 pub nsf: f64,
3328 #[serde(default = "default_chargeback_rate")]
3330 pub chargeback: f64,
3331 #[serde(default = "default_wrong_amount_rate")]
3333 pub wrong_amount: f64,
3334 #[serde(default = "default_wrong_customer_rate")]
3336 pub wrong_customer: f64,
3337 #[serde(default = "default_duplicate_payment_rate")]
3339 pub duplicate_payment: f64,
3340}
3341
3342fn default_nsf_rate() -> f64 {
3343 0.30
3344}
3345
3346fn default_chargeback_rate() -> f64 {
3347 0.20
3348}
3349
3350fn default_wrong_amount_rate() -> f64 {
3351 0.20
3352}
3353
3354fn default_wrong_customer_rate() -> f64 {
3355 0.15
3356}
3357
3358fn default_duplicate_payment_rate() -> f64 {
3359 0.15
3360}
3361
3362impl Default for PaymentCorrectionTypeDistribution {
3363 fn default() -> Self {
3364 Self {
3365 nsf: default_nsf_rate(),
3366 chargeback: default_chargeback_rate(),
3367 wrong_amount: default_wrong_amount_rate(),
3368 wrong_customer: default_wrong_customer_rate(),
3369 duplicate_payment: default_duplicate_payment_rate(),
3370 }
3371 }
3372}
3373
3374#[derive(Debug, Clone, Serialize, Deserialize)]
3376pub struct DocumentLineCountDistribution {
3377 #[serde(default = "default_min_lines")]
3379 pub min_lines: u32,
3380 #[serde(default = "default_max_lines")]
3382 pub max_lines: u32,
3383 #[serde(default = "default_mode_lines")]
3385 pub mode_lines: u32,
3386}
3387
3388fn default_min_lines() -> u32 {
3389 1
3390}
3391
3392fn default_max_lines() -> u32 {
3393 20
3394}
3395
3396fn default_mode_lines() -> u32 {
3397 3
3398}
3399
3400impl Default for DocumentLineCountDistribution {
3401 fn default() -> Self {
3402 Self {
3403 min_lines: default_min_lines(),
3404 max_lines: default_max_lines(),
3405 mode_lines: default_mode_lines(),
3406 }
3407 }
3408}
3409
3410#[derive(Debug, Clone, Serialize, Deserialize)]
3412pub struct CashDiscountConfig {
3413 #[serde(default = "default_discount_eligible_rate")]
3415 pub eligible_rate: f64,
3416 #[serde(default = "default_discount_taken_rate")]
3418 pub taken_rate: f64,
3419 #[serde(default = "default_discount_percent")]
3421 pub discount_percent: f64,
3422 #[serde(default = "default_discount_days")]
3424 pub discount_days: u32,
3425}
3426
3427fn default_discount_eligible_rate() -> f64 {
3428 0.30
3429}
3430
3431fn default_discount_taken_rate() -> f64 {
3432 0.60
3433}
3434
3435fn default_discount_percent() -> f64 {
3436 0.02
3437}
3438
3439fn default_discount_days() -> u32 {
3440 10
3441}
3442
3443impl Default for CashDiscountConfig {
3444 fn default() -> Self {
3445 Self {
3446 eligible_rate: default_discount_eligible_rate(),
3447 taken_rate: default_discount_taken_rate(),
3448 discount_percent: default_discount_percent(),
3449 discount_days: default_discount_days(),
3450 }
3451 }
3452}
3453
3454#[derive(Debug, Clone, Serialize, Deserialize)]
3460pub struct IntercompanyConfig {
3461 #[serde(default)]
3463 pub enabled: bool,
3464 #[serde(default = "default_ic_transaction_rate")]
3466 pub ic_transaction_rate: f64,
3467 #[serde(default)]
3469 pub transfer_pricing_method: TransferPricingMethod,
3470 #[serde(default = "default_markup_percent")]
3472 pub markup_percent: f64,
3473 #[serde(default = "default_true")]
3475 pub generate_matched_pairs: bool,
3476 #[serde(default)]
3478 pub transaction_type_distribution: ICTransactionTypeDistribution,
3479 #[serde(default)]
3481 pub generate_eliminations: bool,
3482}
3483
3484fn default_ic_transaction_rate() -> f64 {
3485 0.15
3486}
3487
3488fn default_markup_percent() -> f64 {
3489 0.05
3490}
3491
3492impl Default for IntercompanyConfig {
3493 fn default() -> Self {
3494 Self {
3495 enabled: false,
3496 ic_transaction_rate: default_ic_transaction_rate(),
3497 transfer_pricing_method: TransferPricingMethod::default(),
3498 markup_percent: default_markup_percent(),
3499 generate_matched_pairs: true,
3500 transaction_type_distribution: ICTransactionTypeDistribution::default(),
3501 generate_eliminations: false,
3502 }
3503 }
3504}
3505
3506#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
3508#[serde(rename_all = "snake_case")]
3509pub enum TransferPricingMethod {
3510 #[default]
3512 CostPlus,
3513 ComparableUncontrolled,
3515 ResalePrice,
3517 TransactionalNetMargin,
3519 ProfitSplit,
3521}
3522
3523#[derive(Debug, Clone, Serialize, Deserialize)]
3525pub struct ICTransactionTypeDistribution {
3526 pub goods_sale: f64,
3528 pub service_provided: f64,
3530 pub loan: f64,
3532 pub dividend: f64,
3534 pub management_fee: f64,
3536 pub royalty: f64,
3538 pub cost_sharing: f64,
3540}
3541
3542impl Default for ICTransactionTypeDistribution {
3543 fn default() -> Self {
3544 Self {
3545 goods_sale: 0.35,
3546 service_provided: 0.20,
3547 loan: 0.10,
3548 dividend: 0.05,
3549 management_fee: 0.15,
3550 royalty: 0.10,
3551 cost_sharing: 0.05,
3552 }
3553 }
3554}
3555
3556#[derive(Debug, Clone, Serialize, Deserialize)]
3562pub struct BalanceConfig {
3563 #[serde(default)]
3565 pub generate_opening_balances: bool,
3566 #[serde(default = "default_true")]
3568 pub generate_trial_balances: bool,
3569 #[serde(default = "default_gross_margin")]
3571 pub target_gross_margin: f64,
3572 #[serde(default = "default_dso")]
3574 pub target_dso_days: u32,
3575 #[serde(default = "default_dpo")]
3577 pub target_dpo_days: u32,
3578 #[serde(default = "default_current_ratio")]
3580 pub target_current_ratio: f64,
3581 #[serde(default = "default_debt_equity")]
3583 pub target_debt_to_equity: f64,
3584 #[serde(default = "default_true")]
3586 pub validate_balance_equation: bool,
3587 #[serde(default = "default_true")]
3589 pub reconcile_subledgers: bool,
3590}
3591
3592fn default_gross_margin() -> f64 {
3593 0.35
3594}
3595
3596fn default_dso() -> u32 {
3597 45
3598}
3599
3600fn default_dpo() -> u32 {
3601 30
3602}
3603
3604fn default_current_ratio() -> f64 {
3605 1.5
3606}
3607
3608fn default_debt_equity() -> f64 {
3609 0.5
3610}
3611
3612impl Default for BalanceConfig {
3613 fn default() -> Self {
3614 Self {
3615 generate_opening_balances: false,
3616 generate_trial_balances: true,
3617 target_gross_margin: default_gross_margin(),
3618 target_dso_days: default_dso(),
3619 target_dpo_days: default_dpo(),
3620 target_current_ratio: default_current_ratio(),
3621 target_debt_to_equity: default_debt_equity(),
3622 validate_balance_equation: true,
3623 reconcile_subledgers: true,
3624 }
3625 }
3626}
3627
3628#[derive(Debug, Clone, Serialize, Deserialize)]
3637pub struct OcpmConfig {
3638 #[serde(default)]
3640 pub enabled: bool,
3641
3642 #[serde(default = "default_true")]
3644 pub generate_lifecycle_events: bool,
3645
3646 #[serde(default = "default_true")]
3648 pub include_object_relationships: bool,
3649
3650 #[serde(default = "default_true")]
3652 pub compute_variants: bool,
3653
3654 #[serde(default)]
3656 pub max_variants: usize,
3657
3658 #[serde(default)]
3660 pub p2p_process: OcpmProcessConfig,
3661
3662 #[serde(default)]
3664 pub o2c_process: OcpmProcessConfig,
3665
3666 #[serde(default)]
3668 pub output: OcpmOutputConfig,
3669}
3670
3671impl Default for OcpmConfig {
3672 fn default() -> Self {
3673 Self {
3674 enabled: false,
3675 generate_lifecycle_events: true,
3676 include_object_relationships: true,
3677 compute_variants: true,
3678 max_variants: 0,
3679 p2p_process: OcpmProcessConfig::default(),
3680 o2c_process: OcpmProcessConfig::default(),
3681 output: OcpmOutputConfig::default(),
3682 }
3683 }
3684}
3685
3686#[derive(Debug, Clone, Serialize, Deserialize)]
3688pub struct OcpmProcessConfig {
3689 #[serde(default = "default_rework_probability")]
3691 pub rework_probability: f64,
3692
3693 #[serde(default = "default_skip_probability")]
3695 pub skip_step_probability: f64,
3696
3697 #[serde(default = "default_out_of_order_probability")]
3699 pub out_of_order_probability: f64,
3700}
3701
3702fn default_rework_probability() -> f64 {
3703 0.05
3704}
3705
3706fn default_skip_probability() -> f64 {
3707 0.02
3708}
3709
3710fn default_out_of_order_probability() -> f64 {
3711 0.03
3712}
3713
3714impl Default for OcpmProcessConfig {
3715 fn default() -> Self {
3716 Self {
3717 rework_probability: default_rework_probability(),
3718 skip_step_probability: default_skip_probability(),
3719 out_of_order_probability: default_out_of_order_probability(),
3720 }
3721 }
3722}
3723
3724#[derive(Debug, Clone, Serialize, Deserialize)]
3726pub struct OcpmOutputConfig {
3727 #[serde(default = "default_true")]
3729 pub ocel_json: bool,
3730
3731 #[serde(default)]
3733 pub ocel_xml: bool,
3734
3735 #[serde(default)]
3737 pub xes: bool,
3738
3739 #[serde(default = "default_true")]
3741 pub xes_include_lifecycle: bool,
3742
3743 #[serde(default = "default_true")]
3745 pub xes_include_resources: bool,
3746
3747 #[serde(default = "default_true")]
3749 pub flattened_csv: bool,
3750
3751 #[serde(default = "default_true")]
3753 pub event_object_csv: bool,
3754
3755 #[serde(default = "default_true")]
3757 pub object_relationship_csv: bool,
3758
3759 #[serde(default = "default_true")]
3761 pub variants_csv: bool,
3762
3763 #[serde(default)]
3765 pub export_reference_models: bool,
3766}
3767
3768impl Default for OcpmOutputConfig {
3769 fn default() -> Self {
3770 Self {
3771 ocel_json: true,
3772 ocel_xml: false,
3773 xes: false,
3774 xes_include_lifecycle: true,
3775 xes_include_resources: true,
3776 flattened_csv: true,
3777 event_object_csv: true,
3778 object_relationship_csv: true,
3779 variants_csv: true,
3780 export_reference_models: false,
3781 }
3782 }
3783}
3784
3785#[derive(Debug, Clone, Serialize, Deserialize)]
3787pub struct AuditGenerationConfig {
3788 #[serde(default)]
3790 pub enabled: bool,
3791
3792 #[serde(default = "default_true")]
3794 pub generate_workpapers: bool,
3795
3796 #[serde(default)]
3798 pub engagement_types: AuditEngagementTypesConfig,
3799
3800 #[serde(default)]
3802 pub workpapers: WorkpaperConfig,
3803
3804 #[serde(default)]
3806 pub team: AuditTeamConfig,
3807
3808 #[serde(default)]
3810 pub review: ReviewWorkflowConfig,
3811}
3812
3813impl Default for AuditGenerationConfig {
3814 fn default() -> Self {
3815 Self {
3816 enabled: false,
3817 generate_workpapers: true,
3818 engagement_types: AuditEngagementTypesConfig::default(),
3819 workpapers: WorkpaperConfig::default(),
3820 team: AuditTeamConfig::default(),
3821 review: ReviewWorkflowConfig::default(),
3822 }
3823 }
3824}
3825
3826#[derive(Debug, Clone, Serialize, Deserialize)]
3828pub struct AuditEngagementTypesConfig {
3829 #[serde(default = "default_financial_audit_prob")]
3831 pub financial_statement: f64,
3832 #[serde(default = "default_sox_audit_prob")]
3834 pub sox_icfr: f64,
3835 #[serde(default = "default_integrated_audit_prob")]
3837 pub integrated: f64,
3838 #[serde(default = "default_review_prob")]
3840 pub review: f64,
3841 #[serde(default = "default_aup_prob")]
3843 pub agreed_upon_procedures: f64,
3844}
3845
3846fn default_financial_audit_prob() -> f64 {
3847 0.40
3848}
3849fn default_sox_audit_prob() -> f64 {
3850 0.20
3851}
3852fn default_integrated_audit_prob() -> f64 {
3853 0.25
3854}
3855fn default_review_prob() -> f64 {
3856 0.10
3857}
3858fn default_aup_prob() -> f64 {
3859 0.05
3860}
3861
3862impl Default for AuditEngagementTypesConfig {
3863 fn default() -> Self {
3864 Self {
3865 financial_statement: default_financial_audit_prob(),
3866 sox_icfr: default_sox_audit_prob(),
3867 integrated: default_integrated_audit_prob(),
3868 review: default_review_prob(),
3869 agreed_upon_procedures: default_aup_prob(),
3870 }
3871 }
3872}
3873
3874#[derive(Debug, Clone, Serialize, Deserialize)]
3876pub struct WorkpaperConfig {
3877 #[serde(default = "default_workpapers_per_phase")]
3879 pub average_per_phase: usize,
3880
3881 #[serde(default = "default_true")]
3883 pub include_isa_references: bool,
3884
3885 #[serde(default = "default_true")]
3887 pub include_sample_details: bool,
3888
3889 #[serde(default = "default_true")]
3891 pub include_cross_references: bool,
3892
3893 #[serde(default)]
3895 pub sampling: SamplingConfig,
3896}
3897
3898fn default_workpapers_per_phase() -> usize {
3899 5
3900}
3901
3902impl Default for WorkpaperConfig {
3903 fn default() -> Self {
3904 Self {
3905 average_per_phase: default_workpapers_per_phase(),
3906 include_isa_references: true,
3907 include_sample_details: true,
3908 include_cross_references: true,
3909 sampling: SamplingConfig::default(),
3910 }
3911 }
3912}
3913
3914#[derive(Debug, Clone, Serialize, Deserialize)]
3916pub struct SamplingConfig {
3917 #[serde(default = "default_statistical_rate")]
3919 pub statistical_rate: f64,
3920 #[serde(default = "default_judgmental_rate")]
3922 pub judgmental_rate: f64,
3923 #[serde(default = "default_haphazard_rate")]
3925 pub haphazard_rate: f64,
3926 #[serde(default = "default_complete_examination_rate")]
3928 pub complete_examination_rate: f64,
3929}
3930
3931fn default_statistical_rate() -> f64 {
3932 0.40
3933}
3934fn default_judgmental_rate() -> f64 {
3935 0.30
3936}
3937fn default_haphazard_rate() -> f64 {
3938 0.20
3939}
3940fn default_complete_examination_rate() -> f64 {
3941 0.10
3942}
3943
3944impl Default for SamplingConfig {
3945 fn default() -> Self {
3946 Self {
3947 statistical_rate: default_statistical_rate(),
3948 judgmental_rate: default_judgmental_rate(),
3949 haphazard_rate: default_haphazard_rate(),
3950 complete_examination_rate: default_complete_examination_rate(),
3951 }
3952 }
3953}
3954
3955#[derive(Debug, Clone, Serialize, Deserialize)]
3957pub struct AuditTeamConfig {
3958 #[serde(default = "default_min_team_size")]
3960 pub min_team_size: usize,
3961 #[serde(default = "default_max_team_size")]
3963 pub max_team_size: usize,
3964 #[serde(default = "default_specialist_probability")]
3966 pub specialist_probability: f64,
3967}
3968
3969fn default_min_team_size() -> usize {
3970 3
3971}
3972fn default_max_team_size() -> usize {
3973 8
3974}
3975fn default_specialist_probability() -> f64 {
3976 0.30
3977}
3978
3979impl Default for AuditTeamConfig {
3980 fn default() -> Self {
3981 Self {
3982 min_team_size: default_min_team_size(),
3983 max_team_size: default_max_team_size(),
3984 specialist_probability: default_specialist_probability(),
3985 }
3986 }
3987}
3988
3989#[derive(Debug, Clone, Serialize, Deserialize)]
3991pub struct ReviewWorkflowConfig {
3992 #[serde(default = "default_review_delay_days")]
3994 pub average_review_delay_days: u32,
3995 #[serde(default = "default_rework_probability_review")]
3997 pub rework_probability: f64,
3998 #[serde(default = "default_true")]
4000 pub require_partner_signoff: bool,
4001}
4002
4003fn default_review_delay_days() -> u32 {
4004 2
4005}
4006fn default_rework_probability_review() -> f64 {
4007 0.15
4008}
4009
4010impl Default for ReviewWorkflowConfig {
4011 fn default() -> Self {
4012 Self {
4013 average_review_delay_days: default_review_delay_days(),
4014 rework_probability: default_rework_probability_review(),
4015 require_partner_signoff: true,
4016 }
4017 }
4018}
4019
4020#[derive(Debug, Clone, Serialize, Deserialize)]
4026pub struct DataQualitySchemaConfig {
4027 #[serde(default)]
4029 pub enabled: bool,
4030 #[serde(default)]
4032 pub preset: DataQualityPreset,
4033 #[serde(default)]
4035 pub missing_values: MissingValuesSchemaConfig,
4036 #[serde(default)]
4038 pub typos: TypoSchemaConfig,
4039 #[serde(default)]
4041 pub format_variations: FormatVariationSchemaConfig,
4042 #[serde(default)]
4044 pub duplicates: DuplicateSchemaConfig,
4045 #[serde(default)]
4047 pub encoding_issues: EncodingIssueSchemaConfig,
4048 #[serde(default)]
4050 pub generate_labels: bool,
4051 #[serde(default)]
4053 pub sink_profiles: SinkQualityProfiles,
4054}
4055
4056impl Default for DataQualitySchemaConfig {
4057 fn default() -> Self {
4058 Self {
4059 enabled: false,
4060 preset: DataQualityPreset::None,
4061 missing_values: MissingValuesSchemaConfig::default(),
4062 typos: TypoSchemaConfig::default(),
4063 format_variations: FormatVariationSchemaConfig::default(),
4064 duplicates: DuplicateSchemaConfig::default(),
4065 encoding_issues: EncodingIssueSchemaConfig::default(),
4066 generate_labels: true,
4067 sink_profiles: SinkQualityProfiles::default(),
4068 }
4069 }
4070}
4071
4072impl DataQualitySchemaConfig {
4073 pub fn with_preset(preset: DataQualityPreset) -> Self {
4075 let mut config = Self {
4076 preset,
4077 ..Default::default()
4078 };
4079 config.apply_preset();
4080 config
4081 }
4082
4083 pub fn apply_preset(&mut self) {
4086 if !self.preset.overrides_settings() {
4087 return;
4088 }
4089
4090 self.enabled = true;
4091
4092 self.missing_values.enabled = self.preset.missing_rate() > 0.0;
4094 self.missing_values.rate = self.preset.missing_rate();
4095
4096 self.typos.enabled = self.preset.typo_rate() > 0.0;
4098 self.typos.char_error_rate = self.preset.typo_rate();
4099
4100 self.duplicates.enabled = self.preset.duplicate_rate() > 0.0;
4102 self.duplicates.exact_duplicate_ratio = self.preset.duplicate_rate() * 0.4;
4103 self.duplicates.near_duplicate_ratio = self.preset.duplicate_rate() * 0.4;
4104 self.duplicates.fuzzy_duplicate_ratio = self.preset.duplicate_rate() * 0.2;
4105
4106 self.format_variations.enabled = self.preset.format_variations_enabled();
4108
4109 self.encoding_issues.enabled = self.preset.encoding_issues_enabled();
4111 self.encoding_issues.rate = self.preset.encoding_issue_rate();
4112
4113 if self.preset.ocr_errors_enabled() {
4115 self.typos.type_weights.ocr_errors = 0.3;
4116 }
4117 }
4118
4119 pub fn effective_missing_rate(&self) -> f64 {
4121 if self.preset.overrides_settings() {
4122 self.preset.missing_rate()
4123 } else {
4124 self.missing_values.rate
4125 }
4126 }
4127
4128 pub fn effective_typo_rate(&self) -> f64 {
4130 if self.preset.overrides_settings() {
4131 self.preset.typo_rate()
4132 } else {
4133 self.typos.char_error_rate
4134 }
4135 }
4136
4137 pub fn effective_duplicate_rate(&self) -> f64 {
4139 if self.preset.overrides_settings() {
4140 self.preset.duplicate_rate()
4141 } else {
4142 self.duplicates.exact_duplicate_ratio
4143 + self.duplicates.near_duplicate_ratio
4144 + self.duplicates.fuzzy_duplicate_ratio
4145 }
4146 }
4147
4148 pub fn clean() -> Self {
4150 Self::with_preset(DataQualityPreset::Clean)
4151 }
4152
4153 pub fn noisy() -> Self {
4155 Self::with_preset(DataQualityPreset::Noisy)
4156 }
4157
4158 pub fn legacy() -> Self {
4160 Self::with_preset(DataQualityPreset::Legacy)
4161 }
4162}
4163
4164#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
4166#[serde(rename_all = "snake_case")]
4167pub enum DataQualityPreset {
4168 #[default]
4170 None,
4171 Minimal,
4173 Normal,
4175 High,
4177 Custom,
4179
4180 Clean,
4186 Noisy,
4189 Legacy,
4192}
4193
4194impl DataQualityPreset {
4195 pub fn missing_rate(&self) -> f64 {
4197 match self {
4198 DataQualityPreset::None => 0.0,
4199 DataQualityPreset::Minimal => 0.005,
4200 DataQualityPreset::Normal => 0.02,
4201 DataQualityPreset::High => 0.08,
4202 DataQualityPreset::Custom => 0.01, DataQualityPreset::Clean => 0.001,
4204 DataQualityPreset::Noisy => 0.05,
4205 DataQualityPreset::Legacy => 0.10,
4206 }
4207 }
4208
4209 pub fn typo_rate(&self) -> f64 {
4211 match self {
4212 DataQualityPreset::None => 0.0,
4213 DataQualityPreset::Minimal => 0.0005,
4214 DataQualityPreset::Normal => 0.002,
4215 DataQualityPreset::High => 0.01,
4216 DataQualityPreset::Custom => 0.001, DataQualityPreset::Clean => 0.0005,
4218 DataQualityPreset::Noisy => 0.02,
4219 DataQualityPreset::Legacy => 0.05,
4220 }
4221 }
4222
4223 pub fn duplicate_rate(&self) -> f64 {
4225 match self {
4226 DataQualityPreset::None => 0.0,
4227 DataQualityPreset::Minimal => 0.001,
4228 DataQualityPreset::Normal => 0.005,
4229 DataQualityPreset::High => 0.02,
4230 DataQualityPreset::Custom => 0.0, DataQualityPreset::Clean => 0.0,
4232 DataQualityPreset::Noisy => 0.01,
4233 DataQualityPreset::Legacy => 0.03,
4234 }
4235 }
4236
4237 pub fn format_variations_enabled(&self) -> bool {
4239 match self {
4240 DataQualityPreset::None | DataQualityPreset::Clean => false,
4241 DataQualityPreset::Minimal => true,
4242 DataQualityPreset::Normal => true,
4243 DataQualityPreset::High => true,
4244 DataQualityPreset::Custom => true,
4245 DataQualityPreset::Noisy => true,
4246 DataQualityPreset::Legacy => true,
4247 }
4248 }
4249
4250 pub fn ocr_errors_enabled(&self) -> bool {
4252 matches!(self, DataQualityPreset::Legacy | DataQualityPreset::High)
4253 }
4254
4255 pub fn encoding_issues_enabled(&self) -> bool {
4257 matches!(
4258 self,
4259 DataQualityPreset::Legacy | DataQualityPreset::High | DataQualityPreset::Noisy
4260 )
4261 }
4262
4263 pub fn encoding_issue_rate(&self) -> f64 {
4265 match self {
4266 DataQualityPreset::None | DataQualityPreset::Clean | DataQualityPreset::Minimal => 0.0,
4267 DataQualityPreset::Normal => 0.002,
4268 DataQualityPreset::High => 0.01,
4269 DataQualityPreset::Custom => 0.0,
4270 DataQualityPreset::Noisy => 0.005,
4271 DataQualityPreset::Legacy => 0.02,
4272 }
4273 }
4274
4275 pub fn overrides_settings(&self) -> bool {
4277 !matches!(self, DataQualityPreset::Custom | DataQualityPreset::None)
4278 }
4279
4280 pub fn description(&self) -> &'static str {
4282 match self {
4283 DataQualityPreset::None => "No data quality issues (pristine data)",
4284 DataQualityPreset::Minimal => "Very rare data quality issues",
4285 DataQualityPreset::Normal => "Realistic enterprise data quality",
4286 DataQualityPreset::High => "Messy data for stress testing",
4287 DataQualityPreset::Custom => "Custom settings from configuration",
4288 DataQualityPreset::Clean => "ML-ready clean data with minimal issues",
4289 DataQualityPreset::Noisy => "Typical production data with moderate issues",
4290 DataQualityPreset::Legacy => "Legacy/migrated data with heavy issues and OCR errors",
4291 }
4292 }
4293}
4294
4295#[derive(Debug, Clone, Serialize, Deserialize)]
4297pub struct MissingValuesSchemaConfig {
4298 #[serde(default)]
4300 pub enabled: bool,
4301 #[serde(default = "default_missing_rate")]
4303 pub rate: f64,
4304 #[serde(default)]
4306 pub strategy: MissingValueStrategy,
4307 #[serde(default)]
4309 pub field_rates: std::collections::HashMap<String, f64>,
4310 #[serde(default)]
4312 pub protected_fields: Vec<String>,
4313}
4314
4315fn default_missing_rate() -> f64 {
4316 0.01
4317}
4318
4319impl Default for MissingValuesSchemaConfig {
4320 fn default() -> Self {
4321 Self {
4322 enabled: false,
4323 rate: default_missing_rate(),
4324 strategy: MissingValueStrategy::Mcar,
4325 field_rates: std::collections::HashMap::new(),
4326 protected_fields: vec![
4327 "document_id".to_string(),
4328 "company_code".to_string(),
4329 "posting_date".to_string(),
4330 ],
4331 }
4332 }
4333}
4334
4335#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
4337#[serde(rename_all = "snake_case")]
4338pub enum MissingValueStrategy {
4339 #[default]
4341 Mcar,
4342 Mar,
4344 Mnar,
4346 Systematic,
4348}
4349
4350#[derive(Debug, Clone, Serialize, Deserialize)]
4352pub struct TypoSchemaConfig {
4353 #[serde(default)]
4355 pub enabled: bool,
4356 #[serde(default = "default_typo_rate")]
4358 pub char_error_rate: f64,
4359 #[serde(default)]
4361 pub type_weights: TypoTypeWeights,
4362 #[serde(default)]
4364 pub protected_fields: Vec<String>,
4365}
4366
4367fn default_typo_rate() -> f64 {
4368 0.001
4369}
4370
4371impl Default for TypoSchemaConfig {
4372 fn default() -> Self {
4373 Self {
4374 enabled: false,
4375 char_error_rate: default_typo_rate(),
4376 type_weights: TypoTypeWeights::default(),
4377 protected_fields: vec![
4378 "document_id".to_string(),
4379 "gl_account".to_string(),
4380 "company_code".to_string(),
4381 ],
4382 }
4383 }
4384}
4385
4386#[derive(Debug, Clone, Serialize, Deserialize)]
4388pub struct TypoTypeWeights {
4389 #[serde(default = "default_substitution_weight")]
4391 pub substitution: f64,
4392 #[serde(default = "default_transposition_weight")]
4394 pub transposition: f64,
4395 #[serde(default = "default_insertion_weight")]
4397 pub insertion: f64,
4398 #[serde(default = "default_deletion_weight")]
4400 pub deletion: f64,
4401 #[serde(default = "default_ocr_weight")]
4403 pub ocr_errors: f64,
4404 #[serde(default = "default_homophone_weight")]
4406 pub homophones: f64,
4407}
4408
4409fn default_substitution_weight() -> f64 {
4410 0.35
4411}
4412fn default_transposition_weight() -> f64 {
4413 0.25
4414}
4415fn default_insertion_weight() -> f64 {
4416 0.10
4417}
4418fn default_deletion_weight() -> f64 {
4419 0.15
4420}
4421fn default_ocr_weight() -> f64 {
4422 0.10
4423}
4424fn default_homophone_weight() -> f64 {
4425 0.05
4426}
4427
4428impl Default for TypoTypeWeights {
4429 fn default() -> Self {
4430 Self {
4431 substitution: default_substitution_weight(),
4432 transposition: default_transposition_weight(),
4433 insertion: default_insertion_weight(),
4434 deletion: default_deletion_weight(),
4435 ocr_errors: default_ocr_weight(),
4436 homophones: default_homophone_weight(),
4437 }
4438 }
4439}
4440
4441#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4443pub struct FormatVariationSchemaConfig {
4444 #[serde(default)]
4446 pub enabled: bool,
4447 #[serde(default)]
4449 pub dates: DateFormatVariationConfig,
4450 #[serde(default)]
4452 pub amounts: AmountFormatVariationConfig,
4453 #[serde(default)]
4455 pub identifiers: IdentifierFormatVariationConfig,
4456}
4457
4458#[derive(Debug, Clone, Serialize, Deserialize)]
4460pub struct DateFormatVariationConfig {
4461 #[serde(default)]
4463 pub enabled: bool,
4464 #[serde(default = "default_date_variation_rate")]
4466 pub rate: f64,
4467 #[serde(default = "default_true")]
4469 pub iso_format: bool,
4470 #[serde(default)]
4472 pub us_format: bool,
4473 #[serde(default)]
4475 pub eu_format: bool,
4476 #[serde(default)]
4478 pub long_format: bool,
4479}
4480
4481fn default_date_variation_rate() -> f64 {
4482 0.05
4483}
4484
4485impl Default for DateFormatVariationConfig {
4486 fn default() -> Self {
4487 Self {
4488 enabled: false,
4489 rate: default_date_variation_rate(),
4490 iso_format: true,
4491 us_format: false,
4492 eu_format: false,
4493 long_format: false,
4494 }
4495 }
4496}
4497
4498#[derive(Debug, Clone, Serialize, Deserialize)]
4500pub struct AmountFormatVariationConfig {
4501 #[serde(default)]
4503 pub enabled: bool,
4504 #[serde(default = "default_amount_variation_rate")]
4506 pub rate: f64,
4507 #[serde(default)]
4509 pub us_comma_format: bool,
4510 #[serde(default)]
4512 pub eu_format: bool,
4513 #[serde(default)]
4515 pub currency_prefix: bool,
4516 #[serde(default)]
4518 pub accounting_format: bool,
4519}
4520
4521fn default_amount_variation_rate() -> f64 {
4522 0.02
4523}
4524
4525impl Default for AmountFormatVariationConfig {
4526 fn default() -> Self {
4527 Self {
4528 enabled: false,
4529 rate: default_amount_variation_rate(),
4530 us_comma_format: false,
4531 eu_format: false,
4532 currency_prefix: false,
4533 accounting_format: false,
4534 }
4535 }
4536}
4537
4538#[derive(Debug, Clone, Serialize, Deserialize)]
4540pub struct IdentifierFormatVariationConfig {
4541 #[serde(default)]
4543 pub enabled: bool,
4544 #[serde(default = "default_identifier_variation_rate")]
4546 pub rate: f64,
4547 #[serde(default)]
4549 pub case_variations: bool,
4550 #[serde(default)]
4552 pub padding_variations: bool,
4553 #[serde(default)]
4555 pub separator_variations: bool,
4556}
4557
4558fn default_identifier_variation_rate() -> f64 {
4559 0.02
4560}
4561
4562impl Default for IdentifierFormatVariationConfig {
4563 fn default() -> Self {
4564 Self {
4565 enabled: false,
4566 rate: default_identifier_variation_rate(),
4567 case_variations: false,
4568 padding_variations: false,
4569 separator_variations: false,
4570 }
4571 }
4572}
4573
4574#[derive(Debug, Clone, Serialize, Deserialize)]
4576pub struct DuplicateSchemaConfig {
4577 #[serde(default)]
4579 pub enabled: bool,
4580 #[serde(default = "default_duplicate_rate")]
4582 pub rate: f64,
4583 #[serde(default = "default_exact_duplicate_ratio")]
4585 pub exact_duplicate_ratio: f64,
4586 #[serde(default = "default_near_duplicate_ratio")]
4588 pub near_duplicate_ratio: f64,
4589 #[serde(default = "default_fuzzy_duplicate_ratio")]
4591 pub fuzzy_duplicate_ratio: f64,
4592 #[serde(default = "default_max_date_offset")]
4594 pub max_date_offset_days: u32,
4595 #[serde(default = "default_max_amount_variance")]
4597 pub max_amount_variance: f64,
4598}
4599
4600fn default_duplicate_rate() -> f64 {
4601 0.005
4602}
4603fn default_exact_duplicate_ratio() -> f64 {
4604 0.4
4605}
4606fn default_near_duplicate_ratio() -> f64 {
4607 0.35
4608}
4609fn default_fuzzy_duplicate_ratio() -> f64 {
4610 0.25
4611}
4612fn default_max_date_offset() -> u32 {
4613 3
4614}
4615fn default_max_amount_variance() -> f64 {
4616 0.01
4617}
4618
4619impl Default for DuplicateSchemaConfig {
4620 fn default() -> Self {
4621 Self {
4622 enabled: false,
4623 rate: default_duplicate_rate(),
4624 exact_duplicate_ratio: default_exact_duplicate_ratio(),
4625 near_duplicate_ratio: default_near_duplicate_ratio(),
4626 fuzzy_duplicate_ratio: default_fuzzy_duplicate_ratio(),
4627 max_date_offset_days: default_max_date_offset(),
4628 max_amount_variance: default_max_amount_variance(),
4629 }
4630 }
4631}
4632
4633#[derive(Debug, Clone, Serialize, Deserialize)]
4635pub struct EncodingIssueSchemaConfig {
4636 #[serde(default)]
4638 pub enabled: bool,
4639 #[serde(default = "default_encoding_rate")]
4641 pub rate: f64,
4642 #[serde(default)]
4644 pub mojibake: bool,
4645 #[serde(default)]
4647 pub html_entities: bool,
4648 #[serde(default)]
4650 pub bom_issues: bool,
4651}
4652
4653fn default_encoding_rate() -> f64 {
4654 0.001
4655}
4656
4657impl Default for EncodingIssueSchemaConfig {
4658 fn default() -> Self {
4659 Self {
4660 enabled: false,
4661 rate: default_encoding_rate(),
4662 mojibake: false,
4663 html_entities: false,
4664 bom_issues: false,
4665 }
4666 }
4667}
4668
4669#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4671pub struct SinkQualityProfiles {
4672 #[serde(default)]
4674 pub csv: Option<SinkQualityOverride>,
4675 #[serde(default)]
4677 pub json: Option<SinkQualityOverride>,
4678 #[serde(default)]
4680 pub parquet: Option<SinkQualityOverride>,
4681}
4682
4683#[derive(Debug, Clone, Serialize, Deserialize)]
4685pub struct SinkQualityOverride {
4686 pub enabled: Option<bool>,
4688 pub missing_rate: Option<f64>,
4690 pub typo_rate: Option<f64>,
4692 pub format_variation_rate: Option<f64>,
4694 pub duplicate_rate: Option<f64>,
4696}
4697
4698#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4710pub struct AccountingStandardsConfig {
4711 #[serde(default)]
4713 pub enabled: bool,
4714
4715 #[serde(default, skip_serializing_if = "Option::is_none")]
4719 pub framework: Option<AccountingFrameworkConfig>,
4720
4721 #[serde(default)]
4723 pub revenue_recognition: RevenueRecognitionConfig,
4724
4725 #[serde(default)]
4727 pub leases: LeaseAccountingConfig,
4728
4729 #[serde(default)]
4731 pub fair_value: FairValueConfig,
4732
4733 #[serde(default)]
4735 pub impairment: ImpairmentConfig,
4736
4737 #[serde(default)]
4739 pub generate_differences: bool,
4740}
4741
4742#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
4744#[serde(rename_all = "snake_case")]
4745pub enum AccountingFrameworkConfig {
4746 #[default]
4748 UsGaap,
4749 Ifrs,
4751 DualReporting,
4753 FrenchGaap,
4755 GermanGaap,
4757}
4758
4759#[derive(Debug, Clone, Serialize, Deserialize)]
4761pub struct RevenueRecognitionConfig {
4762 #[serde(default)]
4764 pub enabled: bool,
4765
4766 #[serde(default = "default_true")]
4768 pub generate_contracts: bool,
4769
4770 #[serde(default = "default_avg_obligations")]
4772 pub avg_obligations_per_contract: f64,
4773
4774 #[serde(default = "default_variable_consideration_rate")]
4776 pub variable_consideration_rate: f64,
4777
4778 #[serde(default = "default_over_time_rate")]
4780 pub over_time_recognition_rate: f64,
4781
4782 #[serde(default = "default_contract_count")]
4784 pub contract_count: usize,
4785}
4786
4787fn default_avg_obligations() -> f64 {
4788 2.0
4789}
4790
4791fn default_variable_consideration_rate() -> f64 {
4792 0.15
4793}
4794
4795fn default_over_time_rate() -> f64 {
4796 0.30
4797}
4798
4799fn default_contract_count() -> usize {
4800 100
4801}
4802
4803impl Default for RevenueRecognitionConfig {
4804 fn default() -> Self {
4805 Self {
4806 enabled: false,
4807 generate_contracts: true,
4808 avg_obligations_per_contract: default_avg_obligations(),
4809 variable_consideration_rate: default_variable_consideration_rate(),
4810 over_time_recognition_rate: default_over_time_rate(),
4811 contract_count: default_contract_count(),
4812 }
4813 }
4814}
4815
4816#[derive(Debug, Clone, Serialize, Deserialize)]
4818pub struct LeaseAccountingConfig {
4819 #[serde(default)]
4821 pub enabled: bool,
4822
4823 #[serde(default = "default_lease_count")]
4825 pub lease_count: usize,
4826
4827 #[serde(default = "default_finance_lease_pct")]
4829 pub finance_lease_percent: f64,
4830
4831 #[serde(default = "default_avg_lease_term")]
4833 pub avg_lease_term_months: u32,
4834
4835 #[serde(default = "default_true")]
4837 pub generate_amortization: bool,
4838
4839 #[serde(default = "default_real_estate_pct")]
4841 pub real_estate_percent: f64,
4842}
4843
4844fn default_lease_count() -> usize {
4845 50
4846}
4847
4848fn default_finance_lease_pct() -> f64 {
4849 0.30
4850}
4851
4852fn default_avg_lease_term() -> u32 {
4853 60
4854}
4855
4856fn default_real_estate_pct() -> f64 {
4857 0.40
4858}
4859
4860impl Default for LeaseAccountingConfig {
4861 fn default() -> Self {
4862 Self {
4863 enabled: false,
4864 lease_count: default_lease_count(),
4865 finance_lease_percent: default_finance_lease_pct(),
4866 avg_lease_term_months: default_avg_lease_term(),
4867 generate_amortization: true,
4868 real_estate_percent: default_real_estate_pct(),
4869 }
4870 }
4871}
4872
4873#[derive(Debug, Clone, Serialize, Deserialize)]
4875pub struct FairValueConfig {
4876 #[serde(default)]
4878 pub enabled: bool,
4879
4880 #[serde(default = "default_fv_count")]
4882 pub measurement_count: usize,
4883
4884 #[serde(default = "default_level1_pct")]
4886 pub level1_percent: f64,
4887
4888 #[serde(default = "default_level2_pct")]
4890 pub level2_percent: f64,
4891
4892 #[serde(default = "default_level3_pct")]
4894 pub level3_percent: f64,
4895
4896 #[serde(default)]
4898 pub include_sensitivity_analysis: bool,
4899}
4900
4901fn default_fv_count() -> usize {
4902 25
4903}
4904
4905fn default_level1_pct() -> f64 {
4906 0.40
4907}
4908
4909fn default_level2_pct() -> f64 {
4910 0.35
4911}
4912
4913fn default_level3_pct() -> f64 {
4914 0.25
4915}
4916
4917impl Default for FairValueConfig {
4918 fn default() -> Self {
4919 Self {
4920 enabled: false,
4921 measurement_count: default_fv_count(),
4922 level1_percent: default_level1_pct(),
4923 level2_percent: default_level2_pct(),
4924 level3_percent: default_level3_pct(),
4925 include_sensitivity_analysis: false,
4926 }
4927 }
4928}
4929
4930#[derive(Debug, Clone, Serialize, Deserialize)]
4932pub struct ImpairmentConfig {
4933 #[serde(default)]
4935 pub enabled: bool,
4936
4937 #[serde(default = "default_impairment_count")]
4939 pub test_count: usize,
4940
4941 #[serde(default = "default_impairment_rate")]
4943 pub impairment_rate: f64,
4944
4945 #[serde(default = "default_true")]
4947 pub generate_projections: bool,
4948
4949 #[serde(default)]
4951 pub include_goodwill: bool,
4952}
4953
4954fn default_impairment_count() -> usize {
4955 15
4956}
4957
4958fn default_impairment_rate() -> f64 {
4959 0.10
4960}
4961
4962impl Default for ImpairmentConfig {
4963 fn default() -> Self {
4964 Self {
4965 enabled: false,
4966 test_count: default_impairment_count(),
4967 impairment_rate: default_impairment_rate(),
4968 generate_projections: true,
4969 include_goodwill: false,
4970 }
4971 }
4972}
4973
4974#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4987pub struct AuditStandardsConfig {
4988 #[serde(default)]
4990 pub enabled: bool,
4991
4992 #[serde(default)]
4994 pub isa_compliance: IsaComplianceConfig,
4995
4996 #[serde(default)]
4998 pub analytical_procedures: AnalyticalProceduresConfig,
4999
5000 #[serde(default)]
5002 pub confirmations: ConfirmationsConfig,
5003
5004 #[serde(default)]
5006 pub opinion: AuditOpinionConfig,
5007
5008 #[serde(default)]
5010 pub generate_audit_trail: bool,
5011
5012 #[serde(default)]
5014 pub sox: SoxComplianceConfig,
5015
5016 #[serde(default)]
5018 pub pcaob: PcaobConfig,
5019}
5020
5021#[derive(Debug, Clone, Serialize, Deserialize)]
5023pub struct IsaComplianceConfig {
5024 #[serde(default)]
5026 pub enabled: bool,
5027
5028 #[serde(default = "default_compliance_level")]
5030 pub compliance_level: String,
5031
5032 #[serde(default = "default_true")]
5034 pub generate_isa_mappings: bool,
5035
5036 #[serde(default = "default_true")]
5038 pub generate_coverage_summary: bool,
5039
5040 #[serde(default)]
5042 pub include_pcaob: bool,
5043
5044 #[serde(default = "default_audit_framework")]
5046 pub framework: String,
5047}
5048
5049fn default_compliance_level() -> String {
5050 "standard".to_string()
5051}
5052
5053fn default_audit_framework() -> String {
5054 "isa".to_string()
5055}
5056
5057impl Default for IsaComplianceConfig {
5058 fn default() -> Self {
5059 Self {
5060 enabled: false,
5061 compliance_level: default_compliance_level(),
5062 generate_isa_mappings: true,
5063 generate_coverage_summary: true,
5064 include_pcaob: false,
5065 framework: default_audit_framework(),
5066 }
5067 }
5068}
5069
5070#[derive(Debug, Clone, Serialize, Deserialize)]
5072pub struct AnalyticalProceduresConfig {
5073 #[serde(default)]
5075 pub enabled: bool,
5076
5077 #[serde(default = "default_procedures_per_account")]
5079 pub procedures_per_account: usize,
5080
5081 #[serde(default = "default_variance_probability")]
5083 pub variance_probability: f64,
5084
5085 #[serde(default = "default_true")]
5087 pub generate_investigations: bool,
5088
5089 #[serde(default = "default_true")]
5091 pub include_ratio_analysis: bool,
5092}
5093
5094fn default_procedures_per_account() -> usize {
5095 3
5096}
5097
5098fn default_variance_probability() -> f64 {
5099 0.20
5100}
5101
5102impl Default for AnalyticalProceduresConfig {
5103 fn default() -> Self {
5104 Self {
5105 enabled: false,
5106 procedures_per_account: default_procedures_per_account(),
5107 variance_probability: default_variance_probability(),
5108 generate_investigations: true,
5109 include_ratio_analysis: true,
5110 }
5111 }
5112}
5113
5114#[derive(Debug, Clone, Serialize, Deserialize)]
5116pub struct ConfirmationsConfig {
5117 #[serde(default)]
5119 pub enabled: bool,
5120
5121 #[serde(default = "default_confirmation_count")]
5123 pub confirmation_count: usize,
5124
5125 #[serde(default = "default_positive_response_rate")]
5127 pub positive_response_rate: f64,
5128
5129 #[serde(default = "default_exception_rate_confirm")]
5131 pub exception_rate: f64,
5132
5133 #[serde(default = "default_non_response_rate")]
5135 pub non_response_rate: f64,
5136
5137 #[serde(default = "default_true")]
5139 pub generate_alternative_procedures: bool,
5140}
5141
5142fn default_confirmation_count() -> usize {
5143 50
5144}
5145
5146fn default_positive_response_rate() -> f64 {
5147 0.85
5148}
5149
5150fn default_exception_rate_confirm() -> f64 {
5151 0.10
5152}
5153
5154fn default_non_response_rate() -> f64 {
5155 0.05
5156}
5157
5158impl Default for ConfirmationsConfig {
5159 fn default() -> Self {
5160 Self {
5161 enabled: false,
5162 confirmation_count: default_confirmation_count(),
5163 positive_response_rate: default_positive_response_rate(),
5164 exception_rate: default_exception_rate_confirm(),
5165 non_response_rate: default_non_response_rate(),
5166 generate_alternative_procedures: true,
5167 }
5168 }
5169}
5170
5171#[derive(Debug, Clone, Serialize, Deserialize)]
5173pub struct AuditOpinionConfig {
5174 #[serde(default)]
5176 pub enabled: bool,
5177
5178 #[serde(default = "default_true")]
5180 pub generate_kam: bool,
5181
5182 #[serde(default = "default_kam_count")]
5184 pub average_kam_count: usize,
5185
5186 #[serde(default = "default_modified_opinion_rate")]
5188 pub modified_opinion_rate: f64,
5189
5190 #[serde(default)]
5192 pub include_emphasis_of_matter: bool,
5193
5194 #[serde(default = "default_true")]
5196 pub include_going_concern: bool,
5197}
5198
5199fn default_kam_count() -> usize {
5200 3
5201}
5202
5203fn default_modified_opinion_rate() -> f64 {
5204 0.05
5205}
5206
5207impl Default for AuditOpinionConfig {
5208 fn default() -> Self {
5209 Self {
5210 enabled: false,
5211 generate_kam: true,
5212 average_kam_count: default_kam_count(),
5213 modified_opinion_rate: default_modified_opinion_rate(),
5214 include_emphasis_of_matter: false,
5215 include_going_concern: true,
5216 }
5217 }
5218}
5219
5220#[derive(Debug, Clone, Serialize, Deserialize)]
5222pub struct SoxComplianceConfig {
5223 #[serde(default)]
5225 pub enabled: bool,
5226
5227 #[serde(default = "default_true")]
5229 pub generate_302_certifications: bool,
5230
5231 #[serde(default = "default_true")]
5233 pub generate_404_assessments: bool,
5234
5235 #[serde(default = "default_sox_materiality_threshold")]
5237 pub materiality_threshold: f64,
5238
5239 #[serde(default = "default_material_weakness_rate")]
5241 pub material_weakness_rate: f64,
5242
5243 #[serde(default = "default_significant_deficiency_rate")]
5245 pub significant_deficiency_rate: f64,
5246}
5247
5248fn default_material_weakness_rate() -> f64 {
5249 0.02
5250}
5251
5252fn default_significant_deficiency_rate() -> f64 {
5253 0.08
5254}
5255
5256impl Default for SoxComplianceConfig {
5257 fn default() -> Self {
5258 Self {
5259 enabled: false,
5260 generate_302_certifications: true,
5261 generate_404_assessments: true,
5262 materiality_threshold: default_sox_materiality_threshold(),
5263 material_weakness_rate: default_material_weakness_rate(),
5264 significant_deficiency_rate: default_significant_deficiency_rate(),
5265 }
5266 }
5267}
5268
5269#[derive(Debug, Clone, Serialize, Deserialize)]
5271pub struct PcaobConfig {
5272 #[serde(default)]
5274 pub enabled: bool,
5275
5276 #[serde(default)]
5278 pub is_pcaob_audit: bool,
5279
5280 #[serde(default = "default_true")]
5282 pub generate_cam: bool,
5283
5284 #[serde(default)]
5286 pub include_icfr_opinion: bool,
5287
5288 #[serde(default)]
5290 pub generate_standard_mappings: bool,
5291}
5292
5293impl Default for PcaobConfig {
5294 fn default() -> Self {
5295 Self {
5296 enabled: false,
5297 is_pcaob_audit: false,
5298 generate_cam: true,
5299 include_icfr_opinion: false,
5300 generate_standard_mappings: false,
5301 }
5302 }
5303}
5304
5305#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5318pub struct AdvancedDistributionConfig {
5319 #[serde(default)]
5321 pub enabled: bool,
5322
5323 #[serde(default)]
5325 pub amounts: MixtureDistributionSchemaConfig,
5326
5327 #[serde(default)]
5329 pub correlations: CorrelationSchemaConfig,
5330
5331 #[serde(default)]
5333 pub conditional: Vec<ConditionalDistributionSchemaConfig>,
5334
5335 #[serde(default)]
5337 pub regime_changes: RegimeChangeSchemaConfig,
5338
5339 #[serde(default)]
5341 pub industry_profile: Option<IndustryProfileType>,
5342
5343 #[serde(default)]
5345 pub validation: StatisticalValidationSchemaConfig,
5346}
5347
5348#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
5350#[serde(rename_all = "snake_case")]
5351pub enum IndustryProfileType {
5352 Retail,
5354 Manufacturing,
5356 FinancialServices,
5358 Healthcare,
5360 Technology,
5362}
5363
5364#[derive(Debug, Clone, Serialize, Deserialize)]
5366pub struct MixtureDistributionSchemaConfig {
5367 #[serde(default)]
5369 pub enabled: bool,
5370
5371 #[serde(default = "default_mixture_type")]
5373 pub distribution_type: MixtureDistributionType,
5374
5375 #[serde(default)]
5377 pub components: Vec<MixtureComponentConfig>,
5378
5379 #[serde(default = "default_min_amount")]
5381 pub min_value: f64,
5382
5383 #[serde(default)]
5385 pub max_value: Option<f64>,
5386
5387 #[serde(default = "default_decimal_places")]
5389 pub decimal_places: u8,
5390}
5391
5392fn default_mixture_type() -> MixtureDistributionType {
5393 MixtureDistributionType::LogNormal
5394}
5395
5396fn default_min_amount() -> f64 {
5397 0.01
5398}
5399
5400fn default_decimal_places() -> u8 {
5401 2
5402}
5403
5404impl Default for MixtureDistributionSchemaConfig {
5405 fn default() -> Self {
5406 Self {
5407 enabled: false,
5408 distribution_type: MixtureDistributionType::LogNormal,
5409 components: Vec::new(),
5410 min_value: 0.01,
5411 max_value: None,
5412 decimal_places: 2,
5413 }
5414 }
5415}
5416
5417#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5419#[serde(rename_all = "snake_case")]
5420pub enum MixtureDistributionType {
5421 Gaussian,
5423 #[default]
5425 LogNormal,
5426}
5427
5428#[derive(Debug, Clone, Serialize, Deserialize)]
5430pub struct MixtureComponentConfig {
5431 pub weight: f64,
5433
5434 pub mu: f64,
5436
5437 pub sigma: f64,
5439
5440 #[serde(default)]
5442 pub label: Option<String>,
5443}
5444
5445#[derive(Debug, Clone, Serialize, Deserialize)]
5447pub struct CorrelationSchemaConfig {
5448 #[serde(default)]
5450 pub enabled: bool,
5451
5452 #[serde(default)]
5454 pub copula_type: CopulaSchemaType,
5455
5456 #[serde(default)]
5458 pub fields: Vec<CorrelatedFieldConfig>,
5459
5460 #[serde(default)]
5463 pub matrix: Vec<f64>,
5464
5465 #[serde(default)]
5467 pub expected_correlations: Vec<ExpectedCorrelationConfig>,
5468}
5469
5470impl Default for CorrelationSchemaConfig {
5471 fn default() -> Self {
5472 Self {
5473 enabled: false,
5474 copula_type: CopulaSchemaType::Gaussian,
5475 fields: Vec::new(),
5476 matrix: Vec::new(),
5477 expected_correlations: Vec::new(),
5478 }
5479 }
5480}
5481
5482#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5484#[serde(rename_all = "snake_case")]
5485pub enum CopulaSchemaType {
5486 #[default]
5488 Gaussian,
5489 Clayton,
5491 Gumbel,
5493 Frank,
5495 StudentT,
5497}
5498
5499#[derive(Debug, Clone, Serialize, Deserialize)]
5501pub struct CorrelatedFieldConfig {
5502 pub name: String,
5504
5505 #[serde(default)]
5507 pub distribution: MarginalDistributionConfig,
5508}
5509
5510#[derive(Debug, Clone, Serialize, Deserialize)]
5512#[serde(tag = "type", rename_all = "snake_case")]
5513pub enum MarginalDistributionConfig {
5514 Normal {
5516 mu: f64,
5518 sigma: f64,
5520 },
5521 LogNormal {
5523 mu: f64,
5525 sigma: f64,
5527 },
5528 Uniform {
5530 min: f64,
5532 max: f64,
5534 },
5535 DiscreteUniform {
5537 min: i32,
5539 max: i32,
5541 },
5542}
5543
5544impl Default for MarginalDistributionConfig {
5545 fn default() -> Self {
5546 Self::Normal {
5547 mu: 0.0,
5548 sigma: 1.0,
5549 }
5550 }
5551}
5552
5553#[derive(Debug, Clone, Serialize, Deserialize)]
5555pub struct ExpectedCorrelationConfig {
5556 pub field1: String,
5558 pub field2: String,
5560 pub expected_r: f64,
5562 #[serde(default = "default_correlation_tolerance")]
5564 pub tolerance: f64,
5565}
5566
5567fn default_correlation_tolerance() -> f64 {
5568 0.10
5569}
5570
5571#[derive(Debug, Clone, Serialize, Deserialize)]
5573pub struct ConditionalDistributionSchemaConfig {
5574 pub output_field: String,
5576
5577 pub input_field: String,
5579
5580 #[serde(default)]
5582 pub breakpoints: Vec<ConditionalBreakpointConfig>,
5583
5584 #[serde(default)]
5586 pub default_distribution: ConditionalDistributionParamsConfig,
5587
5588 #[serde(default)]
5590 pub min_value: Option<f64>,
5591
5592 #[serde(default)]
5594 pub max_value: Option<f64>,
5595
5596 #[serde(default = "default_decimal_places")]
5598 pub decimal_places: u8,
5599}
5600
5601#[derive(Debug, Clone, Serialize, Deserialize)]
5603pub struct ConditionalBreakpointConfig {
5604 pub threshold: f64,
5606
5607 pub distribution: ConditionalDistributionParamsConfig,
5609}
5610
5611#[derive(Debug, Clone, Serialize, Deserialize)]
5613#[serde(tag = "type", rename_all = "snake_case")]
5614pub enum ConditionalDistributionParamsConfig {
5615 Fixed {
5617 value: f64,
5619 },
5620 Normal {
5622 mu: f64,
5624 sigma: f64,
5626 },
5627 LogNormal {
5629 mu: f64,
5631 sigma: f64,
5633 },
5634 Uniform {
5636 min: f64,
5638 max: f64,
5640 },
5641 Beta {
5643 alpha: f64,
5645 beta: f64,
5647 min: f64,
5649 max: f64,
5651 },
5652 Discrete {
5654 values: Vec<f64>,
5656 weights: Vec<f64>,
5658 },
5659}
5660
5661impl Default for ConditionalDistributionParamsConfig {
5662 fn default() -> Self {
5663 Self::Normal {
5664 mu: 0.0,
5665 sigma: 1.0,
5666 }
5667 }
5668}
5669
5670#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5672pub struct RegimeChangeSchemaConfig {
5673 #[serde(default)]
5675 pub enabled: bool,
5676
5677 #[serde(default)]
5679 pub changes: Vec<RegimeChangeEventConfig>,
5680
5681 #[serde(default)]
5683 pub economic_cycle: Option<EconomicCycleSchemaConfig>,
5684
5685 #[serde(default)]
5687 pub parameter_drifts: Vec<ParameterDriftSchemaConfig>,
5688}
5689
5690#[derive(Debug, Clone, Serialize, Deserialize)]
5692pub struct RegimeChangeEventConfig {
5693 pub date: String,
5695
5696 pub change_type: RegimeChangeTypeConfig,
5698
5699 #[serde(default)]
5701 pub description: Option<String>,
5702
5703 #[serde(default)]
5705 pub effects: Vec<RegimeEffectConfig>,
5706}
5707
5708#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
5710#[serde(rename_all = "snake_case")]
5711pub enum RegimeChangeTypeConfig {
5712 Acquisition,
5714 Divestiture,
5716 PriceIncrease,
5718 PriceDecrease,
5720 ProductLaunch,
5722 ProductDiscontinuation,
5724 PolicyChange,
5726 CompetitorEntry,
5728 Custom,
5730}
5731
5732#[derive(Debug, Clone, Serialize, Deserialize)]
5734pub struct RegimeEffectConfig {
5735 pub field: String,
5737
5738 pub multiplier: f64,
5740}
5741
5742#[derive(Debug, Clone, Serialize, Deserialize)]
5744pub struct EconomicCycleSchemaConfig {
5745 #[serde(default)]
5747 pub enabled: bool,
5748
5749 #[serde(default = "default_cycle_period")]
5751 pub period_months: u32,
5752
5753 #[serde(default = "default_cycle_amplitude")]
5755 pub amplitude: f64,
5756
5757 #[serde(default)]
5759 pub phase_offset: u32,
5760
5761 #[serde(default)]
5763 pub recessions: Vec<RecessionPeriodConfig>,
5764}
5765
5766fn default_cycle_period() -> u32 {
5767 48
5768}
5769
5770fn default_cycle_amplitude() -> f64 {
5771 0.15
5772}
5773
5774impl Default for EconomicCycleSchemaConfig {
5775 fn default() -> Self {
5776 Self {
5777 enabled: false,
5778 period_months: 48,
5779 amplitude: 0.15,
5780 phase_offset: 0,
5781 recessions: Vec::new(),
5782 }
5783 }
5784}
5785
5786#[derive(Debug, Clone, Serialize, Deserialize)]
5788pub struct RecessionPeriodConfig {
5789 pub start_month: u32,
5791
5792 pub duration_months: u32,
5794
5795 #[serde(default = "default_recession_severity")]
5797 pub severity: f64,
5798}
5799
5800fn default_recession_severity() -> f64 {
5801 0.20
5802}
5803
5804#[derive(Debug, Clone, Serialize, Deserialize)]
5806pub struct ParameterDriftSchemaConfig {
5807 pub parameter: String,
5809
5810 pub drift_type: ParameterDriftTypeConfig,
5812
5813 pub start_value: f64,
5815
5816 pub end_value: f64,
5818
5819 #[serde(default)]
5821 pub start_period: u32,
5822
5823 #[serde(default)]
5825 pub end_period: Option<u32>,
5826}
5827
5828#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5830#[serde(rename_all = "snake_case")]
5831pub enum ParameterDriftTypeConfig {
5832 #[default]
5834 Linear,
5835 Exponential,
5837 Logistic,
5839 Step,
5841}
5842
5843#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5845pub struct StatisticalValidationSchemaConfig {
5846 #[serde(default)]
5848 pub enabled: bool,
5849
5850 #[serde(default)]
5852 pub tests: Vec<StatisticalTestConfig>,
5853
5854 #[serde(default)]
5856 pub reporting: ValidationReportingConfig,
5857}
5858
5859#[derive(Debug, Clone, Serialize, Deserialize)]
5861#[serde(tag = "type", rename_all = "snake_case")]
5862pub enum StatisticalTestConfig {
5863 BenfordFirstDigit {
5865 #[serde(default = "default_benford_threshold")]
5867 threshold_mad: f64,
5868 #[serde(default = "default_benford_warning")]
5870 warning_mad: f64,
5871 },
5872 DistributionFit {
5874 target: TargetDistributionConfig,
5876 #[serde(default = "default_ks_significance")]
5878 ks_significance: f64,
5879 #[serde(default)]
5881 method: DistributionFitMethod,
5882 },
5883 CorrelationCheck {
5885 expected_correlations: Vec<ExpectedCorrelationConfig>,
5887 },
5888 ChiSquared {
5890 #[serde(default = "default_chi_squared_bins")]
5892 bins: usize,
5893 #[serde(default = "default_chi_squared_significance")]
5895 significance: f64,
5896 },
5897 AndersonDarling {
5899 target: TargetDistributionConfig,
5901 #[serde(default = "default_ad_significance")]
5903 significance: f64,
5904 },
5905}
5906
5907fn default_benford_threshold() -> f64 {
5908 0.015
5909}
5910
5911fn default_benford_warning() -> f64 {
5912 0.010
5913}
5914
5915fn default_ks_significance() -> f64 {
5916 0.05
5917}
5918
5919fn default_chi_squared_bins() -> usize {
5920 10
5921}
5922
5923fn default_chi_squared_significance() -> f64 {
5924 0.05
5925}
5926
5927fn default_ad_significance() -> f64 {
5928 0.05
5929}
5930
5931#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5933#[serde(rename_all = "snake_case")]
5934pub enum TargetDistributionConfig {
5935 Normal,
5937 #[default]
5939 LogNormal,
5940 Exponential,
5942 Uniform,
5944}
5945
5946#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5948#[serde(rename_all = "snake_case")]
5949pub enum DistributionFitMethod {
5950 #[default]
5952 KolmogorovSmirnov,
5953 AndersonDarling,
5955 ChiSquared,
5957}
5958
5959#[derive(Debug, Clone, Serialize, Deserialize)]
5961pub struct ValidationReportingConfig {
5962 #[serde(default)]
5964 pub output_report: bool,
5965
5966 #[serde(default)]
5968 pub format: ValidationReportFormat,
5969
5970 #[serde(default)]
5972 pub fail_on_error: bool,
5973
5974 #[serde(default = "default_true")]
5976 pub include_details: bool,
5977}
5978
5979impl Default for ValidationReportingConfig {
5980 fn default() -> Self {
5981 Self {
5982 output_report: false,
5983 format: ValidationReportFormat::Json,
5984 fail_on_error: false,
5985 include_details: true,
5986 }
5987 }
5988}
5989
5990#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5992#[serde(rename_all = "snake_case")]
5993pub enum ValidationReportFormat {
5994 #[default]
5996 Json,
5997 Yaml,
5999 Html,
6001}
6002
6003#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6015pub struct TemporalPatternsConfig {
6016 #[serde(default)]
6018 pub enabled: bool,
6019
6020 #[serde(default)]
6022 pub business_days: BusinessDaySchemaConfig,
6023
6024 #[serde(default)]
6026 pub calendars: CalendarSchemaConfig,
6027
6028 #[serde(default)]
6030 pub period_end: PeriodEndSchemaConfig,
6031
6032 #[serde(default)]
6034 pub processing_lags: ProcessingLagSchemaConfig,
6035
6036 #[serde(default)]
6038 pub fiscal_calendar: FiscalCalendarSchemaConfig,
6039
6040 #[serde(default)]
6042 pub intraday: IntraDaySchemaConfig,
6043
6044 #[serde(default)]
6046 pub timezones: TimezoneSchemaConfig,
6047}
6048
6049#[derive(Debug, Clone, Serialize, Deserialize)]
6051pub struct BusinessDaySchemaConfig {
6052 #[serde(default = "default_true")]
6054 pub enabled: bool,
6055
6056 #[serde(default = "default_half_day_policy")]
6058 pub half_day_policy: String,
6059
6060 #[serde(default)]
6062 pub settlement_rules: SettlementRulesSchemaConfig,
6063
6064 #[serde(default = "default_month_end_convention")]
6066 pub month_end_convention: String,
6067
6068 #[serde(default)]
6070 pub weekend_days: Option<Vec<String>>,
6071}
6072
6073fn default_half_day_policy() -> String {
6074 "half_day".to_string()
6075}
6076
6077fn default_month_end_convention() -> String {
6078 "modified_following".to_string()
6079}
6080
6081impl Default for BusinessDaySchemaConfig {
6082 fn default() -> Self {
6083 Self {
6084 enabled: true,
6085 half_day_policy: "half_day".to_string(),
6086 settlement_rules: SettlementRulesSchemaConfig::default(),
6087 month_end_convention: "modified_following".to_string(),
6088 weekend_days: None,
6089 }
6090 }
6091}
6092
6093#[derive(Debug, Clone, Serialize, Deserialize)]
6095pub struct SettlementRulesSchemaConfig {
6096 #[serde(default = "default_settlement_2")]
6098 pub equity_days: i32,
6099
6100 #[serde(default = "default_settlement_1")]
6102 pub government_bonds_days: i32,
6103
6104 #[serde(default = "default_settlement_2")]
6106 pub fx_spot_days: i32,
6107
6108 #[serde(default = "default_settlement_2")]
6110 pub corporate_bonds_days: i32,
6111
6112 #[serde(default = "default_wire_cutoff")]
6114 pub wire_cutoff_time: String,
6115
6116 #[serde(default = "default_settlement_1")]
6118 pub wire_international_days: i32,
6119
6120 #[serde(default = "default_settlement_1")]
6122 pub ach_days: i32,
6123}
6124
6125fn default_settlement_1() -> i32 {
6126 1
6127}
6128
6129fn default_settlement_2() -> i32 {
6130 2
6131}
6132
6133fn default_wire_cutoff() -> String {
6134 "14:00".to_string()
6135}
6136
6137impl Default for SettlementRulesSchemaConfig {
6138 fn default() -> Self {
6139 Self {
6140 equity_days: 2,
6141 government_bonds_days: 1,
6142 fx_spot_days: 2,
6143 corporate_bonds_days: 2,
6144 wire_cutoff_time: "14:00".to_string(),
6145 wire_international_days: 1,
6146 ach_days: 1,
6147 }
6148 }
6149}
6150
6151#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6153pub struct CalendarSchemaConfig {
6154 #[serde(default)]
6156 pub regions: Vec<String>,
6157
6158 #[serde(default)]
6160 pub custom_holidays: Vec<CustomHolidaySchemaConfig>,
6161}
6162
6163#[derive(Debug, Clone, Serialize, Deserialize)]
6165pub struct CustomHolidaySchemaConfig {
6166 pub name: String,
6168 pub month: u8,
6170 pub day: u8,
6172 #[serde(default = "default_holiday_multiplier")]
6174 pub activity_multiplier: f64,
6175}
6176
6177fn default_holiday_multiplier() -> f64 {
6178 0.05
6179}
6180
6181#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6183pub struct PeriodEndSchemaConfig {
6184 #[serde(default)]
6186 pub model: Option<String>,
6187
6188 #[serde(default)]
6190 pub month_end: Option<PeriodEndModelSchemaConfig>,
6191
6192 #[serde(default)]
6194 pub quarter_end: Option<PeriodEndModelSchemaConfig>,
6195
6196 #[serde(default)]
6198 pub year_end: Option<PeriodEndModelSchemaConfig>,
6199}
6200
6201#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6203pub struct PeriodEndModelSchemaConfig {
6204 #[serde(default)]
6206 pub inherit_from: Option<String>,
6207
6208 #[serde(default)]
6210 pub additional_multiplier: Option<f64>,
6211
6212 #[serde(default)]
6214 pub start_day: Option<i32>,
6215
6216 #[serde(default)]
6218 pub base_multiplier: Option<f64>,
6219
6220 #[serde(default)]
6222 pub peak_multiplier: Option<f64>,
6223
6224 #[serde(default)]
6226 pub decay_rate: Option<f64>,
6227
6228 #[serde(default)]
6230 pub sustained_high_days: Option<i32>,
6231}
6232
6233#[derive(Debug, Clone, Serialize, Deserialize)]
6235pub struct ProcessingLagSchemaConfig {
6236 #[serde(default = "default_true")]
6238 pub enabled: bool,
6239
6240 #[serde(default)]
6242 pub sales_order_lag: Option<LagDistributionSchemaConfig>,
6243
6244 #[serde(default)]
6246 pub purchase_order_lag: Option<LagDistributionSchemaConfig>,
6247
6248 #[serde(default)]
6250 pub goods_receipt_lag: Option<LagDistributionSchemaConfig>,
6251
6252 #[serde(default)]
6254 pub invoice_receipt_lag: Option<LagDistributionSchemaConfig>,
6255
6256 #[serde(default)]
6258 pub invoice_issue_lag: Option<LagDistributionSchemaConfig>,
6259
6260 #[serde(default)]
6262 pub payment_lag: Option<LagDistributionSchemaConfig>,
6263
6264 #[serde(default)]
6266 pub journal_entry_lag: Option<LagDistributionSchemaConfig>,
6267
6268 #[serde(default)]
6270 pub cross_day_posting: Option<CrossDayPostingSchemaConfig>,
6271}
6272
6273impl Default for ProcessingLagSchemaConfig {
6274 fn default() -> Self {
6275 Self {
6276 enabled: true,
6277 sales_order_lag: None,
6278 purchase_order_lag: None,
6279 goods_receipt_lag: None,
6280 invoice_receipt_lag: None,
6281 invoice_issue_lag: None,
6282 payment_lag: None,
6283 journal_entry_lag: None,
6284 cross_day_posting: None,
6285 }
6286 }
6287}
6288
6289#[derive(Debug, Clone, Serialize, Deserialize)]
6291pub struct LagDistributionSchemaConfig {
6292 pub mu: f64,
6294 pub sigma: f64,
6296 #[serde(default)]
6298 pub min_hours: Option<f64>,
6299 #[serde(default)]
6301 pub max_hours: Option<f64>,
6302}
6303
6304#[derive(Debug, Clone, Serialize, Deserialize)]
6306pub struct CrossDayPostingSchemaConfig {
6307 #[serde(default = "default_true")]
6309 pub enabled: bool,
6310
6311 #[serde(default)]
6314 pub probability_by_hour: std::collections::HashMap<u8, f64>,
6315}
6316
6317impl Default for CrossDayPostingSchemaConfig {
6318 fn default() -> Self {
6319 let mut probability_by_hour = std::collections::HashMap::new();
6320 probability_by_hour.insert(17, 0.3);
6321 probability_by_hour.insert(18, 0.6);
6322 probability_by_hour.insert(19, 0.8);
6323 probability_by_hour.insert(20, 0.9);
6324 probability_by_hour.insert(21, 0.95);
6325 probability_by_hour.insert(22, 0.99);
6326
6327 Self {
6328 enabled: true,
6329 probability_by_hour,
6330 }
6331 }
6332}
6333
6334#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6343pub struct FiscalCalendarSchemaConfig {
6344 #[serde(default)]
6346 pub enabled: bool,
6347
6348 #[serde(default = "default_fiscal_calendar_type")]
6350 pub calendar_type: String,
6351
6352 #[serde(default)]
6354 pub year_start_month: Option<u8>,
6355
6356 #[serde(default)]
6358 pub year_start_day: Option<u8>,
6359
6360 #[serde(default)]
6362 pub four_four_five: Option<FourFourFiveSchemaConfig>,
6363}
6364
6365fn default_fiscal_calendar_type() -> String {
6366 "calendar_year".to_string()
6367}
6368
6369#[derive(Debug, Clone, Serialize, Deserialize)]
6371pub struct FourFourFiveSchemaConfig {
6372 #[serde(default = "default_week_pattern")]
6374 pub pattern: String,
6375
6376 #[serde(default = "default_anchor_type")]
6378 pub anchor_type: String,
6379
6380 #[serde(default = "default_anchor_month")]
6382 pub anchor_month: u8,
6383
6384 #[serde(default = "default_leap_week_placement")]
6386 pub leap_week_placement: String,
6387}
6388
6389fn default_week_pattern() -> String {
6390 "four_four_five".to_string()
6391}
6392
6393fn default_anchor_type() -> String {
6394 "last_saturday".to_string()
6395}
6396
6397fn default_anchor_month() -> u8 {
6398 1 }
6400
6401fn default_leap_week_placement() -> String {
6402 "q4_period3".to_string()
6403}
6404
6405impl Default for FourFourFiveSchemaConfig {
6406 fn default() -> Self {
6407 Self {
6408 pattern: "four_four_five".to_string(),
6409 anchor_type: "last_saturday".to_string(),
6410 anchor_month: 1,
6411 leap_week_placement: "q4_period3".to_string(),
6412 }
6413 }
6414}
6415
6416#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6425pub struct IntraDaySchemaConfig {
6426 #[serde(default)]
6428 pub enabled: bool,
6429
6430 #[serde(default)]
6432 pub segments: Vec<IntraDaySegmentSchemaConfig>,
6433}
6434
6435#[derive(Debug, Clone, Serialize, Deserialize)]
6437pub struct IntraDaySegmentSchemaConfig {
6438 pub name: String,
6440
6441 pub start: String,
6443
6444 pub end: String,
6446
6447 #[serde(default = "default_multiplier")]
6449 pub multiplier: f64,
6450
6451 #[serde(default = "default_posting_type")]
6453 pub posting_type: String,
6454}
6455
6456fn default_multiplier() -> f64 {
6457 1.0
6458}
6459
6460fn default_posting_type() -> String {
6461 "both".to_string()
6462}
6463
6464#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6470pub struct TimezoneSchemaConfig {
6471 #[serde(default)]
6473 pub enabled: bool,
6474
6475 #[serde(default = "default_timezone")]
6477 pub default_timezone: String,
6478
6479 #[serde(default = "default_consolidation_timezone")]
6481 pub consolidation_timezone: String,
6482
6483 #[serde(default)]
6486 pub entity_mappings: Vec<EntityTimezoneMapping>,
6487}
6488
6489fn default_timezone() -> String {
6490 "America/New_York".to_string()
6491}
6492
6493fn default_consolidation_timezone() -> String {
6494 "UTC".to_string()
6495}
6496
6497#[derive(Debug, Clone, Serialize, Deserialize)]
6499pub struct EntityTimezoneMapping {
6500 pub pattern: String,
6502
6503 pub timezone: String,
6505}
6506
6507#[derive(Debug, Clone, Serialize, Deserialize)]
6513pub struct VendorNetworkSchemaConfig {
6514 #[serde(default)]
6516 pub enabled: bool,
6517
6518 #[serde(default = "default_vendor_tier_depth")]
6520 pub depth: u8,
6521
6522 #[serde(default)]
6524 pub tier1: TierCountSchemaConfig,
6525
6526 #[serde(default)]
6528 pub tier2_per_parent: TierCountSchemaConfig,
6529
6530 #[serde(default)]
6532 pub tier3_per_parent: TierCountSchemaConfig,
6533
6534 #[serde(default)]
6536 pub clusters: VendorClusterSchemaConfig,
6537
6538 #[serde(default)]
6540 pub dependencies: DependencySchemaConfig,
6541}
6542
6543fn default_vendor_tier_depth() -> u8 {
6544 3
6545}
6546
6547impl Default for VendorNetworkSchemaConfig {
6548 fn default() -> Self {
6549 Self {
6550 enabled: false,
6551 depth: 3,
6552 tier1: TierCountSchemaConfig { min: 50, max: 100 },
6553 tier2_per_parent: TierCountSchemaConfig { min: 4, max: 10 },
6554 tier3_per_parent: TierCountSchemaConfig { min: 2, max: 5 },
6555 clusters: VendorClusterSchemaConfig::default(),
6556 dependencies: DependencySchemaConfig::default(),
6557 }
6558 }
6559}
6560
6561#[derive(Debug, Clone, Serialize, Deserialize)]
6563pub struct TierCountSchemaConfig {
6564 #[serde(default = "default_tier_min")]
6566 pub min: usize,
6567
6568 #[serde(default = "default_tier_max")]
6570 pub max: usize,
6571}
6572
6573fn default_tier_min() -> usize {
6574 5
6575}
6576
6577fn default_tier_max() -> usize {
6578 20
6579}
6580
6581impl Default for TierCountSchemaConfig {
6582 fn default() -> Self {
6583 Self {
6584 min: default_tier_min(),
6585 max: default_tier_max(),
6586 }
6587 }
6588}
6589
6590#[derive(Debug, Clone, Serialize, Deserialize)]
6592pub struct VendorClusterSchemaConfig {
6593 #[serde(default = "default_reliable_strategic")]
6595 pub reliable_strategic: f64,
6596
6597 #[serde(default = "default_standard_operational")]
6599 pub standard_operational: f64,
6600
6601 #[serde(default = "default_transactional")]
6603 pub transactional: f64,
6604
6605 #[serde(default = "default_problematic")]
6607 pub problematic: f64,
6608}
6609
6610fn default_reliable_strategic() -> f64 {
6611 0.20
6612}
6613
6614fn default_standard_operational() -> f64 {
6615 0.50
6616}
6617
6618fn default_transactional() -> f64 {
6619 0.25
6620}
6621
6622fn default_problematic() -> f64 {
6623 0.05
6624}
6625
6626impl Default for VendorClusterSchemaConfig {
6627 fn default() -> Self {
6628 Self {
6629 reliable_strategic: 0.20,
6630 standard_operational: 0.50,
6631 transactional: 0.25,
6632 problematic: 0.05,
6633 }
6634 }
6635}
6636
6637#[derive(Debug, Clone, Serialize, Deserialize)]
6639pub struct DependencySchemaConfig {
6640 #[serde(default = "default_max_single_vendor")]
6642 pub max_single_vendor_concentration: f64,
6643
6644 #[serde(default = "default_max_top5")]
6646 pub top_5_concentration: f64,
6647
6648 #[serde(default = "default_single_source_percent")]
6650 pub single_source_percent: f64,
6651}
6652
6653fn default_max_single_vendor() -> f64 {
6654 0.15
6655}
6656
6657fn default_max_top5() -> f64 {
6658 0.45
6659}
6660
6661fn default_single_source_percent() -> f64 {
6662 0.05
6663}
6664
6665impl Default for DependencySchemaConfig {
6666 fn default() -> Self {
6667 Self {
6668 max_single_vendor_concentration: 0.15,
6669 top_5_concentration: 0.45,
6670 single_source_percent: 0.05,
6671 }
6672 }
6673}
6674
6675#[derive(Debug, Clone, Default, Serialize, Deserialize)]
6681pub struct CustomerSegmentationSchemaConfig {
6682 #[serde(default)]
6684 pub enabled: bool,
6685
6686 #[serde(default)]
6688 pub value_segments: ValueSegmentsSchemaConfig,
6689
6690 #[serde(default)]
6692 pub lifecycle: LifecycleSchemaConfig,
6693
6694 #[serde(default)]
6696 pub networks: CustomerNetworksSchemaConfig,
6697}
6698
6699#[derive(Debug, Clone, Serialize, Deserialize)]
6701pub struct ValueSegmentsSchemaConfig {
6702 #[serde(default)]
6704 pub enterprise: SegmentDetailSchemaConfig,
6705
6706 #[serde(default)]
6708 pub mid_market: SegmentDetailSchemaConfig,
6709
6710 #[serde(default)]
6712 pub smb: SegmentDetailSchemaConfig,
6713
6714 #[serde(default)]
6716 pub consumer: SegmentDetailSchemaConfig,
6717}
6718
6719impl Default for ValueSegmentsSchemaConfig {
6720 fn default() -> Self {
6721 Self {
6722 enterprise: SegmentDetailSchemaConfig {
6723 revenue_share: 0.40,
6724 customer_share: 0.05,
6725 avg_order_value_range: "50000+".to_string(),
6726 },
6727 mid_market: SegmentDetailSchemaConfig {
6728 revenue_share: 0.35,
6729 customer_share: 0.20,
6730 avg_order_value_range: "5000-50000".to_string(),
6731 },
6732 smb: SegmentDetailSchemaConfig {
6733 revenue_share: 0.20,
6734 customer_share: 0.50,
6735 avg_order_value_range: "500-5000".to_string(),
6736 },
6737 consumer: SegmentDetailSchemaConfig {
6738 revenue_share: 0.05,
6739 customer_share: 0.25,
6740 avg_order_value_range: "50-500".to_string(),
6741 },
6742 }
6743 }
6744}
6745
6746#[derive(Debug, Clone, Serialize, Deserialize)]
6748pub struct SegmentDetailSchemaConfig {
6749 #[serde(default)]
6751 pub revenue_share: f64,
6752
6753 #[serde(default)]
6755 pub customer_share: f64,
6756
6757 #[serde(default)]
6759 pub avg_order_value_range: String,
6760}
6761
6762impl Default for SegmentDetailSchemaConfig {
6763 fn default() -> Self {
6764 Self {
6765 revenue_share: 0.25,
6766 customer_share: 0.25,
6767 avg_order_value_range: "1000-10000".to_string(),
6768 }
6769 }
6770}
6771
6772#[derive(Debug, Clone, Serialize, Deserialize)]
6774pub struct LifecycleSchemaConfig {
6775 #[serde(default)]
6777 pub prospect_rate: f64,
6778
6779 #[serde(default = "default_new_rate")]
6781 pub new_rate: f64,
6782
6783 #[serde(default = "default_growth_rate")]
6785 pub growth_rate: f64,
6786
6787 #[serde(default = "default_mature_rate")]
6789 pub mature_rate: f64,
6790
6791 #[serde(default = "default_at_risk_rate")]
6793 pub at_risk_rate: f64,
6794
6795 #[serde(default = "default_churned_rate")]
6797 pub churned_rate: f64,
6798}
6799
6800fn default_new_rate() -> f64 {
6801 0.10
6802}
6803
6804fn default_growth_rate() -> f64 {
6805 0.15
6806}
6807
6808fn default_mature_rate() -> f64 {
6809 0.60
6810}
6811
6812fn default_at_risk_rate() -> f64 {
6813 0.10
6814}
6815
6816fn default_churned_rate() -> f64 {
6817 0.05
6818}
6819
6820impl Default for LifecycleSchemaConfig {
6821 fn default() -> Self {
6822 Self {
6823 prospect_rate: 0.0,
6824 new_rate: 0.10,
6825 growth_rate: 0.15,
6826 mature_rate: 0.60,
6827 at_risk_rate: 0.10,
6828 churned_rate: 0.05,
6829 }
6830 }
6831}
6832
6833#[derive(Debug, Clone, Default, Serialize, Deserialize)]
6835pub struct CustomerNetworksSchemaConfig {
6836 #[serde(default)]
6838 pub referrals: ReferralSchemaConfig,
6839
6840 #[serde(default)]
6842 pub corporate_hierarchies: HierarchySchemaConfig,
6843}
6844
6845#[derive(Debug, Clone, Serialize, Deserialize)]
6847pub struct ReferralSchemaConfig {
6848 #[serde(default = "default_true")]
6850 pub enabled: bool,
6851
6852 #[serde(default = "default_referral_rate")]
6854 pub referral_rate: f64,
6855}
6856
6857fn default_referral_rate() -> f64 {
6858 0.15
6859}
6860
6861impl Default for ReferralSchemaConfig {
6862 fn default() -> Self {
6863 Self {
6864 enabled: true,
6865 referral_rate: 0.15,
6866 }
6867 }
6868}
6869
6870#[derive(Debug, Clone, Serialize, Deserialize)]
6872pub struct HierarchySchemaConfig {
6873 #[serde(default = "default_true")]
6875 pub enabled: bool,
6876
6877 #[serde(default = "default_hierarchy_rate")]
6879 pub probability: f64,
6880}
6881
6882fn default_hierarchy_rate() -> f64 {
6883 0.30
6884}
6885
6886impl Default for HierarchySchemaConfig {
6887 fn default() -> Self {
6888 Self {
6889 enabled: true,
6890 probability: 0.30,
6891 }
6892 }
6893}
6894
6895#[derive(Debug, Clone, Default, Serialize, Deserialize)]
6901pub struct RelationshipStrengthSchemaConfig {
6902 #[serde(default)]
6904 pub enabled: bool,
6905
6906 #[serde(default)]
6908 pub calculation: StrengthCalculationSchemaConfig,
6909
6910 #[serde(default)]
6912 pub thresholds: StrengthThresholdsSchemaConfig,
6913}
6914
6915#[derive(Debug, Clone, Serialize, Deserialize)]
6917pub struct StrengthCalculationSchemaConfig {
6918 #[serde(default = "default_volume_weight")]
6920 pub transaction_volume_weight: f64,
6921
6922 #[serde(default = "default_count_weight")]
6924 pub transaction_count_weight: f64,
6925
6926 #[serde(default = "default_duration_weight")]
6928 pub relationship_duration_weight: f64,
6929
6930 #[serde(default = "default_recency_weight")]
6932 pub recency_weight: f64,
6933
6934 #[serde(default = "default_mutual_weight")]
6936 pub mutual_connections_weight: f64,
6937
6938 #[serde(default = "default_recency_half_life")]
6940 pub recency_half_life_days: u32,
6941}
6942
6943fn default_volume_weight() -> f64 {
6944 0.30
6945}
6946
6947fn default_count_weight() -> f64 {
6948 0.25
6949}
6950
6951fn default_duration_weight() -> f64 {
6952 0.20
6953}
6954
6955fn default_recency_weight() -> f64 {
6956 0.15
6957}
6958
6959fn default_mutual_weight() -> f64 {
6960 0.10
6961}
6962
6963fn default_recency_half_life() -> u32 {
6964 90
6965}
6966
6967impl Default for StrengthCalculationSchemaConfig {
6968 fn default() -> Self {
6969 Self {
6970 transaction_volume_weight: 0.30,
6971 transaction_count_weight: 0.25,
6972 relationship_duration_weight: 0.20,
6973 recency_weight: 0.15,
6974 mutual_connections_weight: 0.10,
6975 recency_half_life_days: 90,
6976 }
6977 }
6978}
6979
6980#[derive(Debug, Clone, Serialize, Deserialize)]
6982pub struct StrengthThresholdsSchemaConfig {
6983 #[serde(default = "default_strong_threshold")]
6985 pub strong: f64,
6986
6987 #[serde(default = "default_moderate_threshold")]
6989 pub moderate: f64,
6990
6991 #[serde(default = "default_weak_threshold")]
6993 pub weak: f64,
6994}
6995
6996fn default_strong_threshold() -> f64 {
6997 0.7
6998}
6999
7000fn default_moderate_threshold() -> f64 {
7001 0.4
7002}
7003
7004fn default_weak_threshold() -> f64 {
7005 0.1
7006}
7007
7008impl Default for StrengthThresholdsSchemaConfig {
7009 fn default() -> Self {
7010 Self {
7011 strong: 0.7,
7012 moderate: 0.4,
7013 weak: 0.1,
7014 }
7015 }
7016}
7017
7018#[derive(Debug, Clone, Serialize, Deserialize)]
7024pub struct CrossProcessLinksSchemaConfig {
7025 #[serde(default)]
7027 pub enabled: bool,
7028
7029 #[serde(default = "default_true")]
7031 pub inventory_p2p_o2c: bool,
7032
7033 #[serde(default = "default_true")]
7035 pub payment_bank_reconciliation: bool,
7036
7037 #[serde(default = "default_true")]
7039 pub intercompany_bilateral: bool,
7040
7041 #[serde(default = "default_inventory_link_rate")]
7043 pub inventory_link_rate: f64,
7044}
7045
7046fn default_inventory_link_rate() -> f64 {
7047 0.30
7048}
7049
7050impl Default for CrossProcessLinksSchemaConfig {
7051 fn default() -> Self {
7052 Self {
7053 enabled: false,
7054 inventory_p2p_o2c: true,
7055 payment_bank_reconciliation: true,
7056 intercompany_bilateral: true,
7057 inventory_link_rate: 0.30,
7058 }
7059 }
7060}
7061
7062#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7068pub struct OrganizationalEventsSchemaConfig {
7069 #[serde(default)]
7071 pub enabled: bool,
7072
7073 #[serde(default)]
7075 pub effect_blending: EffectBlendingModeConfig,
7076
7077 #[serde(default)]
7079 pub events: Vec<OrganizationalEventSchemaConfig>,
7080
7081 #[serde(default)]
7083 pub process_evolution: Vec<ProcessEvolutionSchemaConfig>,
7084
7085 #[serde(default)]
7087 pub technology_transitions: Vec<TechnologyTransitionSchemaConfig>,
7088}
7089
7090#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
7092#[serde(rename_all = "snake_case")]
7093pub enum EffectBlendingModeConfig {
7094 #[default]
7096 Multiplicative,
7097 Additive,
7099 Maximum,
7101 Minimum,
7103}
7104
7105#[derive(Debug, Clone, Serialize, Deserialize)]
7107pub struct OrganizationalEventSchemaConfig {
7108 pub id: String,
7110
7111 pub event_type: OrganizationalEventTypeSchemaConfig,
7113
7114 pub effective_date: String,
7116
7117 #[serde(default = "default_org_transition_months")]
7119 pub transition_months: u32,
7120
7121 #[serde(default)]
7123 pub description: Option<String>,
7124}
7125
7126fn default_org_transition_months() -> u32 {
7127 6
7128}
7129
7130#[derive(Debug, Clone, Serialize, Deserialize)]
7132#[serde(tag = "type", rename_all = "snake_case")]
7133pub enum OrganizationalEventTypeSchemaConfig {
7134 Acquisition {
7136 acquired_entity: String,
7138 #[serde(default = "default_acquisition_volume")]
7140 volume_increase: f64,
7141 #[serde(default = "default_acquisition_error")]
7143 integration_error_rate: f64,
7144 #[serde(default = "default_parallel_days")]
7146 parallel_posting_days: u32,
7147 },
7148 Divestiture {
7150 divested_entity: String,
7152 #[serde(default = "default_divestiture_volume")]
7154 volume_reduction: f64,
7155 #[serde(default = "default_true_val")]
7157 remove_entity: bool,
7158 },
7159 Reorganization {
7161 #[serde(default)]
7163 cost_center_remapping: std::collections::HashMap<String, String>,
7164 #[serde(default = "default_reorg_error")]
7166 transition_error_rate: f64,
7167 },
7168 LeadershipChange {
7170 role: String,
7172 #[serde(default)]
7174 policy_changes: Vec<String>,
7175 },
7176 WorkforceReduction {
7178 #[serde(default = "default_workforce_reduction")]
7180 reduction_percent: f64,
7181 #[serde(default = "default_workforce_error")]
7183 error_rate_increase: f64,
7184 },
7185 Merger {
7187 merged_entity: String,
7189 #[serde(default = "default_merger_volume")]
7191 volume_increase: f64,
7192 },
7193}
7194
7195fn default_acquisition_volume() -> f64 {
7196 1.35
7197}
7198
7199fn default_acquisition_error() -> f64 {
7200 0.05
7201}
7202
7203fn default_parallel_days() -> u32 {
7204 30
7205}
7206
7207fn default_divestiture_volume() -> f64 {
7208 0.70
7209}
7210
7211fn default_true_val() -> bool {
7212 true
7213}
7214
7215fn default_reorg_error() -> f64 {
7216 0.04
7217}
7218
7219fn default_workforce_reduction() -> f64 {
7220 0.10
7221}
7222
7223fn default_workforce_error() -> f64 {
7224 0.05
7225}
7226
7227fn default_merger_volume() -> f64 {
7228 1.80
7229}
7230
7231#[derive(Debug, Clone, Serialize, Deserialize)]
7233pub struct ProcessEvolutionSchemaConfig {
7234 pub id: String,
7236
7237 pub event_type: ProcessEvolutionTypeSchemaConfig,
7239
7240 pub effective_date: String,
7242
7243 #[serde(default)]
7245 pub description: Option<String>,
7246}
7247
7248#[derive(Debug, Clone, Serialize, Deserialize)]
7250#[serde(tag = "type", rename_all = "snake_case")]
7251pub enum ProcessEvolutionTypeSchemaConfig {
7252 ProcessAutomation {
7254 process_name: String,
7256 #[serde(default = "default_manual_before")]
7258 manual_rate_before: f64,
7259 #[serde(default = "default_manual_after")]
7261 manual_rate_after: f64,
7262 },
7263 ApprovalWorkflowChange {
7265 description: String,
7267 },
7268 ControlEnhancement {
7270 control_id: String,
7272 #[serde(default = "default_error_reduction")]
7274 error_reduction: f64,
7275 },
7276}
7277
7278fn default_manual_before() -> f64 {
7279 0.80
7280}
7281
7282fn default_manual_after() -> f64 {
7283 0.15
7284}
7285
7286fn default_error_reduction() -> f64 {
7287 0.02
7288}
7289
7290#[derive(Debug, Clone, Serialize, Deserialize)]
7292pub struct TechnologyTransitionSchemaConfig {
7293 pub id: String,
7295
7296 pub event_type: TechnologyTransitionTypeSchemaConfig,
7298
7299 #[serde(default)]
7301 pub description: Option<String>,
7302}
7303
7304#[derive(Debug, Clone, Serialize, Deserialize)]
7306#[serde(tag = "type", rename_all = "snake_case")]
7307pub enum TechnologyTransitionTypeSchemaConfig {
7308 ErpMigration {
7310 source_system: String,
7312 target_system: String,
7314 cutover_date: String,
7316 stabilization_end: String,
7318 #[serde(default = "default_erp_duplicate_rate")]
7320 duplicate_rate: f64,
7321 #[serde(default = "default_format_mismatch")]
7323 format_mismatch_rate: f64,
7324 },
7325 ModuleImplementation {
7327 module_name: String,
7329 go_live_date: String,
7331 },
7332}
7333
7334fn default_erp_duplicate_rate() -> f64 {
7335 0.02
7336}
7337
7338fn default_format_mismatch() -> f64 {
7339 0.03
7340}
7341
7342#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7348pub struct BehavioralDriftSchemaConfig {
7349 #[serde(default)]
7351 pub enabled: bool,
7352
7353 #[serde(default)]
7355 pub vendor_behavior: VendorBehaviorSchemaConfig,
7356
7357 #[serde(default)]
7359 pub customer_behavior: CustomerBehaviorSchemaConfig,
7360
7361 #[serde(default)]
7363 pub employee_behavior: EmployeeBehaviorSchemaConfig,
7364
7365 #[serde(default)]
7367 pub collective: CollectiveBehaviorSchemaConfig,
7368}
7369
7370#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7372pub struct VendorBehaviorSchemaConfig {
7373 #[serde(default)]
7375 pub payment_terms_drift: PaymentTermsDriftSchemaConfig,
7376
7377 #[serde(default)]
7379 pub quality_drift: QualityDriftSchemaConfig,
7380}
7381
7382#[derive(Debug, Clone, Serialize, Deserialize)]
7384pub struct PaymentTermsDriftSchemaConfig {
7385 #[serde(default = "default_extension_rate")]
7387 pub extension_rate_per_year: f64,
7388
7389 #[serde(default = "default_economic_sensitivity")]
7391 pub economic_sensitivity: f64,
7392}
7393
7394fn default_extension_rate() -> f64 {
7395 2.5
7396}
7397
7398fn default_economic_sensitivity() -> f64 {
7399 1.0
7400}
7401
7402impl Default for PaymentTermsDriftSchemaConfig {
7403 fn default() -> Self {
7404 Self {
7405 extension_rate_per_year: 2.5,
7406 economic_sensitivity: 1.0,
7407 }
7408 }
7409}
7410
7411#[derive(Debug, Clone, Serialize, Deserialize)]
7413pub struct QualityDriftSchemaConfig {
7414 #[serde(default = "default_improvement_rate")]
7416 pub new_vendor_improvement_rate: f64,
7417
7418 #[serde(default = "default_decline_rate")]
7420 pub complacency_decline_rate: f64,
7421}
7422
7423fn default_improvement_rate() -> f64 {
7424 0.02
7425}
7426
7427fn default_decline_rate() -> f64 {
7428 0.01
7429}
7430
7431impl Default for QualityDriftSchemaConfig {
7432 fn default() -> Self {
7433 Self {
7434 new_vendor_improvement_rate: 0.02,
7435 complacency_decline_rate: 0.01,
7436 }
7437 }
7438}
7439
7440#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7442pub struct CustomerBehaviorSchemaConfig {
7443 #[serde(default)]
7445 pub payment_drift: CustomerPaymentDriftSchemaConfig,
7446
7447 #[serde(default)]
7449 pub order_drift: OrderDriftSchemaConfig,
7450}
7451
7452#[derive(Debug, Clone, Serialize, Deserialize)]
7454pub struct CustomerPaymentDriftSchemaConfig {
7455 #[serde(default = "default_downturn_extension")]
7457 pub downturn_days_extension: (u32, u32),
7458
7459 #[serde(default = "default_bad_debt_increase")]
7461 pub downturn_bad_debt_increase: f64,
7462}
7463
7464fn default_downturn_extension() -> (u32, u32) {
7465 (5, 15)
7466}
7467
7468fn default_bad_debt_increase() -> f64 {
7469 0.02
7470}
7471
7472impl Default for CustomerPaymentDriftSchemaConfig {
7473 fn default() -> Self {
7474 Self {
7475 downturn_days_extension: (5, 15),
7476 downturn_bad_debt_increase: 0.02,
7477 }
7478 }
7479}
7480
7481#[derive(Debug, Clone, Serialize, Deserialize)]
7483pub struct OrderDriftSchemaConfig {
7484 #[serde(default = "default_digital_shift")]
7486 pub digital_shift_rate: f64,
7487}
7488
7489fn default_digital_shift() -> f64 {
7490 0.05
7491}
7492
7493impl Default for OrderDriftSchemaConfig {
7494 fn default() -> Self {
7495 Self {
7496 digital_shift_rate: 0.05,
7497 }
7498 }
7499}
7500
7501#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7503pub struct EmployeeBehaviorSchemaConfig {
7504 #[serde(default)]
7506 pub approval_drift: ApprovalDriftSchemaConfig,
7507
7508 #[serde(default)]
7510 pub error_drift: ErrorDriftSchemaConfig,
7511}
7512
7513#[derive(Debug, Clone, Serialize, Deserialize)]
7515pub struct ApprovalDriftSchemaConfig {
7516 #[serde(default = "default_eom_intensity")]
7518 pub eom_intensity_increase_per_year: f64,
7519
7520 #[serde(default = "default_rubber_stamp")]
7522 pub rubber_stamp_volume_threshold: u32,
7523}
7524
7525fn default_eom_intensity() -> f64 {
7526 0.05
7527}
7528
7529fn default_rubber_stamp() -> u32 {
7530 50
7531}
7532
7533impl Default for ApprovalDriftSchemaConfig {
7534 fn default() -> Self {
7535 Self {
7536 eom_intensity_increase_per_year: 0.05,
7537 rubber_stamp_volume_threshold: 50,
7538 }
7539 }
7540}
7541
7542#[derive(Debug, Clone, Serialize, Deserialize)]
7544pub struct ErrorDriftSchemaConfig {
7545 #[serde(default = "default_new_error")]
7547 pub new_employee_error_rate: f64,
7548
7549 #[serde(default = "default_learning_months")]
7551 pub learning_curve_months: u32,
7552}
7553
7554fn default_new_error() -> f64 {
7555 0.08
7556}
7557
7558fn default_learning_months() -> u32 {
7559 6
7560}
7561
7562impl Default for ErrorDriftSchemaConfig {
7563 fn default() -> Self {
7564 Self {
7565 new_employee_error_rate: 0.08,
7566 learning_curve_months: 6,
7567 }
7568 }
7569}
7570
7571#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7573pub struct CollectiveBehaviorSchemaConfig {
7574 #[serde(default)]
7576 pub automation_adoption: AutomationAdoptionSchemaConfig,
7577}
7578
7579#[derive(Debug, Clone, Serialize, Deserialize)]
7581pub struct AutomationAdoptionSchemaConfig {
7582 #[serde(default)]
7584 pub s_curve_enabled: bool,
7585
7586 #[serde(default = "default_midpoint")]
7588 pub adoption_midpoint_months: u32,
7589
7590 #[serde(default = "default_steepness")]
7592 pub steepness: f64,
7593}
7594
7595fn default_midpoint() -> u32 {
7596 24
7597}
7598
7599fn default_steepness() -> f64 {
7600 0.15
7601}
7602
7603impl Default for AutomationAdoptionSchemaConfig {
7604 fn default() -> Self {
7605 Self {
7606 s_curve_enabled: false,
7607 adoption_midpoint_months: 24,
7608 steepness: 0.15,
7609 }
7610 }
7611}
7612
7613#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7619pub struct MarketDriftSchemaConfig {
7620 #[serde(default)]
7622 pub enabled: bool,
7623
7624 #[serde(default)]
7626 pub economic_cycle: MarketEconomicCycleSchemaConfig,
7627
7628 #[serde(default)]
7630 pub industry_cycles: std::collections::HashMap<String, IndustryCycleSchemaConfig>,
7631
7632 #[serde(default)]
7634 pub commodities: CommoditiesSchemaConfig,
7635}
7636
7637#[derive(Debug, Clone, Serialize, Deserialize)]
7639pub struct MarketEconomicCycleSchemaConfig {
7640 #[serde(default)]
7642 pub enabled: bool,
7643
7644 #[serde(default)]
7646 pub cycle_type: CycleTypeSchemaConfig,
7647
7648 #[serde(default = "default_market_cycle_period")]
7650 pub period_months: u32,
7651
7652 #[serde(default = "default_market_amplitude")]
7654 pub amplitude: f64,
7655
7656 #[serde(default)]
7658 pub recession: RecessionSchemaConfig,
7659}
7660
7661fn default_market_cycle_period() -> u32 {
7662 48
7663}
7664
7665fn default_market_amplitude() -> f64 {
7666 0.15
7667}
7668
7669impl Default for MarketEconomicCycleSchemaConfig {
7670 fn default() -> Self {
7671 Self {
7672 enabled: false,
7673 cycle_type: CycleTypeSchemaConfig::Sinusoidal,
7674 period_months: 48,
7675 amplitude: 0.15,
7676 recession: RecessionSchemaConfig::default(),
7677 }
7678 }
7679}
7680
7681#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
7683#[serde(rename_all = "snake_case")]
7684pub enum CycleTypeSchemaConfig {
7685 #[default]
7687 Sinusoidal,
7688 Asymmetric,
7690 MeanReverting,
7692}
7693
7694#[derive(Debug, Clone, Serialize, Deserialize)]
7696pub struct RecessionSchemaConfig {
7697 #[serde(default)]
7699 pub enabled: bool,
7700
7701 #[serde(default = "default_recession_prob")]
7703 pub probability_per_year: f64,
7704
7705 #[serde(default)]
7707 pub severity: RecessionSeveritySchemaConfig,
7708
7709 #[serde(default)]
7711 pub recession_periods: Vec<RecessionPeriodSchemaConfig>,
7712}
7713
7714fn default_recession_prob() -> f64 {
7715 0.10
7716}
7717
7718impl Default for RecessionSchemaConfig {
7719 fn default() -> Self {
7720 Self {
7721 enabled: false,
7722 probability_per_year: 0.10,
7723 severity: RecessionSeveritySchemaConfig::Moderate,
7724 recession_periods: Vec::new(),
7725 }
7726 }
7727}
7728
7729#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
7731#[serde(rename_all = "snake_case")]
7732pub enum RecessionSeveritySchemaConfig {
7733 Mild,
7735 #[default]
7737 Moderate,
7738 Severe,
7740}
7741
7742#[derive(Debug, Clone, Serialize, Deserialize)]
7744pub struct RecessionPeriodSchemaConfig {
7745 pub start_month: u32,
7747 pub duration_months: u32,
7749}
7750
7751#[derive(Debug, Clone, Serialize, Deserialize)]
7753pub struct IndustryCycleSchemaConfig {
7754 #[serde(default = "default_industry_period")]
7756 pub period_months: u32,
7757
7758 #[serde(default = "default_industry_amp")]
7760 pub amplitude: f64,
7761}
7762
7763fn default_industry_period() -> u32 {
7764 36
7765}
7766
7767fn default_industry_amp() -> f64 {
7768 0.20
7769}
7770
7771#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7773pub struct CommoditiesSchemaConfig {
7774 #[serde(default)]
7776 pub enabled: bool,
7777
7778 #[serde(default)]
7780 pub items: Vec<CommodityItemSchemaConfig>,
7781}
7782
7783#[derive(Debug, Clone, Serialize, Deserialize)]
7785pub struct CommodityItemSchemaConfig {
7786 pub name: String,
7788
7789 #[serde(default = "default_volatility")]
7791 pub volatility: f64,
7792
7793 #[serde(default)]
7795 pub cogs_pass_through: f64,
7796
7797 #[serde(default)]
7799 pub overhead_pass_through: f64,
7800}
7801
7802fn default_volatility() -> f64 {
7803 0.20
7804}
7805
7806#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7812pub struct DriftLabelingSchemaConfig {
7813 #[serde(default)]
7815 pub enabled: bool,
7816
7817 #[serde(default)]
7819 pub statistical: StatisticalDriftLabelingSchemaConfig,
7820
7821 #[serde(default)]
7823 pub categorical: CategoricalDriftLabelingSchemaConfig,
7824
7825 #[serde(default)]
7827 pub temporal: TemporalDriftLabelingSchemaConfig,
7828
7829 #[serde(default)]
7831 pub regulatory_calendar_preset: Option<String>,
7832}
7833
7834#[derive(Debug, Clone, Serialize, Deserialize)]
7836pub struct StatisticalDriftLabelingSchemaConfig {
7837 #[serde(default = "default_true_val")]
7839 pub enabled: bool,
7840
7841 #[serde(default = "default_min_magnitude")]
7843 pub min_magnitude_threshold: f64,
7844}
7845
7846fn default_min_magnitude() -> f64 {
7847 0.05
7848}
7849
7850impl Default for StatisticalDriftLabelingSchemaConfig {
7851 fn default() -> Self {
7852 Self {
7853 enabled: true,
7854 min_magnitude_threshold: 0.05,
7855 }
7856 }
7857}
7858
7859#[derive(Debug, Clone, Serialize, Deserialize)]
7861pub struct CategoricalDriftLabelingSchemaConfig {
7862 #[serde(default = "default_true_val")]
7864 pub enabled: bool,
7865}
7866
7867impl Default for CategoricalDriftLabelingSchemaConfig {
7868 fn default() -> Self {
7869 Self { enabled: true }
7870 }
7871}
7872
7873#[derive(Debug, Clone, Serialize, Deserialize)]
7875pub struct TemporalDriftLabelingSchemaConfig {
7876 #[serde(default = "default_true_val")]
7878 pub enabled: bool,
7879}
7880
7881impl Default for TemporalDriftLabelingSchemaConfig {
7882 fn default() -> Self {
7883 Self { enabled: true }
7884 }
7885}
7886
7887#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7900pub struct EnhancedAnomalyConfig {
7901 #[serde(default)]
7903 pub enabled: bool,
7904
7905 #[serde(default)]
7907 pub rates: AnomalyRateConfig,
7908
7909 #[serde(default)]
7911 pub multi_stage_schemes: MultiStageSchemeConfig,
7912
7913 #[serde(default)]
7915 pub correlated_injection: CorrelatedInjectionConfig,
7916
7917 #[serde(default)]
7919 pub near_miss: NearMissConfig,
7920
7921 #[serde(default)]
7923 pub difficulty_classification: DifficultyClassificationConfig,
7924
7925 #[serde(default)]
7927 pub context_aware: ContextAwareConfig,
7928
7929 #[serde(default)]
7931 pub labeling: EnhancedLabelingConfig,
7932}
7933
7934#[derive(Debug, Clone, Serialize, Deserialize)]
7936pub struct AnomalyRateConfig {
7937 #[serde(default = "default_total_anomaly_rate")]
7939 pub total_rate: f64,
7940
7941 #[serde(default = "default_fraud_anomaly_rate")]
7943 pub fraud_rate: f64,
7944
7945 #[serde(default = "default_error_anomaly_rate")]
7947 pub error_rate: f64,
7948
7949 #[serde(default = "default_process_anomaly_rate")]
7951 pub process_rate: f64,
7952}
7953
7954fn default_total_anomaly_rate() -> f64 {
7955 0.03
7956}
7957fn default_fraud_anomaly_rate() -> f64 {
7958 0.01
7959}
7960fn default_error_anomaly_rate() -> f64 {
7961 0.015
7962}
7963fn default_process_anomaly_rate() -> f64 {
7964 0.005
7965}
7966
7967impl Default for AnomalyRateConfig {
7968 fn default() -> Self {
7969 Self {
7970 total_rate: default_total_anomaly_rate(),
7971 fraud_rate: default_fraud_anomaly_rate(),
7972 error_rate: default_error_anomaly_rate(),
7973 process_rate: default_process_anomaly_rate(),
7974 }
7975 }
7976}
7977
7978#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7980pub struct MultiStageSchemeConfig {
7981 #[serde(default)]
7983 pub enabled: bool,
7984
7985 #[serde(default)]
7987 pub embezzlement: EmbezzlementSchemeConfig,
7988
7989 #[serde(default)]
7991 pub revenue_manipulation: RevenueManipulationSchemeConfig,
7992
7993 #[serde(default)]
7995 pub kickback: KickbackSchemeConfig,
7996}
7997
7998#[derive(Debug, Clone, Serialize, Deserialize)]
8000pub struct EmbezzlementSchemeConfig {
8001 #[serde(default = "default_embezzlement_probability")]
8003 pub probability: f64,
8004
8005 #[serde(default)]
8007 pub testing_stage: SchemeStageConfig,
8008
8009 #[serde(default)]
8011 pub escalation_stage: SchemeStageConfig,
8012
8013 #[serde(default)]
8015 pub acceleration_stage: SchemeStageConfig,
8016
8017 #[serde(default)]
8019 pub desperation_stage: SchemeStageConfig,
8020}
8021
8022fn default_embezzlement_probability() -> f64 {
8023 0.02
8024}
8025
8026impl Default for EmbezzlementSchemeConfig {
8027 fn default() -> Self {
8028 Self {
8029 probability: default_embezzlement_probability(),
8030 testing_stage: SchemeStageConfig {
8031 duration_months: 2,
8032 amount_min: 100.0,
8033 amount_max: 500.0,
8034 transaction_count_min: 2,
8035 transaction_count_max: 5,
8036 difficulty: "hard".to_string(),
8037 },
8038 escalation_stage: SchemeStageConfig {
8039 duration_months: 6,
8040 amount_min: 500.0,
8041 amount_max: 2000.0,
8042 transaction_count_min: 3,
8043 transaction_count_max: 8,
8044 difficulty: "moderate".to_string(),
8045 },
8046 acceleration_stage: SchemeStageConfig {
8047 duration_months: 3,
8048 amount_min: 2000.0,
8049 amount_max: 10000.0,
8050 transaction_count_min: 5,
8051 transaction_count_max: 12,
8052 difficulty: "easy".to_string(),
8053 },
8054 desperation_stage: SchemeStageConfig {
8055 duration_months: 1,
8056 amount_min: 10000.0,
8057 amount_max: 50000.0,
8058 transaction_count_min: 3,
8059 transaction_count_max: 6,
8060 difficulty: "trivial".to_string(),
8061 },
8062 }
8063 }
8064}
8065
8066#[derive(Debug, Clone, Serialize, Deserialize)]
8068pub struct RevenueManipulationSchemeConfig {
8069 #[serde(default = "default_revenue_manipulation_probability")]
8071 pub probability: f64,
8072
8073 #[serde(default = "default_early_recognition_target")]
8075 pub early_recognition_target: f64,
8076
8077 #[serde(default = "default_expense_deferral_target")]
8079 pub expense_deferral_target: f64,
8080
8081 #[serde(default = "default_reserve_release_target")]
8083 pub reserve_release_target: f64,
8084
8085 #[serde(default = "default_channel_stuffing_target")]
8087 pub channel_stuffing_target: f64,
8088}
8089
8090fn default_revenue_manipulation_probability() -> f64 {
8091 0.01
8092}
8093fn default_early_recognition_target() -> f64 {
8094 0.02
8095}
8096fn default_expense_deferral_target() -> f64 {
8097 0.03
8098}
8099fn default_reserve_release_target() -> f64 {
8100 0.02
8101}
8102fn default_channel_stuffing_target() -> f64 {
8103 0.05
8104}
8105
8106impl Default for RevenueManipulationSchemeConfig {
8107 fn default() -> Self {
8108 Self {
8109 probability: default_revenue_manipulation_probability(),
8110 early_recognition_target: default_early_recognition_target(),
8111 expense_deferral_target: default_expense_deferral_target(),
8112 reserve_release_target: default_reserve_release_target(),
8113 channel_stuffing_target: default_channel_stuffing_target(),
8114 }
8115 }
8116}
8117
8118#[derive(Debug, Clone, Serialize, Deserialize)]
8120pub struct KickbackSchemeConfig {
8121 #[serde(default = "default_kickback_probability")]
8123 pub probability: f64,
8124
8125 #[serde(default = "default_kickback_inflation_min")]
8127 pub inflation_min: f64,
8128
8129 #[serde(default = "default_kickback_inflation_max")]
8131 pub inflation_max: f64,
8132
8133 #[serde(default = "default_kickback_percent")]
8135 pub kickback_percent: f64,
8136
8137 #[serde(default = "default_kickback_setup_months")]
8139 pub setup_months: u32,
8140
8141 #[serde(default = "default_kickback_operation_months")]
8143 pub operation_months: u32,
8144}
8145
8146fn default_kickback_probability() -> f64 {
8147 0.01
8148}
8149fn default_kickback_inflation_min() -> f64 {
8150 0.10
8151}
8152fn default_kickback_inflation_max() -> f64 {
8153 0.25
8154}
8155fn default_kickback_percent() -> f64 {
8156 0.50
8157}
8158fn default_kickback_setup_months() -> u32 {
8159 3
8160}
8161fn default_kickback_operation_months() -> u32 {
8162 12
8163}
8164
8165impl Default for KickbackSchemeConfig {
8166 fn default() -> Self {
8167 Self {
8168 probability: default_kickback_probability(),
8169 inflation_min: default_kickback_inflation_min(),
8170 inflation_max: default_kickback_inflation_max(),
8171 kickback_percent: default_kickback_percent(),
8172 setup_months: default_kickback_setup_months(),
8173 operation_months: default_kickback_operation_months(),
8174 }
8175 }
8176}
8177
8178#[derive(Debug, Clone, Serialize, Deserialize)]
8180pub struct SchemeStageConfig {
8181 pub duration_months: u32,
8183
8184 pub amount_min: f64,
8186
8187 pub amount_max: f64,
8189
8190 pub transaction_count_min: u32,
8192
8193 pub transaction_count_max: u32,
8195
8196 pub difficulty: String,
8198}
8199
8200impl Default for SchemeStageConfig {
8201 fn default() -> Self {
8202 Self {
8203 duration_months: 3,
8204 amount_min: 100.0,
8205 amount_max: 1000.0,
8206 transaction_count_min: 2,
8207 transaction_count_max: 10,
8208 difficulty: "moderate".to_string(),
8209 }
8210 }
8211}
8212
8213#[derive(Debug, Clone, Serialize, Deserialize)]
8215pub struct CorrelatedInjectionConfig {
8216 #[serde(default)]
8218 pub enabled: bool,
8219
8220 #[serde(default = "default_true_val")]
8222 pub fraud_concealment: bool,
8223
8224 #[serde(default = "default_true_val")]
8226 pub error_cascade: bool,
8227
8228 #[serde(default = "default_true_val")]
8230 pub temporal_clustering: bool,
8231
8232 #[serde(default)]
8234 pub temporal_clustering_config: TemporalClusteringConfig,
8235
8236 #[serde(default)]
8238 pub co_occurrence_patterns: Vec<CoOccurrencePatternConfig>,
8239}
8240
8241impl Default for CorrelatedInjectionConfig {
8242 fn default() -> Self {
8243 Self {
8244 enabled: false,
8245 fraud_concealment: true,
8246 error_cascade: true,
8247 temporal_clustering: true,
8248 temporal_clustering_config: TemporalClusteringConfig::default(),
8249 co_occurrence_patterns: Vec::new(),
8250 }
8251 }
8252}
8253
8254#[derive(Debug, Clone, Serialize, Deserialize)]
8256pub struct TemporalClusteringConfig {
8257 #[serde(default = "default_period_end_multiplier")]
8259 pub period_end_multiplier: f64,
8260
8261 #[serde(default = "default_period_end_days")]
8263 pub period_end_days: u32,
8264
8265 #[serde(default = "default_quarter_end_multiplier")]
8267 pub quarter_end_multiplier: f64,
8268
8269 #[serde(default = "default_year_end_multiplier")]
8271 pub year_end_multiplier: f64,
8272}
8273
8274fn default_period_end_multiplier() -> f64 {
8275 2.5
8276}
8277fn default_period_end_days() -> u32 {
8278 5
8279}
8280fn default_quarter_end_multiplier() -> f64 {
8281 1.5
8282}
8283fn default_year_end_multiplier() -> f64 {
8284 2.0
8285}
8286
8287impl Default for TemporalClusteringConfig {
8288 fn default() -> Self {
8289 Self {
8290 period_end_multiplier: default_period_end_multiplier(),
8291 period_end_days: default_period_end_days(),
8292 quarter_end_multiplier: default_quarter_end_multiplier(),
8293 year_end_multiplier: default_year_end_multiplier(),
8294 }
8295 }
8296}
8297
8298#[derive(Debug, Clone, Serialize, Deserialize)]
8300pub struct CoOccurrencePatternConfig {
8301 pub name: String,
8303
8304 pub primary_type: String,
8306
8307 pub correlated: Vec<CorrelatedAnomalyConfig>,
8309}
8310
8311#[derive(Debug, Clone, Serialize, Deserialize)]
8313pub struct CorrelatedAnomalyConfig {
8314 pub anomaly_type: String,
8316
8317 pub probability: f64,
8319
8320 pub lag_days_min: i32,
8322
8323 pub lag_days_max: i32,
8325}
8326
8327#[derive(Debug, Clone, Serialize, Deserialize)]
8329pub struct NearMissConfig {
8330 #[serde(default)]
8332 pub enabled: bool,
8333
8334 #[serde(default = "default_near_miss_proportion")]
8336 pub proportion: f64,
8337
8338 #[serde(default = "default_true_val")]
8340 pub near_duplicate: bool,
8341
8342 #[serde(default)]
8344 pub near_duplicate_days: NearDuplicateDaysConfig,
8345
8346 #[serde(default = "default_true_val")]
8348 pub threshold_proximity: bool,
8349
8350 #[serde(default)]
8352 pub threshold_proximity_range: ThresholdProximityRangeConfig,
8353
8354 #[serde(default = "default_true_val")]
8356 pub unusual_legitimate: bool,
8357
8358 #[serde(default = "default_unusual_legitimate_types")]
8360 pub unusual_legitimate_types: Vec<String>,
8361
8362 #[serde(default = "default_true_val")]
8364 pub corrected_errors: bool,
8365
8366 #[serde(default)]
8368 pub corrected_error_lag: CorrectedErrorLagConfig,
8369}
8370
8371fn default_near_miss_proportion() -> f64 {
8372 0.30
8373}
8374
8375fn default_unusual_legitimate_types() -> Vec<String> {
8376 vec![
8377 "year_end_bonus".to_string(),
8378 "contract_prepayment".to_string(),
8379 "insurance_claim".to_string(),
8380 "settlement_payment".to_string(),
8381 ]
8382}
8383
8384impl Default for NearMissConfig {
8385 fn default() -> Self {
8386 Self {
8387 enabled: false,
8388 proportion: default_near_miss_proportion(),
8389 near_duplicate: true,
8390 near_duplicate_days: NearDuplicateDaysConfig::default(),
8391 threshold_proximity: true,
8392 threshold_proximity_range: ThresholdProximityRangeConfig::default(),
8393 unusual_legitimate: true,
8394 unusual_legitimate_types: default_unusual_legitimate_types(),
8395 corrected_errors: true,
8396 corrected_error_lag: CorrectedErrorLagConfig::default(),
8397 }
8398 }
8399}
8400
8401#[derive(Debug, Clone, Serialize, Deserialize)]
8403pub struct NearDuplicateDaysConfig {
8404 #[serde(default = "default_near_duplicate_min")]
8406 pub min: u32,
8407
8408 #[serde(default = "default_near_duplicate_max")]
8410 pub max: u32,
8411}
8412
8413fn default_near_duplicate_min() -> u32 {
8414 1
8415}
8416fn default_near_duplicate_max() -> u32 {
8417 3
8418}
8419
8420impl Default for NearDuplicateDaysConfig {
8421 fn default() -> Self {
8422 Self {
8423 min: default_near_duplicate_min(),
8424 max: default_near_duplicate_max(),
8425 }
8426 }
8427}
8428
8429#[derive(Debug, Clone, Serialize, Deserialize)]
8431pub struct ThresholdProximityRangeConfig {
8432 #[serde(default = "default_threshold_proximity_min")]
8434 pub min: f64,
8435
8436 #[serde(default = "default_threshold_proximity_max")]
8438 pub max: f64,
8439}
8440
8441fn default_threshold_proximity_min() -> f64 {
8442 0.90
8443}
8444fn default_threshold_proximity_max() -> f64 {
8445 0.99
8446}
8447
8448impl Default for ThresholdProximityRangeConfig {
8449 fn default() -> Self {
8450 Self {
8451 min: default_threshold_proximity_min(),
8452 max: default_threshold_proximity_max(),
8453 }
8454 }
8455}
8456
8457#[derive(Debug, Clone, Serialize, Deserialize)]
8459pub struct CorrectedErrorLagConfig {
8460 #[serde(default = "default_corrected_error_lag_min")]
8462 pub min: u32,
8463
8464 #[serde(default = "default_corrected_error_lag_max")]
8466 pub max: u32,
8467}
8468
8469fn default_corrected_error_lag_min() -> u32 {
8470 1
8471}
8472fn default_corrected_error_lag_max() -> u32 {
8473 5
8474}
8475
8476impl Default for CorrectedErrorLagConfig {
8477 fn default() -> Self {
8478 Self {
8479 min: default_corrected_error_lag_min(),
8480 max: default_corrected_error_lag_max(),
8481 }
8482 }
8483}
8484
8485#[derive(Debug, Clone, Serialize, Deserialize)]
8487pub struct DifficultyClassificationConfig {
8488 #[serde(default)]
8490 pub enabled: bool,
8491
8492 #[serde(default)]
8494 pub target_distribution: DifficultyDistributionConfig,
8495}
8496
8497impl Default for DifficultyClassificationConfig {
8498 fn default() -> Self {
8499 Self {
8500 enabled: true,
8501 target_distribution: DifficultyDistributionConfig::default(),
8502 }
8503 }
8504}
8505
8506#[derive(Debug, Clone, Serialize, Deserialize)]
8508pub struct DifficultyDistributionConfig {
8509 #[serde(default = "default_difficulty_trivial")]
8511 pub trivial: f64,
8512
8513 #[serde(default = "default_difficulty_easy")]
8515 pub easy: f64,
8516
8517 #[serde(default = "default_difficulty_moderate")]
8519 pub moderate: f64,
8520
8521 #[serde(default = "default_difficulty_hard")]
8523 pub hard: f64,
8524
8525 #[serde(default = "default_difficulty_expert")]
8527 pub expert: f64,
8528}
8529
8530fn default_difficulty_trivial() -> f64 {
8531 0.15
8532}
8533fn default_difficulty_easy() -> f64 {
8534 0.25
8535}
8536fn default_difficulty_moderate() -> f64 {
8537 0.30
8538}
8539fn default_difficulty_hard() -> f64 {
8540 0.20
8541}
8542fn default_difficulty_expert() -> f64 {
8543 0.10
8544}
8545
8546impl Default for DifficultyDistributionConfig {
8547 fn default() -> Self {
8548 Self {
8549 trivial: default_difficulty_trivial(),
8550 easy: default_difficulty_easy(),
8551 moderate: default_difficulty_moderate(),
8552 hard: default_difficulty_hard(),
8553 expert: default_difficulty_expert(),
8554 }
8555 }
8556}
8557
8558#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8560pub struct ContextAwareConfig {
8561 #[serde(default)]
8563 pub enabled: bool,
8564
8565 #[serde(default)]
8567 pub vendor_rules: VendorAnomalyRulesConfig,
8568
8569 #[serde(default)]
8571 pub employee_rules: EmployeeAnomalyRulesConfig,
8572
8573 #[serde(default)]
8575 pub account_rules: AccountAnomalyRulesConfig,
8576
8577 #[serde(default)]
8579 pub behavioral_baseline: BehavioralBaselineConfig,
8580}
8581
8582#[derive(Debug, Clone, Serialize, Deserialize)]
8584pub struct VendorAnomalyRulesConfig {
8585 #[serde(default = "default_new_vendor_multiplier")]
8587 pub new_vendor_error_multiplier: f64,
8588
8589 #[serde(default = "default_new_vendor_threshold")]
8591 pub new_vendor_threshold_days: u32,
8592
8593 #[serde(default = "default_international_multiplier")]
8595 pub international_error_multiplier: f64,
8596
8597 #[serde(default = "default_strategic_vendor_types")]
8599 pub strategic_vendor_anomaly_types: Vec<String>,
8600}
8601
8602fn default_new_vendor_multiplier() -> f64 {
8603 2.5
8604}
8605fn default_new_vendor_threshold() -> u32 {
8606 90
8607}
8608fn default_international_multiplier() -> f64 {
8609 1.5
8610}
8611fn default_strategic_vendor_types() -> Vec<String> {
8612 vec![
8613 "pricing_dispute".to_string(),
8614 "contract_violation".to_string(),
8615 ]
8616}
8617
8618impl Default for VendorAnomalyRulesConfig {
8619 fn default() -> Self {
8620 Self {
8621 new_vendor_error_multiplier: default_new_vendor_multiplier(),
8622 new_vendor_threshold_days: default_new_vendor_threshold(),
8623 international_error_multiplier: default_international_multiplier(),
8624 strategic_vendor_anomaly_types: default_strategic_vendor_types(),
8625 }
8626 }
8627}
8628
8629#[derive(Debug, Clone, Serialize, Deserialize)]
8631pub struct EmployeeAnomalyRulesConfig {
8632 #[serde(default = "default_new_employee_rate")]
8634 pub new_employee_error_rate: f64,
8635
8636 #[serde(default = "default_new_employee_threshold")]
8638 pub new_employee_threshold_days: u32,
8639
8640 #[serde(default = "default_volume_fatigue_threshold")]
8642 pub volume_fatigue_threshold: u32,
8643
8644 #[serde(default = "default_coverage_multiplier")]
8646 pub coverage_error_multiplier: f64,
8647}
8648
8649fn default_new_employee_rate() -> f64 {
8650 0.05
8651}
8652fn default_new_employee_threshold() -> u32 {
8653 180
8654}
8655fn default_volume_fatigue_threshold() -> u32 {
8656 50
8657}
8658fn default_coverage_multiplier() -> f64 {
8659 1.8
8660}
8661
8662impl Default for EmployeeAnomalyRulesConfig {
8663 fn default() -> Self {
8664 Self {
8665 new_employee_error_rate: default_new_employee_rate(),
8666 new_employee_threshold_days: default_new_employee_threshold(),
8667 volume_fatigue_threshold: default_volume_fatigue_threshold(),
8668 coverage_error_multiplier: default_coverage_multiplier(),
8669 }
8670 }
8671}
8672
8673#[derive(Debug, Clone, Serialize, Deserialize)]
8675pub struct AccountAnomalyRulesConfig {
8676 #[serde(default = "default_high_risk_multiplier")]
8678 pub high_risk_account_multiplier: f64,
8679
8680 #[serde(default = "default_high_risk_accounts")]
8682 pub high_risk_accounts: Vec<String>,
8683
8684 #[serde(default = "default_suspense_multiplier")]
8686 pub suspense_account_multiplier: f64,
8687
8688 #[serde(default = "default_suspense_accounts")]
8690 pub suspense_accounts: Vec<String>,
8691
8692 #[serde(default = "default_intercompany_multiplier")]
8694 pub intercompany_account_multiplier: f64,
8695}
8696
8697fn default_high_risk_multiplier() -> f64 {
8698 2.0
8699}
8700fn default_high_risk_accounts() -> Vec<String> {
8701 vec![
8702 "1100".to_string(), "2000".to_string(), "3000".to_string(), ]
8706}
8707fn default_suspense_multiplier() -> f64 {
8708 3.0
8709}
8710fn default_suspense_accounts() -> Vec<String> {
8711 vec!["9999".to_string(), "9998".to_string()]
8712}
8713fn default_intercompany_multiplier() -> f64 {
8714 1.5
8715}
8716
8717impl Default for AccountAnomalyRulesConfig {
8718 fn default() -> Self {
8719 Self {
8720 high_risk_account_multiplier: default_high_risk_multiplier(),
8721 high_risk_accounts: default_high_risk_accounts(),
8722 suspense_account_multiplier: default_suspense_multiplier(),
8723 suspense_accounts: default_suspense_accounts(),
8724 intercompany_account_multiplier: default_intercompany_multiplier(),
8725 }
8726 }
8727}
8728
8729#[derive(Debug, Clone, Serialize, Deserialize)]
8731pub struct BehavioralBaselineConfig {
8732 #[serde(default)]
8734 pub enabled: bool,
8735
8736 #[serde(default = "default_baseline_period")]
8738 pub baseline_period_days: u32,
8739
8740 #[serde(default = "default_deviation_threshold")]
8742 pub deviation_threshold_std: f64,
8743
8744 #[serde(default = "default_frequency_deviation")]
8746 pub frequency_deviation_threshold: f64,
8747}
8748
8749fn default_baseline_period() -> u32 {
8750 90
8751}
8752fn default_deviation_threshold() -> f64 {
8753 3.0
8754}
8755fn default_frequency_deviation() -> f64 {
8756 2.0
8757}
8758
8759impl Default for BehavioralBaselineConfig {
8760 fn default() -> Self {
8761 Self {
8762 enabled: false,
8763 baseline_period_days: default_baseline_period(),
8764 deviation_threshold_std: default_deviation_threshold(),
8765 frequency_deviation_threshold: default_frequency_deviation(),
8766 }
8767 }
8768}
8769
8770#[derive(Debug, Clone, Serialize, Deserialize)]
8772pub struct EnhancedLabelingConfig {
8773 #[serde(default = "default_true_val")]
8775 pub severity_scoring: bool,
8776
8777 #[serde(default = "default_true_val")]
8779 pub difficulty_classification: bool,
8780
8781 #[serde(default)]
8783 pub materiality_thresholds: MaterialityThresholdsConfig,
8784}
8785
8786impl Default for EnhancedLabelingConfig {
8787 fn default() -> Self {
8788 Self {
8789 severity_scoring: true,
8790 difficulty_classification: true,
8791 materiality_thresholds: MaterialityThresholdsConfig::default(),
8792 }
8793 }
8794}
8795
8796#[derive(Debug, Clone, Serialize, Deserialize)]
8798pub struct MaterialityThresholdsConfig {
8799 #[serde(default = "default_materiality_trivial")]
8801 pub trivial: f64,
8802
8803 #[serde(default = "default_materiality_immaterial")]
8805 pub immaterial: f64,
8806
8807 #[serde(default = "default_materiality_material")]
8809 pub material: f64,
8810
8811 #[serde(default = "default_materiality_highly_material")]
8813 pub highly_material: f64,
8814}
8815
8816fn default_materiality_trivial() -> f64 {
8817 0.001
8818}
8819fn default_materiality_immaterial() -> f64 {
8820 0.01
8821}
8822fn default_materiality_material() -> f64 {
8823 0.05
8824}
8825fn default_materiality_highly_material() -> f64 {
8826 0.10
8827}
8828
8829impl Default for MaterialityThresholdsConfig {
8830 fn default() -> Self {
8831 Self {
8832 trivial: default_materiality_trivial(),
8833 immaterial: default_materiality_immaterial(),
8834 material: default_materiality_material(),
8835 highly_material: default_materiality_highly_material(),
8836 }
8837 }
8838}
8839
8840#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8852pub struct IndustrySpecificConfig {
8853 #[serde(default)]
8855 pub enabled: bool,
8856
8857 #[serde(default)]
8859 pub manufacturing: ManufacturingConfig,
8860
8861 #[serde(default)]
8863 pub retail: RetailConfig,
8864
8865 #[serde(default)]
8867 pub healthcare: HealthcareConfig,
8868
8869 #[serde(default)]
8871 pub technology: TechnologyConfig,
8872
8873 #[serde(default)]
8875 pub financial_services: FinancialServicesConfig,
8876
8877 #[serde(default)]
8879 pub professional_services: ProfessionalServicesConfig,
8880}
8881
8882#[derive(Debug, Clone, Serialize, Deserialize)]
8884pub struct ManufacturingConfig {
8885 #[serde(default)]
8887 pub enabled: bool,
8888
8889 #[serde(default = "default_bom_depth")]
8891 pub bom_depth: u32,
8892
8893 #[serde(default)]
8895 pub just_in_time: bool,
8896
8897 #[serde(default = "default_production_order_types")]
8899 pub production_order_types: Vec<String>,
8900
8901 #[serde(default)]
8903 pub quality_framework: Option<String>,
8904
8905 #[serde(default = "default_supplier_tiers")]
8907 pub supplier_tiers: u32,
8908
8909 #[serde(default = "default_cost_frequency")]
8911 pub standard_cost_frequency: String,
8912
8913 #[serde(default = "default_yield_rate")]
8915 pub target_yield_rate: f64,
8916
8917 #[serde(default = "default_scrap_threshold")]
8919 pub scrap_alert_threshold: f64,
8920
8921 #[serde(default)]
8923 pub anomaly_rates: ManufacturingAnomalyRates,
8924}
8925
8926fn default_bom_depth() -> u32 {
8927 4
8928}
8929
8930fn default_production_order_types() -> Vec<String> {
8931 vec![
8932 "standard".to_string(),
8933 "rework".to_string(),
8934 "prototype".to_string(),
8935 ]
8936}
8937
8938fn default_supplier_tiers() -> u32 {
8939 2
8940}
8941
8942fn default_cost_frequency() -> String {
8943 "quarterly".to_string()
8944}
8945
8946fn default_yield_rate() -> f64 {
8947 0.97
8948}
8949
8950fn default_scrap_threshold() -> f64 {
8951 0.03
8952}
8953
8954impl Default for ManufacturingConfig {
8955 fn default() -> Self {
8956 Self {
8957 enabled: false,
8958 bom_depth: default_bom_depth(),
8959 just_in_time: false,
8960 production_order_types: default_production_order_types(),
8961 quality_framework: Some("ISO_9001".to_string()),
8962 supplier_tiers: default_supplier_tiers(),
8963 standard_cost_frequency: default_cost_frequency(),
8964 target_yield_rate: default_yield_rate(),
8965 scrap_alert_threshold: default_scrap_threshold(),
8966 anomaly_rates: ManufacturingAnomalyRates::default(),
8967 }
8968 }
8969}
8970
8971#[derive(Debug, Clone, Serialize, Deserialize)]
8973pub struct ManufacturingAnomalyRates {
8974 #[serde(default = "default_mfg_yield_rate")]
8976 pub yield_manipulation: f64,
8977
8978 #[serde(default = "default_mfg_labor_rate")]
8980 pub labor_misallocation: f64,
8981
8982 #[serde(default = "default_mfg_phantom_rate")]
8984 pub phantom_production: f64,
8985
8986 #[serde(default = "default_mfg_cost_rate")]
8988 pub standard_cost_manipulation: f64,
8989
8990 #[serde(default = "default_mfg_inventory_rate")]
8992 pub inventory_fraud: f64,
8993}
8994
8995fn default_mfg_yield_rate() -> f64 {
8996 0.015
8997}
8998
8999fn default_mfg_labor_rate() -> f64 {
9000 0.02
9001}
9002
9003fn default_mfg_phantom_rate() -> f64 {
9004 0.005
9005}
9006
9007fn default_mfg_cost_rate() -> f64 {
9008 0.01
9009}
9010
9011fn default_mfg_inventory_rate() -> f64 {
9012 0.008
9013}
9014
9015impl Default for ManufacturingAnomalyRates {
9016 fn default() -> Self {
9017 Self {
9018 yield_manipulation: default_mfg_yield_rate(),
9019 labor_misallocation: default_mfg_labor_rate(),
9020 phantom_production: default_mfg_phantom_rate(),
9021 standard_cost_manipulation: default_mfg_cost_rate(),
9022 inventory_fraud: default_mfg_inventory_rate(),
9023 }
9024 }
9025}
9026
9027#[derive(Debug, Clone, Serialize, Deserialize)]
9029pub struct RetailConfig {
9030 #[serde(default)]
9032 pub enabled: bool,
9033
9034 #[serde(default)]
9036 pub store_types: RetailStoreTypeConfig,
9037
9038 #[serde(default = "default_retail_daily_txns")]
9040 pub avg_daily_transactions: u32,
9041
9042 #[serde(default = "default_true")]
9044 pub loss_prevention: bool,
9045
9046 #[serde(default = "default_shrinkage_rate")]
9048 pub shrinkage_rate: f64,
9049
9050 #[serde(default)]
9052 pub anomaly_rates: RetailAnomalyRates,
9053}
9054
9055fn default_retail_daily_txns() -> u32 {
9056 500
9057}
9058
9059fn default_shrinkage_rate() -> f64 {
9060 0.015
9061}
9062
9063impl Default for RetailConfig {
9064 fn default() -> Self {
9065 Self {
9066 enabled: false,
9067 store_types: RetailStoreTypeConfig::default(),
9068 avg_daily_transactions: default_retail_daily_txns(),
9069 loss_prevention: true,
9070 shrinkage_rate: default_shrinkage_rate(),
9071 anomaly_rates: RetailAnomalyRates::default(),
9072 }
9073 }
9074}
9075
9076#[derive(Debug, Clone, Serialize, Deserialize)]
9078pub struct RetailStoreTypeConfig {
9079 #[serde(default = "default_flagship_pct")]
9081 pub flagship: f64,
9082
9083 #[serde(default = "default_regional_pct")]
9085 pub regional: f64,
9086
9087 #[serde(default = "default_outlet_pct")]
9089 pub outlet: f64,
9090
9091 #[serde(default = "default_ecommerce_pct")]
9093 pub ecommerce: f64,
9094}
9095
9096fn default_flagship_pct() -> f64 {
9097 0.10
9098}
9099
9100fn default_regional_pct() -> f64 {
9101 0.50
9102}
9103
9104fn default_outlet_pct() -> f64 {
9105 0.25
9106}
9107
9108fn default_ecommerce_pct() -> f64 {
9109 0.15
9110}
9111
9112impl Default for RetailStoreTypeConfig {
9113 fn default() -> Self {
9114 Self {
9115 flagship: default_flagship_pct(),
9116 regional: default_regional_pct(),
9117 outlet: default_outlet_pct(),
9118 ecommerce: default_ecommerce_pct(),
9119 }
9120 }
9121}
9122
9123#[derive(Debug, Clone, Serialize, Deserialize)]
9125pub struct RetailAnomalyRates {
9126 #[serde(default = "default_sweethearting_rate")]
9128 pub sweethearting: f64,
9129
9130 #[serde(default = "default_skimming_rate")]
9132 pub skimming: f64,
9133
9134 #[serde(default = "default_refund_fraud_rate")]
9136 pub refund_fraud: f64,
9137
9138 #[serde(default = "default_void_abuse_rate")]
9140 pub void_abuse: f64,
9141
9142 #[serde(default = "default_gift_card_rate")]
9144 pub gift_card_fraud: f64,
9145
9146 #[serde(default = "default_retail_kickback_rate")]
9148 pub vendor_kickback: f64,
9149}
9150
9151fn default_sweethearting_rate() -> f64 {
9152 0.02
9153}
9154
9155fn default_skimming_rate() -> f64 {
9156 0.005
9157}
9158
9159fn default_refund_fraud_rate() -> f64 {
9160 0.015
9161}
9162
9163fn default_void_abuse_rate() -> f64 {
9164 0.01
9165}
9166
9167fn default_gift_card_rate() -> f64 {
9168 0.008
9169}
9170
9171fn default_retail_kickback_rate() -> f64 {
9172 0.003
9173}
9174
9175impl Default for RetailAnomalyRates {
9176 fn default() -> Self {
9177 Self {
9178 sweethearting: default_sweethearting_rate(),
9179 skimming: default_skimming_rate(),
9180 refund_fraud: default_refund_fraud_rate(),
9181 void_abuse: default_void_abuse_rate(),
9182 gift_card_fraud: default_gift_card_rate(),
9183 vendor_kickback: default_retail_kickback_rate(),
9184 }
9185 }
9186}
9187
9188#[derive(Debug, Clone, Serialize, Deserialize)]
9190pub struct HealthcareConfig {
9191 #[serde(default)]
9193 pub enabled: bool,
9194
9195 #[serde(default = "default_facility_type")]
9197 pub facility_type: String,
9198
9199 #[serde(default)]
9201 pub payer_mix: HealthcarePayerMix,
9202
9203 #[serde(default)]
9205 pub coding_systems: HealthcareCodingSystems,
9206
9207 #[serde(default)]
9209 pub compliance: HealthcareComplianceConfig,
9210
9211 #[serde(default = "default_daily_encounters")]
9213 pub avg_daily_encounters: u32,
9214
9215 #[serde(default = "default_charges_per_encounter")]
9217 pub avg_charges_per_encounter: u32,
9218
9219 #[serde(default = "default_hc_denial_rate")]
9221 pub denial_rate: f64,
9222
9223 #[serde(default = "default_hc_bad_debt_rate")]
9225 pub bad_debt_rate: f64,
9226
9227 #[serde(default = "default_hc_charity_care_rate")]
9229 pub charity_care_rate: f64,
9230
9231 #[serde(default)]
9233 pub anomaly_rates: HealthcareAnomalyRates,
9234}
9235
9236fn default_facility_type() -> String {
9237 "hospital".to_string()
9238}
9239
9240fn default_daily_encounters() -> u32 {
9241 150
9242}
9243
9244fn default_charges_per_encounter() -> u32 {
9245 8
9246}
9247
9248fn default_hc_denial_rate() -> f64 {
9249 0.05
9250}
9251
9252fn default_hc_bad_debt_rate() -> f64 {
9253 0.03
9254}
9255
9256fn default_hc_charity_care_rate() -> f64 {
9257 0.02
9258}
9259
9260impl Default for HealthcareConfig {
9261 fn default() -> Self {
9262 Self {
9263 enabled: false,
9264 facility_type: default_facility_type(),
9265 payer_mix: HealthcarePayerMix::default(),
9266 coding_systems: HealthcareCodingSystems::default(),
9267 compliance: HealthcareComplianceConfig::default(),
9268 avg_daily_encounters: default_daily_encounters(),
9269 avg_charges_per_encounter: default_charges_per_encounter(),
9270 denial_rate: default_hc_denial_rate(),
9271 bad_debt_rate: default_hc_bad_debt_rate(),
9272 charity_care_rate: default_hc_charity_care_rate(),
9273 anomaly_rates: HealthcareAnomalyRates::default(),
9274 }
9275 }
9276}
9277
9278#[derive(Debug, Clone, Serialize, Deserialize)]
9280pub struct HealthcarePayerMix {
9281 #[serde(default = "default_medicare_pct")]
9283 pub medicare: f64,
9284
9285 #[serde(default = "default_medicaid_pct")]
9287 pub medicaid: f64,
9288
9289 #[serde(default = "default_commercial_pct")]
9291 pub commercial: f64,
9292
9293 #[serde(default = "default_self_pay_pct")]
9295 pub self_pay: f64,
9296}
9297
9298fn default_medicare_pct() -> f64 {
9299 0.40
9300}
9301
9302fn default_medicaid_pct() -> f64 {
9303 0.20
9304}
9305
9306fn default_commercial_pct() -> f64 {
9307 0.30
9308}
9309
9310fn default_self_pay_pct() -> f64 {
9311 0.10
9312}
9313
9314impl Default for HealthcarePayerMix {
9315 fn default() -> Self {
9316 Self {
9317 medicare: default_medicare_pct(),
9318 medicaid: default_medicaid_pct(),
9319 commercial: default_commercial_pct(),
9320 self_pay: default_self_pay_pct(),
9321 }
9322 }
9323}
9324
9325#[derive(Debug, Clone, Serialize, Deserialize)]
9327pub struct HealthcareCodingSystems {
9328 #[serde(default = "default_true")]
9330 pub icd10: bool,
9331
9332 #[serde(default = "default_true")]
9334 pub cpt: bool,
9335
9336 #[serde(default = "default_true")]
9338 pub drg: bool,
9339
9340 #[serde(default = "default_true")]
9342 pub hcpcs: bool,
9343
9344 #[serde(default = "default_true")]
9346 pub revenue_codes: bool,
9347}
9348
9349impl Default for HealthcareCodingSystems {
9350 fn default() -> Self {
9351 Self {
9352 icd10: true,
9353 cpt: true,
9354 drg: true,
9355 hcpcs: true,
9356 revenue_codes: true,
9357 }
9358 }
9359}
9360
9361#[derive(Debug, Clone, Serialize, Deserialize)]
9363pub struct HealthcareComplianceConfig {
9364 #[serde(default = "default_true")]
9366 pub hipaa: bool,
9367
9368 #[serde(default = "default_true")]
9370 pub stark_law: bool,
9371
9372 #[serde(default = "default_true")]
9374 pub anti_kickback: bool,
9375
9376 #[serde(default = "default_true")]
9378 pub false_claims_act: bool,
9379
9380 #[serde(default = "default_true")]
9382 pub emtala: bool,
9383}
9384
9385impl Default for HealthcareComplianceConfig {
9386 fn default() -> Self {
9387 Self {
9388 hipaa: true,
9389 stark_law: true,
9390 anti_kickback: true,
9391 false_claims_act: true,
9392 emtala: true,
9393 }
9394 }
9395}
9396
9397#[derive(Debug, Clone, Serialize, Deserialize)]
9399pub struct HealthcareAnomalyRates {
9400 #[serde(default = "default_upcoding_rate")]
9402 pub upcoding: f64,
9403
9404 #[serde(default = "default_unbundling_rate")]
9406 pub unbundling: f64,
9407
9408 #[serde(default = "default_phantom_billing_rate")]
9410 pub phantom_billing: f64,
9411
9412 #[serde(default = "default_healthcare_kickback_rate")]
9414 pub kickbacks: f64,
9415
9416 #[serde(default = "default_duplicate_billing_rate")]
9418 pub duplicate_billing: f64,
9419
9420 #[serde(default = "default_med_necessity_rate")]
9422 pub medical_necessity_abuse: f64,
9423}
9424
9425fn default_upcoding_rate() -> f64 {
9426 0.02
9427}
9428
9429fn default_unbundling_rate() -> f64 {
9430 0.015
9431}
9432
9433fn default_phantom_billing_rate() -> f64 {
9434 0.005
9435}
9436
9437fn default_healthcare_kickback_rate() -> f64 {
9438 0.003
9439}
9440
9441fn default_duplicate_billing_rate() -> f64 {
9442 0.008
9443}
9444
9445fn default_med_necessity_rate() -> f64 {
9446 0.01
9447}
9448
9449impl Default for HealthcareAnomalyRates {
9450 fn default() -> Self {
9451 Self {
9452 upcoding: default_upcoding_rate(),
9453 unbundling: default_unbundling_rate(),
9454 phantom_billing: default_phantom_billing_rate(),
9455 kickbacks: default_healthcare_kickback_rate(),
9456 duplicate_billing: default_duplicate_billing_rate(),
9457 medical_necessity_abuse: default_med_necessity_rate(),
9458 }
9459 }
9460}
9461
9462#[derive(Debug, Clone, Serialize, Deserialize)]
9464pub struct TechnologyConfig {
9465 #[serde(default)]
9467 pub enabled: bool,
9468
9469 #[serde(default = "default_revenue_model")]
9471 pub revenue_model: String,
9472
9473 #[serde(default = "default_subscription_pct")]
9475 pub subscription_revenue_pct: f64,
9476
9477 #[serde(default = "default_license_pct")]
9479 pub license_revenue_pct: f64,
9480
9481 #[serde(default = "default_services_pct")]
9483 pub services_revenue_pct: f64,
9484
9485 #[serde(default)]
9487 pub rd_capitalization: RdCapitalizationConfig,
9488
9489 #[serde(default)]
9491 pub anomaly_rates: TechnologyAnomalyRates,
9492}
9493
9494fn default_revenue_model() -> String {
9495 "saas".to_string()
9496}
9497
9498fn default_subscription_pct() -> f64 {
9499 0.60
9500}
9501
9502fn default_license_pct() -> f64 {
9503 0.25
9504}
9505
9506fn default_services_pct() -> f64 {
9507 0.15
9508}
9509
9510impl Default for TechnologyConfig {
9511 fn default() -> Self {
9512 Self {
9513 enabled: false,
9514 revenue_model: default_revenue_model(),
9515 subscription_revenue_pct: default_subscription_pct(),
9516 license_revenue_pct: default_license_pct(),
9517 services_revenue_pct: default_services_pct(),
9518 rd_capitalization: RdCapitalizationConfig::default(),
9519 anomaly_rates: TechnologyAnomalyRates::default(),
9520 }
9521 }
9522}
9523
9524#[derive(Debug, Clone, Serialize, Deserialize)]
9526pub struct RdCapitalizationConfig {
9527 #[serde(default = "default_true")]
9529 pub enabled: bool,
9530
9531 #[serde(default = "default_cap_rate")]
9533 pub capitalization_rate: f64,
9534
9535 #[serde(default = "default_useful_life")]
9537 pub useful_life_years: u32,
9538}
9539
9540fn default_cap_rate() -> f64 {
9541 0.30
9542}
9543
9544fn default_useful_life() -> u32 {
9545 3
9546}
9547
9548impl Default for RdCapitalizationConfig {
9549 fn default() -> Self {
9550 Self {
9551 enabled: true,
9552 capitalization_rate: default_cap_rate(),
9553 useful_life_years: default_useful_life(),
9554 }
9555 }
9556}
9557
9558#[derive(Debug, Clone, Serialize, Deserialize)]
9560pub struct TechnologyAnomalyRates {
9561 #[serde(default = "default_premature_rev_rate")]
9563 pub premature_revenue: f64,
9564
9565 #[serde(default = "default_side_letter_rate")]
9567 pub side_letter_abuse: f64,
9568
9569 #[serde(default = "default_channel_stuffing_rate")]
9571 pub channel_stuffing: f64,
9572
9573 #[serde(default = "default_improper_cap_rate")]
9575 pub improper_capitalization: f64,
9576}
9577
9578fn default_premature_rev_rate() -> f64 {
9579 0.015
9580}
9581
9582fn default_side_letter_rate() -> f64 {
9583 0.008
9584}
9585
9586fn default_channel_stuffing_rate() -> f64 {
9587 0.01
9588}
9589
9590fn default_improper_cap_rate() -> f64 {
9591 0.012
9592}
9593
9594impl Default for TechnologyAnomalyRates {
9595 fn default() -> Self {
9596 Self {
9597 premature_revenue: default_premature_rev_rate(),
9598 side_letter_abuse: default_side_letter_rate(),
9599 channel_stuffing: default_channel_stuffing_rate(),
9600 improper_capitalization: default_improper_cap_rate(),
9601 }
9602 }
9603}
9604
9605#[derive(Debug, Clone, Serialize, Deserialize)]
9607pub struct FinancialServicesConfig {
9608 #[serde(default)]
9610 pub enabled: bool,
9611
9612 #[serde(default = "default_fi_type")]
9614 pub institution_type: String,
9615
9616 #[serde(default = "default_fi_regulatory")]
9618 pub regulatory_framework: String,
9619
9620 #[serde(default)]
9622 pub anomaly_rates: FinancialServicesAnomalyRates,
9623}
9624
9625fn default_fi_type() -> String {
9626 "commercial_bank".to_string()
9627}
9628
9629fn default_fi_regulatory() -> String {
9630 "us_banking".to_string()
9631}
9632
9633impl Default for FinancialServicesConfig {
9634 fn default() -> Self {
9635 Self {
9636 enabled: false,
9637 institution_type: default_fi_type(),
9638 regulatory_framework: default_fi_regulatory(),
9639 anomaly_rates: FinancialServicesAnomalyRates::default(),
9640 }
9641 }
9642}
9643
9644#[derive(Debug, Clone, Serialize, Deserialize)]
9646pub struct FinancialServicesAnomalyRates {
9647 #[serde(default = "default_loan_fraud_rate")]
9649 pub loan_fraud: f64,
9650
9651 #[serde(default = "default_trading_fraud_rate")]
9653 pub trading_fraud: f64,
9654
9655 #[serde(default = "default_insurance_fraud_rate")]
9657 pub insurance_fraud: f64,
9658
9659 #[serde(default = "default_account_manip_rate")]
9661 pub account_manipulation: f64,
9662}
9663
9664fn default_loan_fraud_rate() -> f64 {
9665 0.01
9666}
9667
9668fn default_trading_fraud_rate() -> f64 {
9669 0.008
9670}
9671
9672fn default_insurance_fraud_rate() -> f64 {
9673 0.012
9674}
9675
9676fn default_account_manip_rate() -> f64 {
9677 0.005
9678}
9679
9680impl Default for FinancialServicesAnomalyRates {
9681 fn default() -> Self {
9682 Self {
9683 loan_fraud: default_loan_fraud_rate(),
9684 trading_fraud: default_trading_fraud_rate(),
9685 insurance_fraud: default_insurance_fraud_rate(),
9686 account_manipulation: default_account_manip_rate(),
9687 }
9688 }
9689}
9690
9691#[derive(Debug, Clone, Serialize, Deserialize)]
9693pub struct ProfessionalServicesConfig {
9694 #[serde(default)]
9696 pub enabled: bool,
9697
9698 #[serde(default = "default_firm_type")]
9700 pub firm_type: String,
9701
9702 #[serde(default = "default_billing_model")]
9704 pub billing_model: String,
9705
9706 #[serde(default = "default_hourly_rate")]
9708 pub avg_hourly_rate: f64,
9709
9710 #[serde(default)]
9712 pub trust_accounting: TrustAccountingConfig,
9713
9714 #[serde(default)]
9716 pub anomaly_rates: ProfessionalServicesAnomalyRates,
9717}
9718
9719fn default_firm_type() -> String {
9720 "consulting".to_string()
9721}
9722
9723fn default_billing_model() -> String {
9724 "time_and_materials".to_string()
9725}
9726
9727fn default_hourly_rate() -> f64 {
9728 250.0
9729}
9730
9731impl Default for ProfessionalServicesConfig {
9732 fn default() -> Self {
9733 Self {
9734 enabled: false,
9735 firm_type: default_firm_type(),
9736 billing_model: default_billing_model(),
9737 avg_hourly_rate: default_hourly_rate(),
9738 trust_accounting: TrustAccountingConfig::default(),
9739 anomaly_rates: ProfessionalServicesAnomalyRates::default(),
9740 }
9741 }
9742}
9743
9744#[derive(Debug, Clone, Serialize, Deserialize)]
9746pub struct TrustAccountingConfig {
9747 #[serde(default)]
9749 pub enabled: bool,
9750
9751 #[serde(default = "default_true")]
9753 pub require_three_way_reconciliation: bool,
9754}
9755
9756impl Default for TrustAccountingConfig {
9757 fn default() -> Self {
9758 Self {
9759 enabled: false,
9760 require_three_way_reconciliation: true,
9761 }
9762 }
9763}
9764
9765#[derive(Debug, Clone, Serialize, Deserialize)]
9767pub struct ProfessionalServicesAnomalyRates {
9768 #[serde(default = "default_time_fraud_rate")]
9770 pub time_billing_fraud: f64,
9771
9772 #[serde(default = "default_expense_fraud_rate")]
9774 pub expense_fraud: f64,
9775
9776 #[serde(default = "default_trust_misappropriation_rate")]
9778 pub trust_misappropriation: f64,
9779}
9780
9781fn default_time_fraud_rate() -> f64 {
9782 0.02
9783}
9784
9785fn default_expense_fraud_rate() -> f64 {
9786 0.015
9787}
9788
9789fn default_trust_misappropriation_rate() -> f64 {
9790 0.003
9791}
9792
9793impl Default for ProfessionalServicesAnomalyRates {
9794 fn default() -> Self {
9795 Self {
9796 time_billing_fraud: default_time_fraud_rate(),
9797 expense_fraud: default_expense_fraud_rate(),
9798 trust_misappropriation: default_trust_misappropriation_rate(),
9799 }
9800 }
9801}
9802
9803#[derive(Debug, Clone, Serialize, Deserialize)]
9817pub struct FingerprintPrivacyConfig {
9818 #[serde(default)]
9820 pub level: String,
9821 #[serde(default = "default_epsilon")]
9823 pub epsilon: f64,
9824 #[serde(default = "default_delta")]
9826 pub delta: f64,
9827 #[serde(default = "default_k_anonymity")]
9829 pub k_anonymity: u32,
9830 #[serde(default)]
9832 pub composition_method: String,
9833}
9834
9835fn default_epsilon() -> f64 {
9836 1.0
9837}
9838
9839fn default_delta() -> f64 {
9840 1e-5
9841}
9842
9843fn default_k_anonymity() -> u32 {
9844 5
9845}
9846
9847impl Default for FingerprintPrivacyConfig {
9848 fn default() -> Self {
9849 Self {
9850 level: "standard".to_string(),
9851 epsilon: default_epsilon(),
9852 delta: default_delta(),
9853 k_anonymity: default_k_anonymity(),
9854 composition_method: "naive".to_string(),
9855 }
9856 }
9857}
9858
9859#[derive(Debug, Clone, Serialize, Deserialize)]
9873pub struct QualityGatesSchemaConfig {
9874 #[serde(default)]
9876 pub enabled: bool,
9877 #[serde(default = "default_gate_profile_name")]
9879 pub profile: String,
9880 #[serde(default)]
9882 pub fail_on_violation: bool,
9883 #[serde(default)]
9885 pub custom_gates: Vec<QualityGateEntry>,
9886}
9887
9888fn default_gate_profile_name() -> String {
9889 "default".to_string()
9890}
9891
9892impl Default for QualityGatesSchemaConfig {
9893 fn default() -> Self {
9894 Self {
9895 enabled: false,
9896 profile: default_gate_profile_name(),
9897 fail_on_violation: false,
9898 custom_gates: Vec::new(),
9899 }
9900 }
9901}
9902
9903#[derive(Debug, Clone, Serialize, Deserialize)]
9905pub struct QualityGateEntry {
9906 pub name: String,
9908 pub metric: String,
9912 pub threshold: f64,
9914 #[serde(default)]
9916 pub upper_threshold: Option<f64>,
9917 #[serde(default = "default_gate_comparison")]
9919 pub comparison: String,
9920}
9921
9922fn default_gate_comparison() -> String {
9923 "gte".to_string()
9924}
9925
9926#[derive(Debug, Clone, Default, Serialize, Deserialize)]
9936pub struct ComplianceSchemaConfig {
9937 #[serde(default)]
9939 pub content_marking: ContentMarkingSchemaConfig,
9940 #[serde(default)]
9942 pub article10_report: bool,
9943 #[serde(default)]
9945 pub certificates: CertificateSchemaConfig,
9946}
9947
9948#[derive(Debug, Clone, Default, Serialize, Deserialize)]
9950pub struct CertificateSchemaConfig {
9951 #[serde(default)]
9953 pub enabled: bool,
9954 #[serde(default)]
9956 pub signing_key_env: Option<String>,
9957 #[serde(default)]
9959 pub include_quality_metrics: bool,
9960}
9961
9962#[derive(Debug, Clone, Serialize, Deserialize)]
9964pub struct ContentMarkingSchemaConfig {
9965 #[serde(default = "default_true")]
9967 pub enabled: bool,
9968 #[serde(default = "default_marking_format")]
9970 pub format: String,
9971}
9972
9973fn default_marking_format() -> String {
9974 "embedded".to_string()
9975}
9976
9977impl Default for ContentMarkingSchemaConfig {
9978 fn default() -> Self {
9979 Self {
9980 enabled: true,
9981 format: default_marking_format(),
9982 }
9983 }
9984}
9985
9986#[derive(Debug, Clone, Default, Serialize, Deserialize)]
9988pub struct WebhookSchemaConfig {
9989 #[serde(default)]
9991 pub enabled: bool,
9992 #[serde(default)]
9994 pub endpoints: Vec<WebhookEndpointConfig>,
9995}
9996
9997#[derive(Debug, Clone, Serialize, Deserialize)]
9999pub struct WebhookEndpointConfig {
10000 pub url: String,
10002 #[serde(default)]
10004 pub events: Vec<String>,
10005 #[serde(default)]
10007 pub secret: Option<String>,
10008 #[serde(default = "default_webhook_retries")]
10010 pub max_retries: u32,
10011 #[serde(default = "default_webhook_timeout")]
10013 pub timeout_secs: u64,
10014}
10015
10016fn default_webhook_retries() -> u32 {
10017 3
10018}
10019fn default_webhook_timeout() -> u64 {
10020 10
10021}
10022
10023#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10029pub struct SourceToPayConfig {
10030 #[serde(default)]
10032 pub enabled: bool,
10033 #[serde(default)]
10035 pub spend_analysis: SpendAnalysisConfig,
10036 #[serde(default)]
10038 pub sourcing: SourcingConfig,
10039 #[serde(default)]
10041 pub qualification: QualificationConfig,
10042 #[serde(default)]
10044 pub rfx: RfxConfig,
10045 #[serde(default)]
10047 pub contracts: ContractConfig,
10048 #[serde(default)]
10050 pub catalog: CatalogConfig,
10051 #[serde(default)]
10053 pub scorecards: ScorecardConfig,
10054 #[serde(default)]
10056 pub p2p_integration: P2PIntegrationConfig,
10057}
10058
10059#[derive(Debug, Clone, Serialize, Deserialize)]
10061pub struct SpendAnalysisConfig {
10062 #[serde(default = "default_hhi_threshold")]
10064 pub hhi_threshold: f64,
10065 #[serde(default = "default_contract_coverage_target")]
10067 pub contract_coverage_target: f64,
10068}
10069
10070impl Default for SpendAnalysisConfig {
10071 fn default() -> Self {
10072 Self {
10073 hhi_threshold: default_hhi_threshold(),
10074 contract_coverage_target: default_contract_coverage_target(),
10075 }
10076 }
10077}
10078
10079fn default_hhi_threshold() -> f64 {
10080 2500.0
10081}
10082fn default_contract_coverage_target() -> f64 {
10083 0.80
10084}
10085
10086#[derive(Debug, Clone, Serialize, Deserialize)]
10088pub struct SourcingConfig {
10089 #[serde(default = "default_sourcing_projects_per_year")]
10091 pub projects_per_year: u32,
10092 #[serde(default = "default_renewal_horizon_months")]
10094 pub renewal_horizon_months: u32,
10095 #[serde(default = "default_project_duration_months")]
10097 pub project_duration_months: u32,
10098}
10099
10100impl Default for SourcingConfig {
10101 fn default() -> Self {
10102 Self {
10103 projects_per_year: default_sourcing_projects_per_year(),
10104 renewal_horizon_months: default_renewal_horizon_months(),
10105 project_duration_months: default_project_duration_months(),
10106 }
10107 }
10108}
10109
10110fn default_sourcing_projects_per_year() -> u32 {
10111 10
10112}
10113fn default_renewal_horizon_months() -> u32 {
10114 3
10115}
10116fn default_project_duration_months() -> u32 {
10117 4
10118}
10119
10120#[derive(Debug, Clone, Serialize, Deserialize)]
10122pub struct QualificationConfig {
10123 #[serde(default = "default_qualification_pass_rate")]
10125 pub pass_rate: f64,
10126 #[serde(default = "default_qualification_validity_days")]
10128 pub validity_days: u32,
10129 #[serde(default = "default_financial_weight")]
10131 pub financial_weight: f64,
10132 #[serde(default = "default_quality_weight")]
10134 pub quality_weight: f64,
10135 #[serde(default = "default_delivery_weight")]
10137 pub delivery_weight: f64,
10138 #[serde(default = "default_compliance_weight")]
10140 pub compliance_weight: f64,
10141}
10142
10143impl Default for QualificationConfig {
10144 fn default() -> Self {
10145 Self {
10146 pass_rate: default_qualification_pass_rate(),
10147 validity_days: default_qualification_validity_days(),
10148 financial_weight: default_financial_weight(),
10149 quality_weight: default_quality_weight(),
10150 delivery_weight: default_delivery_weight(),
10151 compliance_weight: default_compliance_weight(),
10152 }
10153 }
10154}
10155
10156fn default_qualification_pass_rate() -> f64 {
10157 0.75
10158}
10159fn default_qualification_validity_days() -> u32 {
10160 365
10161}
10162fn default_financial_weight() -> f64 {
10163 0.25
10164}
10165fn default_quality_weight() -> f64 {
10166 0.30
10167}
10168fn default_delivery_weight() -> f64 {
10169 0.25
10170}
10171fn default_compliance_weight() -> f64 {
10172 0.20
10173}
10174
10175#[derive(Debug, Clone, Serialize, Deserialize)]
10177pub struct RfxConfig {
10178 #[serde(default = "default_rfi_threshold")]
10180 pub rfi_threshold: f64,
10181 #[serde(default = "default_min_invited_vendors")]
10183 pub min_invited_vendors: u32,
10184 #[serde(default = "default_max_invited_vendors")]
10186 pub max_invited_vendors: u32,
10187 #[serde(default = "default_response_rate")]
10189 pub response_rate: f64,
10190 #[serde(default = "default_price_weight")]
10192 pub default_price_weight: f64,
10193 #[serde(default = "default_rfx_quality_weight")]
10195 pub default_quality_weight: f64,
10196 #[serde(default = "default_rfx_delivery_weight")]
10198 pub default_delivery_weight: f64,
10199}
10200
10201impl Default for RfxConfig {
10202 fn default() -> Self {
10203 Self {
10204 rfi_threshold: default_rfi_threshold(),
10205 min_invited_vendors: default_min_invited_vendors(),
10206 max_invited_vendors: default_max_invited_vendors(),
10207 response_rate: default_response_rate(),
10208 default_price_weight: default_price_weight(),
10209 default_quality_weight: default_rfx_quality_weight(),
10210 default_delivery_weight: default_rfx_delivery_weight(),
10211 }
10212 }
10213}
10214
10215fn default_rfi_threshold() -> f64 {
10216 100_000.0
10217}
10218fn default_min_invited_vendors() -> u32 {
10219 3
10220}
10221fn default_max_invited_vendors() -> u32 {
10222 8
10223}
10224fn default_response_rate() -> f64 {
10225 0.70
10226}
10227fn default_price_weight() -> f64 {
10228 0.40
10229}
10230fn default_rfx_quality_weight() -> f64 {
10231 0.35
10232}
10233fn default_rfx_delivery_weight() -> f64 {
10234 0.25
10235}
10236
10237#[derive(Debug, Clone, Serialize, Deserialize)]
10239pub struct ContractConfig {
10240 #[serde(default = "default_min_contract_months")]
10242 pub min_duration_months: u32,
10243 #[serde(default = "default_max_contract_months")]
10245 pub max_duration_months: u32,
10246 #[serde(default = "default_auto_renewal_rate")]
10248 pub auto_renewal_rate: f64,
10249 #[serde(default = "default_amendment_rate")]
10251 pub amendment_rate: f64,
10252 #[serde(default)]
10254 pub type_distribution: ContractTypeDistribution,
10255}
10256
10257impl Default for ContractConfig {
10258 fn default() -> Self {
10259 Self {
10260 min_duration_months: default_min_contract_months(),
10261 max_duration_months: default_max_contract_months(),
10262 auto_renewal_rate: default_auto_renewal_rate(),
10263 amendment_rate: default_amendment_rate(),
10264 type_distribution: ContractTypeDistribution::default(),
10265 }
10266 }
10267}
10268
10269fn default_min_contract_months() -> u32 {
10270 12
10271}
10272fn default_max_contract_months() -> u32 {
10273 36
10274}
10275fn default_auto_renewal_rate() -> f64 {
10276 0.40
10277}
10278fn default_amendment_rate() -> f64 {
10279 0.20
10280}
10281
10282#[derive(Debug, Clone, Serialize, Deserialize)]
10284pub struct ContractTypeDistribution {
10285 #[serde(default = "default_fixed_price_pct")]
10287 pub fixed_price: f64,
10288 #[serde(default = "default_blanket_pct")]
10290 pub blanket: f64,
10291 #[serde(default = "default_time_materials_pct")]
10293 pub time_and_materials: f64,
10294 #[serde(default = "default_service_agreement_pct")]
10296 pub service_agreement: f64,
10297}
10298
10299impl Default for ContractTypeDistribution {
10300 fn default() -> Self {
10301 Self {
10302 fixed_price: default_fixed_price_pct(),
10303 blanket: default_blanket_pct(),
10304 time_and_materials: default_time_materials_pct(),
10305 service_agreement: default_service_agreement_pct(),
10306 }
10307 }
10308}
10309
10310fn default_fixed_price_pct() -> f64 {
10311 0.40
10312}
10313fn default_blanket_pct() -> f64 {
10314 0.30
10315}
10316fn default_time_materials_pct() -> f64 {
10317 0.15
10318}
10319fn default_service_agreement_pct() -> f64 {
10320 0.15
10321}
10322
10323#[derive(Debug, Clone, Serialize, Deserialize)]
10325pub struct CatalogConfig {
10326 #[serde(default = "default_preferred_vendor_flag_rate")]
10328 pub preferred_vendor_flag_rate: f64,
10329 #[serde(default = "default_multi_source_rate")]
10331 pub multi_source_rate: f64,
10332}
10333
10334impl Default for CatalogConfig {
10335 fn default() -> Self {
10336 Self {
10337 preferred_vendor_flag_rate: default_preferred_vendor_flag_rate(),
10338 multi_source_rate: default_multi_source_rate(),
10339 }
10340 }
10341}
10342
10343fn default_preferred_vendor_flag_rate() -> f64 {
10344 0.70
10345}
10346fn default_multi_source_rate() -> f64 {
10347 0.25
10348}
10349
10350#[derive(Debug, Clone, Serialize, Deserialize)]
10352pub struct ScorecardConfig {
10353 #[serde(default = "default_scorecard_frequency")]
10355 pub frequency: String,
10356 #[serde(default = "default_otd_weight")]
10358 pub on_time_delivery_weight: f64,
10359 #[serde(default = "default_quality_score_weight")]
10361 pub quality_weight: f64,
10362 #[serde(default = "default_price_score_weight")]
10364 pub price_weight: f64,
10365 #[serde(default = "default_responsiveness_weight")]
10367 pub responsiveness_weight: f64,
10368 #[serde(default = "default_grade_a_threshold")]
10370 pub grade_a_threshold: f64,
10371 #[serde(default = "default_grade_b_threshold")]
10373 pub grade_b_threshold: f64,
10374 #[serde(default = "default_grade_c_threshold")]
10376 pub grade_c_threshold: f64,
10377}
10378
10379impl Default for ScorecardConfig {
10380 fn default() -> Self {
10381 Self {
10382 frequency: default_scorecard_frequency(),
10383 on_time_delivery_weight: default_otd_weight(),
10384 quality_weight: default_quality_score_weight(),
10385 price_weight: default_price_score_weight(),
10386 responsiveness_weight: default_responsiveness_weight(),
10387 grade_a_threshold: default_grade_a_threshold(),
10388 grade_b_threshold: default_grade_b_threshold(),
10389 grade_c_threshold: default_grade_c_threshold(),
10390 }
10391 }
10392}
10393
10394fn default_scorecard_frequency() -> String {
10395 "quarterly".to_string()
10396}
10397fn default_otd_weight() -> f64 {
10398 0.30
10399}
10400fn default_quality_score_weight() -> f64 {
10401 0.30
10402}
10403fn default_price_score_weight() -> f64 {
10404 0.25
10405}
10406fn default_responsiveness_weight() -> f64 {
10407 0.15
10408}
10409fn default_grade_a_threshold() -> f64 {
10410 90.0
10411}
10412fn default_grade_b_threshold() -> f64 {
10413 75.0
10414}
10415fn default_grade_c_threshold() -> f64 {
10416 60.0
10417}
10418
10419#[derive(Debug, Clone, Serialize, Deserialize)]
10421pub struct P2PIntegrationConfig {
10422 #[serde(default = "default_off_contract_rate")]
10424 pub off_contract_rate: f64,
10425 #[serde(default = "default_price_tolerance")]
10427 pub price_tolerance: f64,
10428 #[serde(default)]
10430 pub catalog_enforcement: bool,
10431}
10432
10433impl Default for P2PIntegrationConfig {
10434 fn default() -> Self {
10435 Self {
10436 off_contract_rate: default_off_contract_rate(),
10437 price_tolerance: default_price_tolerance(),
10438 catalog_enforcement: false,
10439 }
10440 }
10441}
10442
10443fn default_off_contract_rate() -> f64 {
10444 0.15
10445}
10446fn default_price_tolerance() -> f64 {
10447 0.02
10448}
10449
10450#[derive(Debug, Clone, Serialize, Deserialize)]
10454pub struct FinancialReportingConfig {
10455 #[serde(default)]
10457 pub enabled: bool,
10458 #[serde(default = "default_true")]
10460 pub generate_balance_sheet: bool,
10461 #[serde(default = "default_true")]
10463 pub generate_income_statement: bool,
10464 #[serde(default = "default_true")]
10466 pub generate_cash_flow: bool,
10467 #[serde(default = "default_true")]
10469 pub generate_changes_in_equity: bool,
10470 #[serde(default = "default_comparative_periods")]
10472 pub comparative_periods: u32,
10473 #[serde(default)]
10475 pub management_kpis: ManagementKpisConfig,
10476 #[serde(default)]
10478 pub budgets: BudgetConfig,
10479}
10480
10481impl Default for FinancialReportingConfig {
10482 fn default() -> Self {
10483 Self {
10484 enabled: false,
10485 generate_balance_sheet: true,
10486 generate_income_statement: true,
10487 generate_cash_flow: true,
10488 generate_changes_in_equity: true,
10489 comparative_periods: default_comparative_periods(),
10490 management_kpis: ManagementKpisConfig::default(),
10491 budgets: BudgetConfig::default(),
10492 }
10493 }
10494}
10495
10496fn default_comparative_periods() -> u32 {
10497 1
10498}
10499
10500#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10502pub struct ManagementKpisConfig {
10503 #[serde(default)]
10505 pub enabled: bool,
10506 #[serde(default = "default_kpi_frequency")]
10508 pub frequency: String,
10509}
10510
10511fn default_kpi_frequency() -> String {
10512 "monthly".to_string()
10513}
10514
10515#[derive(Debug, Clone, Serialize, Deserialize)]
10517pub struct BudgetConfig {
10518 #[serde(default)]
10520 pub enabled: bool,
10521 #[serde(default = "default_revenue_growth_rate")]
10523 pub revenue_growth_rate: f64,
10524 #[serde(default = "default_expense_inflation_rate")]
10526 pub expense_inflation_rate: f64,
10527 #[serde(default = "default_variance_noise")]
10529 pub variance_noise: f64,
10530}
10531
10532impl Default for BudgetConfig {
10533 fn default() -> Self {
10534 Self {
10535 enabled: false,
10536 revenue_growth_rate: default_revenue_growth_rate(),
10537 expense_inflation_rate: default_expense_inflation_rate(),
10538 variance_noise: default_variance_noise(),
10539 }
10540 }
10541}
10542
10543fn default_revenue_growth_rate() -> f64 {
10544 0.05
10545}
10546fn default_expense_inflation_rate() -> f64 {
10547 0.03
10548}
10549fn default_variance_noise() -> f64 {
10550 0.10
10551}
10552
10553#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10557pub struct HrConfig {
10558 #[serde(default)]
10560 pub enabled: bool,
10561 #[serde(default)]
10563 pub payroll: PayrollConfig,
10564 #[serde(default)]
10566 pub time_attendance: TimeAttendanceConfig,
10567 #[serde(default)]
10569 pub expenses: ExpenseConfig,
10570}
10571
10572#[derive(Debug, Clone, Serialize, Deserialize)]
10574pub struct PayrollConfig {
10575 #[serde(default = "default_true")]
10577 pub enabled: bool,
10578 #[serde(default = "default_pay_frequency")]
10580 pub pay_frequency: String,
10581 #[serde(default)]
10583 pub salary_ranges: PayrollSalaryRanges,
10584 #[serde(default)]
10586 pub tax_rates: PayrollTaxRates,
10587 #[serde(default = "default_benefits_enrollment_rate")]
10589 pub benefits_enrollment_rate: f64,
10590 #[serde(default = "default_retirement_participation_rate")]
10592 pub retirement_participation_rate: f64,
10593}
10594
10595impl Default for PayrollConfig {
10596 fn default() -> Self {
10597 Self {
10598 enabled: true,
10599 pay_frequency: default_pay_frequency(),
10600 salary_ranges: PayrollSalaryRanges::default(),
10601 tax_rates: PayrollTaxRates::default(),
10602 benefits_enrollment_rate: default_benefits_enrollment_rate(),
10603 retirement_participation_rate: default_retirement_participation_rate(),
10604 }
10605 }
10606}
10607
10608fn default_pay_frequency() -> String {
10609 "monthly".to_string()
10610}
10611fn default_benefits_enrollment_rate() -> f64 {
10612 0.60
10613}
10614fn default_retirement_participation_rate() -> f64 {
10615 0.45
10616}
10617
10618#[derive(Debug, Clone, Serialize, Deserialize)]
10620pub struct PayrollSalaryRanges {
10621 #[serde(default = "default_staff_min")]
10623 pub staff_min: f64,
10624 #[serde(default = "default_staff_max")]
10625 pub staff_max: f64,
10626 #[serde(default = "default_manager_min")]
10628 pub manager_min: f64,
10629 #[serde(default = "default_manager_max")]
10630 pub manager_max: f64,
10631 #[serde(default = "default_director_min")]
10633 pub director_min: f64,
10634 #[serde(default = "default_director_max")]
10635 pub director_max: f64,
10636 #[serde(default = "default_executive_min")]
10638 pub executive_min: f64,
10639 #[serde(default = "default_executive_max")]
10640 pub executive_max: f64,
10641}
10642
10643impl Default for PayrollSalaryRanges {
10644 fn default() -> Self {
10645 Self {
10646 staff_min: default_staff_min(),
10647 staff_max: default_staff_max(),
10648 manager_min: default_manager_min(),
10649 manager_max: default_manager_max(),
10650 director_min: default_director_min(),
10651 director_max: default_director_max(),
10652 executive_min: default_executive_min(),
10653 executive_max: default_executive_max(),
10654 }
10655 }
10656}
10657
10658fn default_staff_min() -> f64 {
10659 50_000.0
10660}
10661fn default_staff_max() -> f64 {
10662 70_000.0
10663}
10664fn default_manager_min() -> f64 {
10665 80_000.0
10666}
10667fn default_manager_max() -> f64 {
10668 120_000.0
10669}
10670fn default_director_min() -> f64 {
10671 120_000.0
10672}
10673fn default_director_max() -> f64 {
10674 180_000.0
10675}
10676fn default_executive_min() -> f64 {
10677 180_000.0
10678}
10679fn default_executive_max() -> f64 {
10680 350_000.0
10681}
10682
10683#[derive(Debug, Clone, Serialize, Deserialize)]
10685pub struct PayrollTaxRates {
10686 #[serde(default = "default_federal_rate")]
10688 pub federal_effective: f64,
10689 #[serde(default = "default_state_rate")]
10691 pub state_effective: f64,
10692 #[serde(default = "default_fica_rate")]
10694 pub fica: f64,
10695}
10696
10697impl Default for PayrollTaxRates {
10698 fn default() -> Self {
10699 Self {
10700 federal_effective: default_federal_rate(),
10701 state_effective: default_state_rate(),
10702 fica: default_fica_rate(),
10703 }
10704 }
10705}
10706
10707fn default_federal_rate() -> f64 {
10708 0.22
10709}
10710fn default_state_rate() -> f64 {
10711 0.05
10712}
10713fn default_fica_rate() -> f64 {
10714 0.0765
10715}
10716
10717#[derive(Debug, Clone, Serialize, Deserialize)]
10719pub struct TimeAttendanceConfig {
10720 #[serde(default = "default_true")]
10722 pub enabled: bool,
10723 #[serde(default = "default_overtime_rate")]
10725 pub overtime_rate: f64,
10726}
10727
10728impl Default for TimeAttendanceConfig {
10729 fn default() -> Self {
10730 Self {
10731 enabled: true,
10732 overtime_rate: default_overtime_rate(),
10733 }
10734 }
10735}
10736
10737fn default_overtime_rate() -> f64 {
10738 0.10
10739}
10740
10741#[derive(Debug, Clone, Serialize, Deserialize)]
10743pub struct ExpenseConfig {
10744 #[serde(default = "default_true")]
10746 pub enabled: bool,
10747 #[serde(default = "default_expense_submission_rate")]
10749 pub submission_rate: f64,
10750 #[serde(default = "default_policy_violation_rate")]
10752 pub policy_violation_rate: f64,
10753}
10754
10755impl Default for ExpenseConfig {
10756 fn default() -> Self {
10757 Self {
10758 enabled: true,
10759 submission_rate: default_expense_submission_rate(),
10760 policy_violation_rate: default_policy_violation_rate(),
10761 }
10762 }
10763}
10764
10765fn default_expense_submission_rate() -> f64 {
10766 0.30
10767}
10768fn default_policy_violation_rate() -> f64 {
10769 0.08
10770}
10771
10772#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10776pub struct ManufacturingProcessConfig {
10777 #[serde(default)]
10779 pub enabled: bool,
10780 #[serde(default)]
10782 pub production_orders: ProductionOrderConfig,
10783 #[serde(default)]
10785 pub costing: ManufacturingCostingConfig,
10786 #[serde(default)]
10788 pub routing: RoutingConfig,
10789}
10790
10791#[derive(Debug, Clone, Serialize, Deserialize)]
10793pub struct ProductionOrderConfig {
10794 #[serde(default = "default_prod_orders_per_month")]
10796 pub orders_per_month: u32,
10797 #[serde(default = "default_prod_avg_batch_size")]
10799 pub avg_batch_size: u32,
10800 #[serde(default = "default_prod_yield_rate")]
10802 pub yield_rate: f64,
10803 #[serde(default = "default_prod_make_to_order_rate")]
10805 pub make_to_order_rate: f64,
10806 #[serde(default = "default_prod_rework_rate")]
10808 pub rework_rate: f64,
10809}
10810
10811impl Default for ProductionOrderConfig {
10812 fn default() -> Self {
10813 Self {
10814 orders_per_month: default_prod_orders_per_month(),
10815 avg_batch_size: default_prod_avg_batch_size(),
10816 yield_rate: default_prod_yield_rate(),
10817 make_to_order_rate: default_prod_make_to_order_rate(),
10818 rework_rate: default_prod_rework_rate(),
10819 }
10820 }
10821}
10822
10823fn default_prod_orders_per_month() -> u32 {
10824 50
10825}
10826fn default_prod_avg_batch_size() -> u32 {
10827 100
10828}
10829fn default_prod_yield_rate() -> f64 {
10830 0.97
10831}
10832fn default_prod_make_to_order_rate() -> f64 {
10833 0.20
10834}
10835fn default_prod_rework_rate() -> f64 {
10836 0.03
10837}
10838
10839#[derive(Debug, Clone, Serialize, Deserialize)]
10841pub struct ManufacturingCostingConfig {
10842 #[serde(default = "default_labor_rate")]
10844 pub labor_rate_per_hour: f64,
10845 #[serde(default = "default_overhead_rate")]
10847 pub overhead_rate: f64,
10848 #[serde(default = "default_cost_update_frequency")]
10850 pub standard_cost_update_frequency: String,
10851}
10852
10853impl Default for ManufacturingCostingConfig {
10854 fn default() -> Self {
10855 Self {
10856 labor_rate_per_hour: default_labor_rate(),
10857 overhead_rate: default_overhead_rate(),
10858 standard_cost_update_frequency: default_cost_update_frequency(),
10859 }
10860 }
10861}
10862
10863fn default_labor_rate() -> f64 {
10864 35.0
10865}
10866fn default_overhead_rate() -> f64 {
10867 1.50
10868}
10869fn default_cost_update_frequency() -> String {
10870 "quarterly".to_string()
10871}
10872
10873#[derive(Debug, Clone, Serialize, Deserialize)]
10875pub struct RoutingConfig {
10876 #[serde(default = "default_avg_operations")]
10878 pub avg_operations: u32,
10879 #[serde(default = "default_setup_time")]
10881 pub setup_time_hours: f64,
10882 #[serde(default = "default_run_time_variation")]
10884 pub run_time_variation: f64,
10885}
10886
10887impl Default for RoutingConfig {
10888 fn default() -> Self {
10889 Self {
10890 avg_operations: default_avg_operations(),
10891 setup_time_hours: default_setup_time(),
10892 run_time_variation: default_run_time_variation(),
10893 }
10894 }
10895}
10896
10897fn default_avg_operations() -> u32 {
10898 4
10899}
10900fn default_setup_time() -> f64 {
10901 1.5
10902}
10903fn default_run_time_variation() -> f64 {
10904 0.15
10905}
10906
10907#[derive(Debug, Clone, Serialize, Deserialize)]
10911pub struct SalesQuoteConfig {
10912 #[serde(default)]
10914 pub enabled: bool,
10915 #[serde(default = "default_quotes_per_month")]
10917 pub quotes_per_month: u32,
10918 #[serde(default = "default_quote_win_rate")]
10920 pub win_rate: f64,
10921 #[serde(default = "default_quote_validity_days")]
10923 pub validity_days: u32,
10924}
10925
10926impl Default for SalesQuoteConfig {
10927 fn default() -> Self {
10928 Self {
10929 enabled: false,
10930 quotes_per_month: default_quotes_per_month(),
10931 win_rate: default_quote_win_rate(),
10932 validity_days: default_quote_validity_days(),
10933 }
10934 }
10935}
10936
10937fn default_quotes_per_month() -> u32 {
10938 30
10939}
10940fn default_quote_win_rate() -> f64 {
10941 0.35
10942}
10943fn default_quote_validity_days() -> u32 {
10944 30
10945}
10946
10947#[derive(Debug, Clone, Serialize, Deserialize)]
10956pub struct TaxConfig {
10957 #[serde(default)]
10959 pub enabled: bool,
10960 #[serde(default)]
10962 pub jurisdictions: TaxJurisdictionConfig,
10963 #[serde(default)]
10965 pub vat_gst: VatGstConfig,
10966 #[serde(default)]
10968 pub sales_tax: SalesTaxConfig,
10969 #[serde(default)]
10971 pub withholding: WithholdingTaxSchemaConfig,
10972 #[serde(default)]
10974 pub provisions: TaxProvisionSchemaConfig,
10975 #[serde(default)]
10977 pub payroll_tax: PayrollTaxSchemaConfig,
10978 #[serde(default = "default_tax_anomaly_rate")]
10980 pub anomaly_rate: f64,
10981}
10982
10983fn default_tax_anomaly_rate() -> f64 {
10984 0.03
10985}
10986
10987impl Default for TaxConfig {
10988 fn default() -> Self {
10989 Self {
10990 enabled: false,
10991 jurisdictions: TaxJurisdictionConfig::default(),
10992 vat_gst: VatGstConfig::default(),
10993 sales_tax: SalesTaxConfig::default(),
10994 withholding: WithholdingTaxSchemaConfig::default(),
10995 provisions: TaxProvisionSchemaConfig::default(),
10996 payroll_tax: PayrollTaxSchemaConfig::default(),
10997 anomaly_rate: default_tax_anomaly_rate(),
10998 }
10999 }
11000}
11001
11002#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11007pub struct TaxJurisdictionConfig {
11008 #[serde(default)]
11010 pub countries: Vec<String>,
11011 #[serde(default)]
11013 pub include_subnational: bool,
11014}
11015
11016#[derive(Debug, Clone, Serialize, Deserialize)]
11021pub struct VatGstConfig {
11022 #[serde(default)]
11024 pub enabled: bool,
11025 #[serde(default)]
11027 pub standard_rates: std::collections::HashMap<String, f64>,
11028 #[serde(default)]
11030 pub reduced_rates: std::collections::HashMap<String, f64>,
11031 #[serde(default)]
11033 pub exempt_categories: Vec<String>,
11034 #[serde(default = "default_true")]
11036 pub reverse_charge: bool,
11037}
11038
11039impl Default for VatGstConfig {
11040 fn default() -> Self {
11041 Self {
11042 enabled: false,
11043 standard_rates: std::collections::HashMap::new(),
11044 reduced_rates: std::collections::HashMap::new(),
11045 exempt_categories: Vec::new(),
11046 reverse_charge: true,
11047 }
11048 }
11049}
11050
11051#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11055pub struct SalesTaxConfig {
11056 #[serde(default)]
11058 pub enabled: bool,
11059 #[serde(default)]
11061 pub nexus_states: Vec<String>,
11062}
11063
11064#[derive(Debug, Clone, Serialize, Deserialize)]
11069pub struct WithholdingTaxSchemaConfig {
11070 #[serde(default)]
11072 pub enabled: bool,
11073 #[serde(default = "default_true")]
11075 pub treaty_network: bool,
11076 #[serde(default = "default_withholding_rate")]
11078 pub default_rate: f64,
11079 #[serde(default = "default_treaty_reduced_rate")]
11081 pub treaty_reduced_rate: f64,
11082}
11083
11084fn default_withholding_rate() -> f64 {
11085 0.30
11086}
11087
11088fn default_treaty_reduced_rate() -> f64 {
11089 0.15
11090}
11091
11092impl Default for WithholdingTaxSchemaConfig {
11093 fn default() -> Self {
11094 Self {
11095 enabled: false,
11096 treaty_network: true,
11097 default_rate: default_withholding_rate(),
11098 treaty_reduced_rate: default_treaty_reduced_rate(),
11099 }
11100 }
11101}
11102
11103#[derive(Debug, Clone, Serialize, Deserialize)]
11108pub struct TaxProvisionSchemaConfig {
11109 #[serde(default = "default_true")]
11112 pub enabled: bool,
11113 #[serde(default = "default_statutory_rate")]
11115 pub statutory_rate: f64,
11116 #[serde(default = "default_true")]
11118 pub uncertain_positions: bool,
11119}
11120
11121fn default_statutory_rate() -> f64 {
11122 0.21
11123}
11124
11125impl Default for TaxProvisionSchemaConfig {
11126 fn default() -> Self {
11127 Self {
11128 enabled: true,
11129 statutory_rate: default_statutory_rate(),
11130 uncertain_positions: true,
11131 }
11132 }
11133}
11134
11135#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11140pub struct PayrollTaxSchemaConfig {
11141 #[serde(default)]
11143 pub enabled: bool,
11144}
11145
11146#[derive(Debug, Clone, Serialize, Deserialize)]
11156pub struct TreasuryConfig {
11157 #[serde(default)]
11159 pub enabled: bool,
11160 #[serde(default)]
11162 pub cash_positioning: CashPositioningConfig,
11163 #[serde(default)]
11165 pub cash_forecasting: CashForecastingConfig,
11166 #[serde(default)]
11168 pub cash_pooling: CashPoolingConfig,
11169 #[serde(default)]
11171 pub hedging: HedgingSchemaConfig,
11172 #[serde(default)]
11174 pub debt: DebtSchemaConfig,
11175 #[serde(default)]
11177 pub netting: NettingSchemaConfig,
11178 #[serde(default)]
11180 pub bank_guarantees: BankGuaranteeSchemaConfig,
11181 #[serde(default = "default_treasury_anomaly_rate")]
11183 pub anomaly_rate: f64,
11184}
11185
11186fn default_treasury_anomaly_rate() -> f64 {
11187 0.02
11188}
11189
11190impl Default for TreasuryConfig {
11191 fn default() -> Self {
11192 Self {
11193 enabled: false,
11194 cash_positioning: CashPositioningConfig::default(),
11195 cash_forecasting: CashForecastingConfig::default(),
11196 cash_pooling: CashPoolingConfig::default(),
11197 hedging: HedgingSchemaConfig::default(),
11198 debt: DebtSchemaConfig::default(),
11199 netting: NettingSchemaConfig::default(),
11200 bank_guarantees: BankGuaranteeSchemaConfig::default(),
11201 anomaly_rate: default_treasury_anomaly_rate(),
11202 }
11203 }
11204}
11205
11206#[derive(Debug, Clone, Serialize, Deserialize)]
11210pub struct CashPositioningConfig {
11211 #[serde(default = "default_true")]
11213 pub enabled: bool,
11214 #[serde(default = "default_cash_frequency")]
11216 pub frequency: String,
11217 #[serde(default = "default_minimum_balance_policy")]
11219 pub minimum_balance_policy: f64,
11220}
11221
11222fn default_cash_frequency() -> String {
11223 "daily".to_string()
11224}
11225
11226fn default_minimum_balance_policy() -> f64 {
11227 100_000.0
11228}
11229
11230impl Default for CashPositioningConfig {
11231 fn default() -> Self {
11232 Self {
11233 enabled: true,
11234 frequency: default_cash_frequency(),
11235 minimum_balance_policy: default_minimum_balance_policy(),
11236 }
11237 }
11238}
11239
11240#[derive(Debug, Clone, Serialize, Deserialize)]
11244pub struct CashForecastingConfig {
11245 #[serde(default = "default_true")]
11247 pub enabled: bool,
11248 #[serde(default = "default_horizon_days")]
11250 pub horizon_days: u32,
11251 #[serde(default = "default_ar_probability_curve")]
11253 pub ar_collection_probability_curve: String,
11254 #[serde(default = "default_confidence_interval")]
11256 pub confidence_interval: f64,
11257}
11258
11259fn default_horizon_days() -> u32 {
11260 90
11261}
11262
11263fn default_ar_probability_curve() -> String {
11264 "aging".to_string()
11265}
11266
11267fn default_confidence_interval() -> f64 {
11268 0.90
11269}
11270
11271impl Default for CashForecastingConfig {
11272 fn default() -> Self {
11273 Self {
11274 enabled: true,
11275 horizon_days: default_horizon_days(),
11276 ar_collection_probability_curve: default_ar_probability_curve(),
11277 confidence_interval: default_confidence_interval(),
11278 }
11279 }
11280}
11281
11282#[derive(Debug, Clone, Serialize, Deserialize)]
11286pub struct CashPoolingConfig {
11287 #[serde(default)]
11289 pub enabled: bool,
11290 #[serde(default = "default_pool_type")]
11292 pub pool_type: String,
11293 #[serde(default = "default_sweep_time")]
11295 pub sweep_time: String,
11296}
11297
11298fn default_pool_type() -> String {
11299 "zero_balancing".to_string()
11300}
11301
11302fn default_sweep_time() -> String {
11303 "16:00".to_string()
11304}
11305
11306impl Default for CashPoolingConfig {
11307 fn default() -> Self {
11308 Self {
11309 enabled: false,
11310 pool_type: default_pool_type(),
11311 sweep_time: default_sweep_time(),
11312 }
11313 }
11314}
11315
11316#[derive(Debug, Clone, Serialize, Deserialize)]
11321pub struct HedgingSchemaConfig {
11322 #[serde(default)]
11324 pub enabled: bool,
11325 #[serde(default = "default_hedge_ratio")]
11327 pub hedge_ratio: f64,
11328 #[serde(default = "default_hedge_instruments")]
11330 pub instruments: Vec<String>,
11331 #[serde(default = "default_true")]
11333 pub hedge_accounting: bool,
11334 #[serde(default = "default_effectiveness_method")]
11336 pub effectiveness_method: String,
11337}
11338
11339fn default_hedge_ratio() -> f64 {
11340 0.75
11341}
11342
11343fn default_hedge_instruments() -> Vec<String> {
11344 vec!["fx_forward".to_string(), "interest_rate_swap".to_string()]
11345}
11346
11347fn default_effectiveness_method() -> String {
11348 "regression".to_string()
11349}
11350
11351impl Default for HedgingSchemaConfig {
11352 fn default() -> Self {
11353 Self {
11354 enabled: false,
11355 hedge_ratio: default_hedge_ratio(),
11356 instruments: default_hedge_instruments(),
11357 hedge_accounting: true,
11358 effectiveness_method: default_effectiveness_method(),
11359 }
11360 }
11361}
11362
11363#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11368pub struct DebtSchemaConfig {
11369 #[serde(default)]
11371 pub enabled: bool,
11372 #[serde(default)]
11374 pub instruments: Vec<DebtInstrumentDef>,
11375 #[serde(default)]
11377 pub covenants: Vec<CovenantDef>,
11378}
11379
11380#[derive(Debug, Clone, Serialize, Deserialize)]
11382pub struct DebtInstrumentDef {
11383 #[serde(rename = "type")]
11385 pub instrument_type: String,
11386 #[serde(default)]
11388 pub principal: Option<f64>,
11389 #[serde(default)]
11391 pub rate: Option<f64>,
11392 #[serde(default)]
11394 pub maturity_months: Option<u32>,
11395 #[serde(default)]
11397 pub facility: Option<f64>,
11398}
11399
11400#[derive(Debug, Clone, Serialize, Deserialize)]
11402pub struct CovenantDef {
11403 #[serde(rename = "type")]
11406 pub covenant_type: String,
11407 pub threshold: f64,
11409}
11410
11411#[derive(Debug, Clone, Serialize, Deserialize)]
11415pub struct NettingSchemaConfig {
11416 #[serde(default)]
11418 pub enabled: bool,
11419 #[serde(default = "default_netting_cycle")]
11421 pub cycle: String,
11422}
11423
11424fn default_netting_cycle() -> String {
11425 "monthly".to_string()
11426}
11427
11428impl Default for NettingSchemaConfig {
11429 fn default() -> Self {
11430 Self {
11431 enabled: false,
11432 cycle: default_netting_cycle(),
11433 }
11434 }
11435}
11436
11437#[derive(Debug, Clone, Serialize, Deserialize)]
11441pub struct BankGuaranteeSchemaConfig {
11442 #[serde(default)]
11444 pub enabled: bool,
11445 #[serde(default = "default_guarantee_count")]
11447 pub count: u32,
11448}
11449
11450fn default_guarantee_count() -> u32 {
11451 5
11452}
11453
11454impl Default for BankGuaranteeSchemaConfig {
11455 fn default() -> Self {
11456 Self {
11457 enabled: false,
11458 count: default_guarantee_count(),
11459 }
11460 }
11461}
11462
11463#[derive(Debug, Clone, Serialize, Deserialize)]
11472pub struct ProjectAccountingConfig {
11473 #[serde(default)]
11475 pub enabled: bool,
11476 #[serde(default = "default_project_count")]
11478 pub project_count: u32,
11479 #[serde(default)]
11481 pub project_types: ProjectTypeDistribution,
11482 #[serde(default)]
11484 pub wbs: WbsSchemaConfig,
11485 #[serde(default)]
11487 pub cost_allocation: CostAllocationConfig,
11488 #[serde(default)]
11490 pub revenue_recognition: ProjectRevenueRecognitionConfig,
11491 #[serde(default)]
11493 pub milestones: MilestoneSchemaConfig,
11494 #[serde(default)]
11496 pub change_orders: ChangeOrderSchemaConfig,
11497 #[serde(default)]
11499 pub retainage: RetainageSchemaConfig,
11500 #[serde(default)]
11502 pub earned_value: EarnedValueSchemaConfig,
11503 #[serde(default = "default_project_anomaly_rate")]
11505 pub anomaly_rate: f64,
11506}
11507
11508fn default_project_count() -> u32 {
11509 10
11510}
11511
11512fn default_project_anomaly_rate() -> f64 {
11513 0.03
11514}
11515
11516impl Default for ProjectAccountingConfig {
11517 fn default() -> Self {
11518 Self {
11519 enabled: false,
11520 project_count: default_project_count(),
11521 project_types: ProjectTypeDistribution::default(),
11522 wbs: WbsSchemaConfig::default(),
11523 cost_allocation: CostAllocationConfig::default(),
11524 revenue_recognition: ProjectRevenueRecognitionConfig::default(),
11525 milestones: MilestoneSchemaConfig::default(),
11526 change_orders: ChangeOrderSchemaConfig::default(),
11527 retainage: RetainageSchemaConfig::default(),
11528 earned_value: EarnedValueSchemaConfig::default(),
11529 anomaly_rate: default_project_anomaly_rate(),
11530 }
11531 }
11532}
11533
11534#[derive(Debug, Clone, Serialize, Deserialize)]
11536pub struct ProjectTypeDistribution {
11537 #[serde(default = "default_capital_weight")]
11539 pub capital: f64,
11540 #[serde(default = "default_internal_weight")]
11542 pub internal: f64,
11543 #[serde(default = "default_customer_weight")]
11545 pub customer: f64,
11546 #[serde(default = "default_rnd_weight")]
11548 pub r_and_d: f64,
11549 #[serde(default = "default_maintenance_weight")]
11551 pub maintenance: f64,
11552 #[serde(default = "default_technology_weight")]
11554 pub technology: f64,
11555}
11556
11557fn default_capital_weight() -> f64 {
11558 0.25
11559}
11560fn default_internal_weight() -> f64 {
11561 0.20
11562}
11563fn default_customer_weight() -> f64 {
11564 0.30
11565}
11566fn default_rnd_weight() -> f64 {
11567 0.10
11568}
11569fn default_maintenance_weight() -> f64 {
11570 0.10
11571}
11572fn default_technology_weight() -> f64 {
11573 0.05
11574}
11575
11576impl Default for ProjectTypeDistribution {
11577 fn default() -> Self {
11578 Self {
11579 capital: default_capital_weight(),
11580 internal: default_internal_weight(),
11581 customer: default_customer_weight(),
11582 r_and_d: default_rnd_weight(),
11583 maintenance: default_maintenance_weight(),
11584 technology: default_technology_weight(),
11585 }
11586 }
11587}
11588
11589#[derive(Debug, Clone, Serialize, Deserialize)]
11591pub struct WbsSchemaConfig {
11592 #[serde(default = "default_wbs_max_depth")]
11594 pub max_depth: u32,
11595 #[serde(default = "default_wbs_min_elements")]
11597 pub min_elements_per_level: u32,
11598 #[serde(default = "default_wbs_max_elements")]
11600 pub max_elements_per_level: u32,
11601}
11602
11603fn default_wbs_max_depth() -> u32 {
11604 3
11605}
11606fn default_wbs_min_elements() -> u32 {
11607 2
11608}
11609fn default_wbs_max_elements() -> u32 {
11610 6
11611}
11612
11613impl Default for WbsSchemaConfig {
11614 fn default() -> Self {
11615 Self {
11616 max_depth: default_wbs_max_depth(),
11617 min_elements_per_level: default_wbs_min_elements(),
11618 max_elements_per_level: default_wbs_max_elements(),
11619 }
11620 }
11621}
11622
11623#[derive(Debug, Clone, Serialize, Deserialize)]
11625pub struct CostAllocationConfig {
11626 #[serde(default = "default_time_entry_rate")]
11628 pub time_entry_project_rate: f64,
11629 #[serde(default = "default_expense_rate")]
11631 pub expense_project_rate: f64,
11632 #[serde(default = "default_po_rate")]
11634 pub purchase_order_project_rate: f64,
11635 #[serde(default = "default_vi_rate")]
11637 pub vendor_invoice_project_rate: f64,
11638}
11639
11640fn default_time_entry_rate() -> f64 {
11641 0.60
11642}
11643fn default_expense_rate() -> f64 {
11644 0.30
11645}
11646fn default_po_rate() -> f64 {
11647 0.40
11648}
11649fn default_vi_rate() -> f64 {
11650 0.35
11651}
11652
11653impl Default for CostAllocationConfig {
11654 fn default() -> Self {
11655 Self {
11656 time_entry_project_rate: default_time_entry_rate(),
11657 expense_project_rate: default_expense_rate(),
11658 purchase_order_project_rate: default_po_rate(),
11659 vendor_invoice_project_rate: default_vi_rate(),
11660 }
11661 }
11662}
11663
11664#[derive(Debug, Clone, Serialize, Deserialize)]
11666pub struct ProjectRevenueRecognitionConfig {
11667 #[serde(default = "default_true")]
11669 pub enabled: bool,
11670 #[serde(default = "default_revenue_method")]
11672 pub method: String,
11673 #[serde(default = "default_completion_measure")]
11675 pub completion_measure: String,
11676 #[serde(default = "default_avg_contract_value")]
11678 pub avg_contract_value: f64,
11679}
11680
11681fn default_revenue_method() -> String {
11682 "percentage_of_completion".to_string()
11683}
11684fn default_completion_measure() -> String {
11685 "cost_to_cost".to_string()
11686}
11687fn default_avg_contract_value() -> f64 {
11688 500_000.0
11689}
11690
11691impl Default for ProjectRevenueRecognitionConfig {
11692 fn default() -> Self {
11693 Self {
11694 enabled: true,
11695 method: default_revenue_method(),
11696 completion_measure: default_completion_measure(),
11697 avg_contract_value: default_avg_contract_value(),
11698 }
11699 }
11700}
11701
11702#[derive(Debug, Clone, Serialize, Deserialize)]
11704pub struct MilestoneSchemaConfig {
11705 #[serde(default = "default_true")]
11707 pub enabled: bool,
11708 #[serde(default = "default_milestones_per_project")]
11710 pub avg_per_project: u32,
11711 #[serde(default = "default_payment_milestone_rate")]
11713 pub payment_milestone_rate: f64,
11714}
11715
11716fn default_milestones_per_project() -> u32 {
11717 4
11718}
11719fn default_payment_milestone_rate() -> f64 {
11720 0.50
11721}
11722
11723impl Default for MilestoneSchemaConfig {
11724 fn default() -> Self {
11725 Self {
11726 enabled: true,
11727 avg_per_project: default_milestones_per_project(),
11728 payment_milestone_rate: default_payment_milestone_rate(),
11729 }
11730 }
11731}
11732
11733#[derive(Debug, Clone, Serialize, Deserialize)]
11735pub struct ChangeOrderSchemaConfig {
11736 #[serde(default = "default_true")]
11738 pub enabled: bool,
11739 #[serde(default = "default_change_order_probability")]
11741 pub probability: f64,
11742 #[serde(default = "default_max_change_orders")]
11744 pub max_per_project: u32,
11745 #[serde(default = "default_change_order_approval_rate")]
11747 pub approval_rate: f64,
11748}
11749
11750fn default_change_order_probability() -> f64 {
11751 0.40
11752}
11753fn default_max_change_orders() -> u32 {
11754 3
11755}
11756fn default_change_order_approval_rate() -> f64 {
11757 0.75
11758}
11759
11760impl Default for ChangeOrderSchemaConfig {
11761 fn default() -> Self {
11762 Self {
11763 enabled: true,
11764 probability: default_change_order_probability(),
11765 max_per_project: default_max_change_orders(),
11766 approval_rate: default_change_order_approval_rate(),
11767 }
11768 }
11769}
11770
11771#[derive(Debug, Clone, Serialize, Deserialize)]
11773pub struct RetainageSchemaConfig {
11774 #[serde(default)]
11776 pub enabled: bool,
11777 #[serde(default = "default_retainage_pct")]
11779 pub default_percentage: f64,
11780}
11781
11782fn default_retainage_pct() -> f64 {
11783 0.10
11784}
11785
11786impl Default for RetainageSchemaConfig {
11787 fn default() -> Self {
11788 Self {
11789 enabled: false,
11790 default_percentage: default_retainage_pct(),
11791 }
11792 }
11793}
11794
11795#[derive(Debug, Clone, Serialize, Deserialize)]
11797pub struct EarnedValueSchemaConfig {
11798 #[serde(default = "default_true")]
11800 pub enabled: bool,
11801 #[serde(default = "default_evm_frequency")]
11803 pub frequency: String,
11804}
11805
11806fn default_evm_frequency() -> String {
11807 "monthly".to_string()
11808}
11809
11810impl Default for EarnedValueSchemaConfig {
11811 fn default() -> Self {
11812 Self {
11813 enabled: true,
11814 frequency: default_evm_frequency(),
11815 }
11816 }
11817}
11818
11819#[derive(Debug, Clone, Serialize, Deserialize)]
11825pub struct EsgConfig {
11826 #[serde(default)]
11828 pub enabled: bool,
11829 #[serde(default)]
11831 pub environmental: EnvironmentalConfig,
11832 #[serde(default)]
11834 pub social: SocialConfig,
11835 #[serde(default)]
11837 pub governance: GovernanceSchemaConfig,
11838 #[serde(default)]
11840 pub supply_chain_esg: SupplyChainEsgConfig,
11841 #[serde(default)]
11843 pub reporting: EsgReportingConfig,
11844 #[serde(default)]
11846 pub climate_scenarios: ClimateScenarioConfig,
11847 #[serde(default = "default_esg_anomaly_rate")]
11849 pub anomaly_rate: f64,
11850}
11851
11852fn default_esg_anomaly_rate() -> f64 {
11853 0.02
11854}
11855
11856impl Default for EsgConfig {
11857 fn default() -> Self {
11858 Self {
11859 enabled: false,
11860 environmental: EnvironmentalConfig::default(),
11861 social: SocialConfig::default(),
11862 governance: GovernanceSchemaConfig::default(),
11863 supply_chain_esg: SupplyChainEsgConfig::default(),
11864 reporting: EsgReportingConfig::default(),
11865 climate_scenarios: ClimateScenarioConfig::default(),
11866 anomaly_rate: default_esg_anomaly_rate(),
11867 }
11868 }
11869}
11870
11871#[derive(Debug, Clone, Serialize, Deserialize, Default)]
11876pub struct CountryPacksSchemaConfig {
11877 #[serde(default)]
11879 pub external_dir: Option<PathBuf>,
11880 #[serde(default)]
11884 pub overrides: std::collections::HashMap<String, serde_json::Value>,
11885}
11886
11887#[derive(Debug, Clone, Serialize, Deserialize)]
11889pub struct EnvironmentalConfig {
11890 #[serde(default = "default_true")]
11892 pub enabled: bool,
11893 #[serde(default)]
11895 pub scope1: EmissionScopeConfig,
11896 #[serde(default)]
11898 pub scope2: EmissionScopeConfig,
11899 #[serde(default)]
11901 pub scope3: Scope3Config,
11902 #[serde(default)]
11904 pub energy: EnergySchemaConfig,
11905 #[serde(default)]
11907 pub water: WaterSchemaConfig,
11908 #[serde(default)]
11910 pub waste: WasteSchemaConfig,
11911}
11912
11913impl Default for EnvironmentalConfig {
11914 fn default() -> Self {
11915 Self {
11916 enabled: true,
11917 scope1: EmissionScopeConfig::default(),
11918 scope2: EmissionScopeConfig::default(),
11919 scope3: Scope3Config::default(),
11920 energy: EnergySchemaConfig::default(),
11921 water: WaterSchemaConfig::default(),
11922 waste: WasteSchemaConfig::default(),
11923 }
11924 }
11925}
11926
11927#[derive(Debug, Clone, Serialize, Deserialize)]
11929pub struct EmissionScopeConfig {
11930 #[serde(default = "default_true")]
11932 pub enabled: bool,
11933 #[serde(default = "default_emission_region")]
11935 pub factor_region: String,
11936}
11937
11938fn default_emission_region() -> String {
11939 "US".to_string()
11940}
11941
11942impl Default for EmissionScopeConfig {
11943 fn default() -> Self {
11944 Self {
11945 enabled: true,
11946 factor_region: default_emission_region(),
11947 }
11948 }
11949}
11950
11951#[derive(Debug, Clone, Serialize, Deserialize)]
11953pub struct Scope3Config {
11954 #[serde(default = "default_true")]
11956 pub enabled: bool,
11957 #[serde(default = "default_scope3_categories")]
11959 pub categories: Vec<String>,
11960 #[serde(default = "default_spend_intensity")]
11962 pub default_spend_intensity_kg_per_usd: f64,
11963}
11964
11965fn default_scope3_categories() -> Vec<String> {
11966 vec![
11967 "purchased_goods".to_string(),
11968 "business_travel".to_string(),
11969 "employee_commuting".to_string(),
11970 ]
11971}
11972
11973fn default_spend_intensity() -> f64 {
11974 0.5
11975}
11976
11977impl Default for Scope3Config {
11978 fn default() -> Self {
11979 Self {
11980 enabled: true,
11981 categories: default_scope3_categories(),
11982 default_spend_intensity_kg_per_usd: default_spend_intensity(),
11983 }
11984 }
11985}
11986
11987#[derive(Debug, Clone, Serialize, Deserialize)]
11989pub struct EnergySchemaConfig {
11990 #[serde(default = "default_true")]
11992 pub enabled: bool,
11993 #[serde(default = "default_facility_count")]
11995 pub facility_count: u32,
11996 #[serde(default = "default_renewable_target")]
11998 pub renewable_target: f64,
11999}
12000
12001fn default_facility_count() -> u32 {
12002 5
12003}
12004
12005fn default_renewable_target() -> f64 {
12006 0.30
12007}
12008
12009impl Default for EnergySchemaConfig {
12010 fn default() -> Self {
12011 Self {
12012 enabled: true,
12013 facility_count: default_facility_count(),
12014 renewable_target: default_renewable_target(),
12015 }
12016 }
12017}
12018
12019#[derive(Debug, Clone, Serialize, Deserialize)]
12021pub struct WaterSchemaConfig {
12022 #[serde(default = "default_true")]
12024 pub enabled: bool,
12025 #[serde(default = "default_water_facility_count")]
12027 pub facility_count: u32,
12028}
12029
12030fn default_water_facility_count() -> u32 {
12031 3
12032}
12033
12034impl Default for WaterSchemaConfig {
12035 fn default() -> Self {
12036 Self {
12037 enabled: true,
12038 facility_count: default_water_facility_count(),
12039 }
12040 }
12041}
12042
12043#[derive(Debug, Clone, Serialize, Deserialize)]
12045pub struct WasteSchemaConfig {
12046 #[serde(default = "default_true")]
12048 pub enabled: bool,
12049 #[serde(default = "default_diversion_target")]
12051 pub diversion_target: f64,
12052}
12053
12054fn default_diversion_target() -> f64 {
12055 0.50
12056}
12057
12058impl Default for WasteSchemaConfig {
12059 fn default() -> Self {
12060 Self {
12061 enabled: true,
12062 diversion_target: default_diversion_target(),
12063 }
12064 }
12065}
12066
12067#[derive(Debug, Clone, Serialize, Deserialize)]
12069pub struct SocialConfig {
12070 #[serde(default = "default_true")]
12072 pub enabled: bool,
12073 #[serde(default)]
12075 pub diversity: DiversitySchemaConfig,
12076 #[serde(default)]
12078 pub pay_equity: PayEquitySchemaConfig,
12079 #[serde(default)]
12081 pub safety: SafetySchemaConfig,
12082}
12083
12084impl Default for SocialConfig {
12085 fn default() -> Self {
12086 Self {
12087 enabled: true,
12088 diversity: DiversitySchemaConfig::default(),
12089 pay_equity: PayEquitySchemaConfig::default(),
12090 safety: SafetySchemaConfig::default(),
12091 }
12092 }
12093}
12094
12095#[derive(Debug, Clone, Serialize, Deserialize)]
12097pub struct DiversitySchemaConfig {
12098 #[serde(default = "default_true")]
12100 pub enabled: bool,
12101 #[serde(default = "default_diversity_dimensions")]
12103 pub dimensions: Vec<String>,
12104}
12105
12106fn default_diversity_dimensions() -> Vec<String> {
12107 vec![
12108 "gender".to_string(),
12109 "ethnicity".to_string(),
12110 "age_group".to_string(),
12111 ]
12112}
12113
12114impl Default for DiversitySchemaConfig {
12115 fn default() -> Self {
12116 Self {
12117 enabled: true,
12118 dimensions: default_diversity_dimensions(),
12119 }
12120 }
12121}
12122
12123#[derive(Debug, Clone, Serialize, Deserialize)]
12125pub struct PayEquitySchemaConfig {
12126 #[serde(default = "default_true")]
12128 pub enabled: bool,
12129 #[serde(default = "default_pay_gap_threshold")]
12131 pub gap_threshold: f64,
12132}
12133
12134fn default_pay_gap_threshold() -> f64 {
12135 0.05
12136}
12137
12138impl Default for PayEquitySchemaConfig {
12139 fn default() -> Self {
12140 Self {
12141 enabled: true,
12142 gap_threshold: default_pay_gap_threshold(),
12143 }
12144 }
12145}
12146
12147#[derive(Debug, Clone, Serialize, Deserialize)]
12149pub struct SafetySchemaConfig {
12150 #[serde(default = "default_true")]
12152 pub enabled: bool,
12153 #[serde(default = "default_trir_target")]
12155 pub target_trir: f64,
12156 #[serde(default = "default_incident_count")]
12158 pub incident_count: u32,
12159}
12160
12161fn default_trir_target() -> f64 {
12162 2.5
12163}
12164
12165fn default_incident_count() -> u32 {
12166 20
12167}
12168
12169impl Default for SafetySchemaConfig {
12170 fn default() -> Self {
12171 Self {
12172 enabled: true,
12173 target_trir: default_trir_target(),
12174 incident_count: default_incident_count(),
12175 }
12176 }
12177}
12178
12179#[derive(Debug, Clone, Serialize, Deserialize)]
12181pub struct GovernanceSchemaConfig {
12182 #[serde(default = "default_true")]
12184 pub enabled: bool,
12185 #[serde(default = "default_board_size")]
12187 pub board_size: u32,
12188 #[serde(default = "default_independence_target")]
12190 pub independence_target: f64,
12191}
12192
12193fn default_board_size() -> u32 {
12194 11
12195}
12196
12197fn default_independence_target() -> f64 {
12198 0.67
12199}
12200
12201impl Default for GovernanceSchemaConfig {
12202 fn default() -> Self {
12203 Self {
12204 enabled: true,
12205 board_size: default_board_size(),
12206 independence_target: default_independence_target(),
12207 }
12208 }
12209}
12210
12211#[derive(Debug, Clone, Serialize, Deserialize)]
12213pub struct SupplyChainEsgConfig {
12214 #[serde(default = "default_true")]
12216 pub enabled: bool,
12217 #[serde(default = "default_assessment_coverage")]
12219 pub assessment_coverage: f64,
12220 #[serde(default = "default_high_risk_countries")]
12222 pub high_risk_countries: Vec<String>,
12223}
12224
12225fn default_assessment_coverage() -> f64 {
12226 0.80
12227}
12228
12229fn default_high_risk_countries() -> Vec<String> {
12230 vec!["CN".to_string(), "BD".to_string(), "MM".to_string()]
12231}
12232
12233impl Default for SupplyChainEsgConfig {
12234 fn default() -> Self {
12235 Self {
12236 enabled: true,
12237 assessment_coverage: default_assessment_coverage(),
12238 high_risk_countries: default_high_risk_countries(),
12239 }
12240 }
12241}
12242
12243#[derive(Debug, Clone, Serialize, Deserialize)]
12245pub struct EsgReportingConfig {
12246 #[serde(default = "default_true")]
12248 pub enabled: bool,
12249 #[serde(default = "default_esg_frameworks")]
12251 pub frameworks: Vec<String>,
12252 #[serde(default = "default_true")]
12254 pub materiality_assessment: bool,
12255 #[serde(default = "default_materiality_threshold")]
12257 pub impact_threshold: f64,
12258 #[serde(default = "default_materiality_threshold")]
12260 pub financial_threshold: f64,
12261}
12262
12263fn default_esg_frameworks() -> Vec<String> {
12264 vec!["GRI".to_string(), "ESRS".to_string()]
12265}
12266
12267fn default_materiality_threshold() -> f64 {
12268 0.6
12269}
12270
12271impl Default for EsgReportingConfig {
12272 fn default() -> Self {
12273 Self {
12274 enabled: true,
12275 frameworks: default_esg_frameworks(),
12276 materiality_assessment: true,
12277 impact_threshold: default_materiality_threshold(),
12278 financial_threshold: default_materiality_threshold(),
12279 }
12280 }
12281}
12282
12283#[derive(Debug, Clone, Serialize, Deserialize)]
12285pub struct ClimateScenarioConfig {
12286 #[serde(default)]
12288 pub enabled: bool,
12289 #[serde(default = "default_climate_scenarios")]
12291 pub scenarios: Vec<String>,
12292 #[serde(default = "default_time_horizons")]
12294 pub time_horizons: Vec<u32>,
12295}
12296
12297fn default_climate_scenarios() -> Vec<String> {
12298 vec![
12299 "net_zero_2050".to_string(),
12300 "stated_policies".to_string(),
12301 "current_trajectory".to_string(),
12302 ]
12303}
12304
12305fn default_time_horizons() -> Vec<u32> {
12306 vec![5, 10, 30]
12307}
12308
12309impl Default for ClimateScenarioConfig {
12310 fn default() -> Self {
12311 Self {
12312 enabled: false,
12313 scenarios: default_climate_scenarios(),
12314 time_horizons: default_time_horizons(),
12315 }
12316 }
12317}
12318
12319#[derive(Debug, Clone, Serialize, Deserialize, Default)]
12323pub struct ScenariosConfig {
12324 #[serde(default)]
12326 pub enabled: bool,
12327 #[serde(default)]
12329 pub scenarios: Vec<ScenarioSchemaConfig>,
12330 #[serde(default)]
12332 pub causal_model: CausalModelSchemaConfig,
12333 #[serde(default)]
12335 pub defaults: ScenarioDefaultsConfig,
12336}
12337
12338#[derive(Debug, Clone, Serialize, Deserialize)]
12340pub struct ScenarioSchemaConfig {
12341 pub name: String,
12343 #[serde(default)]
12345 pub description: String,
12346 #[serde(default)]
12348 pub tags: Vec<String>,
12349 pub base: Option<String>,
12351 pub probability_weight: Option<f64>,
12353 #[serde(default)]
12355 pub interventions: Vec<InterventionSchemaConfig>,
12356 #[serde(default)]
12358 pub constraints: ScenarioConstraintsSchemaConfig,
12359 #[serde(default)]
12361 pub output: ScenarioOutputSchemaConfig,
12362 #[serde(default)]
12364 pub metadata: std::collections::HashMap<String, String>,
12365}
12366
12367#[derive(Debug, Clone, Serialize, Deserialize)]
12369pub struct InterventionSchemaConfig {
12370 #[serde(flatten)]
12372 pub intervention_type: serde_json::Value,
12373 #[serde(default)]
12375 pub timing: InterventionTimingSchemaConfig,
12376 pub label: Option<String>,
12378 #[serde(default)]
12380 pub priority: u32,
12381}
12382
12383#[derive(Debug, Clone, Serialize, Deserialize)]
12385pub struct InterventionTimingSchemaConfig {
12386 #[serde(default = "default_start_month")]
12388 pub start_month: u32,
12389 pub duration_months: Option<u32>,
12391 #[serde(default = "default_onset")]
12393 pub onset: String,
12394 pub ramp_months: Option<u32>,
12396}
12397
12398fn default_start_month() -> u32 {
12399 1
12400}
12401
12402fn default_onset() -> String {
12403 "sudden".to_string()
12404}
12405
12406impl Default for InterventionTimingSchemaConfig {
12407 fn default() -> Self {
12408 Self {
12409 start_month: 1,
12410 duration_months: None,
12411 onset: "sudden".to_string(),
12412 ramp_months: None,
12413 }
12414 }
12415}
12416
12417#[derive(Debug, Clone, Serialize, Deserialize)]
12419pub struct ScenarioConstraintsSchemaConfig {
12420 #[serde(default = "default_true")]
12421 pub preserve_accounting_identity: bool,
12422 #[serde(default = "default_true")]
12423 pub preserve_document_chains: bool,
12424 #[serde(default = "default_true")]
12425 pub preserve_period_close: bool,
12426 #[serde(default = "default_true")]
12427 pub preserve_balance_coherence: bool,
12428 #[serde(default)]
12429 pub custom: Vec<CustomConstraintSchemaConfig>,
12430}
12431
12432impl Default for ScenarioConstraintsSchemaConfig {
12433 fn default() -> Self {
12434 Self {
12435 preserve_accounting_identity: true,
12436 preserve_document_chains: true,
12437 preserve_period_close: true,
12438 preserve_balance_coherence: true,
12439 custom: Vec::new(),
12440 }
12441 }
12442}
12443
12444#[derive(Debug, Clone, Serialize, Deserialize)]
12446pub struct CustomConstraintSchemaConfig {
12447 pub config_path: String,
12448 pub min: Option<f64>,
12449 pub max: Option<f64>,
12450 #[serde(default)]
12451 pub description: String,
12452}
12453
12454#[derive(Debug, Clone, Serialize, Deserialize)]
12456pub struct ScenarioOutputSchemaConfig {
12457 #[serde(default = "default_true")]
12458 pub paired: bool,
12459 #[serde(default = "default_diff_formats_schema")]
12460 pub diff_formats: Vec<String>,
12461 #[serde(default)]
12462 pub diff_scope: Vec<String>,
12463}
12464
12465fn default_diff_formats_schema() -> Vec<String> {
12466 vec!["summary".to_string(), "aggregate".to_string()]
12467}
12468
12469impl Default for ScenarioOutputSchemaConfig {
12470 fn default() -> Self {
12471 Self {
12472 paired: true,
12473 diff_formats: default_diff_formats_schema(),
12474 diff_scope: Vec::new(),
12475 }
12476 }
12477}
12478
12479#[derive(Debug, Clone, Serialize, Deserialize)]
12481pub struct CausalModelSchemaConfig {
12482 #[serde(default = "default_causal_preset")]
12484 pub preset: String,
12485 #[serde(default)]
12487 pub nodes: Vec<serde_json::Value>,
12488 #[serde(default)]
12490 pub edges: Vec<serde_json::Value>,
12491}
12492
12493fn default_causal_preset() -> String {
12494 "default".to_string()
12495}
12496
12497impl Default for CausalModelSchemaConfig {
12498 fn default() -> Self {
12499 Self {
12500 preset: "default".to_string(),
12501 nodes: Vec::new(),
12502 edges: Vec::new(),
12503 }
12504 }
12505}
12506
12507#[derive(Debug, Clone, Serialize, Deserialize, Default)]
12509pub struct ScenarioDefaultsConfig {
12510 #[serde(default)]
12511 pub constraints: ScenarioConstraintsSchemaConfig,
12512 #[serde(default)]
12513 pub output: ScenarioOutputSchemaConfig,
12514}
12515
12516#[derive(Debug, Clone, Default, Serialize, Deserialize)]
12549pub struct ComplianceRegulationsConfig {
12550 #[serde(default)]
12552 pub enabled: bool,
12553 #[serde(default)]
12556 pub jurisdictions: Vec<String>,
12557 #[serde(default)]
12560 pub reference_date: Option<String>,
12561 #[serde(default)]
12563 pub standards_selection: StandardsSelectionConfig,
12564 #[serde(default)]
12566 pub audit_procedures: AuditProcedureGenConfig,
12567 #[serde(default)]
12569 pub findings: ComplianceFindingGenConfig,
12570 #[serde(default)]
12572 pub filings: ComplianceFilingGenConfig,
12573 #[serde(default)]
12575 pub graph: ComplianceGraphConfig,
12576 #[serde(default)]
12578 pub output: ComplianceOutputConfig,
12579}
12580
12581#[derive(Debug, Clone, Default, Serialize, Deserialize)]
12583pub struct StandardsSelectionConfig {
12584 #[serde(default)]
12587 pub categories: Vec<String>,
12588 #[serde(default)]
12591 pub include: Vec<String>,
12592 #[serde(default)]
12594 pub exclude: Vec<String>,
12595 #[serde(default)]
12597 pub include_superseded: bool,
12598}
12599
12600#[derive(Debug, Clone, Serialize, Deserialize)]
12602pub struct AuditProcedureGenConfig {
12603 #[serde(default)]
12605 pub enabled: bool,
12606 #[serde(default = "default_procedures_per_standard")]
12608 pub procedures_per_standard: usize,
12609 #[serde(default = "default_sampling_method")]
12611 pub sampling_method: String,
12612 #[serde(default = "default_confidence_level")]
12614 pub confidence_level: f64,
12615 #[serde(default = "default_tolerable_misstatement")]
12617 pub tolerable_misstatement: f64,
12618}
12619
12620fn default_procedures_per_standard() -> usize {
12621 3
12622}
12623
12624fn default_sampling_method() -> String {
12625 "statistical".to_string()
12626}
12627
12628fn default_confidence_level() -> f64 {
12629 0.95
12630}
12631
12632fn default_tolerable_misstatement() -> f64 {
12633 0.05
12634}
12635
12636impl Default for AuditProcedureGenConfig {
12637 fn default() -> Self {
12638 Self {
12639 enabled: false,
12640 procedures_per_standard: default_procedures_per_standard(),
12641 sampling_method: default_sampling_method(),
12642 confidence_level: default_confidence_level(),
12643 tolerable_misstatement: default_tolerable_misstatement(),
12644 }
12645 }
12646}
12647
12648#[derive(Debug, Clone, Serialize, Deserialize)]
12650pub struct ComplianceFindingGenConfig {
12651 #[serde(default)]
12653 pub enabled: bool,
12654 #[serde(default = "default_finding_rate")]
12656 pub finding_rate: f64,
12657 #[serde(default = "default_cr_material_weakness_rate")]
12659 pub material_weakness_rate: f64,
12660 #[serde(default = "default_cr_significant_deficiency_rate")]
12662 pub significant_deficiency_rate: f64,
12663 #[serde(default = "default_true")]
12665 pub generate_remediation: bool,
12666}
12667
12668fn default_finding_rate() -> f64 {
12669 0.05
12670}
12671
12672fn default_cr_material_weakness_rate() -> f64 {
12673 0.02
12674}
12675
12676fn default_cr_significant_deficiency_rate() -> f64 {
12677 0.08
12678}
12679
12680impl Default for ComplianceFindingGenConfig {
12681 fn default() -> Self {
12682 Self {
12683 enabled: false,
12684 finding_rate: default_finding_rate(),
12685 material_weakness_rate: default_cr_material_weakness_rate(),
12686 significant_deficiency_rate: default_cr_significant_deficiency_rate(),
12687 generate_remediation: true,
12688 }
12689 }
12690}
12691
12692#[derive(Debug, Clone, Serialize, Deserialize)]
12694pub struct ComplianceFilingGenConfig {
12695 #[serde(default)]
12697 pub enabled: bool,
12698 #[serde(default)]
12701 pub filing_types: Vec<String>,
12702 #[serde(default = "default_true")]
12704 pub generate_status_progression: bool,
12705}
12706
12707impl Default for ComplianceFilingGenConfig {
12708 fn default() -> Self {
12709 Self {
12710 enabled: false,
12711 filing_types: Vec::new(),
12712 generate_status_progression: true,
12713 }
12714 }
12715}
12716
12717#[derive(Debug, Clone, Serialize, Deserialize)]
12719pub struct ComplianceGraphConfig {
12720 #[serde(default)]
12722 pub enabled: bool,
12723 #[serde(default = "default_true")]
12725 pub include_compliance_nodes: bool,
12726 #[serde(default = "default_true")]
12728 pub include_compliance_edges: bool,
12729 #[serde(default = "default_true")]
12731 pub include_cross_references: bool,
12732 #[serde(default)]
12734 pub include_supersession_edges: bool,
12735 #[serde(default = "default_true")]
12737 pub include_account_links: bool,
12738 #[serde(default = "default_true")]
12740 pub include_control_links: bool,
12741 #[serde(default = "default_true")]
12743 pub include_company_links: bool,
12744}
12745
12746impl Default for ComplianceGraphConfig {
12747 fn default() -> Self {
12748 Self {
12749 enabled: false,
12750 include_compliance_nodes: true,
12751 include_compliance_edges: true,
12752 include_cross_references: true,
12753 include_supersession_edges: false,
12754 include_account_links: true,
12755 include_control_links: true,
12756 include_company_links: true,
12757 }
12758 }
12759}
12760
12761#[derive(Debug, Clone, Serialize, Deserialize)]
12763pub struct ComplianceOutputConfig {
12764 #[serde(default = "default_true")]
12766 pub export_registry: bool,
12767 #[serde(default = "default_true")]
12769 pub export_jurisdictions: bool,
12770 #[serde(default = "default_true")]
12772 pub export_cross_references: bool,
12773 #[serde(default)]
12775 pub export_version_history: bool,
12776}
12777
12778impl Default for ComplianceOutputConfig {
12779 fn default() -> Self {
12780 Self {
12781 export_registry: true,
12782 export_jurisdictions: true,
12783 export_cross_references: true,
12784 export_version_history: false,
12785 }
12786 }
12787}
12788
12789#[cfg(test)]
12790#[allow(clippy::unwrap_used)]
12791mod tests {
12792 use super::*;
12793 use crate::presets::demo_preset;
12794
12795 #[test]
12800 fn test_config_yaml_roundtrip() {
12801 let config = demo_preset();
12802 let yaml = serde_yaml::to_string(&config).expect("Failed to serialize to YAML");
12803 let deserialized: GeneratorConfig =
12804 serde_yaml::from_str(&yaml).expect("Failed to deserialize from YAML");
12805
12806 assert_eq!(
12807 config.global.period_months,
12808 deserialized.global.period_months
12809 );
12810 assert_eq!(config.global.industry, deserialized.global.industry);
12811 assert_eq!(config.companies.len(), deserialized.companies.len());
12812 assert_eq!(config.companies[0].code, deserialized.companies[0].code);
12813 }
12814
12815 #[test]
12816 fn test_config_json_roundtrip() {
12817 let mut config = demo_preset();
12819 config.master_data.employees.approval_limits.executive = 1e12;
12821
12822 let json = serde_json::to_string(&config).expect("Failed to serialize to JSON");
12823 let deserialized: GeneratorConfig =
12824 serde_json::from_str(&json).expect("Failed to deserialize from JSON");
12825
12826 assert_eq!(
12827 config.global.period_months,
12828 deserialized.global.period_months
12829 );
12830 assert_eq!(config.global.industry, deserialized.global.industry);
12831 assert_eq!(config.companies.len(), deserialized.companies.len());
12832 }
12833
12834 #[test]
12835 fn test_transaction_volume_serialization() {
12836 let volumes = vec![
12838 (TransactionVolume::TenK, "ten_k"),
12839 (TransactionVolume::HundredK, "hundred_k"),
12840 (TransactionVolume::OneM, "one_m"),
12841 (TransactionVolume::TenM, "ten_m"),
12842 (TransactionVolume::HundredM, "hundred_m"),
12843 ];
12844
12845 for (volume, expected_key) in volumes {
12846 let json = serde_json::to_string(&volume).expect("Failed to serialize");
12847 assert!(
12848 json.contains(expected_key),
12849 "Expected {} in JSON: {}",
12850 expected_key,
12851 json
12852 );
12853 }
12854 }
12855
12856 #[test]
12857 fn test_transaction_volume_custom_serialization() {
12858 let volume = TransactionVolume::Custom(12345);
12859 let json = serde_json::to_string(&volume).expect("Failed to serialize");
12860 let deserialized: TransactionVolume =
12861 serde_json::from_str(&json).expect("Failed to deserialize");
12862 assert_eq!(deserialized.count(), 12345);
12863 }
12864
12865 #[test]
12866 fn test_output_mode_serialization() {
12867 let modes = vec![
12868 OutputMode::Streaming,
12869 OutputMode::FlatFile,
12870 OutputMode::Both,
12871 ];
12872
12873 for mode in modes {
12874 let json = serde_json::to_string(&mode).expect("Failed to serialize");
12875 let deserialized: OutputMode =
12876 serde_json::from_str(&json).expect("Failed to deserialize");
12877 assert!(format!("{:?}", mode) == format!("{:?}", deserialized));
12878 }
12879 }
12880
12881 #[test]
12882 fn test_file_format_serialization() {
12883 let formats = vec![
12884 FileFormat::Csv,
12885 FileFormat::Parquet,
12886 FileFormat::Json,
12887 FileFormat::JsonLines,
12888 ];
12889
12890 for format in formats {
12891 let json = serde_json::to_string(&format).expect("Failed to serialize");
12892 let deserialized: FileFormat =
12893 serde_json::from_str(&json).expect("Failed to deserialize");
12894 assert!(format!("{:?}", format) == format!("{:?}", deserialized));
12895 }
12896 }
12897
12898 #[test]
12899 fn test_compression_algorithm_serialization() {
12900 let algos = vec![
12901 CompressionAlgorithm::Gzip,
12902 CompressionAlgorithm::Zstd,
12903 CompressionAlgorithm::Lz4,
12904 CompressionAlgorithm::Snappy,
12905 ];
12906
12907 for algo in algos {
12908 let json = serde_json::to_string(&algo).expect("Failed to serialize");
12909 let deserialized: CompressionAlgorithm =
12910 serde_json::from_str(&json).expect("Failed to deserialize");
12911 assert!(format!("{:?}", algo) == format!("{:?}", deserialized));
12912 }
12913 }
12914
12915 #[test]
12916 fn test_transfer_pricing_method_serialization() {
12917 let methods = vec![
12918 TransferPricingMethod::CostPlus,
12919 TransferPricingMethod::ComparableUncontrolled,
12920 TransferPricingMethod::ResalePrice,
12921 TransferPricingMethod::TransactionalNetMargin,
12922 TransferPricingMethod::ProfitSplit,
12923 ];
12924
12925 for method in methods {
12926 let json = serde_json::to_string(&method).expect("Failed to serialize");
12927 let deserialized: TransferPricingMethod =
12928 serde_json::from_str(&json).expect("Failed to deserialize");
12929 assert!(format!("{:?}", method) == format!("{:?}", deserialized));
12930 }
12931 }
12932
12933 #[test]
12934 fn test_benford_exemption_serialization() {
12935 let exemptions = vec![
12936 BenfordExemption::Recurring,
12937 BenfordExemption::Payroll,
12938 BenfordExemption::FixedFees,
12939 BenfordExemption::RoundAmounts,
12940 ];
12941
12942 for exemption in exemptions {
12943 let json = serde_json::to_string(&exemption).expect("Failed to serialize");
12944 let deserialized: BenfordExemption =
12945 serde_json::from_str(&json).expect("Failed to deserialize");
12946 assert!(format!("{:?}", exemption) == format!("{:?}", deserialized));
12947 }
12948 }
12949
12950 #[test]
12955 fn test_global_config_defaults() {
12956 let yaml = r#"
12957 industry: manufacturing
12958 start_date: "2024-01-01"
12959 period_months: 6
12960 "#;
12961 let config: GlobalConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12962 assert_eq!(config.group_currency, "USD");
12963 assert!(config.parallel);
12964 assert_eq!(config.worker_threads, 0);
12965 assert_eq!(config.memory_limit_mb, 0);
12966 }
12967
12968 #[test]
12969 fn test_fraud_config_defaults() {
12970 let config = FraudConfig::default();
12971 assert!(!config.enabled);
12972 assert_eq!(config.fraud_rate, 0.005);
12973 assert!(!config.clustering_enabled);
12974 }
12975
12976 #[test]
12977 fn test_internal_controls_config_defaults() {
12978 let config = InternalControlsConfig::default();
12979 assert!(!config.enabled);
12980 assert_eq!(config.exception_rate, 0.02);
12981 assert_eq!(config.sod_violation_rate, 0.01);
12982 assert!(config.export_control_master_data);
12983 assert_eq!(config.sox_materiality_threshold, 10000.0);
12984 assert!(config.coso_enabled);
12986 assert!(!config.include_entity_level_controls);
12987 assert_eq!(config.target_maturity_level, "mixed");
12988 }
12989
12990 #[test]
12991 fn test_output_config_defaults() {
12992 let config = OutputConfig::default();
12993 assert!(matches!(config.mode, OutputMode::FlatFile));
12994 assert_eq!(config.formats, vec![FileFormat::Parquet]);
12995 assert!(config.compression.enabled);
12996 assert!(matches!(
12997 config.compression.algorithm,
12998 CompressionAlgorithm::Zstd
12999 ));
13000 assert!(config.include_acdoca);
13001 assert!(!config.include_bseg);
13002 assert!(config.partition_by_period);
13003 assert!(!config.partition_by_company);
13004 }
13005
13006 #[test]
13007 fn test_approval_config_defaults() {
13008 let config = ApprovalConfig::default();
13009 assert!(!config.enabled);
13010 assert_eq!(config.auto_approve_threshold, 1000.0);
13011 assert_eq!(config.rejection_rate, 0.02);
13012 assert_eq!(config.revision_rate, 0.05);
13013 assert_eq!(config.average_approval_delay_hours, 4.0);
13014 assert_eq!(config.thresholds.len(), 4);
13015 }
13016
13017 #[test]
13018 fn test_p2p_flow_config_defaults() {
13019 let config = P2PFlowConfig::default();
13020 assert!(config.enabled);
13021 assert_eq!(config.three_way_match_rate, 0.95);
13022 assert_eq!(config.partial_delivery_rate, 0.15);
13023 assert_eq!(config.average_po_to_gr_days, 14);
13024 }
13025
13026 #[test]
13027 fn test_o2c_flow_config_defaults() {
13028 let config = O2CFlowConfig::default();
13029 assert!(config.enabled);
13030 assert_eq!(config.credit_check_failure_rate, 0.02);
13031 assert_eq!(config.return_rate, 0.03);
13032 assert_eq!(config.bad_debt_rate, 0.01);
13033 }
13034
13035 #[test]
13036 fn test_balance_config_defaults() {
13037 let config = BalanceConfig::default();
13038 assert!(!config.generate_opening_balances);
13039 assert!(config.generate_trial_balances);
13040 assert_eq!(config.target_gross_margin, 0.35);
13041 assert!(config.validate_balance_equation);
13042 assert!(config.reconcile_subledgers);
13043 }
13044
13045 #[test]
13050 fn test_partial_config_with_defaults() {
13051 let yaml = r#"
13053 global:
13054 industry: manufacturing
13055 start_date: "2024-01-01"
13056 period_months: 3
13057 companies:
13058 - code: "TEST"
13059 name: "Test Company"
13060 currency: "USD"
13061 country: "US"
13062 annual_transaction_volume: ten_k
13063 chart_of_accounts:
13064 complexity: small
13065 output:
13066 output_directory: "./output"
13067 "#;
13068
13069 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13070 assert_eq!(config.global.period_months, 3);
13071 assert_eq!(config.companies.len(), 1);
13072 assert!(!config.fraud.enabled); assert!(!config.internal_controls.enabled); }
13075
13076 #[test]
13077 fn test_config_with_fraud_enabled() {
13078 let yaml = r#"
13079 global:
13080 industry: retail
13081 start_date: "2024-01-01"
13082 period_months: 12
13083 companies:
13084 - code: "RETAIL"
13085 name: "Retail Co"
13086 currency: "USD"
13087 country: "US"
13088 annual_transaction_volume: hundred_k
13089 chart_of_accounts:
13090 complexity: medium
13091 output:
13092 output_directory: "./output"
13093 fraud:
13094 enabled: true
13095 fraud_rate: 0.05
13096 clustering_enabled: true
13097 "#;
13098
13099 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13100 assert!(config.fraud.enabled);
13101 assert_eq!(config.fraud.fraud_rate, 0.05);
13102 assert!(config.fraud.clustering_enabled);
13103 }
13104
13105 #[test]
13106 fn test_config_with_multiple_companies() {
13107 let yaml = r#"
13108 global:
13109 industry: manufacturing
13110 start_date: "2024-01-01"
13111 period_months: 6
13112 companies:
13113 - code: "HQ"
13114 name: "Headquarters"
13115 currency: "USD"
13116 country: "US"
13117 annual_transaction_volume: hundred_k
13118 volume_weight: 1.0
13119 - code: "EU"
13120 name: "European Subsidiary"
13121 currency: "EUR"
13122 country: "DE"
13123 annual_transaction_volume: hundred_k
13124 volume_weight: 0.5
13125 - code: "APAC"
13126 name: "Asia Pacific"
13127 currency: "JPY"
13128 country: "JP"
13129 annual_transaction_volume: ten_k
13130 volume_weight: 0.3
13131 chart_of_accounts:
13132 complexity: large
13133 output:
13134 output_directory: "./output"
13135 "#;
13136
13137 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13138 assert_eq!(config.companies.len(), 3);
13139 assert_eq!(config.companies[0].code, "HQ");
13140 assert_eq!(config.companies[1].currency, "EUR");
13141 assert_eq!(config.companies[2].volume_weight, 0.3);
13142 }
13143
13144 #[test]
13145 fn test_intercompany_config() {
13146 let yaml = r#"
13147 enabled: true
13148 ic_transaction_rate: 0.20
13149 transfer_pricing_method: cost_plus
13150 markup_percent: 0.08
13151 generate_matched_pairs: true
13152 generate_eliminations: true
13153 "#;
13154
13155 let config: IntercompanyConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13156 assert!(config.enabled);
13157 assert_eq!(config.ic_transaction_rate, 0.20);
13158 assert!(matches!(
13159 config.transfer_pricing_method,
13160 TransferPricingMethod::CostPlus
13161 ));
13162 assert_eq!(config.markup_percent, 0.08);
13163 assert!(config.generate_eliminations);
13164 }
13165
13166 #[test]
13171 fn test_company_config_defaults() {
13172 let yaml = r#"
13173 code: "TEST"
13174 name: "Test Company"
13175 currency: "USD"
13176 country: "US"
13177 annual_transaction_volume: ten_k
13178 "#;
13179
13180 let config: CompanyConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13181 assert_eq!(config.fiscal_year_variant, "K4"); assert_eq!(config.volume_weight, 1.0); }
13184
13185 #[test]
13190 fn test_coa_config_defaults() {
13191 let yaml = r#"
13192 complexity: medium
13193 "#;
13194
13195 let config: ChartOfAccountsConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13196 assert!(config.industry_specific); assert!(config.custom_accounts.is_none());
13198 assert_eq!(config.min_hierarchy_depth, 2); assert_eq!(config.max_hierarchy_depth, 5); }
13201
13202 #[test]
13207 fn test_accounting_standards_config_defaults() {
13208 let config = AccountingStandardsConfig::default();
13209 assert!(!config.enabled);
13210 assert!(config.framework.is_none());
13211 assert!(!config.revenue_recognition.enabled);
13212 assert!(!config.leases.enabled);
13213 assert!(!config.fair_value.enabled);
13214 assert!(!config.impairment.enabled);
13215 assert!(!config.generate_differences);
13216 }
13217
13218 #[test]
13219 fn test_accounting_standards_config_yaml() {
13220 let yaml = r#"
13221 enabled: true
13222 framework: ifrs
13223 revenue_recognition:
13224 enabled: true
13225 generate_contracts: true
13226 avg_obligations_per_contract: 2.5
13227 variable_consideration_rate: 0.20
13228 over_time_recognition_rate: 0.35
13229 contract_count: 150
13230 leases:
13231 enabled: true
13232 lease_count: 75
13233 finance_lease_percent: 0.25
13234 avg_lease_term_months: 48
13235 generate_differences: true
13236 "#;
13237
13238 let config: AccountingStandardsConfig =
13239 serde_yaml::from_str(yaml).expect("Failed to parse");
13240 assert!(config.enabled);
13241 assert!(matches!(
13242 config.framework,
13243 Some(AccountingFrameworkConfig::Ifrs)
13244 ));
13245 assert!(config.revenue_recognition.enabled);
13246 assert_eq!(config.revenue_recognition.contract_count, 150);
13247 assert_eq!(config.revenue_recognition.avg_obligations_per_contract, 2.5);
13248 assert!(config.leases.enabled);
13249 assert_eq!(config.leases.lease_count, 75);
13250 assert_eq!(config.leases.finance_lease_percent, 0.25);
13251 assert!(config.generate_differences);
13252 }
13253
13254 #[test]
13255 fn test_accounting_framework_serialization() {
13256 let frameworks = [
13257 AccountingFrameworkConfig::UsGaap,
13258 AccountingFrameworkConfig::Ifrs,
13259 AccountingFrameworkConfig::DualReporting,
13260 AccountingFrameworkConfig::FrenchGaap,
13261 AccountingFrameworkConfig::GermanGaap,
13262 ];
13263
13264 for framework in frameworks {
13265 let json = serde_json::to_string(&framework).expect("Failed to serialize");
13266 let deserialized: AccountingFrameworkConfig =
13267 serde_json::from_str(&json).expect("Failed to deserialize");
13268 assert!(format!("{:?}", framework) == format!("{:?}", deserialized));
13269 }
13270 }
13271
13272 #[test]
13273 fn test_revenue_recognition_config_defaults() {
13274 let config = RevenueRecognitionConfig::default();
13275 assert!(!config.enabled);
13276 assert!(config.generate_contracts);
13277 assert_eq!(config.avg_obligations_per_contract, 2.0);
13278 assert_eq!(config.variable_consideration_rate, 0.15);
13279 assert_eq!(config.over_time_recognition_rate, 0.30);
13280 assert_eq!(config.contract_count, 100);
13281 }
13282
13283 #[test]
13284 fn test_lease_accounting_config_defaults() {
13285 let config = LeaseAccountingConfig::default();
13286 assert!(!config.enabled);
13287 assert_eq!(config.lease_count, 50);
13288 assert_eq!(config.finance_lease_percent, 0.30);
13289 assert_eq!(config.avg_lease_term_months, 60);
13290 assert!(config.generate_amortization);
13291 assert_eq!(config.real_estate_percent, 0.40);
13292 }
13293
13294 #[test]
13295 fn test_fair_value_config_defaults() {
13296 let config = FairValueConfig::default();
13297 assert!(!config.enabled);
13298 assert_eq!(config.measurement_count, 25);
13299 assert_eq!(config.level1_percent, 0.40);
13300 assert_eq!(config.level2_percent, 0.35);
13301 assert_eq!(config.level3_percent, 0.25);
13302 assert!(!config.include_sensitivity_analysis);
13303 }
13304
13305 #[test]
13306 fn test_impairment_config_defaults() {
13307 let config = ImpairmentConfig::default();
13308 assert!(!config.enabled);
13309 assert_eq!(config.test_count, 15);
13310 assert_eq!(config.impairment_rate, 0.10);
13311 assert!(config.generate_projections);
13312 assert!(!config.include_goodwill);
13313 }
13314
13315 #[test]
13320 fn test_audit_standards_config_defaults() {
13321 let config = AuditStandardsConfig::default();
13322 assert!(!config.enabled);
13323 assert!(!config.isa_compliance.enabled);
13324 assert!(!config.analytical_procedures.enabled);
13325 assert!(!config.confirmations.enabled);
13326 assert!(!config.opinion.enabled);
13327 assert!(!config.generate_audit_trail);
13328 assert!(!config.sox.enabled);
13329 assert!(!config.pcaob.enabled);
13330 }
13331
13332 #[test]
13333 fn test_audit_standards_config_yaml() {
13334 let yaml = r#"
13335 enabled: true
13336 isa_compliance:
13337 enabled: true
13338 compliance_level: comprehensive
13339 generate_isa_mappings: true
13340 include_pcaob: true
13341 framework: dual
13342 analytical_procedures:
13343 enabled: true
13344 procedures_per_account: 5
13345 variance_probability: 0.25
13346 confirmations:
13347 enabled: true
13348 confirmation_count: 75
13349 positive_response_rate: 0.90
13350 exception_rate: 0.08
13351 opinion:
13352 enabled: true
13353 generate_kam: true
13354 average_kam_count: 4
13355 sox:
13356 enabled: true
13357 generate_302_certifications: true
13358 generate_404_assessments: true
13359 material_weakness_rate: 0.03
13360 pcaob:
13361 enabled: true
13362 is_pcaob_audit: true
13363 include_icfr_opinion: true
13364 generate_audit_trail: true
13365 "#;
13366
13367 let config: AuditStandardsConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13368 assert!(config.enabled);
13369 assert!(config.isa_compliance.enabled);
13370 assert_eq!(config.isa_compliance.compliance_level, "comprehensive");
13371 assert!(config.isa_compliance.include_pcaob);
13372 assert_eq!(config.isa_compliance.framework, "dual");
13373 assert!(config.analytical_procedures.enabled);
13374 assert_eq!(config.analytical_procedures.procedures_per_account, 5);
13375 assert!(config.confirmations.enabled);
13376 assert_eq!(config.confirmations.confirmation_count, 75);
13377 assert!(config.opinion.enabled);
13378 assert_eq!(config.opinion.average_kam_count, 4);
13379 assert!(config.sox.enabled);
13380 assert!(config.sox.generate_302_certifications);
13381 assert_eq!(config.sox.material_weakness_rate, 0.03);
13382 assert!(config.pcaob.enabled);
13383 assert!(config.pcaob.is_pcaob_audit);
13384 assert!(config.pcaob.include_icfr_opinion);
13385 assert!(config.generate_audit_trail);
13386 }
13387
13388 #[test]
13389 fn test_isa_compliance_config_defaults() {
13390 let config = IsaComplianceConfig::default();
13391 assert!(!config.enabled);
13392 assert_eq!(config.compliance_level, "standard");
13393 assert!(config.generate_isa_mappings);
13394 assert!(config.generate_coverage_summary);
13395 assert!(!config.include_pcaob);
13396 assert_eq!(config.framework, "isa");
13397 }
13398
13399 #[test]
13400 fn test_sox_compliance_config_defaults() {
13401 let config = SoxComplianceConfig::default();
13402 assert!(!config.enabled);
13403 assert!(config.generate_302_certifications);
13404 assert!(config.generate_404_assessments);
13405 assert_eq!(config.materiality_threshold, 10000.0);
13406 assert_eq!(config.material_weakness_rate, 0.02);
13407 assert_eq!(config.significant_deficiency_rate, 0.08);
13408 }
13409
13410 #[test]
13411 fn test_pcaob_config_defaults() {
13412 let config = PcaobConfig::default();
13413 assert!(!config.enabled);
13414 assert!(!config.is_pcaob_audit);
13415 assert!(config.generate_cam);
13416 assert!(!config.include_icfr_opinion);
13417 assert!(!config.generate_standard_mappings);
13418 }
13419
13420 #[test]
13421 fn test_config_with_standards_enabled() {
13422 let yaml = r#"
13423 global:
13424 industry: financial_services
13425 start_date: "2024-01-01"
13426 period_months: 12
13427 companies:
13428 - code: "BANK"
13429 name: "Test Bank"
13430 currency: "USD"
13431 country: "US"
13432 annual_transaction_volume: hundred_k
13433 chart_of_accounts:
13434 complexity: large
13435 output:
13436 output_directory: "./output"
13437 accounting_standards:
13438 enabled: true
13439 framework: us_gaap
13440 revenue_recognition:
13441 enabled: true
13442 leases:
13443 enabled: true
13444 audit_standards:
13445 enabled: true
13446 isa_compliance:
13447 enabled: true
13448 sox:
13449 enabled: true
13450 "#;
13451
13452 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13453 assert!(config.accounting_standards.enabled);
13454 assert!(matches!(
13455 config.accounting_standards.framework,
13456 Some(AccountingFrameworkConfig::UsGaap)
13457 ));
13458 assert!(config.accounting_standards.revenue_recognition.enabled);
13459 assert!(config.accounting_standards.leases.enabled);
13460 assert!(config.audit_standards.enabled);
13461 assert!(config.audit_standards.isa_compliance.enabled);
13462 assert!(config.audit_standards.sox.enabled);
13463 }
13464
13465 #[test]
13470 fn test_industry_specific_config_defaults() {
13471 let config = IndustrySpecificConfig::default();
13472 assert!(!config.enabled);
13473 assert!(!config.manufacturing.enabled);
13474 assert!(!config.retail.enabled);
13475 assert!(!config.healthcare.enabled);
13476 assert!(!config.technology.enabled);
13477 assert!(!config.financial_services.enabled);
13478 assert!(!config.professional_services.enabled);
13479 }
13480
13481 #[test]
13482 fn test_manufacturing_config_defaults() {
13483 let config = ManufacturingConfig::default();
13484 assert!(!config.enabled);
13485 assert_eq!(config.bom_depth, 4);
13486 assert!(!config.just_in_time);
13487 assert_eq!(config.supplier_tiers, 2);
13488 assert_eq!(config.target_yield_rate, 0.97);
13489 assert_eq!(config.scrap_alert_threshold, 0.03);
13490 }
13491
13492 #[test]
13493 fn test_retail_config_defaults() {
13494 let config = RetailConfig::default();
13495 assert!(!config.enabled);
13496 assert_eq!(config.avg_daily_transactions, 500);
13497 assert!(config.loss_prevention);
13498 assert_eq!(config.shrinkage_rate, 0.015);
13499 }
13500
13501 #[test]
13502 fn test_healthcare_config_defaults() {
13503 let config = HealthcareConfig::default();
13504 assert!(!config.enabled);
13505 assert_eq!(config.facility_type, "hospital");
13506 assert_eq!(config.avg_daily_encounters, 150);
13507 assert!(config.compliance.hipaa);
13508 assert!(config.compliance.stark_law);
13509 assert!(config.coding_systems.icd10);
13510 assert!(config.coding_systems.cpt);
13511 }
13512
13513 #[test]
13514 fn test_technology_config_defaults() {
13515 let config = TechnologyConfig::default();
13516 assert!(!config.enabled);
13517 assert_eq!(config.revenue_model, "saas");
13518 assert_eq!(config.subscription_revenue_pct, 0.60);
13519 assert!(config.rd_capitalization.enabled);
13520 }
13521
13522 #[test]
13523 fn test_config_with_industry_specific() {
13524 let yaml = r#"
13525 global:
13526 industry: healthcare
13527 start_date: "2024-01-01"
13528 period_months: 12
13529 companies:
13530 - code: "HOSP"
13531 name: "Test Hospital"
13532 currency: "USD"
13533 country: "US"
13534 annual_transaction_volume: hundred_k
13535 chart_of_accounts:
13536 complexity: medium
13537 output:
13538 output_directory: "./output"
13539 industry_specific:
13540 enabled: true
13541 healthcare:
13542 enabled: true
13543 facility_type: hospital
13544 payer_mix:
13545 medicare: 0.45
13546 medicaid: 0.15
13547 commercial: 0.35
13548 self_pay: 0.05
13549 coding_systems:
13550 icd10: true
13551 cpt: true
13552 drg: true
13553 compliance:
13554 hipaa: true
13555 stark_law: true
13556 anomaly_rates:
13557 upcoding: 0.03
13558 unbundling: 0.02
13559 "#;
13560
13561 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13562 assert!(config.industry_specific.enabled);
13563 assert!(config.industry_specific.healthcare.enabled);
13564 assert_eq!(
13565 config.industry_specific.healthcare.facility_type,
13566 "hospital"
13567 );
13568 assert_eq!(config.industry_specific.healthcare.payer_mix.medicare, 0.45);
13569 assert_eq!(config.industry_specific.healthcare.payer_mix.self_pay, 0.05);
13570 assert!(config.industry_specific.healthcare.coding_systems.icd10);
13571 assert!(config.industry_specific.healthcare.compliance.hipaa);
13572 assert_eq!(
13573 config.industry_specific.healthcare.anomaly_rates.upcoding,
13574 0.03
13575 );
13576 }
13577
13578 #[test]
13579 fn test_config_with_manufacturing_specific() {
13580 let yaml = r#"
13581 global:
13582 industry: manufacturing
13583 start_date: "2024-01-01"
13584 period_months: 12
13585 companies:
13586 - code: "MFG"
13587 name: "Test Manufacturing"
13588 currency: "USD"
13589 country: "US"
13590 annual_transaction_volume: hundred_k
13591 chart_of_accounts:
13592 complexity: medium
13593 output:
13594 output_directory: "./output"
13595 industry_specific:
13596 enabled: true
13597 manufacturing:
13598 enabled: true
13599 bom_depth: 5
13600 just_in_time: true
13601 supplier_tiers: 3
13602 target_yield_rate: 0.98
13603 anomaly_rates:
13604 yield_manipulation: 0.02
13605 phantom_production: 0.01
13606 "#;
13607
13608 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13609 assert!(config.industry_specific.enabled);
13610 assert!(config.industry_specific.manufacturing.enabled);
13611 assert_eq!(config.industry_specific.manufacturing.bom_depth, 5);
13612 assert!(config.industry_specific.manufacturing.just_in_time);
13613 assert_eq!(config.industry_specific.manufacturing.supplier_tiers, 3);
13614 assert_eq!(
13615 config.industry_specific.manufacturing.target_yield_rate,
13616 0.98
13617 );
13618 assert_eq!(
13619 config
13620 .industry_specific
13621 .manufacturing
13622 .anomaly_rates
13623 .yield_manipulation,
13624 0.02
13625 );
13626 }
13627
13628 #[test]
13633 fn test_tax_config_defaults() {
13634 let tax = TaxConfig::default();
13635 assert!(!tax.enabled);
13636 assert!(tax.jurisdictions.countries.is_empty());
13637 assert!(!tax.jurisdictions.include_subnational);
13638 assert!(!tax.vat_gst.enabled);
13639 assert!(tax.vat_gst.standard_rates.is_empty());
13640 assert!(tax.vat_gst.reduced_rates.is_empty());
13641 assert!(tax.vat_gst.exempt_categories.is_empty());
13642 assert!(tax.vat_gst.reverse_charge);
13643 assert!(!tax.sales_tax.enabled);
13644 assert!(tax.sales_tax.nexus_states.is_empty());
13645 assert!(!tax.withholding.enabled);
13646 assert!(tax.withholding.treaty_network);
13647 assert_eq!(tax.withholding.default_rate, 0.30);
13648 assert_eq!(tax.withholding.treaty_reduced_rate, 0.15);
13649 assert!(tax.provisions.enabled);
13650 assert_eq!(tax.provisions.statutory_rate, 0.21);
13651 assert!(tax.provisions.uncertain_positions);
13652 assert!(!tax.payroll_tax.enabled);
13653 assert_eq!(tax.anomaly_rate, 0.03);
13654 }
13655
13656 #[test]
13657 fn test_tax_config_from_yaml() {
13658 let yaml = r#"
13659 global:
13660 seed: 42
13661 start_date: "2024-01-01"
13662 period_months: 12
13663 industry: retail
13664 companies:
13665 - code: C001
13666 name: Test Corp
13667 currency: USD
13668 country: US
13669 annual_transaction_volume: ten_k
13670 chart_of_accounts:
13671 complexity: small
13672 output:
13673 output_directory: ./output
13674 tax:
13675 enabled: true
13676 anomaly_rate: 0.05
13677 jurisdictions:
13678 countries: ["US", "DE", "GB"]
13679 include_subnational: true
13680 vat_gst:
13681 enabled: true
13682 standard_rates:
13683 DE: 0.19
13684 GB: 0.20
13685 reduced_rates:
13686 DE: 0.07
13687 GB: 0.05
13688 exempt_categories:
13689 - financial_services
13690 - healthcare
13691 reverse_charge: false
13692 sales_tax:
13693 enabled: true
13694 nexus_states: ["CA", "NY", "TX"]
13695 withholding:
13696 enabled: true
13697 treaty_network: false
13698 default_rate: 0.25
13699 treaty_reduced_rate: 0.10
13700 provisions:
13701 enabled: false
13702 statutory_rate: 0.28
13703 uncertain_positions: false
13704 payroll_tax:
13705 enabled: true
13706 "#;
13707
13708 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13709 assert!(config.tax.enabled);
13710 assert_eq!(config.tax.anomaly_rate, 0.05);
13711
13712 assert_eq!(config.tax.jurisdictions.countries.len(), 3);
13714 assert!(config
13715 .tax
13716 .jurisdictions
13717 .countries
13718 .contains(&"DE".to_string()));
13719 assert!(config.tax.jurisdictions.include_subnational);
13720
13721 assert!(config.tax.vat_gst.enabled);
13723 assert_eq!(config.tax.vat_gst.standard_rates.get("DE"), Some(&0.19));
13724 assert_eq!(config.tax.vat_gst.standard_rates.get("GB"), Some(&0.20));
13725 assert_eq!(config.tax.vat_gst.reduced_rates.get("DE"), Some(&0.07));
13726 assert_eq!(config.tax.vat_gst.exempt_categories.len(), 2);
13727 assert!(!config.tax.vat_gst.reverse_charge);
13728
13729 assert!(config.tax.sales_tax.enabled);
13731 assert_eq!(config.tax.sales_tax.nexus_states.len(), 3);
13732 assert!(config
13733 .tax
13734 .sales_tax
13735 .nexus_states
13736 .contains(&"CA".to_string()));
13737
13738 assert!(config.tax.withholding.enabled);
13740 assert!(!config.tax.withholding.treaty_network);
13741 assert_eq!(config.tax.withholding.default_rate, 0.25);
13742 assert_eq!(config.tax.withholding.treaty_reduced_rate, 0.10);
13743
13744 assert!(!config.tax.provisions.enabled);
13746 assert_eq!(config.tax.provisions.statutory_rate, 0.28);
13747 assert!(!config.tax.provisions.uncertain_positions);
13748
13749 assert!(config.tax.payroll_tax.enabled);
13751 }
13752
13753 #[test]
13754 fn test_generator_config_with_tax_default() {
13755 let yaml = r#"
13756 global:
13757 seed: 42
13758 start_date: "2024-01-01"
13759 period_months: 12
13760 industry: retail
13761 companies:
13762 - code: C001
13763 name: Test Corp
13764 currency: USD
13765 country: US
13766 annual_transaction_volume: ten_k
13767 chart_of_accounts:
13768 complexity: small
13769 output:
13770 output_directory: ./output
13771 "#;
13772
13773 let config: GeneratorConfig =
13774 serde_yaml::from_str(yaml).expect("Failed to parse config without tax section");
13775 assert!(!config.tax.enabled);
13777 assert!(config.tax.jurisdictions.countries.is_empty());
13778 assert_eq!(config.tax.anomaly_rate, 0.03);
13779 assert!(config.tax.provisions.enabled); assert_eq!(config.tax.provisions.statutory_rate, 0.21);
13781 }
13782
13783 #[test]
13788 fn test_session_config_default_disabled() {
13789 let yaml = "{}";
13790 let config: SessionSchemaConfig =
13791 serde_yaml::from_str(yaml).expect("Failed to parse empty session config");
13792 assert!(!config.enabled);
13793 assert!(config.checkpoint_path.is_none());
13794 assert!(config.per_period_output);
13795 assert!(config.consolidated_output);
13796 }
13797
13798 #[test]
13799 fn test_config_backward_compatible_without_session() {
13800 let yaml = r#"
13801 global:
13802 seed: 42
13803 start_date: "2024-01-01"
13804 period_months: 12
13805 industry: retail
13806 companies:
13807 - code: C001
13808 name: Test Corp
13809 currency: USD
13810 country: US
13811 annual_transaction_volume: ten_k
13812 chart_of_accounts:
13813 complexity: small
13814 output:
13815 output_directory: ./output
13816 "#;
13817
13818 let config: GeneratorConfig =
13819 serde_yaml::from_str(yaml).expect("Failed to parse config without session");
13820 assert!(!config.session.enabled);
13822 assert!(config.session.per_period_output);
13823 assert!(config.session.consolidated_output);
13824 assert!(config.global.fiscal_year_months.is_none());
13826 }
13827
13828 #[test]
13829 fn test_fiscal_year_months_parsed() {
13830 let yaml = r#"
13831 global:
13832 seed: 42
13833 start_date: "2024-01-01"
13834 period_months: 24
13835 industry: retail
13836 fiscal_year_months: 12
13837 companies:
13838 - code: C001
13839 name: Test Corp
13840 currency: USD
13841 country: US
13842 annual_transaction_volume: ten_k
13843 chart_of_accounts:
13844 complexity: small
13845 output:
13846 output_directory: ./output
13847 session:
13848 enabled: true
13849 checkpoint_path: /tmp/checkpoints
13850 per_period_output: true
13851 consolidated_output: false
13852 "#;
13853
13854 let config: GeneratorConfig =
13855 serde_yaml::from_str(yaml).expect("Failed to parse config with fiscal_year_months");
13856 assert_eq!(config.global.fiscal_year_months, Some(12));
13857 assert!(config.session.enabled);
13858 assert_eq!(
13859 config.session.checkpoint_path,
13860 Some("/tmp/checkpoints".to_string())
13861 );
13862 assert!(config.session.per_period_output);
13863 assert!(!config.session.consolidated_output);
13864 }
13865}