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)]
1720pub struct FraudConfig {
1721 #[serde(default)]
1723 pub enabled: bool,
1724 #[serde(default = "default_fraud_rate")]
1726 pub fraud_rate: f64,
1727 #[serde(default)]
1732 pub document_fraud_rate: Option<f64>,
1733 #[serde(default = "default_true")]
1738 pub propagate_to_lines: bool,
1739 #[serde(default = "default_true")]
1743 pub propagate_to_document: bool,
1744 #[serde(default)]
1746 pub fraud_type_distribution: FraudTypeDistribution,
1747 #[serde(default)]
1749 pub clustering_enabled: bool,
1750 #[serde(default = "default_clustering_factor")]
1752 pub clustering_factor: f64,
1753 #[serde(default = "default_approval_thresholds")]
1755 pub approval_thresholds: Vec<f64>,
1756}
1757
1758fn default_approval_thresholds() -> Vec<f64> {
1759 vec![1000.0, 5000.0, 10000.0, 25000.0, 50000.0, 100000.0]
1760}
1761
1762fn default_fraud_rate() -> f64 {
1763 0.005
1764}
1765fn default_clustering_factor() -> f64 {
1766 3.0
1767}
1768
1769impl Default for FraudConfig {
1770 fn default() -> Self {
1771 Self {
1772 enabled: false,
1773 fraud_rate: default_fraud_rate(),
1774 document_fraud_rate: None,
1775 propagate_to_lines: true,
1776 propagate_to_document: true,
1777 fraud_type_distribution: FraudTypeDistribution::default(),
1778 clustering_enabled: false,
1779 clustering_factor: default_clustering_factor(),
1780 approval_thresholds: default_approval_thresholds(),
1781 }
1782 }
1783}
1784
1785#[derive(Debug, Clone, Serialize, Deserialize)]
1787pub struct FraudTypeDistribution {
1788 pub suspense_account_abuse: f64,
1789 pub fictitious_transaction: f64,
1790 pub revenue_manipulation: f64,
1791 pub expense_capitalization: f64,
1792 pub split_transaction: f64,
1793 pub timing_anomaly: f64,
1794 pub unauthorized_access: f64,
1795 pub duplicate_payment: f64,
1796}
1797
1798impl Default for FraudTypeDistribution {
1799 fn default() -> Self {
1800 Self {
1801 suspense_account_abuse: 0.25,
1802 fictitious_transaction: 0.15,
1803 revenue_manipulation: 0.10,
1804 expense_capitalization: 0.10,
1805 split_transaction: 0.15,
1806 timing_anomaly: 0.10,
1807 unauthorized_access: 0.10,
1808 duplicate_payment: 0.05,
1809 }
1810 }
1811}
1812
1813#[derive(Debug, Clone, Serialize, Deserialize)]
1815pub struct InternalControlsConfig {
1816 #[serde(default)]
1818 pub enabled: bool,
1819 #[serde(default = "default_exception_rate")]
1821 pub exception_rate: f64,
1822 #[serde(default = "default_sod_violation_rate")]
1824 pub sod_violation_rate: f64,
1825 #[serde(default = "default_true")]
1827 pub export_control_master_data: bool,
1828 #[serde(default = "default_sox_materiality_threshold")]
1830 pub sox_materiality_threshold: f64,
1831 #[serde(default = "default_true")]
1833 pub coso_enabled: bool,
1834 #[serde(default)]
1836 pub include_entity_level_controls: bool,
1837 #[serde(default = "default_target_maturity_level")]
1840 pub target_maturity_level: String,
1841}
1842
1843fn default_exception_rate() -> f64 {
1844 0.02
1845}
1846
1847fn default_sod_violation_rate() -> f64 {
1848 0.01
1849}
1850
1851fn default_sox_materiality_threshold() -> f64 {
1852 10000.0
1853}
1854
1855fn default_target_maturity_level() -> String {
1856 "mixed".to_string()
1857}
1858
1859impl Default for InternalControlsConfig {
1860 fn default() -> Self {
1861 Self {
1862 enabled: false,
1863 exception_rate: default_exception_rate(),
1864 sod_violation_rate: default_sod_violation_rate(),
1865 export_control_master_data: true,
1866 sox_materiality_threshold: default_sox_materiality_threshold(),
1867 coso_enabled: true,
1868 include_entity_level_controls: false,
1869 target_maturity_level: default_target_maturity_level(),
1870 }
1871 }
1872}
1873
1874#[derive(Debug, Clone, Serialize, Deserialize)]
1876pub struct BusinessProcessConfig {
1877 #[serde(default = "default_o2c")]
1879 pub o2c_weight: f64,
1880 #[serde(default = "default_p2p")]
1882 pub p2p_weight: f64,
1883 #[serde(default = "default_r2r")]
1885 pub r2r_weight: f64,
1886 #[serde(default = "default_h2r")]
1888 pub h2r_weight: f64,
1889 #[serde(default = "default_a2r")]
1891 pub a2r_weight: f64,
1892}
1893
1894fn default_o2c() -> f64 {
1895 0.35
1896}
1897fn default_p2p() -> f64 {
1898 0.30
1899}
1900fn default_r2r() -> f64 {
1901 0.20
1902}
1903fn default_h2r() -> f64 {
1904 0.10
1905}
1906fn default_a2r() -> f64 {
1907 0.05
1908}
1909
1910impl Default for BusinessProcessConfig {
1911 fn default() -> Self {
1912 Self {
1913 o2c_weight: default_o2c(),
1914 p2p_weight: default_p2p(),
1915 r2r_weight: default_r2r(),
1916 h2r_weight: default_h2r(),
1917 a2r_weight: default_a2r(),
1918 }
1919 }
1920}
1921
1922#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1924pub struct UserPersonaConfig {
1925 #[serde(default)]
1927 pub persona_distribution: PersonaDistribution,
1928 #[serde(default)]
1930 pub users_per_persona: UsersPerPersona,
1931}
1932
1933#[derive(Debug, Clone, Serialize, Deserialize)]
1935pub struct PersonaDistribution {
1936 pub junior_accountant: f64,
1937 pub senior_accountant: f64,
1938 pub controller: f64,
1939 pub manager: f64,
1940 pub automated_system: f64,
1941}
1942
1943impl Default for PersonaDistribution {
1944 fn default() -> Self {
1945 Self {
1946 junior_accountant: 0.15,
1947 senior_accountant: 0.15,
1948 controller: 0.05,
1949 manager: 0.05,
1950 automated_system: 0.60,
1951 }
1952 }
1953}
1954
1955#[derive(Debug, Clone, Serialize, Deserialize)]
1957pub struct UsersPerPersona {
1958 pub junior_accountant: usize,
1959 pub senior_accountant: usize,
1960 pub controller: usize,
1961 pub manager: usize,
1962 pub automated_system: usize,
1963}
1964
1965impl Default for UsersPerPersona {
1966 fn default() -> Self {
1967 Self {
1968 junior_accountant: 10,
1969 senior_accountant: 5,
1970 controller: 2,
1971 manager: 3,
1972 automated_system: 20,
1973 }
1974 }
1975}
1976
1977#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1979pub struct TemplateConfig {
1980 #[serde(default)]
1982 pub names: NameTemplateConfig,
1983 #[serde(default)]
1985 pub descriptions: DescriptionTemplateConfig,
1986 #[serde(default)]
1988 pub references: ReferenceTemplateConfig,
1989}
1990
1991#[derive(Debug, Clone, Serialize, Deserialize)]
1993pub struct NameTemplateConfig {
1994 #[serde(default)]
1996 pub culture_distribution: CultureDistribution,
1997 #[serde(default = "default_email_domain")]
1999 pub email_domain: String,
2000 #[serde(default = "default_true")]
2002 pub generate_realistic_names: bool,
2003}
2004
2005fn default_email_domain() -> String {
2006 "company.com".to_string()
2007}
2008
2009impl Default for NameTemplateConfig {
2010 fn default() -> Self {
2011 Self {
2012 culture_distribution: CultureDistribution::default(),
2013 email_domain: default_email_domain(),
2014 generate_realistic_names: true,
2015 }
2016 }
2017}
2018
2019#[derive(Debug, Clone, Serialize, Deserialize)]
2021pub struct CultureDistribution {
2022 pub western_us: f64,
2023 pub hispanic: f64,
2024 pub german: f64,
2025 pub french: f64,
2026 pub chinese: f64,
2027 pub japanese: f64,
2028 pub indian: f64,
2029}
2030
2031impl Default for CultureDistribution {
2032 fn default() -> Self {
2033 Self {
2034 western_us: 0.40,
2035 hispanic: 0.20,
2036 german: 0.10,
2037 french: 0.05,
2038 chinese: 0.10,
2039 japanese: 0.05,
2040 indian: 0.10,
2041 }
2042 }
2043}
2044
2045#[derive(Debug, Clone, Serialize, Deserialize)]
2047pub struct DescriptionTemplateConfig {
2048 #[serde(default = "default_true")]
2050 pub generate_header_text: bool,
2051 #[serde(default = "default_true")]
2053 pub generate_line_text: bool,
2054}
2055
2056impl Default for DescriptionTemplateConfig {
2057 fn default() -> Self {
2058 Self {
2059 generate_header_text: true,
2060 generate_line_text: true,
2061 }
2062 }
2063}
2064
2065#[derive(Debug, Clone, Serialize, Deserialize)]
2067pub struct ReferenceTemplateConfig {
2068 #[serde(default = "default_true")]
2070 pub generate_references: bool,
2071 #[serde(default = "default_invoice_prefix")]
2073 pub invoice_prefix: String,
2074 #[serde(default = "default_po_prefix")]
2076 pub po_prefix: String,
2077 #[serde(default = "default_so_prefix")]
2079 pub so_prefix: String,
2080}
2081
2082fn default_invoice_prefix() -> String {
2083 "INV".to_string()
2084}
2085fn default_po_prefix() -> String {
2086 "PO".to_string()
2087}
2088fn default_so_prefix() -> String {
2089 "SO".to_string()
2090}
2091
2092impl Default for ReferenceTemplateConfig {
2093 fn default() -> Self {
2094 Self {
2095 generate_references: true,
2096 invoice_prefix: default_invoice_prefix(),
2097 po_prefix: default_po_prefix(),
2098 so_prefix: default_so_prefix(),
2099 }
2100 }
2101}
2102
2103#[derive(Debug, Clone, Serialize, Deserialize)]
2105pub struct ApprovalConfig {
2106 #[serde(default)]
2108 pub enabled: bool,
2109 #[serde(default = "default_auto_approve_threshold")]
2111 pub auto_approve_threshold: f64,
2112 #[serde(default = "default_rejection_rate")]
2114 pub rejection_rate: f64,
2115 #[serde(default = "default_revision_rate")]
2117 pub revision_rate: f64,
2118 #[serde(default = "default_approval_delay_hours")]
2120 pub average_approval_delay_hours: f64,
2121 #[serde(default)]
2123 pub thresholds: Vec<ApprovalThresholdConfig>,
2124}
2125
2126fn default_auto_approve_threshold() -> f64 {
2127 1000.0
2128}
2129fn default_rejection_rate() -> f64 {
2130 0.02
2131}
2132fn default_revision_rate() -> f64 {
2133 0.05
2134}
2135fn default_approval_delay_hours() -> f64 {
2136 4.0
2137}
2138
2139impl Default for ApprovalConfig {
2140 fn default() -> Self {
2141 Self {
2142 enabled: false,
2143 auto_approve_threshold: default_auto_approve_threshold(),
2144 rejection_rate: default_rejection_rate(),
2145 revision_rate: default_revision_rate(),
2146 average_approval_delay_hours: default_approval_delay_hours(),
2147 thresholds: vec![
2148 ApprovalThresholdConfig {
2149 amount: 1000.0,
2150 level: 1,
2151 roles: vec!["senior_accountant".to_string()],
2152 },
2153 ApprovalThresholdConfig {
2154 amount: 10000.0,
2155 level: 2,
2156 roles: vec!["senior_accountant".to_string(), "controller".to_string()],
2157 },
2158 ApprovalThresholdConfig {
2159 amount: 100000.0,
2160 level: 3,
2161 roles: vec![
2162 "senior_accountant".to_string(),
2163 "controller".to_string(),
2164 "manager".to_string(),
2165 ],
2166 },
2167 ApprovalThresholdConfig {
2168 amount: 500000.0,
2169 level: 4,
2170 roles: vec![
2171 "senior_accountant".to_string(),
2172 "controller".to_string(),
2173 "manager".to_string(),
2174 "executive".to_string(),
2175 ],
2176 },
2177 ],
2178 }
2179 }
2180}
2181
2182#[derive(Debug, Clone, Serialize, Deserialize)]
2184pub struct ApprovalThresholdConfig {
2185 pub amount: f64,
2187 pub level: u8,
2189 pub roles: Vec<String>,
2191}
2192
2193#[derive(Debug, Clone, Serialize, Deserialize)]
2195pub struct DepartmentConfig {
2196 #[serde(default)]
2198 pub enabled: bool,
2199 #[serde(default = "default_headcount_multiplier")]
2201 pub headcount_multiplier: f64,
2202 #[serde(default)]
2204 pub custom_departments: Vec<CustomDepartmentConfig>,
2205}
2206
2207fn default_headcount_multiplier() -> f64 {
2208 1.0
2209}
2210
2211impl Default for DepartmentConfig {
2212 fn default() -> Self {
2213 Self {
2214 enabled: false,
2215 headcount_multiplier: default_headcount_multiplier(),
2216 custom_departments: Vec::new(),
2217 }
2218 }
2219}
2220
2221#[derive(Debug, Clone, Serialize, Deserialize)]
2223pub struct CustomDepartmentConfig {
2224 pub code: String,
2226 pub name: String,
2228 #[serde(default)]
2230 pub cost_center: Option<String>,
2231 #[serde(default)]
2233 pub primary_processes: Vec<String>,
2234 #[serde(default)]
2236 pub parent_code: Option<String>,
2237}
2238
2239#[derive(Debug, Clone, Default, Serialize, Deserialize)]
2245pub struct MasterDataConfig {
2246 #[serde(default)]
2248 pub vendors: VendorMasterConfig,
2249 #[serde(default)]
2251 pub customers: CustomerMasterConfig,
2252 #[serde(default)]
2254 pub materials: MaterialMasterConfig,
2255 #[serde(default)]
2257 pub fixed_assets: FixedAssetMasterConfig,
2258 #[serde(default)]
2260 pub employees: EmployeeMasterConfig,
2261 #[serde(default)]
2263 pub cost_centers: CostCenterMasterConfig,
2264}
2265
2266#[derive(Debug, Clone, Serialize, Deserialize)]
2268pub struct VendorMasterConfig {
2269 #[serde(default = "default_vendor_count")]
2271 pub count: usize,
2272 #[serde(default = "default_intercompany_percent")]
2274 pub intercompany_percent: f64,
2275 #[serde(default)]
2277 pub payment_terms_distribution: PaymentTermsDistribution,
2278 #[serde(default)]
2280 pub behavior_distribution: VendorBehaviorDistribution,
2281 #[serde(default = "default_true")]
2283 pub generate_bank_accounts: bool,
2284 #[serde(default = "default_true")]
2286 pub generate_tax_ids: bool,
2287}
2288
2289fn default_vendor_count() -> usize {
2290 500
2291}
2292
2293fn default_intercompany_percent() -> f64 {
2294 0.05
2295}
2296
2297impl Default for VendorMasterConfig {
2298 fn default() -> Self {
2299 Self {
2300 count: default_vendor_count(),
2301 intercompany_percent: default_intercompany_percent(),
2302 payment_terms_distribution: PaymentTermsDistribution::default(),
2303 behavior_distribution: VendorBehaviorDistribution::default(),
2304 generate_bank_accounts: true,
2305 generate_tax_ids: true,
2306 }
2307 }
2308}
2309
2310#[derive(Debug, Clone, Serialize, Deserialize)]
2312pub struct PaymentTermsDistribution {
2313 pub net_30: f64,
2315 pub net_60: f64,
2317 pub net_90: f64,
2319 pub two_ten_net_30: f64,
2321 pub due_on_receipt: f64,
2323 pub end_of_month: f64,
2325}
2326
2327impl Default for PaymentTermsDistribution {
2328 fn default() -> Self {
2329 Self {
2330 net_30: 0.40,
2331 net_60: 0.20,
2332 net_90: 0.10,
2333 two_ten_net_30: 0.15,
2334 due_on_receipt: 0.05,
2335 end_of_month: 0.10,
2336 }
2337 }
2338}
2339
2340#[derive(Debug, Clone, Serialize, Deserialize)]
2342pub struct VendorBehaviorDistribution {
2343 pub reliable: f64,
2345 pub sometimes_late: f64,
2347 pub inconsistent_quality: f64,
2349 pub premium: f64,
2351 pub budget: f64,
2353}
2354
2355impl Default for VendorBehaviorDistribution {
2356 fn default() -> Self {
2357 Self {
2358 reliable: 0.50,
2359 sometimes_late: 0.20,
2360 inconsistent_quality: 0.10,
2361 premium: 0.10,
2362 budget: 0.10,
2363 }
2364 }
2365}
2366
2367#[derive(Debug, Clone, Serialize, Deserialize)]
2369pub struct CustomerMasterConfig {
2370 #[serde(default = "default_customer_count")]
2372 pub count: usize,
2373 #[serde(default = "default_intercompany_percent")]
2375 pub intercompany_percent: f64,
2376 #[serde(default)]
2378 pub credit_rating_distribution: CreditRatingDistribution,
2379 #[serde(default)]
2381 pub payment_behavior_distribution: PaymentBehaviorDistribution,
2382 #[serde(default = "default_true")]
2384 pub generate_credit_limits: bool,
2385}
2386
2387fn default_customer_count() -> usize {
2388 2000
2389}
2390
2391impl Default for CustomerMasterConfig {
2392 fn default() -> Self {
2393 Self {
2394 count: default_customer_count(),
2395 intercompany_percent: default_intercompany_percent(),
2396 credit_rating_distribution: CreditRatingDistribution::default(),
2397 payment_behavior_distribution: PaymentBehaviorDistribution::default(),
2398 generate_credit_limits: true,
2399 }
2400 }
2401}
2402
2403#[derive(Debug, Clone, Serialize, Deserialize)]
2405pub struct CreditRatingDistribution {
2406 pub aaa: f64,
2408 pub aa: f64,
2410 pub a: f64,
2412 pub bbb: f64,
2414 pub bb: f64,
2416 pub b: f64,
2418 pub below_b: f64,
2420}
2421
2422impl Default for CreditRatingDistribution {
2423 fn default() -> Self {
2424 Self {
2425 aaa: 0.05,
2426 aa: 0.10,
2427 a: 0.20,
2428 bbb: 0.30,
2429 bb: 0.20,
2430 b: 0.10,
2431 below_b: 0.05,
2432 }
2433 }
2434}
2435
2436#[derive(Debug, Clone, Serialize, Deserialize)]
2438pub struct PaymentBehaviorDistribution {
2439 pub early_payer: f64,
2441 pub on_time: f64,
2443 pub occasional_late: f64,
2445 pub frequent_late: f64,
2447 pub discount_taker: f64,
2449}
2450
2451impl Default for PaymentBehaviorDistribution {
2452 fn default() -> Self {
2453 Self {
2454 early_payer: 0.10,
2455 on_time: 0.50,
2456 occasional_late: 0.25,
2457 frequent_late: 0.10,
2458 discount_taker: 0.05,
2459 }
2460 }
2461}
2462
2463#[derive(Debug, Clone, Serialize, Deserialize)]
2465pub struct MaterialMasterConfig {
2466 #[serde(default = "default_material_count")]
2468 pub count: usize,
2469 #[serde(default)]
2471 pub type_distribution: MaterialTypeDistribution,
2472 #[serde(default)]
2474 pub valuation_distribution: ValuationMethodDistribution,
2475 #[serde(default = "default_bom_percent")]
2477 pub bom_percent: f64,
2478 #[serde(default = "default_max_bom_depth")]
2480 pub max_bom_depth: u8,
2481}
2482
2483fn default_material_count() -> usize {
2484 5000
2485}
2486
2487fn default_bom_percent() -> f64 {
2488 0.20
2489}
2490
2491fn default_max_bom_depth() -> u8 {
2492 3
2493}
2494
2495impl Default for MaterialMasterConfig {
2496 fn default() -> Self {
2497 Self {
2498 count: default_material_count(),
2499 type_distribution: MaterialTypeDistribution::default(),
2500 valuation_distribution: ValuationMethodDistribution::default(),
2501 bom_percent: default_bom_percent(),
2502 max_bom_depth: default_max_bom_depth(),
2503 }
2504 }
2505}
2506
2507#[derive(Debug, Clone, Serialize, Deserialize)]
2509pub struct MaterialTypeDistribution {
2510 pub raw_material: f64,
2512 pub semi_finished: f64,
2514 pub finished_good: f64,
2516 pub trading_good: f64,
2518 pub operating_supply: f64,
2520 pub service: f64,
2522}
2523
2524impl Default for MaterialTypeDistribution {
2525 fn default() -> Self {
2526 Self {
2527 raw_material: 0.30,
2528 semi_finished: 0.15,
2529 finished_good: 0.25,
2530 trading_good: 0.15,
2531 operating_supply: 0.10,
2532 service: 0.05,
2533 }
2534 }
2535}
2536
2537#[derive(Debug, Clone, Serialize, Deserialize)]
2539pub struct ValuationMethodDistribution {
2540 pub standard_cost: f64,
2542 pub moving_average: f64,
2544 pub fifo: f64,
2546 pub lifo: f64,
2548}
2549
2550impl Default for ValuationMethodDistribution {
2551 fn default() -> Self {
2552 Self {
2553 standard_cost: 0.50,
2554 moving_average: 0.30,
2555 fifo: 0.15,
2556 lifo: 0.05,
2557 }
2558 }
2559}
2560
2561#[derive(Debug, Clone, Serialize, Deserialize)]
2563pub struct FixedAssetMasterConfig {
2564 #[serde(default = "default_asset_count")]
2566 pub count: usize,
2567 #[serde(default)]
2569 pub class_distribution: AssetClassDistribution,
2570 #[serde(default)]
2572 pub depreciation_distribution: DepreciationMethodDistribution,
2573 #[serde(default = "default_fully_depreciated_percent")]
2575 pub fully_depreciated_percent: f64,
2576 #[serde(default = "default_true")]
2578 pub generate_acquisition_history: bool,
2579}
2580
2581fn default_asset_count() -> usize {
2582 800
2583}
2584
2585fn default_fully_depreciated_percent() -> f64 {
2586 0.15
2587}
2588
2589impl Default for FixedAssetMasterConfig {
2590 fn default() -> Self {
2591 Self {
2592 count: default_asset_count(),
2593 class_distribution: AssetClassDistribution::default(),
2594 depreciation_distribution: DepreciationMethodDistribution::default(),
2595 fully_depreciated_percent: default_fully_depreciated_percent(),
2596 generate_acquisition_history: true,
2597 }
2598 }
2599}
2600
2601#[derive(Debug, Clone, Serialize, Deserialize)]
2603pub struct AssetClassDistribution {
2604 pub buildings: f64,
2606 pub machinery: f64,
2608 pub vehicles: f64,
2610 pub it_equipment: f64,
2612 pub furniture: f64,
2614 pub land: f64,
2616 pub leasehold: f64,
2618}
2619
2620impl Default for AssetClassDistribution {
2621 fn default() -> Self {
2622 Self {
2623 buildings: 0.15,
2624 machinery: 0.30,
2625 vehicles: 0.15,
2626 it_equipment: 0.20,
2627 furniture: 0.10,
2628 land: 0.05,
2629 leasehold: 0.05,
2630 }
2631 }
2632}
2633
2634#[derive(Debug, Clone, Serialize, Deserialize)]
2636pub struct DepreciationMethodDistribution {
2637 pub straight_line: f64,
2639 pub declining_balance: f64,
2641 pub double_declining: f64,
2643 pub sum_of_years: f64,
2645 pub units_of_production: f64,
2647}
2648
2649impl Default for DepreciationMethodDistribution {
2650 fn default() -> Self {
2651 Self {
2652 straight_line: 0.60,
2653 declining_balance: 0.20,
2654 double_declining: 0.10,
2655 sum_of_years: 0.05,
2656 units_of_production: 0.05,
2657 }
2658 }
2659}
2660
2661#[derive(Debug, Clone, Serialize, Deserialize)]
2663pub struct EmployeeMasterConfig {
2664 #[serde(default = "default_employee_count")]
2666 pub count: usize,
2667 #[serde(default = "default_true")]
2669 pub generate_hierarchy: bool,
2670 #[serde(default = "default_hierarchy_depth")]
2672 pub max_hierarchy_depth: u8,
2673 #[serde(default = "default_span_of_control")]
2675 pub average_span_of_control: f64,
2676 #[serde(default)]
2678 pub approval_limits: ApprovalLimitDistribution,
2679 #[serde(default)]
2681 pub department_distribution: EmployeeDepartmentDistribution,
2682}
2683
2684fn default_employee_count() -> usize {
2685 1500
2686}
2687
2688fn default_hierarchy_depth() -> u8 {
2689 6
2690}
2691
2692fn default_span_of_control() -> f64 {
2693 5.0
2694}
2695
2696impl Default for EmployeeMasterConfig {
2697 fn default() -> Self {
2698 Self {
2699 count: default_employee_count(),
2700 generate_hierarchy: true,
2701 max_hierarchy_depth: default_hierarchy_depth(),
2702 average_span_of_control: default_span_of_control(),
2703 approval_limits: ApprovalLimitDistribution::default(),
2704 department_distribution: EmployeeDepartmentDistribution::default(),
2705 }
2706 }
2707}
2708
2709#[derive(Debug, Clone, Serialize, Deserialize)]
2711pub struct ApprovalLimitDistribution {
2712 #[serde(default = "default_staff_limit")]
2714 pub staff: f64,
2715 #[serde(default = "default_senior_limit")]
2717 pub senior: f64,
2718 #[serde(default = "default_manager_limit")]
2720 pub manager: f64,
2721 #[serde(default = "default_director_limit")]
2723 pub director: f64,
2724 #[serde(default = "default_vp_limit")]
2726 pub vp: f64,
2727 #[serde(default = "default_executive_limit")]
2729 pub executive: f64,
2730}
2731
2732fn default_staff_limit() -> f64 {
2733 1000.0
2734}
2735fn default_senior_limit() -> f64 {
2736 5000.0
2737}
2738fn default_manager_limit() -> f64 {
2739 25000.0
2740}
2741fn default_director_limit() -> f64 {
2742 100000.0
2743}
2744fn default_vp_limit() -> f64 {
2745 500000.0
2746}
2747fn default_executive_limit() -> f64 {
2748 f64::INFINITY
2749}
2750
2751impl Default for ApprovalLimitDistribution {
2752 fn default() -> Self {
2753 Self {
2754 staff: default_staff_limit(),
2755 senior: default_senior_limit(),
2756 manager: default_manager_limit(),
2757 director: default_director_limit(),
2758 vp: default_vp_limit(),
2759 executive: default_executive_limit(),
2760 }
2761 }
2762}
2763
2764#[derive(Debug, Clone, Serialize, Deserialize)]
2766pub struct EmployeeDepartmentDistribution {
2767 pub finance: f64,
2769 pub procurement: f64,
2771 pub sales: f64,
2773 pub warehouse: f64,
2775 pub it: f64,
2777 pub hr: f64,
2779 pub operations: f64,
2781 pub executive: f64,
2783}
2784
2785impl Default for EmployeeDepartmentDistribution {
2786 fn default() -> Self {
2787 Self {
2788 finance: 0.12,
2789 procurement: 0.10,
2790 sales: 0.25,
2791 warehouse: 0.15,
2792 it: 0.10,
2793 hr: 0.05,
2794 operations: 0.20,
2795 executive: 0.03,
2796 }
2797 }
2798}
2799
2800#[derive(Debug, Clone, Serialize, Deserialize)]
2802pub struct CostCenterMasterConfig {
2803 #[serde(default = "default_cost_center_count")]
2805 pub count: usize,
2806 #[serde(default = "default_true")]
2808 pub generate_hierarchy: bool,
2809 #[serde(default = "default_cc_hierarchy_depth")]
2811 pub max_hierarchy_depth: u8,
2812}
2813
2814fn default_cost_center_count() -> usize {
2815 50
2816}
2817
2818fn default_cc_hierarchy_depth() -> u8 {
2819 3
2820}
2821
2822impl Default for CostCenterMasterConfig {
2823 fn default() -> Self {
2824 Self {
2825 count: default_cost_center_count(),
2826 generate_hierarchy: true,
2827 max_hierarchy_depth: default_cc_hierarchy_depth(),
2828 }
2829 }
2830}
2831
2832#[derive(Debug, Clone, Serialize, Deserialize)]
2838pub struct DocumentFlowConfig {
2839 #[serde(default)]
2841 pub p2p: P2PFlowConfig,
2842 #[serde(default)]
2844 pub o2c: O2CFlowConfig,
2845 #[serde(default = "default_true")]
2847 pub generate_document_references: bool,
2848 #[serde(default)]
2850 pub export_flow_graph: bool,
2851}
2852
2853impl Default for DocumentFlowConfig {
2854 fn default() -> Self {
2855 Self {
2856 p2p: P2PFlowConfig::default(),
2857 o2c: O2CFlowConfig::default(),
2858 generate_document_references: true,
2859 export_flow_graph: false,
2860 }
2861 }
2862}
2863
2864#[derive(Debug, Clone, Serialize, Deserialize)]
2866pub struct P2PFlowConfig {
2867 #[serde(default = "default_true")]
2869 pub enabled: bool,
2870 #[serde(default = "default_three_way_match_rate")]
2872 pub three_way_match_rate: f64,
2873 #[serde(default = "default_partial_delivery_rate")]
2875 pub partial_delivery_rate: f64,
2876 #[serde(default = "default_price_variance_rate")]
2878 pub price_variance_rate: f64,
2879 #[serde(default = "default_max_price_variance")]
2881 pub max_price_variance_percent: f64,
2882 #[serde(default = "default_quantity_variance_rate")]
2884 pub quantity_variance_rate: f64,
2885 #[serde(default = "default_po_to_gr_days")]
2887 pub average_po_to_gr_days: u32,
2888 #[serde(default = "default_gr_to_invoice_days")]
2890 pub average_gr_to_invoice_days: u32,
2891 #[serde(default = "default_invoice_to_payment_days")]
2893 pub average_invoice_to_payment_days: u32,
2894 #[serde(default)]
2896 pub line_count_distribution: DocumentLineCountDistribution,
2897 #[serde(default)]
2899 pub payment_behavior: P2PPaymentBehaviorConfig,
2900 #[serde(default)]
2902 pub over_delivery_rate: Option<f64>,
2903 #[serde(default)]
2905 pub early_payment_discount_rate: Option<f64>,
2906}
2907
2908fn default_three_way_match_rate() -> f64 {
2909 0.95
2910}
2911
2912fn default_partial_delivery_rate() -> f64 {
2913 0.15
2914}
2915
2916fn default_price_variance_rate() -> f64 {
2917 0.08
2918}
2919
2920fn default_max_price_variance() -> f64 {
2921 0.05
2922}
2923
2924fn default_quantity_variance_rate() -> f64 {
2925 0.05
2926}
2927
2928fn default_po_to_gr_days() -> u32 {
2929 14
2930}
2931
2932fn default_gr_to_invoice_days() -> u32 {
2933 5
2934}
2935
2936fn default_invoice_to_payment_days() -> u32 {
2937 30
2938}
2939
2940impl Default for P2PFlowConfig {
2941 fn default() -> Self {
2942 Self {
2943 enabled: true,
2944 three_way_match_rate: default_three_way_match_rate(),
2945 partial_delivery_rate: default_partial_delivery_rate(),
2946 price_variance_rate: default_price_variance_rate(),
2947 max_price_variance_percent: default_max_price_variance(),
2948 quantity_variance_rate: default_quantity_variance_rate(),
2949 average_po_to_gr_days: default_po_to_gr_days(),
2950 average_gr_to_invoice_days: default_gr_to_invoice_days(),
2951 average_invoice_to_payment_days: default_invoice_to_payment_days(),
2952 line_count_distribution: DocumentLineCountDistribution::default(),
2953 payment_behavior: P2PPaymentBehaviorConfig::default(),
2954 over_delivery_rate: None,
2955 early_payment_discount_rate: None,
2956 }
2957 }
2958}
2959
2960#[derive(Debug, Clone, Serialize, Deserialize)]
2966pub struct P2PPaymentBehaviorConfig {
2967 #[serde(default = "default_p2p_late_payment_rate")]
2969 pub late_payment_rate: f64,
2970 #[serde(default)]
2972 pub late_payment_days_distribution: LatePaymentDaysDistribution,
2973 #[serde(default = "default_p2p_partial_payment_rate")]
2975 pub partial_payment_rate: f64,
2976 #[serde(default = "default_p2p_payment_correction_rate")]
2978 pub payment_correction_rate: f64,
2979 #[serde(default = "default_p2p_avg_days_until_remainder")]
2981 pub avg_days_until_remainder: u32,
2982}
2983
2984fn default_p2p_late_payment_rate() -> f64 {
2985 0.15
2986}
2987
2988fn default_p2p_partial_payment_rate() -> f64 {
2989 0.05
2990}
2991
2992fn default_p2p_payment_correction_rate() -> f64 {
2993 0.02
2994}
2995
2996fn default_p2p_avg_days_until_remainder() -> u32 {
2997 30
2998}
2999
3000impl Default for P2PPaymentBehaviorConfig {
3001 fn default() -> Self {
3002 Self {
3003 late_payment_rate: default_p2p_late_payment_rate(),
3004 late_payment_days_distribution: LatePaymentDaysDistribution::default(),
3005 partial_payment_rate: default_p2p_partial_payment_rate(),
3006 payment_correction_rate: default_p2p_payment_correction_rate(),
3007 avg_days_until_remainder: default_p2p_avg_days_until_remainder(),
3008 }
3009 }
3010}
3011
3012#[derive(Debug, Clone, Serialize, Deserialize)]
3014pub struct LatePaymentDaysDistribution {
3015 #[serde(default = "default_slightly_late")]
3017 pub slightly_late_1_to_7: f64,
3018 #[serde(default = "default_late_8_14")]
3020 pub late_8_to_14: f64,
3021 #[serde(default = "default_very_late")]
3023 pub very_late_15_to_30: f64,
3024 #[serde(default = "default_severely_late")]
3026 pub severely_late_31_to_60: f64,
3027 #[serde(default = "default_extremely_late")]
3029 pub extremely_late_over_60: f64,
3030}
3031
3032fn default_slightly_late() -> f64 {
3033 0.50
3034}
3035
3036fn default_late_8_14() -> f64 {
3037 0.25
3038}
3039
3040fn default_very_late() -> f64 {
3041 0.15
3042}
3043
3044fn default_severely_late() -> f64 {
3045 0.07
3046}
3047
3048fn default_extremely_late() -> f64 {
3049 0.03
3050}
3051
3052impl Default for LatePaymentDaysDistribution {
3053 fn default() -> Self {
3054 Self {
3055 slightly_late_1_to_7: default_slightly_late(),
3056 late_8_to_14: default_late_8_14(),
3057 very_late_15_to_30: default_very_late(),
3058 severely_late_31_to_60: default_severely_late(),
3059 extremely_late_over_60: default_extremely_late(),
3060 }
3061 }
3062}
3063
3064#[derive(Debug, Clone, Serialize, Deserialize)]
3066pub struct O2CFlowConfig {
3067 #[serde(default = "default_true")]
3069 pub enabled: bool,
3070 #[serde(default = "default_credit_check_failure_rate")]
3072 pub credit_check_failure_rate: f64,
3073 #[serde(default = "default_partial_shipment_rate")]
3075 pub partial_shipment_rate: f64,
3076 #[serde(default = "default_return_rate")]
3078 pub return_rate: f64,
3079 #[serde(default = "default_bad_debt_rate")]
3081 pub bad_debt_rate: f64,
3082 #[serde(default = "default_so_to_delivery_days")]
3084 pub average_so_to_delivery_days: u32,
3085 #[serde(default = "default_delivery_to_invoice_days")]
3087 pub average_delivery_to_invoice_days: u32,
3088 #[serde(default = "default_invoice_to_receipt_days")]
3090 pub average_invoice_to_receipt_days: u32,
3091 #[serde(default)]
3093 pub line_count_distribution: DocumentLineCountDistribution,
3094 #[serde(default)]
3096 pub cash_discount: CashDiscountConfig,
3097 #[serde(default)]
3099 pub payment_behavior: O2CPaymentBehaviorConfig,
3100 #[serde(default)]
3102 pub late_payment_rate: Option<f64>,
3103}
3104
3105fn default_credit_check_failure_rate() -> f64 {
3106 0.02
3107}
3108
3109fn default_partial_shipment_rate() -> f64 {
3110 0.10
3111}
3112
3113fn default_return_rate() -> f64 {
3114 0.03
3115}
3116
3117fn default_bad_debt_rate() -> f64 {
3118 0.01
3119}
3120
3121fn default_so_to_delivery_days() -> u32 {
3122 7
3123}
3124
3125fn default_delivery_to_invoice_days() -> u32 {
3126 1
3127}
3128
3129fn default_invoice_to_receipt_days() -> u32 {
3130 45
3131}
3132
3133impl Default for O2CFlowConfig {
3134 fn default() -> Self {
3135 Self {
3136 enabled: true,
3137 credit_check_failure_rate: default_credit_check_failure_rate(),
3138 partial_shipment_rate: default_partial_shipment_rate(),
3139 return_rate: default_return_rate(),
3140 bad_debt_rate: default_bad_debt_rate(),
3141 average_so_to_delivery_days: default_so_to_delivery_days(),
3142 average_delivery_to_invoice_days: default_delivery_to_invoice_days(),
3143 average_invoice_to_receipt_days: default_invoice_to_receipt_days(),
3144 line_count_distribution: DocumentLineCountDistribution::default(),
3145 cash_discount: CashDiscountConfig::default(),
3146 payment_behavior: O2CPaymentBehaviorConfig::default(),
3147 late_payment_rate: None,
3148 }
3149 }
3150}
3151
3152#[derive(Debug, Clone, Serialize, Deserialize, Default)]
3158pub struct O2CPaymentBehaviorConfig {
3159 #[serde(default)]
3161 pub dunning: DunningConfig,
3162 #[serde(default)]
3164 pub partial_payments: PartialPaymentConfig,
3165 #[serde(default)]
3167 pub short_payments: ShortPaymentConfig,
3168 #[serde(default)]
3170 pub on_account_payments: OnAccountPaymentConfig,
3171 #[serde(default)]
3173 pub payment_corrections: PaymentCorrectionConfig,
3174}
3175
3176#[derive(Debug, Clone, Serialize, Deserialize)]
3178pub struct DunningConfig {
3179 #[serde(default)]
3181 pub enabled: bool,
3182 #[serde(default = "default_dunning_level_1_days")]
3184 pub level_1_days_overdue: u32,
3185 #[serde(default = "default_dunning_level_2_days")]
3187 pub level_2_days_overdue: u32,
3188 #[serde(default = "default_dunning_level_3_days")]
3190 pub level_3_days_overdue: u32,
3191 #[serde(default = "default_collection_days")]
3193 pub collection_days_overdue: u32,
3194 #[serde(default)]
3196 pub payment_after_dunning_rates: DunningPaymentRates,
3197 #[serde(default = "default_dunning_block_rate")]
3199 pub dunning_block_rate: f64,
3200 #[serde(default = "default_dunning_interest_rate")]
3202 pub interest_rate_per_year: f64,
3203 #[serde(default = "default_dunning_charge")]
3205 pub dunning_charge: f64,
3206}
3207
3208fn default_dunning_level_1_days() -> u32 {
3209 14
3210}
3211
3212fn default_dunning_level_2_days() -> u32 {
3213 28
3214}
3215
3216fn default_dunning_level_3_days() -> u32 {
3217 42
3218}
3219
3220fn default_collection_days() -> u32 {
3221 60
3222}
3223
3224fn default_dunning_block_rate() -> f64 {
3225 0.05
3226}
3227
3228fn default_dunning_interest_rate() -> f64 {
3229 0.09
3230}
3231
3232fn default_dunning_charge() -> f64 {
3233 25.0
3234}
3235
3236impl Default for DunningConfig {
3237 fn default() -> Self {
3238 Self {
3239 enabled: false,
3240 level_1_days_overdue: default_dunning_level_1_days(),
3241 level_2_days_overdue: default_dunning_level_2_days(),
3242 level_3_days_overdue: default_dunning_level_3_days(),
3243 collection_days_overdue: default_collection_days(),
3244 payment_after_dunning_rates: DunningPaymentRates::default(),
3245 dunning_block_rate: default_dunning_block_rate(),
3246 interest_rate_per_year: default_dunning_interest_rate(),
3247 dunning_charge: default_dunning_charge(),
3248 }
3249 }
3250}
3251
3252#[derive(Debug, Clone, Serialize, Deserialize)]
3254pub struct DunningPaymentRates {
3255 #[serde(default = "default_after_level_1")]
3257 pub after_level_1: f64,
3258 #[serde(default = "default_after_level_2")]
3260 pub after_level_2: f64,
3261 #[serde(default = "default_after_level_3")]
3263 pub after_level_3: f64,
3264 #[serde(default = "default_during_collection")]
3266 pub during_collection: f64,
3267 #[serde(default = "default_never_pay")]
3269 pub never_pay: f64,
3270}
3271
3272fn default_after_level_1() -> f64 {
3273 0.40
3274}
3275
3276fn default_after_level_2() -> f64 {
3277 0.30
3278}
3279
3280fn default_after_level_3() -> f64 {
3281 0.15
3282}
3283
3284fn default_during_collection() -> f64 {
3285 0.05
3286}
3287
3288fn default_never_pay() -> f64 {
3289 0.10
3290}
3291
3292impl Default for DunningPaymentRates {
3293 fn default() -> Self {
3294 Self {
3295 after_level_1: default_after_level_1(),
3296 after_level_2: default_after_level_2(),
3297 after_level_3: default_after_level_3(),
3298 during_collection: default_during_collection(),
3299 never_pay: default_never_pay(),
3300 }
3301 }
3302}
3303
3304#[derive(Debug, Clone, Serialize, Deserialize)]
3306pub struct PartialPaymentConfig {
3307 #[serde(default = "default_partial_payment_rate")]
3309 pub rate: f64,
3310 #[serde(default)]
3312 pub percentage_distribution: PartialPaymentPercentageDistribution,
3313 #[serde(default = "default_avg_days_until_remainder")]
3315 pub avg_days_until_remainder: u32,
3316}
3317
3318fn default_partial_payment_rate() -> f64 {
3319 0.08
3320}
3321
3322fn default_avg_days_until_remainder() -> u32 {
3323 30
3324}
3325
3326impl Default for PartialPaymentConfig {
3327 fn default() -> Self {
3328 Self {
3329 rate: default_partial_payment_rate(),
3330 percentage_distribution: PartialPaymentPercentageDistribution::default(),
3331 avg_days_until_remainder: default_avg_days_until_remainder(),
3332 }
3333 }
3334}
3335
3336#[derive(Debug, Clone, Serialize, Deserialize)]
3338pub struct PartialPaymentPercentageDistribution {
3339 #[serde(default = "default_partial_25")]
3341 pub pay_25_percent: f64,
3342 #[serde(default = "default_partial_50")]
3344 pub pay_50_percent: f64,
3345 #[serde(default = "default_partial_75")]
3347 pub pay_75_percent: f64,
3348 #[serde(default = "default_partial_random")]
3350 pub pay_random_percent: f64,
3351}
3352
3353fn default_partial_25() -> f64 {
3354 0.15
3355}
3356
3357fn default_partial_50() -> f64 {
3358 0.50
3359}
3360
3361fn default_partial_75() -> f64 {
3362 0.25
3363}
3364
3365fn default_partial_random() -> f64 {
3366 0.10
3367}
3368
3369impl Default for PartialPaymentPercentageDistribution {
3370 fn default() -> Self {
3371 Self {
3372 pay_25_percent: default_partial_25(),
3373 pay_50_percent: default_partial_50(),
3374 pay_75_percent: default_partial_75(),
3375 pay_random_percent: default_partial_random(),
3376 }
3377 }
3378}
3379
3380#[derive(Debug, Clone, Serialize, Deserialize)]
3382pub struct ShortPaymentConfig {
3383 #[serde(default = "default_short_payment_rate")]
3385 pub rate: f64,
3386 #[serde(default)]
3388 pub reason_distribution: ShortPaymentReasonDistribution,
3389 #[serde(default = "default_max_short_percent")]
3391 pub max_short_percent: f64,
3392}
3393
3394fn default_short_payment_rate() -> f64 {
3395 0.03
3396}
3397
3398fn default_max_short_percent() -> f64 {
3399 0.10
3400}
3401
3402impl Default for ShortPaymentConfig {
3403 fn default() -> Self {
3404 Self {
3405 rate: default_short_payment_rate(),
3406 reason_distribution: ShortPaymentReasonDistribution::default(),
3407 max_short_percent: default_max_short_percent(),
3408 }
3409 }
3410}
3411
3412#[derive(Debug, Clone, Serialize, Deserialize)]
3414pub struct ShortPaymentReasonDistribution {
3415 #[serde(default = "default_pricing_dispute")]
3417 pub pricing_dispute: f64,
3418 #[serde(default = "default_quality_issue")]
3420 pub quality_issue: f64,
3421 #[serde(default = "default_quantity_discrepancy")]
3423 pub quantity_discrepancy: f64,
3424 #[serde(default = "default_unauthorized_deduction")]
3426 pub unauthorized_deduction: f64,
3427 #[serde(default = "default_incorrect_discount")]
3429 pub incorrect_discount: f64,
3430}
3431
3432fn default_pricing_dispute() -> f64 {
3433 0.30
3434}
3435
3436fn default_quality_issue() -> f64 {
3437 0.20
3438}
3439
3440fn default_quantity_discrepancy() -> f64 {
3441 0.20
3442}
3443
3444fn default_unauthorized_deduction() -> f64 {
3445 0.15
3446}
3447
3448fn default_incorrect_discount() -> f64 {
3449 0.15
3450}
3451
3452impl Default for ShortPaymentReasonDistribution {
3453 fn default() -> Self {
3454 Self {
3455 pricing_dispute: default_pricing_dispute(),
3456 quality_issue: default_quality_issue(),
3457 quantity_discrepancy: default_quantity_discrepancy(),
3458 unauthorized_deduction: default_unauthorized_deduction(),
3459 incorrect_discount: default_incorrect_discount(),
3460 }
3461 }
3462}
3463
3464#[derive(Debug, Clone, Serialize, Deserialize)]
3466pub struct OnAccountPaymentConfig {
3467 #[serde(default = "default_on_account_rate")]
3469 pub rate: f64,
3470 #[serde(default = "default_avg_days_until_applied")]
3472 pub avg_days_until_applied: u32,
3473}
3474
3475fn default_on_account_rate() -> f64 {
3476 0.02
3477}
3478
3479fn default_avg_days_until_applied() -> u32 {
3480 14
3481}
3482
3483impl Default for OnAccountPaymentConfig {
3484 fn default() -> Self {
3485 Self {
3486 rate: default_on_account_rate(),
3487 avg_days_until_applied: default_avg_days_until_applied(),
3488 }
3489 }
3490}
3491
3492#[derive(Debug, Clone, Serialize, Deserialize)]
3494pub struct PaymentCorrectionConfig {
3495 #[serde(default = "default_payment_correction_rate")]
3497 pub rate: f64,
3498 #[serde(default)]
3500 pub type_distribution: PaymentCorrectionTypeDistribution,
3501}
3502
3503fn default_payment_correction_rate() -> f64 {
3504 0.02
3505}
3506
3507impl Default for PaymentCorrectionConfig {
3508 fn default() -> Self {
3509 Self {
3510 rate: default_payment_correction_rate(),
3511 type_distribution: PaymentCorrectionTypeDistribution::default(),
3512 }
3513 }
3514}
3515
3516#[derive(Debug, Clone, Serialize, Deserialize)]
3518pub struct PaymentCorrectionTypeDistribution {
3519 #[serde(default = "default_nsf_rate")]
3521 pub nsf: f64,
3522 #[serde(default = "default_chargeback_rate")]
3524 pub chargeback: f64,
3525 #[serde(default = "default_wrong_amount_rate")]
3527 pub wrong_amount: f64,
3528 #[serde(default = "default_wrong_customer_rate")]
3530 pub wrong_customer: f64,
3531 #[serde(default = "default_duplicate_payment_rate")]
3533 pub duplicate_payment: f64,
3534}
3535
3536fn default_nsf_rate() -> f64 {
3537 0.30
3538}
3539
3540fn default_chargeback_rate() -> f64 {
3541 0.20
3542}
3543
3544fn default_wrong_amount_rate() -> f64 {
3545 0.20
3546}
3547
3548fn default_wrong_customer_rate() -> f64 {
3549 0.15
3550}
3551
3552fn default_duplicate_payment_rate() -> f64 {
3553 0.15
3554}
3555
3556impl Default for PaymentCorrectionTypeDistribution {
3557 fn default() -> Self {
3558 Self {
3559 nsf: default_nsf_rate(),
3560 chargeback: default_chargeback_rate(),
3561 wrong_amount: default_wrong_amount_rate(),
3562 wrong_customer: default_wrong_customer_rate(),
3563 duplicate_payment: default_duplicate_payment_rate(),
3564 }
3565 }
3566}
3567
3568#[derive(Debug, Clone, Serialize, Deserialize)]
3570pub struct DocumentLineCountDistribution {
3571 #[serde(default = "default_min_lines")]
3573 pub min_lines: u32,
3574 #[serde(default = "default_max_lines")]
3576 pub max_lines: u32,
3577 #[serde(default = "default_mode_lines")]
3579 pub mode_lines: u32,
3580}
3581
3582fn default_min_lines() -> u32 {
3583 1
3584}
3585
3586fn default_max_lines() -> u32 {
3587 20
3588}
3589
3590fn default_mode_lines() -> u32 {
3591 3
3592}
3593
3594impl Default for DocumentLineCountDistribution {
3595 fn default() -> Self {
3596 Self {
3597 min_lines: default_min_lines(),
3598 max_lines: default_max_lines(),
3599 mode_lines: default_mode_lines(),
3600 }
3601 }
3602}
3603
3604#[derive(Debug, Clone, Serialize, Deserialize)]
3606pub struct CashDiscountConfig {
3607 #[serde(default = "default_discount_eligible_rate")]
3609 pub eligible_rate: f64,
3610 #[serde(default = "default_discount_taken_rate")]
3612 pub taken_rate: f64,
3613 #[serde(default = "default_discount_percent")]
3615 pub discount_percent: f64,
3616 #[serde(default = "default_discount_days")]
3618 pub discount_days: u32,
3619}
3620
3621fn default_discount_eligible_rate() -> f64 {
3622 0.30
3623}
3624
3625fn default_discount_taken_rate() -> f64 {
3626 0.60
3627}
3628
3629fn default_discount_percent() -> f64 {
3630 0.02
3631}
3632
3633fn default_discount_days() -> u32 {
3634 10
3635}
3636
3637impl Default for CashDiscountConfig {
3638 fn default() -> Self {
3639 Self {
3640 eligible_rate: default_discount_eligible_rate(),
3641 taken_rate: default_discount_taken_rate(),
3642 discount_percent: default_discount_percent(),
3643 discount_days: default_discount_days(),
3644 }
3645 }
3646}
3647
3648#[derive(Debug, Clone, Serialize, Deserialize)]
3654pub struct IntercompanyConfig {
3655 #[serde(default)]
3657 pub enabled: bool,
3658 #[serde(default = "default_ic_transaction_rate")]
3660 pub ic_transaction_rate: f64,
3661 #[serde(default)]
3663 pub transfer_pricing_method: TransferPricingMethod,
3664 #[serde(default = "default_markup_percent")]
3666 pub markup_percent: f64,
3667 #[serde(default = "default_true")]
3669 pub generate_matched_pairs: bool,
3670 #[serde(default)]
3672 pub transaction_type_distribution: ICTransactionTypeDistribution,
3673 #[serde(default)]
3675 pub generate_eliminations: bool,
3676}
3677
3678fn default_ic_transaction_rate() -> f64 {
3679 0.15
3680}
3681
3682fn default_markup_percent() -> f64 {
3683 0.05
3684}
3685
3686impl Default for IntercompanyConfig {
3687 fn default() -> Self {
3688 Self {
3689 enabled: false,
3690 ic_transaction_rate: default_ic_transaction_rate(),
3691 transfer_pricing_method: TransferPricingMethod::default(),
3692 markup_percent: default_markup_percent(),
3693 generate_matched_pairs: true,
3694 transaction_type_distribution: ICTransactionTypeDistribution::default(),
3695 generate_eliminations: false,
3696 }
3697 }
3698}
3699
3700#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
3702#[serde(rename_all = "snake_case")]
3703pub enum TransferPricingMethod {
3704 #[default]
3706 CostPlus,
3707 ComparableUncontrolled,
3709 ResalePrice,
3711 TransactionalNetMargin,
3713 ProfitSplit,
3715}
3716
3717#[derive(Debug, Clone, Serialize, Deserialize)]
3719pub struct ICTransactionTypeDistribution {
3720 pub goods_sale: f64,
3722 pub service_provided: f64,
3724 pub loan: f64,
3726 pub dividend: f64,
3728 pub management_fee: f64,
3730 pub royalty: f64,
3732 pub cost_sharing: f64,
3734}
3735
3736impl Default for ICTransactionTypeDistribution {
3737 fn default() -> Self {
3738 Self {
3739 goods_sale: 0.35,
3740 service_provided: 0.20,
3741 loan: 0.10,
3742 dividend: 0.05,
3743 management_fee: 0.15,
3744 royalty: 0.10,
3745 cost_sharing: 0.05,
3746 }
3747 }
3748}
3749
3750#[derive(Debug, Clone, Serialize, Deserialize)]
3756pub struct BalanceConfig {
3757 #[serde(default)]
3759 pub generate_opening_balances: bool,
3760 #[serde(default = "default_true")]
3762 pub generate_trial_balances: bool,
3763 #[serde(default = "default_gross_margin")]
3765 pub target_gross_margin: f64,
3766 #[serde(default = "default_dso")]
3768 pub target_dso_days: u32,
3769 #[serde(default = "default_dpo")]
3771 pub target_dpo_days: u32,
3772 #[serde(default = "default_current_ratio")]
3774 pub target_current_ratio: f64,
3775 #[serde(default = "default_debt_equity")]
3777 pub target_debt_to_equity: f64,
3778 #[serde(default = "default_true")]
3780 pub validate_balance_equation: bool,
3781 #[serde(default = "default_true")]
3783 pub reconcile_subledgers: bool,
3784}
3785
3786fn default_gross_margin() -> f64 {
3787 0.35
3788}
3789
3790fn default_dso() -> u32 {
3791 45
3792}
3793
3794fn default_dpo() -> u32 {
3795 30
3796}
3797
3798fn default_current_ratio() -> f64 {
3799 1.5
3800}
3801
3802fn default_debt_equity() -> f64 {
3803 0.5
3804}
3805
3806impl Default for BalanceConfig {
3807 fn default() -> Self {
3808 Self {
3809 generate_opening_balances: false,
3810 generate_trial_balances: true,
3811 target_gross_margin: default_gross_margin(),
3812 target_dso_days: default_dso(),
3813 target_dpo_days: default_dpo(),
3814 target_current_ratio: default_current_ratio(),
3815 target_debt_to_equity: default_debt_equity(),
3816 validate_balance_equation: true,
3817 reconcile_subledgers: true,
3818 }
3819 }
3820}
3821
3822#[derive(Debug, Clone, Serialize, Deserialize)]
3831pub struct OcpmConfig {
3832 #[serde(default)]
3834 pub enabled: bool,
3835
3836 #[serde(default = "default_true")]
3838 pub generate_lifecycle_events: bool,
3839
3840 #[serde(default = "default_true")]
3842 pub include_object_relationships: bool,
3843
3844 #[serde(default = "default_true")]
3846 pub compute_variants: bool,
3847
3848 #[serde(default)]
3850 pub max_variants: usize,
3851
3852 #[serde(default)]
3854 pub p2p_process: OcpmProcessConfig,
3855
3856 #[serde(default)]
3858 pub o2c_process: OcpmProcessConfig,
3859
3860 #[serde(default)]
3862 pub output: OcpmOutputConfig,
3863}
3864
3865impl Default for OcpmConfig {
3866 fn default() -> Self {
3867 Self {
3868 enabled: false,
3869 generate_lifecycle_events: true,
3870 include_object_relationships: true,
3871 compute_variants: true,
3872 max_variants: 0,
3873 p2p_process: OcpmProcessConfig::default(),
3874 o2c_process: OcpmProcessConfig::default(),
3875 output: OcpmOutputConfig::default(),
3876 }
3877 }
3878}
3879
3880#[derive(Debug, Clone, Serialize, Deserialize)]
3882pub struct OcpmProcessConfig {
3883 #[serde(default = "default_rework_probability")]
3885 pub rework_probability: f64,
3886
3887 #[serde(default = "default_skip_probability")]
3889 pub skip_step_probability: f64,
3890
3891 #[serde(default = "default_out_of_order_probability")]
3893 pub out_of_order_probability: f64,
3894}
3895
3896fn default_rework_probability() -> f64 {
3900 0.15
3901}
3902
3903fn default_skip_probability() -> f64 {
3904 0.10
3905}
3906
3907fn default_out_of_order_probability() -> f64 {
3908 0.08
3909}
3910
3911impl Default for OcpmProcessConfig {
3912 fn default() -> Self {
3913 Self {
3914 rework_probability: default_rework_probability(),
3915 skip_step_probability: default_skip_probability(),
3916 out_of_order_probability: default_out_of_order_probability(),
3917 }
3918 }
3919}
3920
3921#[derive(Debug, Clone, Serialize, Deserialize)]
3923pub struct OcpmOutputConfig {
3924 #[serde(default = "default_true")]
3926 pub ocel_json: bool,
3927
3928 #[serde(default)]
3930 pub ocel_xml: bool,
3931
3932 #[serde(default)]
3934 pub xes: bool,
3935
3936 #[serde(default = "default_true")]
3938 pub xes_include_lifecycle: bool,
3939
3940 #[serde(default = "default_true")]
3942 pub xes_include_resources: bool,
3943
3944 #[serde(default = "default_true")]
3946 pub flattened_csv: bool,
3947
3948 #[serde(default = "default_true")]
3950 pub event_object_csv: bool,
3951
3952 #[serde(default = "default_true")]
3954 pub object_relationship_csv: bool,
3955
3956 #[serde(default = "default_true")]
3958 pub variants_csv: bool,
3959
3960 #[serde(default)]
3962 pub export_reference_models: bool,
3963}
3964
3965impl Default for OcpmOutputConfig {
3966 fn default() -> Self {
3967 Self {
3968 ocel_json: true,
3969 ocel_xml: false,
3970 xes: false,
3971 xes_include_lifecycle: true,
3972 xes_include_resources: true,
3973 flattened_csv: true,
3974 event_object_csv: true,
3975 object_relationship_csv: true,
3976 variants_csv: true,
3977 export_reference_models: false,
3978 }
3979 }
3980}
3981
3982#[derive(Debug, Clone, Serialize, Deserialize)]
3984pub struct AuditGenerationConfig {
3985 #[serde(default)]
3987 pub enabled: bool,
3988
3989 #[serde(default = "default_true")]
3992 pub generate_workpapers: bool,
3993
3994 #[serde(default)]
3997 pub engagement_types: AuditEngagementTypesConfig,
3998
3999 #[serde(default)]
4002 pub workpapers: WorkpaperConfig,
4003
4004 #[serde(default)]
4007 pub team: AuditTeamConfig,
4008
4009 #[serde(default)]
4012 pub review: ReviewWorkflowConfig,
4013
4014 #[serde(default)]
4016 pub fsm: Option<AuditFsmConfig>,
4017}
4018
4019impl Default for AuditGenerationConfig {
4020 fn default() -> Self {
4021 Self {
4022 enabled: false,
4023 generate_workpapers: true,
4024 engagement_types: AuditEngagementTypesConfig::default(),
4025 workpapers: WorkpaperConfig::default(),
4026 team: AuditTeamConfig::default(),
4027 review: ReviewWorkflowConfig::default(),
4028 fsm: None,
4029 }
4030 }
4031}
4032
4033#[derive(Debug, Clone, Serialize, Deserialize)]
4035pub struct AuditFsmConfig {
4036 #[serde(default)]
4038 pub enabled: bool,
4039
4040 #[serde(default = "default_audit_fsm_blueprint")]
4042 pub blueprint: String,
4043
4044 #[serde(default = "default_audit_fsm_overlay")]
4046 pub overlay: String,
4047
4048 #[serde(default)]
4050 pub depth: Option<String>,
4051
4052 #[serde(default)]
4054 pub discriminators: std::collections::HashMap<String, Vec<String>>,
4055
4056 #[serde(default)]
4058 pub event_trail: AuditEventTrailConfig,
4059
4060 #[serde(default)]
4062 pub seed: Option<u64>,
4063}
4064
4065impl Default for AuditFsmConfig {
4066 fn default() -> Self {
4067 Self {
4068 enabled: false,
4069 blueprint: default_audit_fsm_blueprint(),
4070 overlay: default_audit_fsm_overlay(),
4071 depth: None,
4072 discriminators: std::collections::HashMap::new(),
4073 event_trail: AuditEventTrailConfig::default(),
4074 seed: None,
4075 }
4076 }
4077}
4078
4079fn default_audit_fsm_blueprint() -> String {
4080 "builtin:fsa".to_string()
4081}
4082
4083fn default_audit_fsm_overlay() -> String {
4084 "builtin:default".to_string()
4085}
4086
4087#[derive(Debug, Clone, Serialize, Deserialize)]
4089pub struct AuditEventTrailConfig {
4090 #[serde(default = "default_true")]
4092 pub flat_log: bool,
4093 #[serde(default)]
4095 pub ocel_projection: bool,
4096}
4097
4098impl Default for AuditEventTrailConfig {
4099 fn default() -> Self {
4100 Self {
4101 flat_log: true,
4102 ocel_projection: false,
4103 }
4104 }
4105}
4106
4107#[derive(Debug, Clone, Serialize, Deserialize)]
4109pub struct AuditEngagementTypesConfig {
4110 #[serde(default = "default_financial_audit_prob")]
4112 pub financial_statement: f64,
4113 #[serde(default = "default_sox_audit_prob")]
4115 pub sox_icfr: f64,
4116 #[serde(default = "default_integrated_audit_prob")]
4118 pub integrated: f64,
4119 #[serde(default = "default_review_prob")]
4121 pub review: f64,
4122 #[serde(default = "default_aup_prob")]
4124 pub agreed_upon_procedures: f64,
4125}
4126
4127fn default_financial_audit_prob() -> f64 {
4128 0.40
4129}
4130fn default_sox_audit_prob() -> f64 {
4131 0.20
4132}
4133fn default_integrated_audit_prob() -> f64 {
4134 0.25
4135}
4136fn default_review_prob() -> f64 {
4137 0.10
4138}
4139fn default_aup_prob() -> f64 {
4140 0.05
4141}
4142
4143impl Default for AuditEngagementTypesConfig {
4144 fn default() -> Self {
4145 Self {
4146 financial_statement: default_financial_audit_prob(),
4147 sox_icfr: default_sox_audit_prob(),
4148 integrated: default_integrated_audit_prob(),
4149 review: default_review_prob(),
4150 agreed_upon_procedures: default_aup_prob(),
4151 }
4152 }
4153}
4154
4155#[derive(Debug, Clone, Serialize, Deserialize)]
4157pub struct WorkpaperConfig {
4158 #[serde(default = "default_workpapers_per_phase")]
4160 pub average_per_phase: usize,
4161
4162 #[serde(default = "default_true")]
4164 pub include_isa_references: bool,
4165
4166 #[serde(default = "default_true")]
4168 pub include_sample_details: bool,
4169
4170 #[serde(default = "default_true")]
4172 pub include_cross_references: bool,
4173
4174 #[serde(default)]
4176 pub sampling: SamplingConfig,
4177}
4178
4179fn default_workpapers_per_phase() -> usize {
4180 5
4181}
4182
4183impl Default for WorkpaperConfig {
4184 fn default() -> Self {
4185 Self {
4186 average_per_phase: default_workpapers_per_phase(),
4187 include_isa_references: true,
4188 include_sample_details: true,
4189 include_cross_references: true,
4190 sampling: SamplingConfig::default(),
4191 }
4192 }
4193}
4194
4195#[derive(Debug, Clone, Serialize, Deserialize)]
4197pub struct SamplingConfig {
4198 #[serde(default = "default_statistical_rate")]
4200 pub statistical_rate: f64,
4201 #[serde(default = "default_judgmental_rate")]
4203 pub judgmental_rate: f64,
4204 #[serde(default = "default_haphazard_rate")]
4206 pub haphazard_rate: f64,
4207 #[serde(default = "default_complete_examination_rate")]
4209 pub complete_examination_rate: f64,
4210}
4211
4212fn default_statistical_rate() -> f64 {
4213 0.40
4214}
4215fn default_judgmental_rate() -> f64 {
4216 0.30
4217}
4218fn default_haphazard_rate() -> f64 {
4219 0.20
4220}
4221fn default_complete_examination_rate() -> f64 {
4222 0.10
4223}
4224
4225impl Default for SamplingConfig {
4226 fn default() -> Self {
4227 Self {
4228 statistical_rate: default_statistical_rate(),
4229 judgmental_rate: default_judgmental_rate(),
4230 haphazard_rate: default_haphazard_rate(),
4231 complete_examination_rate: default_complete_examination_rate(),
4232 }
4233 }
4234}
4235
4236#[derive(Debug, Clone, Serialize, Deserialize)]
4238pub struct AuditTeamConfig {
4239 #[serde(default = "default_min_team_size")]
4241 pub min_team_size: usize,
4242 #[serde(default = "default_max_team_size")]
4244 pub max_team_size: usize,
4245 #[serde(default = "default_specialist_probability")]
4247 pub specialist_probability: f64,
4248}
4249
4250fn default_min_team_size() -> usize {
4251 3
4252}
4253fn default_max_team_size() -> usize {
4254 8
4255}
4256fn default_specialist_probability() -> f64 {
4257 0.30
4258}
4259
4260impl Default for AuditTeamConfig {
4261 fn default() -> Self {
4262 Self {
4263 min_team_size: default_min_team_size(),
4264 max_team_size: default_max_team_size(),
4265 specialist_probability: default_specialist_probability(),
4266 }
4267 }
4268}
4269
4270#[derive(Debug, Clone, Serialize, Deserialize)]
4272pub struct ReviewWorkflowConfig {
4273 #[serde(default = "default_review_delay_days")]
4275 pub average_review_delay_days: u32,
4276 #[serde(default = "default_rework_probability_review")]
4278 pub rework_probability: f64,
4279 #[serde(default = "default_true")]
4281 pub require_partner_signoff: bool,
4282}
4283
4284fn default_review_delay_days() -> u32 {
4285 2
4286}
4287fn default_rework_probability_review() -> f64 {
4288 0.15
4289}
4290
4291impl Default for ReviewWorkflowConfig {
4292 fn default() -> Self {
4293 Self {
4294 average_review_delay_days: default_review_delay_days(),
4295 rework_probability: default_rework_probability_review(),
4296 require_partner_signoff: true,
4297 }
4298 }
4299}
4300
4301#[derive(Debug, Clone, Serialize, Deserialize)]
4307pub struct DataQualitySchemaConfig {
4308 #[serde(default)]
4310 pub enabled: bool,
4311 #[serde(default)]
4313 pub preset: DataQualityPreset,
4314 #[serde(default)]
4316 pub missing_values: MissingValuesSchemaConfig,
4317 #[serde(default)]
4319 pub typos: TypoSchemaConfig,
4320 #[serde(default)]
4322 pub format_variations: FormatVariationSchemaConfig,
4323 #[serde(default)]
4325 pub duplicates: DuplicateSchemaConfig,
4326 #[serde(default)]
4328 pub encoding_issues: EncodingIssueSchemaConfig,
4329 #[serde(default)]
4331 pub generate_labels: bool,
4332 #[serde(default)]
4334 pub sink_profiles: SinkQualityProfiles,
4335}
4336
4337impl Default for DataQualitySchemaConfig {
4338 fn default() -> Self {
4339 Self {
4340 enabled: false,
4341 preset: DataQualityPreset::None,
4342 missing_values: MissingValuesSchemaConfig::default(),
4343 typos: TypoSchemaConfig::default(),
4344 format_variations: FormatVariationSchemaConfig::default(),
4345 duplicates: DuplicateSchemaConfig::default(),
4346 encoding_issues: EncodingIssueSchemaConfig::default(),
4347 generate_labels: true,
4348 sink_profiles: SinkQualityProfiles::default(),
4349 }
4350 }
4351}
4352
4353impl DataQualitySchemaConfig {
4354 pub fn with_preset(preset: DataQualityPreset) -> Self {
4356 let mut config = Self {
4357 preset,
4358 ..Default::default()
4359 };
4360 config.apply_preset();
4361 config
4362 }
4363
4364 pub fn apply_preset(&mut self) {
4367 if !self.preset.overrides_settings() {
4368 return;
4369 }
4370
4371 self.enabled = true;
4372
4373 self.missing_values.enabled = self.preset.missing_rate() > 0.0;
4375 self.missing_values.rate = self.preset.missing_rate();
4376
4377 self.typos.enabled = self.preset.typo_rate() > 0.0;
4379 self.typos.char_error_rate = self.preset.typo_rate();
4380
4381 self.duplicates.enabled = self.preset.duplicate_rate() > 0.0;
4383 self.duplicates.exact_duplicate_ratio = self.preset.duplicate_rate() * 0.4;
4384 self.duplicates.near_duplicate_ratio = self.preset.duplicate_rate() * 0.4;
4385 self.duplicates.fuzzy_duplicate_ratio = self.preset.duplicate_rate() * 0.2;
4386
4387 self.format_variations.enabled = self.preset.format_variations_enabled();
4389
4390 self.encoding_issues.enabled = self.preset.encoding_issues_enabled();
4392 self.encoding_issues.rate = self.preset.encoding_issue_rate();
4393
4394 if self.preset.ocr_errors_enabled() {
4396 self.typos.type_weights.ocr_errors = 0.3;
4397 }
4398 }
4399
4400 pub fn effective_missing_rate(&self) -> f64 {
4402 if self.preset.overrides_settings() {
4403 self.preset.missing_rate()
4404 } else {
4405 self.missing_values.rate
4406 }
4407 }
4408
4409 pub fn effective_typo_rate(&self) -> f64 {
4411 if self.preset.overrides_settings() {
4412 self.preset.typo_rate()
4413 } else {
4414 self.typos.char_error_rate
4415 }
4416 }
4417
4418 pub fn effective_duplicate_rate(&self) -> f64 {
4420 if self.preset.overrides_settings() {
4421 self.preset.duplicate_rate()
4422 } else {
4423 self.duplicates.exact_duplicate_ratio
4424 + self.duplicates.near_duplicate_ratio
4425 + self.duplicates.fuzzy_duplicate_ratio
4426 }
4427 }
4428
4429 pub fn clean() -> Self {
4431 Self::with_preset(DataQualityPreset::Clean)
4432 }
4433
4434 pub fn noisy() -> Self {
4436 Self::with_preset(DataQualityPreset::Noisy)
4437 }
4438
4439 pub fn legacy() -> Self {
4441 Self::with_preset(DataQualityPreset::Legacy)
4442 }
4443}
4444
4445#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
4447#[serde(rename_all = "snake_case")]
4448pub enum DataQualityPreset {
4449 #[default]
4451 None,
4452 Minimal,
4454 Normal,
4456 High,
4458 Custom,
4460
4461 Clean,
4467 Noisy,
4470 Legacy,
4473}
4474
4475impl DataQualityPreset {
4476 pub fn missing_rate(&self) -> f64 {
4478 match self {
4479 DataQualityPreset::None => 0.0,
4480 DataQualityPreset::Minimal => 0.005,
4481 DataQualityPreset::Normal => 0.02,
4482 DataQualityPreset::High => 0.08,
4483 DataQualityPreset::Custom => 0.01, DataQualityPreset::Clean => 0.001,
4485 DataQualityPreset::Noisy => 0.05,
4486 DataQualityPreset::Legacy => 0.10,
4487 }
4488 }
4489
4490 pub fn typo_rate(&self) -> f64 {
4492 match self {
4493 DataQualityPreset::None => 0.0,
4494 DataQualityPreset::Minimal => 0.0005,
4495 DataQualityPreset::Normal => 0.002,
4496 DataQualityPreset::High => 0.01,
4497 DataQualityPreset::Custom => 0.001, DataQualityPreset::Clean => 0.0005,
4499 DataQualityPreset::Noisy => 0.02,
4500 DataQualityPreset::Legacy => 0.05,
4501 }
4502 }
4503
4504 pub fn duplicate_rate(&self) -> f64 {
4506 match self {
4507 DataQualityPreset::None => 0.0,
4508 DataQualityPreset::Minimal => 0.001,
4509 DataQualityPreset::Normal => 0.005,
4510 DataQualityPreset::High => 0.02,
4511 DataQualityPreset::Custom => 0.0, DataQualityPreset::Clean => 0.0,
4513 DataQualityPreset::Noisy => 0.01,
4514 DataQualityPreset::Legacy => 0.03,
4515 }
4516 }
4517
4518 pub fn format_variations_enabled(&self) -> bool {
4520 match self {
4521 DataQualityPreset::None | DataQualityPreset::Clean => false,
4522 DataQualityPreset::Minimal => true,
4523 DataQualityPreset::Normal => true,
4524 DataQualityPreset::High => true,
4525 DataQualityPreset::Custom => true,
4526 DataQualityPreset::Noisy => true,
4527 DataQualityPreset::Legacy => true,
4528 }
4529 }
4530
4531 pub fn ocr_errors_enabled(&self) -> bool {
4533 matches!(self, DataQualityPreset::Legacy | DataQualityPreset::High)
4534 }
4535
4536 pub fn encoding_issues_enabled(&self) -> bool {
4538 matches!(
4539 self,
4540 DataQualityPreset::Legacy | DataQualityPreset::High | DataQualityPreset::Noisy
4541 )
4542 }
4543
4544 pub fn encoding_issue_rate(&self) -> f64 {
4546 match self {
4547 DataQualityPreset::None | DataQualityPreset::Clean | DataQualityPreset::Minimal => 0.0,
4548 DataQualityPreset::Normal => 0.002,
4549 DataQualityPreset::High => 0.01,
4550 DataQualityPreset::Custom => 0.0,
4551 DataQualityPreset::Noisy => 0.005,
4552 DataQualityPreset::Legacy => 0.02,
4553 }
4554 }
4555
4556 pub fn overrides_settings(&self) -> bool {
4558 !matches!(self, DataQualityPreset::Custom | DataQualityPreset::None)
4559 }
4560
4561 pub fn description(&self) -> &'static str {
4563 match self {
4564 DataQualityPreset::None => "No data quality issues (pristine data)",
4565 DataQualityPreset::Minimal => "Very rare data quality issues",
4566 DataQualityPreset::Normal => "Realistic enterprise data quality",
4567 DataQualityPreset::High => "Messy data for stress testing",
4568 DataQualityPreset::Custom => "Custom settings from configuration",
4569 DataQualityPreset::Clean => "ML-ready clean data with minimal issues",
4570 DataQualityPreset::Noisy => "Typical production data with moderate issues",
4571 DataQualityPreset::Legacy => "Legacy/migrated data with heavy issues and OCR errors",
4572 }
4573 }
4574}
4575
4576#[derive(Debug, Clone, Serialize, Deserialize)]
4578pub struct MissingValuesSchemaConfig {
4579 #[serde(default)]
4581 pub enabled: bool,
4582 #[serde(default = "default_missing_rate")]
4584 pub rate: f64,
4585 #[serde(default)]
4587 pub strategy: MissingValueStrategy,
4588 #[serde(default)]
4590 pub field_rates: std::collections::HashMap<String, f64>,
4591 #[serde(default)]
4593 pub protected_fields: Vec<String>,
4594}
4595
4596fn default_missing_rate() -> f64 {
4597 0.01
4598}
4599
4600impl Default for MissingValuesSchemaConfig {
4601 fn default() -> Self {
4602 Self {
4603 enabled: false,
4604 rate: default_missing_rate(),
4605 strategy: MissingValueStrategy::Mcar,
4606 field_rates: std::collections::HashMap::new(),
4607 protected_fields: vec![
4608 "document_id".to_string(),
4609 "company_code".to_string(),
4610 "posting_date".to_string(),
4611 ],
4612 }
4613 }
4614}
4615
4616#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
4618#[serde(rename_all = "snake_case")]
4619pub enum MissingValueStrategy {
4620 #[default]
4622 Mcar,
4623 Mar,
4625 Mnar,
4627 Systematic,
4629}
4630
4631#[derive(Debug, Clone, Serialize, Deserialize)]
4633pub struct TypoSchemaConfig {
4634 #[serde(default)]
4636 pub enabled: bool,
4637 #[serde(default = "default_typo_rate")]
4639 pub char_error_rate: f64,
4640 #[serde(default)]
4642 pub type_weights: TypoTypeWeights,
4643 #[serde(default)]
4645 pub protected_fields: Vec<String>,
4646}
4647
4648fn default_typo_rate() -> f64 {
4649 0.001
4650}
4651
4652impl Default for TypoSchemaConfig {
4653 fn default() -> Self {
4654 Self {
4655 enabled: false,
4656 char_error_rate: default_typo_rate(),
4657 type_weights: TypoTypeWeights::default(),
4658 protected_fields: vec![
4659 "document_id".to_string(),
4660 "gl_account".to_string(),
4661 "company_code".to_string(),
4662 ],
4663 }
4664 }
4665}
4666
4667#[derive(Debug, Clone, Serialize, Deserialize)]
4669pub struct TypoTypeWeights {
4670 #[serde(default = "default_substitution_weight")]
4672 pub substitution: f64,
4673 #[serde(default = "default_transposition_weight")]
4675 pub transposition: f64,
4676 #[serde(default = "default_insertion_weight")]
4678 pub insertion: f64,
4679 #[serde(default = "default_deletion_weight")]
4681 pub deletion: f64,
4682 #[serde(default = "default_ocr_weight")]
4684 pub ocr_errors: f64,
4685 #[serde(default = "default_homophone_weight")]
4687 pub homophones: f64,
4688}
4689
4690fn default_substitution_weight() -> f64 {
4691 0.35
4692}
4693fn default_transposition_weight() -> f64 {
4694 0.25
4695}
4696fn default_insertion_weight() -> f64 {
4697 0.10
4698}
4699fn default_deletion_weight() -> f64 {
4700 0.15
4701}
4702fn default_ocr_weight() -> f64 {
4703 0.10
4704}
4705fn default_homophone_weight() -> f64 {
4706 0.05
4707}
4708
4709impl Default for TypoTypeWeights {
4710 fn default() -> Self {
4711 Self {
4712 substitution: default_substitution_weight(),
4713 transposition: default_transposition_weight(),
4714 insertion: default_insertion_weight(),
4715 deletion: default_deletion_weight(),
4716 ocr_errors: default_ocr_weight(),
4717 homophones: default_homophone_weight(),
4718 }
4719 }
4720}
4721
4722#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4724pub struct FormatVariationSchemaConfig {
4725 #[serde(default)]
4727 pub enabled: bool,
4728 #[serde(default)]
4730 pub dates: DateFormatVariationConfig,
4731 #[serde(default)]
4733 pub amounts: AmountFormatVariationConfig,
4734 #[serde(default)]
4736 pub identifiers: IdentifierFormatVariationConfig,
4737}
4738
4739#[derive(Debug, Clone, Serialize, Deserialize)]
4741pub struct DateFormatVariationConfig {
4742 #[serde(default)]
4744 pub enabled: bool,
4745 #[serde(default = "default_date_variation_rate")]
4747 pub rate: f64,
4748 #[serde(default = "default_true")]
4750 pub iso_format: bool,
4751 #[serde(default)]
4753 pub us_format: bool,
4754 #[serde(default)]
4756 pub eu_format: bool,
4757 #[serde(default)]
4759 pub long_format: bool,
4760}
4761
4762fn default_date_variation_rate() -> f64 {
4763 0.05
4764}
4765
4766impl Default for DateFormatVariationConfig {
4767 fn default() -> Self {
4768 Self {
4769 enabled: false,
4770 rate: default_date_variation_rate(),
4771 iso_format: true,
4772 us_format: false,
4773 eu_format: false,
4774 long_format: false,
4775 }
4776 }
4777}
4778
4779#[derive(Debug, Clone, Serialize, Deserialize)]
4781pub struct AmountFormatVariationConfig {
4782 #[serde(default)]
4784 pub enabled: bool,
4785 #[serde(default = "default_amount_variation_rate")]
4787 pub rate: f64,
4788 #[serde(default)]
4790 pub us_comma_format: bool,
4791 #[serde(default)]
4793 pub eu_format: bool,
4794 #[serde(default)]
4796 pub currency_prefix: bool,
4797 #[serde(default)]
4799 pub accounting_format: bool,
4800}
4801
4802fn default_amount_variation_rate() -> f64 {
4803 0.02
4804}
4805
4806impl Default for AmountFormatVariationConfig {
4807 fn default() -> Self {
4808 Self {
4809 enabled: false,
4810 rate: default_amount_variation_rate(),
4811 us_comma_format: false,
4812 eu_format: false,
4813 currency_prefix: false,
4814 accounting_format: false,
4815 }
4816 }
4817}
4818
4819#[derive(Debug, Clone, Serialize, Deserialize)]
4821pub struct IdentifierFormatVariationConfig {
4822 #[serde(default)]
4824 pub enabled: bool,
4825 #[serde(default = "default_identifier_variation_rate")]
4827 pub rate: f64,
4828 #[serde(default)]
4830 pub case_variations: bool,
4831 #[serde(default)]
4833 pub padding_variations: bool,
4834 #[serde(default)]
4836 pub separator_variations: bool,
4837}
4838
4839fn default_identifier_variation_rate() -> f64 {
4840 0.02
4841}
4842
4843impl Default for IdentifierFormatVariationConfig {
4844 fn default() -> Self {
4845 Self {
4846 enabled: false,
4847 rate: default_identifier_variation_rate(),
4848 case_variations: false,
4849 padding_variations: false,
4850 separator_variations: false,
4851 }
4852 }
4853}
4854
4855#[derive(Debug, Clone, Serialize, Deserialize)]
4857pub struct DuplicateSchemaConfig {
4858 #[serde(default)]
4860 pub enabled: bool,
4861 #[serde(default = "default_duplicate_rate")]
4863 pub rate: f64,
4864 #[serde(default = "default_exact_duplicate_ratio")]
4866 pub exact_duplicate_ratio: f64,
4867 #[serde(default = "default_near_duplicate_ratio")]
4869 pub near_duplicate_ratio: f64,
4870 #[serde(default = "default_fuzzy_duplicate_ratio")]
4872 pub fuzzy_duplicate_ratio: f64,
4873 #[serde(default = "default_max_date_offset")]
4875 pub max_date_offset_days: u32,
4876 #[serde(default = "default_max_amount_variance")]
4878 pub max_amount_variance: f64,
4879}
4880
4881fn default_duplicate_rate() -> f64 {
4882 0.005
4883}
4884fn default_exact_duplicate_ratio() -> f64 {
4885 0.4
4886}
4887fn default_near_duplicate_ratio() -> f64 {
4888 0.35
4889}
4890fn default_fuzzy_duplicate_ratio() -> f64 {
4891 0.25
4892}
4893fn default_max_date_offset() -> u32 {
4894 3
4895}
4896fn default_max_amount_variance() -> f64 {
4897 0.01
4898}
4899
4900impl Default for DuplicateSchemaConfig {
4901 fn default() -> Self {
4902 Self {
4903 enabled: false,
4904 rate: default_duplicate_rate(),
4905 exact_duplicate_ratio: default_exact_duplicate_ratio(),
4906 near_duplicate_ratio: default_near_duplicate_ratio(),
4907 fuzzy_duplicate_ratio: default_fuzzy_duplicate_ratio(),
4908 max_date_offset_days: default_max_date_offset(),
4909 max_amount_variance: default_max_amount_variance(),
4910 }
4911 }
4912}
4913
4914#[derive(Debug, Clone, Serialize, Deserialize)]
4916pub struct EncodingIssueSchemaConfig {
4917 #[serde(default)]
4919 pub enabled: bool,
4920 #[serde(default = "default_encoding_rate")]
4922 pub rate: f64,
4923 #[serde(default)]
4925 pub mojibake: bool,
4926 #[serde(default)]
4928 pub html_entities: bool,
4929 #[serde(default)]
4931 pub bom_issues: bool,
4932}
4933
4934fn default_encoding_rate() -> f64 {
4935 0.001
4936}
4937
4938impl Default for EncodingIssueSchemaConfig {
4939 fn default() -> Self {
4940 Self {
4941 enabled: false,
4942 rate: default_encoding_rate(),
4943 mojibake: false,
4944 html_entities: false,
4945 bom_issues: false,
4946 }
4947 }
4948}
4949
4950#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4952pub struct SinkQualityProfiles {
4953 #[serde(default)]
4955 pub csv: Option<SinkQualityOverride>,
4956 #[serde(default)]
4958 pub json: Option<SinkQualityOverride>,
4959 #[serde(default)]
4961 pub parquet: Option<SinkQualityOverride>,
4962}
4963
4964#[derive(Debug, Clone, Serialize, Deserialize)]
4966pub struct SinkQualityOverride {
4967 pub enabled: Option<bool>,
4969 pub missing_rate: Option<f64>,
4971 pub typo_rate: Option<f64>,
4973 pub format_variation_rate: Option<f64>,
4975 pub duplicate_rate: Option<f64>,
4977}
4978
4979#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4991pub struct AccountingStandardsConfig {
4992 #[serde(default)]
4994 pub enabled: bool,
4995
4996 #[serde(default, skip_serializing_if = "Option::is_none")]
5000 pub framework: Option<AccountingFrameworkConfig>,
5001
5002 #[serde(default)]
5004 pub revenue_recognition: RevenueRecognitionConfig,
5005
5006 #[serde(default)]
5008 pub leases: LeaseAccountingConfig,
5009
5010 #[serde(default)]
5012 pub fair_value: FairValueConfig,
5013
5014 #[serde(default)]
5016 pub impairment: ImpairmentConfig,
5017
5018 #[serde(default)]
5020 pub business_combinations: BusinessCombinationsConfig,
5021
5022 #[serde(default)]
5024 pub expected_credit_loss: EclConfig,
5025
5026 #[serde(default)]
5028 pub generate_differences: bool,
5029}
5030
5031#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5033#[serde(rename_all = "snake_case")]
5034pub enum AccountingFrameworkConfig {
5035 #[default]
5037 UsGaap,
5038 Ifrs,
5040 DualReporting,
5042 FrenchGaap,
5044 GermanGaap,
5046}
5047
5048#[derive(Debug, Clone, Serialize, Deserialize)]
5050pub struct RevenueRecognitionConfig {
5051 #[serde(default)]
5053 pub enabled: bool,
5054
5055 #[serde(default = "default_true")]
5057 pub generate_contracts: bool,
5058
5059 #[serde(default = "default_avg_obligations")]
5061 pub avg_obligations_per_contract: f64,
5062
5063 #[serde(default = "default_variable_consideration_rate")]
5065 pub variable_consideration_rate: f64,
5066
5067 #[serde(default = "default_over_time_rate")]
5069 pub over_time_recognition_rate: f64,
5070
5071 #[serde(default = "default_contract_count")]
5073 pub contract_count: usize,
5074}
5075
5076fn default_avg_obligations() -> f64 {
5077 2.0
5078}
5079
5080fn default_variable_consideration_rate() -> f64 {
5081 0.15
5082}
5083
5084fn default_over_time_rate() -> f64 {
5085 0.30
5086}
5087
5088fn default_contract_count() -> usize {
5089 100
5090}
5091
5092impl Default for RevenueRecognitionConfig {
5093 fn default() -> Self {
5094 Self {
5095 enabled: false,
5096 generate_contracts: true,
5097 avg_obligations_per_contract: default_avg_obligations(),
5098 variable_consideration_rate: default_variable_consideration_rate(),
5099 over_time_recognition_rate: default_over_time_rate(),
5100 contract_count: default_contract_count(),
5101 }
5102 }
5103}
5104
5105#[derive(Debug, Clone, Serialize, Deserialize)]
5107pub struct LeaseAccountingConfig {
5108 #[serde(default)]
5110 pub enabled: bool,
5111
5112 #[serde(default = "default_lease_count")]
5114 pub lease_count: usize,
5115
5116 #[serde(default = "default_finance_lease_pct")]
5118 pub finance_lease_percent: f64,
5119
5120 #[serde(default = "default_avg_lease_term")]
5122 pub avg_lease_term_months: u32,
5123
5124 #[serde(default = "default_true")]
5126 pub generate_amortization: bool,
5127
5128 #[serde(default = "default_real_estate_pct")]
5130 pub real_estate_percent: f64,
5131}
5132
5133fn default_lease_count() -> usize {
5134 50
5135}
5136
5137fn default_finance_lease_pct() -> f64 {
5138 0.30
5139}
5140
5141fn default_avg_lease_term() -> u32 {
5142 60
5143}
5144
5145fn default_real_estate_pct() -> f64 {
5146 0.40
5147}
5148
5149impl Default for LeaseAccountingConfig {
5150 fn default() -> Self {
5151 Self {
5152 enabled: false,
5153 lease_count: default_lease_count(),
5154 finance_lease_percent: default_finance_lease_pct(),
5155 avg_lease_term_months: default_avg_lease_term(),
5156 generate_amortization: true,
5157 real_estate_percent: default_real_estate_pct(),
5158 }
5159 }
5160}
5161
5162#[derive(Debug, Clone, Serialize, Deserialize)]
5164pub struct FairValueConfig {
5165 #[serde(default)]
5167 pub enabled: bool,
5168
5169 #[serde(default = "default_fv_count")]
5171 pub measurement_count: usize,
5172
5173 #[serde(default = "default_level1_pct")]
5175 pub level1_percent: f64,
5176
5177 #[serde(default = "default_level2_pct")]
5179 pub level2_percent: f64,
5180
5181 #[serde(default = "default_level3_pct")]
5183 pub level3_percent: f64,
5184
5185 #[serde(default)]
5187 pub include_sensitivity_analysis: bool,
5188}
5189
5190fn default_fv_count() -> usize {
5191 25
5192}
5193
5194fn default_level1_pct() -> f64 {
5195 0.40
5196}
5197
5198fn default_level2_pct() -> f64 {
5199 0.35
5200}
5201
5202fn default_level3_pct() -> f64 {
5203 0.25
5204}
5205
5206impl Default for FairValueConfig {
5207 fn default() -> Self {
5208 Self {
5209 enabled: false,
5210 measurement_count: default_fv_count(),
5211 level1_percent: default_level1_pct(),
5212 level2_percent: default_level2_pct(),
5213 level3_percent: default_level3_pct(),
5214 include_sensitivity_analysis: false,
5215 }
5216 }
5217}
5218
5219#[derive(Debug, Clone, Serialize, Deserialize)]
5221pub struct ImpairmentConfig {
5222 #[serde(default)]
5224 pub enabled: bool,
5225
5226 #[serde(default = "default_impairment_count")]
5228 pub test_count: usize,
5229
5230 #[serde(default = "default_impairment_rate")]
5232 pub impairment_rate: f64,
5233
5234 #[serde(default = "default_true")]
5236 pub generate_projections: bool,
5237
5238 #[serde(default)]
5240 pub include_goodwill: bool,
5241}
5242
5243fn default_impairment_count() -> usize {
5244 15
5245}
5246
5247fn default_impairment_rate() -> f64 {
5248 0.10
5249}
5250
5251impl Default for ImpairmentConfig {
5252 fn default() -> Self {
5253 Self {
5254 enabled: false,
5255 test_count: default_impairment_count(),
5256 impairment_rate: default_impairment_rate(),
5257 generate_projections: true,
5258 include_goodwill: false,
5259 }
5260 }
5261}
5262
5263#[derive(Debug, Clone, Serialize, Deserialize)]
5269pub struct BusinessCombinationsConfig {
5270 #[serde(default)]
5272 pub enabled: bool,
5273
5274 #[serde(default = "default_bc_acquisition_count")]
5276 pub acquisition_count: usize,
5277}
5278
5279fn default_bc_acquisition_count() -> usize {
5280 2
5281}
5282
5283impl Default for BusinessCombinationsConfig {
5284 fn default() -> Self {
5285 Self {
5286 enabled: false,
5287 acquisition_count: default_bc_acquisition_count(),
5288 }
5289 }
5290}
5291
5292#[derive(Debug, Clone, Serialize, Deserialize)]
5298pub struct EclConfig {
5299 #[serde(default)]
5301 pub enabled: bool,
5302
5303 #[serde(default = "default_ecl_base_weight")]
5305 pub base_scenario_weight: f64,
5306
5307 #[serde(default = "default_ecl_base_multiplier")]
5309 pub base_scenario_multiplier: f64,
5310
5311 #[serde(default = "default_ecl_optimistic_weight")]
5313 pub optimistic_scenario_weight: f64,
5314
5315 #[serde(default = "default_ecl_optimistic_multiplier")]
5317 pub optimistic_scenario_multiplier: f64,
5318
5319 #[serde(default = "default_ecl_pessimistic_weight")]
5321 pub pessimistic_scenario_weight: f64,
5322
5323 #[serde(default = "default_ecl_pessimistic_multiplier")]
5325 pub pessimistic_scenario_multiplier: f64,
5326}
5327
5328fn default_ecl_base_weight() -> f64 {
5329 0.50
5330}
5331fn default_ecl_base_multiplier() -> f64 {
5332 1.0
5333}
5334fn default_ecl_optimistic_weight() -> f64 {
5335 0.30
5336}
5337fn default_ecl_optimistic_multiplier() -> f64 {
5338 0.8
5339}
5340fn default_ecl_pessimistic_weight() -> f64 {
5341 0.20
5342}
5343fn default_ecl_pessimistic_multiplier() -> f64 {
5344 1.4
5345}
5346
5347impl Default for EclConfig {
5348 fn default() -> Self {
5349 Self {
5350 enabled: false,
5351 base_scenario_weight: default_ecl_base_weight(),
5352 base_scenario_multiplier: default_ecl_base_multiplier(),
5353 optimistic_scenario_weight: default_ecl_optimistic_weight(),
5354 optimistic_scenario_multiplier: default_ecl_optimistic_multiplier(),
5355 pessimistic_scenario_weight: default_ecl_pessimistic_weight(),
5356 pessimistic_scenario_multiplier: default_ecl_pessimistic_multiplier(),
5357 }
5358 }
5359}
5360
5361#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5374pub struct AuditStandardsConfig {
5375 #[serde(default)]
5377 pub enabled: bool,
5378
5379 #[serde(default)]
5381 pub isa_compliance: IsaComplianceConfig,
5382
5383 #[serde(default)]
5385 pub analytical_procedures: AnalyticalProceduresConfig,
5386
5387 #[serde(default)]
5389 pub confirmations: ConfirmationsConfig,
5390
5391 #[serde(default)]
5393 pub opinion: AuditOpinionConfig,
5394
5395 #[serde(default)]
5397 pub generate_audit_trail: bool,
5398
5399 #[serde(default)]
5401 pub sox: SoxComplianceConfig,
5402
5403 #[serde(default)]
5405 pub pcaob: PcaobConfig,
5406}
5407
5408#[derive(Debug, Clone, Serialize, Deserialize)]
5410pub struct IsaComplianceConfig {
5411 #[serde(default)]
5413 pub enabled: bool,
5414
5415 #[serde(default = "default_compliance_level")]
5417 pub compliance_level: String,
5418
5419 #[serde(default = "default_true")]
5421 pub generate_isa_mappings: bool,
5422
5423 #[serde(default = "default_true")]
5425 pub generate_coverage_summary: bool,
5426
5427 #[serde(default)]
5429 pub include_pcaob: bool,
5430
5431 #[serde(default = "default_audit_framework")]
5433 pub framework: String,
5434}
5435
5436fn default_compliance_level() -> String {
5437 "standard".to_string()
5438}
5439
5440fn default_audit_framework() -> String {
5441 "isa".to_string()
5442}
5443
5444impl Default for IsaComplianceConfig {
5445 fn default() -> Self {
5446 Self {
5447 enabled: false,
5448 compliance_level: default_compliance_level(),
5449 generate_isa_mappings: true,
5450 generate_coverage_summary: true,
5451 include_pcaob: false,
5452 framework: default_audit_framework(),
5453 }
5454 }
5455}
5456
5457#[derive(Debug, Clone, Serialize, Deserialize)]
5459pub struct AnalyticalProceduresConfig {
5460 #[serde(default)]
5462 pub enabled: bool,
5463
5464 #[serde(default = "default_procedures_per_account")]
5466 pub procedures_per_account: usize,
5467
5468 #[serde(default = "default_variance_probability")]
5470 pub variance_probability: f64,
5471
5472 #[serde(default = "default_true")]
5474 pub generate_investigations: bool,
5475
5476 #[serde(default = "default_true")]
5478 pub include_ratio_analysis: bool,
5479}
5480
5481fn default_procedures_per_account() -> usize {
5482 3
5483}
5484
5485fn default_variance_probability() -> f64 {
5486 0.20
5487}
5488
5489impl Default for AnalyticalProceduresConfig {
5490 fn default() -> Self {
5491 Self {
5492 enabled: false,
5493 procedures_per_account: default_procedures_per_account(),
5494 variance_probability: default_variance_probability(),
5495 generate_investigations: true,
5496 include_ratio_analysis: true,
5497 }
5498 }
5499}
5500
5501#[derive(Debug, Clone, Serialize, Deserialize)]
5503pub struct ConfirmationsConfig {
5504 #[serde(default)]
5506 pub enabled: bool,
5507
5508 #[serde(default = "default_confirmation_count")]
5510 pub confirmation_count: usize,
5511
5512 #[serde(default = "default_positive_response_rate")]
5514 pub positive_response_rate: f64,
5515
5516 #[serde(default = "default_exception_rate_confirm")]
5518 pub exception_rate: f64,
5519
5520 #[serde(default = "default_non_response_rate")]
5522 pub non_response_rate: f64,
5523
5524 #[serde(default = "default_true")]
5526 pub generate_alternative_procedures: bool,
5527}
5528
5529fn default_confirmation_count() -> usize {
5530 50
5531}
5532
5533fn default_positive_response_rate() -> f64 {
5534 0.85
5535}
5536
5537fn default_exception_rate_confirm() -> f64 {
5538 0.10
5539}
5540
5541fn default_non_response_rate() -> f64 {
5542 0.05
5543}
5544
5545impl Default for ConfirmationsConfig {
5546 fn default() -> Self {
5547 Self {
5548 enabled: false,
5549 confirmation_count: default_confirmation_count(),
5550 positive_response_rate: default_positive_response_rate(),
5551 exception_rate: default_exception_rate_confirm(),
5552 non_response_rate: default_non_response_rate(),
5553 generate_alternative_procedures: true,
5554 }
5555 }
5556}
5557
5558#[derive(Debug, Clone, Serialize, Deserialize)]
5560pub struct AuditOpinionConfig {
5561 #[serde(default)]
5563 pub enabled: bool,
5564
5565 #[serde(default = "default_true")]
5567 pub generate_kam: bool,
5568
5569 #[serde(default = "default_kam_count")]
5571 pub average_kam_count: usize,
5572
5573 #[serde(default = "default_modified_opinion_rate")]
5575 pub modified_opinion_rate: f64,
5576
5577 #[serde(default)]
5579 pub include_emphasis_of_matter: bool,
5580
5581 #[serde(default = "default_true")]
5583 pub include_going_concern: bool,
5584}
5585
5586fn default_kam_count() -> usize {
5587 3
5588}
5589
5590fn default_modified_opinion_rate() -> f64 {
5591 0.05
5592}
5593
5594impl Default for AuditOpinionConfig {
5595 fn default() -> Self {
5596 Self {
5597 enabled: false,
5598 generate_kam: true,
5599 average_kam_count: default_kam_count(),
5600 modified_opinion_rate: default_modified_opinion_rate(),
5601 include_emphasis_of_matter: false,
5602 include_going_concern: true,
5603 }
5604 }
5605}
5606
5607#[derive(Debug, Clone, Serialize, Deserialize)]
5609pub struct SoxComplianceConfig {
5610 #[serde(default)]
5612 pub enabled: bool,
5613
5614 #[serde(default = "default_true")]
5616 pub generate_302_certifications: bool,
5617
5618 #[serde(default = "default_true")]
5620 pub generate_404_assessments: bool,
5621
5622 #[serde(default = "default_sox_materiality_threshold")]
5624 pub materiality_threshold: f64,
5625
5626 #[serde(default = "default_material_weakness_rate")]
5628 pub material_weakness_rate: f64,
5629
5630 #[serde(default = "default_significant_deficiency_rate")]
5632 pub significant_deficiency_rate: f64,
5633}
5634
5635fn default_material_weakness_rate() -> f64 {
5636 0.02
5637}
5638
5639fn default_significant_deficiency_rate() -> f64 {
5640 0.08
5641}
5642
5643impl Default for SoxComplianceConfig {
5644 fn default() -> Self {
5645 Self {
5646 enabled: false,
5647 generate_302_certifications: true,
5648 generate_404_assessments: true,
5649 materiality_threshold: default_sox_materiality_threshold(),
5650 material_weakness_rate: default_material_weakness_rate(),
5651 significant_deficiency_rate: default_significant_deficiency_rate(),
5652 }
5653 }
5654}
5655
5656#[derive(Debug, Clone, Serialize, Deserialize)]
5658pub struct PcaobConfig {
5659 #[serde(default)]
5661 pub enabled: bool,
5662
5663 #[serde(default)]
5665 pub is_pcaob_audit: bool,
5666
5667 #[serde(default = "default_true")]
5669 pub generate_cam: bool,
5670
5671 #[serde(default)]
5673 pub include_icfr_opinion: bool,
5674
5675 #[serde(default)]
5677 pub generate_standard_mappings: bool,
5678}
5679
5680impl Default for PcaobConfig {
5681 fn default() -> Self {
5682 Self {
5683 enabled: false,
5684 is_pcaob_audit: false,
5685 generate_cam: true,
5686 include_icfr_opinion: false,
5687 generate_standard_mappings: false,
5688 }
5689 }
5690}
5691
5692#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5705pub struct AdvancedDistributionConfig {
5706 #[serde(default)]
5708 pub enabled: bool,
5709
5710 #[serde(default)]
5712 pub amounts: MixtureDistributionSchemaConfig,
5713
5714 #[serde(default)]
5716 pub correlations: CorrelationSchemaConfig,
5717
5718 #[serde(default)]
5720 pub conditional: Vec<ConditionalDistributionSchemaConfig>,
5721
5722 #[serde(default)]
5724 pub regime_changes: RegimeChangeSchemaConfig,
5725
5726 #[serde(default)]
5728 pub industry_profile: Option<IndustryProfileType>,
5729
5730 #[serde(default)]
5732 pub validation: StatisticalValidationSchemaConfig,
5733}
5734
5735#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
5737#[serde(rename_all = "snake_case")]
5738pub enum IndustryProfileType {
5739 Retail,
5741 Manufacturing,
5743 FinancialServices,
5745 Healthcare,
5747 Technology,
5749}
5750
5751#[derive(Debug, Clone, Serialize, Deserialize)]
5753pub struct MixtureDistributionSchemaConfig {
5754 #[serde(default)]
5756 pub enabled: bool,
5757
5758 #[serde(default = "default_mixture_type")]
5760 pub distribution_type: MixtureDistributionType,
5761
5762 #[serde(default)]
5764 pub components: Vec<MixtureComponentConfig>,
5765
5766 #[serde(default = "default_min_amount")]
5768 pub min_value: f64,
5769
5770 #[serde(default)]
5772 pub max_value: Option<f64>,
5773
5774 #[serde(default = "default_decimal_places")]
5776 pub decimal_places: u8,
5777}
5778
5779fn default_mixture_type() -> MixtureDistributionType {
5780 MixtureDistributionType::LogNormal
5781}
5782
5783fn default_min_amount() -> f64 {
5784 0.01
5785}
5786
5787fn default_decimal_places() -> u8 {
5788 2
5789}
5790
5791impl Default for MixtureDistributionSchemaConfig {
5792 fn default() -> Self {
5793 Self {
5794 enabled: false,
5795 distribution_type: MixtureDistributionType::LogNormal,
5796 components: Vec::new(),
5797 min_value: 0.01,
5798 max_value: None,
5799 decimal_places: 2,
5800 }
5801 }
5802}
5803
5804#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5806#[serde(rename_all = "snake_case")]
5807pub enum MixtureDistributionType {
5808 Gaussian,
5810 #[default]
5812 LogNormal,
5813}
5814
5815#[derive(Debug, Clone, Serialize, Deserialize)]
5817pub struct MixtureComponentConfig {
5818 pub weight: f64,
5820
5821 pub mu: f64,
5823
5824 pub sigma: f64,
5826
5827 #[serde(default)]
5829 pub label: Option<String>,
5830}
5831
5832#[derive(Debug, Clone, Serialize, Deserialize)]
5834pub struct CorrelationSchemaConfig {
5835 #[serde(default)]
5837 pub enabled: bool,
5838
5839 #[serde(default)]
5841 pub copula_type: CopulaSchemaType,
5842
5843 #[serde(default)]
5845 pub fields: Vec<CorrelatedFieldConfig>,
5846
5847 #[serde(default)]
5850 pub matrix: Vec<f64>,
5851
5852 #[serde(default)]
5854 pub expected_correlations: Vec<ExpectedCorrelationConfig>,
5855}
5856
5857impl Default for CorrelationSchemaConfig {
5858 fn default() -> Self {
5859 Self {
5860 enabled: false,
5861 copula_type: CopulaSchemaType::Gaussian,
5862 fields: Vec::new(),
5863 matrix: Vec::new(),
5864 expected_correlations: Vec::new(),
5865 }
5866 }
5867}
5868
5869#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5871#[serde(rename_all = "snake_case")]
5872pub enum CopulaSchemaType {
5873 #[default]
5875 Gaussian,
5876 Clayton,
5878 Gumbel,
5880 Frank,
5882 StudentT,
5884}
5885
5886#[derive(Debug, Clone, Serialize, Deserialize)]
5888pub struct CorrelatedFieldConfig {
5889 pub name: String,
5891
5892 #[serde(default)]
5894 pub distribution: MarginalDistributionConfig,
5895}
5896
5897#[derive(Debug, Clone, Serialize, Deserialize)]
5899#[serde(tag = "type", rename_all = "snake_case")]
5900pub enum MarginalDistributionConfig {
5901 Normal {
5903 mu: f64,
5905 sigma: f64,
5907 },
5908 LogNormal {
5910 mu: f64,
5912 sigma: f64,
5914 },
5915 Uniform {
5917 min: f64,
5919 max: f64,
5921 },
5922 DiscreteUniform {
5924 min: i32,
5926 max: i32,
5928 },
5929}
5930
5931impl Default for MarginalDistributionConfig {
5932 fn default() -> Self {
5933 Self::Normal {
5934 mu: 0.0,
5935 sigma: 1.0,
5936 }
5937 }
5938}
5939
5940#[derive(Debug, Clone, Serialize, Deserialize)]
5942pub struct ExpectedCorrelationConfig {
5943 pub field1: String,
5945 pub field2: String,
5947 pub expected_r: f64,
5949 #[serde(default = "default_correlation_tolerance")]
5951 pub tolerance: f64,
5952}
5953
5954fn default_correlation_tolerance() -> f64 {
5955 0.10
5956}
5957
5958#[derive(Debug, Clone, Serialize, Deserialize)]
5960pub struct ConditionalDistributionSchemaConfig {
5961 pub output_field: String,
5963
5964 pub input_field: String,
5966
5967 #[serde(default)]
5969 pub breakpoints: Vec<ConditionalBreakpointConfig>,
5970
5971 #[serde(default)]
5973 pub default_distribution: ConditionalDistributionParamsConfig,
5974
5975 #[serde(default)]
5977 pub min_value: Option<f64>,
5978
5979 #[serde(default)]
5981 pub max_value: Option<f64>,
5982
5983 #[serde(default = "default_decimal_places")]
5985 pub decimal_places: u8,
5986}
5987
5988#[derive(Debug, Clone, Serialize, Deserialize)]
5990pub struct ConditionalBreakpointConfig {
5991 pub threshold: f64,
5993
5994 pub distribution: ConditionalDistributionParamsConfig,
5996}
5997
5998#[derive(Debug, Clone, Serialize, Deserialize)]
6000#[serde(tag = "type", rename_all = "snake_case")]
6001pub enum ConditionalDistributionParamsConfig {
6002 Fixed {
6004 value: f64,
6006 },
6007 Normal {
6009 mu: f64,
6011 sigma: f64,
6013 },
6014 LogNormal {
6016 mu: f64,
6018 sigma: f64,
6020 },
6021 Uniform {
6023 min: f64,
6025 max: f64,
6027 },
6028 Beta {
6030 alpha: f64,
6032 beta: f64,
6034 min: f64,
6036 max: f64,
6038 },
6039 Discrete {
6041 values: Vec<f64>,
6043 weights: Vec<f64>,
6045 },
6046}
6047
6048impl Default for ConditionalDistributionParamsConfig {
6049 fn default() -> Self {
6050 Self::Normal {
6051 mu: 0.0,
6052 sigma: 1.0,
6053 }
6054 }
6055}
6056
6057#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6059pub struct RegimeChangeSchemaConfig {
6060 #[serde(default)]
6062 pub enabled: bool,
6063
6064 #[serde(default)]
6066 pub changes: Vec<RegimeChangeEventConfig>,
6067
6068 #[serde(default)]
6070 pub economic_cycle: Option<EconomicCycleSchemaConfig>,
6071
6072 #[serde(default)]
6074 pub parameter_drifts: Vec<ParameterDriftSchemaConfig>,
6075}
6076
6077#[derive(Debug, Clone, Serialize, Deserialize)]
6079pub struct RegimeChangeEventConfig {
6080 pub date: String,
6082
6083 pub change_type: RegimeChangeTypeConfig,
6085
6086 #[serde(default)]
6088 pub description: Option<String>,
6089
6090 #[serde(default)]
6092 pub effects: Vec<RegimeEffectConfig>,
6093}
6094
6095#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
6097#[serde(rename_all = "snake_case")]
6098pub enum RegimeChangeTypeConfig {
6099 Acquisition,
6101 Divestiture,
6103 PriceIncrease,
6105 PriceDecrease,
6107 ProductLaunch,
6109 ProductDiscontinuation,
6111 PolicyChange,
6113 CompetitorEntry,
6115 Custom,
6117}
6118
6119#[derive(Debug, Clone, Serialize, Deserialize)]
6121pub struct RegimeEffectConfig {
6122 pub field: String,
6124
6125 pub multiplier: f64,
6127}
6128
6129#[derive(Debug, Clone, Serialize, Deserialize)]
6131pub struct EconomicCycleSchemaConfig {
6132 #[serde(default)]
6134 pub enabled: bool,
6135
6136 #[serde(default = "default_cycle_period")]
6138 pub period_months: u32,
6139
6140 #[serde(default = "default_cycle_amplitude")]
6142 pub amplitude: f64,
6143
6144 #[serde(default)]
6146 pub phase_offset: u32,
6147
6148 #[serde(default)]
6150 pub recessions: Vec<RecessionPeriodConfig>,
6151}
6152
6153fn default_cycle_period() -> u32 {
6154 48
6155}
6156
6157fn default_cycle_amplitude() -> f64 {
6158 0.15
6159}
6160
6161impl Default for EconomicCycleSchemaConfig {
6162 fn default() -> Self {
6163 Self {
6164 enabled: false,
6165 period_months: 48,
6166 amplitude: 0.15,
6167 phase_offset: 0,
6168 recessions: Vec::new(),
6169 }
6170 }
6171}
6172
6173#[derive(Debug, Clone, Serialize, Deserialize)]
6175pub struct RecessionPeriodConfig {
6176 pub start_month: u32,
6178
6179 pub duration_months: u32,
6181
6182 #[serde(default = "default_recession_severity")]
6184 pub severity: f64,
6185}
6186
6187fn default_recession_severity() -> f64 {
6188 0.20
6189}
6190
6191#[derive(Debug, Clone, Serialize, Deserialize)]
6193pub struct ParameterDriftSchemaConfig {
6194 pub parameter: String,
6196
6197 pub drift_type: ParameterDriftTypeConfig,
6199
6200 pub start_value: f64,
6202
6203 pub end_value: f64,
6205
6206 #[serde(default)]
6208 pub start_period: u32,
6209
6210 #[serde(default)]
6212 pub end_period: Option<u32>,
6213}
6214
6215#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
6217#[serde(rename_all = "snake_case")]
6218pub enum ParameterDriftTypeConfig {
6219 #[default]
6221 Linear,
6222 Exponential,
6224 Logistic,
6226 Step,
6228}
6229
6230#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6232pub struct StatisticalValidationSchemaConfig {
6233 #[serde(default)]
6235 pub enabled: bool,
6236
6237 #[serde(default)]
6239 pub tests: Vec<StatisticalTestConfig>,
6240
6241 #[serde(default)]
6243 pub reporting: ValidationReportingConfig,
6244}
6245
6246#[derive(Debug, Clone, Serialize, Deserialize)]
6248#[serde(tag = "type", rename_all = "snake_case")]
6249pub enum StatisticalTestConfig {
6250 BenfordFirstDigit {
6252 #[serde(default = "default_benford_threshold")]
6254 threshold_mad: f64,
6255 #[serde(default = "default_benford_warning")]
6257 warning_mad: f64,
6258 },
6259 DistributionFit {
6261 target: TargetDistributionConfig,
6263 #[serde(default = "default_ks_significance")]
6265 ks_significance: f64,
6266 #[serde(default)]
6268 method: DistributionFitMethod,
6269 },
6270 CorrelationCheck {
6272 expected_correlations: Vec<ExpectedCorrelationConfig>,
6274 },
6275 ChiSquared {
6277 #[serde(default = "default_chi_squared_bins")]
6279 bins: usize,
6280 #[serde(default = "default_chi_squared_significance")]
6282 significance: f64,
6283 },
6284 AndersonDarling {
6286 target: TargetDistributionConfig,
6288 #[serde(default = "default_ad_significance")]
6290 significance: f64,
6291 },
6292}
6293
6294fn default_benford_threshold() -> f64 {
6295 0.015
6296}
6297
6298fn default_benford_warning() -> f64 {
6299 0.010
6300}
6301
6302fn default_ks_significance() -> f64 {
6303 0.05
6304}
6305
6306fn default_chi_squared_bins() -> usize {
6307 10
6308}
6309
6310fn default_chi_squared_significance() -> f64 {
6311 0.05
6312}
6313
6314fn default_ad_significance() -> f64 {
6315 0.05
6316}
6317
6318#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
6320#[serde(rename_all = "snake_case")]
6321pub enum TargetDistributionConfig {
6322 Normal,
6324 #[default]
6326 LogNormal,
6327 Exponential,
6329 Uniform,
6331}
6332
6333#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
6335#[serde(rename_all = "snake_case")]
6336pub enum DistributionFitMethod {
6337 #[default]
6339 KolmogorovSmirnov,
6340 AndersonDarling,
6342 ChiSquared,
6344}
6345
6346#[derive(Debug, Clone, Serialize, Deserialize)]
6348pub struct ValidationReportingConfig {
6349 #[serde(default)]
6351 pub output_report: bool,
6352
6353 #[serde(default)]
6355 pub format: ValidationReportFormat,
6356
6357 #[serde(default)]
6359 pub fail_on_error: bool,
6360
6361 #[serde(default = "default_true")]
6363 pub include_details: bool,
6364}
6365
6366impl Default for ValidationReportingConfig {
6367 fn default() -> Self {
6368 Self {
6369 output_report: false,
6370 format: ValidationReportFormat::Json,
6371 fail_on_error: false,
6372 include_details: true,
6373 }
6374 }
6375}
6376
6377#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
6379#[serde(rename_all = "snake_case")]
6380pub enum ValidationReportFormat {
6381 #[default]
6383 Json,
6384 Yaml,
6386 Html,
6388}
6389
6390#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6402pub struct TemporalPatternsConfig {
6403 #[serde(default)]
6405 pub enabled: bool,
6406
6407 #[serde(default)]
6409 pub business_days: BusinessDaySchemaConfig,
6410
6411 #[serde(default)]
6413 pub calendars: CalendarSchemaConfig,
6414
6415 #[serde(default)]
6417 pub period_end: PeriodEndSchemaConfig,
6418
6419 #[serde(default)]
6421 pub processing_lags: ProcessingLagSchemaConfig,
6422
6423 #[serde(default)]
6425 pub fiscal_calendar: FiscalCalendarSchemaConfig,
6426
6427 #[serde(default)]
6429 pub intraday: IntraDaySchemaConfig,
6430
6431 #[serde(default)]
6433 pub timezones: TimezoneSchemaConfig,
6434}
6435
6436#[derive(Debug, Clone, Serialize, Deserialize)]
6438pub struct BusinessDaySchemaConfig {
6439 #[serde(default = "default_true")]
6441 pub enabled: bool,
6442
6443 #[serde(default = "default_half_day_policy")]
6445 pub half_day_policy: String,
6446
6447 #[serde(default)]
6449 pub settlement_rules: SettlementRulesSchemaConfig,
6450
6451 #[serde(default = "default_month_end_convention")]
6453 pub month_end_convention: String,
6454
6455 #[serde(default)]
6457 pub weekend_days: Option<Vec<String>>,
6458}
6459
6460fn default_half_day_policy() -> String {
6461 "half_day".to_string()
6462}
6463
6464fn default_month_end_convention() -> String {
6465 "modified_following".to_string()
6466}
6467
6468impl Default for BusinessDaySchemaConfig {
6469 fn default() -> Self {
6470 Self {
6471 enabled: true,
6472 half_day_policy: "half_day".to_string(),
6473 settlement_rules: SettlementRulesSchemaConfig::default(),
6474 month_end_convention: "modified_following".to_string(),
6475 weekend_days: None,
6476 }
6477 }
6478}
6479
6480#[derive(Debug, Clone, Serialize, Deserialize)]
6482pub struct SettlementRulesSchemaConfig {
6483 #[serde(default = "default_settlement_2")]
6485 pub equity_days: i32,
6486
6487 #[serde(default = "default_settlement_1")]
6489 pub government_bonds_days: i32,
6490
6491 #[serde(default = "default_settlement_2")]
6493 pub fx_spot_days: i32,
6494
6495 #[serde(default = "default_settlement_2")]
6497 pub corporate_bonds_days: i32,
6498
6499 #[serde(default = "default_wire_cutoff")]
6501 pub wire_cutoff_time: String,
6502
6503 #[serde(default = "default_settlement_1")]
6505 pub wire_international_days: i32,
6506
6507 #[serde(default = "default_settlement_1")]
6509 pub ach_days: i32,
6510}
6511
6512fn default_settlement_1() -> i32 {
6513 1
6514}
6515
6516fn default_settlement_2() -> i32 {
6517 2
6518}
6519
6520fn default_wire_cutoff() -> String {
6521 "14:00".to_string()
6522}
6523
6524impl Default for SettlementRulesSchemaConfig {
6525 fn default() -> Self {
6526 Self {
6527 equity_days: 2,
6528 government_bonds_days: 1,
6529 fx_spot_days: 2,
6530 corporate_bonds_days: 2,
6531 wire_cutoff_time: "14:00".to_string(),
6532 wire_international_days: 1,
6533 ach_days: 1,
6534 }
6535 }
6536}
6537
6538#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6540pub struct CalendarSchemaConfig {
6541 #[serde(default)]
6543 pub regions: Vec<String>,
6544
6545 #[serde(default)]
6547 pub custom_holidays: Vec<CustomHolidaySchemaConfig>,
6548}
6549
6550#[derive(Debug, Clone, Serialize, Deserialize)]
6552pub struct CustomHolidaySchemaConfig {
6553 pub name: String,
6555 pub month: u8,
6557 pub day: u8,
6559 #[serde(default = "default_holiday_multiplier")]
6561 pub activity_multiplier: f64,
6562}
6563
6564fn default_holiday_multiplier() -> f64 {
6565 0.05
6566}
6567
6568#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6570pub struct PeriodEndSchemaConfig {
6571 #[serde(default)]
6573 pub model: Option<String>,
6574
6575 #[serde(default)]
6577 pub month_end: Option<PeriodEndModelSchemaConfig>,
6578
6579 #[serde(default)]
6581 pub quarter_end: Option<PeriodEndModelSchemaConfig>,
6582
6583 #[serde(default)]
6585 pub year_end: Option<PeriodEndModelSchemaConfig>,
6586}
6587
6588#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6590pub struct PeriodEndModelSchemaConfig {
6591 #[serde(default)]
6593 pub inherit_from: Option<String>,
6594
6595 #[serde(default)]
6597 pub additional_multiplier: Option<f64>,
6598
6599 #[serde(default)]
6601 pub start_day: Option<i32>,
6602
6603 #[serde(default)]
6605 pub base_multiplier: Option<f64>,
6606
6607 #[serde(default)]
6609 pub peak_multiplier: Option<f64>,
6610
6611 #[serde(default)]
6613 pub decay_rate: Option<f64>,
6614
6615 #[serde(default)]
6617 pub sustained_high_days: Option<i32>,
6618}
6619
6620#[derive(Debug, Clone, Serialize, Deserialize)]
6622pub struct ProcessingLagSchemaConfig {
6623 #[serde(default = "default_true")]
6625 pub enabled: bool,
6626
6627 #[serde(default)]
6629 pub sales_order_lag: Option<LagDistributionSchemaConfig>,
6630
6631 #[serde(default)]
6633 pub purchase_order_lag: Option<LagDistributionSchemaConfig>,
6634
6635 #[serde(default)]
6637 pub goods_receipt_lag: Option<LagDistributionSchemaConfig>,
6638
6639 #[serde(default)]
6641 pub invoice_receipt_lag: Option<LagDistributionSchemaConfig>,
6642
6643 #[serde(default)]
6645 pub invoice_issue_lag: Option<LagDistributionSchemaConfig>,
6646
6647 #[serde(default)]
6649 pub payment_lag: Option<LagDistributionSchemaConfig>,
6650
6651 #[serde(default)]
6653 pub journal_entry_lag: Option<LagDistributionSchemaConfig>,
6654
6655 #[serde(default)]
6657 pub cross_day_posting: Option<CrossDayPostingSchemaConfig>,
6658}
6659
6660impl Default for ProcessingLagSchemaConfig {
6661 fn default() -> Self {
6662 Self {
6663 enabled: true,
6664 sales_order_lag: None,
6665 purchase_order_lag: None,
6666 goods_receipt_lag: None,
6667 invoice_receipt_lag: None,
6668 invoice_issue_lag: None,
6669 payment_lag: None,
6670 journal_entry_lag: None,
6671 cross_day_posting: None,
6672 }
6673 }
6674}
6675
6676#[derive(Debug, Clone, Serialize, Deserialize)]
6678pub struct LagDistributionSchemaConfig {
6679 pub mu: f64,
6681 pub sigma: f64,
6683 #[serde(default)]
6685 pub min_hours: Option<f64>,
6686 #[serde(default)]
6688 pub max_hours: Option<f64>,
6689}
6690
6691#[derive(Debug, Clone, Serialize, Deserialize)]
6693pub struct CrossDayPostingSchemaConfig {
6694 #[serde(default = "default_true")]
6696 pub enabled: bool,
6697
6698 #[serde(default)]
6701 pub probability_by_hour: std::collections::HashMap<u8, f64>,
6702}
6703
6704impl Default for CrossDayPostingSchemaConfig {
6705 fn default() -> Self {
6706 let mut probability_by_hour = std::collections::HashMap::new();
6707 probability_by_hour.insert(17, 0.3);
6708 probability_by_hour.insert(18, 0.6);
6709 probability_by_hour.insert(19, 0.8);
6710 probability_by_hour.insert(20, 0.9);
6711 probability_by_hour.insert(21, 0.95);
6712 probability_by_hour.insert(22, 0.99);
6713
6714 Self {
6715 enabled: true,
6716 probability_by_hour,
6717 }
6718 }
6719}
6720
6721#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6730pub struct FiscalCalendarSchemaConfig {
6731 #[serde(default)]
6733 pub enabled: bool,
6734
6735 #[serde(default = "default_fiscal_calendar_type")]
6737 pub calendar_type: String,
6738
6739 #[serde(default)]
6741 pub year_start_month: Option<u8>,
6742
6743 #[serde(default)]
6745 pub year_start_day: Option<u8>,
6746
6747 #[serde(default)]
6749 pub four_four_five: Option<FourFourFiveSchemaConfig>,
6750}
6751
6752fn default_fiscal_calendar_type() -> String {
6753 "calendar_year".to_string()
6754}
6755
6756#[derive(Debug, Clone, Serialize, Deserialize)]
6758pub struct FourFourFiveSchemaConfig {
6759 #[serde(default = "default_week_pattern")]
6761 pub pattern: String,
6762
6763 #[serde(default = "default_anchor_type")]
6765 pub anchor_type: String,
6766
6767 #[serde(default = "default_anchor_month")]
6769 pub anchor_month: u8,
6770
6771 #[serde(default = "default_leap_week_placement")]
6773 pub leap_week_placement: String,
6774}
6775
6776fn default_week_pattern() -> String {
6777 "four_four_five".to_string()
6778}
6779
6780fn default_anchor_type() -> String {
6781 "last_saturday".to_string()
6782}
6783
6784fn default_anchor_month() -> u8 {
6785 1 }
6787
6788fn default_leap_week_placement() -> String {
6789 "q4_period3".to_string()
6790}
6791
6792impl Default for FourFourFiveSchemaConfig {
6793 fn default() -> Self {
6794 Self {
6795 pattern: "four_four_five".to_string(),
6796 anchor_type: "last_saturday".to_string(),
6797 anchor_month: 1,
6798 leap_week_placement: "q4_period3".to_string(),
6799 }
6800 }
6801}
6802
6803#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6812pub struct IntraDaySchemaConfig {
6813 #[serde(default)]
6815 pub enabled: bool,
6816
6817 #[serde(default)]
6819 pub segments: Vec<IntraDaySegmentSchemaConfig>,
6820}
6821
6822#[derive(Debug, Clone, Serialize, Deserialize)]
6824pub struct IntraDaySegmentSchemaConfig {
6825 pub name: String,
6827
6828 pub start: String,
6830
6831 pub end: String,
6833
6834 #[serde(default = "default_multiplier")]
6836 pub multiplier: f64,
6837
6838 #[serde(default = "default_posting_type")]
6840 pub posting_type: String,
6841}
6842
6843fn default_multiplier() -> f64 {
6844 1.0
6845}
6846
6847fn default_posting_type() -> String {
6848 "both".to_string()
6849}
6850
6851#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6857pub struct TimezoneSchemaConfig {
6858 #[serde(default)]
6860 pub enabled: bool,
6861
6862 #[serde(default = "default_timezone")]
6864 pub default_timezone: String,
6865
6866 #[serde(default = "default_consolidation_timezone")]
6868 pub consolidation_timezone: String,
6869
6870 #[serde(default)]
6873 pub entity_mappings: Vec<EntityTimezoneMapping>,
6874}
6875
6876fn default_timezone() -> String {
6877 "America/New_York".to_string()
6878}
6879
6880fn default_consolidation_timezone() -> String {
6881 "UTC".to_string()
6882}
6883
6884#[derive(Debug, Clone, Serialize, Deserialize)]
6886pub struct EntityTimezoneMapping {
6887 pub pattern: String,
6889
6890 pub timezone: String,
6892}
6893
6894#[derive(Debug, Clone, Serialize, Deserialize)]
6900pub struct VendorNetworkSchemaConfig {
6901 #[serde(default)]
6903 pub enabled: bool,
6904
6905 #[serde(default = "default_vendor_tier_depth")]
6907 pub depth: u8,
6908
6909 #[serde(default)]
6911 pub tier1: TierCountSchemaConfig,
6912
6913 #[serde(default)]
6915 pub tier2_per_parent: TierCountSchemaConfig,
6916
6917 #[serde(default)]
6919 pub tier3_per_parent: TierCountSchemaConfig,
6920
6921 #[serde(default)]
6923 pub clusters: VendorClusterSchemaConfig,
6924
6925 #[serde(default)]
6927 pub dependencies: DependencySchemaConfig,
6928}
6929
6930fn default_vendor_tier_depth() -> u8 {
6931 3
6932}
6933
6934impl Default for VendorNetworkSchemaConfig {
6935 fn default() -> Self {
6936 Self {
6937 enabled: false,
6938 depth: 3,
6939 tier1: TierCountSchemaConfig { min: 50, max: 100 },
6940 tier2_per_parent: TierCountSchemaConfig { min: 4, max: 10 },
6941 tier3_per_parent: TierCountSchemaConfig { min: 2, max: 5 },
6942 clusters: VendorClusterSchemaConfig::default(),
6943 dependencies: DependencySchemaConfig::default(),
6944 }
6945 }
6946}
6947
6948#[derive(Debug, Clone, Serialize, Deserialize)]
6950pub struct TierCountSchemaConfig {
6951 #[serde(default = "default_tier_min")]
6953 pub min: usize,
6954
6955 #[serde(default = "default_tier_max")]
6957 pub max: usize,
6958}
6959
6960fn default_tier_min() -> usize {
6961 5
6962}
6963
6964fn default_tier_max() -> usize {
6965 20
6966}
6967
6968impl Default for TierCountSchemaConfig {
6969 fn default() -> Self {
6970 Self {
6971 min: default_tier_min(),
6972 max: default_tier_max(),
6973 }
6974 }
6975}
6976
6977#[derive(Debug, Clone, Serialize, Deserialize)]
6979pub struct VendorClusterSchemaConfig {
6980 #[serde(default = "default_reliable_strategic")]
6982 pub reliable_strategic: f64,
6983
6984 #[serde(default = "default_standard_operational")]
6986 pub standard_operational: f64,
6987
6988 #[serde(default = "default_transactional")]
6990 pub transactional: f64,
6991
6992 #[serde(default = "default_problematic")]
6994 pub problematic: f64,
6995}
6996
6997fn default_reliable_strategic() -> f64 {
6998 0.20
6999}
7000
7001fn default_standard_operational() -> f64 {
7002 0.50
7003}
7004
7005fn default_transactional() -> f64 {
7006 0.25
7007}
7008
7009fn default_problematic() -> f64 {
7010 0.05
7011}
7012
7013impl Default for VendorClusterSchemaConfig {
7014 fn default() -> Self {
7015 Self {
7016 reliable_strategic: 0.20,
7017 standard_operational: 0.50,
7018 transactional: 0.25,
7019 problematic: 0.05,
7020 }
7021 }
7022}
7023
7024#[derive(Debug, Clone, Serialize, Deserialize)]
7026pub struct DependencySchemaConfig {
7027 #[serde(default = "default_max_single_vendor")]
7029 pub max_single_vendor_concentration: f64,
7030
7031 #[serde(default = "default_max_top5")]
7033 pub top_5_concentration: f64,
7034
7035 #[serde(default = "default_single_source_percent")]
7037 pub single_source_percent: f64,
7038}
7039
7040fn default_max_single_vendor() -> f64 {
7041 0.15
7042}
7043
7044fn default_max_top5() -> f64 {
7045 0.45
7046}
7047
7048fn default_single_source_percent() -> f64 {
7049 0.05
7050}
7051
7052impl Default for DependencySchemaConfig {
7053 fn default() -> Self {
7054 Self {
7055 max_single_vendor_concentration: 0.15,
7056 top_5_concentration: 0.45,
7057 single_source_percent: 0.05,
7058 }
7059 }
7060}
7061
7062#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7068pub struct CustomerSegmentationSchemaConfig {
7069 #[serde(default)]
7071 pub enabled: bool,
7072
7073 #[serde(default)]
7075 pub value_segments: ValueSegmentsSchemaConfig,
7076
7077 #[serde(default)]
7079 pub lifecycle: LifecycleSchemaConfig,
7080
7081 #[serde(default)]
7083 pub networks: CustomerNetworksSchemaConfig,
7084}
7085
7086#[derive(Debug, Clone, Serialize, Deserialize)]
7088pub struct ValueSegmentsSchemaConfig {
7089 #[serde(default)]
7091 pub enterprise: SegmentDetailSchemaConfig,
7092
7093 #[serde(default)]
7095 pub mid_market: SegmentDetailSchemaConfig,
7096
7097 #[serde(default)]
7099 pub smb: SegmentDetailSchemaConfig,
7100
7101 #[serde(default)]
7103 pub consumer: SegmentDetailSchemaConfig,
7104}
7105
7106impl Default for ValueSegmentsSchemaConfig {
7107 fn default() -> Self {
7108 Self {
7109 enterprise: SegmentDetailSchemaConfig {
7110 revenue_share: 0.40,
7111 customer_share: 0.05,
7112 avg_order_value_range: "50000+".to_string(),
7113 },
7114 mid_market: SegmentDetailSchemaConfig {
7115 revenue_share: 0.35,
7116 customer_share: 0.20,
7117 avg_order_value_range: "5000-50000".to_string(),
7118 },
7119 smb: SegmentDetailSchemaConfig {
7120 revenue_share: 0.20,
7121 customer_share: 0.50,
7122 avg_order_value_range: "500-5000".to_string(),
7123 },
7124 consumer: SegmentDetailSchemaConfig {
7125 revenue_share: 0.05,
7126 customer_share: 0.25,
7127 avg_order_value_range: "50-500".to_string(),
7128 },
7129 }
7130 }
7131}
7132
7133#[derive(Debug, Clone, Serialize, Deserialize)]
7135pub struct SegmentDetailSchemaConfig {
7136 #[serde(default)]
7138 pub revenue_share: f64,
7139
7140 #[serde(default)]
7142 pub customer_share: f64,
7143
7144 #[serde(default)]
7146 pub avg_order_value_range: String,
7147}
7148
7149impl Default for SegmentDetailSchemaConfig {
7150 fn default() -> Self {
7151 Self {
7152 revenue_share: 0.25,
7153 customer_share: 0.25,
7154 avg_order_value_range: "1000-10000".to_string(),
7155 }
7156 }
7157}
7158
7159#[derive(Debug, Clone, Serialize, Deserialize)]
7161pub struct LifecycleSchemaConfig {
7162 #[serde(default)]
7164 pub prospect_rate: f64,
7165
7166 #[serde(default = "default_new_rate")]
7168 pub new_rate: f64,
7169
7170 #[serde(default = "default_growth_rate")]
7172 pub growth_rate: f64,
7173
7174 #[serde(default = "default_mature_rate")]
7176 pub mature_rate: f64,
7177
7178 #[serde(default = "default_at_risk_rate")]
7180 pub at_risk_rate: f64,
7181
7182 #[serde(default = "default_churned_rate")]
7184 pub churned_rate: f64,
7185
7186 #[serde(default)]
7188 pub won_back_rate: f64,
7189}
7190
7191fn default_new_rate() -> f64 {
7192 0.10
7193}
7194
7195fn default_growth_rate() -> f64 {
7196 0.15
7197}
7198
7199fn default_mature_rate() -> f64 {
7200 0.60
7201}
7202
7203fn default_at_risk_rate() -> f64 {
7204 0.10
7205}
7206
7207fn default_churned_rate() -> f64 {
7208 0.05
7209}
7210
7211impl Default for LifecycleSchemaConfig {
7212 fn default() -> Self {
7213 Self {
7214 prospect_rate: 0.0,
7215 new_rate: 0.10,
7216 growth_rate: 0.15,
7217 mature_rate: 0.60,
7218 at_risk_rate: 0.10,
7219 churned_rate: 0.05,
7220 won_back_rate: 0.0,
7221 }
7222 }
7223}
7224
7225#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7227pub struct CustomerNetworksSchemaConfig {
7228 #[serde(default)]
7230 pub referrals: ReferralSchemaConfig,
7231
7232 #[serde(default)]
7234 pub corporate_hierarchies: HierarchySchemaConfig,
7235}
7236
7237#[derive(Debug, Clone, Serialize, Deserialize)]
7239pub struct ReferralSchemaConfig {
7240 #[serde(default = "default_true")]
7242 pub enabled: bool,
7243
7244 #[serde(default = "default_referral_rate")]
7246 pub referral_rate: f64,
7247}
7248
7249fn default_referral_rate() -> f64 {
7250 0.15
7251}
7252
7253impl Default for ReferralSchemaConfig {
7254 fn default() -> Self {
7255 Self {
7256 enabled: true,
7257 referral_rate: 0.15,
7258 }
7259 }
7260}
7261
7262#[derive(Debug, Clone, Serialize, Deserialize)]
7264pub struct HierarchySchemaConfig {
7265 #[serde(default = "default_true")]
7267 pub enabled: bool,
7268
7269 #[serde(default = "default_hierarchy_rate")]
7271 pub probability: f64,
7272}
7273
7274fn default_hierarchy_rate() -> f64 {
7275 0.30
7276}
7277
7278impl Default for HierarchySchemaConfig {
7279 fn default() -> Self {
7280 Self {
7281 enabled: true,
7282 probability: 0.30,
7283 }
7284 }
7285}
7286
7287#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7293pub struct RelationshipStrengthSchemaConfig {
7294 #[serde(default)]
7296 pub enabled: bool,
7297
7298 #[serde(default)]
7300 pub calculation: StrengthCalculationSchemaConfig,
7301
7302 #[serde(default)]
7304 pub thresholds: StrengthThresholdsSchemaConfig,
7305}
7306
7307#[derive(Debug, Clone, Serialize, Deserialize)]
7309pub struct StrengthCalculationSchemaConfig {
7310 #[serde(default = "default_volume_weight")]
7312 pub transaction_volume_weight: f64,
7313
7314 #[serde(default = "default_count_weight")]
7316 pub transaction_count_weight: f64,
7317
7318 #[serde(default = "default_duration_weight")]
7320 pub relationship_duration_weight: f64,
7321
7322 #[serde(default = "default_recency_weight")]
7324 pub recency_weight: f64,
7325
7326 #[serde(default = "default_mutual_weight")]
7328 pub mutual_connections_weight: f64,
7329
7330 #[serde(default = "default_recency_half_life")]
7332 pub recency_half_life_days: u32,
7333}
7334
7335fn default_volume_weight() -> f64 {
7336 0.30
7337}
7338
7339fn default_count_weight() -> f64 {
7340 0.25
7341}
7342
7343fn default_duration_weight() -> f64 {
7344 0.20
7345}
7346
7347fn default_recency_weight() -> f64 {
7348 0.15
7349}
7350
7351fn default_mutual_weight() -> f64 {
7352 0.10
7353}
7354
7355fn default_recency_half_life() -> u32 {
7356 90
7357}
7358
7359impl Default for StrengthCalculationSchemaConfig {
7360 fn default() -> Self {
7361 Self {
7362 transaction_volume_weight: 0.30,
7363 transaction_count_weight: 0.25,
7364 relationship_duration_weight: 0.20,
7365 recency_weight: 0.15,
7366 mutual_connections_weight: 0.10,
7367 recency_half_life_days: 90,
7368 }
7369 }
7370}
7371
7372#[derive(Debug, Clone, Serialize, Deserialize)]
7374pub struct StrengthThresholdsSchemaConfig {
7375 #[serde(default = "default_strong_threshold")]
7377 pub strong: f64,
7378
7379 #[serde(default = "default_moderate_threshold")]
7381 pub moderate: f64,
7382
7383 #[serde(default = "default_weak_threshold")]
7385 pub weak: f64,
7386}
7387
7388fn default_strong_threshold() -> f64 {
7389 0.7
7390}
7391
7392fn default_moderate_threshold() -> f64 {
7393 0.4
7394}
7395
7396fn default_weak_threshold() -> f64 {
7397 0.1
7398}
7399
7400impl Default for StrengthThresholdsSchemaConfig {
7401 fn default() -> Self {
7402 Self {
7403 strong: 0.7,
7404 moderate: 0.4,
7405 weak: 0.1,
7406 }
7407 }
7408}
7409
7410#[derive(Debug, Clone, Serialize, Deserialize)]
7416pub struct CrossProcessLinksSchemaConfig {
7417 #[serde(default)]
7419 pub enabled: bool,
7420
7421 #[serde(default = "default_true")]
7423 pub inventory_p2p_o2c: bool,
7424
7425 #[serde(default = "default_true")]
7427 pub payment_bank_reconciliation: bool,
7428
7429 #[serde(default = "default_true")]
7431 pub intercompany_bilateral: bool,
7432
7433 #[serde(default = "default_inventory_link_rate")]
7435 pub inventory_link_rate: f64,
7436}
7437
7438fn default_inventory_link_rate() -> f64 {
7439 0.30
7440}
7441
7442impl Default for CrossProcessLinksSchemaConfig {
7443 fn default() -> Self {
7444 Self {
7445 enabled: false,
7446 inventory_p2p_o2c: true,
7447 payment_bank_reconciliation: true,
7448 intercompany_bilateral: true,
7449 inventory_link_rate: 0.30,
7450 }
7451 }
7452}
7453
7454#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7460pub struct OrganizationalEventsSchemaConfig {
7461 #[serde(default)]
7463 pub enabled: bool,
7464
7465 #[serde(default)]
7467 pub effect_blending: EffectBlendingModeConfig,
7468
7469 #[serde(default)]
7471 pub events: Vec<OrganizationalEventSchemaConfig>,
7472
7473 #[serde(default)]
7475 pub process_evolution: Vec<ProcessEvolutionSchemaConfig>,
7476
7477 #[serde(default)]
7479 pub technology_transitions: Vec<TechnologyTransitionSchemaConfig>,
7480}
7481
7482#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
7484#[serde(rename_all = "snake_case")]
7485pub enum EffectBlendingModeConfig {
7486 #[default]
7488 Multiplicative,
7489 Additive,
7491 Maximum,
7493 Minimum,
7495}
7496
7497#[derive(Debug, Clone, Serialize, Deserialize)]
7499pub struct OrganizationalEventSchemaConfig {
7500 pub id: String,
7502
7503 pub event_type: OrganizationalEventTypeSchemaConfig,
7505
7506 pub effective_date: String,
7508
7509 #[serde(default = "default_org_transition_months")]
7511 pub transition_months: u32,
7512
7513 #[serde(default)]
7515 pub description: Option<String>,
7516}
7517
7518fn default_org_transition_months() -> u32 {
7519 6
7520}
7521
7522#[derive(Debug, Clone, Serialize, Deserialize)]
7524#[serde(tag = "type", rename_all = "snake_case")]
7525pub enum OrganizationalEventTypeSchemaConfig {
7526 Acquisition {
7528 acquired_entity: String,
7530 #[serde(default = "default_acquisition_volume")]
7532 volume_increase: f64,
7533 #[serde(default = "default_acquisition_error")]
7535 integration_error_rate: f64,
7536 #[serde(default = "default_parallel_days")]
7538 parallel_posting_days: u32,
7539 },
7540 Divestiture {
7542 divested_entity: String,
7544 #[serde(default = "default_divestiture_volume")]
7546 volume_reduction: f64,
7547 #[serde(default = "default_true_val")]
7549 remove_entity: bool,
7550 },
7551 Reorganization {
7553 #[serde(default)]
7555 cost_center_remapping: std::collections::HashMap<String, String>,
7556 #[serde(default = "default_reorg_error")]
7558 transition_error_rate: f64,
7559 },
7560 LeadershipChange {
7562 role: String,
7564 #[serde(default)]
7566 policy_changes: Vec<String>,
7567 },
7568 WorkforceReduction {
7570 #[serde(default = "default_workforce_reduction")]
7572 reduction_percent: f64,
7573 #[serde(default = "default_workforce_error")]
7575 error_rate_increase: f64,
7576 },
7577 Merger {
7579 merged_entity: String,
7581 #[serde(default = "default_merger_volume")]
7583 volume_increase: f64,
7584 },
7585}
7586
7587fn default_acquisition_volume() -> f64 {
7588 1.35
7589}
7590
7591fn default_acquisition_error() -> f64 {
7592 0.05
7593}
7594
7595fn default_parallel_days() -> u32 {
7596 30
7597}
7598
7599fn default_divestiture_volume() -> f64 {
7600 0.70
7601}
7602
7603fn default_true_val() -> bool {
7604 true
7605}
7606
7607fn default_reorg_error() -> f64 {
7608 0.04
7609}
7610
7611fn default_workforce_reduction() -> f64 {
7612 0.10
7613}
7614
7615fn default_workforce_error() -> f64 {
7616 0.05
7617}
7618
7619fn default_merger_volume() -> f64 {
7620 1.80
7621}
7622
7623#[derive(Debug, Clone, Serialize, Deserialize)]
7625pub struct ProcessEvolutionSchemaConfig {
7626 pub id: String,
7628
7629 pub event_type: ProcessEvolutionTypeSchemaConfig,
7631
7632 pub effective_date: String,
7634
7635 #[serde(default)]
7637 pub description: Option<String>,
7638}
7639
7640#[derive(Debug, Clone, Serialize, Deserialize)]
7642#[serde(tag = "type", rename_all = "snake_case")]
7643pub enum ProcessEvolutionTypeSchemaConfig {
7644 ProcessAutomation {
7646 process_name: String,
7648 #[serde(default = "default_manual_before")]
7650 manual_rate_before: f64,
7651 #[serde(default = "default_manual_after")]
7653 manual_rate_after: f64,
7654 },
7655 ApprovalWorkflowChange {
7657 description: String,
7659 },
7660 ControlEnhancement {
7662 control_id: String,
7664 #[serde(default = "default_error_reduction")]
7666 error_reduction: f64,
7667 },
7668}
7669
7670fn default_manual_before() -> f64 {
7671 0.80
7672}
7673
7674fn default_manual_after() -> f64 {
7675 0.15
7676}
7677
7678fn default_error_reduction() -> f64 {
7679 0.02
7680}
7681
7682#[derive(Debug, Clone, Serialize, Deserialize)]
7684pub struct TechnologyTransitionSchemaConfig {
7685 pub id: String,
7687
7688 pub event_type: TechnologyTransitionTypeSchemaConfig,
7690
7691 #[serde(default)]
7693 pub description: Option<String>,
7694}
7695
7696#[derive(Debug, Clone, Serialize, Deserialize)]
7698#[serde(tag = "type", rename_all = "snake_case")]
7699pub enum TechnologyTransitionTypeSchemaConfig {
7700 ErpMigration {
7702 source_system: String,
7704 target_system: String,
7706 cutover_date: String,
7708 stabilization_end: String,
7710 #[serde(default = "default_erp_duplicate_rate")]
7712 duplicate_rate: f64,
7713 #[serde(default = "default_format_mismatch")]
7715 format_mismatch_rate: f64,
7716 },
7717 ModuleImplementation {
7719 module_name: String,
7721 go_live_date: String,
7723 },
7724}
7725
7726fn default_erp_duplicate_rate() -> f64 {
7727 0.02
7728}
7729
7730fn default_format_mismatch() -> f64 {
7731 0.03
7732}
7733
7734#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7740pub struct BehavioralDriftSchemaConfig {
7741 #[serde(default)]
7743 pub enabled: bool,
7744
7745 #[serde(default)]
7747 pub vendor_behavior: VendorBehaviorSchemaConfig,
7748
7749 #[serde(default)]
7751 pub customer_behavior: CustomerBehaviorSchemaConfig,
7752
7753 #[serde(default)]
7755 pub employee_behavior: EmployeeBehaviorSchemaConfig,
7756
7757 #[serde(default)]
7759 pub collective: CollectiveBehaviorSchemaConfig,
7760}
7761
7762#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7764pub struct VendorBehaviorSchemaConfig {
7765 #[serde(default)]
7767 pub payment_terms_drift: PaymentTermsDriftSchemaConfig,
7768
7769 #[serde(default)]
7771 pub quality_drift: QualityDriftSchemaConfig,
7772}
7773
7774#[derive(Debug, Clone, Serialize, Deserialize)]
7776pub struct PaymentTermsDriftSchemaConfig {
7777 #[serde(default = "default_extension_rate")]
7779 pub extension_rate_per_year: f64,
7780
7781 #[serde(default = "default_economic_sensitivity")]
7783 pub economic_sensitivity: f64,
7784}
7785
7786fn default_extension_rate() -> f64 {
7787 2.5
7788}
7789
7790fn default_economic_sensitivity() -> f64 {
7791 1.0
7792}
7793
7794impl Default for PaymentTermsDriftSchemaConfig {
7795 fn default() -> Self {
7796 Self {
7797 extension_rate_per_year: 2.5,
7798 economic_sensitivity: 1.0,
7799 }
7800 }
7801}
7802
7803#[derive(Debug, Clone, Serialize, Deserialize)]
7805pub struct QualityDriftSchemaConfig {
7806 #[serde(default = "default_improvement_rate")]
7808 pub new_vendor_improvement_rate: f64,
7809
7810 #[serde(default = "default_decline_rate")]
7812 pub complacency_decline_rate: f64,
7813}
7814
7815fn default_improvement_rate() -> f64 {
7816 0.02
7817}
7818
7819fn default_decline_rate() -> f64 {
7820 0.01
7821}
7822
7823impl Default for QualityDriftSchemaConfig {
7824 fn default() -> Self {
7825 Self {
7826 new_vendor_improvement_rate: 0.02,
7827 complacency_decline_rate: 0.01,
7828 }
7829 }
7830}
7831
7832#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7834pub struct CustomerBehaviorSchemaConfig {
7835 #[serde(default)]
7837 pub payment_drift: CustomerPaymentDriftSchemaConfig,
7838
7839 #[serde(default)]
7841 pub order_drift: OrderDriftSchemaConfig,
7842}
7843
7844#[derive(Debug, Clone, Serialize, Deserialize)]
7846pub struct CustomerPaymentDriftSchemaConfig {
7847 #[serde(default = "default_downturn_extension")]
7849 pub downturn_days_extension: (u32, u32),
7850
7851 #[serde(default = "default_bad_debt_increase")]
7853 pub downturn_bad_debt_increase: f64,
7854}
7855
7856fn default_downturn_extension() -> (u32, u32) {
7857 (5, 15)
7858}
7859
7860fn default_bad_debt_increase() -> f64 {
7861 0.02
7862}
7863
7864impl Default for CustomerPaymentDriftSchemaConfig {
7865 fn default() -> Self {
7866 Self {
7867 downturn_days_extension: (5, 15),
7868 downturn_bad_debt_increase: 0.02,
7869 }
7870 }
7871}
7872
7873#[derive(Debug, Clone, Serialize, Deserialize)]
7875pub struct OrderDriftSchemaConfig {
7876 #[serde(default = "default_digital_shift")]
7878 pub digital_shift_rate: f64,
7879}
7880
7881fn default_digital_shift() -> f64 {
7882 0.05
7883}
7884
7885impl Default for OrderDriftSchemaConfig {
7886 fn default() -> Self {
7887 Self {
7888 digital_shift_rate: 0.05,
7889 }
7890 }
7891}
7892
7893#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7895pub struct EmployeeBehaviorSchemaConfig {
7896 #[serde(default)]
7898 pub approval_drift: ApprovalDriftSchemaConfig,
7899
7900 #[serde(default)]
7902 pub error_drift: ErrorDriftSchemaConfig,
7903}
7904
7905#[derive(Debug, Clone, Serialize, Deserialize)]
7907pub struct ApprovalDriftSchemaConfig {
7908 #[serde(default = "default_eom_intensity")]
7910 pub eom_intensity_increase_per_year: f64,
7911
7912 #[serde(default = "default_rubber_stamp")]
7914 pub rubber_stamp_volume_threshold: u32,
7915}
7916
7917fn default_eom_intensity() -> f64 {
7918 0.05
7919}
7920
7921fn default_rubber_stamp() -> u32 {
7922 50
7923}
7924
7925impl Default for ApprovalDriftSchemaConfig {
7926 fn default() -> Self {
7927 Self {
7928 eom_intensity_increase_per_year: 0.05,
7929 rubber_stamp_volume_threshold: 50,
7930 }
7931 }
7932}
7933
7934#[derive(Debug, Clone, Serialize, Deserialize)]
7936pub struct ErrorDriftSchemaConfig {
7937 #[serde(default = "default_new_error")]
7939 pub new_employee_error_rate: f64,
7940
7941 #[serde(default = "default_learning_months")]
7943 pub learning_curve_months: u32,
7944}
7945
7946fn default_new_error() -> f64 {
7947 0.08
7948}
7949
7950fn default_learning_months() -> u32 {
7951 6
7952}
7953
7954impl Default for ErrorDriftSchemaConfig {
7955 fn default() -> Self {
7956 Self {
7957 new_employee_error_rate: 0.08,
7958 learning_curve_months: 6,
7959 }
7960 }
7961}
7962
7963#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7965pub struct CollectiveBehaviorSchemaConfig {
7966 #[serde(default)]
7968 pub automation_adoption: AutomationAdoptionSchemaConfig,
7969}
7970
7971#[derive(Debug, Clone, Serialize, Deserialize)]
7973pub struct AutomationAdoptionSchemaConfig {
7974 #[serde(default)]
7976 pub s_curve_enabled: bool,
7977
7978 #[serde(default = "default_midpoint")]
7980 pub adoption_midpoint_months: u32,
7981
7982 #[serde(default = "default_steepness")]
7984 pub steepness: f64,
7985}
7986
7987fn default_midpoint() -> u32 {
7988 24
7989}
7990
7991fn default_steepness() -> f64 {
7992 0.15
7993}
7994
7995impl Default for AutomationAdoptionSchemaConfig {
7996 fn default() -> Self {
7997 Self {
7998 s_curve_enabled: false,
7999 adoption_midpoint_months: 24,
8000 steepness: 0.15,
8001 }
8002 }
8003}
8004
8005#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8011pub struct MarketDriftSchemaConfig {
8012 #[serde(default)]
8014 pub enabled: bool,
8015
8016 #[serde(default)]
8018 pub economic_cycle: MarketEconomicCycleSchemaConfig,
8019
8020 #[serde(default)]
8022 pub industry_cycles: std::collections::HashMap<String, IndustryCycleSchemaConfig>,
8023
8024 #[serde(default)]
8026 pub commodities: CommoditiesSchemaConfig,
8027}
8028
8029#[derive(Debug, Clone, Serialize, Deserialize)]
8031pub struct MarketEconomicCycleSchemaConfig {
8032 #[serde(default)]
8034 pub enabled: bool,
8035
8036 #[serde(default)]
8038 pub cycle_type: CycleTypeSchemaConfig,
8039
8040 #[serde(default = "default_market_cycle_period")]
8042 pub period_months: u32,
8043
8044 #[serde(default = "default_market_amplitude")]
8046 pub amplitude: f64,
8047
8048 #[serde(default)]
8050 pub recession: RecessionSchemaConfig,
8051}
8052
8053fn default_market_cycle_period() -> u32 {
8054 48
8055}
8056
8057fn default_market_amplitude() -> f64 {
8058 0.15
8059}
8060
8061impl Default for MarketEconomicCycleSchemaConfig {
8062 fn default() -> Self {
8063 Self {
8064 enabled: false,
8065 cycle_type: CycleTypeSchemaConfig::Sinusoidal,
8066 period_months: 48,
8067 amplitude: 0.15,
8068 recession: RecessionSchemaConfig::default(),
8069 }
8070 }
8071}
8072
8073#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
8075#[serde(rename_all = "snake_case")]
8076pub enum CycleTypeSchemaConfig {
8077 #[default]
8079 Sinusoidal,
8080 Asymmetric,
8082 MeanReverting,
8084}
8085
8086#[derive(Debug, Clone, Serialize, Deserialize)]
8088pub struct RecessionSchemaConfig {
8089 #[serde(default)]
8091 pub enabled: bool,
8092
8093 #[serde(default = "default_recession_prob")]
8095 pub probability_per_year: f64,
8096
8097 #[serde(default)]
8099 pub severity: RecessionSeveritySchemaConfig,
8100
8101 #[serde(default)]
8103 pub recession_periods: Vec<RecessionPeriodSchemaConfig>,
8104}
8105
8106fn default_recession_prob() -> f64 {
8107 0.10
8108}
8109
8110impl Default for RecessionSchemaConfig {
8111 fn default() -> Self {
8112 Self {
8113 enabled: false,
8114 probability_per_year: 0.10,
8115 severity: RecessionSeveritySchemaConfig::Moderate,
8116 recession_periods: Vec::new(),
8117 }
8118 }
8119}
8120
8121#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
8123#[serde(rename_all = "snake_case")]
8124pub enum RecessionSeveritySchemaConfig {
8125 Mild,
8127 #[default]
8129 Moderate,
8130 Severe,
8132}
8133
8134#[derive(Debug, Clone, Serialize, Deserialize)]
8136pub struct RecessionPeriodSchemaConfig {
8137 pub start_month: u32,
8139 pub duration_months: u32,
8141}
8142
8143#[derive(Debug, Clone, Serialize, Deserialize)]
8145pub struct IndustryCycleSchemaConfig {
8146 #[serde(default = "default_industry_period")]
8148 pub period_months: u32,
8149
8150 #[serde(default = "default_industry_amp")]
8152 pub amplitude: f64,
8153}
8154
8155fn default_industry_period() -> u32 {
8156 36
8157}
8158
8159fn default_industry_amp() -> f64 {
8160 0.20
8161}
8162
8163#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8165pub struct CommoditiesSchemaConfig {
8166 #[serde(default)]
8168 pub enabled: bool,
8169
8170 #[serde(default)]
8172 pub items: Vec<CommodityItemSchemaConfig>,
8173}
8174
8175#[derive(Debug, Clone, Serialize, Deserialize)]
8177pub struct CommodityItemSchemaConfig {
8178 pub name: String,
8180
8181 #[serde(default = "default_volatility")]
8183 pub volatility: f64,
8184
8185 #[serde(default)]
8187 pub cogs_pass_through: f64,
8188
8189 #[serde(default)]
8191 pub overhead_pass_through: f64,
8192}
8193
8194fn default_volatility() -> f64 {
8195 0.20
8196}
8197
8198#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8204pub struct DriftLabelingSchemaConfig {
8205 #[serde(default)]
8207 pub enabled: bool,
8208
8209 #[serde(default)]
8211 pub statistical: StatisticalDriftLabelingSchemaConfig,
8212
8213 #[serde(default)]
8215 pub categorical: CategoricalDriftLabelingSchemaConfig,
8216
8217 #[serde(default)]
8219 pub temporal: TemporalDriftLabelingSchemaConfig,
8220
8221 #[serde(default)]
8223 pub regulatory_calendar_preset: Option<String>,
8224}
8225
8226#[derive(Debug, Clone, Serialize, Deserialize)]
8228pub struct StatisticalDriftLabelingSchemaConfig {
8229 #[serde(default = "default_true_val")]
8231 pub enabled: bool,
8232
8233 #[serde(default = "default_min_magnitude")]
8235 pub min_magnitude_threshold: f64,
8236}
8237
8238fn default_min_magnitude() -> f64 {
8239 0.05
8240}
8241
8242impl Default for StatisticalDriftLabelingSchemaConfig {
8243 fn default() -> Self {
8244 Self {
8245 enabled: true,
8246 min_magnitude_threshold: 0.05,
8247 }
8248 }
8249}
8250
8251#[derive(Debug, Clone, Serialize, Deserialize)]
8253pub struct CategoricalDriftLabelingSchemaConfig {
8254 #[serde(default = "default_true_val")]
8256 pub enabled: bool,
8257}
8258
8259impl Default for CategoricalDriftLabelingSchemaConfig {
8260 fn default() -> Self {
8261 Self { enabled: true }
8262 }
8263}
8264
8265#[derive(Debug, Clone, Serialize, Deserialize)]
8267pub struct TemporalDriftLabelingSchemaConfig {
8268 #[serde(default = "default_true_val")]
8270 pub enabled: bool,
8271}
8272
8273impl Default for TemporalDriftLabelingSchemaConfig {
8274 fn default() -> Self {
8275 Self { enabled: true }
8276 }
8277}
8278
8279#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8292pub struct EnhancedAnomalyConfig {
8293 #[serde(default)]
8295 pub enabled: bool,
8296
8297 #[serde(default)]
8299 pub rates: AnomalyRateConfig,
8300
8301 #[serde(default)]
8303 pub multi_stage_schemes: MultiStageSchemeConfig,
8304
8305 #[serde(default)]
8307 pub correlated_injection: CorrelatedInjectionConfig,
8308
8309 #[serde(default)]
8311 pub near_miss: NearMissConfig,
8312
8313 #[serde(default)]
8315 pub difficulty_classification: DifficultyClassificationConfig,
8316
8317 #[serde(default)]
8319 pub context_aware: ContextAwareConfig,
8320
8321 #[serde(default)]
8323 pub labeling: EnhancedLabelingConfig,
8324}
8325
8326#[derive(Debug, Clone, Serialize, Deserialize)]
8328pub struct AnomalyRateConfig {
8329 #[serde(default = "default_total_anomaly_rate")]
8331 pub total_rate: f64,
8332
8333 #[serde(default = "default_fraud_anomaly_rate")]
8335 pub fraud_rate: f64,
8336
8337 #[serde(default = "default_error_anomaly_rate")]
8339 pub error_rate: f64,
8340
8341 #[serde(default = "default_process_anomaly_rate")]
8343 pub process_rate: f64,
8344}
8345
8346fn default_total_anomaly_rate() -> f64 {
8347 0.03
8348}
8349fn default_fraud_anomaly_rate() -> f64 {
8350 0.01
8351}
8352fn default_error_anomaly_rate() -> f64 {
8353 0.015
8354}
8355fn default_process_anomaly_rate() -> f64 {
8356 0.005
8357}
8358
8359impl Default for AnomalyRateConfig {
8360 fn default() -> Self {
8361 Self {
8362 total_rate: default_total_anomaly_rate(),
8363 fraud_rate: default_fraud_anomaly_rate(),
8364 error_rate: default_error_anomaly_rate(),
8365 process_rate: default_process_anomaly_rate(),
8366 }
8367 }
8368}
8369
8370#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8372pub struct MultiStageSchemeConfig {
8373 #[serde(default)]
8375 pub enabled: bool,
8376
8377 #[serde(default)]
8379 pub embezzlement: EmbezzlementSchemeConfig,
8380
8381 #[serde(default)]
8383 pub revenue_manipulation: RevenueManipulationSchemeConfig,
8384
8385 #[serde(default)]
8387 pub kickback: KickbackSchemeConfig,
8388}
8389
8390#[derive(Debug, Clone, Serialize, Deserialize)]
8392pub struct EmbezzlementSchemeConfig {
8393 #[serde(default = "default_embezzlement_probability")]
8395 pub probability: f64,
8396
8397 #[serde(default)]
8399 pub testing_stage: SchemeStageConfig,
8400
8401 #[serde(default)]
8403 pub escalation_stage: SchemeStageConfig,
8404
8405 #[serde(default)]
8407 pub acceleration_stage: SchemeStageConfig,
8408
8409 #[serde(default)]
8411 pub desperation_stage: SchemeStageConfig,
8412}
8413
8414fn default_embezzlement_probability() -> f64 {
8415 0.02
8416}
8417
8418impl Default for EmbezzlementSchemeConfig {
8419 fn default() -> Self {
8420 Self {
8421 probability: default_embezzlement_probability(),
8422 testing_stage: SchemeStageConfig {
8423 duration_months: 2,
8424 amount_min: 100.0,
8425 amount_max: 500.0,
8426 transaction_count_min: 2,
8427 transaction_count_max: 5,
8428 difficulty: "hard".to_string(),
8429 },
8430 escalation_stage: SchemeStageConfig {
8431 duration_months: 6,
8432 amount_min: 500.0,
8433 amount_max: 2000.0,
8434 transaction_count_min: 3,
8435 transaction_count_max: 8,
8436 difficulty: "moderate".to_string(),
8437 },
8438 acceleration_stage: SchemeStageConfig {
8439 duration_months: 3,
8440 amount_min: 2000.0,
8441 amount_max: 10000.0,
8442 transaction_count_min: 5,
8443 transaction_count_max: 12,
8444 difficulty: "easy".to_string(),
8445 },
8446 desperation_stage: SchemeStageConfig {
8447 duration_months: 1,
8448 amount_min: 10000.0,
8449 amount_max: 50000.0,
8450 transaction_count_min: 3,
8451 transaction_count_max: 6,
8452 difficulty: "trivial".to_string(),
8453 },
8454 }
8455 }
8456}
8457
8458#[derive(Debug, Clone, Serialize, Deserialize)]
8460pub struct RevenueManipulationSchemeConfig {
8461 #[serde(default = "default_revenue_manipulation_probability")]
8463 pub probability: f64,
8464
8465 #[serde(default = "default_early_recognition_target")]
8467 pub early_recognition_target: f64,
8468
8469 #[serde(default = "default_expense_deferral_target")]
8471 pub expense_deferral_target: f64,
8472
8473 #[serde(default = "default_reserve_release_target")]
8475 pub reserve_release_target: f64,
8476
8477 #[serde(default = "default_channel_stuffing_target")]
8479 pub channel_stuffing_target: f64,
8480}
8481
8482fn default_revenue_manipulation_probability() -> f64 {
8483 0.01
8484}
8485fn default_early_recognition_target() -> f64 {
8486 0.02
8487}
8488fn default_expense_deferral_target() -> f64 {
8489 0.03
8490}
8491fn default_reserve_release_target() -> f64 {
8492 0.02
8493}
8494fn default_channel_stuffing_target() -> f64 {
8495 0.05
8496}
8497
8498impl Default for RevenueManipulationSchemeConfig {
8499 fn default() -> Self {
8500 Self {
8501 probability: default_revenue_manipulation_probability(),
8502 early_recognition_target: default_early_recognition_target(),
8503 expense_deferral_target: default_expense_deferral_target(),
8504 reserve_release_target: default_reserve_release_target(),
8505 channel_stuffing_target: default_channel_stuffing_target(),
8506 }
8507 }
8508}
8509
8510#[derive(Debug, Clone, Serialize, Deserialize)]
8512pub struct KickbackSchemeConfig {
8513 #[serde(default = "default_kickback_probability")]
8515 pub probability: f64,
8516
8517 #[serde(default = "default_kickback_inflation_min")]
8519 pub inflation_min: f64,
8520
8521 #[serde(default = "default_kickback_inflation_max")]
8523 pub inflation_max: f64,
8524
8525 #[serde(default = "default_kickback_percent")]
8527 pub kickback_percent: f64,
8528
8529 #[serde(default = "default_kickback_setup_months")]
8531 pub setup_months: u32,
8532
8533 #[serde(default = "default_kickback_operation_months")]
8535 pub operation_months: u32,
8536}
8537
8538fn default_kickback_probability() -> f64 {
8539 0.01
8540}
8541fn default_kickback_inflation_min() -> f64 {
8542 0.10
8543}
8544fn default_kickback_inflation_max() -> f64 {
8545 0.25
8546}
8547fn default_kickback_percent() -> f64 {
8548 0.50
8549}
8550fn default_kickback_setup_months() -> u32 {
8551 3
8552}
8553fn default_kickback_operation_months() -> u32 {
8554 12
8555}
8556
8557impl Default for KickbackSchemeConfig {
8558 fn default() -> Self {
8559 Self {
8560 probability: default_kickback_probability(),
8561 inflation_min: default_kickback_inflation_min(),
8562 inflation_max: default_kickback_inflation_max(),
8563 kickback_percent: default_kickback_percent(),
8564 setup_months: default_kickback_setup_months(),
8565 operation_months: default_kickback_operation_months(),
8566 }
8567 }
8568}
8569
8570#[derive(Debug, Clone, Serialize, Deserialize)]
8572pub struct SchemeStageConfig {
8573 pub duration_months: u32,
8575
8576 pub amount_min: f64,
8578
8579 pub amount_max: f64,
8581
8582 pub transaction_count_min: u32,
8584
8585 pub transaction_count_max: u32,
8587
8588 pub difficulty: String,
8590}
8591
8592impl Default for SchemeStageConfig {
8593 fn default() -> Self {
8594 Self {
8595 duration_months: 3,
8596 amount_min: 100.0,
8597 amount_max: 1000.0,
8598 transaction_count_min: 2,
8599 transaction_count_max: 10,
8600 difficulty: "moderate".to_string(),
8601 }
8602 }
8603}
8604
8605#[derive(Debug, Clone, Serialize, Deserialize)]
8607pub struct CorrelatedInjectionConfig {
8608 #[serde(default)]
8610 pub enabled: bool,
8611
8612 #[serde(default = "default_true_val")]
8614 pub fraud_concealment: bool,
8615
8616 #[serde(default = "default_true_val")]
8618 pub error_cascade: bool,
8619
8620 #[serde(default = "default_true_val")]
8622 pub temporal_clustering: bool,
8623
8624 #[serde(default)]
8626 pub temporal_clustering_config: TemporalClusteringConfig,
8627
8628 #[serde(default)]
8630 pub co_occurrence_patterns: Vec<CoOccurrencePatternConfig>,
8631}
8632
8633impl Default for CorrelatedInjectionConfig {
8634 fn default() -> Self {
8635 Self {
8636 enabled: false,
8637 fraud_concealment: true,
8638 error_cascade: true,
8639 temporal_clustering: true,
8640 temporal_clustering_config: TemporalClusteringConfig::default(),
8641 co_occurrence_patterns: Vec::new(),
8642 }
8643 }
8644}
8645
8646#[derive(Debug, Clone, Serialize, Deserialize)]
8648pub struct TemporalClusteringConfig {
8649 #[serde(default = "default_period_end_multiplier")]
8651 pub period_end_multiplier: f64,
8652
8653 #[serde(default = "default_period_end_days")]
8655 pub period_end_days: u32,
8656
8657 #[serde(default = "default_quarter_end_multiplier")]
8659 pub quarter_end_multiplier: f64,
8660
8661 #[serde(default = "default_year_end_multiplier")]
8663 pub year_end_multiplier: f64,
8664}
8665
8666fn default_period_end_multiplier() -> f64 {
8667 2.5
8668}
8669fn default_period_end_days() -> u32 {
8670 5
8671}
8672fn default_quarter_end_multiplier() -> f64 {
8673 1.5
8674}
8675fn default_year_end_multiplier() -> f64 {
8676 2.0
8677}
8678
8679impl Default for TemporalClusteringConfig {
8680 fn default() -> Self {
8681 Self {
8682 period_end_multiplier: default_period_end_multiplier(),
8683 period_end_days: default_period_end_days(),
8684 quarter_end_multiplier: default_quarter_end_multiplier(),
8685 year_end_multiplier: default_year_end_multiplier(),
8686 }
8687 }
8688}
8689
8690#[derive(Debug, Clone, Serialize, Deserialize)]
8692pub struct CoOccurrencePatternConfig {
8693 pub name: String,
8695
8696 pub primary_type: String,
8698
8699 pub correlated: Vec<CorrelatedAnomalyConfig>,
8701}
8702
8703#[derive(Debug, Clone, Serialize, Deserialize)]
8705pub struct CorrelatedAnomalyConfig {
8706 pub anomaly_type: String,
8708
8709 pub probability: f64,
8711
8712 pub lag_days_min: i32,
8714
8715 pub lag_days_max: i32,
8717}
8718
8719#[derive(Debug, Clone, Serialize, Deserialize)]
8721pub struct NearMissConfig {
8722 #[serde(default)]
8724 pub enabled: bool,
8725
8726 #[serde(default = "default_near_miss_proportion")]
8728 pub proportion: f64,
8729
8730 #[serde(default = "default_true_val")]
8732 pub near_duplicate: bool,
8733
8734 #[serde(default)]
8736 pub near_duplicate_days: NearDuplicateDaysConfig,
8737
8738 #[serde(default = "default_true_val")]
8740 pub threshold_proximity: bool,
8741
8742 #[serde(default)]
8744 pub threshold_proximity_range: ThresholdProximityRangeConfig,
8745
8746 #[serde(default = "default_true_val")]
8748 pub unusual_legitimate: bool,
8749
8750 #[serde(default = "default_unusual_legitimate_types")]
8752 pub unusual_legitimate_types: Vec<String>,
8753
8754 #[serde(default = "default_true_val")]
8756 pub corrected_errors: bool,
8757
8758 #[serde(default)]
8760 pub corrected_error_lag: CorrectedErrorLagConfig,
8761}
8762
8763fn default_near_miss_proportion() -> f64 {
8764 0.30
8765}
8766
8767fn default_unusual_legitimate_types() -> Vec<String> {
8768 vec![
8769 "year_end_bonus".to_string(),
8770 "contract_prepayment".to_string(),
8771 "insurance_claim".to_string(),
8772 "settlement_payment".to_string(),
8773 ]
8774}
8775
8776impl Default for NearMissConfig {
8777 fn default() -> Self {
8778 Self {
8779 enabled: false,
8780 proportion: default_near_miss_proportion(),
8781 near_duplicate: true,
8782 near_duplicate_days: NearDuplicateDaysConfig::default(),
8783 threshold_proximity: true,
8784 threshold_proximity_range: ThresholdProximityRangeConfig::default(),
8785 unusual_legitimate: true,
8786 unusual_legitimate_types: default_unusual_legitimate_types(),
8787 corrected_errors: true,
8788 corrected_error_lag: CorrectedErrorLagConfig::default(),
8789 }
8790 }
8791}
8792
8793#[derive(Debug, Clone, Serialize, Deserialize)]
8795pub struct NearDuplicateDaysConfig {
8796 #[serde(default = "default_near_duplicate_min")]
8798 pub min: u32,
8799
8800 #[serde(default = "default_near_duplicate_max")]
8802 pub max: u32,
8803}
8804
8805fn default_near_duplicate_min() -> u32 {
8806 1
8807}
8808fn default_near_duplicate_max() -> u32 {
8809 3
8810}
8811
8812impl Default for NearDuplicateDaysConfig {
8813 fn default() -> Self {
8814 Self {
8815 min: default_near_duplicate_min(),
8816 max: default_near_duplicate_max(),
8817 }
8818 }
8819}
8820
8821#[derive(Debug, Clone, Serialize, Deserialize)]
8823pub struct ThresholdProximityRangeConfig {
8824 #[serde(default = "default_threshold_proximity_min")]
8826 pub min: f64,
8827
8828 #[serde(default = "default_threshold_proximity_max")]
8830 pub max: f64,
8831}
8832
8833fn default_threshold_proximity_min() -> f64 {
8834 0.90
8835}
8836fn default_threshold_proximity_max() -> f64 {
8837 0.99
8838}
8839
8840impl Default for ThresholdProximityRangeConfig {
8841 fn default() -> Self {
8842 Self {
8843 min: default_threshold_proximity_min(),
8844 max: default_threshold_proximity_max(),
8845 }
8846 }
8847}
8848
8849#[derive(Debug, Clone, Serialize, Deserialize)]
8851pub struct CorrectedErrorLagConfig {
8852 #[serde(default = "default_corrected_error_lag_min")]
8854 pub min: u32,
8855
8856 #[serde(default = "default_corrected_error_lag_max")]
8858 pub max: u32,
8859}
8860
8861fn default_corrected_error_lag_min() -> u32 {
8862 1
8863}
8864fn default_corrected_error_lag_max() -> u32 {
8865 5
8866}
8867
8868impl Default for CorrectedErrorLagConfig {
8869 fn default() -> Self {
8870 Self {
8871 min: default_corrected_error_lag_min(),
8872 max: default_corrected_error_lag_max(),
8873 }
8874 }
8875}
8876
8877#[derive(Debug, Clone, Serialize, Deserialize)]
8879pub struct DifficultyClassificationConfig {
8880 #[serde(default)]
8882 pub enabled: bool,
8883
8884 #[serde(default)]
8886 pub target_distribution: DifficultyDistributionConfig,
8887}
8888
8889impl Default for DifficultyClassificationConfig {
8890 fn default() -> Self {
8891 Self {
8892 enabled: true,
8893 target_distribution: DifficultyDistributionConfig::default(),
8894 }
8895 }
8896}
8897
8898#[derive(Debug, Clone, Serialize, Deserialize)]
8900pub struct DifficultyDistributionConfig {
8901 #[serde(default = "default_difficulty_trivial")]
8903 pub trivial: f64,
8904
8905 #[serde(default = "default_difficulty_easy")]
8907 pub easy: f64,
8908
8909 #[serde(default = "default_difficulty_moderate")]
8911 pub moderate: f64,
8912
8913 #[serde(default = "default_difficulty_hard")]
8915 pub hard: f64,
8916
8917 #[serde(default = "default_difficulty_expert")]
8919 pub expert: f64,
8920}
8921
8922fn default_difficulty_trivial() -> f64 {
8923 0.15
8924}
8925fn default_difficulty_easy() -> f64 {
8926 0.25
8927}
8928fn default_difficulty_moderate() -> f64 {
8929 0.30
8930}
8931fn default_difficulty_hard() -> f64 {
8932 0.20
8933}
8934fn default_difficulty_expert() -> f64 {
8935 0.10
8936}
8937
8938impl Default for DifficultyDistributionConfig {
8939 fn default() -> Self {
8940 Self {
8941 trivial: default_difficulty_trivial(),
8942 easy: default_difficulty_easy(),
8943 moderate: default_difficulty_moderate(),
8944 hard: default_difficulty_hard(),
8945 expert: default_difficulty_expert(),
8946 }
8947 }
8948}
8949
8950#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8952pub struct ContextAwareConfig {
8953 #[serde(default)]
8955 pub enabled: bool,
8956
8957 #[serde(default)]
8959 pub vendor_rules: VendorAnomalyRulesConfig,
8960
8961 #[serde(default)]
8963 pub employee_rules: EmployeeAnomalyRulesConfig,
8964
8965 #[serde(default)]
8967 pub account_rules: AccountAnomalyRulesConfig,
8968
8969 #[serde(default)]
8971 pub behavioral_baseline: BehavioralBaselineConfig,
8972}
8973
8974#[derive(Debug, Clone, Serialize, Deserialize)]
8976pub struct VendorAnomalyRulesConfig {
8977 #[serde(default = "default_new_vendor_multiplier")]
8979 pub new_vendor_error_multiplier: f64,
8980
8981 #[serde(default = "default_new_vendor_threshold")]
8983 pub new_vendor_threshold_days: u32,
8984
8985 #[serde(default = "default_international_multiplier")]
8987 pub international_error_multiplier: f64,
8988
8989 #[serde(default = "default_strategic_vendor_types")]
8991 pub strategic_vendor_anomaly_types: Vec<String>,
8992}
8993
8994fn default_new_vendor_multiplier() -> f64 {
8995 2.5
8996}
8997fn default_new_vendor_threshold() -> u32 {
8998 90
8999}
9000fn default_international_multiplier() -> f64 {
9001 1.5
9002}
9003fn default_strategic_vendor_types() -> Vec<String> {
9004 vec![
9005 "pricing_dispute".to_string(),
9006 "contract_violation".to_string(),
9007 ]
9008}
9009
9010impl Default for VendorAnomalyRulesConfig {
9011 fn default() -> Self {
9012 Self {
9013 new_vendor_error_multiplier: default_new_vendor_multiplier(),
9014 new_vendor_threshold_days: default_new_vendor_threshold(),
9015 international_error_multiplier: default_international_multiplier(),
9016 strategic_vendor_anomaly_types: default_strategic_vendor_types(),
9017 }
9018 }
9019}
9020
9021#[derive(Debug, Clone, Serialize, Deserialize)]
9023pub struct EmployeeAnomalyRulesConfig {
9024 #[serde(default = "default_new_employee_rate")]
9026 pub new_employee_error_rate: f64,
9027
9028 #[serde(default = "default_new_employee_threshold")]
9030 pub new_employee_threshold_days: u32,
9031
9032 #[serde(default = "default_volume_fatigue_threshold")]
9034 pub volume_fatigue_threshold: u32,
9035
9036 #[serde(default = "default_coverage_multiplier")]
9038 pub coverage_error_multiplier: f64,
9039}
9040
9041fn default_new_employee_rate() -> f64 {
9042 0.05
9043}
9044fn default_new_employee_threshold() -> u32 {
9045 180
9046}
9047fn default_volume_fatigue_threshold() -> u32 {
9048 50
9049}
9050fn default_coverage_multiplier() -> f64 {
9051 1.8
9052}
9053
9054impl Default for EmployeeAnomalyRulesConfig {
9055 fn default() -> Self {
9056 Self {
9057 new_employee_error_rate: default_new_employee_rate(),
9058 new_employee_threshold_days: default_new_employee_threshold(),
9059 volume_fatigue_threshold: default_volume_fatigue_threshold(),
9060 coverage_error_multiplier: default_coverage_multiplier(),
9061 }
9062 }
9063}
9064
9065#[derive(Debug, Clone, Serialize, Deserialize)]
9067pub struct AccountAnomalyRulesConfig {
9068 #[serde(default = "default_high_risk_multiplier")]
9070 pub high_risk_account_multiplier: f64,
9071
9072 #[serde(default = "default_high_risk_accounts")]
9074 pub high_risk_accounts: Vec<String>,
9075
9076 #[serde(default = "default_suspense_multiplier")]
9078 pub suspense_account_multiplier: f64,
9079
9080 #[serde(default = "default_suspense_accounts")]
9082 pub suspense_accounts: Vec<String>,
9083
9084 #[serde(default = "default_intercompany_multiplier")]
9086 pub intercompany_account_multiplier: f64,
9087}
9088
9089fn default_high_risk_multiplier() -> f64 {
9090 2.0
9091}
9092fn default_high_risk_accounts() -> Vec<String> {
9093 vec![
9094 "1100".to_string(), "2000".to_string(), "3000".to_string(), ]
9098}
9099fn default_suspense_multiplier() -> f64 {
9100 3.0
9101}
9102fn default_suspense_accounts() -> Vec<String> {
9103 vec!["9999".to_string(), "9998".to_string()]
9104}
9105fn default_intercompany_multiplier() -> f64 {
9106 1.5
9107}
9108
9109impl Default for AccountAnomalyRulesConfig {
9110 fn default() -> Self {
9111 Self {
9112 high_risk_account_multiplier: default_high_risk_multiplier(),
9113 high_risk_accounts: default_high_risk_accounts(),
9114 suspense_account_multiplier: default_suspense_multiplier(),
9115 suspense_accounts: default_suspense_accounts(),
9116 intercompany_account_multiplier: default_intercompany_multiplier(),
9117 }
9118 }
9119}
9120
9121#[derive(Debug, Clone, Serialize, Deserialize)]
9123pub struct BehavioralBaselineConfig {
9124 #[serde(default)]
9126 pub enabled: bool,
9127
9128 #[serde(default = "default_baseline_period")]
9130 pub baseline_period_days: u32,
9131
9132 #[serde(default = "default_deviation_threshold")]
9134 pub deviation_threshold_std: f64,
9135
9136 #[serde(default = "default_frequency_deviation")]
9138 pub frequency_deviation_threshold: f64,
9139}
9140
9141fn default_baseline_period() -> u32 {
9142 90
9143}
9144fn default_deviation_threshold() -> f64 {
9145 3.0
9146}
9147fn default_frequency_deviation() -> f64 {
9148 2.0
9149}
9150
9151impl Default for BehavioralBaselineConfig {
9152 fn default() -> Self {
9153 Self {
9154 enabled: false,
9155 baseline_period_days: default_baseline_period(),
9156 deviation_threshold_std: default_deviation_threshold(),
9157 frequency_deviation_threshold: default_frequency_deviation(),
9158 }
9159 }
9160}
9161
9162#[derive(Debug, Clone, Serialize, Deserialize)]
9164pub struct EnhancedLabelingConfig {
9165 #[serde(default = "default_true_val")]
9167 pub severity_scoring: bool,
9168
9169 #[serde(default = "default_true_val")]
9171 pub difficulty_classification: bool,
9172
9173 #[serde(default)]
9175 pub materiality_thresholds: MaterialityThresholdsConfig,
9176}
9177
9178impl Default for EnhancedLabelingConfig {
9179 fn default() -> Self {
9180 Self {
9181 severity_scoring: true,
9182 difficulty_classification: true,
9183 materiality_thresholds: MaterialityThresholdsConfig::default(),
9184 }
9185 }
9186}
9187
9188#[derive(Debug, Clone, Serialize, Deserialize)]
9190pub struct MaterialityThresholdsConfig {
9191 #[serde(default = "default_materiality_trivial")]
9193 pub trivial: f64,
9194
9195 #[serde(default = "default_materiality_immaterial")]
9197 pub immaterial: f64,
9198
9199 #[serde(default = "default_materiality_material")]
9201 pub material: f64,
9202
9203 #[serde(default = "default_materiality_highly_material")]
9205 pub highly_material: f64,
9206}
9207
9208fn default_materiality_trivial() -> f64 {
9209 0.001
9210}
9211fn default_materiality_immaterial() -> f64 {
9212 0.01
9213}
9214fn default_materiality_material() -> f64 {
9215 0.05
9216}
9217fn default_materiality_highly_material() -> f64 {
9218 0.10
9219}
9220
9221impl Default for MaterialityThresholdsConfig {
9222 fn default() -> Self {
9223 Self {
9224 trivial: default_materiality_trivial(),
9225 immaterial: default_materiality_immaterial(),
9226 material: default_materiality_material(),
9227 highly_material: default_materiality_highly_material(),
9228 }
9229 }
9230}
9231
9232#[derive(Debug, Clone, Serialize, Deserialize, Default)]
9244pub struct IndustrySpecificConfig {
9245 #[serde(default)]
9247 pub enabled: bool,
9248
9249 #[serde(default)]
9251 pub manufacturing: ManufacturingConfig,
9252
9253 #[serde(default)]
9255 pub retail: RetailConfig,
9256
9257 #[serde(default)]
9259 pub healthcare: HealthcareConfig,
9260
9261 #[serde(default)]
9263 pub technology: TechnologyConfig,
9264
9265 #[serde(default)]
9267 pub financial_services: FinancialServicesConfig,
9268
9269 #[serde(default)]
9271 pub professional_services: ProfessionalServicesConfig,
9272}
9273
9274#[derive(Debug, Clone, Serialize, Deserialize)]
9276pub struct ManufacturingConfig {
9277 #[serde(default)]
9279 pub enabled: bool,
9280
9281 #[serde(default = "default_bom_depth")]
9283 pub bom_depth: u32,
9284
9285 #[serde(default)]
9287 pub just_in_time: bool,
9288
9289 #[serde(default = "default_production_order_types")]
9291 pub production_order_types: Vec<String>,
9292
9293 #[serde(default)]
9295 pub quality_framework: Option<String>,
9296
9297 #[serde(default = "default_supplier_tiers")]
9299 pub supplier_tiers: u32,
9300
9301 #[serde(default = "default_cost_frequency")]
9303 pub standard_cost_frequency: String,
9304
9305 #[serde(default = "default_yield_rate")]
9307 pub target_yield_rate: f64,
9308
9309 #[serde(default = "default_scrap_threshold")]
9311 pub scrap_alert_threshold: f64,
9312
9313 #[serde(default)]
9315 pub anomaly_rates: ManufacturingAnomalyRates,
9316
9317 #[serde(default)]
9319 pub cost_accounting: ManufacturingCostAccountingConfig,
9320}
9321
9322#[derive(Debug, Clone, Serialize, Deserialize)]
9324pub struct ManufacturingCostAccountingConfig {
9325 #[serde(default = "default_true")]
9327 pub enabled: bool,
9328
9329 #[serde(default = "default_true")]
9331 pub variance_accounts_enabled: bool,
9332
9333 #[serde(default = "default_true")]
9335 pub warranty_provisions_enabled: bool,
9336
9337 #[serde(default = "default_warranty_defect_threshold")]
9339 pub warranty_defect_threshold: f64,
9340}
9341
9342fn default_warranty_defect_threshold() -> f64 {
9343 0.01
9344}
9345
9346impl Default for ManufacturingCostAccountingConfig {
9347 fn default() -> Self {
9348 Self {
9349 enabled: true,
9350 variance_accounts_enabled: true,
9351 warranty_provisions_enabled: true,
9352 warranty_defect_threshold: 0.01,
9353 }
9354 }
9355}
9356
9357fn default_bom_depth() -> u32 {
9358 4
9359}
9360
9361fn default_production_order_types() -> Vec<String> {
9362 vec![
9363 "standard".to_string(),
9364 "rework".to_string(),
9365 "prototype".to_string(),
9366 ]
9367}
9368
9369fn default_supplier_tiers() -> u32 {
9370 2
9371}
9372
9373fn default_cost_frequency() -> String {
9374 "quarterly".to_string()
9375}
9376
9377fn default_yield_rate() -> f64 {
9378 0.97
9379}
9380
9381fn default_scrap_threshold() -> f64 {
9382 0.03
9383}
9384
9385impl Default for ManufacturingConfig {
9386 fn default() -> Self {
9387 Self {
9388 enabled: false,
9389 bom_depth: default_bom_depth(),
9390 just_in_time: false,
9391 production_order_types: default_production_order_types(),
9392 quality_framework: Some("ISO_9001".to_string()),
9393 supplier_tiers: default_supplier_tiers(),
9394 standard_cost_frequency: default_cost_frequency(),
9395 target_yield_rate: default_yield_rate(),
9396 scrap_alert_threshold: default_scrap_threshold(),
9397 anomaly_rates: ManufacturingAnomalyRates::default(),
9398 cost_accounting: ManufacturingCostAccountingConfig::default(),
9399 }
9400 }
9401}
9402
9403#[derive(Debug, Clone, Serialize, Deserialize)]
9405pub struct ManufacturingAnomalyRates {
9406 #[serde(default = "default_mfg_yield_rate")]
9408 pub yield_manipulation: f64,
9409
9410 #[serde(default = "default_mfg_labor_rate")]
9412 pub labor_misallocation: f64,
9413
9414 #[serde(default = "default_mfg_phantom_rate")]
9416 pub phantom_production: f64,
9417
9418 #[serde(default = "default_mfg_cost_rate")]
9420 pub standard_cost_manipulation: f64,
9421
9422 #[serde(default = "default_mfg_inventory_rate")]
9424 pub inventory_fraud: f64,
9425}
9426
9427fn default_mfg_yield_rate() -> f64 {
9428 0.015
9429}
9430
9431fn default_mfg_labor_rate() -> f64 {
9432 0.02
9433}
9434
9435fn default_mfg_phantom_rate() -> f64 {
9436 0.005
9437}
9438
9439fn default_mfg_cost_rate() -> f64 {
9440 0.01
9441}
9442
9443fn default_mfg_inventory_rate() -> f64 {
9444 0.008
9445}
9446
9447impl Default for ManufacturingAnomalyRates {
9448 fn default() -> Self {
9449 Self {
9450 yield_manipulation: default_mfg_yield_rate(),
9451 labor_misallocation: default_mfg_labor_rate(),
9452 phantom_production: default_mfg_phantom_rate(),
9453 standard_cost_manipulation: default_mfg_cost_rate(),
9454 inventory_fraud: default_mfg_inventory_rate(),
9455 }
9456 }
9457}
9458
9459#[derive(Debug, Clone, Serialize, Deserialize)]
9461pub struct RetailConfig {
9462 #[serde(default)]
9464 pub enabled: bool,
9465
9466 #[serde(default)]
9468 pub store_types: RetailStoreTypeConfig,
9469
9470 #[serde(default = "default_retail_daily_txns")]
9472 pub avg_daily_transactions: u32,
9473
9474 #[serde(default = "default_true")]
9476 pub loss_prevention: bool,
9477
9478 #[serde(default = "default_shrinkage_rate")]
9480 pub shrinkage_rate: f64,
9481
9482 #[serde(default)]
9484 pub anomaly_rates: RetailAnomalyRates,
9485}
9486
9487fn default_retail_daily_txns() -> u32 {
9488 500
9489}
9490
9491fn default_shrinkage_rate() -> f64 {
9492 0.015
9493}
9494
9495impl Default for RetailConfig {
9496 fn default() -> Self {
9497 Self {
9498 enabled: false,
9499 store_types: RetailStoreTypeConfig::default(),
9500 avg_daily_transactions: default_retail_daily_txns(),
9501 loss_prevention: true,
9502 shrinkage_rate: default_shrinkage_rate(),
9503 anomaly_rates: RetailAnomalyRates::default(),
9504 }
9505 }
9506}
9507
9508#[derive(Debug, Clone, Serialize, Deserialize)]
9510pub struct RetailStoreTypeConfig {
9511 #[serde(default = "default_flagship_pct")]
9513 pub flagship: f64,
9514
9515 #[serde(default = "default_regional_pct")]
9517 pub regional: f64,
9518
9519 #[serde(default = "default_outlet_pct")]
9521 pub outlet: f64,
9522
9523 #[serde(default = "default_ecommerce_pct")]
9525 pub ecommerce: f64,
9526}
9527
9528fn default_flagship_pct() -> f64 {
9529 0.10
9530}
9531
9532fn default_regional_pct() -> f64 {
9533 0.50
9534}
9535
9536fn default_outlet_pct() -> f64 {
9537 0.25
9538}
9539
9540fn default_ecommerce_pct() -> f64 {
9541 0.15
9542}
9543
9544impl Default for RetailStoreTypeConfig {
9545 fn default() -> Self {
9546 Self {
9547 flagship: default_flagship_pct(),
9548 regional: default_regional_pct(),
9549 outlet: default_outlet_pct(),
9550 ecommerce: default_ecommerce_pct(),
9551 }
9552 }
9553}
9554
9555#[derive(Debug, Clone, Serialize, Deserialize)]
9557pub struct RetailAnomalyRates {
9558 #[serde(default = "default_sweethearting_rate")]
9560 pub sweethearting: f64,
9561
9562 #[serde(default = "default_skimming_rate")]
9564 pub skimming: f64,
9565
9566 #[serde(default = "default_refund_fraud_rate")]
9568 pub refund_fraud: f64,
9569
9570 #[serde(default = "default_void_abuse_rate")]
9572 pub void_abuse: f64,
9573
9574 #[serde(default = "default_gift_card_rate")]
9576 pub gift_card_fraud: f64,
9577
9578 #[serde(default = "default_retail_kickback_rate")]
9580 pub vendor_kickback: f64,
9581}
9582
9583fn default_sweethearting_rate() -> f64 {
9584 0.02
9585}
9586
9587fn default_skimming_rate() -> f64 {
9588 0.005
9589}
9590
9591fn default_refund_fraud_rate() -> f64 {
9592 0.015
9593}
9594
9595fn default_void_abuse_rate() -> f64 {
9596 0.01
9597}
9598
9599fn default_gift_card_rate() -> f64 {
9600 0.008
9601}
9602
9603fn default_retail_kickback_rate() -> f64 {
9604 0.003
9605}
9606
9607impl Default for RetailAnomalyRates {
9608 fn default() -> Self {
9609 Self {
9610 sweethearting: default_sweethearting_rate(),
9611 skimming: default_skimming_rate(),
9612 refund_fraud: default_refund_fraud_rate(),
9613 void_abuse: default_void_abuse_rate(),
9614 gift_card_fraud: default_gift_card_rate(),
9615 vendor_kickback: default_retail_kickback_rate(),
9616 }
9617 }
9618}
9619
9620#[derive(Debug, Clone, Serialize, Deserialize)]
9622pub struct HealthcareConfig {
9623 #[serde(default)]
9625 pub enabled: bool,
9626
9627 #[serde(default = "default_facility_type")]
9629 pub facility_type: String,
9630
9631 #[serde(default)]
9633 pub payer_mix: HealthcarePayerMix,
9634
9635 #[serde(default)]
9637 pub coding_systems: HealthcareCodingSystems,
9638
9639 #[serde(default)]
9641 pub compliance: HealthcareComplianceConfig,
9642
9643 #[serde(default = "default_daily_encounters")]
9645 pub avg_daily_encounters: u32,
9646
9647 #[serde(default = "default_charges_per_encounter")]
9649 pub avg_charges_per_encounter: u32,
9650
9651 #[serde(default = "default_hc_denial_rate")]
9653 pub denial_rate: f64,
9654
9655 #[serde(default = "default_hc_bad_debt_rate")]
9657 pub bad_debt_rate: f64,
9658
9659 #[serde(default = "default_hc_charity_care_rate")]
9661 pub charity_care_rate: f64,
9662
9663 #[serde(default)]
9665 pub anomaly_rates: HealthcareAnomalyRates,
9666}
9667
9668fn default_facility_type() -> String {
9669 "hospital".to_string()
9670}
9671
9672fn default_daily_encounters() -> u32 {
9673 150
9674}
9675
9676fn default_charges_per_encounter() -> u32 {
9677 8
9678}
9679
9680fn default_hc_denial_rate() -> f64 {
9681 0.05
9682}
9683
9684fn default_hc_bad_debt_rate() -> f64 {
9685 0.03
9686}
9687
9688fn default_hc_charity_care_rate() -> f64 {
9689 0.02
9690}
9691
9692impl Default for HealthcareConfig {
9693 fn default() -> Self {
9694 Self {
9695 enabled: false,
9696 facility_type: default_facility_type(),
9697 payer_mix: HealthcarePayerMix::default(),
9698 coding_systems: HealthcareCodingSystems::default(),
9699 compliance: HealthcareComplianceConfig::default(),
9700 avg_daily_encounters: default_daily_encounters(),
9701 avg_charges_per_encounter: default_charges_per_encounter(),
9702 denial_rate: default_hc_denial_rate(),
9703 bad_debt_rate: default_hc_bad_debt_rate(),
9704 charity_care_rate: default_hc_charity_care_rate(),
9705 anomaly_rates: HealthcareAnomalyRates::default(),
9706 }
9707 }
9708}
9709
9710#[derive(Debug, Clone, Serialize, Deserialize)]
9712pub struct HealthcarePayerMix {
9713 #[serde(default = "default_medicare_pct")]
9715 pub medicare: f64,
9716
9717 #[serde(default = "default_medicaid_pct")]
9719 pub medicaid: f64,
9720
9721 #[serde(default = "default_commercial_pct")]
9723 pub commercial: f64,
9724
9725 #[serde(default = "default_self_pay_pct")]
9727 pub self_pay: f64,
9728}
9729
9730fn default_medicare_pct() -> f64 {
9731 0.40
9732}
9733
9734fn default_medicaid_pct() -> f64 {
9735 0.20
9736}
9737
9738fn default_commercial_pct() -> f64 {
9739 0.30
9740}
9741
9742fn default_self_pay_pct() -> f64 {
9743 0.10
9744}
9745
9746impl Default for HealthcarePayerMix {
9747 fn default() -> Self {
9748 Self {
9749 medicare: default_medicare_pct(),
9750 medicaid: default_medicaid_pct(),
9751 commercial: default_commercial_pct(),
9752 self_pay: default_self_pay_pct(),
9753 }
9754 }
9755}
9756
9757#[derive(Debug, Clone, Serialize, Deserialize)]
9759pub struct HealthcareCodingSystems {
9760 #[serde(default = "default_true")]
9762 pub icd10: bool,
9763
9764 #[serde(default = "default_true")]
9766 pub cpt: bool,
9767
9768 #[serde(default = "default_true")]
9770 pub drg: bool,
9771
9772 #[serde(default = "default_true")]
9774 pub hcpcs: bool,
9775
9776 #[serde(default = "default_true")]
9778 pub revenue_codes: bool,
9779}
9780
9781impl Default for HealthcareCodingSystems {
9782 fn default() -> Self {
9783 Self {
9784 icd10: true,
9785 cpt: true,
9786 drg: true,
9787 hcpcs: true,
9788 revenue_codes: true,
9789 }
9790 }
9791}
9792
9793#[derive(Debug, Clone, Serialize, Deserialize)]
9795pub struct HealthcareComplianceConfig {
9796 #[serde(default = "default_true")]
9798 pub hipaa: bool,
9799
9800 #[serde(default = "default_true")]
9802 pub stark_law: bool,
9803
9804 #[serde(default = "default_true")]
9806 pub anti_kickback: bool,
9807
9808 #[serde(default = "default_true")]
9810 pub false_claims_act: bool,
9811
9812 #[serde(default = "default_true")]
9814 pub emtala: bool,
9815}
9816
9817impl Default for HealthcareComplianceConfig {
9818 fn default() -> Self {
9819 Self {
9820 hipaa: true,
9821 stark_law: true,
9822 anti_kickback: true,
9823 false_claims_act: true,
9824 emtala: true,
9825 }
9826 }
9827}
9828
9829#[derive(Debug, Clone, Serialize, Deserialize)]
9831pub struct HealthcareAnomalyRates {
9832 #[serde(default = "default_upcoding_rate")]
9834 pub upcoding: f64,
9835
9836 #[serde(default = "default_unbundling_rate")]
9838 pub unbundling: f64,
9839
9840 #[serde(default = "default_phantom_billing_rate")]
9842 pub phantom_billing: f64,
9843
9844 #[serde(default = "default_healthcare_kickback_rate")]
9846 pub kickbacks: f64,
9847
9848 #[serde(default = "default_duplicate_billing_rate")]
9850 pub duplicate_billing: f64,
9851
9852 #[serde(default = "default_med_necessity_rate")]
9854 pub medical_necessity_abuse: f64,
9855}
9856
9857fn default_upcoding_rate() -> f64 {
9858 0.02
9859}
9860
9861fn default_unbundling_rate() -> f64 {
9862 0.015
9863}
9864
9865fn default_phantom_billing_rate() -> f64 {
9866 0.005
9867}
9868
9869fn default_healthcare_kickback_rate() -> f64 {
9870 0.003
9871}
9872
9873fn default_duplicate_billing_rate() -> f64 {
9874 0.008
9875}
9876
9877fn default_med_necessity_rate() -> f64 {
9878 0.01
9879}
9880
9881impl Default for HealthcareAnomalyRates {
9882 fn default() -> Self {
9883 Self {
9884 upcoding: default_upcoding_rate(),
9885 unbundling: default_unbundling_rate(),
9886 phantom_billing: default_phantom_billing_rate(),
9887 kickbacks: default_healthcare_kickback_rate(),
9888 duplicate_billing: default_duplicate_billing_rate(),
9889 medical_necessity_abuse: default_med_necessity_rate(),
9890 }
9891 }
9892}
9893
9894#[derive(Debug, Clone, Serialize, Deserialize)]
9896pub struct TechnologyConfig {
9897 #[serde(default)]
9899 pub enabled: bool,
9900
9901 #[serde(default = "default_revenue_model")]
9903 pub revenue_model: String,
9904
9905 #[serde(default = "default_subscription_pct")]
9907 pub subscription_revenue_pct: f64,
9908
9909 #[serde(default = "default_license_pct")]
9911 pub license_revenue_pct: f64,
9912
9913 #[serde(default = "default_services_pct")]
9915 pub services_revenue_pct: f64,
9916
9917 #[serde(default)]
9919 pub rd_capitalization: RdCapitalizationConfig,
9920
9921 #[serde(default)]
9923 pub anomaly_rates: TechnologyAnomalyRates,
9924}
9925
9926fn default_revenue_model() -> String {
9927 "saas".to_string()
9928}
9929
9930fn default_subscription_pct() -> f64 {
9931 0.60
9932}
9933
9934fn default_license_pct() -> f64 {
9935 0.25
9936}
9937
9938fn default_services_pct() -> f64 {
9939 0.15
9940}
9941
9942impl Default for TechnologyConfig {
9943 fn default() -> Self {
9944 Self {
9945 enabled: false,
9946 revenue_model: default_revenue_model(),
9947 subscription_revenue_pct: default_subscription_pct(),
9948 license_revenue_pct: default_license_pct(),
9949 services_revenue_pct: default_services_pct(),
9950 rd_capitalization: RdCapitalizationConfig::default(),
9951 anomaly_rates: TechnologyAnomalyRates::default(),
9952 }
9953 }
9954}
9955
9956#[derive(Debug, Clone, Serialize, Deserialize)]
9958pub struct RdCapitalizationConfig {
9959 #[serde(default = "default_true")]
9961 pub enabled: bool,
9962
9963 #[serde(default = "default_cap_rate")]
9965 pub capitalization_rate: f64,
9966
9967 #[serde(default = "default_useful_life")]
9969 pub useful_life_years: u32,
9970}
9971
9972fn default_cap_rate() -> f64 {
9973 0.30
9974}
9975
9976fn default_useful_life() -> u32 {
9977 3
9978}
9979
9980impl Default for RdCapitalizationConfig {
9981 fn default() -> Self {
9982 Self {
9983 enabled: true,
9984 capitalization_rate: default_cap_rate(),
9985 useful_life_years: default_useful_life(),
9986 }
9987 }
9988}
9989
9990#[derive(Debug, Clone, Serialize, Deserialize)]
9992pub struct TechnologyAnomalyRates {
9993 #[serde(default = "default_premature_rev_rate")]
9995 pub premature_revenue: f64,
9996
9997 #[serde(default = "default_side_letter_rate")]
9999 pub side_letter_abuse: f64,
10000
10001 #[serde(default = "default_channel_stuffing_rate")]
10003 pub channel_stuffing: f64,
10004
10005 #[serde(default = "default_improper_cap_rate")]
10007 pub improper_capitalization: f64,
10008}
10009
10010fn default_premature_rev_rate() -> f64 {
10011 0.015
10012}
10013
10014fn default_side_letter_rate() -> f64 {
10015 0.008
10016}
10017
10018fn default_channel_stuffing_rate() -> f64 {
10019 0.01
10020}
10021
10022fn default_improper_cap_rate() -> f64 {
10023 0.012
10024}
10025
10026impl Default for TechnologyAnomalyRates {
10027 fn default() -> Self {
10028 Self {
10029 premature_revenue: default_premature_rev_rate(),
10030 side_letter_abuse: default_side_letter_rate(),
10031 channel_stuffing: default_channel_stuffing_rate(),
10032 improper_capitalization: default_improper_cap_rate(),
10033 }
10034 }
10035}
10036
10037#[derive(Debug, Clone, Serialize, Deserialize)]
10039pub struct FinancialServicesConfig {
10040 #[serde(default)]
10042 pub enabled: bool,
10043
10044 #[serde(default = "default_fi_type")]
10046 pub institution_type: String,
10047
10048 #[serde(default = "default_fi_regulatory")]
10050 pub regulatory_framework: String,
10051
10052 #[serde(default)]
10054 pub anomaly_rates: FinancialServicesAnomalyRates,
10055}
10056
10057fn default_fi_type() -> String {
10058 "commercial_bank".to_string()
10059}
10060
10061fn default_fi_regulatory() -> String {
10062 "us_banking".to_string()
10063}
10064
10065impl Default for FinancialServicesConfig {
10066 fn default() -> Self {
10067 Self {
10068 enabled: false,
10069 institution_type: default_fi_type(),
10070 regulatory_framework: default_fi_regulatory(),
10071 anomaly_rates: FinancialServicesAnomalyRates::default(),
10072 }
10073 }
10074}
10075
10076#[derive(Debug, Clone, Serialize, Deserialize)]
10078pub struct FinancialServicesAnomalyRates {
10079 #[serde(default = "default_loan_fraud_rate")]
10081 pub loan_fraud: f64,
10082
10083 #[serde(default = "default_trading_fraud_rate")]
10085 pub trading_fraud: f64,
10086
10087 #[serde(default = "default_insurance_fraud_rate")]
10089 pub insurance_fraud: f64,
10090
10091 #[serde(default = "default_account_manip_rate")]
10093 pub account_manipulation: f64,
10094}
10095
10096fn default_loan_fraud_rate() -> f64 {
10097 0.01
10098}
10099
10100fn default_trading_fraud_rate() -> f64 {
10101 0.008
10102}
10103
10104fn default_insurance_fraud_rate() -> f64 {
10105 0.012
10106}
10107
10108fn default_account_manip_rate() -> f64 {
10109 0.005
10110}
10111
10112impl Default for FinancialServicesAnomalyRates {
10113 fn default() -> Self {
10114 Self {
10115 loan_fraud: default_loan_fraud_rate(),
10116 trading_fraud: default_trading_fraud_rate(),
10117 insurance_fraud: default_insurance_fraud_rate(),
10118 account_manipulation: default_account_manip_rate(),
10119 }
10120 }
10121}
10122
10123#[derive(Debug, Clone, Serialize, Deserialize)]
10125pub struct ProfessionalServicesConfig {
10126 #[serde(default)]
10128 pub enabled: bool,
10129
10130 #[serde(default = "default_firm_type")]
10132 pub firm_type: String,
10133
10134 #[serde(default = "default_billing_model")]
10136 pub billing_model: String,
10137
10138 #[serde(default = "default_hourly_rate")]
10140 pub avg_hourly_rate: f64,
10141
10142 #[serde(default)]
10144 pub trust_accounting: TrustAccountingConfig,
10145
10146 #[serde(default)]
10148 pub anomaly_rates: ProfessionalServicesAnomalyRates,
10149}
10150
10151fn default_firm_type() -> String {
10152 "consulting".to_string()
10153}
10154
10155fn default_billing_model() -> String {
10156 "time_and_materials".to_string()
10157}
10158
10159fn default_hourly_rate() -> f64 {
10160 250.0
10161}
10162
10163impl Default for ProfessionalServicesConfig {
10164 fn default() -> Self {
10165 Self {
10166 enabled: false,
10167 firm_type: default_firm_type(),
10168 billing_model: default_billing_model(),
10169 avg_hourly_rate: default_hourly_rate(),
10170 trust_accounting: TrustAccountingConfig::default(),
10171 anomaly_rates: ProfessionalServicesAnomalyRates::default(),
10172 }
10173 }
10174}
10175
10176#[derive(Debug, Clone, Serialize, Deserialize)]
10178pub struct TrustAccountingConfig {
10179 #[serde(default)]
10181 pub enabled: bool,
10182
10183 #[serde(default = "default_true")]
10185 pub require_three_way_reconciliation: bool,
10186}
10187
10188impl Default for TrustAccountingConfig {
10189 fn default() -> Self {
10190 Self {
10191 enabled: false,
10192 require_three_way_reconciliation: true,
10193 }
10194 }
10195}
10196
10197#[derive(Debug, Clone, Serialize, Deserialize)]
10199pub struct ProfessionalServicesAnomalyRates {
10200 #[serde(default = "default_time_fraud_rate")]
10202 pub time_billing_fraud: f64,
10203
10204 #[serde(default = "default_expense_fraud_rate")]
10206 pub expense_fraud: f64,
10207
10208 #[serde(default = "default_trust_misappropriation_rate")]
10210 pub trust_misappropriation: f64,
10211}
10212
10213fn default_time_fraud_rate() -> f64 {
10214 0.02
10215}
10216
10217fn default_expense_fraud_rate() -> f64 {
10218 0.015
10219}
10220
10221fn default_trust_misappropriation_rate() -> f64 {
10222 0.003
10223}
10224
10225impl Default for ProfessionalServicesAnomalyRates {
10226 fn default() -> Self {
10227 Self {
10228 time_billing_fraud: default_time_fraud_rate(),
10229 expense_fraud: default_expense_fraud_rate(),
10230 trust_misappropriation: default_trust_misappropriation_rate(),
10231 }
10232 }
10233}
10234
10235#[derive(Debug, Clone, Serialize, Deserialize)]
10249pub struct FingerprintPrivacyConfig {
10250 #[serde(default)]
10252 pub level: String,
10253 #[serde(default = "default_epsilon")]
10255 pub epsilon: f64,
10256 #[serde(default = "default_delta")]
10258 pub delta: f64,
10259 #[serde(default = "default_k_anonymity")]
10261 pub k_anonymity: u32,
10262 #[serde(default)]
10264 pub composition_method: String,
10265}
10266
10267fn default_epsilon() -> f64 {
10268 1.0
10269}
10270
10271fn default_delta() -> f64 {
10272 1e-5
10273}
10274
10275fn default_k_anonymity() -> u32 {
10276 5
10277}
10278
10279impl Default for FingerprintPrivacyConfig {
10280 fn default() -> Self {
10281 Self {
10282 level: "standard".to_string(),
10283 epsilon: default_epsilon(),
10284 delta: default_delta(),
10285 k_anonymity: default_k_anonymity(),
10286 composition_method: "naive".to_string(),
10287 }
10288 }
10289}
10290
10291#[derive(Debug, Clone, Serialize, Deserialize)]
10305pub struct QualityGatesSchemaConfig {
10306 #[serde(default)]
10308 pub enabled: bool,
10309 #[serde(default = "default_gate_profile_name")]
10311 pub profile: String,
10312 #[serde(default)]
10314 pub fail_on_violation: bool,
10315 #[serde(default)]
10317 pub custom_gates: Vec<QualityGateEntry>,
10318}
10319
10320fn default_gate_profile_name() -> String {
10321 "default".to_string()
10322}
10323
10324impl Default for QualityGatesSchemaConfig {
10325 fn default() -> Self {
10326 Self {
10327 enabled: false,
10328 profile: default_gate_profile_name(),
10329 fail_on_violation: false,
10330 custom_gates: Vec::new(),
10331 }
10332 }
10333}
10334
10335#[derive(Debug, Clone, Serialize, Deserialize)]
10337pub struct QualityGateEntry {
10338 pub name: String,
10340 pub metric: String,
10344 pub threshold: f64,
10346 #[serde(default)]
10348 pub upper_threshold: Option<f64>,
10349 #[serde(default = "default_gate_comparison")]
10351 pub comparison: String,
10352}
10353
10354fn default_gate_comparison() -> String {
10355 "gte".to_string()
10356}
10357
10358#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10368pub struct ComplianceSchemaConfig {
10369 #[serde(default)]
10371 pub content_marking: ContentMarkingSchemaConfig,
10372 #[serde(default)]
10374 pub article10_report: bool,
10375 #[serde(default)]
10377 pub certificates: CertificateSchemaConfig,
10378}
10379
10380#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10382pub struct CertificateSchemaConfig {
10383 #[serde(default)]
10385 pub enabled: bool,
10386 #[serde(default)]
10388 pub signing_key_env: Option<String>,
10389 #[serde(default)]
10391 pub include_quality_metrics: bool,
10392}
10393
10394#[derive(Debug, Clone, Serialize, Deserialize)]
10396pub struct ContentMarkingSchemaConfig {
10397 #[serde(default = "default_true")]
10399 pub enabled: bool,
10400 #[serde(default = "default_marking_format")]
10402 pub format: String,
10403}
10404
10405fn default_marking_format() -> String {
10406 "embedded".to_string()
10407}
10408
10409impl Default for ContentMarkingSchemaConfig {
10410 fn default() -> Self {
10411 Self {
10412 enabled: true,
10413 format: default_marking_format(),
10414 }
10415 }
10416}
10417
10418#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10420pub struct WebhookSchemaConfig {
10421 #[serde(default)]
10423 pub enabled: bool,
10424 #[serde(default)]
10426 pub endpoints: Vec<WebhookEndpointConfig>,
10427}
10428
10429#[derive(Debug, Clone, Serialize, Deserialize)]
10431pub struct WebhookEndpointConfig {
10432 pub url: String,
10434 #[serde(default)]
10436 pub events: Vec<String>,
10437 #[serde(default)]
10439 pub secret: Option<String>,
10440 #[serde(default = "default_webhook_retries")]
10442 pub max_retries: u32,
10443 #[serde(default = "default_webhook_timeout")]
10445 pub timeout_secs: u64,
10446}
10447
10448fn default_webhook_retries() -> u32 {
10449 3
10450}
10451fn default_webhook_timeout() -> u64 {
10452 10
10453}
10454
10455#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10461pub struct SourceToPayConfig {
10462 #[serde(default)]
10464 pub enabled: bool,
10465 #[serde(default)]
10467 pub spend_analysis: SpendAnalysisConfig,
10468 #[serde(default)]
10470 pub sourcing: SourcingConfig,
10471 #[serde(default)]
10473 pub qualification: QualificationConfig,
10474 #[serde(default)]
10476 pub rfx: RfxConfig,
10477 #[serde(default)]
10479 pub contracts: ContractConfig,
10480 #[serde(default)]
10482 pub catalog: CatalogConfig,
10483 #[serde(default)]
10485 pub scorecards: ScorecardConfig,
10486 #[serde(default)]
10488 pub p2p_integration: P2PIntegrationConfig,
10489}
10490
10491#[derive(Debug, Clone, Serialize, Deserialize)]
10493pub struct SpendAnalysisConfig {
10494 #[serde(default = "default_hhi_threshold")]
10496 pub hhi_threshold: f64,
10497 #[serde(default = "default_contract_coverage_target")]
10499 pub contract_coverage_target: f64,
10500}
10501
10502impl Default for SpendAnalysisConfig {
10503 fn default() -> Self {
10504 Self {
10505 hhi_threshold: default_hhi_threshold(),
10506 contract_coverage_target: default_contract_coverage_target(),
10507 }
10508 }
10509}
10510
10511fn default_hhi_threshold() -> f64 {
10512 2500.0
10513}
10514fn default_contract_coverage_target() -> f64 {
10515 0.80
10516}
10517
10518#[derive(Debug, Clone, Serialize, Deserialize)]
10520pub struct SourcingConfig {
10521 #[serde(default = "default_sourcing_projects_per_year")]
10523 pub projects_per_year: u32,
10524 #[serde(default = "default_renewal_horizon_months")]
10526 pub renewal_horizon_months: u32,
10527 #[serde(default = "default_project_duration_months")]
10529 pub project_duration_months: u32,
10530}
10531
10532impl Default for SourcingConfig {
10533 fn default() -> Self {
10534 Self {
10535 projects_per_year: default_sourcing_projects_per_year(),
10536 renewal_horizon_months: default_renewal_horizon_months(),
10537 project_duration_months: default_project_duration_months(),
10538 }
10539 }
10540}
10541
10542fn default_sourcing_projects_per_year() -> u32 {
10543 10
10544}
10545fn default_renewal_horizon_months() -> u32 {
10546 3
10547}
10548fn default_project_duration_months() -> u32 {
10549 4
10550}
10551
10552#[derive(Debug, Clone, Serialize, Deserialize)]
10554pub struct QualificationConfig {
10555 #[serde(default = "default_qualification_pass_rate")]
10557 pub pass_rate: f64,
10558 #[serde(default = "default_qualification_validity_days")]
10560 pub validity_days: u32,
10561 #[serde(default = "default_financial_weight")]
10563 pub financial_weight: f64,
10564 #[serde(default = "default_quality_weight")]
10566 pub quality_weight: f64,
10567 #[serde(default = "default_delivery_weight")]
10569 pub delivery_weight: f64,
10570 #[serde(default = "default_compliance_weight")]
10572 pub compliance_weight: f64,
10573}
10574
10575impl Default for QualificationConfig {
10576 fn default() -> Self {
10577 Self {
10578 pass_rate: default_qualification_pass_rate(),
10579 validity_days: default_qualification_validity_days(),
10580 financial_weight: default_financial_weight(),
10581 quality_weight: default_quality_weight(),
10582 delivery_weight: default_delivery_weight(),
10583 compliance_weight: default_compliance_weight(),
10584 }
10585 }
10586}
10587
10588fn default_qualification_pass_rate() -> f64 {
10589 0.75
10590}
10591fn default_qualification_validity_days() -> u32 {
10592 365
10593}
10594fn default_financial_weight() -> f64 {
10595 0.25
10596}
10597fn default_quality_weight() -> f64 {
10598 0.30
10599}
10600fn default_delivery_weight() -> f64 {
10601 0.25
10602}
10603fn default_compliance_weight() -> f64 {
10604 0.20
10605}
10606
10607#[derive(Debug, Clone, Serialize, Deserialize)]
10609pub struct RfxConfig {
10610 #[serde(default = "default_rfi_threshold")]
10612 pub rfi_threshold: f64,
10613 #[serde(default = "default_min_invited_vendors")]
10615 pub min_invited_vendors: u32,
10616 #[serde(default = "default_max_invited_vendors")]
10618 pub max_invited_vendors: u32,
10619 #[serde(default = "default_response_rate")]
10621 pub response_rate: f64,
10622 #[serde(default = "default_price_weight")]
10624 pub default_price_weight: f64,
10625 #[serde(default = "default_rfx_quality_weight")]
10627 pub default_quality_weight: f64,
10628 #[serde(default = "default_rfx_delivery_weight")]
10630 pub default_delivery_weight: f64,
10631}
10632
10633impl Default for RfxConfig {
10634 fn default() -> Self {
10635 Self {
10636 rfi_threshold: default_rfi_threshold(),
10637 min_invited_vendors: default_min_invited_vendors(),
10638 max_invited_vendors: default_max_invited_vendors(),
10639 response_rate: default_response_rate(),
10640 default_price_weight: default_price_weight(),
10641 default_quality_weight: default_rfx_quality_weight(),
10642 default_delivery_weight: default_rfx_delivery_weight(),
10643 }
10644 }
10645}
10646
10647fn default_rfi_threshold() -> f64 {
10648 100_000.0
10649}
10650fn default_min_invited_vendors() -> u32 {
10651 3
10652}
10653fn default_max_invited_vendors() -> u32 {
10654 8
10655}
10656fn default_response_rate() -> f64 {
10657 0.70
10658}
10659fn default_price_weight() -> f64 {
10660 0.40
10661}
10662fn default_rfx_quality_weight() -> f64 {
10663 0.35
10664}
10665fn default_rfx_delivery_weight() -> f64 {
10666 0.25
10667}
10668
10669#[derive(Debug, Clone, Serialize, Deserialize)]
10671pub struct ContractConfig {
10672 #[serde(default = "default_min_contract_months")]
10674 pub min_duration_months: u32,
10675 #[serde(default = "default_max_contract_months")]
10677 pub max_duration_months: u32,
10678 #[serde(default = "default_auto_renewal_rate")]
10680 pub auto_renewal_rate: f64,
10681 #[serde(default = "default_amendment_rate")]
10683 pub amendment_rate: f64,
10684 #[serde(default)]
10686 pub type_distribution: ContractTypeDistribution,
10687}
10688
10689impl Default for ContractConfig {
10690 fn default() -> Self {
10691 Self {
10692 min_duration_months: default_min_contract_months(),
10693 max_duration_months: default_max_contract_months(),
10694 auto_renewal_rate: default_auto_renewal_rate(),
10695 amendment_rate: default_amendment_rate(),
10696 type_distribution: ContractTypeDistribution::default(),
10697 }
10698 }
10699}
10700
10701fn default_min_contract_months() -> u32 {
10702 12
10703}
10704fn default_max_contract_months() -> u32 {
10705 36
10706}
10707fn default_auto_renewal_rate() -> f64 {
10708 0.40
10709}
10710fn default_amendment_rate() -> f64 {
10711 0.20
10712}
10713
10714#[derive(Debug, Clone, Serialize, Deserialize)]
10716pub struct ContractTypeDistribution {
10717 #[serde(default = "default_fixed_price_pct")]
10719 pub fixed_price: f64,
10720 #[serde(default = "default_blanket_pct")]
10722 pub blanket: f64,
10723 #[serde(default = "default_time_materials_pct")]
10725 pub time_and_materials: f64,
10726 #[serde(default = "default_service_agreement_pct")]
10728 pub service_agreement: f64,
10729}
10730
10731impl Default for ContractTypeDistribution {
10732 fn default() -> Self {
10733 Self {
10734 fixed_price: default_fixed_price_pct(),
10735 blanket: default_blanket_pct(),
10736 time_and_materials: default_time_materials_pct(),
10737 service_agreement: default_service_agreement_pct(),
10738 }
10739 }
10740}
10741
10742fn default_fixed_price_pct() -> f64 {
10743 0.40
10744}
10745fn default_blanket_pct() -> f64 {
10746 0.30
10747}
10748fn default_time_materials_pct() -> f64 {
10749 0.15
10750}
10751fn default_service_agreement_pct() -> f64 {
10752 0.15
10753}
10754
10755#[derive(Debug, Clone, Serialize, Deserialize)]
10757pub struct CatalogConfig {
10758 #[serde(default = "default_preferred_vendor_flag_rate")]
10760 pub preferred_vendor_flag_rate: f64,
10761 #[serde(default = "default_multi_source_rate")]
10763 pub multi_source_rate: f64,
10764}
10765
10766impl Default for CatalogConfig {
10767 fn default() -> Self {
10768 Self {
10769 preferred_vendor_flag_rate: default_preferred_vendor_flag_rate(),
10770 multi_source_rate: default_multi_source_rate(),
10771 }
10772 }
10773}
10774
10775fn default_preferred_vendor_flag_rate() -> f64 {
10776 0.70
10777}
10778fn default_multi_source_rate() -> f64 {
10779 0.25
10780}
10781
10782#[derive(Debug, Clone, Serialize, Deserialize)]
10784pub struct ScorecardConfig {
10785 #[serde(default = "default_scorecard_frequency")]
10787 pub frequency: String,
10788 #[serde(default = "default_otd_weight")]
10790 pub on_time_delivery_weight: f64,
10791 #[serde(default = "default_quality_score_weight")]
10793 pub quality_weight: f64,
10794 #[serde(default = "default_price_score_weight")]
10796 pub price_weight: f64,
10797 #[serde(default = "default_responsiveness_weight")]
10799 pub responsiveness_weight: f64,
10800 #[serde(default = "default_grade_a_threshold")]
10802 pub grade_a_threshold: f64,
10803 #[serde(default = "default_grade_b_threshold")]
10805 pub grade_b_threshold: f64,
10806 #[serde(default = "default_grade_c_threshold")]
10808 pub grade_c_threshold: f64,
10809}
10810
10811impl Default for ScorecardConfig {
10812 fn default() -> Self {
10813 Self {
10814 frequency: default_scorecard_frequency(),
10815 on_time_delivery_weight: default_otd_weight(),
10816 quality_weight: default_quality_score_weight(),
10817 price_weight: default_price_score_weight(),
10818 responsiveness_weight: default_responsiveness_weight(),
10819 grade_a_threshold: default_grade_a_threshold(),
10820 grade_b_threshold: default_grade_b_threshold(),
10821 grade_c_threshold: default_grade_c_threshold(),
10822 }
10823 }
10824}
10825
10826fn default_scorecard_frequency() -> String {
10827 "quarterly".to_string()
10828}
10829fn default_otd_weight() -> f64 {
10830 0.30
10831}
10832fn default_quality_score_weight() -> f64 {
10833 0.30
10834}
10835fn default_price_score_weight() -> f64 {
10836 0.25
10837}
10838fn default_responsiveness_weight() -> f64 {
10839 0.15
10840}
10841fn default_grade_a_threshold() -> f64 {
10842 90.0
10843}
10844fn default_grade_b_threshold() -> f64 {
10845 75.0
10846}
10847fn default_grade_c_threshold() -> f64 {
10848 60.0
10849}
10850
10851#[derive(Debug, Clone, Serialize, Deserialize)]
10853pub struct P2PIntegrationConfig {
10854 #[serde(default = "default_off_contract_rate")]
10856 pub off_contract_rate: f64,
10857 #[serde(default = "default_price_tolerance")]
10859 pub price_tolerance: f64,
10860 #[serde(default)]
10862 pub catalog_enforcement: bool,
10863}
10864
10865impl Default for P2PIntegrationConfig {
10866 fn default() -> Self {
10867 Self {
10868 off_contract_rate: default_off_contract_rate(),
10869 price_tolerance: default_price_tolerance(),
10870 catalog_enforcement: false,
10871 }
10872 }
10873}
10874
10875fn default_off_contract_rate() -> f64 {
10876 0.15
10877}
10878fn default_price_tolerance() -> f64 {
10879 0.02
10880}
10881
10882#[derive(Debug, Clone, Serialize, Deserialize)]
10886pub struct FinancialReportingConfig {
10887 #[serde(default)]
10889 pub enabled: bool,
10890 #[serde(default = "default_true")]
10892 pub generate_balance_sheet: bool,
10893 #[serde(default = "default_true")]
10895 pub generate_income_statement: bool,
10896 #[serde(default = "default_true")]
10898 pub generate_cash_flow: bool,
10899 #[serde(default = "default_true")]
10901 pub generate_changes_in_equity: bool,
10902 #[serde(default = "default_comparative_periods")]
10904 pub comparative_periods: u32,
10905 #[serde(default)]
10907 pub management_kpis: ManagementKpisConfig,
10908 #[serde(default)]
10910 pub budgets: BudgetConfig,
10911}
10912
10913impl Default for FinancialReportingConfig {
10914 fn default() -> Self {
10915 Self {
10916 enabled: false,
10917 generate_balance_sheet: true,
10918 generate_income_statement: true,
10919 generate_cash_flow: true,
10920 generate_changes_in_equity: true,
10921 comparative_periods: default_comparative_periods(),
10922 management_kpis: ManagementKpisConfig::default(),
10923 budgets: BudgetConfig::default(),
10924 }
10925 }
10926}
10927
10928fn default_comparative_periods() -> u32 {
10929 1
10930}
10931
10932#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10934pub struct ManagementKpisConfig {
10935 #[serde(default)]
10937 pub enabled: bool,
10938 #[serde(default = "default_kpi_frequency")]
10940 pub frequency: String,
10941}
10942
10943fn default_kpi_frequency() -> String {
10944 "monthly".to_string()
10945}
10946
10947#[derive(Debug, Clone, Serialize, Deserialize)]
10949pub struct BudgetConfig {
10950 #[serde(default)]
10952 pub enabled: bool,
10953 #[serde(default = "default_revenue_growth_rate")]
10955 pub revenue_growth_rate: f64,
10956 #[serde(default = "default_expense_inflation_rate")]
10958 pub expense_inflation_rate: f64,
10959 #[serde(default = "default_variance_noise")]
10961 pub variance_noise: f64,
10962}
10963
10964impl Default for BudgetConfig {
10965 fn default() -> Self {
10966 Self {
10967 enabled: false,
10968 revenue_growth_rate: default_revenue_growth_rate(),
10969 expense_inflation_rate: default_expense_inflation_rate(),
10970 variance_noise: default_variance_noise(),
10971 }
10972 }
10973}
10974
10975fn default_revenue_growth_rate() -> f64 {
10976 0.05
10977}
10978fn default_expense_inflation_rate() -> f64 {
10979 0.03
10980}
10981fn default_variance_noise() -> f64 {
10982 0.10
10983}
10984
10985#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10989pub struct HrConfig {
10990 #[serde(default)]
10992 pub enabled: bool,
10993 #[serde(default)]
10995 pub payroll: PayrollConfig,
10996 #[serde(default)]
10998 pub time_attendance: TimeAttendanceConfig,
10999 #[serde(default)]
11001 pub expenses: ExpenseConfig,
11002}
11003
11004#[derive(Debug, Clone, Serialize, Deserialize)]
11006pub struct PayrollConfig {
11007 #[serde(default = "default_true")]
11009 pub enabled: bool,
11010 #[serde(default = "default_pay_frequency")]
11012 pub pay_frequency: String,
11013 #[serde(default)]
11015 pub salary_ranges: PayrollSalaryRanges,
11016 #[serde(default)]
11018 pub tax_rates: PayrollTaxRates,
11019 #[serde(default = "default_benefits_enrollment_rate")]
11021 pub benefits_enrollment_rate: f64,
11022 #[serde(default = "default_retirement_participation_rate")]
11024 pub retirement_participation_rate: f64,
11025}
11026
11027impl Default for PayrollConfig {
11028 fn default() -> Self {
11029 Self {
11030 enabled: true,
11031 pay_frequency: default_pay_frequency(),
11032 salary_ranges: PayrollSalaryRanges::default(),
11033 tax_rates: PayrollTaxRates::default(),
11034 benefits_enrollment_rate: default_benefits_enrollment_rate(),
11035 retirement_participation_rate: default_retirement_participation_rate(),
11036 }
11037 }
11038}
11039
11040fn default_pay_frequency() -> String {
11041 "monthly".to_string()
11042}
11043fn default_benefits_enrollment_rate() -> f64 {
11044 0.60
11045}
11046fn default_retirement_participation_rate() -> f64 {
11047 0.45
11048}
11049
11050#[derive(Debug, Clone, Serialize, Deserialize)]
11052pub struct PayrollSalaryRanges {
11053 #[serde(default = "default_staff_min")]
11055 pub staff_min: f64,
11056 #[serde(default = "default_staff_max")]
11057 pub staff_max: f64,
11058 #[serde(default = "default_manager_min")]
11060 pub manager_min: f64,
11061 #[serde(default = "default_manager_max")]
11062 pub manager_max: f64,
11063 #[serde(default = "default_director_min")]
11065 pub director_min: f64,
11066 #[serde(default = "default_director_max")]
11067 pub director_max: f64,
11068 #[serde(default = "default_executive_min")]
11070 pub executive_min: f64,
11071 #[serde(default = "default_executive_max")]
11072 pub executive_max: f64,
11073}
11074
11075impl Default for PayrollSalaryRanges {
11076 fn default() -> Self {
11077 Self {
11078 staff_min: default_staff_min(),
11079 staff_max: default_staff_max(),
11080 manager_min: default_manager_min(),
11081 manager_max: default_manager_max(),
11082 director_min: default_director_min(),
11083 director_max: default_director_max(),
11084 executive_min: default_executive_min(),
11085 executive_max: default_executive_max(),
11086 }
11087 }
11088}
11089
11090fn default_staff_min() -> f64 {
11091 50_000.0
11092}
11093fn default_staff_max() -> f64 {
11094 70_000.0
11095}
11096fn default_manager_min() -> f64 {
11097 80_000.0
11098}
11099fn default_manager_max() -> f64 {
11100 120_000.0
11101}
11102fn default_director_min() -> f64 {
11103 120_000.0
11104}
11105fn default_director_max() -> f64 {
11106 180_000.0
11107}
11108fn default_executive_min() -> f64 {
11109 180_000.0
11110}
11111fn default_executive_max() -> f64 {
11112 350_000.0
11113}
11114
11115#[derive(Debug, Clone, Serialize, Deserialize)]
11117pub struct PayrollTaxRates {
11118 #[serde(default = "default_federal_rate")]
11120 pub federal_effective: f64,
11121 #[serde(default = "default_state_rate")]
11123 pub state_effective: f64,
11124 #[serde(default = "default_fica_rate")]
11126 pub fica: f64,
11127}
11128
11129impl Default for PayrollTaxRates {
11130 fn default() -> Self {
11131 Self {
11132 federal_effective: default_federal_rate(),
11133 state_effective: default_state_rate(),
11134 fica: default_fica_rate(),
11135 }
11136 }
11137}
11138
11139fn default_federal_rate() -> f64 {
11140 0.22
11141}
11142fn default_state_rate() -> f64 {
11143 0.05
11144}
11145fn default_fica_rate() -> f64 {
11146 0.0765
11147}
11148
11149#[derive(Debug, Clone, Serialize, Deserialize)]
11151pub struct TimeAttendanceConfig {
11152 #[serde(default = "default_true")]
11154 pub enabled: bool,
11155 #[serde(default = "default_overtime_rate")]
11157 pub overtime_rate: f64,
11158}
11159
11160impl Default for TimeAttendanceConfig {
11161 fn default() -> Self {
11162 Self {
11163 enabled: true,
11164 overtime_rate: default_overtime_rate(),
11165 }
11166 }
11167}
11168
11169fn default_overtime_rate() -> f64 {
11170 0.10
11171}
11172
11173#[derive(Debug, Clone, Serialize, Deserialize)]
11175pub struct ExpenseConfig {
11176 #[serde(default = "default_true")]
11178 pub enabled: bool,
11179 #[serde(default = "default_expense_submission_rate")]
11181 pub submission_rate: f64,
11182 #[serde(default = "default_policy_violation_rate")]
11184 pub policy_violation_rate: f64,
11185}
11186
11187impl Default for ExpenseConfig {
11188 fn default() -> Self {
11189 Self {
11190 enabled: true,
11191 submission_rate: default_expense_submission_rate(),
11192 policy_violation_rate: default_policy_violation_rate(),
11193 }
11194 }
11195}
11196
11197fn default_expense_submission_rate() -> f64 {
11198 0.30
11199}
11200fn default_policy_violation_rate() -> f64 {
11201 0.08
11202}
11203
11204#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11208pub struct ManufacturingProcessConfig {
11209 #[serde(default)]
11211 pub enabled: bool,
11212 #[serde(default)]
11214 pub production_orders: ProductionOrderConfig,
11215 #[serde(default)]
11217 pub costing: ManufacturingCostingConfig,
11218 #[serde(default)]
11220 pub routing: RoutingConfig,
11221}
11222
11223#[derive(Debug, Clone, Serialize, Deserialize)]
11225pub struct ProductionOrderConfig {
11226 #[serde(default = "default_prod_orders_per_month")]
11228 pub orders_per_month: u32,
11229 #[serde(default = "default_prod_avg_batch_size")]
11231 pub avg_batch_size: u32,
11232 #[serde(default = "default_prod_yield_rate")]
11234 pub yield_rate: f64,
11235 #[serde(default = "default_prod_make_to_order_rate")]
11237 pub make_to_order_rate: f64,
11238 #[serde(default = "default_prod_rework_rate")]
11240 pub rework_rate: f64,
11241}
11242
11243impl Default for ProductionOrderConfig {
11244 fn default() -> Self {
11245 Self {
11246 orders_per_month: default_prod_orders_per_month(),
11247 avg_batch_size: default_prod_avg_batch_size(),
11248 yield_rate: default_prod_yield_rate(),
11249 make_to_order_rate: default_prod_make_to_order_rate(),
11250 rework_rate: default_prod_rework_rate(),
11251 }
11252 }
11253}
11254
11255fn default_prod_orders_per_month() -> u32 {
11256 50
11257}
11258fn default_prod_avg_batch_size() -> u32 {
11259 100
11260}
11261fn default_prod_yield_rate() -> f64 {
11262 0.97
11263}
11264fn default_prod_make_to_order_rate() -> f64 {
11265 0.20
11266}
11267fn default_prod_rework_rate() -> f64 {
11268 0.03
11269}
11270
11271#[derive(Debug, Clone, Serialize, Deserialize)]
11273pub struct ManufacturingCostingConfig {
11274 #[serde(default = "default_labor_rate")]
11276 pub labor_rate_per_hour: f64,
11277 #[serde(default = "default_overhead_rate")]
11279 pub overhead_rate: f64,
11280 #[serde(default = "default_cost_update_frequency")]
11282 pub standard_cost_update_frequency: String,
11283}
11284
11285impl Default for ManufacturingCostingConfig {
11286 fn default() -> Self {
11287 Self {
11288 labor_rate_per_hour: default_labor_rate(),
11289 overhead_rate: default_overhead_rate(),
11290 standard_cost_update_frequency: default_cost_update_frequency(),
11291 }
11292 }
11293}
11294
11295fn default_labor_rate() -> f64 {
11296 35.0
11297}
11298fn default_overhead_rate() -> f64 {
11299 1.50
11300}
11301fn default_cost_update_frequency() -> String {
11302 "quarterly".to_string()
11303}
11304
11305#[derive(Debug, Clone, Serialize, Deserialize)]
11307pub struct RoutingConfig {
11308 #[serde(default = "default_avg_operations")]
11310 pub avg_operations: u32,
11311 #[serde(default = "default_setup_time")]
11313 pub setup_time_hours: f64,
11314 #[serde(default = "default_run_time_variation")]
11316 pub run_time_variation: f64,
11317}
11318
11319impl Default for RoutingConfig {
11320 fn default() -> Self {
11321 Self {
11322 avg_operations: default_avg_operations(),
11323 setup_time_hours: default_setup_time(),
11324 run_time_variation: default_run_time_variation(),
11325 }
11326 }
11327}
11328
11329fn default_avg_operations() -> u32 {
11330 4
11331}
11332fn default_setup_time() -> f64 {
11333 1.5
11334}
11335fn default_run_time_variation() -> f64 {
11336 0.15
11337}
11338
11339#[derive(Debug, Clone, Serialize, Deserialize)]
11343pub struct SalesQuoteConfig {
11344 #[serde(default)]
11346 pub enabled: bool,
11347 #[serde(default = "default_quotes_per_month")]
11349 pub quotes_per_month: u32,
11350 #[serde(default = "default_quote_win_rate")]
11352 pub win_rate: f64,
11353 #[serde(default = "default_quote_validity_days")]
11355 pub validity_days: u32,
11356}
11357
11358impl Default for SalesQuoteConfig {
11359 fn default() -> Self {
11360 Self {
11361 enabled: false,
11362 quotes_per_month: default_quotes_per_month(),
11363 win_rate: default_quote_win_rate(),
11364 validity_days: default_quote_validity_days(),
11365 }
11366 }
11367}
11368
11369fn default_quotes_per_month() -> u32 {
11370 30
11371}
11372fn default_quote_win_rate() -> f64 {
11373 0.35
11374}
11375fn default_quote_validity_days() -> u32 {
11376 30
11377}
11378
11379#[derive(Debug, Clone, Serialize, Deserialize)]
11388pub struct TaxConfig {
11389 #[serde(default)]
11391 pub enabled: bool,
11392 #[serde(default)]
11394 pub jurisdictions: TaxJurisdictionConfig,
11395 #[serde(default)]
11397 pub vat_gst: VatGstConfig,
11398 #[serde(default)]
11400 pub sales_tax: SalesTaxConfig,
11401 #[serde(default)]
11403 pub withholding: WithholdingTaxSchemaConfig,
11404 #[serde(default)]
11406 pub provisions: TaxProvisionSchemaConfig,
11407 #[serde(default)]
11409 pub payroll_tax: PayrollTaxSchemaConfig,
11410 #[serde(default = "default_tax_anomaly_rate")]
11412 pub anomaly_rate: f64,
11413}
11414
11415fn default_tax_anomaly_rate() -> f64 {
11416 0.03
11417}
11418
11419impl Default for TaxConfig {
11420 fn default() -> Self {
11421 Self {
11422 enabled: false,
11423 jurisdictions: TaxJurisdictionConfig::default(),
11424 vat_gst: VatGstConfig::default(),
11425 sales_tax: SalesTaxConfig::default(),
11426 withholding: WithholdingTaxSchemaConfig::default(),
11427 provisions: TaxProvisionSchemaConfig::default(),
11428 payroll_tax: PayrollTaxSchemaConfig::default(),
11429 anomaly_rate: default_tax_anomaly_rate(),
11430 }
11431 }
11432}
11433
11434#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11439pub struct TaxJurisdictionConfig {
11440 #[serde(default)]
11442 pub countries: Vec<String>,
11443 #[serde(default)]
11445 pub include_subnational: bool,
11446}
11447
11448#[derive(Debug, Clone, Serialize, Deserialize)]
11453pub struct VatGstConfig {
11454 #[serde(default)]
11456 pub enabled: bool,
11457 #[serde(default)]
11459 pub standard_rates: std::collections::HashMap<String, f64>,
11460 #[serde(default)]
11462 pub reduced_rates: std::collections::HashMap<String, f64>,
11463 #[serde(default)]
11465 pub exempt_categories: Vec<String>,
11466 #[serde(default = "default_true")]
11468 pub reverse_charge: bool,
11469}
11470
11471impl Default for VatGstConfig {
11472 fn default() -> Self {
11473 Self {
11474 enabled: false,
11475 standard_rates: std::collections::HashMap::new(),
11476 reduced_rates: std::collections::HashMap::new(),
11477 exempt_categories: Vec::new(),
11478 reverse_charge: true,
11479 }
11480 }
11481}
11482
11483#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11487pub struct SalesTaxConfig {
11488 #[serde(default)]
11490 pub enabled: bool,
11491 #[serde(default)]
11493 pub nexus_states: Vec<String>,
11494}
11495
11496#[derive(Debug, Clone, Serialize, Deserialize)]
11501pub struct WithholdingTaxSchemaConfig {
11502 #[serde(default)]
11504 pub enabled: bool,
11505 #[serde(default = "default_true")]
11507 pub treaty_network: bool,
11508 #[serde(default = "default_withholding_rate")]
11510 pub default_rate: f64,
11511 #[serde(default = "default_treaty_reduced_rate")]
11513 pub treaty_reduced_rate: f64,
11514}
11515
11516fn default_withholding_rate() -> f64 {
11517 0.30
11518}
11519
11520fn default_treaty_reduced_rate() -> f64 {
11521 0.15
11522}
11523
11524impl Default for WithholdingTaxSchemaConfig {
11525 fn default() -> Self {
11526 Self {
11527 enabled: false,
11528 treaty_network: true,
11529 default_rate: default_withholding_rate(),
11530 treaty_reduced_rate: default_treaty_reduced_rate(),
11531 }
11532 }
11533}
11534
11535#[derive(Debug, Clone, Serialize, Deserialize)]
11540pub struct TaxProvisionSchemaConfig {
11541 #[serde(default = "default_true")]
11544 pub enabled: bool,
11545 #[serde(default = "default_statutory_rate")]
11547 pub statutory_rate: f64,
11548 #[serde(default = "default_true")]
11550 pub uncertain_positions: bool,
11551}
11552
11553fn default_statutory_rate() -> f64 {
11554 0.21
11555}
11556
11557impl Default for TaxProvisionSchemaConfig {
11558 fn default() -> Self {
11559 Self {
11560 enabled: true,
11561 statutory_rate: default_statutory_rate(),
11562 uncertain_positions: true,
11563 }
11564 }
11565}
11566
11567#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11572pub struct PayrollTaxSchemaConfig {
11573 #[serde(default)]
11575 pub enabled: bool,
11576}
11577
11578#[derive(Debug, Clone, Serialize, Deserialize)]
11588pub struct TreasuryConfig {
11589 #[serde(default)]
11591 pub enabled: bool,
11592 #[serde(default)]
11594 pub cash_positioning: CashPositioningConfig,
11595 #[serde(default)]
11597 pub cash_forecasting: CashForecastingConfig,
11598 #[serde(default)]
11600 pub cash_pooling: CashPoolingConfig,
11601 #[serde(default)]
11603 pub hedging: HedgingSchemaConfig,
11604 #[serde(default)]
11606 pub debt: DebtSchemaConfig,
11607 #[serde(default)]
11609 pub netting: NettingSchemaConfig,
11610 #[serde(default)]
11612 pub bank_guarantees: BankGuaranteeSchemaConfig,
11613 #[serde(default = "default_treasury_anomaly_rate")]
11615 pub anomaly_rate: f64,
11616}
11617
11618fn default_treasury_anomaly_rate() -> f64 {
11619 0.02
11620}
11621
11622impl Default for TreasuryConfig {
11623 fn default() -> Self {
11624 Self {
11625 enabled: false,
11626 cash_positioning: CashPositioningConfig::default(),
11627 cash_forecasting: CashForecastingConfig::default(),
11628 cash_pooling: CashPoolingConfig::default(),
11629 hedging: HedgingSchemaConfig::default(),
11630 debt: DebtSchemaConfig::default(),
11631 netting: NettingSchemaConfig::default(),
11632 bank_guarantees: BankGuaranteeSchemaConfig::default(),
11633 anomaly_rate: default_treasury_anomaly_rate(),
11634 }
11635 }
11636}
11637
11638#[derive(Debug, Clone, Serialize, Deserialize)]
11642pub struct CashPositioningConfig {
11643 #[serde(default = "default_true")]
11645 pub enabled: bool,
11646 #[serde(default = "default_cash_frequency")]
11648 pub frequency: String,
11649 #[serde(default = "default_minimum_balance_policy")]
11651 pub minimum_balance_policy: f64,
11652}
11653
11654fn default_cash_frequency() -> String {
11655 "daily".to_string()
11656}
11657
11658fn default_minimum_balance_policy() -> f64 {
11659 100_000.0
11660}
11661
11662impl Default for CashPositioningConfig {
11663 fn default() -> Self {
11664 Self {
11665 enabled: true,
11666 frequency: default_cash_frequency(),
11667 minimum_balance_policy: default_minimum_balance_policy(),
11668 }
11669 }
11670}
11671
11672#[derive(Debug, Clone, Serialize, Deserialize)]
11676pub struct CashForecastingConfig {
11677 #[serde(default = "default_true")]
11679 pub enabled: bool,
11680 #[serde(default = "default_horizon_days")]
11682 pub horizon_days: u32,
11683 #[serde(default = "default_ar_probability_curve")]
11685 pub ar_collection_probability_curve: String,
11686 #[serde(default = "default_confidence_interval")]
11688 pub confidence_interval: f64,
11689}
11690
11691fn default_horizon_days() -> u32 {
11692 90
11693}
11694
11695fn default_ar_probability_curve() -> String {
11696 "aging".to_string()
11697}
11698
11699fn default_confidence_interval() -> f64 {
11700 0.90
11701}
11702
11703impl Default for CashForecastingConfig {
11704 fn default() -> Self {
11705 Self {
11706 enabled: true,
11707 horizon_days: default_horizon_days(),
11708 ar_collection_probability_curve: default_ar_probability_curve(),
11709 confidence_interval: default_confidence_interval(),
11710 }
11711 }
11712}
11713
11714#[derive(Debug, Clone, Serialize, Deserialize)]
11718pub struct CashPoolingConfig {
11719 #[serde(default)]
11721 pub enabled: bool,
11722 #[serde(default = "default_pool_type")]
11724 pub pool_type: String,
11725 #[serde(default = "default_sweep_time")]
11727 pub sweep_time: String,
11728}
11729
11730fn default_pool_type() -> String {
11731 "zero_balancing".to_string()
11732}
11733
11734fn default_sweep_time() -> String {
11735 "16:00".to_string()
11736}
11737
11738impl Default for CashPoolingConfig {
11739 fn default() -> Self {
11740 Self {
11741 enabled: false,
11742 pool_type: default_pool_type(),
11743 sweep_time: default_sweep_time(),
11744 }
11745 }
11746}
11747
11748#[derive(Debug, Clone, Serialize, Deserialize)]
11753pub struct HedgingSchemaConfig {
11754 #[serde(default)]
11756 pub enabled: bool,
11757 #[serde(default = "default_hedge_ratio")]
11759 pub hedge_ratio: f64,
11760 #[serde(default = "default_hedge_instruments")]
11762 pub instruments: Vec<String>,
11763 #[serde(default = "default_true")]
11765 pub hedge_accounting: bool,
11766 #[serde(default = "default_effectiveness_method")]
11768 pub effectiveness_method: String,
11769}
11770
11771fn default_hedge_ratio() -> f64 {
11772 0.75
11773}
11774
11775fn default_hedge_instruments() -> Vec<String> {
11776 vec!["fx_forward".to_string(), "interest_rate_swap".to_string()]
11777}
11778
11779fn default_effectiveness_method() -> String {
11780 "regression".to_string()
11781}
11782
11783impl Default for HedgingSchemaConfig {
11784 fn default() -> Self {
11785 Self {
11786 enabled: false,
11787 hedge_ratio: default_hedge_ratio(),
11788 instruments: default_hedge_instruments(),
11789 hedge_accounting: true,
11790 effectiveness_method: default_effectiveness_method(),
11791 }
11792 }
11793}
11794
11795#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11800pub struct DebtSchemaConfig {
11801 #[serde(default)]
11803 pub enabled: bool,
11804 #[serde(default)]
11806 pub instruments: Vec<DebtInstrumentDef>,
11807 #[serde(default)]
11809 pub covenants: Vec<CovenantDef>,
11810}
11811
11812#[derive(Debug, Clone, Serialize, Deserialize)]
11814pub struct DebtInstrumentDef {
11815 #[serde(rename = "type")]
11817 pub instrument_type: String,
11818 #[serde(default)]
11820 pub principal: Option<f64>,
11821 #[serde(default)]
11823 pub rate: Option<f64>,
11824 #[serde(default)]
11826 pub maturity_months: Option<u32>,
11827 #[serde(default)]
11829 pub facility: Option<f64>,
11830}
11831
11832#[derive(Debug, Clone, Serialize, Deserialize)]
11834pub struct CovenantDef {
11835 #[serde(rename = "type")]
11838 pub covenant_type: String,
11839 pub threshold: f64,
11841}
11842
11843#[derive(Debug, Clone, Serialize, Deserialize)]
11847pub struct NettingSchemaConfig {
11848 #[serde(default)]
11850 pub enabled: bool,
11851 #[serde(default = "default_netting_cycle")]
11853 pub cycle: String,
11854}
11855
11856fn default_netting_cycle() -> String {
11857 "monthly".to_string()
11858}
11859
11860impl Default for NettingSchemaConfig {
11861 fn default() -> Self {
11862 Self {
11863 enabled: false,
11864 cycle: default_netting_cycle(),
11865 }
11866 }
11867}
11868
11869#[derive(Debug, Clone, Serialize, Deserialize)]
11873pub struct BankGuaranteeSchemaConfig {
11874 #[serde(default)]
11876 pub enabled: bool,
11877 #[serde(default = "default_guarantee_count")]
11879 pub count: u32,
11880}
11881
11882fn default_guarantee_count() -> u32 {
11883 5
11884}
11885
11886impl Default for BankGuaranteeSchemaConfig {
11887 fn default() -> Self {
11888 Self {
11889 enabled: false,
11890 count: default_guarantee_count(),
11891 }
11892 }
11893}
11894
11895#[derive(Debug, Clone, Serialize, Deserialize)]
11904pub struct ProjectAccountingConfig {
11905 #[serde(default)]
11907 pub enabled: bool,
11908 #[serde(default = "default_project_count")]
11910 pub project_count: u32,
11911 #[serde(default)]
11913 pub project_types: ProjectTypeDistribution,
11914 #[serde(default)]
11916 pub wbs: WbsSchemaConfig,
11917 #[serde(default)]
11919 pub cost_allocation: CostAllocationConfig,
11920 #[serde(default)]
11922 pub revenue_recognition: ProjectRevenueRecognitionConfig,
11923 #[serde(default)]
11925 pub milestones: MilestoneSchemaConfig,
11926 #[serde(default)]
11928 pub change_orders: ChangeOrderSchemaConfig,
11929 #[serde(default)]
11931 pub retainage: RetainageSchemaConfig,
11932 #[serde(default)]
11934 pub earned_value: EarnedValueSchemaConfig,
11935 #[serde(default = "default_project_anomaly_rate")]
11937 pub anomaly_rate: f64,
11938}
11939
11940fn default_project_count() -> u32 {
11941 10
11942}
11943
11944fn default_project_anomaly_rate() -> f64 {
11945 0.03
11946}
11947
11948impl Default for ProjectAccountingConfig {
11949 fn default() -> Self {
11950 Self {
11951 enabled: false,
11952 project_count: default_project_count(),
11953 project_types: ProjectTypeDistribution::default(),
11954 wbs: WbsSchemaConfig::default(),
11955 cost_allocation: CostAllocationConfig::default(),
11956 revenue_recognition: ProjectRevenueRecognitionConfig::default(),
11957 milestones: MilestoneSchemaConfig::default(),
11958 change_orders: ChangeOrderSchemaConfig::default(),
11959 retainage: RetainageSchemaConfig::default(),
11960 earned_value: EarnedValueSchemaConfig::default(),
11961 anomaly_rate: default_project_anomaly_rate(),
11962 }
11963 }
11964}
11965
11966#[derive(Debug, Clone, Serialize, Deserialize)]
11968pub struct ProjectTypeDistribution {
11969 #[serde(default = "default_capital_weight")]
11971 pub capital: f64,
11972 #[serde(default = "default_internal_weight")]
11974 pub internal: f64,
11975 #[serde(default = "default_customer_weight")]
11977 pub customer: f64,
11978 #[serde(default = "default_rnd_weight")]
11980 pub r_and_d: f64,
11981 #[serde(default = "default_maintenance_weight")]
11983 pub maintenance: f64,
11984 #[serde(default = "default_technology_weight")]
11986 pub technology: f64,
11987}
11988
11989fn default_capital_weight() -> f64 {
11990 0.25
11991}
11992fn default_internal_weight() -> f64 {
11993 0.20
11994}
11995fn default_customer_weight() -> f64 {
11996 0.30
11997}
11998fn default_rnd_weight() -> f64 {
11999 0.10
12000}
12001fn default_maintenance_weight() -> f64 {
12002 0.10
12003}
12004fn default_technology_weight() -> f64 {
12005 0.05
12006}
12007
12008impl Default for ProjectTypeDistribution {
12009 fn default() -> Self {
12010 Self {
12011 capital: default_capital_weight(),
12012 internal: default_internal_weight(),
12013 customer: default_customer_weight(),
12014 r_and_d: default_rnd_weight(),
12015 maintenance: default_maintenance_weight(),
12016 technology: default_technology_weight(),
12017 }
12018 }
12019}
12020
12021#[derive(Debug, Clone, Serialize, Deserialize)]
12023pub struct WbsSchemaConfig {
12024 #[serde(default = "default_wbs_max_depth")]
12026 pub max_depth: u32,
12027 #[serde(default = "default_wbs_min_elements")]
12029 pub min_elements_per_level: u32,
12030 #[serde(default = "default_wbs_max_elements")]
12032 pub max_elements_per_level: u32,
12033}
12034
12035fn default_wbs_max_depth() -> u32 {
12036 3
12037}
12038fn default_wbs_min_elements() -> u32 {
12039 2
12040}
12041fn default_wbs_max_elements() -> u32 {
12042 6
12043}
12044
12045impl Default for WbsSchemaConfig {
12046 fn default() -> Self {
12047 Self {
12048 max_depth: default_wbs_max_depth(),
12049 min_elements_per_level: default_wbs_min_elements(),
12050 max_elements_per_level: default_wbs_max_elements(),
12051 }
12052 }
12053}
12054
12055#[derive(Debug, Clone, Serialize, Deserialize)]
12057pub struct CostAllocationConfig {
12058 #[serde(default = "default_time_entry_rate")]
12060 pub time_entry_project_rate: f64,
12061 #[serde(default = "default_expense_rate")]
12063 pub expense_project_rate: f64,
12064 #[serde(default = "default_po_rate")]
12066 pub purchase_order_project_rate: f64,
12067 #[serde(default = "default_vi_rate")]
12069 pub vendor_invoice_project_rate: f64,
12070}
12071
12072fn default_time_entry_rate() -> f64 {
12073 0.60
12074}
12075fn default_expense_rate() -> f64 {
12076 0.30
12077}
12078fn default_po_rate() -> f64 {
12079 0.40
12080}
12081fn default_vi_rate() -> f64 {
12082 0.35
12083}
12084
12085impl Default for CostAllocationConfig {
12086 fn default() -> Self {
12087 Self {
12088 time_entry_project_rate: default_time_entry_rate(),
12089 expense_project_rate: default_expense_rate(),
12090 purchase_order_project_rate: default_po_rate(),
12091 vendor_invoice_project_rate: default_vi_rate(),
12092 }
12093 }
12094}
12095
12096#[derive(Debug, Clone, Serialize, Deserialize)]
12098pub struct ProjectRevenueRecognitionConfig {
12099 #[serde(default = "default_true")]
12101 pub enabled: bool,
12102 #[serde(default = "default_revenue_method")]
12104 pub method: String,
12105 #[serde(default = "default_completion_measure")]
12107 pub completion_measure: String,
12108 #[serde(default = "default_avg_contract_value")]
12110 pub avg_contract_value: f64,
12111}
12112
12113fn default_revenue_method() -> String {
12114 "percentage_of_completion".to_string()
12115}
12116fn default_completion_measure() -> String {
12117 "cost_to_cost".to_string()
12118}
12119fn default_avg_contract_value() -> f64 {
12120 500_000.0
12121}
12122
12123impl Default for ProjectRevenueRecognitionConfig {
12124 fn default() -> Self {
12125 Self {
12126 enabled: true,
12127 method: default_revenue_method(),
12128 completion_measure: default_completion_measure(),
12129 avg_contract_value: default_avg_contract_value(),
12130 }
12131 }
12132}
12133
12134#[derive(Debug, Clone, Serialize, Deserialize)]
12136pub struct MilestoneSchemaConfig {
12137 #[serde(default = "default_true")]
12139 pub enabled: bool,
12140 #[serde(default = "default_milestones_per_project")]
12142 pub avg_per_project: u32,
12143 #[serde(default = "default_payment_milestone_rate")]
12145 pub payment_milestone_rate: f64,
12146}
12147
12148fn default_milestones_per_project() -> u32 {
12149 4
12150}
12151fn default_payment_milestone_rate() -> f64 {
12152 0.50
12153}
12154
12155impl Default for MilestoneSchemaConfig {
12156 fn default() -> Self {
12157 Self {
12158 enabled: true,
12159 avg_per_project: default_milestones_per_project(),
12160 payment_milestone_rate: default_payment_milestone_rate(),
12161 }
12162 }
12163}
12164
12165#[derive(Debug, Clone, Serialize, Deserialize)]
12167pub struct ChangeOrderSchemaConfig {
12168 #[serde(default = "default_true")]
12170 pub enabled: bool,
12171 #[serde(default = "default_change_order_probability")]
12173 pub probability: f64,
12174 #[serde(default = "default_max_change_orders")]
12176 pub max_per_project: u32,
12177 #[serde(default = "default_change_order_approval_rate")]
12179 pub approval_rate: f64,
12180}
12181
12182fn default_change_order_probability() -> f64 {
12183 0.40
12184}
12185fn default_max_change_orders() -> u32 {
12186 3
12187}
12188fn default_change_order_approval_rate() -> f64 {
12189 0.75
12190}
12191
12192impl Default for ChangeOrderSchemaConfig {
12193 fn default() -> Self {
12194 Self {
12195 enabled: true,
12196 probability: default_change_order_probability(),
12197 max_per_project: default_max_change_orders(),
12198 approval_rate: default_change_order_approval_rate(),
12199 }
12200 }
12201}
12202
12203#[derive(Debug, Clone, Serialize, Deserialize)]
12205pub struct RetainageSchemaConfig {
12206 #[serde(default)]
12208 pub enabled: bool,
12209 #[serde(default = "default_retainage_pct")]
12211 pub default_percentage: f64,
12212}
12213
12214fn default_retainage_pct() -> f64 {
12215 0.10
12216}
12217
12218impl Default for RetainageSchemaConfig {
12219 fn default() -> Self {
12220 Self {
12221 enabled: false,
12222 default_percentage: default_retainage_pct(),
12223 }
12224 }
12225}
12226
12227#[derive(Debug, Clone, Serialize, Deserialize)]
12229pub struct EarnedValueSchemaConfig {
12230 #[serde(default = "default_true")]
12232 pub enabled: bool,
12233 #[serde(default = "default_evm_frequency")]
12235 pub frequency: String,
12236}
12237
12238fn default_evm_frequency() -> String {
12239 "monthly".to_string()
12240}
12241
12242impl Default for EarnedValueSchemaConfig {
12243 fn default() -> Self {
12244 Self {
12245 enabled: true,
12246 frequency: default_evm_frequency(),
12247 }
12248 }
12249}
12250
12251#[derive(Debug, Clone, Serialize, Deserialize)]
12257pub struct EsgConfig {
12258 #[serde(default)]
12260 pub enabled: bool,
12261 #[serde(default)]
12263 pub environmental: EnvironmentalConfig,
12264 #[serde(default)]
12266 pub social: SocialConfig,
12267 #[serde(default)]
12269 pub governance: GovernanceSchemaConfig,
12270 #[serde(default)]
12272 pub supply_chain_esg: SupplyChainEsgConfig,
12273 #[serde(default)]
12275 pub reporting: EsgReportingConfig,
12276 #[serde(default)]
12278 pub climate_scenarios: ClimateScenarioConfig,
12279 #[serde(default = "default_esg_anomaly_rate")]
12281 pub anomaly_rate: f64,
12282}
12283
12284fn default_esg_anomaly_rate() -> f64 {
12285 0.02
12286}
12287
12288impl Default for EsgConfig {
12289 fn default() -> Self {
12290 Self {
12291 enabled: false,
12292 environmental: EnvironmentalConfig::default(),
12293 social: SocialConfig::default(),
12294 governance: GovernanceSchemaConfig::default(),
12295 supply_chain_esg: SupplyChainEsgConfig::default(),
12296 reporting: EsgReportingConfig::default(),
12297 climate_scenarios: ClimateScenarioConfig::default(),
12298 anomaly_rate: default_esg_anomaly_rate(),
12299 }
12300 }
12301}
12302
12303#[derive(Debug, Clone, Serialize, Deserialize, Default)]
12308pub struct CountryPacksSchemaConfig {
12309 #[serde(default)]
12311 pub external_dir: Option<PathBuf>,
12312 #[serde(default)]
12316 pub overrides: std::collections::HashMap<String, serde_json::Value>,
12317}
12318
12319#[derive(Debug, Clone, Serialize, Deserialize)]
12321pub struct EnvironmentalConfig {
12322 #[serde(default = "default_true")]
12324 pub enabled: bool,
12325 #[serde(default)]
12327 pub scope1: EmissionScopeConfig,
12328 #[serde(default)]
12330 pub scope2: EmissionScopeConfig,
12331 #[serde(default)]
12333 pub scope3: Scope3Config,
12334 #[serde(default)]
12336 pub energy: EnergySchemaConfig,
12337 #[serde(default)]
12339 pub water: WaterSchemaConfig,
12340 #[serde(default)]
12342 pub waste: WasteSchemaConfig,
12343}
12344
12345impl Default for EnvironmentalConfig {
12346 fn default() -> Self {
12347 Self {
12348 enabled: true,
12349 scope1: EmissionScopeConfig::default(),
12350 scope2: EmissionScopeConfig::default(),
12351 scope3: Scope3Config::default(),
12352 energy: EnergySchemaConfig::default(),
12353 water: WaterSchemaConfig::default(),
12354 waste: WasteSchemaConfig::default(),
12355 }
12356 }
12357}
12358
12359#[derive(Debug, Clone, Serialize, Deserialize)]
12361pub struct EmissionScopeConfig {
12362 #[serde(default = "default_true")]
12364 pub enabled: bool,
12365 #[serde(default = "default_emission_region")]
12367 pub factor_region: String,
12368}
12369
12370fn default_emission_region() -> String {
12371 "US".to_string()
12372}
12373
12374impl Default for EmissionScopeConfig {
12375 fn default() -> Self {
12376 Self {
12377 enabled: true,
12378 factor_region: default_emission_region(),
12379 }
12380 }
12381}
12382
12383#[derive(Debug, Clone, Serialize, Deserialize)]
12385pub struct Scope3Config {
12386 #[serde(default = "default_true")]
12388 pub enabled: bool,
12389 #[serde(default = "default_scope3_categories")]
12391 pub categories: Vec<String>,
12392 #[serde(default = "default_spend_intensity")]
12394 pub default_spend_intensity_kg_per_usd: f64,
12395}
12396
12397fn default_scope3_categories() -> Vec<String> {
12398 vec![
12399 "purchased_goods".to_string(),
12400 "business_travel".to_string(),
12401 "employee_commuting".to_string(),
12402 ]
12403}
12404
12405fn default_spend_intensity() -> f64 {
12406 0.5
12407}
12408
12409impl Default for Scope3Config {
12410 fn default() -> Self {
12411 Self {
12412 enabled: true,
12413 categories: default_scope3_categories(),
12414 default_spend_intensity_kg_per_usd: default_spend_intensity(),
12415 }
12416 }
12417}
12418
12419#[derive(Debug, Clone, Serialize, Deserialize)]
12421pub struct EnergySchemaConfig {
12422 #[serde(default = "default_true")]
12424 pub enabled: bool,
12425 #[serde(default = "default_facility_count")]
12427 pub facility_count: u32,
12428 #[serde(default = "default_renewable_target")]
12430 pub renewable_target: f64,
12431}
12432
12433fn default_facility_count() -> u32 {
12434 5
12435}
12436
12437fn default_renewable_target() -> f64 {
12438 0.30
12439}
12440
12441impl Default for EnergySchemaConfig {
12442 fn default() -> Self {
12443 Self {
12444 enabled: true,
12445 facility_count: default_facility_count(),
12446 renewable_target: default_renewable_target(),
12447 }
12448 }
12449}
12450
12451#[derive(Debug, Clone, Serialize, Deserialize)]
12453pub struct WaterSchemaConfig {
12454 #[serde(default = "default_true")]
12456 pub enabled: bool,
12457 #[serde(default = "default_water_facility_count")]
12459 pub facility_count: u32,
12460}
12461
12462fn default_water_facility_count() -> u32 {
12463 3
12464}
12465
12466impl Default for WaterSchemaConfig {
12467 fn default() -> Self {
12468 Self {
12469 enabled: true,
12470 facility_count: default_water_facility_count(),
12471 }
12472 }
12473}
12474
12475#[derive(Debug, Clone, Serialize, Deserialize)]
12477pub struct WasteSchemaConfig {
12478 #[serde(default = "default_true")]
12480 pub enabled: bool,
12481 #[serde(default = "default_diversion_target")]
12483 pub diversion_target: f64,
12484}
12485
12486fn default_diversion_target() -> f64 {
12487 0.50
12488}
12489
12490impl Default for WasteSchemaConfig {
12491 fn default() -> Self {
12492 Self {
12493 enabled: true,
12494 diversion_target: default_diversion_target(),
12495 }
12496 }
12497}
12498
12499#[derive(Debug, Clone, Serialize, Deserialize)]
12501pub struct SocialConfig {
12502 #[serde(default = "default_true")]
12504 pub enabled: bool,
12505 #[serde(default)]
12507 pub diversity: DiversitySchemaConfig,
12508 #[serde(default)]
12510 pub pay_equity: PayEquitySchemaConfig,
12511 #[serde(default)]
12513 pub safety: SafetySchemaConfig,
12514}
12515
12516impl Default for SocialConfig {
12517 fn default() -> Self {
12518 Self {
12519 enabled: true,
12520 diversity: DiversitySchemaConfig::default(),
12521 pay_equity: PayEquitySchemaConfig::default(),
12522 safety: SafetySchemaConfig::default(),
12523 }
12524 }
12525}
12526
12527#[derive(Debug, Clone, Serialize, Deserialize)]
12529pub struct DiversitySchemaConfig {
12530 #[serde(default = "default_true")]
12532 pub enabled: bool,
12533 #[serde(default = "default_diversity_dimensions")]
12535 pub dimensions: Vec<String>,
12536}
12537
12538fn default_diversity_dimensions() -> Vec<String> {
12539 vec![
12540 "gender".to_string(),
12541 "ethnicity".to_string(),
12542 "age_group".to_string(),
12543 ]
12544}
12545
12546impl Default for DiversitySchemaConfig {
12547 fn default() -> Self {
12548 Self {
12549 enabled: true,
12550 dimensions: default_diversity_dimensions(),
12551 }
12552 }
12553}
12554
12555#[derive(Debug, Clone, Serialize, Deserialize)]
12557pub struct PayEquitySchemaConfig {
12558 #[serde(default = "default_true")]
12560 pub enabled: bool,
12561 #[serde(default = "default_pay_gap_threshold")]
12563 pub gap_threshold: f64,
12564}
12565
12566fn default_pay_gap_threshold() -> f64 {
12567 0.05
12568}
12569
12570impl Default for PayEquitySchemaConfig {
12571 fn default() -> Self {
12572 Self {
12573 enabled: true,
12574 gap_threshold: default_pay_gap_threshold(),
12575 }
12576 }
12577}
12578
12579#[derive(Debug, Clone, Serialize, Deserialize)]
12581pub struct SafetySchemaConfig {
12582 #[serde(default = "default_true")]
12584 pub enabled: bool,
12585 #[serde(default = "default_trir_target")]
12587 pub target_trir: f64,
12588 #[serde(default = "default_incident_count")]
12590 pub incident_count: u32,
12591}
12592
12593fn default_trir_target() -> f64 {
12594 2.5
12595}
12596
12597fn default_incident_count() -> u32 {
12598 20
12599}
12600
12601impl Default for SafetySchemaConfig {
12602 fn default() -> Self {
12603 Self {
12604 enabled: true,
12605 target_trir: default_trir_target(),
12606 incident_count: default_incident_count(),
12607 }
12608 }
12609}
12610
12611#[derive(Debug, Clone, Serialize, Deserialize)]
12613pub struct GovernanceSchemaConfig {
12614 #[serde(default = "default_true")]
12616 pub enabled: bool,
12617 #[serde(default = "default_board_size")]
12619 pub board_size: u32,
12620 #[serde(default = "default_independence_target")]
12622 pub independence_target: f64,
12623}
12624
12625fn default_board_size() -> u32 {
12626 11
12627}
12628
12629fn default_independence_target() -> f64 {
12630 0.67
12631}
12632
12633impl Default for GovernanceSchemaConfig {
12634 fn default() -> Self {
12635 Self {
12636 enabled: true,
12637 board_size: default_board_size(),
12638 independence_target: default_independence_target(),
12639 }
12640 }
12641}
12642
12643#[derive(Debug, Clone, Serialize, Deserialize)]
12645pub struct SupplyChainEsgConfig {
12646 #[serde(default = "default_true")]
12648 pub enabled: bool,
12649 #[serde(default = "default_assessment_coverage")]
12651 pub assessment_coverage: f64,
12652 #[serde(default = "default_high_risk_countries")]
12654 pub high_risk_countries: Vec<String>,
12655}
12656
12657fn default_assessment_coverage() -> f64 {
12658 0.80
12659}
12660
12661fn default_high_risk_countries() -> Vec<String> {
12662 vec!["CN".to_string(), "BD".to_string(), "MM".to_string()]
12663}
12664
12665impl Default for SupplyChainEsgConfig {
12666 fn default() -> Self {
12667 Self {
12668 enabled: true,
12669 assessment_coverage: default_assessment_coverage(),
12670 high_risk_countries: default_high_risk_countries(),
12671 }
12672 }
12673}
12674
12675#[derive(Debug, Clone, Serialize, Deserialize)]
12677pub struct EsgReportingConfig {
12678 #[serde(default = "default_true")]
12680 pub enabled: bool,
12681 #[serde(default = "default_esg_frameworks")]
12683 pub frameworks: Vec<String>,
12684 #[serde(default = "default_true")]
12686 pub materiality_assessment: bool,
12687 #[serde(default = "default_materiality_threshold")]
12689 pub impact_threshold: f64,
12690 #[serde(default = "default_materiality_threshold")]
12692 pub financial_threshold: f64,
12693}
12694
12695fn default_esg_frameworks() -> Vec<String> {
12696 vec!["GRI".to_string(), "ESRS".to_string()]
12697}
12698
12699fn default_materiality_threshold() -> f64 {
12700 0.6
12701}
12702
12703impl Default for EsgReportingConfig {
12704 fn default() -> Self {
12705 Self {
12706 enabled: true,
12707 frameworks: default_esg_frameworks(),
12708 materiality_assessment: true,
12709 impact_threshold: default_materiality_threshold(),
12710 financial_threshold: default_materiality_threshold(),
12711 }
12712 }
12713}
12714
12715#[derive(Debug, Clone, Serialize, Deserialize)]
12717pub struct ClimateScenarioConfig {
12718 #[serde(default)]
12720 pub enabled: bool,
12721 #[serde(default = "default_climate_scenarios")]
12723 pub scenarios: Vec<String>,
12724 #[serde(default = "default_time_horizons")]
12726 pub time_horizons: Vec<u32>,
12727}
12728
12729fn default_climate_scenarios() -> Vec<String> {
12730 vec![
12731 "net_zero_2050".to_string(),
12732 "stated_policies".to_string(),
12733 "current_trajectory".to_string(),
12734 ]
12735}
12736
12737fn default_time_horizons() -> Vec<u32> {
12738 vec![5, 10, 30]
12739}
12740
12741impl Default for ClimateScenarioConfig {
12742 fn default() -> Self {
12743 Self {
12744 enabled: false,
12745 scenarios: default_climate_scenarios(),
12746 time_horizons: default_time_horizons(),
12747 }
12748 }
12749}
12750
12751#[derive(Debug, Clone, Serialize, Deserialize, Default)]
12755pub struct ScenariosConfig {
12756 #[serde(default)]
12758 pub enabled: bool,
12759 #[serde(default)]
12761 pub scenarios: Vec<ScenarioSchemaConfig>,
12762 #[serde(default)]
12764 pub causal_model: CausalModelSchemaConfig,
12765 #[serde(default)]
12767 pub defaults: ScenarioDefaultsConfig,
12768 #[serde(default)]
12771 pub generate_counterfactuals: bool,
12772}
12773
12774#[derive(Debug, Clone, Serialize, Deserialize)]
12776pub struct ScenarioSchemaConfig {
12777 pub name: String,
12779 #[serde(default)]
12781 pub description: String,
12782 #[serde(default)]
12784 pub tags: Vec<String>,
12785 pub base: Option<String>,
12787 pub probability_weight: Option<f64>,
12789 #[serde(default)]
12791 pub interventions: Vec<InterventionSchemaConfig>,
12792 #[serde(default)]
12794 pub constraints: ScenarioConstraintsSchemaConfig,
12795 #[serde(default)]
12797 pub output: ScenarioOutputSchemaConfig,
12798 #[serde(default)]
12800 pub metadata: std::collections::HashMap<String, String>,
12801}
12802
12803#[derive(Debug, Clone, Serialize, Deserialize)]
12805pub struct InterventionSchemaConfig {
12806 #[serde(flatten)]
12808 pub intervention_type: serde_json::Value,
12809 #[serde(default)]
12811 pub timing: InterventionTimingSchemaConfig,
12812 pub label: Option<String>,
12814 #[serde(default)]
12816 pub priority: u32,
12817}
12818
12819#[derive(Debug, Clone, Serialize, Deserialize)]
12821pub struct InterventionTimingSchemaConfig {
12822 #[serde(default = "default_start_month")]
12824 pub start_month: u32,
12825 pub duration_months: Option<u32>,
12827 #[serde(default = "default_onset")]
12829 pub onset: String,
12830 pub ramp_months: Option<u32>,
12832}
12833
12834fn default_start_month() -> u32 {
12835 1
12836}
12837
12838fn default_onset() -> String {
12839 "sudden".to_string()
12840}
12841
12842impl Default for InterventionTimingSchemaConfig {
12843 fn default() -> Self {
12844 Self {
12845 start_month: 1,
12846 duration_months: None,
12847 onset: "sudden".to_string(),
12848 ramp_months: None,
12849 }
12850 }
12851}
12852
12853#[derive(Debug, Clone, Serialize, Deserialize)]
12855pub struct ScenarioConstraintsSchemaConfig {
12856 #[serde(default = "default_true")]
12857 pub preserve_accounting_identity: bool,
12858 #[serde(default = "default_true")]
12859 pub preserve_document_chains: bool,
12860 #[serde(default = "default_true")]
12861 pub preserve_period_close: bool,
12862 #[serde(default = "default_true")]
12863 pub preserve_balance_coherence: bool,
12864 #[serde(default)]
12865 pub custom: Vec<CustomConstraintSchemaConfig>,
12866}
12867
12868impl Default for ScenarioConstraintsSchemaConfig {
12869 fn default() -> Self {
12870 Self {
12871 preserve_accounting_identity: true,
12872 preserve_document_chains: true,
12873 preserve_period_close: true,
12874 preserve_balance_coherence: true,
12875 custom: Vec::new(),
12876 }
12877 }
12878}
12879
12880#[derive(Debug, Clone, Serialize, Deserialize)]
12882pub struct CustomConstraintSchemaConfig {
12883 pub config_path: String,
12884 pub min: Option<f64>,
12885 pub max: Option<f64>,
12886 #[serde(default)]
12887 pub description: String,
12888}
12889
12890#[derive(Debug, Clone, Serialize, Deserialize)]
12892pub struct ScenarioOutputSchemaConfig {
12893 #[serde(default = "default_true")]
12894 pub paired: bool,
12895 #[serde(default = "default_diff_formats_schema")]
12896 pub diff_formats: Vec<String>,
12897 #[serde(default)]
12898 pub diff_scope: Vec<String>,
12899}
12900
12901fn default_diff_formats_schema() -> Vec<String> {
12902 vec!["summary".to_string(), "aggregate".to_string()]
12903}
12904
12905impl Default for ScenarioOutputSchemaConfig {
12906 fn default() -> Self {
12907 Self {
12908 paired: true,
12909 diff_formats: default_diff_formats_schema(),
12910 diff_scope: Vec::new(),
12911 }
12912 }
12913}
12914
12915#[derive(Debug, Clone, Serialize, Deserialize)]
12917pub struct CausalModelSchemaConfig {
12918 #[serde(default = "default_causal_preset")]
12920 pub preset: String,
12921 #[serde(default)]
12923 pub nodes: Vec<serde_json::Value>,
12924 #[serde(default)]
12926 pub edges: Vec<serde_json::Value>,
12927}
12928
12929fn default_causal_preset() -> String {
12930 "default".to_string()
12931}
12932
12933impl Default for CausalModelSchemaConfig {
12934 fn default() -> Self {
12935 Self {
12936 preset: "default".to_string(),
12937 nodes: Vec::new(),
12938 edges: Vec::new(),
12939 }
12940 }
12941}
12942
12943#[derive(Debug, Clone, Serialize, Deserialize, Default)]
12945pub struct ScenarioDefaultsConfig {
12946 #[serde(default)]
12947 pub constraints: ScenarioConstraintsSchemaConfig,
12948 #[serde(default)]
12949 pub output: ScenarioOutputSchemaConfig,
12950}
12951
12952#[derive(Debug, Clone, Default, Serialize, Deserialize)]
12985pub struct ComplianceRegulationsConfig {
12986 #[serde(default)]
12988 pub enabled: bool,
12989 #[serde(default)]
12992 pub jurisdictions: Vec<String>,
12993 #[serde(default)]
12996 pub reference_date: Option<String>,
12997 #[serde(default)]
12999 pub standards_selection: StandardsSelectionConfig,
13000 #[serde(default)]
13002 pub audit_procedures: AuditProcedureGenConfig,
13003 #[serde(default)]
13005 pub findings: ComplianceFindingGenConfig,
13006 #[serde(default)]
13008 pub filings: ComplianceFilingGenConfig,
13009 #[serde(default)]
13011 pub graph: ComplianceGraphConfig,
13012 #[serde(default)]
13014 pub output: ComplianceOutputConfig,
13015}
13016
13017#[derive(Debug, Clone, Default, Serialize, Deserialize)]
13019pub struct StandardsSelectionConfig {
13020 #[serde(default)]
13023 pub categories: Vec<String>,
13024 #[serde(default)]
13027 pub include: Vec<String>,
13028 #[serde(default)]
13030 pub exclude: Vec<String>,
13031 #[serde(default)]
13033 pub include_superseded: bool,
13034}
13035
13036#[derive(Debug, Clone, Serialize, Deserialize)]
13038pub struct AuditProcedureGenConfig {
13039 #[serde(default)]
13041 pub enabled: bool,
13042 #[serde(default = "default_procedures_per_standard")]
13044 pub procedures_per_standard: usize,
13045 #[serde(default = "default_sampling_method")]
13047 pub sampling_method: String,
13048 #[serde(default = "default_confidence_level")]
13050 pub confidence_level: f64,
13051 #[serde(default = "default_tolerable_misstatement")]
13053 pub tolerable_misstatement: f64,
13054}
13055
13056fn default_procedures_per_standard() -> usize {
13057 3
13058}
13059
13060fn default_sampling_method() -> String {
13061 "statistical".to_string()
13062}
13063
13064fn default_confidence_level() -> f64 {
13065 0.95
13066}
13067
13068fn default_tolerable_misstatement() -> f64 {
13069 0.05
13070}
13071
13072impl Default for AuditProcedureGenConfig {
13073 fn default() -> Self {
13074 Self {
13075 enabled: false,
13076 procedures_per_standard: default_procedures_per_standard(),
13077 sampling_method: default_sampling_method(),
13078 confidence_level: default_confidence_level(),
13079 tolerable_misstatement: default_tolerable_misstatement(),
13080 }
13081 }
13082}
13083
13084#[derive(Debug, Clone, Serialize, Deserialize)]
13086pub struct ComplianceFindingGenConfig {
13087 #[serde(default)]
13089 pub enabled: bool,
13090 #[serde(default = "default_finding_rate")]
13092 pub finding_rate: f64,
13093 #[serde(default = "default_cr_material_weakness_rate")]
13095 pub material_weakness_rate: f64,
13096 #[serde(default = "default_cr_significant_deficiency_rate")]
13098 pub significant_deficiency_rate: f64,
13099 #[serde(default = "default_true")]
13101 pub generate_remediation: bool,
13102}
13103
13104fn default_finding_rate() -> f64 {
13105 0.05
13106}
13107
13108fn default_cr_material_weakness_rate() -> f64 {
13109 0.02
13110}
13111
13112fn default_cr_significant_deficiency_rate() -> f64 {
13113 0.08
13114}
13115
13116impl Default for ComplianceFindingGenConfig {
13117 fn default() -> Self {
13118 Self {
13119 enabled: false,
13120 finding_rate: default_finding_rate(),
13121 material_weakness_rate: default_cr_material_weakness_rate(),
13122 significant_deficiency_rate: default_cr_significant_deficiency_rate(),
13123 generate_remediation: true,
13124 }
13125 }
13126}
13127
13128#[derive(Debug, Clone, Serialize, Deserialize)]
13130pub struct ComplianceFilingGenConfig {
13131 #[serde(default)]
13133 pub enabled: bool,
13134 #[serde(default)]
13137 pub filing_types: Vec<String>,
13138 #[serde(default = "default_true")]
13140 pub generate_status_progression: bool,
13141}
13142
13143impl Default for ComplianceFilingGenConfig {
13144 fn default() -> Self {
13145 Self {
13146 enabled: false,
13147 filing_types: Vec::new(),
13148 generate_status_progression: true,
13149 }
13150 }
13151}
13152
13153#[derive(Debug, Clone, Serialize, Deserialize)]
13155pub struct ComplianceGraphConfig {
13156 #[serde(default)]
13158 pub enabled: bool,
13159 #[serde(default = "default_true")]
13161 pub include_compliance_nodes: bool,
13162 #[serde(default = "default_true")]
13164 pub include_compliance_edges: bool,
13165 #[serde(default = "default_true")]
13167 pub include_cross_references: bool,
13168 #[serde(default)]
13170 pub include_supersession_edges: bool,
13171 #[serde(default = "default_true")]
13173 pub include_account_links: bool,
13174 #[serde(default = "default_true")]
13176 pub include_control_links: bool,
13177 #[serde(default = "default_true")]
13179 pub include_company_links: bool,
13180}
13181
13182impl Default for ComplianceGraphConfig {
13183 fn default() -> Self {
13184 Self {
13185 enabled: false,
13186 include_compliance_nodes: true,
13187 include_compliance_edges: true,
13188 include_cross_references: true,
13189 include_supersession_edges: false,
13190 include_account_links: true,
13191 include_control_links: true,
13192 include_company_links: true,
13193 }
13194 }
13195}
13196
13197#[derive(Debug, Clone, Serialize, Deserialize)]
13199pub struct ComplianceOutputConfig {
13200 #[serde(default = "default_true")]
13202 pub export_registry: bool,
13203 #[serde(default = "default_true")]
13205 pub export_jurisdictions: bool,
13206 #[serde(default = "default_true")]
13208 pub export_cross_references: bool,
13209 #[serde(default)]
13211 pub export_version_history: bool,
13212}
13213
13214impl Default for ComplianceOutputConfig {
13215 fn default() -> Self {
13216 Self {
13217 export_registry: true,
13218 export_jurisdictions: true,
13219 export_cross_references: true,
13220 export_version_history: false,
13221 }
13222 }
13223}
13224
13225#[cfg(test)]
13226#[allow(clippy::unwrap_used)]
13227mod tests {
13228 use super::*;
13229 use crate::presets::demo_preset;
13230
13231 #[test]
13236 fn test_config_yaml_roundtrip() {
13237 let config = demo_preset();
13238 let yaml = serde_yaml::to_string(&config).expect("Failed to serialize to YAML");
13239 let deserialized: GeneratorConfig =
13240 serde_yaml::from_str(&yaml).expect("Failed to deserialize from YAML");
13241
13242 assert_eq!(
13243 config.global.period_months,
13244 deserialized.global.period_months
13245 );
13246 assert_eq!(config.global.industry, deserialized.global.industry);
13247 assert_eq!(config.companies.len(), deserialized.companies.len());
13248 assert_eq!(config.companies[0].code, deserialized.companies[0].code);
13249 }
13250
13251 #[test]
13252 fn test_config_json_roundtrip() {
13253 let mut config = demo_preset();
13255 config.master_data.employees.approval_limits.executive = 1e12;
13257
13258 let json = serde_json::to_string(&config).expect("Failed to serialize to JSON");
13259 let deserialized: GeneratorConfig =
13260 serde_json::from_str(&json).expect("Failed to deserialize from JSON");
13261
13262 assert_eq!(
13263 config.global.period_months,
13264 deserialized.global.period_months
13265 );
13266 assert_eq!(config.global.industry, deserialized.global.industry);
13267 assert_eq!(config.companies.len(), deserialized.companies.len());
13268 }
13269
13270 #[test]
13271 fn test_transaction_volume_serialization() {
13272 let volumes = vec![
13274 (TransactionVolume::TenK, "ten_k"),
13275 (TransactionVolume::HundredK, "hundred_k"),
13276 (TransactionVolume::OneM, "one_m"),
13277 (TransactionVolume::TenM, "ten_m"),
13278 (TransactionVolume::HundredM, "hundred_m"),
13279 ];
13280
13281 for (volume, expected_key) in volumes {
13282 let json = serde_json::to_string(&volume).expect("Failed to serialize");
13283 assert!(
13284 json.contains(expected_key),
13285 "Expected {} in JSON: {}",
13286 expected_key,
13287 json
13288 );
13289 }
13290 }
13291
13292 #[test]
13293 fn test_transaction_volume_custom_serialization() {
13294 let volume = TransactionVolume::Custom(12345);
13295 let json = serde_json::to_string(&volume).expect("Failed to serialize");
13296 let deserialized: TransactionVolume =
13297 serde_json::from_str(&json).expect("Failed to deserialize");
13298 assert_eq!(deserialized.count(), 12345);
13299 }
13300
13301 #[test]
13302 fn test_output_mode_serialization() {
13303 let modes = vec![
13304 OutputMode::Streaming,
13305 OutputMode::FlatFile,
13306 OutputMode::Both,
13307 ];
13308
13309 for mode in modes {
13310 let json = serde_json::to_string(&mode).expect("Failed to serialize");
13311 let deserialized: OutputMode =
13312 serde_json::from_str(&json).expect("Failed to deserialize");
13313 assert!(format!("{:?}", mode) == format!("{:?}", deserialized));
13314 }
13315 }
13316
13317 #[test]
13318 fn test_file_format_serialization() {
13319 let formats = vec![
13320 FileFormat::Csv,
13321 FileFormat::Parquet,
13322 FileFormat::Json,
13323 FileFormat::JsonLines,
13324 ];
13325
13326 for format in formats {
13327 let json = serde_json::to_string(&format).expect("Failed to serialize");
13328 let deserialized: FileFormat =
13329 serde_json::from_str(&json).expect("Failed to deserialize");
13330 assert!(format!("{:?}", format) == format!("{:?}", deserialized));
13331 }
13332 }
13333
13334 #[test]
13335 fn test_compression_algorithm_serialization() {
13336 let algos = vec![
13337 CompressionAlgorithm::Gzip,
13338 CompressionAlgorithm::Zstd,
13339 CompressionAlgorithm::Lz4,
13340 CompressionAlgorithm::Snappy,
13341 ];
13342
13343 for algo in algos {
13344 let json = serde_json::to_string(&algo).expect("Failed to serialize");
13345 let deserialized: CompressionAlgorithm =
13346 serde_json::from_str(&json).expect("Failed to deserialize");
13347 assert!(format!("{:?}", algo) == format!("{:?}", deserialized));
13348 }
13349 }
13350
13351 #[test]
13352 fn test_transfer_pricing_method_serialization() {
13353 let methods = vec![
13354 TransferPricingMethod::CostPlus,
13355 TransferPricingMethod::ComparableUncontrolled,
13356 TransferPricingMethod::ResalePrice,
13357 TransferPricingMethod::TransactionalNetMargin,
13358 TransferPricingMethod::ProfitSplit,
13359 ];
13360
13361 for method in methods {
13362 let json = serde_json::to_string(&method).expect("Failed to serialize");
13363 let deserialized: TransferPricingMethod =
13364 serde_json::from_str(&json).expect("Failed to deserialize");
13365 assert!(format!("{:?}", method) == format!("{:?}", deserialized));
13366 }
13367 }
13368
13369 #[test]
13370 fn test_benford_exemption_serialization() {
13371 let exemptions = vec![
13372 BenfordExemption::Recurring,
13373 BenfordExemption::Payroll,
13374 BenfordExemption::FixedFees,
13375 BenfordExemption::RoundAmounts,
13376 ];
13377
13378 for exemption in exemptions {
13379 let json = serde_json::to_string(&exemption).expect("Failed to serialize");
13380 let deserialized: BenfordExemption =
13381 serde_json::from_str(&json).expect("Failed to deserialize");
13382 assert!(format!("{:?}", exemption) == format!("{:?}", deserialized));
13383 }
13384 }
13385
13386 #[test]
13391 fn test_global_config_defaults() {
13392 let yaml = r#"
13393 industry: manufacturing
13394 start_date: "2024-01-01"
13395 period_months: 6
13396 "#;
13397 let config: GlobalConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13398 assert_eq!(config.group_currency, "USD");
13399 assert!(config.parallel);
13400 assert_eq!(config.worker_threads, 0);
13401 assert_eq!(config.memory_limit_mb, 0);
13402 }
13403
13404 #[test]
13405 fn test_fraud_config_defaults() {
13406 let config = FraudConfig::default();
13407 assert!(!config.enabled);
13408 assert_eq!(config.fraud_rate, 0.005);
13409 assert!(!config.clustering_enabled);
13410 }
13411
13412 #[test]
13413 fn test_internal_controls_config_defaults() {
13414 let config = InternalControlsConfig::default();
13415 assert!(!config.enabled);
13416 assert_eq!(config.exception_rate, 0.02);
13417 assert_eq!(config.sod_violation_rate, 0.01);
13418 assert!(config.export_control_master_data);
13419 assert_eq!(config.sox_materiality_threshold, 10000.0);
13420 assert!(config.coso_enabled);
13422 assert!(!config.include_entity_level_controls);
13423 assert_eq!(config.target_maturity_level, "mixed");
13424 }
13425
13426 #[test]
13427 fn test_output_config_defaults() {
13428 let config = OutputConfig::default();
13429 assert!(matches!(config.mode, OutputMode::FlatFile));
13430 assert_eq!(config.formats, vec![FileFormat::Parquet]);
13431 assert!(config.compression.enabled);
13432 assert!(matches!(
13433 config.compression.algorithm,
13434 CompressionAlgorithm::Zstd
13435 ));
13436 assert!(config.include_acdoca);
13437 assert!(!config.include_bseg);
13438 assert!(config.partition_by_period);
13439 assert!(!config.partition_by_company);
13440 }
13441
13442 #[test]
13443 fn test_approval_config_defaults() {
13444 let config = ApprovalConfig::default();
13445 assert!(!config.enabled);
13446 assert_eq!(config.auto_approve_threshold, 1000.0);
13447 assert_eq!(config.rejection_rate, 0.02);
13448 assert_eq!(config.revision_rate, 0.05);
13449 assert_eq!(config.average_approval_delay_hours, 4.0);
13450 assert_eq!(config.thresholds.len(), 4);
13451 }
13452
13453 #[test]
13454 fn test_p2p_flow_config_defaults() {
13455 let config = P2PFlowConfig::default();
13456 assert!(config.enabled);
13457 assert_eq!(config.three_way_match_rate, 0.95);
13458 assert_eq!(config.partial_delivery_rate, 0.15);
13459 assert_eq!(config.average_po_to_gr_days, 14);
13460 }
13461
13462 #[test]
13463 fn test_o2c_flow_config_defaults() {
13464 let config = O2CFlowConfig::default();
13465 assert!(config.enabled);
13466 assert_eq!(config.credit_check_failure_rate, 0.02);
13467 assert_eq!(config.return_rate, 0.03);
13468 assert_eq!(config.bad_debt_rate, 0.01);
13469 }
13470
13471 #[test]
13472 fn test_balance_config_defaults() {
13473 let config = BalanceConfig::default();
13474 assert!(!config.generate_opening_balances);
13475 assert!(config.generate_trial_balances);
13476 assert_eq!(config.target_gross_margin, 0.35);
13477 assert!(config.validate_balance_equation);
13478 assert!(config.reconcile_subledgers);
13479 }
13480
13481 #[test]
13486 fn test_partial_config_with_defaults() {
13487 let yaml = r#"
13489 global:
13490 industry: manufacturing
13491 start_date: "2024-01-01"
13492 period_months: 3
13493 companies:
13494 - code: "TEST"
13495 name: "Test Company"
13496 currency: "USD"
13497 country: "US"
13498 annual_transaction_volume: ten_k
13499 chart_of_accounts:
13500 complexity: small
13501 output:
13502 output_directory: "./output"
13503 "#;
13504
13505 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13506 assert_eq!(config.global.period_months, 3);
13507 assert_eq!(config.companies.len(), 1);
13508 assert!(!config.fraud.enabled); assert!(!config.internal_controls.enabled); }
13511
13512 #[test]
13513 fn test_config_with_fraud_enabled() {
13514 let yaml = r#"
13515 global:
13516 industry: retail
13517 start_date: "2024-01-01"
13518 period_months: 12
13519 companies:
13520 - code: "RETAIL"
13521 name: "Retail Co"
13522 currency: "USD"
13523 country: "US"
13524 annual_transaction_volume: hundred_k
13525 chart_of_accounts:
13526 complexity: medium
13527 output:
13528 output_directory: "./output"
13529 fraud:
13530 enabled: true
13531 fraud_rate: 0.05
13532 clustering_enabled: true
13533 "#;
13534
13535 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13536 assert!(config.fraud.enabled);
13537 assert_eq!(config.fraud.fraud_rate, 0.05);
13538 assert!(config.fraud.clustering_enabled);
13539 }
13540
13541 #[test]
13542 fn test_config_with_multiple_companies() {
13543 let yaml = r#"
13544 global:
13545 industry: manufacturing
13546 start_date: "2024-01-01"
13547 period_months: 6
13548 companies:
13549 - code: "HQ"
13550 name: "Headquarters"
13551 currency: "USD"
13552 country: "US"
13553 annual_transaction_volume: hundred_k
13554 volume_weight: 1.0
13555 - code: "EU"
13556 name: "European Subsidiary"
13557 currency: "EUR"
13558 country: "DE"
13559 annual_transaction_volume: hundred_k
13560 volume_weight: 0.5
13561 - code: "APAC"
13562 name: "Asia Pacific"
13563 currency: "JPY"
13564 country: "JP"
13565 annual_transaction_volume: ten_k
13566 volume_weight: 0.3
13567 chart_of_accounts:
13568 complexity: large
13569 output:
13570 output_directory: "./output"
13571 "#;
13572
13573 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13574 assert_eq!(config.companies.len(), 3);
13575 assert_eq!(config.companies[0].code, "HQ");
13576 assert_eq!(config.companies[1].currency, "EUR");
13577 assert_eq!(config.companies[2].volume_weight, 0.3);
13578 }
13579
13580 #[test]
13581 fn test_intercompany_config() {
13582 let yaml = r#"
13583 enabled: true
13584 ic_transaction_rate: 0.20
13585 transfer_pricing_method: cost_plus
13586 markup_percent: 0.08
13587 generate_matched_pairs: true
13588 generate_eliminations: true
13589 "#;
13590
13591 let config: IntercompanyConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13592 assert!(config.enabled);
13593 assert_eq!(config.ic_transaction_rate, 0.20);
13594 assert!(matches!(
13595 config.transfer_pricing_method,
13596 TransferPricingMethod::CostPlus
13597 ));
13598 assert_eq!(config.markup_percent, 0.08);
13599 assert!(config.generate_eliminations);
13600 }
13601
13602 #[test]
13607 fn test_company_config_defaults() {
13608 let yaml = r#"
13609 code: "TEST"
13610 name: "Test Company"
13611 currency: "USD"
13612 country: "US"
13613 annual_transaction_volume: ten_k
13614 "#;
13615
13616 let config: CompanyConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13617 assert_eq!(config.fiscal_year_variant, "K4"); assert_eq!(config.volume_weight, 1.0); }
13620
13621 #[test]
13626 fn test_coa_config_defaults() {
13627 let yaml = r#"
13628 complexity: medium
13629 "#;
13630
13631 let config: ChartOfAccountsConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13632 assert!(config.industry_specific); assert!(config.custom_accounts.is_none());
13634 assert_eq!(config.min_hierarchy_depth, 2); assert_eq!(config.max_hierarchy_depth, 5); }
13637
13638 #[test]
13643 fn test_accounting_standards_config_defaults() {
13644 let config = AccountingStandardsConfig::default();
13645 assert!(!config.enabled);
13646 assert!(config.framework.is_none());
13647 assert!(!config.revenue_recognition.enabled);
13648 assert!(!config.leases.enabled);
13649 assert!(!config.fair_value.enabled);
13650 assert!(!config.impairment.enabled);
13651 assert!(!config.generate_differences);
13652 }
13653
13654 #[test]
13655 fn test_accounting_standards_config_yaml() {
13656 let yaml = r#"
13657 enabled: true
13658 framework: ifrs
13659 revenue_recognition:
13660 enabled: true
13661 generate_contracts: true
13662 avg_obligations_per_contract: 2.5
13663 variable_consideration_rate: 0.20
13664 over_time_recognition_rate: 0.35
13665 contract_count: 150
13666 leases:
13667 enabled: true
13668 lease_count: 75
13669 finance_lease_percent: 0.25
13670 avg_lease_term_months: 48
13671 generate_differences: true
13672 "#;
13673
13674 let config: AccountingStandardsConfig =
13675 serde_yaml::from_str(yaml).expect("Failed to parse");
13676 assert!(config.enabled);
13677 assert!(matches!(
13678 config.framework,
13679 Some(AccountingFrameworkConfig::Ifrs)
13680 ));
13681 assert!(config.revenue_recognition.enabled);
13682 assert_eq!(config.revenue_recognition.contract_count, 150);
13683 assert_eq!(config.revenue_recognition.avg_obligations_per_contract, 2.5);
13684 assert!(config.leases.enabled);
13685 assert_eq!(config.leases.lease_count, 75);
13686 assert_eq!(config.leases.finance_lease_percent, 0.25);
13687 assert!(config.generate_differences);
13688 }
13689
13690 #[test]
13691 fn test_accounting_framework_serialization() {
13692 let frameworks = [
13693 AccountingFrameworkConfig::UsGaap,
13694 AccountingFrameworkConfig::Ifrs,
13695 AccountingFrameworkConfig::DualReporting,
13696 AccountingFrameworkConfig::FrenchGaap,
13697 AccountingFrameworkConfig::GermanGaap,
13698 ];
13699
13700 for framework in frameworks {
13701 let json = serde_json::to_string(&framework).expect("Failed to serialize");
13702 let deserialized: AccountingFrameworkConfig =
13703 serde_json::from_str(&json).expect("Failed to deserialize");
13704 assert!(format!("{:?}", framework) == format!("{:?}", deserialized));
13705 }
13706 }
13707
13708 #[test]
13709 fn test_revenue_recognition_config_defaults() {
13710 let config = RevenueRecognitionConfig::default();
13711 assert!(!config.enabled);
13712 assert!(config.generate_contracts);
13713 assert_eq!(config.avg_obligations_per_contract, 2.0);
13714 assert_eq!(config.variable_consideration_rate, 0.15);
13715 assert_eq!(config.over_time_recognition_rate, 0.30);
13716 assert_eq!(config.contract_count, 100);
13717 }
13718
13719 #[test]
13720 fn test_lease_accounting_config_defaults() {
13721 let config = LeaseAccountingConfig::default();
13722 assert!(!config.enabled);
13723 assert_eq!(config.lease_count, 50);
13724 assert_eq!(config.finance_lease_percent, 0.30);
13725 assert_eq!(config.avg_lease_term_months, 60);
13726 assert!(config.generate_amortization);
13727 assert_eq!(config.real_estate_percent, 0.40);
13728 }
13729
13730 #[test]
13731 fn test_fair_value_config_defaults() {
13732 let config = FairValueConfig::default();
13733 assert!(!config.enabled);
13734 assert_eq!(config.measurement_count, 25);
13735 assert_eq!(config.level1_percent, 0.40);
13736 assert_eq!(config.level2_percent, 0.35);
13737 assert_eq!(config.level3_percent, 0.25);
13738 assert!(!config.include_sensitivity_analysis);
13739 }
13740
13741 #[test]
13742 fn test_impairment_config_defaults() {
13743 let config = ImpairmentConfig::default();
13744 assert!(!config.enabled);
13745 assert_eq!(config.test_count, 15);
13746 assert_eq!(config.impairment_rate, 0.10);
13747 assert!(config.generate_projections);
13748 assert!(!config.include_goodwill);
13749 }
13750
13751 #[test]
13756 fn test_audit_standards_config_defaults() {
13757 let config = AuditStandardsConfig::default();
13758 assert!(!config.enabled);
13759 assert!(!config.isa_compliance.enabled);
13760 assert!(!config.analytical_procedures.enabled);
13761 assert!(!config.confirmations.enabled);
13762 assert!(!config.opinion.enabled);
13763 assert!(!config.generate_audit_trail);
13764 assert!(!config.sox.enabled);
13765 assert!(!config.pcaob.enabled);
13766 }
13767
13768 #[test]
13769 fn test_audit_standards_config_yaml() {
13770 let yaml = r#"
13771 enabled: true
13772 isa_compliance:
13773 enabled: true
13774 compliance_level: comprehensive
13775 generate_isa_mappings: true
13776 include_pcaob: true
13777 framework: dual
13778 analytical_procedures:
13779 enabled: true
13780 procedures_per_account: 5
13781 variance_probability: 0.25
13782 confirmations:
13783 enabled: true
13784 confirmation_count: 75
13785 positive_response_rate: 0.90
13786 exception_rate: 0.08
13787 opinion:
13788 enabled: true
13789 generate_kam: true
13790 average_kam_count: 4
13791 sox:
13792 enabled: true
13793 generate_302_certifications: true
13794 generate_404_assessments: true
13795 material_weakness_rate: 0.03
13796 pcaob:
13797 enabled: true
13798 is_pcaob_audit: true
13799 include_icfr_opinion: true
13800 generate_audit_trail: true
13801 "#;
13802
13803 let config: AuditStandardsConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13804 assert!(config.enabled);
13805 assert!(config.isa_compliance.enabled);
13806 assert_eq!(config.isa_compliance.compliance_level, "comprehensive");
13807 assert!(config.isa_compliance.include_pcaob);
13808 assert_eq!(config.isa_compliance.framework, "dual");
13809 assert!(config.analytical_procedures.enabled);
13810 assert_eq!(config.analytical_procedures.procedures_per_account, 5);
13811 assert!(config.confirmations.enabled);
13812 assert_eq!(config.confirmations.confirmation_count, 75);
13813 assert!(config.opinion.enabled);
13814 assert_eq!(config.opinion.average_kam_count, 4);
13815 assert!(config.sox.enabled);
13816 assert!(config.sox.generate_302_certifications);
13817 assert_eq!(config.sox.material_weakness_rate, 0.03);
13818 assert!(config.pcaob.enabled);
13819 assert!(config.pcaob.is_pcaob_audit);
13820 assert!(config.pcaob.include_icfr_opinion);
13821 assert!(config.generate_audit_trail);
13822 }
13823
13824 #[test]
13825 fn test_isa_compliance_config_defaults() {
13826 let config = IsaComplianceConfig::default();
13827 assert!(!config.enabled);
13828 assert_eq!(config.compliance_level, "standard");
13829 assert!(config.generate_isa_mappings);
13830 assert!(config.generate_coverage_summary);
13831 assert!(!config.include_pcaob);
13832 assert_eq!(config.framework, "isa");
13833 }
13834
13835 #[test]
13836 fn test_sox_compliance_config_defaults() {
13837 let config = SoxComplianceConfig::default();
13838 assert!(!config.enabled);
13839 assert!(config.generate_302_certifications);
13840 assert!(config.generate_404_assessments);
13841 assert_eq!(config.materiality_threshold, 10000.0);
13842 assert_eq!(config.material_weakness_rate, 0.02);
13843 assert_eq!(config.significant_deficiency_rate, 0.08);
13844 }
13845
13846 #[test]
13847 fn test_pcaob_config_defaults() {
13848 let config = PcaobConfig::default();
13849 assert!(!config.enabled);
13850 assert!(!config.is_pcaob_audit);
13851 assert!(config.generate_cam);
13852 assert!(!config.include_icfr_opinion);
13853 assert!(!config.generate_standard_mappings);
13854 }
13855
13856 #[test]
13857 fn test_config_with_standards_enabled() {
13858 let yaml = r#"
13859 global:
13860 industry: financial_services
13861 start_date: "2024-01-01"
13862 period_months: 12
13863 companies:
13864 - code: "BANK"
13865 name: "Test Bank"
13866 currency: "USD"
13867 country: "US"
13868 annual_transaction_volume: hundred_k
13869 chart_of_accounts:
13870 complexity: large
13871 output:
13872 output_directory: "./output"
13873 accounting_standards:
13874 enabled: true
13875 framework: us_gaap
13876 revenue_recognition:
13877 enabled: true
13878 leases:
13879 enabled: true
13880 audit_standards:
13881 enabled: true
13882 isa_compliance:
13883 enabled: true
13884 sox:
13885 enabled: true
13886 "#;
13887
13888 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13889 assert!(config.accounting_standards.enabled);
13890 assert!(matches!(
13891 config.accounting_standards.framework,
13892 Some(AccountingFrameworkConfig::UsGaap)
13893 ));
13894 assert!(config.accounting_standards.revenue_recognition.enabled);
13895 assert!(config.accounting_standards.leases.enabled);
13896 assert!(config.audit_standards.enabled);
13897 assert!(config.audit_standards.isa_compliance.enabled);
13898 assert!(config.audit_standards.sox.enabled);
13899 }
13900
13901 #[test]
13906 fn test_industry_specific_config_defaults() {
13907 let config = IndustrySpecificConfig::default();
13908 assert!(!config.enabled);
13909 assert!(!config.manufacturing.enabled);
13910 assert!(!config.retail.enabled);
13911 assert!(!config.healthcare.enabled);
13912 assert!(!config.technology.enabled);
13913 assert!(!config.financial_services.enabled);
13914 assert!(!config.professional_services.enabled);
13915 }
13916
13917 #[test]
13918 fn test_manufacturing_config_defaults() {
13919 let config = ManufacturingConfig::default();
13920 assert!(!config.enabled);
13921 assert_eq!(config.bom_depth, 4);
13922 assert!(!config.just_in_time);
13923 assert_eq!(config.supplier_tiers, 2);
13924 assert_eq!(config.target_yield_rate, 0.97);
13925 assert_eq!(config.scrap_alert_threshold, 0.03);
13926 }
13927
13928 #[test]
13929 fn test_retail_config_defaults() {
13930 let config = RetailConfig::default();
13931 assert!(!config.enabled);
13932 assert_eq!(config.avg_daily_transactions, 500);
13933 assert!(config.loss_prevention);
13934 assert_eq!(config.shrinkage_rate, 0.015);
13935 }
13936
13937 #[test]
13938 fn test_healthcare_config_defaults() {
13939 let config = HealthcareConfig::default();
13940 assert!(!config.enabled);
13941 assert_eq!(config.facility_type, "hospital");
13942 assert_eq!(config.avg_daily_encounters, 150);
13943 assert!(config.compliance.hipaa);
13944 assert!(config.compliance.stark_law);
13945 assert!(config.coding_systems.icd10);
13946 assert!(config.coding_systems.cpt);
13947 }
13948
13949 #[test]
13950 fn test_technology_config_defaults() {
13951 let config = TechnologyConfig::default();
13952 assert!(!config.enabled);
13953 assert_eq!(config.revenue_model, "saas");
13954 assert_eq!(config.subscription_revenue_pct, 0.60);
13955 assert!(config.rd_capitalization.enabled);
13956 }
13957
13958 #[test]
13959 fn test_config_with_industry_specific() {
13960 let yaml = r#"
13961 global:
13962 industry: healthcare
13963 start_date: "2024-01-01"
13964 period_months: 12
13965 companies:
13966 - code: "HOSP"
13967 name: "Test Hospital"
13968 currency: "USD"
13969 country: "US"
13970 annual_transaction_volume: hundred_k
13971 chart_of_accounts:
13972 complexity: medium
13973 output:
13974 output_directory: "./output"
13975 industry_specific:
13976 enabled: true
13977 healthcare:
13978 enabled: true
13979 facility_type: hospital
13980 payer_mix:
13981 medicare: 0.45
13982 medicaid: 0.15
13983 commercial: 0.35
13984 self_pay: 0.05
13985 coding_systems:
13986 icd10: true
13987 cpt: true
13988 drg: true
13989 compliance:
13990 hipaa: true
13991 stark_law: true
13992 anomaly_rates:
13993 upcoding: 0.03
13994 unbundling: 0.02
13995 "#;
13996
13997 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13998 assert!(config.industry_specific.enabled);
13999 assert!(config.industry_specific.healthcare.enabled);
14000 assert_eq!(
14001 config.industry_specific.healthcare.facility_type,
14002 "hospital"
14003 );
14004 assert_eq!(config.industry_specific.healthcare.payer_mix.medicare, 0.45);
14005 assert_eq!(config.industry_specific.healthcare.payer_mix.self_pay, 0.05);
14006 assert!(config.industry_specific.healthcare.coding_systems.icd10);
14007 assert!(config.industry_specific.healthcare.compliance.hipaa);
14008 assert_eq!(
14009 config.industry_specific.healthcare.anomaly_rates.upcoding,
14010 0.03
14011 );
14012 }
14013
14014 #[test]
14015 fn test_config_with_manufacturing_specific() {
14016 let yaml = r#"
14017 global:
14018 industry: manufacturing
14019 start_date: "2024-01-01"
14020 period_months: 12
14021 companies:
14022 - code: "MFG"
14023 name: "Test Manufacturing"
14024 currency: "USD"
14025 country: "US"
14026 annual_transaction_volume: hundred_k
14027 chart_of_accounts:
14028 complexity: medium
14029 output:
14030 output_directory: "./output"
14031 industry_specific:
14032 enabled: true
14033 manufacturing:
14034 enabled: true
14035 bom_depth: 5
14036 just_in_time: true
14037 supplier_tiers: 3
14038 target_yield_rate: 0.98
14039 anomaly_rates:
14040 yield_manipulation: 0.02
14041 phantom_production: 0.01
14042 "#;
14043
14044 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
14045 assert!(config.industry_specific.enabled);
14046 assert!(config.industry_specific.manufacturing.enabled);
14047 assert_eq!(config.industry_specific.manufacturing.bom_depth, 5);
14048 assert!(config.industry_specific.manufacturing.just_in_time);
14049 assert_eq!(config.industry_specific.manufacturing.supplier_tiers, 3);
14050 assert_eq!(
14051 config.industry_specific.manufacturing.target_yield_rate,
14052 0.98
14053 );
14054 assert_eq!(
14055 config
14056 .industry_specific
14057 .manufacturing
14058 .anomaly_rates
14059 .yield_manipulation,
14060 0.02
14061 );
14062 }
14063
14064 #[test]
14069 fn test_tax_config_defaults() {
14070 let tax = TaxConfig::default();
14071 assert!(!tax.enabled);
14072 assert!(tax.jurisdictions.countries.is_empty());
14073 assert!(!tax.jurisdictions.include_subnational);
14074 assert!(!tax.vat_gst.enabled);
14075 assert!(tax.vat_gst.standard_rates.is_empty());
14076 assert!(tax.vat_gst.reduced_rates.is_empty());
14077 assert!(tax.vat_gst.exempt_categories.is_empty());
14078 assert!(tax.vat_gst.reverse_charge);
14079 assert!(!tax.sales_tax.enabled);
14080 assert!(tax.sales_tax.nexus_states.is_empty());
14081 assert!(!tax.withholding.enabled);
14082 assert!(tax.withholding.treaty_network);
14083 assert_eq!(tax.withholding.default_rate, 0.30);
14084 assert_eq!(tax.withholding.treaty_reduced_rate, 0.15);
14085 assert!(tax.provisions.enabled);
14086 assert_eq!(tax.provisions.statutory_rate, 0.21);
14087 assert!(tax.provisions.uncertain_positions);
14088 assert!(!tax.payroll_tax.enabled);
14089 assert_eq!(tax.anomaly_rate, 0.03);
14090 }
14091
14092 #[test]
14093 fn test_tax_config_from_yaml() {
14094 let yaml = r#"
14095 global:
14096 seed: 42
14097 start_date: "2024-01-01"
14098 period_months: 12
14099 industry: retail
14100 companies:
14101 - code: C001
14102 name: Test Corp
14103 currency: USD
14104 country: US
14105 annual_transaction_volume: ten_k
14106 chart_of_accounts:
14107 complexity: small
14108 output:
14109 output_directory: ./output
14110 tax:
14111 enabled: true
14112 anomaly_rate: 0.05
14113 jurisdictions:
14114 countries: ["US", "DE", "GB"]
14115 include_subnational: true
14116 vat_gst:
14117 enabled: true
14118 standard_rates:
14119 DE: 0.19
14120 GB: 0.20
14121 reduced_rates:
14122 DE: 0.07
14123 GB: 0.05
14124 exempt_categories:
14125 - financial_services
14126 - healthcare
14127 reverse_charge: false
14128 sales_tax:
14129 enabled: true
14130 nexus_states: ["CA", "NY", "TX"]
14131 withholding:
14132 enabled: true
14133 treaty_network: false
14134 default_rate: 0.25
14135 treaty_reduced_rate: 0.10
14136 provisions:
14137 enabled: false
14138 statutory_rate: 0.28
14139 uncertain_positions: false
14140 payroll_tax:
14141 enabled: true
14142 "#;
14143
14144 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
14145 assert!(config.tax.enabled);
14146 assert_eq!(config.tax.anomaly_rate, 0.05);
14147
14148 assert_eq!(config.tax.jurisdictions.countries.len(), 3);
14150 assert!(config
14151 .tax
14152 .jurisdictions
14153 .countries
14154 .contains(&"DE".to_string()));
14155 assert!(config.tax.jurisdictions.include_subnational);
14156
14157 assert!(config.tax.vat_gst.enabled);
14159 assert_eq!(config.tax.vat_gst.standard_rates.get("DE"), Some(&0.19));
14160 assert_eq!(config.tax.vat_gst.standard_rates.get("GB"), Some(&0.20));
14161 assert_eq!(config.tax.vat_gst.reduced_rates.get("DE"), Some(&0.07));
14162 assert_eq!(config.tax.vat_gst.exempt_categories.len(), 2);
14163 assert!(!config.tax.vat_gst.reverse_charge);
14164
14165 assert!(config.tax.sales_tax.enabled);
14167 assert_eq!(config.tax.sales_tax.nexus_states.len(), 3);
14168 assert!(config
14169 .tax
14170 .sales_tax
14171 .nexus_states
14172 .contains(&"CA".to_string()));
14173
14174 assert!(config.tax.withholding.enabled);
14176 assert!(!config.tax.withholding.treaty_network);
14177 assert_eq!(config.tax.withholding.default_rate, 0.25);
14178 assert_eq!(config.tax.withholding.treaty_reduced_rate, 0.10);
14179
14180 assert!(!config.tax.provisions.enabled);
14182 assert_eq!(config.tax.provisions.statutory_rate, 0.28);
14183 assert!(!config.tax.provisions.uncertain_positions);
14184
14185 assert!(config.tax.payroll_tax.enabled);
14187 }
14188
14189 #[test]
14190 fn test_generator_config_with_tax_default() {
14191 let yaml = r#"
14192 global:
14193 seed: 42
14194 start_date: "2024-01-01"
14195 period_months: 12
14196 industry: retail
14197 companies:
14198 - code: C001
14199 name: Test Corp
14200 currency: USD
14201 country: US
14202 annual_transaction_volume: ten_k
14203 chart_of_accounts:
14204 complexity: small
14205 output:
14206 output_directory: ./output
14207 "#;
14208
14209 let config: GeneratorConfig =
14210 serde_yaml::from_str(yaml).expect("Failed to parse config without tax section");
14211 assert!(!config.tax.enabled);
14213 assert!(config.tax.jurisdictions.countries.is_empty());
14214 assert_eq!(config.tax.anomaly_rate, 0.03);
14215 assert!(config.tax.provisions.enabled); assert_eq!(config.tax.provisions.statutory_rate, 0.21);
14217 }
14218
14219 #[test]
14224 fn test_session_config_default_disabled() {
14225 let yaml = "{}";
14226 let config: SessionSchemaConfig =
14227 serde_yaml::from_str(yaml).expect("Failed to parse empty session config");
14228 assert!(!config.enabled);
14229 assert!(config.checkpoint_path.is_none());
14230 assert!(config.per_period_output);
14231 assert!(config.consolidated_output);
14232 }
14233
14234 #[test]
14235 fn test_config_backward_compatible_without_session() {
14236 let yaml = r#"
14237 global:
14238 seed: 42
14239 start_date: "2024-01-01"
14240 period_months: 12
14241 industry: retail
14242 companies:
14243 - code: C001
14244 name: Test Corp
14245 currency: USD
14246 country: US
14247 annual_transaction_volume: ten_k
14248 chart_of_accounts:
14249 complexity: small
14250 output:
14251 output_directory: ./output
14252 "#;
14253
14254 let config: GeneratorConfig =
14255 serde_yaml::from_str(yaml).expect("Failed to parse config without session");
14256 assert!(!config.session.enabled);
14258 assert!(config.session.per_period_output);
14259 assert!(config.session.consolidated_output);
14260 assert!(config.global.fiscal_year_months.is_none());
14262 }
14263
14264 #[test]
14265 fn test_fiscal_year_months_parsed() {
14266 let yaml = r#"
14267 global:
14268 seed: 42
14269 start_date: "2024-01-01"
14270 period_months: 24
14271 industry: retail
14272 fiscal_year_months: 12
14273 companies:
14274 - code: C001
14275 name: Test Corp
14276 currency: USD
14277 country: US
14278 annual_transaction_volume: ten_k
14279 chart_of_accounts:
14280 complexity: small
14281 output:
14282 output_directory: ./output
14283 session:
14284 enabled: true
14285 checkpoint_path: /tmp/checkpoints
14286 per_period_output: true
14287 consolidated_output: false
14288 "#;
14289
14290 let config: GeneratorConfig =
14291 serde_yaml::from_str(yaml).expect("Failed to parse config with fiscal_year_months");
14292 assert_eq!(config.global.fiscal_year_months, Some(12));
14293 assert!(config.session.enabled);
14294 assert_eq!(
14295 config.session.checkpoint_path,
14296 Some("/tmp/checkpoints".to_string())
14297 );
14298 assert!(config.session.per_period_output);
14299 assert!(!config.session.consolidated_output);
14300 }
14301}