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 #[serde(default = "default_diffusion_backend")]
261 pub backend: String,
262 #[serde(default)]
264 pub neural: NeuralDiffusionSchemaConfig,
265}
266
267fn default_diffusion_steps() -> usize {
268 100
269}
270
271fn default_diffusion_schedule() -> String {
272 "linear".to_string()
273}
274
275fn default_diffusion_sample_size() -> usize {
276 100
277}
278
279fn default_diffusion_backend() -> String {
280 "statistical".to_string()
281}
282
283impl Default for DiffusionSchemaConfig {
284 fn default() -> Self {
285 Self {
286 enabled: false,
287 n_steps: default_diffusion_steps(),
288 schedule: default_diffusion_schedule(),
289 sample_size: default_diffusion_sample_size(),
290 backend: default_diffusion_backend(),
291 neural: NeuralDiffusionSchemaConfig::default(),
292 }
293 }
294}
295
296#[derive(Debug, Clone, Serialize, Deserialize)]
301pub struct NeuralDiffusionSchemaConfig {
302 #[serde(default = "default_neural_hidden_dims")]
304 pub hidden_dims: Vec<usize>,
305 #[serde(default = "default_neural_timestep_embed_dim")]
307 pub timestep_embed_dim: usize,
308 #[serde(default = "default_neural_learning_rate")]
310 pub learning_rate: f64,
311 #[serde(default = "default_neural_training_epochs")]
313 pub training_epochs: usize,
314 #[serde(default = "default_neural_batch_size")]
316 pub batch_size: usize,
317 #[serde(default = "default_neural_hybrid_weight")]
319 pub hybrid_weight: f64,
320 #[serde(default = "default_neural_hybrid_strategy")]
322 pub hybrid_strategy: String,
323 #[serde(default)]
325 pub neural_columns: Vec<String>,
326}
327
328fn default_neural_hidden_dims() -> Vec<usize> {
329 vec![256, 256, 128]
330}
331
332fn default_neural_timestep_embed_dim() -> usize {
333 64
334}
335
336fn default_neural_learning_rate() -> f64 {
337 0.001
338}
339
340fn default_neural_training_epochs() -> usize {
341 100
342}
343
344fn default_neural_batch_size() -> usize {
345 64
346}
347
348fn default_neural_hybrid_weight() -> f64 {
349 0.5
350}
351
352fn default_neural_hybrid_strategy() -> String {
353 "weighted_average".to_string()
354}
355
356impl Default for NeuralDiffusionSchemaConfig {
357 fn default() -> Self {
358 Self {
359 hidden_dims: default_neural_hidden_dims(),
360 timestep_embed_dim: default_neural_timestep_embed_dim(),
361 learning_rate: default_neural_learning_rate(),
362 training_epochs: default_neural_training_epochs(),
363 batch_size: default_neural_batch_size(),
364 hybrid_weight: default_neural_hybrid_weight(),
365 hybrid_strategy: default_neural_hybrid_strategy(),
366 neural_columns: Vec::new(),
367 }
368 }
369}
370
371#[derive(Debug, Clone, Serialize, Deserialize)]
377pub struct CausalSchemaConfig {
378 #[serde(default)]
380 pub enabled: bool,
381 #[serde(default = "default_causal_template")]
383 pub template: String,
384 #[serde(default = "default_causal_sample_size")]
386 pub sample_size: usize,
387 #[serde(default = "default_true")]
389 pub validate: bool,
390}
391
392fn default_causal_template() -> String {
393 "fraud_detection".to_string()
394}
395
396fn default_causal_sample_size() -> usize {
397 500
398}
399
400impl Default for CausalSchemaConfig {
401 fn default() -> Self {
402 Self {
403 enabled: false,
404 template: default_causal_template(),
405 sample_size: default_causal_sample_size(),
406 validate: true,
407 }
408 }
409}
410
411#[derive(Debug, Clone, Serialize, Deserialize)]
418pub struct GraphExportConfig {
419 #[serde(default)]
421 pub enabled: bool,
422
423 #[serde(default = "default_graph_types")]
425 pub graph_types: Vec<GraphTypeConfig>,
426
427 #[serde(default = "default_graph_formats")]
429 pub formats: Vec<GraphExportFormat>,
430
431 #[serde(default = "default_train_ratio")]
433 pub train_ratio: f64,
434
435 #[serde(default = "default_val_ratio")]
437 pub validation_ratio: f64,
438
439 #[serde(default)]
441 pub split_seed: Option<u64>,
442
443 #[serde(default = "default_graph_subdir")]
445 pub output_subdirectory: String,
446
447 #[serde(default)]
449 pub hypergraph: HypergraphExportSettings,
450
451 #[serde(default)]
453 pub dgl: DglExportConfig,
454}
455
456fn default_graph_types() -> Vec<GraphTypeConfig> {
457 vec![GraphTypeConfig::default()]
458}
459
460fn default_graph_formats() -> Vec<GraphExportFormat> {
461 vec![GraphExportFormat::PytorchGeometric]
462}
463
464fn default_train_ratio() -> f64 {
465 0.7
466}
467
468fn default_val_ratio() -> f64 {
469 0.15
470}
471
472fn default_graph_subdir() -> String {
473 "graphs".to_string()
474}
475
476impl Default for GraphExportConfig {
477 fn default() -> Self {
478 Self {
479 enabled: false,
480 graph_types: default_graph_types(),
481 formats: default_graph_formats(),
482 train_ratio: 0.7,
483 validation_ratio: 0.15,
484 split_seed: None,
485 output_subdirectory: "graphs".to_string(),
486 hypergraph: HypergraphExportSettings::default(),
487 dgl: DglExportConfig::default(),
488 }
489 }
490}
491
492#[derive(Debug, Clone, Default, Serialize, Deserialize)]
494pub struct DglExportConfig {
495 #[serde(default)]
501 pub heterogeneous: bool,
502}
503
504#[derive(Debug, Clone, Serialize, Deserialize)]
513pub struct HypergraphExportSettings {
514 #[serde(default)]
516 pub enabled: bool,
517
518 #[serde(default = "default_hypergraph_max_nodes")]
520 pub max_nodes: usize,
521
522 #[serde(default = "default_aggregation_strategy")]
524 pub aggregation_strategy: String,
525
526 #[serde(default)]
528 pub governance_layer: GovernanceLayerSettings,
529
530 #[serde(default)]
532 pub process_layer: ProcessLayerSettings,
533
534 #[serde(default)]
536 pub accounting_layer: AccountingLayerSettings,
537
538 #[serde(default)]
540 pub cross_layer: CrossLayerSettings,
541
542 #[serde(default = "default_hypergraph_subdir")]
544 pub output_subdirectory: String,
545
546 #[serde(default = "default_hypergraph_format")]
548 pub output_format: String,
549
550 #[serde(default)]
552 pub stream_target: Option<String>,
553
554 #[serde(default = "default_stream_batch_size")]
556 pub stream_batch_size: usize,
557}
558
559fn default_hypergraph_max_nodes() -> usize {
560 50_000
561}
562
563fn default_aggregation_strategy() -> String {
564 "pool_by_counterparty".to_string()
565}
566
567fn default_hypergraph_subdir() -> String {
568 "hypergraph".to_string()
569}
570
571fn default_hypergraph_format() -> String {
572 "native".to_string()
573}
574
575fn default_stream_batch_size() -> usize {
576 1000
577}
578
579impl Default for HypergraphExportSettings {
580 fn default() -> Self {
581 Self {
582 enabled: false,
583 max_nodes: 50_000,
584 aggregation_strategy: "pool_by_counterparty".to_string(),
585 governance_layer: GovernanceLayerSettings::default(),
586 process_layer: ProcessLayerSettings::default(),
587 accounting_layer: AccountingLayerSettings::default(),
588 cross_layer: CrossLayerSettings::default(),
589 output_subdirectory: "hypergraph".to_string(),
590 output_format: "native".to_string(),
591 stream_target: None,
592 stream_batch_size: 1000,
593 }
594 }
595}
596
597#[derive(Debug, Clone, Serialize, Deserialize)]
599pub struct GovernanceLayerSettings {
600 #[serde(default = "default_true")]
602 pub include_coso: bool,
603 #[serde(default = "default_true")]
605 pub include_controls: bool,
606 #[serde(default = "default_true")]
608 pub include_sox: bool,
609 #[serde(default = "default_true")]
611 pub include_vendors: bool,
612 #[serde(default = "default_true")]
614 pub include_customers: bool,
615 #[serde(default = "default_true")]
617 pub include_employees: bool,
618}
619
620impl Default for GovernanceLayerSettings {
621 fn default() -> Self {
622 Self {
623 include_coso: true,
624 include_controls: true,
625 include_sox: true,
626 include_vendors: true,
627 include_customers: true,
628 include_employees: true,
629 }
630 }
631}
632
633#[derive(Debug, Clone, Serialize, Deserialize)]
635pub struct ProcessLayerSettings {
636 #[serde(default = "default_true")]
638 pub include_p2p: bool,
639 #[serde(default = "default_true")]
641 pub include_o2c: bool,
642 #[serde(default = "default_true")]
644 pub include_s2c: bool,
645 #[serde(default = "default_true")]
647 pub include_h2r: bool,
648 #[serde(default = "default_true")]
650 pub include_mfg: bool,
651 #[serde(default = "default_true")]
653 pub include_bank: bool,
654 #[serde(default = "default_true")]
656 pub include_audit: bool,
657 #[serde(default = "default_true")]
659 pub include_r2r: bool,
660 #[serde(default = "default_true")]
662 pub events_as_hyperedges: bool,
663 #[serde(default = "default_docs_per_counterparty_threshold")]
665 pub docs_per_counterparty_threshold: usize,
666}
667
668fn default_docs_per_counterparty_threshold() -> usize {
669 20
670}
671
672impl Default for ProcessLayerSettings {
673 fn default() -> Self {
674 Self {
675 include_p2p: true,
676 include_o2c: true,
677 include_s2c: true,
678 include_h2r: true,
679 include_mfg: true,
680 include_bank: true,
681 include_audit: true,
682 include_r2r: true,
683 events_as_hyperedges: true,
684 docs_per_counterparty_threshold: 20,
685 }
686 }
687}
688
689#[derive(Debug, Clone, Serialize, Deserialize)]
691pub struct AccountingLayerSettings {
692 #[serde(default = "default_true")]
694 pub include_accounts: bool,
695 #[serde(default = "default_true")]
697 pub je_as_hyperedges: bool,
698}
699
700impl Default for AccountingLayerSettings {
701 fn default() -> Self {
702 Self {
703 include_accounts: true,
704 je_as_hyperedges: true,
705 }
706 }
707}
708
709#[derive(Debug, Clone, Serialize, Deserialize)]
711pub struct CrossLayerSettings {
712 #[serde(default = "default_true")]
714 pub enabled: bool,
715}
716
717impl Default for CrossLayerSettings {
718 fn default() -> Self {
719 Self { enabled: true }
720 }
721}
722
723#[derive(Debug, Clone, Serialize, Deserialize)]
725pub struct GraphTypeConfig {
726 #[serde(default = "default_graph_name")]
728 pub name: String,
729
730 #[serde(default)]
732 pub aggregate_edges: bool,
733
734 #[serde(default)]
736 pub min_edge_weight: f64,
737
738 #[serde(default)]
740 pub include_document_nodes: bool,
741}
742
743fn default_graph_name() -> String {
744 "accounting_network".to_string()
745}
746
747impl Default for GraphTypeConfig {
748 fn default() -> Self {
749 Self {
750 name: "accounting_network".to_string(),
751 aggregate_edges: false,
752 min_edge_weight: 0.0,
753 include_document_nodes: false,
754 }
755 }
756}
757
758#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
760#[serde(rename_all = "snake_case")]
761pub enum GraphExportFormat {
762 PytorchGeometric,
764 Neo4j,
766 Dgl,
768 RustGraph,
770 RustGraphHypergraph,
772}
773
774#[derive(Debug, Clone, Default, Serialize, Deserialize)]
778pub struct ScenarioConfig {
779 #[serde(default)]
782 pub tags: Vec<String>,
783
784 #[serde(default)]
789 pub profile: Option<String>,
790
791 #[serde(default)]
793 pub description: Option<String>,
794
795 #[serde(default)]
797 pub ml_training: bool,
798
799 #[serde(default)]
802 pub target_anomaly_ratio: Option<f64>,
803
804 #[serde(default)]
806 pub metadata: std::collections::HashMap<String, String>,
807}
808
809#[derive(Debug, Clone, Serialize, Deserialize)]
814pub struct TemporalDriftConfig {
815 #[serde(default)]
817 pub enabled: bool,
818
819 #[serde(default = "default_amount_drift")]
822 pub amount_mean_drift: f64,
823
824 #[serde(default)]
827 pub amount_variance_drift: f64,
828
829 #[serde(default)]
832 pub anomaly_rate_drift: f64,
833
834 #[serde(default = "default_concept_drift")]
837 pub concept_drift_rate: f64,
838
839 #[serde(default)]
841 pub sudden_drift_probability: f64,
842
843 #[serde(default = "default_sudden_drift_magnitude")]
845 pub sudden_drift_magnitude: f64,
846
847 #[serde(default)]
849 pub seasonal_drift: bool,
850
851 #[serde(default)]
853 pub drift_start_period: u32,
854
855 #[serde(default = "default_drift_type")]
857 pub drift_type: DriftType,
858}
859
860fn default_amount_drift() -> f64 {
861 0.02
862}
863
864fn default_concept_drift() -> f64 {
865 0.01
866}
867
868fn default_sudden_drift_magnitude() -> f64 {
869 2.0
870}
871
872fn default_drift_type() -> DriftType {
873 DriftType::Gradual
874}
875
876impl Default for TemporalDriftConfig {
877 fn default() -> Self {
878 Self {
879 enabled: false,
880 amount_mean_drift: 0.02,
881 amount_variance_drift: 0.0,
882 anomaly_rate_drift: 0.0,
883 concept_drift_rate: 0.01,
884 sudden_drift_probability: 0.0,
885 sudden_drift_magnitude: 2.0,
886 seasonal_drift: false,
887 drift_start_period: 0,
888 drift_type: DriftType::Gradual,
889 }
890 }
891}
892
893impl TemporalDriftConfig {
894 pub fn to_core_config(&self) -> datasynth_core::distributions::DriftConfig {
896 datasynth_core::distributions::DriftConfig {
897 enabled: self.enabled,
898 amount_mean_drift: self.amount_mean_drift,
899 amount_variance_drift: self.amount_variance_drift,
900 anomaly_rate_drift: self.anomaly_rate_drift,
901 concept_drift_rate: self.concept_drift_rate,
902 sudden_drift_probability: self.sudden_drift_probability,
903 sudden_drift_magnitude: self.sudden_drift_magnitude,
904 seasonal_drift: self.seasonal_drift,
905 drift_start_period: self.drift_start_period,
906 drift_type: match self.drift_type {
907 DriftType::Gradual => datasynth_core::distributions::DriftType::Gradual,
908 DriftType::Sudden => datasynth_core::distributions::DriftType::Sudden,
909 DriftType::Recurring => datasynth_core::distributions::DriftType::Recurring,
910 DriftType::Mixed => datasynth_core::distributions::DriftType::Mixed,
911 },
912 regime_changes: Vec::new(),
913 economic_cycle: Default::default(),
914 parameter_drifts: Vec::new(),
915 }
916 }
917}
918
919#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
921#[serde(rename_all = "snake_case")]
922pub enum DriftType {
923 #[default]
925 Gradual,
926 Sudden,
928 Recurring,
930 Mixed,
932}
933
934#[derive(Debug, Clone, Serialize, Deserialize)]
940pub struct StreamingSchemaConfig {
941 #[serde(default)]
943 pub enabled: bool,
944 #[serde(default)]
946 pub events_per_second: f64,
947 #[serde(default = "default_burst_size")]
949 pub burst_size: u32,
950 #[serde(default = "default_buffer_size")]
952 pub buffer_size: usize,
953 #[serde(default = "default_true")]
955 pub enable_progress: bool,
956 #[serde(default = "default_progress_interval")]
958 pub progress_interval: u64,
959 #[serde(default)]
961 pub backpressure: BackpressureSchemaStrategy,
962}
963
964fn default_buffer_size() -> usize {
965 1000
966}
967
968fn default_progress_interval() -> u64 {
969 100
970}
971
972impl Default for StreamingSchemaConfig {
973 fn default() -> Self {
974 Self {
975 enabled: false,
976 events_per_second: 0.0,
977 burst_size: 100,
978 buffer_size: 1000,
979 enable_progress: true,
980 progress_interval: 100,
981 backpressure: BackpressureSchemaStrategy::Block,
982 }
983 }
984}
985
986#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
988#[serde(rename_all = "snake_case")]
989pub enum BackpressureSchemaStrategy {
990 #[default]
992 Block,
993 DropOldest,
995 DropNewest,
997 Buffer,
999}
1000
1001#[derive(Debug, Clone, Serialize, Deserialize)]
1007pub struct RateLimitSchemaConfig {
1008 #[serde(default)]
1010 pub enabled: bool,
1011 #[serde(default = "default_entities_per_second")]
1013 pub entities_per_second: f64,
1014 #[serde(default = "default_burst_size")]
1016 pub burst_size: u32,
1017 #[serde(default)]
1019 pub backpressure: RateLimitBackpressureSchema,
1020}
1021
1022fn default_entities_per_second() -> f64 {
1023 1000.0
1024}
1025
1026fn default_burst_size() -> u32 {
1027 100
1028}
1029
1030impl Default for RateLimitSchemaConfig {
1031 fn default() -> Self {
1032 Self {
1033 enabled: false,
1034 entities_per_second: 1000.0,
1035 burst_size: 100,
1036 backpressure: RateLimitBackpressureSchema::Block,
1037 }
1038 }
1039}
1040
1041#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
1043#[serde(rename_all = "snake_case")]
1044pub enum RateLimitBackpressureSchema {
1045 #[default]
1047 Block,
1048 Drop,
1050 Buffer,
1052}
1053
1054#[derive(Debug, Clone, Serialize, Deserialize)]
1060pub struct TemporalAttributeSchemaConfig {
1061 #[serde(default)]
1063 pub enabled: bool,
1064 #[serde(default)]
1066 pub valid_time: ValidTimeSchemaConfig,
1067 #[serde(default)]
1069 pub transaction_time: TransactionTimeSchemaConfig,
1070 #[serde(default)]
1072 pub generate_version_chains: bool,
1073 #[serde(default = "default_avg_versions")]
1075 pub avg_versions_per_entity: f64,
1076}
1077
1078fn default_avg_versions() -> f64 {
1079 1.5
1080}
1081
1082impl Default for TemporalAttributeSchemaConfig {
1083 fn default() -> Self {
1084 Self {
1085 enabled: false,
1086 valid_time: ValidTimeSchemaConfig::default(),
1087 transaction_time: TransactionTimeSchemaConfig::default(),
1088 generate_version_chains: false,
1089 avg_versions_per_entity: 1.5,
1090 }
1091 }
1092}
1093
1094#[derive(Debug, Clone, Serialize, Deserialize)]
1096pub struct ValidTimeSchemaConfig {
1097 #[serde(default = "default_closed_probability")]
1099 pub closed_probability: f64,
1100 #[serde(default = "default_avg_validity_days")]
1102 pub avg_validity_days: u32,
1103 #[serde(default = "default_validity_stddev")]
1105 pub validity_stddev_days: u32,
1106}
1107
1108fn default_closed_probability() -> f64 {
1109 0.1
1110}
1111
1112fn default_avg_validity_days() -> u32 {
1113 365
1114}
1115
1116fn default_validity_stddev() -> u32 {
1117 90
1118}
1119
1120impl Default for ValidTimeSchemaConfig {
1121 fn default() -> Self {
1122 Self {
1123 closed_probability: 0.1,
1124 avg_validity_days: 365,
1125 validity_stddev_days: 90,
1126 }
1127 }
1128}
1129
1130#[derive(Debug, Clone, Serialize, Deserialize)]
1132pub struct TransactionTimeSchemaConfig {
1133 #[serde(default)]
1135 pub avg_recording_delay_seconds: u32,
1136 #[serde(default)]
1138 pub allow_backdating: bool,
1139 #[serde(default = "default_backdating_probability")]
1141 pub backdating_probability: f64,
1142 #[serde(default = "default_max_backdate_days")]
1144 pub max_backdate_days: u32,
1145}
1146
1147fn default_backdating_probability() -> f64 {
1148 0.01
1149}
1150
1151fn default_max_backdate_days() -> u32 {
1152 30
1153}
1154
1155impl Default for TransactionTimeSchemaConfig {
1156 fn default() -> Self {
1157 Self {
1158 avg_recording_delay_seconds: 0,
1159 allow_backdating: false,
1160 backdating_probability: 0.01,
1161 max_backdate_days: 30,
1162 }
1163 }
1164}
1165
1166#[derive(Debug, Clone, Serialize, Deserialize)]
1172pub struct RelationshipSchemaConfig {
1173 #[serde(default)]
1175 pub relationship_types: Vec<RelationshipTypeSchemaConfig>,
1176 #[serde(default = "default_true")]
1178 pub allow_orphans: bool,
1179 #[serde(default = "default_orphan_probability")]
1181 pub orphan_probability: f64,
1182 #[serde(default)]
1184 pub allow_circular: bool,
1185 #[serde(default = "default_max_circular_depth")]
1187 pub max_circular_depth: u32,
1188}
1189
1190fn default_orphan_probability() -> f64 {
1191 0.01
1192}
1193
1194fn default_max_circular_depth() -> u32 {
1195 3
1196}
1197
1198impl Default for RelationshipSchemaConfig {
1199 fn default() -> Self {
1200 Self {
1201 relationship_types: Vec::new(),
1202 allow_orphans: true,
1203 orphan_probability: 0.01,
1204 allow_circular: false,
1205 max_circular_depth: 3,
1206 }
1207 }
1208}
1209
1210#[derive(Debug, Clone, Serialize, Deserialize)]
1212pub struct RelationshipTypeSchemaConfig {
1213 pub name: String,
1215 pub source_type: String,
1217 pub target_type: String,
1219 #[serde(default)]
1221 pub cardinality: CardinalitySchemaRule,
1222 #[serde(default = "default_relationship_weight")]
1224 pub weight: f64,
1225 #[serde(default)]
1227 pub required: bool,
1228 #[serde(default = "default_true")]
1230 pub directed: bool,
1231}
1232
1233fn default_relationship_weight() -> f64 {
1234 1.0
1235}
1236
1237impl Default for RelationshipTypeSchemaConfig {
1238 fn default() -> Self {
1239 Self {
1240 name: String::new(),
1241 source_type: String::new(),
1242 target_type: String::new(),
1243 cardinality: CardinalitySchemaRule::default(),
1244 weight: 1.0,
1245 required: false,
1246 directed: true,
1247 }
1248 }
1249}
1250
1251#[derive(Debug, Clone, Serialize, Deserialize)]
1253#[serde(rename_all = "snake_case")]
1254pub enum CardinalitySchemaRule {
1255 OneToOne,
1257 OneToMany {
1259 min: u32,
1261 max: u32,
1263 },
1264 ManyToOne {
1266 min: u32,
1268 max: u32,
1270 },
1271 ManyToMany {
1273 min_per_source: u32,
1275 max_per_source: u32,
1277 },
1278}
1279
1280impl Default for CardinalitySchemaRule {
1281 fn default() -> Self {
1282 Self::OneToMany { min: 1, max: 5 }
1283 }
1284}
1285
1286#[derive(Debug, Clone, Serialize, Deserialize)]
1288pub struct GlobalConfig {
1289 pub seed: Option<u64>,
1291 pub industry: IndustrySector,
1293 pub start_date: String,
1295 pub period_months: u32,
1297 #[serde(default = "default_currency")]
1299 pub group_currency: String,
1300 #[serde(default)]
1303 pub presentation_currency: Option<String>,
1304 #[serde(default = "default_true")]
1306 pub parallel: bool,
1307 #[serde(default)]
1309 pub worker_threads: usize,
1310 #[serde(default)]
1312 pub memory_limit_mb: usize,
1313 #[serde(default)]
1316 pub fiscal_year_months: Option<u32>,
1317}
1318
1319fn default_currency() -> String {
1320 "USD".to_string()
1321}
1322fn default_true() -> bool {
1323 true
1324}
1325
1326#[derive(Debug, Clone, Serialize, Deserialize)]
1331pub struct SessionSchemaConfig {
1332 #[serde(default)]
1334 pub enabled: bool,
1335 #[serde(default)]
1337 pub checkpoint_path: Option<String>,
1338 #[serde(default = "default_true")]
1340 pub per_period_output: bool,
1341 #[serde(default = "default_true")]
1343 pub consolidated_output: bool,
1344}
1345
1346impl Default for SessionSchemaConfig {
1347 fn default() -> Self {
1348 Self {
1349 enabled: false,
1350 checkpoint_path: None,
1351 per_period_output: true,
1352 consolidated_output: true,
1353 }
1354 }
1355}
1356
1357#[derive(Debug, Clone, Serialize, Deserialize)]
1359pub struct CompanyConfig {
1360 pub code: String,
1362 pub name: String,
1364 pub currency: String,
1366 #[serde(default)]
1369 pub functional_currency: Option<String>,
1370 pub country: String,
1372 #[serde(default = "default_fiscal_variant")]
1374 pub fiscal_year_variant: String,
1375 pub annual_transaction_volume: TransactionVolume,
1377 #[serde(default = "default_weight")]
1379 pub volume_weight: f64,
1380}
1381
1382fn default_fiscal_variant() -> String {
1383 "K4".to_string()
1384}
1385fn default_weight() -> f64 {
1386 1.0
1387}
1388
1389#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1391#[serde(rename_all = "snake_case")]
1392pub enum TransactionVolume {
1393 TenK,
1395 HundredK,
1397 OneM,
1399 TenM,
1401 HundredM,
1403 Custom(u64),
1405}
1406
1407impl TransactionVolume {
1408 pub fn count(&self) -> u64 {
1410 match self {
1411 Self::TenK => 10_000,
1412 Self::HundredK => 100_000,
1413 Self::OneM => 1_000_000,
1414 Self::TenM => 10_000_000,
1415 Self::HundredM => 100_000_000,
1416 Self::Custom(n) => *n,
1417 }
1418 }
1419}
1420
1421#[derive(Debug, Clone, Serialize, Deserialize)]
1423pub struct ChartOfAccountsConfig {
1424 pub complexity: CoAComplexity,
1426 #[serde(default = "default_true")]
1428 pub industry_specific: bool,
1429 pub custom_accounts: Option<PathBuf>,
1431 #[serde(default = "default_min_depth")]
1433 pub min_hierarchy_depth: u8,
1434 #[serde(default = "default_max_depth")]
1436 pub max_hierarchy_depth: u8,
1437}
1438
1439fn default_min_depth() -> u8 {
1440 2
1441}
1442fn default_max_depth() -> u8 {
1443 5
1444}
1445
1446impl Default for ChartOfAccountsConfig {
1447 fn default() -> Self {
1448 Self {
1449 complexity: CoAComplexity::Small,
1450 industry_specific: true,
1451 custom_accounts: None,
1452 min_hierarchy_depth: default_min_depth(),
1453 max_hierarchy_depth: default_max_depth(),
1454 }
1455 }
1456}
1457
1458#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1460pub struct TransactionConfig {
1461 #[serde(default)]
1463 pub line_item_distribution: LineItemDistributionConfig,
1464 #[serde(default)]
1466 pub debit_credit_distribution: DebitCreditDistributionConfig,
1467 #[serde(default)]
1469 pub even_odd_distribution: EvenOddDistributionConfig,
1470 #[serde(default)]
1472 pub source_distribution: SourceDistribution,
1473 #[serde(default)]
1475 pub seasonality: SeasonalityConfig,
1476 #[serde(default)]
1478 pub amounts: AmountDistributionConfig,
1479 #[serde(default)]
1481 pub benford: BenfordConfig,
1482}
1483
1484#[derive(Debug, Clone, Serialize, Deserialize)]
1486pub struct BenfordConfig {
1487 #[serde(default = "default_true")]
1489 pub enabled: bool,
1490 #[serde(default = "default_benford_tolerance")]
1492 pub tolerance: f64,
1493 #[serde(default)]
1495 pub exempt_sources: Vec<BenfordExemption>,
1496}
1497
1498fn default_benford_tolerance() -> f64 {
1499 0.05
1500}
1501
1502impl Default for BenfordConfig {
1503 fn default() -> Self {
1504 Self {
1505 enabled: true,
1506 tolerance: default_benford_tolerance(),
1507 exempt_sources: vec![BenfordExemption::Recurring, BenfordExemption::Payroll],
1508 }
1509 }
1510}
1511
1512#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1514#[serde(rename_all = "snake_case")]
1515pub enum BenfordExemption {
1516 Recurring,
1518 Payroll,
1520 FixedFees,
1522 RoundAmounts,
1524}
1525
1526#[derive(Debug, Clone, Serialize, Deserialize)]
1528pub struct SourceDistribution {
1529 pub manual: f64,
1531 pub automated: f64,
1533 pub recurring: f64,
1535 pub adjustment: f64,
1537}
1538
1539impl Default for SourceDistribution {
1540 fn default() -> Self {
1541 Self {
1542 manual: 0.20,
1543 automated: 0.70,
1544 recurring: 0.07,
1545 adjustment: 0.03,
1546 }
1547 }
1548}
1549
1550#[derive(Debug, Clone, Serialize, Deserialize)]
1552pub struct OutputConfig {
1553 #[serde(default)]
1555 pub mode: OutputMode,
1556 pub output_directory: PathBuf,
1558 #[serde(default = "default_formats")]
1560 pub formats: Vec<FileFormat>,
1561 #[serde(default)]
1563 pub compression: CompressionConfig,
1564 #[serde(default = "default_batch_size")]
1566 pub batch_size: usize,
1567 #[serde(default = "default_true")]
1569 pub include_acdoca: bool,
1570 #[serde(default)]
1572 pub include_bseg: bool,
1573 #[serde(default = "default_true")]
1575 pub partition_by_period: bool,
1576 #[serde(default)]
1578 pub partition_by_company: bool,
1579 #[serde(default)]
1583 pub numeric_mode: NumericMode,
1584 #[serde(default)]
1588 pub export_layout: ExportLayout,
1589}
1590
1591fn default_formats() -> Vec<FileFormat> {
1592 vec![FileFormat::Parquet]
1593}
1594fn default_batch_size() -> usize {
1595 100_000
1596}
1597
1598impl Default for OutputConfig {
1599 fn default() -> Self {
1600 Self {
1601 mode: OutputMode::FlatFile,
1602 output_directory: PathBuf::from("./output"),
1603 formats: default_formats(),
1604 compression: CompressionConfig::default(),
1605 batch_size: default_batch_size(),
1606 include_acdoca: true,
1607 include_bseg: false,
1608 partition_by_period: true,
1609 partition_by_company: false,
1610 numeric_mode: NumericMode::default(),
1611 export_layout: ExportLayout::default(),
1612 }
1613 }
1614}
1615
1616#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
1618#[serde(rename_all = "snake_case")]
1619pub enum NumericMode {
1620 #[default]
1622 String,
1623 Native,
1625}
1626
1627#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
1629#[serde(rename_all = "snake_case")]
1630pub enum ExportLayout {
1631 #[default]
1633 Nested,
1634 Flat,
1636}
1637
1638#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
1640#[serde(rename_all = "snake_case")]
1641pub enum OutputMode {
1642 Streaming,
1644 #[default]
1646 FlatFile,
1647 Both,
1649}
1650
1651#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1653#[serde(rename_all = "snake_case")]
1654pub enum FileFormat {
1655 Csv,
1656 Parquet,
1657 Json,
1658 JsonLines,
1659}
1660
1661#[derive(Debug, Clone, Serialize, Deserialize)]
1663pub struct CompressionConfig {
1664 #[serde(default = "default_true")]
1666 pub enabled: bool,
1667 #[serde(default)]
1669 pub algorithm: CompressionAlgorithm,
1670 #[serde(default = "default_compression_level")]
1672 pub level: u8,
1673}
1674
1675fn default_compression_level() -> u8 {
1676 3
1677}
1678
1679impl Default for CompressionConfig {
1680 fn default() -> Self {
1681 Self {
1682 enabled: true,
1683 algorithm: CompressionAlgorithm::default(),
1684 level: default_compression_level(),
1685 }
1686 }
1687}
1688
1689#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
1691#[serde(rename_all = "snake_case")]
1692pub enum CompressionAlgorithm {
1693 Gzip,
1694 #[default]
1695 Zstd,
1696 Lz4,
1697 Snappy,
1698}
1699
1700#[derive(Debug, Clone, Serialize, Deserialize)]
1702pub struct FraudConfig {
1703 #[serde(default)]
1705 pub enabled: bool,
1706 #[serde(default = "default_fraud_rate")]
1708 pub fraud_rate: f64,
1709 #[serde(default)]
1711 pub fraud_type_distribution: FraudTypeDistribution,
1712 #[serde(default)]
1714 pub clustering_enabled: bool,
1715 #[serde(default = "default_clustering_factor")]
1717 pub clustering_factor: f64,
1718 #[serde(default = "default_approval_thresholds")]
1720 pub approval_thresholds: Vec<f64>,
1721}
1722
1723fn default_approval_thresholds() -> Vec<f64> {
1724 vec![1000.0, 5000.0, 10000.0, 25000.0, 50000.0, 100000.0]
1725}
1726
1727fn default_fraud_rate() -> f64 {
1728 0.005
1729}
1730fn default_clustering_factor() -> f64 {
1731 3.0
1732}
1733
1734impl Default for FraudConfig {
1735 fn default() -> Self {
1736 Self {
1737 enabled: false,
1738 fraud_rate: default_fraud_rate(),
1739 fraud_type_distribution: FraudTypeDistribution::default(),
1740 clustering_enabled: false,
1741 clustering_factor: default_clustering_factor(),
1742 approval_thresholds: default_approval_thresholds(),
1743 }
1744 }
1745}
1746
1747#[derive(Debug, Clone, Serialize, Deserialize)]
1749pub struct FraudTypeDistribution {
1750 pub suspense_account_abuse: f64,
1751 pub fictitious_transaction: f64,
1752 pub revenue_manipulation: f64,
1753 pub expense_capitalization: f64,
1754 pub split_transaction: f64,
1755 pub timing_anomaly: f64,
1756 pub unauthorized_access: f64,
1757 pub duplicate_payment: f64,
1758}
1759
1760impl Default for FraudTypeDistribution {
1761 fn default() -> Self {
1762 Self {
1763 suspense_account_abuse: 0.25,
1764 fictitious_transaction: 0.15,
1765 revenue_manipulation: 0.10,
1766 expense_capitalization: 0.10,
1767 split_transaction: 0.15,
1768 timing_anomaly: 0.10,
1769 unauthorized_access: 0.10,
1770 duplicate_payment: 0.05,
1771 }
1772 }
1773}
1774
1775#[derive(Debug, Clone, Serialize, Deserialize)]
1777pub struct InternalControlsConfig {
1778 #[serde(default)]
1780 pub enabled: bool,
1781 #[serde(default = "default_exception_rate")]
1783 pub exception_rate: f64,
1784 #[serde(default = "default_sod_violation_rate")]
1786 pub sod_violation_rate: f64,
1787 #[serde(default = "default_true")]
1789 pub export_control_master_data: bool,
1790 #[serde(default = "default_sox_materiality_threshold")]
1792 pub sox_materiality_threshold: f64,
1793 #[serde(default = "default_true")]
1795 pub coso_enabled: bool,
1796 #[serde(default)]
1798 pub include_entity_level_controls: bool,
1799 #[serde(default = "default_target_maturity_level")]
1802 pub target_maturity_level: String,
1803}
1804
1805fn default_exception_rate() -> f64 {
1806 0.02
1807}
1808
1809fn default_sod_violation_rate() -> f64 {
1810 0.01
1811}
1812
1813fn default_sox_materiality_threshold() -> f64 {
1814 10000.0
1815}
1816
1817fn default_target_maturity_level() -> String {
1818 "mixed".to_string()
1819}
1820
1821impl Default for InternalControlsConfig {
1822 fn default() -> Self {
1823 Self {
1824 enabled: false,
1825 exception_rate: default_exception_rate(),
1826 sod_violation_rate: default_sod_violation_rate(),
1827 export_control_master_data: true,
1828 sox_materiality_threshold: default_sox_materiality_threshold(),
1829 coso_enabled: true,
1830 include_entity_level_controls: false,
1831 target_maturity_level: default_target_maturity_level(),
1832 }
1833 }
1834}
1835
1836#[derive(Debug, Clone, Serialize, Deserialize)]
1838pub struct BusinessProcessConfig {
1839 #[serde(default = "default_o2c")]
1841 pub o2c_weight: f64,
1842 #[serde(default = "default_p2p")]
1844 pub p2p_weight: f64,
1845 #[serde(default = "default_r2r")]
1847 pub r2r_weight: f64,
1848 #[serde(default = "default_h2r")]
1850 pub h2r_weight: f64,
1851 #[serde(default = "default_a2r")]
1853 pub a2r_weight: f64,
1854}
1855
1856fn default_o2c() -> f64 {
1857 0.35
1858}
1859fn default_p2p() -> f64 {
1860 0.30
1861}
1862fn default_r2r() -> f64 {
1863 0.20
1864}
1865fn default_h2r() -> f64 {
1866 0.10
1867}
1868fn default_a2r() -> f64 {
1869 0.05
1870}
1871
1872impl Default for BusinessProcessConfig {
1873 fn default() -> Self {
1874 Self {
1875 o2c_weight: default_o2c(),
1876 p2p_weight: default_p2p(),
1877 r2r_weight: default_r2r(),
1878 h2r_weight: default_h2r(),
1879 a2r_weight: default_a2r(),
1880 }
1881 }
1882}
1883
1884#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1886pub struct UserPersonaConfig {
1887 #[serde(default)]
1889 pub persona_distribution: PersonaDistribution,
1890 #[serde(default)]
1892 pub users_per_persona: UsersPerPersona,
1893}
1894
1895#[derive(Debug, Clone, Serialize, Deserialize)]
1897pub struct PersonaDistribution {
1898 pub junior_accountant: f64,
1899 pub senior_accountant: f64,
1900 pub controller: f64,
1901 pub manager: f64,
1902 pub automated_system: f64,
1903}
1904
1905impl Default for PersonaDistribution {
1906 fn default() -> Self {
1907 Self {
1908 junior_accountant: 0.15,
1909 senior_accountant: 0.15,
1910 controller: 0.05,
1911 manager: 0.05,
1912 automated_system: 0.60,
1913 }
1914 }
1915}
1916
1917#[derive(Debug, Clone, Serialize, Deserialize)]
1919pub struct UsersPerPersona {
1920 pub junior_accountant: usize,
1921 pub senior_accountant: usize,
1922 pub controller: usize,
1923 pub manager: usize,
1924 pub automated_system: usize,
1925}
1926
1927impl Default for UsersPerPersona {
1928 fn default() -> Self {
1929 Self {
1930 junior_accountant: 10,
1931 senior_accountant: 5,
1932 controller: 2,
1933 manager: 3,
1934 automated_system: 20,
1935 }
1936 }
1937}
1938
1939#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1941pub struct TemplateConfig {
1942 #[serde(default)]
1944 pub names: NameTemplateConfig,
1945 #[serde(default)]
1947 pub descriptions: DescriptionTemplateConfig,
1948 #[serde(default)]
1950 pub references: ReferenceTemplateConfig,
1951}
1952
1953#[derive(Debug, Clone, Serialize, Deserialize)]
1955pub struct NameTemplateConfig {
1956 #[serde(default)]
1958 pub culture_distribution: CultureDistribution,
1959 #[serde(default = "default_email_domain")]
1961 pub email_domain: String,
1962 #[serde(default = "default_true")]
1964 pub generate_realistic_names: bool,
1965}
1966
1967fn default_email_domain() -> String {
1968 "company.com".to_string()
1969}
1970
1971impl Default for NameTemplateConfig {
1972 fn default() -> Self {
1973 Self {
1974 culture_distribution: CultureDistribution::default(),
1975 email_domain: default_email_domain(),
1976 generate_realistic_names: true,
1977 }
1978 }
1979}
1980
1981#[derive(Debug, Clone, Serialize, Deserialize)]
1983pub struct CultureDistribution {
1984 pub western_us: f64,
1985 pub hispanic: f64,
1986 pub german: f64,
1987 pub french: f64,
1988 pub chinese: f64,
1989 pub japanese: f64,
1990 pub indian: f64,
1991}
1992
1993impl Default for CultureDistribution {
1994 fn default() -> Self {
1995 Self {
1996 western_us: 0.40,
1997 hispanic: 0.20,
1998 german: 0.10,
1999 french: 0.05,
2000 chinese: 0.10,
2001 japanese: 0.05,
2002 indian: 0.10,
2003 }
2004 }
2005}
2006
2007#[derive(Debug, Clone, Serialize, Deserialize)]
2009pub struct DescriptionTemplateConfig {
2010 #[serde(default = "default_true")]
2012 pub generate_header_text: bool,
2013 #[serde(default = "default_true")]
2015 pub generate_line_text: bool,
2016}
2017
2018impl Default for DescriptionTemplateConfig {
2019 fn default() -> Self {
2020 Self {
2021 generate_header_text: true,
2022 generate_line_text: true,
2023 }
2024 }
2025}
2026
2027#[derive(Debug, Clone, Serialize, Deserialize)]
2029pub struct ReferenceTemplateConfig {
2030 #[serde(default = "default_true")]
2032 pub generate_references: bool,
2033 #[serde(default = "default_invoice_prefix")]
2035 pub invoice_prefix: String,
2036 #[serde(default = "default_po_prefix")]
2038 pub po_prefix: String,
2039 #[serde(default = "default_so_prefix")]
2041 pub so_prefix: String,
2042}
2043
2044fn default_invoice_prefix() -> String {
2045 "INV".to_string()
2046}
2047fn default_po_prefix() -> String {
2048 "PO".to_string()
2049}
2050fn default_so_prefix() -> String {
2051 "SO".to_string()
2052}
2053
2054impl Default for ReferenceTemplateConfig {
2055 fn default() -> Self {
2056 Self {
2057 generate_references: true,
2058 invoice_prefix: default_invoice_prefix(),
2059 po_prefix: default_po_prefix(),
2060 so_prefix: default_so_prefix(),
2061 }
2062 }
2063}
2064
2065#[derive(Debug, Clone, Serialize, Deserialize)]
2067pub struct ApprovalConfig {
2068 #[serde(default)]
2070 pub enabled: bool,
2071 #[serde(default = "default_auto_approve_threshold")]
2073 pub auto_approve_threshold: f64,
2074 #[serde(default = "default_rejection_rate")]
2076 pub rejection_rate: f64,
2077 #[serde(default = "default_revision_rate")]
2079 pub revision_rate: f64,
2080 #[serde(default = "default_approval_delay_hours")]
2082 pub average_approval_delay_hours: f64,
2083 #[serde(default)]
2085 pub thresholds: Vec<ApprovalThresholdConfig>,
2086}
2087
2088fn default_auto_approve_threshold() -> f64 {
2089 1000.0
2090}
2091fn default_rejection_rate() -> f64 {
2092 0.02
2093}
2094fn default_revision_rate() -> f64 {
2095 0.05
2096}
2097fn default_approval_delay_hours() -> f64 {
2098 4.0
2099}
2100
2101impl Default for ApprovalConfig {
2102 fn default() -> Self {
2103 Self {
2104 enabled: false,
2105 auto_approve_threshold: default_auto_approve_threshold(),
2106 rejection_rate: default_rejection_rate(),
2107 revision_rate: default_revision_rate(),
2108 average_approval_delay_hours: default_approval_delay_hours(),
2109 thresholds: vec![
2110 ApprovalThresholdConfig {
2111 amount: 1000.0,
2112 level: 1,
2113 roles: vec!["senior_accountant".to_string()],
2114 },
2115 ApprovalThresholdConfig {
2116 amount: 10000.0,
2117 level: 2,
2118 roles: vec!["senior_accountant".to_string(), "controller".to_string()],
2119 },
2120 ApprovalThresholdConfig {
2121 amount: 100000.0,
2122 level: 3,
2123 roles: vec![
2124 "senior_accountant".to_string(),
2125 "controller".to_string(),
2126 "manager".to_string(),
2127 ],
2128 },
2129 ApprovalThresholdConfig {
2130 amount: 500000.0,
2131 level: 4,
2132 roles: vec![
2133 "senior_accountant".to_string(),
2134 "controller".to_string(),
2135 "manager".to_string(),
2136 "executive".to_string(),
2137 ],
2138 },
2139 ],
2140 }
2141 }
2142}
2143
2144#[derive(Debug, Clone, Serialize, Deserialize)]
2146pub struct ApprovalThresholdConfig {
2147 pub amount: f64,
2149 pub level: u8,
2151 pub roles: Vec<String>,
2153}
2154
2155#[derive(Debug, Clone, Serialize, Deserialize)]
2157pub struct DepartmentConfig {
2158 #[serde(default)]
2160 pub enabled: bool,
2161 #[serde(default = "default_headcount_multiplier")]
2163 pub headcount_multiplier: f64,
2164 #[serde(default)]
2166 pub custom_departments: Vec<CustomDepartmentConfig>,
2167}
2168
2169fn default_headcount_multiplier() -> f64 {
2170 1.0
2171}
2172
2173impl Default for DepartmentConfig {
2174 fn default() -> Self {
2175 Self {
2176 enabled: false,
2177 headcount_multiplier: default_headcount_multiplier(),
2178 custom_departments: Vec::new(),
2179 }
2180 }
2181}
2182
2183#[derive(Debug, Clone, Serialize, Deserialize)]
2185pub struct CustomDepartmentConfig {
2186 pub code: String,
2188 pub name: String,
2190 #[serde(default)]
2192 pub cost_center: Option<String>,
2193 #[serde(default)]
2195 pub primary_processes: Vec<String>,
2196 #[serde(default)]
2198 pub parent_code: Option<String>,
2199}
2200
2201#[derive(Debug, Clone, Default, Serialize, Deserialize)]
2207pub struct MasterDataConfig {
2208 #[serde(default)]
2210 pub vendors: VendorMasterConfig,
2211 #[serde(default)]
2213 pub customers: CustomerMasterConfig,
2214 #[serde(default)]
2216 pub materials: MaterialMasterConfig,
2217 #[serde(default)]
2219 pub fixed_assets: FixedAssetMasterConfig,
2220 #[serde(default)]
2222 pub employees: EmployeeMasterConfig,
2223 #[serde(default)]
2225 pub cost_centers: CostCenterMasterConfig,
2226}
2227
2228#[derive(Debug, Clone, Serialize, Deserialize)]
2230pub struct VendorMasterConfig {
2231 #[serde(default = "default_vendor_count")]
2233 pub count: usize,
2234 #[serde(default = "default_intercompany_percent")]
2236 pub intercompany_percent: f64,
2237 #[serde(default)]
2239 pub payment_terms_distribution: PaymentTermsDistribution,
2240 #[serde(default)]
2242 pub behavior_distribution: VendorBehaviorDistribution,
2243 #[serde(default = "default_true")]
2245 pub generate_bank_accounts: bool,
2246 #[serde(default = "default_true")]
2248 pub generate_tax_ids: bool,
2249}
2250
2251fn default_vendor_count() -> usize {
2252 500
2253}
2254
2255fn default_intercompany_percent() -> f64 {
2256 0.05
2257}
2258
2259impl Default for VendorMasterConfig {
2260 fn default() -> Self {
2261 Self {
2262 count: default_vendor_count(),
2263 intercompany_percent: default_intercompany_percent(),
2264 payment_terms_distribution: PaymentTermsDistribution::default(),
2265 behavior_distribution: VendorBehaviorDistribution::default(),
2266 generate_bank_accounts: true,
2267 generate_tax_ids: true,
2268 }
2269 }
2270}
2271
2272#[derive(Debug, Clone, Serialize, Deserialize)]
2274pub struct PaymentTermsDistribution {
2275 pub net_30: f64,
2277 pub net_60: f64,
2279 pub net_90: f64,
2281 pub two_ten_net_30: f64,
2283 pub due_on_receipt: f64,
2285 pub end_of_month: f64,
2287}
2288
2289impl Default for PaymentTermsDistribution {
2290 fn default() -> Self {
2291 Self {
2292 net_30: 0.40,
2293 net_60: 0.20,
2294 net_90: 0.10,
2295 two_ten_net_30: 0.15,
2296 due_on_receipt: 0.05,
2297 end_of_month: 0.10,
2298 }
2299 }
2300}
2301
2302#[derive(Debug, Clone, Serialize, Deserialize)]
2304pub struct VendorBehaviorDistribution {
2305 pub reliable: f64,
2307 pub sometimes_late: f64,
2309 pub inconsistent_quality: f64,
2311 pub premium: f64,
2313 pub budget: f64,
2315}
2316
2317impl Default for VendorBehaviorDistribution {
2318 fn default() -> Self {
2319 Self {
2320 reliable: 0.50,
2321 sometimes_late: 0.20,
2322 inconsistent_quality: 0.10,
2323 premium: 0.10,
2324 budget: 0.10,
2325 }
2326 }
2327}
2328
2329#[derive(Debug, Clone, Serialize, Deserialize)]
2331pub struct CustomerMasterConfig {
2332 #[serde(default = "default_customer_count")]
2334 pub count: usize,
2335 #[serde(default = "default_intercompany_percent")]
2337 pub intercompany_percent: f64,
2338 #[serde(default)]
2340 pub credit_rating_distribution: CreditRatingDistribution,
2341 #[serde(default)]
2343 pub payment_behavior_distribution: PaymentBehaviorDistribution,
2344 #[serde(default = "default_true")]
2346 pub generate_credit_limits: bool,
2347}
2348
2349fn default_customer_count() -> usize {
2350 2000
2351}
2352
2353impl Default for CustomerMasterConfig {
2354 fn default() -> Self {
2355 Self {
2356 count: default_customer_count(),
2357 intercompany_percent: default_intercompany_percent(),
2358 credit_rating_distribution: CreditRatingDistribution::default(),
2359 payment_behavior_distribution: PaymentBehaviorDistribution::default(),
2360 generate_credit_limits: true,
2361 }
2362 }
2363}
2364
2365#[derive(Debug, Clone, Serialize, Deserialize)]
2367pub struct CreditRatingDistribution {
2368 pub aaa: f64,
2370 pub aa: f64,
2372 pub a: f64,
2374 pub bbb: f64,
2376 pub bb: f64,
2378 pub b: f64,
2380 pub below_b: f64,
2382}
2383
2384impl Default for CreditRatingDistribution {
2385 fn default() -> Self {
2386 Self {
2387 aaa: 0.05,
2388 aa: 0.10,
2389 a: 0.20,
2390 bbb: 0.30,
2391 bb: 0.20,
2392 b: 0.10,
2393 below_b: 0.05,
2394 }
2395 }
2396}
2397
2398#[derive(Debug, Clone, Serialize, Deserialize)]
2400pub struct PaymentBehaviorDistribution {
2401 pub early_payer: f64,
2403 pub on_time: f64,
2405 pub occasional_late: f64,
2407 pub frequent_late: f64,
2409 pub discount_taker: f64,
2411}
2412
2413impl Default for PaymentBehaviorDistribution {
2414 fn default() -> Self {
2415 Self {
2416 early_payer: 0.10,
2417 on_time: 0.50,
2418 occasional_late: 0.25,
2419 frequent_late: 0.10,
2420 discount_taker: 0.05,
2421 }
2422 }
2423}
2424
2425#[derive(Debug, Clone, Serialize, Deserialize)]
2427pub struct MaterialMasterConfig {
2428 #[serde(default = "default_material_count")]
2430 pub count: usize,
2431 #[serde(default)]
2433 pub type_distribution: MaterialTypeDistribution,
2434 #[serde(default)]
2436 pub valuation_distribution: ValuationMethodDistribution,
2437 #[serde(default = "default_bom_percent")]
2439 pub bom_percent: f64,
2440 #[serde(default = "default_max_bom_depth")]
2442 pub max_bom_depth: u8,
2443}
2444
2445fn default_material_count() -> usize {
2446 5000
2447}
2448
2449fn default_bom_percent() -> f64 {
2450 0.20
2451}
2452
2453fn default_max_bom_depth() -> u8 {
2454 3
2455}
2456
2457impl Default for MaterialMasterConfig {
2458 fn default() -> Self {
2459 Self {
2460 count: default_material_count(),
2461 type_distribution: MaterialTypeDistribution::default(),
2462 valuation_distribution: ValuationMethodDistribution::default(),
2463 bom_percent: default_bom_percent(),
2464 max_bom_depth: default_max_bom_depth(),
2465 }
2466 }
2467}
2468
2469#[derive(Debug, Clone, Serialize, Deserialize)]
2471pub struct MaterialTypeDistribution {
2472 pub raw_material: f64,
2474 pub semi_finished: f64,
2476 pub finished_good: f64,
2478 pub trading_good: f64,
2480 pub operating_supply: f64,
2482 pub service: f64,
2484}
2485
2486impl Default for MaterialTypeDistribution {
2487 fn default() -> Self {
2488 Self {
2489 raw_material: 0.30,
2490 semi_finished: 0.15,
2491 finished_good: 0.25,
2492 trading_good: 0.15,
2493 operating_supply: 0.10,
2494 service: 0.05,
2495 }
2496 }
2497}
2498
2499#[derive(Debug, Clone, Serialize, Deserialize)]
2501pub struct ValuationMethodDistribution {
2502 pub standard_cost: f64,
2504 pub moving_average: f64,
2506 pub fifo: f64,
2508 pub lifo: f64,
2510}
2511
2512impl Default for ValuationMethodDistribution {
2513 fn default() -> Self {
2514 Self {
2515 standard_cost: 0.50,
2516 moving_average: 0.30,
2517 fifo: 0.15,
2518 lifo: 0.05,
2519 }
2520 }
2521}
2522
2523#[derive(Debug, Clone, Serialize, Deserialize)]
2525pub struct FixedAssetMasterConfig {
2526 #[serde(default = "default_asset_count")]
2528 pub count: usize,
2529 #[serde(default)]
2531 pub class_distribution: AssetClassDistribution,
2532 #[serde(default)]
2534 pub depreciation_distribution: DepreciationMethodDistribution,
2535 #[serde(default = "default_fully_depreciated_percent")]
2537 pub fully_depreciated_percent: f64,
2538 #[serde(default = "default_true")]
2540 pub generate_acquisition_history: bool,
2541}
2542
2543fn default_asset_count() -> usize {
2544 800
2545}
2546
2547fn default_fully_depreciated_percent() -> f64 {
2548 0.15
2549}
2550
2551impl Default for FixedAssetMasterConfig {
2552 fn default() -> Self {
2553 Self {
2554 count: default_asset_count(),
2555 class_distribution: AssetClassDistribution::default(),
2556 depreciation_distribution: DepreciationMethodDistribution::default(),
2557 fully_depreciated_percent: default_fully_depreciated_percent(),
2558 generate_acquisition_history: true,
2559 }
2560 }
2561}
2562
2563#[derive(Debug, Clone, Serialize, Deserialize)]
2565pub struct AssetClassDistribution {
2566 pub buildings: f64,
2568 pub machinery: f64,
2570 pub vehicles: f64,
2572 pub it_equipment: f64,
2574 pub furniture: f64,
2576 pub land: f64,
2578 pub leasehold: f64,
2580}
2581
2582impl Default for AssetClassDistribution {
2583 fn default() -> Self {
2584 Self {
2585 buildings: 0.15,
2586 machinery: 0.30,
2587 vehicles: 0.15,
2588 it_equipment: 0.20,
2589 furniture: 0.10,
2590 land: 0.05,
2591 leasehold: 0.05,
2592 }
2593 }
2594}
2595
2596#[derive(Debug, Clone, Serialize, Deserialize)]
2598pub struct DepreciationMethodDistribution {
2599 pub straight_line: f64,
2601 pub declining_balance: f64,
2603 pub double_declining: f64,
2605 pub sum_of_years: f64,
2607 pub units_of_production: f64,
2609}
2610
2611impl Default for DepreciationMethodDistribution {
2612 fn default() -> Self {
2613 Self {
2614 straight_line: 0.60,
2615 declining_balance: 0.20,
2616 double_declining: 0.10,
2617 sum_of_years: 0.05,
2618 units_of_production: 0.05,
2619 }
2620 }
2621}
2622
2623#[derive(Debug, Clone, Serialize, Deserialize)]
2625pub struct EmployeeMasterConfig {
2626 #[serde(default = "default_employee_count")]
2628 pub count: usize,
2629 #[serde(default = "default_true")]
2631 pub generate_hierarchy: bool,
2632 #[serde(default = "default_hierarchy_depth")]
2634 pub max_hierarchy_depth: u8,
2635 #[serde(default = "default_span_of_control")]
2637 pub average_span_of_control: f64,
2638 #[serde(default)]
2640 pub approval_limits: ApprovalLimitDistribution,
2641 #[serde(default)]
2643 pub department_distribution: EmployeeDepartmentDistribution,
2644}
2645
2646fn default_employee_count() -> usize {
2647 1500
2648}
2649
2650fn default_hierarchy_depth() -> u8 {
2651 6
2652}
2653
2654fn default_span_of_control() -> f64 {
2655 5.0
2656}
2657
2658impl Default for EmployeeMasterConfig {
2659 fn default() -> Self {
2660 Self {
2661 count: default_employee_count(),
2662 generate_hierarchy: true,
2663 max_hierarchy_depth: default_hierarchy_depth(),
2664 average_span_of_control: default_span_of_control(),
2665 approval_limits: ApprovalLimitDistribution::default(),
2666 department_distribution: EmployeeDepartmentDistribution::default(),
2667 }
2668 }
2669}
2670
2671#[derive(Debug, Clone, Serialize, Deserialize)]
2673pub struct ApprovalLimitDistribution {
2674 #[serde(default = "default_staff_limit")]
2676 pub staff: f64,
2677 #[serde(default = "default_senior_limit")]
2679 pub senior: f64,
2680 #[serde(default = "default_manager_limit")]
2682 pub manager: f64,
2683 #[serde(default = "default_director_limit")]
2685 pub director: f64,
2686 #[serde(default = "default_vp_limit")]
2688 pub vp: f64,
2689 #[serde(default = "default_executive_limit")]
2691 pub executive: f64,
2692}
2693
2694fn default_staff_limit() -> f64 {
2695 1000.0
2696}
2697fn default_senior_limit() -> f64 {
2698 5000.0
2699}
2700fn default_manager_limit() -> f64 {
2701 25000.0
2702}
2703fn default_director_limit() -> f64 {
2704 100000.0
2705}
2706fn default_vp_limit() -> f64 {
2707 500000.0
2708}
2709fn default_executive_limit() -> f64 {
2710 f64::INFINITY
2711}
2712
2713impl Default for ApprovalLimitDistribution {
2714 fn default() -> Self {
2715 Self {
2716 staff: default_staff_limit(),
2717 senior: default_senior_limit(),
2718 manager: default_manager_limit(),
2719 director: default_director_limit(),
2720 vp: default_vp_limit(),
2721 executive: default_executive_limit(),
2722 }
2723 }
2724}
2725
2726#[derive(Debug, Clone, Serialize, Deserialize)]
2728pub struct EmployeeDepartmentDistribution {
2729 pub finance: f64,
2731 pub procurement: f64,
2733 pub sales: f64,
2735 pub warehouse: f64,
2737 pub it: f64,
2739 pub hr: f64,
2741 pub operations: f64,
2743 pub executive: f64,
2745}
2746
2747impl Default for EmployeeDepartmentDistribution {
2748 fn default() -> Self {
2749 Self {
2750 finance: 0.12,
2751 procurement: 0.10,
2752 sales: 0.25,
2753 warehouse: 0.15,
2754 it: 0.10,
2755 hr: 0.05,
2756 operations: 0.20,
2757 executive: 0.03,
2758 }
2759 }
2760}
2761
2762#[derive(Debug, Clone, Serialize, Deserialize)]
2764pub struct CostCenterMasterConfig {
2765 #[serde(default = "default_cost_center_count")]
2767 pub count: usize,
2768 #[serde(default = "default_true")]
2770 pub generate_hierarchy: bool,
2771 #[serde(default = "default_cc_hierarchy_depth")]
2773 pub max_hierarchy_depth: u8,
2774}
2775
2776fn default_cost_center_count() -> usize {
2777 50
2778}
2779
2780fn default_cc_hierarchy_depth() -> u8 {
2781 3
2782}
2783
2784impl Default for CostCenterMasterConfig {
2785 fn default() -> Self {
2786 Self {
2787 count: default_cost_center_count(),
2788 generate_hierarchy: true,
2789 max_hierarchy_depth: default_cc_hierarchy_depth(),
2790 }
2791 }
2792}
2793
2794#[derive(Debug, Clone, Serialize, Deserialize)]
2800pub struct DocumentFlowConfig {
2801 #[serde(default)]
2803 pub p2p: P2PFlowConfig,
2804 #[serde(default)]
2806 pub o2c: O2CFlowConfig,
2807 #[serde(default = "default_true")]
2809 pub generate_document_references: bool,
2810 #[serde(default)]
2812 pub export_flow_graph: bool,
2813}
2814
2815impl Default for DocumentFlowConfig {
2816 fn default() -> Self {
2817 Self {
2818 p2p: P2PFlowConfig::default(),
2819 o2c: O2CFlowConfig::default(),
2820 generate_document_references: true,
2821 export_flow_graph: false,
2822 }
2823 }
2824}
2825
2826#[derive(Debug, Clone, Serialize, Deserialize)]
2828pub struct P2PFlowConfig {
2829 #[serde(default = "default_true")]
2831 pub enabled: bool,
2832 #[serde(default = "default_three_way_match_rate")]
2834 pub three_way_match_rate: f64,
2835 #[serde(default = "default_partial_delivery_rate")]
2837 pub partial_delivery_rate: f64,
2838 #[serde(default = "default_price_variance_rate")]
2840 pub price_variance_rate: f64,
2841 #[serde(default = "default_max_price_variance")]
2843 pub max_price_variance_percent: f64,
2844 #[serde(default = "default_quantity_variance_rate")]
2846 pub quantity_variance_rate: f64,
2847 #[serde(default = "default_po_to_gr_days")]
2849 pub average_po_to_gr_days: u32,
2850 #[serde(default = "default_gr_to_invoice_days")]
2852 pub average_gr_to_invoice_days: u32,
2853 #[serde(default = "default_invoice_to_payment_days")]
2855 pub average_invoice_to_payment_days: u32,
2856 #[serde(default)]
2858 pub line_count_distribution: DocumentLineCountDistribution,
2859 #[serde(default)]
2861 pub payment_behavior: P2PPaymentBehaviorConfig,
2862 #[serde(default)]
2864 pub over_delivery_rate: Option<f64>,
2865 #[serde(default)]
2867 pub early_payment_discount_rate: Option<f64>,
2868}
2869
2870fn default_three_way_match_rate() -> f64 {
2871 0.95
2872}
2873
2874fn default_partial_delivery_rate() -> f64 {
2875 0.15
2876}
2877
2878fn default_price_variance_rate() -> f64 {
2879 0.08
2880}
2881
2882fn default_max_price_variance() -> f64 {
2883 0.05
2884}
2885
2886fn default_quantity_variance_rate() -> f64 {
2887 0.05
2888}
2889
2890fn default_po_to_gr_days() -> u32 {
2891 14
2892}
2893
2894fn default_gr_to_invoice_days() -> u32 {
2895 5
2896}
2897
2898fn default_invoice_to_payment_days() -> u32 {
2899 30
2900}
2901
2902impl Default for P2PFlowConfig {
2903 fn default() -> Self {
2904 Self {
2905 enabled: true,
2906 three_way_match_rate: default_three_way_match_rate(),
2907 partial_delivery_rate: default_partial_delivery_rate(),
2908 price_variance_rate: default_price_variance_rate(),
2909 max_price_variance_percent: default_max_price_variance(),
2910 quantity_variance_rate: default_quantity_variance_rate(),
2911 average_po_to_gr_days: default_po_to_gr_days(),
2912 average_gr_to_invoice_days: default_gr_to_invoice_days(),
2913 average_invoice_to_payment_days: default_invoice_to_payment_days(),
2914 line_count_distribution: DocumentLineCountDistribution::default(),
2915 payment_behavior: P2PPaymentBehaviorConfig::default(),
2916 over_delivery_rate: None,
2917 early_payment_discount_rate: None,
2918 }
2919 }
2920}
2921
2922#[derive(Debug, Clone, Serialize, Deserialize)]
2928pub struct P2PPaymentBehaviorConfig {
2929 #[serde(default = "default_p2p_late_payment_rate")]
2931 pub late_payment_rate: f64,
2932 #[serde(default)]
2934 pub late_payment_days_distribution: LatePaymentDaysDistribution,
2935 #[serde(default = "default_p2p_partial_payment_rate")]
2937 pub partial_payment_rate: f64,
2938 #[serde(default = "default_p2p_payment_correction_rate")]
2940 pub payment_correction_rate: f64,
2941 #[serde(default = "default_p2p_avg_days_until_remainder")]
2943 pub avg_days_until_remainder: u32,
2944}
2945
2946fn default_p2p_late_payment_rate() -> f64 {
2947 0.15
2948}
2949
2950fn default_p2p_partial_payment_rate() -> f64 {
2951 0.05
2952}
2953
2954fn default_p2p_payment_correction_rate() -> f64 {
2955 0.02
2956}
2957
2958fn default_p2p_avg_days_until_remainder() -> u32 {
2959 30
2960}
2961
2962impl Default for P2PPaymentBehaviorConfig {
2963 fn default() -> Self {
2964 Self {
2965 late_payment_rate: default_p2p_late_payment_rate(),
2966 late_payment_days_distribution: LatePaymentDaysDistribution::default(),
2967 partial_payment_rate: default_p2p_partial_payment_rate(),
2968 payment_correction_rate: default_p2p_payment_correction_rate(),
2969 avg_days_until_remainder: default_p2p_avg_days_until_remainder(),
2970 }
2971 }
2972}
2973
2974#[derive(Debug, Clone, Serialize, Deserialize)]
2976pub struct LatePaymentDaysDistribution {
2977 #[serde(default = "default_slightly_late")]
2979 pub slightly_late_1_to_7: f64,
2980 #[serde(default = "default_late_8_14")]
2982 pub late_8_to_14: f64,
2983 #[serde(default = "default_very_late")]
2985 pub very_late_15_to_30: f64,
2986 #[serde(default = "default_severely_late")]
2988 pub severely_late_31_to_60: f64,
2989 #[serde(default = "default_extremely_late")]
2991 pub extremely_late_over_60: f64,
2992}
2993
2994fn default_slightly_late() -> f64 {
2995 0.50
2996}
2997
2998fn default_late_8_14() -> f64 {
2999 0.25
3000}
3001
3002fn default_very_late() -> f64 {
3003 0.15
3004}
3005
3006fn default_severely_late() -> f64 {
3007 0.07
3008}
3009
3010fn default_extremely_late() -> f64 {
3011 0.03
3012}
3013
3014impl Default for LatePaymentDaysDistribution {
3015 fn default() -> Self {
3016 Self {
3017 slightly_late_1_to_7: default_slightly_late(),
3018 late_8_to_14: default_late_8_14(),
3019 very_late_15_to_30: default_very_late(),
3020 severely_late_31_to_60: default_severely_late(),
3021 extremely_late_over_60: default_extremely_late(),
3022 }
3023 }
3024}
3025
3026#[derive(Debug, Clone, Serialize, Deserialize)]
3028pub struct O2CFlowConfig {
3029 #[serde(default = "default_true")]
3031 pub enabled: bool,
3032 #[serde(default = "default_credit_check_failure_rate")]
3034 pub credit_check_failure_rate: f64,
3035 #[serde(default = "default_partial_shipment_rate")]
3037 pub partial_shipment_rate: f64,
3038 #[serde(default = "default_return_rate")]
3040 pub return_rate: f64,
3041 #[serde(default = "default_bad_debt_rate")]
3043 pub bad_debt_rate: f64,
3044 #[serde(default = "default_so_to_delivery_days")]
3046 pub average_so_to_delivery_days: u32,
3047 #[serde(default = "default_delivery_to_invoice_days")]
3049 pub average_delivery_to_invoice_days: u32,
3050 #[serde(default = "default_invoice_to_receipt_days")]
3052 pub average_invoice_to_receipt_days: u32,
3053 #[serde(default)]
3055 pub line_count_distribution: DocumentLineCountDistribution,
3056 #[serde(default)]
3058 pub cash_discount: CashDiscountConfig,
3059 #[serde(default)]
3061 pub payment_behavior: O2CPaymentBehaviorConfig,
3062 #[serde(default)]
3064 pub late_payment_rate: Option<f64>,
3065}
3066
3067fn default_credit_check_failure_rate() -> f64 {
3068 0.02
3069}
3070
3071fn default_partial_shipment_rate() -> f64 {
3072 0.10
3073}
3074
3075fn default_return_rate() -> f64 {
3076 0.03
3077}
3078
3079fn default_bad_debt_rate() -> f64 {
3080 0.01
3081}
3082
3083fn default_so_to_delivery_days() -> u32 {
3084 7
3085}
3086
3087fn default_delivery_to_invoice_days() -> u32 {
3088 1
3089}
3090
3091fn default_invoice_to_receipt_days() -> u32 {
3092 45
3093}
3094
3095impl Default for O2CFlowConfig {
3096 fn default() -> Self {
3097 Self {
3098 enabled: true,
3099 credit_check_failure_rate: default_credit_check_failure_rate(),
3100 partial_shipment_rate: default_partial_shipment_rate(),
3101 return_rate: default_return_rate(),
3102 bad_debt_rate: default_bad_debt_rate(),
3103 average_so_to_delivery_days: default_so_to_delivery_days(),
3104 average_delivery_to_invoice_days: default_delivery_to_invoice_days(),
3105 average_invoice_to_receipt_days: default_invoice_to_receipt_days(),
3106 line_count_distribution: DocumentLineCountDistribution::default(),
3107 cash_discount: CashDiscountConfig::default(),
3108 payment_behavior: O2CPaymentBehaviorConfig::default(),
3109 late_payment_rate: None,
3110 }
3111 }
3112}
3113
3114#[derive(Debug, Clone, Serialize, Deserialize, Default)]
3120pub struct O2CPaymentBehaviorConfig {
3121 #[serde(default)]
3123 pub dunning: DunningConfig,
3124 #[serde(default)]
3126 pub partial_payments: PartialPaymentConfig,
3127 #[serde(default)]
3129 pub short_payments: ShortPaymentConfig,
3130 #[serde(default)]
3132 pub on_account_payments: OnAccountPaymentConfig,
3133 #[serde(default)]
3135 pub payment_corrections: PaymentCorrectionConfig,
3136}
3137
3138#[derive(Debug, Clone, Serialize, Deserialize)]
3140pub struct DunningConfig {
3141 #[serde(default)]
3143 pub enabled: bool,
3144 #[serde(default = "default_dunning_level_1_days")]
3146 pub level_1_days_overdue: u32,
3147 #[serde(default = "default_dunning_level_2_days")]
3149 pub level_2_days_overdue: u32,
3150 #[serde(default = "default_dunning_level_3_days")]
3152 pub level_3_days_overdue: u32,
3153 #[serde(default = "default_collection_days")]
3155 pub collection_days_overdue: u32,
3156 #[serde(default)]
3158 pub payment_after_dunning_rates: DunningPaymentRates,
3159 #[serde(default = "default_dunning_block_rate")]
3161 pub dunning_block_rate: f64,
3162 #[serde(default = "default_dunning_interest_rate")]
3164 pub interest_rate_per_year: f64,
3165 #[serde(default = "default_dunning_charge")]
3167 pub dunning_charge: f64,
3168}
3169
3170fn default_dunning_level_1_days() -> u32 {
3171 14
3172}
3173
3174fn default_dunning_level_2_days() -> u32 {
3175 28
3176}
3177
3178fn default_dunning_level_3_days() -> u32 {
3179 42
3180}
3181
3182fn default_collection_days() -> u32 {
3183 60
3184}
3185
3186fn default_dunning_block_rate() -> f64 {
3187 0.05
3188}
3189
3190fn default_dunning_interest_rate() -> f64 {
3191 0.09
3192}
3193
3194fn default_dunning_charge() -> f64 {
3195 25.0
3196}
3197
3198impl Default for DunningConfig {
3199 fn default() -> Self {
3200 Self {
3201 enabled: false,
3202 level_1_days_overdue: default_dunning_level_1_days(),
3203 level_2_days_overdue: default_dunning_level_2_days(),
3204 level_3_days_overdue: default_dunning_level_3_days(),
3205 collection_days_overdue: default_collection_days(),
3206 payment_after_dunning_rates: DunningPaymentRates::default(),
3207 dunning_block_rate: default_dunning_block_rate(),
3208 interest_rate_per_year: default_dunning_interest_rate(),
3209 dunning_charge: default_dunning_charge(),
3210 }
3211 }
3212}
3213
3214#[derive(Debug, Clone, Serialize, Deserialize)]
3216pub struct DunningPaymentRates {
3217 #[serde(default = "default_after_level_1")]
3219 pub after_level_1: f64,
3220 #[serde(default = "default_after_level_2")]
3222 pub after_level_2: f64,
3223 #[serde(default = "default_after_level_3")]
3225 pub after_level_3: f64,
3226 #[serde(default = "default_during_collection")]
3228 pub during_collection: f64,
3229 #[serde(default = "default_never_pay")]
3231 pub never_pay: f64,
3232}
3233
3234fn default_after_level_1() -> f64 {
3235 0.40
3236}
3237
3238fn default_after_level_2() -> f64 {
3239 0.30
3240}
3241
3242fn default_after_level_3() -> f64 {
3243 0.15
3244}
3245
3246fn default_during_collection() -> f64 {
3247 0.05
3248}
3249
3250fn default_never_pay() -> f64 {
3251 0.10
3252}
3253
3254impl Default for DunningPaymentRates {
3255 fn default() -> Self {
3256 Self {
3257 after_level_1: default_after_level_1(),
3258 after_level_2: default_after_level_2(),
3259 after_level_3: default_after_level_3(),
3260 during_collection: default_during_collection(),
3261 never_pay: default_never_pay(),
3262 }
3263 }
3264}
3265
3266#[derive(Debug, Clone, Serialize, Deserialize)]
3268pub struct PartialPaymentConfig {
3269 #[serde(default = "default_partial_payment_rate")]
3271 pub rate: f64,
3272 #[serde(default)]
3274 pub percentage_distribution: PartialPaymentPercentageDistribution,
3275 #[serde(default = "default_avg_days_until_remainder")]
3277 pub avg_days_until_remainder: u32,
3278}
3279
3280fn default_partial_payment_rate() -> f64 {
3281 0.08
3282}
3283
3284fn default_avg_days_until_remainder() -> u32 {
3285 30
3286}
3287
3288impl Default for PartialPaymentConfig {
3289 fn default() -> Self {
3290 Self {
3291 rate: default_partial_payment_rate(),
3292 percentage_distribution: PartialPaymentPercentageDistribution::default(),
3293 avg_days_until_remainder: default_avg_days_until_remainder(),
3294 }
3295 }
3296}
3297
3298#[derive(Debug, Clone, Serialize, Deserialize)]
3300pub struct PartialPaymentPercentageDistribution {
3301 #[serde(default = "default_partial_25")]
3303 pub pay_25_percent: f64,
3304 #[serde(default = "default_partial_50")]
3306 pub pay_50_percent: f64,
3307 #[serde(default = "default_partial_75")]
3309 pub pay_75_percent: f64,
3310 #[serde(default = "default_partial_random")]
3312 pub pay_random_percent: f64,
3313}
3314
3315fn default_partial_25() -> f64 {
3316 0.15
3317}
3318
3319fn default_partial_50() -> f64 {
3320 0.50
3321}
3322
3323fn default_partial_75() -> f64 {
3324 0.25
3325}
3326
3327fn default_partial_random() -> f64 {
3328 0.10
3329}
3330
3331impl Default for PartialPaymentPercentageDistribution {
3332 fn default() -> Self {
3333 Self {
3334 pay_25_percent: default_partial_25(),
3335 pay_50_percent: default_partial_50(),
3336 pay_75_percent: default_partial_75(),
3337 pay_random_percent: default_partial_random(),
3338 }
3339 }
3340}
3341
3342#[derive(Debug, Clone, Serialize, Deserialize)]
3344pub struct ShortPaymentConfig {
3345 #[serde(default = "default_short_payment_rate")]
3347 pub rate: f64,
3348 #[serde(default)]
3350 pub reason_distribution: ShortPaymentReasonDistribution,
3351 #[serde(default = "default_max_short_percent")]
3353 pub max_short_percent: f64,
3354}
3355
3356fn default_short_payment_rate() -> f64 {
3357 0.03
3358}
3359
3360fn default_max_short_percent() -> f64 {
3361 0.10
3362}
3363
3364impl Default for ShortPaymentConfig {
3365 fn default() -> Self {
3366 Self {
3367 rate: default_short_payment_rate(),
3368 reason_distribution: ShortPaymentReasonDistribution::default(),
3369 max_short_percent: default_max_short_percent(),
3370 }
3371 }
3372}
3373
3374#[derive(Debug, Clone, Serialize, Deserialize)]
3376pub struct ShortPaymentReasonDistribution {
3377 #[serde(default = "default_pricing_dispute")]
3379 pub pricing_dispute: f64,
3380 #[serde(default = "default_quality_issue")]
3382 pub quality_issue: f64,
3383 #[serde(default = "default_quantity_discrepancy")]
3385 pub quantity_discrepancy: f64,
3386 #[serde(default = "default_unauthorized_deduction")]
3388 pub unauthorized_deduction: f64,
3389 #[serde(default = "default_incorrect_discount")]
3391 pub incorrect_discount: f64,
3392}
3393
3394fn default_pricing_dispute() -> f64 {
3395 0.30
3396}
3397
3398fn default_quality_issue() -> f64 {
3399 0.20
3400}
3401
3402fn default_quantity_discrepancy() -> f64 {
3403 0.20
3404}
3405
3406fn default_unauthorized_deduction() -> f64 {
3407 0.15
3408}
3409
3410fn default_incorrect_discount() -> f64 {
3411 0.15
3412}
3413
3414impl Default for ShortPaymentReasonDistribution {
3415 fn default() -> Self {
3416 Self {
3417 pricing_dispute: default_pricing_dispute(),
3418 quality_issue: default_quality_issue(),
3419 quantity_discrepancy: default_quantity_discrepancy(),
3420 unauthorized_deduction: default_unauthorized_deduction(),
3421 incorrect_discount: default_incorrect_discount(),
3422 }
3423 }
3424}
3425
3426#[derive(Debug, Clone, Serialize, Deserialize)]
3428pub struct OnAccountPaymentConfig {
3429 #[serde(default = "default_on_account_rate")]
3431 pub rate: f64,
3432 #[serde(default = "default_avg_days_until_applied")]
3434 pub avg_days_until_applied: u32,
3435}
3436
3437fn default_on_account_rate() -> f64 {
3438 0.02
3439}
3440
3441fn default_avg_days_until_applied() -> u32 {
3442 14
3443}
3444
3445impl Default for OnAccountPaymentConfig {
3446 fn default() -> Self {
3447 Self {
3448 rate: default_on_account_rate(),
3449 avg_days_until_applied: default_avg_days_until_applied(),
3450 }
3451 }
3452}
3453
3454#[derive(Debug, Clone, Serialize, Deserialize)]
3456pub struct PaymentCorrectionConfig {
3457 #[serde(default = "default_payment_correction_rate")]
3459 pub rate: f64,
3460 #[serde(default)]
3462 pub type_distribution: PaymentCorrectionTypeDistribution,
3463}
3464
3465fn default_payment_correction_rate() -> f64 {
3466 0.02
3467}
3468
3469impl Default for PaymentCorrectionConfig {
3470 fn default() -> Self {
3471 Self {
3472 rate: default_payment_correction_rate(),
3473 type_distribution: PaymentCorrectionTypeDistribution::default(),
3474 }
3475 }
3476}
3477
3478#[derive(Debug, Clone, Serialize, Deserialize)]
3480pub struct PaymentCorrectionTypeDistribution {
3481 #[serde(default = "default_nsf_rate")]
3483 pub nsf: f64,
3484 #[serde(default = "default_chargeback_rate")]
3486 pub chargeback: f64,
3487 #[serde(default = "default_wrong_amount_rate")]
3489 pub wrong_amount: f64,
3490 #[serde(default = "default_wrong_customer_rate")]
3492 pub wrong_customer: f64,
3493 #[serde(default = "default_duplicate_payment_rate")]
3495 pub duplicate_payment: f64,
3496}
3497
3498fn default_nsf_rate() -> f64 {
3499 0.30
3500}
3501
3502fn default_chargeback_rate() -> f64 {
3503 0.20
3504}
3505
3506fn default_wrong_amount_rate() -> f64 {
3507 0.20
3508}
3509
3510fn default_wrong_customer_rate() -> f64 {
3511 0.15
3512}
3513
3514fn default_duplicate_payment_rate() -> f64 {
3515 0.15
3516}
3517
3518impl Default for PaymentCorrectionTypeDistribution {
3519 fn default() -> Self {
3520 Self {
3521 nsf: default_nsf_rate(),
3522 chargeback: default_chargeback_rate(),
3523 wrong_amount: default_wrong_amount_rate(),
3524 wrong_customer: default_wrong_customer_rate(),
3525 duplicate_payment: default_duplicate_payment_rate(),
3526 }
3527 }
3528}
3529
3530#[derive(Debug, Clone, Serialize, Deserialize)]
3532pub struct DocumentLineCountDistribution {
3533 #[serde(default = "default_min_lines")]
3535 pub min_lines: u32,
3536 #[serde(default = "default_max_lines")]
3538 pub max_lines: u32,
3539 #[serde(default = "default_mode_lines")]
3541 pub mode_lines: u32,
3542}
3543
3544fn default_min_lines() -> u32 {
3545 1
3546}
3547
3548fn default_max_lines() -> u32 {
3549 20
3550}
3551
3552fn default_mode_lines() -> u32 {
3553 3
3554}
3555
3556impl Default for DocumentLineCountDistribution {
3557 fn default() -> Self {
3558 Self {
3559 min_lines: default_min_lines(),
3560 max_lines: default_max_lines(),
3561 mode_lines: default_mode_lines(),
3562 }
3563 }
3564}
3565
3566#[derive(Debug, Clone, Serialize, Deserialize)]
3568pub struct CashDiscountConfig {
3569 #[serde(default = "default_discount_eligible_rate")]
3571 pub eligible_rate: f64,
3572 #[serde(default = "default_discount_taken_rate")]
3574 pub taken_rate: f64,
3575 #[serde(default = "default_discount_percent")]
3577 pub discount_percent: f64,
3578 #[serde(default = "default_discount_days")]
3580 pub discount_days: u32,
3581}
3582
3583fn default_discount_eligible_rate() -> f64 {
3584 0.30
3585}
3586
3587fn default_discount_taken_rate() -> f64 {
3588 0.60
3589}
3590
3591fn default_discount_percent() -> f64 {
3592 0.02
3593}
3594
3595fn default_discount_days() -> u32 {
3596 10
3597}
3598
3599impl Default for CashDiscountConfig {
3600 fn default() -> Self {
3601 Self {
3602 eligible_rate: default_discount_eligible_rate(),
3603 taken_rate: default_discount_taken_rate(),
3604 discount_percent: default_discount_percent(),
3605 discount_days: default_discount_days(),
3606 }
3607 }
3608}
3609
3610#[derive(Debug, Clone, Serialize, Deserialize)]
3616pub struct IntercompanyConfig {
3617 #[serde(default)]
3619 pub enabled: bool,
3620 #[serde(default = "default_ic_transaction_rate")]
3622 pub ic_transaction_rate: f64,
3623 #[serde(default)]
3625 pub transfer_pricing_method: TransferPricingMethod,
3626 #[serde(default = "default_markup_percent")]
3628 pub markup_percent: f64,
3629 #[serde(default = "default_true")]
3631 pub generate_matched_pairs: bool,
3632 #[serde(default)]
3634 pub transaction_type_distribution: ICTransactionTypeDistribution,
3635 #[serde(default)]
3637 pub generate_eliminations: bool,
3638}
3639
3640fn default_ic_transaction_rate() -> f64 {
3641 0.15
3642}
3643
3644fn default_markup_percent() -> f64 {
3645 0.05
3646}
3647
3648impl Default for IntercompanyConfig {
3649 fn default() -> Self {
3650 Self {
3651 enabled: false,
3652 ic_transaction_rate: default_ic_transaction_rate(),
3653 transfer_pricing_method: TransferPricingMethod::default(),
3654 markup_percent: default_markup_percent(),
3655 generate_matched_pairs: true,
3656 transaction_type_distribution: ICTransactionTypeDistribution::default(),
3657 generate_eliminations: false,
3658 }
3659 }
3660}
3661
3662#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
3664#[serde(rename_all = "snake_case")]
3665pub enum TransferPricingMethod {
3666 #[default]
3668 CostPlus,
3669 ComparableUncontrolled,
3671 ResalePrice,
3673 TransactionalNetMargin,
3675 ProfitSplit,
3677}
3678
3679#[derive(Debug, Clone, Serialize, Deserialize)]
3681pub struct ICTransactionTypeDistribution {
3682 pub goods_sale: f64,
3684 pub service_provided: f64,
3686 pub loan: f64,
3688 pub dividend: f64,
3690 pub management_fee: f64,
3692 pub royalty: f64,
3694 pub cost_sharing: f64,
3696}
3697
3698impl Default for ICTransactionTypeDistribution {
3699 fn default() -> Self {
3700 Self {
3701 goods_sale: 0.35,
3702 service_provided: 0.20,
3703 loan: 0.10,
3704 dividend: 0.05,
3705 management_fee: 0.15,
3706 royalty: 0.10,
3707 cost_sharing: 0.05,
3708 }
3709 }
3710}
3711
3712#[derive(Debug, Clone, Serialize, Deserialize)]
3718pub struct BalanceConfig {
3719 #[serde(default)]
3721 pub generate_opening_balances: bool,
3722 #[serde(default = "default_true")]
3724 pub generate_trial_balances: bool,
3725 #[serde(default = "default_gross_margin")]
3727 pub target_gross_margin: f64,
3728 #[serde(default = "default_dso")]
3730 pub target_dso_days: u32,
3731 #[serde(default = "default_dpo")]
3733 pub target_dpo_days: u32,
3734 #[serde(default = "default_current_ratio")]
3736 pub target_current_ratio: f64,
3737 #[serde(default = "default_debt_equity")]
3739 pub target_debt_to_equity: f64,
3740 #[serde(default = "default_true")]
3742 pub validate_balance_equation: bool,
3743 #[serde(default = "default_true")]
3745 pub reconcile_subledgers: bool,
3746}
3747
3748fn default_gross_margin() -> f64 {
3749 0.35
3750}
3751
3752fn default_dso() -> u32 {
3753 45
3754}
3755
3756fn default_dpo() -> u32 {
3757 30
3758}
3759
3760fn default_current_ratio() -> f64 {
3761 1.5
3762}
3763
3764fn default_debt_equity() -> f64 {
3765 0.5
3766}
3767
3768impl Default for BalanceConfig {
3769 fn default() -> Self {
3770 Self {
3771 generate_opening_balances: false,
3772 generate_trial_balances: true,
3773 target_gross_margin: default_gross_margin(),
3774 target_dso_days: default_dso(),
3775 target_dpo_days: default_dpo(),
3776 target_current_ratio: default_current_ratio(),
3777 target_debt_to_equity: default_debt_equity(),
3778 validate_balance_equation: true,
3779 reconcile_subledgers: true,
3780 }
3781 }
3782}
3783
3784#[derive(Debug, Clone, Serialize, Deserialize)]
3793pub struct OcpmConfig {
3794 #[serde(default)]
3796 pub enabled: bool,
3797
3798 #[serde(default = "default_true")]
3800 pub generate_lifecycle_events: bool,
3801
3802 #[serde(default = "default_true")]
3804 pub include_object_relationships: bool,
3805
3806 #[serde(default = "default_true")]
3808 pub compute_variants: bool,
3809
3810 #[serde(default)]
3812 pub max_variants: usize,
3813
3814 #[serde(default)]
3816 pub p2p_process: OcpmProcessConfig,
3817
3818 #[serde(default)]
3820 pub o2c_process: OcpmProcessConfig,
3821
3822 #[serde(default)]
3824 pub output: OcpmOutputConfig,
3825}
3826
3827impl Default for OcpmConfig {
3828 fn default() -> Self {
3829 Self {
3830 enabled: false,
3831 generate_lifecycle_events: true,
3832 include_object_relationships: true,
3833 compute_variants: true,
3834 max_variants: 0,
3835 p2p_process: OcpmProcessConfig::default(),
3836 o2c_process: OcpmProcessConfig::default(),
3837 output: OcpmOutputConfig::default(),
3838 }
3839 }
3840}
3841
3842#[derive(Debug, Clone, Serialize, Deserialize)]
3844pub struct OcpmProcessConfig {
3845 #[serde(default = "default_rework_probability")]
3847 pub rework_probability: f64,
3848
3849 #[serde(default = "default_skip_probability")]
3851 pub skip_step_probability: f64,
3852
3853 #[serde(default = "default_out_of_order_probability")]
3855 pub out_of_order_probability: f64,
3856}
3857
3858fn default_rework_probability() -> f64 {
3859 0.05
3860}
3861
3862fn default_skip_probability() -> f64 {
3863 0.02
3864}
3865
3866fn default_out_of_order_probability() -> f64 {
3867 0.03
3868}
3869
3870impl Default for OcpmProcessConfig {
3871 fn default() -> Self {
3872 Self {
3873 rework_probability: default_rework_probability(),
3874 skip_step_probability: default_skip_probability(),
3875 out_of_order_probability: default_out_of_order_probability(),
3876 }
3877 }
3878}
3879
3880#[derive(Debug, Clone, Serialize, Deserialize)]
3882pub struct OcpmOutputConfig {
3883 #[serde(default = "default_true")]
3885 pub ocel_json: bool,
3886
3887 #[serde(default)]
3889 pub ocel_xml: bool,
3890
3891 #[serde(default)]
3893 pub xes: bool,
3894
3895 #[serde(default = "default_true")]
3897 pub xes_include_lifecycle: bool,
3898
3899 #[serde(default = "default_true")]
3901 pub xes_include_resources: bool,
3902
3903 #[serde(default = "default_true")]
3905 pub flattened_csv: bool,
3906
3907 #[serde(default = "default_true")]
3909 pub event_object_csv: bool,
3910
3911 #[serde(default = "default_true")]
3913 pub object_relationship_csv: bool,
3914
3915 #[serde(default = "default_true")]
3917 pub variants_csv: bool,
3918
3919 #[serde(default)]
3921 pub export_reference_models: bool,
3922}
3923
3924impl Default for OcpmOutputConfig {
3925 fn default() -> Self {
3926 Self {
3927 ocel_json: true,
3928 ocel_xml: false,
3929 xes: false,
3930 xes_include_lifecycle: true,
3931 xes_include_resources: true,
3932 flattened_csv: true,
3933 event_object_csv: true,
3934 object_relationship_csv: true,
3935 variants_csv: true,
3936 export_reference_models: false,
3937 }
3938 }
3939}
3940
3941#[derive(Debug, Clone, Serialize, Deserialize)]
3943pub struct AuditGenerationConfig {
3944 #[serde(default)]
3946 pub enabled: bool,
3947
3948 #[serde(default = "default_true")]
3951 pub generate_workpapers: bool,
3952
3953 #[serde(default)]
3956 pub engagement_types: AuditEngagementTypesConfig,
3957
3958 #[serde(default)]
3961 pub workpapers: WorkpaperConfig,
3962
3963 #[serde(default)]
3966 pub team: AuditTeamConfig,
3967
3968 #[serde(default)]
3971 pub review: ReviewWorkflowConfig,
3972
3973 #[serde(default)]
3975 pub fsm: Option<AuditFsmConfig>,
3976}
3977
3978impl Default for AuditGenerationConfig {
3979 fn default() -> Self {
3980 Self {
3981 enabled: false,
3982 generate_workpapers: true,
3983 engagement_types: AuditEngagementTypesConfig::default(),
3984 workpapers: WorkpaperConfig::default(),
3985 team: AuditTeamConfig::default(),
3986 review: ReviewWorkflowConfig::default(),
3987 fsm: None,
3988 }
3989 }
3990}
3991
3992#[derive(Debug, Clone, Serialize, Deserialize)]
3994pub struct AuditFsmConfig {
3995 #[serde(default)]
3997 pub enabled: bool,
3998
3999 #[serde(default = "default_audit_fsm_blueprint")]
4001 pub blueprint: String,
4002
4003 #[serde(default = "default_audit_fsm_overlay")]
4005 pub overlay: String,
4006
4007 #[serde(default)]
4009 pub depth: Option<String>,
4010
4011 #[serde(default)]
4013 pub discriminators: std::collections::HashMap<String, Vec<String>>,
4014
4015 #[serde(default)]
4017 pub event_trail: AuditEventTrailConfig,
4018
4019 #[serde(default)]
4021 pub seed: Option<u64>,
4022}
4023
4024impl Default for AuditFsmConfig {
4025 fn default() -> Self {
4026 Self {
4027 enabled: false,
4028 blueprint: default_audit_fsm_blueprint(),
4029 overlay: default_audit_fsm_overlay(),
4030 depth: None,
4031 discriminators: std::collections::HashMap::new(),
4032 event_trail: AuditEventTrailConfig::default(),
4033 seed: None,
4034 }
4035 }
4036}
4037
4038fn default_audit_fsm_blueprint() -> String {
4039 "builtin:fsa".to_string()
4040}
4041
4042fn default_audit_fsm_overlay() -> String {
4043 "builtin:default".to_string()
4044}
4045
4046#[derive(Debug, Clone, Serialize, Deserialize)]
4048pub struct AuditEventTrailConfig {
4049 #[serde(default = "default_true")]
4051 pub flat_log: bool,
4052 #[serde(default)]
4054 pub ocel_projection: bool,
4055}
4056
4057impl Default for AuditEventTrailConfig {
4058 fn default() -> Self {
4059 Self {
4060 flat_log: true,
4061 ocel_projection: false,
4062 }
4063 }
4064}
4065
4066#[derive(Debug, Clone, Serialize, Deserialize)]
4068pub struct AuditEngagementTypesConfig {
4069 #[serde(default = "default_financial_audit_prob")]
4071 pub financial_statement: f64,
4072 #[serde(default = "default_sox_audit_prob")]
4074 pub sox_icfr: f64,
4075 #[serde(default = "default_integrated_audit_prob")]
4077 pub integrated: f64,
4078 #[serde(default = "default_review_prob")]
4080 pub review: f64,
4081 #[serde(default = "default_aup_prob")]
4083 pub agreed_upon_procedures: f64,
4084}
4085
4086fn default_financial_audit_prob() -> f64 {
4087 0.40
4088}
4089fn default_sox_audit_prob() -> f64 {
4090 0.20
4091}
4092fn default_integrated_audit_prob() -> f64 {
4093 0.25
4094}
4095fn default_review_prob() -> f64 {
4096 0.10
4097}
4098fn default_aup_prob() -> f64 {
4099 0.05
4100}
4101
4102impl Default for AuditEngagementTypesConfig {
4103 fn default() -> Self {
4104 Self {
4105 financial_statement: default_financial_audit_prob(),
4106 sox_icfr: default_sox_audit_prob(),
4107 integrated: default_integrated_audit_prob(),
4108 review: default_review_prob(),
4109 agreed_upon_procedures: default_aup_prob(),
4110 }
4111 }
4112}
4113
4114#[derive(Debug, Clone, Serialize, Deserialize)]
4116pub struct WorkpaperConfig {
4117 #[serde(default = "default_workpapers_per_phase")]
4119 pub average_per_phase: usize,
4120
4121 #[serde(default = "default_true")]
4123 pub include_isa_references: bool,
4124
4125 #[serde(default = "default_true")]
4127 pub include_sample_details: bool,
4128
4129 #[serde(default = "default_true")]
4131 pub include_cross_references: bool,
4132
4133 #[serde(default)]
4135 pub sampling: SamplingConfig,
4136}
4137
4138fn default_workpapers_per_phase() -> usize {
4139 5
4140}
4141
4142impl Default for WorkpaperConfig {
4143 fn default() -> Self {
4144 Self {
4145 average_per_phase: default_workpapers_per_phase(),
4146 include_isa_references: true,
4147 include_sample_details: true,
4148 include_cross_references: true,
4149 sampling: SamplingConfig::default(),
4150 }
4151 }
4152}
4153
4154#[derive(Debug, Clone, Serialize, Deserialize)]
4156pub struct SamplingConfig {
4157 #[serde(default = "default_statistical_rate")]
4159 pub statistical_rate: f64,
4160 #[serde(default = "default_judgmental_rate")]
4162 pub judgmental_rate: f64,
4163 #[serde(default = "default_haphazard_rate")]
4165 pub haphazard_rate: f64,
4166 #[serde(default = "default_complete_examination_rate")]
4168 pub complete_examination_rate: f64,
4169}
4170
4171fn default_statistical_rate() -> f64 {
4172 0.40
4173}
4174fn default_judgmental_rate() -> f64 {
4175 0.30
4176}
4177fn default_haphazard_rate() -> f64 {
4178 0.20
4179}
4180fn default_complete_examination_rate() -> f64 {
4181 0.10
4182}
4183
4184impl Default for SamplingConfig {
4185 fn default() -> Self {
4186 Self {
4187 statistical_rate: default_statistical_rate(),
4188 judgmental_rate: default_judgmental_rate(),
4189 haphazard_rate: default_haphazard_rate(),
4190 complete_examination_rate: default_complete_examination_rate(),
4191 }
4192 }
4193}
4194
4195#[derive(Debug, Clone, Serialize, Deserialize)]
4197pub struct AuditTeamConfig {
4198 #[serde(default = "default_min_team_size")]
4200 pub min_team_size: usize,
4201 #[serde(default = "default_max_team_size")]
4203 pub max_team_size: usize,
4204 #[serde(default = "default_specialist_probability")]
4206 pub specialist_probability: f64,
4207}
4208
4209fn default_min_team_size() -> usize {
4210 3
4211}
4212fn default_max_team_size() -> usize {
4213 8
4214}
4215fn default_specialist_probability() -> f64 {
4216 0.30
4217}
4218
4219impl Default for AuditTeamConfig {
4220 fn default() -> Self {
4221 Self {
4222 min_team_size: default_min_team_size(),
4223 max_team_size: default_max_team_size(),
4224 specialist_probability: default_specialist_probability(),
4225 }
4226 }
4227}
4228
4229#[derive(Debug, Clone, Serialize, Deserialize)]
4231pub struct ReviewWorkflowConfig {
4232 #[serde(default = "default_review_delay_days")]
4234 pub average_review_delay_days: u32,
4235 #[serde(default = "default_rework_probability_review")]
4237 pub rework_probability: f64,
4238 #[serde(default = "default_true")]
4240 pub require_partner_signoff: bool,
4241}
4242
4243fn default_review_delay_days() -> u32 {
4244 2
4245}
4246fn default_rework_probability_review() -> f64 {
4247 0.15
4248}
4249
4250impl Default for ReviewWorkflowConfig {
4251 fn default() -> Self {
4252 Self {
4253 average_review_delay_days: default_review_delay_days(),
4254 rework_probability: default_rework_probability_review(),
4255 require_partner_signoff: true,
4256 }
4257 }
4258}
4259
4260#[derive(Debug, Clone, Serialize, Deserialize)]
4266pub struct DataQualitySchemaConfig {
4267 #[serde(default)]
4269 pub enabled: bool,
4270 #[serde(default)]
4272 pub preset: DataQualityPreset,
4273 #[serde(default)]
4275 pub missing_values: MissingValuesSchemaConfig,
4276 #[serde(default)]
4278 pub typos: TypoSchemaConfig,
4279 #[serde(default)]
4281 pub format_variations: FormatVariationSchemaConfig,
4282 #[serde(default)]
4284 pub duplicates: DuplicateSchemaConfig,
4285 #[serde(default)]
4287 pub encoding_issues: EncodingIssueSchemaConfig,
4288 #[serde(default)]
4290 pub generate_labels: bool,
4291 #[serde(default)]
4293 pub sink_profiles: SinkQualityProfiles,
4294}
4295
4296impl Default for DataQualitySchemaConfig {
4297 fn default() -> Self {
4298 Self {
4299 enabled: false,
4300 preset: DataQualityPreset::None,
4301 missing_values: MissingValuesSchemaConfig::default(),
4302 typos: TypoSchemaConfig::default(),
4303 format_variations: FormatVariationSchemaConfig::default(),
4304 duplicates: DuplicateSchemaConfig::default(),
4305 encoding_issues: EncodingIssueSchemaConfig::default(),
4306 generate_labels: true,
4307 sink_profiles: SinkQualityProfiles::default(),
4308 }
4309 }
4310}
4311
4312impl DataQualitySchemaConfig {
4313 pub fn with_preset(preset: DataQualityPreset) -> Self {
4315 let mut config = Self {
4316 preset,
4317 ..Default::default()
4318 };
4319 config.apply_preset();
4320 config
4321 }
4322
4323 pub fn apply_preset(&mut self) {
4326 if !self.preset.overrides_settings() {
4327 return;
4328 }
4329
4330 self.enabled = true;
4331
4332 self.missing_values.enabled = self.preset.missing_rate() > 0.0;
4334 self.missing_values.rate = self.preset.missing_rate();
4335
4336 self.typos.enabled = self.preset.typo_rate() > 0.0;
4338 self.typos.char_error_rate = self.preset.typo_rate();
4339
4340 self.duplicates.enabled = self.preset.duplicate_rate() > 0.0;
4342 self.duplicates.exact_duplicate_ratio = self.preset.duplicate_rate() * 0.4;
4343 self.duplicates.near_duplicate_ratio = self.preset.duplicate_rate() * 0.4;
4344 self.duplicates.fuzzy_duplicate_ratio = self.preset.duplicate_rate() * 0.2;
4345
4346 self.format_variations.enabled = self.preset.format_variations_enabled();
4348
4349 self.encoding_issues.enabled = self.preset.encoding_issues_enabled();
4351 self.encoding_issues.rate = self.preset.encoding_issue_rate();
4352
4353 if self.preset.ocr_errors_enabled() {
4355 self.typos.type_weights.ocr_errors = 0.3;
4356 }
4357 }
4358
4359 pub fn effective_missing_rate(&self) -> f64 {
4361 if self.preset.overrides_settings() {
4362 self.preset.missing_rate()
4363 } else {
4364 self.missing_values.rate
4365 }
4366 }
4367
4368 pub fn effective_typo_rate(&self) -> f64 {
4370 if self.preset.overrides_settings() {
4371 self.preset.typo_rate()
4372 } else {
4373 self.typos.char_error_rate
4374 }
4375 }
4376
4377 pub fn effective_duplicate_rate(&self) -> f64 {
4379 if self.preset.overrides_settings() {
4380 self.preset.duplicate_rate()
4381 } else {
4382 self.duplicates.exact_duplicate_ratio
4383 + self.duplicates.near_duplicate_ratio
4384 + self.duplicates.fuzzy_duplicate_ratio
4385 }
4386 }
4387
4388 pub fn clean() -> Self {
4390 Self::with_preset(DataQualityPreset::Clean)
4391 }
4392
4393 pub fn noisy() -> Self {
4395 Self::with_preset(DataQualityPreset::Noisy)
4396 }
4397
4398 pub fn legacy() -> Self {
4400 Self::with_preset(DataQualityPreset::Legacy)
4401 }
4402}
4403
4404#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
4406#[serde(rename_all = "snake_case")]
4407pub enum DataQualityPreset {
4408 #[default]
4410 None,
4411 Minimal,
4413 Normal,
4415 High,
4417 Custom,
4419
4420 Clean,
4426 Noisy,
4429 Legacy,
4432}
4433
4434impl DataQualityPreset {
4435 pub fn missing_rate(&self) -> f64 {
4437 match self {
4438 DataQualityPreset::None => 0.0,
4439 DataQualityPreset::Minimal => 0.005,
4440 DataQualityPreset::Normal => 0.02,
4441 DataQualityPreset::High => 0.08,
4442 DataQualityPreset::Custom => 0.01, DataQualityPreset::Clean => 0.001,
4444 DataQualityPreset::Noisy => 0.05,
4445 DataQualityPreset::Legacy => 0.10,
4446 }
4447 }
4448
4449 pub fn typo_rate(&self) -> f64 {
4451 match self {
4452 DataQualityPreset::None => 0.0,
4453 DataQualityPreset::Minimal => 0.0005,
4454 DataQualityPreset::Normal => 0.002,
4455 DataQualityPreset::High => 0.01,
4456 DataQualityPreset::Custom => 0.001, DataQualityPreset::Clean => 0.0005,
4458 DataQualityPreset::Noisy => 0.02,
4459 DataQualityPreset::Legacy => 0.05,
4460 }
4461 }
4462
4463 pub fn duplicate_rate(&self) -> f64 {
4465 match self {
4466 DataQualityPreset::None => 0.0,
4467 DataQualityPreset::Minimal => 0.001,
4468 DataQualityPreset::Normal => 0.005,
4469 DataQualityPreset::High => 0.02,
4470 DataQualityPreset::Custom => 0.0, DataQualityPreset::Clean => 0.0,
4472 DataQualityPreset::Noisy => 0.01,
4473 DataQualityPreset::Legacy => 0.03,
4474 }
4475 }
4476
4477 pub fn format_variations_enabled(&self) -> bool {
4479 match self {
4480 DataQualityPreset::None | DataQualityPreset::Clean => false,
4481 DataQualityPreset::Minimal => true,
4482 DataQualityPreset::Normal => true,
4483 DataQualityPreset::High => true,
4484 DataQualityPreset::Custom => true,
4485 DataQualityPreset::Noisy => true,
4486 DataQualityPreset::Legacy => true,
4487 }
4488 }
4489
4490 pub fn ocr_errors_enabled(&self) -> bool {
4492 matches!(self, DataQualityPreset::Legacy | DataQualityPreset::High)
4493 }
4494
4495 pub fn encoding_issues_enabled(&self) -> bool {
4497 matches!(
4498 self,
4499 DataQualityPreset::Legacy | DataQualityPreset::High | DataQualityPreset::Noisy
4500 )
4501 }
4502
4503 pub fn encoding_issue_rate(&self) -> f64 {
4505 match self {
4506 DataQualityPreset::None | DataQualityPreset::Clean | DataQualityPreset::Minimal => 0.0,
4507 DataQualityPreset::Normal => 0.002,
4508 DataQualityPreset::High => 0.01,
4509 DataQualityPreset::Custom => 0.0,
4510 DataQualityPreset::Noisy => 0.005,
4511 DataQualityPreset::Legacy => 0.02,
4512 }
4513 }
4514
4515 pub fn overrides_settings(&self) -> bool {
4517 !matches!(self, DataQualityPreset::Custom | DataQualityPreset::None)
4518 }
4519
4520 pub fn description(&self) -> &'static str {
4522 match self {
4523 DataQualityPreset::None => "No data quality issues (pristine data)",
4524 DataQualityPreset::Minimal => "Very rare data quality issues",
4525 DataQualityPreset::Normal => "Realistic enterprise data quality",
4526 DataQualityPreset::High => "Messy data for stress testing",
4527 DataQualityPreset::Custom => "Custom settings from configuration",
4528 DataQualityPreset::Clean => "ML-ready clean data with minimal issues",
4529 DataQualityPreset::Noisy => "Typical production data with moderate issues",
4530 DataQualityPreset::Legacy => "Legacy/migrated data with heavy issues and OCR errors",
4531 }
4532 }
4533}
4534
4535#[derive(Debug, Clone, Serialize, Deserialize)]
4537pub struct MissingValuesSchemaConfig {
4538 #[serde(default)]
4540 pub enabled: bool,
4541 #[serde(default = "default_missing_rate")]
4543 pub rate: f64,
4544 #[serde(default)]
4546 pub strategy: MissingValueStrategy,
4547 #[serde(default)]
4549 pub field_rates: std::collections::HashMap<String, f64>,
4550 #[serde(default)]
4552 pub protected_fields: Vec<String>,
4553}
4554
4555fn default_missing_rate() -> f64 {
4556 0.01
4557}
4558
4559impl Default for MissingValuesSchemaConfig {
4560 fn default() -> Self {
4561 Self {
4562 enabled: false,
4563 rate: default_missing_rate(),
4564 strategy: MissingValueStrategy::Mcar,
4565 field_rates: std::collections::HashMap::new(),
4566 protected_fields: vec![
4567 "document_id".to_string(),
4568 "company_code".to_string(),
4569 "posting_date".to_string(),
4570 ],
4571 }
4572 }
4573}
4574
4575#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
4577#[serde(rename_all = "snake_case")]
4578pub enum MissingValueStrategy {
4579 #[default]
4581 Mcar,
4582 Mar,
4584 Mnar,
4586 Systematic,
4588}
4589
4590#[derive(Debug, Clone, Serialize, Deserialize)]
4592pub struct TypoSchemaConfig {
4593 #[serde(default)]
4595 pub enabled: bool,
4596 #[serde(default = "default_typo_rate")]
4598 pub char_error_rate: f64,
4599 #[serde(default)]
4601 pub type_weights: TypoTypeWeights,
4602 #[serde(default)]
4604 pub protected_fields: Vec<String>,
4605}
4606
4607fn default_typo_rate() -> f64 {
4608 0.001
4609}
4610
4611impl Default for TypoSchemaConfig {
4612 fn default() -> Self {
4613 Self {
4614 enabled: false,
4615 char_error_rate: default_typo_rate(),
4616 type_weights: TypoTypeWeights::default(),
4617 protected_fields: vec![
4618 "document_id".to_string(),
4619 "gl_account".to_string(),
4620 "company_code".to_string(),
4621 ],
4622 }
4623 }
4624}
4625
4626#[derive(Debug, Clone, Serialize, Deserialize)]
4628pub struct TypoTypeWeights {
4629 #[serde(default = "default_substitution_weight")]
4631 pub substitution: f64,
4632 #[serde(default = "default_transposition_weight")]
4634 pub transposition: f64,
4635 #[serde(default = "default_insertion_weight")]
4637 pub insertion: f64,
4638 #[serde(default = "default_deletion_weight")]
4640 pub deletion: f64,
4641 #[serde(default = "default_ocr_weight")]
4643 pub ocr_errors: f64,
4644 #[serde(default = "default_homophone_weight")]
4646 pub homophones: f64,
4647}
4648
4649fn default_substitution_weight() -> f64 {
4650 0.35
4651}
4652fn default_transposition_weight() -> f64 {
4653 0.25
4654}
4655fn default_insertion_weight() -> f64 {
4656 0.10
4657}
4658fn default_deletion_weight() -> f64 {
4659 0.15
4660}
4661fn default_ocr_weight() -> f64 {
4662 0.10
4663}
4664fn default_homophone_weight() -> f64 {
4665 0.05
4666}
4667
4668impl Default for TypoTypeWeights {
4669 fn default() -> Self {
4670 Self {
4671 substitution: default_substitution_weight(),
4672 transposition: default_transposition_weight(),
4673 insertion: default_insertion_weight(),
4674 deletion: default_deletion_weight(),
4675 ocr_errors: default_ocr_weight(),
4676 homophones: default_homophone_weight(),
4677 }
4678 }
4679}
4680
4681#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4683pub struct FormatVariationSchemaConfig {
4684 #[serde(default)]
4686 pub enabled: bool,
4687 #[serde(default)]
4689 pub dates: DateFormatVariationConfig,
4690 #[serde(default)]
4692 pub amounts: AmountFormatVariationConfig,
4693 #[serde(default)]
4695 pub identifiers: IdentifierFormatVariationConfig,
4696}
4697
4698#[derive(Debug, Clone, Serialize, Deserialize)]
4700pub struct DateFormatVariationConfig {
4701 #[serde(default)]
4703 pub enabled: bool,
4704 #[serde(default = "default_date_variation_rate")]
4706 pub rate: f64,
4707 #[serde(default = "default_true")]
4709 pub iso_format: bool,
4710 #[serde(default)]
4712 pub us_format: bool,
4713 #[serde(default)]
4715 pub eu_format: bool,
4716 #[serde(default)]
4718 pub long_format: bool,
4719}
4720
4721fn default_date_variation_rate() -> f64 {
4722 0.05
4723}
4724
4725impl Default for DateFormatVariationConfig {
4726 fn default() -> Self {
4727 Self {
4728 enabled: false,
4729 rate: default_date_variation_rate(),
4730 iso_format: true,
4731 us_format: false,
4732 eu_format: false,
4733 long_format: false,
4734 }
4735 }
4736}
4737
4738#[derive(Debug, Clone, Serialize, Deserialize)]
4740pub struct AmountFormatVariationConfig {
4741 #[serde(default)]
4743 pub enabled: bool,
4744 #[serde(default = "default_amount_variation_rate")]
4746 pub rate: f64,
4747 #[serde(default)]
4749 pub us_comma_format: bool,
4750 #[serde(default)]
4752 pub eu_format: bool,
4753 #[serde(default)]
4755 pub currency_prefix: bool,
4756 #[serde(default)]
4758 pub accounting_format: bool,
4759}
4760
4761fn default_amount_variation_rate() -> f64 {
4762 0.02
4763}
4764
4765impl Default for AmountFormatVariationConfig {
4766 fn default() -> Self {
4767 Self {
4768 enabled: false,
4769 rate: default_amount_variation_rate(),
4770 us_comma_format: false,
4771 eu_format: false,
4772 currency_prefix: false,
4773 accounting_format: false,
4774 }
4775 }
4776}
4777
4778#[derive(Debug, Clone, Serialize, Deserialize)]
4780pub struct IdentifierFormatVariationConfig {
4781 #[serde(default)]
4783 pub enabled: bool,
4784 #[serde(default = "default_identifier_variation_rate")]
4786 pub rate: f64,
4787 #[serde(default)]
4789 pub case_variations: bool,
4790 #[serde(default)]
4792 pub padding_variations: bool,
4793 #[serde(default)]
4795 pub separator_variations: bool,
4796}
4797
4798fn default_identifier_variation_rate() -> f64 {
4799 0.02
4800}
4801
4802impl Default for IdentifierFormatVariationConfig {
4803 fn default() -> Self {
4804 Self {
4805 enabled: false,
4806 rate: default_identifier_variation_rate(),
4807 case_variations: false,
4808 padding_variations: false,
4809 separator_variations: false,
4810 }
4811 }
4812}
4813
4814#[derive(Debug, Clone, Serialize, Deserialize)]
4816pub struct DuplicateSchemaConfig {
4817 #[serde(default)]
4819 pub enabled: bool,
4820 #[serde(default = "default_duplicate_rate")]
4822 pub rate: f64,
4823 #[serde(default = "default_exact_duplicate_ratio")]
4825 pub exact_duplicate_ratio: f64,
4826 #[serde(default = "default_near_duplicate_ratio")]
4828 pub near_duplicate_ratio: f64,
4829 #[serde(default = "default_fuzzy_duplicate_ratio")]
4831 pub fuzzy_duplicate_ratio: f64,
4832 #[serde(default = "default_max_date_offset")]
4834 pub max_date_offset_days: u32,
4835 #[serde(default = "default_max_amount_variance")]
4837 pub max_amount_variance: f64,
4838}
4839
4840fn default_duplicate_rate() -> f64 {
4841 0.005
4842}
4843fn default_exact_duplicate_ratio() -> f64 {
4844 0.4
4845}
4846fn default_near_duplicate_ratio() -> f64 {
4847 0.35
4848}
4849fn default_fuzzy_duplicate_ratio() -> f64 {
4850 0.25
4851}
4852fn default_max_date_offset() -> u32 {
4853 3
4854}
4855fn default_max_amount_variance() -> f64 {
4856 0.01
4857}
4858
4859impl Default for DuplicateSchemaConfig {
4860 fn default() -> Self {
4861 Self {
4862 enabled: false,
4863 rate: default_duplicate_rate(),
4864 exact_duplicate_ratio: default_exact_duplicate_ratio(),
4865 near_duplicate_ratio: default_near_duplicate_ratio(),
4866 fuzzy_duplicate_ratio: default_fuzzy_duplicate_ratio(),
4867 max_date_offset_days: default_max_date_offset(),
4868 max_amount_variance: default_max_amount_variance(),
4869 }
4870 }
4871}
4872
4873#[derive(Debug, Clone, Serialize, Deserialize)]
4875pub struct EncodingIssueSchemaConfig {
4876 #[serde(default)]
4878 pub enabled: bool,
4879 #[serde(default = "default_encoding_rate")]
4881 pub rate: f64,
4882 #[serde(default)]
4884 pub mojibake: bool,
4885 #[serde(default)]
4887 pub html_entities: bool,
4888 #[serde(default)]
4890 pub bom_issues: bool,
4891}
4892
4893fn default_encoding_rate() -> f64 {
4894 0.001
4895}
4896
4897impl Default for EncodingIssueSchemaConfig {
4898 fn default() -> Self {
4899 Self {
4900 enabled: false,
4901 rate: default_encoding_rate(),
4902 mojibake: false,
4903 html_entities: false,
4904 bom_issues: false,
4905 }
4906 }
4907}
4908
4909#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4911pub struct SinkQualityProfiles {
4912 #[serde(default)]
4914 pub csv: Option<SinkQualityOverride>,
4915 #[serde(default)]
4917 pub json: Option<SinkQualityOverride>,
4918 #[serde(default)]
4920 pub parquet: Option<SinkQualityOverride>,
4921}
4922
4923#[derive(Debug, Clone, Serialize, Deserialize)]
4925pub struct SinkQualityOverride {
4926 pub enabled: Option<bool>,
4928 pub missing_rate: Option<f64>,
4930 pub typo_rate: Option<f64>,
4932 pub format_variation_rate: Option<f64>,
4934 pub duplicate_rate: Option<f64>,
4936}
4937
4938#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4950pub struct AccountingStandardsConfig {
4951 #[serde(default)]
4953 pub enabled: bool,
4954
4955 #[serde(default, skip_serializing_if = "Option::is_none")]
4959 pub framework: Option<AccountingFrameworkConfig>,
4960
4961 #[serde(default)]
4963 pub revenue_recognition: RevenueRecognitionConfig,
4964
4965 #[serde(default)]
4967 pub leases: LeaseAccountingConfig,
4968
4969 #[serde(default)]
4971 pub fair_value: FairValueConfig,
4972
4973 #[serde(default)]
4975 pub impairment: ImpairmentConfig,
4976
4977 #[serde(default)]
4979 pub business_combinations: BusinessCombinationsConfig,
4980
4981 #[serde(default)]
4983 pub expected_credit_loss: EclConfig,
4984
4985 #[serde(default)]
4987 pub generate_differences: bool,
4988}
4989
4990#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
4992#[serde(rename_all = "snake_case")]
4993pub enum AccountingFrameworkConfig {
4994 #[default]
4996 UsGaap,
4997 Ifrs,
4999 DualReporting,
5001 FrenchGaap,
5003 GermanGaap,
5005}
5006
5007#[derive(Debug, Clone, Serialize, Deserialize)]
5009pub struct RevenueRecognitionConfig {
5010 #[serde(default)]
5012 pub enabled: bool,
5013
5014 #[serde(default = "default_true")]
5016 pub generate_contracts: bool,
5017
5018 #[serde(default = "default_avg_obligations")]
5020 pub avg_obligations_per_contract: f64,
5021
5022 #[serde(default = "default_variable_consideration_rate")]
5024 pub variable_consideration_rate: f64,
5025
5026 #[serde(default = "default_over_time_rate")]
5028 pub over_time_recognition_rate: f64,
5029
5030 #[serde(default = "default_contract_count")]
5032 pub contract_count: usize,
5033}
5034
5035fn default_avg_obligations() -> f64 {
5036 2.0
5037}
5038
5039fn default_variable_consideration_rate() -> f64 {
5040 0.15
5041}
5042
5043fn default_over_time_rate() -> f64 {
5044 0.30
5045}
5046
5047fn default_contract_count() -> usize {
5048 100
5049}
5050
5051impl Default for RevenueRecognitionConfig {
5052 fn default() -> Self {
5053 Self {
5054 enabled: false,
5055 generate_contracts: true,
5056 avg_obligations_per_contract: default_avg_obligations(),
5057 variable_consideration_rate: default_variable_consideration_rate(),
5058 over_time_recognition_rate: default_over_time_rate(),
5059 contract_count: default_contract_count(),
5060 }
5061 }
5062}
5063
5064#[derive(Debug, Clone, Serialize, Deserialize)]
5066pub struct LeaseAccountingConfig {
5067 #[serde(default)]
5069 pub enabled: bool,
5070
5071 #[serde(default = "default_lease_count")]
5073 pub lease_count: usize,
5074
5075 #[serde(default = "default_finance_lease_pct")]
5077 pub finance_lease_percent: f64,
5078
5079 #[serde(default = "default_avg_lease_term")]
5081 pub avg_lease_term_months: u32,
5082
5083 #[serde(default = "default_true")]
5085 pub generate_amortization: bool,
5086
5087 #[serde(default = "default_real_estate_pct")]
5089 pub real_estate_percent: f64,
5090}
5091
5092fn default_lease_count() -> usize {
5093 50
5094}
5095
5096fn default_finance_lease_pct() -> f64 {
5097 0.30
5098}
5099
5100fn default_avg_lease_term() -> u32 {
5101 60
5102}
5103
5104fn default_real_estate_pct() -> f64 {
5105 0.40
5106}
5107
5108impl Default for LeaseAccountingConfig {
5109 fn default() -> Self {
5110 Self {
5111 enabled: false,
5112 lease_count: default_lease_count(),
5113 finance_lease_percent: default_finance_lease_pct(),
5114 avg_lease_term_months: default_avg_lease_term(),
5115 generate_amortization: true,
5116 real_estate_percent: default_real_estate_pct(),
5117 }
5118 }
5119}
5120
5121#[derive(Debug, Clone, Serialize, Deserialize)]
5123pub struct FairValueConfig {
5124 #[serde(default)]
5126 pub enabled: bool,
5127
5128 #[serde(default = "default_fv_count")]
5130 pub measurement_count: usize,
5131
5132 #[serde(default = "default_level1_pct")]
5134 pub level1_percent: f64,
5135
5136 #[serde(default = "default_level2_pct")]
5138 pub level2_percent: f64,
5139
5140 #[serde(default = "default_level3_pct")]
5142 pub level3_percent: f64,
5143
5144 #[serde(default)]
5146 pub include_sensitivity_analysis: bool,
5147}
5148
5149fn default_fv_count() -> usize {
5150 25
5151}
5152
5153fn default_level1_pct() -> f64 {
5154 0.40
5155}
5156
5157fn default_level2_pct() -> f64 {
5158 0.35
5159}
5160
5161fn default_level3_pct() -> f64 {
5162 0.25
5163}
5164
5165impl Default for FairValueConfig {
5166 fn default() -> Self {
5167 Self {
5168 enabled: false,
5169 measurement_count: default_fv_count(),
5170 level1_percent: default_level1_pct(),
5171 level2_percent: default_level2_pct(),
5172 level3_percent: default_level3_pct(),
5173 include_sensitivity_analysis: false,
5174 }
5175 }
5176}
5177
5178#[derive(Debug, Clone, Serialize, Deserialize)]
5180pub struct ImpairmentConfig {
5181 #[serde(default)]
5183 pub enabled: bool,
5184
5185 #[serde(default = "default_impairment_count")]
5187 pub test_count: usize,
5188
5189 #[serde(default = "default_impairment_rate")]
5191 pub impairment_rate: f64,
5192
5193 #[serde(default = "default_true")]
5195 pub generate_projections: bool,
5196
5197 #[serde(default)]
5199 pub include_goodwill: bool,
5200}
5201
5202fn default_impairment_count() -> usize {
5203 15
5204}
5205
5206fn default_impairment_rate() -> f64 {
5207 0.10
5208}
5209
5210impl Default for ImpairmentConfig {
5211 fn default() -> Self {
5212 Self {
5213 enabled: false,
5214 test_count: default_impairment_count(),
5215 impairment_rate: default_impairment_rate(),
5216 generate_projections: true,
5217 include_goodwill: false,
5218 }
5219 }
5220}
5221
5222#[derive(Debug, Clone, Serialize, Deserialize)]
5228pub struct BusinessCombinationsConfig {
5229 #[serde(default)]
5231 pub enabled: bool,
5232
5233 #[serde(default = "default_bc_acquisition_count")]
5235 pub acquisition_count: usize,
5236}
5237
5238fn default_bc_acquisition_count() -> usize {
5239 2
5240}
5241
5242impl Default for BusinessCombinationsConfig {
5243 fn default() -> Self {
5244 Self {
5245 enabled: false,
5246 acquisition_count: default_bc_acquisition_count(),
5247 }
5248 }
5249}
5250
5251#[derive(Debug, Clone, Serialize, Deserialize)]
5257pub struct EclConfig {
5258 #[serde(default)]
5260 pub enabled: bool,
5261
5262 #[serde(default = "default_ecl_base_weight")]
5264 pub base_scenario_weight: f64,
5265
5266 #[serde(default = "default_ecl_base_multiplier")]
5268 pub base_scenario_multiplier: f64,
5269
5270 #[serde(default = "default_ecl_optimistic_weight")]
5272 pub optimistic_scenario_weight: f64,
5273
5274 #[serde(default = "default_ecl_optimistic_multiplier")]
5276 pub optimistic_scenario_multiplier: f64,
5277
5278 #[serde(default = "default_ecl_pessimistic_weight")]
5280 pub pessimistic_scenario_weight: f64,
5281
5282 #[serde(default = "default_ecl_pessimistic_multiplier")]
5284 pub pessimistic_scenario_multiplier: f64,
5285}
5286
5287fn default_ecl_base_weight() -> f64 {
5288 0.50
5289}
5290fn default_ecl_base_multiplier() -> f64 {
5291 1.0
5292}
5293fn default_ecl_optimistic_weight() -> f64 {
5294 0.30
5295}
5296fn default_ecl_optimistic_multiplier() -> f64 {
5297 0.8
5298}
5299fn default_ecl_pessimistic_weight() -> f64 {
5300 0.20
5301}
5302fn default_ecl_pessimistic_multiplier() -> f64 {
5303 1.4
5304}
5305
5306impl Default for EclConfig {
5307 fn default() -> Self {
5308 Self {
5309 enabled: false,
5310 base_scenario_weight: default_ecl_base_weight(),
5311 base_scenario_multiplier: default_ecl_base_multiplier(),
5312 optimistic_scenario_weight: default_ecl_optimistic_weight(),
5313 optimistic_scenario_multiplier: default_ecl_optimistic_multiplier(),
5314 pessimistic_scenario_weight: default_ecl_pessimistic_weight(),
5315 pessimistic_scenario_multiplier: default_ecl_pessimistic_multiplier(),
5316 }
5317 }
5318}
5319
5320#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5333pub struct AuditStandardsConfig {
5334 #[serde(default)]
5336 pub enabled: bool,
5337
5338 #[serde(default)]
5340 pub isa_compliance: IsaComplianceConfig,
5341
5342 #[serde(default)]
5344 pub analytical_procedures: AnalyticalProceduresConfig,
5345
5346 #[serde(default)]
5348 pub confirmations: ConfirmationsConfig,
5349
5350 #[serde(default)]
5352 pub opinion: AuditOpinionConfig,
5353
5354 #[serde(default)]
5356 pub generate_audit_trail: bool,
5357
5358 #[serde(default)]
5360 pub sox: SoxComplianceConfig,
5361
5362 #[serde(default)]
5364 pub pcaob: PcaobConfig,
5365}
5366
5367#[derive(Debug, Clone, Serialize, Deserialize)]
5369pub struct IsaComplianceConfig {
5370 #[serde(default)]
5372 pub enabled: bool,
5373
5374 #[serde(default = "default_compliance_level")]
5376 pub compliance_level: String,
5377
5378 #[serde(default = "default_true")]
5380 pub generate_isa_mappings: bool,
5381
5382 #[serde(default = "default_true")]
5384 pub generate_coverage_summary: bool,
5385
5386 #[serde(default)]
5388 pub include_pcaob: bool,
5389
5390 #[serde(default = "default_audit_framework")]
5392 pub framework: String,
5393}
5394
5395fn default_compliance_level() -> String {
5396 "standard".to_string()
5397}
5398
5399fn default_audit_framework() -> String {
5400 "isa".to_string()
5401}
5402
5403impl Default for IsaComplianceConfig {
5404 fn default() -> Self {
5405 Self {
5406 enabled: false,
5407 compliance_level: default_compliance_level(),
5408 generate_isa_mappings: true,
5409 generate_coverage_summary: true,
5410 include_pcaob: false,
5411 framework: default_audit_framework(),
5412 }
5413 }
5414}
5415
5416#[derive(Debug, Clone, Serialize, Deserialize)]
5418pub struct AnalyticalProceduresConfig {
5419 #[serde(default)]
5421 pub enabled: bool,
5422
5423 #[serde(default = "default_procedures_per_account")]
5425 pub procedures_per_account: usize,
5426
5427 #[serde(default = "default_variance_probability")]
5429 pub variance_probability: f64,
5430
5431 #[serde(default = "default_true")]
5433 pub generate_investigations: bool,
5434
5435 #[serde(default = "default_true")]
5437 pub include_ratio_analysis: bool,
5438}
5439
5440fn default_procedures_per_account() -> usize {
5441 3
5442}
5443
5444fn default_variance_probability() -> f64 {
5445 0.20
5446}
5447
5448impl Default for AnalyticalProceduresConfig {
5449 fn default() -> Self {
5450 Self {
5451 enabled: false,
5452 procedures_per_account: default_procedures_per_account(),
5453 variance_probability: default_variance_probability(),
5454 generate_investigations: true,
5455 include_ratio_analysis: true,
5456 }
5457 }
5458}
5459
5460#[derive(Debug, Clone, Serialize, Deserialize)]
5462pub struct ConfirmationsConfig {
5463 #[serde(default)]
5465 pub enabled: bool,
5466
5467 #[serde(default = "default_confirmation_count")]
5469 pub confirmation_count: usize,
5470
5471 #[serde(default = "default_positive_response_rate")]
5473 pub positive_response_rate: f64,
5474
5475 #[serde(default = "default_exception_rate_confirm")]
5477 pub exception_rate: f64,
5478
5479 #[serde(default = "default_non_response_rate")]
5481 pub non_response_rate: f64,
5482
5483 #[serde(default = "default_true")]
5485 pub generate_alternative_procedures: bool,
5486}
5487
5488fn default_confirmation_count() -> usize {
5489 50
5490}
5491
5492fn default_positive_response_rate() -> f64 {
5493 0.85
5494}
5495
5496fn default_exception_rate_confirm() -> f64 {
5497 0.10
5498}
5499
5500fn default_non_response_rate() -> f64 {
5501 0.05
5502}
5503
5504impl Default for ConfirmationsConfig {
5505 fn default() -> Self {
5506 Self {
5507 enabled: false,
5508 confirmation_count: default_confirmation_count(),
5509 positive_response_rate: default_positive_response_rate(),
5510 exception_rate: default_exception_rate_confirm(),
5511 non_response_rate: default_non_response_rate(),
5512 generate_alternative_procedures: true,
5513 }
5514 }
5515}
5516
5517#[derive(Debug, Clone, Serialize, Deserialize)]
5519pub struct AuditOpinionConfig {
5520 #[serde(default)]
5522 pub enabled: bool,
5523
5524 #[serde(default = "default_true")]
5526 pub generate_kam: bool,
5527
5528 #[serde(default = "default_kam_count")]
5530 pub average_kam_count: usize,
5531
5532 #[serde(default = "default_modified_opinion_rate")]
5534 pub modified_opinion_rate: f64,
5535
5536 #[serde(default)]
5538 pub include_emphasis_of_matter: bool,
5539
5540 #[serde(default = "default_true")]
5542 pub include_going_concern: bool,
5543}
5544
5545fn default_kam_count() -> usize {
5546 3
5547}
5548
5549fn default_modified_opinion_rate() -> f64 {
5550 0.05
5551}
5552
5553impl Default for AuditOpinionConfig {
5554 fn default() -> Self {
5555 Self {
5556 enabled: false,
5557 generate_kam: true,
5558 average_kam_count: default_kam_count(),
5559 modified_opinion_rate: default_modified_opinion_rate(),
5560 include_emphasis_of_matter: false,
5561 include_going_concern: true,
5562 }
5563 }
5564}
5565
5566#[derive(Debug, Clone, Serialize, Deserialize)]
5568pub struct SoxComplianceConfig {
5569 #[serde(default)]
5571 pub enabled: bool,
5572
5573 #[serde(default = "default_true")]
5575 pub generate_302_certifications: bool,
5576
5577 #[serde(default = "default_true")]
5579 pub generate_404_assessments: bool,
5580
5581 #[serde(default = "default_sox_materiality_threshold")]
5583 pub materiality_threshold: f64,
5584
5585 #[serde(default = "default_material_weakness_rate")]
5587 pub material_weakness_rate: f64,
5588
5589 #[serde(default = "default_significant_deficiency_rate")]
5591 pub significant_deficiency_rate: f64,
5592}
5593
5594fn default_material_weakness_rate() -> f64 {
5595 0.02
5596}
5597
5598fn default_significant_deficiency_rate() -> f64 {
5599 0.08
5600}
5601
5602impl Default for SoxComplianceConfig {
5603 fn default() -> Self {
5604 Self {
5605 enabled: false,
5606 generate_302_certifications: true,
5607 generate_404_assessments: true,
5608 materiality_threshold: default_sox_materiality_threshold(),
5609 material_weakness_rate: default_material_weakness_rate(),
5610 significant_deficiency_rate: default_significant_deficiency_rate(),
5611 }
5612 }
5613}
5614
5615#[derive(Debug, Clone, Serialize, Deserialize)]
5617pub struct PcaobConfig {
5618 #[serde(default)]
5620 pub enabled: bool,
5621
5622 #[serde(default)]
5624 pub is_pcaob_audit: bool,
5625
5626 #[serde(default = "default_true")]
5628 pub generate_cam: bool,
5629
5630 #[serde(default)]
5632 pub include_icfr_opinion: bool,
5633
5634 #[serde(default)]
5636 pub generate_standard_mappings: bool,
5637}
5638
5639impl Default for PcaobConfig {
5640 fn default() -> Self {
5641 Self {
5642 enabled: false,
5643 is_pcaob_audit: false,
5644 generate_cam: true,
5645 include_icfr_opinion: false,
5646 generate_standard_mappings: false,
5647 }
5648 }
5649}
5650
5651#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5664pub struct AdvancedDistributionConfig {
5665 #[serde(default)]
5667 pub enabled: bool,
5668
5669 #[serde(default)]
5671 pub amounts: MixtureDistributionSchemaConfig,
5672
5673 #[serde(default)]
5675 pub correlations: CorrelationSchemaConfig,
5676
5677 #[serde(default)]
5679 pub conditional: Vec<ConditionalDistributionSchemaConfig>,
5680
5681 #[serde(default)]
5683 pub regime_changes: RegimeChangeSchemaConfig,
5684
5685 #[serde(default)]
5687 pub industry_profile: Option<IndustryProfileType>,
5688
5689 #[serde(default)]
5691 pub validation: StatisticalValidationSchemaConfig,
5692}
5693
5694#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
5696#[serde(rename_all = "snake_case")]
5697pub enum IndustryProfileType {
5698 Retail,
5700 Manufacturing,
5702 FinancialServices,
5704 Healthcare,
5706 Technology,
5708}
5709
5710#[derive(Debug, Clone, Serialize, Deserialize)]
5712pub struct MixtureDistributionSchemaConfig {
5713 #[serde(default)]
5715 pub enabled: bool,
5716
5717 #[serde(default = "default_mixture_type")]
5719 pub distribution_type: MixtureDistributionType,
5720
5721 #[serde(default)]
5723 pub components: Vec<MixtureComponentConfig>,
5724
5725 #[serde(default = "default_min_amount")]
5727 pub min_value: f64,
5728
5729 #[serde(default)]
5731 pub max_value: Option<f64>,
5732
5733 #[serde(default = "default_decimal_places")]
5735 pub decimal_places: u8,
5736}
5737
5738fn default_mixture_type() -> MixtureDistributionType {
5739 MixtureDistributionType::LogNormal
5740}
5741
5742fn default_min_amount() -> f64 {
5743 0.01
5744}
5745
5746fn default_decimal_places() -> u8 {
5747 2
5748}
5749
5750impl Default for MixtureDistributionSchemaConfig {
5751 fn default() -> Self {
5752 Self {
5753 enabled: false,
5754 distribution_type: MixtureDistributionType::LogNormal,
5755 components: Vec::new(),
5756 min_value: 0.01,
5757 max_value: None,
5758 decimal_places: 2,
5759 }
5760 }
5761}
5762
5763#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5765#[serde(rename_all = "snake_case")]
5766pub enum MixtureDistributionType {
5767 Gaussian,
5769 #[default]
5771 LogNormal,
5772}
5773
5774#[derive(Debug, Clone, Serialize, Deserialize)]
5776pub struct MixtureComponentConfig {
5777 pub weight: f64,
5779
5780 pub mu: f64,
5782
5783 pub sigma: f64,
5785
5786 #[serde(default)]
5788 pub label: Option<String>,
5789}
5790
5791#[derive(Debug, Clone, Serialize, Deserialize)]
5793pub struct CorrelationSchemaConfig {
5794 #[serde(default)]
5796 pub enabled: bool,
5797
5798 #[serde(default)]
5800 pub copula_type: CopulaSchemaType,
5801
5802 #[serde(default)]
5804 pub fields: Vec<CorrelatedFieldConfig>,
5805
5806 #[serde(default)]
5809 pub matrix: Vec<f64>,
5810
5811 #[serde(default)]
5813 pub expected_correlations: Vec<ExpectedCorrelationConfig>,
5814}
5815
5816impl Default for CorrelationSchemaConfig {
5817 fn default() -> Self {
5818 Self {
5819 enabled: false,
5820 copula_type: CopulaSchemaType::Gaussian,
5821 fields: Vec::new(),
5822 matrix: Vec::new(),
5823 expected_correlations: Vec::new(),
5824 }
5825 }
5826}
5827
5828#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5830#[serde(rename_all = "snake_case")]
5831pub enum CopulaSchemaType {
5832 #[default]
5834 Gaussian,
5835 Clayton,
5837 Gumbel,
5839 Frank,
5841 StudentT,
5843}
5844
5845#[derive(Debug, Clone, Serialize, Deserialize)]
5847pub struct CorrelatedFieldConfig {
5848 pub name: String,
5850
5851 #[serde(default)]
5853 pub distribution: MarginalDistributionConfig,
5854}
5855
5856#[derive(Debug, Clone, Serialize, Deserialize)]
5858#[serde(tag = "type", rename_all = "snake_case")]
5859pub enum MarginalDistributionConfig {
5860 Normal {
5862 mu: f64,
5864 sigma: f64,
5866 },
5867 LogNormal {
5869 mu: f64,
5871 sigma: f64,
5873 },
5874 Uniform {
5876 min: f64,
5878 max: f64,
5880 },
5881 DiscreteUniform {
5883 min: i32,
5885 max: i32,
5887 },
5888}
5889
5890impl Default for MarginalDistributionConfig {
5891 fn default() -> Self {
5892 Self::Normal {
5893 mu: 0.0,
5894 sigma: 1.0,
5895 }
5896 }
5897}
5898
5899#[derive(Debug, Clone, Serialize, Deserialize)]
5901pub struct ExpectedCorrelationConfig {
5902 pub field1: String,
5904 pub field2: String,
5906 pub expected_r: f64,
5908 #[serde(default = "default_correlation_tolerance")]
5910 pub tolerance: f64,
5911}
5912
5913fn default_correlation_tolerance() -> f64 {
5914 0.10
5915}
5916
5917#[derive(Debug, Clone, Serialize, Deserialize)]
5919pub struct ConditionalDistributionSchemaConfig {
5920 pub output_field: String,
5922
5923 pub input_field: String,
5925
5926 #[serde(default)]
5928 pub breakpoints: Vec<ConditionalBreakpointConfig>,
5929
5930 #[serde(default)]
5932 pub default_distribution: ConditionalDistributionParamsConfig,
5933
5934 #[serde(default)]
5936 pub min_value: Option<f64>,
5937
5938 #[serde(default)]
5940 pub max_value: Option<f64>,
5941
5942 #[serde(default = "default_decimal_places")]
5944 pub decimal_places: u8,
5945}
5946
5947#[derive(Debug, Clone, Serialize, Deserialize)]
5949pub struct ConditionalBreakpointConfig {
5950 pub threshold: f64,
5952
5953 pub distribution: ConditionalDistributionParamsConfig,
5955}
5956
5957#[derive(Debug, Clone, Serialize, Deserialize)]
5959#[serde(tag = "type", rename_all = "snake_case")]
5960pub enum ConditionalDistributionParamsConfig {
5961 Fixed {
5963 value: f64,
5965 },
5966 Normal {
5968 mu: f64,
5970 sigma: f64,
5972 },
5973 LogNormal {
5975 mu: f64,
5977 sigma: f64,
5979 },
5980 Uniform {
5982 min: f64,
5984 max: f64,
5986 },
5987 Beta {
5989 alpha: f64,
5991 beta: f64,
5993 min: f64,
5995 max: f64,
5997 },
5998 Discrete {
6000 values: Vec<f64>,
6002 weights: Vec<f64>,
6004 },
6005}
6006
6007impl Default for ConditionalDistributionParamsConfig {
6008 fn default() -> Self {
6009 Self::Normal {
6010 mu: 0.0,
6011 sigma: 1.0,
6012 }
6013 }
6014}
6015
6016#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6018pub struct RegimeChangeSchemaConfig {
6019 #[serde(default)]
6021 pub enabled: bool,
6022
6023 #[serde(default)]
6025 pub changes: Vec<RegimeChangeEventConfig>,
6026
6027 #[serde(default)]
6029 pub economic_cycle: Option<EconomicCycleSchemaConfig>,
6030
6031 #[serde(default)]
6033 pub parameter_drifts: Vec<ParameterDriftSchemaConfig>,
6034}
6035
6036#[derive(Debug, Clone, Serialize, Deserialize)]
6038pub struct RegimeChangeEventConfig {
6039 pub date: String,
6041
6042 pub change_type: RegimeChangeTypeConfig,
6044
6045 #[serde(default)]
6047 pub description: Option<String>,
6048
6049 #[serde(default)]
6051 pub effects: Vec<RegimeEffectConfig>,
6052}
6053
6054#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
6056#[serde(rename_all = "snake_case")]
6057pub enum RegimeChangeTypeConfig {
6058 Acquisition,
6060 Divestiture,
6062 PriceIncrease,
6064 PriceDecrease,
6066 ProductLaunch,
6068 ProductDiscontinuation,
6070 PolicyChange,
6072 CompetitorEntry,
6074 Custom,
6076}
6077
6078#[derive(Debug, Clone, Serialize, Deserialize)]
6080pub struct RegimeEffectConfig {
6081 pub field: String,
6083
6084 pub multiplier: f64,
6086}
6087
6088#[derive(Debug, Clone, Serialize, Deserialize)]
6090pub struct EconomicCycleSchemaConfig {
6091 #[serde(default)]
6093 pub enabled: bool,
6094
6095 #[serde(default = "default_cycle_period")]
6097 pub period_months: u32,
6098
6099 #[serde(default = "default_cycle_amplitude")]
6101 pub amplitude: f64,
6102
6103 #[serde(default)]
6105 pub phase_offset: u32,
6106
6107 #[serde(default)]
6109 pub recessions: Vec<RecessionPeriodConfig>,
6110}
6111
6112fn default_cycle_period() -> u32 {
6113 48
6114}
6115
6116fn default_cycle_amplitude() -> f64 {
6117 0.15
6118}
6119
6120impl Default for EconomicCycleSchemaConfig {
6121 fn default() -> Self {
6122 Self {
6123 enabled: false,
6124 period_months: 48,
6125 amplitude: 0.15,
6126 phase_offset: 0,
6127 recessions: Vec::new(),
6128 }
6129 }
6130}
6131
6132#[derive(Debug, Clone, Serialize, Deserialize)]
6134pub struct RecessionPeriodConfig {
6135 pub start_month: u32,
6137
6138 pub duration_months: u32,
6140
6141 #[serde(default = "default_recession_severity")]
6143 pub severity: f64,
6144}
6145
6146fn default_recession_severity() -> f64 {
6147 0.20
6148}
6149
6150#[derive(Debug, Clone, Serialize, Deserialize)]
6152pub struct ParameterDriftSchemaConfig {
6153 pub parameter: String,
6155
6156 pub drift_type: ParameterDriftTypeConfig,
6158
6159 pub start_value: f64,
6161
6162 pub end_value: f64,
6164
6165 #[serde(default)]
6167 pub start_period: u32,
6168
6169 #[serde(default)]
6171 pub end_period: Option<u32>,
6172}
6173
6174#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
6176#[serde(rename_all = "snake_case")]
6177pub enum ParameterDriftTypeConfig {
6178 #[default]
6180 Linear,
6181 Exponential,
6183 Logistic,
6185 Step,
6187}
6188
6189#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6191pub struct StatisticalValidationSchemaConfig {
6192 #[serde(default)]
6194 pub enabled: bool,
6195
6196 #[serde(default)]
6198 pub tests: Vec<StatisticalTestConfig>,
6199
6200 #[serde(default)]
6202 pub reporting: ValidationReportingConfig,
6203}
6204
6205#[derive(Debug, Clone, Serialize, Deserialize)]
6207#[serde(tag = "type", rename_all = "snake_case")]
6208pub enum StatisticalTestConfig {
6209 BenfordFirstDigit {
6211 #[serde(default = "default_benford_threshold")]
6213 threshold_mad: f64,
6214 #[serde(default = "default_benford_warning")]
6216 warning_mad: f64,
6217 },
6218 DistributionFit {
6220 target: TargetDistributionConfig,
6222 #[serde(default = "default_ks_significance")]
6224 ks_significance: f64,
6225 #[serde(default)]
6227 method: DistributionFitMethod,
6228 },
6229 CorrelationCheck {
6231 expected_correlations: Vec<ExpectedCorrelationConfig>,
6233 },
6234 ChiSquared {
6236 #[serde(default = "default_chi_squared_bins")]
6238 bins: usize,
6239 #[serde(default = "default_chi_squared_significance")]
6241 significance: f64,
6242 },
6243 AndersonDarling {
6245 target: TargetDistributionConfig,
6247 #[serde(default = "default_ad_significance")]
6249 significance: f64,
6250 },
6251}
6252
6253fn default_benford_threshold() -> f64 {
6254 0.015
6255}
6256
6257fn default_benford_warning() -> f64 {
6258 0.010
6259}
6260
6261fn default_ks_significance() -> f64 {
6262 0.05
6263}
6264
6265fn default_chi_squared_bins() -> usize {
6266 10
6267}
6268
6269fn default_chi_squared_significance() -> f64 {
6270 0.05
6271}
6272
6273fn default_ad_significance() -> f64 {
6274 0.05
6275}
6276
6277#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
6279#[serde(rename_all = "snake_case")]
6280pub enum TargetDistributionConfig {
6281 Normal,
6283 #[default]
6285 LogNormal,
6286 Exponential,
6288 Uniform,
6290}
6291
6292#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
6294#[serde(rename_all = "snake_case")]
6295pub enum DistributionFitMethod {
6296 #[default]
6298 KolmogorovSmirnov,
6299 AndersonDarling,
6301 ChiSquared,
6303}
6304
6305#[derive(Debug, Clone, Serialize, Deserialize)]
6307pub struct ValidationReportingConfig {
6308 #[serde(default)]
6310 pub output_report: bool,
6311
6312 #[serde(default)]
6314 pub format: ValidationReportFormat,
6315
6316 #[serde(default)]
6318 pub fail_on_error: bool,
6319
6320 #[serde(default = "default_true")]
6322 pub include_details: bool,
6323}
6324
6325impl Default for ValidationReportingConfig {
6326 fn default() -> Self {
6327 Self {
6328 output_report: false,
6329 format: ValidationReportFormat::Json,
6330 fail_on_error: false,
6331 include_details: true,
6332 }
6333 }
6334}
6335
6336#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
6338#[serde(rename_all = "snake_case")]
6339pub enum ValidationReportFormat {
6340 #[default]
6342 Json,
6343 Yaml,
6345 Html,
6347}
6348
6349#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6361pub struct TemporalPatternsConfig {
6362 #[serde(default)]
6364 pub enabled: bool,
6365
6366 #[serde(default)]
6368 pub business_days: BusinessDaySchemaConfig,
6369
6370 #[serde(default)]
6372 pub calendars: CalendarSchemaConfig,
6373
6374 #[serde(default)]
6376 pub period_end: PeriodEndSchemaConfig,
6377
6378 #[serde(default)]
6380 pub processing_lags: ProcessingLagSchemaConfig,
6381
6382 #[serde(default)]
6384 pub fiscal_calendar: FiscalCalendarSchemaConfig,
6385
6386 #[serde(default)]
6388 pub intraday: IntraDaySchemaConfig,
6389
6390 #[serde(default)]
6392 pub timezones: TimezoneSchemaConfig,
6393}
6394
6395#[derive(Debug, Clone, Serialize, Deserialize)]
6397pub struct BusinessDaySchemaConfig {
6398 #[serde(default = "default_true")]
6400 pub enabled: bool,
6401
6402 #[serde(default = "default_half_day_policy")]
6404 pub half_day_policy: String,
6405
6406 #[serde(default)]
6408 pub settlement_rules: SettlementRulesSchemaConfig,
6409
6410 #[serde(default = "default_month_end_convention")]
6412 pub month_end_convention: String,
6413
6414 #[serde(default)]
6416 pub weekend_days: Option<Vec<String>>,
6417}
6418
6419fn default_half_day_policy() -> String {
6420 "half_day".to_string()
6421}
6422
6423fn default_month_end_convention() -> String {
6424 "modified_following".to_string()
6425}
6426
6427impl Default for BusinessDaySchemaConfig {
6428 fn default() -> Self {
6429 Self {
6430 enabled: true,
6431 half_day_policy: "half_day".to_string(),
6432 settlement_rules: SettlementRulesSchemaConfig::default(),
6433 month_end_convention: "modified_following".to_string(),
6434 weekend_days: None,
6435 }
6436 }
6437}
6438
6439#[derive(Debug, Clone, Serialize, Deserialize)]
6441pub struct SettlementRulesSchemaConfig {
6442 #[serde(default = "default_settlement_2")]
6444 pub equity_days: i32,
6445
6446 #[serde(default = "default_settlement_1")]
6448 pub government_bonds_days: i32,
6449
6450 #[serde(default = "default_settlement_2")]
6452 pub fx_spot_days: i32,
6453
6454 #[serde(default = "default_settlement_2")]
6456 pub corporate_bonds_days: i32,
6457
6458 #[serde(default = "default_wire_cutoff")]
6460 pub wire_cutoff_time: String,
6461
6462 #[serde(default = "default_settlement_1")]
6464 pub wire_international_days: i32,
6465
6466 #[serde(default = "default_settlement_1")]
6468 pub ach_days: i32,
6469}
6470
6471fn default_settlement_1() -> i32 {
6472 1
6473}
6474
6475fn default_settlement_2() -> i32 {
6476 2
6477}
6478
6479fn default_wire_cutoff() -> String {
6480 "14:00".to_string()
6481}
6482
6483impl Default for SettlementRulesSchemaConfig {
6484 fn default() -> Self {
6485 Self {
6486 equity_days: 2,
6487 government_bonds_days: 1,
6488 fx_spot_days: 2,
6489 corporate_bonds_days: 2,
6490 wire_cutoff_time: "14:00".to_string(),
6491 wire_international_days: 1,
6492 ach_days: 1,
6493 }
6494 }
6495}
6496
6497#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6499pub struct CalendarSchemaConfig {
6500 #[serde(default)]
6502 pub regions: Vec<String>,
6503
6504 #[serde(default)]
6506 pub custom_holidays: Vec<CustomHolidaySchemaConfig>,
6507}
6508
6509#[derive(Debug, Clone, Serialize, Deserialize)]
6511pub struct CustomHolidaySchemaConfig {
6512 pub name: String,
6514 pub month: u8,
6516 pub day: u8,
6518 #[serde(default = "default_holiday_multiplier")]
6520 pub activity_multiplier: f64,
6521}
6522
6523fn default_holiday_multiplier() -> f64 {
6524 0.05
6525}
6526
6527#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6529pub struct PeriodEndSchemaConfig {
6530 #[serde(default)]
6532 pub model: Option<String>,
6533
6534 #[serde(default)]
6536 pub month_end: Option<PeriodEndModelSchemaConfig>,
6537
6538 #[serde(default)]
6540 pub quarter_end: Option<PeriodEndModelSchemaConfig>,
6541
6542 #[serde(default)]
6544 pub year_end: Option<PeriodEndModelSchemaConfig>,
6545}
6546
6547#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6549pub struct PeriodEndModelSchemaConfig {
6550 #[serde(default)]
6552 pub inherit_from: Option<String>,
6553
6554 #[serde(default)]
6556 pub additional_multiplier: Option<f64>,
6557
6558 #[serde(default)]
6560 pub start_day: Option<i32>,
6561
6562 #[serde(default)]
6564 pub base_multiplier: Option<f64>,
6565
6566 #[serde(default)]
6568 pub peak_multiplier: Option<f64>,
6569
6570 #[serde(default)]
6572 pub decay_rate: Option<f64>,
6573
6574 #[serde(default)]
6576 pub sustained_high_days: Option<i32>,
6577}
6578
6579#[derive(Debug, Clone, Serialize, Deserialize)]
6581pub struct ProcessingLagSchemaConfig {
6582 #[serde(default = "default_true")]
6584 pub enabled: bool,
6585
6586 #[serde(default)]
6588 pub sales_order_lag: Option<LagDistributionSchemaConfig>,
6589
6590 #[serde(default)]
6592 pub purchase_order_lag: Option<LagDistributionSchemaConfig>,
6593
6594 #[serde(default)]
6596 pub goods_receipt_lag: Option<LagDistributionSchemaConfig>,
6597
6598 #[serde(default)]
6600 pub invoice_receipt_lag: Option<LagDistributionSchemaConfig>,
6601
6602 #[serde(default)]
6604 pub invoice_issue_lag: Option<LagDistributionSchemaConfig>,
6605
6606 #[serde(default)]
6608 pub payment_lag: Option<LagDistributionSchemaConfig>,
6609
6610 #[serde(default)]
6612 pub journal_entry_lag: Option<LagDistributionSchemaConfig>,
6613
6614 #[serde(default)]
6616 pub cross_day_posting: Option<CrossDayPostingSchemaConfig>,
6617}
6618
6619impl Default for ProcessingLagSchemaConfig {
6620 fn default() -> Self {
6621 Self {
6622 enabled: true,
6623 sales_order_lag: None,
6624 purchase_order_lag: None,
6625 goods_receipt_lag: None,
6626 invoice_receipt_lag: None,
6627 invoice_issue_lag: None,
6628 payment_lag: None,
6629 journal_entry_lag: None,
6630 cross_day_posting: None,
6631 }
6632 }
6633}
6634
6635#[derive(Debug, Clone, Serialize, Deserialize)]
6637pub struct LagDistributionSchemaConfig {
6638 pub mu: f64,
6640 pub sigma: f64,
6642 #[serde(default)]
6644 pub min_hours: Option<f64>,
6645 #[serde(default)]
6647 pub max_hours: Option<f64>,
6648}
6649
6650#[derive(Debug, Clone, Serialize, Deserialize)]
6652pub struct CrossDayPostingSchemaConfig {
6653 #[serde(default = "default_true")]
6655 pub enabled: bool,
6656
6657 #[serde(default)]
6660 pub probability_by_hour: std::collections::HashMap<u8, f64>,
6661}
6662
6663impl Default for CrossDayPostingSchemaConfig {
6664 fn default() -> Self {
6665 let mut probability_by_hour = std::collections::HashMap::new();
6666 probability_by_hour.insert(17, 0.3);
6667 probability_by_hour.insert(18, 0.6);
6668 probability_by_hour.insert(19, 0.8);
6669 probability_by_hour.insert(20, 0.9);
6670 probability_by_hour.insert(21, 0.95);
6671 probability_by_hour.insert(22, 0.99);
6672
6673 Self {
6674 enabled: true,
6675 probability_by_hour,
6676 }
6677 }
6678}
6679
6680#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6689pub struct FiscalCalendarSchemaConfig {
6690 #[serde(default)]
6692 pub enabled: bool,
6693
6694 #[serde(default = "default_fiscal_calendar_type")]
6696 pub calendar_type: String,
6697
6698 #[serde(default)]
6700 pub year_start_month: Option<u8>,
6701
6702 #[serde(default)]
6704 pub year_start_day: Option<u8>,
6705
6706 #[serde(default)]
6708 pub four_four_five: Option<FourFourFiveSchemaConfig>,
6709}
6710
6711fn default_fiscal_calendar_type() -> String {
6712 "calendar_year".to_string()
6713}
6714
6715#[derive(Debug, Clone, Serialize, Deserialize)]
6717pub struct FourFourFiveSchemaConfig {
6718 #[serde(default = "default_week_pattern")]
6720 pub pattern: String,
6721
6722 #[serde(default = "default_anchor_type")]
6724 pub anchor_type: String,
6725
6726 #[serde(default = "default_anchor_month")]
6728 pub anchor_month: u8,
6729
6730 #[serde(default = "default_leap_week_placement")]
6732 pub leap_week_placement: String,
6733}
6734
6735fn default_week_pattern() -> String {
6736 "four_four_five".to_string()
6737}
6738
6739fn default_anchor_type() -> String {
6740 "last_saturday".to_string()
6741}
6742
6743fn default_anchor_month() -> u8 {
6744 1 }
6746
6747fn default_leap_week_placement() -> String {
6748 "q4_period3".to_string()
6749}
6750
6751impl Default for FourFourFiveSchemaConfig {
6752 fn default() -> Self {
6753 Self {
6754 pattern: "four_four_five".to_string(),
6755 anchor_type: "last_saturday".to_string(),
6756 anchor_month: 1,
6757 leap_week_placement: "q4_period3".to_string(),
6758 }
6759 }
6760}
6761
6762#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6771pub struct IntraDaySchemaConfig {
6772 #[serde(default)]
6774 pub enabled: bool,
6775
6776 #[serde(default)]
6778 pub segments: Vec<IntraDaySegmentSchemaConfig>,
6779}
6780
6781#[derive(Debug, Clone, Serialize, Deserialize)]
6783pub struct IntraDaySegmentSchemaConfig {
6784 pub name: String,
6786
6787 pub start: String,
6789
6790 pub end: String,
6792
6793 #[serde(default = "default_multiplier")]
6795 pub multiplier: f64,
6796
6797 #[serde(default = "default_posting_type")]
6799 pub posting_type: String,
6800}
6801
6802fn default_multiplier() -> f64 {
6803 1.0
6804}
6805
6806fn default_posting_type() -> String {
6807 "both".to_string()
6808}
6809
6810#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6816pub struct TimezoneSchemaConfig {
6817 #[serde(default)]
6819 pub enabled: bool,
6820
6821 #[serde(default = "default_timezone")]
6823 pub default_timezone: String,
6824
6825 #[serde(default = "default_consolidation_timezone")]
6827 pub consolidation_timezone: String,
6828
6829 #[serde(default)]
6832 pub entity_mappings: Vec<EntityTimezoneMapping>,
6833}
6834
6835fn default_timezone() -> String {
6836 "America/New_York".to_string()
6837}
6838
6839fn default_consolidation_timezone() -> String {
6840 "UTC".to_string()
6841}
6842
6843#[derive(Debug, Clone, Serialize, Deserialize)]
6845pub struct EntityTimezoneMapping {
6846 pub pattern: String,
6848
6849 pub timezone: String,
6851}
6852
6853#[derive(Debug, Clone, Serialize, Deserialize)]
6859pub struct VendorNetworkSchemaConfig {
6860 #[serde(default)]
6862 pub enabled: bool,
6863
6864 #[serde(default = "default_vendor_tier_depth")]
6866 pub depth: u8,
6867
6868 #[serde(default)]
6870 pub tier1: TierCountSchemaConfig,
6871
6872 #[serde(default)]
6874 pub tier2_per_parent: TierCountSchemaConfig,
6875
6876 #[serde(default)]
6878 pub tier3_per_parent: TierCountSchemaConfig,
6879
6880 #[serde(default)]
6882 pub clusters: VendorClusterSchemaConfig,
6883
6884 #[serde(default)]
6886 pub dependencies: DependencySchemaConfig,
6887}
6888
6889fn default_vendor_tier_depth() -> u8 {
6890 3
6891}
6892
6893impl Default for VendorNetworkSchemaConfig {
6894 fn default() -> Self {
6895 Self {
6896 enabled: false,
6897 depth: 3,
6898 tier1: TierCountSchemaConfig { min: 50, max: 100 },
6899 tier2_per_parent: TierCountSchemaConfig { min: 4, max: 10 },
6900 tier3_per_parent: TierCountSchemaConfig { min: 2, max: 5 },
6901 clusters: VendorClusterSchemaConfig::default(),
6902 dependencies: DependencySchemaConfig::default(),
6903 }
6904 }
6905}
6906
6907#[derive(Debug, Clone, Serialize, Deserialize)]
6909pub struct TierCountSchemaConfig {
6910 #[serde(default = "default_tier_min")]
6912 pub min: usize,
6913
6914 #[serde(default = "default_tier_max")]
6916 pub max: usize,
6917}
6918
6919fn default_tier_min() -> usize {
6920 5
6921}
6922
6923fn default_tier_max() -> usize {
6924 20
6925}
6926
6927impl Default for TierCountSchemaConfig {
6928 fn default() -> Self {
6929 Self {
6930 min: default_tier_min(),
6931 max: default_tier_max(),
6932 }
6933 }
6934}
6935
6936#[derive(Debug, Clone, Serialize, Deserialize)]
6938pub struct VendorClusterSchemaConfig {
6939 #[serde(default = "default_reliable_strategic")]
6941 pub reliable_strategic: f64,
6942
6943 #[serde(default = "default_standard_operational")]
6945 pub standard_operational: f64,
6946
6947 #[serde(default = "default_transactional")]
6949 pub transactional: f64,
6950
6951 #[serde(default = "default_problematic")]
6953 pub problematic: f64,
6954}
6955
6956fn default_reliable_strategic() -> f64 {
6957 0.20
6958}
6959
6960fn default_standard_operational() -> f64 {
6961 0.50
6962}
6963
6964fn default_transactional() -> f64 {
6965 0.25
6966}
6967
6968fn default_problematic() -> f64 {
6969 0.05
6970}
6971
6972impl Default for VendorClusterSchemaConfig {
6973 fn default() -> Self {
6974 Self {
6975 reliable_strategic: 0.20,
6976 standard_operational: 0.50,
6977 transactional: 0.25,
6978 problematic: 0.05,
6979 }
6980 }
6981}
6982
6983#[derive(Debug, Clone, Serialize, Deserialize)]
6985pub struct DependencySchemaConfig {
6986 #[serde(default = "default_max_single_vendor")]
6988 pub max_single_vendor_concentration: f64,
6989
6990 #[serde(default = "default_max_top5")]
6992 pub top_5_concentration: f64,
6993
6994 #[serde(default = "default_single_source_percent")]
6996 pub single_source_percent: f64,
6997}
6998
6999fn default_max_single_vendor() -> f64 {
7000 0.15
7001}
7002
7003fn default_max_top5() -> f64 {
7004 0.45
7005}
7006
7007fn default_single_source_percent() -> f64 {
7008 0.05
7009}
7010
7011impl Default for DependencySchemaConfig {
7012 fn default() -> Self {
7013 Self {
7014 max_single_vendor_concentration: 0.15,
7015 top_5_concentration: 0.45,
7016 single_source_percent: 0.05,
7017 }
7018 }
7019}
7020
7021#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7027pub struct CustomerSegmentationSchemaConfig {
7028 #[serde(default)]
7030 pub enabled: bool,
7031
7032 #[serde(default)]
7034 pub value_segments: ValueSegmentsSchemaConfig,
7035
7036 #[serde(default)]
7038 pub lifecycle: LifecycleSchemaConfig,
7039
7040 #[serde(default)]
7042 pub networks: CustomerNetworksSchemaConfig,
7043}
7044
7045#[derive(Debug, Clone, Serialize, Deserialize)]
7047pub struct ValueSegmentsSchemaConfig {
7048 #[serde(default)]
7050 pub enterprise: SegmentDetailSchemaConfig,
7051
7052 #[serde(default)]
7054 pub mid_market: SegmentDetailSchemaConfig,
7055
7056 #[serde(default)]
7058 pub smb: SegmentDetailSchemaConfig,
7059
7060 #[serde(default)]
7062 pub consumer: SegmentDetailSchemaConfig,
7063}
7064
7065impl Default for ValueSegmentsSchemaConfig {
7066 fn default() -> Self {
7067 Self {
7068 enterprise: SegmentDetailSchemaConfig {
7069 revenue_share: 0.40,
7070 customer_share: 0.05,
7071 avg_order_value_range: "50000+".to_string(),
7072 },
7073 mid_market: SegmentDetailSchemaConfig {
7074 revenue_share: 0.35,
7075 customer_share: 0.20,
7076 avg_order_value_range: "5000-50000".to_string(),
7077 },
7078 smb: SegmentDetailSchemaConfig {
7079 revenue_share: 0.20,
7080 customer_share: 0.50,
7081 avg_order_value_range: "500-5000".to_string(),
7082 },
7083 consumer: SegmentDetailSchemaConfig {
7084 revenue_share: 0.05,
7085 customer_share: 0.25,
7086 avg_order_value_range: "50-500".to_string(),
7087 },
7088 }
7089 }
7090}
7091
7092#[derive(Debug, Clone, Serialize, Deserialize)]
7094pub struct SegmentDetailSchemaConfig {
7095 #[serde(default)]
7097 pub revenue_share: f64,
7098
7099 #[serde(default)]
7101 pub customer_share: f64,
7102
7103 #[serde(default)]
7105 pub avg_order_value_range: String,
7106}
7107
7108impl Default for SegmentDetailSchemaConfig {
7109 fn default() -> Self {
7110 Self {
7111 revenue_share: 0.25,
7112 customer_share: 0.25,
7113 avg_order_value_range: "1000-10000".to_string(),
7114 }
7115 }
7116}
7117
7118#[derive(Debug, Clone, Serialize, Deserialize)]
7120pub struct LifecycleSchemaConfig {
7121 #[serde(default)]
7123 pub prospect_rate: f64,
7124
7125 #[serde(default = "default_new_rate")]
7127 pub new_rate: f64,
7128
7129 #[serde(default = "default_growth_rate")]
7131 pub growth_rate: f64,
7132
7133 #[serde(default = "default_mature_rate")]
7135 pub mature_rate: f64,
7136
7137 #[serde(default = "default_at_risk_rate")]
7139 pub at_risk_rate: f64,
7140
7141 #[serde(default = "default_churned_rate")]
7143 pub churned_rate: f64,
7144
7145 #[serde(default)]
7147 pub won_back_rate: f64,
7148}
7149
7150fn default_new_rate() -> f64 {
7151 0.10
7152}
7153
7154fn default_growth_rate() -> f64 {
7155 0.15
7156}
7157
7158fn default_mature_rate() -> f64 {
7159 0.60
7160}
7161
7162fn default_at_risk_rate() -> f64 {
7163 0.10
7164}
7165
7166fn default_churned_rate() -> f64 {
7167 0.05
7168}
7169
7170impl Default for LifecycleSchemaConfig {
7171 fn default() -> Self {
7172 Self {
7173 prospect_rate: 0.0,
7174 new_rate: 0.10,
7175 growth_rate: 0.15,
7176 mature_rate: 0.60,
7177 at_risk_rate: 0.10,
7178 churned_rate: 0.05,
7179 won_back_rate: 0.0,
7180 }
7181 }
7182}
7183
7184#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7186pub struct CustomerNetworksSchemaConfig {
7187 #[serde(default)]
7189 pub referrals: ReferralSchemaConfig,
7190
7191 #[serde(default)]
7193 pub corporate_hierarchies: HierarchySchemaConfig,
7194}
7195
7196#[derive(Debug, Clone, Serialize, Deserialize)]
7198pub struct ReferralSchemaConfig {
7199 #[serde(default = "default_true")]
7201 pub enabled: bool,
7202
7203 #[serde(default = "default_referral_rate")]
7205 pub referral_rate: f64,
7206}
7207
7208fn default_referral_rate() -> f64 {
7209 0.15
7210}
7211
7212impl Default for ReferralSchemaConfig {
7213 fn default() -> Self {
7214 Self {
7215 enabled: true,
7216 referral_rate: 0.15,
7217 }
7218 }
7219}
7220
7221#[derive(Debug, Clone, Serialize, Deserialize)]
7223pub struct HierarchySchemaConfig {
7224 #[serde(default = "default_true")]
7226 pub enabled: bool,
7227
7228 #[serde(default = "default_hierarchy_rate")]
7230 pub probability: f64,
7231}
7232
7233fn default_hierarchy_rate() -> f64 {
7234 0.30
7235}
7236
7237impl Default for HierarchySchemaConfig {
7238 fn default() -> Self {
7239 Self {
7240 enabled: true,
7241 probability: 0.30,
7242 }
7243 }
7244}
7245
7246#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7252pub struct RelationshipStrengthSchemaConfig {
7253 #[serde(default)]
7255 pub enabled: bool,
7256
7257 #[serde(default)]
7259 pub calculation: StrengthCalculationSchemaConfig,
7260
7261 #[serde(default)]
7263 pub thresholds: StrengthThresholdsSchemaConfig,
7264}
7265
7266#[derive(Debug, Clone, Serialize, Deserialize)]
7268pub struct StrengthCalculationSchemaConfig {
7269 #[serde(default = "default_volume_weight")]
7271 pub transaction_volume_weight: f64,
7272
7273 #[serde(default = "default_count_weight")]
7275 pub transaction_count_weight: f64,
7276
7277 #[serde(default = "default_duration_weight")]
7279 pub relationship_duration_weight: f64,
7280
7281 #[serde(default = "default_recency_weight")]
7283 pub recency_weight: f64,
7284
7285 #[serde(default = "default_mutual_weight")]
7287 pub mutual_connections_weight: f64,
7288
7289 #[serde(default = "default_recency_half_life")]
7291 pub recency_half_life_days: u32,
7292}
7293
7294fn default_volume_weight() -> f64 {
7295 0.30
7296}
7297
7298fn default_count_weight() -> f64 {
7299 0.25
7300}
7301
7302fn default_duration_weight() -> f64 {
7303 0.20
7304}
7305
7306fn default_recency_weight() -> f64 {
7307 0.15
7308}
7309
7310fn default_mutual_weight() -> f64 {
7311 0.10
7312}
7313
7314fn default_recency_half_life() -> u32 {
7315 90
7316}
7317
7318impl Default for StrengthCalculationSchemaConfig {
7319 fn default() -> Self {
7320 Self {
7321 transaction_volume_weight: 0.30,
7322 transaction_count_weight: 0.25,
7323 relationship_duration_weight: 0.20,
7324 recency_weight: 0.15,
7325 mutual_connections_weight: 0.10,
7326 recency_half_life_days: 90,
7327 }
7328 }
7329}
7330
7331#[derive(Debug, Clone, Serialize, Deserialize)]
7333pub struct StrengthThresholdsSchemaConfig {
7334 #[serde(default = "default_strong_threshold")]
7336 pub strong: f64,
7337
7338 #[serde(default = "default_moderate_threshold")]
7340 pub moderate: f64,
7341
7342 #[serde(default = "default_weak_threshold")]
7344 pub weak: f64,
7345}
7346
7347fn default_strong_threshold() -> f64 {
7348 0.7
7349}
7350
7351fn default_moderate_threshold() -> f64 {
7352 0.4
7353}
7354
7355fn default_weak_threshold() -> f64 {
7356 0.1
7357}
7358
7359impl Default for StrengthThresholdsSchemaConfig {
7360 fn default() -> Self {
7361 Self {
7362 strong: 0.7,
7363 moderate: 0.4,
7364 weak: 0.1,
7365 }
7366 }
7367}
7368
7369#[derive(Debug, Clone, Serialize, Deserialize)]
7375pub struct CrossProcessLinksSchemaConfig {
7376 #[serde(default)]
7378 pub enabled: bool,
7379
7380 #[serde(default = "default_true")]
7382 pub inventory_p2p_o2c: bool,
7383
7384 #[serde(default = "default_true")]
7386 pub payment_bank_reconciliation: bool,
7387
7388 #[serde(default = "default_true")]
7390 pub intercompany_bilateral: bool,
7391
7392 #[serde(default = "default_inventory_link_rate")]
7394 pub inventory_link_rate: f64,
7395}
7396
7397fn default_inventory_link_rate() -> f64 {
7398 0.30
7399}
7400
7401impl Default for CrossProcessLinksSchemaConfig {
7402 fn default() -> Self {
7403 Self {
7404 enabled: false,
7405 inventory_p2p_o2c: true,
7406 payment_bank_reconciliation: true,
7407 intercompany_bilateral: true,
7408 inventory_link_rate: 0.30,
7409 }
7410 }
7411}
7412
7413#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7419pub struct OrganizationalEventsSchemaConfig {
7420 #[serde(default)]
7422 pub enabled: bool,
7423
7424 #[serde(default)]
7426 pub effect_blending: EffectBlendingModeConfig,
7427
7428 #[serde(default)]
7430 pub events: Vec<OrganizationalEventSchemaConfig>,
7431
7432 #[serde(default)]
7434 pub process_evolution: Vec<ProcessEvolutionSchemaConfig>,
7435
7436 #[serde(default)]
7438 pub technology_transitions: Vec<TechnologyTransitionSchemaConfig>,
7439}
7440
7441#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
7443#[serde(rename_all = "snake_case")]
7444pub enum EffectBlendingModeConfig {
7445 #[default]
7447 Multiplicative,
7448 Additive,
7450 Maximum,
7452 Minimum,
7454}
7455
7456#[derive(Debug, Clone, Serialize, Deserialize)]
7458pub struct OrganizationalEventSchemaConfig {
7459 pub id: String,
7461
7462 pub event_type: OrganizationalEventTypeSchemaConfig,
7464
7465 pub effective_date: String,
7467
7468 #[serde(default = "default_org_transition_months")]
7470 pub transition_months: u32,
7471
7472 #[serde(default)]
7474 pub description: Option<String>,
7475}
7476
7477fn default_org_transition_months() -> u32 {
7478 6
7479}
7480
7481#[derive(Debug, Clone, Serialize, Deserialize)]
7483#[serde(tag = "type", rename_all = "snake_case")]
7484pub enum OrganizationalEventTypeSchemaConfig {
7485 Acquisition {
7487 acquired_entity: String,
7489 #[serde(default = "default_acquisition_volume")]
7491 volume_increase: f64,
7492 #[serde(default = "default_acquisition_error")]
7494 integration_error_rate: f64,
7495 #[serde(default = "default_parallel_days")]
7497 parallel_posting_days: u32,
7498 },
7499 Divestiture {
7501 divested_entity: String,
7503 #[serde(default = "default_divestiture_volume")]
7505 volume_reduction: f64,
7506 #[serde(default = "default_true_val")]
7508 remove_entity: bool,
7509 },
7510 Reorganization {
7512 #[serde(default)]
7514 cost_center_remapping: std::collections::HashMap<String, String>,
7515 #[serde(default = "default_reorg_error")]
7517 transition_error_rate: f64,
7518 },
7519 LeadershipChange {
7521 role: String,
7523 #[serde(default)]
7525 policy_changes: Vec<String>,
7526 },
7527 WorkforceReduction {
7529 #[serde(default = "default_workforce_reduction")]
7531 reduction_percent: f64,
7532 #[serde(default = "default_workforce_error")]
7534 error_rate_increase: f64,
7535 },
7536 Merger {
7538 merged_entity: String,
7540 #[serde(default = "default_merger_volume")]
7542 volume_increase: f64,
7543 },
7544}
7545
7546fn default_acquisition_volume() -> f64 {
7547 1.35
7548}
7549
7550fn default_acquisition_error() -> f64 {
7551 0.05
7552}
7553
7554fn default_parallel_days() -> u32 {
7555 30
7556}
7557
7558fn default_divestiture_volume() -> f64 {
7559 0.70
7560}
7561
7562fn default_true_val() -> bool {
7563 true
7564}
7565
7566fn default_reorg_error() -> f64 {
7567 0.04
7568}
7569
7570fn default_workforce_reduction() -> f64 {
7571 0.10
7572}
7573
7574fn default_workforce_error() -> f64 {
7575 0.05
7576}
7577
7578fn default_merger_volume() -> f64 {
7579 1.80
7580}
7581
7582#[derive(Debug, Clone, Serialize, Deserialize)]
7584pub struct ProcessEvolutionSchemaConfig {
7585 pub id: String,
7587
7588 pub event_type: ProcessEvolutionTypeSchemaConfig,
7590
7591 pub effective_date: String,
7593
7594 #[serde(default)]
7596 pub description: Option<String>,
7597}
7598
7599#[derive(Debug, Clone, Serialize, Deserialize)]
7601#[serde(tag = "type", rename_all = "snake_case")]
7602pub enum ProcessEvolutionTypeSchemaConfig {
7603 ProcessAutomation {
7605 process_name: String,
7607 #[serde(default = "default_manual_before")]
7609 manual_rate_before: f64,
7610 #[serde(default = "default_manual_after")]
7612 manual_rate_after: f64,
7613 },
7614 ApprovalWorkflowChange {
7616 description: String,
7618 },
7619 ControlEnhancement {
7621 control_id: String,
7623 #[serde(default = "default_error_reduction")]
7625 error_reduction: f64,
7626 },
7627}
7628
7629fn default_manual_before() -> f64 {
7630 0.80
7631}
7632
7633fn default_manual_after() -> f64 {
7634 0.15
7635}
7636
7637fn default_error_reduction() -> f64 {
7638 0.02
7639}
7640
7641#[derive(Debug, Clone, Serialize, Deserialize)]
7643pub struct TechnologyTransitionSchemaConfig {
7644 pub id: String,
7646
7647 pub event_type: TechnologyTransitionTypeSchemaConfig,
7649
7650 #[serde(default)]
7652 pub description: Option<String>,
7653}
7654
7655#[derive(Debug, Clone, Serialize, Deserialize)]
7657#[serde(tag = "type", rename_all = "snake_case")]
7658pub enum TechnologyTransitionTypeSchemaConfig {
7659 ErpMigration {
7661 source_system: String,
7663 target_system: String,
7665 cutover_date: String,
7667 stabilization_end: String,
7669 #[serde(default = "default_erp_duplicate_rate")]
7671 duplicate_rate: f64,
7672 #[serde(default = "default_format_mismatch")]
7674 format_mismatch_rate: f64,
7675 },
7676 ModuleImplementation {
7678 module_name: String,
7680 go_live_date: String,
7682 },
7683}
7684
7685fn default_erp_duplicate_rate() -> f64 {
7686 0.02
7687}
7688
7689fn default_format_mismatch() -> f64 {
7690 0.03
7691}
7692
7693#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7699pub struct BehavioralDriftSchemaConfig {
7700 #[serde(default)]
7702 pub enabled: bool,
7703
7704 #[serde(default)]
7706 pub vendor_behavior: VendorBehaviorSchemaConfig,
7707
7708 #[serde(default)]
7710 pub customer_behavior: CustomerBehaviorSchemaConfig,
7711
7712 #[serde(default)]
7714 pub employee_behavior: EmployeeBehaviorSchemaConfig,
7715
7716 #[serde(default)]
7718 pub collective: CollectiveBehaviorSchemaConfig,
7719}
7720
7721#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7723pub struct VendorBehaviorSchemaConfig {
7724 #[serde(default)]
7726 pub payment_terms_drift: PaymentTermsDriftSchemaConfig,
7727
7728 #[serde(default)]
7730 pub quality_drift: QualityDriftSchemaConfig,
7731}
7732
7733#[derive(Debug, Clone, Serialize, Deserialize)]
7735pub struct PaymentTermsDriftSchemaConfig {
7736 #[serde(default = "default_extension_rate")]
7738 pub extension_rate_per_year: f64,
7739
7740 #[serde(default = "default_economic_sensitivity")]
7742 pub economic_sensitivity: f64,
7743}
7744
7745fn default_extension_rate() -> f64 {
7746 2.5
7747}
7748
7749fn default_economic_sensitivity() -> f64 {
7750 1.0
7751}
7752
7753impl Default for PaymentTermsDriftSchemaConfig {
7754 fn default() -> Self {
7755 Self {
7756 extension_rate_per_year: 2.5,
7757 economic_sensitivity: 1.0,
7758 }
7759 }
7760}
7761
7762#[derive(Debug, Clone, Serialize, Deserialize)]
7764pub struct QualityDriftSchemaConfig {
7765 #[serde(default = "default_improvement_rate")]
7767 pub new_vendor_improvement_rate: f64,
7768
7769 #[serde(default = "default_decline_rate")]
7771 pub complacency_decline_rate: f64,
7772}
7773
7774fn default_improvement_rate() -> f64 {
7775 0.02
7776}
7777
7778fn default_decline_rate() -> f64 {
7779 0.01
7780}
7781
7782impl Default for QualityDriftSchemaConfig {
7783 fn default() -> Self {
7784 Self {
7785 new_vendor_improvement_rate: 0.02,
7786 complacency_decline_rate: 0.01,
7787 }
7788 }
7789}
7790
7791#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7793pub struct CustomerBehaviorSchemaConfig {
7794 #[serde(default)]
7796 pub payment_drift: CustomerPaymentDriftSchemaConfig,
7797
7798 #[serde(default)]
7800 pub order_drift: OrderDriftSchemaConfig,
7801}
7802
7803#[derive(Debug, Clone, Serialize, Deserialize)]
7805pub struct CustomerPaymentDriftSchemaConfig {
7806 #[serde(default = "default_downturn_extension")]
7808 pub downturn_days_extension: (u32, u32),
7809
7810 #[serde(default = "default_bad_debt_increase")]
7812 pub downturn_bad_debt_increase: f64,
7813}
7814
7815fn default_downturn_extension() -> (u32, u32) {
7816 (5, 15)
7817}
7818
7819fn default_bad_debt_increase() -> f64 {
7820 0.02
7821}
7822
7823impl Default for CustomerPaymentDriftSchemaConfig {
7824 fn default() -> Self {
7825 Self {
7826 downturn_days_extension: (5, 15),
7827 downturn_bad_debt_increase: 0.02,
7828 }
7829 }
7830}
7831
7832#[derive(Debug, Clone, Serialize, Deserialize)]
7834pub struct OrderDriftSchemaConfig {
7835 #[serde(default = "default_digital_shift")]
7837 pub digital_shift_rate: f64,
7838}
7839
7840fn default_digital_shift() -> f64 {
7841 0.05
7842}
7843
7844impl Default for OrderDriftSchemaConfig {
7845 fn default() -> Self {
7846 Self {
7847 digital_shift_rate: 0.05,
7848 }
7849 }
7850}
7851
7852#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7854pub struct EmployeeBehaviorSchemaConfig {
7855 #[serde(default)]
7857 pub approval_drift: ApprovalDriftSchemaConfig,
7858
7859 #[serde(default)]
7861 pub error_drift: ErrorDriftSchemaConfig,
7862}
7863
7864#[derive(Debug, Clone, Serialize, Deserialize)]
7866pub struct ApprovalDriftSchemaConfig {
7867 #[serde(default = "default_eom_intensity")]
7869 pub eom_intensity_increase_per_year: f64,
7870
7871 #[serde(default = "default_rubber_stamp")]
7873 pub rubber_stamp_volume_threshold: u32,
7874}
7875
7876fn default_eom_intensity() -> f64 {
7877 0.05
7878}
7879
7880fn default_rubber_stamp() -> u32 {
7881 50
7882}
7883
7884impl Default for ApprovalDriftSchemaConfig {
7885 fn default() -> Self {
7886 Self {
7887 eom_intensity_increase_per_year: 0.05,
7888 rubber_stamp_volume_threshold: 50,
7889 }
7890 }
7891}
7892
7893#[derive(Debug, Clone, Serialize, Deserialize)]
7895pub struct ErrorDriftSchemaConfig {
7896 #[serde(default = "default_new_error")]
7898 pub new_employee_error_rate: f64,
7899
7900 #[serde(default = "default_learning_months")]
7902 pub learning_curve_months: u32,
7903}
7904
7905fn default_new_error() -> f64 {
7906 0.08
7907}
7908
7909fn default_learning_months() -> u32 {
7910 6
7911}
7912
7913impl Default for ErrorDriftSchemaConfig {
7914 fn default() -> Self {
7915 Self {
7916 new_employee_error_rate: 0.08,
7917 learning_curve_months: 6,
7918 }
7919 }
7920}
7921
7922#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7924pub struct CollectiveBehaviorSchemaConfig {
7925 #[serde(default)]
7927 pub automation_adoption: AutomationAdoptionSchemaConfig,
7928}
7929
7930#[derive(Debug, Clone, Serialize, Deserialize)]
7932pub struct AutomationAdoptionSchemaConfig {
7933 #[serde(default)]
7935 pub s_curve_enabled: bool,
7936
7937 #[serde(default = "default_midpoint")]
7939 pub adoption_midpoint_months: u32,
7940
7941 #[serde(default = "default_steepness")]
7943 pub steepness: f64,
7944}
7945
7946fn default_midpoint() -> u32 {
7947 24
7948}
7949
7950fn default_steepness() -> f64 {
7951 0.15
7952}
7953
7954impl Default for AutomationAdoptionSchemaConfig {
7955 fn default() -> Self {
7956 Self {
7957 s_curve_enabled: false,
7958 adoption_midpoint_months: 24,
7959 steepness: 0.15,
7960 }
7961 }
7962}
7963
7964#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7970pub struct MarketDriftSchemaConfig {
7971 #[serde(default)]
7973 pub enabled: bool,
7974
7975 #[serde(default)]
7977 pub economic_cycle: MarketEconomicCycleSchemaConfig,
7978
7979 #[serde(default)]
7981 pub industry_cycles: std::collections::HashMap<String, IndustryCycleSchemaConfig>,
7982
7983 #[serde(default)]
7985 pub commodities: CommoditiesSchemaConfig,
7986}
7987
7988#[derive(Debug, Clone, Serialize, Deserialize)]
7990pub struct MarketEconomicCycleSchemaConfig {
7991 #[serde(default)]
7993 pub enabled: bool,
7994
7995 #[serde(default)]
7997 pub cycle_type: CycleTypeSchemaConfig,
7998
7999 #[serde(default = "default_market_cycle_period")]
8001 pub period_months: u32,
8002
8003 #[serde(default = "default_market_amplitude")]
8005 pub amplitude: f64,
8006
8007 #[serde(default)]
8009 pub recession: RecessionSchemaConfig,
8010}
8011
8012fn default_market_cycle_period() -> u32 {
8013 48
8014}
8015
8016fn default_market_amplitude() -> f64 {
8017 0.15
8018}
8019
8020impl Default for MarketEconomicCycleSchemaConfig {
8021 fn default() -> Self {
8022 Self {
8023 enabled: false,
8024 cycle_type: CycleTypeSchemaConfig::Sinusoidal,
8025 period_months: 48,
8026 amplitude: 0.15,
8027 recession: RecessionSchemaConfig::default(),
8028 }
8029 }
8030}
8031
8032#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
8034#[serde(rename_all = "snake_case")]
8035pub enum CycleTypeSchemaConfig {
8036 #[default]
8038 Sinusoidal,
8039 Asymmetric,
8041 MeanReverting,
8043}
8044
8045#[derive(Debug, Clone, Serialize, Deserialize)]
8047pub struct RecessionSchemaConfig {
8048 #[serde(default)]
8050 pub enabled: bool,
8051
8052 #[serde(default = "default_recession_prob")]
8054 pub probability_per_year: f64,
8055
8056 #[serde(default)]
8058 pub severity: RecessionSeveritySchemaConfig,
8059
8060 #[serde(default)]
8062 pub recession_periods: Vec<RecessionPeriodSchemaConfig>,
8063}
8064
8065fn default_recession_prob() -> f64 {
8066 0.10
8067}
8068
8069impl Default for RecessionSchemaConfig {
8070 fn default() -> Self {
8071 Self {
8072 enabled: false,
8073 probability_per_year: 0.10,
8074 severity: RecessionSeveritySchemaConfig::Moderate,
8075 recession_periods: Vec::new(),
8076 }
8077 }
8078}
8079
8080#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
8082#[serde(rename_all = "snake_case")]
8083pub enum RecessionSeveritySchemaConfig {
8084 Mild,
8086 #[default]
8088 Moderate,
8089 Severe,
8091}
8092
8093#[derive(Debug, Clone, Serialize, Deserialize)]
8095pub struct RecessionPeriodSchemaConfig {
8096 pub start_month: u32,
8098 pub duration_months: u32,
8100}
8101
8102#[derive(Debug, Clone, Serialize, Deserialize)]
8104pub struct IndustryCycleSchemaConfig {
8105 #[serde(default = "default_industry_period")]
8107 pub period_months: u32,
8108
8109 #[serde(default = "default_industry_amp")]
8111 pub amplitude: f64,
8112}
8113
8114fn default_industry_period() -> u32 {
8115 36
8116}
8117
8118fn default_industry_amp() -> f64 {
8119 0.20
8120}
8121
8122#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8124pub struct CommoditiesSchemaConfig {
8125 #[serde(default)]
8127 pub enabled: bool,
8128
8129 #[serde(default)]
8131 pub items: Vec<CommodityItemSchemaConfig>,
8132}
8133
8134#[derive(Debug, Clone, Serialize, Deserialize)]
8136pub struct CommodityItemSchemaConfig {
8137 pub name: String,
8139
8140 #[serde(default = "default_volatility")]
8142 pub volatility: f64,
8143
8144 #[serde(default)]
8146 pub cogs_pass_through: f64,
8147
8148 #[serde(default)]
8150 pub overhead_pass_through: f64,
8151}
8152
8153fn default_volatility() -> f64 {
8154 0.20
8155}
8156
8157#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8163pub struct DriftLabelingSchemaConfig {
8164 #[serde(default)]
8166 pub enabled: bool,
8167
8168 #[serde(default)]
8170 pub statistical: StatisticalDriftLabelingSchemaConfig,
8171
8172 #[serde(default)]
8174 pub categorical: CategoricalDriftLabelingSchemaConfig,
8175
8176 #[serde(default)]
8178 pub temporal: TemporalDriftLabelingSchemaConfig,
8179
8180 #[serde(default)]
8182 pub regulatory_calendar_preset: Option<String>,
8183}
8184
8185#[derive(Debug, Clone, Serialize, Deserialize)]
8187pub struct StatisticalDriftLabelingSchemaConfig {
8188 #[serde(default = "default_true_val")]
8190 pub enabled: bool,
8191
8192 #[serde(default = "default_min_magnitude")]
8194 pub min_magnitude_threshold: f64,
8195}
8196
8197fn default_min_magnitude() -> f64 {
8198 0.05
8199}
8200
8201impl Default for StatisticalDriftLabelingSchemaConfig {
8202 fn default() -> Self {
8203 Self {
8204 enabled: true,
8205 min_magnitude_threshold: 0.05,
8206 }
8207 }
8208}
8209
8210#[derive(Debug, Clone, Serialize, Deserialize)]
8212pub struct CategoricalDriftLabelingSchemaConfig {
8213 #[serde(default = "default_true_val")]
8215 pub enabled: bool,
8216}
8217
8218impl Default for CategoricalDriftLabelingSchemaConfig {
8219 fn default() -> Self {
8220 Self { enabled: true }
8221 }
8222}
8223
8224#[derive(Debug, Clone, Serialize, Deserialize)]
8226pub struct TemporalDriftLabelingSchemaConfig {
8227 #[serde(default = "default_true_val")]
8229 pub enabled: bool,
8230}
8231
8232impl Default for TemporalDriftLabelingSchemaConfig {
8233 fn default() -> Self {
8234 Self { enabled: true }
8235 }
8236}
8237
8238#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8251pub struct EnhancedAnomalyConfig {
8252 #[serde(default)]
8254 pub enabled: bool,
8255
8256 #[serde(default)]
8258 pub rates: AnomalyRateConfig,
8259
8260 #[serde(default)]
8262 pub multi_stage_schemes: MultiStageSchemeConfig,
8263
8264 #[serde(default)]
8266 pub correlated_injection: CorrelatedInjectionConfig,
8267
8268 #[serde(default)]
8270 pub near_miss: NearMissConfig,
8271
8272 #[serde(default)]
8274 pub difficulty_classification: DifficultyClassificationConfig,
8275
8276 #[serde(default)]
8278 pub context_aware: ContextAwareConfig,
8279
8280 #[serde(default)]
8282 pub labeling: EnhancedLabelingConfig,
8283}
8284
8285#[derive(Debug, Clone, Serialize, Deserialize)]
8287pub struct AnomalyRateConfig {
8288 #[serde(default = "default_total_anomaly_rate")]
8290 pub total_rate: f64,
8291
8292 #[serde(default = "default_fraud_anomaly_rate")]
8294 pub fraud_rate: f64,
8295
8296 #[serde(default = "default_error_anomaly_rate")]
8298 pub error_rate: f64,
8299
8300 #[serde(default = "default_process_anomaly_rate")]
8302 pub process_rate: f64,
8303}
8304
8305fn default_total_anomaly_rate() -> f64 {
8306 0.03
8307}
8308fn default_fraud_anomaly_rate() -> f64 {
8309 0.01
8310}
8311fn default_error_anomaly_rate() -> f64 {
8312 0.015
8313}
8314fn default_process_anomaly_rate() -> f64 {
8315 0.005
8316}
8317
8318impl Default for AnomalyRateConfig {
8319 fn default() -> Self {
8320 Self {
8321 total_rate: default_total_anomaly_rate(),
8322 fraud_rate: default_fraud_anomaly_rate(),
8323 error_rate: default_error_anomaly_rate(),
8324 process_rate: default_process_anomaly_rate(),
8325 }
8326 }
8327}
8328
8329#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8331pub struct MultiStageSchemeConfig {
8332 #[serde(default)]
8334 pub enabled: bool,
8335
8336 #[serde(default)]
8338 pub embezzlement: EmbezzlementSchemeConfig,
8339
8340 #[serde(default)]
8342 pub revenue_manipulation: RevenueManipulationSchemeConfig,
8343
8344 #[serde(default)]
8346 pub kickback: KickbackSchemeConfig,
8347}
8348
8349#[derive(Debug, Clone, Serialize, Deserialize)]
8351pub struct EmbezzlementSchemeConfig {
8352 #[serde(default = "default_embezzlement_probability")]
8354 pub probability: f64,
8355
8356 #[serde(default)]
8358 pub testing_stage: SchemeStageConfig,
8359
8360 #[serde(default)]
8362 pub escalation_stage: SchemeStageConfig,
8363
8364 #[serde(default)]
8366 pub acceleration_stage: SchemeStageConfig,
8367
8368 #[serde(default)]
8370 pub desperation_stage: SchemeStageConfig,
8371}
8372
8373fn default_embezzlement_probability() -> f64 {
8374 0.02
8375}
8376
8377impl Default for EmbezzlementSchemeConfig {
8378 fn default() -> Self {
8379 Self {
8380 probability: default_embezzlement_probability(),
8381 testing_stage: SchemeStageConfig {
8382 duration_months: 2,
8383 amount_min: 100.0,
8384 amount_max: 500.0,
8385 transaction_count_min: 2,
8386 transaction_count_max: 5,
8387 difficulty: "hard".to_string(),
8388 },
8389 escalation_stage: SchemeStageConfig {
8390 duration_months: 6,
8391 amount_min: 500.0,
8392 amount_max: 2000.0,
8393 transaction_count_min: 3,
8394 transaction_count_max: 8,
8395 difficulty: "moderate".to_string(),
8396 },
8397 acceleration_stage: SchemeStageConfig {
8398 duration_months: 3,
8399 amount_min: 2000.0,
8400 amount_max: 10000.0,
8401 transaction_count_min: 5,
8402 transaction_count_max: 12,
8403 difficulty: "easy".to_string(),
8404 },
8405 desperation_stage: SchemeStageConfig {
8406 duration_months: 1,
8407 amount_min: 10000.0,
8408 amount_max: 50000.0,
8409 transaction_count_min: 3,
8410 transaction_count_max: 6,
8411 difficulty: "trivial".to_string(),
8412 },
8413 }
8414 }
8415}
8416
8417#[derive(Debug, Clone, Serialize, Deserialize)]
8419pub struct RevenueManipulationSchemeConfig {
8420 #[serde(default = "default_revenue_manipulation_probability")]
8422 pub probability: f64,
8423
8424 #[serde(default = "default_early_recognition_target")]
8426 pub early_recognition_target: f64,
8427
8428 #[serde(default = "default_expense_deferral_target")]
8430 pub expense_deferral_target: f64,
8431
8432 #[serde(default = "default_reserve_release_target")]
8434 pub reserve_release_target: f64,
8435
8436 #[serde(default = "default_channel_stuffing_target")]
8438 pub channel_stuffing_target: f64,
8439}
8440
8441fn default_revenue_manipulation_probability() -> f64 {
8442 0.01
8443}
8444fn default_early_recognition_target() -> f64 {
8445 0.02
8446}
8447fn default_expense_deferral_target() -> f64 {
8448 0.03
8449}
8450fn default_reserve_release_target() -> f64 {
8451 0.02
8452}
8453fn default_channel_stuffing_target() -> f64 {
8454 0.05
8455}
8456
8457impl Default for RevenueManipulationSchemeConfig {
8458 fn default() -> Self {
8459 Self {
8460 probability: default_revenue_manipulation_probability(),
8461 early_recognition_target: default_early_recognition_target(),
8462 expense_deferral_target: default_expense_deferral_target(),
8463 reserve_release_target: default_reserve_release_target(),
8464 channel_stuffing_target: default_channel_stuffing_target(),
8465 }
8466 }
8467}
8468
8469#[derive(Debug, Clone, Serialize, Deserialize)]
8471pub struct KickbackSchemeConfig {
8472 #[serde(default = "default_kickback_probability")]
8474 pub probability: f64,
8475
8476 #[serde(default = "default_kickback_inflation_min")]
8478 pub inflation_min: f64,
8479
8480 #[serde(default = "default_kickback_inflation_max")]
8482 pub inflation_max: f64,
8483
8484 #[serde(default = "default_kickback_percent")]
8486 pub kickback_percent: f64,
8487
8488 #[serde(default = "default_kickback_setup_months")]
8490 pub setup_months: u32,
8491
8492 #[serde(default = "default_kickback_operation_months")]
8494 pub operation_months: u32,
8495}
8496
8497fn default_kickback_probability() -> f64 {
8498 0.01
8499}
8500fn default_kickback_inflation_min() -> f64 {
8501 0.10
8502}
8503fn default_kickback_inflation_max() -> f64 {
8504 0.25
8505}
8506fn default_kickback_percent() -> f64 {
8507 0.50
8508}
8509fn default_kickback_setup_months() -> u32 {
8510 3
8511}
8512fn default_kickback_operation_months() -> u32 {
8513 12
8514}
8515
8516impl Default for KickbackSchemeConfig {
8517 fn default() -> Self {
8518 Self {
8519 probability: default_kickback_probability(),
8520 inflation_min: default_kickback_inflation_min(),
8521 inflation_max: default_kickback_inflation_max(),
8522 kickback_percent: default_kickback_percent(),
8523 setup_months: default_kickback_setup_months(),
8524 operation_months: default_kickback_operation_months(),
8525 }
8526 }
8527}
8528
8529#[derive(Debug, Clone, Serialize, Deserialize)]
8531pub struct SchemeStageConfig {
8532 pub duration_months: u32,
8534
8535 pub amount_min: f64,
8537
8538 pub amount_max: f64,
8540
8541 pub transaction_count_min: u32,
8543
8544 pub transaction_count_max: u32,
8546
8547 pub difficulty: String,
8549}
8550
8551impl Default for SchemeStageConfig {
8552 fn default() -> Self {
8553 Self {
8554 duration_months: 3,
8555 amount_min: 100.0,
8556 amount_max: 1000.0,
8557 transaction_count_min: 2,
8558 transaction_count_max: 10,
8559 difficulty: "moderate".to_string(),
8560 }
8561 }
8562}
8563
8564#[derive(Debug, Clone, Serialize, Deserialize)]
8566pub struct CorrelatedInjectionConfig {
8567 #[serde(default)]
8569 pub enabled: bool,
8570
8571 #[serde(default = "default_true_val")]
8573 pub fraud_concealment: bool,
8574
8575 #[serde(default = "default_true_val")]
8577 pub error_cascade: bool,
8578
8579 #[serde(default = "default_true_val")]
8581 pub temporal_clustering: bool,
8582
8583 #[serde(default)]
8585 pub temporal_clustering_config: TemporalClusteringConfig,
8586
8587 #[serde(default)]
8589 pub co_occurrence_patterns: Vec<CoOccurrencePatternConfig>,
8590}
8591
8592impl Default for CorrelatedInjectionConfig {
8593 fn default() -> Self {
8594 Self {
8595 enabled: false,
8596 fraud_concealment: true,
8597 error_cascade: true,
8598 temporal_clustering: true,
8599 temporal_clustering_config: TemporalClusteringConfig::default(),
8600 co_occurrence_patterns: Vec::new(),
8601 }
8602 }
8603}
8604
8605#[derive(Debug, Clone, Serialize, Deserialize)]
8607pub struct TemporalClusteringConfig {
8608 #[serde(default = "default_period_end_multiplier")]
8610 pub period_end_multiplier: f64,
8611
8612 #[serde(default = "default_period_end_days")]
8614 pub period_end_days: u32,
8615
8616 #[serde(default = "default_quarter_end_multiplier")]
8618 pub quarter_end_multiplier: f64,
8619
8620 #[serde(default = "default_year_end_multiplier")]
8622 pub year_end_multiplier: f64,
8623}
8624
8625fn default_period_end_multiplier() -> f64 {
8626 2.5
8627}
8628fn default_period_end_days() -> u32 {
8629 5
8630}
8631fn default_quarter_end_multiplier() -> f64 {
8632 1.5
8633}
8634fn default_year_end_multiplier() -> f64 {
8635 2.0
8636}
8637
8638impl Default for TemporalClusteringConfig {
8639 fn default() -> Self {
8640 Self {
8641 period_end_multiplier: default_period_end_multiplier(),
8642 period_end_days: default_period_end_days(),
8643 quarter_end_multiplier: default_quarter_end_multiplier(),
8644 year_end_multiplier: default_year_end_multiplier(),
8645 }
8646 }
8647}
8648
8649#[derive(Debug, Clone, Serialize, Deserialize)]
8651pub struct CoOccurrencePatternConfig {
8652 pub name: String,
8654
8655 pub primary_type: String,
8657
8658 pub correlated: Vec<CorrelatedAnomalyConfig>,
8660}
8661
8662#[derive(Debug, Clone, Serialize, Deserialize)]
8664pub struct CorrelatedAnomalyConfig {
8665 pub anomaly_type: String,
8667
8668 pub probability: f64,
8670
8671 pub lag_days_min: i32,
8673
8674 pub lag_days_max: i32,
8676}
8677
8678#[derive(Debug, Clone, Serialize, Deserialize)]
8680pub struct NearMissConfig {
8681 #[serde(default)]
8683 pub enabled: bool,
8684
8685 #[serde(default = "default_near_miss_proportion")]
8687 pub proportion: f64,
8688
8689 #[serde(default = "default_true_val")]
8691 pub near_duplicate: bool,
8692
8693 #[serde(default)]
8695 pub near_duplicate_days: NearDuplicateDaysConfig,
8696
8697 #[serde(default = "default_true_val")]
8699 pub threshold_proximity: bool,
8700
8701 #[serde(default)]
8703 pub threshold_proximity_range: ThresholdProximityRangeConfig,
8704
8705 #[serde(default = "default_true_val")]
8707 pub unusual_legitimate: bool,
8708
8709 #[serde(default = "default_unusual_legitimate_types")]
8711 pub unusual_legitimate_types: Vec<String>,
8712
8713 #[serde(default = "default_true_val")]
8715 pub corrected_errors: bool,
8716
8717 #[serde(default)]
8719 pub corrected_error_lag: CorrectedErrorLagConfig,
8720}
8721
8722fn default_near_miss_proportion() -> f64 {
8723 0.30
8724}
8725
8726fn default_unusual_legitimate_types() -> Vec<String> {
8727 vec![
8728 "year_end_bonus".to_string(),
8729 "contract_prepayment".to_string(),
8730 "insurance_claim".to_string(),
8731 "settlement_payment".to_string(),
8732 ]
8733}
8734
8735impl Default for NearMissConfig {
8736 fn default() -> Self {
8737 Self {
8738 enabled: false,
8739 proportion: default_near_miss_proportion(),
8740 near_duplicate: true,
8741 near_duplicate_days: NearDuplicateDaysConfig::default(),
8742 threshold_proximity: true,
8743 threshold_proximity_range: ThresholdProximityRangeConfig::default(),
8744 unusual_legitimate: true,
8745 unusual_legitimate_types: default_unusual_legitimate_types(),
8746 corrected_errors: true,
8747 corrected_error_lag: CorrectedErrorLagConfig::default(),
8748 }
8749 }
8750}
8751
8752#[derive(Debug, Clone, Serialize, Deserialize)]
8754pub struct NearDuplicateDaysConfig {
8755 #[serde(default = "default_near_duplicate_min")]
8757 pub min: u32,
8758
8759 #[serde(default = "default_near_duplicate_max")]
8761 pub max: u32,
8762}
8763
8764fn default_near_duplicate_min() -> u32 {
8765 1
8766}
8767fn default_near_duplicate_max() -> u32 {
8768 3
8769}
8770
8771impl Default for NearDuplicateDaysConfig {
8772 fn default() -> Self {
8773 Self {
8774 min: default_near_duplicate_min(),
8775 max: default_near_duplicate_max(),
8776 }
8777 }
8778}
8779
8780#[derive(Debug, Clone, Serialize, Deserialize)]
8782pub struct ThresholdProximityRangeConfig {
8783 #[serde(default = "default_threshold_proximity_min")]
8785 pub min: f64,
8786
8787 #[serde(default = "default_threshold_proximity_max")]
8789 pub max: f64,
8790}
8791
8792fn default_threshold_proximity_min() -> f64 {
8793 0.90
8794}
8795fn default_threshold_proximity_max() -> f64 {
8796 0.99
8797}
8798
8799impl Default for ThresholdProximityRangeConfig {
8800 fn default() -> Self {
8801 Self {
8802 min: default_threshold_proximity_min(),
8803 max: default_threshold_proximity_max(),
8804 }
8805 }
8806}
8807
8808#[derive(Debug, Clone, Serialize, Deserialize)]
8810pub struct CorrectedErrorLagConfig {
8811 #[serde(default = "default_corrected_error_lag_min")]
8813 pub min: u32,
8814
8815 #[serde(default = "default_corrected_error_lag_max")]
8817 pub max: u32,
8818}
8819
8820fn default_corrected_error_lag_min() -> u32 {
8821 1
8822}
8823fn default_corrected_error_lag_max() -> u32 {
8824 5
8825}
8826
8827impl Default for CorrectedErrorLagConfig {
8828 fn default() -> Self {
8829 Self {
8830 min: default_corrected_error_lag_min(),
8831 max: default_corrected_error_lag_max(),
8832 }
8833 }
8834}
8835
8836#[derive(Debug, Clone, Serialize, Deserialize)]
8838pub struct DifficultyClassificationConfig {
8839 #[serde(default)]
8841 pub enabled: bool,
8842
8843 #[serde(default)]
8845 pub target_distribution: DifficultyDistributionConfig,
8846}
8847
8848impl Default for DifficultyClassificationConfig {
8849 fn default() -> Self {
8850 Self {
8851 enabled: true,
8852 target_distribution: DifficultyDistributionConfig::default(),
8853 }
8854 }
8855}
8856
8857#[derive(Debug, Clone, Serialize, Deserialize)]
8859pub struct DifficultyDistributionConfig {
8860 #[serde(default = "default_difficulty_trivial")]
8862 pub trivial: f64,
8863
8864 #[serde(default = "default_difficulty_easy")]
8866 pub easy: f64,
8867
8868 #[serde(default = "default_difficulty_moderate")]
8870 pub moderate: f64,
8871
8872 #[serde(default = "default_difficulty_hard")]
8874 pub hard: f64,
8875
8876 #[serde(default = "default_difficulty_expert")]
8878 pub expert: f64,
8879}
8880
8881fn default_difficulty_trivial() -> f64 {
8882 0.15
8883}
8884fn default_difficulty_easy() -> f64 {
8885 0.25
8886}
8887fn default_difficulty_moderate() -> f64 {
8888 0.30
8889}
8890fn default_difficulty_hard() -> f64 {
8891 0.20
8892}
8893fn default_difficulty_expert() -> f64 {
8894 0.10
8895}
8896
8897impl Default for DifficultyDistributionConfig {
8898 fn default() -> Self {
8899 Self {
8900 trivial: default_difficulty_trivial(),
8901 easy: default_difficulty_easy(),
8902 moderate: default_difficulty_moderate(),
8903 hard: default_difficulty_hard(),
8904 expert: default_difficulty_expert(),
8905 }
8906 }
8907}
8908
8909#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8911pub struct ContextAwareConfig {
8912 #[serde(default)]
8914 pub enabled: bool,
8915
8916 #[serde(default)]
8918 pub vendor_rules: VendorAnomalyRulesConfig,
8919
8920 #[serde(default)]
8922 pub employee_rules: EmployeeAnomalyRulesConfig,
8923
8924 #[serde(default)]
8926 pub account_rules: AccountAnomalyRulesConfig,
8927
8928 #[serde(default)]
8930 pub behavioral_baseline: BehavioralBaselineConfig,
8931}
8932
8933#[derive(Debug, Clone, Serialize, Deserialize)]
8935pub struct VendorAnomalyRulesConfig {
8936 #[serde(default = "default_new_vendor_multiplier")]
8938 pub new_vendor_error_multiplier: f64,
8939
8940 #[serde(default = "default_new_vendor_threshold")]
8942 pub new_vendor_threshold_days: u32,
8943
8944 #[serde(default = "default_international_multiplier")]
8946 pub international_error_multiplier: f64,
8947
8948 #[serde(default = "default_strategic_vendor_types")]
8950 pub strategic_vendor_anomaly_types: Vec<String>,
8951}
8952
8953fn default_new_vendor_multiplier() -> f64 {
8954 2.5
8955}
8956fn default_new_vendor_threshold() -> u32 {
8957 90
8958}
8959fn default_international_multiplier() -> f64 {
8960 1.5
8961}
8962fn default_strategic_vendor_types() -> Vec<String> {
8963 vec![
8964 "pricing_dispute".to_string(),
8965 "contract_violation".to_string(),
8966 ]
8967}
8968
8969impl Default for VendorAnomalyRulesConfig {
8970 fn default() -> Self {
8971 Self {
8972 new_vendor_error_multiplier: default_new_vendor_multiplier(),
8973 new_vendor_threshold_days: default_new_vendor_threshold(),
8974 international_error_multiplier: default_international_multiplier(),
8975 strategic_vendor_anomaly_types: default_strategic_vendor_types(),
8976 }
8977 }
8978}
8979
8980#[derive(Debug, Clone, Serialize, Deserialize)]
8982pub struct EmployeeAnomalyRulesConfig {
8983 #[serde(default = "default_new_employee_rate")]
8985 pub new_employee_error_rate: f64,
8986
8987 #[serde(default = "default_new_employee_threshold")]
8989 pub new_employee_threshold_days: u32,
8990
8991 #[serde(default = "default_volume_fatigue_threshold")]
8993 pub volume_fatigue_threshold: u32,
8994
8995 #[serde(default = "default_coverage_multiplier")]
8997 pub coverage_error_multiplier: f64,
8998}
8999
9000fn default_new_employee_rate() -> f64 {
9001 0.05
9002}
9003fn default_new_employee_threshold() -> u32 {
9004 180
9005}
9006fn default_volume_fatigue_threshold() -> u32 {
9007 50
9008}
9009fn default_coverage_multiplier() -> f64 {
9010 1.8
9011}
9012
9013impl Default for EmployeeAnomalyRulesConfig {
9014 fn default() -> Self {
9015 Self {
9016 new_employee_error_rate: default_new_employee_rate(),
9017 new_employee_threshold_days: default_new_employee_threshold(),
9018 volume_fatigue_threshold: default_volume_fatigue_threshold(),
9019 coverage_error_multiplier: default_coverage_multiplier(),
9020 }
9021 }
9022}
9023
9024#[derive(Debug, Clone, Serialize, Deserialize)]
9026pub struct AccountAnomalyRulesConfig {
9027 #[serde(default = "default_high_risk_multiplier")]
9029 pub high_risk_account_multiplier: f64,
9030
9031 #[serde(default = "default_high_risk_accounts")]
9033 pub high_risk_accounts: Vec<String>,
9034
9035 #[serde(default = "default_suspense_multiplier")]
9037 pub suspense_account_multiplier: f64,
9038
9039 #[serde(default = "default_suspense_accounts")]
9041 pub suspense_accounts: Vec<String>,
9042
9043 #[serde(default = "default_intercompany_multiplier")]
9045 pub intercompany_account_multiplier: f64,
9046}
9047
9048fn default_high_risk_multiplier() -> f64 {
9049 2.0
9050}
9051fn default_high_risk_accounts() -> Vec<String> {
9052 vec![
9053 "1100".to_string(), "2000".to_string(), "3000".to_string(), ]
9057}
9058fn default_suspense_multiplier() -> f64 {
9059 3.0
9060}
9061fn default_suspense_accounts() -> Vec<String> {
9062 vec!["9999".to_string(), "9998".to_string()]
9063}
9064fn default_intercompany_multiplier() -> f64 {
9065 1.5
9066}
9067
9068impl Default for AccountAnomalyRulesConfig {
9069 fn default() -> Self {
9070 Self {
9071 high_risk_account_multiplier: default_high_risk_multiplier(),
9072 high_risk_accounts: default_high_risk_accounts(),
9073 suspense_account_multiplier: default_suspense_multiplier(),
9074 suspense_accounts: default_suspense_accounts(),
9075 intercompany_account_multiplier: default_intercompany_multiplier(),
9076 }
9077 }
9078}
9079
9080#[derive(Debug, Clone, Serialize, Deserialize)]
9082pub struct BehavioralBaselineConfig {
9083 #[serde(default)]
9085 pub enabled: bool,
9086
9087 #[serde(default = "default_baseline_period")]
9089 pub baseline_period_days: u32,
9090
9091 #[serde(default = "default_deviation_threshold")]
9093 pub deviation_threshold_std: f64,
9094
9095 #[serde(default = "default_frequency_deviation")]
9097 pub frequency_deviation_threshold: f64,
9098}
9099
9100fn default_baseline_period() -> u32 {
9101 90
9102}
9103fn default_deviation_threshold() -> f64 {
9104 3.0
9105}
9106fn default_frequency_deviation() -> f64 {
9107 2.0
9108}
9109
9110impl Default for BehavioralBaselineConfig {
9111 fn default() -> Self {
9112 Self {
9113 enabled: false,
9114 baseline_period_days: default_baseline_period(),
9115 deviation_threshold_std: default_deviation_threshold(),
9116 frequency_deviation_threshold: default_frequency_deviation(),
9117 }
9118 }
9119}
9120
9121#[derive(Debug, Clone, Serialize, Deserialize)]
9123pub struct EnhancedLabelingConfig {
9124 #[serde(default = "default_true_val")]
9126 pub severity_scoring: bool,
9127
9128 #[serde(default = "default_true_val")]
9130 pub difficulty_classification: bool,
9131
9132 #[serde(default)]
9134 pub materiality_thresholds: MaterialityThresholdsConfig,
9135}
9136
9137impl Default for EnhancedLabelingConfig {
9138 fn default() -> Self {
9139 Self {
9140 severity_scoring: true,
9141 difficulty_classification: true,
9142 materiality_thresholds: MaterialityThresholdsConfig::default(),
9143 }
9144 }
9145}
9146
9147#[derive(Debug, Clone, Serialize, Deserialize)]
9149pub struct MaterialityThresholdsConfig {
9150 #[serde(default = "default_materiality_trivial")]
9152 pub trivial: f64,
9153
9154 #[serde(default = "default_materiality_immaterial")]
9156 pub immaterial: f64,
9157
9158 #[serde(default = "default_materiality_material")]
9160 pub material: f64,
9161
9162 #[serde(default = "default_materiality_highly_material")]
9164 pub highly_material: f64,
9165}
9166
9167fn default_materiality_trivial() -> f64 {
9168 0.001
9169}
9170fn default_materiality_immaterial() -> f64 {
9171 0.01
9172}
9173fn default_materiality_material() -> f64 {
9174 0.05
9175}
9176fn default_materiality_highly_material() -> f64 {
9177 0.10
9178}
9179
9180impl Default for MaterialityThresholdsConfig {
9181 fn default() -> Self {
9182 Self {
9183 trivial: default_materiality_trivial(),
9184 immaterial: default_materiality_immaterial(),
9185 material: default_materiality_material(),
9186 highly_material: default_materiality_highly_material(),
9187 }
9188 }
9189}
9190
9191#[derive(Debug, Clone, Serialize, Deserialize, Default)]
9203pub struct IndustrySpecificConfig {
9204 #[serde(default)]
9206 pub enabled: bool,
9207
9208 #[serde(default)]
9210 pub manufacturing: ManufacturingConfig,
9211
9212 #[serde(default)]
9214 pub retail: RetailConfig,
9215
9216 #[serde(default)]
9218 pub healthcare: HealthcareConfig,
9219
9220 #[serde(default)]
9222 pub technology: TechnologyConfig,
9223
9224 #[serde(default)]
9226 pub financial_services: FinancialServicesConfig,
9227
9228 #[serde(default)]
9230 pub professional_services: ProfessionalServicesConfig,
9231}
9232
9233#[derive(Debug, Clone, Serialize, Deserialize)]
9235pub struct ManufacturingConfig {
9236 #[serde(default)]
9238 pub enabled: bool,
9239
9240 #[serde(default = "default_bom_depth")]
9242 pub bom_depth: u32,
9243
9244 #[serde(default)]
9246 pub just_in_time: bool,
9247
9248 #[serde(default = "default_production_order_types")]
9250 pub production_order_types: Vec<String>,
9251
9252 #[serde(default)]
9254 pub quality_framework: Option<String>,
9255
9256 #[serde(default = "default_supplier_tiers")]
9258 pub supplier_tiers: u32,
9259
9260 #[serde(default = "default_cost_frequency")]
9262 pub standard_cost_frequency: String,
9263
9264 #[serde(default = "default_yield_rate")]
9266 pub target_yield_rate: f64,
9267
9268 #[serde(default = "default_scrap_threshold")]
9270 pub scrap_alert_threshold: f64,
9271
9272 #[serde(default)]
9274 pub anomaly_rates: ManufacturingAnomalyRates,
9275
9276 #[serde(default)]
9278 pub cost_accounting: ManufacturingCostAccountingConfig,
9279}
9280
9281#[derive(Debug, Clone, Serialize, Deserialize)]
9283pub struct ManufacturingCostAccountingConfig {
9284 #[serde(default = "default_true")]
9286 pub enabled: bool,
9287
9288 #[serde(default = "default_true")]
9290 pub variance_accounts_enabled: bool,
9291
9292 #[serde(default = "default_true")]
9294 pub warranty_provisions_enabled: bool,
9295
9296 #[serde(default = "default_warranty_defect_threshold")]
9298 pub warranty_defect_threshold: f64,
9299}
9300
9301fn default_warranty_defect_threshold() -> f64 {
9302 0.01
9303}
9304
9305impl Default for ManufacturingCostAccountingConfig {
9306 fn default() -> Self {
9307 Self {
9308 enabled: true,
9309 variance_accounts_enabled: true,
9310 warranty_provisions_enabled: true,
9311 warranty_defect_threshold: 0.01,
9312 }
9313 }
9314}
9315
9316fn default_bom_depth() -> u32 {
9317 4
9318}
9319
9320fn default_production_order_types() -> Vec<String> {
9321 vec![
9322 "standard".to_string(),
9323 "rework".to_string(),
9324 "prototype".to_string(),
9325 ]
9326}
9327
9328fn default_supplier_tiers() -> u32 {
9329 2
9330}
9331
9332fn default_cost_frequency() -> String {
9333 "quarterly".to_string()
9334}
9335
9336fn default_yield_rate() -> f64 {
9337 0.97
9338}
9339
9340fn default_scrap_threshold() -> f64 {
9341 0.03
9342}
9343
9344impl Default for ManufacturingConfig {
9345 fn default() -> Self {
9346 Self {
9347 enabled: false,
9348 bom_depth: default_bom_depth(),
9349 just_in_time: false,
9350 production_order_types: default_production_order_types(),
9351 quality_framework: Some("ISO_9001".to_string()),
9352 supplier_tiers: default_supplier_tiers(),
9353 standard_cost_frequency: default_cost_frequency(),
9354 target_yield_rate: default_yield_rate(),
9355 scrap_alert_threshold: default_scrap_threshold(),
9356 anomaly_rates: ManufacturingAnomalyRates::default(),
9357 cost_accounting: ManufacturingCostAccountingConfig::default(),
9358 }
9359 }
9360}
9361
9362#[derive(Debug, Clone, Serialize, Deserialize)]
9364pub struct ManufacturingAnomalyRates {
9365 #[serde(default = "default_mfg_yield_rate")]
9367 pub yield_manipulation: f64,
9368
9369 #[serde(default = "default_mfg_labor_rate")]
9371 pub labor_misallocation: f64,
9372
9373 #[serde(default = "default_mfg_phantom_rate")]
9375 pub phantom_production: f64,
9376
9377 #[serde(default = "default_mfg_cost_rate")]
9379 pub standard_cost_manipulation: f64,
9380
9381 #[serde(default = "default_mfg_inventory_rate")]
9383 pub inventory_fraud: f64,
9384}
9385
9386fn default_mfg_yield_rate() -> f64 {
9387 0.015
9388}
9389
9390fn default_mfg_labor_rate() -> f64 {
9391 0.02
9392}
9393
9394fn default_mfg_phantom_rate() -> f64 {
9395 0.005
9396}
9397
9398fn default_mfg_cost_rate() -> f64 {
9399 0.01
9400}
9401
9402fn default_mfg_inventory_rate() -> f64 {
9403 0.008
9404}
9405
9406impl Default for ManufacturingAnomalyRates {
9407 fn default() -> Self {
9408 Self {
9409 yield_manipulation: default_mfg_yield_rate(),
9410 labor_misallocation: default_mfg_labor_rate(),
9411 phantom_production: default_mfg_phantom_rate(),
9412 standard_cost_manipulation: default_mfg_cost_rate(),
9413 inventory_fraud: default_mfg_inventory_rate(),
9414 }
9415 }
9416}
9417
9418#[derive(Debug, Clone, Serialize, Deserialize)]
9420pub struct RetailConfig {
9421 #[serde(default)]
9423 pub enabled: bool,
9424
9425 #[serde(default)]
9427 pub store_types: RetailStoreTypeConfig,
9428
9429 #[serde(default = "default_retail_daily_txns")]
9431 pub avg_daily_transactions: u32,
9432
9433 #[serde(default = "default_true")]
9435 pub loss_prevention: bool,
9436
9437 #[serde(default = "default_shrinkage_rate")]
9439 pub shrinkage_rate: f64,
9440
9441 #[serde(default)]
9443 pub anomaly_rates: RetailAnomalyRates,
9444}
9445
9446fn default_retail_daily_txns() -> u32 {
9447 500
9448}
9449
9450fn default_shrinkage_rate() -> f64 {
9451 0.015
9452}
9453
9454impl Default for RetailConfig {
9455 fn default() -> Self {
9456 Self {
9457 enabled: false,
9458 store_types: RetailStoreTypeConfig::default(),
9459 avg_daily_transactions: default_retail_daily_txns(),
9460 loss_prevention: true,
9461 shrinkage_rate: default_shrinkage_rate(),
9462 anomaly_rates: RetailAnomalyRates::default(),
9463 }
9464 }
9465}
9466
9467#[derive(Debug, Clone, Serialize, Deserialize)]
9469pub struct RetailStoreTypeConfig {
9470 #[serde(default = "default_flagship_pct")]
9472 pub flagship: f64,
9473
9474 #[serde(default = "default_regional_pct")]
9476 pub regional: f64,
9477
9478 #[serde(default = "default_outlet_pct")]
9480 pub outlet: f64,
9481
9482 #[serde(default = "default_ecommerce_pct")]
9484 pub ecommerce: f64,
9485}
9486
9487fn default_flagship_pct() -> f64 {
9488 0.10
9489}
9490
9491fn default_regional_pct() -> f64 {
9492 0.50
9493}
9494
9495fn default_outlet_pct() -> f64 {
9496 0.25
9497}
9498
9499fn default_ecommerce_pct() -> f64 {
9500 0.15
9501}
9502
9503impl Default for RetailStoreTypeConfig {
9504 fn default() -> Self {
9505 Self {
9506 flagship: default_flagship_pct(),
9507 regional: default_regional_pct(),
9508 outlet: default_outlet_pct(),
9509 ecommerce: default_ecommerce_pct(),
9510 }
9511 }
9512}
9513
9514#[derive(Debug, Clone, Serialize, Deserialize)]
9516pub struct RetailAnomalyRates {
9517 #[serde(default = "default_sweethearting_rate")]
9519 pub sweethearting: f64,
9520
9521 #[serde(default = "default_skimming_rate")]
9523 pub skimming: f64,
9524
9525 #[serde(default = "default_refund_fraud_rate")]
9527 pub refund_fraud: f64,
9528
9529 #[serde(default = "default_void_abuse_rate")]
9531 pub void_abuse: f64,
9532
9533 #[serde(default = "default_gift_card_rate")]
9535 pub gift_card_fraud: f64,
9536
9537 #[serde(default = "default_retail_kickback_rate")]
9539 pub vendor_kickback: f64,
9540}
9541
9542fn default_sweethearting_rate() -> f64 {
9543 0.02
9544}
9545
9546fn default_skimming_rate() -> f64 {
9547 0.005
9548}
9549
9550fn default_refund_fraud_rate() -> f64 {
9551 0.015
9552}
9553
9554fn default_void_abuse_rate() -> f64 {
9555 0.01
9556}
9557
9558fn default_gift_card_rate() -> f64 {
9559 0.008
9560}
9561
9562fn default_retail_kickback_rate() -> f64 {
9563 0.003
9564}
9565
9566impl Default for RetailAnomalyRates {
9567 fn default() -> Self {
9568 Self {
9569 sweethearting: default_sweethearting_rate(),
9570 skimming: default_skimming_rate(),
9571 refund_fraud: default_refund_fraud_rate(),
9572 void_abuse: default_void_abuse_rate(),
9573 gift_card_fraud: default_gift_card_rate(),
9574 vendor_kickback: default_retail_kickback_rate(),
9575 }
9576 }
9577}
9578
9579#[derive(Debug, Clone, Serialize, Deserialize)]
9581pub struct HealthcareConfig {
9582 #[serde(default)]
9584 pub enabled: bool,
9585
9586 #[serde(default = "default_facility_type")]
9588 pub facility_type: String,
9589
9590 #[serde(default)]
9592 pub payer_mix: HealthcarePayerMix,
9593
9594 #[serde(default)]
9596 pub coding_systems: HealthcareCodingSystems,
9597
9598 #[serde(default)]
9600 pub compliance: HealthcareComplianceConfig,
9601
9602 #[serde(default = "default_daily_encounters")]
9604 pub avg_daily_encounters: u32,
9605
9606 #[serde(default = "default_charges_per_encounter")]
9608 pub avg_charges_per_encounter: u32,
9609
9610 #[serde(default = "default_hc_denial_rate")]
9612 pub denial_rate: f64,
9613
9614 #[serde(default = "default_hc_bad_debt_rate")]
9616 pub bad_debt_rate: f64,
9617
9618 #[serde(default = "default_hc_charity_care_rate")]
9620 pub charity_care_rate: f64,
9621
9622 #[serde(default)]
9624 pub anomaly_rates: HealthcareAnomalyRates,
9625}
9626
9627fn default_facility_type() -> String {
9628 "hospital".to_string()
9629}
9630
9631fn default_daily_encounters() -> u32 {
9632 150
9633}
9634
9635fn default_charges_per_encounter() -> u32 {
9636 8
9637}
9638
9639fn default_hc_denial_rate() -> f64 {
9640 0.05
9641}
9642
9643fn default_hc_bad_debt_rate() -> f64 {
9644 0.03
9645}
9646
9647fn default_hc_charity_care_rate() -> f64 {
9648 0.02
9649}
9650
9651impl Default for HealthcareConfig {
9652 fn default() -> Self {
9653 Self {
9654 enabled: false,
9655 facility_type: default_facility_type(),
9656 payer_mix: HealthcarePayerMix::default(),
9657 coding_systems: HealthcareCodingSystems::default(),
9658 compliance: HealthcareComplianceConfig::default(),
9659 avg_daily_encounters: default_daily_encounters(),
9660 avg_charges_per_encounter: default_charges_per_encounter(),
9661 denial_rate: default_hc_denial_rate(),
9662 bad_debt_rate: default_hc_bad_debt_rate(),
9663 charity_care_rate: default_hc_charity_care_rate(),
9664 anomaly_rates: HealthcareAnomalyRates::default(),
9665 }
9666 }
9667}
9668
9669#[derive(Debug, Clone, Serialize, Deserialize)]
9671pub struct HealthcarePayerMix {
9672 #[serde(default = "default_medicare_pct")]
9674 pub medicare: f64,
9675
9676 #[serde(default = "default_medicaid_pct")]
9678 pub medicaid: f64,
9679
9680 #[serde(default = "default_commercial_pct")]
9682 pub commercial: f64,
9683
9684 #[serde(default = "default_self_pay_pct")]
9686 pub self_pay: f64,
9687}
9688
9689fn default_medicare_pct() -> f64 {
9690 0.40
9691}
9692
9693fn default_medicaid_pct() -> f64 {
9694 0.20
9695}
9696
9697fn default_commercial_pct() -> f64 {
9698 0.30
9699}
9700
9701fn default_self_pay_pct() -> f64 {
9702 0.10
9703}
9704
9705impl Default for HealthcarePayerMix {
9706 fn default() -> Self {
9707 Self {
9708 medicare: default_medicare_pct(),
9709 medicaid: default_medicaid_pct(),
9710 commercial: default_commercial_pct(),
9711 self_pay: default_self_pay_pct(),
9712 }
9713 }
9714}
9715
9716#[derive(Debug, Clone, Serialize, Deserialize)]
9718pub struct HealthcareCodingSystems {
9719 #[serde(default = "default_true")]
9721 pub icd10: bool,
9722
9723 #[serde(default = "default_true")]
9725 pub cpt: bool,
9726
9727 #[serde(default = "default_true")]
9729 pub drg: bool,
9730
9731 #[serde(default = "default_true")]
9733 pub hcpcs: bool,
9734
9735 #[serde(default = "default_true")]
9737 pub revenue_codes: bool,
9738}
9739
9740impl Default for HealthcareCodingSystems {
9741 fn default() -> Self {
9742 Self {
9743 icd10: true,
9744 cpt: true,
9745 drg: true,
9746 hcpcs: true,
9747 revenue_codes: true,
9748 }
9749 }
9750}
9751
9752#[derive(Debug, Clone, Serialize, Deserialize)]
9754pub struct HealthcareComplianceConfig {
9755 #[serde(default = "default_true")]
9757 pub hipaa: bool,
9758
9759 #[serde(default = "default_true")]
9761 pub stark_law: bool,
9762
9763 #[serde(default = "default_true")]
9765 pub anti_kickback: bool,
9766
9767 #[serde(default = "default_true")]
9769 pub false_claims_act: bool,
9770
9771 #[serde(default = "default_true")]
9773 pub emtala: bool,
9774}
9775
9776impl Default for HealthcareComplianceConfig {
9777 fn default() -> Self {
9778 Self {
9779 hipaa: true,
9780 stark_law: true,
9781 anti_kickback: true,
9782 false_claims_act: true,
9783 emtala: true,
9784 }
9785 }
9786}
9787
9788#[derive(Debug, Clone, Serialize, Deserialize)]
9790pub struct HealthcareAnomalyRates {
9791 #[serde(default = "default_upcoding_rate")]
9793 pub upcoding: f64,
9794
9795 #[serde(default = "default_unbundling_rate")]
9797 pub unbundling: f64,
9798
9799 #[serde(default = "default_phantom_billing_rate")]
9801 pub phantom_billing: f64,
9802
9803 #[serde(default = "default_healthcare_kickback_rate")]
9805 pub kickbacks: f64,
9806
9807 #[serde(default = "default_duplicate_billing_rate")]
9809 pub duplicate_billing: f64,
9810
9811 #[serde(default = "default_med_necessity_rate")]
9813 pub medical_necessity_abuse: f64,
9814}
9815
9816fn default_upcoding_rate() -> f64 {
9817 0.02
9818}
9819
9820fn default_unbundling_rate() -> f64 {
9821 0.015
9822}
9823
9824fn default_phantom_billing_rate() -> f64 {
9825 0.005
9826}
9827
9828fn default_healthcare_kickback_rate() -> f64 {
9829 0.003
9830}
9831
9832fn default_duplicate_billing_rate() -> f64 {
9833 0.008
9834}
9835
9836fn default_med_necessity_rate() -> f64 {
9837 0.01
9838}
9839
9840impl Default for HealthcareAnomalyRates {
9841 fn default() -> Self {
9842 Self {
9843 upcoding: default_upcoding_rate(),
9844 unbundling: default_unbundling_rate(),
9845 phantom_billing: default_phantom_billing_rate(),
9846 kickbacks: default_healthcare_kickback_rate(),
9847 duplicate_billing: default_duplicate_billing_rate(),
9848 medical_necessity_abuse: default_med_necessity_rate(),
9849 }
9850 }
9851}
9852
9853#[derive(Debug, Clone, Serialize, Deserialize)]
9855pub struct TechnologyConfig {
9856 #[serde(default)]
9858 pub enabled: bool,
9859
9860 #[serde(default = "default_revenue_model")]
9862 pub revenue_model: String,
9863
9864 #[serde(default = "default_subscription_pct")]
9866 pub subscription_revenue_pct: f64,
9867
9868 #[serde(default = "default_license_pct")]
9870 pub license_revenue_pct: f64,
9871
9872 #[serde(default = "default_services_pct")]
9874 pub services_revenue_pct: f64,
9875
9876 #[serde(default)]
9878 pub rd_capitalization: RdCapitalizationConfig,
9879
9880 #[serde(default)]
9882 pub anomaly_rates: TechnologyAnomalyRates,
9883}
9884
9885fn default_revenue_model() -> String {
9886 "saas".to_string()
9887}
9888
9889fn default_subscription_pct() -> f64 {
9890 0.60
9891}
9892
9893fn default_license_pct() -> f64 {
9894 0.25
9895}
9896
9897fn default_services_pct() -> f64 {
9898 0.15
9899}
9900
9901impl Default for TechnologyConfig {
9902 fn default() -> Self {
9903 Self {
9904 enabled: false,
9905 revenue_model: default_revenue_model(),
9906 subscription_revenue_pct: default_subscription_pct(),
9907 license_revenue_pct: default_license_pct(),
9908 services_revenue_pct: default_services_pct(),
9909 rd_capitalization: RdCapitalizationConfig::default(),
9910 anomaly_rates: TechnologyAnomalyRates::default(),
9911 }
9912 }
9913}
9914
9915#[derive(Debug, Clone, Serialize, Deserialize)]
9917pub struct RdCapitalizationConfig {
9918 #[serde(default = "default_true")]
9920 pub enabled: bool,
9921
9922 #[serde(default = "default_cap_rate")]
9924 pub capitalization_rate: f64,
9925
9926 #[serde(default = "default_useful_life")]
9928 pub useful_life_years: u32,
9929}
9930
9931fn default_cap_rate() -> f64 {
9932 0.30
9933}
9934
9935fn default_useful_life() -> u32 {
9936 3
9937}
9938
9939impl Default for RdCapitalizationConfig {
9940 fn default() -> Self {
9941 Self {
9942 enabled: true,
9943 capitalization_rate: default_cap_rate(),
9944 useful_life_years: default_useful_life(),
9945 }
9946 }
9947}
9948
9949#[derive(Debug, Clone, Serialize, Deserialize)]
9951pub struct TechnologyAnomalyRates {
9952 #[serde(default = "default_premature_rev_rate")]
9954 pub premature_revenue: f64,
9955
9956 #[serde(default = "default_side_letter_rate")]
9958 pub side_letter_abuse: f64,
9959
9960 #[serde(default = "default_channel_stuffing_rate")]
9962 pub channel_stuffing: f64,
9963
9964 #[serde(default = "default_improper_cap_rate")]
9966 pub improper_capitalization: f64,
9967}
9968
9969fn default_premature_rev_rate() -> f64 {
9970 0.015
9971}
9972
9973fn default_side_letter_rate() -> f64 {
9974 0.008
9975}
9976
9977fn default_channel_stuffing_rate() -> f64 {
9978 0.01
9979}
9980
9981fn default_improper_cap_rate() -> f64 {
9982 0.012
9983}
9984
9985impl Default for TechnologyAnomalyRates {
9986 fn default() -> Self {
9987 Self {
9988 premature_revenue: default_premature_rev_rate(),
9989 side_letter_abuse: default_side_letter_rate(),
9990 channel_stuffing: default_channel_stuffing_rate(),
9991 improper_capitalization: default_improper_cap_rate(),
9992 }
9993 }
9994}
9995
9996#[derive(Debug, Clone, Serialize, Deserialize)]
9998pub struct FinancialServicesConfig {
9999 #[serde(default)]
10001 pub enabled: bool,
10002
10003 #[serde(default = "default_fi_type")]
10005 pub institution_type: String,
10006
10007 #[serde(default = "default_fi_regulatory")]
10009 pub regulatory_framework: String,
10010
10011 #[serde(default)]
10013 pub anomaly_rates: FinancialServicesAnomalyRates,
10014}
10015
10016fn default_fi_type() -> String {
10017 "commercial_bank".to_string()
10018}
10019
10020fn default_fi_regulatory() -> String {
10021 "us_banking".to_string()
10022}
10023
10024impl Default for FinancialServicesConfig {
10025 fn default() -> Self {
10026 Self {
10027 enabled: false,
10028 institution_type: default_fi_type(),
10029 regulatory_framework: default_fi_regulatory(),
10030 anomaly_rates: FinancialServicesAnomalyRates::default(),
10031 }
10032 }
10033}
10034
10035#[derive(Debug, Clone, Serialize, Deserialize)]
10037pub struct FinancialServicesAnomalyRates {
10038 #[serde(default = "default_loan_fraud_rate")]
10040 pub loan_fraud: f64,
10041
10042 #[serde(default = "default_trading_fraud_rate")]
10044 pub trading_fraud: f64,
10045
10046 #[serde(default = "default_insurance_fraud_rate")]
10048 pub insurance_fraud: f64,
10049
10050 #[serde(default = "default_account_manip_rate")]
10052 pub account_manipulation: f64,
10053}
10054
10055fn default_loan_fraud_rate() -> f64 {
10056 0.01
10057}
10058
10059fn default_trading_fraud_rate() -> f64 {
10060 0.008
10061}
10062
10063fn default_insurance_fraud_rate() -> f64 {
10064 0.012
10065}
10066
10067fn default_account_manip_rate() -> f64 {
10068 0.005
10069}
10070
10071impl Default for FinancialServicesAnomalyRates {
10072 fn default() -> Self {
10073 Self {
10074 loan_fraud: default_loan_fraud_rate(),
10075 trading_fraud: default_trading_fraud_rate(),
10076 insurance_fraud: default_insurance_fraud_rate(),
10077 account_manipulation: default_account_manip_rate(),
10078 }
10079 }
10080}
10081
10082#[derive(Debug, Clone, Serialize, Deserialize)]
10084pub struct ProfessionalServicesConfig {
10085 #[serde(default)]
10087 pub enabled: bool,
10088
10089 #[serde(default = "default_firm_type")]
10091 pub firm_type: String,
10092
10093 #[serde(default = "default_billing_model")]
10095 pub billing_model: String,
10096
10097 #[serde(default = "default_hourly_rate")]
10099 pub avg_hourly_rate: f64,
10100
10101 #[serde(default)]
10103 pub trust_accounting: TrustAccountingConfig,
10104
10105 #[serde(default)]
10107 pub anomaly_rates: ProfessionalServicesAnomalyRates,
10108}
10109
10110fn default_firm_type() -> String {
10111 "consulting".to_string()
10112}
10113
10114fn default_billing_model() -> String {
10115 "time_and_materials".to_string()
10116}
10117
10118fn default_hourly_rate() -> f64 {
10119 250.0
10120}
10121
10122impl Default for ProfessionalServicesConfig {
10123 fn default() -> Self {
10124 Self {
10125 enabled: false,
10126 firm_type: default_firm_type(),
10127 billing_model: default_billing_model(),
10128 avg_hourly_rate: default_hourly_rate(),
10129 trust_accounting: TrustAccountingConfig::default(),
10130 anomaly_rates: ProfessionalServicesAnomalyRates::default(),
10131 }
10132 }
10133}
10134
10135#[derive(Debug, Clone, Serialize, Deserialize)]
10137pub struct TrustAccountingConfig {
10138 #[serde(default)]
10140 pub enabled: bool,
10141
10142 #[serde(default = "default_true")]
10144 pub require_three_way_reconciliation: bool,
10145}
10146
10147impl Default for TrustAccountingConfig {
10148 fn default() -> Self {
10149 Self {
10150 enabled: false,
10151 require_three_way_reconciliation: true,
10152 }
10153 }
10154}
10155
10156#[derive(Debug, Clone, Serialize, Deserialize)]
10158pub struct ProfessionalServicesAnomalyRates {
10159 #[serde(default = "default_time_fraud_rate")]
10161 pub time_billing_fraud: f64,
10162
10163 #[serde(default = "default_expense_fraud_rate")]
10165 pub expense_fraud: f64,
10166
10167 #[serde(default = "default_trust_misappropriation_rate")]
10169 pub trust_misappropriation: f64,
10170}
10171
10172fn default_time_fraud_rate() -> f64 {
10173 0.02
10174}
10175
10176fn default_expense_fraud_rate() -> f64 {
10177 0.015
10178}
10179
10180fn default_trust_misappropriation_rate() -> f64 {
10181 0.003
10182}
10183
10184impl Default for ProfessionalServicesAnomalyRates {
10185 fn default() -> Self {
10186 Self {
10187 time_billing_fraud: default_time_fraud_rate(),
10188 expense_fraud: default_expense_fraud_rate(),
10189 trust_misappropriation: default_trust_misappropriation_rate(),
10190 }
10191 }
10192}
10193
10194#[derive(Debug, Clone, Serialize, Deserialize)]
10208pub struct FingerprintPrivacyConfig {
10209 #[serde(default)]
10211 pub level: String,
10212 #[serde(default = "default_epsilon")]
10214 pub epsilon: f64,
10215 #[serde(default = "default_delta")]
10217 pub delta: f64,
10218 #[serde(default = "default_k_anonymity")]
10220 pub k_anonymity: u32,
10221 #[serde(default)]
10223 pub composition_method: String,
10224}
10225
10226fn default_epsilon() -> f64 {
10227 1.0
10228}
10229
10230fn default_delta() -> f64 {
10231 1e-5
10232}
10233
10234fn default_k_anonymity() -> u32 {
10235 5
10236}
10237
10238impl Default for FingerprintPrivacyConfig {
10239 fn default() -> Self {
10240 Self {
10241 level: "standard".to_string(),
10242 epsilon: default_epsilon(),
10243 delta: default_delta(),
10244 k_anonymity: default_k_anonymity(),
10245 composition_method: "naive".to_string(),
10246 }
10247 }
10248}
10249
10250#[derive(Debug, Clone, Serialize, Deserialize)]
10264pub struct QualityGatesSchemaConfig {
10265 #[serde(default)]
10267 pub enabled: bool,
10268 #[serde(default = "default_gate_profile_name")]
10270 pub profile: String,
10271 #[serde(default)]
10273 pub fail_on_violation: bool,
10274 #[serde(default)]
10276 pub custom_gates: Vec<QualityGateEntry>,
10277}
10278
10279fn default_gate_profile_name() -> String {
10280 "default".to_string()
10281}
10282
10283impl Default for QualityGatesSchemaConfig {
10284 fn default() -> Self {
10285 Self {
10286 enabled: false,
10287 profile: default_gate_profile_name(),
10288 fail_on_violation: false,
10289 custom_gates: Vec::new(),
10290 }
10291 }
10292}
10293
10294#[derive(Debug, Clone, Serialize, Deserialize)]
10296pub struct QualityGateEntry {
10297 pub name: String,
10299 pub metric: String,
10303 pub threshold: f64,
10305 #[serde(default)]
10307 pub upper_threshold: Option<f64>,
10308 #[serde(default = "default_gate_comparison")]
10310 pub comparison: String,
10311}
10312
10313fn default_gate_comparison() -> String {
10314 "gte".to_string()
10315}
10316
10317#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10327pub struct ComplianceSchemaConfig {
10328 #[serde(default)]
10330 pub content_marking: ContentMarkingSchemaConfig,
10331 #[serde(default)]
10333 pub article10_report: bool,
10334 #[serde(default)]
10336 pub certificates: CertificateSchemaConfig,
10337}
10338
10339#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10341pub struct CertificateSchemaConfig {
10342 #[serde(default)]
10344 pub enabled: bool,
10345 #[serde(default)]
10347 pub signing_key_env: Option<String>,
10348 #[serde(default)]
10350 pub include_quality_metrics: bool,
10351}
10352
10353#[derive(Debug, Clone, Serialize, Deserialize)]
10355pub struct ContentMarkingSchemaConfig {
10356 #[serde(default = "default_true")]
10358 pub enabled: bool,
10359 #[serde(default = "default_marking_format")]
10361 pub format: String,
10362}
10363
10364fn default_marking_format() -> String {
10365 "embedded".to_string()
10366}
10367
10368impl Default for ContentMarkingSchemaConfig {
10369 fn default() -> Self {
10370 Self {
10371 enabled: true,
10372 format: default_marking_format(),
10373 }
10374 }
10375}
10376
10377#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10379pub struct WebhookSchemaConfig {
10380 #[serde(default)]
10382 pub enabled: bool,
10383 #[serde(default)]
10385 pub endpoints: Vec<WebhookEndpointConfig>,
10386}
10387
10388#[derive(Debug, Clone, Serialize, Deserialize)]
10390pub struct WebhookEndpointConfig {
10391 pub url: String,
10393 #[serde(default)]
10395 pub events: Vec<String>,
10396 #[serde(default)]
10398 pub secret: Option<String>,
10399 #[serde(default = "default_webhook_retries")]
10401 pub max_retries: u32,
10402 #[serde(default = "default_webhook_timeout")]
10404 pub timeout_secs: u64,
10405}
10406
10407fn default_webhook_retries() -> u32 {
10408 3
10409}
10410fn default_webhook_timeout() -> u64 {
10411 10
10412}
10413
10414#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10420pub struct SourceToPayConfig {
10421 #[serde(default)]
10423 pub enabled: bool,
10424 #[serde(default)]
10426 pub spend_analysis: SpendAnalysisConfig,
10427 #[serde(default)]
10429 pub sourcing: SourcingConfig,
10430 #[serde(default)]
10432 pub qualification: QualificationConfig,
10433 #[serde(default)]
10435 pub rfx: RfxConfig,
10436 #[serde(default)]
10438 pub contracts: ContractConfig,
10439 #[serde(default)]
10441 pub catalog: CatalogConfig,
10442 #[serde(default)]
10444 pub scorecards: ScorecardConfig,
10445 #[serde(default)]
10447 pub p2p_integration: P2PIntegrationConfig,
10448}
10449
10450#[derive(Debug, Clone, Serialize, Deserialize)]
10452pub struct SpendAnalysisConfig {
10453 #[serde(default = "default_hhi_threshold")]
10455 pub hhi_threshold: f64,
10456 #[serde(default = "default_contract_coverage_target")]
10458 pub contract_coverage_target: f64,
10459}
10460
10461impl Default for SpendAnalysisConfig {
10462 fn default() -> Self {
10463 Self {
10464 hhi_threshold: default_hhi_threshold(),
10465 contract_coverage_target: default_contract_coverage_target(),
10466 }
10467 }
10468}
10469
10470fn default_hhi_threshold() -> f64 {
10471 2500.0
10472}
10473fn default_contract_coverage_target() -> f64 {
10474 0.80
10475}
10476
10477#[derive(Debug, Clone, Serialize, Deserialize)]
10479pub struct SourcingConfig {
10480 #[serde(default = "default_sourcing_projects_per_year")]
10482 pub projects_per_year: u32,
10483 #[serde(default = "default_renewal_horizon_months")]
10485 pub renewal_horizon_months: u32,
10486 #[serde(default = "default_project_duration_months")]
10488 pub project_duration_months: u32,
10489}
10490
10491impl Default for SourcingConfig {
10492 fn default() -> Self {
10493 Self {
10494 projects_per_year: default_sourcing_projects_per_year(),
10495 renewal_horizon_months: default_renewal_horizon_months(),
10496 project_duration_months: default_project_duration_months(),
10497 }
10498 }
10499}
10500
10501fn default_sourcing_projects_per_year() -> u32 {
10502 10
10503}
10504fn default_renewal_horizon_months() -> u32 {
10505 3
10506}
10507fn default_project_duration_months() -> u32 {
10508 4
10509}
10510
10511#[derive(Debug, Clone, Serialize, Deserialize)]
10513pub struct QualificationConfig {
10514 #[serde(default = "default_qualification_pass_rate")]
10516 pub pass_rate: f64,
10517 #[serde(default = "default_qualification_validity_days")]
10519 pub validity_days: u32,
10520 #[serde(default = "default_financial_weight")]
10522 pub financial_weight: f64,
10523 #[serde(default = "default_quality_weight")]
10525 pub quality_weight: f64,
10526 #[serde(default = "default_delivery_weight")]
10528 pub delivery_weight: f64,
10529 #[serde(default = "default_compliance_weight")]
10531 pub compliance_weight: f64,
10532}
10533
10534impl Default for QualificationConfig {
10535 fn default() -> Self {
10536 Self {
10537 pass_rate: default_qualification_pass_rate(),
10538 validity_days: default_qualification_validity_days(),
10539 financial_weight: default_financial_weight(),
10540 quality_weight: default_quality_weight(),
10541 delivery_weight: default_delivery_weight(),
10542 compliance_weight: default_compliance_weight(),
10543 }
10544 }
10545}
10546
10547fn default_qualification_pass_rate() -> f64 {
10548 0.75
10549}
10550fn default_qualification_validity_days() -> u32 {
10551 365
10552}
10553fn default_financial_weight() -> f64 {
10554 0.25
10555}
10556fn default_quality_weight() -> f64 {
10557 0.30
10558}
10559fn default_delivery_weight() -> f64 {
10560 0.25
10561}
10562fn default_compliance_weight() -> f64 {
10563 0.20
10564}
10565
10566#[derive(Debug, Clone, Serialize, Deserialize)]
10568pub struct RfxConfig {
10569 #[serde(default = "default_rfi_threshold")]
10571 pub rfi_threshold: f64,
10572 #[serde(default = "default_min_invited_vendors")]
10574 pub min_invited_vendors: u32,
10575 #[serde(default = "default_max_invited_vendors")]
10577 pub max_invited_vendors: u32,
10578 #[serde(default = "default_response_rate")]
10580 pub response_rate: f64,
10581 #[serde(default = "default_price_weight")]
10583 pub default_price_weight: f64,
10584 #[serde(default = "default_rfx_quality_weight")]
10586 pub default_quality_weight: f64,
10587 #[serde(default = "default_rfx_delivery_weight")]
10589 pub default_delivery_weight: f64,
10590}
10591
10592impl Default for RfxConfig {
10593 fn default() -> Self {
10594 Self {
10595 rfi_threshold: default_rfi_threshold(),
10596 min_invited_vendors: default_min_invited_vendors(),
10597 max_invited_vendors: default_max_invited_vendors(),
10598 response_rate: default_response_rate(),
10599 default_price_weight: default_price_weight(),
10600 default_quality_weight: default_rfx_quality_weight(),
10601 default_delivery_weight: default_rfx_delivery_weight(),
10602 }
10603 }
10604}
10605
10606fn default_rfi_threshold() -> f64 {
10607 100_000.0
10608}
10609fn default_min_invited_vendors() -> u32 {
10610 3
10611}
10612fn default_max_invited_vendors() -> u32 {
10613 8
10614}
10615fn default_response_rate() -> f64 {
10616 0.70
10617}
10618fn default_price_weight() -> f64 {
10619 0.40
10620}
10621fn default_rfx_quality_weight() -> f64 {
10622 0.35
10623}
10624fn default_rfx_delivery_weight() -> f64 {
10625 0.25
10626}
10627
10628#[derive(Debug, Clone, Serialize, Deserialize)]
10630pub struct ContractConfig {
10631 #[serde(default = "default_min_contract_months")]
10633 pub min_duration_months: u32,
10634 #[serde(default = "default_max_contract_months")]
10636 pub max_duration_months: u32,
10637 #[serde(default = "default_auto_renewal_rate")]
10639 pub auto_renewal_rate: f64,
10640 #[serde(default = "default_amendment_rate")]
10642 pub amendment_rate: f64,
10643 #[serde(default)]
10645 pub type_distribution: ContractTypeDistribution,
10646}
10647
10648impl Default for ContractConfig {
10649 fn default() -> Self {
10650 Self {
10651 min_duration_months: default_min_contract_months(),
10652 max_duration_months: default_max_contract_months(),
10653 auto_renewal_rate: default_auto_renewal_rate(),
10654 amendment_rate: default_amendment_rate(),
10655 type_distribution: ContractTypeDistribution::default(),
10656 }
10657 }
10658}
10659
10660fn default_min_contract_months() -> u32 {
10661 12
10662}
10663fn default_max_contract_months() -> u32 {
10664 36
10665}
10666fn default_auto_renewal_rate() -> f64 {
10667 0.40
10668}
10669fn default_amendment_rate() -> f64 {
10670 0.20
10671}
10672
10673#[derive(Debug, Clone, Serialize, Deserialize)]
10675pub struct ContractTypeDistribution {
10676 #[serde(default = "default_fixed_price_pct")]
10678 pub fixed_price: f64,
10679 #[serde(default = "default_blanket_pct")]
10681 pub blanket: f64,
10682 #[serde(default = "default_time_materials_pct")]
10684 pub time_and_materials: f64,
10685 #[serde(default = "default_service_agreement_pct")]
10687 pub service_agreement: f64,
10688}
10689
10690impl Default for ContractTypeDistribution {
10691 fn default() -> Self {
10692 Self {
10693 fixed_price: default_fixed_price_pct(),
10694 blanket: default_blanket_pct(),
10695 time_and_materials: default_time_materials_pct(),
10696 service_agreement: default_service_agreement_pct(),
10697 }
10698 }
10699}
10700
10701fn default_fixed_price_pct() -> f64 {
10702 0.40
10703}
10704fn default_blanket_pct() -> f64 {
10705 0.30
10706}
10707fn default_time_materials_pct() -> f64 {
10708 0.15
10709}
10710fn default_service_agreement_pct() -> f64 {
10711 0.15
10712}
10713
10714#[derive(Debug, Clone, Serialize, Deserialize)]
10716pub struct CatalogConfig {
10717 #[serde(default = "default_preferred_vendor_flag_rate")]
10719 pub preferred_vendor_flag_rate: f64,
10720 #[serde(default = "default_multi_source_rate")]
10722 pub multi_source_rate: f64,
10723}
10724
10725impl Default for CatalogConfig {
10726 fn default() -> Self {
10727 Self {
10728 preferred_vendor_flag_rate: default_preferred_vendor_flag_rate(),
10729 multi_source_rate: default_multi_source_rate(),
10730 }
10731 }
10732}
10733
10734fn default_preferred_vendor_flag_rate() -> f64 {
10735 0.70
10736}
10737fn default_multi_source_rate() -> f64 {
10738 0.25
10739}
10740
10741#[derive(Debug, Clone, Serialize, Deserialize)]
10743pub struct ScorecardConfig {
10744 #[serde(default = "default_scorecard_frequency")]
10746 pub frequency: String,
10747 #[serde(default = "default_otd_weight")]
10749 pub on_time_delivery_weight: f64,
10750 #[serde(default = "default_quality_score_weight")]
10752 pub quality_weight: f64,
10753 #[serde(default = "default_price_score_weight")]
10755 pub price_weight: f64,
10756 #[serde(default = "default_responsiveness_weight")]
10758 pub responsiveness_weight: f64,
10759 #[serde(default = "default_grade_a_threshold")]
10761 pub grade_a_threshold: f64,
10762 #[serde(default = "default_grade_b_threshold")]
10764 pub grade_b_threshold: f64,
10765 #[serde(default = "default_grade_c_threshold")]
10767 pub grade_c_threshold: f64,
10768}
10769
10770impl Default for ScorecardConfig {
10771 fn default() -> Self {
10772 Self {
10773 frequency: default_scorecard_frequency(),
10774 on_time_delivery_weight: default_otd_weight(),
10775 quality_weight: default_quality_score_weight(),
10776 price_weight: default_price_score_weight(),
10777 responsiveness_weight: default_responsiveness_weight(),
10778 grade_a_threshold: default_grade_a_threshold(),
10779 grade_b_threshold: default_grade_b_threshold(),
10780 grade_c_threshold: default_grade_c_threshold(),
10781 }
10782 }
10783}
10784
10785fn default_scorecard_frequency() -> String {
10786 "quarterly".to_string()
10787}
10788fn default_otd_weight() -> f64 {
10789 0.30
10790}
10791fn default_quality_score_weight() -> f64 {
10792 0.30
10793}
10794fn default_price_score_weight() -> f64 {
10795 0.25
10796}
10797fn default_responsiveness_weight() -> f64 {
10798 0.15
10799}
10800fn default_grade_a_threshold() -> f64 {
10801 90.0
10802}
10803fn default_grade_b_threshold() -> f64 {
10804 75.0
10805}
10806fn default_grade_c_threshold() -> f64 {
10807 60.0
10808}
10809
10810#[derive(Debug, Clone, Serialize, Deserialize)]
10812pub struct P2PIntegrationConfig {
10813 #[serde(default = "default_off_contract_rate")]
10815 pub off_contract_rate: f64,
10816 #[serde(default = "default_price_tolerance")]
10818 pub price_tolerance: f64,
10819 #[serde(default)]
10821 pub catalog_enforcement: bool,
10822}
10823
10824impl Default for P2PIntegrationConfig {
10825 fn default() -> Self {
10826 Self {
10827 off_contract_rate: default_off_contract_rate(),
10828 price_tolerance: default_price_tolerance(),
10829 catalog_enforcement: false,
10830 }
10831 }
10832}
10833
10834fn default_off_contract_rate() -> f64 {
10835 0.15
10836}
10837fn default_price_tolerance() -> f64 {
10838 0.02
10839}
10840
10841#[derive(Debug, Clone, Serialize, Deserialize)]
10845pub struct FinancialReportingConfig {
10846 #[serde(default)]
10848 pub enabled: bool,
10849 #[serde(default = "default_true")]
10851 pub generate_balance_sheet: bool,
10852 #[serde(default = "default_true")]
10854 pub generate_income_statement: bool,
10855 #[serde(default = "default_true")]
10857 pub generate_cash_flow: bool,
10858 #[serde(default = "default_true")]
10860 pub generate_changes_in_equity: bool,
10861 #[serde(default = "default_comparative_periods")]
10863 pub comparative_periods: u32,
10864 #[serde(default)]
10866 pub management_kpis: ManagementKpisConfig,
10867 #[serde(default)]
10869 pub budgets: BudgetConfig,
10870}
10871
10872impl Default for FinancialReportingConfig {
10873 fn default() -> Self {
10874 Self {
10875 enabled: false,
10876 generate_balance_sheet: true,
10877 generate_income_statement: true,
10878 generate_cash_flow: true,
10879 generate_changes_in_equity: true,
10880 comparative_periods: default_comparative_periods(),
10881 management_kpis: ManagementKpisConfig::default(),
10882 budgets: BudgetConfig::default(),
10883 }
10884 }
10885}
10886
10887fn default_comparative_periods() -> u32 {
10888 1
10889}
10890
10891#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10893pub struct ManagementKpisConfig {
10894 #[serde(default)]
10896 pub enabled: bool,
10897 #[serde(default = "default_kpi_frequency")]
10899 pub frequency: String,
10900}
10901
10902fn default_kpi_frequency() -> String {
10903 "monthly".to_string()
10904}
10905
10906#[derive(Debug, Clone, Serialize, Deserialize)]
10908pub struct BudgetConfig {
10909 #[serde(default)]
10911 pub enabled: bool,
10912 #[serde(default = "default_revenue_growth_rate")]
10914 pub revenue_growth_rate: f64,
10915 #[serde(default = "default_expense_inflation_rate")]
10917 pub expense_inflation_rate: f64,
10918 #[serde(default = "default_variance_noise")]
10920 pub variance_noise: f64,
10921}
10922
10923impl Default for BudgetConfig {
10924 fn default() -> Self {
10925 Self {
10926 enabled: false,
10927 revenue_growth_rate: default_revenue_growth_rate(),
10928 expense_inflation_rate: default_expense_inflation_rate(),
10929 variance_noise: default_variance_noise(),
10930 }
10931 }
10932}
10933
10934fn default_revenue_growth_rate() -> f64 {
10935 0.05
10936}
10937fn default_expense_inflation_rate() -> f64 {
10938 0.03
10939}
10940fn default_variance_noise() -> f64 {
10941 0.10
10942}
10943
10944#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10948pub struct HrConfig {
10949 #[serde(default)]
10951 pub enabled: bool,
10952 #[serde(default)]
10954 pub payroll: PayrollConfig,
10955 #[serde(default)]
10957 pub time_attendance: TimeAttendanceConfig,
10958 #[serde(default)]
10960 pub expenses: ExpenseConfig,
10961}
10962
10963#[derive(Debug, Clone, Serialize, Deserialize)]
10965pub struct PayrollConfig {
10966 #[serde(default = "default_true")]
10968 pub enabled: bool,
10969 #[serde(default = "default_pay_frequency")]
10971 pub pay_frequency: String,
10972 #[serde(default)]
10974 pub salary_ranges: PayrollSalaryRanges,
10975 #[serde(default)]
10977 pub tax_rates: PayrollTaxRates,
10978 #[serde(default = "default_benefits_enrollment_rate")]
10980 pub benefits_enrollment_rate: f64,
10981 #[serde(default = "default_retirement_participation_rate")]
10983 pub retirement_participation_rate: f64,
10984}
10985
10986impl Default for PayrollConfig {
10987 fn default() -> Self {
10988 Self {
10989 enabled: true,
10990 pay_frequency: default_pay_frequency(),
10991 salary_ranges: PayrollSalaryRanges::default(),
10992 tax_rates: PayrollTaxRates::default(),
10993 benefits_enrollment_rate: default_benefits_enrollment_rate(),
10994 retirement_participation_rate: default_retirement_participation_rate(),
10995 }
10996 }
10997}
10998
10999fn default_pay_frequency() -> String {
11000 "monthly".to_string()
11001}
11002fn default_benefits_enrollment_rate() -> f64 {
11003 0.60
11004}
11005fn default_retirement_participation_rate() -> f64 {
11006 0.45
11007}
11008
11009#[derive(Debug, Clone, Serialize, Deserialize)]
11011pub struct PayrollSalaryRanges {
11012 #[serde(default = "default_staff_min")]
11014 pub staff_min: f64,
11015 #[serde(default = "default_staff_max")]
11016 pub staff_max: f64,
11017 #[serde(default = "default_manager_min")]
11019 pub manager_min: f64,
11020 #[serde(default = "default_manager_max")]
11021 pub manager_max: f64,
11022 #[serde(default = "default_director_min")]
11024 pub director_min: f64,
11025 #[serde(default = "default_director_max")]
11026 pub director_max: f64,
11027 #[serde(default = "default_executive_min")]
11029 pub executive_min: f64,
11030 #[serde(default = "default_executive_max")]
11031 pub executive_max: f64,
11032}
11033
11034impl Default for PayrollSalaryRanges {
11035 fn default() -> Self {
11036 Self {
11037 staff_min: default_staff_min(),
11038 staff_max: default_staff_max(),
11039 manager_min: default_manager_min(),
11040 manager_max: default_manager_max(),
11041 director_min: default_director_min(),
11042 director_max: default_director_max(),
11043 executive_min: default_executive_min(),
11044 executive_max: default_executive_max(),
11045 }
11046 }
11047}
11048
11049fn default_staff_min() -> f64 {
11050 50_000.0
11051}
11052fn default_staff_max() -> f64 {
11053 70_000.0
11054}
11055fn default_manager_min() -> f64 {
11056 80_000.0
11057}
11058fn default_manager_max() -> f64 {
11059 120_000.0
11060}
11061fn default_director_min() -> f64 {
11062 120_000.0
11063}
11064fn default_director_max() -> f64 {
11065 180_000.0
11066}
11067fn default_executive_min() -> f64 {
11068 180_000.0
11069}
11070fn default_executive_max() -> f64 {
11071 350_000.0
11072}
11073
11074#[derive(Debug, Clone, Serialize, Deserialize)]
11076pub struct PayrollTaxRates {
11077 #[serde(default = "default_federal_rate")]
11079 pub federal_effective: f64,
11080 #[serde(default = "default_state_rate")]
11082 pub state_effective: f64,
11083 #[serde(default = "default_fica_rate")]
11085 pub fica: f64,
11086}
11087
11088impl Default for PayrollTaxRates {
11089 fn default() -> Self {
11090 Self {
11091 federal_effective: default_federal_rate(),
11092 state_effective: default_state_rate(),
11093 fica: default_fica_rate(),
11094 }
11095 }
11096}
11097
11098fn default_federal_rate() -> f64 {
11099 0.22
11100}
11101fn default_state_rate() -> f64 {
11102 0.05
11103}
11104fn default_fica_rate() -> f64 {
11105 0.0765
11106}
11107
11108#[derive(Debug, Clone, Serialize, Deserialize)]
11110pub struct TimeAttendanceConfig {
11111 #[serde(default = "default_true")]
11113 pub enabled: bool,
11114 #[serde(default = "default_overtime_rate")]
11116 pub overtime_rate: f64,
11117}
11118
11119impl Default for TimeAttendanceConfig {
11120 fn default() -> Self {
11121 Self {
11122 enabled: true,
11123 overtime_rate: default_overtime_rate(),
11124 }
11125 }
11126}
11127
11128fn default_overtime_rate() -> f64 {
11129 0.10
11130}
11131
11132#[derive(Debug, Clone, Serialize, Deserialize)]
11134pub struct ExpenseConfig {
11135 #[serde(default = "default_true")]
11137 pub enabled: bool,
11138 #[serde(default = "default_expense_submission_rate")]
11140 pub submission_rate: f64,
11141 #[serde(default = "default_policy_violation_rate")]
11143 pub policy_violation_rate: f64,
11144}
11145
11146impl Default for ExpenseConfig {
11147 fn default() -> Self {
11148 Self {
11149 enabled: true,
11150 submission_rate: default_expense_submission_rate(),
11151 policy_violation_rate: default_policy_violation_rate(),
11152 }
11153 }
11154}
11155
11156fn default_expense_submission_rate() -> f64 {
11157 0.30
11158}
11159fn default_policy_violation_rate() -> f64 {
11160 0.08
11161}
11162
11163#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11167pub struct ManufacturingProcessConfig {
11168 #[serde(default)]
11170 pub enabled: bool,
11171 #[serde(default)]
11173 pub production_orders: ProductionOrderConfig,
11174 #[serde(default)]
11176 pub costing: ManufacturingCostingConfig,
11177 #[serde(default)]
11179 pub routing: RoutingConfig,
11180}
11181
11182#[derive(Debug, Clone, Serialize, Deserialize)]
11184pub struct ProductionOrderConfig {
11185 #[serde(default = "default_prod_orders_per_month")]
11187 pub orders_per_month: u32,
11188 #[serde(default = "default_prod_avg_batch_size")]
11190 pub avg_batch_size: u32,
11191 #[serde(default = "default_prod_yield_rate")]
11193 pub yield_rate: f64,
11194 #[serde(default = "default_prod_make_to_order_rate")]
11196 pub make_to_order_rate: f64,
11197 #[serde(default = "default_prod_rework_rate")]
11199 pub rework_rate: f64,
11200}
11201
11202impl Default for ProductionOrderConfig {
11203 fn default() -> Self {
11204 Self {
11205 orders_per_month: default_prod_orders_per_month(),
11206 avg_batch_size: default_prod_avg_batch_size(),
11207 yield_rate: default_prod_yield_rate(),
11208 make_to_order_rate: default_prod_make_to_order_rate(),
11209 rework_rate: default_prod_rework_rate(),
11210 }
11211 }
11212}
11213
11214fn default_prod_orders_per_month() -> u32 {
11215 50
11216}
11217fn default_prod_avg_batch_size() -> u32 {
11218 100
11219}
11220fn default_prod_yield_rate() -> f64 {
11221 0.97
11222}
11223fn default_prod_make_to_order_rate() -> f64 {
11224 0.20
11225}
11226fn default_prod_rework_rate() -> f64 {
11227 0.03
11228}
11229
11230#[derive(Debug, Clone, Serialize, Deserialize)]
11232pub struct ManufacturingCostingConfig {
11233 #[serde(default = "default_labor_rate")]
11235 pub labor_rate_per_hour: f64,
11236 #[serde(default = "default_overhead_rate")]
11238 pub overhead_rate: f64,
11239 #[serde(default = "default_cost_update_frequency")]
11241 pub standard_cost_update_frequency: String,
11242}
11243
11244impl Default for ManufacturingCostingConfig {
11245 fn default() -> Self {
11246 Self {
11247 labor_rate_per_hour: default_labor_rate(),
11248 overhead_rate: default_overhead_rate(),
11249 standard_cost_update_frequency: default_cost_update_frequency(),
11250 }
11251 }
11252}
11253
11254fn default_labor_rate() -> f64 {
11255 35.0
11256}
11257fn default_overhead_rate() -> f64 {
11258 1.50
11259}
11260fn default_cost_update_frequency() -> String {
11261 "quarterly".to_string()
11262}
11263
11264#[derive(Debug, Clone, Serialize, Deserialize)]
11266pub struct RoutingConfig {
11267 #[serde(default = "default_avg_operations")]
11269 pub avg_operations: u32,
11270 #[serde(default = "default_setup_time")]
11272 pub setup_time_hours: f64,
11273 #[serde(default = "default_run_time_variation")]
11275 pub run_time_variation: f64,
11276}
11277
11278impl Default for RoutingConfig {
11279 fn default() -> Self {
11280 Self {
11281 avg_operations: default_avg_operations(),
11282 setup_time_hours: default_setup_time(),
11283 run_time_variation: default_run_time_variation(),
11284 }
11285 }
11286}
11287
11288fn default_avg_operations() -> u32 {
11289 4
11290}
11291fn default_setup_time() -> f64 {
11292 1.5
11293}
11294fn default_run_time_variation() -> f64 {
11295 0.15
11296}
11297
11298#[derive(Debug, Clone, Serialize, Deserialize)]
11302pub struct SalesQuoteConfig {
11303 #[serde(default)]
11305 pub enabled: bool,
11306 #[serde(default = "default_quotes_per_month")]
11308 pub quotes_per_month: u32,
11309 #[serde(default = "default_quote_win_rate")]
11311 pub win_rate: f64,
11312 #[serde(default = "default_quote_validity_days")]
11314 pub validity_days: u32,
11315}
11316
11317impl Default for SalesQuoteConfig {
11318 fn default() -> Self {
11319 Self {
11320 enabled: false,
11321 quotes_per_month: default_quotes_per_month(),
11322 win_rate: default_quote_win_rate(),
11323 validity_days: default_quote_validity_days(),
11324 }
11325 }
11326}
11327
11328fn default_quotes_per_month() -> u32 {
11329 30
11330}
11331fn default_quote_win_rate() -> f64 {
11332 0.35
11333}
11334fn default_quote_validity_days() -> u32 {
11335 30
11336}
11337
11338#[derive(Debug, Clone, Serialize, Deserialize)]
11347pub struct TaxConfig {
11348 #[serde(default)]
11350 pub enabled: bool,
11351 #[serde(default)]
11353 pub jurisdictions: TaxJurisdictionConfig,
11354 #[serde(default)]
11356 pub vat_gst: VatGstConfig,
11357 #[serde(default)]
11359 pub sales_tax: SalesTaxConfig,
11360 #[serde(default)]
11362 pub withholding: WithholdingTaxSchemaConfig,
11363 #[serde(default)]
11365 pub provisions: TaxProvisionSchemaConfig,
11366 #[serde(default)]
11368 pub payroll_tax: PayrollTaxSchemaConfig,
11369 #[serde(default = "default_tax_anomaly_rate")]
11371 pub anomaly_rate: f64,
11372}
11373
11374fn default_tax_anomaly_rate() -> f64 {
11375 0.03
11376}
11377
11378impl Default for TaxConfig {
11379 fn default() -> Self {
11380 Self {
11381 enabled: false,
11382 jurisdictions: TaxJurisdictionConfig::default(),
11383 vat_gst: VatGstConfig::default(),
11384 sales_tax: SalesTaxConfig::default(),
11385 withholding: WithholdingTaxSchemaConfig::default(),
11386 provisions: TaxProvisionSchemaConfig::default(),
11387 payroll_tax: PayrollTaxSchemaConfig::default(),
11388 anomaly_rate: default_tax_anomaly_rate(),
11389 }
11390 }
11391}
11392
11393#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11398pub struct TaxJurisdictionConfig {
11399 #[serde(default)]
11401 pub countries: Vec<String>,
11402 #[serde(default)]
11404 pub include_subnational: bool,
11405}
11406
11407#[derive(Debug, Clone, Serialize, Deserialize)]
11412pub struct VatGstConfig {
11413 #[serde(default)]
11415 pub enabled: bool,
11416 #[serde(default)]
11418 pub standard_rates: std::collections::HashMap<String, f64>,
11419 #[serde(default)]
11421 pub reduced_rates: std::collections::HashMap<String, f64>,
11422 #[serde(default)]
11424 pub exempt_categories: Vec<String>,
11425 #[serde(default = "default_true")]
11427 pub reverse_charge: bool,
11428}
11429
11430impl Default for VatGstConfig {
11431 fn default() -> Self {
11432 Self {
11433 enabled: false,
11434 standard_rates: std::collections::HashMap::new(),
11435 reduced_rates: std::collections::HashMap::new(),
11436 exempt_categories: Vec::new(),
11437 reverse_charge: true,
11438 }
11439 }
11440}
11441
11442#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11446pub struct SalesTaxConfig {
11447 #[serde(default)]
11449 pub enabled: bool,
11450 #[serde(default)]
11452 pub nexus_states: Vec<String>,
11453}
11454
11455#[derive(Debug, Clone, Serialize, Deserialize)]
11460pub struct WithholdingTaxSchemaConfig {
11461 #[serde(default)]
11463 pub enabled: bool,
11464 #[serde(default = "default_true")]
11466 pub treaty_network: bool,
11467 #[serde(default = "default_withholding_rate")]
11469 pub default_rate: f64,
11470 #[serde(default = "default_treaty_reduced_rate")]
11472 pub treaty_reduced_rate: f64,
11473}
11474
11475fn default_withholding_rate() -> f64 {
11476 0.30
11477}
11478
11479fn default_treaty_reduced_rate() -> f64 {
11480 0.15
11481}
11482
11483impl Default for WithholdingTaxSchemaConfig {
11484 fn default() -> Self {
11485 Self {
11486 enabled: false,
11487 treaty_network: true,
11488 default_rate: default_withholding_rate(),
11489 treaty_reduced_rate: default_treaty_reduced_rate(),
11490 }
11491 }
11492}
11493
11494#[derive(Debug, Clone, Serialize, Deserialize)]
11499pub struct TaxProvisionSchemaConfig {
11500 #[serde(default = "default_true")]
11503 pub enabled: bool,
11504 #[serde(default = "default_statutory_rate")]
11506 pub statutory_rate: f64,
11507 #[serde(default = "default_true")]
11509 pub uncertain_positions: bool,
11510}
11511
11512fn default_statutory_rate() -> f64 {
11513 0.21
11514}
11515
11516impl Default for TaxProvisionSchemaConfig {
11517 fn default() -> Self {
11518 Self {
11519 enabled: true,
11520 statutory_rate: default_statutory_rate(),
11521 uncertain_positions: true,
11522 }
11523 }
11524}
11525
11526#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11531pub struct PayrollTaxSchemaConfig {
11532 #[serde(default)]
11534 pub enabled: bool,
11535}
11536
11537#[derive(Debug, Clone, Serialize, Deserialize)]
11547pub struct TreasuryConfig {
11548 #[serde(default)]
11550 pub enabled: bool,
11551 #[serde(default)]
11553 pub cash_positioning: CashPositioningConfig,
11554 #[serde(default)]
11556 pub cash_forecasting: CashForecastingConfig,
11557 #[serde(default)]
11559 pub cash_pooling: CashPoolingConfig,
11560 #[serde(default)]
11562 pub hedging: HedgingSchemaConfig,
11563 #[serde(default)]
11565 pub debt: DebtSchemaConfig,
11566 #[serde(default)]
11568 pub netting: NettingSchemaConfig,
11569 #[serde(default)]
11571 pub bank_guarantees: BankGuaranteeSchemaConfig,
11572 #[serde(default = "default_treasury_anomaly_rate")]
11574 pub anomaly_rate: f64,
11575}
11576
11577fn default_treasury_anomaly_rate() -> f64 {
11578 0.02
11579}
11580
11581impl Default for TreasuryConfig {
11582 fn default() -> Self {
11583 Self {
11584 enabled: false,
11585 cash_positioning: CashPositioningConfig::default(),
11586 cash_forecasting: CashForecastingConfig::default(),
11587 cash_pooling: CashPoolingConfig::default(),
11588 hedging: HedgingSchemaConfig::default(),
11589 debt: DebtSchemaConfig::default(),
11590 netting: NettingSchemaConfig::default(),
11591 bank_guarantees: BankGuaranteeSchemaConfig::default(),
11592 anomaly_rate: default_treasury_anomaly_rate(),
11593 }
11594 }
11595}
11596
11597#[derive(Debug, Clone, Serialize, Deserialize)]
11601pub struct CashPositioningConfig {
11602 #[serde(default = "default_true")]
11604 pub enabled: bool,
11605 #[serde(default = "default_cash_frequency")]
11607 pub frequency: String,
11608 #[serde(default = "default_minimum_balance_policy")]
11610 pub minimum_balance_policy: f64,
11611}
11612
11613fn default_cash_frequency() -> String {
11614 "daily".to_string()
11615}
11616
11617fn default_minimum_balance_policy() -> f64 {
11618 100_000.0
11619}
11620
11621impl Default for CashPositioningConfig {
11622 fn default() -> Self {
11623 Self {
11624 enabled: true,
11625 frequency: default_cash_frequency(),
11626 minimum_balance_policy: default_minimum_balance_policy(),
11627 }
11628 }
11629}
11630
11631#[derive(Debug, Clone, Serialize, Deserialize)]
11635pub struct CashForecastingConfig {
11636 #[serde(default = "default_true")]
11638 pub enabled: bool,
11639 #[serde(default = "default_horizon_days")]
11641 pub horizon_days: u32,
11642 #[serde(default = "default_ar_probability_curve")]
11644 pub ar_collection_probability_curve: String,
11645 #[serde(default = "default_confidence_interval")]
11647 pub confidence_interval: f64,
11648}
11649
11650fn default_horizon_days() -> u32 {
11651 90
11652}
11653
11654fn default_ar_probability_curve() -> String {
11655 "aging".to_string()
11656}
11657
11658fn default_confidence_interval() -> f64 {
11659 0.90
11660}
11661
11662impl Default for CashForecastingConfig {
11663 fn default() -> Self {
11664 Self {
11665 enabled: true,
11666 horizon_days: default_horizon_days(),
11667 ar_collection_probability_curve: default_ar_probability_curve(),
11668 confidence_interval: default_confidence_interval(),
11669 }
11670 }
11671}
11672
11673#[derive(Debug, Clone, Serialize, Deserialize)]
11677pub struct CashPoolingConfig {
11678 #[serde(default)]
11680 pub enabled: bool,
11681 #[serde(default = "default_pool_type")]
11683 pub pool_type: String,
11684 #[serde(default = "default_sweep_time")]
11686 pub sweep_time: String,
11687}
11688
11689fn default_pool_type() -> String {
11690 "zero_balancing".to_string()
11691}
11692
11693fn default_sweep_time() -> String {
11694 "16:00".to_string()
11695}
11696
11697impl Default for CashPoolingConfig {
11698 fn default() -> Self {
11699 Self {
11700 enabled: false,
11701 pool_type: default_pool_type(),
11702 sweep_time: default_sweep_time(),
11703 }
11704 }
11705}
11706
11707#[derive(Debug, Clone, Serialize, Deserialize)]
11712pub struct HedgingSchemaConfig {
11713 #[serde(default)]
11715 pub enabled: bool,
11716 #[serde(default = "default_hedge_ratio")]
11718 pub hedge_ratio: f64,
11719 #[serde(default = "default_hedge_instruments")]
11721 pub instruments: Vec<String>,
11722 #[serde(default = "default_true")]
11724 pub hedge_accounting: bool,
11725 #[serde(default = "default_effectiveness_method")]
11727 pub effectiveness_method: String,
11728}
11729
11730fn default_hedge_ratio() -> f64 {
11731 0.75
11732}
11733
11734fn default_hedge_instruments() -> Vec<String> {
11735 vec!["fx_forward".to_string(), "interest_rate_swap".to_string()]
11736}
11737
11738fn default_effectiveness_method() -> String {
11739 "regression".to_string()
11740}
11741
11742impl Default for HedgingSchemaConfig {
11743 fn default() -> Self {
11744 Self {
11745 enabled: false,
11746 hedge_ratio: default_hedge_ratio(),
11747 instruments: default_hedge_instruments(),
11748 hedge_accounting: true,
11749 effectiveness_method: default_effectiveness_method(),
11750 }
11751 }
11752}
11753
11754#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11759pub struct DebtSchemaConfig {
11760 #[serde(default)]
11762 pub enabled: bool,
11763 #[serde(default)]
11765 pub instruments: Vec<DebtInstrumentDef>,
11766 #[serde(default)]
11768 pub covenants: Vec<CovenantDef>,
11769}
11770
11771#[derive(Debug, Clone, Serialize, Deserialize)]
11773pub struct DebtInstrumentDef {
11774 #[serde(rename = "type")]
11776 pub instrument_type: String,
11777 #[serde(default)]
11779 pub principal: Option<f64>,
11780 #[serde(default)]
11782 pub rate: Option<f64>,
11783 #[serde(default)]
11785 pub maturity_months: Option<u32>,
11786 #[serde(default)]
11788 pub facility: Option<f64>,
11789}
11790
11791#[derive(Debug, Clone, Serialize, Deserialize)]
11793pub struct CovenantDef {
11794 #[serde(rename = "type")]
11797 pub covenant_type: String,
11798 pub threshold: f64,
11800}
11801
11802#[derive(Debug, Clone, Serialize, Deserialize)]
11806pub struct NettingSchemaConfig {
11807 #[serde(default)]
11809 pub enabled: bool,
11810 #[serde(default = "default_netting_cycle")]
11812 pub cycle: String,
11813}
11814
11815fn default_netting_cycle() -> String {
11816 "monthly".to_string()
11817}
11818
11819impl Default for NettingSchemaConfig {
11820 fn default() -> Self {
11821 Self {
11822 enabled: false,
11823 cycle: default_netting_cycle(),
11824 }
11825 }
11826}
11827
11828#[derive(Debug, Clone, Serialize, Deserialize)]
11832pub struct BankGuaranteeSchemaConfig {
11833 #[serde(default)]
11835 pub enabled: bool,
11836 #[serde(default = "default_guarantee_count")]
11838 pub count: u32,
11839}
11840
11841fn default_guarantee_count() -> u32 {
11842 5
11843}
11844
11845impl Default for BankGuaranteeSchemaConfig {
11846 fn default() -> Self {
11847 Self {
11848 enabled: false,
11849 count: default_guarantee_count(),
11850 }
11851 }
11852}
11853
11854#[derive(Debug, Clone, Serialize, Deserialize)]
11863pub struct ProjectAccountingConfig {
11864 #[serde(default)]
11866 pub enabled: bool,
11867 #[serde(default = "default_project_count")]
11869 pub project_count: u32,
11870 #[serde(default)]
11872 pub project_types: ProjectTypeDistribution,
11873 #[serde(default)]
11875 pub wbs: WbsSchemaConfig,
11876 #[serde(default)]
11878 pub cost_allocation: CostAllocationConfig,
11879 #[serde(default)]
11881 pub revenue_recognition: ProjectRevenueRecognitionConfig,
11882 #[serde(default)]
11884 pub milestones: MilestoneSchemaConfig,
11885 #[serde(default)]
11887 pub change_orders: ChangeOrderSchemaConfig,
11888 #[serde(default)]
11890 pub retainage: RetainageSchemaConfig,
11891 #[serde(default)]
11893 pub earned_value: EarnedValueSchemaConfig,
11894 #[serde(default = "default_project_anomaly_rate")]
11896 pub anomaly_rate: f64,
11897}
11898
11899fn default_project_count() -> u32 {
11900 10
11901}
11902
11903fn default_project_anomaly_rate() -> f64 {
11904 0.03
11905}
11906
11907impl Default for ProjectAccountingConfig {
11908 fn default() -> Self {
11909 Self {
11910 enabled: false,
11911 project_count: default_project_count(),
11912 project_types: ProjectTypeDistribution::default(),
11913 wbs: WbsSchemaConfig::default(),
11914 cost_allocation: CostAllocationConfig::default(),
11915 revenue_recognition: ProjectRevenueRecognitionConfig::default(),
11916 milestones: MilestoneSchemaConfig::default(),
11917 change_orders: ChangeOrderSchemaConfig::default(),
11918 retainage: RetainageSchemaConfig::default(),
11919 earned_value: EarnedValueSchemaConfig::default(),
11920 anomaly_rate: default_project_anomaly_rate(),
11921 }
11922 }
11923}
11924
11925#[derive(Debug, Clone, Serialize, Deserialize)]
11927pub struct ProjectTypeDistribution {
11928 #[serde(default = "default_capital_weight")]
11930 pub capital: f64,
11931 #[serde(default = "default_internal_weight")]
11933 pub internal: f64,
11934 #[serde(default = "default_customer_weight")]
11936 pub customer: f64,
11937 #[serde(default = "default_rnd_weight")]
11939 pub r_and_d: f64,
11940 #[serde(default = "default_maintenance_weight")]
11942 pub maintenance: f64,
11943 #[serde(default = "default_technology_weight")]
11945 pub technology: f64,
11946}
11947
11948fn default_capital_weight() -> f64 {
11949 0.25
11950}
11951fn default_internal_weight() -> f64 {
11952 0.20
11953}
11954fn default_customer_weight() -> f64 {
11955 0.30
11956}
11957fn default_rnd_weight() -> f64 {
11958 0.10
11959}
11960fn default_maintenance_weight() -> f64 {
11961 0.10
11962}
11963fn default_technology_weight() -> f64 {
11964 0.05
11965}
11966
11967impl Default for ProjectTypeDistribution {
11968 fn default() -> Self {
11969 Self {
11970 capital: default_capital_weight(),
11971 internal: default_internal_weight(),
11972 customer: default_customer_weight(),
11973 r_and_d: default_rnd_weight(),
11974 maintenance: default_maintenance_weight(),
11975 technology: default_technology_weight(),
11976 }
11977 }
11978}
11979
11980#[derive(Debug, Clone, Serialize, Deserialize)]
11982pub struct WbsSchemaConfig {
11983 #[serde(default = "default_wbs_max_depth")]
11985 pub max_depth: u32,
11986 #[serde(default = "default_wbs_min_elements")]
11988 pub min_elements_per_level: u32,
11989 #[serde(default = "default_wbs_max_elements")]
11991 pub max_elements_per_level: u32,
11992}
11993
11994fn default_wbs_max_depth() -> u32 {
11995 3
11996}
11997fn default_wbs_min_elements() -> u32 {
11998 2
11999}
12000fn default_wbs_max_elements() -> u32 {
12001 6
12002}
12003
12004impl Default for WbsSchemaConfig {
12005 fn default() -> Self {
12006 Self {
12007 max_depth: default_wbs_max_depth(),
12008 min_elements_per_level: default_wbs_min_elements(),
12009 max_elements_per_level: default_wbs_max_elements(),
12010 }
12011 }
12012}
12013
12014#[derive(Debug, Clone, Serialize, Deserialize)]
12016pub struct CostAllocationConfig {
12017 #[serde(default = "default_time_entry_rate")]
12019 pub time_entry_project_rate: f64,
12020 #[serde(default = "default_expense_rate")]
12022 pub expense_project_rate: f64,
12023 #[serde(default = "default_po_rate")]
12025 pub purchase_order_project_rate: f64,
12026 #[serde(default = "default_vi_rate")]
12028 pub vendor_invoice_project_rate: f64,
12029}
12030
12031fn default_time_entry_rate() -> f64 {
12032 0.60
12033}
12034fn default_expense_rate() -> f64 {
12035 0.30
12036}
12037fn default_po_rate() -> f64 {
12038 0.40
12039}
12040fn default_vi_rate() -> f64 {
12041 0.35
12042}
12043
12044impl Default for CostAllocationConfig {
12045 fn default() -> Self {
12046 Self {
12047 time_entry_project_rate: default_time_entry_rate(),
12048 expense_project_rate: default_expense_rate(),
12049 purchase_order_project_rate: default_po_rate(),
12050 vendor_invoice_project_rate: default_vi_rate(),
12051 }
12052 }
12053}
12054
12055#[derive(Debug, Clone, Serialize, Deserialize)]
12057pub struct ProjectRevenueRecognitionConfig {
12058 #[serde(default = "default_true")]
12060 pub enabled: bool,
12061 #[serde(default = "default_revenue_method")]
12063 pub method: String,
12064 #[serde(default = "default_completion_measure")]
12066 pub completion_measure: String,
12067 #[serde(default = "default_avg_contract_value")]
12069 pub avg_contract_value: f64,
12070}
12071
12072fn default_revenue_method() -> String {
12073 "percentage_of_completion".to_string()
12074}
12075fn default_completion_measure() -> String {
12076 "cost_to_cost".to_string()
12077}
12078fn default_avg_contract_value() -> f64 {
12079 500_000.0
12080}
12081
12082impl Default for ProjectRevenueRecognitionConfig {
12083 fn default() -> Self {
12084 Self {
12085 enabled: true,
12086 method: default_revenue_method(),
12087 completion_measure: default_completion_measure(),
12088 avg_contract_value: default_avg_contract_value(),
12089 }
12090 }
12091}
12092
12093#[derive(Debug, Clone, Serialize, Deserialize)]
12095pub struct MilestoneSchemaConfig {
12096 #[serde(default = "default_true")]
12098 pub enabled: bool,
12099 #[serde(default = "default_milestones_per_project")]
12101 pub avg_per_project: u32,
12102 #[serde(default = "default_payment_milestone_rate")]
12104 pub payment_milestone_rate: f64,
12105}
12106
12107fn default_milestones_per_project() -> u32 {
12108 4
12109}
12110fn default_payment_milestone_rate() -> f64 {
12111 0.50
12112}
12113
12114impl Default for MilestoneSchemaConfig {
12115 fn default() -> Self {
12116 Self {
12117 enabled: true,
12118 avg_per_project: default_milestones_per_project(),
12119 payment_milestone_rate: default_payment_milestone_rate(),
12120 }
12121 }
12122}
12123
12124#[derive(Debug, Clone, Serialize, Deserialize)]
12126pub struct ChangeOrderSchemaConfig {
12127 #[serde(default = "default_true")]
12129 pub enabled: bool,
12130 #[serde(default = "default_change_order_probability")]
12132 pub probability: f64,
12133 #[serde(default = "default_max_change_orders")]
12135 pub max_per_project: u32,
12136 #[serde(default = "default_change_order_approval_rate")]
12138 pub approval_rate: f64,
12139}
12140
12141fn default_change_order_probability() -> f64 {
12142 0.40
12143}
12144fn default_max_change_orders() -> u32 {
12145 3
12146}
12147fn default_change_order_approval_rate() -> f64 {
12148 0.75
12149}
12150
12151impl Default for ChangeOrderSchemaConfig {
12152 fn default() -> Self {
12153 Self {
12154 enabled: true,
12155 probability: default_change_order_probability(),
12156 max_per_project: default_max_change_orders(),
12157 approval_rate: default_change_order_approval_rate(),
12158 }
12159 }
12160}
12161
12162#[derive(Debug, Clone, Serialize, Deserialize)]
12164pub struct RetainageSchemaConfig {
12165 #[serde(default)]
12167 pub enabled: bool,
12168 #[serde(default = "default_retainage_pct")]
12170 pub default_percentage: f64,
12171}
12172
12173fn default_retainage_pct() -> f64 {
12174 0.10
12175}
12176
12177impl Default for RetainageSchemaConfig {
12178 fn default() -> Self {
12179 Self {
12180 enabled: false,
12181 default_percentage: default_retainage_pct(),
12182 }
12183 }
12184}
12185
12186#[derive(Debug, Clone, Serialize, Deserialize)]
12188pub struct EarnedValueSchemaConfig {
12189 #[serde(default = "default_true")]
12191 pub enabled: bool,
12192 #[serde(default = "default_evm_frequency")]
12194 pub frequency: String,
12195}
12196
12197fn default_evm_frequency() -> String {
12198 "monthly".to_string()
12199}
12200
12201impl Default for EarnedValueSchemaConfig {
12202 fn default() -> Self {
12203 Self {
12204 enabled: true,
12205 frequency: default_evm_frequency(),
12206 }
12207 }
12208}
12209
12210#[derive(Debug, Clone, Serialize, Deserialize)]
12216pub struct EsgConfig {
12217 #[serde(default)]
12219 pub enabled: bool,
12220 #[serde(default)]
12222 pub environmental: EnvironmentalConfig,
12223 #[serde(default)]
12225 pub social: SocialConfig,
12226 #[serde(default)]
12228 pub governance: GovernanceSchemaConfig,
12229 #[serde(default)]
12231 pub supply_chain_esg: SupplyChainEsgConfig,
12232 #[serde(default)]
12234 pub reporting: EsgReportingConfig,
12235 #[serde(default)]
12237 pub climate_scenarios: ClimateScenarioConfig,
12238 #[serde(default = "default_esg_anomaly_rate")]
12240 pub anomaly_rate: f64,
12241}
12242
12243fn default_esg_anomaly_rate() -> f64 {
12244 0.02
12245}
12246
12247impl Default for EsgConfig {
12248 fn default() -> Self {
12249 Self {
12250 enabled: false,
12251 environmental: EnvironmentalConfig::default(),
12252 social: SocialConfig::default(),
12253 governance: GovernanceSchemaConfig::default(),
12254 supply_chain_esg: SupplyChainEsgConfig::default(),
12255 reporting: EsgReportingConfig::default(),
12256 climate_scenarios: ClimateScenarioConfig::default(),
12257 anomaly_rate: default_esg_anomaly_rate(),
12258 }
12259 }
12260}
12261
12262#[derive(Debug, Clone, Serialize, Deserialize, Default)]
12267pub struct CountryPacksSchemaConfig {
12268 #[serde(default)]
12270 pub external_dir: Option<PathBuf>,
12271 #[serde(default)]
12275 pub overrides: std::collections::HashMap<String, serde_json::Value>,
12276}
12277
12278#[derive(Debug, Clone, Serialize, Deserialize)]
12280pub struct EnvironmentalConfig {
12281 #[serde(default = "default_true")]
12283 pub enabled: bool,
12284 #[serde(default)]
12286 pub scope1: EmissionScopeConfig,
12287 #[serde(default)]
12289 pub scope2: EmissionScopeConfig,
12290 #[serde(default)]
12292 pub scope3: Scope3Config,
12293 #[serde(default)]
12295 pub energy: EnergySchemaConfig,
12296 #[serde(default)]
12298 pub water: WaterSchemaConfig,
12299 #[serde(default)]
12301 pub waste: WasteSchemaConfig,
12302}
12303
12304impl Default for EnvironmentalConfig {
12305 fn default() -> Self {
12306 Self {
12307 enabled: true,
12308 scope1: EmissionScopeConfig::default(),
12309 scope2: EmissionScopeConfig::default(),
12310 scope3: Scope3Config::default(),
12311 energy: EnergySchemaConfig::default(),
12312 water: WaterSchemaConfig::default(),
12313 waste: WasteSchemaConfig::default(),
12314 }
12315 }
12316}
12317
12318#[derive(Debug, Clone, Serialize, Deserialize)]
12320pub struct EmissionScopeConfig {
12321 #[serde(default = "default_true")]
12323 pub enabled: bool,
12324 #[serde(default = "default_emission_region")]
12326 pub factor_region: String,
12327}
12328
12329fn default_emission_region() -> String {
12330 "US".to_string()
12331}
12332
12333impl Default for EmissionScopeConfig {
12334 fn default() -> Self {
12335 Self {
12336 enabled: true,
12337 factor_region: default_emission_region(),
12338 }
12339 }
12340}
12341
12342#[derive(Debug, Clone, Serialize, Deserialize)]
12344pub struct Scope3Config {
12345 #[serde(default = "default_true")]
12347 pub enabled: bool,
12348 #[serde(default = "default_scope3_categories")]
12350 pub categories: Vec<String>,
12351 #[serde(default = "default_spend_intensity")]
12353 pub default_spend_intensity_kg_per_usd: f64,
12354}
12355
12356fn default_scope3_categories() -> Vec<String> {
12357 vec![
12358 "purchased_goods".to_string(),
12359 "business_travel".to_string(),
12360 "employee_commuting".to_string(),
12361 ]
12362}
12363
12364fn default_spend_intensity() -> f64 {
12365 0.5
12366}
12367
12368impl Default for Scope3Config {
12369 fn default() -> Self {
12370 Self {
12371 enabled: true,
12372 categories: default_scope3_categories(),
12373 default_spend_intensity_kg_per_usd: default_spend_intensity(),
12374 }
12375 }
12376}
12377
12378#[derive(Debug, Clone, Serialize, Deserialize)]
12380pub struct EnergySchemaConfig {
12381 #[serde(default = "default_true")]
12383 pub enabled: bool,
12384 #[serde(default = "default_facility_count")]
12386 pub facility_count: u32,
12387 #[serde(default = "default_renewable_target")]
12389 pub renewable_target: f64,
12390}
12391
12392fn default_facility_count() -> u32 {
12393 5
12394}
12395
12396fn default_renewable_target() -> f64 {
12397 0.30
12398}
12399
12400impl Default for EnergySchemaConfig {
12401 fn default() -> Self {
12402 Self {
12403 enabled: true,
12404 facility_count: default_facility_count(),
12405 renewable_target: default_renewable_target(),
12406 }
12407 }
12408}
12409
12410#[derive(Debug, Clone, Serialize, Deserialize)]
12412pub struct WaterSchemaConfig {
12413 #[serde(default = "default_true")]
12415 pub enabled: bool,
12416 #[serde(default = "default_water_facility_count")]
12418 pub facility_count: u32,
12419}
12420
12421fn default_water_facility_count() -> u32 {
12422 3
12423}
12424
12425impl Default for WaterSchemaConfig {
12426 fn default() -> Self {
12427 Self {
12428 enabled: true,
12429 facility_count: default_water_facility_count(),
12430 }
12431 }
12432}
12433
12434#[derive(Debug, Clone, Serialize, Deserialize)]
12436pub struct WasteSchemaConfig {
12437 #[serde(default = "default_true")]
12439 pub enabled: bool,
12440 #[serde(default = "default_diversion_target")]
12442 pub diversion_target: f64,
12443}
12444
12445fn default_diversion_target() -> f64 {
12446 0.50
12447}
12448
12449impl Default for WasteSchemaConfig {
12450 fn default() -> Self {
12451 Self {
12452 enabled: true,
12453 diversion_target: default_diversion_target(),
12454 }
12455 }
12456}
12457
12458#[derive(Debug, Clone, Serialize, Deserialize)]
12460pub struct SocialConfig {
12461 #[serde(default = "default_true")]
12463 pub enabled: bool,
12464 #[serde(default)]
12466 pub diversity: DiversitySchemaConfig,
12467 #[serde(default)]
12469 pub pay_equity: PayEquitySchemaConfig,
12470 #[serde(default)]
12472 pub safety: SafetySchemaConfig,
12473}
12474
12475impl Default for SocialConfig {
12476 fn default() -> Self {
12477 Self {
12478 enabled: true,
12479 diversity: DiversitySchemaConfig::default(),
12480 pay_equity: PayEquitySchemaConfig::default(),
12481 safety: SafetySchemaConfig::default(),
12482 }
12483 }
12484}
12485
12486#[derive(Debug, Clone, Serialize, Deserialize)]
12488pub struct DiversitySchemaConfig {
12489 #[serde(default = "default_true")]
12491 pub enabled: bool,
12492 #[serde(default = "default_diversity_dimensions")]
12494 pub dimensions: Vec<String>,
12495}
12496
12497fn default_diversity_dimensions() -> Vec<String> {
12498 vec![
12499 "gender".to_string(),
12500 "ethnicity".to_string(),
12501 "age_group".to_string(),
12502 ]
12503}
12504
12505impl Default for DiversitySchemaConfig {
12506 fn default() -> Self {
12507 Self {
12508 enabled: true,
12509 dimensions: default_diversity_dimensions(),
12510 }
12511 }
12512}
12513
12514#[derive(Debug, Clone, Serialize, Deserialize)]
12516pub struct PayEquitySchemaConfig {
12517 #[serde(default = "default_true")]
12519 pub enabled: bool,
12520 #[serde(default = "default_pay_gap_threshold")]
12522 pub gap_threshold: f64,
12523}
12524
12525fn default_pay_gap_threshold() -> f64 {
12526 0.05
12527}
12528
12529impl Default for PayEquitySchemaConfig {
12530 fn default() -> Self {
12531 Self {
12532 enabled: true,
12533 gap_threshold: default_pay_gap_threshold(),
12534 }
12535 }
12536}
12537
12538#[derive(Debug, Clone, Serialize, Deserialize)]
12540pub struct SafetySchemaConfig {
12541 #[serde(default = "default_true")]
12543 pub enabled: bool,
12544 #[serde(default = "default_trir_target")]
12546 pub target_trir: f64,
12547 #[serde(default = "default_incident_count")]
12549 pub incident_count: u32,
12550}
12551
12552fn default_trir_target() -> f64 {
12553 2.5
12554}
12555
12556fn default_incident_count() -> u32 {
12557 20
12558}
12559
12560impl Default for SafetySchemaConfig {
12561 fn default() -> Self {
12562 Self {
12563 enabled: true,
12564 target_trir: default_trir_target(),
12565 incident_count: default_incident_count(),
12566 }
12567 }
12568}
12569
12570#[derive(Debug, Clone, Serialize, Deserialize)]
12572pub struct GovernanceSchemaConfig {
12573 #[serde(default = "default_true")]
12575 pub enabled: bool,
12576 #[serde(default = "default_board_size")]
12578 pub board_size: u32,
12579 #[serde(default = "default_independence_target")]
12581 pub independence_target: f64,
12582}
12583
12584fn default_board_size() -> u32 {
12585 11
12586}
12587
12588fn default_independence_target() -> f64 {
12589 0.67
12590}
12591
12592impl Default for GovernanceSchemaConfig {
12593 fn default() -> Self {
12594 Self {
12595 enabled: true,
12596 board_size: default_board_size(),
12597 independence_target: default_independence_target(),
12598 }
12599 }
12600}
12601
12602#[derive(Debug, Clone, Serialize, Deserialize)]
12604pub struct SupplyChainEsgConfig {
12605 #[serde(default = "default_true")]
12607 pub enabled: bool,
12608 #[serde(default = "default_assessment_coverage")]
12610 pub assessment_coverage: f64,
12611 #[serde(default = "default_high_risk_countries")]
12613 pub high_risk_countries: Vec<String>,
12614}
12615
12616fn default_assessment_coverage() -> f64 {
12617 0.80
12618}
12619
12620fn default_high_risk_countries() -> Vec<String> {
12621 vec!["CN".to_string(), "BD".to_string(), "MM".to_string()]
12622}
12623
12624impl Default for SupplyChainEsgConfig {
12625 fn default() -> Self {
12626 Self {
12627 enabled: true,
12628 assessment_coverage: default_assessment_coverage(),
12629 high_risk_countries: default_high_risk_countries(),
12630 }
12631 }
12632}
12633
12634#[derive(Debug, Clone, Serialize, Deserialize)]
12636pub struct EsgReportingConfig {
12637 #[serde(default = "default_true")]
12639 pub enabled: bool,
12640 #[serde(default = "default_esg_frameworks")]
12642 pub frameworks: Vec<String>,
12643 #[serde(default = "default_true")]
12645 pub materiality_assessment: bool,
12646 #[serde(default = "default_materiality_threshold")]
12648 pub impact_threshold: f64,
12649 #[serde(default = "default_materiality_threshold")]
12651 pub financial_threshold: f64,
12652}
12653
12654fn default_esg_frameworks() -> Vec<String> {
12655 vec!["GRI".to_string(), "ESRS".to_string()]
12656}
12657
12658fn default_materiality_threshold() -> f64 {
12659 0.6
12660}
12661
12662impl Default for EsgReportingConfig {
12663 fn default() -> Self {
12664 Self {
12665 enabled: true,
12666 frameworks: default_esg_frameworks(),
12667 materiality_assessment: true,
12668 impact_threshold: default_materiality_threshold(),
12669 financial_threshold: default_materiality_threshold(),
12670 }
12671 }
12672}
12673
12674#[derive(Debug, Clone, Serialize, Deserialize)]
12676pub struct ClimateScenarioConfig {
12677 #[serde(default)]
12679 pub enabled: bool,
12680 #[serde(default = "default_climate_scenarios")]
12682 pub scenarios: Vec<String>,
12683 #[serde(default = "default_time_horizons")]
12685 pub time_horizons: Vec<u32>,
12686}
12687
12688fn default_climate_scenarios() -> Vec<String> {
12689 vec![
12690 "net_zero_2050".to_string(),
12691 "stated_policies".to_string(),
12692 "current_trajectory".to_string(),
12693 ]
12694}
12695
12696fn default_time_horizons() -> Vec<u32> {
12697 vec![5, 10, 30]
12698}
12699
12700impl Default for ClimateScenarioConfig {
12701 fn default() -> Self {
12702 Self {
12703 enabled: false,
12704 scenarios: default_climate_scenarios(),
12705 time_horizons: default_time_horizons(),
12706 }
12707 }
12708}
12709
12710#[derive(Debug, Clone, Serialize, Deserialize, Default)]
12714pub struct ScenariosConfig {
12715 #[serde(default)]
12717 pub enabled: bool,
12718 #[serde(default)]
12720 pub scenarios: Vec<ScenarioSchemaConfig>,
12721 #[serde(default)]
12723 pub causal_model: CausalModelSchemaConfig,
12724 #[serde(default)]
12726 pub defaults: ScenarioDefaultsConfig,
12727 #[serde(default)]
12730 pub generate_counterfactuals: bool,
12731}
12732
12733#[derive(Debug, Clone, Serialize, Deserialize)]
12735pub struct ScenarioSchemaConfig {
12736 pub name: String,
12738 #[serde(default)]
12740 pub description: String,
12741 #[serde(default)]
12743 pub tags: Vec<String>,
12744 pub base: Option<String>,
12746 pub probability_weight: Option<f64>,
12748 #[serde(default)]
12750 pub interventions: Vec<InterventionSchemaConfig>,
12751 #[serde(default)]
12753 pub constraints: ScenarioConstraintsSchemaConfig,
12754 #[serde(default)]
12756 pub output: ScenarioOutputSchemaConfig,
12757 #[serde(default)]
12759 pub metadata: std::collections::HashMap<String, String>,
12760}
12761
12762#[derive(Debug, Clone, Serialize, Deserialize)]
12764pub struct InterventionSchemaConfig {
12765 #[serde(flatten)]
12767 pub intervention_type: serde_json::Value,
12768 #[serde(default)]
12770 pub timing: InterventionTimingSchemaConfig,
12771 pub label: Option<String>,
12773 #[serde(default)]
12775 pub priority: u32,
12776}
12777
12778#[derive(Debug, Clone, Serialize, Deserialize)]
12780pub struct InterventionTimingSchemaConfig {
12781 #[serde(default = "default_start_month")]
12783 pub start_month: u32,
12784 pub duration_months: Option<u32>,
12786 #[serde(default = "default_onset")]
12788 pub onset: String,
12789 pub ramp_months: Option<u32>,
12791}
12792
12793fn default_start_month() -> u32 {
12794 1
12795}
12796
12797fn default_onset() -> String {
12798 "sudden".to_string()
12799}
12800
12801impl Default for InterventionTimingSchemaConfig {
12802 fn default() -> Self {
12803 Self {
12804 start_month: 1,
12805 duration_months: None,
12806 onset: "sudden".to_string(),
12807 ramp_months: None,
12808 }
12809 }
12810}
12811
12812#[derive(Debug, Clone, Serialize, Deserialize)]
12814pub struct ScenarioConstraintsSchemaConfig {
12815 #[serde(default = "default_true")]
12816 pub preserve_accounting_identity: bool,
12817 #[serde(default = "default_true")]
12818 pub preserve_document_chains: bool,
12819 #[serde(default = "default_true")]
12820 pub preserve_period_close: bool,
12821 #[serde(default = "default_true")]
12822 pub preserve_balance_coherence: bool,
12823 #[serde(default)]
12824 pub custom: Vec<CustomConstraintSchemaConfig>,
12825}
12826
12827impl Default for ScenarioConstraintsSchemaConfig {
12828 fn default() -> Self {
12829 Self {
12830 preserve_accounting_identity: true,
12831 preserve_document_chains: true,
12832 preserve_period_close: true,
12833 preserve_balance_coherence: true,
12834 custom: Vec::new(),
12835 }
12836 }
12837}
12838
12839#[derive(Debug, Clone, Serialize, Deserialize)]
12841pub struct CustomConstraintSchemaConfig {
12842 pub config_path: String,
12843 pub min: Option<f64>,
12844 pub max: Option<f64>,
12845 #[serde(default)]
12846 pub description: String,
12847}
12848
12849#[derive(Debug, Clone, Serialize, Deserialize)]
12851pub struct ScenarioOutputSchemaConfig {
12852 #[serde(default = "default_true")]
12853 pub paired: bool,
12854 #[serde(default = "default_diff_formats_schema")]
12855 pub diff_formats: Vec<String>,
12856 #[serde(default)]
12857 pub diff_scope: Vec<String>,
12858}
12859
12860fn default_diff_formats_schema() -> Vec<String> {
12861 vec!["summary".to_string(), "aggregate".to_string()]
12862}
12863
12864impl Default for ScenarioOutputSchemaConfig {
12865 fn default() -> Self {
12866 Self {
12867 paired: true,
12868 diff_formats: default_diff_formats_schema(),
12869 diff_scope: Vec::new(),
12870 }
12871 }
12872}
12873
12874#[derive(Debug, Clone, Serialize, Deserialize)]
12876pub struct CausalModelSchemaConfig {
12877 #[serde(default = "default_causal_preset")]
12879 pub preset: String,
12880 #[serde(default)]
12882 pub nodes: Vec<serde_json::Value>,
12883 #[serde(default)]
12885 pub edges: Vec<serde_json::Value>,
12886}
12887
12888fn default_causal_preset() -> String {
12889 "default".to_string()
12890}
12891
12892impl Default for CausalModelSchemaConfig {
12893 fn default() -> Self {
12894 Self {
12895 preset: "default".to_string(),
12896 nodes: Vec::new(),
12897 edges: Vec::new(),
12898 }
12899 }
12900}
12901
12902#[derive(Debug, Clone, Serialize, Deserialize, Default)]
12904pub struct ScenarioDefaultsConfig {
12905 #[serde(default)]
12906 pub constraints: ScenarioConstraintsSchemaConfig,
12907 #[serde(default)]
12908 pub output: ScenarioOutputSchemaConfig,
12909}
12910
12911#[derive(Debug, Clone, Default, Serialize, Deserialize)]
12944pub struct ComplianceRegulationsConfig {
12945 #[serde(default)]
12947 pub enabled: bool,
12948 #[serde(default)]
12951 pub jurisdictions: Vec<String>,
12952 #[serde(default)]
12955 pub reference_date: Option<String>,
12956 #[serde(default)]
12958 pub standards_selection: StandardsSelectionConfig,
12959 #[serde(default)]
12961 pub audit_procedures: AuditProcedureGenConfig,
12962 #[serde(default)]
12964 pub findings: ComplianceFindingGenConfig,
12965 #[serde(default)]
12967 pub filings: ComplianceFilingGenConfig,
12968 #[serde(default)]
12970 pub graph: ComplianceGraphConfig,
12971 #[serde(default)]
12973 pub output: ComplianceOutputConfig,
12974}
12975
12976#[derive(Debug, Clone, Default, Serialize, Deserialize)]
12978pub struct StandardsSelectionConfig {
12979 #[serde(default)]
12982 pub categories: Vec<String>,
12983 #[serde(default)]
12986 pub include: Vec<String>,
12987 #[serde(default)]
12989 pub exclude: Vec<String>,
12990 #[serde(default)]
12992 pub include_superseded: bool,
12993}
12994
12995#[derive(Debug, Clone, Serialize, Deserialize)]
12997pub struct AuditProcedureGenConfig {
12998 #[serde(default)]
13000 pub enabled: bool,
13001 #[serde(default = "default_procedures_per_standard")]
13003 pub procedures_per_standard: usize,
13004 #[serde(default = "default_sampling_method")]
13006 pub sampling_method: String,
13007 #[serde(default = "default_confidence_level")]
13009 pub confidence_level: f64,
13010 #[serde(default = "default_tolerable_misstatement")]
13012 pub tolerable_misstatement: f64,
13013}
13014
13015fn default_procedures_per_standard() -> usize {
13016 3
13017}
13018
13019fn default_sampling_method() -> String {
13020 "statistical".to_string()
13021}
13022
13023fn default_confidence_level() -> f64 {
13024 0.95
13025}
13026
13027fn default_tolerable_misstatement() -> f64 {
13028 0.05
13029}
13030
13031impl Default for AuditProcedureGenConfig {
13032 fn default() -> Self {
13033 Self {
13034 enabled: false,
13035 procedures_per_standard: default_procedures_per_standard(),
13036 sampling_method: default_sampling_method(),
13037 confidence_level: default_confidence_level(),
13038 tolerable_misstatement: default_tolerable_misstatement(),
13039 }
13040 }
13041}
13042
13043#[derive(Debug, Clone, Serialize, Deserialize)]
13045pub struct ComplianceFindingGenConfig {
13046 #[serde(default)]
13048 pub enabled: bool,
13049 #[serde(default = "default_finding_rate")]
13051 pub finding_rate: f64,
13052 #[serde(default = "default_cr_material_weakness_rate")]
13054 pub material_weakness_rate: f64,
13055 #[serde(default = "default_cr_significant_deficiency_rate")]
13057 pub significant_deficiency_rate: f64,
13058 #[serde(default = "default_true")]
13060 pub generate_remediation: bool,
13061}
13062
13063fn default_finding_rate() -> f64 {
13064 0.05
13065}
13066
13067fn default_cr_material_weakness_rate() -> f64 {
13068 0.02
13069}
13070
13071fn default_cr_significant_deficiency_rate() -> f64 {
13072 0.08
13073}
13074
13075impl Default for ComplianceFindingGenConfig {
13076 fn default() -> Self {
13077 Self {
13078 enabled: false,
13079 finding_rate: default_finding_rate(),
13080 material_weakness_rate: default_cr_material_weakness_rate(),
13081 significant_deficiency_rate: default_cr_significant_deficiency_rate(),
13082 generate_remediation: true,
13083 }
13084 }
13085}
13086
13087#[derive(Debug, Clone, Serialize, Deserialize)]
13089pub struct ComplianceFilingGenConfig {
13090 #[serde(default)]
13092 pub enabled: bool,
13093 #[serde(default)]
13096 pub filing_types: Vec<String>,
13097 #[serde(default = "default_true")]
13099 pub generate_status_progression: bool,
13100}
13101
13102impl Default for ComplianceFilingGenConfig {
13103 fn default() -> Self {
13104 Self {
13105 enabled: false,
13106 filing_types: Vec::new(),
13107 generate_status_progression: true,
13108 }
13109 }
13110}
13111
13112#[derive(Debug, Clone, Serialize, Deserialize)]
13114pub struct ComplianceGraphConfig {
13115 #[serde(default)]
13117 pub enabled: bool,
13118 #[serde(default = "default_true")]
13120 pub include_compliance_nodes: bool,
13121 #[serde(default = "default_true")]
13123 pub include_compliance_edges: bool,
13124 #[serde(default = "default_true")]
13126 pub include_cross_references: bool,
13127 #[serde(default)]
13129 pub include_supersession_edges: bool,
13130 #[serde(default = "default_true")]
13132 pub include_account_links: bool,
13133 #[serde(default = "default_true")]
13135 pub include_control_links: bool,
13136 #[serde(default = "default_true")]
13138 pub include_company_links: bool,
13139}
13140
13141impl Default for ComplianceGraphConfig {
13142 fn default() -> Self {
13143 Self {
13144 enabled: false,
13145 include_compliance_nodes: true,
13146 include_compliance_edges: true,
13147 include_cross_references: true,
13148 include_supersession_edges: false,
13149 include_account_links: true,
13150 include_control_links: true,
13151 include_company_links: true,
13152 }
13153 }
13154}
13155
13156#[derive(Debug, Clone, Serialize, Deserialize)]
13158pub struct ComplianceOutputConfig {
13159 #[serde(default = "default_true")]
13161 pub export_registry: bool,
13162 #[serde(default = "default_true")]
13164 pub export_jurisdictions: bool,
13165 #[serde(default = "default_true")]
13167 pub export_cross_references: bool,
13168 #[serde(default)]
13170 pub export_version_history: bool,
13171}
13172
13173impl Default for ComplianceOutputConfig {
13174 fn default() -> Self {
13175 Self {
13176 export_registry: true,
13177 export_jurisdictions: true,
13178 export_cross_references: true,
13179 export_version_history: false,
13180 }
13181 }
13182}
13183
13184#[cfg(test)]
13185#[allow(clippy::unwrap_used)]
13186mod tests {
13187 use super::*;
13188 use crate::presets::demo_preset;
13189
13190 #[test]
13195 fn test_config_yaml_roundtrip() {
13196 let config = demo_preset();
13197 let yaml = serde_yaml::to_string(&config).expect("Failed to serialize to YAML");
13198 let deserialized: GeneratorConfig =
13199 serde_yaml::from_str(&yaml).expect("Failed to deserialize from YAML");
13200
13201 assert_eq!(
13202 config.global.period_months,
13203 deserialized.global.period_months
13204 );
13205 assert_eq!(config.global.industry, deserialized.global.industry);
13206 assert_eq!(config.companies.len(), deserialized.companies.len());
13207 assert_eq!(config.companies[0].code, deserialized.companies[0].code);
13208 }
13209
13210 #[test]
13211 fn test_config_json_roundtrip() {
13212 let mut config = demo_preset();
13214 config.master_data.employees.approval_limits.executive = 1e12;
13216
13217 let json = serde_json::to_string(&config).expect("Failed to serialize to JSON");
13218 let deserialized: GeneratorConfig =
13219 serde_json::from_str(&json).expect("Failed to deserialize from JSON");
13220
13221 assert_eq!(
13222 config.global.period_months,
13223 deserialized.global.period_months
13224 );
13225 assert_eq!(config.global.industry, deserialized.global.industry);
13226 assert_eq!(config.companies.len(), deserialized.companies.len());
13227 }
13228
13229 #[test]
13230 fn test_transaction_volume_serialization() {
13231 let volumes = vec![
13233 (TransactionVolume::TenK, "ten_k"),
13234 (TransactionVolume::HundredK, "hundred_k"),
13235 (TransactionVolume::OneM, "one_m"),
13236 (TransactionVolume::TenM, "ten_m"),
13237 (TransactionVolume::HundredM, "hundred_m"),
13238 ];
13239
13240 for (volume, expected_key) in volumes {
13241 let json = serde_json::to_string(&volume).expect("Failed to serialize");
13242 assert!(
13243 json.contains(expected_key),
13244 "Expected {} in JSON: {}",
13245 expected_key,
13246 json
13247 );
13248 }
13249 }
13250
13251 #[test]
13252 fn test_transaction_volume_custom_serialization() {
13253 let volume = TransactionVolume::Custom(12345);
13254 let json = serde_json::to_string(&volume).expect("Failed to serialize");
13255 let deserialized: TransactionVolume =
13256 serde_json::from_str(&json).expect("Failed to deserialize");
13257 assert_eq!(deserialized.count(), 12345);
13258 }
13259
13260 #[test]
13261 fn test_output_mode_serialization() {
13262 let modes = vec![
13263 OutputMode::Streaming,
13264 OutputMode::FlatFile,
13265 OutputMode::Both,
13266 ];
13267
13268 for mode in modes {
13269 let json = serde_json::to_string(&mode).expect("Failed to serialize");
13270 let deserialized: OutputMode =
13271 serde_json::from_str(&json).expect("Failed to deserialize");
13272 assert!(format!("{:?}", mode) == format!("{:?}", deserialized));
13273 }
13274 }
13275
13276 #[test]
13277 fn test_file_format_serialization() {
13278 let formats = vec![
13279 FileFormat::Csv,
13280 FileFormat::Parquet,
13281 FileFormat::Json,
13282 FileFormat::JsonLines,
13283 ];
13284
13285 for format in formats {
13286 let json = serde_json::to_string(&format).expect("Failed to serialize");
13287 let deserialized: FileFormat =
13288 serde_json::from_str(&json).expect("Failed to deserialize");
13289 assert!(format!("{:?}", format) == format!("{:?}", deserialized));
13290 }
13291 }
13292
13293 #[test]
13294 fn test_compression_algorithm_serialization() {
13295 let algos = vec![
13296 CompressionAlgorithm::Gzip,
13297 CompressionAlgorithm::Zstd,
13298 CompressionAlgorithm::Lz4,
13299 CompressionAlgorithm::Snappy,
13300 ];
13301
13302 for algo in algos {
13303 let json = serde_json::to_string(&algo).expect("Failed to serialize");
13304 let deserialized: CompressionAlgorithm =
13305 serde_json::from_str(&json).expect("Failed to deserialize");
13306 assert!(format!("{:?}", algo) == format!("{:?}", deserialized));
13307 }
13308 }
13309
13310 #[test]
13311 fn test_transfer_pricing_method_serialization() {
13312 let methods = vec![
13313 TransferPricingMethod::CostPlus,
13314 TransferPricingMethod::ComparableUncontrolled,
13315 TransferPricingMethod::ResalePrice,
13316 TransferPricingMethod::TransactionalNetMargin,
13317 TransferPricingMethod::ProfitSplit,
13318 ];
13319
13320 for method in methods {
13321 let json = serde_json::to_string(&method).expect("Failed to serialize");
13322 let deserialized: TransferPricingMethod =
13323 serde_json::from_str(&json).expect("Failed to deserialize");
13324 assert!(format!("{:?}", method) == format!("{:?}", deserialized));
13325 }
13326 }
13327
13328 #[test]
13329 fn test_benford_exemption_serialization() {
13330 let exemptions = vec![
13331 BenfordExemption::Recurring,
13332 BenfordExemption::Payroll,
13333 BenfordExemption::FixedFees,
13334 BenfordExemption::RoundAmounts,
13335 ];
13336
13337 for exemption in exemptions {
13338 let json = serde_json::to_string(&exemption).expect("Failed to serialize");
13339 let deserialized: BenfordExemption =
13340 serde_json::from_str(&json).expect("Failed to deserialize");
13341 assert!(format!("{:?}", exemption) == format!("{:?}", deserialized));
13342 }
13343 }
13344
13345 #[test]
13350 fn test_global_config_defaults() {
13351 let yaml = r#"
13352 industry: manufacturing
13353 start_date: "2024-01-01"
13354 period_months: 6
13355 "#;
13356 let config: GlobalConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13357 assert_eq!(config.group_currency, "USD");
13358 assert!(config.parallel);
13359 assert_eq!(config.worker_threads, 0);
13360 assert_eq!(config.memory_limit_mb, 0);
13361 }
13362
13363 #[test]
13364 fn test_fraud_config_defaults() {
13365 let config = FraudConfig::default();
13366 assert!(!config.enabled);
13367 assert_eq!(config.fraud_rate, 0.005);
13368 assert!(!config.clustering_enabled);
13369 }
13370
13371 #[test]
13372 fn test_internal_controls_config_defaults() {
13373 let config = InternalControlsConfig::default();
13374 assert!(!config.enabled);
13375 assert_eq!(config.exception_rate, 0.02);
13376 assert_eq!(config.sod_violation_rate, 0.01);
13377 assert!(config.export_control_master_data);
13378 assert_eq!(config.sox_materiality_threshold, 10000.0);
13379 assert!(config.coso_enabled);
13381 assert!(!config.include_entity_level_controls);
13382 assert_eq!(config.target_maturity_level, "mixed");
13383 }
13384
13385 #[test]
13386 fn test_output_config_defaults() {
13387 let config = OutputConfig::default();
13388 assert!(matches!(config.mode, OutputMode::FlatFile));
13389 assert_eq!(config.formats, vec![FileFormat::Parquet]);
13390 assert!(config.compression.enabled);
13391 assert!(matches!(
13392 config.compression.algorithm,
13393 CompressionAlgorithm::Zstd
13394 ));
13395 assert!(config.include_acdoca);
13396 assert!(!config.include_bseg);
13397 assert!(config.partition_by_period);
13398 assert!(!config.partition_by_company);
13399 }
13400
13401 #[test]
13402 fn test_approval_config_defaults() {
13403 let config = ApprovalConfig::default();
13404 assert!(!config.enabled);
13405 assert_eq!(config.auto_approve_threshold, 1000.0);
13406 assert_eq!(config.rejection_rate, 0.02);
13407 assert_eq!(config.revision_rate, 0.05);
13408 assert_eq!(config.average_approval_delay_hours, 4.0);
13409 assert_eq!(config.thresholds.len(), 4);
13410 }
13411
13412 #[test]
13413 fn test_p2p_flow_config_defaults() {
13414 let config = P2PFlowConfig::default();
13415 assert!(config.enabled);
13416 assert_eq!(config.three_way_match_rate, 0.95);
13417 assert_eq!(config.partial_delivery_rate, 0.15);
13418 assert_eq!(config.average_po_to_gr_days, 14);
13419 }
13420
13421 #[test]
13422 fn test_o2c_flow_config_defaults() {
13423 let config = O2CFlowConfig::default();
13424 assert!(config.enabled);
13425 assert_eq!(config.credit_check_failure_rate, 0.02);
13426 assert_eq!(config.return_rate, 0.03);
13427 assert_eq!(config.bad_debt_rate, 0.01);
13428 }
13429
13430 #[test]
13431 fn test_balance_config_defaults() {
13432 let config = BalanceConfig::default();
13433 assert!(!config.generate_opening_balances);
13434 assert!(config.generate_trial_balances);
13435 assert_eq!(config.target_gross_margin, 0.35);
13436 assert!(config.validate_balance_equation);
13437 assert!(config.reconcile_subledgers);
13438 }
13439
13440 #[test]
13445 fn test_partial_config_with_defaults() {
13446 let yaml = r#"
13448 global:
13449 industry: manufacturing
13450 start_date: "2024-01-01"
13451 period_months: 3
13452 companies:
13453 - code: "TEST"
13454 name: "Test Company"
13455 currency: "USD"
13456 country: "US"
13457 annual_transaction_volume: ten_k
13458 chart_of_accounts:
13459 complexity: small
13460 output:
13461 output_directory: "./output"
13462 "#;
13463
13464 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13465 assert_eq!(config.global.period_months, 3);
13466 assert_eq!(config.companies.len(), 1);
13467 assert!(!config.fraud.enabled); assert!(!config.internal_controls.enabled); }
13470
13471 #[test]
13472 fn test_config_with_fraud_enabled() {
13473 let yaml = r#"
13474 global:
13475 industry: retail
13476 start_date: "2024-01-01"
13477 period_months: 12
13478 companies:
13479 - code: "RETAIL"
13480 name: "Retail Co"
13481 currency: "USD"
13482 country: "US"
13483 annual_transaction_volume: hundred_k
13484 chart_of_accounts:
13485 complexity: medium
13486 output:
13487 output_directory: "./output"
13488 fraud:
13489 enabled: true
13490 fraud_rate: 0.05
13491 clustering_enabled: true
13492 "#;
13493
13494 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13495 assert!(config.fraud.enabled);
13496 assert_eq!(config.fraud.fraud_rate, 0.05);
13497 assert!(config.fraud.clustering_enabled);
13498 }
13499
13500 #[test]
13501 fn test_config_with_multiple_companies() {
13502 let yaml = r#"
13503 global:
13504 industry: manufacturing
13505 start_date: "2024-01-01"
13506 period_months: 6
13507 companies:
13508 - code: "HQ"
13509 name: "Headquarters"
13510 currency: "USD"
13511 country: "US"
13512 annual_transaction_volume: hundred_k
13513 volume_weight: 1.0
13514 - code: "EU"
13515 name: "European Subsidiary"
13516 currency: "EUR"
13517 country: "DE"
13518 annual_transaction_volume: hundred_k
13519 volume_weight: 0.5
13520 - code: "APAC"
13521 name: "Asia Pacific"
13522 currency: "JPY"
13523 country: "JP"
13524 annual_transaction_volume: ten_k
13525 volume_weight: 0.3
13526 chart_of_accounts:
13527 complexity: large
13528 output:
13529 output_directory: "./output"
13530 "#;
13531
13532 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13533 assert_eq!(config.companies.len(), 3);
13534 assert_eq!(config.companies[0].code, "HQ");
13535 assert_eq!(config.companies[1].currency, "EUR");
13536 assert_eq!(config.companies[2].volume_weight, 0.3);
13537 }
13538
13539 #[test]
13540 fn test_intercompany_config() {
13541 let yaml = r#"
13542 enabled: true
13543 ic_transaction_rate: 0.20
13544 transfer_pricing_method: cost_plus
13545 markup_percent: 0.08
13546 generate_matched_pairs: true
13547 generate_eliminations: true
13548 "#;
13549
13550 let config: IntercompanyConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13551 assert!(config.enabled);
13552 assert_eq!(config.ic_transaction_rate, 0.20);
13553 assert!(matches!(
13554 config.transfer_pricing_method,
13555 TransferPricingMethod::CostPlus
13556 ));
13557 assert_eq!(config.markup_percent, 0.08);
13558 assert!(config.generate_eliminations);
13559 }
13560
13561 #[test]
13566 fn test_company_config_defaults() {
13567 let yaml = r#"
13568 code: "TEST"
13569 name: "Test Company"
13570 currency: "USD"
13571 country: "US"
13572 annual_transaction_volume: ten_k
13573 "#;
13574
13575 let config: CompanyConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13576 assert_eq!(config.fiscal_year_variant, "K4"); assert_eq!(config.volume_weight, 1.0); }
13579
13580 #[test]
13585 fn test_coa_config_defaults() {
13586 let yaml = r#"
13587 complexity: medium
13588 "#;
13589
13590 let config: ChartOfAccountsConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13591 assert!(config.industry_specific); assert!(config.custom_accounts.is_none());
13593 assert_eq!(config.min_hierarchy_depth, 2); assert_eq!(config.max_hierarchy_depth, 5); }
13596
13597 #[test]
13602 fn test_accounting_standards_config_defaults() {
13603 let config = AccountingStandardsConfig::default();
13604 assert!(!config.enabled);
13605 assert!(config.framework.is_none());
13606 assert!(!config.revenue_recognition.enabled);
13607 assert!(!config.leases.enabled);
13608 assert!(!config.fair_value.enabled);
13609 assert!(!config.impairment.enabled);
13610 assert!(!config.generate_differences);
13611 }
13612
13613 #[test]
13614 fn test_accounting_standards_config_yaml() {
13615 let yaml = r#"
13616 enabled: true
13617 framework: ifrs
13618 revenue_recognition:
13619 enabled: true
13620 generate_contracts: true
13621 avg_obligations_per_contract: 2.5
13622 variable_consideration_rate: 0.20
13623 over_time_recognition_rate: 0.35
13624 contract_count: 150
13625 leases:
13626 enabled: true
13627 lease_count: 75
13628 finance_lease_percent: 0.25
13629 avg_lease_term_months: 48
13630 generate_differences: true
13631 "#;
13632
13633 let config: AccountingStandardsConfig =
13634 serde_yaml::from_str(yaml).expect("Failed to parse");
13635 assert!(config.enabled);
13636 assert!(matches!(
13637 config.framework,
13638 Some(AccountingFrameworkConfig::Ifrs)
13639 ));
13640 assert!(config.revenue_recognition.enabled);
13641 assert_eq!(config.revenue_recognition.contract_count, 150);
13642 assert_eq!(config.revenue_recognition.avg_obligations_per_contract, 2.5);
13643 assert!(config.leases.enabled);
13644 assert_eq!(config.leases.lease_count, 75);
13645 assert_eq!(config.leases.finance_lease_percent, 0.25);
13646 assert!(config.generate_differences);
13647 }
13648
13649 #[test]
13650 fn test_accounting_framework_serialization() {
13651 let frameworks = [
13652 AccountingFrameworkConfig::UsGaap,
13653 AccountingFrameworkConfig::Ifrs,
13654 AccountingFrameworkConfig::DualReporting,
13655 AccountingFrameworkConfig::FrenchGaap,
13656 AccountingFrameworkConfig::GermanGaap,
13657 ];
13658
13659 for framework in frameworks {
13660 let json = serde_json::to_string(&framework).expect("Failed to serialize");
13661 let deserialized: AccountingFrameworkConfig =
13662 serde_json::from_str(&json).expect("Failed to deserialize");
13663 assert!(format!("{:?}", framework) == format!("{:?}", deserialized));
13664 }
13665 }
13666
13667 #[test]
13668 fn test_revenue_recognition_config_defaults() {
13669 let config = RevenueRecognitionConfig::default();
13670 assert!(!config.enabled);
13671 assert!(config.generate_contracts);
13672 assert_eq!(config.avg_obligations_per_contract, 2.0);
13673 assert_eq!(config.variable_consideration_rate, 0.15);
13674 assert_eq!(config.over_time_recognition_rate, 0.30);
13675 assert_eq!(config.contract_count, 100);
13676 }
13677
13678 #[test]
13679 fn test_lease_accounting_config_defaults() {
13680 let config = LeaseAccountingConfig::default();
13681 assert!(!config.enabled);
13682 assert_eq!(config.lease_count, 50);
13683 assert_eq!(config.finance_lease_percent, 0.30);
13684 assert_eq!(config.avg_lease_term_months, 60);
13685 assert!(config.generate_amortization);
13686 assert_eq!(config.real_estate_percent, 0.40);
13687 }
13688
13689 #[test]
13690 fn test_fair_value_config_defaults() {
13691 let config = FairValueConfig::default();
13692 assert!(!config.enabled);
13693 assert_eq!(config.measurement_count, 25);
13694 assert_eq!(config.level1_percent, 0.40);
13695 assert_eq!(config.level2_percent, 0.35);
13696 assert_eq!(config.level3_percent, 0.25);
13697 assert!(!config.include_sensitivity_analysis);
13698 }
13699
13700 #[test]
13701 fn test_impairment_config_defaults() {
13702 let config = ImpairmentConfig::default();
13703 assert!(!config.enabled);
13704 assert_eq!(config.test_count, 15);
13705 assert_eq!(config.impairment_rate, 0.10);
13706 assert!(config.generate_projections);
13707 assert!(!config.include_goodwill);
13708 }
13709
13710 #[test]
13715 fn test_audit_standards_config_defaults() {
13716 let config = AuditStandardsConfig::default();
13717 assert!(!config.enabled);
13718 assert!(!config.isa_compliance.enabled);
13719 assert!(!config.analytical_procedures.enabled);
13720 assert!(!config.confirmations.enabled);
13721 assert!(!config.opinion.enabled);
13722 assert!(!config.generate_audit_trail);
13723 assert!(!config.sox.enabled);
13724 assert!(!config.pcaob.enabled);
13725 }
13726
13727 #[test]
13728 fn test_audit_standards_config_yaml() {
13729 let yaml = r#"
13730 enabled: true
13731 isa_compliance:
13732 enabled: true
13733 compliance_level: comprehensive
13734 generate_isa_mappings: true
13735 include_pcaob: true
13736 framework: dual
13737 analytical_procedures:
13738 enabled: true
13739 procedures_per_account: 5
13740 variance_probability: 0.25
13741 confirmations:
13742 enabled: true
13743 confirmation_count: 75
13744 positive_response_rate: 0.90
13745 exception_rate: 0.08
13746 opinion:
13747 enabled: true
13748 generate_kam: true
13749 average_kam_count: 4
13750 sox:
13751 enabled: true
13752 generate_302_certifications: true
13753 generate_404_assessments: true
13754 material_weakness_rate: 0.03
13755 pcaob:
13756 enabled: true
13757 is_pcaob_audit: true
13758 include_icfr_opinion: true
13759 generate_audit_trail: true
13760 "#;
13761
13762 let config: AuditStandardsConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13763 assert!(config.enabled);
13764 assert!(config.isa_compliance.enabled);
13765 assert_eq!(config.isa_compliance.compliance_level, "comprehensive");
13766 assert!(config.isa_compliance.include_pcaob);
13767 assert_eq!(config.isa_compliance.framework, "dual");
13768 assert!(config.analytical_procedures.enabled);
13769 assert_eq!(config.analytical_procedures.procedures_per_account, 5);
13770 assert!(config.confirmations.enabled);
13771 assert_eq!(config.confirmations.confirmation_count, 75);
13772 assert!(config.opinion.enabled);
13773 assert_eq!(config.opinion.average_kam_count, 4);
13774 assert!(config.sox.enabled);
13775 assert!(config.sox.generate_302_certifications);
13776 assert_eq!(config.sox.material_weakness_rate, 0.03);
13777 assert!(config.pcaob.enabled);
13778 assert!(config.pcaob.is_pcaob_audit);
13779 assert!(config.pcaob.include_icfr_opinion);
13780 assert!(config.generate_audit_trail);
13781 }
13782
13783 #[test]
13784 fn test_isa_compliance_config_defaults() {
13785 let config = IsaComplianceConfig::default();
13786 assert!(!config.enabled);
13787 assert_eq!(config.compliance_level, "standard");
13788 assert!(config.generate_isa_mappings);
13789 assert!(config.generate_coverage_summary);
13790 assert!(!config.include_pcaob);
13791 assert_eq!(config.framework, "isa");
13792 }
13793
13794 #[test]
13795 fn test_sox_compliance_config_defaults() {
13796 let config = SoxComplianceConfig::default();
13797 assert!(!config.enabled);
13798 assert!(config.generate_302_certifications);
13799 assert!(config.generate_404_assessments);
13800 assert_eq!(config.materiality_threshold, 10000.0);
13801 assert_eq!(config.material_weakness_rate, 0.02);
13802 assert_eq!(config.significant_deficiency_rate, 0.08);
13803 }
13804
13805 #[test]
13806 fn test_pcaob_config_defaults() {
13807 let config = PcaobConfig::default();
13808 assert!(!config.enabled);
13809 assert!(!config.is_pcaob_audit);
13810 assert!(config.generate_cam);
13811 assert!(!config.include_icfr_opinion);
13812 assert!(!config.generate_standard_mappings);
13813 }
13814
13815 #[test]
13816 fn test_config_with_standards_enabled() {
13817 let yaml = r#"
13818 global:
13819 industry: financial_services
13820 start_date: "2024-01-01"
13821 period_months: 12
13822 companies:
13823 - code: "BANK"
13824 name: "Test Bank"
13825 currency: "USD"
13826 country: "US"
13827 annual_transaction_volume: hundred_k
13828 chart_of_accounts:
13829 complexity: large
13830 output:
13831 output_directory: "./output"
13832 accounting_standards:
13833 enabled: true
13834 framework: us_gaap
13835 revenue_recognition:
13836 enabled: true
13837 leases:
13838 enabled: true
13839 audit_standards:
13840 enabled: true
13841 isa_compliance:
13842 enabled: true
13843 sox:
13844 enabled: true
13845 "#;
13846
13847 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13848 assert!(config.accounting_standards.enabled);
13849 assert!(matches!(
13850 config.accounting_standards.framework,
13851 Some(AccountingFrameworkConfig::UsGaap)
13852 ));
13853 assert!(config.accounting_standards.revenue_recognition.enabled);
13854 assert!(config.accounting_standards.leases.enabled);
13855 assert!(config.audit_standards.enabled);
13856 assert!(config.audit_standards.isa_compliance.enabled);
13857 assert!(config.audit_standards.sox.enabled);
13858 }
13859
13860 #[test]
13865 fn test_industry_specific_config_defaults() {
13866 let config = IndustrySpecificConfig::default();
13867 assert!(!config.enabled);
13868 assert!(!config.manufacturing.enabled);
13869 assert!(!config.retail.enabled);
13870 assert!(!config.healthcare.enabled);
13871 assert!(!config.technology.enabled);
13872 assert!(!config.financial_services.enabled);
13873 assert!(!config.professional_services.enabled);
13874 }
13875
13876 #[test]
13877 fn test_manufacturing_config_defaults() {
13878 let config = ManufacturingConfig::default();
13879 assert!(!config.enabled);
13880 assert_eq!(config.bom_depth, 4);
13881 assert!(!config.just_in_time);
13882 assert_eq!(config.supplier_tiers, 2);
13883 assert_eq!(config.target_yield_rate, 0.97);
13884 assert_eq!(config.scrap_alert_threshold, 0.03);
13885 }
13886
13887 #[test]
13888 fn test_retail_config_defaults() {
13889 let config = RetailConfig::default();
13890 assert!(!config.enabled);
13891 assert_eq!(config.avg_daily_transactions, 500);
13892 assert!(config.loss_prevention);
13893 assert_eq!(config.shrinkage_rate, 0.015);
13894 }
13895
13896 #[test]
13897 fn test_healthcare_config_defaults() {
13898 let config = HealthcareConfig::default();
13899 assert!(!config.enabled);
13900 assert_eq!(config.facility_type, "hospital");
13901 assert_eq!(config.avg_daily_encounters, 150);
13902 assert!(config.compliance.hipaa);
13903 assert!(config.compliance.stark_law);
13904 assert!(config.coding_systems.icd10);
13905 assert!(config.coding_systems.cpt);
13906 }
13907
13908 #[test]
13909 fn test_technology_config_defaults() {
13910 let config = TechnologyConfig::default();
13911 assert!(!config.enabled);
13912 assert_eq!(config.revenue_model, "saas");
13913 assert_eq!(config.subscription_revenue_pct, 0.60);
13914 assert!(config.rd_capitalization.enabled);
13915 }
13916
13917 #[test]
13918 fn test_config_with_industry_specific() {
13919 let yaml = r#"
13920 global:
13921 industry: healthcare
13922 start_date: "2024-01-01"
13923 period_months: 12
13924 companies:
13925 - code: "HOSP"
13926 name: "Test Hospital"
13927 currency: "USD"
13928 country: "US"
13929 annual_transaction_volume: hundred_k
13930 chart_of_accounts:
13931 complexity: medium
13932 output:
13933 output_directory: "./output"
13934 industry_specific:
13935 enabled: true
13936 healthcare:
13937 enabled: true
13938 facility_type: hospital
13939 payer_mix:
13940 medicare: 0.45
13941 medicaid: 0.15
13942 commercial: 0.35
13943 self_pay: 0.05
13944 coding_systems:
13945 icd10: true
13946 cpt: true
13947 drg: true
13948 compliance:
13949 hipaa: true
13950 stark_law: true
13951 anomaly_rates:
13952 upcoding: 0.03
13953 unbundling: 0.02
13954 "#;
13955
13956 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13957 assert!(config.industry_specific.enabled);
13958 assert!(config.industry_specific.healthcare.enabled);
13959 assert_eq!(
13960 config.industry_specific.healthcare.facility_type,
13961 "hospital"
13962 );
13963 assert_eq!(config.industry_specific.healthcare.payer_mix.medicare, 0.45);
13964 assert_eq!(config.industry_specific.healthcare.payer_mix.self_pay, 0.05);
13965 assert!(config.industry_specific.healthcare.coding_systems.icd10);
13966 assert!(config.industry_specific.healthcare.compliance.hipaa);
13967 assert_eq!(
13968 config.industry_specific.healthcare.anomaly_rates.upcoding,
13969 0.03
13970 );
13971 }
13972
13973 #[test]
13974 fn test_config_with_manufacturing_specific() {
13975 let yaml = r#"
13976 global:
13977 industry: manufacturing
13978 start_date: "2024-01-01"
13979 period_months: 12
13980 companies:
13981 - code: "MFG"
13982 name: "Test Manufacturing"
13983 currency: "USD"
13984 country: "US"
13985 annual_transaction_volume: hundred_k
13986 chart_of_accounts:
13987 complexity: medium
13988 output:
13989 output_directory: "./output"
13990 industry_specific:
13991 enabled: true
13992 manufacturing:
13993 enabled: true
13994 bom_depth: 5
13995 just_in_time: true
13996 supplier_tiers: 3
13997 target_yield_rate: 0.98
13998 anomaly_rates:
13999 yield_manipulation: 0.02
14000 phantom_production: 0.01
14001 "#;
14002
14003 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
14004 assert!(config.industry_specific.enabled);
14005 assert!(config.industry_specific.manufacturing.enabled);
14006 assert_eq!(config.industry_specific.manufacturing.bom_depth, 5);
14007 assert!(config.industry_specific.manufacturing.just_in_time);
14008 assert_eq!(config.industry_specific.manufacturing.supplier_tiers, 3);
14009 assert_eq!(
14010 config.industry_specific.manufacturing.target_yield_rate,
14011 0.98
14012 );
14013 assert_eq!(
14014 config
14015 .industry_specific
14016 .manufacturing
14017 .anomaly_rates
14018 .yield_manipulation,
14019 0.02
14020 );
14021 }
14022
14023 #[test]
14028 fn test_tax_config_defaults() {
14029 let tax = TaxConfig::default();
14030 assert!(!tax.enabled);
14031 assert!(tax.jurisdictions.countries.is_empty());
14032 assert!(!tax.jurisdictions.include_subnational);
14033 assert!(!tax.vat_gst.enabled);
14034 assert!(tax.vat_gst.standard_rates.is_empty());
14035 assert!(tax.vat_gst.reduced_rates.is_empty());
14036 assert!(tax.vat_gst.exempt_categories.is_empty());
14037 assert!(tax.vat_gst.reverse_charge);
14038 assert!(!tax.sales_tax.enabled);
14039 assert!(tax.sales_tax.nexus_states.is_empty());
14040 assert!(!tax.withholding.enabled);
14041 assert!(tax.withholding.treaty_network);
14042 assert_eq!(tax.withholding.default_rate, 0.30);
14043 assert_eq!(tax.withholding.treaty_reduced_rate, 0.15);
14044 assert!(tax.provisions.enabled);
14045 assert_eq!(tax.provisions.statutory_rate, 0.21);
14046 assert!(tax.provisions.uncertain_positions);
14047 assert!(!tax.payroll_tax.enabled);
14048 assert_eq!(tax.anomaly_rate, 0.03);
14049 }
14050
14051 #[test]
14052 fn test_tax_config_from_yaml() {
14053 let yaml = r#"
14054 global:
14055 seed: 42
14056 start_date: "2024-01-01"
14057 period_months: 12
14058 industry: retail
14059 companies:
14060 - code: C001
14061 name: Test Corp
14062 currency: USD
14063 country: US
14064 annual_transaction_volume: ten_k
14065 chart_of_accounts:
14066 complexity: small
14067 output:
14068 output_directory: ./output
14069 tax:
14070 enabled: true
14071 anomaly_rate: 0.05
14072 jurisdictions:
14073 countries: ["US", "DE", "GB"]
14074 include_subnational: true
14075 vat_gst:
14076 enabled: true
14077 standard_rates:
14078 DE: 0.19
14079 GB: 0.20
14080 reduced_rates:
14081 DE: 0.07
14082 GB: 0.05
14083 exempt_categories:
14084 - financial_services
14085 - healthcare
14086 reverse_charge: false
14087 sales_tax:
14088 enabled: true
14089 nexus_states: ["CA", "NY", "TX"]
14090 withholding:
14091 enabled: true
14092 treaty_network: false
14093 default_rate: 0.25
14094 treaty_reduced_rate: 0.10
14095 provisions:
14096 enabled: false
14097 statutory_rate: 0.28
14098 uncertain_positions: false
14099 payroll_tax:
14100 enabled: true
14101 "#;
14102
14103 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
14104 assert!(config.tax.enabled);
14105 assert_eq!(config.tax.anomaly_rate, 0.05);
14106
14107 assert_eq!(config.tax.jurisdictions.countries.len(), 3);
14109 assert!(config
14110 .tax
14111 .jurisdictions
14112 .countries
14113 .contains(&"DE".to_string()));
14114 assert!(config.tax.jurisdictions.include_subnational);
14115
14116 assert!(config.tax.vat_gst.enabled);
14118 assert_eq!(config.tax.vat_gst.standard_rates.get("DE"), Some(&0.19));
14119 assert_eq!(config.tax.vat_gst.standard_rates.get("GB"), Some(&0.20));
14120 assert_eq!(config.tax.vat_gst.reduced_rates.get("DE"), Some(&0.07));
14121 assert_eq!(config.tax.vat_gst.exempt_categories.len(), 2);
14122 assert!(!config.tax.vat_gst.reverse_charge);
14123
14124 assert!(config.tax.sales_tax.enabled);
14126 assert_eq!(config.tax.sales_tax.nexus_states.len(), 3);
14127 assert!(config
14128 .tax
14129 .sales_tax
14130 .nexus_states
14131 .contains(&"CA".to_string()));
14132
14133 assert!(config.tax.withholding.enabled);
14135 assert!(!config.tax.withholding.treaty_network);
14136 assert_eq!(config.tax.withholding.default_rate, 0.25);
14137 assert_eq!(config.tax.withholding.treaty_reduced_rate, 0.10);
14138
14139 assert!(!config.tax.provisions.enabled);
14141 assert_eq!(config.tax.provisions.statutory_rate, 0.28);
14142 assert!(!config.tax.provisions.uncertain_positions);
14143
14144 assert!(config.tax.payroll_tax.enabled);
14146 }
14147
14148 #[test]
14149 fn test_generator_config_with_tax_default() {
14150 let yaml = r#"
14151 global:
14152 seed: 42
14153 start_date: "2024-01-01"
14154 period_months: 12
14155 industry: retail
14156 companies:
14157 - code: C001
14158 name: Test Corp
14159 currency: USD
14160 country: US
14161 annual_transaction_volume: ten_k
14162 chart_of_accounts:
14163 complexity: small
14164 output:
14165 output_directory: ./output
14166 "#;
14167
14168 let config: GeneratorConfig =
14169 serde_yaml::from_str(yaml).expect("Failed to parse config without tax section");
14170 assert!(!config.tax.enabled);
14172 assert!(config.tax.jurisdictions.countries.is_empty());
14173 assert_eq!(config.tax.anomaly_rate, 0.03);
14174 assert!(config.tax.provisions.enabled); assert_eq!(config.tax.provisions.statutory_rate, 0.21);
14176 }
14177
14178 #[test]
14183 fn test_session_config_default_disabled() {
14184 let yaml = "{}";
14185 let config: SessionSchemaConfig =
14186 serde_yaml::from_str(yaml).expect("Failed to parse empty session config");
14187 assert!(!config.enabled);
14188 assert!(config.checkpoint_path.is_none());
14189 assert!(config.per_period_output);
14190 assert!(config.consolidated_output);
14191 }
14192
14193 #[test]
14194 fn test_config_backward_compatible_without_session() {
14195 let yaml = r#"
14196 global:
14197 seed: 42
14198 start_date: "2024-01-01"
14199 period_months: 12
14200 industry: retail
14201 companies:
14202 - code: C001
14203 name: Test Corp
14204 currency: USD
14205 country: US
14206 annual_transaction_volume: ten_k
14207 chart_of_accounts:
14208 complexity: small
14209 output:
14210 output_directory: ./output
14211 "#;
14212
14213 let config: GeneratorConfig =
14214 serde_yaml::from_str(yaml).expect("Failed to parse config without session");
14215 assert!(!config.session.enabled);
14217 assert!(config.session.per_period_output);
14218 assert!(config.session.consolidated_output);
14219 assert!(config.global.fiscal_year_months.is_none());
14221 }
14222
14223 #[test]
14224 fn test_fiscal_year_months_parsed() {
14225 let yaml = r#"
14226 global:
14227 seed: 42
14228 start_date: "2024-01-01"
14229 period_months: 24
14230 industry: retail
14231 fiscal_year_months: 12
14232 companies:
14233 - code: C001
14234 name: Test Corp
14235 currency: USD
14236 country: US
14237 annual_transaction_volume: ten_k
14238 chart_of_accounts:
14239 complexity: small
14240 output:
14241 output_directory: ./output
14242 session:
14243 enabled: true
14244 checkpoint_path: /tmp/checkpoints
14245 per_period_output: true
14246 consolidated_output: false
14247 "#;
14248
14249 let config: GeneratorConfig =
14250 serde_yaml::from_str(yaml).expect("Failed to parse config with fiscal_year_months");
14251 assert_eq!(config.global.fiscal_year_months, Some(12));
14252 assert!(config.session.enabled);
14253 assert_eq!(
14254 config.session.checkpoint_path,
14255 Some("/tmp/checkpoints".to_string())
14256 );
14257 assert!(config.session.per_period_output);
14258 assert!(!config.session.consolidated_output);
14259 }
14260}