1use datasynth_core::distributions::{
4 AmountDistributionConfig, DebitCreditDistributionConfig, EvenOddDistributionConfig,
5 LineItemDistributionConfig, SeasonalityConfig,
6};
7use datasynth_core::models::{CoAComplexity, IndustrySector};
8use serde::{Deserialize, Serialize};
9use std::path::PathBuf;
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct GeneratorConfig {
14 pub global: GlobalConfig,
16 pub companies: Vec<CompanyConfig>,
18 pub chart_of_accounts: ChartOfAccountsConfig,
20 #[serde(default)]
22 pub transactions: TransactionConfig,
23 pub output: OutputConfig,
25 #[serde(default)]
27 pub fraud: FraudConfig,
28 #[serde(default)]
30 pub data_quality: DataQualitySchemaConfig,
31 #[serde(default)]
33 pub internal_controls: InternalControlsConfig,
34 #[serde(default)]
36 pub business_processes: BusinessProcessConfig,
37 #[serde(default)]
39 pub user_personas: UserPersonaConfig,
40 #[serde(default)]
42 pub templates: TemplateConfig,
43 #[serde(default)]
45 pub approval: ApprovalConfig,
46 #[serde(default)]
48 pub departments: DepartmentConfig,
49 #[serde(default)]
51 pub master_data: MasterDataConfig,
52 #[serde(default)]
54 pub document_flows: DocumentFlowConfig,
55 #[serde(default)]
57 pub intercompany: IntercompanyConfig,
58 #[serde(default)]
60 pub balance: BalanceConfig,
61 #[serde(default)]
63 pub ocpm: OcpmConfig,
64 #[serde(default)]
66 pub audit: AuditGenerationConfig,
67 #[serde(default)]
69 pub banking: datasynth_banking::BankingConfig,
70 #[serde(default)]
72 pub scenario: ScenarioConfig,
73 #[serde(default)]
75 pub temporal: TemporalDriftConfig,
76 #[serde(default)]
78 pub graph_export: GraphExportConfig,
79 #[serde(default)]
81 pub streaming: StreamingSchemaConfig,
82 #[serde(default)]
84 pub rate_limit: RateLimitSchemaConfig,
85 #[serde(default)]
87 pub temporal_attributes: TemporalAttributeSchemaConfig,
88 #[serde(default)]
90 pub relationships: RelationshipSchemaConfig,
91 #[serde(default)]
93 pub accounting_standards: AccountingStandardsConfig,
94 #[serde(default)]
96 pub audit_standards: AuditStandardsConfig,
97 #[serde(default)]
99 pub distributions: AdvancedDistributionConfig,
100 #[serde(default)]
102 pub temporal_patterns: TemporalPatternsConfig,
103 #[serde(default)]
105 pub vendor_network: VendorNetworkSchemaConfig,
106 #[serde(default)]
108 pub customer_segmentation: CustomerSegmentationSchemaConfig,
109 #[serde(default)]
111 pub relationship_strength: RelationshipStrengthSchemaConfig,
112 #[serde(default)]
114 pub cross_process_links: CrossProcessLinksSchemaConfig,
115 #[serde(default)]
117 pub organizational_events: OrganizationalEventsSchemaConfig,
118 #[serde(default)]
120 pub behavioral_drift: BehavioralDriftSchemaConfig,
121 #[serde(default)]
123 pub market_drift: MarketDriftSchemaConfig,
124 #[serde(default)]
126 pub drift_labeling: DriftLabelingSchemaConfig,
127 #[serde(default)]
129 pub anomaly_injection: EnhancedAnomalyConfig,
130 #[serde(default)]
132 pub industry_specific: IndustrySpecificConfig,
133 #[serde(default)]
135 pub fingerprint_privacy: FingerprintPrivacyConfig,
136 #[serde(default)]
138 pub quality_gates: QualityGatesSchemaConfig,
139 #[serde(default)]
141 pub compliance: ComplianceSchemaConfig,
142 #[serde(default)]
144 pub webhooks: WebhookSchemaConfig,
145 #[serde(default)]
147 pub llm: LlmSchemaConfig,
148 #[serde(default)]
150 pub diffusion: DiffusionSchemaConfig,
151 #[serde(default)]
153 pub causal: CausalSchemaConfig,
154
155 #[serde(default)]
158 pub source_to_pay: SourceToPayConfig,
159 #[serde(default)]
161 pub financial_reporting: FinancialReportingConfig,
162 #[serde(default)]
164 pub hr: HrConfig,
165 #[serde(default)]
167 pub manufacturing: ManufacturingProcessConfig,
168 #[serde(default)]
170 pub sales_quotes: SalesQuoteConfig,
171 #[serde(default)]
173 pub tax: TaxConfig,
174 #[serde(default)]
176 pub treasury: TreasuryConfig,
177 #[serde(default)]
179 pub project_accounting: ProjectAccountingConfig,
180 #[serde(default)]
182 pub esg: EsgConfig,
183 #[serde(default)]
185 pub country_packs: Option<CountryPacksSchemaConfig>,
186 #[serde(default)]
188 pub scenarios: ScenariosConfig,
189 #[serde(default)]
191 pub session: SessionSchemaConfig,
192 #[serde(default)]
194 pub compliance_regulations: ComplianceRegulationsConfig,
195}
196
197#[derive(Debug, Clone, Serialize, Deserialize)]
203pub struct LlmSchemaConfig {
204 #[serde(default)]
206 pub enabled: bool,
207 #[serde(default = "default_llm_provider")]
209 pub provider: String,
210 #[serde(default = "default_llm_model_name")]
212 pub model: String,
213 #[serde(default = "default_llm_batch_size")]
215 pub max_vendor_enrichments: usize,
216}
217
218fn default_llm_provider() -> String {
219 "mock".to_string()
220}
221
222fn default_llm_model_name() -> String {
223 "gpt-4o-mini".to_string()
224}
225
226fn default_llm_batch_size() -> usize {
227 50
228}
229
230impl Default for LlmSchemaConfig {
231 fn default() -> Self {
232 Self {
233 enabled: false,
234 provider: default_llm_provider(),
235 model: default_llm_model_name(),
236 max_vendor_enrichments: default_llm_batch_size(),
237 }
238 }
239}
240
241#[derive(Debug, Clone, Serialize, Deserialize)]
246pub struct DiffusionSchemaConfig {
247 #[serde(default)]
249 pub enabled: bool,
250 #[serde(default = "default_diffusion_steps")]
252 pub n_steps: usize,
253 #[serde(default = "default_diffusion_schedule")]
255 pub schedule: String,
256 #[serde(default = "default_diffusion_sample_size")]
258 pub sample_size: usize,
259}
260
261fn default_diffusion_steps() -> usize {
262 100
263}
264
265fn default_diffusion_schedule() -> String {
266 "linear".to_string()
267}
268
269fn default_diffusion_sample_size() -> usize {
270 100
271}
272
273impl Default for DiffusionSchemaConfig {
274 fn default() -> Self {
275 Self {
276 enabled: false,
277 n_steps: default_diffusion_steps(),
278 schedule: default_diffusion_schedule(),
279 sample_size: default_diffusion_sample_size(),
280 }
281 }
282}
283
284#[derive(Debug, Clone, Serialize, Deserialize)]
290pub struct CausalSchemaConfig {
291 #[serde(default)]
293 pub enabled: bool,
294 #[serde(default = "default_causal_template")]
296 pub template: String,
297 #[serde(default = "default_causal_sample_size")]
299 pub sample_size: usize,
300 #[serde(default = "default_true")]
302 pub validate: bool,
303}
304
305fn default_causal_template() -> String {
306 "fraud_detection".to_string()
307}
308
309fn default_causal_sample_size() -> usize {
310 500
311}
312
313impl Default for CausalSchemaConfig {
314 fn default() -> Self {
315 Self {
316 enabled: false,
317 template: default_causal_template(),
318 sample_size: default_causal_sample_size(),
319 validate: true,
320 }
321 }
322}
323
324#[derive(Debug, Clone, Serialize, Deserialize)]
331pub struct GraphExportConfig {
332 #[serde(default)]
334 pub enabled: bool,
335
336 #[serde(default = "default_graph_types")]
338 pub graph_types: Vec<GraphTypeConfig>,
339
340 #[serde(default = "default_graph_formats")]
342 pub formats: Vec<GraphExportFormat>,
343
344 #[serde(default = "default_train_ratio")]
346 pub train_ratio: f64,
347
348 #[serde(default = "default_val_ratio")]
350 pub validation_ratio: f64,
351
352 #[serde(default)]
354 pub split_seed: Option<u64>,
355
356 #[serde(default = "default_graph_subdir")]
358 pub output_subdirectory: String,
359
360 #[serde(default)]
362 pub hypergraph: HypergraphExportSettings,
363
364 #[serde(default)]
366 pub dgl: DglExportConfig,
367}
368
369fn default_graph_types() -> Vec<GraphTypeConfig> {
370 vec![GraphTypeConfig::default()]
371}
372
373fn default_graph_formats() -> Vec<GraphExportFormat> {
374 vec![GraphExportFormat::PytorchGeometric]
375}
376
377fn default_train_ratio() -> f64 {
378 0.7
379}
380
381fn default_val_ratio() -> f64 {
382 0.15
383}
384
385fn default_graph_subdir() -> String {
386 "graphs".to_string()
387}
388
389impl Default for GraphExportConfig {
390 fn default() -> Self {
391 Self {
392 enabled: false,
393 graph_types: default_graph_types(),
394 formats: default_graph_formats(),
395 train_ratio: 0.7,
396 validation_ratio: 0.15,
397 split_seed: None,
398 output_subdirectory: "graphs".to_string(),
399 hypergraph: HypergraphExportSettings::default(),
400 dgl: DglExportConfig::default(),
401 }
402 }
403}
404
405#[derive(Debug, Clone, Default, Serialize, Deserialize)]
407pub struct DglExportConfig {
408 #[serde(default)]
414 pub heterogeneous: bool,
415}
416
417#[derive(Debug, Clone, Serialize, Deserialize)]
426pub struct HypergraphExportSettings {
427 #[serde(default)]
429 pub enabled: bool,
430
431 #[serde(default = "default_hypergraph_max_nodes")]
433 pub max_nodes: usize,
434
435 #[serde(default = "default_aggregation_strategy")]
437 pub aggregation_strategy: String,
438
439 #[serde(default)]
441 pub governance_layer: GovernanceLayerSettings,
442
443 #[serde(default)]
445 pub process_layer: ProcessLayerSettings,
446
447 #[serde(default)]
449 pub accounting_layer: AccountingLayerSettings,
450
451 #[serde(default)]
453 pub cross_layer: CrossLayerSettings,
454
455 #[serde(default = "default_hypergraph_subdir")]
457 pub output_subdirectory: String,
458
459 #[serde(default = "default_hypergraph_format")]
461 pub output_format: String,
462
463 #[serde(default)]
465 pub stream_target: Option<String>,
466
467 #[serde(default = "default_stream_batch_size")]
469 pub stream_batch_size: usize,
470}
471
472fn default_hypergraph_max_nodes() -> usize {
473 50_000
474}
475
476fn default_aggregation_strategy() -> String {
477 "pool_by_counterparty".to_string()
478}
479
480fn default_hypergraph_subdir() -> String {
481 "hypergraph".to_string()
482}
483
484fn default_hypergraph_format() -> String {
485 "native".to_string()
486}
487
488fn default_stream_batch_size() -> usize {
489 1000
490}
491
492impl Default for HypergraphExportSettings {
493 fn default() -> Self {
494 Self {
495 enabled: false,
496 max_nodes: 50_000,
497 aggregation_strategy: "pool_by_counterparty".to_string(),
498 governance_layer: GovernanceLayerSettings::default(),
499 process_layer: ProcessLayerSettings::default(),
500 accounting_layer: AccountingLayerSettings::default(),
501 cross_layer: CrossLayerSettings::default(),
502 output_subdirectory: "hypergraph".to_string(),
503 output_format: "native".to_string(),
504 stream_target: None,
505 stream_batch_size: 1000,
506 }
507 }
508}
509
510#[derive(Debug, Clone, Serialize, Deserialize)]
512pub struct GovernanceLayerSettings {
513 #[serde(default = "default_true")]
515 pub include_coso: bool,
516 #[serde(default = "default_true")]
518 pub include_controls: bool,
519 #[serde(default = "default_true")]
521 pub include_sox: bool,
522 #[serde(default = "default_true")]
524 pub include_vendors: bool,
525 #[serde(default = "default_true")]
527 pub include_customers: bool,
528 #[serde(default = "default_true")]
530 pub include_employees: bool,
531}
532
533impl Default for GovernanceLayerSettings {
534 fn default() -> Self {
535 Self {
536 include_coso: true,
537 include_controls: true,
538 include_sox: true,
539 include_vendors: true,
540 include_customers: true,
541 include_employees: true,
542 }
543 }
544}
545
546#[derive(Debug, Clone, Serialize, Deserialize)]
548pub struct ProcessLayerSettings {
549 #[serde(default = "default_true")]
551 pub include_p2p: bool,
552 #[serde(default = "default_true")]
554 pub include_o2c: bool,
555 #[serde(default = "default_true")]
557 pub include_s2c: bool,
558 #[serde(default = "default_true")]
560 pub include_h2r: bool,
561 #[serde(default = "default_true")]
563 pub include_mfg: bool,
564 #[serde(default = "default_true")]
566 pub include_bank: bool,
567 #[serde(default = "default_true")]
569 pub include_audit: bool,
570 #[serde(default = "default_true")]
572 pub include_r2r: bool,
573 #[serde(default = "default_true")]
575 pub events_as_hyperedges: bool,
576 #[serde(default = "default_docs_per_counterparty_threshold")]
578 pub docs_per_counterparty_threshold: usize,
579}
580
581fn default_docs_per_counterparty_threshold() -> usize {
582 20
583}
584
585impl Default for ProcessLayerSettings {
586 fn default() -> Self {
587 Self {
588 include_p2p: true,
589 include_o2c: true,
590 include_s2c: true,
591 include_h2r: true,
592 include_mfg: true,
593 include_bank: true,
594 include_audit: true,
595 include_r2r: true,
596 events_as_hyperedges: true,
597 docs_per_counterparty_threshold: 20,
598 }
599 }
600}
601
602#[derive(Debug, Clone, Serialize, Deserialize)]
604pub struct AccountingLayerSettings {
605 #[serde(default = "default_true")]
607 pub include_accounts: bool,
608 #[serde(default = "default_true")]
610 pub je_as_hyperedges: bool,
611}
612
613impl Default for AccountingLayerSettings {
614 fn default() -> Self {
615 Self {
616 include_accounts: true,
617 je_as_hyperedges: true,
618 }
619 }
620}
621
622#[derive(Debug, Clone, Serialize, Deserialize)]
624pub struct CrossLayerSettings {
625 #[serde(default = "default_true")]
627 pub enabled: bool,
628}
629
630impl Default for CrossLayerSettings {
631 fn default() -> Self {
632 Self { enabled: true }
633 }
634}
635
636#[derive(Debug, Clone, Serialize, Deserialize)]
638pub struct GraphTypeConfig {
639 #[serde(default = "default_graph_name")]
641 pub name: String,
642
643 #[serde(default)]
645 pub aggregate_edges: bool,
646
647 #[serde(default)]
649 pub min_edge_weight: f64,
650
651 #[serde(default)]
653 pub include_document_nodes: bool,
654}
655
656fn default_graph_name() -> String {
657 "accounting_network".to_string()
658}
659
660impl Default for GraphTypeConfig {
661 fn default() -> Self {
662 Self {
663 name: "accounting_network".to_string(),
664 aggregate_edges: false,
665 min_edge_weight: 0.0,
666 include_document_nodes: false,
667 }
668 }
669}
670
671#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
673#[serde(rename_all = "snake_case")]
674pub enum GraphExportFormat {
675 PytorchGeometric,
677 Neo4j,
679 Dgl,
681 RustGraph,
683 RustGraphHypergraph,
685}
686
687#[derive(Debug, Clone, Default, Serialize, Deserialize)]
691pub struct ScenarioConfig {
692 #[serde(default)]
695 pub tags: Vec<String>,
696
697 #[serde(default)]
702 pub profile: Option<String>,
703
704 #[serde(default)]
706 pub description: Option<String>,
707
708 #[serde(default)]
710 pub ml_training: bool,
711
712 #[serde(default)]
715 pub target_anomaly_ratio: Option<f64>,
716
717 #[serde(default)]
719 pub metadata: std::collections::HashMap<String, String>,
720}
721
722#[derive(Debug, Clone, Serialize, Deserialize)]
727pub struct TemporalDriftConfig {
728 #[serde(default)]
730 pub enabled: bool,
731
732 #[serde(default = "default_amount_drift")]
735 pub amount_mean_drift: f64,
736
737 #[serde(default)]
740 pub amount_variance_drift: f64,
741
742 #[serde(default)]
745 pub anomaly_rate_drift: f64,
746
747 #[serde(default = "default_concept_drift")]
750 pub concept_drift_rate: f64,
751
752 #[serde(default)]
754 pub sudden_drift_probability: f64,
755
756 #[serde(default = "default_sudden_drift_magnitude")]
758 pub sudden_drift_magnitude: f64,
759
760 #[serde(default)]
762 pub seasonal_drift: bool,
763
764 #[serde(default)]
766 pub drift_start_period: u32,
767
768 #[serde(default = "default_drift_type")]
770 pub drift_type: DriftType,
771}
772
773fn default_amount_drift() -> f64 {
774 0.02
775}
776
777fn default_concept_drift() -> f64 {
778 0.01
779}
780
781fn default_sudden_drift_magnitude() -> f64 {
782 2.0
783}
784
785fn default_drift_type() -> DriftType {
786 DriftType::Gradual
787}
788
789impl Default for TemporalDriftConfig {
790 fn default() -> Self {
791 Self {
792 enabled: false,
793 amount_mean_drift: 0.02,
794 amount_variance_drift: 0.0,
795 anomaly_rate_drift: 0.0,
796 concept_drift_rate: 0.01,
797 sudden_drift_probability: 0.0,
798 sudden_drift_magnitude: 2.0,
799 seasonal_drift: false,
800 drift_start_period: 0,
801 drift_type: DriftType::Gradual,
802 }
803 }
804}
805
806impl TemporalDriftConfig {
807 pub fn to_core_config(&self) -> datasynth_core::distributions::DriftConfig {
809 datasynth_core::distributions::DriftConfig {
810 enabled: self.enabled,
811 amount_mean_drift: self.amount_mean_drift,
812 amount_variance_drift: self.amount_variance_drift,
813 anomaly_rate_drift: self.anomaly_rate_drift,
814 concept_drift_rate: self.concept_drift_rate,
815 sudden_drift_probability: self.sudden_drift_probability,
816 sudden_drift_magnitude: self.sudden_drift_magnitude,
817 seasonal_drift: self.seasonal_drift,
818 drift_start_period: self.drift_start_period,
819 drift_type: match self.drift_type {
820 DriftType::Gradual => datasynth_core::distributions::DriftType::Gradual,
821 DriftType::Sudden => datasynth_core::distributions::DriftType::Sudden,
822 DriftType::Recurring => datasynth_core::distributions::DriftType::Recurring,
823 DriftType::Mixed => datasynth_core::distributions::DriftType::Mixed,
824 },
825 regime_changes: Vec::new(),
826 economic_cycle: Default::default(),
827 parameter_drifts: Vec::new(),
828 }
829 }
830}
831
832#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
834#[serde(rename_all = "snake_case")]
835pub enum DriftType {
836 #[default]
838 Gradual,
839 Sudden,
841 Recurring,
843 Mixed,
845}
846
847#[derive(Debug, Clone, Serialize, Deserialize)]
853pub struct StreamingSchemaConfig {
854 #[serde(default)]
856 pub enabled: bool,
857 #[serde(default = "default_buffer_size")]
859 pub buffer_size: usize,
860 #[serde(default = "default_true")]
862 pub enable_progress: bool,
863 #[serde(default = "default_progress_interval")]
865 pub progress_interval: u64,
866 #[serde(default)]
868 pub backpressure: BackpressureSchemaStrategy,
869}
870
871fn default_buffer_size() -> usize {
872 1000
873}
874
875fn default_progress_interval() -> u64 {
876 100
877}
878
879impl Default for StreamingSchemaConfig {
880 fn default() -> Self {
881 Self {
882 enabled: false,
883 buffer_size: 1000,
884 enable_progress: true,
885 progress_interval: 100,
886 backpressure: BackpressureSchemaStrategy::Block,
887 }
888 }
889}
890
891#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
893#[serde(rename_all = "snake_case")]
894pub enum BackpressureSchemaStrategy {
895 #[default]
897 Block,
898 DropOldest,
900 DropNewest,
902 Buffer,
904}
905
906#[derive(Debug, Clone, Serialize, Deserialize)]
912pub struct RateLimitSchemaConfig {
913 #[serde(default)]
915 pub enabled: bool,
916 #[serde(default = "default_entities_per_second")]
918 pub entities_per_second: f64,
919 #[serde(default = "default_burst_size")]
921 pub burst_size: u32,
922 #[serde(default)]
924 pub backpressure: RateLimitBackpressureSchema,
925}
926
927fn default_entities_per_second() -> f64 {
928 1000.0
929}
930
931fn default_burst_size() -> u32 {
932 100
933}
934
935impl Default for RateLimitSchemaConfig {
936 fn default() -> Self {
937 Self {
938 enabled: false,
939 entities_per_second: 1000.0,
940 burst_size: 100,
941 backpressure: RateLimitBackpressureSchema::Block,
942 }
943 }
944}
945
946#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
948#[serde(rename_all = "snake_case")]
949pub enum RateLimitBackpressureSchema {
950 #[default]
952 Block,
953 Drop,
955 Buffer,
957}
958
959#[derive(Debug, Clone, Serialize, Deserialize)]
965pub struct TemporalAttributeSchemaConfig {
966 #[serde(default)]
968 pub enabled: bool,
969 #[serde(default)]
971 pub valid_time: ValidTimeSchemaConfig,
972 #[serde(default)]
974 pub transaction_time: TransactionTimeSchemaConfig,
975 #[serde(default)]
977 pub generate_version_chains: bool,
978 #[serde(default = "default_avg_versions")]
980 pub avg_versions_per_entity: f64,
981}
982
983fn default_avg_versions() -> f64 {
984 1.5
985}
986
987impl Default for TemporalAttributeSchemaConfig {
988 fn default() -> Self {
989 Self {
990 enabled: false,
991 valid_time: ValidTimeSchemaConfig::default(),
992 transaction_time: TransactionTimeSchemaConfig::default(),
993 generate_version_chains: false,
994 avg_versions_per_entity: 1.5,
995 }
996 }
997}
998
999#[derive(Debug, Clone, Serialize, Deserialize)]
1001pub struct ValidTimeSchemaConfig {
1002 #[serde(default = "default_closed_probability")]
1004 pub closed_probability: f64,
1005 #[serde(default = "default_avg_validity_days")]
1007 pub avg_validity_days: u32,
1008 #[serde(default = "default_validity_stddev")]
1010 pub validity_stddev_days: u32,
1011}
1012
1013fn default_closed_probability() -> f64 {
1014 0.1
1015}
1016
1017fn default_avg_validity_days() -> u32 {
1018 365
1019}
1020
1021fn default_validity_stddev() -> u32 {
1022 90
1023}
1024
1025impl Default for ValidTimeSchemaConfig {
1026 fn default() -> Self {
1027 Self {
1028 closed_probability: 0.1,
1029 avg_validity_days: 365,
1030 validity_stddev_days: 90,
1031 }
1032 }
1033}
1034
1035#[derive(Debug, Clone, Serialize, Deserialize)]
1037pub struct TransactionTimeSchemaConfig {
1038 #[serde(default)]
1040 pub avg_recording_delay_seconds: u32,
1041 #[serde(default)]
1043 pub allow_backdating: bool,
1044 #[serde(default = "default_backdating_probability")]
1046 pub backdating_probability: f64,
1047 #[serde(default = "default_max_backdate_days")]
1049 pub max_backdate_days: u32,
1050}
1051
1052fn default_backdating_probability() -> f64 {
1053 0.01
1054}
1055
1056fn default_max_backdate_days() -> u32 {
1057 30
1058}
1059
1060impl Default for TransactionTimeSchemaConfig {
1061 fn default() -> Self {
1062 Self {
1063 avg_recording_delay_seconds: 0,
1064 allow_backdating: false,
1065 backdating_probability: 0.01,
1066 max_backdate_days: 30,
1067 }
1068 }
1069}
1070
1071#[derive(Debug, Clone, Serialize, Deserialize)]
1077pub struct RelationshipSchemaConfig {
1078 #[serde(default)]
1080 pub relationship_types: Vec<RelationshipTypeSchemaConfig>,
1081 #[serde(default = "default_true")]
1083 pub allow_orphans: bool,
1084 #[serde(default = "default_orphan_probability")]
1086 pub orphan_probability: f64,
1087 #[serde(default)]
1089 pub allow_circular: bool,
1090 #[serde(default = "default_max_circular_depth")]
1092 pub max_circular_depth: u32,
1093}
1094
1095fn default_orphan_probability() -> f64 {
1096 0.01
1097}
1098
1099fn default_max_circular_depth() -> u32 {
1100 3
1101}
1102
1103impl Default for RelationshipSchemaConfig {
1104 fn default() -> Self {
1105 Self {
1106 relationship_types: Vec::new(),
1107 allow_orphans: true,
1108 orphan_probability: 0.01,
1109 allow_circular: false,
1110 max_circular_depth: 3,
1111 }
1112 }
1113}
1114
1115#[derive(Debug, Clone, Serialize, Deserialize)]
1117pub struct RelationshipTypeSchemaConfig {
1118 pub name: String,
1120 pub source_type: String,
1122 pub target_type: String,
1124 #[serde(default)]
1126 pub cardinality: CardinalitySchemaRule,
1127 #[serde(default = "default_relationship_weight")]
1129 pub weight: f64,
1130 #[serde(default)]
1132 pub required: bool,
1133 #[serde(default = "default_true")]
1135 pub directed: bool,
1136}
1137
1138fn default_relationship_weight() -> f64 {
1139 1.0
1140}
1141
1142impl Default for RelationshipTypeSchemaConfig {
1143 fn default() -> Self {
1144 Self {
1145 name: String::new(),
1146 source_type: String::new(),
1147 target_type: String::new(),
1148 cardinality: CardinalitySchemaRule::default(),
1149 weight: 1.0,
1150 required: false,
1151 directed: true,
1152 }
1153 }
1154}
1155
1156#[derive(Debug, Clone, Serialize, Deserialize)]
1158#[serde(rename_all = "snake_case")]
1159pub enum CardinalitySchemaRule {
1160 OneToOne,
1162 OneToMany {
1164 min: u32,
1166 max: u32,
1168 },
1169 ManyToOne {
1171 min: u32,
1173 max: u32,
1175 },
1176 ManyToMany {
1178 min_per_source: u32,
1180 max_per_source: u32,
1182 },
1183}
1184
1185impl Default for CardinalitySchemaRule {
1186 fn default() -> Self {
1187 Self::OneToMany { min: 1, max: 5 }
1188 }
1189}
1190
1191#[derive(Debug, Clone, Serialize, Deserialize)]
1193pub struct GlobalConfig {
1194 pub seed: Option<u64>,
1196 pub industry: IndustrySector,
1198 pub start_date: String,
1200 pub period_months: u32,
1202 #[serde(default = "default_currency")]
1204 pub group_currency: String,
1205 #[serde(default)]
1208 pub presentation_currency: Option<String>,
1209 #[serde(default = "default_true")]
1211 pub parallel: bool,
1212 #[serde(default)]
1214 pub worker_threads: usize,
1215 #[serde(default)]
1217 pub memory_limit_mb: usize,
1218 #[serde(default)]
1221 pub fiscal_year_months: Option<u32>,
1222}
1223
1224fn default_currency() -> String {
1225 "USD".to_string()
1226}
1227fn default_true() -> bool {
1228 true
1229}
1230
1231#[derive(Debug, Clone, Serialize, Deserialize)]
1236pub struct SessionSchemaConfig {
1237 #[serde(default)]
1239 pub enabled: bool,
1240 #[serde(default)]
1242 pub checkpoint_path: Option<String>,
1243 #[serde(default = "default_true")]
1245 pub per_period_output: bool,
1246 #[serde(default = "default_true")]
1248 pub consolidated_output: bool,
1249}
1250
1251impl Default for SessionSchemaConfig {
1252 fn default() -> Self {
1253 Self {
1254 enabled: false,
1255 checkpoint_path: None,
1256 per_period_output: true,
1257 consolidated_output: true,
1258 }
1259 }
1260}
1261
1262#[derive(Debug, Clone, Serialize, Deserialize)]
1264pub struct CompanyConfig {
1265 pub code: String,
1267 pub name: String,
1269 pub currency: String,
1271 #[serde(default)]
1274 pub functional_currency: Option<String>,
1275 pub country: String,
1277 #[serde(default = "default_fiscal_variant")]
1279 pub fiscal_year_variant: String,
1280 pub annual_transaction_volume: TransactionVolume,
1282 #[serde(default = "default_weight")]
1284 pub volume_weight: f64,
1285}
1286
1287fn default_fiscal_variant() -> String {
1288 "K4".to_string()
1289}
1290fn default_weight() -> f64 {
1291 1.0
1292}
1293
1294#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1296#[serde(rename_all = "snake_case")]
1297pub enum TransactionVolume {
1298 TenK,
1300 HundredK,
1302 OneM,
1304 TenM,
1306 HundredM,
1308 Custom(u64),
1310}
1311
1312impl TransactionVolume {
1313 pub fn count(&self) -> u64 {
1315 match self {
1316 Self::TenK => 10_000,
1317 Self::HundredK => 100_000,
1318 Self::OneM => 1_000_000,
1319 Self::TenM => 10_000_000,
1320 Self::HundredM => 100_000_000,
1321 Self::Custom(n) => *n,
1322 }
1323 }
1324}
1325
1326#[derive(Debug, Clone, Serialize, Deserialize)]
1328pub struct ChartOfAccountsConfig {
1329 pub complexity: CoAComplexity,
1331 #[serde(default = "default_true")]
1333 pub industry_specific: bool,
1334 pub custom_accounts: Option<PathBuf>,
1336 #[serde(default = "default_min_depth")]
1338 pub min_hierarchy_depth: u8,
1339 #[serde(default = "default_max_depth")]
1341 pub max_hierarchy_depth: u8,
1342}
1343
1344fn default_min_depth() -> u8 {
1345 2
1346}
1347fn default_max_depth() -> u8 {
1348 5
1349}
1350
1351impl Default for ChartOfAccountsConfig {
1352 fn default() -> Self {
1353 Self {
1354 complexity: CoAComplexity::Small,
1355 industry_specific: true,
1356 custom_accounts: None,
1357 min_hierarchy_depth: default_min_depth(),
1358 max_hierarchy_depth: default_max_depth(),
1359 }
1360 }
1361}
1362
1363#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1365pub struct TransactionConfig {
1366 #[serde(default)]
1368 pub line_item_distribution: LineItemDistributionConfig,
1369 #[serde(default)]
1371 pub debit_credit_distribution: DebitCreditDistributionConfig,
1372 #[serde(default)]
1374 pub even_odd_distribution: EvenOddDistributionConfig,
1375 #[serde(default)]
1377 pub source_distribution: SourceDistribution,
1378 #[serde(default)]
1380 pub seasonality: SeasonalityConfig,
1381 #[serde(default)]
1383 pub amounts: AmountDistributionConfig,
1384 #[serde(default)]
1386 pub benford: BenfordConfig,
1387}
1388
1389#[derive(Debug, Clone, Serialize, Deserialize)]
1391pub struct BenfordConfig {
1392 #[serde(default = "default_true")]
1394 pub enabled: bool,
1395 #[serde(default = "default_benford_tolerance")]
1397 pub tolerance: f64,
1398 #[serde(default)]
1400 pub exempt_sources: Vec<BenfordExemption>,
1401}
1402
1403fn default_benford_tolerance() -> f64 {
1404 0.05
1405}
1406
1407impl Default for BenfordConfig {
1408 fn default() -> Self {
1409 Self {
1410 enabled: true,
1411 tolerance: default_benford_tolerance(),
1412 exempt_sources: vec![BenfordExemption::Recurring, BenfordExemption::Payroll],
1413 }
1414 }
1415}
1416
1417#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1419#[serde(rename_all = "snake_case")]
1420pub enum BenfordExemption {
1421 Recurring,
1423 Payroll,
1425 FixedFees,
1427 RoundAmounts,
1429}
1430
1431#[derive(Debug, Clone, Serialize, Deserialize)]
1433pub struct SourceDistribution {
1434 pub manual: f64,
1436 pub automated: f64,
1438 pub recurring: f64,
1440 pub adjustment: f64,
1442}
1443
1444impl Default for SourceDistribution {
1445 fn default() -> Self {
1446 Self {
1447 manual: 0.20,
1448 automated: 0.70,
1449 recurring: 0.07,
1450 adjustment: 0.03,
1451 }
1452 }
1453}
1454
1455#[derive(Debug, Clone, Serialize, Deserialize)]
1457pub struct OutputConfig {
1458 #[serde(default)]
1460 pub mode: OutputMode,
1461 pub output_directory: PathBuf,
1463 #[serde(default = "default_formats")]
1465 pub formats: Vec<FileFormat>,
1466 #[serde(default)]
1468 pub compression: CompressionConfig,
1469 #[serde(default = "default_batch_size")]
1471 pub batch_size: usize,
1472 #[serde(default = "default_true")]
1474 pub include_acdoca: bool,
1475 #[serde(default)]
1477 pub include_bseg: bool,
1478 #[serde(default = "default_true")]
1480 pub partition_by_period: bool,
1481 #[serde(default)]
1483 pub partition_by_company: bool,
1484}
1485
1486fn default_formats() -> Vec<FileFormat> {
1487 vec![FileFormat::Parquet]
1488}
1489fn default_batch_size() -> usize {
1490 100_000
1491}
1492
1493impl Default for OutputConfig {
1494 fn default() -> Self {
1495 Self {
1496 mode: OutputMode::FlatFile,
1497 output_directory: PathBuf::from("./output"),
1498 formats: default_formats(),
1499 compression: CompressionConfig::default(),
1500 batch_size: default_batch_size(),
1501 include_acdoca: true,
1502 include_bseg: false,
1503 partition_by_period: true,
1504 partition_by_company: false,
1505 }
1506 }
1507}
1508
1509#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
1511#[serde(rename_all = "snake_case")]
1512pub enum OutputMode {
1513 Streaming,
1515 #[default]
1517 FlatFile,
1518 Both,
1520}
1521
1522#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1524#[serde(rename_all = "snake_case")]
1525pub enum FileFormat {
1526 Csv,
1527 Parquet,
1528 Json,
1529 JsonLines,
1530}
1531
1532#[derive(Debug, Clone, Serialize, Deserialize)]
1534pub struct CompressionConfig {
1535 #[serde(default = "default_true")]
1537 pub enabled: bool,
1538 #[serde(default)]
1540 pub algorithm: CompressionAlgorithm,
1541 #[serde(default = "default_compression_level")]
1543 pub level: u8,
1544}
1545
1546fn default_compression_level() -> u8 {
1547 3
1548}
1549
1550impl Default for CompressionConfig {
1551 fn default() -> Self {
1552 Self {
1553 enabled: true,
1554 algorithm: CompressionAlgorithm::default(),
1555 level: default_compression_level(),
1556 }
1557 }
1558}
1559
1560#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
1562#[serde(rename_all = "snake_case")]
1563pub enum CompressionAlgorithm {
1564 Gzip,
1565 #[default]
1566 Zstd,
1567 Lz4,
1568 Snappy,
1569}
1570
1571#[derive(Debug, Clone, Serialize, Deserialize)]
1573pub struct FraudConfig {
1574 #[serde(default)]
1576 pub enabled: bool,
1577 #[serde(default = "default_fraud_rate")]
1579 pub fraud_rate: f64,
1580 #[serde(default)]
1582 pub fraud_type_distribution: FraudTypeDistribution,
1583 #[serde(default)]
1585 pub clustering_enabled: bool,
1586 #[serde(default = "default_clustering_factor")]
1588 pub clustering_factor: f64,
1589 #[serde(default = "default_approval_thresholds")]
1591 pub approval_thresholds: Vec<f64>,
1592}
1593
1594fn default_approval_thresholds() -> Vec<f64> {
1595 vec![1000.0, 5000.0, 10000.0, 25000.0, 50000.0, 100000.0]
1596}
1597
1598fn default_fraud_rate() -> f64 {
1599 0.005
1600}
1601fn default_clustering_factor() -> f64 {
1602 3.0
1603}
1604
1605impl Default for FraudConfig {
1606 fn default() -> Self {
1607 Self {
1608 enabled: false,
1609 fraud_rate: default_fraud_rate(),
1610 fraud_type_distribution: FraudTypeDistribution::default(),
1611 clustering_enabled: false,
1612 clustering_factor: default_clustering_factor(),
1613 approval_thresholds: default_approval_thresholds(),
1614 }
1615 }
1616}
1617
1618#[derive(Debug, Clone, Serialize, Deserialize)]
1620pub struct FraudTypeDistribution {
1621 pub suspense_account_abuse: f64,
1622 pub fictitious_transaction: f64,
1623 pub revenue_manipulation: f64,
1624 pub expense_capitalization: f64,
1625 pub split_transaction: f64,
1626 pub timing_anomaly: f64,
1627 pub unauthorized_access: f64,
1628 pub duplicate_payment: f64,
1629}
1630
1631impl Default for FraudTypeDistribution {
1632 fn default() -> Self {
1633 Self {
1634 suspense_account_abuse: 0.25,
1635 fictitious_transaction: 0.15,
1636 revenue_manipulation: 0.10,
1637 expense_capitalization: 0.10,
1638 split_transaction: 0.15,
1639 timing_anomaly: 0.10,
1640 unauthorized_access: 0.10,
1641 duplicate_payment: 0.05,
1642 }
1643 }
1644}
1645
1646#[derive(Debug, Clone, Serialize, Deserialize)]
1648pub struct InternalControlsConfig {
1649 #[serde(default)]
1651 pub enabled: bool,
1652 #[serde(default = "default_exception_rate")]
1654 pub exception_rate: f64,
1655 #[serde(default = "default_sod_violation_rate")]
1657 pub sod_violation_rate: f64,
1658 #[serde(default = "default_true")]
1660 pub export_control_master_data: bool,
1661 #[serde(default = "default_sox_materiality_threshold")]
1663 pub sox_materiality_threshold: f64,
1664 #[serde(default = "default_true")]
1666 pub coso_enabled: bool,
1667 #[serde(default)]
1669 pub include_entity_level_controls: bool,
1670 #[serde(default = "default_target_maturity_level")]
1673 pub target_maturity_level: String,
1674}
1675
1676fn default_exception_rate() -> f64 {
1677 0.02
1678}
1679
1680fn default_sod_violation_rate() -> f64 {
1681 0.01
1682}
1683
1684fn default_sox_materiality_threshold() -> f64 {
1685 10000.0
1686}
1687
1688fn default_target_maturity_level() -> String {
1689 "mixed".to_string()
1690}
1691
1692impl Default for InternalControlsConfig {
1693 fn default() -> Self {
1694 Self {
1695 enabled: false,
1696 exception_rate: default_exception_rate(),
1697 sod_violation_rate: default_sod_violation_rate(),
1698 export_control_master_data: true,
1699 sox_materiality_threshold: default_sox_materiality_threshold(),
1700 coso_enabled: true,
1701 include_entity_level_controls: false,
1702 target_maturity_level: default_target_maturity_level(),
1703 }
1704 }
1705}
1706
1707#[derive(Debug, Clone, Serialize, Deserialize)]
1709pub struct BusinessProcessConfig {
1710 #[serde(default = "default_o2c")]
1712 pub o2c_weight: f64,
1713 #[serde(default = "default_p2p")]
1715 pub p2p_weight: f64,
1716 #[serde(default = "default_r2r")]
1718 pub r2r_weight: f64,
1719 #[serde(default = "default_h2r")]
1721 pub h2r_weight: f64,
1722 #[serde(default = "default_a2r")]
1724 pub a2r_weight: f64,
1725}
1726
1727fn default_o2c() -> f64 {
1728 0.35
1729}
1730fn default_p2p() -> f64 {
1731 0.30
1732}
1733fn default_r2r() -> f64 {
1734 0.20
1735}
1736fn default_h2r() -> f64 {
1737 0.10
1738}
1739fn default_a2r() -> f64 {
1740 0.05
1741}
1742
1743impl Default for BusinessProcessConfig {
1744 fn default() -> Self {
1745 Self {
1746 o2c_weight: default_o2c(),
1747 p2p_weight: default_p2p(),
1748 r2r_weight: default_r2r(),
1749 h2r_weight: default_h2r(),
1750 a2r_weight: default_a2r(),
1751 }
1752 }
1753}
1754
1755#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1757pub struct UserPersonaConfig {
1758 #[serde(default)]
1760 pub persona_distribution: PersonaDistribution,
1761 #[serde(default)]
1763 pub users_per_persona: UsersPerPersona,
1764}
1765
1766#[derive(Debug, Clone, Serialize, Deserialize)]
1768pub struct PersonaDistribution {
1769 pub junior_accountant: f64,
1770 pub senior_accountant: f64,
1771 pub controller: f64,
1772 pub manager: f64,
1773 pub automated_system: f64,
1774}
1775
1776impl Default for PersonaDistribution {
1777 fn default() -> Self {
1778 Self {
1779 junior_accountant: 0.15,
1780 senior_accountant: 0.15,
1781 controller: 0.05,
1782 manager: 0.05,
1783 automated_system: 0.60,
1784 }
1785 }
1786}
1787
1788#[derive(Debug, Clone, Serialize, Deserialize)]
1790pub struct UsersPerPersona {
1791 pub junior_accountant: usize,
1792 pub senior_accountant: usize,
1793 pub controller: usize,
1794 pub manager: usize,
1795 pub automated_system: usize,
1796}
1797
1798impl Default for UsersPerPersona {
1799 fn default() -> Self {
1800 Self {
1801 junior_accountant: 10,
1802 senior_accountant: 5,
1803 controller: 2,
1804 manager: 3,
1805 automated_system: 20,
1806 }
1807 }
1808}
1809
1810#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1812pub struct TemplateConfig {
1813 #[serde(default)]
1815 pub names: NameTemplateConfig,
1816 #[serde(default)]
1818 pub descriptions: DescriptionTemplateConfig,
1819 #[serde(default)]
1821 pub references: ReferenceTemplateConfig,
1822}
1823
1824#[derive(Debug, Clone, Serialize, Deserialize)]
1826pub struct NameTemplateConfig {
1827 #[serde(default)]
1829 pub culture_distribution: CultureDistribution,
1830 #[serde(default = "default_email_domain")]
1832 pub email_domain: String,
1833 #[serde(default = "default_true")]
1835 pub generate_realistic_names: bool,
1836}
1837
1838fn default_email_domain() -> String {
1839 "company.com".to_string()
1840}
1841
1842impl Default for NameTemplateConfig {
1843 fn default() -> Self {
1844 Self {
1845 culture_distribution: CultureDistribution::default(),
1846 email_domain: default_email_domain(),
1847 generate_realistic_names: true,
1848 }
1849 }
1850}
1851
1852#[derive(Debug, Clone, Serialize, Deserialize)]
1854pub struct CultureDistribution {
1855 pub western_us: f64,
1856 pub hispanic: f64,
1857 pub german: f64,
1858 pub french: f64,
1859 pub chinese: f64,
1860 pub japanese: f64,
1861 pub indian: f64,
1862}
1863
1864impl Default for CultureDistribution {
1865 fn default() -> Self {
1866 Self {
1867 western_us: 0.40,
1868 hispanic: 0.20,
1869 german: 0.10,
1870 french: 0.05,
1871 chinese: 0.10,
1872 japanese: 0.05,
1873 indian: 0.10,
1874 }
1875 }
1876}
1877
1878#[derive(Debug, Clone, Serialize, Deserialize)]
1880pub struct DescriptionTemplateConfig {
1881 #[serde(default = "default_true")]
1883 pub generate_header_text: bool,
1884 #[serde(default = "default_true")]
1886 pub generate_line_text: bool,
1887}
1888
1889impl Default for DescriptionTemplateConfig {
1890 fn default() -> Self {
1891 Self {
1892 generate_header_text: true,
1893 generate_line_text: true,
1894 }
1895 }
1896}
1897
1898#[derive(Debug, Clone, Serialize, Deserialize)]
1900pub struct ReferenceTemplateConfig {
1901 #[serde(default = "default_true")]
1903 pub generate_references: bool,
1904 #[serde(default = "default_invoice_prefix")]
1906 pub invoice_prefix: String,
1907 #[serde(default = "default_po_prefix")]
1909 pub po_prefix: String,
1910 #[serde(default = "default_so_prefix")]
1912 pub so_prefix: String,
1913}
1914
1915fn default_invoice_prefix() -> String {
1916 "INV".to_string()
1917}
1918fn default_po_prefix() -> String {
1919 "PO".to_string()
1920}
1921fn default_so_prefix() -> String {
1922 "SO".to_string()
1923}
1924
1925impl Default for ReferenceTemplateConfig {
1926 fn default() -> Self {
1927 Self {
1928 generate_references: true,
1929 invoice_prefix: default_invoice_prefix(),
1930 po_prefix: default_po_prefix(),
1931 so_prefix: default_so_prefix(),
1932 }
1933 }
1934}
1935
1936#[derive(Debug, Clone, Serialize, Deserialize)]
1938pub struct ApprovalConfig {
1939 #[serde(default)]
1941 pub enabled: bool,
1942 #[serde(default = "default_auto_approve_threshold")]
1944 pub auto_approve_threshold: f64,
1945 #[serde(default = "default_rejection_rate")]
1947 pub rejection_rate: f64,
1948 #[serde(default = "default_revision_rate")]
1950 pub revision_rate: f64,
1951 #[serde(default = "default_approval_delay_hours")]
1953 pub average_approval_delay_hours: f64,
1954 #[serde(default)]
1956 pub thresholds: Vec<ApprovalThresholdConfig>,
1957}
1958
1959fn default_auto_approve_threshold() -> f64 {
1960 1000.0
1961}
1962fn default_rejection_rate() -> f64 {
1963 0.02
1964}
1965fn default_revision_rate() -> f64 {
1966 0.05
1967}
1968fn default_approval_delay_hours() -> f64 {
1969 4.0
1970}
1971
1972impl Default for ApprovalConfig {
1973 fn default() -> Self {
1974 Self {
1975 enabled: false,
1976 auto_approve_threshold: default_auto_approve_threshold(),
1977 rejection_rate: default_rejection_rate(),
1978 revision_rate: default_revision_rate(),
1979 average_approval_delay_hours: default_approval_delay_hours(),
1980 thresholds: vec![
1981 ApprovalThresholdConfig {
1982 amount: 1000.0,
1983 level: 1,
1984 roles: vec!["senior_accountant".to_string()],
1985 },
1986 ApprovalThresholdConfig {
1987 amount: 10000.0,
1988 level: 2,
1989 roles: vec!["senior_accountant".to_string(), "controller".to_string()],
1990 },
1991 ApprovalThresholdConfig {
1992 amount: 100000.0,
1993 level: 3,
1994 roles: vec![
1995 "senior_accountant".to_string(),
1996 "controller".to_string(),
1997 "manager".to_string(),
1998 ],
1999 },
2000 ApprovalThresholdConfig {
2001 amount: 500000.0,
2002 level: 4,
2003 roles: vec![
2004 "senior_accountant".to_string(),
2005 "controller".to_string(),
2006 "manager".to_string(),
2007 "executive".to_string(),
2008 ],
2009 },
2010 ],
2011 }
2012 }
2013}
2014
2015#[derive(Debug, Clone, Serialize, Deserialize)]
2017pub struct ApprovalThresholdConfig {
2018 pub amount: f64,
2020 pub level: u8,
2022 pub roles: Vec<String>,
2024}
2025
2026#[derive(Debug, Clone, Serialize, Deserialize)]
2028pub struct DepartmentConfig {
2029 #[serde(default)]
2031 pub enabled: bool,
2032 #[serde(default = "default_headcount_multiplier")]
2034 pub headcount_multiplier: f64,
2035 #[serde(default)]
2037 pub custom_departments: Vec<CustomDepartmentConfig>,
2038}
2039
2040fn default_headcount_multiplier() -> f64 {
2041 1.0
2042}
2043
2044impl Default for DepartmentConfig {
2045 fn default() -> Self {
2046 Self {
2047 enabled: false,
2048 headcount_multiplier: default_headcount_multiplier(),
2049 custom_departments: Vec::new(),
2050 }
2051 }
2052}
2053
2054#[derive(Debug, Clone, Serialize, Deserialize)]
2056pub struct CustomDepartmentConfig {
2057 pub code: String,
2059 pub name: String,
2061 #[serde(default)]
2063 pub cost_center: Option<String>,
2064 #[serde(default)]
2066 pub primary_processes: Vec<String>,
2067 #[serde(default)]
2069 pub parent_code: Option<String>,
2070}
2071
2072#[derive(Debug, Clone, Default, Serialize, Deserialize)]
2078pub struct MasterDataConfig {
2079 #[serde(default)]
2081 pub vendors: VendorMasterConfig,
2082 #[serde(default)]
2084 pub customers: CustomerMasterConfig,
2085 #[serde(default)]
2087 pub materials: MaterialMasterConfig,
2088 #[serde(default)]
2090 pub fixed_assets: FixedAssetMasterConfig,
2091 #[serde(default)]
2093 pub employees: EmployeeMasterConfig,
2094 #[serde(default)]
2096 pub cost_centers: CostCenterMasterConfig,
2097}
2098
2099#[derive(Debug, Clone, Serialize, Deserialize)]
2101pub struct VendorMasterConfig {
2102 #[serde(default = "default_vendor_count")]
2104 pub count: usize,
2105 #[serde(default = "default_intercompany_percent")]
2107 pub intercompany_percent: f64,
2108 #[serde(default)]
2110 pub payment_terms_distribution: PaymentTermsDistribution,
2111 #[serde(default)]
2113 pub behavior_distribution: VendorBehaviorDistribution,
2114 #[serde(default = "default_true")]
2116 pub generate_bank_accounts: bool,
2117 #[serde(default = "default_true")]
2119 pub generate_tax_ids: bool,
2120}
2121
2122fn default_vendor_count() -> usize {
2123 500
2124}
2125
2126fn default_intercompany_percent() -> f64 {
2127 0.05
2128}
2129
2130impl Default for VendorMasterConfig {
2131 fn default() -> Self {
2132 Self {
2133 count: default_vendor_count(),
2134 intercompany_percent: default_intercompany_percent(),
2135 payment_terms_distribution: PaymentTermsDistribution::default(),
2136 behavior_distribution: VendorBehaviorDistribution::default(),
2137 generate_bank_accounts: true,
2138 generate_tax_ids: true,
2139 }
2140 }
2141}
2142
2143#[derive(Debug, Clone, Serialize, Deserialize)]
2145pub struct PaymentTermsDistribution {
2146 pub net_30: f64,
2148 pub net_60: f64,
2150 pub net_90: f64,
2152 pub two_ten_net_30: f64,
2154 pub due_on_receipt: f64,
2156 pub end_of_month: f64,
2158}
2159
2160impl Default for PaymentTermsDistribution {
2161 fn default() -> Self {
2162 Self {
2163 net_30: 0.40,
2164 net_60: 0.20,
2165 net_90: 0.10,
2166 two_ten_net_30: 0.15,
2167 due_on_receipt: 0.05,
2168 end_of_month: 0.10,
2169 }
2170 }
2171}
2172
2173#[derive(Debug, Clone, Serialize, Deserialize)]
2175pub struct VendorBehaviorDistribution {
2176 pub reliable: f64,
2178 pub sometimes_late: f64,
2180 pub inconsistent_quality: f64,
2182 pub premium: f64,
2184 pub budget: f64,
2186}
2187
2188impl Default for VendorBehaviorDistribution {
2189 fn default() -> Self {
2190 Self {
2191 reliable: 0.50,
2192 sometimes_late: 0.20,
2193 inconsistent_quality: 0.10,
2194 premium: 0.10,
2195 budget: 0.10,
2196 }
2197 }
2198}
2199
2200#[derive(Debug, Clone, Serialize, Deserialize)]
2202pub struct CustomerMasterConfig {
2203 #[serde(default = "default_customer_count")]
2205 pub count: usize,
2206 #[serde(default = "default_intercompany_percent")]
2208 pub intercompany_percent: f64,
2209 #[serde(default)]
2211 pub credit_rating_distribution: CreditRatingDistribution,
2212 #[serde(default)]
2214 pub payment_behavior_distribution: PaymentBehaviorDistribution,
2215 #[serde(default = "default_true")]
2217 pub generate_credit_limits: bool,
2218}
2219
2220fn default_customer_count() -> usize {
2221 2000
2222}
2223
2224impl Default for CustomerMasterConfig {
2225 fn default() -> Self {
2226 Self {
2227 count: default_customer_count(),
2228 intercompany_percent: default_intercompany_percent(),
2229 credit_rating_distribution: CreditRatingDistribution::default(),
2230 payment_behavior_distribution: PaymentBehaviorDistribution::default(),
2231 generate_credit_limits: true,
2232 }
2233 }
2234}
2235
2236#[derive(Debug, Clone, Serialize, Deserialize)]
2238pub struct CreditRatingDistribution {
2239 pub aaa: f64,
2241 pub aa: f64,
2243 pub a: f64,
2245 pub bbb: f64,
2247 pub bb: f64,
2249 pub b: f64,
2251 pub below_b: f64,
2253}
2254
2255impl Default for CreditRatingDistribution {
2256 fn default() -> Self {
2257 Self {
2258 aaa: 0.05,
2259 aa: 0.10,
2260 a: 0.20,
2261 bbb: 0.30,
2262 bb: 0.20,
2263 b: 0.10,
2264 below_b: 0.05,
2265 }
2266 }
2267}
2268
2269#[derive(Debug, Clone, Serialize, Deserialize)]
2271pub struct PaymentBehaviorDistribution {
2272 pub early_payer: f64,
2274 pub on_time: f64,
2276 pub occasional_late: f64,
2278 pub frequent_late: f64,
2280 pub discount_taker: f64,
2282}
2283
2284impl Default for PaymentBehaviorDistribution {
2285 fn default() -> Self {
2286 Self {
2287 early_payer: 0.10,
2288 on_time: 0.50,
2289 occasional_late: 0.25,
2290 frequent_late: 0.10,
2291 discount_taker: 0.05,
2292 }
2293 }
2294}
2295
2296#[derive(Debug, Clone, Serialize, Deserialize)]
2298pub struct MaterialMasterConfig {
2299 #[serde(default = "default_material_count")]
2301 pub count: usize,
2302 #[serde(default)]
2304 pub type_distribution: MaterialTypeDistribution,
2305 #[serde(default)]
2307 pub valuation_distribution: ValuationMethodDistribution,
2308 #[serde(default = "default_bom_percent")]
2310 pub bom_percent: f64,
2311 #[serde(default = "default_max_bom_depth")]
2313 pub max_bom_depth: u8,
2314}
2315
2316fn default_material_count() -> usize {
2317 5000
2318}
2319
2320fn default_bom_percent() -> f64 {
2321 0.20
2322}
2323
2324fn default_max_bom_depth() -> u8 {
2325 3
2326}
2327
2328impl Default for MaterialMasterConfig {
2329 fn default() -> Self {
2330 Self {
2331 count: default_material_count(),
2332 type_distribution: MaterialTypeDistribution::default(),
2333 valuation_distribution: ValuationMethodDistribution::default(),
2334 bom_percent: default_bom_percent(),
2335 max_bom_depth: default_max_bom_depth(),
2336 }
2337 }
2338}
2339
2340#[derive(Debug, Clone, Serialize, Deserialize)]
2342pub struct MaterialTypeDistribution {
2343 pub raw_material: f64,
2345 pub semi_finished: f64,
2347 pub finished_good: f64,
2349 pub trading_good: f64,
2351 pub operating_supply: f64,
2353 pub service: f64,
2355}
2356
2357impl Default for MaterialTypeDistribution {
2358 fn default() -> Self {
2359 Self {
2360 raw_material: 0.30,
2361 semi_finished: 0.15,
2362 finished_good: 0.25,
2363 trading_good: 0.15,
2364 operating_supply: 0.10,
2365 service: 0.05,
2366 }
2367 }
2368}
2369
2370#[derive(Debug, Clone, Serialize, Deserialize)]
2372pub struct ValuationMethodDistribution {
2373 pub standard_cost: f64,
2375 pub moving_average: f64,
2377 pub fifo: f64,
2379 pub lifo: f64,
2381}
2382
2383impl Default for ValuationMethodDistribution {
2384 fn default() -> Self {
2385 Self {
2386 standard_cost: 0.50,
2387 moving_average: 0.30,
2388 fifo: 0.15,
2389 lifo: 0.05,
2390 }
2391 }
2392}
2393
2394#[derive(Debug, Clone, Serialize, Deserialize)]
2396pub struct FixedAssetMasterConfig {
2397 #[serde(default = "default_asset_count")]
2399 pub count: usize,
2400 #[serde(default)]
2402 pub class_distribution: AssetClassDistribution,
2403 #[serde(default)]
2405 pub depreciation_distribution: DepreciationMethodDistribution,
2406 #[serde(default = "default_fully_depreciated_percent")]
2408 pub fully_depreciated_percent: f64,
2409 #[serde(default = "default_true")]
2411 pub generate_acquisition_history: bool,
2412}
2413
2414fn default_asset_count() -> usize {
2415 800
2416}
2417
2418fn default_fully_depreciated_percent() -> f64 {
2419 0.15
2420}
2421
2422impl Default for FixedAssetMasterConfig {
2423 fn default() -> Self {
2424 Self {
2425 count: default_asset_count(),
2426 class_distribution: AssetClassDistribution::default(),
2427 depreciation_distribution: DepreciationMethodDistribution::default(),
2428 fully_depreciated_percent: default_fully_depreciated_percent(),
2429 generate_acquisition_history: true,
2430 }
2431 }
2432}
2433
2434#[derive(Debug, Clone, Serialize, Deserialize)]
2436pub struct AssetClassDistribution {
2437 pub buildings: f64,
2439 pub machinery: f64,
2441 pub vehicles: f64,
2443 pub it_equipment: f64,
2445 pub furniture: f64,
2447 pub land: f64,
2449 pub leasehold: f64,
2451}
2452
2453impl Default for AssetClassDistribution {
2454 fn default() -> Self {
2455 Self {
2456 buildings: 0.15,
2457 machinery: 0.30,
2458 vehicles: 0.15,
2459 it_equipment: 0.20,
2460 furniture: 0.10,
2461 land: 0.05,
2462 leasehold: 0.05,
2463 }
2464 }
2465}
2466
2467#[derive(Debug, Clone, Serialize, Deserialize)]
2469pub struct DepreciationMethodDistribution {
2470 pub straight_line: f64,
2472 pub declining_balance: f64,
2474 pub double_declining: f64,
2476 pub sum_of_years: f64,
2478 pub units_of_production: f64,
2480}
2481
2482impl Default for DepreciationMethodDistribution {
2483 fn default() -> Self {
2484 Self {
2485 straight_line: 0.60,
2486 declining_balance: 0.20,
2487 double_declining: 0.10,
2488 sum_of_years: 0.05,
2489 units_of_production: 0.05,
2490 }
2491 }
2492}
2493
2494#[derive(Debug, Clone, Serialize, Deserialize)]
2496pub struct EmployeeMasterConfig {
2497 #[serde(default = "default_employee_count")]
2499 pub count: usize,
2500 #[serde(default = "default_true")]
2502 pub generate_hierarchy: bool,
2503 #[serde(default = "default_hierarchy_depth")]
2505 pub max_hierarchy_depth: u8,
2506 #[serde(default = "default_span_of_control")]
2508 pub average_span_of_control: f64,
2509 #[serde(default)]
2511 pub approval_limits: ApprovalLimitDistribution,
2512 #[serde(default)]
2514 pub department_distribution: EmployeeDepartmentDistribution,
2515}
2516
2517fn default_employee_count() -> usize {
2518 1500
2519}
2520
2521fn default_hierarchy_depth() -> u8 {
2522 6
2523}
2524
2525fn default_span_of_control() -> f64 {
2526 5.0
2527}
2528
2529impl Default for EmployeeMasterConfig {
2530 fn default() -> Self {
2531 Self {
2532 count: default_employee_count(),
2533 generate_hierarchy: true,
2534 max_hierarchy_depth: default_hierarchy_depth(),
2535 average_span_of_control: default_span_of_control(),
2536 approval_limits: ApprovalLimitDistribution::default(),
2537 department_distribution: EmployeeDepartmentDistribution::default(),
2538 }
2539 }
2540}
2541
2542#[derive(Debug, Clone, Serialize, Deserialize)]
2544pub struct ApprovalLimitDistribution {
2545 #[serde(default = "default_staff_limit")]
2547 pub staff: f64,
2548 #[serde(default = "default_senior_limit")]
2550 pub senior: f64,
2551 #[serde(default = "default_manager_limit")]
2553 pub manager: f64,
2554 #[serde(default = "default_director_limit")]
2556 pub director: f64,
2557 #[serde(default = "default_vp_limit")]
2559 pub vp: f64,
2560 #[serde(default = "default_executive_limit")]
2562 pub executive: f64,
2563}
2564
2565fn default_staff_limit() -> f64 {
2566 1000.0
2567}
2568fn default_senior_limit() -> f64 {
2569 5000.0
2570}
2571fn default_manager_limit() -> f64 {
2572 25000.0
2573}
2574fn default_director_limit() -> f64 {
2575 100000.0
2576}
2577fn default_vp_limit() -> f64 {
2578 500000.0
2579}
2580fn default_executive_limit() -> f64 {
2581 f64::INFINITY
2582}
2583
2584impl Default for ApprovalLimitDistribution {
2585 fn default() -> Self {
2586 Self {
2587 staff: default_staff_limit(),
2588 senior: default_senior_limit(),
2589 manager: default_manager_limit(),
2590 director: default_director_limit(),
2591 vp: default_vp_limit(),
2592 executive: default_executive_limit(),
2593 }
2594 }
2595}
2596
2597#[derive(Debug, Clone, Serialize, Deserialize)]
2599pub struct EmployeeDepartmentDistribution {
2600 pub finance: f64,
2602 pub procurement: f64,
2604 pub sales: f64,
2606 pub warehouse: f64,
2608 pub it: f64,
2610 pub hr: f64,
2612 pub operations: f64,
2614 pub executive: f64,
2616}
2617
2618impl Default for EmployeeDepartmentDistribution {
2619 fn default() -> Self {
2620 Self {
2621 finance: 0.12,
2622 procurement: 0.10,
2623 sales: 0.25,
2624 warehouse: 0.15,
2625 it: 0.10,
2626 hr: 0.05,
2627 operations: 0.20,
2628 executive: 0.03,
2629 }
2630 }
2631}
2632
2633#[derive(Debug, Clone, Serialize, Deserialize)]
2635pub struct CostCenterMasterConfig {
2636 #[serde(default = "default_cost_center_count")]
2638 pub count: usize,
2639 #[serde(default = "default_true")]
2641 pub generate_hierarchy: bool,
2642 #[serde(default = "default_cc_hierarchy_depth")]
2644 pub max_hierarchy_depth: u8,
2645}
2646
2647fn default_cost_center_count() -> usize {
2648 50
2649}
2650
2651fn default_cc_hierarchy_depth() -> u8 {
2652 3
2653}
2654
2655impl Default for CostCenterMasterConfig {
2656 fn default() -> Self {
2657 Self {
2658 count: default_cost_center_count(),
2659 generate_hierarchy: true,
2660 max_hierarchy_depth: default_cc_hierarchy_depth(),
2661 }
2662 }
2663}
2664
2665#[derive(Debug, Clone, Serialize, Deserialize)]
2671pub struct DocumentFlowConfig {
2672 #[serde(default)]
2674 pub p2p: P2PFlowConfig,
2675 #[serde(default)]
2677 pub o2c: O2CFlowConfig,
2678 #[serde(default = "default_true")]
2680 pub generate_document_references: bool,
2681 #[serde(default)]
2683 pub export_flow_graph: bool,
2684}
2685
2686impl Default for DocumentFlowConfig {
2687 fn default() -> Self {
2688 Self {
2689 p2p: P2PFlowConfig::default(),
2690 o2c: O2CFlowConfig::default(),
2691 generate_document_references: true,
2692 export_flow_graph: false,
2693 }
2694 }
2695}
2696
2697#[derive(Debug, Clone, Serialize, Deserialize)]
2699pub struct P2PFlowConfig {
2700 #[serde(default = "default_true")]
2702 pub enabled: bool,
2703 #[serde(default = "default_three_way_match_rate")]
2705 pub three_way_match_rate: f64,
2706 #[serde(default = "default_partial_delivery_rate")]
2708 pub partial_delivery_rate: f64,
2709 #[serde(default = "default_price_variance_rate")]
2711 pub price_variance_rate: f64,
2712 #[serde(default = "default_max_price_variance")]
2714 pub max_price_variance_percent: f64,
2715 #[serde(default = "default_quantity_variance_rate")]
2717 pub quantity_variance_rate: f64,
2718 #[serde(default = "default_po_to_gr_days")]
2720 pub average_po_to_gr_days: u32,
2721 #[serde(default = "default_gr_to_invoice_days")]
2723 pub average_gr_to_invoice_days: u32,
2724 #[serde(default = "default_invoice_to_payment_days")]
2726 pub average_invoice_to_payment_days: u32,
2727 #[serde(default)]
2729 pub line_count_distribution: DocumentLineCountDistribution,
2730 #[serde(default)]
2732 pub payment_behavior: P2PPaymentBehaviorConfig,
2733 #[serde(default)]
2735 pub over_delivery_rate: Option<f64>,
2736 #[serde(default)]
2738 pub early_payment_discount_rate: Option<f64>,
2739}
2740
2741fn default_three_way_match_rate() -> f64 {
2742 0.95
2743}
2744
2745fn default_partial_delivery_rate() -> f64 {
2746 0.15
2747}
2748
2749fn default_price_variance_rate() -> f64 {
2750 0.08
2751}
2752
2753fn default_max_price_variance() -> f64 {
2754 0.05
2755}
2756
2757fn default_quantity_variance_rate() -> f64 {
2758 0.05
2759}
2760
2761fn default_po_to_gr_days() -> u32 {
2762 14
2763}
2764
2765fn default_gr_to_invoice_days() -> u32 {
2766 5
2767}
2768
2769fn default_invoice_to_payment_days() -> u32 {
2770 30
2771}
2772
2773impl Default for P2PFlowConfig {
2774 fn default() -> Self {
2775 Self {
2776 enabled: true,
2777 three_way_match_rate: default_three_way_match_rate(),
2778 partial_delivery_rate: default_partial_delivery_rate(),
2779 price_variance_rate: default_price_variance_rate(),
2780 max_price_variance_percent: default_max_price_variance(),
2781 quantity_variance_rate: default_quantity_variance_rate(),
2782 average_po_to_gr_days: default_po_to_gr_days(),
2783 average_gr_to_invoice_days: default_gr_to_invoice_days(),
2784 average_invoice_to_payment_days: default_invoice_to_payment_days(),
2785 line_count_distribution: DocumentLineCountDistribution::default(),
2786 payment_behavior: P2PPaymentBehaviorConfig::default(),
2787 over_delivery_rate: None,
2788 early_payment_discount_rate: None,
2789 }
2790 }
2791}
2792
2793#[derive(Debug, Clone, Serialize, Deserialize)]
2799pub struct P2PPaymentBehaviorConfig {
2800 #[serde(default = "default_p2p_late_payment_rate")]
2802 pub late_payment_rate: f64,
2803 #[serde(default)]
2805 pub late_payment_days_distribution: LatePaymentDaysDistribution,
2806 #[serde(default = "default_p2p_partial_payment_rate")]
2808 pub partial_payment_rate: f64,
2809 #[serde(default = "default_p2p_payment_correction_rate")]
2811 pub payment_correction_rate: f64,
2812 #[serde(default = "default_p2p_avg_days_until_remainder")]
2814 pub avg_days_until_remainder: u32,
2815}
2816
2817fn default_p2p_late_payment_rate() -> f64 {
2818 0.15
2819}
2820
2821fn default_p2p_partial_payment_rate() -> f64 {
2822 0.05
2823}
2824
2825fn default_p2p_payment_correction_rate() -> f64 {
2826 0.02
2827}
2828
2829fn default_p2p_avg_days_until_remainder() -> u32 {
2830 30
2831}
2832
2833impl Default for P2PPaymentBehaviorConfig {
2834 fn default() -> Self {
2835 Self {
2836 late_payment_rate: default_p2p_late_payment_rate(),
2837 late_payment_days_distribution: LatePaymentDaysDistribution::default(),
2838 partial_payment_rate: default_p2p_partial_payment_rate(),
2839 payment_correction_rate: default_p2p_payment_correction_rate(),
2840 avg_days_until_remainder: default_p2p_avg_days_until_remainder(),
2841 }
2842 }
2843}
2844
2845#[derive(Debug, Clone, Serialize, Deserialize)]
2847pub struct LatePaymentDaysDistribution {
2848 #[serde(default = "default_slightly_late")]
2850 pub slightly_late_1_to_7: f64,
2851 #[serde(default = "default_late_8_14")]
2853 pub late_8_to_14: f64,
2854 #[serde(default = "default_very_late")]
2856 pub very_late_15_to_30: f64,
2857 #[serde(default = "default_severely_late")]
2859 pub severely_late_31_to_60: f64,
2860 #[serde(default = "default_extremely_late")]
2862 pub extremely_late_over_60: f64,
2863}
2864
2865fn default_slightly_late() -> f64 {
2866 0.50
2867}
2868
2869fn default_late_8_14() -> f64 {
2870 0.25
2871}
2872
2873fn default_very_late() -> f64 {
2874 0.15
2875}
2876
2877fn default_severely_late() -> f64 {
2878 0.07
2879}
2880
2881fn default_extremely_late() -> f64 {
2882 0.03
2883}
2884
2885impl Default for LatePaymentDaysDistribution {
2886 fn default() -> Self {
2887 Self {
2888 slightly_late_1_to_7: default_slightly_late(),
2889 late_8_to_14: default_late_8_14(),
2890 very_late_15_to_30: default_very_late(),
2891 severely_late_31_to_60: default_severely_late(),
2892 extremely_late_over_60: default_extremely_late(),
2893 }
2894 }
2895}
2896
2897#[derive(Debug, Clone, Serialize, Deserialize)]
2899pub struct O2CFlowConfig {
2900 #[serde(default = "default_true")]
2902 pub enabled: bool,
2903 #[serde(default = "default_credit_check_failure_rate")]
2905 pub credit_check_failure_rate: f64,
2906 #[serde(default = "default_partial_shipment_rate")]
2908 pub partial_shipment_rate: f64,
2909 #[serde(default = "default_return_rate")]
2911 pub return_rate: f64,
2912 #[serde(default = "default_bad_debt_rate")]
2914 pub bad_debt_rate: f64,
2915 #[serde(default = "default_so_to_delivery_days")]
2917 pub average_so_to_delivery_days: u32,
2918 #[serde(default = "default_delivery_to_invoice_days")]
2920 pub average_delivery_to_invoice_days: u32,
2921 #[serde(default = "default_invoice_to_receipt_days")]
2923 pub average_invoice_to_receipt_days: u32,
2924 #[serde(default)]
2926 pub line_count_distribution: DocumentLineCountDistribution,
2927 #[serde(default)]
2929 pub cash_discount: CashDiscountConfig,
2930 #[serde(default)]
2932 pub payment_behavior: O2CPaymentBehaviorConfig,
2933 #[serde(default)]
2935 pub late_payment_rate: Option<f64>,
2936}
2937
2938fn default_credit_check_failure_rate() -> f64 {
2939 0.02
2940}
2941
2942fn default_partial_shipment_rate() -> f64 {
2943 0.10
2944}
2945
2946fn default_return_rate() -> f64 {
2947 0.03
2948}
2949
2950fn default_bad_debt_rate() -> f64 {
2951 0.01
2952}
2953
2954fn default_so_to_delivery_days() -> u32 {
2955 7
2956}
2957
2958fn default_delivery_to_invoice_days() -> u32 {
2959 1
2960}
2961
2962fn default_invoice_to_receipt_days() -> u32 {
2963 45
2964}
2965
2966impl Default for O2CFlowConfig {
2967 fn default() -> Self {
2968 Self {
2969 enabled: true,
2970 credit_check_failure_rate: default_credit_check_failure_rate(),
2971 partial_shipment_rate: default_partial_shipment_rate(),
2972 return_rate: default_return_rate(),
2973 bad_debt_rate: default_bad_debt_rate(),
2974 average_so_to_delivery_days: default_so_to_delivery_days(),
2975 average_delivery_to_invoice_days: default_delivery_to_invoice_days(),
2976 average_invoice_to_receipt_days: default_invoice_to_receipt_days(),
2977 line_count_distribution: DocumentLineCountDistribution::default(),
2978 cash_discount: CashDiscountConfig::default(),
2979 payment_behavior: O2CPaymentBehaviorConfig::default(),
2980 late_payment_rate: None,
2981 }
2982 }
2983}
2984
2985#[derive(Debug, Clone, Serialize, Deserialize, Default)]
2991pub struct O2CPaymentBehaviorConfig {
2992 #[serde(default)]
2994 pub dunning: DunningConfig,
2995 #[serde(default)]
2997 pub partial_payments: PartialPaymentConfig,
2998 #[serde(default)]
3000 pub short_payments: ShortPaymentConfig,
3001 #[serde(default)]
3003 pub on_account_payments: OnAccountPaymentConfig,
3004 #[serde(default)]
3006 pub payment_corrections: PaymentCorrectionConfig,
3007}
3008
3009#[derive(Debug, Clone, Serialize, Deserialize)]
3011pub struct DunningConfig {
3012 #[serde(default)]
3014 pub enabled: bool,
3015 #[serde(default = "default_dunning_level_1_days")]
3017 pub level_1_days_overdue: u32,
3018 #[serde(default = "default_dunning_level_2_days")]
3020 pub level_2_days_overdue: u32,
3021 #[serde(default = "default_dunning_level_3_days")]
3023 pub level_3_days_overdue: u32,
3024 #[serde(default = "default_collection_days")]
3026 pub collection_days_overdue: u32,
3027 #[serde(default)]
3029 pub payment_after_dunning_rates: DunningPaymentRates,
3030 #[serde(default = "default_dunning_block_rate")]
3032 pub dunning_block_rate: f64,
3033 #[serde(default = "default_dunning_interest_rate")]
3035 pub interest_rate_per_year: f64,
3036 #[serde(default = "default_dunning_charge")]
3038 pub dunning_charge: f64,
3039}
3040
3041fn default_dunning_level_1_days() -> u32 {
3042 14
3043}
3044
3045fn default_dunning_level_2_days() -> u32 {
3046 28
3047}
3048
3049fn default_dunning_level_3_days() -> u32 {
3050 42
3051}
3052
3053fn default_collection_days() -> u32 {
3054 60
3055}
3056
3057fn default_dunning_block_rate() -> f64 {
3058 0.05
3059}
3060
3061fn default_dunning_interest_rate() -> f64 {
3062 0.09
3063}
3064
3065fn default_dunning_charge() -> f64 {
3066 25.0
3067}
3068
3069impl Default for DunningConfig {
3070 fn default() -> Self {
3071 Self {
3072 enabled: false,
3073 level_1_days_overdue: default_dunning_level_1_days(),
3074 level_2_days_overdue: default_dunning_level_2_days(),
3075 level_3_days_overdue: default_dunning_level_3_days(),
3076 collection_days_overdue: default_collection_days(),
3077 payment_after_dunning_rates: DunningPaymentRates::default(),
3078 dunning_block_rate: default_dunning_block_rate(),
3079 interest_rate_per_year: default_dunning_interest_rate(),
3080 dunning_charge: default_dunning_charge(),
3081 }
3082 }
3083}
3084
3085#[derive(Debug, Clone, Serialize, Deserialize)]
3087pub struct DunningPaymentRates {
3088 #[serde(default = "default_after_level_1")]
3090 pub after_level_1: f64,
3091 #[serde(default = "default_after_level_2")]
3093 pub after_level_2: f64,
3094 #[serde(default = "default_after_level_3")]
3096 pub after_level_3: f64,
3097 #[serde(default = "default_during_collection")]
3099 pub during_collection: f64,
3100 #[serde(default = "default_never_pay")]
3102 pub never_pay: f64,
3103}
3104
3105fn default_after_level_1() -> f64 {
3106 0.40
3107}
3108
3109fn default_after_level_2() -> f64 {
3110 0.30
3111}
3112
3113fn default_after_level_3() -> f64 {
3114 0.15
3115}
3116
3117fn default_during_collection() -> f64 {
3118 0.05
3119}
3120
3121fn default_never_pay() -> f64 {
3122 0.10
3123}
3124
3125impl Default for DunningPaymentRates {
3126 fn default() -> Self {
3127 Self {
3128 after_level_1: default_after_level_1(),
3129 after_level_2: default_after_level_2(),
3130 after_level_3: default_after_level_3(),
3131 during_collection: default_during_collection(),
3132 never_pay: default_never_pay(),
3133 }
3134 }
3135}
3136
3137#[derive(Debug, Clone, Serialize, Deserialize)]
3139pub struct PartialPaymentConfig {
3140 #[serde(default = "default_partial_payment_rate")]
3142 pub rate: f64,
3143 #[serde(default)]
3145 pub percentage_distribution: PartialPaymentPercentageDistribution,
3146 #[serde(default = "default_avg_days_until_remainder")]
3148 pub avg_days_until_remainder: u32,
3149}
3150
3151fn default_partial_payment_rate() -> f64 {
3152 0.08
3153}
3154
3155fn default_avg_days_until_remainder() -> u32 {
3156 30
3157}
3158
3159impl Default for PartialPaymentConfig {
3160 fn default() -> Self {
3161 Self {
3162 rate: default_partial_payment_rate(),
3163 percentage_distribution: PartialPaymentPercentageDistribution::default(),
3164 avg_days_until_remainder: default_avg_days_until_remainder(),
3165 }
3166 }
3167}
3168
3169#[derive(Debug, Clone, Serialize, Deserialize)]
3171pub struct PartialPaymentPercentageDistribution {
3172 #[serde(default = "default_partial_25")]
3174 pub pay_25_percent: f64,
3175 #[serde(default = "default_partial_50")]
3177 pub pay_50_percent: f64,
3178 #[serde(default = "default_partial_75")]
3180 pub pay_75_percent: f64,
3181 #[serde(default = "default_partial_random")]
3183 pub pay_random_percent: f64,
3184}
3185
3186fn default_partial_25() -> f64 {
3187 0.15
3188}
3189
3190fn default_partial_50() -> f64 {
3191 0.50
3192}
3193
3194fn default_partial_75() -> f64 {
3195 0.25
3196}
3197
3198fn default_partial_random() -> f64 {
3199 0.10
3200}
3201
3202impl Default for PartialPaymentPercentageDistribution {
3203 fn default() -> Self {
3204 Self {
3205 pay_25_percent: default_partial_25(),
3206 pay_50_percent: default_partial_50(),
3207 pay_75_percent: default_partial_75(),
3208 pay_random_percent: default_partial_random(),
3209 }
3210 }
3211}
3212
3213#[derive(Debug, Clone, Serialize, Deserialize)]
3215pub struct ShortPaymentConfig {
3216 #[serde(default = "default_short_payment_rate")]
3218 pub rate: f64,
3219 #[serde(default)]
3221 pub reason_distribution: ShortPaymentReasonDistribution,
3222 #[serde(default = "default_max_short_percent")]
3224 pub max_short_percent: f64,
3225}
3226
3227fn default_short_payment_rate() -> f64 {
3228 0.03
3229}
3230
3231fn default_max_short_percent() -> f64 {
3232 0.10
3233}
3234
3235impl Default for ShortPaymentConfig {
3236 fn default() -> Self {
3237 Self {
3238 rate: default_short_payment_rate(),
3239 reason_distribution: ShortPaymentReasonDistribution::default(),
3240 max_short_percent: default_max_short_percent(),
3241 }
3242 }
3243}
3244
3245#[derive(Debug, Clone, Serialize, Deserialize)]
3247pub struct ShortPaymentReasonDistribution {
3248 #[serde(default = "default_pricing_dispute")]
3250 pub pricing_dispute: f64,
3251 #[serde(default = "default_quality_issue")]
3253 pub quality_issue: f64,
3254 #[serde(default = "default_quantity_discrepancy")]
3256 pub quantity_discrepancy: f64,
3257 #[serde(default = "default_unauthorized_deduction")]
3259 pub unauthorized_deduction: f64,
3260 #[serde(default = "default_incorrect_discount")]
3262 pub incorrect_discount: f64,
3263}
3264
3265fn default_pricing_dispute() -> f64 {
3266 0.30
3267}
3268
3269fn default_quality_issue() -> f64 {
3270 0.20
3271}
3272
3273fn default_quantity_discrepancy() -> f64 {
3274 0.20
3275}
3276
3277fn default_unauthorized_deduction() -> f64 {
3278 0.15
3279}
3280
3281fn default_incorrect_discount() -> f64 {
3282 0.15
3283}
3284
3285impl Default for ShortPaymentReasonDistribution {
3286 fn default() -> Self {
3287 Self {
3288 pricing_dispute: default_pricing_dispute(),
3289 quality_issue: default_quality_issue(),
3290 quantity_discrepancy: default_quantity_discrepancy(),
3291 unauthorized_deduction: default_unauthorized_deduction(),
3292 incorrect_discount: default_incorrect_discount(),
3293 }
3294 }
3295}
3296
3297#[derive(Debug, Clone, Serialize, Deserialize)]
3299pub struct OnAccountPaymentConfig {
3300 #[serde(default = "default_on_account_rate")]
3302 pub rate: f64,
3303 #[serde(default = "default_avg_days_until_applied")]
3305 pub avg_days_until_applied: u32,
3306}
3307
3308fn default_on_account_rate() -> f64 {
3309 0.02
3310}
3311
3312fn default_avg_days_until_applied() -> u32 {
3313 14
3314}
3315
3316impl Default for OnAccountPaymentConfig {
3317 fn default() -> Self {
3318 Self {
3319 rate: default_on_account_rate(),
3320 avg_days_until_applied: default_avg_days_until_applied(),
3321 }
3322 }
3323}
3324
3325#[derive(Debug, Clone, Serialize, Deserialize)]
3327pub struct PaymentCorrectionConfig {
3328 #[serde(default = "default_payment_correction_rate")]
3330 pub rate: f64,
3331 #[serde(default)]
3333 pub type_distribution: PaymentCorrectionTypeDistribution,
3334}
3335
3336fn default_payment_correction_rate() -> f64 {
3337 0.02
3338}
3339
3340impl Default for PaymentCorrectionConfig {
3341 fn default() -> Self {
3342 Self {
3343 rate: default_payment_correction_rate(),
3344 type_distribution: PaymentCorrectionTypeDistribution::default(),
3345 }
3346 }
3347}
3348
3349#[derive(Debug, Clone, Serialize, Deserialize)]
3351pub struct PaymentCorrectionTypeDistribution {
3352 #[serde(default = "default_nsf_rate")]
3354 pub nsf: f64,
3355 #[serde(default = "default_chargeback_rate")]
3357 pub chargeback: f64,
3358 #[serde(default = "default_wrong_amount_rate")]
3360 pub wrong_amount: f64,
3361 #[serde(default = "default_wrong_customer_rate")]
3363 pub wrong_customer: f64,
3364 #[serde(default = "default_duplicate_payment_rate")]
3366 pub duplicate_payment: f64,
3367}
3368
3369fn default_nsf_rate() -> f64 {
3370 0.30
3371}
3372
3373fn default_chargeback_rate() -> f64 {
3374 0.20
3375}
3376
3377fn default_wrong_amount_rate() -> f64 {
3378 0.20
3379}
3380
3381fn default_wrong_customer_rate() -> f64 {
3382 0.15
3383}
3384
3385fn default_duplicate_payment_rate() -> f64 {
3386 0.15
3387}
3388
3389impl Default for PaymentCorrectionTypeDistribution {
3390 fn default() -> Self {
3391 Self {
3392 nsf: default_nsf_rate(),
3393 chargeback: default_chargeback_rate(),
3394 wrong_amount: default_wrong_amount_rate(),
3395 wrong_customer: default_wrong_customer_rate(),
3396 duplicate_payment: default_duplicate_payment_rate(),
3397 }
3398 }
3399}
3400
3401#[derive(Debug, Clone, Serialize, Deserialize)]
3403pub struct DocumentLineCountDistribution {
3404 #[serde(default = "default_min_lines")]
3406 pub min_lines: u32,
3407 #[serde(default = "default_max_lines")]
3409 pub max_lines: u32,
3410 #[serde(default = "default_mode_lines")]
3412 pub mode_lines: u32,
3413}
3414
3415fn default_min_lines() -> u32 {
3416 1
3417}
3418
3419fn default_max_lines() -> u32 {
3420 20
3421}
3422
3423fn default_mode_lines() -> u32 {
3424 3
3425}
3426
3427impl Default for DocumentLineCountDistribution {
3428 fn default() -> Self {
3429 Self {
3430 min_lines: default_min_lines(),
3431 max_lines: default_max_lines(),
3432 mode_lines: default_mode_lines(),
3433 }
3434 }
3435}
3436
3437#[derive(Debug, Clone, Serialize, Deserialize)]
3439pub struct CashDiscountConfig {
3440 #[serde(default = "default_discount_eligible_rate")]
3442 pub eligible_rate: f64,
3443 #[serde(default = "default_discount_taken_rate")]
3445 pub taken_rate: f64,
3446 #[serde(default = "default_discount_percent")]
3448 pub discount_percent: f64,
3449 #[serde(default = "default_discount_days")]
3451 pub discount_days: u32,
3452}
3453
3454fn default_discount_eligible_rate() -> f64 {
3455 0.30
3456}
3457
3458fn default_discount_taken_rate() -> f64 {
3459 0.60
3460}
3461
3462fn default_discount_percent() -> f64 {
3463 0.02
3464}
3465
3466fn default_discount_days() -> u32 {
3467 10
3468}
3469
3470impl Default for CashDiscountConfig {
3471 fn default() -> Self {
3472 Self {
3473 eligible_rate: default_discount_eligible_rate(),
3474 taken_rate: default_discount_taken_rate(),
3475 discount_percent: default_discount_percent(),
3476 discount_days: default_discount_days(),
3477 }
3478 }
3479}
3480
3481#[derive(Debug, Clone, Serialize, Deserialize)]
3487pub struct IntercompanyConfig {
3488 #[serde(default)]
3490 pub enabled: bool,
3491 #[serde(default = "default_ic_transaction_rate")]
3493 pub ic_transaction_rate: f64,
3494 #[serde(default)]
3496 pub transfer_pricing_method: TransferPricingMethod,
3497 #[serde(default = "default_markup_percent")]
3499 pub markup_percent: f64,
3500 #[serde(default = "default_true")]
3502 pub generate_matched_pairs: bool,
3503 #[serde(default)]
3505 pub transaction_type_distribution: ICTransactionTypeDistribution,
3506 #[serde(default)]
3508 pub generate_eliminations: bool,
3509}
3510
3511fn default_ic_transaction_rate() -> f64 {
3512 0.15
3513}
3514
3515fn default_markup_percent() -> f64 {
3516 0.05
3517}
3518
3519impl Default for IntercompanyConfig {
3520 fn default() -> Self {
3521 Self {
3522 enabled: false,
3523 ic_transaction_rate: default_ic_transaction_rate(),
3524 transfer_pricing_method: TransferPricingMethod::default(),
3525 markup_percent: default_markup_percent(),
3526 generate_matched_pairs: true,
3527 transaction_type_distribution: ICTransactionTypeDistribution::default(),
3528 generate_eliminations: false,
3529 }
3530 }
3531}
3532
3533#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
3535#[serde(rename_all = "snake_case")]
3536pub enum TransferPricingMethod {
3537 #[default]
3539 CostPlus,
3540 ComparableUncontrolled,
3542 ResalePrice,
3544 TransactionalNetMargin,
3546 ProfitSplit,
3548}
3549
3550#[derive(Debug, Clone, Serialize, Deserialize)]
3552pub struct ICTransactionTypeDistribution {
3553 pub goods_sale: f64,
3555 pub service_provided: f64,
3557 pub loan: f64,
3559 pub dividend: f64,
3561 pub management_fee: f64,
3563 pub royalty: f64,
3565 pub cost_sharing: f64,
3567}
3568
3569impl Default for ICTransactionTypeDistribution {
3570 fn default() -> Self {
3571 Self {
3572 goods_sale: 0.35,
3573 service_provided: 0.20,
3574 loan: 0.10,
3575 dividend: 0.05,
3576 management_fee: 0.15,
3577 royalty: 0.10,
3578 cost_sharing: 0.05,
3579 }
3580 }
3581}
3582
3583#[derive(Debug, Clone, Serialize, Deserialize)]
3589pub struct BalanceConfig {
3590 #[serde(default)]
3592 pub generate_opening_balances: bool,
3593 #[serde(default = "default_true")]
3595 pub generate_trial_balances: bool,
3596 #[serde(default = "default_gross_margin")]
3598 pub target_gross_margin: f64,
3599 #[serde(default = "default_dso")]
3601 pub target_dso_days: u32,
3602 #[serde(default = "default_dpo")]
3604 pub target_dpo_days: u32,
3605 #[serde(default = "default_current_ratio")]
3607 pub target_current_ratio: f64,
3608 #[serde(default = "default_debt_equity")]
3610 pub target_debt_to_equity: f64,
3611 #[serde(default = "default_true")]
3613 pub validate_balance_equation: bool,
3614 #[serde(default = "default_true")]
3616 pub reconcile_subledgers: bool,
3617}
3618
3619fn default_gross_margin() -> f64 {
3620 0.35
3621}
3622
3623fn default_dso() -> u32 {
3624 45
3625}
3626
3627fn default_dpo() -> u32 {
3628 30
3629}
3630
3631fn default_current_ratio() -> f64 {
3632 1.5
3633}
3634
3635fn default_debt_equity() -> f64 {
3636 0.5
3637}
3638
3639impl Default for BalanceConfig {
3640 fn default() -> Self {
3641 Self {
3642 generate_opening_balances: false,
3643 generate_trial_balances: true,
3644 target_gross_margin: default_gross_margin(),
3645 target_dso_days: default_dso(),
3646 target_dpo_days: default_dpo(),
3647 target_current_ratio: default_current_ratio(),
3648 target_debt_to_equity: default_debt_equity(),
3649 validate_balance_equation: true,
3650 reconcile_subledgers: true,
3651 }
3652 }
3653}
3654
3655#[derive(Debug, Clone, Serialize, Deserialize)]
3664pub struct OcpmConfig {
3665 #[serde(default)]
3667 pub enabled: bool,
3668
3669 #[serde(default = "default_true")]
3671 pub generate_lifecycle_events: bool,
3672
3673 #[serde(default = "default_true")]
3675 pub include_object_relationships: bool,
3676
3677 #[serde(default = "default_true")]
3679 pub compute_variants: bool,
3680
3681 #[serde(default)]
3683 pub max_variants: usize,
3684
3685 #[serde(default)]
3687 pub p2p_process: OcpmProcessConfig,
3688
3689 #[serde(default)]
3691 pub o2c_process: OcpmProcessConfig,
3692
3693 #[serde(default)]
3695 pub output: OcpmOutputConfig,
3696}
3697
3698impl Default for OcpmConfig {
3699 fn default() -> Self {
3700 Self {
3701 enabled: false,
3702 generate_lifecycle_events: true,
3703 include_object_relationships: true,
3704 compute_variants: true,
3705 max_variants: 0,
3706 p2p_process: OcpmProcessConfig::default(),
3707 o2c_process: OcpmProcessConfig::default(),
3708 output: OcpmOutputConfig::default(),
3709 }
3710 }
3711}
3712
3713#[derive(Debug, Clone, Serialize, Deserialize)]
3715pub struct OcpmProcessConfig {
3716 #[serde(default = "default_rework_probability")]
3718 pub rework_probability: f64,
3719
3720 #[serde(default = "default_skip_probability")]
3722 pub skip_step_probability: f64,
3723
3724 #[serde(default = "default_out_of_order_probability")]
3726 pub out_of_order_probability: f64,
3727}
3728
3729fn default_rework_probability() -> f64 {
3730 0.05
3731}
3732
3733fn default_skip_probability() -> f64 {
3734 0.02
3735}
3736
3737fn default_out_of_order_probability() -> f64 {
3738 0.03
3739}
3740
3741impl Default for OcpmProcessConfig {
3742 fn default() -> Self {
3743 Self {
3744 rework_probability: default_rework_probability(),
3745 skip_step_probability: default_skip_probability(),
3746 out_of_order_probability: default_out_of_order_probability(),
3747 }
3748 }
3749}
3750
3751#[derive(Debug, Clone, Serialize, Deserialize)]
3753pub struct OcpmOutputConfig {
3754 #[serde(default = "default_true")]
3756 pub ocel_json: bool,
3757
3758 #[serde(default)]
3760 pub ocel_xml: bool,
3761
3762 #[serde(default)]
3764 pub xes: bool,
3765
3766 #[serde(default = "default_true")]
3768 pub xes_include_lifecycle: bool,
3769
3770 #[serde(default = "default_true")]
3772 pub xes_include_resources: bool,
3773
3774 #[serde(default = "default_true")]
3776 pub flattened_csv: bool,
3777
3778 #[serde(default = "default_true")]
3780 pub event_object_csv: bool,
3781
3782 #[serde(default = "default_true")]
3784 pub object_relationship_csv: bool,
3785
3786 #[serde(default = "default_true")]
3788 pub variants_csv: bool,
3789
3790 #[serde(default)]
3792 pub export_reference_models: bool,
3793}
3794
3795impl Default for OcpmOutputConfig {
3796 fn default() -> Self {
3797 Self {
3798 ocel_json: true,
3799 ocel_xml: false,
3800 xes: false,
3801 xes_include_lifecycle: true,
3802 xes_include_resources: true,
3803 flattened_csv: true,
3804 event_object_csv: true,
3805 object_relationship_csv: true,
3806 variants_csv: true,
3807 export_reference_models: false,
3808 }
3809 }
3810}
3811
3812#[derive(Debug, Clone, Serialize, Deserialize)]
3814pub struct AuditGenerationConfig {
3815 #[serde(default)]
3817 pub enabled: bool,
3818
3819 #[serde(default = "default_true")]
3822 pub generate_workpapers: bool,
3823
3824 #[serde(default)]
3827 pub engagement_types: AuditEngagementTypesConfig,
3828
3829 #[serde(default)]
3832 pub workpapers: WorkpaperConfig,
3833
3834 #[serde(default)]
3837 pub team: AuditTeamConfig,
3838
3839 #[serde(default)]
3842 pub review: ReviewWorkflowConfig,
3843}
3844
3845impl Default for AuditGenerationConfig {
3846 fn default() -> Self {
3847 Self {
3848 enabled: false,
3849 generate_workpapers: true,
3850 engagement_types: AuditEngagementTypesConfig::default(),
3851 workpapers: WorkpaperConfig::default(),
3852 team: AuditTeamConfig::default(),
3853 review: ReviewWorkflowConfig::default(),
3854 }
3855 }
3856}
3857
3858#[derive(Debug, Clone, Serialize, Deserialize)]
3860pub struct AuditEngagementTypesConfig {
3861 #[serde(default = "default_financial_audit_prob")]
3863 pub financial_statement: f64,
3864 #[serde(default = "default_sox_audit_prob")]
3866 pub sox_icfr: f64,
3867 #[serde(default = "default_integrated_audit_prob")]
3869 pub integrated: f64,
3870 #[serde(default = "default_review_prob")]
3872 pub review: f64,
3873 #[serde(default = "default_aup_prob")]
3875 pub agreed_upon_procedures: f64,
3876}
3877
3878fn default_financial_audit_prob() -> f64 {
3879 0.40
3880}
3881fn default_sox_audit_prob() -> f64 {
3882 0.20
3883}
3884fn default_integrated_audit_prob() -> f64 {
3885 0.25
3886}
3887fn default_review_prob() -> f64 {
3888 0.10
3889}
3890fn default_aup_prob() -> f64 {
3891 0.05
3892}
3893
3894impl Default for AuditEngagementTypesConfig {
3895 fn default() -> Self {
3896 Self {
3897 financial_statement: default_financial_audit_prob(),
3898 sox_icfr: default_sox_audit_prob(),
3899 integrated: default_integrated_audit_prob(),
3900 review: default_review_prob(),
3901 agreed_upon_procedures: default_aup_prob(),
3902 }
3903 }
3904}
3905
3906#[derive(Debug, Clone, Serialize, Deserialize)]
3908pub struct WorkpaperConfig {
3909 #[serde(default = "default_workpapers_per_phase")]
3911 pub average_per_phase: usize,
3912
3913 #[serde(default = "default_true")]
3915 pub include_isa_references: bool,
3916
3917 #[serde(default = "default_true")]
3919 pub include_sample_details: bool,
3920
3921 #[serde(default = "default_true")]
3923 pub include_cross_references: bool,
3924
3925 #[serde(default)]
3927 pub sampling: SamplingConfig,
3928}
3929
3930fn default_workpapers_per_phase() -> usize {
3931 5
3932}
3933
3934impl Default for WorkpaperConfig {
3935 fn default() -> Self {
3936 Self {
3937 average_per_phase: default_workpapers_per_phase(),
3938 include_isa_references: true,
3939 include_sample_details: true,
3940 include_cross_references: true,
3941 sampling: SamplingConfig::default(),
3942 }
3943 }
3944}
3945
3946#[derive(Debug, Clone, Serialize, Deserialize)]
3948pub struct SamplingConfig {
3949 #[serde(default = "default_statistical_rate")]
3951 pub statistical_rate: f64,
3952 #[serde(default = "default_judgmental_rate")]
3954 pub judgmental_rate: f64,
3955 #[serde(default = "default_haphazard_rate")]
3957 pub haphazard_rate: f64,
3958 #[serde(default = "default_complete_examination_rate")]
3960 pub complete_examination_rate: f64,
3961}
3962
3963fn default_statistical_rate() -> f64 {
3964 0.40
3965}
3966fn default_judgmental_rate() -> f64 {
3967 0.30
3968}
3969fn default_haphazard_rate() -> f64 {
3970 0.20
3971}
3972fn default_complete_examination_rate() -> f64 {
3973 0.10
3974}
3975
3976impl Default for SamplingConfig {
3977 fn default() -> Self {
3978 Self {
3979 statistical_rate: default_statistical_rate(),
3980 judgmental_rate: default_judgmental_rate(),
3981 haphazard_rate: default_haphazard_rate(),
3982 complete_examination_rate: default_complete_examination_rate(),
3983 }
3984 }
3985}
3986
3987#[derive(Debug, Clone, Serialize, Deserialize)]
3989pub struct AuditTeamConfig {
3990 #[serde(default = "default_min_team_size")]
3992 pub min_team_size: usize,
3993 #[serde(default = "default_max_team_size")]
3995 pub max_team_size: usize,
3996 #[serde(default = "default_specialist_probability")]
3998 pub specialist_probability: f64,
3999}
4000
4001fn default_min_team_size() -> usize {
4002 3
4003}
4004fn default_max_team_size() -> usize {
4005 8
4006}
4007fn default_specialist_probability() -> f64 {
4008 0.30
4009}
4010
4011impl Default for AuditTeamConfig {
4012 fn default() -> Self {
4013 Self {
4014 min_team_size: default_min_team_size(),
4015 max_team_size: default_max_team_size(),
4016 specialist_probability: default_specialist_probability(),
4017 }
4018 }
4019}
4020
4021#[derive(Debug, Clone, Serialize, Deserialize)]
4023pub struct ReviewWorkflowConfig {
4024 #[serde(default = "default_review_delay_days")]
4026 pub average_review_delay_days: u32,
4027 #[serde(default = "default_rework_probability_review")]
4029 pub rework_probability: f64,
4030 #[serde(default = "default_true")]
4032 pub require_partner_signoff: bool,
4033}
4034
4035fn default_review_delay_days() -> u32 {
4036 2
4037}
4038fn default_rework_probability_review() -> f64 {
4039 0.15
4040}
4041
4042impl Default for ReviewWorkflowConfig {
4043 fn default() -> Self {
4044 Self {
4045 average_review_delay_days: default_review_delay_days(),
4046 rework_probability: default_rework_probability_review(),
4047 require_partner_signoff: true,
4048 }
4049 }
4050}
4051
4052#[derive(Debug, Clone, Serialize, Deserialize)]
4058pub struct DataQualitySchemaConfig {
4059 #[serde(default)]
4061 pub enabled: bool,
4062 #[serde(default)]
4064 pub preset: DataQualityPreset,
4065 #[serde(default)]
4067 pub missing_values: MissingValuesSchemaConfig,
4068 #[serde(default)]
4070 pub typos: TypoSchemaConfig,
4071 #[serde(default)]
4073 pub format_variations: FormatVariationSchemaConfig,
4074 #[serde(default)]
4076 pub duplicates: DuplicateSchemaConfig,
4077 #[serde(default)]
4079 pub encoding_issues: EncodingIssueSchemaConfig,
4080 #[serde(default)]
4082 pub generate_labels: bool,
4083 #[serde(default)]
4085 pub sink_profiles: SinkQualityProfiles,
4086}
4087
4088impl Default for DataQualitySchemaConfig {
4089 fn default() -> Self {
4090 Self {
4091 enabled: false,
4092 preset: DataQualityPreset::None,
4093 missing_values: MissingValuesSchemaConfig::default(),
4094 typos: TypoSchemaConfig::default(),
4095 format_variations: FormatVariationSchemaConfig::default(),
4096 duplicates: DuplicateSchemaConfig::default(),
4097 encoding_issues: EncodingIssueSchemaConfig::default(),
4098 generate_labels: true,
4099 sink_profiles: SinkQualityProfiles::default(),
4100 }
4101 }
4102}
4103
4104impl DataQualitySchemaConfig {
4105 pub fn with_preset(preset: DataQualityPreset) -> Self {
4107 let mut config = Self {
4108 preset,
4109 ..Default::default()
4110 };
4111 config.apply_preset();
4112 config
4113 }
4114
4115 pub fn apply_preset(&mut self) {
4118 if !self.preset.overrides_settings() {
4119 return;
4120 }
4121
4122 self.enabled = true;
4123
4124 self.missing_values.enabled = self.preset.missing_rate() > 0.0;
4126 self.missing_values.rate = self.preset.missing_rate();
4127
4128 self.typos.enabled = self.preset.typo_rate() > 0.0;
4130 self.typos.char_error_rate = self.preset.typo_rate();
4131
4132 self.duplicates.enabled = self.preset.duplicate_rate() > 0.0;
4134 self.duplicates.exact_duplicate_ratio = self.preset.duplicate_rate() * 0.4;
4135 self.duplicates.near_duplicate_ratio = self.preset.duplicate_rate() * 0.4;
4136 self.duplicates.fuzzy_duplicate_ratio = self.preset.duplicate_rate() * 0.2;
4137
4138 self.format_variations.enabled = self.preset.format_variations_enabled();
4140
4141 self.encoding_issues.enabled = self.preset.encoding_issues_enabled();
4143 self.encoding_issues.rate = self.preset.encoding_issue_rate();
4144
4145 if self.preset.ocr_errors_enabled() {
4147 self.typos.type_weights.ocr_errors = 0.3;
4148 }
4149 }
4150
4151 pub fn effective_missing_rate(&self) -> f64 {
4153 if self.preset.overrides_settings() {
4154 self.preset.missing_rate()
4155 } else {
4156 self.missing_values.rate
4157 }
4158 }
4159
4160 pub fn effective_typo_rate(&self) -> f64 {
4162 if self.preset.overrides_settings() {
4163 self.preset.typo_rate()
4164 } else {
4165 self.typos.char_error_rate
4166 }
4167 }
4168
4169 pub fn effective_duplicate_rate(&self) -> f64 {
4171 if self.preset.overrides_settings() {
4172 self.preset.duplicate_rate()
4173 } else {
4174 self.duplicates.exact_duplicate_ratio
4175 + self.duplicates.near_duplicate_ratio
4176 + self.duplicates.fuzzy_duplicate_ratio
4177 }
4178 }
4179
4180 pub fn clean() -> Self {
4182 Self::with_preset(DataQualityPreset::Clean)
4183 }
4184
4185 pub fn noisy() -> Self {
4187 Self::with_preset(DataQualityPreset::Noisy)
4188 }
4189
4190 pub fn legacy() -> Self {
4192 Self::with_preset(DataQualityPreset::Legacy)
4193 }
4194}
4195
4196#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
4198#[serde(rename_all = "snake_case")]
4199pub enum DataQualityPreset {
4200 #[default]
4202 None,
4203 Minimal,
4205 Normal,
4207 High,
4209 Custom,
4211
4212 Clean,
4218 Noisy,
4221 Legacy,
4224}
4225
4226impl DataQualityPreset {
4227 pub fn missing_rate(&self) -> f64 {
4229 match self {
4230 DataQualityPreset::None => 0.0,
4231 DataQualityPreset::Minimal => 0.005,
4232 DataQualityPreset::Normal => 0.02,
4233 DataQualityPreset::High => 0.08,
4234 DataQualityPreset::Custom => 0.01, DataQualityPreset::Clean => 0.001,
4236 DataQualityPreset::Noisy => 0.05,
4237 DataQualityPreset::Legacy => 0.10,
4238 }
4239 }
4240
4241 pub fn typo_rate(&self) -> f64 {
4243 match self {
4244 DataQualityPreset::None => 0.0,
4245 DataQualityPreset::Minimal => 0.0005,
4246 DataQualityPreset::Normal => 0.002,
4247 DataQualityPreset::High => 0.01,
4248 DataQualityPreset::Custom => 0.001, DataQualityPreset::Clean => 0.0005,
4250 DataQualityPreset::Noisy => 0.02,
4251 DataQualityPreset::Legacy => 0.05,
4252 }
4253 }
4254
4255 pub fn duplicate_rate(&self) -> f64 {
4257 match self {
4258 DataQualityPreset::None => 0.0,
4259 DataQualityPreset::Minimal => 0.001,
4260 DataQualityPreset::Normal => 0.005,
4261 DataQualityPreset::High => 0.02,
4262 DataQualityPreset::Custom => 0.0, DataQualityPreset::Clean => 0.0,
4264 DataQualityPreset::Noisy => 0.01,
4265 DataQualityPreset::Legacy => 0.03,
4266 }
4267 }
4268
4269 pub fn format_variations_enabled(&self) -> bool {
4271 match self {
4272 DataQualityPreset::None | DataQualityPreset::Clean => false,
4273 DataQualityPreset::Minimal => true,
4274 DataQualityPreset::Normal => true,
4275 DataQualityPreset::High => true,
4276 DataQualityPreset::Custom => true,
4277 DataQualityPreset::Noisy => true,
4278 DataQualityPreset::Legacy => true,
4279 }
4280 }
4281
4282 pub fn ocr_errors_enabled(&self) -> bool {
4284 matches!(self, DataQualityPreset::Legacy | DataQualityPreset::High)
4285 }
4286
4287 pub fn encoding_issues_enabled(&self) -> bool {
4289 matches!(
4290 self,
4291 DataQualityPreset::Legacy | DataQualityPreset::High | DataQualityPreset::Noisy
4292 )
4293 }
4294
4295 pub fn encoding_issue_rate(&self) -> f64 {
4297 match self {
4298 DataQualityPreset::None | DataQualityPreset::Clean | DataQualityPreset::Minimal => 0.0,
4299 DataQualityPreset::Normal => 0.002,
4300 DataQualityPreset::High => 0.01,
4301 DataQualityPreset::Custom => 0.0,
4302 DataQualityPreset::Noisy => 0.005,
4303 DataQualityPreset::Legacy => 0.02,
4304 }
4305 }
4306
4307 pub fn overrides_settings(&self) -> bool {
4309 !matches!(self, DataQualityPreset::Custom | DataQualityPreset::None)
4310 }
4311
4312 pub fn description(&self) -> &'static str {
4314 match self {
4315 DataQualityPreset::None => "No data quality issues (pristine data)",
4316 DataQualityPreset::Minimal => "Very rare data quality issues",
4317 DataQualityPreset::Normal => "Realistic enterprise data quality",
4318 DataQualityPreset::High => "Messy data for stress testing",
4319 DataQualityPreset::Custom => "Custom settings from configuration",
4320 DataQualityPreset::Clean => "ML-ready clean data with minimal issues",
4321 DataQualityPreset::Noisy => "Typical production data with moderate issues",
4322 DataQualityPreset::Legacy => "Legacy/migrated data with heavy issues and OCR errors",
4323 }
4324 }
4325}
4326
4327#[derive(Debug, Clone, Serialize, Deserialize)]
4329pub struct MissingValuesSchemaConfig {
4330 #[serde(default)]
4332 pub enabled: bool,
4333 #[serde(default = "default_missing_rate")]
4335 pub rate: f64,
4336 #[serde(default)]
4338 pub strategy: MissingValueStrategy,
4339 #[serde(default)]
4341 pub field_rates: std::collections::HashMap<String, f64>,
4342 #[serde(default)]
4344 pub protected_fields: Vec<String>,
4345}
4346
4347fn default_missing_rate() -> f64 {
4348 0.01
4349}
4350
4351impl Default for MissingValuesSchemaConfig {
4352 fn default() -> Self {
4353 Self {
4354 enabled: false,
4355 rate: default_missing_rate(),
4356 strategy: MissingValueStrategy::Mcar,
4357 field_rates: std::collections::HashMap::new(),
4358 protected_fields: vec![
4359 "document_id".to_string(),
4360 "company_code".to_string(),
4361 "posting_date".to_string(),
4362 ],
4363 }
4364 }
4365}
4366
4367#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
4369#[serde(rename_all = "snake_case")]
4370pub enum MissingValueStrategy {
4371 #[default]
4373 Mcar,
4374 Mar,
4376 Mnar,
4378 Systematic,
4380}
4381
4382#[derive(Debug, Clone, Serialize, Deserialize)]
4384pub struct TypoSchemaConfig {
4385 #[serde(default)]
4387 pub enabled: bool,
4388 #[serde(default = "default_typo_rate")]
4390 pub char_error_rate: f64,
4391 #[serde(default)]
4393 pub type_weights: TypoTypeWeights,
4394 #[serde(default)]
4396 pub protected_fields: Vec<String>,
4397}
4398
4399fn default_typo_rate() -> f64 {
4400 0.001
4401}
4402
4403impl Default for TypoSchemaConfig {
4404 fn default() -> Self {
4405 Self {
4406 enabled: false,
4407 char_error_rate: default_typo_rate(),
4408 type_weights: TypoTypeWeights::default(),
4409 protected_fields: vec![
4410 "document_id".to_string(),
4411 "gl_account".to_string(),
4412 "company_code".to_string(),
4413 ],
4414 }
4415 }
4416}
4417
4418#[derive(Debug, Clone, Serialize, Deserialize)]
4420pub struct TypoTypeWeights {
4421 #[serde(default = "default_substitution_weight")]
4423 pub substitution: f64,
4424 #[serde(default = "default_transposition_weight")]
4426 pub transposition: f64,
4427 #[serde(default = "default_insertion_weight")]
4429 pub insertion: f64,
4430 #[serde(default = "default_deletion_weight")]
4432 pub deletion: f64,
4433 #[serde(default = "default_ocr_weight")]
4435 pub ocr_errors: f64,
4436 #[serde(default = "default_homophone_weight")]
4438 pub homophones: f64,
4439}
4440
4441fn default_substitution_weight() -> f64 {
4442 0.35
4443}
4444fn default_transposition_weight() -> f64 {
4445 0.25
4446}
4447fn default_insertion_weight() -> f64 {
4448 0.10
4449}
4450fn default_deletion_weight() -> f64 {
4451 0.15
4452}
4453fn default_ocr_weight() -> f64 {
4454 0.10
4455}
4456fn default_homophone_weight() -> f64 {
4457 0.05
4458}
4459
4460impl Default for TypoTypeWeights {
4461 fn default() -> Self {
4462 Self {
4463 substitution: default_substitution_weight(),
4464 transposition: default_transposition_weight(),
4465 insertion: default_insertion_weight(),
4466 deletion: default_deletion_weight(),
4467 ocr_errors: default_ocr_weight(),
4468 homophones: default_homophone_weight(),
4469 }
4470 }
4471}
4472
4473#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4475pub struct FormatVariationSchemaConfig {
4476 #[serde(default)]
4478 pub enabled: bool,
4479 #[serde(default)]
4481 pub dates: DateFormatVariationConfig,
4482 #[serde(default)]
4484 pub amounts: AmountFormatVariationConfig,
4485 #[serde(default)]
4487 pub identifiers: IdentifierFormatVariationConfig,
4488}
4489
4490#[derive(Debug, Clone, Serialize, Deserialize)]
4492pub struct DateFormatVariationConfig {
4493 #[serde(default)]
4495 pub enabled: bool,
4496 #[serde(default = "default_date_variation_rate")]
4498 pub rate: f64,
4499 #[serde(default = "default_true")]
4501 pub iso_format: bool,
4502 #[serde(default)]
4504 pub us_format: bool,
4505 #[serde(default)]
4507 pub eu_format: bool,
4508 #[serde(default)]
4510 pub long_format: bool,
4511}
4512
4513fn default_date_variation_rate() -> f64 {
4514 0.05
4515}
4516
4517impl Default for DateFormatVariationConfig {
4518 fn default() -> Self {
4519 Self {
4520 enabled: false,
4521 rate: default_date_variation_rate(),
4522 iso_format: true,
4523 us_format: false,
4524 eu_format: false,
4525 long_format: false,
4526 }
4527 }
4528}
4529
4530#[derive(Debug, Clone, Serialize, Deserialize)]
4532pub struct AmountFormatVariationConfig {
4533 #[serde(default)]
4535 pub enabled: bool,
4536 #[serde(default = "default_amount_variation_rate")]
4538 pub rate: f64,
4539 #[serde(default)]
4541 pub us_comma_format: bool,
4542 #[serde(default)]
4544 pub eu_format: bool,
4545 #[serde(default)]
4547 pub currency_prefix: bool,
4548 #[serde(default)]
4550 pub accounting_format: bool,
4551}
4552
4553fn default_amount_variation_rate() -> f64 {
4554 0.02
4555}
4556
4557impl Default for AmountFormatVariationConfig {
4558 fn default() -> Self {
4559 Self {
4560 enabled: false,
4561 rate: default_amount_variation_rate(),
4562 us_comma_format: false,
4563 eu_format: false,
4564 currency_prefix: false,
4565 accounting_format: false,
4566 }
4567 }
4568}
4569
4570#[derive(Debug, Clone, Serialize, Deserialize)]
4572pub struct IdentifierFormatVariationConfig {
4573 #[serde(default)]
4575 pub enabled: bool,
4576 #[serde(default = "default_identifier_variation_rate")]
4578 pub rate: f64,
4579 #[serde(default)]
4581 pub case_variations: bool,
4582 #[serde(default)]
4584 pub padding_variations: bool,
4585 #[serde(default)]
4587 pub separator_variations: bool,
4588}
4589
4590fn default_identifier_variation_rate() -> f64 {
4591 0.02
4592}
4593
4594impl Default for IdentifierFormatVariationConfig {
4595 fn default() -> Self {
4596 Self {
4597 enabled: false,
4598 rate: default_identifier_variation_rate(),
4599 case_variations: false,
4600 padding_variations: false,
4601 separator_variations: false,
4602 }
4603 }
4604}
4605
4606#[derive(Debug, Clone, Serialize, Deserialize)]
4608pub struct DuplicateSchemaConfig {
4609 #[serde(default)]
4611 pub enabled: bool,
4612 #[serde(default = "default_duplicate_rate")]
4614 pub rate: f64,
4615 #[serde(default = "default_exact_duplicate_ratio")]
4617 pub exact_duplicate_ratio: f64,
4618 #[serde(default = "default_near_duplicate_ratio")]
4620 pub near_duplicate_ratio: f64,
4621 #[serde(default = "default_fuzzy_duplicate_ratio")]
4623 pub fuzzy_duplicate_ratio: f64,
4624 #[serde(default = "default_max_date_offset")]
4626 pub max_date_offset_days: u32,
4627 #[serde(default = "default_max_amount_variance")]
4629 pub max_amount_variance: f64,
4630}
4631
4632fn default_duplicate_rate() -> f64 {
4633 0.005
4634}
4635fn default_exact_duplicate_ratio() -> f64 {
4636 0.4
4637}
4638fn default_near_duplicate_ratio() -> f64 {
4639 0.35
4640}
4641fn default_fuzzy_duplicate_ratio() -> f64 {
4642 0.25
4643}
4644fn default_max_date_offset() -> u32 {
4645 3
4646}
4647fn default_max_amount_variance() -> f64 {
4648 0.01
4649}
4650
4651impl Default for DuplicateSchemaConfig {
4652 fn default() -> Self {
4653 Self {
4654 enabled: false,
4655 rate: default_duplicate_rate(),
4656 exact_duplicate_ratio: default_exact_duplicate_ratio(),
4657 near_duplicate_ratio: default_near_duplicate_ratio(),
4658 fuzzy_duplicate_ratio: default_fuzzy_duplicate_ratio(),
4659 max_date_offset_days: default_max_date_offset(),
4660 max_amount_variance: default_max_amount_variance(),
4661 }
4662 }
4663}
4664
4665#[derive(Debug, Clone, Serialize, Deserialize)]
4667pub struct EncodingIssueSchemaConfig {
4668 #[serde(default)]
4670 pub enabled: bool,
4671 #[serde(default = "default_encoding_rate")]
4673 pub rate: f64,
4674 #[serde(default)]
4676 pub mojibake: bool,
4677 #[serde(default)]
4679 pub html_entities: bool,
4680 #[serde(default)]
4682 pub bom_issues: bool,
4683}
4684
4685fn default_encoding_rate() -> f64 {
4686 0.001
4687}
4688
4689impl Default for EncodingIssueSchemaConfig {
4690 fn default() -> Self {
4691 Self {
4692 enabled: false,
4693 rate: default_encoding_rate(),
4694 mojibake: false,
4695 html_entities: false,
4696 bom_issues: false,
4697 }
4698 }
4699}
4700
4701#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4703pub struct SinkQualityProfiles {
4704 #[serde(default)]
4706 pub csv: Option<SinkQualityOverride>,
4707 #[serde(default)]
4709 pub json: Option<SinkQualityOverride>,
4710 #[serde(default)]
4712 pub parquet: Option<SinkQualityOverride>,
4713}
4714
4715#[derive(Debug, Clone, Serialize, Deserialize)]
4717pub struct SinkQualityOverride {
4718 pub enabled: Option<bool>,
4720 pub missing_rate: Option<f64>,
4722 pub typo_rate: Option<f64>,
4724 pub format_variation_rate: Option<f64>,
4726 pub duplicate_rate: Option<f64>,
4728}
4729
4730#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4742pub struct AccountingStandardsConfig {
4743 #[serde(default)]
4745 pub enabled: bool,
4746
4747 #[serde(default, skip_serializing_if = "Option::is_none")]
4751 pub framework: Option<AccountingFrameworkConfig>,
4752
4753 #[serde(default)]
4755 pub revenue_recognition: RevenueRecognitionConfig,
4756
4757 #[serde(default)]
4759 pub leases: LeaseAccountingConfig,
4760
4761 #[serde(default)]
4763 pub fair_value: FairValueConfig,
4764
4765 #[serde(default)]
4767 pub impairment: ImpairmentConfig,
4768
4769 #[serde(default)]
4771 pub business_combinations: BusinessCombinationsConfig,
4772
4773 #[serde(default)]
4775 pub expected_credit_loss: EclConfig,
4776
4777 #[serde(default)]
4779 pub generate_differences: bool,
4780}
4781
4782#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
4784#[serde(rename_all = "snake_case")]
4785pub enum AccountingFrameworkConfig {
4786 #[default]
4788 UsGaap,
4789 Ifrs,
4791 DualReporting,
4793 FrenchGaap,
4795 GermanGaap,
4797}
4798
4799#[derive(Debug, Clone, Serialize, Deserialize)]
4801pub struct RevenueRecognitionConfig {
4802 #[serde(default)]
4804 pub enabled: bool,
4805
4806 #[serde(default = "default_true")]
4808 pub generate_contracts: bool,
4809
4810 #[serde(default = "default_avg_obligations")]
4812 pub avg_obligations_per_contract: f64,
4813
4814 #[serde(default = "default_variable_consideration_rate")]
4816 pub variable_consideration_rate: f64,
4817
4818 #[serde(default = "default_over_time_rate")]
4820 pub over_time_recognition_rate: f64,
4821
4822 #[serde(default = "default_contract_count")]
4824 pub contract_count: usize,
4825}
4826
4827fn default_avg_obligations() -> f64 {
4828 2.0
4829}
4830
4831fn default_variable_consideration_rate() -> f64 {
4832 0.15
4833}
4834
4835fn default_over_time_rate() -> f64 {
4836 0.30
4837}
4838
4839fn default_contract_count() -> usize {
4840 100
4841}
4842
4843impl Default for RevenueRecognitionConfig {
4844 fn default() -> Self {
4845 Self {
4846 enabled: false,
4847 generate_contracts: true,
4848 avg_obligations_per_contract: default_avg_obligations(),
4849 variable_consideration_rate: default_variable_consideration_rate(),
4850 over_time_recognition_rate: default_over_time_rate(),
4851 contract_count: default_contract_count(),
4852 }
4853 }
4854}
4855
4856#[derive(Debug, Clone, Serialize, Deserialize)]
4858pub struct LeaseAccountingConfig {
4859 #[serde(default)]
4861 pub enabled: bool,
4862
4863 #[serde(default = "default_lease_count")]
4865 pub lease_count: usize,
4866
4867 #[serde(default = "default_finance_lease_pct")]
4869 pub finance_lease_percent: f64,
4870
4871 #[serde(default = "default_avg_lease_term")]
4873 pub avg_lease_term_months: u32,
4874
4875 #[serde(default = "default_true")]
4877 pub generate_amortization: bool,
4878
4879 #[serde(default = "default_real_estate_pct")]
4881 pub real_estate_percent: f64,
4882}
4883
4884fn default_lease_count() -> usize {
4885 50
4886}
4887
4888fn default_finance_lease_pct() -> f64 {
4889 0.30
4890}
4891
4892fn default_avg_lease_term() -> u32 {
4893 60
4894}
4895
4896fn default_real_estate_pct() -> f64 {
4897 0.40
4898}
4899
4900impl Default for LeaseAccountingConfig {
4901 fn default() -> Self {
4902 Self {
4903 enabled: false,
4904 lease_count: default_lease_count(),
4905 finance_lease_percent: default_finance_lease_pct(),
4906 avg_lease_term_months: default_avg_lease_term(),
4907 generate_amortization: true,
4908 real_estate_percent: default_real_estate_pct(),
4909 }
4910 }
4911}
4912
4913#[derive(Debug, Clone, Serialize, Deserialize)]
4915pub struct FairValueConfig {
4916 #[serde(default)]
4918 pub enabled: bool,
4919
4920 #[serde(default = "default_fv_count")]
4922 pub measurement_count: usize,
4923
4924 #[serde(default = "default_level1_pct")]
4926 pub level1_percent: f64,
4927
4928 #[serde(default = "default_level2_pct")]
4930 pub level2_percent: f64,
4931
4932 #[serde(default = "default_level3_pct")]
4934 pub level3_percent: f64,
4935
4936 #[serde(default)]
4938 pub include_sensitivity_analysis: bool,
4939}
4940
4941fn default_fv_count() -> usize {
4942 25
4943}
4944
4945fn default_level1_pct() -> f64 {
4946 0.40
4947}
4948
4949fn default_level2_pct() -> f64 {
4950 0.35
4951}
4952
4953fn default_level3_pct() -> f64 {
4954 0.25
4955}
4956
4957impl Default for FairValueConfig {
4958 fn default() -> Self {
4959 Self {
4960 enabled: false,
4961 measurement_count: default_fv_count(),
4962 level1_percent: default_level1_pct(),
4963 level2_percent: default_level2_pct(),
4964 level3_percent: default_level3_pct(),
4965 include_sensitivity_analysis: false,
4966 }
4967 }
4968}
4969
4970#[derive(Debug, Clone, Serialize, Deserialize)]
4972pub struct ImpairmentConfig {
4973 #[serde(default)]
4975 pub enabled: bool,
4976
4977 #[serde(default = "default_impairment_count")]
4979 pub test_count: usize,
4980
4981 #[serde(default = "default_impairment_rate")]
4983 pub impairment_rate: f64,
4984
4985 #[serde(default = "default_true")]
4987 pub generate_projections: bool,
4988
4989 #[serde(default)]
4991 pub include_goodwill: bool,
4992}
4993
4994fn default_impairment_count() -> usize {
4995 15
4996}
4997
4998fn default_impairment_rate() -> f64 {
4999 0.10
5000}
5001
5002impl Default for ImpairmentConfig {
5003 fn default() -> Self {
5004 Self {
5005 enabled: false,
5006 test_count: default_impairment_count(),
5007 impairment_rate: default_impairment_rate(),
5008 generate_projections: true,
5009 include_goodwill: false,
5010 }
5011 }
5012}
5013
5014#[derive(Debug, Clone, Serialize, Deserialize)]
5020pub struct BusinessCombinationsConfig {
5021 #[serde(default)]
5023 pub enabled: bool,
5024
5025 #[serde(default = "default_bc_acquisition_count")]
5027 pub acquisition_count: usize,
5028}
5029
5030fn default_bc_acquisition_count() -> usize {
5031 2
5032}
5033
5034impl Default for BusinessCombinationsConfig {
5035 fn default() -> Self {
5036 Self {
5037 enabled: false,
5038 acquisition_count: default_bc_acquisition_count(),
5039 }
5040 }
5041}
5042
5043#[derive(Debug, Clone, Serialize, Deserialize)]
5049pub struct EclConfig {
5050 #[serde(default)]
5052 pub enabled: bool,
5053
5054 #[serde(default = "default_ecl_base_weight")]
5056 pub base_scenario_weight: f64,
5057
5058 #[serde(default = "default_ecl_base_multiplier")]
5060 pub base_scenario_multiplier: f64,
5061
5062 #[serde(default = "default_ecl_optimistic_weight")]
5064 pub optimistic_scenario_weight: f64,
5065
5066 #[serde(default = "default_ecl_optimistic_multiplier")]
5068 pub optimistic_scenario_multiplier: f64,
5069
5070 #[serde(default = "default_ecl_pessimistic_weight")]
5072 pub pessimistic_scenario_weight: f64,
5073
5074 #[serde(default = "default_ecl_pessimistic_multiplier")]
5076 pub pessimistic_scenario_multiplier: f64,
5077}
5078
5079fn default_ecl_base_weight() -> f64 {
5080 0.50
5081}
5082fn default_ecl_base_multiplier() -> f64 {
5083 1.0
5084}
5085fn default_ecl_optimistic_weight() -> f64 {
5086 0.30
5087}
5088fn default_ecl_optimistic_multiplier() -> f64 {
5089 0.8
5090}
5091fn default_ecl_pessimistic_weight() -> f64 {
5092 0.20
5093}
5094fn default_ecl_pessimistic_multiplier() -> f64 {
5095 1.4
5096}
5097
5098impl Default for EclConfig {
5099 fn default() -> Self {
5100 Self {
5101 enabled: false,
5102 base_scenario_weight: default_ecl_base_weight(),
5103 base_scenario_multiplier: default_ecl_base_multiplier(),
5104 optimistic_scenario_weight: default_ecl_optimistic_weight(),
5105 optimistic_scenario_multiplier: default_ecl_optimistic_multiplier(),
5106 pessimistic_scenario_weight: default_ecl_pessimistic_weight(),
5107 pessimistic_scenario_multiplier: default_ecl_pessimistic_multiplier(),
5108 }
5109 }
5110}
5111
5112#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5125pub struct AuditStandardsConfig {
5126 #[serde(default)]
5128 pub enabled: bool,
5129
5130 #[serde(default)]
5132 pub isa_compliance: IsaComplianceConfig,
5133
5134 #[serde(default)]
5136 pub analytical_procedures: AnalyticalProceduresConfig,
5137
5138 #[serde(default)]
5140 pub confirmations: ConfirmationsConfig,
5141
5142 #[serde(default)]
5144 pub opinion: AuditOpinionConfig,
5145
5146 #[serde(default)]
5148 pub generate_audit_trail: bool,
5149
5150 #[serde(default)]
5152 pub sox: SoxComplianceConfig,
5153
5154 #[serde(default)]
5156 pub pcaob: PcaobConfig,
5157}
5158
5159#[derive(Debug, Clone, Serialize, Deserialize)]
5161pub struct IsaComplianceConfig {
5162 #[serde(default)]
5164 pub enabled: bool,
5165
5166 #[serde(default = "default_compliance_level")]
5168 pub compliance_level: String,
5169
5170 #[serde(default = "default_true")]
5172 pub generate_isa_mappings: bool,
5173
5174 #[serde(default = "default_true")]
5176 pub generate_coverage_summary: bool,
5177
5178 #[serde(default)]
5180 pub include_pcaob: bool,
5181
5182 #[serde(default = "default_audit_framework")]
5184 pub framework: String,
5185}
5186
5187fn default_compliance_level() -> String {
5188 "standard".to_string()
5189}
5190
5191fn default_audit_framework() -> String {
5192 "isa".to_string()
5193}
5194
5195impl Default for IsaComplianceConfig {
5196 fn default() -> Self {
5197 Self {
5198 enabled: false,
5199 compliance_level: default_compliance_level(),
5200 generate_isa_mappings: true,
5201 generate_coverage_summary: true,
5202 include_pcaob: false,
5203 framework: default_audit_framework(),
5204 }
5205 }
5206}
5207
5208#[derive(Debug, Clone, Serialize, Deserialize)]
5210pub struct AnalyticalProceduresConfig {
5211 #[serde(default)]
5213 pub enabled: bool,
5214
5215 #[serde(default = "default_procedures_per_account")]
5217 pub procedures_per_account: usize,
5218
5219 #[serde(default = "default_variance_probability")]
5221 pub variance_probability: f64,
5222
5223 #[serde(default = "default_true")]
5225 pub generate_investigations: bool,
5226
5227 #[serde(default = "default_true")]
5229 pub include_ratio_analysis: bool,
5230}
5231
5232fn default_procedures_per_account() -> usize {
5233 3
5234}
5235
5236fn default_variance_probability() -> f64 {
5237 0.20
5238}
5239
5240impl Default for AnalyticalProceduresConfig {
5241 fn default() -> Self {
5242 Self {
5243 enabled: false,
5244 procedures_per_account: default_procedures_per_account(),
5245 variance_probability: default_variance_probability(),
5246 generate_investigations: true,
5247 include_ratio_analysis: true,
5248 }
5249 }
5250}
5251
5252#[derive(Debug, Clone, Serialize, Deserialize)]
5254pub struct ConfirmationsConfig {
5255 #[serde(default)]
5257 pub enabled: bool,
5258
5259 #[serde(default = "default_confirmation_count")]
5261 pub confirmation_count: usize,
5262
5263 #[serde(default = "default_positive_response_rate")]
5265 pub positive_response_rate: f64,
5266
5267 #[serde(default = "default_exception_rate_confirm")]
5269 pub exception_rate: f64,
5270
5271 #[serde(default = "default_non_response_rate")]
5273 pub non_response_rate: f64,
5274
5275 #[serde(default = "default_true")]
5277 pub generate_alternative_procedures: bool,
5278}
5279
5280fn default_confirmation_count() -> usize {
5281 50
5282}
5283
5284fn default_positive_response_rate() -> f64 {
5285 0.85
5286}
5287
5288fn default_exception_rate_confirm() -> f64 {
5289 0.10
5290}
5291
5292fn default_non_response_rate() -> f64 {
5293 0.05
5294}
5295
5296impl Default for ConfirmationsConfig {
5297 fn default() -> Self {
5298 Self {
5299 enabled: false,
5300 confirmation_count: default_confirmation_count(),
5301 positive_response_rate: default_positive_response_rate(),
5302 exception_rate: default_exception_rate_confirm(),
5303 non_response_rate: default_non_response_rate(),
5304 generate_alternative_procedures: true,
5305 }
5306 }
5307}
5308
5309#[derive(Debug, Clone, Serialize, Deserialize)]
5311pub struct AuditOpinionConfig {
5312 #[serde(default)]
5314 pub enabled: bool,
5315
5316 #[serde(default = "default_true")]
5318 pub generate_kam: bool,
5319
5320 #[serde(default = "default_kam_count")]
5322 pub average_kam_count: usize,
5323
5324 #[serde(default = "default_modified_opinion_rate")]
5326 pub modified_opinion_rate: f64,
5327
5328 #[serde(default)]
5330 pub include_emphasis_of_matter: bool,
5331
5332 #[serde(default = "default_true")]
5334 pub include_going_concern: bool,
5335}
5336
5337fn default_kam_count() -> usize {
5338 3
5339}
5340
5341fn default_modified_opinion_rate() -> f64 {
5342 0.05
5343}
5344
5345impl Default for AuditOpinionConfig {
5346 fn default() -> Self {
5347 Self {
5348 enabled: false,
5349 generate_kam: true,
5350 average_kam_count: default_kam_count(),
5351 modified_opinion_rate: default_modified_opinion_rate(),
5352 include_emphasis_of_matter: false,
5353 include_going_concern: true,
5354 }
5355 }
5356}
5357
5358#[derive(Debug, Clone, Serialize, Deserialize)]
5360pub struct SoxComplianceConfig {
5361 #[serde(default)]
5363 pub enabled: bool,
5364
5365 #[serde(default = "default_true")]
5367 pub generate_302_certifications: bool,
5368
5369 #[serde(default = "default_true")]
5371 pub generate_404_assessments: bool,
5372
5373 #[serde(default = "default_sox_materiality_threshold")]
5375 pub materiality_threshold: f64,
5376
5377 #[serde(default = "default_material_weakness_rate")]
5379 pub material_weakness_rate: f64,
5380
5381 #[serde(default = "default_significant_deficiency_rate")]
5383 pub significant_deficiency_rate: f64,
5384}
5385
5386fn default_material_weakness_rate() -> f64 {
5387 0.02
5388}
5389
5390fn default_significant_deficiency_rate() -> f64 {
5391 0.08
5392}
5393
5394impl Default for SoxComplianceConfig {
5395 fn default() -> Self {
5396 Self {
5397 enabled: false,
5398 generate_302_certifications: true,
5399 generate_404_assessments: true,
5400 materiality_threshold: default_sox_materiality_threshold(),
5401 material_weakness_rate: default_material_weakness_rate(),
5402 significant_deficiency_rate: default_significant_deficiency_rate(),
5403 }
5404 }
5405}
5406
5407#[derive(Debug, Clone, Serialize, Deserialize)]
5409pub struct PcaobConfig {
5410 #[serde(default)]
5412 pub enabled: bool,
5413
5414 #[serde(default)]
5416 pub is_pcaob_audit: bool,
5417
5418 #[serde(default = "default_true")]
5420 pub generate_cam: bool,
5421
5422 #[serde(default)]
5424 pub include_icfr_opinion: bool,
5425
5426 #[serde(default)]
5428 pub generate_standard_mappings: bool,
5429}
5430
5431impl Default for PcaobConfig {
5432 fn default() -> Self {
5433 Self {
5434 enabled: false,
5435 is_pcaob_audit: false,
5436 generate_cam: true,
5437 include_icfr_opinion: false,
5438 generate_standard_mappings: false,
5439 }
5440 }
5441}
5442
5443#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5456pub struct AdvancedDistributionConfig {
5457 #[serde(default)]
5459 pub enabled: bool,
5460
5461 #[serde(default)]
5463 pub amounts: MixtureDistributionSchemaConfig,
5464
5465 #[serde(default)]
5467 pub correlations: CorrelationSchemaConfig,
5468
5469 #[serde(default)]
5471 pub conditional: Vec<ConditionalDistributionSchemaConfig>,
5472
5473 #[serde(default)]
5475 pub regime_changes: RegimeChangeSchemaConfig,
5476
5477 #[serde(default)]
5479 pub industry_profile: Option<IndustryProfileType>,
5480
5481 #[serde(default)]
5483 pub validation: StatisticalValidationSchemaConfig,
5484}
5485
5486#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
5488#[serde(rename_all = "snake_case")]
5489pub enum IndustryProfileType {
5490 Retail,
5492 Manufacturing,
5494 FinancialServices,
5496 Healthcare,
5498 Technology,
5500}
5501
5502#[derive(Debug, Clone, Serialize, Deserialize)]
5504pub struct MixtureDistributionSchemaConfig {
5505 #[serde(default)]
5507 pub enabled: bool,
5508
5509 #[serde(default = "default_mixture_type")]
5511 pub distribution_type: MixtureDistributionType,
5512
5513 #[serde(default)]
5515 pub components: Vec<MixtureComponentConfig>,
5516
5517 #[serde(default = "default_min_amount")]
5519 pub min_value: f64,
5520
5521 #[serde(default)]
5523 pub max_value: Option<f64>,
5524
5525 #[serde(default = "default_decimal_places")]
5527 pub decimal_places: u8,
5528}
5529
5530fn default_mixture_type() -> MixtureDistributionType {
5531 MixtureDistributionType::LogNormal
5532}
5533
5534fn default_min_amount() -> f64 {
5535 0.01
5536}
5537
5538fn default_decimal_places() -> u8 {
5539 2
5540}
5541
5542impl Default for MixtureDistributionSchemaConfig {
5543 fn default() -> Self {
5544 Self {
5545 enabled: false,
5546 distribution_type: MixtureDistributionType::LogNormal,
5547 components: Vec::new(),
5548 min_value: 0.01,
5549 max_value: None,
5550 decimal_places: 2,
5551 }
5552 }
5553}
5554
5555#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5557#[serde(rename_all = "snake_case")]
5558pub enum MixtureDistributionType {
5559 Gaussian,
5561 #[default]
5563 LogNormal,
5564}
5565
5566#[derive(Debug, Clone, Serialize, Deserialize)]
5568pub struct MixtureComponentConfig {
5569 pub weight: f64,
5571
5572 pub mu: f64,
5574
5575 pub sigma: f64,
5577
5578 #[serde(default)]
5580 pub label: Option<String>,
5581}
5582
5583#[derive(Debug, Clone, Serialize, Deserialize)]
5585pub struct CorrelationSchemaConfig {
5586 #[serde(default)]
5588 pub enabled: bool,
5589
5590 #[serde(default)]
5592 pub copula_type: CopulaSchemaType,
5593
5594 #[serde(default)]
5596 pub fields: Vec<CorrelatedFieldConfig>,
5597
5598 #[serde(default)]
5601 pub matrix: Vec<f64>,
5602
5603 #[serde(default)]
5605 pub expected_correlations: Vec<ExpectedCorrelationConfig>,
5606}
5607
5608impl Default for CorrelationSchemaConfig {
5609 fn default() -> Self {
5610 Self {
5611 enabled: false,
5612 copula_type: CopulaSchemaType::Gaussian,
5613 fields: Vec::new(),
5614 matrix: Vec::new(),
5615 expected_correlations: Vec::new(),
5616 }
5617 }
5618}
5619
5620#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5622#[serde(rename_all = "snake_case")]
5623pub enum CopulaSchemaType {
5624 #[default]
5626 Gaussian,
5627 Clayton,
5629 Gumbel,
5631 Frank,
5633 StudentT,
5635}
5636
5637#[derive(Debug, Clone, Serialize, Deserialize)]
5639pub struct CorrelatedFieldConfig {
5640 pub name: String,
5642
5643 #[serde(default)]
5645 pub distribution: MarginalDistributionConfig,
5646}
5647
5648#[derive(Debug, Clone, Serialize, Deserialize)]
5650#[serde(tag = "type", rename_all = "snake_case")]
5651pub enum MarginalDistributionConfig {
5652 Normal {
5654 mu: f64,
5656 sigma: f64,
5658 },
5659 LogNormal {
5661 mu: f64,
5663 sigma: f64,
5665 },
5666 Uniform {
5668 min: f64,
5670 max: f64,
5672 },
5673 DiscreteUniform {
5675 min: i32,
5677 max: i32,
5679 },
5680}
5681
5682impl Default for MarginalDistributionConfig {
5683 fn default() -> Self {
5684 Self::Normal {
5685 mu: 0.0,
5686 sigma: 1.0,
5687 }
5688 }
5689}
5690
5691#[derive(Debug, Clone, Serialize, Deserialize)]
5693pub struct ExpectedCorrelationConfig {
5694 pub field1: String,
5696 pub field2: String,
5698 pub expected_r: f64,
5700 #[serde(default = "default_correlation_tolerance")]
5702 pub tolerance: f64,
5703}
5704
5705fn default_correlation_tolerance() -> f64 {
5706 0.10
5707}
5708
5709#[derive(Debug, Clone, Serialize, Deserialize)]
5711pub struct ConditionalDistributionSchemaConfig {
5712 pub output_field: String,
5714
5715 pub input_field: String,
5717
5718 #[serde(default)]
5720 pub breakpoints: Vec<ConditionalBreakpointConfig>,
5721
5722 #[serde(default)]
5724 pub default_distribution: ConditionalDistributionParamsConfig,
5725
5726 #[serde(default)]
5728 pub min_value: Option<f64>,
5729
5730 #[serde(default)]
5732 pub max_value: Option<f64>,
5733
5734 #[serde(default = "default_decimal_places")]
5736 pub decimal_places: u8,
5737}
5738
5739#[derive(Debug, Clone, Serialize, Deserialize)]
5741pub struct ConditionalBreakpointConfig {
5742 pub threshold: f64,
5744
5745 pub distribution: ConditionalDistributionParamsConfig,
5747}
5748
5749#[derive(Debug, Clone, Serialize, Deserialize)]
5751#[serde(tag = "type", rename_all = "snake_case")]
5752pub enum ConditionalDistributionParamsConfig {
5753 Fixed {
5755 value: f64,
5757 },
5758 Normal {
5760 mu: f64,
5762 sigma: f64,
5764 },
5765 LogNormal {
5767 mu: f64,
5769 sigma: f64,
5771 },
5772 Uniform {
5774 min: f64,
5776 max: f64,
5778 },
5779 Beta {
5781 alpha: f64,
5783 beta: f64,
5785 min: f64,
5787 max: f64,
5789 },
5790 Discrete {
5792 values: Vec<f64>,
5794 weights: Vec<f64>,
5796 },
5797}
5798
5799impl Default for ConditionalDistributionParamsConfig {
5800 fn default() -> Self {
5801 Self::Normal {
5802 mu: 0.0,
5803 sigma: 1.0,
5804 }
5805 }
5806}
5807
5808#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5810pub struct RegimeChangeSchemaConfig {
5811 #[serde(default)]
5813 pub enabled: bool,
5814
5815 #[serde(default)]
5817 pub changes: Vec<RegimeChangeEventConfig>,
5818
5819 #[serde(default)]
5821 pub economic_cycle: Option<EconomicCycleSchemaConfig>,
5822
5823 #[serde(default)]
5825 pub parameter_drifts: Vec<ParameterDriftSchemaConfig>,
5826}
5827
5828#[derive(Debug, Clone, Serialize, Deserialize)]
5830pub struct RegimeChangeEventConfig {
5831 pub date: String,
5833
5834 pub change_type: RegimeChangeTypeConfig,
5836
5837 #[serde(default)]
5839 pub description: Option<String>,
5840
5841 #[serde(default)]
5843 pub effects: Vec<RegimeEffectConfig>,
5844}
5845
5846#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
5848#[serde(rename_all = "snake_case")]
5849pub enum RegimeChangeTypeConfig {
5850 Acquisition,
5852 Divestiture,
5854 PriceIncrease,
5856 PriceDecrease,
5858 ProductLaunch,
5860 ProductDiscontinuation,
5862 PolicyChange,
5864 CompetitorEntry,
5866 Custom,
5868}
5869
5870#[derive(Debug, Clone, Serialize, Deserialize)]
5872pub struct RegimeEffectConfig {
5873 pub field: String,
5875
5876 pub multiplier: f64,
5878}
5879
5880#[derive(Debug, Clone, Serialize, Deserialize)]
5882pub struct EconomicCycleSchemaConfig {
5883 #[serde(default)]
5885 pub enabled: bool,
5886
5887 #[serde(default = "default_cycle_period")]
5889 pub period_months: u32,
5890
5891 #[serde(default = "default_cycle_amplitude")]
5893 pub amplitude: f64,
5894
5895 #[serde(default)]
5897 pub phase_offset: u32,
5898
5899 #[serde(default)]
5901 pub recessions: Vec<RecessionPeriodConfig>,
5902}
5903
5904fn default_cycle_period() -> u32 {
5905 48
5906}
5907
5908fn default_cycle_amplitude() -> f64 {
5909 0.15
5910}
5911
5912impl Default for EconomicCycleSchemaConfig {
5913 fn default() -> Self {
5914 Self {
5915 enabled: false,
5916 period_months: 48,
5917 amplitude: 0.15,
5918 phase_offset: 0,
5919 recessions: Vec::new(),
5920 }
5921 }
5922}
5923
5924#[derive(Debug, Clone, Serialize, Deserialize)]
5926pub struct RecessionPeriodConfig {
5927 pub start_month: u32,
5929
5930 pub duration_months: u32,
5932
5933 #[serde(default = "default_recession_severity")]
5935 pub severity: f64,
5936}
5937
5938fn default_recession_severity() -> f64 {
5939 0.20
5940}
5941
5942#[derive(Debug, Clone, Serialize, Deserialize)]
5944pub struct ParameterDriftSchemaConfig {
5945 pub parameter: String,
5947
5948 pub drift_type: ParameterDriftTypeConfig,
5950
5951 pub start_value: f64,
5953
5954 pub end_value: f64,
5956
5957 #[serde(default)]
5959 pub start_period: u32,
5960
5961 #[serde(default)]
5963 pub end_period: Option<u32>,
5964}
5965
5966#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5968#[serde(rename_all = "snake_case")]
5969pub enum ParameterDriftTypeConfig {
5970 #[default]
5972 Linear,
5973 Exponential,
5975 Logistic,
5977 Step,
5979}
5980
5981#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5983pub struct StatisticalValidationSchemaConfig {
5984 #[serde(default)]
5986 pub enabled: bool,
5987
5988 #[serde(default)]
5990 pub tests: Vec<StatisticalTestConfig>,
5991
5992 #[serde(default)]
5994 pub reporting: ValidationReportingConfig,
5995}
5996
5997#[derive(Debug, Clone, Serialize, Deserialize)]
5999#[serde(tag = "type", rename_all = "snake_case")]
6000pub enum StatisticalTestConfig {
6001 BenfordFirstDigit {
6003 #[serde(default = "default_benford_threshold")]
6005 threshold_mad: f64,
6006 #[serde(default = "default_benford_warning")]
6008 warning_mad: f64,
6009 },
6010 DistributionFit {
6012 target: TargetDistributionConfig,
6014 #[serde(default = "default_ks_significance")]
6016 ks_significance: f64,
6017 #[serde(default)]
6019 method: DistributionFitMethod,
6020 },
6021 CorrelationCheck {
6023 expected_correlations: Vec<ExpectedCorrelationConfig>,
6025 },
6026 ChiSquared {
6028 #[serde(default = "default_chi_squared_bins")]
6030 bins: usize,
6031 #[serde(default = "default_chi_squared_significance")]
6033 significance: f64,
6034 },
6035 AndersonDarling {
6037 target: TargetDistributionConfig,
6039 #[serde(default = "default_ad_significance")]
6041 significance: f64,
6042 },
6043}
6044
6045fn default_benford_threshold() -> f64 {
6046 0.015
6047}
6048
6049fn default_benford_warning() -> f64 {
6050 0.010
6051}
6052
6053fn default_ks_significance() -> f64 {
6054 0.05
6055}
6056
6057fn default_chi_squared_bins() -> usize {
6058 10
6059}
6060
6061fn default_chi_squared_significance() -> f64 {
6062 0.05
6063}
6064
6065fn default_ad_significance() -> f64 {
6066 0.05
6067}
6068
6069#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
6071#[serde(rename_all = "snake_case")]
6072pub enum TargetDistributionConfig {
6073 Normal,
6075 #[default]
6077 LogNormal,
6078 Exponential,
6080 Uniform,
6082}
6083
6084#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
6086#[serde(rename_all = "snake_case")]
6087pub enum DistributionFitMethod {
6088 #[default]
6090 KolmogorovSmirnov,
6091 AndersonDarling,
6093 ChiSquared,
6095}
6096
6097#[derive(Debug, Clone, Serialize, Deserialize)]
6099pub struct ValidationReportingConfig {
6100 #[serde(default)]
6102 pub output_report: bool,
6103
6104 #[serde(default)]
6106 pub format: ValidationReportFormat,
6107
6108 #[serde(default)]
6110 pub fail_on_error: bool,
6111
6112 #[serde(default = "default_true")]
6114 pub include_details: bool,
6115}
6116
6117impl Default for ValidationReportingConfig {
6118 fn default() -> Self {
6119 Self {
6120 output_report: false,
6121 format: ValidationReportFormat::Json,
6122 fail_on_error: false,
6123 include_details: true,
6124 }
6125 }
6126}
6127
6128#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
6130#[serde(rename_all = "snake_case")]
6131pub enum ValidationReportFormat {
6132 #[default]
6134 Json,
6135 Yaml,
6137 Html,
6139}
6140
6141#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6153pub struct TemporalPatternsConfig {
6154 #[serde(default)]
6156 pub enabled: bool,
6157
6158 #[serde(default)]
6160 pub business_days: BusinessDaySchemaConfig,
6161
6162 #[serde(default)]
6164 pub calendars: CalendarSchemaConfig,
6165
6166 #[serde(default)]
6168 pub period_end: PeriodEndSchemaConfig,
6169
6170 #[serde(default)]
6172 pub processing_lags: ProcessingLagSchemaConfig,
6173
6174 #[serde(default)]
6176 pub fiscal_calendar: FiscalCalendarSchemaConfig,
6177
6178 #[serde(default)]
6180 pub intraday: IntraDaySchemaConfig,
6181
6182 #[serde(default)]
6184 pub timezones: TimezoneSchemaConfig,
6185}
6186
6187#[derive(Debug, Clone, Serialize, Deserialize)]
6189pub struct BusinessDaySchemaConfig {
6190 #[serde(default = "default_true")]
6192 pub enabled: bool,
6193
6194 #[serde(default = "default_half_day_policy")]
6196 pub half_day_policy: String,
6197
6198 #[serde(default)]
6200 pub settlement_rules: SettlementRulesSchemaConfig,
6201
6202 #[serde(default = "default_month_end_convention")]
6204 pub month_end_convention: String,
6205
6206 #[serde(default)]
6208 pub weekend_days: Option<Vec<String>>,
6209}
6210
6211fn default_half_day_policy() -> String {
6212 "half_day".to_string()
6213}
6214
6215fn default_month_end_convention() -> String {
6216 "modified_following".to_string()
6217}
6218
6219impl Default for BusinessDaySchemaConfig {
6220 fn default() -> Self {
6221 Self {
6222 enabled: true,
6223 half_day_policy: "half_day".to_string(),
6224 settlement_rules: SettlementRulesSchemaConfig::default(),
6225 month_end_convention: "modified_following".to_string(),
6226 weekend_days: None,
6227 }
6228 }
6229}
6230
6231#[derive(Debug, Clone, Serialize, Deserialize)]
6233pub struct SettlementRulesSchemaConfig {
6234 #[serde(default = "default_settlement_2")]
6236 pub equity_days: i32,
6237
6238 #[serde(default = "default_settlement_1")]
6240 pub government_bonds_days: i32,
6241
6242 #[serde(default = "default_settlement_2")]
6244 pub fx_spot_days: i32,
6245
6246 #[serde(default = "default_settlement_2")]
6248 pub corporate_bonds_days: i32,
6249
6250 #[serde(default = "default_wire_cutoff")]
6252 pub wire_cutoff_time: String,
6253
6254 #[serde(default = "default_settlement_1")]
6256 pub wire_international_days: i32,
6257
6258 #[serde(default = "default_settlement_1")]
6260 pub ach_days: i32,
6261}
6262
6263fn default_settlement_1() -> i32 {
6264 1
6265}
6266
6267fn default_settlement_2() -> i32 {
6268 2
6269}
6270
6271fn default_wire_cutoff() -> String {
6272 "14:00".to_string()
6273}
6274
6275impl Default for SettlementRulesSchemaConfig {
6276 fn default() -> Self {
6277 Self {
6278 equity_days: 2,
6279 government_bonds_days: 1,
6280 fx_spot_days: 2,
6281 corporate_bonds_days: 2,
6282 wire_cutoff_time: "14:00".to_string(),
6283 wire_international_days: 1,
6284 ach_days: 1,
6285 }
6286 }
6287}
6288
6289#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6291pub struct CalendarSchemaConfig {
6292 #[serde(default)]
6294 pub regions: Vec<String>,
6295
6296 #[serde(default)]
6298 pub custom_holidays: Vec<CustomHolidaySchemaConfig>,
6299}
6300
6301#[derive(Debug, Clone, Serialize, Deserialize)]
6303pub struct CustomHolidaySchemaConfig {
6304 pub name: String,
6306 pub month: u8,
6308 pub day: u8,
6310 #[serde(default = "default_holiday_multiplier")]
6312 pub activity_multiplier: f64,
6313}
6314
6315fn default_holiday_multiplier() -> f64 {
6316 0.05
6317}
6318
6319#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6321pub struct PeriodEndSchemaConfig {
6322 #[serde(default)]
6324 pub model: Option<String>,
6325
6326 #[serde(default)]
6328 pub month_end: Option<PeriodEndModelSchemaConfig>,
6329
6330 #[serde(default)]
6332 pub quarter_end: Option<PeriodEndModelSchemaConfig>,
6333
6334 #[serde(default)]
6336 pub year_end: Option<PeriodEndModelSchemaConfig>,
6337}
6338
6339#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6341pub struct PeriodEndModelSchemaConfig {
6342 #[serde(default)]
6344 pub inherit_from: Option<String>,
6345
6346 #[serde(default)]
6348 pub additional_multiplier: Option<f64>,
6349
6350 #[serde(default)]
6352 pub start_day: Option<i32>,
6353
6354 #[serde(default)]
6356 pub base_multiplier: Option<f64>,
6357
6358 #[serde(default)]
6360 pub peak_multiplier: Option<f64>,
6361
6362 #[serde(default)]
6364 pub decay_rate: Option<f64>,
6365
6366 #[serde(default)]
6368 pub sustained_high_days: Option<i32>,
6369}
6370
6371#[derive(Debug, Clone, Serialize, Deserialize)]
6373pub struct ProcessingLagSchemaConfig {
6374 #[serde(default = "default_true")]
6376 pub enabled: bool,
6377
6378 #[serde(default)]
6380 pub sales_order_lag: Option<LagDistributionSchemaConfig>,
6381
6382 #[serde(default)]
6384 pub purchase_order_lag: Option<LagDistributionSchemaConfig>,
6385
6386 #[serde(default)]
6388 pub goods_receipt_lag: Option<LagDistributionSchemaConfig>,
6389
6390 #[serde(default)]
6392 pub invoice_receipt_lag: Option<LagDistributionSchemaConfig>,
6393
6394 #[serde(default)]
6396 pub invoice_issue_lag: Option<LagDistributionSchemaConfig>,
6397
6398 #[serde(default)]
6400 pub payment_lag: Option<LagDistributionSchemaConfig>,
6401
6402 #[serde(default)]
6404 pub journal_entry_lag: Option<LagDistributionSchemaConfig>,
6405
6406 #[serde(default)]
6408 pub cross_day_posting: Option<CrossDayPostingSchemaConfig>,
6409}
6410
6411impl Default for ProcessingLagSchemaConfig {
6412 fn default() -> Self {
6413 Self {
6414 enabled: true,
6415 sales_order_lag: None,
6416 purchase_order_lag: None,
6417 goods_receipt_lag: None,
6418 invoice_receipt_lag: None,
6419 invoice_issue_lag: None,
6420 payment_lag: None,
6421 journal_entry_lag: None,
6422 cross_day_posting: None,
6423 }
6424 }
6425}
6426
6427#[derive(Debug, Clone, Serialize, Deserialize)]
6429pub struct LagDistributionSchemaConfig {
6430 pub mu: f64,
6432 pub sigma: f64,
6434 #[serde(default)]
6436 pub min_hours: Option<f64>,
6437 #[serde(default)]
6439 pub max_hours: Option<f64>,
6440}
6441
6442#[derive(Debug, Clone, Serialize, Deserialize)]
6444pub struct CrossDayPostingSchemaConfig {
6445 #[serde(default = "default_true")]
6447 pub enabled: bool,
6448
6449 #[serde(default)]
6452 pub probability_by_hour: std::collections::HashMap<u8, f64>,
6453}
6454
6455impl Default for CrossDayPostingSchemaConfig {
6456 fn default() -> Self {
6457 let mut probability_by_hour = std::collections::HashMap::new();
6458 probability_by_hour.insert(17, 0.3);
6459 probability_by_hour.insert(18, 0.6);
6460 probability_by_hour.insert(19, 0.8);
6461 probability_by_hour.insert(20, 0.9);
6462 probability_by_hour.insert(21, 0.95);
6463 probability_by_hour.insert(22, 0.99);
6464
6465 Self {
6466 enabled: true,
6467 probability_by_hour,
6468 }
6469 }
6470}
6471
6472#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6481pub struct FiscalCalendarSchemaConfig {
6482 #[serde(default)]
6484 pub enabled: bool,
6485
6486 #[serde(default = "default_fiscal_calendar_type")]
6488 pub calendar_type: String,
6489
6490 #[serde(default)]
6492 pub year_start_month: Option<u8>,
6493
6494 #[serde(default)]
6496 pub year_start_day: Option<u8>,
6497
6498 #[serde(default)]
6500 pub four_four_five: Option<FourFourFiveSchemaConfig>,
6501}
6502
6503fn default_fiscal_calendar_type() -> String {
6504 "calendar_year".to_string()
6505}
6506
6507#[derive(Debug, Clone, Serialize, Deserialize)]
6509pub struct FourFourFiveSchemaConfig {
6510 #[serde(default = "default_week_pattern")]
6512 pub pattern: String,
6513
6514 #[serde(default = "default_anchor_type")]
6516 pub anchor_type: String,
6517
6518 #[serde(default = "default_anchor_month")]
6520 pub anchor_month: u8,
6521
6522 #[serde(default = "default_leap_week_placement")]
6524 pub leap_week_placement: String,
6525}
6526
6527fn default_week_pattern() -> String {
6528 "four_four_five".to_string()
6529}
6530
6531fn default_anchor_type() -> String {
6532 "last_saturday".to_string()
6533}
6534
6535fn default_anchor_month() -> u8 {
6536 1 }
6538
6539fn default_leap_week_placement() -> String {
6540 "q4_period3".to_string()
6541}
6542
6543impl Default for FourFourFiveSchemaConfig {
6544 fn default() -> Self {
6545 Self {
6546 pattern: "four_four_five".to_string(),
6547 anchor_type: "last_saturday".to_string(),
6548 anchor_month: 1,
6549 leap_week_placement: "q4_period3".to_string(),
6550 }
6551 }
6552}
6553
6554#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6563pub struct IntraDaySchemaConfig {
6564 #[serde(default)]
6566 pub enabled: bool,
6567
6568 #[serde(default)]
6570 pub segments: Vec<IntraDaySegmentSchemaConfig>,
6571}
6572
6573#[derive(Debug, Clone, Serialize, Deserialize)]
6575pub struct IntraDaySegmentSchemaConfig {
6576 pub name: String,
6578
6579 pub start: String,
6581
6582 pub end: String,
6584
6585 #[serde(default = "default_multiplier")]
6587 pub multiplier: f64,
6588
6589 #[serde(default = "default_posting_type")]
6591 pub posting_type: String,
6592}
6593
6594fn default_multiplier() -> f64 {
6595 1.0
6596}
6597
6598fn default_posting_type() -> String {
6599 "both".to_string()
6600}
6601
6602#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6608pub struct TimezoneSchemaConfig {
6609 #[serde(default)]
6611 pub enabled: bool,
6612
6613 #[serde(default = "default_timezone")]
6615 pub default_timezone: String,
6616
6617 #[serde(default = "default_consolidation_timezone")]
6619 pub consolidation_timezone: String,
6620
6621 #[serde(default)]
6624 pub entity_mappings: Vec<EntityTimezoneMapping>,
6625}
6626
6627fn default_timezone() -> String {
6628 "America/New_York".to_string()
6629}
6630
6631fn default_consolidation_timezone() -> String {
6632 "UTC".to_string()
6633}
6634
6635#[derive(Debug, Clone, Serialize, Deserialize)]
6637pub struct EntityTimezoneMapping {
6638 pub pattern: String,
6640
6641 pub timezone: String,
6643}
6644
6645#[derive(Debug, Clone, Serialize, Deserialize)]
6651pub struct VendorNetworkSchemaConfig {
6652 #[serde(default)]
6654 pub enabled: bool,
6655
6656 #[serde(default = "default_vendor_tier_depth")]
6658 pub depth: u8,
6659
6660 #[serde(default)]
6662 pub tier1: TierCountSchemaConfig,
6663
6664 #[serde(default)]
6666 pub tier2_per_parent: TierCountSchemaConfig,
6667
6668 #[serde(default)]
6670 pub tier3_per_parent: TierCountSchemaConfig,
6671
6672 #[serde(default)]
6674 pub clusters: VendorClusterSchemaConfig,
6675
6676 #[serde(default)]
6678 pub dependencies: DependencySchemaConfig,
6679}
6680
6681fn default_vendor_tier_depth() -> u8 {
6682 3
6683}
6684
6685impl Default for VendorNetworkSchemaConfig {
6686 fn default() -> Self {
6687 Self {
6688 enabled: false,
6689 depth: 3,
6690 tier1: TierCountSchemaConfig { min: 50, max: 100 },
6691 tier2_per_parent: TierCountSchemaConfig { min: 4, max: 10 },
6692 tier3_per_parent: TierCountSchemaConfig { min: 2, max: 5 },
6693 clusters: VendorClusterSchemaConfig::default(),
6694 dependencies: DependencySchemaConfig::default(),
6695 }
6696 }
6697}
6698
6699#[derive(Debug, Clone, Serialize, Deserialize)]
6701pub struct TierCountSchemaConfig {
6702 #[serde(default = "default_tier_min")]
6704 pub min: usize,
6705
6706 #[serde(default = "default_tier_max")]
6708 pub max: usize,
6709}
6710
6711fn default_tier_min() -> usize {
6712 5
6713}
6714
6715fn default_tier_max() -> usize {
6716 20
6717}
6718
6719impl Default for TierCountSchemaConfig {
6720 fn default() -> Self {
6721 Self {
6722 min: default_tier_min(),
6723 max: default_tier_max(),
6724 }
6725 }
6726}
6727
6728#[derive(Debug, Clone, Serialize, Deserialize)]
6730pub struct VendorClusterSchemaConfig {
6731 #[serde(default = "default_reliable_strategic")]
6733 pub reliable_strategic: f64,
6734
6735 #[serde(default = "default_standard_operational")]
6737 pub standard_operational: f64,
6738
6739 #[serde(default = "default_transactional")]
6741 pub transactional: f64,
6742
6743 #[serde(default = "default_problematic")]
6745 pub problematic: f64,
6746}
6747
6748fn default_reliable_strategic() -> f64 {
6749 0.20
6750}
6751
6752fn default_standard_operational() -> f64 {
6753 0.50
6754}
6755
6756fn default_transactional() -> f64 {
6757 0.25
6758}
6759
6760fn default_problematic() -> f64 {
6761 0.05
6762}
6763
6764impl Default for VendorClusterSchemaConfig {
6765 fn default() -> Self {
6766 Self {
6767 reliable_strategic: 0.20,
6768 standard_operational: 0.50,
6769 transactional: 0.25,
6770 problematic: 0.05,
6771 }
6772 }
6773}
6774
6775#[derive(Debug, Clone, Serialize, Deserialize)]
6777pub struct DependencySchemaConfig {
6778 #[serde(default = "default_max_single_vendor")]
6780 pub max_single_vendor_concentration: f64,
6781
6782 #[serde(default = "default_max_top5")]
6784 pub top_5_concentration: f64,
6785
6786 #[serde(default = "default_single_source_percent")]
6788 pub single_source_percent: f64,
6789}
6790
6791fn default_max_single_vendor() -> f64 {
6792 0.15
6793}
6794
6795fn default_max_top5() -> f64 {
6796 0.45
6797}
6798
6799fn default_single_source_percent() -> f64 {
6800 0.05
6801}
6802
6803impl Default for DependencySchemaConfig {
6804 fn default() -> Self {
6805 Self {
6806 max_single_vendor_concentration: 0.15,
6807 top_5_concentration: 0.45,
6808 single_source_percent: 0.05,
6809 }
6810 }
6811}
6812
6813#[derive(Debug, Clone, Default, Serialize, Deserialize)]
6819pub struct CustomerSegmentationSchemaConfig {
6820 #[serde(default)]
6822 pub enabled: bool,
6823
6824 #[serde(default)]
6826 pub value_segments: ValueSegmentsSchemaConfig,
6827
6828 #[serde(default)]
6830 pub lifecycle: LifecycleSchemaConfig,
6831
6832 #[serde(default)]
6834 pub networks: CustomerNetworksSchemaConfig,
6835}
6836
6837#[derive(Debug, Clone, Serialize, Deserialize)]
6839pub struct ValueSegmentsSchemaConfig {
6840 #[serde(default)]
6842 pub enterprise: SegmentDetailSchemaConfig,
6843
6844 #[serde(default)]
6846 pub mid_market: SegmentDetailSchemaConfig,
6847
6848 #[serde(default)]
6850 pub smb: SegmentDetailSchemaConfig,
6851
6852 #[serde(default)]
6854 pub consumer: SegmentDetailSchemaConfig,
6855}
6856
6857impl Default for ValueSegmentsSchemaConfig {
6858 fn default() -> Self {
6859 Self {
6860 enterprise: SegmentDetailSchemaConfig {
6861 revenue_share: 0.40,
6862 customer_share: 0.05,
6863 avg_order_value_range: "50000+".to_string(),
6864 },
6865 mid_market: SegmentDetailSchemaConfig {
6866 revenue_share: 0.35,
6867 customer_share: 0.20,
6868 avg_order_value_range: "5000-50000".to_string(),
6869 },
6870 smb: SegmentDetailSchemaConfig {
6871 revenue_share: 0.20,
6872 customer_share: 0.50,
6873 avg_order_value_range: "500-5000".to_string(),
6874 },
6875 consumer: SegmentDetailSchemaConfig {
6876 revenue_share: 0.05,
6877 customer_share: 0.25,
6878 avg_order_value_range: "50-500".to_string(),
6879 },
6880 }
6881 }
6882}
6883
6884#[derive(Debug, Clone, Serialize, Deserialize)]
6886pub struct SegmentDetailSchemaConfig {
6887 #[serde(default)]
6889 pub revenue_share: f64,
6890
6891 #[serde(default)]
6893 pub customer_share: f64,
6894
6895 #[serde(default)]
6897 pub avg_order_value_range: String,
6898}
6899
6900impl Default for SegmentDetailSchemaConfig {
6901 fn default() -> Self {
6902 Self {
6903 revenue_share: 0.25,
6904 customer_share: 0.25,
6905 avg_order_value_range: "1000-10000".to_string(),
6906 }
6907 }
6908}
6909
6910#[derive(Debug, Clone, Serialize, Deserialize)]
6912pub struct LifecycleSchemaConfig {
6913 #[serde(default)]
6915 pub prospect_rate: f64,
6916
6917 #[serde(default = "default_new_rate")]
6919 pub new_rate: f64,
6920
6921 #[serde(default = "default_growth_rate")]
6923 pub growth_rate: f64,
6924
6925 #[serde(default = "default_mature_rate")]
6927 pub mature_rate: f64,
6928
6929 #[serde(default = "default_at_risk_rate")]
6931 pub at_risk_rate: f64,
6932
6933 #[serde(default = "default_churned_rate")]
6935 pub churned_rate: f64,
6936
6937 #[serde(default)]
6939 pub won_back_rate: f64,
6940}
6941
6942fn default_new_rate() -> f64 {
6943 0.10
6944}
6945
6946fn default_growth_rate() -> f64 {
6947 0.15
6948}
6949
6950fn default_mature_rate() -> f64 {
6951 0.60
6952}
6953
6954fn default_at_risk_rate() -> f64 {
6955 0.10
6956}
6957
6958fn default_churned_rate() -> f64 {
6959 0.05
6960}
6961
6962impl Default for LifecycleSchemaConfig {
6963 fn default() -> Self {
6964 Self {
6965 prospect_rate: 0.0,
6966 new_rate: 0.10,
6967 growth_rate: 0.15,
6968 mature_rate: 0.60,
6969 at_risk_rate: 0.10,
6970 churned_rate: 0.05,
6971 won_back_rate: 0.0,
6972 }
6973 }
6974}
6975
6976#[derive(Debug, Clone, Default, Serialize, Deserialize)]
6978pub struct CustomerNetworksSchemaConfig {
6979 #[serde(default)]
6981 pub referrals: ReferralSchemaConfig,
6982
6983 #[serde(default)]
6985 pub corporate_hierarchies: HierarchySchemaConfig,
6986}
6987
6988#[derive(Debug, Clone, Serialize, Deserialize)]
6990pub struct ReferralSchemaConfig {
6991 #[serde(default = "default_true")]
6993 pub enabled: bool,
6994
6995 #[serde(default = "default_referral_rate")]
6997 pub referral_rate: f64,
6998}
6999
7000fn default_referral_rate() -> f64 {
7001 0.15
7002}
7003
7004impl Default for ReferralSchemaConfig {
7005 fn default() -> Self {
7006 Self {
7007 enabled: true,
7008 referral_rate: 0.15,
7009 }
7010 }
7011}
7012
7013#[derive(Debug, Clone, Serialize, Deserialize)]
7015pub struct HierarchySchemaConfig {
7016 #[serde(default = "default_true")]
7018 pub enabled: bool,
7019
7020 #[serde(default = "default_hierarchy_rate")]
7022 pub probability: f64,
7023}
7024
7025fn default_hierarchy_rate() -> f64 {
7026 0.30
7027}
7028
7029impl Default for HierarchySchemaConfig {
7030 fn default() -> Self {
7031 Self {
7032 enabled: true,
7033 probability: 0.30,
7034 }
7035 }
7036}
7037
7038#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7044pub struct RelationshipStrengthSchemaConfig {
7045 #[serde(default)]
7047 pub enabled: bool,
7048
7049 #[serde(default)]
7051 pub calculation: StrengthCalculationSchemaConfig,
7052
7053 #[serde(default)]
7055 pub thresholds: StrengthThresholdsSchemaConfig,
7056}
7057
7058#[derive(Debug, Clone, Serialize, Deserialize)]
7060pub struct StrengthCalculationSchemaConfig {
7061 #[serde(default = "default_volume_weight")]
7063 pub transaction_volume_weight: f64,
7064
7065 #[serde(default = "default_count_weight")]
7067 pub transaction_count_weight: f64,
7068
7069 #[serde(default = "default_duration_weight")]
7071 pub relationship_duration_weight: f64,
7072
7073 #[serde(default = "default_recency_weight")]
7075 pub recency_weight: f64,
7076
7077 #[serde(default = "default_mutual_weight")]
7079 pub mutual_connections_weight: f64,
7080
7081 #[serde(default = "default_recency_half_life")]
7083 pub recency_half_life_days: u32,
7084}
7085
7086fn default_volume_weight() -> f64 {
7087 0.30
7088}
7089
7090fn default_count_weight() -> f64 {
7091 0.25
7092}
7093
7094fn default_duration_weight() -> f64 {
7095 0.20
7096}
7097
7098fn default_recency_weight() -> f64 {
7099 0.15
7100}
7101
7102fn default_mutual_weight() -> f64 {
7103 0.10
7104}
7105
7106fn default_recency_half_life() -> u32 {
7107 90
7108}
7109
7110impl Default for StrengthCalculationSchemaConfig {
7111 fn default() -> Self {
7112 Self {
7113 transaction_volume_weight: 0.30,
7114 transaction_count_weight: 0.25,
7115 relationship_duration_weight: 0.20,
7116 recency_weight: 0.15,
7117 mutual_connections_weight: 0.10,
7118 recency_half_life_days: 90,
7119 }
7120 }
7121}
7122
7123#[derive(Debug, Clone, Serialize, Deserialize)]
7125pub struct StrengthThresholdsSchemaConfig {
7126 #[serde(default = "default_strong_threshold")]
7128 pub strong: f64,
7129
7130 #[serde(default = "default_moderate_threshold")]
7132 pub moderate: f64,
7133
7134 #[serde(default = "default_weak_threshold")]
7136 pub weak: f64,
7137}
7138
7139fn default_strong_threshold() -> f64 {
7140 0.7
7141}
7142
7143fn default_moderate_threshold() -> f64 {
7144 0.4
7145}
7146
7147fn default_weak_threshold() -> f64 {
7148 0.1
7149}
7150
7151impl Default for StrengthThresholdsSchemaConfig {
7152 fn default() -> Self {
7153 Self {
7154 strong: 0.7,
7155 moderate: 0.4,
7156 weak: 0.1,
7157 }
7158 }
7159}
7160
7161#[derive(Debug, Clone, Serialize, Deserialize)]
7167pub struct CrossProcessLinksSchemaConfig {
7168 #[serde(default)]
7170 pub enabled: bool,
7171
7172 #[serde(default = "default_true")]
7174 pub inventory_p2p_o2c: bool,
7175
7176 #[serde(default = "default_true")]
7178 pub payment_bank_reconciliation: bool,
7179
7180 #[serde(default = "default_true")]
7182 pub intercompany_bilateral: bool,
7183
7184 #[serde(default = "default_inventory_link_rate")]
7186 pub inventory_link_rate: f64,
7187}
7188
7189fn default_inventory_link_rate() -> f64 {
7190 0.30
7191}
7192
7193impl Default for CrossProcessLinksSchemaConfig {
7194 fn default() -> Self {
7195 Self {
7196 enabled: false,
7197 inventory_p2p_o2c: true,
7198 payment_bank_reconciliation: true,
7199 intercompany_bilateral: true,
7200 inventory_link_rate: 0.30,
7201 }
7202 }
7203}
7204
7205#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7211pub struct OrganizationalEventsSchemaConfig {
7212 #[serde(default)]
7214 pub enabled: bool,
7215
7216 #[serde(default)]
7218 pub effect_blending: EffectBlendingModeConfig,
7219
7220 #[serde(default)]
7222 pub events: Vec<OrganizationalEventSchemaConfig>,
7223
7224 #[serde(default)]
7226 pub process_evolution: Vec<ProcessEvolutionSchemaConfig>,
7227
7228 #[serde(default)]
7230 pub technology_transitions: Vec<TechnologyTransitionSchemaConfig>,
7231}
7232
7233#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
7235#[serde(rename_all = "snake_case")]
7236pub enum EffectBlendingModeConfig {
7237 #[default]
7239 Multiplicative,
7240 Additive,
7242 Maximum,
7244 Minimum,
7246}
7247
7248#[derive(Debug, Clone, Serialize, Deserialize)]
7250pub struct OrganizationalEventSchemaConfig {
7251 pub id: String,
7253
7254 pub event_type: OrganizationalEventTypeSchemaConfig,
7256
7257 pub effective_date: String,
7259
7260 #[serde(default = "default_org_transition_months")]
7262 pub transition_months: u32,
7263
7264 #[serde(default)]
7266 pub description: Option<String>,
7267}
7268
7269fn default_org_transition_months() -> u32 {
7270 6
7271}
7272
7273#[derive(Debug, Clone, Serialize, Deserialize)]
7275#[serde(tag = "type", rename_all = "snake_case")]
7276pub enum OrganizationalEventTypeSchemaConfig {
7277 Acquisition {
7279 acquired_entity: String,
7281 #[serde(default = "default_acquisition_volume")]
7283 volume_increase: f64,
7284 #[serde(default = "default_acquisition_error")]
7286 integration_error_rate: f64,
7287 #[serde(default = "default_parallel_days")]
7289 parallel_posting_days: u32,
7290 },
7291 Divestiture {
7293 divested_entity: String,
7295 #[serde(default = "default_divestiture_volume")]
7297 volume_reduction: f64,
7298 #[serde(default = "default_true_val")]
7300 remove_entity: bool,
7301 },
7302 Reorganization {
7304 #[serde(default)]
7306 cost_center_remapping: std::collections::HashMap<String, String>,
7307 #[serde(default = "default_reorg_error")]
7309 transition_error_rate: f64,
7310 },
7311 LeadershipChange {
7313 role: String,
7315 #[serde(default)]
7317 policy_changes: Vec<String>,
7318 },
7319 WorkforceReduction {
7321 #[serde(default = "default_workforce_reduction")]
7323 reduction_percent: f64,
7324 #[serde(default = "default_workforce_error")]
7326 error_rate_increase: f64,
7327 },
7328 Merger {
7330 merged_entity: String,
7332 #[serde(default = "default_merger_volume")]
7334 volume_increase: f64,
7335 },
7336}
7337
7338fn default_acquisition_volume() -> f64 {
7339 1.35
7340}
7341
7342fn default_acquisition_error() -> f64 {
7343 0.05
7344}
7345
7346fn default_parallel_days() -> u32 {
7347 30
7348}
7349
7350fn default_divestiture_volume() -> f64 {
7351 0.70
7352}
7353
7354fn default_true_val() -> bool {
7355 true
7356}
7357
7358fn default_reorg_error() -> f64 {
7359 0.04
7360}
7361
7362fn default_workforce_reduction() -> f64 {
7363 0.10
7364}
7365
7366fn default_workforce_error() -> f64 {
7367 0.05
7368}
7369
7370fn default_merger_volume() -> f64 {
7371 1.80
7372}
7373
7374#[derive(Debug, Clone, Serialize, Deserialize)]
7376pub struct ProcessEvolutionSchemaConfig {
7377 pub id: String,
7379
7380 pub event_type: ProcessEvolutionTypeSchemaConfig,
7382
7383 pub effective_date: String,
7385
7386 #[serde(default)]
7388 pub description: Option<String>,
7389}
7390
7391#[derive(Debug, Clone, Serialize, Deserialize)]
7393#[serde(tag = "type", rename_all = "snake_case")]
7394pub enum ProcessEvolutionTypeSchemaConfig {
7395 ProcessAutomation {
7397 process_name: String,
7399 #[serde(default = "default_manual_before")]
7401 manual_rate_before: f64,
7402 #[serde(default = "default_manual_after")]
7404 manual_rate_after: f64,
7405 },
7406 ApprovalWorkflowChange {
7408 description: String,
7410 },
7411 ControlEnhancement {
7413 control_id: String,
7415 #[serde(default = "default_error_reduction")]
7417 error_reduction: f64,
7418 },
7419}
7420
7421fn default_manual_before() -> f64 {
7422 0.80
7423}
7424
7425fn default_manual_after() -> f64 {
7426 0.15
7427}
7428
7429fn default_error_reduction() -> f64 {
7430 0.02
7431}
7432
7433#[derive(Debug, Clone, Serialize, Deserialize)]
7435pub struct TechnologyTransitionSchemaConfig {
7436 pub id: String,
7438
7439 pub event_type: TechnologyTransitionTypeSchemaConfig,
7441
7442 #[serde(default)]
7444 pub description: Option<String>,
7445}
7446
7447#[derive(Debug, Clone, Serialize, Deserialize)]
7449#[serde(tag = "type", rename_all = "snake_case")]
7450pub enum TechnologyTransitionTypeSchemaConfig {
7451 ErpMigration {
7453 source_system: String,
7455 target_system: String,
7457 cutover_date: String,
7459 stabilization_end: String,
7461 #[serde(default = "default_erp_duplicate_rate")]
7463 duplicate_rate: f64,
7464 #[serde(default = "default_format_mismatch")]
7466 format_mismatch_rate: f64,
7467 },
7468 ModuleImplementation {
7470 module_name: String,
7472 go_live_date: String,
7474 },
7475}
7476
7477fn default_erp_duplicate_rate() -> f64 {
7478 0.02
7479}
7480
7481fn default_format_mismatch() -> f64 {
7482 0.03
7483}
7484
7485#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7491pub struct BehavioralDriftSchemaConfig {
7492 #[serde(default)]
7494 pub enabled: bool,
7495
7496 #[serde(default)]
7498 pub vendor_behavior: VendorBehaviorSchemaConfig,
7499
7500 #[serde(default)]
7502 pub customer_behavior: CustomerBehaviorSchemaConfig,
7503
7504 #[serde(default)]
7506 pub employee_behavior: EmployeeBehaviorSchemaConfig,
7507
7508 #[serde(default)]
7510 pub collective: CollectiveBehaviorSchemaConfig,
7511}
7512
7513#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7515pub struct VendorBehaviorSchemaConfig {
7516 #[serde(default)]
7518 pub payment_terms_drift: PaymentTermsDriftSchemaConfig,
7519
7520 #[serde(default)]
7522 pub quality_drift: QualityDriftSchemaConfig,
7523}
7524
7525#[derive(Debug, Clone, Serialize, Deserialize)]
7527pub struct PaymentTermsDriftSchemaConfig {
7528 #[serde(default = "default_extension_rate")]
7530 pub extension_rate_per_year: f64,
7531
7532 #[serde(default = "default_economic_sensitivity")]
7534 pub economic_sensitivity: f64,
7535}
7536
7537fn default_extension_rate() -> f64 {
7538 2.5
7539}
7540
7541fn default_economic_sensitivity() -> f64 {
7542 1.0
7543}
7544
7545impl Default for PaymentTermsDriftSchemaConfig {
7546 fn default() -> Self {
7547 Self {
7548 extension_rate_per_year: 2.5,
7549 economic_sensitivity: 1.0,
7550 }
7551 }
7552}
7553
7554#[derive(Debug, Clone, Serialize, Deserialize)]
7556pub struct QualityDriftSchemaConfig {
7557 #[serde(default = "default_improvement_rate")]
7559 pub new_vendor_improvement_rate: f64,
7560
7561 #[serde(default = "default_decline_rate")]
7563 pub complacency_decline_rate: f64,
7564}
7565
7566fn default_improvement_rate() -> f64 {
7567 0.02
7568}
7569
7570fn default_decline_rate() -> f64 {
7571 0.01
7572}
7573
7574impl Default for QualityDriftSchemaConfig {
7575 fn default() -> Self {
7576 Self {
7577 new_vendor_improvement_rate: 0.02,
7578 complacency_decline_rate: 0.01,
7579 }
7580 }
7581}
7582
7583#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7585pub struct CustomerBehaviorSchemaConfig {
7586 #[serde(default)]
7588 pub payment_drift: CustomerPaymentDriftSchemaConfig,
7589
7590 #[serde(default)]
7592 pub order_drift: OrderDriftSchemaConfig,
7593}
7594
7595#[derive(Debug, Clone, Serialize, Deserialize)]
7597pub struct CustomerPaymentDriftSchemaConfig {
7598 #[serde(default = "default_downturn_extension")]
7600 pub downturn_days_extension: (u32, u32),
7601
7602 #[serde(default = "default_bad_debt_increase")]
7604 pub downturn_bad_debt_increase: f64,
7605}
7606
7607fn default_downturn_extension() -> (u32, u32) {
7608 (5, 15)
7609}
7610
7611fn default_bad_debt_increase() -> f64 {
7612 0.02
7613}
7614
7615impl Default for CustomerPaymentDriftSchemaConfig {
7616 fn default() -> Self {
7617 Self {
7618 downturn_days_extension: (5, 15),
7619 downturn_bad_debt_increase: 0.02,
7620 }
7621 }
7622}
7623
7624#[derive(Debug, Clone, Serialize, Deserialize)]
7626pub struct OrderDriftSchemaConfig {
7627 #[serde(default = "default_digital_shift")]
7629 pub digital_shift_rate: f64,
7630}
7631
7632fn default_digital_shift() -> f64 {
7633 0.05
7634}
7635
7636impl Default for OrderDriftSchemaConfig {
7637 fn default() -> Self {
7638 Self {
7639 digital_shift_rate: 0.05,
7640 }
7641 }
7642}
7643
7644#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7646pub struct EmployeeBehaviorSchemaConfig {
7647 #[serde(default)]
7649 pub approval_drift: ApprovalDriftSchemaConfig,
7650
7651 #[serde(default)]
7653 pub error_drift: ErrorDriftSchemaConfig,
7654}
7655
7656#[derive(Debug, Clone, Serialize, Deserialize)]
7658pub struct ApprovalDriftSchemaConfig {
7659 #[serde(default = "default_eom_intensity")]
7661 pub eom_intensity_increase_per_year: f64,
7662
7663 #[serde(default = "default_rubber_stamp")]
7665 pub rubber_stamp_volume_threshold: u32,
7666}
7667
7668fn default_eom_intensity() -> f64 {
7669 0.05
7670}
7671
7672fn default_rubber_stamp() -> u32 {
7673 50
7674}
7675
7676impl Default for ApprovalDriftSchemaConfig {
7677 fn default() -> Self {
7678 Self {
7679 eom_intensity_increase_per_year: 0.05,
7680 rubber_stamp_volume_threshold: 50,
7681 }
7682 }
7683}
7684
7685#[derive(Debug, Clone, Serialize, Deserialize)]
7687pub struct ErrorDriftSchemaConfig {
7688 #[serde(default = "default_new_error")]
7690 pub new_employee_error_rate: f64,
7691
7692 #[serde(default = "default_learning_months")]
7694 pub learning_curve_months: u32,
7695}
7696
7697fn default_new_error() -> f64 {
7698 0.08
7699}
7700
7701fn default_learning_months() -> u32 {
7702 6
7703}
7704
7705impl Default for ErrorDriftSchemaConfig {
7706 fn default() -> Self {
7707 Self {
7708 new_employee_error_rate: 0.08,
7709 learning_curve_months: 6,
7710 }
7711 }
7712}
7713
7714#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7716pub struct CollectiveBehaviorSchemaConfig {
7717 #[serde(default)]
7719 pub automation_adoption: AutomationAdoptionSchemaConfig,
7720}
7721
7722#[derive(Debug, Clone, Serialize, Deserialize)]
7724pub struct AutomationAdoptionSchemaConfig {
7725 #[serde(default)]
7727 pub s_curve_enabled: bool,
7728
7729 #[serde(default = "default_midpoint")]
7731 pub adoption_midpoint_months: u32,
7732
7733 #[serde(default = "default_steepness")]
7735 pub steepness: f64,
7736}
7737
7738fn default_midpoint() -> u32 {
7739 24
7740}
7741
7742fn default_steepness() -> f64 {
7743 0.15
7744}
7745
7746impl Default for AutomationAdoptionSchemaConfig {
7747 fn default() -> Self {
7748 Self {
7749 s_curve_enabled: false,
7750 adoption_midpoint_months: 24,
7751 steepness: 0.15,
7752 }
7753 }
7754}
7755
7756#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7762pub struct MarketDriftSchemaConfig {
7763 #[serde(default)]
7765 pub enabled: bool,
7766
7767 #[serde(default)]
7769 pub economic_cycle: MarketEconomicCycleSchemaConfig,
7770
7771 #[serde(default)]
7773 pub industry_cycles: std::collections::HashMap<String, IndustryCycleSchemaConfig>,
7774
7775 #[serde(default)]
7777 pub commodities: CommoditiesSchemaConfig,
7778}
7779
7780#[derive(Debug, Clone, Serialize, Deserialize)]
7782pub struct MarketEconomicCycleSchemaConfig {
7783 #[serde(default)]
7785 pub enabled: bool,
7786
7787 #[serde(default)]
7789 pub cycle_type: CycleTypeSchemaConfig,
7790
7791 #[serde(default = "default_market_cycle_period")]
7793 pub period_months: u32,
7794
7795 #[serde(default = "default_market_amplitude")]
7797 pub amplitude: f64,
7798
7799 #[serde(default)]
7801 pub recession: RecessionSchemaConfig,
7802}
7803
7804fn default_market_cycle_period() -> u32 {
7805 48
7806}
7807
7808fn default_market_amplitude() -> f64 {
7809 0.15
7810}
7811
7812impl Default for MarketEconomicCycleSchemaConfig {
7813 fn default() -> Self {
7814 Self {
7815 enabled: false,
7816 cycle_type: CycleTypeSchemaConfig::Sinusoidal,
7817 period_months: 48,
7818 amplitude: 0.15,
7819 recession: RecessionSchemaConfig::default(),
7820 }
7821 }
7822}
7823
7824#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
7826#[serde(rename_all = "snake_case")]
7827pub enum CycleTypeSchemaConfig {
7828 #[default]
7830 Sinusoidal,
7831 Asymmetric,
7833 MeanReverting,
7835}
7836
7837#[derive(Debug, Clone, Serialize, Deserialize)]
7839pub struct RecessionSchemaConfig {
7840 #[serde(default)]
7842 pub enabled: bool,
7843
7844 #[serde(default = "default_recession_prob")]
7846 pub probability_per_year: f64,
7847
7848 #[serde(default)]
7850 pub severity: RecessionSeveritySchemaConfig,
7851
7852 #[serde(default)]
7854 pub recession_periods: Vec<RecessionPeriodSchemaConfig>,
7855}
7856
7857fn default_recession_prob() -> f64 {
7858 0.10
7859}
7860
7861impl Default for RecessionSchemaConfig {
7862 fn default() -> Self {
7863 Self {
7864 enabled: false,
7865 probability_per_year: 0.10,
7866 severity: RecessionSeveritySchemaConfig::Moderate,
7867 recession_periods: Vec::new(),
7868 }
7869 }
7870}
7871
7872#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
7874#[serde(rename_all = "snake_case")]
7875pub enum RecessionSeveritySchemaConfig {
7876 Mild,
7878 #[default]
7880 Moderate,
7881 Severe,
7883}
7884
7885#[derive(Debug, Clone, Serialize, Deserialize)]
7887pub struct RecessionPeriodSchemaConfig {
7888 pub start_month: u32,
7890 pub duration_months: u32,
7892}
7893
7894#[derive(Debug, Clone, Serialize, Deserialize)]
7896pub struct IndustryCycleSchemaConfig {
7897 #[serde(default = "default_industry_period")]
7899 pub period_months: u32,
7900
7901 #[serde(default = "default_industry_amp")]
7903 pub amplitude: f64,
7904}
7905
7906fn default_industry_period() -> u32 {
7907 36
7908}
7909
7910fn default_industry_amp() -> f64 {
7911 0.20
7912}
7913
7914#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7916pub struct CommoditiesSchemaConfig {
7917 #[serde(default)]
7919 pub enabled: bool,
7920
7921 #[serde(default)]
7923 pub items: Vec<CommodityItemSchemaConfig>,
7924}
7925
7926#[derive(Debug, Clone, Serialize, Deserialize)]
7928pub struct CommodityItemSchemaConfig {
7929 pub name: String,
7931
7932 #[serde(default = "default_volatility")]
7934 pub volatility: f64,
7935
7936 #[serde(default)]
7938 pub cogs_pass_through: f64,
7939
7940 #[serde(default)]
7942 pub overhead_pass_through: f64,
7943}
7944
7945fn default_volatility() -> f64 {
7946 0.20
7947}
7948
7949#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7955pub struct DriftLabelingSchemaConfig {
7956 #[serde(default)]
7958 pub enabled: bool,
7959
7960 #[serde(default)]
7962 pub statistical: StatisticalDriftLabelingSchemaConfig,
7963
7964 #[serde(default)]
7966 pub categorical: CategoricalDriftLabelingSchemaConfig,
7967
7968 #[serde(default)]
7970 pub temporal: TemporalDriftLabelingSchemaConfig,
7971
7972 #[serde(default)]
7974 pub regulatory_calendar_preset: Option<String>,
7975}
7976
7977#[derive(Debug, Clone, Serialize, Deserialize)]
7979pub struct StatisticalDriftLabelingSchemaConfig {
7980 #[serde(default = "default_true_val")]
7982 pub enabled: bool,
7983
7984 #[serde(default = "default_min_magnitude")]
7986 pub min_magnitude_threshold: f64,
7987}
7988
7989fn default_min_magnitude() -> f64 {
7990 0.05
7991}
7992
7993impl Default for StatisticalDriftLabelingSchemaConfig {
7994 fn default() -> Self {
7995 Self {
7996 enabled: true,
7997 min_magnitude_threshold: 0.05,
7998 }
7999 }
8000}
8001
8002#[derive(Debug, Clone, Serialize, Deserialize)]
8004pub struct CategoricalDriftLabelingSchemaConfig {
8005 #[serde(default = "default_true_val")]
8007 pub enabled: bool,
8008}
8009
8010impl Default for CategoricalDriftLabelingSchemaConfig {
8011 fn default() -> Self {
8012 Self { enabled: true }
8013 }
8014}
8015
8016#[derive(Debug, Clone, Serialize, Deserialize)]
8018pub struct TemporalDriftLabelingSchemaConfig {
8019 #[serde(default = "default_true_val")]
8021 pub enabled: bool,
8022}
8023
8024impl Default for TemporalDriftLabelingSchemaConfig {
8025 fn default() -> Self {
8026 Self { enabled: true }
8027 }
8028}
8029
8030#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8043pub struct EnhancedAnomalyConfig {
8044 #[serde(default)]
8046 pub enabled: bool,
8047
8048 #[serde(default)]
8050 pub rates: AnomalyRateConfig,
8051
8052 #[serde(default)]
8054 pub multi_stage_schemes: MultiStageSchemeConfig,
8055
8056 #[serde(default)]
8058 pub correlated_injection: CorrelatedInjectionConfig,
8059
8060 #[serde(default)]
8062 pub near_miss: NearMissConfig,
8063
8064 #[serde(default)]
8066 pub difficulty_classification: DifficultyClassificationConfig,
8067
8068 #[serde(default)]
8070 pub context_aware: ContextAwareConfig,
8071
8072 #[serde(default)]
8074 pub labeling: EnhancedLabelingConfig,
8075}
8076
8077#[derive(Debug, Clone, Serialize, Deserialize)]
8079pub struct AnomalyRateConfig {
8080 #[serde(default = "default_total_anomaly_rate")]
8082 pub total_rate: f64,
8083
8084 #[serde(default = "default_fraud_anomaly_rate")]
8086 pub fraud_rate: f64,
8087
8088 #[serde(default = "default_error_anomaly_rate")]
8090 pub error_rate: f64,
8091
8092 #[serde(default = "default_process_anomaly_rate")]
8094 pub process_rate: f64,
8095}
8096
8097fn default_total_anomaly_rate() -> f64 {
8098 0.03
8099}
8100fn default_fraud_anomaly_rate() -> f64 {
8101 0.01
8102}
8103fn default_error_anomaly_rate() -> f64 {
8104 0.015
8105}
8106fn default_process_anomaly_rate() -> f64 {
8107 0.005
8108}
8109
8110impl Default for AnomalyRateConfig {
8111 fn default() -> Self {
8112 Self {
8113 total_rate: default_total_anomaly_rate(),
8114 fraud_rate: default_fraud_anomaly_rate(),
8115 error_rate: default_error_anomaly_rate(),
8116 process_rate: default_process_anomaly_rate(),
8117 }
8118 }
8119}
8120
8121#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8123pub struct MultiStageSchemeConfig {
8124 #[serde(default)]
8126 pub enabled: bool,
8127
8128 #[serde(default)]
8130 pub embezzlement: EmbezzlementSchemeConfig,
8131
8132 #[serde(default)]
8134 pub revenue_manipulation: RevenueManipulationSchemeConfig,
8135
8136 #[serde(default)]
8138 pub kickback: KickbackSchemeConfig,
8139}
8140
8141#[derive(Debug, Clone, Serialize, Deserialize)]
8143pub struct EmbezzlementSchemeConfig {
8144 #[serde(default = "default_embezzlement_probability")]
8146 pub probability: f64,
8147
8148 #[serde(default)]
8150 pub testing_stage: SchemeStageConfig,
8151
8152 #[serde(default)]
8154 pub escalation_stage: SchemeStageConfig,
8155
8156 #[serde(default)]
8158 pub acceleration_stage: SchemeStageConfig,
8159
8160 #[serde(default)]
8162 pub desperation_stage: SchemeStageConfig,
8163}
8164
8165fn default_embezzlement_probability() -> f64 {
8166 0.02
8167}
8168
8169impl Default for EmbezzlementSchemeConfig {
8170 fn default() -> Self {
8171 Self {
8172 probability: default_embezzlement_probability(),
8173 testing_stage: SchemeStageConfig {
8174 duration_months: 2,
8175 amount_min: 100.0,
8176 amount_max: 500.0,
8177 transaction_count_min: 2,
8178 transaction_count_max: 5,
8179 difficulty: "hard".to_string(),
8180 },
8181 escalation_stage: SchemeStageConfig {
8182 duration_months: 6,
8183 amount_min: 500.0,
8184 amount_max: 2000.0,
8185 transaction_count_min: 3,
8186 transaction_count_max: 8,
8187 difficulty: "moderate".to_string(),
8188 },
8189 acceleration_stage: SchemeStageConfig {
8190 duration_months: 3,
8191 amount_min: 2000.0,
8192 amount_max: 10000.0,
8193 transaction_count_min: 5,
8194 transaction_count_max: 12,
8195 difficulty: "easy".to_string(),
8196 },
8197 desperation_stage: SchemeStageConfig {
8198 duration_months: 1,
8199 amount_min: 10000.0,
8200 amount_max: 50000.0,
8201 transaction_count_min: 3,
8202 transaction_count_max: 6,
8203 difficulty: "trivial".to_string(),
8204 },
8205 }
8206 }
8207}
8208
8209#[derive(Debug, Clone, Serialize, Deserialize)]
8211pub struct RevenueManipulationSchemeConfig {
8212 #[serde(default = "default_revenue_manipulation_probability")]
8214 pub probability: f64,
8215
8216 #[serde(default = "default_early_recognition_target")]
8218 pub early_recognition_target: f64,
8219
8220 #[serde(default = "default_expense_deferral_target")]
8222 pub expense_deferral_target: f64,
8223
8224 #[serde(default = "default_reserve_release_target")]
8226 pub reserve_release_target: f64,
8227
8228 #[serde(default = "default_channel_stuffing_target")]
8230 pub channel_stuffing_target: f64,
8231}
8232
8233fn default_revenue_manipulation_probability() -> f64 {
8234 0.01
8235}
8236fn default_early_recognition_target() -> f64 {
8237 0.02
8238}
8239fn default_expense_deferral_target() -> f64 {
8240 0.03
8241}
8242fn default_reserve_release_target() -> f64 {
8243 0.02
8244}
8245fn default_channel_stuffing_target() -> f64 {
8246 0.05
8247}
8248
8249impl Default for RevenueManipulationSchemeConfig {
8250 fn default() -> Self {
8251 Self {
8252 probability: default_revenue_manipulation_probability(),
8253 early_recognition_target: default_early_recognition_target(),
8254 expense_deferral_target: default_expense_deferral_target(),
8255 reserve_release_target: default_reserve_release_target(),
8256 channel_stuffing_target: default_channel_stuffing_target(),
8257 }
8258 }
8259}
8260
8261#[derive(Debug, Clone, Serialize, Deserialize)]
8263pub struct KickbackSchemeConfig {
8264 #[serde(default = "default_kickback_probability")]
8266 pub probability: f64,
8267
8268 #[serde(default = "default_kickback_inflation_min")]
8270 pub inflation_min: f64,
8271
8272 #[serde(default = "default_kickback_inflation_max")]
8274 pub inflation_max: f64,
8275
8276 #[serde(default = "default_kickback_percent")]
8278 pub kickback_percent: f64,
8279
8280 #[serde(default = "default_kickback_setup_months")]
8282 pub setup_months: u32,
8283
8284 #[serde(default = "default_kickback_operation_months")]
8286 pub operation_months: u32,
8287}
8288
8289fn default_kickback_probability() -> f64 {
8290 0.01
8291}
8292fn default_kickback_inflation_min() -> f64 {
8293 0.10
8294}
8295fn default_kickback_inflation_max() -> f64 {
8296 0.25
8297}
8298fn default_kickback_percent() -> f64 {
8299 0.50
8300}
8301fn default_kickback_setup_months() -> u32 {
8302 3
8303}
8304fn default_kickback_operation_months() -> u32 {
8305 12
8306}
8307
8308impl Default for KickbackSchemeConfig {
8309 fn default() -> Self {
8310 Self {
8311 probability: default_kickback_probability(),
8312 inflation_min: default_kickback_inflation_min(),
8313 inflation_max: default_kickback_inflation_max(),
8314 kickback_percent: default_kickback_percent(),
8315 setup_months: default_kickback_setup_months(),
8316 operation_months: default_kickback_operation_months(),
8317 }
8318 }
8319}
8320
8321#[derive(Debug, Clone, Serialize, Deserialize)]
8323pub struct SchemeStageConfig {
8324 pub duration_months: u32,
8326
8327 pub amount_min: f64,
8329
8330 pub amount_max: f64,
8332
8333 pub transaction_count_min: u32,
8335
8336 pub transaction_count_max: u32,
8338
8339 pub difficulty: String,
8341}
8342
8343impl Default for SchemeStageConfig {
8344 fn default() -> Self {
8345 Self {
8346 duration_months: 3,
8347 amount_min: 100.0,
8348 amount_max: 1000.0,
8349 transaction_count_min: 2,
8350 transaction_count_max: 10,
8351 difficulty: "moderate".to_string(),
8352 }
8353 }
8354}
8355
8356#[derive(Debug, Clone, Serialize, Deserialize)]
8358pub struct CorrelatedInjectionConfig {
8359 #[serde(default)]
8361 pub enabled: bool,
8362
8363 #[serde(default = "default_true_val")]
8365 pub fraud_concealment: bool,
8366
8367 #[serde(default = "default_true_val")]
8369 pub error_cascade: bool,
8370
8371 #[serde(default = "default_true_val")]
8373 pub temporal_clustering: bool,
8374
8375 #[serde(default)]
8377 pub temporal_clustering_config: TemporalClusteringConfig,
8378
8379 #[serde(default)]
8381 pub co_occurrence_patterns: Vec<CoOccurrencePatternConfig>,
8382}
8383
8384impl Default for CorrelatedInjectionConfig {
8385 fn default() -> Self {
8386 Self {
8387 enabled: false,
8388 fraud_concealment: true,
8389 error_cascade: true,
8390 temporal_clustering: true,
8391 temporal_clustering_config: TemporalClusteringConfig::default(),
8392 co_occurrence_patterns: Vec::new(),
8393 }
8394 }
8395}
8396
8397#[derive(Debug, Clone, Serialize, Deserialize)]
8399pub struct TemporalClusteringConfig {
8400 #[serde(default = "default_period_end_multiplier")]
8402 pub period_end_multiplier: f64,
8403
8404 #[serde(default = "default_period_end_days")]
8406 pub period_end_days: u32,
8407
8408 #[serde(default = "default_quarter_end_multiplier")]
8410 pub quarter_end_multiplier: f64,
8411
8412 #[serde(default = "default_year_end_multiplier")]
8414 pub year_end_multiplier: f64,
8415}
8416
8417fn default_period_end_multiplier() -> f64 {
8418 2.5
8419}
8420fn default_period_end_days() -> u32 {
8421 5
8422}
8423fn default_quarter_end_multiplier() -> f64 {
8424 1.5
8425}
8426fn default_year_end_multiplier() -> f64 {
8427 2.0
8428}
8429
8430impl Default for TemporalClusteringConfig {
8431 fn default() -> Self {
8432 Self {
8433 period_end_multiplier: default_period_end_multiplier(),
8434 period_end_days: default_period_end_days(),
8435 quarter_end_multiplier: default_quarter_end_multiplier(),
8436 year_end_multiplier: default_year_end_multiplier(),
8437 }
8438 }
8439}
8440
8441#[derive(Debug, Clone, Serialize, Deserialize)]
8443pub struct CoOccurrencePatternConfig {
8444 pub name: String,
8446
8447 pub primary_type: String,
8449
8450 pub correlated: Vec<CorrelatedAnomalyConfig>,
8452}
8453
8454#[derive(Debug, Clone, Serialize, Deserialize)]
8456pub struct CorrelatedAnomalyConfig {
8457 pub anomaly_type: String,
8459
8460 pub probability: f64,
8462
8463 pub lag_days_min: i32,
8465
8466 pub lag_days_max: i32,
8468}
8469
8470#[derive(Debug, Clone, Serialize, Deserialize)]
8472pub struct NearMissConfig {
8473 #[serde(default)]
8475 pub enabled: bool,
8476
8477 #[serde(default = "default_near_miss_proportion")]
8479 pub proportion: f64,
8480
8481 #[serde(default = "default_true_val")]
8483 pub near_duplicate: bool,
8484
8485 #[serde(default)]
8487 pub near_duplicate_days: NearDuplicateDaysConfig,
8488
8489 #[serde(default = "default_true_val")]
8491 pub threshold_proximity: bool,
8492
8493 #[serde(default)]
8495 pub threshold_proximity_range: ThresholdProximityRangeConfig,
8496
8497 #[serde(default = "default_true_val")]
8499 pub unusual_legitimate: bool,
8500
8501 #[serde(default = "default_unusual_legitimate_types")]
8503 pub unusual_legitimate_types: Vec<String>,
8504
8505 #[serde(default = "default_true_val")]
8507 pub corrected_errors: bool,
8508
8509 #[serde(default)]
8511 pub corrected_error_lag: CorrectedErrorLagConfig,
8512}
8513
8514fn default_near_miss_proportion() -> f64 {
8515 0.30
8516}
8517
8518fn default_unusual_legitimate_types() -> Vec<String> {
8519 vec![
8520 "year_end_bonus".to_string(),
8521 "contract_prepayment".to_string(),
8522 "insurance_claim".to_string(),
8523 "settlement_payment".to_string(),
8524 ]
8525}
8526
8527impl Default for NearMissConfig {
8528 fn default() -> Self {
8529 Self {
8530 enabled: false,
8531 proportion: default_near_miss_proportion(),
8532 near_duplicate: true,
8533 near_duplicate_days: NearDuplicateDaysConfig::default(),
8534 threshold_proximity: true,
8535 threshold_proximity_range: ThresholdProximityRangeConfig::default(),
8536 unusual_legitimate: true,
8537 unusual_legitimate_types: default_unusual_legitimate_types(),
8538 corrected_errors: true,
8539 corrected_error_lag: CorrectedErrorLagConfig::default(),
8540 }
8541 }
8542}
8543
8544#[derive(Debug, Clone, Serialize, Deserialize)]
8546pub struct NearDuplicateDaysConfig {
8547 #[serde(default = "default_near_duplicate_min")]
8549 pub min: u32,
8550
8551 #[serde(default = "default_near_duplicate_max")]
8553 pub max: u32,
8554}
8555
8556fn default_near_duplicate_min() -> u32 {
8557 1
8558}
8559fn default_near_duplicate_max() -> u32 {
8560 3
8561}
8562
8563impl Default for NearDuplicateDaysConfig {
8564 fn default() -> Self {
8565 Self {
8566 min: default_near_duplicate_min(),
8567 max: default_near_duplicate_max(),
8568 }
8569 }
8570}
8571
8572#[derive(Debug, Clone, Serialize, Deserialize)]
8574pub struct ThresholdProximityRangeConfig {
8575 #[serde(default = "default_threshold_proximity_min")]
8577 pub min: f64,
8578
8579 #[serde(default = "default_threshold_proximity_max")]
8581 pub max: f64,
8582}
8583
8584fn default_threshold_proximity_min() -> f64 {
8585 0.90
8586}
8587fn default_threshold_proximity_max() -> f64 {
8588 0.99
8589}
8590
8591impl Default for ThresholdProximityRangeConfig {
8592 fn default() -> Self {
8593 Self {
8594 min: default_threshold_proximity_min(),
8595 max: default_threshold_proximity_max(),
8596 }
8597 }
8598}
8599
8600#[derive(Debug, Clone, Serialize, Deserialize)]
8602pub struct CorrectedErrorLagConfig {
8603 #[serde(default = "default_corrected_error_lag_min")]
8605 pub min: u32,
8606
8607 #[serde(default = "default_corrected_error_lag_max")]
8609 pub max: u32,
8610}
8611
8612fn default_corrected_error_lag_min() -> u32 {
8613 1
8614}
8615fn default_corrected_error_lag_max() -> u32 {
8616 5
8617}
8618
8619impl Default for CorrectedErrorLagConfig {
8620 fn default() -> Self {
8621 Self {
8622 min: default_corrected_error_lag_min(),
8623 max: default_corrected_error_lag_max(),
8624 }
8625 }
8626}
8627
8628#[derive(Debug, Clone, Serialize, Deserialize)]
8630pub struct DifficultyClassificationConfig {
8631 #[serde(default)]
8633 pub enabled: bool,
8634
8635 #[serde(default)]
8637 pub target_distribution: DifficultyDistributionConfig,
8638}
8639
8640impl Default for DifficultyClassificationConfig {
8641 fn default() -> Self {
8642 Self {
8643 enabled: true,
8644 target_distribution: DifficultyDistributionConfig::default(),
8645 }
8646 }
8647}
8648
8649#[derive(Debug, Clone, Serialize, Deserialize)]
8651pub struct DifficultyDistributionConfig {
8652 #[serde(default = "default_difficulty_trivial")]
8654 pub trivial: f64,
8655
8656 #[serde(default = "default_difficulty_easy")]
8658 pub easy: f64,
8659
8660 #[serde(default = "default_difficulty_moderate")]
8662 pub moderate: f64,
8663
8664 #[serde(default = "default_difficulty_hard")]
8666 pub hard: f64,
8667
8668 #[serde(default = "default_difficulty_expert")]
8670 pub expert: f64,
8671}
8672
8673fn default_difficulty_trivial() -> f64 {
8674 0.15
8675}
8676fn default_difficulty_easy() -> f64 {
8677 0.25
8678}
8679fn default_difficulty_moderate() -> f64 {
8680 0.30
8681}
8682fn default_difficulty_hard() -> f64 {
8683 0.20
8684}
8685fn default_difficulty_expert() -> f64 {
8686 0.10
8687}
8688
8689impl Default for DifficultyDistributionConfig {
8690 fn default() -> Self {
8691 Self {
8692 trivial: default_difficulty_trivial(),
8693 easy: default_difficulty_easy(),
8694 moderate: default_difficulty_moderate(),
8695 hard: default_difficulty_hard(),
8696 expert: default_difficulty_expert(),
8697 }
8698 }
8699}
8700
8701#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8703pub struct ContextAwareConfig {
8704 #[serde(default)]
8706 pub enabled: bool,
8707
8708 #[serde(default)]
8710 pub vendor_rules: VendorAnomalyRulesConfig,
8711
8712 #[serde(default)]
8714 pub employee_rules: EmployeeAnomalyRulesConfig,
8715
8716 #[serde(default)]
8718 pub account_rules: AccountAnomalyRulesConfig,
8719
8720 #[serde(default)]
8722 pub behavioral_baseline: BehavioralBaselineConfig,
8723}
8724
8725#[derive(Debug, Clone, Serialize, Deserialize)]
8727pub struct VendorAnomalyRulesConfig {
8728 #[serde(default = "default_new_vendor_multiplier")]
8730 pub new_vendor_error_multiplier: f64,
8731
8732 #[serde(default = "default_new_vendor_threshold")]
8734 pub new_vendor_threshold_days: u32,
8735
8736 #[serde(default = "default_international_multiplier")]
8738 pub international_error_multiplier: f64,
8739
8740 #[serde(default = "default_strategic_vendor_types")]
8742 pub strategic_vendor_anomaly_types: Vec<String>,
8743}
8744
8745fn default_new_vendor_multiplier() -> f64 {
8746 2.5
8747}
8748fn default_new_vendor_threshold() -> u32 {
8749 90
8750}
8751fn default_international_multiplier() -> f64 {
8752 1.5
8753}
8754fn default_strategic_vendor_types() -> Vec<String> {
8755 vec![
8756 "pricing_dispute".to_string(),
8757 "contract_violation".to_string(),
8758 ]
8759}
8760
8761impl Default for VendorAnomalyRulesConfig {
8762 fn default() -> Self {
8763 Self {
8764 new_vendor_error_multiplier: default_new_vendor_multiplier(),
8765 new_vendor_threshold_days: default_new_vendor_threshold(),
8766 international_error_multiplier: default_international_multiplier(),
8767 strategic_vendor_anomaly_types: default_strategic_vendor_types(),
8768 }
8769 }
8770}
8771
8772#[derive(Debug, Clone, Serialize, Deserialize)]
8774pub struct EmployeeAnomalyRulesConfig {
8775 #[serde(default = "default_new_employee_rate")]
8777 pub new_employee_error_rate: f64,
8778
8779 #[serde(default = "default_new_employee_threshold")]
8781 pub new_employee_threshold_days: u32,
8782
8783 #[serde(default = "default_volume_fatigue_threshold")]
8785 pub volume_fatigue_threshold: u32,
8786
8787 #[serde(default = "default_coverage_multiplier")]
8789 pub coverage_error_multiplier: f64,
8790}
8791
8792fn default_new_employee_rate() -> f64 {
8793 0.05
8794}
8795fn default_new_employee_threshold() -> u32 {
8796 180
8797}
8798fn default_volume_fatigue_threshold() -> u32 {
8799 50
8800}
8801fn default_coverage_multiplier() -> f64 {
8802 1.8
8803}
8804
8805impl Default for EmployeeAnomalyRulesConfig {
8806 fn default() -> Self {
8807 Self {
8808 new_employee_error_rate: default_new_employee_rate(),
8809 new_employee_threshold_days: default_new_employee_threshold(),
8810 volume_fatigue_threshold: default_volume_fatigue_threshold(),
8811 coverage_error_multiplier: default_coverage_multiplier(),
8812 }
8813 }
8814}
8815
8816#[derive(Debug, Clone, Serialize, Deserialize)]
8818pub struct AccountAnomalyRulesConfig {
8819 #[serde(default = "default_high_risk_multiplier")]
8821 pub high_risk_account_multiplier: f64,
8822
8823 #[serde(default = "default_high_risk_accounts")]
8825 pub high_risk_accounts: Vec<String>,
8826
8827 #[serde(default = "default_suspense_multiplier")]
8829 pub suspense_account_multiplier: f64,
8830
8831 #[serde(default = "default_suspense_accounts")]
8833 pub suspense_accounts: Vec<String>,
8834
8835 #[serde(default = "default_intercompany_multiplier")]
8837 pub intercompany_account_multiplier: f64,
8838}
8839
8840fn default_high_risk_multiplier() -> f64 {
8841 2.0
8842}
8843fn default_high_risk_accounts() -> Vec<String> {
8844 vec![
8845 "1100".to_string(), "2000".to_string(), "3000".to_string(), ]
8849}
8850fn default_suspense_multiplier() -> f64 {
8851 3.0
8852}
8853fn default_suspense_accounts() -> Vec<String> {
8854 vec!["9999".to_string(), "9998".to_string()]
8855}
8856fn default_intercompany_multiplier() -> f64 {
8857 1.5
8858}
8859
8860impl Default for AccountAnomalyRulesConfig {
8861 fn default() -> Self {
8862 Self {
8863 high_risk_account_multiplier: default_high_risk_multiplier(),
8864 high_risk_accounts: default_high_risk_accounts(),
8865 suspense_account_multiplier: default_suspense_multiplier(),
8866 suspense_accounts: default_suspense_accounts(),
8867 intercompany_account_multiplier: default_intercompany_multiplier(),
8868 }
8869 }
8870}
8871
8872#[derive(Debug, Clone, Serialize, Deserialize)]
8874pub struct BehavioralBaselineConfig {
8875 #[serde(default)]
8877 pub enabled: bool,
8878
8879 #[serde(default = "default_baseline_period")]
8881 pub baseline_period_days: u32,
8882
8883 #[serde(default = "default_deviation_threshold")]
8885 pub deviation_threshold_std: f64,
8886
8887 #[serde(default = "default_frequency_deviation")]
8889 pub frequency_deviation_threshold: f64,
8890}
8891
8892fn default_baseline_period() -> u32 {
8893 90
8894}
8895fn default_deviation_threshold() -> f64 {
8896 3.0
8897}
8898fn default_frequency_deviation() -> f64 {
8899 2.0
8900}
8901
8902impl Default for BehavioralBaselineConfig {
8903 fn default() -> Self {
8904 Self {
8905 enabled: false,
8906 baseline_period_days: default_baseline_period(),
8907 deviation_threshold_std: default_deviation_threshold(),
8908 frequency_deviation_threshold: default_frequency_deviation(),
8909 }
8910 }
8911}
8912
8913#[derive(Debug, Clone, Serialize, Deserialize)]
8915pub struct EnhancedLabelingConfig {
8916 #[serde(default = "default_true_val")]
8918 pub severity_scoring: bool,
8919
8920 #[serde(default = "default_true_val")]
8922 pub difficulty_classification: bool,
8923
8924 #[serde(default)]
8926 pub materiality_thresholds: MaterialityThresholdsConfig,
8927}
8928
8929impl Default for EnhancedLabelingConfig {
8930 fn default() -> Self {
8931 Self {
8932 severity_scoring: true,
8933 difficulty_classification: true,
8934 materiality_thresholds: MaterialityThresholdsConfig::default(),
8935 }
8936 }
8937}
8938
8939#[derive(Debug, Clone, Serialize, Deserialize)]
8941pub struct MaterialityThresholdsConfig {
8942 #[serde(default = "default_materiality_trivial")]
8944 pub trivial: f64,
8945
8946 #[serde(default = "default_materiality_immaterial")]
8948 pub immaterial: f64,
8949
8950 #[serde(default = "default_materiality_material")]
8952 pub material: f64,
8953
8954 #[serde(default = "default_materiality_highly_material")]
8956 pub highly_material: f64,
8957}
8958
8959fn default_materiality_trivial() -> f64 {
8960 0.001
8961}
8962fn default_materiality_immaterial() -> f64 {
8963 0.01
8964}
8965fn default_materiality_material() -> f64 {
8966 0.05
8967}
8968fn default_materiality_highly_material() -> f64 {
8969 0.10
8970}
8971
8972impl Default for MaterialityThresholdsConfig {
8973 fn default() -> Self {
8974 Self {
8975 trivial: default_materiality_trivial(),
8976 immaterial: default_materiality_immaterial(),
8977 material: default_materiality_material(),
8978 highly_material: default_materiality_highly_material(),
8979 }
8980 }
8981}
8982
8983#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8995pub struct IndustrySpecificConfig {
8996 #[serde(default)]
8998 pub enabled: bool,
8999
9000 #[serde(default)]
9002 pub manufacturing: ManufacturingConfig,
9003
9004 #[serde(default)]
9006 pub retail: RetailConfig,
9007
9008 #[serde(default)]
9010 pub healthcare: HealthcareConfig,
9011
9012 #[serde(default)]
9014 pub technology: TechnologyConfig,
9015
9016 #[serde(default)]
9018 pub financial_services: FinancialServicesConfig,
9019
9020 #[serde(default)]
9022 pub professional_services: ProfessionalServicesConfig,
9023}
9024
9025#[derive(Debug, Clone, Serialize, Deserialize)]
9027pub struct ManufacturingConfig {
9028 #[serde(default)]
9030 pub enabled: bool,
9031
9032 #[serde(default = "default_bom_depth")]
9034 pub bom_depth: u32,
9035
9036 #[serde(default)]
9038 pub just_in_time: bool,
9039
9040 #[serde(default = "default_production_order_types")]
9042 pub production_order_types: Vec<String>,
9043
9044 #[serde(default)]
9046 pub quality_framework: Option<String>,
9047
9048 #[serde(default = "default_supplier_tiers")]
9050 pub supplier_tiers: u32,
9051
9052 #[serde(default = "default_cost_frequency")]
9054 pub standard_cost_frequency: String,
9055
9056 #[serde(default = "default_yield_rate")]
9058 pub target_yield_rate: f64,
9059
9060 #[serde(default = "default_scrap_threshold")]
9062 pub scrap_alert_threshold: f64,
9063
9064 #[serde(default)]
9066 pub anomaly_rates: ManufacturingAnomalyRates,
9067}
9068
9069fn default_bom_depth() -> u32 {
9070 4
9071}
9072
9073fn default_production_order_types() -> Vec<String> {
9074 vec![
9075 "standard".to_string(),
9076 "rework".to_string(),
9077 "prototype".to_string(),
9078 ]
9079}
9080
9081fn default_supplier_tiers() -> u32 {
9082 2
9083}
9084
9085fn default_cost_frequency() -> String {
9086 "quarterly".to_string()
9087}
9088
9089fn default_yield_rate() -> f64 {
9090 0.97
9091}
9092
9093fn default_scrap_threshold() -> f64 {
9094 0.03
9095}
9096
9097impl Default for ManufacturingConfig {
9098 fn default() -> Self {
9099 Self {
9100 enabled: false,
9101 bom_depth: default_bom_depth(),
9102 just_in_time: false,
9103 production_order_types: default_production_order_types(),
9104 quality_framework: Some("ISO_9001".to_string()),
9105 supplier_tiers: default_supplier_tiers(),
9106 standard_cost_frequency: default_cost_frequency(),
9107 target_yield_rate: default_yield_rate(),
9108 scrap_alert_threshold: default_scrap_threshold(),
9109 anomaly_rates: ManufacturingAnomalyRates::default(),
9110 }
9111 }
9112}
9113
9114#[derive(Debug, Clone, Serialize, Deserialize)]
9116pub struct ManufacturingAnomalyRates {
9117 #[serde(default = "default_mfg_yield_rate")]
9119 pub yield_manipulation: f64,
9120
9121 #[serde(default = "default_mfg_labor_rate")]
9123 pub labor_misallocation: f64,
9124
9125 #[serde(default = "default_mfg_phantom_rate")]
9127 pub phantom_production: f64,
9128
9129 #[serde(default = "default_mfg_cost_rate")]
9131 pub standard_cost_manipulation: f64,
9132
9133 #[serde(default = "default_mfg_inventory_rate")]
9135 pub inventory_fraud: f64,
9136}
9137
9138fn default_mfg_yield_rate() -> f64 {
9139 0.015
9140}
9141
9142fn default_mfg_labor_rate() -> f64 {
9143 0.02
9144}
9145
9146fn default_mfg_phantom_rate() -> f64 {
9147 0.005
9148}
9149
9150fn default_mfg_cost_rate() -> f64 {
9151 0.01
9152}
9153
9154fn default_mfg_inventory_rate() -> f64 {
9155 0.008
9156}
9157
9158impl Default for ManufacturingAnomalyRates {
9159 fn default() -> Self {
9160 Self {
9161 yield_manipulation: default_mfg_yield_rate(),
9162 labor_misallocation: default_mfg_labor_rate(),
9163 phantom_production: default_mfg_phantom_rate(),
9164 standard_cost_manipulation: default_mfg_cost_rate(),
9165 inventory_fraud: default_mfg_inventory_rate(),
9166 }
9167 }
9168}
9169
9170#[derive(Debug, Clone, Serialize, Deserialize)]
9172pub struct RetailConfig {
9173 #[serde(default)]
9175 pub enabled: bool,
9176
9177 #[serde(default)]
9179 pub store_types: RetailStoreTypeConfig,
9180
9181 #[serde(default = "default_retail_daily_txns")]
9183 pub avg_daily_transactions: u32,
9184
9185 #[serde(default = "default_true")]
9187 pub loss_prevention: bool,
9188
9189 #[serde(default = "default_shrinkage_rate")]
9191 pub shrinkage_rate: f64,
9192
9193 #[serde(default)]
9195 pub anomaly_rates: RetailAnomalyRates,
9196}
9197
9198fn default_retail_daily_txns() -> u32 {
9199 500
9200}
9201
9202fn default_shrinkage_rate() -> f64 {
9203 0.015
9204}
9205
9206impl Default for RetailConfig {
9207 fn default() -> Self {
9208 Self {
9209 enabled: false,
9210 store_types: RetailStoreTypeConfig::default(),
9211 avg_daily_transactions: default_retail_daily_txns(),
9212 loss_prevention: true,
9213 shrinkage_rate: default_shrinkage_rate(),
9214 anomaly_rates: RetailAnomalyRates::default(),
9215 }
9216 }
9217}
9218
9219#[derive(Debug, Clone, Serialize, Deserialize)]
9221pub struct RetailStoreTypeConfig {
9222 #[serde(default = "default_flagship_pct")]
9224 pub flagship: f64,
9225
9226 #[serde(default = "default_regional_pct")]
9228 pub regional: f64,
9229
9230 #[serde(default = "default_outlet_pct")]
9232 pub outlet: f64,
9233
9234 #[serde(default = "default_ecommerce_pct")]
9236 pub ecommerce: f64,
9237}
9238
9239fn default_flagship_pct() -> f64 {
9240 0.10
9241}
9242
9243fn default_regional_pct() -> f64 {
9244 0.50
9245}
9246
9247fn default_outlet_pct() -> f64 {
9248 0.25
9249}
9250
9251fn default_ecommerce_pct() -> f64 {
9252 0.15
9253}
9254
9255impl Default for RetailStoreTypeConfig {
9256 fn default() -> Self {
9257 Self {
9258 flagship: default_flagship_pct(),
9259 regional: default_regional_pct(),
9260 outlet: default_outlet_pct(),
9261 ecommerce: default_ecommerce_pct(),
9262 }
9263 }
9264}
9265
9266#[derive(Debug, Clone, Serialize, Deserialize)]
9268pub struct RetailAnomalyRates {
9269 #[serde(default = "default_sweethearting_rate")]
9271 pub sweethearting: f64,
9272
9273 #[serde(default = "default_skimming_rate")]
9275 pub skimming: f64,
9276
9277 #[serde(default = "default_refund_fraud_rate")]
9279 pub refund_fraud: f64,
9280
9281 #[serde(default = "default_void_abuse_rate")]
9283 pub void_abuse: f64,
9284
9285 #[serde(default = "default_gift_card_rate")]
9287 pub gift_card_fraud: f64,
9288
9289 #[serde(default = "default_retail_kickback_rate")]
9291 pub vendor_kickback: f64,
9292}
9293
9294fn default_sweethearting_rate() -> f64 {
9295 0.02
9296}
9297
9298fn default_skimming_rate() -> f64 {
9299 0.005
9300}
9301
9302fn default_refund_fraud_rate() -> f64 {
9303 0.015
9304}
9305
9306fn default_void_abuse_rate() -> f64 {
9307 0.01
9308}
9309
9310fn default_gift_card_rate() -> f64 {
9311 0.008
9312}
9313
9314fn default_retail_kickback_rate() -> f64 {
9315 0.003
9316}
9317
9318impl Default for RetailAnomalyRates {
9319 fn default() -> Self {
9320 Self {
9321 sweethearting: default_sweethearting_rate(),
9322 skimming: default_skimming_rate(),
9323 refund_fraud: default_refund_fraud_rate(),
9324 void_abuse: default_void_abuse_rate(),
9325 gift_card_fraud: default_gift_card_rate(),
9326 vendor_kickback: default_retail_kickback_rate(),
9327 }
9328 }
9329}
9330
9331#[derive(Debug, Clone, Serialize, Deserialize)]
9333pub struct HealthcareConfig {
9334 #[serde(default)]
9336 pub enabled: bool,
9337
9338 #[serde(default = "default_facility_type")]
9340 pub facility_type: String,
9341
9342 #[serde(default)]
9344 pub payer_mix: HealthcarePayerMix,
9345
9346 #[serde(default)]
9348 pub coding_systems: HealthcareCodingSystems,
9349
9350 #[serde(default)]
9352 pub compliance: HealthcareComplianceConfig,
9353
9354 #[serde(default = "default_daily_encounters")]
9356 pub avg_daily_encounters: u32,
9357
9358 #[serde(default = "default_charges_per_encounter")]
9360 pub avg_charges_per_encounter: u32,
9361
9362 #[serde(default = "default_hc_denial_rate")]
9364 pub denial_rate: f64,
9365
9366 #[serde(default = "default_hc_bad_debt_rate")]
9368 pub bad_debt_rate: f64,
9369
9370 #[serde(default = "default_hc_charity_care_rate")]
9372 pub charity_care_rate: f64,
9373
9374 #[serde(default)]
9376 pub anomaly_rates: HealthcareAnomalyRates,
9377}
9378
9379fn default_facility_type() -> String {
9380 "hospital".to_string()
9381}
9382
9383fn default_daily_encounters() -> u32 {
9384 150
9385}
9386
9387fn default_charges_per_encounter() -> u32 {
9388 8
9389}
9390
9391fn default_hc_denial_rate() -> f64 {
9392 0.05
9393}
9394
9395fn default_hc_bad_debt_rate() -> f64 {
9396 0.03
9397}
9398
9399fn default_hc_charity_care_rate() -> f64 {
9400 0.02
9401}
9402
9403impl Default for HealthcareConfig {
9404 fn default() -> Self {
9405 Self {
9406 enabled: false,
9407 facility_type: default_facility_type(),
9408 payer_mix: HealthcarePayerMix::default(),
9409 coding_systems: HealthcareCodingSystems::default(),
9410 compliance: HealthcareComplianceConfig::default(),
9411 avg_daily_encounters: default_daily_encounters(),
9412 avg_charges_per_encounter: default_charges_per_encounter(),
9413 denial_rate: default_hc_denial_rate(),
9414 bad_debt_rate: default_hc_bad_debt_rate(),
9415 charity_care_rate: default_hc_charity_care_rate(),
9416 anomaly_rates: HealthcareAnomalyRates::default(),
9417 }
9418 }
9419}
9420
9421#[derive(Debug, Clone, Serialize, Deserialize)]
9423pub struct HealthcarePayerMix {
9424 #[serde(default = "default_medicare_pct")]
9426 pub medicare: f64,
9427
9428 #[serde(default = "default_medicaid_pct")]
9430 pub medicaid: f64,
9431
9432 #[serde(default = "default_commercial_pct")]
9434 pub commercial: f64,
9435
9436 #[serde(default = "default_self_pay_pct")]
9438 pub self_pay: f64,
9439}
9440
9441fn default_medicare_pct() -> f64 {
9442 0.40
9443}
9444
9445fn default_medicaid_pct() -> f64 {
9446 0.20
9447}
9448
9449fn default_commercial_pct() -> f64 {
9450 0.30
9451}
9452
9453fn default_self_pay_pct() -> f64 {
9454 0.10
9455}
9456
9457impl Default for HealthcarePayerMix {
9458 fn default() -> Self {
9459 Self {
9460 medicare: default_medicare_pct(),
9461 medicaid: default_medicaid_pct(),
9462 commercial: default_commercial_pct(),
9463 self_pay: default_self_pay_pct(),
9464 }
9465 }
9466}
9467
9468#[derive(Debug, Clone, Serialize, Deserialize)]
9470pub struct HealthcareCodingSystems {
9471 #[serde(default = "default_true")]
9473 pub icd10: bool,
9474
9475 #[serde(default = "default_true")]
9477 pub cpt: bool,
9478
9479 #[serde(default = "default_true")]
9481 pub drg: bool,
9482
9483 #[serde(default = "default_true")]
9485 pub hcpcs: bool,
9486
9487 #[serde(default = "default_true")]
9489 pub revenue_codes: bool,
9490}
9491
9492impl Default for HealthcareCodingSystems {
9493 fn default() -> Self {
9494 Self {
9495 icd10: true,
9496 cpt: true,
9497 drg: true,
9498 hcpcs: true,
9499 revenue_codes: true,
9500 }
9501 }
9502}
9503
9504#[derive(Debug, Clone, Serialize, Deserialize)]
9506pub struct HealthcareComplianceConfig {
9507 #[serde(default = "default_true")]
9509 pub hipaa: bool,
9510
9511 #[serde(default = "default_true")]
9513 pub stark_law: bool,
9514
9515 #[serde(default = "default_true")]
9517 pub anti_kickback: bool,
9518
9519 #[serde(default = "default_true")]
9521 pub false_claims_act: bool,
9522
9523 #[serde(default = "default_true")]
9525 pub emtala: bool,
9526}
9527
9528impl Default for HealthcareComplianceConfig {
9529 fn default() -> Self {
9530 Self {
9531 hipaa: true,
9532 stark_law: true,
9533 anti_kickback: true,
9534 false_claims_act: true,
9535 emtala: true,
9536 }
9537 }
9538}
9539
9540#[derive(Debug, Clone, Serialize, Deserialize)]
9542pub struct HealthcareAnomalyRates {
9543 #[serde(default = "default_upcoding_rate")]
9545 pub upcoding: f64,
9546
9547 #[serde(default = "default_unbundling_rate")]
9549 pub unbundling: f64,
9550
9551 #[serde(default = "default_phantom_billing_rate")]
9553 pub phantom_billing: f64,
9554
9555 #[serde(default = "default_healthcare_kickback_rate")]
9557 pub kickbacks: f64,
9558
9559 #[serde(default = "default_duplicate_billing_rate")]
9561 pub duplicate_billing: f64,
9562
9563 #[serde(default = "default_med_necessity_rate")]
9565 pub medical_necessity_abuse: f64,
9566}
9567
9568fn default_upcoding_rate() -> f64 {
9569 0.02
9570}
9571
9572fn default_unbundling_rate() -> f64 {
9573 0.015
9574}
9575
9576fn default_phantom_billing_rate() -> f64 {
9577 0.005
9578}
9579
9580fn default_healthcare_kickback_rate() -> f64 {
9581 0.003
9582}
9583
9584fn default_duplicate_billing_rate() -> f64 {
9585 0.008
9586}
9587
9588fn default_med_necessity_rate() -> f64 {
9589 0.01
9590}
9591
9592impl Default for HealthcareAnomalyRates {
9593 fn default() -> Self {
9594 Self {
9595 upcoding: default_upcoding_rate(),
9596 unbundling: default_unbundling_rate(),
9597 phantom_billing: default_phantom_billing_rate(),
9598 kickbacks: default_healthcare_kickback_rate(),
9599 duplicate_billing: default_duplicate_billing_rate(),
9600 medical_necessity_abuse: default_med_necessity_rate(),
9601 }
9602 }
9603}
9604
9605#[derive(Debug, Clone, Serialize, Deserialize)]
9607pub struct TechnologyConfig {
9608 #[serde(default)]
9610 pub enabled: bool,
9611
9612 #[serde(default = "default_revenue_model")]
9614 pub revenue_model: String,
9615
9616 #[serde(default = "default_subscription_pct")]
9618 pub subscription_revenue_pct: f64,
9619
9620 #[serde(default = "default_license_pct")]
9622 pub license_revenue_pct: f64,
9623
9624 #[serde(default = "default_services_pct")]
9626 pub services_revenue_pct: f64,
9627
9628 #[serde(default)]
9630 pub rd_capitalization: RdCapitalizationConfig,
9631
9632 #[serde(default)]
9634 pub anomaly_rates: TechnologyAnomalyRates,
9635}
9636
9637fn default_revenue_model() -> String {
9638 "saas".to_string()
9639}
9640
9641fn default_subscription_pct() -> f64 {
9642 0.60
9643}
9644
9645fn default_license_pct() -> f64 {
9646 0.25
9647}
9648
9649fn default_services_pct() -> f64 {
9650 0.15
9651}
9652
9653impl Default for TechnologyConfig {
9654 fn default() -> Self {
9655 Self {
9656 enabled: false,
9657 revenue_model: default_revenue_model(),
9658 subscription_revenue_pct: default_subscription_pct(),
9659 license_revenue_pct: default_license_pct(),
9660 services_revenue_pct: default_services_pct(),
9661 rd_capitalization: RdCapitalizationConfig::default(),
9662 anomaly_rates: TechnologyAnomalyRates::default(),
9663 }
9664 }
9665}
9666
9667#[derive(Debug, Clone, Serialize, Deserialize)]
9669pub struct RdCapitalizationConfig {
9670 #[serde(default = "default_true")]
9672 pub enabled: bool,
9673
9674 #[serde(default = "default_cap_rate")]
9676 pub capitalization_rate: f64,
9677
9678 #[serde(default = "default_useful_life")]
9680 pub useful_life_years: u32,
9681}
9682
9683fn default_cap_rate() -> f64 {
9684 0.30
9685}
9686
9687fn default_useful_life() -> u32 {
9688 3
9689}
9690
9691impl Default for RdCapitalizationConfig {
9692 fn default() -> Self {
9693 Self {
9694 enabled: true,
9695 capitalization_rate: default_cap_rate(),
9696 useful_life_years: default_useful_life(),
9697 }
9698 }
9699}
9700
9701#[derive(Debug, Clone, Serialize, Deserialize)]
9703pub struct TechnologyAnomalyRates {
9704 #[serde(default = "default_premature_rev_rate")]
9706 pub premature_revenue: f64,
9707
9708 #[serde(default = "default_side_letter_rate")]
9710 pub side_letter_abuse: f64,
9711
9712 #[serde(default = "default_channel_stuffing_rate")]
9714 pub channel_stuffing: f64,
9715
9716 #[serde(default = "default_improper_cap_rate")]
9718 pub improper_capitalization: f64,
9719}
9720
9721fn default_premature_rev_rate() -> f64 {
9722 0.015
9723}
9724
9725fn default_side_letter_rate() -> f64 {
9726 0.008
9727}
9728
9729fn default_channel_stuffing_rate() -> f64 {
9730 0.01
9731}
9732
9733fn default_improper_cap_rate() -> f64 {
9734 0.012
9735}
9736
9737impl Default for TechnologyAnomalyRates {
9738 fn default() -> Self {
9739 Self {
9740 premature_revenue: default_premature_rev_rate(),
9741 side_letter_abuse: default_side_letter_rate(),
9742 channel_stuffing: default_channel_stuffing_rate(),
9743 improper_capitalization: default_improper_cap_rate(),
9744 }
9745 }
9746}
9747
9748#[derive(Debug, Clone, Serialize, Deserialize)]
9750pub struct FinancialServicesConfig {
9751 #[serde(default)]
9753 pub enabled: bool,
9754
9755 #[serde(default = "default_fi_type")]
9757 pub institution_type: String,
9758
9759 #[serde(default = "default_fi_regulatory")]
9761 pub regulatory_framework: String,
9762
9763 #[serde(default)]
9765 pub anomaly_rates: FinancialServicesAnomalyRates,
9766}
9767
9768fn default_fi_type() -> String {
9769 "commercial_bank".to_string()
9770}
9771
9772fn default_fi_regulatory() -> String {
9773 "us_banking".to_string()
9774}
9775
9776impl Default for FinancialServicesConfig {
9777 fn default() -> Self {
9778 Self {
9779 enabled: false,
9780 institution_type: default_fi_type(),
9781 regulatory_framework: default_fi_regulatory(),
9782 anomaly_rates: FinancialServicesAnomalyRates::default(),
9783 }
9784 }
9785}
9786
9787#[derive(Debug, Clone, Serialize, Deserialize)]
9789pub struct FinancialServicesAnomalyRates {
9790 #[serde(default = "default_loan_fraud_rate")]
9792 pub loan_fraud: f64,
9793
9794 #[serde(default = "default_trading_fraud_rate")]
9796 pub trading_fraud: f64,
9797
9798 #[serde(default = "default_insurance_fraud_rate")]
9800 pub insurance_fraud: f64,
9801
9802 #[serde(default = "default_account_manip_rate")]
9804 pub account_manipulation: f64,
9805}
9806
9807fn default_loan_fraud_rate() -> f64 {
9808 0.01
9809}
9810
9811fn default_trading_fraud_rate() -> f64 {
9812 0.008
9813}
9814
9815fn default_insurance_fraud_rate() -> f64 {
9816 0.012
9817}
9818
9819fn default_account_manip_rate() -> f64 {
9820 0.005
9821}
9822
9823impl Default for FinancialServicesAnomalyRates {
9824 fn default() -> Self {
9825 Self {
9826 loan_fraud: default_loan_fraud_rate(),
9827 trading_fraud: default_trading_fraud_rate(),
9828 insurance_fraud: default_insurance_fraud_rate(),
9829 account_manipulation: default_account_manip_rate(),
9830 }
9831 }
9832}
9833
9834#[derive(Debug, Clone, Serialize, Deserialize)]
9836pub struct ProfessionalServicesConfig {
9837 #[serde(default)]
9839 pub enabled: bool,
9840
9841 #[serde(default = "default_firm_type")]
9843 pub firm_type: String,
9844
9845 #[serde(default = "default_billing_model")]
9847 pub billing_model: String,
9848
9849 #[serde(default = "default_hourly_rate")]
9851 pub avg_hourly_rate: f64,
9852
9853 #[serde(default)]
9855 pub trust_accounting: TrustAccountingConfig,
9856
9857 #[serde(default)]
9859 pub anomaly_rates: ProfessionalServicesAnomalyRates,
9860}
9861
9862fn default_firm_type() -> String {
9863 "consulting".to_string()
9864}
9865
9866fn default_billing_model() -> String {
9867 "time_and_materials".to_string()
9868}
9869
9870fn default_hourly_rate() -> f64 {
9871 250.0
9872}
9873
9874impl Default for ProfessionalServicesConfig {
9875 fn default() -> Self {
9876 Self {
9877 enabled: false,
9878 firm_type: default_firm_type(),
9879 billing_model: default_billing_model(),
9880 avg_hourly_rate: default_hourly_rate(),
9881 trust_accounting: TrustAccountingConfig::default(),
9882 anomaly_rates: ProfessionalServicesAnomalyRates::default(),
9883 }
9884 }
9885}
9886
9887#[derive(Debug, Clone, Serialize, Deserialize)]
9889pub struct TrustAccountingConfig {
9890 #[serde(default)]
9892 pub enabled: bool,
9893
9894 #[serde(default = "default_true")]
9896 pub require_three_way_reconciliation: bool,
9897}
9898
9899impl Default for TrustAccountingConfig {
9900 fn default() -> Self {
9901 Self {
9902 enabled: false,
9903 require_three_way_reconciliation: true,
9904 }
9905 }
9906}
9907
9908#[derive(Debug, Clone, Serialize, Deserialize)]
9910pub struct ProfessionalServicesAnomalyRates {
9911 #[serde(default = "default_time_fraud_rate")]
9913 pub time_billing_fraud: f64,
9914
9915 #[serde(default = "default_expense_fraud_rate")]
9917 pub expense_fraud: f64,
9918
9919 #[serde(default = "default_trust_misappropriation_rate")]
9921 pub trust_misappropriation: f64,
9922}
9923
9924fn default_time_fraud_rate() -> f64 {
9925 0.02
9926}
9927
9928fn default_expense_fraud_rate() -> f64 {
9929 0.015
9930}
9931
9932fn default_trust_misappropriation_rate() -> f64 {
9933 0.003
9934}
9935
9936impl Default for ProfessionalServicesAnomalyRates {
9937 fn default() -> Self {
9938 Self {
9939 time_billing_fraud: default_time_fraud_rate(),
9940 expense_fraud: default_expense_fraud_rate(),
9941 trust_misappropriation: default_trust_misappropriation_rate(),
9942 }
9943 }
9944}
9945
9946#[derive(Debug, Clone, Serialize, Deserialize)]
9960pub struct FingerprintPrivacyConfig {
9961 #[serde(default)]
9963 pub level: String,
9964 #[serde(default = "default_epsilon")]
9966 pub epsilon: f64,
9967 #[serde(default = "default_delta")]
9969 pub delta: f64,
9970 #[serde(default = "default_k_anonymity")]
9972 pub k_anonymity: u32,
9973 #[serde(default)]
9975 pub composition_method: String,
9976}
9977
9978fn default_epsilon() -> f64 {
9979 1.0
9980}
9981
9982fn default_delta() -> f64 {
9983 1e-5
9984}
9985
9986fn default_k_anonymity() -> u32 {
9987 5
9988}
9989
9990impl Default for FingerprintPrivacyConfig {
9991 fn default() -> Self {
9992 Self {
9993 level: "standard".to_string(),
9994 epsilon: default_epsilon(),
9995 delta: default_delta(),
9996 k_anonymity: default_k_anonymity(),
9997 composition_method: "naive".to_string(),
9998 }
9999 }
10000}
10001
10002#[derive(Debug, Clone, Serialize, Deserialize)]
10016pub struct QualityGatesSchemaConfig {
10017 #[serde(default)]
10019 pub enabled: bool,
10020 #[serde(default = "default_gate_profile_name")]
10022 pub profile: String,
10023 #[serde(default)]
10025 pub fail_on_violation: bool,
10026 #[serde(default)]
10028 pub custom_gates: Vec<QualityGateEntry>,
10029}
10030
10031fn default_gate_profile_name() -> String {
10032 "default".to_string()
10033}
10034
10035impl Default for QualityGatesSchemaConfig {
10036 fn default() -> Self {
10037 Self {
10038 enabled: false,
10039 profile: default_gate_profile_name(),
10040 fail_on_violation: false,
10041 custom_gates: Vec::new(),
10042 }
10043 }
10044}
10045
10046#[derive(Debug, Clone, Serialize, Deserialize)]
10048pub struct QualityGateEntry {
10049 pub name: String,
10051 pub metric: String,
10055 pub threshold: f64,
10057 #[serde(default)]
10059 pub upper_threshold: Option<f64>,
10060 #[serde(default = "default_gate_comparison")]
10062 pub comparison: String,
10063}
10064
10065fn default_gate_comparison() -> String {
10066 "gte".to_string()
10067}
10068
10069#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10079pub struct ComplianceSchemaConfig {
10080 #[serde(default)]
10082 pub content_marking: ContentMarkingSchemaConfig,
10083 #[serde(default)]
10085 pub article10_report: bool,
10086 #[serde(default)]
10088 pub certificates: CertificateSchemaConfig,
10089}
10090
10091#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10093pub struct CertificateSchemaConfig {
10094 #[serde(default)]
10096 pub enabled: bool,
10097 #[serde(default)]
10099 pub signing_key_env: Option<String>,
10100 #[serde(default)]
10102 pub include_quality_metrics: bool,
10103}
10104
10105#[derive(Debug, Clone, Serialize, Deserialize)]
10107pub struct ContentMarkingSchemaConfig {
10108 #[serde(default = "default_true")]
10110 pub enabled: bool,
10111 #[serde(default = "default_marking_format")]
10113 pub format: String,
10114}
10115
10116fn default_marking_format() -> String {
10117 "embedded".to_string()
10118}
10119
10120impl Default for ContentMarkingSchemaConfig {
10121 fn default() -> Self {
10122 Self {
10123 enabled: true,
10124 format: default_marking_format(),
10125 }
10126 }
10127}
10128
10129#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10131pub struct WebhookSchemaConfig {
10132 #[serde(default)]
10134 pub enabled: bool,
10135 #[serde(default)]
10137 pub endpoints: Vec<WebhookEndpointConfig>,
10138}
10139
10140#[derive(Debug, Clone, Serialize, Deserialize)]
10142pub struct WebhookEndpointConfig {
10143 pub url: String,
10145 #[serde(default)]
10147 pub events: Vec<String>,
10148 #[serde(default)]
10150 pub secret: Option<String>,
10151 #[serde(default = "default_webhook_retries")]
10153 pub max_retries: u32,
10154 #[serde(default = "default_webhook_timeout")]
10156 pub timeout_secs: u64,
10157}
10158
10159fn default_webhook_retries() -> u32 {
10160 3
10161}
10162fn default_webhook_timeout() -> u64 {
10163 10
10164}
10165
10166#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10172pub struct SourceToPayConfig {
10173 #[serde(default)]
10175 pub enabled: bool,
10176 #[serde(default)]
10178 pub spend_analysis: SpendAnalysisConfig,
10179 #[serde(default)]
10181 pub sourcing: SourcingConfig,
10182 #[serde(default)]
10184 pub qualification: QualificationConfig,
10185 #[serde(default)]
10187 pub rfx: RfxConfig,
10188 #[serde(default)]
10190 pub contracts: ContractConfig,
10191 #[serde(default)]
10193 pub catalog: CatalogConfig,
10194 #[serde(default)]
10196 pub scorecards: ScorecardConfig,
10197 #[serde(default)]
10199 pub p2p_integration: P2PIntegrationConfig,
10200}
10201
10202#[derive(Debug, Clone, Serialize, Deserialize)]
10204pub struct SpendAnalysisConfig {
10205 #[serde(default = "default_hhi_threshold")]
10207 pub hhi_threshold: f64,
10208 #[serde(default = "default_contract_coverage_target")]
10210 pub contract_coverage_target: f64,
10211}
10212
10213impl Default for SpendAnalysisConfig {
10214 fn default() -> Self {
10215 Self {
10216 hhi_threshold: default_hhi_threshold(),
10217 contract_coverage_target: default_contract_coverage_target(),
10218 }
10219 }
10220}
10221
10222fn default_hhi_threshold() -> f64 {
10223 2500.0
10224}
10225fn default_contract_coverage_target() -> f64 {
10226 0.80
10227}
10228
10229#[derive(Debug, Clone, Serialize, Deserialize)]
10231pub struct SourcingConfig {
10232 #[serde(default = "default_sourcing_projects_per_year")]
10234 pub projects_per_year: u32,
10235 #[serde(default = "default_renewal_horizon_months")]
10237 pub renewal_horizon_months: u32,
10238 #[serde(default = "default_project_duration_months")]
10240 pub project_duration_months: u32,
10241}
10242
10243impl Default for SourcingConfig {
10244 fn default() -> Self {
10245 Self {
10246 projects_per_year: default_sourcing_projects_per_year(),
10247 renewal_horizon_months: default_renewal_horizon_months(),
10248 project_duration_months: default_project_duration_months(),
10249 }
10250 }
10251}
10252
10253fn default_sourcing_projects_per_year() -> u32 {
10254 10
10255}
10256fn default_renewal_horizon_months() -> u32 {
10257 3
10258}
10259fn default_project_duration_months() -> u32 {
10260 4
10261}
10262
10263#[derive(Debug, Clone, Serialize, Deserialize)]
10265pub struct QualificationConfig {
10266 #[serde(default = "default_qualification_pass_rate")]
10268 pub pass_rate: f64,
10269 #[serde(default = "default_qualification_validity_days")]
10271 pub validity_days: u32,
10272 #[serde(default = "default_financial_weight")]
10274 pub financial_weight: f64,
10275 #[serde(default = "default_quality_weight")]
10277 pub quality_weight: f64,
10278 #[serde(default = "default_delivery_weight")]
10280 pub delivery_weight: f64,
10281 #[serde(default = "default_compliance_weight")]
10283 pub compliance_weight: f64,
10284}
10285
10286impl Default for QualificationConfig {
10287 fn default() -> Self {
10288 Self {
10289 pass_rate: default_qualification_pass_rate(),
10290 validity_days: default_qualification_validity_days(),
10291 financial_weight: default_financial_weight(),
10292 quality_weight: default_quality_weight(),
10293 delivery_weight: default_delivery_weight(),
10294 compliance_weight: default_compliance_weight(),
10295 }
10296 }
10297}
10298
10299fn default_qualification_pass_rate() -> f64 {
10300 0.75
10301}
10302fn default_qualification_validity_days() -> u32 {
10303 365
10304}
10305fn default_financial_weight() -> f64 {
10306 0.25
10307}
10308fn default_quality_weight() -> f64 {
10309 0.30
10310}
10311fn default_delivery_weight() -> f64 {
10312 0.25
10313}
10314fn default_compliance_weight() -> f64 {
10315 0.20
10316}
10317
10318#[derive(Debug, Clone, Serialize, Deserialize)]
10320pub struct RfxConfig {
10321 #[serde(default = "default_rfi_threshold")]
10323 pub rfi_threshold: f64,
10324 #[serde(default = "default_min_invited_vendors")]
10326 pub min_invited_vendors: u32,
10327 #[serde(default = "default_max_invited_vendors")]
10329 pub max_invited_vendors: u32,
10330 #[serde(default = "default_response_rate")]
10332 pub response_rate: f64,
10333 #[serde(default = "default_price_weight")]
10335 pub default_price_weight: f64,
10336 #[serde(default = "default_rfx_quality_weight")]
10338 pub default_quality_weight: f64,
10339 #[serde(default = "default_rfx_delivery_weight")]
10341 pub default_delivery_weight: f64,
10342}
10343
10344impl Default for RfxConfig {
10345 fn default() -> Self {
10346 Self {
10347 rfi_threshold: default_rfi_threshold(),
10348 min_invited_vendors: default_min_invited_vendors(),
10349 max_invited_vendors: default_max_invited_vendors(),
10350 response_rate: default_response_rate(),
10351 default_price_weight: default_price_weight(),
10352 default_quality_weight: default_rfx_quality_weight(),
10353 default_delivery_weight: default_rfx_delivery_weight(),
10354 }
10355 }
10356}
10357
10358fn default_rfi_threshold() -> f64 {
10359 100_000.0
10360}
10361fn default_min_invited_vendors() -> u32 {
10362 3
10363}
10364fn default_max_invited_vendors() -> u32 {
10365 8
10366}
10367fn default_response_rate() -> f64 {
10368 0.70
10369}
10370fn default_price_weight() -> f64 {
10371 0.40
10372}
10373fn default_rfx_quality_weight() -> f64 {
10374 0.35
10375}
10376fn default_rfx_delivery_weight() -> f64 {
10377 0.25
10378}
10379
10380#[derive(Debug, Clone, Serialize, Deserialize)]
10382pub struct ContractConfig {
10383 #[serde(default = "default_min_contract_months")]
10385 pub min_duration_months: u32,
10386 #[serde(default = "default_max_contract_months")]
10388 pub max_duration_months: u32,
10389 #[serde(default = "default_auto_renewal_rate")]
10391 pub auto_renewal_rate: f64,
10392 #[serde(default = "default_amendment_rate")]
10394 pub amendment_rate: f64,
10395 #[serde(default)]
10397 pub type_distribution: ContractTypeDistribution,
10398}
10399
10400impl Default for ContractConfig {
10401 fn default() -> Self {
10402 Self {
10403 min_duration_months: default_min_contract_months(),
10404 max_duration_months: default_max_contract_months(),
10405 auto_renewal_rate: default_auto_renewal_rate(),
10406 amendment_rate: default_amendment_rate(),
10407 type_distribution: ContractTypeDistribution::default(),
10408 }
10409 }
10410}
10411
10412fn default_min_contract_months() -> u32 {
10413 12
10414}
10415fn default_max_contract_months() -> u32 {
10416 36
10417}
10418fn default_auto_renewal_rate() -> f64 {
10419 0.40
10420}
10421fn default_amendment_rate() -> f64 {
10422 0.20
10423}
10424
10425#[derive(Debug, Clone, Serialize, Deserialize)]
10427pub struct ContractTypeDistribution {
10428 #[serde(default = "default_fixed_price_pct")]
10430 pub fixed_price: f64,
10431 #[serde(default = "default_blanket_pct")]
10433 pub blanket: f64,
10434 #[serde(default = "default_time_materials_pct")]
10436 pub time_and_materials: f64,
10437 #[serde(default = "default_service_agreement_pct")]
10439 pub service_agreement: f64,
10440}
10441
10442impl Default for ContractTypeDistribution {
10443 fn default() -> Self {
10444 Self {
10445 fixed_price: default_fixed_price_pct(),
10446 blanket: default_blanket_pct(),
10447 time_and_materials: default_time_materials_pct(),
10448 service_agreement: default_service_agreement_pct(),
10449 }
10450 }
10451}
10452
10453fn default_fixed_price_pct() -> f64 {
10454 0.40
10455}
10456fn default_blanket_pct() -> f64 {
10457 0.30
10458}
10459fn default_time_materials_pct() -> f64 {
10460 0.15
10461}
10462fn default_service_agreement_pct() -> f64 {
10463 0.15
10464}
10465
10466#[derive(Debug, Clone, Serialize, Deserialize)]
10468pub struct CatalogConfig {
10469 #[serde(default = "default_preferred_vendor_flag_rate")]
10471 pub preferred_vendor_flag_rate: f64,
10472 #[serde(default = "default_multi_source_rate")]
10474 pub multi_source_rate: f64,
10475}
10476
10477impl Default for CatalogConfig {
10478 fn default() -> Self {
10479 Self {
10480 preferred_vendor_flag_rate: default_preferred_vendor_flag_rate(),
10481 multi_source_rate: default_multi_source_rate(),
10482 }
10483 }
10484}
10485
10486fn default_preferred_vendor_flag_rate() -> f64 {
10487 0.70
10488}
10489fn default_multi_source_rate() -> f64 {
10490 0.25
10491}
10492
10493#[derive(Debug, Clone, Serialize, Deserialize)]
10495pub struct ScorecardConfig {
10496 #[serde(default = "default_scorecard_frequency")]
10498 pub frequency: String,
10499 #[serde(default = "default_otd_weight")]
10501 pub on_time_delivery_weight: f64,
10502 #[serde(default = "default_quality_score_weight")]
10504 pub quality_weight: f64,
10505 #[serde(default = "default_price_score_weight")]
10507 pub price_weight: f64,
10508 #[serde(default = "default_responsiveness_weight")]
10510 pub responsiveness_weight: f64,
10511 #[serde(default = "default_grade_a_threshold")]
10513 pub grade_a_threshold: f64,
10514 #[serde(default = "default_grade_b_threshold")]
10516 pub grade_b_threshold: f64,
10517 #[serde(default = "default_grade_c_threshold")]
10519 pub grade_c_threshold: f64,
10520}
10521
10522impl Default for ScorecardConfig {
10523 fn default() -> Self {
10524 Self {
10525 frequency: default_scorecard_frequency(),
10526 on_time_delivery_weight: default_otd_weight(),
10527 quality_weight: default_quality_score_weight(),
10528 price_weight: default_price_score_weight(),
10529 responsiveness_weight: default_responsiveness_weight(),
10530 grade_a_threshold: default_grade_a_threshold(),
10531 grade_b_threshold: default_grade_b_threshold(),
10532 grade_c_threshold: default_grade_c_threshold(),
10533 }
10534 }
10535}
10536
10537fn default_scorecard_frequency() -> String {
10538 "quarterly".to_string()
10539}
10540fn default_otd_weight() -> f64 {
10541 0.30
10542}
10543fn default_quality_score_weight() -> f64 {
10544 0.30
10545}
10546fn default_price_score_weight() -> f64 {
10547 0.25
10548}
10549fn default_responsiveness_weight() -> f64 {
10550 0.15
10551}
10552fn default_grade_a_threshold() -> f64 {
10553 90.0
10554}
10555fn default_grade_b_threshold() -> f64 {
10556 75.0
10557}
10558fn default_grade_c_threshold() -> f64 {
10559 60.0
10560}
10561
10562#[derive(Debug, Clone, Serialize, Deserialize)]
10564pub struct P2PIntegrationConfig {
10565 #[serde(default = "default_off_contract_rate")]
10567 pub off_contract_rate: f64,
10568 #[serde(default = "default_price_tolerance")]
10570 pub price_tolerance: f64,
10571 #[serde(default)]
10573 pub catalog_enforcement: bool,
10574}
10575
10576impl Default for P2PIntegrationConfig {
10577 fn default() -> Self {
10578 Self {
10579 off_contract_rate: default_off_contract_rate(),
10580 price_tolerance: default_price_tolerance(),
10581 catalog_enforcement: false,
10582 }
10583 }
10584}
10585
10586fn default_off_contract_rate() -> f64 {
10587 0.15
10588}
10589fn default_price_tolerance() -> f64 {
10590 0.02
10591}
10592
10593#[derive(Debug, Clone, Serialize, Deserialize)]
10597pub struct FinancialReportingConfig {
10598 #[serde(default)]
10600 pub enabled: bool,
10601 #[serde(default = "default_true")]
10603 pub generate_balance_sheet: bool,
10604 #[serde(default = "default_true")]
10606 pub generate_income_statement: bool,
10607 #[serde(default = "default_true")]
10609 pub generate_cash_flow: bool,
10610 #[serde(default = "default_true")]
10612 pub generate_changes_in_equity: bool,
10613 #[serde(default = "default_comparative_periods")]
10615 pub comparative_periods: u32,
10616 #[serde(default)]
10618 pub management_kpis: ManagementKpisConfig,
10619 #[serde(default)]
10621 pub budgets: BudgetConfig,
10622}
10623
10624impl Default for FinancialReportingConfig {
10625 fn default() -> Self {
10626 Self {
10627 enabled: false,
10628 generate_balance_sheet: true,
10629 generate_income_statement: true,
10630 generate_cash_flow: true,
10631 generate_changes_in_equity: true,
10632 comparative_periods: default_comparative_periods(),
10633 management_kpis: ManagementKpisConfig::default(),
10634 budgets: BudgetConfig::default(),
10635 }
10636 }
10637}
10638
10639fn default_comparative_periods() -> u32 {
10640 1
10641}
10642
10643#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10645pub struct ManagementKpisConfig {
10646 #[serde(default)]
10648 pub enabled: bool,
10649 #[serde(default = "default_kpi_frequency")]
10651 pub frequency: String,
10652}
10653
10654fn default_kpi_frequency() -> String {
10655 "monthly".to_string()
10656}
10657
10658#[derive(Debug, Clone, Serialize, Deserialize)]
10660pub struct BudgetConfig {
10661 #[serde(default)]
10663 pub enabled: bool,
10664 #[serde(default = "default_revenue_growth_rate")]
10666 pub revenue_growth_rate: f64,
10667 #[serde(default = "default_expense_inflation_rate")]
10669 pub expense_inflation_rate: f64,
10670 #[serde(default = "default_variance_noise")]
10672 pub variance_noise: f64,
10673}
10674
10675impl Default for BudgetConfig {
10676 fn default() -> Self {
10677 Self {
10678 enabled: false,
10679 revenue_growth_rate: default_revenue_growth_rate(),
10680 expense_inflation_rate: default_expense_inflation_rate(),
10681 variance_noise: default_variance_noise(),
10682 }
10683 }
10684}
10685
10686fn default_revenue_growth_rate() -> f64 {
10687 0.05
10688}
10689fn default_expense_inflation_rate() -> f64 {
10690 0.03
10691}
10692fn default_variance_noise() -> f64 {
10693 0.10
10694}
10695
10696#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10700pub struct HrConfig {
10701 #[serde(default)]
10703 pub enabled: bool,
10704 #[serde(default)]
10706 pub payroll: PayrollConfig,
10707 #[serde(default)]
10709 pub time_attendance: TimeAttendanceConfig,
10710 #[serde(default)]
10712 pub expenses: ExpenseConfig,
10713}
10714
10715#[derive(Debug, Clone, Serialize, Deserialize)]
10717pub struct PayrollConfig {
10718 #[serde(default = "default_true")]
10720 pub enabled: bool,
10721 #[serde(default = "default_pay_frequency")]
10723 pub pay_frequency: String,
10724 #[serde(default)]
10726 pub salary_ranges: PayrollSalaryRanges,
10727 #[serde(default)]
10729 pub tax_rates: PayrollTaxRates,
10730 #[serde(default = "default_benefits_enrollment_rate")]
10732 pub benefits_enrollment_rate: f64,
10733 #[serde(default = "default_retirement_participation_rate")]
10735 pub retirement_participation_rate: f64,
10736}
10737
10738impl Default for PayrollConfig {
10739 fn default() -> Self {
10740 Self {
10741 enabled: true,
10742 pay_frequency: default_pay_frequency(),
10743 salary_ranges: PayrollSalaryRanges::default(),
10744 tax_rates: PayrollTaxRates::default(),
10745 benefits_enrollment_rate: default_benefits_enrollment_rate(),
10746 retirement_participation_rate: default_retirement_participation_rate(),
10747 }
10748 }
10749}
10750
10751fn default_pay_frequency() -> String {
10752 "monthly".to_string()
10753}
10754fn default_benefits_enrollment_rate() -> f64 {
10755 0.60
10756}
10757fn default_retirement_participation_rate() -> f64 {
10758 0.45
10759}
10760
10761#[derive(Debug, Clone, Serialize, Deserialize)]
10763pub struct PayrollSalaryRanges {
10764 #[serde(default = "default_staff_min")]
10766 pub staff_min: f64,
10767 #[serde(default = "default_staff_max")]
10768 pub staff_max: f64,
10769 #[serde(default = "default_manager_min")]
10771 pub manager_min: f64,
10772 #[serde(default = "default_manager_max")]
10773 pub manager_max: f64,
10774 #[serde(default = "default_director_min")]
10776 pub director_min: f64,
10777 #[serde(default = "default_director_max")]
10778 pub director_max: f64,
10779 #[serde(default = "default_executive_min")]
10781 pub executive_min: f64,
10782 #[serde(default = "default_executive_max")]
10783 pub executive_max: f64,
10784}
10785
10786impl Default for PayrollSalaryRanges {
10787 fn default() -> Self {
10788 Self {
10789 staff_min: default_staff_min(),
10790 staff_max: default_staff_max(),
10791 manager_min: default_manager_min(),
10792 manager_max: default_manager_max(),
10793 director_min: default_director_min(),
10794 director_max: default_director_max(),
10795 executive_min: default_executive_min(),
10796 executive_max: default_executive_max(),
10797 }
10798 }
10799}
10800
10801fn default_staff_min() -> f64 {
10802 50_000.0
10803}
10804fn default_staff_max() -> f64 {
10805 70_000.0
10806}
10807fn default_manager_min() -> f64 {
10808 80_000.0
10809}
10810fn default_manager_max() -> f64 {
10811 120_000.0
10812}
10813fn default_director_min() -> f64 {
10814 120_000.0
10815}
10816fn default_director_max() -> f64 {
10817 180_000.0
10818}
10819fn default_executive_min() -> f64 {
10820 180_000.0
10821}
10822fn default_executive_max() -> f64 {
10823 350_000.0
10824}
10825
10826#[derive(Debug, Clone, Serialize, Deserialize)]
10828pub struct PayrollTaxRates {
10829 #[serde(default = "default_federal_rate")]
10831 pub federal_effective: f64,
10832 #[serde(default = "default_state_rate")]
10834 pub state_effective: f64,
10835 #[serde(default = "default_fica_rate")]
10837 pub fica: f64,
10838}
10839
10840impl Default for PayrollTaxRates {
10841 fn default() -> Self {
10842 Self {
10843 federal_effective: default_federal_rate(),
10844 state_effective: default_state_rate(),
10845 fica: default_fica_rate(),
10846 }
10847 }
10848}
10849
10850fn default_federal_rate() -> f64 {
10851 0.22
10852}
10853fn default_state_rate() -> f64 {
10854 0.05
10855}
10856fn default_fica_rate() -> f64 {
10857 0.0765
10858}
10859
10860#[derive(Debug, Clone, Serialize, Deserialize)]
10862pub struct TimeAttendanceConfig {
10863 #[serde(default = "default_true")]
10865 pub enabled: bool,
10866 #[serde(default = "default_overtime_rate")]
10868 pub overtime_rate: f64,
10869}
10870
10871impl Default for TimeAttendanceConfig {
10872 fn default() -> Self {
10873 Self {
10874 enabled: true,
10875 overtime_rate: default_overtime_rate(),
10876 }
10877 }
10878}
10879
10880fn default_overtime_rate() -> f64 {
10881 0.10
10882}
10883
10884#[derive(Debug, Clone, Serialize, Deserialize)]
10886pub struct ExpenseConfig {
10887 #[serde(default = "default_true")]
10889 pub enabled: bool,
10890 #[serde(default = "default_expense_submission_rate")]
10892 pub submission_rate: f64,
10893 #[serde(default = "default_policy_violation_rate")]
10895 pub policy_violation_rate: f64,
10896}
10897
10898impl Default for ExpenseConfig {
10899 fn default() -> Self {
10900 Self {
10901 enabled: true,
10902 submission_rate: default_expense_submission_rate(),
10903 policy_violation_rate: default_policy_violation_rate(),
10904 }
10905 }
10906}
10907
10908fn default_expense_submission_rate() -> f64 {
10909 0.30
10910}
10911fn default_policy_violation_rate() -> f64 {
10912 0.08
10913}
10914
10915#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10919pub struct ManufacturingProcessConfig {
10920 #[serde(default)]
10922 pub enabled: bool,
10923 #[serde(default)]
10925 pub production_orders: ProductionOrderConfig,
10926 #[serde(default)]
10928 pub costing: ManufacturingCostingConfig,
10929 #[serde(default)]
10931 pub routing: RoutingConfig,
10932}
10933
10934#[derive(Debug, Clone, Serialize, Deserialize)]
10936pub struct ProductionOrderConfig {
10937 #[serde(default = "default_prod_orders_per_month")]
10939 pub orders_per_month: u32,
10940 #[serde(default = "default_prod_avg_batch_size")]
10942 pub avg_batch_size: u32,
10943 #[serde(default = "default_prod_yield_rate")]
10945 pub yield_rate: f64,
10946 #[serde(default = "default_prod_make_to_order_rate")]
10948 pub make_to_order_rate: f64,
10949 #[serde(default = "default_prod_rework_rate")]
10951 pub rework_rate: f64,
10952}
10953
10954impl Default for ProductionOrderConfig {
10955 fn default() -> Self {
10956 Self {
10957 orders_per_month: default_prod_orders_per_month(),
10958 avg_batch_size: default_prod_avg_batch_size(),
10959 yield_rate: default_prod_yield_rate(),
10960 make_to_order_rate: default_prod_make_to_order_rate(),
10961 rework_rate: default_prod_rework_rate(),
10962 }
10963 }
10964}
10965
10966fn default_prod_orders_per_month() -> u32 {
10967 50
10968}
10969fn default_prod_avg_batch_size() -> u32 {
10970 100
10971}
10972fn default_prod_yield_rate() -> f64 {
10973 0.97
10974}
10975fn default_prod_make_to_order_rate() -> f64 {
10976 0.20
10977}
10978fn default_prod_rework_rate() -> f64 {
10979 0.03
10980}
10981
10982#[derive(Debug, Clone, Serialize, Deserialize)]
10984pub struct ManufacturingCostingConfig {
10985 #[serde(default = "default_labor_rate")]
10987 pub labor_rate_per_hour: f64,
10988 #[serde(default = "default_overhead_rate")]
10990 pub overhead_rate: f64,
10991 #[serde(default = "default_cost_update_frequency")]
10993 pub standard_cost_update_frequency: String,
10994}
10995
10996impl Default for ManufacturingCostingConfig {
10997 fn default() -> Self {
10998 Self {
10999 labor_rate_per_hour: default_labor_rate(),
11000 overhead_rate: default_overhead_rate(),
11001 standard_cost_update_frequency: default_cost_update_frequency(),
11002 }
11003 }
11004}
11005
11006fn default_labor_rate() -> f64 {
11007 35.0
11008}
11009fn default_overhead_rate() -> f64 {
11010 1.50
11011}
11012fn default_cost_update_frequency() -> String {
11013 "quarterly".to_string()
11014}
11015
11016#[derive(Debug, Clone, Serialize, Deserialize)]
11018pub struct RoutingConfig {
11019 #[serde(default = "default_avg_operations")]
11021 pub avg_operations: u32,
11022 #[serde(default = "default_setup_time")]
11024 pub setup_time_hours: f64,
11025 #[serde(default = "default_run_time_variation")]
11027 pub run_time_variation: f64,
11028}
11029
11030impl Default for RoutingConfig {
11031 fn default() -> Self {
11032 Self {
11033 avg_operations: default_avg_operations(),
11034 setup_time_hours: default_setup_time(),
11035 run_time_variation: default_run_time_variation(),
11036 }
11037 }
11038}
11039
11040fn default_avg_operations() -> u32 {
11041 4
11042}
11043fn default_setup_time() -> f64 {
11044 1.5
11045}
11046fn default_run_time_variation() -> f64 {
11047 0.15
11048}
11049
11050#[derive(Debug, Clone, Serialize, Deserialize)]
11054pub struct SalesQuoteConfig {
11055 #[serde(default)]
11057 pub enabled: bool,
11058 #[serde(default = "default_quotes_per_month")]
11060 pub quotes_per_month: u32,
11061 #[serde(default = "default_quote_win_rate")]
11063 pub win_rate: f64,
11064 #[serde(default = "default_quote_validity_days")]
11066 pub validity_days: u32,
11067}
11068
11069impl Default for SalesQuoteConfig {
11070 fn default() -> Self {
11071 Self {
11072 enabled: false,
11073 quotes_per_month: default_quotes_per_month(),
11074 win_rate: default_quote_win_rate(),
11075 validity_days: default_quote_validity_days(),
11076 }
11077 }
11078}
11079
11080fn default_quotes_per_month() -> u32 {
11081 30
11082}
11083fn default_quote_win_rate() -> f64 {
11084 0.35
11085}
11086fn default_quote_validity_days() -> u32 {
11087 30
11088}
11089
11090#[derive(Debug, Clone, Serialize, Deserialize)]
11099pub struct TaxConfig {
11100 #[serde(default)]
11102 pub enabled: bool,
11103 #[serde(default)]
11105 pub jurisdictions: TaxJurisdictionConfig,
11106 #[serde(default)]
11108 pub vat_gst: VatGstConfig,
11109 #[serde(default)]
11111 pub sales_tax: SalesTaxConfig,
11112 #[serde(default)]
11114 pub withholding: WithholdingTaxSchemaConfig,
11115 #[serde(default)]
11117 pub provisions: TaxProvisionSchemaConfig,
11118 #[serde(default)]
11120 pub payroll_tax: PayrollTaxSchemaConfig,
11121 #[serde(default = "default_tax_anomaly_rate")]
11123 pub anomaly_rate: f64,
11124}
11125
11126fn default_tax_anomaly_rate() -> f64 {
11127 0.03
11128}
11129
11130impl Default for TaxConfig {
11131 fn default() -> Self {
11132 Self {
11133 enabled: false,
11134 jurisdictions: TaxJurisdictionConfig::default(),
11135 vat_gst: VatGstConfig::default(),
11136 sales_tax: SalesTaxConfig::default(),
11137 withholding: WithholdingTaxSchemaConfig::default(),
11138 provisions: TaxProvisionSchemaConfig::default(),
11139 payroll_tax: PayrollTaxSchemaConfig::default(),
11140 anomaly_rate: default_tax_anomaly_rate(),
11141 }
11142 }
11143}
11144
11145#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11150pub struct TaxJurisdictionConfig {
11151 #[serde(default)]
11153 pub countries: Vec<String>,
11154 #[serde(default)]
11156 pub include_subnational: bool,
11157}
11158
11159#[derive(Debug, Clone, Serialize, Deserialize)]
11164pub struct VatGstConfig {
11165 #[serde(default)]
11167 pub enabled: bool,
11168 #[serde(default)]
11170 pub standard_rates: std::collections::HashMap<String, f64>,
11171 #[serde(default)]
11173 pub reduced_rates: std::collections::HashMap<String, f64>,
11174 #[serde(default)]
11176 pub exempt_categories: Vec<String>,
11177 #[serde(default = "default_true")]
11179 pub reverse_charge: bool,
11180}
11181
11182impl Default for VatGstConfig {
11183 fn default() -> Self {
11184 Self {
11185 enabled: false,
11186 standard_rates: std::collections::HashMap::new(),
11187 reduced_rates: std::collections::HashMap::new(),
11188 exempt_categories: Vec::new(),
11189 reverse_charge: true,
11190 }
11191 }
11192}
11193
11194#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11198pub struct SalesTaxConfig {
11199 #[serde(default)]
11201 pub enabled: bool,
11202 #[serde(default)]
11204 pub nexus_states: Vec<String>,
11205}
11206
11207#[derive(Debug, Clone, Serialize, Deserialize)]
11212pub struct WithholdingTaxSchemaConfig {
11213 #[serde(default)]
11215 pub enabled: bool,
11216 #[serde(default = "default_true")]
11218 pub treaty_network: bool,
11219 #[serde(default = "default_withholding_rate")]
11221 pub default_rate: f64,
11222 #[serde(default = "default_treaty_reduced_rate")]
11224 pub treaty_reduced_rate: f64,
11225}
11226
11227fn default_withholding_rate() -> f64 {
11228 0.30
11229}
11230
11231fn default_treaty_reduced_rate() -> f64 {
11232 0.15
11233}
11234
11235impl Default for WithholdingTaxSchemaConfig {
11236 fn default() -> Self {
11237 Self {
11238 enabled: false,
11239 treaty_network: true,
11240 default_rate: default_withholding_rate(),
11241 treaty_reduced_rate: default_treaty_reduced_rate(),
11242 }
11243 }
11244}
11245
11246#[derive(Debug, Clone, Serialize, Deserialize)]
11251pub struct TaxProvisionSchemaConfig {
11252 #[serde(default = "default_true")]
11255 pub enabled: bool,
11256 #[serde(default = "default_statutory_rate")]
11258 pub statutory_rate: f64,
11259 #[serde(default = "default_true")]
11261 pub uncertain_positions: bool,
11262}
11263
11264fn default_statutory_rate() -> f64 {
11265 0.21
11266}
11267
11268impl Default for TaxProvisionSchemaConfig {
11269 fn default() -> Self {
11270 Self {
11271 enabled: true,
11272 statutory_rate: default_statutory_rate(),
11273 uncertain_positions: true,
11274 }
11275 }
11276}
11277
11278#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11283pub struct PayrollTaxSchemaConfig {
11284 #[serde(default)]
11286 pub enabled: bool,
11287}
11288
11289#[derive(Debug, Clone, Serialize, Deserialize)]
11299pub struct TreasuryConfig {
11300 #[serde(default)]
11302 pub enabled: bool,
11303 #[serde(default)]
11305 pub cash_positioning: CashPositioningConfig,
11306 #[serde(default)]
11308 pub cash_forecasting: CashForecastingConfig,
11309 #[serde(default)]
11311 pub cash_pooling: CashPoolingConfig,
11312 #[serde(default)]
11314 pub hedging: HedgingSchemaConfig,
11315 #[serde(default)]
11317 pub debt: DebtSchemaConfig,
11318 #[serde(default)]
11320 pub netting: NettingSchemaConfig,
11321 #[serde(default)]
11323 pub bank_guarantees: BankGuaranteeSchemaConfig,
11324 #[serde(default = "default_treasury_anomaly_rate")]
11326 pub anomaly_rate: f64,
11327}
11328
11329fn default_treasury_anomaly_rate() -> f64 {
11330 0.02
11331}
11332
11333impl Default for TreasuryConfig {
11334 fn default() -> Self {
11335 Self {
11336 enabled: false,
11337 cash_positioning: CashPositioningConfig::default(),
11338 cash_forecasting: CashForecastingConfig::default(),
11339 cash_pooling: CashPoolingConfig::default(),
11340 hedging: HedgingSchemaConfig::default(),
11341 debt: DebtSchemaConfig::default(),
11342 netting: NettingSchemaConfig::default(),
11343 bank_guarantees: BankGuaranteeSchemaConfig::default(),
11344 anomaly_rate: default_treasury_anomaly_rate(),
11345 }
11346 }
11347}
11348
11349#[derive(Debug, Clone, Serialize, Deserialize)]
11353pub struct CashPositioningConfig {
11354 #[serde(default = "default_true")]
11356 pub enabled: bool,
11357 #[serde(default = "default_cash_frequency")]
11359 pub frequency: String,
11360 #[serde(default = "default_minimum_balance_policy")]
11362 pub minimum_balance_policy: f64,
11363}
11364
11365fn default_cash_frequency() -> String {
11366 "daily".to_string()
11367}
11368
11369fn default_minimum_balance_policy() -> f64 {
11370 100_000.0
11371}
11372
11373impl Default for CashPositioningConfig {
11374 fn default() -> Self {
11375 Self {
11376 enabled: true,
11377 frequency: default_cash_frequency(),
11378 minimum_balance_policy: default_minimum_balance_policy(),
11379 }
11380 }
11381}
11382
11383#[derive(Debug, Clone, Serialize, Deserialize)]
11387pub struct CashForecastingConfig {
11388 #[serde(default = "default_true")]
11390 pub enabled: bool,
11391 #[serde(default = "default_horizon_days")]
11393 pub horizon_days: u32,
11394 #[serde(default = "default_ar_probability_curve")]
11396 pub ar_collection_probability_curve: String,
11397 #[serde(default = "default_confidence_interval")]
11399 pub confidence_interval: f64,
11400}
11401
11402fn default_horizon_days() -> u32 {
11403 90
11404}
11405
11406fn default_ar_probability_curve() -> String {
11407 "aging".to_string()
11408}
11409
11410fn default_confidence_interval() -> f64 {
11411 0.90
11412}
11413
11414impl Default for CashForecastingConfig {
11415 fn default() -> Self {
11416 Self {
11417 enabled: true,
11418 horizon_days: default_horizon_days(),
11419 ar_collection_probability_curve: default_ar_probability_curve(),
11420 confidence_interval: default_confidence_interval(),
11421 }
11422 }
11423}
11424
11425#[derive(Debug, Clone, Serialize, Deserialize)]
11429pub struct CashPoolingConfig {
11430 #[serde(default)]
11432 pub enabled: bool,
11433 #[serde(default = "default_pool_type")]
11435 pub pool_type: String,
11436 #[serde(default = "default_sweep_time")]
11438 pub sweep_time: String,
11439}
11440
11441fn default_pool_type() -> String {
11442 "zero_balancing".to_string()
11443}
11444
11445fn default_sweep_time() -> String {
11446 "16:00".to_string()
11447}
11448
11449impl Default for CashPoolingConfig {
11450 fn default() -> Self {
11451 Self {
11452 enabled: false,
11453 pool_type: default_pool_type(),
11454 sweep_time: default_sweep_time(),
11455 }
11456 }
11457}
11458
11459#[derive(Debug, Clone, Serialize, Deserialize)]
11464pub struct HedgingSchemaConfig {
11465 #[serde(default)]
11467 pub enabled: bool,
11468 #[serde(default = "default_hedge_ratio")]
11470 pub hedge_ratio: f64,
11471 #[serde(default = "default_hedge_instruments")]
11473 pub instruments: Vec<String>,
11474 #[serde(default = "default_true")]
11476 pub hedge_accounting: bool,
11477 #[serde(default = "default_effectiveness_method")]
11479 pub effectiveness_method: String,
11480}
11481
11482fn default_hedge_ratio() -> f64 {
11483 0.75
11484}
11485
11486fn default_hedge_instruments() -> Vec<String> {
11487 vec!["fx_forward".to_string(), "interest_rate_swap".to_string()]
11488}
11489
11490fn default_effectiveness_method() -> String {
11491 "regression".to_string()
11492}
11493
11494impl Default for HedgingSchemaConfig {
11495 fn default() -> Self {
11496 Self {
11497 enabled: false,
11498 hedge_ratio: default_hedge_ratio(),
11499 instruments: default_hedge_instruments(),
11500 hedge_accounting: true,
11501 effectiveness_method: default_effectiveness_method(),
11502 }
11503 }
11504}
11505
11506#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11511pub struct DebtSchemaConfig {
11512 #[serde(default)]
11514 pub enabled: bool,
11515 #[serde(default)]
11517 pub instruments: Vec<DebtInstrumentDef>,
11518 #[serde(default)]
11520 pub covenants: Vec<CovenantDef>,
11521}
11522
11523#[derive(Debug, Clone, Serialize, Deserialize)]
11525pub struct DebtInstrumentDef {
11526 #[serde(rename = "type")]
11528 pub instrument_type: String,
11529 #[serde(default)]
11531 pub principal: Option<f64>,
11532 #[serde(default)]
11534 pub rate: Option<f64>,
11535 #[serde(default)]
11537 pub maturity_months: Option<u32>,
11538 #[serde(default)]
11540 pub facility: Option<f64>,
11541}
11542
11543#[derive(Debug, Clone, Serialize, Deserialize)]
11545pub struct CovenantDef {
11546 #[serde(rename = "type")]
11549 pub covenant_type: String,
11550 pub threshold: f64,
11552}
11553
11554#[derive(Debug, Clone, Serialize, Deserialize)]
11558pub struct NettingSchemaConfig {
11559 #[serde(default)]
11561 pub enabled: bool,
11562 #[serde(default = "default_netting_cycle")]
11564 pub cycle: String,
11565}
11566
11567fn default_netting_cycle() -> String {
11568 "monthly".to_string()
11569}
11570
11571impl Default for NettingSchemaConfig {
11572 fn default() -> Self {
11573 Self {
11574 enabled: false,
11575 cycle: default_netting_cycle(),
11576 }
11577 }
11578}
11579
11580#[derive(Debug, Clone, Serialize, Deserialize)]
11584pub struct BankGuaranteeSchemaConfig {
11585 #[serde(default)]
11587 pub enabled: bool,
11588 #[serde(default = "default_guarantee_count")]
11590 pub count: u32,
11591}
11592
11593fn default_guarantee_count() -> u32 {
11594 5
11595}
11596
11597impl Default for BankGuaranteeSchemaConfig {
11598 fn default() -> Self {
11599 Self {
11600 enabled: false,
11601 count: default_guarantee_count(),
11602 }
11603 }
11604}
11605
11606#[derive(Debug, Clone, Serialize, Deserialize)]
11615pub struct ProjectAccountingConfig {
11616 #[serde(default)]
11618 pub enabled: bool,
11619 #[serde(default = "default_project_count")]
11621 pub project_count: u32,
11622 #[serde(default)]
11624 pub project_types: ProjectTypeDistribution,
11625 #[serde(default)]
11627 pub wbs: WbsSchemaConfig,
11628 #[serde(default)]
11630 pub cost_allocation: CostAllocationConfig,
11631 #[serde(default)]
11633 pub revenue_recognition: ProjectRevenueRecognitionConfig,
11634 #[serde(default)]
11636 pub milestones: MilestoneSchemaConfig,
11637 #[serde(default)]
11639 pub change_orders: ChangeOrderSchemaConfig,
11640 #[serde(default)]
11642 pub retainage: RetainageSchemaConfig,
11643 #[serde(default)]
11645 pub earned_value: EarnedValueSchemaConfig,
11646 #[serde(default = "default_project_anomaly_rate")]
11648 pub anomaly_rate: f64,
11649}
11650
11651fn default_project_count() -> u32 {
11652 10
11653}
11654
11655fn default_project_anomaly_rate() -> f64 {
11656 0.03
11657}
11658
11659impl Default for ProjectAccountingConfig {
11660 fn default() -> Self {
11661 Self {
11662 enabled: false,
11663 project_count: default_project_count(),
11664 project_types: ProjectTypeDistribution::default(),
11665 wbs: WbsSchemaConfig::default(),
11666 cost_allocation: CostAllocationConfig::default(),
11667 revenue_recognition: ProjectRevenueRecognitionConfig::default(),
11668 milestones: MilestoneSchemaConfig::default(),
11669 change_orders: ChangeOrderSchemaConfig::default(),
11670 retainage: RetainageSchemaConfig::default(),
11671 earned_value: EarnedValueSchemaConfig::default(),
11672 anomaly_rate: default_project_anomaly_rate(),
11673 }
11674 }
11675}
11676
11677#[derive(Debug, Clone, Serialize, Deserialize)]
11679pub struct ProjectTypeDistribution {
11680 #[serde(default = "default_capital_weight")]
11682 pub capital: f64,
11683 #[serde(default = "default_internal_weight")]
11685 pub internal: f64,
11686 #[serde(default = "default_customer_weight")]
11688 pub customer: f64,
11689 #[serde(default = "default_rnd_weight")]
11691 pub r_and_d: f64,
11692 #[serde(default = "default_maintenance_weight")]
11694 pub maintenance: f64,
11695 #[serde(default = "default_technology_weight")]
11697 pub technology: f64,
11698}
11699
11700fn default_capital_weight() -> f64 {
11701 0.25
11702}
11703fn default_internal_weight() -> f64 {
11704 0.20
11705}
11706fn default_customer_weight() -> f64 {
11707 0.30
11708}
11709fn default_rnd_weight() -> f64 {
11710 0.10
11711}
11712fn default_maintenance_weight() -> f64 {
11713 0.10
11714}
11715fn default_technology_weight() -> f64 {
11716 0.05
11717}
11718
11719impl Default for ProjectTypeDistribution {
11720 fn default() -> Self {
11721 Self {
11722 capital: default_capital_weight(),
11723 internal: default_internal_weight(),
11724 customer: default_customer_weight(),
11725 r_and_d: default_rnd_weight(),
11726 maintenance: default_maintenance_weight(),
11727 technology: default_technology_weight(),
11728 }
11729 }
11730}
11731
11732#[derive(Debug, Clone, Serialize, Deserialize)]
11734pub struct WbsSchemaConfig {
11735 #[serde(default = "default_wbs_max_depth")]
11737 pub max_depth: u32,
11738 #[serde(default = "default_wbs_min_elements")]
11740 pub min_elements_per_level: u32,
11741 #[serde(default = "default_wbs_max_elements")]
11743 pub max_elements_per_level: u32,
11744}
11745
11746fn default_wbs_max_depth() -> u32 {
11747 3
11748}
11749fn default_wbs_min_elements() -> u32 {
11750 2
11751}
11752fn default_wbs_max_elements() -> u32 {
11753 6
11754}
11755
11756impl Default for WbsSchemaConfig {
11757 fn default() -> Self {
11758 Self {
11759 max_depth: default_wbs_max_depth(),
11760 min_elements_per_level: default_wbs_min_elements(),
11761 max_elements_per_level: default_wbs_max_elements(),
11762 }
11763 }
11764}
11765
11766#[derive(Debug, Clone, Serialize, Deserialize)]
11768pub struct CostAllocationConfig {
11769 #[serde(default = "default_time_entry_rate")]
11771 pub time_entry_project_rate: f64,
11772 #[serde(default = "default_expense_rate")]
11774 pub expense_project_rate: f64,
11775 #[serde(default = "default_po_rate")]
11777 pub purchase_order_project_rate: f64,
11778 #[serde(default = "default_vi_rate")]
11780 pub vendor_invoice_project_rate: f64,
11781}
11782
11783fn default_time_entry_rate() -> f64 {
11784 0.60
11785}
11786fn default_expense_rate() -> f64 {
11787 0.30
11788}
11789fn default_po_rate() -> f64 {
11790 0.40
11791}
11792fn default_vi_rate() -> f64 {
11793 0.35
11794}
11795
11796impl Default for CostAllocationConfig {
11797 fn default() -> Self {
11798 Self {
11799 time_entry_project_rate: default_time_entry_rate(),
11800 expense_project_rate: default_expense_rate(),
11801 purchase_order_project_rate: default_po_rate(),
11802 vendor_invoice_project_rate: default_vi_rate(),
11803 }
11804 }
11805}
11806
11807#[derive(Debug, Clone, Serialize, Deserialize)]
11809pub struct ProjectRevenueRecognitionConfig {
11810 #[serde(default = "default_true")]
11812 pub enabled: bool,
11813 #[serde(default = "default_revenue_method")]
11815 pub method: String,
11816 #[serde(default = "default_completion_measure")]
11818 pub completion_measure: String,
11819 #[serde(default = "default_avg_contract_value")]
11821 pub avg_contract_value: f64,
11822}
11823
11824fn default_revenue_method() -> String {
11825 "percentage_of_completion".to_string()
11826}
11827fn default_completion_measure() -> String {
11828 "cost_to_cost".to_string()
11829}
11830fn default_avg_contract_value() -> f64 {
11831 500_000.0
11832}
11833
11834impl Default for ProjectRevenueRecognitionConfig {
11835 fn default() -> Self {
11836 Self {
11837 enabled: true,
11838 method: default_revenue_method(),
11839 completion_measure: default_completion_measure(),
11840 avg_contract_value: default_avg_contract_value(),
11841 }
11842 }
11843}
11844
11845#[derive(Debug, Clone, Serialize, Deserialize)]
11847pub struct MilestoneSchemaConfig {
11848 #[serde(default = "default_true")]
11850 pub enabled: bool,
11851 #[serde(default = "default_milestones_per_project")]
11853 pub avg_per_project: u32,
11854 #[serde(default = "default_payment_milestone_rate")]
11856 pub payment_milestone_rate: f64,
11857}
11858
11859fn default_milestones_per_project() -> u32 {
11860 4
11861}
11862fn default_payment_milestone_rate() -> f64 {
11863 0.50
11864}
11865
11866impl Default for MilestoneSchemaConfig {
11867 fn default() -> Self {
11868 Self {
11869 enabled: true,
11870 avg_per_project: default_milestones_per_project(),
11871 payment_milestone_rate: default_payment_milestone_rate(),
11872 }
11873 }
11874}
11875
11876#[derive(Debug, Clone, Serialize, Deserialize)]
11878pub struct ChangeOrderSchemaConfig {
11879 #[serde(default = "default_true")]
11881 pub enabled: bool,
11882 #[serde(default = "default_change_order_probability")]
11884 pub probability: f64,
11885 #[serde(default = "default_max_change_orders")]
11887 pub max_per_project: u32,
11888 #[serde(default = "default_change_order_approval_rate")]
11890 pub approval_rate: f64,
11891}
11892
11893fn default_change_order_probability() -> f64 {
11894 0.40
11895}
11896fn default_max_change_orders() -> u32 {
11897 3
11898}
11899fn default_change_order_approval_rate() -> f64 {
11900 0.75
11901}
11902
11903impl Default for ChangeOrderSchemaConfig {
11904 fn default() -> Self {
11905 Self {
11906 enabled: true,
11907 probability: default_change_order_probability(),
11908 max_per_project: default_max_change_orders(),
11909 approval_rate: default_change_order_approval_rate(),
11910 }
11911 }
11912}
11913
11914#[derive(Debug, Clone, Serialize, Deserialize)]
11916pub struct RetainageSchemaConfig {
11917 #[serde(default)]
11919 pub enabled: bool,
11920 #[serde(default = "default_retainage_pct")]
11922 pub default_percentage: f64,
11923}
11924
11925fn default_retainage_pct() -> f64 {
11926 0.10
11927}
11928
11929impl Default for RetainageSchemaConfig {
11930 fn default() -> Self {
11931 Self {
11932 enabled: false,
11933 default_percentage: default_retainage_pct(),
11934 }
11935 }
11936}
11937
11938#[derive(Debug, Clone, Serialize, Deserialize)]
11940pub struct EarnedValueSchemaConfig {
11941 #[serde(default = "default_true")]
11943 pub enabled: bool,
11944 #[serde(default = "default_evm_frequency")]
11946 pub frequency: String,
11947}
11948
11949fn default_evm_frequency() -> String {
11950 "monthly".to_string()
11951}
11952
11953impl Default for EarnedValueSchemaConfig {
11954 fn default() -> Self {
11955 Self {
11956 enabled: true,
11957 frequency: default_evm_frequency(),
11958 }
11959 }
11960}
11961
11962#[derive(Debug, Clone, Serialize, Deserialize)]
11968pub struct EsgConfig {
11969 #[serde(default)]
11971 pub enabled: bool,
11972 #[serde(default)]
11974 pub environmental: EnvironmentalConfig,
11975 #[serde(default)]
11977 pub social: SocialConfig,
11978 #[serde(default)]
11980 pub governance: GovernanceSchemaConfig,
11981 #[serde(default)]
11983 pub supply_chain_esg: SupplyChainEsgConfig,
11984 #[serde(default)]
11986 pub reporting: EsgReportingConfig,
11987 #[serde(default)]
11989 pub climate_scenarios: ClimateScenarioConfig,
11990 #[serde(default = "default_esg_anomaly_rate")]
11992 pub anomaly_rate: f64,
11993}
11994
11995fn default_esg_anomaly_rate() -> f64 {
11996 0.02
11997}
11998
11999impl Default for EsgConfig {
12000 fn default() -> Self {
12001 Self {
12002 enabled: false,
12003 environmental: EnvironmentalConfig::default(),
12004 social: SocialConfig::default(),
12005 governance: GovernanceSchemaConfig::default(),
12006 supply_chain_esg: SupplyChainEsgConfig::default(),
12007 reporting: EsgReportingConfig::default(),
12008 climate_scenarios: ClimateScenarioConfig::default(),
12009 anomaly_rate: default_esg_anomaly_rate(),
12010 }
12011 }
12012}
12013
12014#[derive(Debug, Clone, Serialize, Deserialize, Default)]
12019pub struct CountryPacksSchemaConfig {
12020 #[serde(default)]
12022 pub external_dir: Option<PathBuf>,
12023 #[serde(default)]
12027 pub overrides: std::collections::HashMap<String, serde_json::Value>,
12028}
12029
12030#[derive(Debug, Clone, Serialize, Deserialize)]
12032pub struct EnvironmentalConfig {
12033 #[serde(default = "default_true")]
12035 pub enabled: bool,
12036 #[serde(default)]
12038 pub scope1: EmissionScopeConfig,
12039 #[serde(default)]
12041 pub scope2: EmissionScopeConfig,
12042 #[serde(default)]
12044 pub scope3: Scope3Config,
12045 #[serde(default)]
12047 pub energy: EnergySchemaConfig,
12048 #[serde(default)]
12050 pub water: WaterSchemaConfig,
12051 #[serde(default)]
12053 pub waste: WasteSchemaConfig,
12054}
12055
12056impl Default for EnvironmentalConfig {
12057 fn default() -> Self {
12058 Self {
12059 enabled: true,
12060 scope1: EmissionScopeConfig::default(),
12061 scope2: EmissionScopeConfig::default(),
12062 scope3: Scope3Config::default(),
12063 energy: EnergySchemaConfig::default(),
12064 water: WaterSchemaConfig::default(),
12065 waste: WasteSchemaConfig::default(),
12066 }
12067 }
12068}
12069
12070#[derive(Debug, Clone, Serialize, Deserialize)]
12072pub struct EmissionScopeConfig {
12073 #[serde(default = "default_true")]
12075 pub enabled: bool,
12076 #[serde(default = "default_emission_region")]
12078 pub factor_region: String,
12079}
12080
12081fn default_emission_region() -> String {
12082 "US".to_string()
12083}
12084
12085impl Default for EmissionScopeConfig {
12086 fn default() -> Self {
12087 Self {
12088 enabled: true,
12089 factor_region: default_emission_region(),
12090 }
12091 }
12092}
12093
12094#[derive(Debug, Clone, Serialize, Deserialize)]
12096pub struct Scope3Config {
12097 #[serde(default = "default_true")]
12099 pub enabled: bool,
12100 #[serde(default = "default_scope3_categories")]
12102 pub categories: Vec<String>,
12103 #[serde(default = "default_spend_intensity")]
12105 pub default_spend_intensity_kg_per_usd: f64,
12106}
12107
12108fn default_scope3_categories() -> Vec<String> {
12109 vec![
12110 "purchased_goods".to_string(),
12111 "business_travel".to_string(),
12112 "employee_commuting".to_string(),
12113 ]
12114}
12115
12116fn default_spend_intensity() -> f64 {
12117 0.5
12118}
12119
12120impl Default for Scope3Config {
12121 fn default() -> Self {
12122 Self {
12123 enabled: true,
12124 categories: default_scope3_categories(),
12125 default_spend_intensity_kg_per_usd: default_spend_intensity(),
12126 }
12127 }
12128}
12129
12130#[derive(Debug, Clone, Serialize, Deserialize)]
12132pub struct EnergySchemaConfig {
12133 #[serde(default = "default_true")]
12135 pub enabled: bool,
12136 #[serde(default = "default_facility_count")]
12138 pub facility_count: u32,
12139 #[serde(default = "default_renewable_target")]
12141 pub renewable_target: f64,
12142}
12143
12144fn default_facility_count() -> u32 {
12145 5
12146}
12147
12148fn default_renewable_target() -> f64 {
12149 0.30
12150}
12151
12152impl Default for EnergySchemaConfig {
12153 fn default() -> Self {
12154 Self {
12155 enabled: true,
12156 facility_count: default_facility_count(),
12157 renewable_target: default_renewable_target(),
12158 }
12159 }
12160}
12161
12162#[derive(Debug, Clone, Serialize, Deserialize)]
12164pub struct WaterSchemaConfig {
12165 #[serde(default = "default_true")]
12167 pub enabled: bool,
12168 #[serde(default = "default_water_facility_count")]
12170 pub facility_count: u32,
12171}
12172
12173fn default_water_facility_count() -> u32 {
12174 3
12175}
12176
12177impl Default for WaterSchemaConfig {
12178 fn default() -> Self {
12179 Self {
12180 enabled: true,
12181 facility_count: default_water_facility_count(),
12182 }
12183 }
12184}
12185
12186#[derive(Debug, Clone, Serialize, Deserialize)]
12188pub struct WasteSchemaConfig {
12189 #[serde(default = "default_true")]
12191 pub enabled: bool,
12192 #[serde(default = "default_diversion_target")]
12194 pub diversion_target: f64,
12195}
12196
12197fn default_diversion_target() -> f64 {
12198 0.50
12199}
12200
12201impl Default for WasteSchemaConfig {
12202 fn default() -> Self {
12203 Self {
12204 enabled: true,
12205 diversion_target: default_diversion_target(),
12206 }
12207 }
12208}
12209
12210#[derive(Debug, Clone, Serialize, Deserialize)]
12212pub struct SocialConfig {
12213 #[serde(default = "default_true")]
12215 pub enabled: bool,
12216 #[serde(default)]
12218 pub diversity: DiversitySchemaConfig,
12219 #[serde(default)]
12221 pub pay_equity: PayEquitySchemaConfig,
12222 #[serde(default)]
12224 pub safety: SafetySchemaConfig,
12225}
12226
12227impl Default for SocialConfig {
12228 fn default() -> Self {
12229 Self {
12230 enabled: true,
12231 diversity: DiversitySchemaConfig::default(),
12232 pay_equity: PayEquitySchemaConfig::default(),
12233 safety: SafetySchemaConfig::default(),
12234 }
12235 }
12236}
12237
12238#[derive(Debug, Clone, Serialize, Deserialize)]
12240pub struct DiversitySchemaConfig {
12241 #[serde(default = "default_true")]
12243 pub enabled: bool,
12244 #[serde(default = "default_diversity_dimensions")]
12246 pub dimensions: Vec<String>,
12247}
12248
12249fn default_diversity_dimensions() -> Vec<String> {
12250 vec![
12251 "gender".to_string(),
12252 "ethnicity".to_string(),
12253 "age_group".to_string(),
12254 ]
12255}
12256
12257impl Default for DiversitySchemaConfig {
12258 fn default() -> Self {
12259 Self {
12260 enabled: true,
12261 dimensions: default_diversity_dimensions(),
12262 }
12263 }
12264}
12265
12266#[derive(Debug, Clone, Serialize, Deserialize)]
12268pub struct PayEquitySchemaConfig {
12269 #[serde(default = "default_true")]
12271 pub enabled: bool,
12272 #[serde(default = "default_pay_gap_threshold")]
12274 pub gap_threshold: f64,
12275}
12276
12277fn default_pay_gap_threshold() -> f64 {
12278 0.05
12279}
12280
12281impl Default for PayEquitySchemaConfig {
12282 fn default() -> Self {
12283 Self {
12284 enabled: true,
12285 gap_threshold: default_pay_gap_threshold(),
12286 }
12287 }
12288}
12289
12290#[derive(Debug, Clone, Serialize, Deserialize)]
12292pub struct SafetySchemaConfig {
12293 #[serde(default = "default_true")]
12295 pub enabled: bool,
12296 #[serde(default = "default_trir_target")]
12298 pub target_trir: f64,
12299 #[serde(default = "default_incident_count")]
12301 pub incident_count: u32,
12302}
12303
12304fn default_trir_target() -> f64 {
12305 2.5
12306}
12307
12308fn default_incident_count() -> u32 {
12309 20
12310}
12311
12312impl Default for SafetySchemaConfig {
12313 fn default() -> Self {
12314 Self {
12315 enabled: true,
12316 target_trir: default_trir_target(),
12317 incident_count: default_incident_count(),
12318 }
12319 }
12320}
12321
12322#[derive(Debug, Clone, Serialize, Deserialize)]
12324pub struct GovernanceSchemaConfig {
12325 #[serde(default = "default_true")]
12327 pub enabled: bool,
12328 #[serde(default = "default_board_size")]
12330 pub board_size: u32,
12331 #[serde(default = "default_independence_target")]
12333 pub independence_target: f64,
12334}
12335
12336fn default_board_size() -> u32 {
12337 11
12338}
12339
12340fn default_independence_target() -> f64 {
12341 0.67
12342}
12343
12344impl Default for GovernanceSchemaConfig {
12345 fn default() -> Self {
12346 Self {
12347 enabled: true,
12348 board_size: default_board_size(),
12349 independence_target: default_independence_target(),
12350 }
12351 }
12352}
12353
12354#[derive(Debug, Clone, Serialize, Deserialize)]
12356pub struct SupplyChainEsgConfig {
12357 #[serde(default = "default_true")]
12359 pub enabled: bool,
12360 #[serde(default = "default_assessment_coverage")]
12362 pub assessment_coverage: f64,
12363 #[serde(default = "default_high_risk_countries")]
12365 pub high_risk_countries: Vec<String>,
12366}
12367
12368fn default_assessment_coverage() -> f64 {
12369 0.80
12370}
12371
12372fn default_high_risk_countries() -> Vec<String> {
12373 vec!["CN".to_string(), "BD".to_string(), "MM".to_string()]
12374}
12375
12376impl Default for SupplyChainEsgConfig {
12377 fn default() -> Self {
12378 Self {
12379 enabled: true,
12380 assessment_coverage: default_assessment_coverage(),
12381 high_risk_countries: default_high_risk_countries(),
12382 }
12383 }
12384}
12385
12386#[derive(Debug, Clone, Serialize, Deserialize)]
12388pub struct EsgReportingConfig {
12389 #[serde(default = "default_true")]
12391 pub enabled: bool,
12392 #[serde(default = "default_esg_frameworks")]
12394 pub frameworks: Vec<String>,
12395 #[serde(default = "default_true")]
12397 pub materiality_assessment: bool,
12398 #[serde(default = "default_materiality_threshold")]
12400 pub impact_threshold: f64,
12401 #[serde(default = "default_materiality_threshold")]
12403 pub financial_threshold: f64,
12404}
12405
12406fn default_esg_frameworks() -> Vec<String> {
12407 vec!["GRI".to_string(), "ESRS".to_string()]
12408}
12409
12410fn default_materiality_threshold() -> f64 {
12411 0.6
12412}
12413
12414impl Default for EsgReportingConfig {
12415 fn default() -> Self {
12416 Self {
12417 enabled: true,
12418 frameworks: default_esg_frameworks(),
12419 materiality_assessment: true,
12420 impact_threshold: default_materiality_threshold(),
12421 financial_threshold: default_materiality_threshold(),
12422 }
12423 }
12424}
12425
12426#[derive(Debug, Clone, Serialize, Deserialize)]
12428pub struct ClimateScenarioConfig {
12429 #[serde(default)]
12431 pub enabled: bool,
12432 #[serde(default = "default_climate_scenarios")]
12434 pub scenarios: Vec<String>,
12435 #[serde(default = "default_time_horizons")]
12437 pub time_horizons: Vec<u32>,
12438}
12439
12440fn default_climate_scenarios() -> Vec<String> {
12441 vec![
12442 "net_zero_2050".to_string(),
12443 "stated_policies".to_string(),
12444 "current_trajectory".to_string(),
12445 ]
12446}
12447
12448fn default_time_horizons() -> Vec<u32> {
12449 vec![5, 10, 30]
12450}
12451
12452impl Default for ClimateScenarioConfig {
12453 fn default() -> Self {
12454 Self {
12455 enabled: false,
12456 scenarios: default_climate_scenarios(),
12457 time_horizons: default_time_horizons(),
12458 }
12459 }
12460}
12461
12462#[derive(Debug, Clone, Serialize, Deserialize, Default)]
12466pub struct ScenariosConfig {
12467 #[serde(default)]
12469 pub enabled: bool,
12470 #[serde(default)]
12472 pub scenarios: Vec<ScenarioSchemaConfig>,
12473 #[serde(default)]
12475 pub causal_model: CausalModelSchemaConfig,
12476 #[serde(default)]
12478 pub defaults: ScenarioDefaultsConfig,
12479 #[serde(default)]
12482 pub generate_counterfactuals: bool,
12483}
12484
12485#[derive(Debug, Clone, Serialize, Deserialize)]
12487pub struct ScenarioSchemaConfig {
12488 pub name: String,
12490 #[serde(default)]
12492 pub description: String,
12493 #[serde(default)]
12495 pub tags: Vec<String>,
12496 pub base: Option<String>,
12498 pub probability_weight: Option<f64>,
12500 #[serde(default)]
12502 pub interventions: Vec<InterventionSchemaConfig>,
12503 #[serde(default)]
12505 pub constraints: ScenarioConstraintsSchemaConfig,
12506 #[serde(default)]
12508 pub output: ScenarioOutputSchemaConfig,
12509 #[serde(default)]
12511 pub metadata: std::collections::HashMap<String, String>,
12512}
12513
12514#[derive(Debug, Clone, Serialize, Deserialize)]
12516pub struct InterventionSchemaConfig {
12517 #[serde(flatten)]
12519 pub intervention_type: serde_json::Value,
12520 #[serde(default)]
12522 pub timing: InterventionTimingSchemaConfig,
12523 pub label: Option<String>,
12525 #[serde(default)]
12527 pub priority: u32,
12528}
12529
12530#[derive(Debug, Clone, Serialize, Deserialize)]
12532pub struct InterventionTimingSchemaConfig {
12533 #[serde(default = "default_start_month")]
12535 pub start_month: u32,
12536 pub duration_months: Option<u32>,
12538 #[serde(default = "default_onset")]
12540 pub onset: String,
12541 pub ramp_months: Option<u32>,
12543}
12544
12545fn default_start_month() -> u32 {
12546 1
12547}
12548
12549fn default_onset() -> String {
12550 "sudden".to_string()
12551}
12552
12553impl Default for InterventionTimingSchemaConfig {
12554 fn default() -> Self {
12555 Self {
12556 start_month: 1,
12557 duration_months: None,
12558 onset: "sudden".to_string(),
12559 ramp_months: None,
12560 }
12561 }
12562}
12563
12564#[derive(Debug, Clone, Serialize, Deserialize)]
12566pub struct ScenarioConstraintsSchemaConfig {
12567 #[serde(default = "default_true")]
12568 pub preserve_accounting_identity: bool,
12569 #[serde(default = "default_true")]
12570 pub preserve_document_chains: bool,
12571 #[serde(default = "default_true")]
12572 pub preserve_period_close: bool,
12573 #[serde(default = "default_true")]
12574 pub preserve_balance_coherence: bool,
12575 #[serde(default)]
12576 pub custom: Vec<CustomConstraintSchemaConfig>,
12577}
12578
12579impl Default for ScenarioConstraintsSchemaConfig {
12580 fn default() -> Self {
12581 Self {
12582 preserve_accounting_identity: true,
12583 preserve_document_chains: true,
12584 preserve_period_close: true,
12585 preserve_balance_coherence: true,
12586 custom: Vec::new(),
12587 }
12588 }
12589}
12590
12591#[derive(Debug, Clone, Serialize, Deserialize)]
12593pub struct CustomConstraintSchemaConfig {
12594 pub config_path: String,
12595 pub min: Option<f64>,
12596 pub max: Option<f64>,
12597 #[serde(default)]
12598 pub description: String,
12599}
12600
12601#[derive(Debug, Clone, Serialize, Deserialize)]
12603pub struct ScenarioOutputSchemaConfig {
12604 #[serde(default = "default_true")]
12605 pub paired: bool,
12606 #[serde(default = "default_diff_formats_schema")]
12607 pub diff_formats: Vec<String>,
12608 #[serde(default)]
12609 pub diff_scope: Vec<String>,
12610}
12611
12612fn default_diff_formats_schema() -> Vec<String> {
12613 vec!["summary".to_string(), "aggregate".to_string()]
12614}
12615
12616impl Default for ScenarioOutputSchemaConfig {
12617 fn default() -> Self {
12618 Self {
12619 paired: true,
12620 diff_formats: default_diff_formats_schema(),
12621 diff_scope: Vec::new(),
12622 }
12623 }
12624}
12625
12626#[derive(Debug, Clone, Serialize, Deserialize)]
12628pub struct CausalModelSchemaConfig {
12629 #[serde(default = "default_causal_preset")]
12631 pub preset: String,
12632 #[serde(default)]
12634 pub nodes: Vec<serde_json::Value>,
12635 #[serde(default)]
12637 pub edges: Vec<serde_json::Value>,
12638}
12639
12640fn default_causal_preset() -> String {
12641 "default".to_string()
12642}
12643
12644impl Default for CausalModelSchemaConfig {
12645 fn default() -> Self {
12646 Self {
12647 preset: "default".to_string(),
12648 nodes: Vec::new(),
12649 edges: Vec::new(),
12650 }
12651 }
12652}
12653
12654#[derive(Debug, Clone, Serialize, Deserialize, Default)]
12656pub struct ScenarioDefaultsConfig {
12657 #[serde(default)]
12658 pub constraints: ScenarioConstraintsSchemaConfig,
12659 #[serde(default)]
12660 pub output: ScenarioOutputSchemaConfig,
12661}
12662
12663#[derive(Debug, Clone, Default, Serialize, Deserialize)]
12696pub struct ComplianceRegulationsConfig {
12697 #[serde(default)]
12699 pub enabled: bool,
12700 #[serde(default)]
12703 pub jurisdictions: Vec<String>,
12704 #[serde(default)]
12707 pub reference_date: Option<String>,
12708 #[serde(default)]
12710 pub standards_selection: StandardsSelectionConfig,
12711 #[serde(default)]
12713 pub audit_procedures: AuditProcedureGenConfig,
12714 #[serde(default)]
12716 pub findings: ComplianceFindingGenConfig,
12717 #[serde(default)]
12719 pub filings: ComplianceFilingGenConfig,
12720 #[serde(default)]
12722 pub graph: ComplianceGraphConfig,
12723 #[serde(default)]
12725 pub output: ComplianceOutputConfig,
12726}
12727
12728#[derive(Debug, Clone, Default, Serialize, Deserialize)]
12730pub struct StandardsSelectionConfig {
12731 #[serde(default)]
12734 pub categories: Vec<String>,
12735 #[serde(default)]
12738 pub include: Vec<String>,
12739 #[serde(default)]
12741 pub exclude: Vec<String>,
12742 #[serde(default)]
12744 pub include_superseded: bool,
12745}
12746
12747#[derive(Debug, Clone, Serialize, Deserialize)]
12749pub struct AuditProcedureGenConfig {
12750 #[serde(default)]
12752 pub enabled: bool,
12753 #[serde(default = "default_procedures_per_standard")]
12755 pub procedures_per_standard: usize,
12756 #[serde(default = "default_sampling_method")]
12758 pub sampling_method: String,
12759 #[serde(default = "default_confidence_level")]
12761 pub confidence_level: f64,
12762 #[serde(default = "default_tolerable_misstatement")]
12764 pub tolerable_misstatement: f64,
12765}
12766
12767fn default_procedures_per_standard() -> usize {
12768 3
12769}
12770
12771fn default_sampling_method() -> String {
12772 "statistical".to_string()
12773}
12774
12775fn default_confidence_level() -> f64 {
12776 0.95
12777}
12778
12779fn default_tolerable_misstatement() -> f64 {
12780 0.05
12781}
12782
12783impl Default for AuditProcedureGenConfig {
12784 fn default() -> Self {
12785 Self {
12786 enabled: false,
12787 procedures_per_standard: default_procedures_per_standard(),
12788 sampling_method: default_sampling_method(),
12789 confidence_level: default_confidence_level(),
12790 tolerable_misstatement: default_tolerable_misstatement(),
12791 }
12792 }
12793}
12794
12795#[derive(Debug, Clone, Serialize, Deserialize)]
12797pub struct ComplianceFindingGenConfig {
12798 #[serde(default)]
12800 pub enabled: bool,
12801 #[serde(default = "default_finding_rate")]
12803 pub finding_rate: f64,
12804 #[serde(default = "default_cr_material_weakness_rate")]
12806 pub material_weakness_rate: f64,
12807 #[serde(default = "default_cr_significant_deficiency_rate")]
12809 pub significant_deficiency_rate: f64,
12810 #[serde(default = "default_true")]
12812 pub generate_remediation: bool,
12813}
12814
12815fn default_finding_rate() -> f64 {
12816 0.05
12817}
12818
12819fn default_cr_material_weakness_rate() -> f64 {
12820 0.02
12821}
12822
12823fn default_cr_significant_deficiency_rate() -> f64 {
12824 0.08
12825}
12826
12827impl Default for ComplianceFindingGenConfig {
12828 fn default() -> Self {
12829 Self {
12830 enabled: false,
12831 finding_rate: default_finding_rate(),
12832 material_weakness_rate: default_cr_material_weakness_rate(),
12833 significant_deficiency_rate: default_cr_significant_deficiency_rate(),
12834 generate_remediation: true,
12835 }
12836 }
12837}
12838
12839#[derive(Debug, Clone, Serialize, Deserialize)]
12841pub struct ComplianceFilingGenConfig {
12842 #[serde(default)]
12844 pub enabled: bool,
12845 #[serde(default)]
12848 pub filing_types: Vec<String>,
12849 #[serde(default = "default_true")]
12851 pub generate_status_progression: bool,
12852}
12853
12854impl Default for ComplianceFilingGenConfig {
12855 fn default() -> Self {
12856 Self {
12857 enabled: false,
12858 filing_types: Vec::new(),
12859 generate_status_progression: true,
12860 }
12861 }
12862}
12863
12864#[derive(Debug, Clone, Serialize, Deserialize)]
12866pub struct ComplianceGraphConfig {
12867 #[serde(default)]
12869 pub enabled: bool,
12870 #[serde(default = "default_true")]
12872 pub include_compliance_nodes: bool,
12873 #[serde(default = "default_true")]
12875 pub include_compliance_edges: bool,
12876 #[serde(default = "default_true")]
12878 pub include_cross_references: bool,
12879 #[serde(default)]
12881 pub include_supersession_edges: bool,
12882 #[serde(default = "default_true")]
12884 pub include_account_links: bool,
12885 #[serde(default = "default_true")]
12887 pub include_control_links: bool,
12888 #[serde(default = "default_true")]
12890 pub include_company_links: bool,
12891}
12892
12893impl Default for ComplianceGraphConfig {
12894 fn default() -> Self {
12895 Self {
12896 enabled: false,
12897 include_compliance_nodes: true,
12898 include_compliance_edges: true,
12899 include_cross_references: true,
12900 include_supersession_edges: false,
12901 include_account_links: true,
12902 include_control_links: true,
12903 include_company_links: true,
12904 }
12905 }
12906}
12907
12908#[derive(Debug, Clone, Serialize, Deserialize)]
12910pub struct ComplianceOutputConfig {
12911 #[serde(default = "default_true")]
12913 pub export_registry: bool,
12914 #[serde(default = "default_true")]
12916 pub export_jurisdictions: bool,
12917 #[serde(default = "default_true")]
12919 pub export_cross_references: bool,
12920 #[serde(default)]
12922 pub export_version_history: bool,
12923}
12924
12925impl Default for ComplianceOutputConfig {
12926 fn default() -> Self {
12927 Self {
12928 export_registry: true,
12929 export_jurisdictions: true,
12930 export_cross_references: true,
12931 export_version_history: false,
12932 }
12933 }
12934}
12935
12936#[cfg(test)]
12937#[allow(clippy::unwrap_used)]
12938mod tests {
12939 use super::*;
12940 use crate::presets::demo_preset;
12941
12942 #[test]
12947 fn test_config_yaml_roundtrip() {
12948 let config = demo_preset();
12949 let yaml = serde_yaml::to_string(&config).expect("Failed to serialize to YAML");
12950 let deserialized: GeneratorConfig =
12951 serde_yaml::from_str(&yaml).expect("Failed to deserialize from YAML");
12952
12953 assert_eq!(
12954 config.global.period_months,
12955 deserialized.global.period_months
12956 );
12957 assert_eq!(config.global.industry, deserialized.global.industry);
12958 assert_eq!(config.companies.len(), deserialized.companies.len());
12959 assert_eq!(config.companies[0].code, deserialized.companies[0].code);
12960 }
12961
12962 #[test]
12963 fn test_config_json_roundtrip() {
12964 let mut config = demo_preset();
12966 config.master_data.employees.approval_limits.executive = 1e12;
12968
12969 let json = serde_json::to_string(&config).expect("Failed to serialize to JSON");
12970 let deserialized: GeneratorConfig =
12971 serde_json::from_str(&json).expect("Failed to deserialize from JSON");
12972
12973 assert_eq!(
12974 config.global.period_months,
12975 deserialized.global.period_months
12976 );
12977 assert_eq!(config.global.industry, deserialized.global.industry);
12978 assert_eq!(config.companies.len(), deserialized.companies.len());
12979 }
12980
12981 #[test]
12982 fn test_transaction_volume_serialization() {
12983 let volumes = vec![
12985 (TransactionVolume::TenK, "ten_k"),
12986 (TransactionVolume::HundredK, "hundred_k"),
12987 (TransactionVolume::OneM, "one_m"),
12988 (TransactionVolume::TenM, "ten_m"),
12989 (TransactionVolume::HundredM, "hundred_m"),
12990 ];
12991
12992 for (volume, expected_key) in volumes {
12993 let json = serde_json::to_string(&volume).expect("Failed to serialize");
12994 assert!(
12995 json.contains(expected_key),
12996 "Expected {} in JSON: {}",
12997 expected_key,
12998 json
12999 );
13000 }
13001 }
13002
13003 #[test]
13004 fn test_transaction_volume_custom_serialization() {
13005 let volume = TransactionVolume::Custom(12345);
13006 let json = serde_json::to_string(&volume).expect("Failed to serialize");
13007 let deserialized: TransactionVolume =
13008 serde_json::from_str(&json).expect("Failed to deserialize");
13009 assert_eq!(deserialized.count(), 12345);
13010 }
13011
13012 #[test]
13013 fn test_output_mode_serialization() {
13014 let modes = vec![
13015 OutputMode::Streaming,
13016 OutputMode::FlatFile,
13017 OutputMode::Both,
13018 ];
13019
13020 for mode in modes {
13021 let json = serde_json::to_string(&mode).expect("Failed to serialize");
13022 let deserialized: OutputMode =
13023 serde_json::from_str(&json).expect("Failed to deserialize");
13024 assert!(format!("{:?}", mode) == format!("{:?}", deserialized));
13025 }
13026 }
13027
13028 #[test]
13029 fn test_file_format_serialization() {
13030 let formats = vec![
13031 FileFormat::Csv,
13032 FileFormat::Parquet,
13033 FileFormat::Json,
13034 FileFormat::JsonLines,
13035 ];
13036
13037 for format in formats {
13038 let json = serde_json::to_string(&format).expect("Failed to serialize");
13039 let deserialized: FileFormat =
13040 serde_json::from_str(&json).expect("Failed to deserialize");
13041 assert!(format!("{:?}", format) == format!("{:?}", deserialized));
13042 }
13043 }
13044
13045 #[test]
13046 fn test_compression_algorithm_serialization() {
13047 let algos = vec![
13048 CompressionAlgorithm::Gzip,
13049 CompressionAlgorithm::Zstd,
13050 CompressionAlgorithm::Lz4,
13051 CompressionAlgorithm::Snappy,
13052 ];
13053
13054 for algo in algos {
13055 let json = serde_json::to_string(&algo).expect("Failed to serialize");
13056 let deserialized: CompressionAlgorithm =
13057 serde_json::from_str(&json).expect("Failed to deserialize");
13058 assert!(format!("{:?}", algo) == format!("{:?}", deserialized));
13059 }
13060 }
13061
13062 #[test]
13063 fn test_transfer_pricing_method_serialization() {
13064 let methods = vec![
13065 TransferPricingMethod::CostPlus,
13066 TransferPricingMethod::ComparableUncontrolled,
13067 TransferPricingMethod::ResalePrice,
13068 TransferPricingMethod::TransactionalNetMargin,
13069 TransferPricingMethod::ProfitSplit,
13070 ];
13071
13072 for method in methods {
13073 let json = serde_json::to_string(&method).expect("Failed to serialize");
13074 let deserialized: TransferPricingMethod =
13075 serde_json::from_str(&json).expect("Failed to deserialize");
13076 assert!(format!("{:?}", method) == format!("{:?}", deserialized));
13077 }
13078 }
13079
13080 #[test]
13081 fn test_benford_exemption_serialization() {
13082 let exemptions = vec![
13083 BenfordExemption::Recurring,
13084 BenfordExemption::Payroll,
13085 BenfordExemption::FixedFees,
13086 BenfordExemption::RoundAmounts,
13087 ];
13088
13089 for exemption in exemptions {
13090 let json = serde_json::to_string(&exemption).expect("Failed to serialize");
13091 let deserialized: BenfordExemption =
13092 serde_json::from_str(&json).expect("Failed to deserialize");
13093 assert!(format!("{:?}", exemption) == format!("{:?}", deserialized));
13094 }
13095 }
13096
13097 #[test]
13102 fn test_global_config_defaults() {
13103 let yaml = r#"
13104 industry: manufacturing
13105 start_date: "2024-01-01"
13106 period_months: 6
13107 "#;
13108 let config: GlobalConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13109 assert_eq!(config.group_currency, "USD");
13110 assert!(config.parallel);
13111 assert_eq!(config.worker_threads, 0);
13112 assert_eq!(config.memory_limit_mb, 0);
13113 }
13114
13115 #[test]
13116 fn test_fraud_config_defaults() {
13117 let config = FraudConfig::default();
13118 assert!(!config.enabled);
13119 assert_eq!(config.fraud_rate, 0.005);
13120 assert!(!config.clustering_enabled);
13121 }
13122
13123 #[test]
13124 fn test_internal_controls_config_defaults() {
13125 let config = InternalControlsConfig::default();
13126 assert!(!config.enabled);
13127 assert_eq!(config.exception_rate, 0.02);
13128 assert_eq!(config.sod_violation_rate, 0.01);
13129 assert!(config.export_control_master_data);
13130 assert_eq!(config.sox_materiality_threshold, 10000.0);
13131 assert!(config.coso_enabled);
13133 assert!(!config.include_entity_level_controls);
13134 assert_eq!(config.target_maturity_level, "mixed");
13135 }
13136
13137 #[test]
13138 fn test_output_config_defaults() {
13139 let config = OutputConfig::default();
13140 assert!(matches!(config.mode, OutputMode::FlatFile));
13141 assert_eq!(config.formats, vec![FileFormat::Parquet]);
13142 assert!(config.compression.enabled);
13143 assert!(matches!(
13144 config.compression.algorithm,
13145 CompressionAlgorithm::Zstd
13146 ));
13147 assert!(config.include_acdoca);
13148 assert!(!config.include_bseg);
13149 assert!(config.partition_by_period);
13150 assert!(!config.partition_by_company);
13151 }
13152
13153 #[test]
13154 fn test_approval_config_defaults() {
13155 let config = ApprovalConfig::default();
13156 assert!(!config.enabled);
13157 assert_eq!(config.auto_approve_threshold, 1000.0);
13158 assert_eq!(config.rejection_rate, 0.02);
13159 assert_eq!(config.revision_rate, 0.05);
13160 assert_eq!(config.average_approval_delay_hours, 4.0);
13161 assert_eq!(config.thresholds.len(), 4);
13162 }
13163
13164 #[test]
13165 fn test_p2p_flow_config_defaults() {
13166 let config = P2PFlowConfig::default();
13167 assert!(config.enabled);
13168 assert_eq!(config.three_way_match_rate, 0.95);
13169 assert_eq!(config.partial_delivery_rate, 0.15);
13170 assert_eq!(config.average_po_to_gr_days, 14);
13171 }
13172
13173 #[test]
13174 fn test_o2c_flow_config_defaults() {
13175 let config = O2CFlowConfig::default();
13176 assert!(config.enabled);
13177 assert_eq!(config.credit_check_failure_rate, 0.02);
13178 assert_eq!(config.return_rate, 0.03);
13179 assert_eq!(config.bad_debt_rate, 0.01);
13180 }
13181
13182 #[test]
13183 fn test_balance_config_defaults() {
13184 let config = BalanceConfig::default();
13185 assert!(!config.generate_opening_balances);
13186 assert!(config.generate_trial_balances);
13187 assert_eq!(config.target_gross_margin, 0.35);
13188 assert!(config.validate_balance_equation);
13189 assert!(config.reconcile_subledgers);
13190 }
13191
13192 #[test]
13197 fn test_partial_config_with_defaults() {
13198 let yaml = r#"
13200 global:
13201 industry: manufacturing
13202 start_date: "2024-01-01"
13203 period_months: 3
13204 companies:
13205 - code: "TEST"
13206 name: "Test Company"
13207 currency: "USD"
13208 country: "US"
13209 annual_transaction_volume: ten_k
13210 chart_of_accounts:
13211 complexity: small
13212 output:
13213 output_directory: "./output"
13214 "#;
13215
13216 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13217 assert_eq!(config.global.period_months, 3);
13218 assert_eq!(config.companies.len(), 1);
13219 assert!(!config.fraud.enabled); assert!(!config.internal_controls.enabled); }
13222
13223 #[test]
13224 fn test_config_with_fraud_enabled() {
13225 let yaml = r#"
13226 global:
13227 industry: retail
13228 start_date: "2024-01-01"
13229 period_months: 12
13230 companies:
13231 - code: "RETAIL"
13232 name: "Retail Co"
13233 currency: "USD"
13234 country: "US"
13235 annual_transaction_volume: hundred_k
13236 chart_of_accounts:
13237 complexity: medium
13238 output:
13239 output_directory: "./output"
13240 fraud:
13241 enabled: true
13242 fraud_rate: 0.05
13243 clustering_enabled: true
13244 "#;
13245
13246 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13247 assert!(config.fraud.enabled);
13248 assert_eq!(config.fraud.fraud_rate, 0.05);
13249 assert!(config.fraud.clustering_enabled);
13250 }
13251
13252 #[test]
13253 fn test_config_with_multiple_companies() {
13254 let yaml = r#"
13255 global:
13256 industry: manufacturing
13257 start_date: "2024-01-01"
13258 period_months: 6
13259 companies:
13260 - code: "HQ"
13261 name: "Headquarters"
13262 currency: "USD"
13263 country: "US"
13264 annual_transaction_volume: hundred_k
13265 volume_weight: 1.0
13266 - code: "EU"
13267 name: "European Subsidiary"
13268 currency: "EUR"
13269 country: "DE"
13270 annual_transaction_volume: hundred_k
13271 volume_weight: 0.5
13272 - code: "APAC"
13273 name: "Asia Pacific"
13274 currency: "JPY"
13275 country: "JP"
13276 annual_transaction_volume: ten_k
13277 volume_weight: 0.3
13278 chart_of_accounts:
13279 complexity: large
13280 output:
13281 output_directory: "./output"
13282 "#;
13283
13284 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13285 assert_eq!(config.companies.len(), 3);
13286 assert_eq!(config.companies[0].code, "HQ");
13287 assert_eq!(config.companies[1].currency, "EUR");
13288 assert_eq!(config.companies[2].volume_weight, 0.3);
13289 }
13290
13291 #[test]
13292 fn test_intercompany_config() {
13293 let yaml = r#"
13294 enabled: true
13295 ic_transaction_rate: 0.20
13296 transfer_pricing_method: cost_plus
13297 markup_percent: 0.08
13298 generate_matched_pairs: true
13299 generate_eliminations: true
13300 "#;
13301
13302 let config: IntercompanyConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13303 assert!(config.enabled);
13304 assert_eq!(config.ic_transaction_rate, 0.20);
13305 assert!(matches!(
13306 config.transfer_pricing_method,
13307 TransferPricingMethod::CostPlus
13308 ));
13309 assert_eq!(config.markup_percent, 0.08);
13310 assert!(config.generate_eliminations);
13311 }
13312
13313 #[test]
13318 fn test_company_config_defaults() {
13319 let yaml = r#"
13320 code: "TEST"
13321 name: "Test Company"
13322 currency: "USD"
13323 country: "US"
13324 annual_transaction_volume: ten_k
13325 "#;
13326
13327 let config: CompanyConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13328 assert_eq!(config.fiscal_year_variant, "K4"); assert_eq!(config.volume_weight, 1.0); }
13331
13332 #[test]
13337 fn test_coa_config_defaults() {
13338 let yaml = r#"
13339 complexity: medium
13340 "#;
13341
13342 let config: ChartOfAccountsConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13343 assert!(config.industry_specific); assert!(config.custom_accounts.is_none());
13345 assert_eq!(config.min_hierarchy_depth, 2); assert_eq!(config.max_hierarchy_depth, 5); }
13348
13349 #[test]
13354 fn test_accounting_standards_config_defaults() {
13355 let config = AccountingStandardsConfig::default();
13356 assert!(!config.enabled);
13357 assert!(config.framework.is_none());
13358 assert!(!config.revenue_recognition.enabled);
13359 assert!(!config.leases.enabled);
13360 assert!(!config.fair_value.enabled);
13361 assert!(!config.impairment.enabled);
13362 assert!(!config.generate_differences);
13363 }
13364
13365 #[test]
13366 fn test_accounting_standards_config_yaml() {
13367 let yaml = r#"
13368 enabled: true
13369 framework: ifrs
13370 revenue_recognition:
13371 enabled: true
13372 generate_contracts: true
13373 avg_obligations_per_contract: 2.5
13374 variable_consideration_rate: 0.20
13375 over_time_recognition_rate: 0.35
13376 contract_count: 150
13377 leases:
13378 enabled: true
13379 lease_count: 75
13380 finance_lease_percent: 0.25
13381 avg_lease_term_months: 48
13382 generate_differences: true
13383 "#;
13384
13385 let config: AccountingStandardsConfig =
13386 serde_yaml::from_str(yaml).expect("Failed to parse");
13387 assert!(config.enabled);
13388 assert!(matches!(
13389 config.framework,
13390 Some(AccountingFrameworkConfig::Ifrs)
13391 ));
13392 assert!(config.revenue_recognition.enabled);
13393 assert_eq!(config.revenue_recognition.contract_count, 150);
13394 assert_eq!(config.revenue_recognition.avg_obligations_per_contract, 2.5);
13395 assert!(config.leases.enabled);
13396 assert_eq!(config.leases.lease_count, 75);
13397 assert_eq!(config.leases.finance_lease_percent, 0.25);
13398 assert!(config.generate_differences);
13399 }
13400
13401 #[test]
13402 fn test_accounting_framework_serialization() {
13403 let frameworks = [
13404 AccountingFrameworkConfig::UsGaap,
13405 AccountingFrameworkConfig::Ifrs,
13406 AccountingFrameworkConfig::DualReporting,
13407 AccountingFrameworkConfig::FrenchGaap,
13408 AccountingFrameworkConfig::GermanGaap,
13409 ];
13410
13411 for framework in frameworks {
13412 let json = serde_json::to_string(&framework).expect("Failed to serialize");
13413 let deserialized: AccountingFrameworkConfig =
13414 serde_json::from_str(&json).expect("Failed to deserialize");
13415 assert!(format!("{:?}", framework) == format!("{:?}", deserialized));
13416 }
13417 }
13418
13419 #[test]
13420 fn test_revenue_recognition_config_defaults() {
13421 let config = RevenueRecognitionConfig::default();
13422 assert!(!config.enabled);
13423 assert!(config.generate_contracts);
13424 assert_eq!(config.avg_obligations_per_contract, 2.0);
13425 assert_eq!(config.variable_consideration_rate, 0.15);
13426 assert_eq!(config.over_time_recognition_rate, 0.30);
13427 assert_eq!(config.contract_count, 100);
13428 }
13429
13430 #[test]
13431 fn test_lease_accounting_config_defaults() {
13432 let config = LeaseAccountingConfig::default();
13433 assert!(!config.enabled);
13434 assert_eq!(config.lease_count, 50);
13435 assert_eq!(config.finance_lease_percent, 0.30);
13436 assert_eq!(config.avg_lease_term_months, 60);
13437 assert!(config.generate_amortization);
13438 assert_eq!(config.real_estate_percent, 0.40);
13439 }
13440
13441 #[test]
13442 fn test_fair_value_config_defaults() {
13443 let config = FairValueConfig::default();
13444 assert!(!config.enabled);
13445 assert_eq!(config.measurement_count, 25);
13446 assert_eq!(config.level1_percent, 0.40);
13447 assert_eq!(config.level2_percent, 0.35);
13448 assert_eq!(config.level3_percent, 0.25);
13449 assert!(!config.include_sensitivity_analysis);
13450 }
13451
13452 #[test]
13453 fn test_impairment_config_defaults() {
13454 let config = ImpairmentConfig::default();
13455 assert!(!config.enabled);
13456 assert_eq!(config.test_count, 15);
13457 assert_eq!(config.impairment_rate, 0.10);
13458 assert!(config.generate_projections);
13459 assert!(!config.include_goodwill);
13460 }
13461
13462 #[test]
13467 fn test_audit_standards_config_defaults() {
13468 let config = AuditStandardsConfig::default();
13469 assert!(!config.enabled);
13470 assert!(!config.isa_compliance.enabled);
13471 assert!(!config.analytical_procedures.enabled);
13472 assert!(!config.confirmations.enabled);
13473 assert!(!config.opinion.enabled);
13474 assert!(!config.generate_audit_trail);
13475 assert!(!config.sox.enabled);
13476 assert!(!config.pcaob.enabled);
13477 }
13478
13479 #[test]
13480 fn test_audit_standards_config_yaml() {
13481 let yaml = r#"
13482 enabled: true
13483 isa_compliance:
13484 enabled: true
13485 compliance_level: comprehensive
13486 generate_isa_mappings: true
13487 include_pcaob: true
13488 framework: dual
13489 analytical_procedures:
13490 enabled: true
13491 procedures_per_account: 5
13492 variance_probability: 0.25
13493 confirmations:
13494 enabled: true
13495 confirmation_count: 75
13496 positive_response_rate: 0.90
13497 exception_rate: 0.08
13498 opinion:
13499 enabled: true
13500 generate_kam: true
13501 average_kam_count: 4
13502 sox:
13503 enabled: true
13504 generate_302_certifications: true
13505 generate_404_assessments: true
13506 material_weakness_rate: 0.03
13507 pcaob:
13508 enabled: true
13509 is_pcaob_audit: true
13510 include_icfr_opinion: true
13511 generate_audit_trail: true
13512 "#;
13513
13514 let config: AuditStandardsConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13515 assert!(config.enabled);
13516 assert!(config.isa_compliance.enabled);
13517 assert_eq!(config.isa_compliance.compliance_level, "comprehensive");
13518 assert!(config.isa_compliance.include_pcaob);
13519 assert_eq!(config.isa_compliance.framework, "dual");
13520 assert!(config.analytical_procedures.enabled);
13521 assert_eq!(config.analytical_procedures.procedures_per_account, 5);
13522 assert!(config.confirmations.enabled);
13523 assert_eq!(config.confirmations.confirmation_count, 75);
13524 assert!(config.opinion.enabled);
13525 assert_eq!(config.opinion.average_kam_count, 4);
13526 assert!(config.sox.enabled);
13527 assert!(config.sox.generate_302_certifications);
13528 assert_eq!(config.sox.material_weakness_rate, 0.03);
13529 assert!(config.pcaob.enabled);
13530 assert!(config.pcaob.is_pcaob_audit);
13531 assert!(config.pcaob.include_icfr_opinion);
13532 assert!(config.generate_audit_trail);
13533 }
13534
13535 #[test]
13536 fn test_isa_compliance_config_defaults() {
13537 let config = IsaComplianceConfig::default();
13538 assert!(!config.enabled);
13539 assert_eq!(config.compliance_level, "standard");
13540 assert!(config.generate_isa_mappings);
13541 assert!(config.generate_coverage_summary);
13542 assert!(!config.include_pcaob);
13543 assert_eq!(config.framework, "isa");
13544 }
13545
13546 #[test]
13547 fn test_sox_compliance_config_defaults() {
13548 let config = SoxComplianceConfig::default();
13549 assert!(!config.enabled);
13550 assert!(config.generate_302_certifications);
13551 assert!(config.generate_404_assessments);
13552 assert_eq!(config.materiality_threshold, 10000.0);
13553 assert_eq!(config.material_weakness_rate, 0.02);
13554 assert_eq!(config.significant_deficiency_rate, 0.08);
13555 }
13556
13557 #[test]
13558 fn test_pcaob_config_defaults() {
13559 let config = PcaobConfig::default();
13560 assert!(!config.enabled);
13561 assert!(!config.is_pcaob_audit);
13562 assert!(config.generate_cam);
13563 assert!(!config.include_icfr_opinion);
13564 assert!(!config.generate_standard_mappings);
13565 }
13566
13567 #[test]
13568 fn test_config_with_standards_enabled() {
13569 let yaml = r#"
13570 global:
13571 industry: financial_services
13572 start_date: "2024-01-01"
13573 period_months: 12
13574 companies:
13575 - code: "BANK"
13576 name: "Test Bank"
13577 currency: "USD"
13578 country: "US"
13579 annual_transaction_volume: hundred_k
13580 chart_of_accounts:
13581 complexity: large
13582 output:
13583 output_directory: "./output"
13584 accounting_standards:
13585 enabled: true
13586 framework: us_gaap
13587 revenue_recognition:
13588 enabled: true
13589 leases:
13590 enabled: true
13591 audit_standards:
13592 enabled: true
13593 isa_compliance:
13594 enabled: true
13595 sox:
13596 enabled: true
13597 "#;
13598
13599 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13600 assert!(config.accounting_standards.enabled);
13601 assert!(matches!(
13602 config.accounting_standards.framework,
13603 Some(AccountingFrameworkConfig::UsGaap)
13604 ));
13605 assert!(config.accounting_standards.revenue_recognition.enabled);
13606 assert!(config.accounting_standards.leases.enabled);
13607 assert!(config.audit_standards.enabled);
13608 assert!(config.audit_standards.isa_compliance.enabled);
13609 assert!(config.audit_standards.sox.enabled);
13610 }
13611
13612 #[test]
13617 fn test_industry_specific_config_defaults() {
13618 let config = IndustrySpecificConfig::default();
13619 assert!(!config.enabled);
13620 assert!(!config.manufacturing.enabled);
13621 assert!(!config.retail.enabled);
13622 assert!(!config.healthcare.enabled);
13623 assert!(!config.technology.enabled);
13624 assert!(!config.financial_services.enabled);
13625 assert!(!config.professional_services.enabled);
13626 }
13627
13628 #[test]
13629 fn test_manufacturing_config_defaults() {
13630 let config = ManufacturingConfig::default();
13631 assert!(!config.enabled);
13632 assert_eq!(config.bom_depth, 4);
13633 assert!(!config.just_in_time);
13634 assert_eq!(config.supplier_tiers, 2);
13635 assert_eq!(config.target_yield_rate, 0.97);
13636 assert_eq!(config.scrap_alert_threshold, 0.03);
13637 }
13638
13639 #[test]
13640 fn test_retail_config_defaults() {
13641 let config = RetailConfig::default();
13642 assert!(!config.enabled);
13643 assert_eq!(config.avg_daily_transactions, 500);
13644 assert!(config.loss_prevention);
13645 assert_eq!(config.shrinkage_rate, 0.015);
13646 }
13647
13648 #[test]
13649 fn test_healthcare_config_defaults() {
13650 let config = HealthcareConfig::default();
13651 assert!(!config.enabled);
13652 assert_eq!(config.facility_type, "hospital");
13653 assert_eq!(config.avg_daily_encounters, 150);
13654 assert!(config.compliance.hipaa);
13655 assert!(config.compliance.stark_law);
13656 assert!(config.coding_systems.icd10);
13657 assert!(config.coding_systems.cpt);
13658 }
13659
13660 #[test]
13661 fn test_technology_config_defaults() {
13662 let config = TechnologyConfig::default();
13663 assert!(!config.enabled);
13664 assert_eq!(config.revenue_model, "saas");
13665 assert_eq!(config.subscription_revenue_pct, 0.60);
13666 assert!(config.rd_capitalization.enabled);
13667 }
13668
13669 #[test]
13670 fn test_config_with_industry_specific() {
13671 let yaml = r#"
13672 global:
13673 industry: healthcare
13674 start_date: "2024-01-01"
13675 period_months: 12
13676 companies:
13677 - code: "HOSP"
13678 name: "Test Hospital"
13679 currency: "USD"
13680 country: "US"
13681 annual_transaction_volume: hundred_k
13682 chart_of_accounts:
13683 complexity: medium
13684 output:
13685 output_directory: "./output"
13686 industry_specific:
13687 enabled: true
13688 healthcare:
13689 enabled: true
13690 facility_type: hospital
13691 payer_mix:
13692 medicare: 0.45
13693 medicaid: 0.15
13694 commercial: 0.35
13695 self_pay: 0.05
13696 coding_systems:
13697 icd10: true
13698 cpt: true
13699 drg: true
13700 compliance:
13701 hipaa: true
13702 stark_law: true
13703 anomaly_rates:
13704 upcoding: 0.03
13705 unbundling: 0.02
13706 "#;
13707
13708 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13709 assert!(config.industry_specific.enabled);
13710 assert!(config.industry_specific.healthcare.enabled);
13711 assert_eq!(
13712 config.industry_specific.healthcare.facility_type,
13713 "hospital"
13714 );
13715 assert_eq!(config.industry_specific.healthcare.payer_mix.medicare, 0.45);
13716 assert_eq!(config.industry_specific.healthcare.payer_mix.self_pay, 0.05);
13717 assert!(config.industry_specific.healthcare.coding_systems.icd10);
13718 assert!(config.industry_specific.healthcare.compliance.hipaa);
13719 assert_eq!(
13720 config.industry_specific.healthcare.anomaly_rates.upcoding,
13721 0.03
13722 );
13723 }
13724
13725 #[test]
13726 fn test_config_with_manufacturing_specific() {
13727 let yaml = r#"
13728 global:
13729 industry: manufacturing
13730 start_date: "2024-01-01"
13731 period_months: 12
13732 companies:
13733 - code: "MFG"
13734 name: "Test Manufacturing"
13735 currency: "USD"
13736 country: "US"
13737 annual_transaction_volume: hundred_k
13738 chart_of_accounts:
13739 complexity: medium
13740 output:
13741 output_directory: "./output"
13742 industry_specific:
13743 enabled: true
13744 manufacturing:
13745 enabled: true
13746 bom_depth: 5
13747 just_in_time: true
13748 supplier_tiers: 3
13749 target_yield_rate: 0.98
13750 anomaly_rates:
13751 yield_manipulation: 0.02
13752 phantom_production: 0.01
13753 "#;
13754
13755 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13756 assert!(config.industry_specific.enabled);
13757 assert!(config.industry_specific.manufacturing.enabled);
13758 assert_eq!(config.industry_specific.manufacturing.bom_depth, 5);
13759 assert!(config.industry_specific.manufacturing.just_in_time);
13760 assert_eq!(config.industry_specific.manufacturing.supplier_tiers, 3);
13761 assert_eq!(
13762 config.industry_specific.manufacturing.target_yield_rate,
13763 0.98
13764 );
13765 assert_eq!(
13766 config
13767 .industry_specific
13768 .manufacturing
13769 .anomaly_rates
13770 .yield_manipulation,
13771 0.02
13772 );
13773 }
13774
13775 #[test]
13780 fn test_tax_config_defaults() {
13781 let tax = TaxConfig::default();
13782 assert!(!tax.enabled);
13783 assert!(tax.jurisdictions.countries.is_empty());
13784 assert!(!tax.jurisdictions.include_subnational);
13785 assert!(!tax.vat_gst.enabled);
13786 assert!(tax.vat_gst.standard_rates.is_empty());
13787 assert!(tax.vat_gst.reduced_rates.is_empty());
13788 assert!(tax.vat_gst.exempt_categories.is_empty());
13789 assert!(tax.vat_gst.reverse_charge);
13790 assert!(!tax.sales_tax.enabled);
13791 assert!(tax.sales_tax.nexus_states.is_empty());
13792 assert!(!tax.withholding.enabled);
13793 assert!(tax.withholding.treaty_network);
13794 assert_eq!(tax.withholding.default_rate, 0.30);
13795 assert_eq!(tax.withholding.treaty_reduced_rate, 0.15);
13796 assert!(tax.provisions.enabled);
13797 assert_eq!(tax.provisions.statutory_rate, 0.21);
13798 assert!(tax.provisions.uncertain_positions);
13799 assert!(!tax.payroll_tax.enabled);
13800 assert_eq!(tax.anomaly_rate, 0.03);
13801 }
13802
13803 #[test]
13804 fn test_tax_config_from_yaml() {
13805 let yaml = r#"
13806 global:
13807 seed: 42
13808 start_date: "2024-01-01"
13809 period_months: 12
13810 industry: retail
13811 companies:
13812 - code: C001
13813 name: Test Corp
13814 currency: USD
13815 country: US
13816 annual_transaction_volume: ten_k
13817 chart_of_accounts:
13818 complexity: small
13819 output:
13820 output_directory: ./output
13821 tax:
13822 enabled: true
13823 anomaly_rate: 0.05
13824 jurisdictions:
13825 countries: ["US", "DE", "GB"]
13826 include_subnational: true
13827 vat_gst:
13828 enabled: true
13829 standard_rates:
13830 DE: 0.19
13831 GB: 0.20
13832 reduced_rates:
13833 DE: 0.07
13834 GB: 0.05
13835 exempt_categories:
13836 - financial_services
13837 - healthcare
13838 reverse_charge: false
13839 sales_tax:
13840 enabled: true
13841 nexus_states: ["CA", "NY", "TX"]
13842 withholding:
13843 enabled: true
13844 treaty_network: false
13845 default_rate: 0.25
13846 treaty_reduced_rate: 0.10
13847 provisions:
13848 enabled: false
13849 statutory_rate: 0.28
13850 uncertain_positions: false
13851 payroll_tax:
13852 enabled: true
13853 "#;
13854
13855 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13856 assert!(config.tax.enabled);
13857 assert_eq!(config.tax.anomaly_rate, 0.05);
13858
13859 assert_eq!(config.tax.jurisdictions.countries.len(), 3);
13861 assert!(config
13862 .tax
13863 .jurisdictions
13864 .countries
13865 .contains(&"DE".to_string()));
13866 assert!(config.tax.jurisdictions.include_subnational);
13867
13868 assert!(config.tax.vat_gst.enabled);
13870 assert_eq!(config.tax.vat_gst.standard_rates.get("DE"), Some(&0.19));
13871 assert_eq!(config.tax.vat_gst.standard_rates.get("GB"), Some(&0.20));
13872 assert_eq!(config.tax.vat_gst.reduced_rates.get("DE"), Some(&0.07));
13873 assert_eq!(config.tax.vat_gst.exempt_categories.len(), 2);
13874 assert!(!config.tax.vat_gst.reverse_charge);
13875
13876 assert!(config.tax.sales_tax.enabled);
13878 assert_eq!(config.tax.sales_tax.nexus_states.len(), 3);
13879 assert!(config
13880 .tax
13881 .sales_tax
13882 .nexus_states
13883 .contains(&"CA".to_string()));
13884
13885 assert!(config.tax.withholding.enabled);
13887 assert!(!config.tax.withholding.treaty_network);
13888 assert_eq!(config.tax.withholding.default_rate, 0.25);
13889 assert_eq!(config.tax.withholding.treaty_reduced_rate, 0.10);
13890
13891 assert!(!config.tax.provisions.enabled);
13893 assert_eq!(config.tax.provisions.statutory_rate, 0.28);
13894 assert!(!config.tax.provisions.uncertain_positions);
13895
13896 assert!(config.tax.payroll_tax.enabled);
13898 }
13899
13900 #[test]
13901 fn test_generator_config_with_tax_default() {
13902 let yaml = r#"
13903 global:
13904 seed: 42
13905 start_date: "2024-01-01"
13906 period_months: 12
13907 industry: retail
13908 companies:
13909 - code: C001
13910 name: Test Corp
13911 currency: USD
13912 country: US
13913 annual_transaction_volume: ten_k
13914 chart_of_accounts:
13915 complexity: small
13916 output:
13917 output_directory: ./output
13918 "#;
13919
13920 let config: GeneratorConfig =
13921 serde_yaml::from_str(yaml).expect("Failed to parse config without tax section");
13922 assert!(!config.tax.enabled);
13924 assert!(config.tax.jurisdictions.countries.is_empty());
13925 assert_eq!(config.tax.anomaly_rate, 0.03);
13926 assert!(config.tax.provisions.enabled); assert_eq!(config.tax.provisions.statutory_rate, 0.21);
13928 }
13929
13930 #[test]
13935 fn test_session_config_default_disabled() {
13936 let yaml = "{}";
13937 let config: SessionSchemaConfig =
13938 serde_yaml::from_str(yaml).expect("Failed to parse empty session config");
13939 assert!(!config.enabled);
13940 assert!(config.checkpoint_path.is_none());
13941 assert!(config.per_period_output);
13942 assert!(config.consolidated_output);
13943 }
13944
13945 #[test]
13946 fn test_config_backward_compatible_without_session() {
13947 let yaml = r#"
13948 global:
13949 seed: 42
13950 start_date: "2024-01-01"
13951 period_months: 12
13952 industry: retail
13953 companies:
13954 - code: C001
13955 name: Test Corp
13956 currency: USD
13957 country: US
13958 annual_transaction_volume: ten_k
13959 chart_of_accounts:
13960 complexity: small
13961 output:
13962 output_directory: ./output
13963 "#;
13964
13965 let config: GeneratorConfig =
13966 serde_yaml::from_str(yaml).expect("Failed to parse config without session");
13967 assert!(!config.session.enabled);
13969 assert!(config.session.per_period_output);
13970 assert!(config.session.consolidated_output);
13971 assert!(config.global.fiscal_year_months.is_none());
13973 }
13974
13975 #[test]
13976 fn test_fiscal_year_months_parsed() {
13977 let yaml = r#"
13978 global:
13979 seed: 42
13980 start_date: "2024-01-01"
13981 period_months: 24
13982 industry: retail
13983 fiscal_year_months: 12
13984 companies:
13985 - code: C001
13986 name: Test Corp
13987 currency: USD
13988 country: US
13989 annual_transaction_volume: ten_k
13990 chart_of_accounts:
13991 complexity: small
13992 output:
13993 output_directory: ./output
13994 session:
13995 enabled: true
13996 checkpoint_path: /tmp/checkpoints
13997 per_period_output: true
13998 consolidated_output: false
13999 "#;
14000
14001 let config: GeneratorConfig =
14002 serde_yaml::from_str(yaml).expect("Failed to parse config with fiscal_year_months");
14003 assert_eq!(config.global.fiscal_year_months, Some(12));
14004 assert!(config.session.enabled);
14005 assert_eq!(
14006 config.session.checkpoint_path,
14007 Some("/tmp/checkpoints".to_string())
14008 );
14009 assert!(config.session.per_period_output);
14010 assert!(!config.session.consolidated_output);
14011 }
14012}