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, alias = "exportLayout")]
1596 pub export_layout: ExportLayout,
1597}
1598
1599fn default_formats() -> Vec<FileFormat> {
1600 vec![FileFormat::Parquet]
1601}
1602fn default_batch_size() -> usize {
1603 100_000
1604}
1605
1606impl Default for OutputConfig {
1607 fn default() -> Self {
1608 Self {
1609 mode: OutputMode::FlatFile,
1610 output_directory: PathBuf::from("./output"),
1611 formats: default_formats(),
1612 compression: CompressionConfig::default(),
1613 batch_size: default_batch_size(),
1614 include_acdoca: true,
1615 include_bseg: false,
1616 partition_by_period: true,
1617 partition_by_company: false,
1618 numeric_mode: NumericMode::default(),
1619 export_layout: ExportLayout::default(),
1620 }
1621 }
1622}
1623
1624#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
1626#[serde(rename_all = "snake_case")]
1627pub enum NumericMode {
1628 #[default]
1630 String,
1631 Native,
1633}
1634
1635#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
1637#[serde(rename_all = "snake_case")]
1638pub enum ExportLayout {
1639 #[default]
1641 Nested,
1642 Flat,
1644}
1645
1646#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
1648#[serde(rename_all = "snake_case")]
1649pub enum OutputMode {
1650 Streaming,
1652 #[default]
1654 FlatFile,
1655 Both,
1657}
1658
1659#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1661#[serde(rename_all = "snake_case")]
1662pub enum FileFormat {
1663 Csv,
1664 Parquet,
1665 Json,
1666 JsonLines,
1667}
1668
1669#[derive(Debug, Clone, Serialize, Deserialize)]
1671pub struct CompressionConfig {
1672 #[serde(default = "default_true")]
1674 pub enabled: bool,
1675 #[serde(default)]
1677 pub algorithm: CompressionAlgorithm,
1678 #[serde(default = "default_compression_level")]
1680 pub level: u8,
1681}
1682
1683fn default_compression_level() -> u8 {
1684 3
1685}
1686
1687impl Default for CompressionConfig {
1688 fn default() -> Self {
1689 Self {
1690 enabled: true,
1691 algorithm: CompressionAlgorithm::default(),
1692 level: default_compression_level(),
1693 }
1694 }
1695}
1696
1697#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
1699#[serde(rename_all = "snake_case")]
1700pub enum CompressionAlgorithm {
1701 Gzip,
1702 #[default]
1703 Zstd,
1704 Lz4,
1705 Snappy,
1706}
1707
1708#[derive(Debug, Clone, Serialize, Deserialize)]
1728pub struct FraudConfig {
1729 #[serde(default)]
1731 pub enabled: bool,
1732 #[serde(default = "default_fraud_rate", alias = "fraudRate")]
1750 pub fraud_rate: f64,
1751 #[serde(default, alias = "documentFraudRate")]
1756 pub document_fraud_rate: Option<f64>,
1757 #[serde(default = "default_true", alias = "propagateToLines")]
1762 pub propagate_to_lines: bool,
1763 #[serde(default = "default_true", alias = "propagateToDocument")]
1767 pub propagate_to_document: bool,
1768 #[serde(default)]
1770 pub fraud_type_distribution: FraudTypeDistribution,
1771 #[serde(default)]
1773 pub clustering_enabled: bool,
1774 #[serde(default = "default_clustering_factor")]
1776 pub clustering_factor: f64,
1777 #[serde(default = "default_approval_thresholds")]
1779 pub approval_thresholds: Vec<f64>,
1780}
1781
1782fn default_approval_thresholds() -> Vec<f64> {
1783 vec![1000.0, 5000.0, 10000.0, 25000.0, 50000.0, 100000.0]
1784}
1785
1786fn default_fraud_rate() -> f64 {
1787 0.005
1788}
1789fn default_clustering_factor() -> f64 {
1790 3.0
1791}
1792
1793impl Default for FraudConfig {
1794 fn default() -> Self {
1795 Self {
1796 enabled: false,
1797 fraud_rate: default_fraud_rate(),
1798 document_fraud_rate: None,
1799 propagate_to_lines: true,
1800 propagate_to_document: true,
1801 fraud_type_distribution: FraudTypeDistribution::default(),
1802 clustering_enabled: false,
1803 clustering_factor: default_clustering_factor(),
1804 approval_thresholds: default_approval_thresholds(),
1805 }
1806 }
1807}
1808
1809#[derive(Debug, Clone, Serialize, Deserialize)]
1811pub struct FraudTypeDistribution {
1812 pub suspense_account_abuse: f64,
1813 pub fictitious_transaction: f64,
1814 pub revenue_manipulation: f64,
1815 pub expense_capitalization: f64,
1816 pub split_transaction: f64,
1817 pub timing_anomaly: f64,
1818 pub unauthorized_access: f64,
1819 pub duplicate_payment: f64,
1820}
1821
1822impl Default for FraudTypeDistribution {
1823 fn default() -> Self {
1824 Self {
1825 suspense_account_abuse: 0.25,
1826 fictitious_transaction: 0.15,
1827 revenue_manipulation: 0.10,
1828 expense_capitalization: 0.10,
1829 split_transaction: 0.15,
1830 timing_anomaly: 0.10,
1831 unauthorized_access: 0.10,
1832 duplicate_payment: 0.05,
1833 }
1834 }
1835}
1836
1837#[derive(Debug, Clone, Serialize, Deserialize)]
1839pub struct InternalControlsConfig {
1840 #[serde(default)]
1842 pub enabled: bool,
1843 #[serde(default = "default_exception_rate")]
1845 pub exception_rate: f64,
1846 #[serde(default = "default_sod_violation_rate")]
1848 pub sod_violation_rate: f64,
1849 #[serde(default = "default_true")]
1851 pub export_control_master_data: bool,
1852 #[serde(default = "default_sox_materiality_threshold")]
1854 pub sox_materiality_threshold: f64,
1855 #[serde(default = "default_true")]
1857 pub coso_enabled: bool,
1858 #[serde(default)]
1860 pub include_entity_level_controls: bool,
1861 #[serde(default = "default_target_maturity_level")]
1864 pub target_maturity_level: String,
1865}
1866
1867fn default_exception_rate() -> f64 {
1868 0.02
1869}
1870
1871fn default_sod_violation_rate() -> f64 {
1872 0.01
1873}
1874
1875fn default_sox_materiality_threshold() -> f64 {
1876 10000.0
1877}
1878
1879fn default_target_maturity_level() -> String {
1880 "mixed".to_string()
1881}
1882
1883impl Default for InternalControlsConfig {
1884 fn default() -> Self {
1885 Self {
1886 enabled: false,
1887 exception_rate: default_exception_rate(),
1888 sod_violation_rate: default_sod_violation_rate(),
1889 export_control_master_data: true,
1890 sox_materiality_threshold: default_sox_materiality_threshold(),
1891 coso_enabled: true,
1892 include_entity_level_controls: false,
1893 target_maturity_level: default_target_maturity_level(),
1894 }
1895 }
1896}
1897
1898#[derive(Debug, Clone, Serialize, Deserialize)]
1900pub struct BusinessProcessConfig {
1901 #[serde(default = "default_o2c")]
1903 pub o2c_weight: f64,
1904 #[serde(default = "default_p2p")]
1906 pub p2p_weight: f64,
1907 #[serde(default = "default_r2r")]
1909 pub r2r_weight: f64,
1910 #[serde(default = "default_h2r")]
1912 pub h2r_weight: f64,
1913 #[serde(default = "default_a2r")]
1915 pub a2r_weight: f64,
1916}
1917
1918fn default_o2c() -> f64 {
1919 0.35
1920}
1921fn default_p2p() -> f64 {
1922 0.30
1923}
1924fn default_r2r() -> f64 {
1925 0.20
1926}
1927fn default_h2r() -> f64 {
1928 0.10
1929}
1930fn default_a2r() -> f64 {
1931 0.05
1932}
1933
1934impl Default for BusinessProcessConfig {
1935 fn default() -> Self {
1936 Self {
1937 o2c_weight: default_o2c(),
1938 p2p_weight: default_p2p(),
1939 r2r_weight: default_r2r(),
1940 h2r_weight: default_h2r(),
1941 a2r_weight: default_a2r(),
1942 }
1943 }
1944}
1945
1946#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1948pub struct UserPersonaConfig {
1949 #[serde(default)]
1951 pub persona_distribution: PersonaDistribution,
1952 #[serde(default)]
1954 pub users_per_persona: UsersPerPersona,
1955}
1956
1957#[derive(Debug, Clone, Serialize, Deserialize)]
1959pub struct PersonaDistribution {
1960 pub junior_accountant: f64,
1961 pub senior_accountant: f64,
1962 pub controller: f64,
1963 pub manager: f64,
1964 pub automated_system: f64,
1965}
1966
1967impl Default for PersonaDistribution {
1968 fn default() -> Self {
1969 Self {
1970 junior_accountant: 0.15,
1971 senior_accountant: 0.15,
1972 controller: 0.05,
1973 manager: 0.05,
1974 automated_system: 0.60,
1975 }
1976 }
1977}
1978
1979#[derive(Debug, Clone, Serialize, Deserialize)]
1981pub struct UsersPerPersona {
1982 pub junior_accountant: usize,
1983 pub senior_accountant: usize,
1984 pub controller: usize,
1985 pub manager: usize,
1986 pub automated_system: usize,
1987}
1988
1989impl Default for UsersPerPersona {
1990 fn default() -> Self {
1991 Self {
1992 junior_accountant: 10,
1993 senior_accountant: 5,
1994 controller: 2,
1995 manager: 3,
1996 automated_system: 20,
1997 }
1998 }
1999}
2000
2001#[derive(Debug, Clone, Serialize, Deserialize, Default)]
2003pub struct TemplateConfig {
2004 #[serde(default)]
2006 pub names: NameTemplateConfig,
2007 #[serde(default)]
2009 pub descriptions: DescriptionTemplateConfig,
2010 #[serde(default)]
2012 pub references: ReferenceTemplateConfig,
2013}
2014
2015#[derive(Debug, Clone, Serialize, Deserialize)]
2017pub struct NameTemplateConfig {
2018 #[serde(default)]
2020 pub culture_distribution: CultureDistribution,
2021 #[serde(default = "default_email_domain")]
2023 pub email_domain: String,
2024 #[serde(default = "default_true")]
2026 pub generate_realistic_names: bool,
2027}
2028
2029fn default_email_domain() -> String {
2030 "company.com".to_string()
2031}
2032
2033impl Default for NameTemplateConfig {
2034 fn default() -> Self {
2035 Self {
2036 culture_distribution: CultureDistribution::default(),
2037 email_domain: default_email_domain(),
2038 generate_realistic_names: true,
2039 }
2040 }
2041}
2042
2043#[derive(Debug, Clone, Serialize, Deserialize)]
2045pub struct CultureDistribution {
2046 pub western_us: f64,
2047 pub hispanic: f64,
2048 pub german: f64,
2049 pub french: f64,
2050 pub chinese: f64,
2051 pub japanese: f64,
2052 pub indian: f64,
2053}
2054
2055impl Default for CultureDistribution {
2056 fn default() -> Self {
2057 Self {
2058 western_us: 0.40,
2059 hispanic: 0.20,
2060 german: 0.10,
2061 french: 0.05,
2062 chinese: 0.10,
2063 japanese: 0.05,
2064 indian: 0.10,
2065 }
2066 }
2067}
2068
2069#[derive(Debug, Clone, Serialize, Deserialize)]
2071pub struct DescriptionTemplateConfig {
2072 #[serde(default = "default_true")]
2074 pub generate_header_text: bool,
2075 #[serde(default = "default_true")]
2077 pub generate_line_text: bool,
2078}
2079
2080impl Default for DescriptionTemplateConfig {
2081 fn default() -> Self {
2082 Self {
2083 generate_header_text: true,
2084 generate_line_text: true,
2085 }
2086 }
2087}
2088
2089#[derive(Debug, Clone, Serialize, Deserialize)]
2091pub struct ReferenceTemplateConfig {
2092 #[serde(default = "default_true")]
2094 pub generate_references: bool,
2095 #[serde(default = "default_invoice_prefix")]
2097 pub invoice_prefix: String,
2098 #[serde(default = "default_po_prefix")]
2100 pub po_prefix: String,
2101 #[serde(default = "default_so_prefix")]
2103 pub so_prefix: String,
2104}
2105
2106fn default_invoice_prefix() -> String {
2107 "INV".to_string()
2108}
2109fn default_po_prefix() -> String {
2110 "PO".to_string()
2111}
2112fn default_so_prefix() -> String {
2113 "SO".to_string()
2114}
2115
2116impl Default for ReferenceTemplateConfig {
2117 fn default() -> Self {
2118 Self {
2119 generate_references: true,
2120 invoice_prefix: default_invoice_prefix(),
2121 po_prefix: default_po_prefix(),
2122 so_prefix: default_so_prefix(),
2123 }
2124 }
2125}
2126
2127#[derive(Debug, Clone, Serialize, Deserialize)]
2129pub struct ApprovalConfig {
2130 #[serde(default)]
2132 pub enabled: bool,
2133 #[serde(default = "default_auto_approve_threshold")]
2135 pub auto_approve_threshold: f64,
2136 #[serde(default = "default_rejection_rate")]
2138 pub rejection_rate: f64,
2139 #[serde(default = "default_revision_rate")]
2141 pub revision_rate: f64,
2142 #[serde(default = "default_approval_delay_hours")]
2144 pub average_approval_delay_hours: f64,
2145 #[serde(default)]
2147 pub thresholds: Vec<ApprovalThresholdConfig>,
2148}
2149
2150fn default_auto_approve_threshold() -> f64 {
2151 1000.0
2152}
2153fn default_rejection_rate() -> f64 {
2154 0.02
2155}
2156fn default_revision_rate() -> f64 {
2157 0.05
2158}
2159fn default_approval_delay_hours() -> f64 {
2160 4.0
2161}
2162
2163impl Default for ApprovalConfig {
2164 fn default() -> Self {
2165 Self {
2166 enabled: false,
2167 auto_approve_threshold: default_auto_approve_threshold(),
2168 rejection_rate: default_rejection_rate(),
2169 revision_rate: default_revision_rate(),
2170 average_approval_delay_hours: default_approval_delay_hours(),
2171 thresholds: vec![
2172 ApprovalThresholdConfig {
2173 amount: 1000.0,
2174 level: 1,
2175 roles: vec!["senior_accountant".to_string()],
2176 },
2177 ApprovalThresholdConfig {
2178 amount: 10000.0,
2179 level: 2,
2180 roles: vec!["senior_accountant".to_string(), "controller".to_string()],
2181 },
2182 ApprovalThresholdConfig {
2183 amount: 100000.0,
2184 level: 3,
2185 roles: vec![
2186 "senior_accountant".to_string(),
2187 "controller".to_string(),
2188 "manager".to_string(),
2189 ],
2190 },
2191 ApprovalThresholdConfig {
2192 amount: 500000.0,
2193 level: 4,
2194 roles: vec![
2195 "senior_accountant".to_string(),
2196 "controller".to_string(),
2197 "manager".to_string(),
2198 "executive".to_string(),
2199 ],
2200 },
2201 ],
2202 }
2203 }
2204}
2205
2206#[derive(Debug, Clone, Serialize, Deserialize)]
2208pub struct ApprovalThresholdConfig {
2209 pub amount: f64,
2211 pub level: u8,
2213 pub roles: Vec<String>,
2215}
2216
2217#[derive(Debug, Clone, Serialize, Deserialize)]
2219pub struct DepartmentConfig {
2220 #[serde(default)]
2222 pub enabled: bool,
2223 #[serde(default = "default_headcount_multiplier")]
2225 pub headcount_multiplier: f64,
2226 #[serde(default)]
2228 pub custom_departments: Vec<CustomDepartmentConfig>,
2229}
2230
2231fn default_headcount_multiplier() -> f64 {
2232 1.0
2233}
2234
2235impl Default for DepartmentConfig {
2236 fn default() -> Self {
2237 Self {
2238 enabled: false,
2239 headcount_multiplier: default_headcount_multiplier(),
2240 custom_departments: Vec::new(),
2241 }
2242 }
2243}
2244
2245#[derive(Debug, Clone, Serialize, Deserialize)]
2247pub struct CustomDepartmentConfig {
2248 pub code: String,
2250 pub name: String,
2252 #[serde(default)]
2254 pub cost_center: Option<String>,
2255 #[serde(default)]
2257 pub primary_processes: Vec<String>,
2258 #[serde(default)]
2260 pub parent_code: Option<String>,
2261}
2262
2263#[derive(Debug, Clone, Default, Serialize, Deserialize)]
2269pub struct MasterDataConfig {
2270 #[serde(default)]
2272 pub vendors: VendorMasterConfig,
2273 #[serde(default)]
2275 pub customers: CustomerMasterConfig,
2276 #[serde(default)]
2278 pub materials: MaterialMasterConfig,
2279 #[serde(default)]
2281 pub fixed_assets: FixedAssetMasterConfig,
2282 #[serde(default)]
2284 pub employees: EmployeeMasterConfig,
2285 #[serde(default)]
2287 pub cost_centers: CostCenterMasterConfig,
2288}
2289
2290#[derive(Debug, Clone, Serialize, Deserialize)]
2292pub struct VendorMasterConfig {
2293 #[serde(default = "default_vendor_count")]
2295 pub count: usize,
2296 #[serde(default = "default_intercompany_percent")]
2298 pub intercompany_percent: f64,
2299 #[serde(default)]
2301 pub payment_terms_distribution: PaymentTermsDistribution,
2302 #[serde(default)]
2304 pub behavior_distribution: VendorBehaviorDistribution,
2305 #[serde(default = "default_true")]
2307 pub generate_bank_accounts: bool,
2308 #[serde(default = "default_true")]
2310 pub generate_tax_ids: bool,
2311}
2312
2313fn default_vendor_count() -> usize {
2314 500
2315}
2316
2317fn default_intercompany_percent() -> f64 {
2318 0.05
2319}
2320
2321impl Default for VendorMasterConfig {
2322 fn default() -> Self {
2323 Self {
2324 count: default_vendor_count(),
2325 intercompany_percent: default_intercompany_percent(),
2326 payment_terms_distribution: PaymentTermsDistribution::default(),
2327 behavior_distribution: VendorBehaviorDistribution::default(),
2328 generate_bank_accounts: true,
2329 generate_tax_ids: true,
2330 }
2331 }
2332}
2333
2334#[derive(Debug, Clone, Serialize, Deserialize)]
2336pub struct PaymentTermsDistribution {
2337 pub net_30: f64,
2339 pub net_60: f64,
2341 pub net_90: f64,
2343 pub two_ten_net_30: f64,
2345 pub due_on_receipt: f64,
2347 pub end_of_month: f64,
2349}
2350
2351impl Default for PaymentTermsDistribution {
2352 fn default() -> Self {
2353 Self {
2354 net_30: 0.40,
2355 net_60: 0.20,
2356 net_90: 0.10,
2357 two_ten_net_30: 0.15,
2358 due_on_receipt: 0.05,
2359 end_of_month: 0.10,
2360 }
2361 }
2362}
2363
2364#[derive(Debug, Clone, Serialize, Deserialize)]
2366pub struct VendorBehaviorDistribution {
2367 pub reliable: f64,
2369 pub sometimes_late: f64,
2371 pub inconsistent_quality: f64,
2373 pub premium: f64,
2375 pub budget: f64,
2377}
2378
2379impl Default for VendorBehaviorDistribution {
2380 fn default() -> Self {
2381 Self {
2382 reliable: 0.50,
2383 sometimes_late: 0.20,
2384 inconsistent_quality: 0.10,
2385 premium: 0.10,
2386 budget: 0.10,
2387 }
2388 }
2389}
2390
2391#[derive(Debug, Clone, Serialize, Deserialize)]
2393pub struct CustomerMasterConfig {
2394 #[serde(default = "default_customer_count")]
2396 pub count: usize,
2397 #[serde(default = "default_intercompany_percent")]
2399 pub intercompany_percent: f64,
2400 #[serde(default)]
2402 pub credit_rating_distribution: CreditRatingDistribution,
2403 #[serde(default)]
2405 pub payment_behavior_distribution: PaymentBehaviorDistribution,
2406 #[serde(default = "default_true")]
2408 pub generate_credit_limits: bool,
2409}
2410
2411fn default_customer_count() -> usize {
2412 2000
2413}
2414
2415impl Default for CustomerMasterConfig {
2416 fn default() -> Self {
2417 Self {
2418 count: default_customer_count(),
2419 intercompany_percent: default_intercompany_percent(),
2420 credit_rating_distribution: CreditRatingDistribution::default(),
2421 payment_behavior_distribution: PaymentBehaviorDistribution::default(),
2422 generate_credit_limits: true,
2423 }
2424 }
2425}
2426
2427#[derive(Debug, Clone, Serialize, Deserialize)]
2429pub struct CreditRatingDistribution {
2430 pub aaa: f64,
2432 pub aa: f64,
2434 pub a: f64,
2436 pub bbb: f64,
2438 pub bb: f64,
2440 pub b: f64,
2442 pub below_b: f64,
2444}
2445
2446impl Default for CreditRatingDistribution {
2447 fn default() -> Self {
2448 Self {
2449 aaa: 0.05,
2450 aa: 0.10,
2451 a: 0.20,
2452 bbb: 0.30,
2453 bb: 0.20,
2454 b: 0.10,
2455 below_b: 0.05,
2456 }
2457 }
2458}
2459
2460#[derive(Debug, Clone, Serialize, Deserialize)]
2462pub struct PaymentBehaviorDistribution {
2463 pub early_payer: f64,
2465 pub on_time: f64,
2467 pub occasional_late: f64,
2469 pub frequent_late: f64,
2471 pub discount_taker: f64,
2473}
2474
2475impl Default for PaymentBehaviorDistribution {
2476 fn default() -> Self {
2477 Self {
2478 early_payer: 0.10,
2479 on_time: 0.50,
2480 occasional_late: 0.25,
2481 frequent_late: 0.10,
2482 discount_taker: 0.05,
2483 }
2484 }
2485}
2486
2487#[derive(Debug, Clone, Serialize, Deserialize)]
2489pub struct MaterialMasterConfig {
2490 #[serde(default = "default_material_count")]
2492 pub count: usize,
2493 #[serde(default)]
2495 pub type_distribution: MaterialTypeDistribution,
2496 #[serde(default)]
2498 pub valuation_distribution: ValuationMethodDistribution,
2499 #[serde(default = "default_bom_percent")]
2501 pub bom_percent: f64,
2502 #[serde(default = "default_max_bom_depth")]
2504 pub max_bom_depth: u8,
2505}
2506
2507fn default_material_count() -> usize {
2508 5000
2509}
2510
2511fn default_bom_percent() -> f64 {
2512 0.20
2513}
2514
2515fn default_max_bom_depth() -> u8 {
2516 3
2517}
2518
2519impl Default for MaterialMasterConfig {
2520 fn default() -> Self {
2521 Self {
2522 count: default_material_count(),
2523 type_distribution: MaterialTypeDistribution::default(),
2524 valuation_distribution: ValuationMethodDistribution::default(),
2525 bom_percent: default_bom_percent(),
2526 max_bom_depth: default_max_bom_depth(),
2527 }
2528 }
2529}
2530
2531#[derive(Debug, Clone, Serialize, Deserialize)]
2533pub struct MaterialTypeDistribution {
2534 pub raw_material: f64,
2536 pub semi_finished: f64,
2538 pub finished_good: f64,
2540 pub trading_good: f64,
2542 pub operating_supply: f64,
2544 pub service: f64,
2546}
2547
2548impl Default for MaterialTypeDistribution {
2549 fn default() -> Self {
2550 Self {
2551 raw_material: 0.30,
2552 semi_finished: 0.15,
2553 finished_good: 0.25,
2554 trading_good: 0.15,
2555 operating_supply: 0.10,
2556 service: 0.05,
2557 }
2558 }
2559}
2560
2561#[derive(Debug, Clone, Serialize, Deserialize)]
2563pub struct ValuationMethodDistribution {
2564 pub standard_cost: f64,
2566 pub moving_average: f64,
2568 pub fifo: f64,
2570 pub lifo: f64,
2572}
2573
2574impl Default for ValuationMethodDistribution {
2575 fn default() -> Self {
2576 Self {
2577 standard_cost: 0.50,
2578 moving_average: 0.30,
2579 fifo: 0.15,
2580 lifo: 0.05,
2581 }
2582 }
2583}
2584
2585#[derive(Debug, Clone, Serialize, Deserialize)]
2587pub struct FixedAssetMasterConfig {
2588 #[serde(default = "default_asset_count")]
2590 pub count: usize,
2591 #[serde(default)]
2593 pub class_distribution: AssetClassDistribution,
2594 #[serde(default)]
2596 pub depreciation_distribution: DepreciationMethodDistribution,
2597 #[serde(default = "default_fully_depreciated_percent")]
2599 pub fully_depreciated_percent: f64,
2600 #[serde(default = "default_true")]
2602 pub generate_acquisition_history: bool,
2603}
2604
2605fn default_asset_count() -> usize {
2606 800
2607}
2608
2609fn default_fully_depreciated_percent() -> f64 {
2610 0.15
2611}
2612
2613impl Default for FixedAssetMasterConfig {
2614 fn default() -> Self {
2615 Self {
2616 count: default_asset_count(),
2617 class_distribution: AssetClassDistribution::default(),
2618 depreciation_distribution: DepreciationMethodDistribution::default(),
2619 fully_depreciated_percent: default_fully_depreciated_percent(),
2620 generate_acquisition_history: true,
2621 }
2622 }
2623}
2624
2625#[derive(Debug, Clone, Serialize, Deserialize)]
2627pub struct AssetClassDistribution {
2628 pub buildings: f64,
2630 pub machinery: f64,
2632 pub vehicles: f64,
2634 pub it_equipment: f64,
2636 pub furniture: f64,
2638 pub land: f64,
2640 pub leasehold: f64,
2642}
2643
2644impl Default for AssetClassDistribution {
2645 fn default() -> Self {
2646 Self {
2647 buildings: 0.15,
2648 machinery: 0.30,
2649 vehicles: 0.15,
2650 it_equipment: 0.20,
2651 furniture: 0.10,
2652 land: 0.05,
2653 leasehold: 0.05,
2654 }
2655 }
2656}
2657
2658#[derive(Debug, Clone, Serialize, Deserialize)]
2660pub struct DepreciationMethodDistribution {
2661 pub straight_line: f64,
2663 pub declining_balance: f64,
2665 pub double_declining: f64,
2667 pub sum_of_years: f64,
2669 pub units_of_production: f64,
2671}
2672
2673impl Default for DepreciationMethodDistribution {
2674 fn default() -> Self {
2675 Self {
2676 straight_line: 0.60,
2677 declining_balance: 0.20,
2678 double_declining: 0.10,
2679 sum_of_years: 0.05,
2680 units_of_production: 0.05,
2681 }
2682 }
2683}
2684
2685#[derive(Debug, Clone, Serialize, Deserialize)]
2687pub struct EmployeeMasterConfig {
2688 #[serde(default = "default_employee_count")]
2690 pub count: usize,
2691 #[serde(default = "default_true")]
2693 pub generate_hierarchy: bool,
2694 #[serde(default = "default_hierarchy_depth")]
2696 pub max_hierarchy_depth: u8,
2697 #[serde(default = "default_span_of_control")]
2699 pub average_span_of_control: f64,
2700 #[serde(default)]
2702 pub approval_limits: ApprovalLimitDistribution,
2703 #[serde(default)]
2705 pub department_distribution: EmployeeDepartmentDistribution,
2706}
2707
2708fn default_employee_count() -> usize {
2709 1500
2710}
2711
2712fn default_hierarchy_depth() -> u8 {
2713 6
2714}
2715
2716fn default_span_of_control() -> f64 {
2717 5.0
2718}
2719
2720impl Default for EmployeeMasterConfig {
2721 fn default() -> Self {
2722 Self {
2723 count: default_employee_count(),
2724 generate_hierarchy: true,
2725 max_hierarchy_depth: default_hierarchy_depth(),
2726 average_span_of_control: default_span_of_control(),
2727 approval_limits: ApprovalLimitDistribution::default(),
2728 department_distribution: EmployeeDepartmentDistribution::default(),
2729 }
2730 }
2731}
2732
2733#[derive(Debug, Clone, Serialize, Deserialize)]
2735pub struct ApprovalLimitDistribution {
2736 #[serde(default = "default_staff_limit")]
2738 pub staff: f64,
2739 #[serde(default = "default_senior_limit")]
2741 pub senior: f64,
2742 #[serde(default = "default_manager_limit")]
2744 pub manager: f64,
2745 #[serde(default = "default_director_limit")]
2747 pub director: f64,
2748 #[serde(default = "default_vp_limit")]
2750 pub vp: f64,
2751 #[serde(default = "default_executive_limit")]
2753 pub executive: f64,
2754}
2755
2756fn default_staff_limit() -> f64 {
2757 1000.0
2758}
2759fn default_senior_limit() -> f64 {
2760 5000.0
2761}
2762fn default_manager_limit() -> f64 {
2763 25000.0
2764}
2765fn default_director_limit() -> f64 {
2766 100000.0
2767}
2768fn default_vp_limit() -> f64 {
2769 500000.0
2770}
2771fn default_executive_limit() -> f64 {
2772 f64::INFINITY
2773}
2774
2775impl Default for ApprovalLimitDistribution {
2776 fn default() -> Self {
2777 Self {
2778 staff: default_staff_limit(),
2779 senior: default_senior_limit(),
2780 manager: default_manager_limit(),
2781 director: default_director_limit(),
2782 vp: default_vp_limit(),
2783 executive: default_executive_limit(),
2784 }
2785 }
2786}
2787
2788#[derive(Debug, Clone, Serialize, Deserialize)]
2790pub struct EmployeeDepartmentDistribution {
2791 pub finance: f64,
2793 pub procurement: f64,
2795 pub sales: f64,
2797 pub warehouse: f64,
2799 pub it: f64,
2801 pub hr: f64,
2803 pub operations: f64,
2805 pub executive: f64,
2807}
2808
2809impl Default for EmployeeDepartmentDistribution {
2810 fn default() -> Self {
2811 Self {
2812 finance: 0.12,
2813 procurement: 0.10,
2814 sales: 0.25,
2815 warehouse: 0.15,
2816 it: 0.10,
2817 hr: 0.05,
2818 operations: 0.20,
2819 executive: 0.03,
2820 }
2821 }
2822}
2823
2824#[derive(Debug, Clone, Serialize, Deserialize)]
2826pub struct CostCenterMasterConfig {
2827 #[serde(default = "default_cost_center_count")]
2829 pub count: usize,
2830 #[serde(default = "default_true")]
2832 pub generate_hierarchy: bool,
2833 #[serde(default = "default_cc_hierarchy_depth")]
2835 pub max_hierarchy_depth: u8,
2836}
2837
2838fn default_cost_center_count() -> usize {
2839 50
2840}
2841
2842fn default_cc_hierarchy_depth() -> u8 {
2843 3
2844}
2845
2846impl Default for CostCenterMasterConfig {
2847 fn default() -> Self {
2848 Self {
2849 count: default_cost_center_count(),
2850 generate_hierarchy: true,
2851 max_hierarchy_depth: default_cc_hierarchy_depth(),
2852 }
2853 }
2854}
2855
2856#[derive(Debug, Clone, Serialize, Deserialize)]
2862pub struct DocumentFlowConfig {
2863 #[serde(default)]
2865 pub p2p: P2PFlowConfig,
2866 #[serde(default)]
2868 pub o2c: O2CFlowConfig,
2869 #[serde(default = "default_true")]
2871 pub generate_document_references: bool,
2872 #[serde(default)]
2874 pub export_flow_graph: bool,
2875}
2876
2877impl Default for DocumentFlowConfig {
2878 fn default() -> Self {
2879 Self {
2880 p2p: P2PFlowConfig::default(),
2881 o2c: O2CFlowConfig::default(),
2882 generate_document_references: true,
2883 export_flow_graph: false,
2884 }
2885 }
2886}
2887
2888#[derive(Debug, Clone, Serialize, Deserialize)]
2890pub struct P2PFlowConfig {
2891 #[serde(default = "default_true")]
2893 pub enabled: bool,
2894 #[serde(default = "default_three_way_match_rate")]
2896 pub three_way_match_rate: f64,
2897 #[serde(default = "default_partial_delivery_rate")]
2899 pub partial_delivery_rate: f64,
2900 #[serde(default = "default_price_variance_rate")]
2902 pub price_variance_rate: f64,
2903 #[serde(default = "default_max_price_variance")]
2905 pub max_price_variance_percent: f64,
2906 #[serde(default = "default_quantity_variance_rate")]
2908 pub quantity_variance_rate: f64,
2909 #[serde(default = "default_po_to_gr_days")]
2911 pub average_po_to_gr_days: u32,
2912 #[serde(default = "default_gr_to_invoice_days")]
2914 pub average_gr_to_invoice_days: u32,
2915 #[serde(default = "default_invoice_to_payment_days")]
2917 pub average_invoice_to_payment_days: u32,
2918 #[serde(default)]
2920 pub line_count_distribution: DocumentLineCountDistribution,
2921 #[serde(default)]
2923 pub payment_behavior: P2PPaymentBehaviorConfig,
2924 #[serde(default)]
2926 pub over_delivery_rate: Option<f64>,
2927 #[serde(default)]
2929 pub early_payment_discount_rate: Option<f64>,
2930}
2931
2932fn default_three_way_match_rate() -> f64 {
2933 0.95
2934}
2935
2936fn default_partial_delivery_rate() -> f64 {
2937 0.15
2938}
2939
2940fn default_price_variance_rate() -> f64 {
2941 0.08
2942}
2943
2944fn default_max_price_variance() -> f64 {
2945 0.05
2946}
2947
2948fn default_quantity_variance_rate() -> f64 {
2949 0.05
2950}
2951
2952fn default_po_to_gr_days() -> u32 {
2953 14
2954}
2955
2956fn default_gr_to_invoice_days() -> u32 {
2957 5
2958}
2959
2960fn default_invoice_to_payment_days() -> u32 {
2961 30
2962}
2963
2964impl Default for P2PFlowConfig {
2965 fn default() -> Self {
2966 Self {
2967 enabled: true,
2968 three_way_match_rate: default_three_way_match_rate(),
2969 partial_delivery_rate: default_partial_delivery_rate(),
2970 price_variance_rate: default_price_variance_rate(),
2971 max_price_variance_percent: default_max_price_variance(),
2972 quantity_variance_rate: default_quantity_variance_rate(),
2973 average_po_to_gr_days: default_po_to_gr_days(),
2974 average_gr_to_invoice_days: default_gr_to_invoice_days(),
2975 average_invoice_to_payment_days: default_invoice_to_payment_days(),
2976 line_count_distribution: DocumentLineCountDistribution::default(),
2977 payment_behavior: P2PPaymentBehaviorConfig::default(),
2978 over_delivery_rate: None,
2979 early_payment_discount_rate: None,
2980 }
2981 }
2982}
2983
2984#[derive(Debug, Clone, Serialize, Deserialize)]
2990pub struct P2PPaymentBehaviorConfig {
2991 #[serde(default = "default_p2p_late_payment_rate")]
2993 pub late_payment_rate: f64,
2994 #[serde(default)]
2996 pub late_payment_days_distribution: LatePaymentDaysDistribution,
2997 #[serde(default = "default_p2p_partial_payment_rate")]
2999 pub partial_payment_rate: f64,
3000 #[serde(default = "default_p2p_payment_correction_rate")]
3002 pub payment_correction_rate: f64,
3003 #[serde(default = "default_p2p_avg_days_until_remainder")]
3005 pub avg_days_until_remainder: u32,
3006}
3007
3008fn default_p2p_late_payment_rate() -> f64 {
3009 0.15
3010}
3011
3012fn default_p2p_partial_payment_rate() -> f64 {
3013 0.05
3014}
3015
3016fn default_p2p_payment_correction_rate() -> f64 {
3017 0.02
3018}
3019
3020fn default_p2p_avg_days_until_remainder() -> u32 {
3021 30
3022}
3023
3024impl Default for P2PPaymentBehaviorConfig {
3025 fn default() -> Self {
3026 Self {
3027 late_payment_rate: default_p2p_late_payment_rate(),
3028 late_payment_days_distribution: LatePaymentDaysDistribution::default(),
3029 partial_payment_rate: default_p2p_partial_payment_rate(),
3030 payment_correction_rate: default_p2p_payment_correction_rate(),
3031 avg_days_until_remainder: default_p2p_avg_days_until_remainder(),
3032 }
3033 }
3034}
3035
3036#[derive(Debug, Clone, Serialize, Deserialize)]
3038pub struct LatePaymentDaysDistribution {
3039 #[serde(default = "default_slightly_late")]
3041 pub slightly_late_1_to_7: f64,
3042 #[serde(default = "default_late_8_14")]
3044 pub late_8_to_14: f64,
3045 #[serde(default = "default_very_late")]
3047 pub very_late_15_to_30: f64,
3048 #[serde(default = "default_severely_late")]
3050 pub severely_late_31_to_60: f64,
3051 #[serde(default = "default_extremely_late")]
3053 pub extremely_late_over_60: f64,
3054}
3055
3056fn default_slightly_late() -> f64 {
3057 0.50
3058}
3059
3060fn default_late_8_14() -> f64 {
3061 0.25
3062}
3063
3064fn default_very_late() -> f64 {
3065 0.15
3066}
3067
3068fn default_severely_late() -> f64 {
3069 0.07
3070}
3071
3072fn default_extremely_late() -> f64 {
3073 0.03
3074}
3075
3076impl Default for LatePaymentDaysDistribution {
3077 fn default() -> Self {
3078 Self {
3079 slightly_late_1_to_7: default_slightly_late(),
3080 late_8_to_14: default_late_8_14(),
3081 very_late_15_to_30: default_very_late(),
3082 severely_late_31_to_60: default_severely_late(),
3083 extremely_late_over_60: default_extremely_late(),
3084 }
3085 }
3086}
3087
3088#[derive(Debug, Clone, Serialize, Deserialize)]
3090pub struct O2CFlowConfig {
3091 #[serde(default = "default_true")]
3093 pub enabled: bool,
3094 #[serde(default = "default_credit_check_failure_rate")]
3096 pub credit_check_failure_rate: f64,
3097 #[serde(default = "default_partial_shipment_rate")]
3099 pub partial_shipment_rate: f64,
3100 #[serde(default = "default_return_rate")]
3102 pub return_rate: f64,
3103 #[serde(default = "default_bad_debt_rate")]
3105 pub bad_debt_rate: f64,
3106 #[serde(default = "default_so_to_delivery_days")]
3108 pub average_so_to_delivery_days: u32,
3109 #[serde(default = "default_delivery_to_invoice_days")]
3111 pub average_delivery_to_invoice_days: u32,
3112 #[serde(default = "default_invoice_to_receipt_days")]
3114 pub average_invoice_to_receipt_days: u32,
3115 #[serde(default)]
3117 pub line_count_distribution: DocumentLineCountDistribution,
3118 #[serde(default)]
3120 pub cash_discount: CashDiscountConfig,
3121 #[serde(default)]
3123 pub payment_behavior: O2CPaymentBehaviorConfig,
3124 #[serde(default)]
3126 pub late_payment_rate: Option<f64>,
3127}
3128
3129fn default_credit_check_failure_rate() -> f64 {
3130 0.02
3131}
3132
3133fn default_partial_shipment_rate() -> f64 {
3134 0.10
3135}
3136
3137fn default_return_rate() -> f64 {
3138 0.03
3139}
3140
3141fn default_bad_debt_rate() -> f64 {
3142 0.01
3143}
3144
3145fn default_so_to_delivery_days() -> u32 {
3146 7
3147}
3148
3149fn default_delivery_to_invoice_days() -> u32 {
3150 1
3151}
3152
3153fn default_invoice_to_receipt_days() -> u32 {
3154 45
3155}
3156
3157impl Default for O2CFlowConfig {
3158 fn default() -> Self {
3159 Self {
3160 enabled: true,
3161 credit_check_failure_rate: default_credit_check_failure_rate(),
3162 partial_shipment_rate: default_partial_shipment_rate(),
3163 return_rate: default_return_rate(),
3164 bad_debt_rate: default_bad_debt_rate(),
3165 average_so_to_delivery_days: default_so_to_delivery_days(),
3166 average_delivery_to_invoice_days: default_delivery_to_invoice_days(),
3167 average_invoice_to_receipt_days: default_invoice_to_receipt_days(),
3168 line_count_distribution: DocumentLineCountDistribution::default(),
3169 cash_discount: CashDiscountConfig::default(),
3170 payment_behavior: O2CPaymentBehaviorConfig::default(),
3171 late_payment_rate: None,
3172 }
3173 }
3174}
3175
3176#[derive(Debug, Clone, Serialize, Deserialize, Default)]
3182pub struct O2CPaymentBehaviorConfig {
3183 #[serde(default)]
3185 pub dunning: DunningConfig,
3186 #[serde(default)]
3188 pub partial_payments: PartialPaymentConfig,
3189 #[serde(default)]
3191 pub short_payments: ShortPaymentConfig,
3192 #[serde(default)]
3194 pub on_account_payments: OnAccountPaymentConfig,
3195 #[serde(default)]
3197 pub payment_corrections: PaymentCorrectionConfig,
3198}
3199
3200#[derive(Debug, Clone, Serialize, Deserialize)]
3202pub struct DunningConfig {
3203 #[serde(default)]
3205 pub enabled: bool,
3206 #[serde(default = "default_dunning_level_1_days")]
3208 pub level_1_days_overdue: u32,
3209 #[serde(default = "default_dunning_level_2_days")]
3211 pub level_2_days_overdue: u32,
3212 #[serde(default = "default_dunning_level_3_days")]
3214 pub level_3_days_overdue: u32,
3215 #[serde(default = "default_collection_days")]
3217 pub collection_days_overdue: u32,
3218 #[serde(default)]
3220 pub payment_after_dunning_rates: DunningPaymentRates,
3221 #[serde(default = "default_dunning_block_rate")]
3223 pub dunning_block_rate: f64,
3224 #[serde(default = "default_dunning_interest_rate")]
3226 pub interest_rate_per_year: f64,
3227 #[serde(default = "default_dunning_charge")]
3229 pub dunning_charge: f64,
3230}
3231
3232fn default_dunning_level_1_days() -> u32 {
3233 14
3234}
3235
3236fn default_dunning_level_2_days() -> u32 {
3237 28
3238}
3239
3240fn default_dunning_level_3_days() -> u32 {
3241 42
3242}
3243
3244fn default_collection_days() -> u32 {
3245 60
3246}
3247
3248fn default_dunning_block_rate() -> f64 {
3249 0.05
3250}
3251
3252fn default_dunning_interest_rate() -> f64 {
3253 0.09
3254}
3255
3256fn default_dunning_charge() -> f64 {
3257 25.0
3258}
3259
3260impl Default for DunningConfig {
3261 fn default() -> Self {
3262 Self {
3263 enabled: false,
3264 level_1_days_overdue: default_dunning_level_1_days(),
3265 level_2_days_overdue: default_dunning_level_2_days(),
3266 level_3_days_overdue: default_dunning_level_3_days(),
3267 collection_days_overdue: default_collection_days(),
3268 payment_after_dunning_rates: DunningPaymentRates::default(),
3269 dunning_block_rate: default_dunning_block_rate(),
3270 interest_rate_per_year: default_dunning_interest_rate(),
3271 dunning_charge: default_dunning_charge(),
3272 }
3273 }
3274}
3275
3276#[derive(Debug, Clone, Serialize, Deserialize)]
3278pub struct DunningPaymentRates {
3279 #[serde(default = "default_after_level_1")]
3281 pub after_level_1: f64,
3282 #[serde(default = "default_after_level_2")]
3284 pub after_level_2: f64,
3285 #[serde(default = "default_after_level_3")]
3287 pub after_level_3: f64,
3288 #[serde(default = "default_during_collection")]
3290 pub during_collection: f64,
3291 #[serde(default = "default_never_pay")]
3293 pub never_pay: f64,
3294}
3295
3296fn default_after_level_1() -> f64 {
3297 0.40
3298}
3299
3300fn default_after_level_2() -> f64 {
3301 0.30
3302}
3303
3304fn default_after_level_3() -> f64 {
3305 0.15
3306}
3307
3308fn default_during_collection() -> f64 {
3309 0.05
3310}
3311
3312fn default_never_pay() -> f64 {
3313 0.10
3314}
3315
3316impl Default for DunningPaymentRates {
3317 fn default() -> Self {
3318 Self {
3319 after_level_1: default_after_level_1(),
3320 after_level_2: default_after_level_2(),
3321 after_level_3: default_after_level_3(),
3322 during_collection: default_during_collection(),
3323 never_pay: default_never_pay(),
3324 }
3325 }
3326}
3327
3328#[derive(Debug, Clone, Serialize, Deserialize)]
3330pub struct PartialPaymentConfig {
3331 #[serde(default = "default_partial_payment_rate")]
3333 pub rate: f64,
3334 #[serde(default)]
3336 pub percentage_distribution: PartialPaymentPercentageDistribution,
3337 #[serde(default = "default_avg_days_until_remainder")]
3339 pub avg_days_until_remainder: u32,
3340}
3341
3342fn default_partial_payment_rate() -> f64 {
3343 0.08
3344}
3345
3346fn default_avg_days_until_remainder() -> u32 {
3347 30
3348}
3349
3350impl Default for PartialPaymentConfig {
3351 fn default() -> Self {
3352 Self {
3353 rate: default_partial_payment_rate(),
3354 percentage_distribution: PartialPaymentPercentageDistribution::default(),
3355 avg_days_until_remainder: default_avg_days_until_remainder(),
3356 }
3357 }
3358}
3359
3360#[derive(Debug, Clone, Serialize, Deserialize)]
3362pub struct PartialPaymentPercentageDistribution {
3363 #[serde(default = "default_partial_25")]
3365 pub pay_25_percent: f64,
3366 #[serde(default = "default_partial_50")]
3368 pub pay_50_percent: f64,
3369 #[serde(default = "default_partial_75")]
3371 pub pay_75_percent: f64,
3372 #[serde(default = "default_partial_random")]
3374 pub pay_random_percent: f64,
3375}
3376
3377fn default_partial_25() -> f64 {
3378 0.15
3379}
3380
3381fn default_partial_50() -> f64 {
3382 0.50
3383}
3384
3385fn default_partial_75() -> f64 {
3386 0.25
3387}
3388
3389fn default_partial_random() -> f64 {
3390 0.10
3391}
3392
3393impl Default for PartialPaymentPercentageDistribution {
3394 fn default() -> Self {
3395 Self {
3396 pay_25_percent: default_partial_25(),
3397 pay_50_percent: default_partial_50(),
3398 pay_75_percent: default_partial_75(),
3399 pay_random_percent: default_partial_random(),
3400 }
3401 }
3402}
3403
3404#[derive(Debug, Clone, Serialize, Deserialize)]
3406pub struct ShortPaymentConfig {
3407 #[serde(default = "default_short_payment_rate")]
3409 pub rate: f64,
3410 #[serde(default)]
3412 pub reason_distribution: ShortPaymentReasonDistribution,
3413 #[serde(default = "default_max_short_percent")]
3415 pub max_short_percent: f64,
3416}
3417
3418fn default_short_payment_rate() -> f64 {
3419 0.03
3420}
3421
3422fn default_max_short_percent() -> f64 {
3423 0.10
3424}
3425
3426impl Default for ShortPaymentConfig {
3427 fn default() -> Self {
3428 Self {
3429 rate: default_short_payment_rate(),
3430 reason_distribution: ShortPaymentReasonDistribution::default(),
3431 max_short_percent: default_max_short_percent(),
3432 }
3433 }
3434}
3435
3436#[derive(Debug, Clone, Serialize, Deserialize)]
3438pub struct ShortPaymentReasonDistribution {
3439 #[serde(default = "default_pricing_dispute")]
3441 pub pricing_dispute: f64,
3442 #[serde(default = "default_quality_issue")]
3444 pub quality_issue: f64,
3445 #[serde(default = "default_quantity_discrepancy")]
3447 pub quantity_discrepancy: f64,
3448 #[serde(default = "default_unauthorized_deduction")]
3450 pub unauthorized_deduction: f64,
3451 #[serde(default = "default_incorrect_discount")]
3453 pub incorrect_discount: f64,
3454}
3455
3456fn default_pricing_dispute() -> f64 {
3457 0.30
3458}
3459
3460fn default_quality_issue() -> f64 {
3461 0.20
3462}
3463
3464fn default_quantity_discrepancy() -> f64 {
3465 0.20
3466}
3467
3468fn default_unauthorized_deduction() -> f64 {
3469 0.15
3470}
3471
3472fn default_incorrect_discount() -> f64 {
3473 0.15
3474}
3475
3476impl Default for ShortPaymentReasonDistribution {
3477 fn default() -> Self {
3478 Self {
3479 pricing_dispute: default_pricing_dispute(),
3480 quality_issue: default_quality_issue(),
3481 quantity_discrepancy: default_quantity_discrepancy(),
3482 unauthorized_deduction: default_unauthorized_deduction(),
3483 incorrect_discount: default_incorrect_discount(),
3484 }
3485 }
3486}
3487
3488#[derive(Debug, Clone, Serialize, Deserialize)]
3490pub struct OnAccountPaymentConfig {
3491 #[serde(default = "default_on_account_rate")]
3493 pub rate: f64,
3494 #[serde(default = "default_avg_days_until_applied")]
3496 pub avg_days_until_applied: u32,
3497}
3498
3499fn default_on_account_rate() -> f64 {
3500 0.02
3501}
3502
3503fn default_avg_days_until_applied() -> u32 {
3504 14
3505}
3506
3507impl Default for OnAccountPaymentConfig {
3508 fn default() -> Self {
3509 Self {
3510 rate: default_on_account_rate(),
3511 avg_days_until_applied: default_avg_days_until_applied(),
3512 }
3513 }
3514}
3515
3516#[derive(Debug, Clone, Serialize, Deserialize)]
3518pub struct PaymentCorrectionConfig {
3519 #[serde(default = "default_payment_correction_rate")]
3521 pub rate: f64,
3522 #[serde(default)]
3524 pub type_distribution: PaymentCorrectionTypeDistribution,
3525}
3526
3527fn default_payment_correction_rate() -> f64 {
3528 0.02
3529}
3530
3531impl Default for PaymentCorrectionConfig {
3532 fn default() -> Self {
3533 Self {
3534 rate: default_payment_correction_rate(),
3535 type_distribution: PaymentCorrectionTypeDistribution::default(),
3536 }
3537 }
3538}
3539
3540#[derive(Debug, Clone, Serialize, Deserialize)]
3542pub struct PaymentCorrectionTypeDistribution {
3543 #[serde(default = "default_nsf_rate")]
3545 pub nsf: f64,
3546 #[serde(default = "default_chargeback_rate")]
3548 pub chargeback: f64,
3549 #[serde(default = "default_wrong_amount_rate")]
3551 pub wrong_amount: f64,
3552 #[serde(default = "default_wrong_customer_rate")]
3554 pub wrong_customer: f64,
3555 #[serde(default = "default_duplicate_payment_rate")]
3557 pub duplicate_payment: f64,
3558}
3559
3560fn default_nsf_rate() -> f64 {
3561 0.30
3562}
3563
3564fn default_chargeback_rate() -> f64 {
3565 0.20
3566}
3567
3568fn default_wrong_amount_rate() -> f64 {
3569 0.20
3570}
3571
3572fn default_wrong_customer_rate() -> f64 {
3573 0.15
3574}
3575
3576fn default_duplicate_payment_rate() -> f64 {
3577 0.15
3578}
3579
3580impl Default for PaymentCorrectionTypeDistribution {
3581 fn default() -> Self {
3582 Self {
3583 nsf: default_nsf_rate(),
3584 chargeback: default_chargeback_rate(),
3585 wrong_amount: default_wrong_amount_rate(),
3586 wrong_customer: default_wrong_customer_rate(),
3587 duplicate_payment: default_duplicate_payment_rate(),
3588 }
3589 }
3590}
3591
3592#[derive(Debug, Clone, Serialize, Deserialize)]
3594pub struct DocumentLineCountDistribution {
3595 #[serde(default = "default_min_lines")]
3597 pub min_lines: u32,
3598 #[serde(default = "default_max_lines")]
3600 pub max_lines: u32,
3601 #[serde(default = "default_mode_lines")]
3603 pub mode_lines: u32,
3604}
3605
3606fn default_min_lines() -> u32 {
3607 1
3608}
3609
3610fn default_max_lines() -> u32 {
3611 20
3612}
3613
3614fn default_mode_lines() -> u32 {
3615 3
3616}
3617
3618impl Default for DocumentLineCountDistribution {
3619 fn default() -> Self {
3620 Self {
3621 min_lines: default_min_lines(),
3622 max_lines: default_max_lines(),
3623 mode_lines: default_mode_lines(),
3624 }
3625 }
3626}
3627
3628#[derive(Debug, Clone, Serialize, Deserialize)]
3630pub struct CashDiscountConfig {
3631 #[serde(default = "default_discount_eligible_rate")]
3633 pub eligible_rate: f64,
3634 #[serde(default = "default_discount_taken_rate")]
3636 pub taken_rate: f64,
3637 #[serde(default = "default_discount_percent")]
3639 pub discount_percent: f64,
3640 #[serde(default = "default_discount_days")]
3642 pub discount_days: u32,
3643}
3644
3645fn default_discount_eligible_rate() -> f64 {
3646 0.30
3647}
3648
3649fn default_discount_taken_rate() -> f64 {
3650 0.60
3651}
3652
3653fn default_discount_percent() -> f64 {
3654 0.02
3655}
3656
3657fn default_discount_days() -> u32 {
3658 10
3659}
3660
3661impl Default for CashDiscountConfig {
3662 fn default() -> Self {
3663 Self {
3664 eligible_rate: default_discount_eligible_rate(),
3665 taken_rate: default_discount_taken_rate(),
3666 discount_percent: default_discount_percent(),
3667 discount_days: default_discount_days(),
3668 }
3669 }
3670}
3671
3672#[derive(Debug, Clone, Serialize, Deserialize)]
3678pub struct IntercompanyConfig {
3679 #[serde(default)]
3681 pub enabled: bool,
3682 #[serde(default = "default_ic_transaction_rate")]
3684 pub ic_transaction_rate: f64,
3685 #[serde(default)]
3687 pub transfer_pricing_method: TransferPricingMethod,
3688 #[serde(default = "default_markup_percent")]
3690 pub markup_percent: f64,
3691 #[serde(default = "default_true")]
3693 pub generate_matched_pairs: bool,
3694 #[serde(default)]
3696 pub transaction_type_distribution: ICTransactionTypeDistribution,
3697 #[serde(default)]
3699 pub generate_eliminations: bool,
3700}
3701
3702fn default_ic_transaction_rate() -> f64 {
3703 0.15
3704}
3705
3706fn default_markup_percent() -> f64 {
3707 0.05
3708}
3709
3710impl Default for IntercompanyConfig {
3711 fn default() -> Self {
3712 Self {
3713 enabled: false,
3714 ic_transaction_rate: default_ic_transaction_rate(),
3715 transfer_pricing_method: TransferPricingMethod::default(),
3716 markup_percent: default_markup_percent(),
3717 generate_matched_pairs: true,
3718 transaction_type_distribution: ICTransactionTypeDistribution::default(),
3719 generate_eliminations: false,
3720 }
3721 }
3722}
3723
3724#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
3726#[serde(rename_all = "snake_case")]
3727pub enum TransferPricingMethod {
3728 #[default]
3730 CostPlus,
3731 ComparableUncontrolled,
3733 ResalePrice,
3735 TransactionalNetMargin,
3737 ProfitSplit,
3739}
3740
3741#[derive(Debug, Clone, Serialize, Deserialize)]
3743pub struct ICTransactionTypeDistribution {
3744 pub goods_sale: f64,
3746 pub service_provided: f64,
3748 pub loan: f64,
3750 pub dividend: f64,
3752 pub management_fee: f64,
3754 pub royalty: f64,
3756 pub cost_sharing: f64,
3758}
3759
3760impl Default for ICTransactionTypeDistribution {
3761 fn default() -> Self {
3762 Self {
3763 goods_sale: 0.35,
3764 service_provided: 0.20,
3765 loan: 0.10,
3766 dividend: 0.05,
3767 management_fee: 0.15,
3768 royalty: 0.10,
3769 cost_sharing: 0.05,
3770 }
3771 }
3772}
3773
3774#[derive(Debug, Clone, Serialize, Deserialize)]
3780pub struct BalanceConfig {
3781 #[serde(default)]
3783 pub generate_opening_balances: bool,
3784 #[serde(default = "default_true")]
3786 pub generate_trial_balances: bool,
3787 #[serde(default = "default_gross_margin")]
3789 pub target_gross_margin: f64,
3790 #[serde(default = "default_dso")]
3792 pub target_dso_days: u32,
3793 #[serde(default = "default_dpo")]
3795 pub target_dpo_days: u32,
3796 #[serde(default = "default_current_ratio")]
3798 pub target_current_ratio: f64,
3799 #[serde(default = "default_debt_equity")]
3801 pub target_debt_to_equity: f64,
3802 #[serde(default = "default_true")]
3804 pub validate_balance_equation: bool,
3805 #[serde(default = "default_true")]
3807 pub reconcile_subledgers: bool,
3808}
3809
3810fn default_gross_margin() -> f64 {
3811 0.35
3812}
3813
3814fn default_dso() -> u32 {
3815 45
3816}
3817
3818fn default_dpo() -> u32 {
3819 30
3820}
3821
3822fn default_current_ratio() -> f64 {
3823 1.5
3824}
3825
3826fn default_debt_equity() -> f64 {
3827 0.5
3828}
3829
3830impl Default for BalanceConfig {
3831 fn default() -> Self {
3832 Self {
3833 generate_opening_balances: false,
3834 generate_trial_balances: true,
3835 target_gross_margin: default_gross_margin(),
3836 target_dso_days: default_dso(),
3837 target_dpo_days: default_dpo(),
3838 target_current_ratio: default_current_ratio(),
3839 target_debt_to_equity: default_debt_equity(),
3840 validate_balance_equation: true,
3841 reconcile_subledgers: true,
3842 }
3843 }
3844}
3845
3846#[derive(Debug, Clone, Serialize, Deserialize)]
3855pub struct OcpmConfig {
3856 #[serde(default)]
3858 pub enabled: bool,
3859
3860 #[serde(default = "default_true")]
3862 pub generate_lifecycle_events: bool,
3863
3864 #[serde(default = "default_true")]
3866 pub include_object_relationships: bool,
3867
3868 #[serde(default = "default_true")]
3870 pub compute_variants: bool,
3871
3872 #[serde(default)]
3874 pub max_variants: usize,
3875
3876 #[serde(default)]
3878 pub p2p_process: OcpmProcessConfig,
3879
3880 #[serde(default)]
3882 pub o2c_process: OcpmProcessConfig,
3883
3884 #[serde(default)]
3886 pub output: OcpmOutputConfig,
3887}
3888
3889impl Default for OcpmConfig {
3890 fn default() -> Self {
3891 Self {
3892 enabled: false,
3893 generate_lifecycle_events: true,
3894 include_object_relationships: true,
3895 compute_variants: true,
3896 max_variants: 0,
3897 p2p_process: OcpmProcessConfig::default(),
3898 o2c_process: OcpmProcessConfig::default(),
3899 output: OcpmOutputConfig::default(),
3900 }
3901 }
3902}
3903
3904#[derive(Debug, Clone, Serialize, Deserialize)]
3906pub struct OcpmProcessConfig {
3907 #[serde(default = "default_rework_probability")]
3909 pub rework_probability: f64,
3910
3911 #[serde(default = "default_skip_probability")]
3913 pub skip_step_probability: f64,
3914
3915 #[serde(default = "default_out_of_order_probability")]
3917 pub out_of_order_probability: f64,
3918}
3919
3920fn default_rework_probability() -> f64 {
3924 0.15
3925}
3926
3927fn default_skip_probability() -> f64 {
3928 0.10
3929}
3930
3931fn default_out_of_order_probability() -> f64 {
3932 0.08
3933}
3934
3935impl Default for OcpmProcessConfig {
3936 fn default() -> Self {
3937 Self {
3938 rework_probability: default_rework_probability(),
3939 skip_step_probability: default_skip_probability(),
3940 out_of_order_probability: default_out_of_order_probability(),
3941 }
3942 }
3943}
3944
3945#[derive(Debug, Clone, Serialize, Deserialize)]
3947pub struct OcpmOutputConfig {
3948 #[serde(default = "default_true")]
3950 pub ocel_json: bool,
3951
3952 #[serde(default)]
3954 pub ocel_xml: bool,
3955
3956 #[serde(default)]
3958 pub xes: bool,
3959
3960 #[serde(default = "default_true")]
3962 pub xes_include_lifecycle: bool,
3963
3964 #[serde(default = "default_true")]
3966 pub xes_include_resources: bool,
3967
3968 #[serde(default = "default_true")]
3970 pub flattened_csv: bool,
3971
3972 #[serde(default = "default_true")]
3974 pub event_object_csv: bool,
3975
3976 #[serde(default = "default_true")]
3978 pub object_relationship_csv: bool,
3979
3980 #[serde(default = "default_true")]
3982 pub variants_csv: bool,
3983
3984 #[serde(default)]
3986 pub export_reference_models: bool,
3987}
3988
3989impl Default for OcpmOutputConfig {
3990 fn default() -> Self {
3991 Self {
3992 ocel_json: true,
3993 ocel_xml: false,
3994 xes: false,
3995 xes_include_lifecycle: true,
3996 xes_include_resources: true,
3997 flattened_csv: true,
3998 event_object_csv: true,
3999 object_relationship_csv: true,
4000 variants_csv: true,
4001 export_reference_models: false,
4002 }
4003 }
4004}
4005
4006#[derive(Debug, Clone, Serialize, Deserialize)]
4008pub struct AuditGenerationConfig {
4009 #[serde(default)]
4011 pub enabled: bool,
4012
4013 #[serde(default = "default_true")]
4016 pub generate_workpapers: bool,
4017
4018 #[serde(default)]
4021 pub engagement_types: AuditEngagementTypesConfig,
4022
4023 #[serde(default)]
4026 pub workpapers: WorkpaperConfig,
4027
4028 #[serde(default)]
4031 pub team: AuditTeamConfig,
4032
4033 #[serde(default)]
4036 pub review: ReviewWorkflowConfig,
4037
4038 #[serde(default)]
4040 pub fsm: Option<AuditFsmConfig>,
4041}
4042
4043impl Default for AuditGenerationConfig {
4044 fn default() -> Self {
4045 Self {
4046 enabled: false,
4047 generate_workpapers: true,
4048 engagement_types: AuditEngagementTypesConfig::default(),
4049 workpapers: WorkpaperConfig::default(),
4050 team: AuditTeamConfig::default(),
4051 review: ReviewWorkflowConfig::default(),
4052 fsm: None,
4053 }
4054 }
4055}
4056
4057#[derive(Debug, Clone, Serialize, Deserialize)]
4059pub struct AuditFsmConfig {
4060 #[serde(default)]
4062 pub enabled: bool,
4063
4064 #[serde(default = "default_audit_fsm_blueprint")]
4066 pub blueprint: String,
4067
4068 #[serde(default = "default_audit_fsm_overlay")]
4070 pub overlay: String,
4071
4072 #[serde(default)]
4074 pub depth: Option<String>,
4075
4076 #[serde(default)]
4078 pub discriminators: std::collections::HashMap<String, Vec<String>>,
4079
4080 #[serde(default)]
4082 pub event_trail: AuditEventTrailConfig,
4083
4084 #[serde(default)]
4086 pub seed: Option<u64>,
4087}
4088
4089impl Default for AuditFsmConfig {
4090 fn default() -> Self {
4091 Self {
4092 enabled: false,
4093 blueprint: default_audit_fsm_blueprint(),
4094 overlay: default_audit_fsm_overlay(),
4095 depth: None,
4096 discriminators: std::collections::HashMap::new(),
4097 event_trail: AuditEventTrailConfig::default(),
4098 seed: None,
4099 }
4100 }
4101}
4102
4103fn default_audit_fsm_blueprint() -> String {
4104 "builtin:fsa".to_string()
4105}
4106
4107fn default_audit_fsm_overlay() -> String {
4108 "builtin:default".to_string()
4109}
4110
4111#[derive(Debug, Clone, Serialize, Deserialize)]
4113pub struct AuditEventTrailConfig {
4114 #[serde(default = "default_true")]
4116 pub flat_log: bool,
4117 #[serde(default)]
4119 pub ocel_projection: bool,
4120}
4121
4122impl Default for AuditEventTrailConfig {
4123 fn default() -> Self {
4124 Self {
4125 flat_log: true,
4126 ocel_projection: false,
4127 }
4128 }
4129}
4130
4131#[derive(Debug, Clone, Serialize, Deserialize)]
4133pub struct AuditEngagementTypesConfig {
4134 #[serde(default = "default_financial_audit_prob")]
4136 pub financial_statement: f64,
4137 #[serde(default = "default_sox_audit_prob")]
4139 pub sox_icfr: f64,
4140 #[serde(default = "default_integrated_audit_prob")]
4142 pub integrated: f64,
4143 #[serde(default = "default_review_prob")]
4145 pub review: f64,
4146 #[serde(default = "default_aup_prob")]
4148 pub agreed_upon_procedures: f64,
4149}
4150
4151fn default_financial_audit_prob() -> f64 {
4152 0.40
4153}
4154fn default_sox_audit_prob() -> f64 {
4155 0.20
4156}
4157fn default_integrated_audit_prob() -> f64 {
4158 0.25
4159}
4160fn default_review_prob() -> f64 {
4161 0.10
4162}
4163fn default_aup_prob() -> f64 {
4164 0.05
4165}
4166
4167impl Default for AuditEngagementTypesConfig {
4168 fn default() -> Self {
4169 Self {
4170 financial_statement: default_financial_audit_prob(),
4171 sox_icfr: default_sox_audit_prob(),
4172 integrated: default_integrated_audit_prob(),
4173 review: default_review_prob(),
4174 agreed_upon_procedures: default_aup_prob(),
4175 }
4176 }
4177}
4178
4179#[derive(Debug, Clone, Serialize, Deserialize)]
4181pub struct WorkpaperConfig {
4182 #[serde(default = "default_workpapers_per_phase")]
4184 pub average_per_phase: usize,
4185
4186 #[serde(default = "default_true")]
4188 pub include_isa_references: bool,
4189
4190 #[serde(default = "default_true")]
4192 pub include_sample_details: bool,
4193
4194 #[serde(default = "default_true")]
4196 pub include_cross_references: bool,
4197
4198 #[serde(default)]
4200 pub sampling: SamplingConfig,
4201}
4202
4203fn default_workpapers_per_phase() -> usize {
4204 5
4205}
4206
4207impl Default for WorkpaperConfig {
4208 fn default() -> Self {
4209 Self {
4210 average_per_phase: default_workpapers_per_phase(),
4211 include_isa_references: true,
4212 include_sample_details: true,
4213 include_cross_references: true,
4214 sampling: SamplingConfig::default(),
4215 }
4216 }
4217}
4218
4219#[derive(Debug, Clone, Serialize, Deserialize)]
4221pub struct SamplingConfig {
4222 #[serde(default = "default_statistical_rate")]
4224 pub statistical_rate: f64,
4225 #[serde(default = "default_judgmental_rate")]
4227 pub judgmental_rate: f64,
4228 #[serde(default = "default_haphazard_rate")]
4230 pub haphazard_rate: f64,
4231 #[serde(default = "default_complete_examination_rate")]
4233 pub complete_examination_rate: f64,
4234}
4235
4236fn default_statistical_rate() -> f64 {
4237 0.40
4238}
4239fn default_judgmental_rate() -> f64 {
4240 0.30
4241}
4242fn default_haphazard_rate() -> f64 {
4243 0.20
4244}
4245fn default_complete_examination_rate() -> f64 {
4246 0.10
4247}
4248
4249impl Default for SamplingConfig {
4250 fn default() -> Self {
4251 Self {
4252 statistical_rate: default_statistical_rate(),
4253 judgmental_rate: default_judgmental_rate(),
4254 haphazard_rate: default_haphazard_rate(),
4255 complete_examination_rate: default_complete_examination_rate(),
4256 }
4257 }
4258}
4259
4260#[derive(Debug, Clone, Serialize, Deserialize)]
4262pub struct AuditTeamConfig {
4263 #[serde(default = "default_min_team_size")]
4265 pub min_team_size: usize,
4266 #[serde(default = "default_max_team_size")]
4268 pub max_team_size: usize,
4269 #[serde(default = "default_specialist_probability")]
4271 pub specialist_probability: f64,
4272}
4273
4274fn default_min_team_size() -> usize {
4275 3
4276}
4277fn default_max_team_size() -> usize {
4278 8
4279}
4280fn default_specialist_probability() -> f64 {
4281 0.30
4282}
4283
4284impl Default for AuditTeamConfig {
4285 fn default() -> Self {
4286 Self {
4287 min_team_size: default_min_team_size(),
4288 max_team_size: default_max_team_size(),
4289 specialist_probability: default_specialist_probability(),
4290 }
4291 }
4292}
4293
4294#[derive(Debug, Clone, Serialize, Deserialize)]
4296pub struct ReviewWorkflowConfig {
4297 #[serde(default = "default_review_delay_days")]
4299 pub average_review_delay_days: u32,
4300 #[serde(default = "default_rework_probability_review")]
4302 pub rework_probability: f64,
4303 #[serde(default = "default_true")]
4305 pub require_partner_signoff: bool,
4306}
4307
4308fn default_review_delay_days() -> u32 {
4309 2
4310}
4311fn default_rework_probability_review() -> f64 {
4312 0.15
4313}
4314
4315impl Default for ReviewWorkflowConfig {
4316 fn default() -> Self {
4317 Self {
4318 average_review_delay_days: default_review_delay_days(),
4319 rework_probability: default_rework_probability_review(),
4320 require_partner_signoff: true,
4321 }
4322 }
4323}
4324
4325#[derive(Debug, Clone, Serialize, Deserialize)]
4331pub struct DataQualitySchemaConfig {
4332 #[serde(default)]
4334 pub enabled: bool,
4335 #[serde(default)]
4337 pub preset: DataQualityPreset,
4338 #[serde(default)]
4340 pub missing_values: MissingValuesSchemaConfig,
4341 #[serde(default)]
4343 pub typos: TypoSchemaConfig,
4344 #[serde(default)]
4346 pub format_variations: FormatVariationSchemaConfig,
4347 #[serde(default)]
4349 pub duplicates: DuplicateSchemaConfig,
4350 #[serde(default)]
4352 pub encoding_issues: EncodingIssueSchemaConfig,
4353 #[serde(default)]
4355 pub generate_labels: bool,
4356 #[serde(default)]
4358 pub sink_profiles: SinkQualityProfiles,
4359}
4360
4361impl Default for DataQualitySchemaConfig {
4362 fn default() -> Self {
4363 Self {
4364 enabled: false,
4365 preset: DataQualityPreset::None,
4366 missing_values: MissingValuesSchemaConfig::default(),
4367 typos: TypoSchemaConfig::default(),
4368 format_variations: FormatVariationSchemaConfig::default(),
4369 duplicates: DuplicateSchemaConfig::default(),
4370 encoding_issues: EncodingIssueSchemaConfig::default(),
4371 generate_labels: true,
4372 sink_profiles: SinkQualityProfiles::default(),
4373 }
4374 }
4375}
4376
4377impl DataQualitySchemaConfig {
4378 pub fn with_preset(preset: DataQualityPreset) -> Self {
4380 let mut config = Self {
4381 preset,
4382 ..Default::default()
4383 };
4384 config.apply_preset();
4385 config
4386 }
4387
4388 pub fn apply_preset(&mut self) {
4391 if !self.preset.overrides_settings() {
4392 return;
4393 }
4394
4395 self.enabled = true;
4396
4397 self.missing_values.enabled = self.preset.missing_rate() > 0.0;
4399 self.missing_values.rate = self.preset.missing_rate();
4400
4401 self.typos.enabled = self.preset.typo_rate() > 0.0;
4403 self.typos.char_error_rate = self.preset.typo_rate();
4404
4405 self.duplicates.enabled = self.preset.duplicate_rate() > 0.0;
4407 self.duplicates.exact_duplicate_ratio = self.preset.duplicate_rate() * 0.4;
4408 self.duplicates.near_duplicate_ratio = self.preset.duplicate_rate() * 0.4;
4409 self.duplicates.fuzzy_duplicate_ratio = self.preset.duplicate_rate() * 0.2;
4410
4411 self.format_variations.enabled = self.preset.format_variations_enabled();
4413
4414 self.encoding_issues.enabled = self.preset.encoding_issues_enabled();
4416 self.encoding_issues.rate = self.preset.encoding_issue_rate();
4417
4418 if self.preset.ocr_errors_enabled() {
4420 self.typos.type_weights.ocr_errors = 0.3;
4421 }
4422 }
4423
4424 pub fn effective_missing_rate(&self) -> f64 {
4426 if self.preset.overrides_settings() {
4427 self.preset.missing_rate()
4428 } else {
4429 self.missing_values.rate
4430 }
4431 }
4432
4433 pub fn effective_typo_rate(&self) -> f64 {
4435 if self.preset.overrides_settings() {
4436 self.preset.typo_rate()
4437 } else {
4438 self.typos.char_error_rate
4439 }
4440 }
4441
4442 pub fn effective_duplicate_rate(&self) -> f64 {
4444 if self.preset.overrides_settings() {
4445 self.preset.duplicate_rate()
4446 } else {
4447 self.duplicates.exact_duplicate_ratio
4448 + self.duplicates.near_duplicate_ratio
4449 + self.duplicates.fuzzy_duplicate_ratio
4450 }
4451 }
4452
4453 pub fn clean() -> Self {
4455 Self::with_preset(DataQualityPreset::Clean)
4456 }
4457
4458 pub fn noisy() -> Self {
4460 Self::with_preset(DataQualityPreset::Noisy)
4461 }
4462
4463 pub fn legacy() -> Self {
4465 Self::with_preset(DataQualityPreset::Legacy)
4466 }
4467}
4468
4469#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
4471#[serde(rename_all = "snake_case")]
4472pub enum DataQualityPreset {
4473 #[default]
4475 None,
4476 Minimal,
4478 Normal,
4480 High,
4482 Custom,
4484
4485 Clean,
4491 Noisy,
4494 Legacy,
4497}
4498
4499impl DataQualityPreset {
4500 pub fn missing_rate(&self) -> f64 {
4502 match self {
4503 DataQualityPreset::None => 0.0,
4504 DataQualityPreset::Minimal => 0.005,
4505 DataQualityPreset::Normal => 0.02,
4506 DataQualityPreset::High => 0.08,
4507 DataQualityPreset::Custom => 0.01, DataQualityPreset::Clean => 0.001,
4509 DataQualityPreset::Noisy => 0.05,
4510 DataQualityPreset::Legacy => 0.10,
4511 }
4512 }
4513
4514 pub fn typo_rate(&self) -> f64 {
4516 match self {
4517 DataQualityPreset::None => 0.0,
4518 DataQualityPreset::Minimal => 0.0005,
4519 DataQualityPreset::Normal => 0.002,
4520 DataQualityPreset::High => 0.01,
4521 DataQualityPreset::Custom => 0.001, DataQualityPreset::Clean => 0.0005,
4523 DataQualityPreset::Noisy => 0.02,
4524 DataQualityPreset::Legacy => 0.05,
4525 }
4526 }
4527
4528 pub fn duplicate_rate(&self) -> f64 {
4530 match self {
4531 DataQualityPreset::None => 0.0,
4532 DataQualityPreset::Minimal => 0.001,
4533 DataQualityPreset::Normal => 0.005,
4534 DataQualityPreset::High => 0.02,
4535 DataQualityPreset::Custom => 0.0, DataQualityPreset::Clean => 0.0,
4537 DataQualityPreset::Noisy => 0.01,
4538 DataQualityPreset::Legacy => 0.03,
4539 }
4540 }
4541
4542 pub fn format_variations_enabled(&self) -> bool {
4544 match self {
4545 DataQualityPreset::None | DataQualityPreset::Clean => false,
4546 DataQualityPreset::Minimal => true,
4547 DataQualityPreset::Normal => true,
4548 DataQualityPreset::High => true,
4549 DataQualityPreset::Custom => true,
4550 DataQualityPreset::Noisy => true,
4551 DataQualityPreset::Legacy => true,
4552 }
4553 }
4554
4555 pub fn ocr_errors_enabled(&self) -> bool {
4557 matches!(self, DataQualityPreset::Legacy | DataQualityPreset::High)
4558 }
4559
4560 pub fn encoding_issues_enabled(&self) -> bool {
4562 matches!(
4563 self,
4564 DataQualityPreset::Legacy | DataQualityPreset::High | DataQualityPreset::Noisy
4565 )
4566 }
4567
4568 pub fn encoding_issue_rate(&self) -> f64 {
4570 match self {
4571 DataQualityPreset::None | DataQualityPreset::Clean | DataQualityPreset::Minimal => 0.0,
4572 DataQualityPreset::Normal => 0.002,
4573 DataQualityPreset::High => 0.01,
4574 DataQualityPreset::Custom => 0.0,
4575 DataQualityPreset::Noisy => 0.005,
4576 DataQualityPreset::Legacy => 0.02,
4577 }
4578 }
4579
4580 pub fn overrides_settings(&self) -> bool {
4582 !matches!(self, DataQualityPreset::Custom | DataQualityPreset::None)
4583 }
4584
4585 pub fn description(&self) -> &'static str {
4587 match self {
4588 DataQualityPreset::None => "No data quality issues (pristine data)",
4589 DataQualityPreset::Minimal => "Very rare data quality issues",
4590 DataQualityPreset::Normal => "Realistic enterprise data quality",
4591 DataQualityPreset::High => "Messy data for stress testing",
4592 DataQualityPreset::Custom => "Custom settings from configuration",
4593 DataQualityPreset::Clean => "ML-ready clean data with minimal issues",
4594 DataQualityPreset::Noisy => "Typical production data with moderate issues",
4595 DataQualityPreset::Legacy => "Legacy/migrated data with heavy issues and OCR errors",
4596 }
4597 }
4598}
4599
4600#[derive(Debug, Clone, Serialize, Deserialize)]
4602pub struct MissingValuesSchemaConfig {
4603 #[serde(default)]
4605 pub enabled: bool,
4606 #[serde(default = "default_missing_rate")]
4608 pub rate: f64,
4609 #[serde(default)]
4611 pub strategy: MissingValueStrategy,
4612 #[serde(default)]
4614 pub field_rates: std::collections::HashMap<String, f64>,
4615 #[serde(default)]
4617 pub protected_fields: Vec<String>,
4618}
4619
4620fn default_missing_rate() -> f64 {
4621 0.01
4622}
4623
4624impl Default for MissingValuesSchemaConfig {
4625 fn default() -> Self {
4626 Self {
4627 enabled: false,
4628 rate: default_missing_rate(),
4629 strategy: MissingValueStrategy::Mcar,
4630 field_rates: std::collections::HashMap::new(),
4631 protected_fields: vec![
4632 "document_id".to_string(),
4633 "company_code".to_string(),
4634 "posting_date".to_string(),
4635 ],
4636 }
4637 }
4638}
4639
4640#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
4642#[serde(rename_all = "snake_case")]
4643pub enum MissingValueStrategy {
4644 #[default]
4646 Mcar,
4647 Mar,
4649 Mnar,
4651 Systematic,
4653}
4654
4655#[derive(Debug, Clone, Serialize, Deserialize)]
4657pub struct TypoSchemaConfig {
4658 #[serde(default)]
4660 pub enabled: bool,
4661 #[serde(default = "default_typo_rate")]
4663 pub char_error_rate: f64,
4664 #[serde(default)]
4666 pub type_weights: TypoTypeWeights,
4667 #[serde(default)]
4669 pub protected_fields: Vec<String>,
4670}
4671
4672fn default_typo_rate() -> f64 {
4673 0.001
4674}
4675
4676impl Default for TypoSchemaConfig {
4677 fn default() -> Self {
4678 Self {
4679 enabled: false,
4680 char_error_rate: default_typo_rate(),
4681 type_weights: TypoTypeWeights::default(),
4682 protected_fields: vec![
4683 "document_id".to_string(),
4684 "gl_account".to_string(),
4685 "company_code".to_string(),
4686 ],
4687 }
4688 }
4689}
4690
4691#[derive(Debug, Clone, Serialize, Deserialize)]
4693pub struct TypoTypeWeights {
4694 #[serde(default = "default_substitution_weight")]
4696 pub substitution: f64,
4697 #[serde(default = "default_transposition_weight")]
4699 pub transposition: f64,
4700 #[serde(default = "default_insertion_weight")]
4702 pub insertion: f64,
4703 #[serde(default = "default_deletion_weight")]
4705 pub deletion: f64,
4706 #[serde(default = "default_ocr_weight")]
4708 pub ocr_errors: f64,
4709 #[serde(default = "default_homophone_weight")]
4711 pub homophones: f64,
4712}
4713
4714fn default_substitution_weight() -> f64 {
4715 0.35
4716}
4717fn default_transposition_weight() -> f64 {
4718 0.25
4719}
4720fn default_insertion_weight() -> f64 {
4721 0.10
4722}
4723fn default_deletion_weight() -> f64 {
4724 0.15
4725}
4726fn default_ocr_weight() -> f64 {
4727 0.10
4728}
4729fn default_homophone_weight() -> f64 {
4730 0.05
4731}
4732
4733impl Default for TypoTypeWeights {
4734 fn default() -> Self {
4735 Self {
4736 substitution: default_substitution_weight(),
4737 transposition: default_transposition_weight(),
4738 insertion: default_insertion_weight(),
4739 deletion: default_deletion_weight(),
4740 ocr_errors: default_ocr_weight(),
4741 homophones: default_homophone_weight(),
4742 }
4743 }
4744}
4745
4746#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4748pub struct FormatVariationSchemaConfig {
4749 #[serde(default)]
4751 pub enabled: bool,
4752 #[serde(default)]
4754 pub dates: DateFormatVariationConfig,
4755 #[serde(default)]
4757 pub amounts: AmountFormatVariationConfig,
4758 #[serde(default)]
4760 pub identifiers: IdentifierFormatVariationConfig,
4761}
4762
4763#[derive(Debug, Clone, Serialize, Deserialize)]
4765pub struct DateFormatVariationConfig {
4766 #[serde(default)]
4768 pub enabled: bool,
4769 #[serde(default = "default_date_variation_rate")]
4771 pub rate: f64,
4772 #[serde(default = "default_true")]
4774 pub iso_format: bool,
4775 #[serde(default)]
4777 pub us_format: bool,
4778 #[serde(default)]
4780 pub eu_format: bool,
4781 #[serde(default)]
4783 pub long_format: bool,
4784}
4785
4786fn default_date_variation_rate() -> f64 {
4787 0.05
4788}
4789
4790impl Default for DateFormatVariationConfig {
4791 fn default() -> Self {
4792 Self {
4793 enabled: false,
4794 rate: default_date_variation_rate(),
4795 iso_format: true,
4796 us_format: false,
4797 eu_format: false,
4798 long_format: false,
4799 }
4800 }
4801}
4802
4803#[derive(Debug, Clone, Serialize, Deserialize)]
4805pub struct AmountFormatVariationConfig {
4806 #[serde(default)]
4808 pub enabled: bool,
4809 #[serde(default = "default_amount_variation_rate")]
4811 pub rate: f64,
4812 #[serde(default)]
4814 pub us_comma_format: bool,
4815 #[serde(default)]
4817 pub eu_format: bool,
4818 #[serde(default)]
4820 pub currency_prefix: bool,
4821 #[serde(default)]
4823 pub accounting_format: bool,
4824}
4825
4826fn default_amount_variation_rate() -> f64 {
4827 0.02
4828}
4829
4830impl Default for AmountFormatVariationConfig {
4831 fn default() -> Self {
4832 Self {
4833 enabled: false,
4834 rate: default_amount_variation_rate(),
4835 us_comma_format: false,
4836 eu_format: false,
4837 currency_prefix: false,
4838 accounting_format: false,
4839 }
4840 }
4841}
4842
4843#[derive(Debug, Clone, Serialize, Deserialize)]
4845pub struct IdentifierFormatVariationConfig {
4846 #[serde(default)]
4848 pub enabled: bool,
4849 #[serde(default = "default_identifier_variation_rate")]
4851 pub rate: f64,
4852 #[serde(default)]
4854 pub case_variations: bool,
4855 #[serde(default)]
4857 pub padding_variations: bool,
4858 #[serde(default)]
4860 pub separator_variations: bool,
4861}
4862
4863fn default_identifier_variation_rate() -> f64 {
4864 0.02
4865}
4866
4867impl Default for IdentifierFormatVariationConfig {
4868 fn default() -> Self {
4869 Self {
4870 enabled: false,
4871 rate: default_identifier_variation_rate(),
4872 case_variations: false,
4873 padding_variations: false,
4874 separator_variations: false,
4875 }
4876 }
4877}
4878
4879#[derive(Debug, Clone, Serialize, Deserialize)]
4881pub struct DuplicateSchemaConfig {
4882 #[serde(default)]
4884 pub enabled: bool,
4885 #[serde(default = "default_duplicate_rate")]
4887 pub rate: f64,
4888 #[serde(default = "default_exact_duplicate_ratio")]
4890 pub exact_duplicate_ratio: f64,
4891 #[serde(default = "default_near_duplicate_ratio")]
4893 pub near_duplicate_ratio: f64,
4894 #[serde(default = "default_fuzzy_duplicate_ratio")]
4896 pub fuzzy_duplicate_ratio: f64,
4897 #[serde(default = "default_max_date_offset")]
4899 pub max_date_offset_days: u32,
4900 #[serde(default = "default_max_amount_variance")]
4902 pub max_amount_variance: f64,
4903}
4904
4905fn default_duplicate_rate() -> f64 {
4906 0.005
4907}
4908fn default_exact_duplicate_ratio() -> f64 {
4909 0.4
4910}
4911fn default_near_duplicate_ratio() -> f64 {
4912 0.35
4913}
4914fn default_fuzzy_duplicate_ratio() -> f64 {
4915 0.25
4916}
4917fn default_max_date_offset() -> u32 {
4918 3
4919}
4920fn default_max_amount_variance() -> f64 {
4921 0.01
4922}
4923
4924impl Default for DuplicateSchemaConfig {
4925 fn default() -> Self {
4926 Self {
4927 enabled: false,
4928 rate: default_duplicate_rate(),
4929 exact_duplicate_ratio: default_exact_duplicate_ratio(),
4930 near_duplicate_ratio: default_near_duplicate_ratio(),
4931 fuzzy_duplicate_ratio: default_fuzzy_duplicate_ratio(),
4932 max_date_offset_days: default_max_date_offset(),
4933 max_amount_variance: default_max_amount_variance(),
4934 }
4935 }
4936}
4937
4938#[derive(Debug, Clone, Serialize, Deserialize)]
4940pub struct EncodingIssueSchemaConfig {
4941 #[serde(default)]
4943 pub enabled: bool,
4944 #[serde(default = "default_encoding_rate")]
4946 pub rate: f64,
4947 #[serde(default)]
4949 pub mojibake: bool,
4950 #[serde(default)]
4952 pub html_entities: bool,
4953 #[serde(default)]
4955 pub bom_issues: bool,
4956}
4957
4958fn default_encoding_rate() -> f64 {
4959 0.001
4960}
4961
4962impl Default for EncodingIssueSchemaConfig {
4963 fn default() -> Self {
4964 Self {
4965 enabled: false,
4966 rate: default_encoding_rate(),
4967 mojibake: false,
4968 html_entities: false,
4969 bom_issues: false,
4970 }
4971 }
4972}
4973
4974#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4976pub struct SinkQualityProfiles {
4977 #[serde(default)]
4979 pub csv: Option<SinkQualityOverride>,
4980 #[serde(default)]
4982 pub json: Option<SinkQualityOverride>,
4983 #[serde(default)]
4985 pub parquet: Option<SinkQualityOverride>,
4986}
4987
4988#[derive(Debug, Clone, Serialize, Deserialize)]
4990pub struct SinkQualityOverride {
4991 pub enabled: Option<bool>,
4993 pub missing_rate: Option<f64>,
4995 pub typo_rate: Option<f64>,
4997 pub format_variation_rate: Option<f64>,
4999 pub duplicate_rate: Option<f64>,
5001}
5002
5003#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5015pub struct AccountingStandardsConfig {
5016 #[serde(default)]
5018 pub enabled: bool,
5019
5020 #[serde(default, skip_serializing_if = "Option::is_none")]
5024 pub framework: Option<AccountingFrameworkConfig>,
5025
5026 #[serde(default)]
5028 pub revenue_recognition: RevenueRecognitionConfig,
5029
5030 #[serde(default)]
5032 pub leases: LeaseAccountingConfig,
5033
5034 #[serde(default)]
5036 pub fair_value: FairValueConfig,
5037
5038 #[serde(default)]
5040 pub impairment: ImpairmentConfig,
5041
5042 #[serde(default)]
5044 pub business_combinations: BusinessCombinationsConfig,
5045
5046 #[serde(default)]
5048 pub expected_credit_loss: EclConfig,
5049
5050 #[serde(default)]
5052 pub generate_differences: bool,
5053}
5054
5055#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5057#[serde(rename_all = "snake_case")]
5058pub enum AccountingFrameworkConfig {
5059 #[default]
5061 UsGaap,
5062 Ifrs,
5064 DualReporting,
5066 FrenchGaap,
5068 GermanGaap,
5070}
5071
5072#[derive(Debug, Clone, Serialize, Deserialize)]
5074pub struct RevenueRecognitionConfig {
5075 #[serde(default)]
5077 pub enabled: bool,
5078
5079 #[serde(default = "default_true")]
5081 pub generate_contracts: bool,
5082
5083 #[serde(default = "default_avg_obligations")]
5085 pub avg_obligations_per_contract: f64,
5086
5087 #[serde(default = "default_variable_consideration_rate")]
5089 pub variable_consideration_rate: f64,
5090
5091 #[serde(default = "default_over_time_rate")]
5093 pub over_time_recognition_rate: f64,
5094
5095 #[serde(default = "default_contract_count")]
5097 pub contract_count: usize,
5098}
5099
5100fn default_avg_obligations() -> f64 {
5101 2.0
5102}
5103
5104fn default_variable_consideration_rate() -> f64 {
5105 0.15
5106}
5107
5108fn default_over_time_rate() -> f64 {
5109 0.30
5110}
5111
5112fn default_contract_count() -> usize {
5113 100
5114}
5115
5116impl Default for RevenueRecognitionConfig {
5117 fn default() -> Self {
5118 Self {
5119 enabled: false,
5120 generate_contracts: true,
5121 avg_obligations_per_contract: default_avg_obligations(),
5122 variable_consideration_rate: default_variable_consideration_rate(),
5123 over_time_recognition_rate: default_over_time_rate(),
5124 contract_count: default_contract_count(),
5125 }
5126 }
5127}
5128
5129#[derive(Debug, Clone, Serialize, Deserialize)]
5131pub struct LeaseAccountingConfig {
5132 #[serde(default)]
5134 pub enabled: bool,
5135
5136 #[serde(default = "default_lease_count")]
5138 pub lease_count: usize,
5139
5140 #[serde(default = "default_finance_lease_pct")]
5142 pub finance_lease_percent: f64,
5143
5144 #[serde(default = "default_avg_lease_term")]
5146 pub avg_lease_term_months: u32,
5147
5148 #[serde(default = "default_true")]
5150 pub generate_amortization: bool,
5151
5152 #[serde(default = "default_real_estate_pct")]
5154 pub real_estate_percent: f64,
5155}
5156
5157fn default_lease_count() -> usize {
5158 50
5159}
5160
5161fn default_finance_lease_pct() -> f64 {
5162 0.30
5163}
5164
5165fn default_avg_lease_term() -> u32 {
5166 60
5167}
5168
5169fn default_real_estate_pct() -> f64 {
5170 0.40
5171}
5172
5173impl Default for LeaseAccountingConfig {
5174 fn default() -> Self {
5175 Self {
5176 enabled: false,
5177 lease_count: default_lease_count(),
5178 finance_lease_percent: default_finance_lease_pct(),
5179 avg_lease_term_months: default_avg_lease_term(),
5180 generate_amortization: true,
5181 real_estate_percent: default_real_estate_pct(),
5182 }
5183 }
5184}
5185
5186#[derive(Debug, Clone, Serialize, Deserialize)]
5188pub struct FairValueConfig {
5189 #[serde(default)]
5191 pub enabled: bool,
5192
5193 #[serde(default = "default_fv_count")]
5195 pub measurement_count: usize,
5196
5197 #[serde(default = "default_level1_pct")]
5199 pub level1_percent: f64,
5200
5201 #[serde(default = "default_level2_pct")]
5203 pub level2_percent: f64,
5204
5205 #[serde(default = "default_level3_pct")]
5207 pub level3_percent: f64,
5208
5209 #[serde(default)]
5211 pub include_sensitivity_analysis: bool,
5212}
5213
5214fn default_fv_count() -> usize {
5215 25
5216}
5217
5218fn default_level1_pct() -> f64 {
5219 0.40
5220}
5221
5222fn default_level2_pct() -> f64 {
5223 0.35
5224}
5225
5226fn default_level3_pct() -> f64 {
5227 0.25
5228}
5229
5230impl Default for FairValueConfig {
5231 fn default() -> Self {
5232 Self {
5233 enabled: false,
5234 measurement_count: default_fv_count(),
5235 level1_percent: default_level1_pct(),
5236 level2_percent: default_level2_pct(),
5237 level3_percent: default_level3_pct(),
5238 include_sensitivity_analysis: false,
5239 }
5240 }
5241}
5242
5243#[derive(Debug, Clone, Serialize, Deserialize)]
5245pub struct ImpairmentConfig {
5246 #[serde(default)]
5248 pub enabled: bool,
5249
5250 #[serde(default = "default_impairment_count")]
5252 pub test_count: usize,
5253
5254 #[serde(default = "default_impairment_rate")]
5256 pub impairment_rate: f64,
5257
5258 #[serde(default = "default_true")]
5260 pub generate_projections: bool,
5261
5262 #[serde(default)]
5264 pub include_goodwill: bool,
5265}
5266
5267fn default_impairment_count() -> usize {
5268 15
5269}
5270
5271fn default_impairment_rate() -> f64 {
5272 0.10
5273}
5274
5275impl Default for ImpairmentConfig {
5276 fn default() -> Self {
5277 Self {
5278 enabled: false,
5279 test_count: default_impairment_count(),
5280 impairment_rate: default_impairment_rate(),
5281 generate_projections: true,
5282 include_goodwill: false,
5283 }
5284 }
5285}
5286
5287#[derive(Debug, Clone, Serialize, Deserialize)]
5293pub struct BusinessCombinationsConfig {
5294 #[serde(default)]
5296 pub enabled: bool,
5297
5298 #[serde(default = "default_bc_acquisition_count")]
5300 pub acquisition_count: usize,
5301}
5302
5303fn default_bc_acquisition_count() -> usize {
5304 2
5305}
5306
5307impl Default for BusinessCombinationsConfig {
5308 fn default() -> Self {
5309 Self {
5310 enabled: false,
5311 acquisition_count: default_bc_acquisition_count(),
5312 }
5313 }
5314}
5315
5316#[derive(Debug, Clone, Serialize, Deserialize)]
5322pub struct EclConfig {
5323 #[serde(default)]
5325 pub enabled: bool,
5326
5327 #[serde(default = "default_ecl_base_weight")]
5329 pub base_scenario_weight: f64,
5330
5331 #[serde(default = "default_ecl_base_multiplier")]
5333 pub base_scenario_multiplier: f64,
5334
5335 #[serde(default = "default_ecl_optimistic_weight")]
5337 pub optimistic_scenario_weight: f64,
5338
5339 #[serde(default = "default_ecl_optimistic_multiplier")]
5341 pub optimistic_scenario_multiplier: f64,
5342
5343 #[serde(default = "default_ecl_pessimistic_weight")]
5345 pub pessimistic_scenario_weight: f64,
5346
5347 #[serde(default = "default_ecl_pessimistic_multiplier")]
5349 pub pessimistic_scenario_multiplier: f64,
5350}
5351
5352fn default_ecl_base_weight() -> f64 {
5353 0.50
5354}
5355fn default_ecl_base_multiplier() -> f64 {
5356 1.0
5357}
5358fn default_ecl_optimistic_weight() -> f64 {
5359 0.30
5360}
5361fn default_ecl_optimistic_multiplier() -> f64 {
5362 0.8
5363}
5364fn default_ecl_pessimistic_weight() -> f64 {
5365 0.20
5366}
5367fn default_ecl_pessimistic_multiplier() -> f64 {
5368 1.4
5369}
5370
5371impl Default for EclConfig {
5372 fn default() -> Self {
5373 Self {
5374 enabled: false,
5375 base_scenario_weight: default_ecl_base_weight(),
5376 base_scenario_multiplier: default_ecl_base_multiplier(),
5377 optimistic_scenario_weight: default_ecl_optimistic_weight(),
5378 optimistic_scenario_multiplier: default_ecl_optimistic_multiplier(),
5379 pessimistic_scenario_weight: default_ecl_pessimistic_weight(),
5380 pessimistic_scenario_multiplier: default_ecl_pessimistic_multiplier(),
5381 }
5382 }
5383}
5384
5385#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5398pub struct AuditStandardsConfig {
5399 #[serde(default)]
5401 pub enabled: bool,
5402
5403 #[serde(default)]
5405 pub isa_compliance: IsaComplianceConfig,
5406
5407 #[serde(default)]
5409 pub analytical_procedures: AnalyticalProceduresConfig,
5410
5411 #[serde(default)]
5413 pub confirmations: ConfirmationsConfig,
5414
5415 #[serde(default)]
5417 pub opinion: AuditOpinionConfig,
5418
5419 #[serde(default)]
5421 pub generate_audit_trail: bool,
5422
5423 #[serde(default)]
5425 pub sox: SoxComplianceConfig,
5426
5427 #[serde(default)]
5429 pub pcaob: PcaobConfig,
5430}
5431
5432#[derive(Debug, Clone, Serialize, Deserialize)]
5434pub struct IsaComplianceConfig {
5435 #[serde(default)]
5437 pub enabled: bool,
5438
5439 #[serde(default = "default_compliance_level")]
5441 pub compliance_level: String,
5442
5443 #[serde(default = "default_true")]
5445 pub generate_isa_mappings: bool,
5446
5447 #[serde(default = "default_true")]
5449 pub generate_coverage_summary: bool,
5450
5451 #[serde(default)]
5453 pub include_pcaob: bool,
5454
5455 #[serde(default = "default_audit_framework")]
5457 pub framework: String,
5458}
5459
5460fn default_compliance_level() -> String {
5461 "standard".to_string()
5462}
5463
5464fn default_audit_framework() -> String {
5465 "isa".to_string()
5466}
5467
5468impl Default for IsaComplianceConfig {
5469 fn default() -> Self {
5470 Self {
5471 enabled: false,
5472 compliance_level: default_compliance_level(),
5473 generate_isa_mappings: true,
5474 generate_coverage_summary: true,
5475 include_pcaob: false,
5476 framework: default_audit_framework(),
5477 }
5478 }
5479}
5480
5481#[derive(Debug, Clone, Serialize, Deserialize)]
5483pub struct AnalyticalProceduresConfig {
5484 #[serde(default)]
5486 pub enabled: bool,
5487
5488 #[serde(default = "default_procedures_per_account")]
5490 pub procedures_per_account: usize,
5491
5492 #[serde(default = "default_variance_probability")]
5494 pub variance_probability: f64,
5495
5496 #[serde(default = "default_true")]
5498 pub generate_investigations: bool,
5499
5500 #[serde(default = "default_true")]
5502 pub include_ratio_analysis: bool,
5503}
5504
5505fn default_procedures_per_account() -> usize {
5506 3
5507}
5508
5509fn default_variance_probability() -> f64 {
5510 0.20
5511}
5512
5513impl Default for AnalyticalProceduresConfig {
5514 fn default() -> Self {
5515 Self {
5516 enabled: false,
5517 procedures_per_account: default_procedures_per_account(),
5518 variance_probability: default_variance_probability(),
5519 generate_investigations: true,
5520 include_ratio_analysis: true,
5521 }
5522 }
5523}
5524
5525#[derive(Debug, Clone, Serialize, Deserialize)]
5527pub struct ConfirmationsConfig {
5528 #[serde(default)]
5530 pub enabled: bool,
5531
5532 #[serde(default = "default_confirmation_count")]
5534 pub confirmation_count: usize,
5535
5536 #[serde(default = "default_positive_response_rate")]
5538 pub positive_response_rate: f64,
5539
5540 #[serde(default = "default_exception_rate_confirm")]
5542 pub exception_rate: f64,
5543
5544 #[serde(default = "default_non_response_rate")]
5546 pub non_response_rate: f64,
5547
5548 #[serde(default = "default_true")]
5550 pub generate_alternative_procedures: bool,
5551}
5552
5553fn default_confirmation_count() -> usize {
5554 50
5555}
5556
5557fn default_positive_response_rate() -> f64 {
5558 0.85
5559}
5560
5561fn default_exception_rate_confirm() -> f64 {
5562 0.10
5563}
5564
5565fn default_non_response_rate() -> f64 {
5566 0.05
5567}
5568
5569impl Default for ConfirmationsConfig {
5570 fn default() -> Self {
5571 Self {
5572 enabled: false,
5573 confirmation_count: default_confirmation_count(),
5574 positive_response_rate: default_positive_response_rate(),
5575 exception_rate: default_exception_rate_confirm(),
5576 non_response_rate: default_non_response_rate(),
5577 generate_alternative_procedures: true,
5578 }
5579 }
5580}
5581
5582#[derive(Debug, Clone, Serialize, Deserialize)]
5584pub struct AuditOpinionConfig {
5585 #[serde(default)]
5587 pub enabled: bool,
5588
5589 #[serde(default = "default_true")]
5591 pub generate_kam: bool,
5592
5593 #[serde(default = "default_kam_count")]
5595 pub average_kam_count: usize,
5596
5597 #[serde(default = "default_modified_opinion_rate")]
5599 pub modified_opinion_rate: f64,
5600
5601 #[serde(default)]
5603 pub include_emphasis_of_matter: bool,
5604
5605 #[serde(default = "default_true")]
5607 pub include_going_concern: bool,
5608}
5609
5610fn default_kam_count() -> usize {
5611 3
5612}
5613
5614fn default_modified_opinion_rate() -> f64 {
5615 0.05
5616}
5617
5618impl Default for AuditOpinionConfig {
5619 fn default() -> Self {
5620 Self {
5621 enabled: false,
5622 generate_kam: true,
5623 average_kam_count: default_kam_count(),
5624 modified_opinion_rate: default_modified_opinion_rate(),
5625 include_emphasis_of_matter: false,
5626 include_going_concern: true,
5627 }
5628 }
5629}
5630
5631#[derive(Debug, Clone, Serialize, Deserialize)]
5633pub struct SoxComplianceConfig {
5634 #[serde(default)]
5636 pub enabled: bool,
5637
5638 #[serde(default = "default_true")]
5640 pub generate_302_certifications: bool,
5641
5642 #[serde(default = "default_true")]
5644 pub generate_404_assessments: bool,
5645
5646 #[serde(default = "default_sox_materiality_threshold")]
5648 pub materiality_threshold: f64,
5649
5650 #[serde(default = "default_material_weakness_rate")]
5652 pub material_weakness_rate: f64,
5653
5654 #[serde(default = "default_significant_deficiency_rate")]
5656 pub significant_deficiency_rate: f64,
5657}
5658
5659fn default_material_weakness_rate() -> f64 {
5660 0.02
5661}
5662
5663fn default_significant_deficiency_rate() -> f64 {
5664 0.08
5665}
5666
5667impl Default for SoxComplianceConfig {
5668 fn default() -> Self {
5669 Self {
5670 enabled: false,
5671 generate_302_certifications: true,
5672 generate_404_assessments: true,
5673 materiality_threshold: default_sox_materiality_threshold(),
5674 material_weakness_rate: default_material_weakness_rate(),
5675 significant_deficiency_rate: default_significant_deficiency_rate(),
5676 }
5677 }
5678}
5679
5680#[derive(Debug, Clone, Serialize, Deserialize)]
5682pub struct PcaobConfig {
5683 #[serde(default)]
5685 pub enabled: bool,
5686
5687 #[serde(default)]
5689 pub is_pcaob_audit: bool,
5690
5691 #[serde(default = "default_true")]
5693 pub generate_cam: bool,
5694
5695 #[serde(default)]
5697 pub include_icfr_opinion: bool,
5698
5699 #[serde(default)]
5701 pub generate_standard_mappings: bool,
5702}
5703
5704impl Default for PcaobConfig {
5705 fn default() -> Self {
5706 Self {
5707 enabled: false,
5708 is_pcaob_audit: false,
5709 generate_cam: true,
5710 include_icfr_opinion: false,
5711 generate_standard_mappings: false,
5712 }
5713 }
5714}
5715
5716#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5729pub struct AdvancedDistributionConfig {
5730 #[serde(default)]
5732 pub enabled: bool,
5733
5734 #[serde(default)]
5736 pub amounts: MixtureDistributionSchemaConfig,
5737
5738 #[serde(default)]
5740 pub correlations: CorrelationSchemaConfig,
5741
5742 #[serde(default)]
5744 pub conditional: Vec<ConditionalDistributionSchemaConfig>,
5745
5746 #[serde(default)]
5748 pub regime_changes: RegimeChangeSchemaConfig,
5749
5750 #[serde(default)]
5752 pub industry_profile: Option<IndustryProfileType>,
5753
5754 #[serde(default)]
5756 pub validation: StatisticalValidationSchemaConfig,
5757}
5758
5759#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
5761#[serde(rename_all = "snake_case")]
5762pub enum IndustryProfileType {
5763 Retail,
5765 Manufacturing,
5767 FinancialServices,
5769 Healthcare,
5771 Technology,
5773}
5774
5775#[derive(Debug, Clone, Serialize, Deserialize)]
5777pub struct MixtureDistributionSchemaConfig {
5778 #[serde(default)]
5780 pub enabled: bool,
5781
5782 #[serde(default = "default_mixture_type")]
5784 pub distribution_type: MixtureDistributionType,
5785
5786 #[serde(default)]
5788 pub components: Vec<MixtureComponentConfig>,
5789
5790 #[serde(default = "default_min_amount")]
5792 pub min_value: f64,
5793
5794 #[serde(default)]
5796 pub max_value: Option<f64>,
5797
5798 #[serde(default = "default_decimal_places")]
5800 pub decimal_places: u8,
5801}
5802
5803fn default_mixture_type() -> MixtureDistributionType {
5804 MixtureDistributionType::LogNormal
5805}
5806
5807fn default_min_amount() -> f64 {
5808 0.01
5809}
5810
5811fn default_decimal_places() -> u8 {
5812 2
5813}
5814
5815impl Default for MixtureDistributionSchemaConfig {
5816 fn default() -> Self {
5817 Self {
5818 enabled: false,
5819 distribution_type: MixtureDistributionType::LogNormal,
5820 components: Vec::new(),
5821 min_value: 0.01,
5822 max_value: None,
5823 decimal_places: 2,
5824 }
5825 }
5826}
5827
5828#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5830#[serde(rename_all = "snake_case")]
5831pub enum MixtureDistributionType {
5832 Gaussian,
5834 #[default]
5836 LogNormal,
5837}
5838
5839#[derive(Debug, Clone, Serialize, Deserialize)]
5841pub struct MixtureComponentConfig {
5842 pub weight: f64,
5844
5845 pub mu: f64,
5847
5848 pub sigma: f64,
5850
5851 #[serde(default)]
5853 pub label: Option<String>,
5854}
5855
5856#[derive(Debug, Clone, Serialize, Deserialize)]
5858pub struct CorrelationSchemaConfig {
5859 #[serde(default)]
5861 pub enabled: bool,
5862
5863 #[serde(default)]
5865 pub copula_type: CopulaSchemaType,
5866
5867 #[serde(default)]
5869 pub fields: Vec<CorrelatedFieldConfig>,
5870
5871 #[serde(default)]
5874 pub matrix: Vec<f64>,
5875
5876 #[serde(default)]
5878 pub expected_correlations: Vec<ExpectedCorrelationConfig>,
5879}
5880
5881impl Default for CorrelationSchemaConfig {
5882 fn default() -> Self {
5883 Self {
5884 enabled: false,
5885 copula_type: CopulaSchemaType::Gaussian,
5886 fields: Vec::new(),
5887 matrix: Vec::new(),
5888 expected_correlations: Vec::new(),
5889 }
5890 }
5891}
5892
5893#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5895#[serde(rename_all = "snake_case")]
5896pub enum CopulaSchemaType {
5897 #[default]
5899 Gaussian,
5900 Clayton,
5902 Gumbel,
5904 Frank,
5906 StudentT,
5908}
5909
5910#[derive(Debug, Clone, Serialize, Deserialize)]
5912pub struct CorrelatedFieldConfig {
5913 pub name: String,
5915
5916 #[serde(default)]
5918 pub distribution: MarginalDistributionConfig,
5919}
5920
5921#[derive(Debug, Clone, Serialize, Deserialize)]
5923#[serde(tag = "type", rename_all = "snake_case")]
5924pub enum MarginalDistributionConfig {
5925 Normal {
5927 mu: f64,
5929 sigma: f64,
5931 },
5932 LogNormal {
5934 mu: f64,
5936 sigma: f64,
5938 },
5939 Uniform {
5941 min: f64,
5943 max: f64,
5945 },
5946 DiscreteUniform {
5948 min: i32,
5950 max: i32,
5952 },
5953}
5954
5955impl Default for MarginalDistributionConfig {
5956 fn default() -> Self {
5957 Self::Normal {
5958 mu: 0.0,
5959 sigma: 1.0,
5960 }
5961 }
5962}
5963
5964#[derive(Debug, Clone, Serialize, Deserialize)]
5966pub struct ExpectedCorrelationConfig {
5967 pub field1: String,
5969 pub field2: String,
5971 pub expected_r: f64,
5973 #[serde(default = "default_correlation_tolerance")]
5975 pub tolerance: f64,
5976}
5977
5978fn default_correlation_tolerance() -> f64 {
5979 0.10
5980}
5981
5982#[derive(Debug, Clone, Serialize, Deserialize)]
5984pub struct ConditionalDistributionSchemaConfig {
5985 pub output_field: String,
5987
5988 pub input_field: String,
5990
5991 #[serde(default)]
5993 pub breakpoints: Vec<ConditionalBreakpointConfig>,
5994
5995 #[serde(default)]
5997 pub default_distribution: ConditionalDistributionParamsConfig,
5998
5999 #[serde(default)]
6001 pub min_value: Option<f64>,
6002
6003 #[serde(default)]
6005 pub max_value: Option<f64>,
6006
6007 #[serde(default = "default_decimal_places")]
6009 pub decimal_places: u8,
6010}
6011
6012#[derive(Debug, Clone, Serialize, Deserialize)]
6014pub struct ConditionalBreakpointConfig {
6015 pub threshold: f64,
6017
6018 pub distribution: ConditionalDistributionParamsConfig,
6020}
6021
6022#[derive(Debug, Clone, Serialize, Deserialize)]
6024#[serde(tag = "type", rename_all = "snake_case")]
6025pub enum ConditionalDistributionParamsConfig {
6026 Fixed {
6028 value: f64,
6030 },
6031 Normal {
6033 mu: f64,
6035 sigma: f64,
6037 },
6038 LogNormal {
6040 mu: f64,
6042 sigma: f64,
6044 },
6045 Uniform {
6047 min: f64,
6049 max: f64,
6051 },
6052 Beta {
6054 alpha: f64,
6056 beta: f64,
6058 min: f64,
6060 max: f64,
6062 },
6063 Discrete {
6065 values: Vec<f64>,
6067 weights: Vec<f64>,
6069 },
6070}
6071
6072impl Default for ConditionalDistributionParamsConfig {
6073 fn default() -> Self {
6074 Self::Normal {
6075 mu: 0.0,
6076 sigma: 1.0,
6077 }
6078 }
6079}
6080
6081#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6083pub struct RegimeChangeSchemaConfig {
6084 #[serde(default)]
6086 pub enabled: bool,
6087
6088 #[serde(default)]
6090 pub changes: Vec<RegimeChangeEventConfig>,
6091
6092 #[serde(default)]
6094 pub economic_cycle: Option<EconomicCycleSchemaConfig>,
6095
6096 #[serde(default)]
6098 pub parameter_drifts: Vec<ParameterDriftSchemaConfig>,
6099}
6100
6101#[derive(Debug, Clone, Serialize, Deserialize)]
6103pub struct RegimeChangeEventConfig {
6104 pub date: String,
6106
6107 pub change_type: RegimeChangeTypeConfig,
6109
6110 #[serde(default)]
6112 pub description: Option<String>,
6113
6114 #[serde(default)]
6116 pub effects: Vec<RegimeEffectConfig>,
6117}
6118
6119#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
6121#[serde(rename_all = "snake_case")]
6122pub enum RegimeChangeTypeConfig {
6123 Acquisition,
6125 Divestiture,
6127 PriceIncrease,
6129 PriceDecrease,
6131 ProductLaunch,
6133 ProductDiscontinuation,
6135 PolicyChange,
6137 CompetitorEntry,
6139 Custom,
6141}
6142
6143#[derive(Debug, Clone, Serialize, Deserialize)]
6145pub struct RegimeEffectConfig {
6146 pub field: String,
6148
6149 pub multiplier: f64,
6151}
6152
6153#[derive(Debug, Clone, Serialize, Deserialize)]
6155pub struct EconomicCycleSchemaConfig {
6156 #[serde(default)]
6158 pub enabled: bool,
6159
6160 #[serde(default = "default_cycle_period")]
6162 pub period_months: u32,
6163
6164 #[serde(default = "default_cycle_amplitude")]
6166 pub amplitude: f64,
6167
6168 #[serde(default)]
6170 pub phase_offset: u32,
6171
6172 #[serde(default)]
6174 pub recessions: Vec<RecessionPeriodConfig>,
6175}
6176
6177fn default_cycle_period() -> u32 {
6178 48
6179}
6180
6181fn default_cycle_amplitude() -> f64 {
6182 0.15
6183}
6184
6185impl Default for EconomicCycleSchemaConfig {
6186 fn default() -> Self {
6187 Self {
6188 enabled: false,
6189 period_months: 48,
6190 amplitude: 0.15,
6191 phase_offset: 0,
6192 recessions: Vec::new(),
6193 }
6194 }
6195}
6196
6197#[derive(Debug, Clone, Serialize, Deserialize)]
6199pub struct RecessionPeriodConfig {
6200 pub start_month: u32,
6202
6203 pub duration_months: u32,
6205
6206 #[serde(default = "default_recession_severity")]
6208 pub severity: f64,
6209}
6210
6211fn default_recession_severity() -> f64 {
6212 0.20
6213}
6214
6215#[derive(Debug, Clone, Serialize, Deserialize)]
6217pub struct ParameterDriftSchemaConfig {
6218 pub parameter: String,
6220
6221 pub drift_type: ParameterDriftTypeConfig,
6223
6224 pub start_value: f64,
6226
6227 pub end_value: f64,
6229
6230 #[serde(default)]
6232 pub start_period: u32,
6233
6234 #[serde(default)]
6236 pub end_period: Option<u32>,
6237}
6238
6239#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
6241#[serde(rename_all = "snake_case")]
6242pub enum ParameterDriftTypeConfig {
6243 #[default]
6245 Linear,
6246 Exponential,
6248 Logistic,
6250 Step,
6252}
6253
6254#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6256pub struct StatisticalValidationSchemaConfig {
6257 #[serde(default)]
6259 pub enabled: bool,
6260
6261 #[serde(default)]
6263 pub tests: Vec<StatisticalTestConfig>,
6264
6265 #[serde(default)]
6267 pub reporting: ValidationReportingConfig,
6268}
6269
6270#[derive(Debug, Clone, Serialize, Deserialize)]
6272#[serde(tag = "type", rename_all = "snake_case")]
6273pub enum StatisticalTestConfig {
6274 BenfordFirstDigit {
6276 #[serde(default = "default_benford_threshold")]
6278 threshold_mad: f64,
6279 #[serde(default = "default_benford_warning")]
6281 warning_mad: f64,
6282 },
6283 DistributionFit {
6285 target: TargetDistributionConfig,
6287 #[serde(default = "default_ks_significance")]
6289 ks_significance: f64,
6290 #[serde(default)]
6292 method: DistributionFitMethod,
6293 },
6294 CorrelationCheck {
6296 expected_correlations: Vec<ExpectedCorrelationConfig>,
6298 },
6299 ChiSquared {
6301 #[serde(default = "default_chi_squared_bins")]
6303 bins: usize,
6304 #[serde(default = "default_chi_squared_significance")]
6306 significance: f64,
6307 },
6308 AndersonDarling {
6310 target: TargetDistributionConfig,
6312 #[serde(default = "default_ad_significance")]
6314 significance: f64,
6315 },
6316}
6317
6318fn default_benford_threshold() -> f64 {
6319 0.015
6320}
6321
6322fn default_benford_warning() -> f64 {
6323 0.010
6324}
6325
6326fn default_ks_significance() -> f64 {
6327 0.05
6328}
6329
6330fn default_chi_squared_bins() -> usize {
6331 10
6332}
6333
6334fn default_chi_squared_significance() -> f64 {
6335 0.05
6336}
6337
6338fn default_ad_significance() -> f64 {
6339 0.05
6340}
6341
6342#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
6344#[serde(rename_all = "snake_case")]
6345pub enum TargetDistributionConfig {
6346 Normal,
6348 #[default]
6350 LogNormal,
6351 Exponential,
6353 Uniform,
6355}
6356
6357#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
6359#[serde(rename_all = "snake_case")]
6360pub enum DistributionFitMethod {
6361 #[default]
6363 KolmogorovSmirnov,
6364 AndersonDarling,
6366 ChiSquared,
6368}
6369
6370#[derive(Debug, Clone, Serialize, Deserialize)]
6372pub struct ValidationReportingConfig {
6373 #[serde(default)]
6375 pub output_report: bool,
6376
6377 #[serde(default)]
6379 pub format: ValidationReportFormat,
6380
6381 #[serde(default)]
6383 pub fail_on_error: bool,
6384
6385 #[serde(default = "default_true")]
6387 pub include_details: bool,
6388}
6389
6390impl Default for ValidationReportingConfig {
6391 fn default() -> Self {
6392 Self {
6393 output_report: false,
6394 format: ValidationReportFormat::Json,
6395 fail_on_error: false,
6396 include_details: true,
6397 }
6398 }
6399}
6400
6401#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
6403#[serde(rename_all = "snake_case")]
6404pub enum ValidationReportFormat {
6405 #[default]
6407 Json,
6408 Yaml,
6410 Html,
6412}
6413
6414#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6426pub struct TemporalPatternsConfig {
6427 #[serde(default)]
6429 pub enabled: bool,
6430
6431 #[serde(default)]
6433 pub business_days: BusinessDaySchemaConfig,
6434
6435 #[serde(default)]
6437 pub calendars: CalendarSchemaConfig,
6438
6439 #[serde(default)]
6441 pub period_end: PeriodEndSchemaConfig,
6442
6443 #[serde(default)]
6445 pub processing_lags: ProcessingLagSchemaConfig,
6446
6447 #[serde(default)]
6449 pub fiscal_calendar: FiscalCalendarSchemaConfig,
6450
6451 #[serde(default)]
6453 pub intraday: IntraDaySchemaConfig,
6454
6455 #[serde(default)]
6457 pub timezones: TimezoneSchemaConfig,
6458}
6459
6460#[derive(Debug, Clone, Serialize, Deserialize)]
6462pub struct BusinessDaySchemaConfig {
6463 #[serde(default = "default_true")]
6465 pub enabled: bool,
6466
6467 #[serde(default = "default_half_day_policy")]
6469 pub half_day_policy: String,
6470
6471 #[serde(default)]
6473 pub settlement_rules: SettlementRulesSchemaConfig,
6474
6475 #[serde(default = "default_month_end_convention")]
6477 pub month_end_convention: String,
6478
6479 #[serde(default)]
6481 pub weekend_days: Option<Vec<String>>,
6482}
6483
6484fn default_half_day_policy() -> String {
6485 "half_day".to_string()
6486}
6487
6488fn default_month_end_convention() -> String {
6489 "modified_following".to_string()
6490}
6491
6492impl Default for BusinessDaySchemaConfig {
6493 fn default() -> Self {
6494 Self {
6495 enabled: true,
6496 half_day_policy: "half_day".to_string(),
6497 settlement_rules: SettlementRulesSchemaConfig::default(),
6498 month_end_convention: "modified_following".to_string(),
6499 weekend_days: None,
6500 }
6501 }
6502}
6503
6504#[derive(Debug, Clone, Serialize, Deserialize)]
6506pub struct SettlementRulesSchemaConfig {
6507 #[serde(default = "default_settlement_2")]
6509 pub equity_days: i32,
6510
6511 #[serde(default = "default_settlement_1")]
6513 pub government_bonds_days: i32,
6514
6515 #[serde(default = "default_settlement_2")]
6517 pub fx_spot_days: i32,
6518
6519 #[serde(default = "default_settlement_2")]
6521 pub corporate_bonds_days: i32,
6522
6523 #[serde(default = "default_wire_cutoff")]
6525 pub wire_cutoff_time: String,
6526
6527 #[serde(default = "default_settlement_1")]
6529 pub wire_international_days: i32,
6530
6531 #[serde(default = "default_settlement_1")]
6533 pub ach_days: i32,
6534}
6535
6536fn default_settlement_1() -> i32 {
6537 1
6538}
6539
6540fn default_settlement_2() -> i32 {
6541 2
6542}
6543
6544fn default_wire_cutoff() -> String {
6545 "14:00".to_string()
6546}
6547
6548impl Default for SettlementRulesSchemaConfig {
6549 fn default() -> Self {
6550 Self {
6551 equity_days: 2,
6552 government_bonds_days: 1,
6553 fx_spot_days: 2,
6554 corporate_bonds_days: 2,
6555 wire_cutoff_time: "14:00".to_string(),
6556 wire_international_days: 1,
6557 ach_days: 1,
6558 }
6559 }
6560}
6561
6562#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6564pub struct CalendarSchemaConfig {
6565 #[serde(default)]
6567 pub regions: Vec<String>,
6568
6569 #[serde(default)]
6571 pub custom_holidays: Vec<CustomHolidaySchemaConfig>,
6572}
6573
6574#[derive(Debug, Clone, Serialize, Deserialize)]
6576pub struct CustomHolidaySchemaConfig {
6577 pub name: String,
6579 pub month: u8,
6581 pub day: u8,
6583 #[serde(default = "default_holiday_multiplier")]
6585 pub activity_multiplier: f64,
6586}
6587
6588fn default_holiday_multiplier() -> f64 {
6589 0.05
6590}
6591
6592#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6594pub struct PeriodEndSchemaConfig {
6595 #[serde(default)]
6597 pub model: Option<String>,
6598
6599 #[serde(default)]
6601 pub month_end: Option<PeriodEndModelSchemaConfig>,
6602
6603 #[serde(default)]
6605 pub quarter_end: Option<PeriodEndModelSchemaConfig>,
6606
6607 #[serde(default)]
6609 pub year_end: Option<PeriodEndModelSchemaConfig>,
6610}
6611
6612#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6614pub struct PeriodEndModelSchemaConfig {
6615 #[serde(default)]
6617 pub inherit_from: Option<String>,
6618
6619 #[serde(default)]
6621 pub additional_multiplier: Option<f64>,
6622
6623 #[serde(default)]
6625 pub start_day: Option<i32>,
6626
6627 #[serde(default)]
6629 pub base_multiplier: Option<f64>,
6630
6631 #[serde(default)]
6633 pub peak_multiplier: Option<f64>,
6634
6635 #[serde(default)]
6637 pub decay_rate: Option<f64>,
6638
6639 #[serde(default)]
6641 pub sustained_high_days: Option<i32>,
6642}
6643
6644#[derive(Debug, Clone, Serialize, Deserialize)]
6646pub struct ProcessingLagSchemaConfig {
6647 #[serde(default = "default_true")]
6649 pub enabled: bool,
6650
6651 #[serde(default)]
6653 pub sales_order_lag: Option<LagDistributionSchemaConfig>,
6654
6655 #[serde(default)]
6657 pub purchase_order_lag: Option<LagDistributionSchemaConfig>,
6658
6659 #[serde(default)]
6661 pub goods_receipt_lag: Option<LagDistributionSchemaConfig>,
6662
6663 #[serde(default)]
6665 pub invoice_receipt_lag: Option<LagDistributionSchemaConfig>,
6666
6667 #[serde(default)]
6669 pub invoice_issue_lag: Option<LagDistributionSchemaConfig>,
6670
6671 #[serde(default)]
6673 pub payment_lag: Option<LagDistributionSchemaConfig>,
6674
6675 #[serde(default)]
6677 pub journal_entry_lag: Option<LagDistributionSchemaConfig>,
6678
6679 #[serde(default)]
6681 pub cross_day_posting: Option<CrossDayPostingSchemaConfig>,
6682}
6683
6684impl Default for ProcessingLagSchemaConfig {
6685 fn default() -> Self {
6686 Self {
6687 enabled: true,
6688 sales_order_lag: None,
6689 purchase_order_lag: None,
6690 goods_receipt_lag: None,
6691 invoice_receipt_lag: None,
6692 invoice_issue_lag: None,
6693 payment_lag: None,
6694 journal_entry_lag: None,
6695 cross_day_posting: None,
6696 }
6697 }
6698}
6699
6700#[derive(Debug, Clone, Serialize, Deserialize)]
6702pub struct LagDistributionSchemaConfig {
6703 pub mu: f64,
6705 pub sigma: f64,
6707 #[serde(default)]
6709 pub min_hours: Option<f64>,
6710 #[serde(default)]
6712 pub max_hours: Option<f64>,
6713}
6714
6715#[derive(Debug, Clone, Serialize, Deserialize)]
6717pub struct CrossDayPostingSchemaConfig {
6718 #[serde(default = "default_true")]
6720 pub enabled: bool,
6721
6722 #[serde(default)]
6725 pub probability_by_hour: std::collections::HashMap<u8, f64>,
6726}
6727
6728impl Default for CrossDayPostingSchemaConfig {
6729 fn default() -> Self {
6730 let mut probability_by_hour = std::collections::HashMap::new();
6731 probability_by_hour.insert(17, 0.3);
6732 probability_by_hour.insert(18, 0.6);
6733 probability_by_hour.insert(19, 0.8);
6734 probability_by_hour.insert(20, 0.9);
6735 probability_by_hour.insert(21, 0.95);
6736 probability_by_hour.insert(22, 0.99);
6737
6738 Self {
6739 enabled: true,
6740 probability_by_hour,
6741 }
6742 }
6743}
6744
6745#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6754pub struct FiscalCalendarSchemaConfig {
6755 #[serde(default)]
6757 pub enabled: bool,
6758
6759 #[serde(default = "default_fiscal_calendar_type")]
6761 pub calendar_type: String,
6762
6763 #[serde(default)]
6765 pub year_start_month: Option<u8>,
6766
6767 #[serde(default)]
6769 pub year_start_day: Option<u8>,
6770
6771 #[serde(default)]
6773 pub four_four_five: Option<FourFourFiveSchemaConfig>,
6774}
6775
6776fn default_fiscal_calendar_type() -> String {
6777 "calendar_year".to_string()
6778}
6779
6780#[derive(Debug, Clone, Serialize, Deserialize)]
6782pub struct FourFourFiveSchemaConfig {
6783 #[serde(default = "default_week_pattern")]
6785 pub pattern: String,
6786
6787 #[serde(default = "default_anchor_type")]
6789 pub anchor_type: String,
6790
6791 #[serde(default = "default_anchor_month")]
6793 pub anchor_month: u8,
6794
6795 #[serde(default = "default_leap_week_placement")]
6797 pub leap_week_placement: String,
6798}
6799
6800fn default_week_pattern() -> String {
6801 "four_four_five".to_string()
6802}
6803
6804fn default_anchor_type() -> String {
6805 "last_saturday".to_string()
6806}
6807
6808fn default_anchor_month() -> u8 {
6809 1 }
6811
6812fn default_leap_week_placement() -> String {
6813 "q4_period3".to_string()
6814}
6815
6816impl Default for FourFourFiveSchemaConfig {
6817 fn default() -> Self {
6818 Self {
6819 pattern: "four_four_five".to_string(),
6820 anchor_type: "last_saturday".to_string(),
6821 anchor_month: 1,
6822 leap_week_placement: "q4_period3".to_string(),
6823 }
6824 }
6825}
6826
6827#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6836pub struct IntraDaySchemaConfig {
6837 #[serde(default)]
6839 pub enabled: bool,
6840
6841 #[serde(default)]
6843 pub segments: Vec<IntraDaySegmentSchemaConfig>,
6844}
6845
6846#[derive(Debug, Clone, Serialize, Deserialize)]
6848pub struct IntraDaySegmentSchemaConfig {
6849 pub name: String,
6851
6852 pub start: String,
6854
6855 pub end: String,
6857
6858 #[serde(default = "default_multiplier")]
6860 pub multiplier: f64,
6861
6862 #[serde(default = "default_posting_type")]
6864 pub posting_type: String,
6865}
6866
6867fn default_multiplier() -> f64 {
6868 1.0
6869}
6870
6871fn default_posting_type() -> String {
6872 "both".to_string()
6873}
6874
6875#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6881pub struct TimezoneSchemaConfig {
6882 #[serde(default)]
6884 pub enabled: bool,
6885
6886 #[serde(default = "default_timezone")]
6888 pub default_timezone: String,
6889
6890 #[serde(default = "default_consolidation_timezone")]
6892 pub consolidation_timezone: String,
6893
6894 #[serde(default)]
6897 pub entity_mappings: Vec<EntityTimezoneMapping>,
6898}
6899
6900fn default_timezone() -> String {
6901 "America/New_York".to_string()
6902}
6903
6904fn default_consolidation_timezone() -> String {
6905 "UTC".to_string()
6906}
6907
6908#[derive(Debug, Clone, Serialize, Deserialize)]
6910pub struct EntityTimezoneMapping {
6911 pub pattern: String,
6913
6914 pub timezone: String,
6916}
6917
6918#[derive(Debug, Clone, Serialize, Deserialize)]
6924pub struct VendorNetworkSchemaConfig {
6925 #[serde(default)]
6927 pub enabled: bool,
6928
6929 #[serde(default = "default_vendor_tier_depth")]
6931 pub depth: u8,
6932
6933 #[serde(default)]
6935 pub tier1: TierCountSchemaConfig,
6936
6937 #[serde(default)]
6939 pub tier2_per_parent: TierCountSchemaConfig,
6940
6941 #[serde(default)]
6943 pub tier3_per_parent: TierCountSchemaConfig,
6944
6945 #[serde(default)]
6947 pub clusters: VendorClusterSchemaConfig,
6948
6949 #[serde(default)]
6951 pub dependencies: DependencySchemaConfig,
6952}
6953
6954fn default_vendor_tier_depth() -> u8 {
6955 3
6956}
6957
6958impl Default for VendorNetworkSchemaConfig {
6959 fn default() -> Self {
6960 Self {
6961 enabled: false,
6962 depth: 3,
6963 tier1: TierCountSchemaConfig { min: 50, max: 100 },
6964 tier2_per_parent: TierCountSchemaConfig { min: 4, max: 10 },
6965 tier3_per_parent: TierCountSchemaConfig { min: 2, max: 5 },
6966 clusters: VendorClusterSchemaConfig::default(),
6967 dependencies: DependencySchemaConfig::default(),
6968 }
6969 }
6970}
6971
6972#[derive(Debug, Clone, Serialize, Deserialize)]
6974pub struct TierCountSchemaConfig {
6975 #[serde(default = "default_tier_min")]
6977 pub min: usize,
6978
6979 #[serde(default = "default_tier_max")]
6981 pub max: usize,
6982}
6983
6984fn default_tier_min() -> usize {
6985 5
6986}
6987
6988fn default_tier_max() -> usize {
6989 20
6990}
6991
6992impl Default for TierCountSchemaConfig {
6993 fn default() -> Self {
6994 Self {
6995 min: default_tier_min(),
6996 max: default_tier_max(),
6997 }
6998 }
6999}
7000
7001#[derive(Debug, Clone, Serialize, Deserialize)]
7003pub struct VendorClusterSchemaConfig {
7004 #[serde(default = "default_reliable_strategic")]
7006 pub reliable_strategic: f64,
7007
7008 #[serde(default = "default_standard_operational")]
7010 pub standard_operational: f64,
7011
7012 #[serde(default = "default_transactional")]
7014 pub transactional: f64,
7015
7016 #[serde(default = "default_problematic")]
7018 pub problematic: f64,
7019}
7020
7021fn default_reliable_strategic() -> f64 {
7022 0.20
7023}
7024
7025fn default_standard_operational() -> f64 {
7026 0.50
7027}
7028
7029fn default_transactional() -> f64 {
7030 0.25
7031}
7032
7033fn default_problematic() -> f64 {
7034 0.05
7035}
7036
7037impl Default for VendorClusterSchemaConfig {
7038 fn default() -> Self {
7039 Self {
7040 reliable_strategic: 0.20,
7041 standard_operational: 0.50,
7042 transactional: 0.25,
7043 problematic: 0.05,
7044 }
7045 }
7046}
7047
7048#[derive(Debug, Clone, Serialize, Deserialize)]
7050pub struct DependencySchemaConfig {
7051 #[serde(default = "default_max_single_vendor")]
7053 pub max_single_vendor_concentration: f64,
7054
7055 #[serde(default = "default_max_top5")]
7057 pub top_5_concentration: f64,
7058
7059 #[serde(default = "default_single_source_percent")]
7061 pub single_source_percent: f64,
7062}
7063
7064fn default_max_single_vendor() -> f64 {
7065 0.15
7066}
7067
7068fn default_max_top5() -> f64 {
7069 0.45
7070}
7071
7072fn default_single_source_percent() -> f64 {
7073 0.05
7074}
7075
7076impl Default for DependencySchemaConfig {
7077 fn default() -> Self {
7078 Self {
7079 max_single_vendor_concentration: 0.15,
7080 top_5_concentration: 0.45,
7081 single_source_percent: 0.05,
7082 }
7083 }
7084}
7085
7086#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7092pub struct CustomerSegmentationSchemaConfig {
7093 #[serde(default)]
7095 pub enabled: bool,
7096
7097 #[serde(default)]
7099 pub value_segments: ValueSegmentsSchemaConfig,
7100
7101 #[serde(default)]
7103 pub lifecycle: LifecycleSchemaConfig,
7104
7105 #[serde(default)]
7107 pub networks: CustomerNetworksSchemaConfig,
7108}
7109
7110#[derive(Debug, Clone, Serialize, Deserialize)]
7112pub struct ValueSegmentsSchemaConfig {
7113 #[serde(default)]
7115 pub enterprise: SegmentDetailSchemaConfig,
7116
7117 #[serde(default)]
7119 pub mid_market: SegmentDetailSchemaConfig,
7120
7121 #[serde(default)]
7123 pub smb: SegmentDetailSchemaConfig,
7124
7125 #[serde(default)]
7127 pub consumer: SegmentDetailSchemaConfig,
7128}
7129
7130impl Default for ValueSegmentsSchemaConfig {
7131 fn default() -> Self {
7132 Self {
7133 enterprise: SegmentDetailSchemaConfig {
7134 revenue_share: 0.40,
7135 customer_share: 0.05,
7136 avg_order_value_range: "50000+".to_string(),
7137 },
7138 mid_market: SegmentDetailSchemaConfig {
7139 revenue_share: 0.35,
7140 customer_share: 0.20,
7141 avg_order_value_range: "5000-50000".to_string(),
7142 },
7143 smb: SegmentDetailSchemaConfig {
7144 revenue_share: 0.20,
7145 customer_share: 0.50,
7146 avg_order_value_range: "500-5000".to_string(),
7147 },
7148 consumer: SegmentDetailSchemaConfig {
7149 revenue_share: 0.05,
7150 customer_share: 0.25,
7151 avg_order_value_range: "50-500".to_string(),
7152 },
7153 }
7154 }
7155}
7156
7157#[derive(Debug, Clone, Serialize, Deserialize)]
7159pub struct SegmentDetailSchemaConfig {
7160 #[serde(default)]
7162 pub revenue_share: f64,
7163
7164 #[serde(default)]
7166 pub customer_share: f64,
7167
7168 #[serde(default)]
7170 pub avg_order_value_range: String,
7171}
7172
7173impl Default for SegmentDetailSchemaConfig {
7174 fn default() -> Self {
7175 Self {
7176 revenue_share: 0.25,
7177 customer_share: 0.25,
7178 avg_order_value_range: "1000-10000".to_string(),
7179 }
7180 }
7181}
7182
7183#[derive(Debug, Clone, Serialize, Deserialize)]
7185pub struct LifecycleSchemaConfig {
7186 #[serde(default)]
7188 pub prospect_rate: f64,
7189
7190 #[serde(default = "default_new_rate")]
7192 pub new_rate: f64,
7193
7194 #[serde(default = "default_growth_rate")]
7196 pub growth_rate: f64,
7197
7198 #[serde(default = "default_mature_rate")]
7200 pub mature_rate: f64,
7201
7202 #[serde(default = "default_at_risk_rate")]
7204 pub at_risk_rate: f64,
7205
7206 #[serde(default = "default_churned_rate")]
7208 pub churned_rate: f64,
7209
7210 #[serde(default)]
7212 pub won_back_rate: f64,
7213}
7214
7215fn default_new_rate() -> f64 {
7216 0.10
7217}
7218
7219fn default_growth_rate() -> f64 {
7220 0.15
7221}
7222
7223fn default_mature_rate() -> f64 {
7224 0.60
7225}
7226
7227fn default_at_risk_rate() -> f64 {
7228 0.10
7229}
7230
7231fn default_churned_rate() -> f64 {
7232 0.05
7233}
7234
7235impl Default for LifecycleSchemaConfig {
7236 fn default() -> Self {
7237 Self {
7238 prospect_rate: 0.0,
7239 new_rate: 0.10,
7240 growth_rate: 0.15,
7241 mature_rate: 0.60,
7242 at_risk_rate: 0.10,
7243 churned_rate: 0.05,
7244 won_back_rate: 0.0,
7245 }
7246 }
7247}
7248
7249#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7251pub struct CustomerNetworksSchemaConfig {
7252 #[serde(default)]
7254 pub referrals: ReferralSchemaConfig,
7255
7256 #[serde(default)]
7258 pub corporate_hierarchies: HierarchySchemaConfig,
7259}
7260
7261#[derive(Debug, Clone, Serialize, Deserialize)]
7263pub struct ReferralSchemaConfig {
7264 #[serde(default = "default_true")]
7266 pub enabled: bool,
7267
7268 #[serde(default = "default_referral_rate")]
7270 pub referral_rate: f64,
7271}
7272
7273fn default_referral_rate() -> f64 {
7274 0.15
7275}
7276
7277impl Default for ReferralSchemaConfig {
7278 fn default() -> Self {
7279 Self {
7280 enabled: true,
7281 referral_rate: 0.15,
7282 }
7283 }
7284}
7285
7286#[derive(Debug, Clone, Serialize, Deserialize)]
7288pub struct HierarchySchemaConfig {
7289 #[serde(default = "default_true")]
7291 pub enabled: bool,
7292
7293 #[serde(default = "default_hierarchy_rate")]
7295 pub probability: f64,
7296}
7297
7298fn default_hierarchy_rate() -> f64 {
7299 0.30
7300}
7301
7302impl Default for HierarchySchemaConfig {
7303 fn default() -> Self {
7304 Self {
7305 enabled: true,
7306 probability: 0.30,
7307 }
7308 }
7309}
7310
7311#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7317pub struct RelationshipStrengthSchemaConfig {
7318 #[serde(default)]
7320 pub enabled: bool,
7321
7322 #[serde(default)]
7324 pub calculation: StrengthCalculationSchemaConfig,
7325
7326 #[serde(default)]
7328 pub thresholds: StrengthThresholdsSchemaConfig,
7329}
7330
7331#[derive(Debug, Clone, Serialize, Deserialize)]
7333pub struct StrengthCalculationSchemaConfig {
7334 #[serde(default = "default_volume_weight")]
7336 pub transaction_volume_weight: f64,
7337
7338 #[serde(default = "default_count_weight")]
7340 pub transaction_count_weight: f64,
7341
7342 #[serde(default = "default_duration_weight")]
7344 pub relationship_duration_weight: f64,
7345
7346 #[serde(default = "default_recency_weight")]
7348 pub recency_weight: f64,
7349
7350 #[serde(default = "default_mutual_weight")]
7352 pub mutual_connections_weight: f64,
7353
7354 #[serde(default = "default_recency_half_life")]
7356 pub recency_half_life_days: u32,
7357}
7358
7359fn default_volume_weight() -> f64 {
7360 0.30
7361}
7362
7363fn default_count_weight() -> f64 {
7364 0.25
7365}
7366
7367fn default_duration_weight() -> f64 {
7368 0.20
7369}
7370
7371fn default_recency_weight() -> f64 {
7372 0.15
7373}
7374
7375fn default_mutual_weight() -> f64 {
7376 0.10
7377}
7378
7379fn default_recency_half_life() -> u32 {
7380 90
7381}
7382
7383impl Default for StrengthCalculationSchemaConfig {
7384 fn default() -> Self {
7385 Self {
7386 transaction_volume_weight: 0.30,
7387 transaction_count_weight: 0.25,
7388 relationship_duration_weight: 0.20,
7389 recency_weight: 0.15,
7390 mutual_connections_weight: 0.10,
7391 recency_half_life_days: 90,
7392 }
7393 }
7394}
7395
7396#[derive(Debug, Clone, Serialize, Deserialize)]
7398pub struct StrengthThresholdsSchemaConfig {
7399 #[serde(default = "default_strong_threshold")]
7401 pub strong: f64,
7402
7403 #[serde(default = "default_moderate_threshold")]
7405 pub moderate: f64,
7406
7407 #[serde(default = "default_weak_threshold")]
7409 pub weak: f64,
7410}
7411
7412fn default_strong_threshold() -> f64 {
7413 0.7
7414}
7415
7416fn default_moderate_threshold() -> f64 {
7417 0.4
7418}
7419
7420fn default_weak_threshold() -> f64 {
7421 0.1
7422}
7423
7424impl Default for StrengthThresholdsSchemaConfig {
7425 fn default() -> Self {
7426 Self {
7427 strong: 0.7,
7428 moderate: 0.4,
7429 weak: 0.1,
7430 }
7431 }
7432}
7433
7434#[derive(Debug, Clone, Serialize, Deserialize)]
7440pub struct CrossProcessLinksSchemaConfig {
7441 #[serde(default)]
7443 pub enabled: bool,
7444
7445 #[serde(default = "default_true")]
7447 pub inventory_p2p_o2c: bool,
7448
7449 #[serde(default = "default_true")]
7451 pub payment_bank_reconciliation: bool,
7452
7453 #[serde(default = "default_true")]
7455 pub intercompany_bilateral: bool,
7456
7457 #[serde(default = "default_inventory_link_rate")]
7459 pub inventory_link_rate: f64,
7460}
7461
7462fn default_inventory_link_rate() -> f64 {
7463 0.30
7464}
7465
7466impl Default for CrossProcessLinksSchemaConfig {
7467 fn default() -> Self {
7468 Self {
7469 enabled: false,
7470 inventory_p2p_o2c: true,
7471 payment_bank_reconciliation: true,
7472 intercompany_bilateral: true,
7473 inventory_link_rate: 0.30,
7474 }
7475 }
7476}
7477
7478#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7484pub struct OrganizationalEventsSchemaConfig {
7485 #[serde(default)]
7487 pub enabled: bool,
7488
7489 #[serde(default)]
7491 pub effect_blending: EffectBlendingModeConfig,
7492
7493 #[serde(default)]
7495 pub events: Vec<OrganizationalEventSchemaConfig>,
7496
7497 #[serde(default)]
7499 pub process_evolution: Vec<ProcessEvolutionSchemaConfig>,
7500
7501 #[serde(default)]
7503 pub technology_transitions: Vec<TechnologyTransitionSchemaConfig>,
7504}
7505
7506#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
7508#[serde(rename_all = "snake_case")]
7509pub enum EffectBlendingModeConfig {
7510 #[default]
7512 Multiplicative,
7513 Additive,
7515 Maximum,
7517 Minimum,
7519}
7520
7521#[derive(Debug, Clone, Serialize, Deserialize)]
7523pub struct OrganizationalEventSchemaConfig {
7524 pub id: String,
7526
7527 pub event_type: OrganizationalEventTypeSchemaConfig,
7529
7530 pub effective_date: String,
7532
7533 #[serde(default = "default_org_transition_months")]
7535 pub transition_months: u32,
7536
7537 #[serde(default)]
7539 pub description: Option<String>,
7540}
7541
7542fn default_org_transition_months() -> u32 {
7543 6
7544}
7545
7546#[derive(Debug, Clone, Serialize, Deserialize)]
7548#[serde(tag = "type", rename_all = "snake_case")]
7549pub enum OrganizationalEventTypeSchemaConfig {
7550 Acquisition {
7552 acquired_entity: String,
7554 #[serde(default = "default_acquisition_volume")]
7556 volume_increase: f64,
7557 #[serde(default = "default_acquisition_error")]
7559 integration_error_rate: f64,
7560 #[serde(default = "default_parallel_days")]
7562 parallel_posting_days: u32,
7563 },
7564 Divestiture {
7566 divested_entity: String,
7568 #[serde(default = "default_divestiture_volume")]
7570 volume_reduction: f64,
7571 #[serde(default = "default_true_val")]
7573 remove_entity: bool,
7574 },
7575 Reorganization {
7577 #[serde(default)]
7579 cost_center_remapping: std::collections::HashMap<String, String>,
7580 #[serde(default = "default_reorg_error")]
7582 transition_error_rate: f64,
7583 },
7584 LeadershipChange {
7586 role: String,
7588 #[serde(default)]
7590 policy_changes: Vec<String>,
7591 },
7592 WorkforceReduction {
7594 #[serde(default = "default_workforce_reduction")]
7596 reduction_percent: f64,
7597 #[serde(default = "default_workforce_error")]
7599 error_rate_increase: f64,
7600 },
7601 Merger {
7603 merged_entity: String,
7605 #[serde(default = "default_merger_volume")]
7607 volume_increase: f64,
7608 },
7609}
7610
7611fn default_acquisition_volume() -> f64 {
7612 1.35
7613}
7614
7615fn default_acquisition_error() -> f64 {
7616 0.05
7617}
7618
7619fn default_parallel_days() -> u32 {
7620 30
7621}
7622
7623fn default_divestiture_volume() -> f64 {
7624 0.70
7625}
7626
7627fn default_true_val() -> bool {
7628 true
7629}
7630
7631fn default_reorg_error() -> f64 {
7632 0.04
7633}
7634
7635fn default_workforce_reduction() -> f64 {
7636 0.10
7637}
7638
7639fn default_workforce_error() -> f64 {
7640 0.05
7641}
7642
7643fn default_merger_volume() -> f64 {
7644 1.80
7645}
7646
7647#[derive(Debug, Clone, Serialize, Deserialize)]
7649pub struct ProcessEvolutionSchemaConfig {
7650 pub id: String,
7652
7653 pub event_type: ProcessEvolutionTypeSchemaConfig,
7655
7656 pub effective_date: String,
7658
7659 #[serde(default)]
7661 pub description: Option<String>,
7662}
7663
7664#[derive(Debug, Clone, Serialize, Deserialize)]
7666#[serde(tag = "type", rename_all = "snake_case")]
7667pub enum ProcessEvolutionTypeSchemaConfig {
7668 ProcessAutomation {
7670 process_name: String,
7672 #[serde(default = "default_manual_before")]
7674 manual_rate_before: f64,
7675 #[serde(default = "default_manual_after")]
7677 manual_rate_after: f64,
7678 },
7679 ApprovalWorkflowChange {
7681 description: String,
7683 },
7684 ControlEnhancement {
7686 control_id: String,
7688 #[serde(default = "default_error_reduction")]
7690 error_reduction: f64,
7691 },
7692}
7693
7694fn default_manual_before() -> f64 {
7695 0.80
7696}
7697
7698fn default_manual_after() -> f64 {
7699 0.15
7700}
7701
7702fn default_error_reduction() -> f64 {
7703 0.02
7704}
7705
7706#[derive(Debug, Clone, Serialize, Deserialize)]
7708pub struct TechnologyTransitionSchemaConfig {
7709 pub id: String,
7711
7712 pub event_type: TechnologyTransitionTypeSchemaConfig,
7714
7715 #[serde(default)]
7717 pub description: Option<String>,
7718}
7719
7720#[derive(Debug, Clone, Serialize, Deserialize)]
7722#[serde(tag = "type", rename_all = "snake_case")]
7723pub enum TechnologyTransitionTypeSchemaConfig {
7724 ErpMigration {
7726 source_system: String,
7728 target_system: String,
7730 cutover_date: String,
7732 stabilization_end: String,
7734 #[serde(default = "default_erp_duplicate_rate")]
7736 duplicate_rate: f64,
7737 #[serde(default = "default_format_mismatch")]
7739 format_mismatch_rate: f64,
7740 },
7741 ModuleImplementation {
7743 module_name: String,
7745 go_live_date: String,
7747 },
7748}
7749
7750fn default_erp_duplicate_rate() -> f64 {
7751 0.02
7752}
7753
7754fn default_format_mismatch() -> f64 {
7755 0.03
7756}
7757
7758#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7764pub struct BehavioralDriftSchemaConfig {
7765 #[serde(default)]
7767 pub enabled: bool,
7768
7769 #[serde(default)]
7771 pub vendor_behavior: VendorBehaviorSchemaConfig,
7772
7773 #[serde(default)]
7775 pub customer_behavior: CustomerBehaviorSchemaConfig,
7776
7777 #[serde(default)]
7779 pub employee_behavior: EmployeeBehaviorSchemaConfig,
7780
7781 #[serde(default)]
7783 pub collective: CollectiveBehaviorSchemaConfig,
7784}
7785
7786#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7788pub struct VendorBehaviorSchemaConfig {
7789 #[serde(default)]
7791 pub payment_terms_drift: PaymentTermsDriftSchemaConfig,
7792
7793 #[serde(default)]
7795 pub quality_drift: QualityDriftSchemaConfig,
7796}
7797
7798#[derive(Debug, Clone, Serialize, Deserialize)]
7800pub struct PaymentTermsDriftSchemaConfig {
7801 #[serde(default = "default_extension_rate")]
7803 pub extension_rate_per_year: f64,
7804
7805 #[serde(default = "default_economic_sensitivity")]
7807 pub economic_sensitivity: f64,
7808}
7809
7810fn default_extension_rate() -> f64 {
7811 2.5
7812}
7813
7814fn default_economic_sensitivity() -> f64 {
7815 1.0
7816}
7817
7818impl Default for PaymentTermsDriftSchemaConfig {
7819 fn default() -> Self {
7820 Self {
7821 extension_rate_per_year: 2.5,
7822 economic_sensitivity: 1.0,
7823 }
7824 }
7825}
7826
7827#[derive(Debug, Clone, Serialize, Deserialize)]
7829pub struct QualityDriftSchemaConfig {
7830 #[serde(default = "default_improvement_rate")]
7832 pub new_vendor_improvement_rate: f64,
7833
7834 #[serde(default = "default_decline_rate")]
7836 pub complacency_decline_rate: f64,
7837}
7838
7839fn default_improvement_rate() -> f64 {
7840 0.02
7841}
7842
7843fn default_decline_rate() -> f64 {
7844 0.01
7845}
7846
7847impl Default for QualityDriftSchemaConfig {
7848 fn default() -> Self {
7849 Self {
7850 new_vendor_improvement_rate: 0.02,
7851 complacency_decline_rate: 0.01,
7852 }
7853 }
7854}
7855
7856#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7858pub struct CustomerBehaviorSchemaConfig {
7859 #[serde(default)]
7861 pub payment_drift: CustomerPaymentDriftSchemaConfig,
7862
7863 #[serde(default)]
7865 pub order_drift: OrderDriftSchemaConfig,
7866}
7867
7868#[derive(Debug, Clone, Serialize, Deserialize)]
7870pub struct CustomerPaymentDriftSchemaConfig {
7871 #[serde(default = "default_downturn_extension")]
7873 pub downturn_days_extension: (u32, u32),
7874
7875 #[serde(default = "default_bad_debt_increase")]
7877 pub downturn_bad_debt_increase: f64,
7878}
7879
7880fn default_downturn_extension() -> (u32, u32) {
7881 (5, 15)
7882}
7883
7884fn default_bad_debt_increase() -> f64 {
7885 0.02
7886}
7887
7888impl Default for CustomerPaymentDriftSchemaConfig {
7889 fn default() -> Self {
7890 Self {
7891 downturn_days_extension: (5, 15),
7892 downturn_bad_debt_increase: 0.02,
7893 }
7894 }
7895}
7896
7897#[derive(Debug, Clone, Serialize, Deserialize)]
7899pub struct OrderDriftSchemaConfig {
7900 #[serde(default = "default_digital_shift")]
7902 pub digital_shift_rate: f64,
7903}
7904
7905fn default_digital_shift() -> f64 {
7906 0.05
7907}
7908
7909impl Default for OrderDriftSchemaConfig {
7910 fn default() -> Self {
7911 Self {
7912 digital_shift_rate: 0.05,
7913 }
7914 }
7915}
7916
7917#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7919pub struct EmployeeBehaviorSchemaConfig {
7920 #[serde(default)]
7922 pub approval_drift: ApprovalDriftSchemaConfig,
7923
7924 #[serde(default)]
7926 pub error_drift: ErrorDriftSchemaConfig,
7927}
7928
7929#[derive(Debug, Clone, Serialize, Deserialize)]
7931pub struct ApprovalDriftSchemaConfig {
7932 #[serde(default = "default_eom_intensity")]
7934 pub eom_intensity_increase_per_year: f64,
7935
7936 #[serde(default = "default_rubber_stamp")]
7938 pub rubber_stamp_volume_threshold: u32,
7939}
7940
7941fn default_eom_intensity() -> f64 {
7942 0.05
7943}
7944
7945fn default_rubber_stamp() -> u32 {
7946 50
7947}
7948
7949impl Default for ApprovalDriftSchemaConfig {
7950 fn default() -> Self {
7951 Self {
7952 eom_intensity_increase_per_year: 0.05,
7953 rubber_stamp_volume_threshold: 50,
7954 }
7955 }
7956}
7957
7958#[derive(Debug, Clone, Serialize, Deserialize)]
7960pub struct ErrorDriftSchemaConfig {
7961 #[serde(default = "default_new_error")]
7963 pub new_employee_error_rate: f64,
7964
7965 #[serde(default = "default_learning_months")]
7967 pub learning_curve_months: u32,
7968}
7969
7970fn default_new_error() -> f64 {
7971 0.08
7972}
7973
7974fn default_learning_months() -> u32 {
7975 6
7976}
7977
7978impl Default for ErrorDriftSchemaConfig {
7979 fn default() -> Self {
7980 Self {
7981 new_employee_error_rate: 0.08,
7982 learning_curve_months: 6,
7983 }
7984 }
7985}
7986
7987#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7989pub struct CollectiveBehaviorSchemaConfig {
7990 #[serde(default)]
7992 pub automation_adoption: AutomationAdoptionSchemaConfig,
7993}
7994
7995#[derive(Debug, Clone, Serialize, Deserialize)]
7997pub struct AutomationAdoptionSchemaConfig {
7998 #[serde(default)]
8000 pub s_curve_enabled: bool,
8001
8002 #[serde(default = "default_midpoint")]
8004 pub adoption_midpoint_months: u32,
8005
8006 #[serde(default = "default_steepness")]
8008 pub steepness: f64,
8009}
8010
8011fn default_midpoint() -> u32 {
8012 24
8013}
8014
8015fn default_steepness() -> f64 {
8016 0.15
8017}
8018
8019impl Default for AutomationAdoptionSchemaConfig {
8020 fn default() -> Self {
8021 Self {
8022 s_curve_enabled: false,
8023 adoption_midpoint_months: 24,
8024 steepness: 0.15,
8025 }
8026 }
8027}
8028
8029#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8035pub struct MarketDriftSchemaConfig {
8036 #[serde(default)]
8038 pub enabled: bool,
8039
8040 #[serde(default)]
8042 pub economic_cycle: MarketEconomicCycleSchemaConfig,
8043
8044 #[serde(default)]
8046 pub industry_cycles: std::collections::HashMap<String, IndustryCycleSchemaConfig>,
8047
8048 #[serde(default)]
8050 pub commodities: CommoditiesSchemaConfig,
8051}
8052
8053#[derive(Debug, Clone, Serialize, Deserialize)]
8055pub struct MarketEconomicCycleSchemaConfig {
8056 #[serde(default)]
8058 pub enabled: bool,
8059
8060 #[serde(default)]
8062 pub cycle_type: CycleTypeSchemaConfig,
8063
8064 #[serde(default = "default_market_cycle_period")]
8066 pub period_months: u32,
8067
8068 #[serde(default = "default_market_amplitude")]
8070 pub amplitude: f64,
8071
8072 #[serde(default)]
8074 pub recession: RecessionSchemaConfig,
8075}
8076
8077fn default_market_cycle_period() -> u32 {
8078 48
8079}
8080
8081fn default_market_amplitude() -> f64 {
8082 0.15
8083}
8084
8085impl Default for MarketEconomicCycleSchemaConfig {
8086 fn default() -> Self {
8087 Self {
8088 enabled: false,
8089 cycle_type: CycleTypeSchemaConfig::Sinusoidal,
8090 period_months: 48,
8091 amplitude: 0.15,
8092 recession: RecessionSchemaConfig::default(),
8093 }
8094 }
8095}
8096
8097#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
8099#[serde(rename_all = "snake_case")]
8100pub enum CycleTypeSchemaConfig {
8101 #[default]
8103 Sinusoidal,
8104 Asymmetric,
8106 MeanReverting,
8108}
8109
8110#[derive(Debug, Clone, Serialize, Deserialize)]
8112pub struct RecessionSchemaConfig {
8113 #[serde(default)]
8115 pub enabled: bool,
8116
8117 #[serde(default = "default_recession_prob")]
8119 pub probability_per_year: f64,
8120
8121 #[serde(default)]
8123 pub severity: RecessionSeveritySchemaConfig,
8124
8125 #[serde(default)]
8127 pub recession_periods: Vec<RecessionPeriodSchemaConfig>,
8128}
8129
8130fn default_recession_prob() -> f64 {
8131 0.10
8132}
8133
8134impl Default for RecessionSchemaConfig {
8135 fn default() -> Self {
8136 Self {
8137 enabled: false,
8138 probability_per_year: 0.10,
8139 severity: RecessionSeveritySchemaConfig::Moderate,
8140 recession_periods: Vec::new(),
8141 }
8142 }
8143}
8144
8145#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
8147#[serde(rename_all = "snake_case")]
8148pub enum RecessionSeveritySchemaConfig {
8149 Mild,
8151 #[default]
8153 Moderate,
8154 Severe,
8156}
8157
8158#[derive(Debug, Clone, Serialize, Deserialize)]
8160pub struct RecessionPeriodSchemaConfig {
8161 pub start_month: u32,
8163 pub duration_months: u32,
8165}
8166
8167#[derive(Debug, Clone, Serialize, Deserialize)]
8169pub struct IndustryCycleSchemaConfig {
8170 #[serde(default = "default_industry_period")]
8172 pub period_months: u32,
8173
8174 #[serde(default = "default_industry_amp")]
8176 pub amplitude: f64,
8177}
8178
8179fn default_industry_period() -> u32 {
8180 36
8181}
8182
8183fn default_industry_amp() -> f64 {
8184 0.20
8185}
8186
8187#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8189pub struct CommoditiesSchemaConfig {
8190 #[serde(default)]
8192 pub enabled: bool,
8193
8194 #[serde(default)]
8196 pub items: Vec<CommodityItemSchemaConfig>,
8197}
8198
8199#[derive(Debug, Clone, Serialize, Deserialize)]
8201pub struct CommodityItemSchemaConfig {
8202 pub name: String,
8204
8205 #[serde(default = "default_volatility")]
8207 pub volatility: f64,
8208
8209 #[serde(default)]
8211 pub cogs_pass_through: f64,
8212
8213 #[serde(default)]
8215 pub overhead_pass_through: f64,
8216}
8217
8218fn default_volatility() -> f64 {
8219 0.20
8220}
8221
8222#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8228pub struct DriftLabelingSchemaConfig {
8229 #[serde(default)]
8231 pub enabled: bool,
8232
8233 #[serde(default)]
8235 pub statistical: StatisticalDriftLabelingSchemaConfig,
8236
8237 #[serde(default)]
8239 pub categorical: CategoricalDriftLabelingSchemaConfig,
8240
8241 #[serde(default)]
8243 pub temporal: TemporalDriftLabelingSchemaConfig,
8244
8245 #[serde(default)]
8247 pub regulatory_calendar_preset: Option<String>,
8248}
8249
8250#[derive(Debug, Clone, Serialize, Deserialize)]
8252pub struct StatisticalDriftLabelingSchemaConfig {
8253 #[serde(default = "default_true_val")]
8255 pub enabled: bool,
8256
8257 #[serde(default = "default_min_magnitude")]
8259 pub min_magnitude_threshold: f64,
8260}
8261
8262fn default_min_magnitude() -> f64 {
8263 0.05
8264}
8265
8266impl Default for StatisticalDriftLabelingSchemaConfig {
8267 fn default() -> Self {
8268 Self {
8269 enabled: true,
8270 min_magnitude_threshold: 0.05,
8271 }
8272 }
8273}
8274
8275#[derive(Debug, Clone, Serialize, Deserialize)]
8277pub struct CategoricalDriftLabelingSchemaConfig {
8278 #[serde(default = "default_true_val")]
8280 pub enabled: bool,
8281}
8282
8283impl Default for CategoricalDriftLabelingSchemaConfig {
8284 fn default() -> Self {
8285 Self { enabled: true }
8286 }
8287}
8288
8289#[derive(Debug, Clone, Serialize, Deserialize)]
8291pub struct TemporalDriftLabelingSchemaConfig {
8292 #[serde(default = "default_true_val")]
8294 pub enabled: bool,
8295}
8296
8297impl Default for TemporalDriftLabelingSchemaConfig {
8298 fn default() -> Self {
8299 Self { enabled: true }
8300 }
8301}
8302
8303#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8316pub struct EnhancedAnomalyConfig {
8317 #[serde(default)]
8319 pub enabled: bool,
8320
8321 #[serde(default)]
8323 pub rates: AnomalyRateConfig,
8324
8325 #[serde(default)]
8327 pub multi_stage_schemes: MultiStageSchemeConfig,
8328
8329 #[serde(default)]
8331 pub correlated_injection: CorrelatedInjectionConfig,
8332
8333 #[serde(default)]
8335 pub near_miss: NearMissConfig,
8336
8337 #[serde(default)]
8339 pub difficulty_classification: DifficultyClassificationConfig,
8340
8341 #[serde(default)]
8343 pub context_aware: ContextAwareConfig,
8344
8345 #[serde(default)]
8347 pub labeling: EnhancedLabelingConfig,
8348}
8349
8350#[derive(Debug, Clone, Serialize, Deserialize)]
8352pub struct AnomalyRateConfig {
8353 #[serde(default = "default_total_anomaly_rate")]
8355 pub total_rate: f64,
8356
8357 #[serde(default = "default_fraud_anomaly_rate")]
8359 pub fraud_rate: f64,
8360
8361 #[serde(default = "default_error_anomaly_rate")]
8363 pub error_rate: f64,
8364
8365 #[serde(default = "default_process_anomaly_rate")]
8367 pub process_rate: f64,
8368}
8369
8370fn default_total_anomaly_rate() -> f64 {
8371 0.03
8372}
8373fn default_fraud_anomaly_rate() -> f64 {
8374 0.01
8375}
8376fn default_error_anomaly_rate() -> f64 {
8377 0.015
8378}
8379fn default_process_anomaly_rate() -> f64 {
8380 0.005
8381}
8382
8383impl Default for AnomalyRateConfig {
8384 fn default() -> Self {
8385 Self {
8386 total_rate: default_total_anomaly_rate(),
8387 fraud_rate: default_fraud_anomaly_rate(),
8388 error_rate: default_error_anomaly_rate(),
8389 process_rate: default_process_anomaly_rate(),
8390 }
8391 }
8392}
8393
8394#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8396pub struct MultiStageSchemeConfig {
8397 #[serde(default)]
8399 pub enabled: bool,
8400
8401 #[serde(default)]
8403 pub embezzlement: EmbezzlementSchemeConfig,
8404
8405 #[serde(default)]
8407 pub revenue_manipulation: RevenueManipulationSchemeConfig,
8408
8409 #[serde(default)]
8411 pub kickback: KickbackSchemeConfig,
8412}
8413
8414#[derive(Debug, Clone, Serialize, Deserialize)]
8416pub struct EmbezzlementSchemeConfig {
8417 #[serde(default = "default_embezzlement_probability")]
8419 pub probability: f64,
8420
8421 #[serde(default)]
8423 pub testing_stage: SchemeStageConfig,
8424
8425 #[serde(default)]
8427 pub escalation_stage: SchemeStageConfig,
8428
8429 #[serde(default)]
8431 pub acceleration_stage: SchemeStageConfig,
8432
8433 #[serde(default)]
8435 pub desperation_stage: SchemeStageConfig,
8436}
8437
8438fn default_embezzlement_probability() -> f64 {
8439 0.02
8440}
8441
8442impl Default for EmbezzlementSchemeConfig {
8443 fn default() -> Self {
8444 Self {
8445 probability: default_embezzlement_probability(),
8446 testing_stage: SchemeStageConfig {
8447 duration_months: 2,
8448 amount_min: 100.0,
8449 amount_max: 500.0,
8450 transaction_count_min: 2,
8451 transaction_count_max: 5,
8452 difficulty: "hard".to_string(),
8453 },
8454 escalation_stage: SchemeStageConfig {
8455 duration_months: 6,
8456 amount_min: 500.0,
8457 amount_max: 2000.0,
8458 transaction_count_min: 3,
8459 transaction_count_max: 8,
8460 difficulty: "moderate".to_string(),
8461 },
8462 acceleration_stage: SchemeStageConfig {
8463 duration_months: 3,
8464 amount_min: 2000.0,
8465 amount_max: 10000.0,
8466 transaction_count_min: 5,
8467 transaction_count_max: 12,
8468 difficulty: "easy".to_string(),
8469 },
8470 desperation_stage: SchemeStageConfig {
8471 duration_months: 1,
8472 amount_min: 10000.0,
8473 amount_max: 50000.0,
8474 transaction_count_min: 3,
8475 transaction_count_max: 6,
8476 difficulty: "trivial".to_string(),
8477 },
8478 }
8479 }
8480}
8481
8482#[derive(Debug, Clone, Serialize, Deserialize)]
8484pub struct RevenueManipulationSchemeConfig {
8485 #[serde(default = "default_revenue_manipulation_probability")]
8487 pub probability: f64,
8488
8489 #[serde(default = "default_early_recognition_target")]
8491 pub early_recognition_target: f64,
8492
8493 #[serde(default = "default_expense_deferral_target")]
8495 pub expense_deferral_target: f64,
8496
8497 #[serde(default = "default_reserve_release_target")]
8499 pub reserve_release_target: f64,
8500
8501 #[serde(default = "default_channel_stuffing_target")]
8503 pub channel_stuffing_target: f64,
8504}
8505
8506fn default_revenue_manipulation_probability() -> f64 {
8507 0.01
8508}
8509fn default_early_recognition_target() -> f64 {
8510 0.02
8511}
8512fn default_expense_deferral_target() -> f64 {
8513 0.03
8514}
8515fn default_reserve_release_target() -> f64 {
8516 0.02
8517}
8518fn default_channel_stuffing_target() -> f64 {
8519 0.05
8520}
8521
8522impl Default for RevenueManipulationSchemeConfig {
8523 fn default() -> Self {
8524 Self {
8525 probability: default_revenue_manipulation_probability(),
8526 early_recognition_target: default_early_recognition_target(),
8527 expense_deferral_target: default_expense_deferral_target(),
8528 reserve_release_target: default_reserve_release_target(),
8529 channel_stuffing_target: default_channel_stuffing_target(),
8530 }
8531 }
8532}
8533
8534#[derive(Debug, Clone, Serialize, Deserialize)]
8536pub struct KickbackSchemeConfig {
8537 #[serde(default = "default_kickback_probability")]
8539 pub probability: f64,
8540
8541 #[serde(default = "default_kickback_inflation_min")]
8543 pub inflation_min: f64,
8544
8545 #[serde(default = "default_kickback_inflation_max")]
8547 pub inflation_max: f64,
8548
8549 #[serde(default = "default_kickback_percent")]
8551 pub kickback_percent: f64,
8552
8553 #[serde(default = "default_kickback_setup_months")]
8555 pub setup_months: u32,
8556
8557 #[serde(default = "default_kickback_operation_months")]
8559 pub operation_months: u32,
8560}
8561
8562fn default_kickback_probability() -> f64 {
8563 0.01
8564}
8565fn default_kickback_inflation_min() -> f64 {
8566 0.10
8567}
8568fn default_kickback_inflation_max() -> f64 {
8569 0.25
8570}
8571fn default_kickback_percent() -> f64 {
8572 0.50
8573}
8574fn default_kickback_setup_months() -> u32 {
8575 3
8576}
8577fn default_kickback_operation_months() -> u32 {
8578 12
8579}
8580
8581impl Default for KickbackSchemeConfig {
8582 fn default() -> Self {
8583 Self {
8584 probability: default_kickback_probability(),
8585 inflation_min: default_kickback_inflation_min(),
8586 inflation_max: default_kickback_inflation_max(),
8587 kickback_percent: default_kickback_percent(),
8588 setup_months: default_kickback_setup_months(),
8589 operation_months: default_kickback_operation_months(),
8590 }
8591 }
8592}
8593
8594#[derive(Debug, Clone, Serialize, Deserialize)]
8596pub struct SchemeStageConfig {
8597 pub duration_months: u32,
8599
8600 pub amount_min: f64,
8602
8603 pub amount_max: f64,
8605
8606 pub transaction_count_min: u32,
8608
8609 pub transaction_count_max: u32,
8611
8612 pub difficulty: String,
8614}
8615
8616impl Default for SchemeStageConfig {
8617 fn default() -> Self {
8618 Self {
8619 duration_months: 3,
8620 amount_min: 100.0,
8621 amount_max: 1000.0,
8622 transaction_count_min: 2,
8623 transaction_count_max: 10,
8624 difficulty: "moderate".to_string(),
8625 }
8626 }
8627}
8628
8629#[derive(Debug, Clone, Serialize, Deserialize)]
8631pub struct CorrelatedInjectionConfig {
8632 #[serde(default)]
8634 pub enabled: bool,
8635
8636 #[serde(default = "default_true_val")]
8638 pub fraud_concealment: bool,
8639
8640 #[serde(default = "default_true_val")]
8642 pub error_cascade: bool,
8643
8644 #[serde(default = "default_true_val")]
8646 pub temporal_clustering: bool,
8647
8648 #[serde(default)]
8650 pub temporal_clustering_config: TemporalClusteringConfig,
8651
8652 #[serde(default)]
8654 pub co_occurrence_patterns: Vec<CoOccurrencePatternConfig>,
8655}
8656
8657impl Default for CorrelatedInjectionConfig {
8658 fn default() -> Self {
8659 Self {
8660 enabled: false,
8661 fraud_concealment: true,
8662 error_cascade: true,
8663 temporal_clustering: true,
8664 temporal_clustering_config: TemporalClusteringConfig::default(),
8665 co_occurrence_patterns: Vec::new(),
8666 }
8667 }
8668}
8669
8670#[derive(Debug, Clone, Serialize, Deserialize)]
8672pub struct TemporalClusteringConfig {
8673 #[serde(default = "default_period_end_multiplier")]
8675 pub period_end_multiplier: f64,
8676
8677 #[serde(default = "default_period_end_days")]
8679 pub period_end_days: u32,
8680
8681 #[serde(default = "default_quarter_end_multiplier")]
8683 pub quarter_end_multiplier: f64,
8684
8685 #[serde(default = "default_year_end_multiplier")]
8687 pub year_end_multiplier: f64,
8688}
8689
8690fn default_period_end_multiplier() -> f64 {
8691 2.5
8692}
8693fn default_period_end_days() -> u32 {
8694 5
8695}
8696fn default_quarter_end_multiplier() -> f64 {
8697 1.5
8698}
8699fn default_year_end_multiplier() -> f64 {
8700 2.0
8701}
8702
8703impl Default for TemporalClusteringConfig {
8704 fn default() -> Self {
8705 Self {
8706 period_end_multiplier: default_period_end_multiplier(),
8707 period_end_days: default_period_end_days(),
8708 quarter_end_multiplier: default_quarter_end_multiplier(),
8709 year_end_multiplier: default_year_end_multiplier(),
8710 }
8711 }
8712}
8713
8714#[derive(Debug, Clone, Serialize, Deserialize)]
8716pub struct CoOccurrencePatternConfig {
8717 pub name: String,
8719
8720 pub primary_type: String,
8722
8723 pub correlated: Vec<CorrelatedAnomalyConfig>,
8725}
8726
8727#[derive(Debug, Clone, Serialize, Deserialize)]
8729pub struct CorrelatedAnomalyConfig {
8730 pub anomaly_type: String,
8732
8733 pub probability: f64,
8735
8736 pub lag_days_min: i32,
8738
8739 pub lag_days_max: i32,
8741}
8742
8743#[derive(Debug, Clone, Serialize, Deserialize)]
8745pub struct NearMissConfig {
8746 #[serde(default)]
8748 pub enabled: bool,
8749
8750 #[serde(default = "default_near_miss_proportion")]
8752 pub proportion: f64,
8753
8754 #[serde(default = "default_true_val")]
8756 pub near_duplicate: bool,
8757
8758 #[serde(default)]
8760 pub near_duplicate_days: NearDuplicateDaysConfig,
8761
8762 #[serde(default = "default_true_val")]
8764 pub threshold_proximity: bool,
8765
8766 #[serde(default)]
8768 pub threshold_proximity_range: ThresholdProximityRangeConfig,
8769
8770 #[serde(default = "default_true_val")]
8772 pub unusual_legitimate: bool,
8773
8774 #[serde(default = "default_unusual_legitimate_types")]
8776 pub unusual_legitimate_types: Vec<String>,
8777
8778 #[serde(default = "default_true_val")]
8780 pub corrected_errors: bool,
8781
8782 #[serde(default)]
8784 pub corrected_error_lag: CorrectedErrorLagConfig,
8785}
8786
8787fn default_near_miss_proportion() -> f64 {
8788 0.30
8789}
8790
8791fn default_unusual_legitimate_types() -> Vec<String> {
8792 vec![
8793 "year_end_bonus".to_string(),
8794 "contract_prepayment".to_string(),
8795 "insurance_claim".to_string(),
8796 "settlement_payment".to_string(),
8797 ]
8798}
8799
8800impl Default for NearMissConfig {
8801 fn default() -> Self {
8802 Self {
8803 enabled: false,
8804 proportion: default_near_miss_proportion(),
8805 near_duplicate: true,
8806 near_duplicate_days: NearDuplicateDaysConfig::default(),
8807 threshold_proximity: true,
8808 threshold_proximity_range: ThresholdProximityRangeConfig::default(),
8809 unusual_legitimate: true,
8810 unusual_legitimate_types: default_unusual_legitimate_types(),
8811 corrected_errors: true,
8812 corrected_error_lag: CorrectedErrorLagConfig::default(),
8813 }
8814 }
8815}
8816
8817#[derive(Debug, Clone, Serialize, Deserialize)]
8819pub struct NearDuplicateDaysConfig {
8820 #[serde(default = "default_near_duplicate_min")]
8822 pub min: u32,
8823
8824 #[serde(default = "default_near_duplicate_max")]
8826 pub max: u32,
8827}
8828
8829fn default_near_duplicate_min() -> u32 {
8830 1
8831}
8832fn default_near_duplicate_max() -> u32 {
8833 3
8834}
8835
8836impl Default for NearDuplicateDaysConfig {
8837 fn default() -> Self {
8838 Self {
8839 min: default_near_duplicate_min(),
8840 max: default_near_duplicate_max(),
8841 }
8842 }
8843}
8844
8845#[derive(Debug, Clone, Serialize, Deserialize)]
8847pub struct ThresholdProximityRangeConfig {
8848 #[serde(default = "default_threshold_proximity_min")]
8850 pub min: f64,
8851
8852 #[serde(default = "default_threshold_proximity_max")]
8854 pub max: f64,
8855}
8856
8857fn default_threshold_proximity_min() -> f64 {
8858 0.90
8859}
8860fn default_threshold_proximity_max() -> f64 {
8861 0.99
8862}
8863
8864impl Default for ThresholdProximityRangeConfig {
8865 fn default() -> Self {
8866 Self {
8867 min: default_threshold_proximity_min(),
8868 max: default_threshold_proximity_max(),
8869 }
8870 }
8871}
8872
8873#[derive(Debug, Clone, Serialize, Deserialize)]
8875pub struct CorrectedErrorLagConfig {
8876 #[serde(default = "default_corrected_error_lag_min")]
8878 pub min: u32,
8879
8880 #[serde(default = "default_corrected_error_lag_max")]
8882 pub max: u32,
8883}
8884
8885fn default_corrected_error_lag_min() -> u32 {
8886 1
8887}
8888fn default_corrected_error_lag_max() -> u32 {
8889 5
8890}
8891
8892impl Default for CorrectedErrorLagConfig {
8893 fn default() -> Self {
8894 Self {
8895 min: default_corrected_error_lag_min(),
8896 max: default_corrected_error_lag_max(),
8897 }
8898 }
8899}
8900
8901#[derive(Debug, Clone, Serialize, Deserialize)]
8903pub struct DifficultyClassificationConfig {
8904 #[serde(default)]
8906 pub enabled: bool,
8907
8908 #[serde(default)]
8910 pub target_distribution: DifficultyDistributionConfig,
8911}
8912
8913impl Default for DifficultyClassificationConfig {
8914 fn default() -> Self {
8915 Self {
8916 enabled: true,
8917 target_distribution: DifficultyDistributionConfig::default(),
8918 }
8919 }
8920}
8921
8922#[derive(Debug, Clone, Serialize, Deserialize)]
8924pub struct DifficultyDistributionConfig {
8925 #[serde(default = "default_difficulty_trivial")]
8927 pub trivial: f64,
8928
8929 #[serde(default = "default_difficulty_easy")]
8931 pub easy: f64,
8932
8933 #[serde(default = "default_difficulty_moderate")]
8935 pub moderate: f64,
8936
8937 #[serde(default = "default_difficulty_hard")]
8939 pub hard: f64,
8940
8941 #[serde(default = "default_difficulty_expert")]
8943 pub expert: f64,
8944}
8945
8946fn default_difficulty_trivial() -> f64 {
8947 0.15
8948}
8949fn default_difficulty_easy() -> f64 {
8950 0.25
8951}
8952fn default_difficulty_moderate() -> f64 {
8953 0.30
8954}
8955fn default_difficulty_hard() -> f64 {
8956 0.20
8957}
8958fn default_difficulty_expert() -> f64 {
8959 0.10
8960}
8961
8962impl Default for DifficultyDistributionConfig {
8963 fn default() -> Self {
8964 Self {
8965 trivial: default_difficulty_trivial(),
8966 easy: default_difficulty_easy(),
8967 moderate: default_difficulty_moderate(),
8968 hard: default_difficulty_hard(),
8969 expert: default_difficulty_expert(),
8970 }
8971 }
8972}
8973
8974#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8976pub struct ContextAwareConfig {
8977 #[serde(default)]
8979 pub enabled: bool,
8980
8981 #[serde(default)]
8983 pub vendor_rules: VendorAnomalyRulesConfig,
8984
8985 #[serde(default)]
8987 pub employee_rules: EmployeeAnomalyRulesConfig,
8988
8989 #[serde(default)]
8991 pub account_rules: AccountAnomalyRulesConfig,
8992
8993 #[serde(default)]
8995 pub behavioral_baseline: BehavioralBaselineConfig,
8996}
8997
8998#[derive(Debug, Clone, Serialize, Deserialize)]
9000pub struct VendorAnomalyRulesConfig {
9001 #[serde(default = "default_new_vendor_multiplier")]
9003 pub new_vendor_error_multiplier: f64,
9004
9005 #[serde(default = "default_new_vendor_threshold")]
9007 pub new_vendor_threshold_days: u32,
9008
9009 #[serde(default = "default_international_multiplier")]
9011 pub international_error_multiplier: f64,
9012
9013 #[serde(default = "default_strategic_vendor_types")]
9015 pub strategic_vendor_anomaly_types: Vec<String>,
9016}
9017
9018fn default_new_vendor_multiplier() -> f64 {
9019 2.5
9020}
9021fn default_new_vendor_threshold() -> u32 {
9022 90
9023}
9024fn default_international_multiplier() -> f64 {
9025 1.5
9026}
9027fn default_strategic_vendor_types() -> Vec<String> {
9028 vec![
9029 "pricing_dispute".to_string(),
9030 "contract_violation".to_string(),
9031 ]
9032}
9033
9034impl Default for VendorAnomalyRulesConfig {
9035 fn default() -> Self {
9036 Self {
9037 new_vendor_error_multiplier: default_new_vendor_multiplier(),
9038 new_vendor_threshold_days: default_new_vendor_threshold(),
9039 international_error_multiplier: default_international_multiplier(),
9040 strategic_vendor_anomaly_types: default_strategic_vendor_types(),
9041 }
9042 }
9043}
9044
9045#[derive(Debug, Clone, Serialize, Deserialize)]
9047pub struct EmployeeAnomalyRulesConfig {
9048 #[serde(default = "default_new_employee_rate")]
9050 pub new_employee_error_rate: f64,
9051
9052 #[serde(default = "default_new_employee_threshold")]
9054 pub new_employee_threshold_days: u32,
9055
9056 #[serde(default = "default_volume_fatigue_threshold")]
9058 pub volume_fatigue_threshold: u32,
9059
9060 #[serde(default = "default_coverage_multiplier")]
9062 pub coverage_error_multiplier: f64,
9063}
9064
9065fn default_new_employee_rate() -> f64 {
9066 0.05
9067}
9068fn default_new_employee_threshold() -> u32 {
9069 180
9070}
9071fn default_volume_fatigue_threshold() -> u32 {
9072 50
9073}
9074fn default_coverage_multiplier() -> f64 {
9075 1.8
9076}
9077
9078impl Default for EmployeeAnomalyRulesConfig {
9079 fn default() -> Self {
9080 Self {
9081 new_employee_error_rate: default_new_employee_rate(),
9082 new_employee_threshold_days: default_new_employee_threshold(),
9083 volume_fatigue_threshold: default_volume_fatigue_threshold(),
9084 coverage_error_multiplier: default_coverage_multiplier(),
9085 }
9086 }
9087}
9088
9089#[derive(Debug, Clone, Serialize, Deserialize)]
9091pub struct AccountAnomalyRulesConfig {
9092 #[serde(default = "default_high_risk_multiplier")]
9094 pub high_risk_account_multiplier: f64,
9095
9096 #[serde(default = "default_high_risk_accounts")]
9098 pub high_risk_accounts: Vec<String>,
9099
9100 #[serde(default = "default_suspense_multiplier")]
9102 pub suspense_account_multiplier: f64,
9103
9104 #[serde(default = "default_suspense_accounts")]
9106 pub suspense_accounts: Vec<String>,
9107
9108 #[serde(default = "default_intercompany_multiplier")]
9110 pub intercompany_account_multiplier: f64,
9111}
9112
9113fn default_high_risk_multiplier() -> f64 {
9114 2.0
9115}
9116fn default_high_risk_accounts() -> Vec<String> {
9117 vec![
9118 "1100".to_string(), "2000".to_string(), "3000".to_string(), ]
9122}
9123fn default_suspense_multiplier() -> f64 {
9124 3.0
9125}
9126fn default_suspense_accounts() -> Vec<String> {
9127 vec!["9999".to_string(), "9998".to_string()]
9128}
9129fn default_intercompany_multiplier() -> f64 {
9130 1.5
9131}
9132
9133impl Default for AccountAnomalyRulesConfig {
9134 fn default() -> Self {
9135 Self {
9136 high_risk_account_multiplier: default_high_risk_multiplier(),
9137 high_risk_accounts: default_high_risk_accounts(),
9138 suspense_account_multiplier: default_suspense_multiplier(),
9139 suspense_accounts: default_suspense_accounts(),
9140 intercompany_account_multiplier: default_intercompany_multiplier(),
9141 }
9142 }
9143}
9144
9145#[derive(Debug, Clone, Serialize, Deserialize)]
9147pub struct BehavioralBaselineConfig {
9148 #[serde(default)]
9150 pub enabled: bool,
9151
9152 #[serde(default = "default_baseline_period")]
9154 pub baseline_period_days: u32,
9155
9156 #[serde(default = "default_deviation_threshold")]
9158 pub deviation_threshold_std: f64,
9159
9160 #[serde(default = "default_frequency_deviation")]
9162 pub frequency_deviation_threshold: f64,
9163}
9164
9165fn default_baseline_period() -> u32 {
9166 90
9167}
9168fn default_deviation_threshold() -> f64 {
9169 3.0
9170}
9171fn default_frequency_deviation() -> f64 {
9172 2.0
9173}
9174
9175impl Default for BehavioralBaselineConfig {
9176 fn default() -> Self {
9177 Self {
9178 enabled: false,
9179 baseline_period_days: default_baseline_period(),
9180 deviation_threshold_std: default_deviation_threshold(),
9181 frequency_deviation_threshold: default_frequency_deviation(),
9182 }
9183 }
9184}
9185
9186#[derive(Debug, Clone, Serialize, Deserialize)]
9188pub struct EnhancedLabelingConfig {
9189 #[serde(default = "default_true_val")]
9191 pub severity_scoring: bool,
9192
9193 #[serde(default = "default_true_val")]
9195 pub difficulty_classification: bool,
9196
9197 #[serde(default)]
9199 pub materiality_thresholds: MaterialityThresholdsConfig,
9200}
9201
9202impl Default for EnhancedLabelingConfig {
9203 fn default() -> Self {
9204 Self {
9205 severity_scoring: true,
9206 difficulty_classification: true,
9207 materiality_thresholds: MaterialityThresholdsConfig::default(),
9208 }
9209 }
9210}
9211
9212#[derive(Debug, Clone, Serialize, Deserialize)]
9214pub struct MaterialityThresholdsConfig {
9215 #[serde(default = "default_materiality_trivial")]
9217 pub trivial: f64,
9218
9219 #[serde(default = "default_materiality_immaterial")]
9221 pub immaterial: f64,
9222
9223 #[serde(default = "default_materiality_material")]
9225 pub material: f64,
9226
9227 #[serde(default = "default_materiality_highly_material")]
9229 pub highly_material: f64,
9230}
9231
9232fn default_materiality_trivial() -> f64 {
9233 0.001
9234}
9235fn default_materiality_immaterial() -> f64 {
9236 0.01
9237}
9238fn default_materiality_material() -> f64 {
9239 0.05
9240}
9241fn default_materiality_highly_material() -> f64 {
9242 0.10
9243}
9244
9245impl Default for MaterialityThresholdsConfig {
9246 fn default() -> Self {
9247 Self {
9248 trivial: default_materiality_trivial(),
9249 immaterial: default_materiality_immaterial(),
9250 material: default_materiality_material(),
9251 highly_material: default_materiality_highly_material(),
9252 }
9253 }
9254}
9255
9256#[derive(Debug, Clone, Serialize, Deserialize, Default)]
9268pub struct IndustrySpecificConfig {
9269 #[serde(default)]
9271 pub enabled: bool,
9272
9273 #[serde(default)]
9275 pub manufacturing: ManufacturingConfig,
9276
9277 #[serde(default)]
9279 pub retail: RetailConfig,
9280
9281 #[serde(default)]
9283 pub healthcare: HealthcareConfig,
9284
9285 #[serde(default)]
9287 pub technology: TechnologyConfig,
9288
9289 #[serde(default)]
9291 pub financial_services: FinancialServicesConfig,
9292
9293 #[serde(default)]
9295 pub professional_services: ProfessionalServicesConfig,
9296}
9297
9298#[derive(Debug, Clone, Serialize, Deserialize)]
9300pub struct ManufacturingConfig {
9301 #[serde(default)]
9303 pub enabled: bool,
9304
9305 #[serde(default = "default_bom_depth")]
9307 pub bom_depth: u32,
9308
9309 #[serde(default)]
9311 pub just_in_time: bool,
9312
9313 #[serde(default = "default_production_order_types")]
9315 pub production_order_types: Vec<String>,
9316
9317 #[serde(default)]
9319 pub quality_framework: Option<String>,
9320
9321 #[serde(default = "default_supplier_tiers")]
9323 pub supplier_tiers: u32,
9324
9325 #[serde(default = "default_cost_frequency")]
9327 pub standard_cost_frequency: String,
9328
9329 #[serde(default = "default_yield_rate")]
9331 pub target_yield_rate: f64,
9332
9333 #[serde(default = "default_scrap_threshold")]
9335 pub scrap_alert_threshold: f64,
9336
9337 #[serde(default)]
9339 pub anomaly_rates: ManufacturingAnomalyRates,
9340
9341 #[serde(default)]
9343 pub cost_accounting: ManufacturingCostAccountingConfig,
9344}
9345
9346#[derive(Debug, Clone, Serialize, Deserialize)]
9348pub struct ManufacturingCostAccountingConfig {
9349 #[serde(default = "default_true")]
9351 pub enabled: bool,
9352
9353 #[serde(default = "default_true")]
9355 pub variance_accounts_enabled: bool,
9356
9357 #[serde(default = "default_true")]
9359 pub warranty_provisions_enabled: bool,
9360
9361 #[serde(default = "default_warranty_defect_threshold")]
9363 pub warranty_defect_threshold: f64,
9364}
9365
9366fn default_warranty_defect_threshold() -> f64 {
9367 0.01
9368}
9369
9370impl Default for ManufacturingCostAccountingConfig {
9371 fn default() -> Self {
9372 Self {
9373 enabled: true,
9374 variance_accounts_enabled: true,
9375 warranty_provisions_enabled: true,
9376 warranty_defect_threshold: 0.01,
9377 }
9378 }
9379}
9380
9381fn default_bom_depth() -> u32 {
9382 4
9383}
9384
9385fn default_production_order_types() -> Vec<String> {
9386 vec![
9387 "standard".to_string(),
9388 "rework".to_string(),
9389 "prototype".to_string(),
9390 ]
9391}
9392
9393fn default_supplier_tiers() -> u32 {
9394 2
9395}
9396
9397fn default_cost_frequency() -> String {
9398 "quarterly".to_string()
9399}
9400
9401fn default_yield_rate() -> f64 {
9402 0.97
9403}
9404
9405fn default_scrap_threshold() -> f64 {
9406 0.03
9407}
9408
9409impl Default for ManufacturingConfig {
9410 fn default() -> Self {
9411 Self {
9412 enabled: false,
9413 bom_depth: default_bom_depth(),
9414 just_in_time: false,
9415 production_order_types: default_production_order_types(),
9416 quality_framework: Some("ISO_9001".to_string()),
9417 supplier_tiers: default_supplier_tiers(),
9418 standard_cost_frequency: default_cost_frequency(),
9419 target_yield_rate: default_yield_rate(),
9420 scrap_alert_threshold: default_scrap_threshold(),
9421 anomaly_rates: ManufacturingAnomalyRates::default(),
9422 cost_accounting: ManufacturingCostAccountingConfig::default(),
9423 }
9424 }
9425}
9426
9427#[derive(Debug, Clone, Serialize, Deserialize)]
9429pub struct ManufacturingAnomalyRates {
9430 #[serde(default = "default_mfg_yield_rate")]
9432 pub yield_manipulation: f64,
9433
9434 #[serde(default = "default_mfg_labor_rate")]
9436 pub labor_misallocation: f64,
9437
9438 #[serde(default = "default_mfg_phantom_rate")]
9440 pub phantom_production: f64,
9441
9442 #[serde(default = "default_mfg_cost_rate")]
9444 pub standard_cost_manipulation: f64,
9445
9446 #[serde(default = "default_mfg_inventory_rate")]
9448 pub inventory_fraud: f64,
9449}
9450
9451fn default_mfg_yield_rate() -> f64 {
9452 0.015
9453}
9454
9455fn default_mfg_labor_rate() -> f64 {
9456 0.02
9457}
9458
9459fn default_mfg_phantom_rate() -> f64 {
9460 0.005
9461}
9462
9463fn default_mfg_cost_rate() -> f64 {
9464 0.01
9465}
9466
9467fn default_mfg_inventory_rate() -> f64 {
9468 0.008
9469}
9470
9471impl Default for ManufacturingAnomalyRates {
9472 fn default() -> Self {
9473 Self {
9474 yield_manipulation: default_mfg_yield_rate(),
9475 labor_misallocation: default_mfg_labor_rate(),
9476 phantom_production: default_mfg_phantom_rate(),
9477 standard_cost_manipulation: default_mfg_cost_rate(),
9478 inventory_fraud: default_mfg_inventory_rate(),
9479 }
9480 }
9481}
9482
9483#[derive(Debug, Clone, Serialize, Deserialize)]
9485pub struct RetailConfig {
9486 #[serde(default)]
9488 pub enabled: bool,
9489
9490 #[serde(default)]
9492 pub store_types: RetailStoreTypeConfig,
9493
9494 #[serde(default = "default_retail_daily_txns")]
9496 pub avg_daily_transactions: u32,
9497
9498 #[serde(default = "default_true")]
9500 pub loss_prevention: bool,
9501
9502 #[serde(default = "default_shrinkage_rate")]
9504 pub shrinkage_rate: f64,
9505
9506 #[serde(default)]
9508 pub anomaly_rates: RetailAnomalyRates,
9509}
9510
9511fn default_retail_daily_txns() -> u32 {
9512 500
9513}
9514
9515fn default_shrinkage_rate() -> f64 {
9516 0.015
9517}
9518
9519impl Default for RetailConfig {
9520 fn default() -> Self {
9521 Self {
9522 enabled: false,
9523 store_types: RetailStoreTypeConfig::default(),
9524 avg_daily_transactions: default_retail_daily_txns(),
9525 loss_prevention: true,
9526 shrinkage_rate: default_shrinkage_rate(),
9527 anomaly_rates: RetailAnomalyRates::default(),
9528 }
9529 }
9530}
9531
9532#[derive(Debug, Clone, Serialize, Deserialize)]
9534pub struct RetailStoreTypeConfig {
9535 #[serde(default = "default_flagship_pct")]
9537 pub flagship: f64,
9538
9539 #[serde(default = "default_regional_pct")]
9541 pub regional: f64,
9542
9543 #[serde(default = "default_outlet_pct")]
9545 pub outlet: f64,
9546
9547 #[serde(default = "default_ecommerce_pct")]
9549 pub ecommerce: f64,
9550}
9551
9552fn default_flagship_pct() -> f64 {
9553 0.10
9554}
9555
9556fn default_regional_pct() -> f64 {
9557 0.50
9558}
9559
9560fn default_outlet_pct() -> f64 {
9561 0.25
9562}
9563
9564fn default_ecommerce_pct() -> f64 {
9565 0.15
9566}
9567
9568impl Default for RetailStoreTypeConfig {
9569 fn default() -> Self {
9570 Self {
9571 flagship: default_flagship_pct(),
9572 regional: default_regional_pct(),
9573 outlet: default_outlet_pct(),
9574 ecommerce: default_ecommerce_pct(),
9575 }
9576 }
9577}
9578
9579#[derive(Debug, Clone, Serialize, Deserialize)]
9581pub struct RetailAnomalyRates {
9582 #[serde(default = "default_sweethearting_rate")]
9584 pub sweethearting: f64,
9585
9586 #[serde(default = "default_skimming_rate")]
9588 pub skimming: f64,
9589
9590 #[serde(default = "default_refund_fraud_rate")]
9592 pub refund_fraud: f64,
9593
9594 #[serde(default = "default_void_abuse_rate")]
9596 pub void_abuse: f64,
9597
9598 #[serde(default = "default_gift_card_rate")]
9600 pub gift_card_fraud: f64,
9601
9602 #[serde(default = "default_retail_kickback_rate")]
9604 pub vendor_kickback: f64,
9605}
9606
9607fn default_sweethearting_rate() -> f64 {
9608 0.02
9609}
9610
9611fn default_skimming_rate() -> f64 {
9612 0.005
9613}
9614
9615fn default_refund_fraud_rate() -> f64 {
9616 0.015
9617}
9618
9619fn default_void_abuse_rate() -> f64 {
9620 0.01
9621}
9622
9623fn default_gift_card_rate() -> f64 {
9624 0.008
9625}
9626
9627fn default_retail_kickback_rate() -> f64 {
9628 0.003
9629}
9630
9631impl Default for RetailAnomalyRates {
9632 fn default() -> Self {
9633 Self {
9634 sweethearting: default_sweethearting_rate(),
9635 skimming: default_skimming_rate(),
9636 refund_fraud: default_refund_fraud_rate(),
9637 void_abuse: default_void_abuse_rate(),
9638 gift_card_fraud: default_gift_card_rate(),
9639 vendor_kickback: default_retail_kickback_rate(),
9640 }
9641 }
9642}
9643
9644#[derive(Debug, Clone, Serialize, Deserialize)]
9646pub struct HealthcareConfig {
9647 #[serde(default)]
9649 pub enabled: bool,
9650
9651 #[serde(default = "default_facility_type")]
9653 pub facility_type: String,
9654
9655 #[serde(default)]
9657 pub payer_mix: HealthcarePayerMix,
9658
9659 #[serde(default)]
9661 pub coding_systems: HealthcareCodingSystems,
9662
9663 #[serde(default)]
9665 pub compliance: HealthcareComplianceConfig,
9666
9667 #[serde(default = "default_daily_encounters")]
9669 pub avg_daily_encounters: u32,
9670
9671 #[serde(default = "default_charges_per_encounter")]
9673 pub avg_charges_per_encounter: u32,
9674
9675 #[serde(default = "default_hc_denial_rate")]
9677 pub denial_rate: f64,
9678
9679 #[serde(default = "default_hc_bad_debt_rate")]
9681 pub bad_debt_rate: f64,
9682
9683 #[serde(default = "default_hc_charity_care_rate")]
9685 pub charity_care_rate: f64,
9686
9687 #[serde(default)]
9689 pub anomaly_rates: HealthcareAnomalyRates,
9690}
9691
9692fn default_facility_type() -> String {
9693 "hospital".to_string()
9694}
9695
9696fn default_daily_encounters() -> u32 {
9697 150
9698}
9699
9700fn default_charges_per_encounter() -> u32 {
9701 8
9702}
9703
9704fn default_hc_denial_rate() -> f64 {
9705 0.05
9706}
9707
9708fn default_hc_bad_debt_rate() -> f64 {
9709 0.03
9710}
9711
9712fn default_hc_charity_care_rate() -> f64 {
9713 0.02
9714}
9715
9716impl Default for HealthcareConfig {
9717 fn default() -> Self {
9718 Self {
9719 enabled: false,
9720 facility_type: default_facility_type(),
9721 payer_mix: HealthcarePayerMix::default(),
9722 coding_systems: HealthcareCodingSystems::default(),
9723 compliance: HealthcareComplianceConfig::default(),
9724 avg_daily_encounters: default_daily_encounters(),
9725 avg_charges_per_encounter: default_charges_per_encounter(),
9726 denial_rate: default_hc_denial_rate(),
9727 bad_debt_rate: default_hc_bad_debt_rate(),
9728 charity_care_rate: default_hc_charity_care_rate(),
9729 anomaly_rates: HealthcareAnomalyRates::default(),
9730 }
9731 }
9732}
9733
9734#[derive(Debug, Clone, Serialize, Deserialize)]
9736pub struct HealthcarePayerMix {
9737 #[serde(default = "default_medicare_pct")]
9739 pub medicare: f64,
9740
9741 #[serde(default = "default_medicaid_pct")]
9743 pub medicaid: f64,
9744
9745 #[serde(default = "default_commercial_pct")]
9747 pub commercial: f64,
9748
9749 #[serde(default = "default_self_pay_pct")]
9751 pub self_pay: f64,
9752}
9753
9754fn default_medicare_pct() -> f64 {
9755 0.40
9756}
9757
9758fn default_medicaid_pct() -> f64 {
9759 0.20
9760}
9761
9762fn default_commercial_pct() -> f64 {
9763 0.30
9764}
9765
9766fn default_self_pay_pct() -> f64 {
9767 0.10
9768}
9769
9770impl Default for HealthcarePayerMix {
9771 fn default() -> Self {
9772 Self {
9773 medicare: default_medicare_pct(),
9774 medicaid: default_medicaid_pct(),
9775 commercial: default_commercial_pct(),
9776 self_pay: default_self_pay_pct(),
9777 }
9778 }
9779}
9780
9781#[derive(Debug, Clone, Serialize, Deserialize)]
9783pub struct HealthcareCodingSystems {
9784 #[serde(default = "default_true")]
9786 pub icd10: bool,
9787
9788 #[serde(default = "default_true")]
9790 pub cpt: bool,
9791
9792 #[serde(default = "default_true")]
9794 pub drg: bool,
9795
9796 #[serde(default = "default_true")]
9798 pub hcpcs: bool,
9799
9800 #[serde(default = "default_true")]
9802 pub revenue_codes: bool,
9803}
9804
9805impl Default for HealthcareCodingSystems {
9806 fn default() -> Self {
9807 Self {
9808 icd10: true,
9809 cpt: true,
9810 drg: true,
9811 hcpcs: true,
9812 revenue_codes: true,
9813 }
9814 }
9815}
9816
9817#[derive(Debug, Clone, Serialize, Deserialize)]
9819pub struct HealthcareComplianceConfig {
9820 #[serde(default = "default_true")]
9822 pub hipaa: bool,
9823
9824 #[serde(default = "default_true")]
9826 pub stark_law: bool,
9827
9828 #[serde(default = "default_true")]
9830 pub anti_kickback: bool,
9831
9832 #[serde(default = "default_true")]
9834 pub false_claims_act: bool,
9835
9836 #[serde(default = "default_true")]
9838 pub emtala: bool,
9839}
9840
9841impl Default for HealthcareComplianceConfig {
9842 fn default() -> Self {
9843 Self {
9844 hipaa: true,
9845 stark_law: true,
9846 anti_kickback: true,
9847 false_claims_act: true,
9848 emtala: true,
9849 }
9850 }
9851}
9852
9853#[derive(Debug, Clone, Serialize, Deserialize)]
9855pub struct HealthcareAnomalyRates {
9856 #[serde(default = "default_upcoding_rate")]
9858 pub upcoding: f64,
9859
9860 #[serde(default = "default_unbundling_rate")]
9862 pub unbundling: f64,
9863
9864 #[serde(default = "default_phantom_billing_rate")]
9866 pub phantom_billing: f64,
9867
9868 #[serde(default = "default_healthcare_kickback_rate")]
9870 pub kickbacks: f64,
9871
9872 #[serde(default = "default_duplicate_billing_rate")]
9874 pub duplicate_billing: f64,
9875
9876 #[serde(default = "default_med_necessity_rate")]
9878 pub medical_necessity_abuse: f64,
9879}
9880
9881fn default_upcoding_rate() -> f64 {
9882 0.02
9883}
9884
9885fn default_unbundling_rate() -> f64 {
9886 0.015
9887}
9888
9889fn default_phantom_billing_rate() -> f64 {
9890 0.005
9891}
9892
9893fn default_healthcare_kickback_rate() -> f64 {
9894 0.003
9895}
9896
9897fn default_duplicate_billing_rate() -> f64 {
9898 0.008
9899}
9900
9901fn default_med_necessity_rate() -> f64 {
9902 0.01
9903}
9904
9905impl Default for HealthcareAnomalyRates {
9906 fn default() -> Self {
9907 Self {
9908 upcoding: default_upcoding_rate(),
9909 unbundling: default_unbundling_rate(),
9910 phantom_billing: default_phantom_billing_rate(),
9911 kickbacks: default_healthcare_kickback_rate(),
9912 duplicate_billing: default_duplicate_billing_rate(),
9913 medical_necessity_abuse: default_med_necessity_rate(),
9914 }
9915 }
9916}
9917
9918#[derive(Debug, Clone, Serialize, Deserialize)]
9920pub struct TechnologyConfig {
9921 #[serde(default)]
9923 pub enabled: bool,
9924
9925 #[serde(default = "default_revenue_model")]
9927 pub revenue_model: String,
9928
9929 #[serde(default = "default_subscription_pct")]
9931 pub subscription_revenue_pct: f64,
9932
9933 #[serde(default = "default_license_pct")]
9935 pub license_revenue_pct: f64,
9936
9937 #[serde(default = "default_services_pct")]
9939 pub services_revenue_pct: f64,
9940
9941 #[serde(default)]
9943 pub rd_capitalization: RdCapitalizationConfig,
9944
9945 #[serde(default)]
9947 pub anomaly_rates: TechnologyAnomalyRates,
9948}
9949
9950fn default_revenue_model() -> String {
9951 "saas".to_string()
9952}
9953
9954fn default_subscription_pct() -> f64 {
9955 0.60
9956}
9957
9958fn default_license_pct() -> f64 {
9959 0.25
9960}
9961
9962fn default_services_pct() -> f64 {
9963 0.15
9964}
9965
9966impl Default for TechnologyConfig {
9967 fn default() -> Self {
9968 Self {
9969 enabled: false,
9970 revenue_model: default_revenue_model(),
9971 subscription_revenue_pct: default_subscription_pct(),
9972 license_revenue_pct: default_license_pct(),
9973 services_revenue_pct: default_services_pct(),
9974 rd_capitalization: RdCapitalizationConfig::default(),
9975 anomaly_rates: TechnologyAnomalyRates::default(),
9976 }
9977 }
9978}
9979
9980#[derive(Debug, Clone, Serialize, Deserialize)]
9982pub struct RdCapitalizationConfig {
9983 #[serde(default = "default_true")]
9985 pub enabled: bool,
9986
9987 #[serde(default = "default_cap_rate")]
9989 pub capitalization_rate: f64,
9990
9991 #[serde(default = "default_useful_life")]
9993 pub useful_life_years: u32,
9994}
9995
9996fn default_cap_rate() -> f64 {
9997 0.30
9998}
9999
10000fn default_useful_life() -> u32 {
10001 3
10002}
10003
10004impl Default for RdCapitalizationConfig {
10005 fn default() -> Self {
10006 Self {
10007 enabled: true,
10008 capitalization_rate: default_cap_rate(),
10009 useful_life_years: default_useful_life(),
10010 }
10011 }
10012}
10013
10014#[derive(Debug, Clone, Serialize, Deserialize)]
10016pub struct TechnologyAnomalyRates {
10017 #[serde(default = "default_premature_rev_rate")]
10019 pub premature_revenue: f64,
10020
10021 #[serde(default = "default_side_letter_rate")]
10023 pub side_letter_abuse: f64,
10024
10025 #[serde(default = "default_channel_stuffing_rate")]
10027 pub channel_stuffing: f64,
10028
10029 #[serde(default = "default_improper_cap_rate")]
10031 pub improper_capitalization: f64,
10032}
10033
10034fn default_premature_rev_rate() -> f64 {
10035 0.015
10036}
10037
10038fn default_side_letter_rate() -> f64 {
10039 0.008
10040}
10041
10042fn default_channel_stuffing_rate() -> f64 {
10043 0.01
10044}
10045
10046fn default_improper_cap_rate() -> f64 {
10047 0.012
10048}
10049
10050impl Default for TechnologyAnomalyRates {
10051 fn default() -> Self {
10052 Self {
10053 premature_revenue: default_premature_rev_rate(),
10054 side_letter_abuse: default_side_letter_rate(),
10055 channel_stuffing: default_channel_stuffing_rate(),
10056 improper_capitalization: default_improper_cap_rate(),
10057 }
10058 }
10059}
10060
10061#[derive(Debug, Clone, Serialize, Deserialize)]
10063pub struct FinancialServicesConfig {
10064 #[serde(default)]
10066 pub enabled: bool,
10067
10068 #[serde(default = "default_fi_type")]
10070 pub institution_type: String,
10071
10072 #[serde(default = "default_fi_regulatory")]
10074 pub regulatory_framework: String,
10075
10076 #[serde(default)]
10078 pub anomaly_rates: FinancialServicesAnomalyRates,
10079}
10080
10081fn default_fi_type() -> String {
10082 "commercial_bank".to_string()
10083}
10084
10085fn default_fi_regulatory() -> String {
10086 "us_banking".to_string()
10087}
10088
10089impl Default for FinancialServicesConfig {
10090 fn default() -> Self {
10091 Self {
10092 enabled: false,
10093 institution_type: default_fi_type(),
10094 regulatory_framework: default_fi_regulatory(),
10095 anomaly_rates: FinancialServicesAnomalyRates::default(),
10096 }
10097 }
10098}
10099
10100#[derive(Debug, Clone, Serialize, Deserialize)]
10102pub struct FinancialServicesAnomalyRates {
10103 #[serde(default = "default_loan_fraud_rate")]
10105 pub loan_fraud: f64,
10106
10107 #[serde(default = "default_trading_fraud_rate")]
10109 pub trading_fraud: f64,
10110
10111 #[serde(default = "default_insurance_fraud_rate")]
10113 pub insurance_fraud: f64,
10114
10115 #[serde(default = "default_account_manip_rate")]
10117 pub account_manipulation: f64,
10118}
10119
10120fn default_loan_fraud_rate() -> f64 {
10121 0.01
10122}
10123
10124fn default_trading_fraud_rate() -> f64 {
10125 0.008
10126}
10127
10128fn default_insurance_fraud_rate() -> f64 {
10129 0.012
10130}
10131
10132fn default_account_manip_rate() -> f64 {
10133 0.005
10134}
10135
10136impl Default for FinancialServicesAnomalyRates {
10137 fn default() -> Self {
10138 Self {
10139 loan_fraud: default_loan_fraud_rate(),
10140 trading_fraud: default_trading_fraud_rate(),
10141 insurance_fraud: default_insurance_fraud_rate(),
10142 account_manipulation: default_account_manip_rate(),
10143 }
10144 }
10145}
10146
10147#[derive(Debug, Clone, Serialize, Deserialize)]
10149pub struct ProfessionalServicesConfig {
10150 #[serde(default)]
10152 pub enabled: bool,
10153
10154 #[serde(default = "default_firm_type")]
10156 pub firm_type: String,
10157
10158 #[serde(default = "default_billing_model")]
10160 pub billing_model: String,
10161
10162 #[serde(default = "default_hourly_rate")]
10164 pub avg_hourly_rate: f64,
10165
10166 #[serde(default)]
10168 pub trust_accounting: TrustAccountingConfig,
10169
10170 #[serde(default)]
10172 pub anomaly_rates: ProfessionalServicesAnomalyRates,
10173}
10174
10175fn default_firm_type() -> String {
10176 "consulting".to_string()
10177}
10178
10179fn default_billing_model() -> String {
10180 "time_and_materials".to_string()
10181}
10182
10183fn default_hourly_rate() -> f64 {
10184 250.0
10185}
10186
10187impl Default for ProfessionalServicesConfig {
10188 fn default() -> Self {
10189 Self {
10190 enabled: false,
10191 firm_type: default_firm_type(),
10192 billing_model: default_billing_model(),
10193 avg_hourly_rate: default_hourly_rate(),
10194 trust_accounting: TrustAccountingConfig::default(),
10195 anomaly_rates: ProfessionalServicesAnomalyRates::default(),
10196 }
10197 }
10198}
10199
10200#[derive(Debug, Clone, Serialize, Deserialize)]
10202pub struct TrustAccountingConfig {
10203 #[serde(default)]
10205 pub enabled: bool,
10206
10207 #[serde(default = "default_true")]
10209 pub require_three_way_reconciliation: bool,
10210}
10211
10212impl Default for TrustAccountingConfig {
10213 fn default() -> Self {
10214 Self {
10215 enabled: false,
10216 require_three_way_reconciliation: true,
10217 }
10218 }
10219}
10220
10221#[derive(Debug, Clone, Serialize, Deserialize)]
10223pub struct ProfessionalServicesAnomalyRates {
10224 #[serde(default = "default_time_fraud_rate")]
10226 pub time_billing_fraud: f64,
10227
10228 #[serde(default = "default_expense_fraud_rate")]
10230 pub expense_fraud: f64,
10231
10232 #[serde(default = "default_trust_misappropriation_rate")]
10234 pub trust_misappropriation: f64,
10235}
10236
10237fn default_time_fraud_rate() -> f64 {
10238 0.02
10239}
10240
10241fn default_expense_fraud_rate() -> f64 {
10242 0.015
10243}
10244
10245fn default_trust_misappropriation_rate() -> f64 {
10246 0.003
10247}
10248
10249impl Default for ProfessionalServicesAnomalyRates {
10250 fn default() -> Self {
10251 Self {
10252 time_billing_fraud: default_time_fraud_rate(),
10253 expense_fraud: default_expense_fraud_rate(),
10254 trust_misappropriation: default_trust_misappropriation_rate(),
10255 }
10256 }
10257}
10258
10259#[derive(Debug, Clone, Serialize, Deserialize)]
10273pub struct FingerprintPrivacyConfig {
10274 #[serde(default)]
10276 pub level: String,
10277 #[serde(default = "default_epsilon")]
10279 pub epsilon: f64,
10280 #[serde(default = "default_delta")]
10282 pub delta: f64,
10283 #[serde(default = "default_k_anonymity")]
10285 pub k_anonymity: u32,
10286 #[serde(default)]
10288 pub composition_method: String,
10289}
10290
10291fn default_epsilon() -> f64 {
10292 1.0
10293}
10294
10295fn default_delta() -> f64 {
10296 1e-5
10297}
10298
10299fn default_k_anonymity() -> u32 {
10300 5
10301}
10302
10303impl Default for FingerprintPrivacyConfig {
10304 fn default() -> Self {
10305 Self {
10306 level: "standard".to_string(),
10307 epsilon: default_epsilon(),
10308 delta: default_delta(),
10309 k_anonymity: default_k_anonymity(),
10310 composition_method: "naive".to_string(),
10311 }
10312 }
10313}
10314
10315#[derive(Debug, Clone, Serialize, Deserialize)]
10329pub struct QualityGatesSchemaConfig {
10330 #[serde(default)]
10332 pub enabled: bool,
10333 #[serde(default = "default_gate_profile_name")]
10335 pub profile: String,
10336 #[serde(default)]
10338 pub fail_on_violation: bool,
10339 #[serde(default)]
10341 pub custom_gates: Vec<QualityGateEntry>,
10342}
10343
10344fn default_gate_profile_name() -> String {
10345 "default".to_string()
10346}
10347
10348impl Default for QualityGatesSchemaConfig {
10349 fn default() -> Self {
10350 Self {
10351 enabled: false,
10352 profile: default_gate_profile_name(),
10353 fail_on_violation: false,
10354 custom_gates: Vec::new(),
10355 }
10356 }
10357}
10358
10359#[derive(Debug, Clone, Serialize, Deserialize)]
10361pub struct QualityGateEntry {
10362 pub name: String,
10364 pub metric: String,
10368 pub threshold: f64,
10370 #[serde(default)]
10372 pub upper_threshold: Option<f64>,
10373 #[serde(default = "default_gate_comparison")]
10375 pub comparison: String,
10376}
10377
10378fn default_gate_comparison() -> String {
10379 "gte".to_string()
10380}
10381
10382#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10392pub struct ComplianceSchemaConfig {
10393 #[serde(default)]
10395 pub content_marking: ContentMarkingSchemaConfig,
10396 #[serde(default)]
10398 pub article10_report: bool,
10399 #[serde(default)]
10401 pub certificates: CertificateSchemaConfig,
10402}
10403
10404#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10406pub struct CertificateSchemaConfig {
10407 #[serde(default)]
10409 pub enabled: bool,
10410 #[serde(default)]
10412 pub signing_key_env: Option<String>,
10413 #[serde(default)]
10415 pub include_quality_metrics: bool,
10416}
10417
10418#[derive(Debug, Clone, Serialize, Deserialize)]
10420pub struct ContentMarkingSchemaConfig {
10421 #[serde(default = "default_true")]
10423 pub enabled: bool,
10424 #[serde(default = "default_marking_format")]
10426 pub format: String,
10427}
10428
10429fn default_marking_format() -> String {
10430 "embedded".to_string()
10431}
10432
10433impl Default for ContentMarkingSchemaConfig {
10434 fn default() -> Self {
10435 Self {
10436 enabled: true,
10437 format: default_marking_format(),
10438 }
10439 }
10440}
10441
10442#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10444pub struct WebhookSchemaConfig {
10445 #[serde(default)]
10447 pub enabled: bool,
10448 #[serde(default)]
10450 pub endpoints: Vec<WebhookEndpointConfig>,
10451}
10452
10453#[derive(Debug, Clone, Serialize, Deserialize)]
10455pub struct WebhookEndpointConfig {
10456 pub url: String,
10458 #[serde(default)]
10460 pub events: Vec<String>,
10461 #[serde(default)]
10463 pub secret: Option<String>,
10464 #[serde(default = "default_webhook_retries")]
10466 pub max_retries: u32,
10467 #[serde(default = "default_webhook_timeout")]
10469 pub timeout_secs: u64,
10470}
10471
10472fn default_webhook_retries() -> u32 {
10473 3
10474}
10475fn default_webhook_timeout() -> u64 {
10476 10
10477}
10478
10479#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10485pub struct SourceToPayConfig {
10486 #[serde(default)]
10488 pub enabled: bool,
10489 #[serde(default)]
10491 pub spend_analysis: SpendAnalysisConfig,
10492 #[serde(default)]
10494 pub sourcing: SourcingConfig,
10495 #[serde(default)]
10497 pub qualification: QualificationConfig,
10498 #[serde(default)]
10500 pub rfx: RfxConfig,
10501 #[serde(default)]
10503 pub contracts: ContractConfig,
10504 #[serde(default)]
10506 pub catalog: CatalogConfig,
10507 #[serde(default)]
10509 pub scorecards: ScorecardConfig,
10510 #[serde(default)]
10512 pub p2p_integration: P2PIntegrationConfig,
10513}
10514
10515#[derive(Debug, Clone, Serialize, Deserialize)]
10517pub struct SpendAnalysisConfig {
10518 #[serde(default = "default_hhi_threshold")]
10520 pub hhi_threshold: f64,
10521 #[serde(default = "default_contract_coverage_target")]
10523 pub contract_coverage_target: f64,
10524}
10525
10526impl Default for SpendAnalysisConfig {
10527 fn default() -> Self {
10528 Self {
10529 hhi_threshold: default_hhi_threshold(),
10530 contract_coverage_target: default_contract_coverage_target(),
10531 }
10532 }
10533}
10534
10535fn default_hhi_threshold() -> f64 {
10536 2500.0
10537}
10538fn default_contract_coverage_target() -> f64 {
10539 0.80
10540}
10541
10542#[derive(Debug, Clone, Serialize, Deserialize)]
10544pub struct SourcingConfig {
10545 #[serde(default = "default_sourcing_projects_per_year")]
10547 pub projects_per_year: u32,
10548 #[serde(default = "default_renewal_horizon_months")]
10550 pub renewal_horizon_months: u32,
10551 #[serde(default = "default_project_duration_months")]
10553 pub project_duration_months: u32,
10554}
10555
10556impl Default for SourcingConfig {
10557 fn default() -> Self {
10558 Self {
10559 projects_per_year: default_sourcing_projects_per_year(),
10560 renewal_horizon_months: default_renewal_horizon_months(),
10561 project_duration_months: default_project_duration_months(),
10562 }
10563 }
10564}
10565
10566fn default_sourcing_projects_per_year() -> u32 {
10567 10
10568}
10569fn default_renewal_horizon_months() -> u32 {
10570 3
10571}
10572fn default_project_duration_months() -> u32 {
10573 4
10574}
10575
10576#[derive(Debug, Clone, Serialize, Deserialize)]
10578pub struct QualificationConfig {
10579 #[serde(default = "default_qualification_pass_rate")]
10581 pub pass_rate: f64,
10582 #[serde(default = "default_qualification_validity_days")]
10584 pub validity_days: u32,
10585 #[serde(default = "default_financial_weight")]
10587 pub financial_weight: f64,
10588 #[serde(default = "default_quality_weight")]
10590 pub quality_weight: f64,
10591 #[serde(default = "default_delivery_weight")]
10593 pub delivery_weight: f64,
10594 #[serde(default = "default_compliance_weight")]
10596 pub compliance_weight: f64,
10597}
10598
10599impl Default for QualificationConfig {
10600 fn default() -> Self {
10601 Self {
10602 pass_rate: default_qualification_pass_rate(),
10603 validity_days: default_qualification_validity_days(),
10604 financial_weight: default_financial_weight(),
10605 quality_weight: default_quality_weight(),
10606 delivery_weight: default_delivery_weight(),
10607 compliance_weight: default_compliance_weight(),
10608 }
10609 }
10610}
10611
10612fn default_qualification_pass_rate() -> f64 {
10613 0.75
10614}
10615fn default_qualification_validity_days() -> u32 {
10616 365
10617}
10618fn default_financial_weight() -> f64 {
10619 0.25
10620}
10621fn default_quality_weight() -> f64 {
10622 0.30
10623}
10624fn default_delivery_weight() -> f64 {
10625 0.25
10626}
10627fn default_compliance_weight() -> f64 {
10628 0.20
10629}
10630
10631#[derive(Debug, Clone, Serialize, Deserialize)]
10633pub struct RfxConfig {
10634 #[serde(default = "default_rfi_threshold")]
10636 pub rfi_threshold: f64,
10637 #[serde(default = "default_min_invited_vendors")]
10639 pub min_invited_vendors: u32,
10640 #[serde(default = "default_max_invited_vendors")]
10642 pub max_invited_vendors: u32,
10643 #[serde(default = "default_response_rate")]
10645 pub response_rate: f64,
10646 #[serde(default = "default_price_weight")]
10648 pub default_price_weight: f64,
10649 #[serde(default = "default_rfx_quality_weight")]
10651 pub default_quality_weight: f64,
10652 #[serde(default = "default_rfx_delivery_weight")]
10654 pub default_delivery_weight: f64,
10655}
10656
10657impl Default for RfxConfig {
10658 fn default() -> Self {
10659 Self {
10660 rfi_threshold: default_rfi_threshold(),
10661 min_invited_vendors: default_min_invited_vendors(),
10662 max_invited_vendors: default_max_invited_vendors(),
10663 response_rate: default_response_rate(),
10664 default_price_weight: default_price_weight(),
10665 default_quality_weight: default_rfx_quality_weight(),
10666 default_delivery_weight: default_rfx_delivery_weight(),
10667 }
10668 }
10669}
10670
10671fn default_rfi_threshold() -> f64 {
10672 100_000.0
10673}
10674fn default_min_invited_vendors() -> u32 {
10675 3
10676}
10677fn default_max_invited_vendors() -> u32 {
10678 8
10679}
10680fn default_response_rate() -> f64 {
10681 0.70
10682}
10683fn default_price_weight() -> f64 {
10684 0.40
10685}
10686fn default_rfx_quality_weight() -> f64 {
10687 0.35
10688}
10689fn default_rfx_delivery_weight() -> f64 {
10690 0.25
10691}
10692
10693#[derive(Debug, Clone, Serialize, Deserialize)]
10695pub struct ContractConfig {
10696 #[serde(default = "default_min_contract_months")]
10698 pub min_duration_months: u32,
10699 #[serde(default = "default_max_contract_months")]
10701 pub max_duration_months: u32,
10702 #[serde(default = "default_auto_renewal_rate")]
10704 pub auto_renewal_rate: f64,
10705 #[serde(default = "default_amendment_rate")]
10707 pub amendment_rate: f64,
10708 #[serde(default)]
10710 pub type_distribution: ContractTypeDistribution,
10711}
10712
10713impl Default for ContractConfig {
10714 fn default() -> Self {
10715 Self {
10716 min_duration_months: default_min_contract_months(),
10717 max_duration_months: default_max_contract_months(),
10718 auto_renewal_rate: default_auto_renewal_rate(),
10719 amendment_rate: default_amendment_rate(),
10720 type_distribution: ContractTypeDistribution::default(),
10721 }
10722 }
10723}
10724
10725fn default_min_contract_months() -> u32 {
10726 12
10727}
10728fn default_max_contract_months() -> u32 {
10729 36
10730}
10731fn default_auto_renewal_rate() -> f64 {
10732 0.40
10733}
10734fn default_amendment_rate() -> f64 {
10735 0.20
10736}
10737
10738#[derive(Debug, Clone, Serialize, Deserialize)]
10740pub struct ContractTypeDistribution {
10741 #[serde(default = "default_fixed_price_pct")]
10743 pub fixed_price: f64,
10744 #[serde(default = "default_blanket_pct")]
10746 pub blanket: f64,
10747 #[serde(default = "default_time_materials_pct")]
10749 pub time_and_materials: f64,
10750 #[serde(default = "default_service_agreement_pct")]
10752 pub service_agreement: f64,
10753}
10754
10755impl Default for ContractTypeDistribution {
10756 fn default() -> Self {
10757 Self {
10758 fixed_price: default_fixed_price_pct(),
10759 blanket: default_blanket_pct(),
10760 time_and_materials: default_time_materials_pct(),
10761 service_agreement: default_service_agreement_pct(),
10762 }
10763 }
10764}
10765
10766fn default_fixed_price_pct() -> f64 {
10767 0.40
10768}
10769fn default_blanket_pct() -> f64 {
10770 0.30
10771}
10772fn default_time_materials_pct() -> f64 {
10773 0.15
10774}
10775fn default_service_agreement_pct() -> f64 {
10776 0.15
10777}
10778
10779#[derive(Debug, Clone, Serialize, Deserialize)]
10781pub struct CatalogConfig {
10782 #[serde(default = "default_preferred_vendor_flag_rate")]
10784 pub preferred_vendor_flag_rate: f64,
10785 #[serde(default = "default_multi_source_rate")]
10787 pub multi_source_rate: f64,
10788}
10789
10790impl Default for CatalogConfig {
10791 fn default() -> Self {
10792 Self {
10793 preferred_vendor_flag_rate: default_preferred_vendor_flag_rate(),
10794 multi_source_rate: default_multi_source_rate(),
10795 }
10796 }
10797}
10798
10799fn default_preferred_vendor_flag_rate() -> f64 {
10800 0.70
10801}
10802fn default_multi_source_rate() -> f64 {
10803 0.25
10804}
10805
10806#[derive(Debug, Clone, Serialize, Deserialize)]
10808pub struct ScorecardConfig {
10809 #[serde(default = "default_scorecard_frequency")]
10811 pub frequency: String,
10812 #[serde(default = "default_otd_weight")]
10814 pub on_time_delivery_weight: f64,
10815 #[serde(default = "default_quality_score_weight")]
10817 pub quality_weight: f64,
10818 #[serde(default = "default_price_score_weight")]
10820 pub price_weight: f64,
10821 #[serde(default = "default_responsiveness_weight")]
10823 pub responsiveness_weight: f64,
10824 #[serde(default = "default_grade_a_threshold")]
10826 pub grade_a_threshold: f64,
10827 #[serde(default = "default_grade_b_threshold")]
10829 pub grade_b_threshold: f64,
10830 #[serde(default = "default_grade_c_threshold")]
10832 pub grade_c_threshold: f64,
10833}
10834
10835impl Default for ScorecardConfig {
10836 fn default() -> Self {
10837 Self {
10838 frequency: default_scorecard_frequency(),
10839 on_time_delivery_weight: default_otd_weight(),
10840 quality_weight: default_quality_score_weight(),
10841 price_weight: default_price_score_weight(),
10842 responsiveness_weight: default_responsiveness_weight(),
10843 grade_a_threshold: default_grade_a_threshold(),
10844 grade_b_threshold: default_grade_b_threshold(),
10845 grade_c_threshold: default_grade_c_threshold(),
10846 }
10847 }
10848}
10849
10850fn default_scorecard_frequency() -> String {
10851 "quarterly".to_string()
10852}
10853fn default_otd_weight() -> f64 {
10854 0.30
10855}
10856fn default_quality_score_weight() -> f64 {
10857 0.30
10858}
10859fn default_price_score_weight() -> f64 {
10860 0.25
10861}
10862fn default_responsiveness_weight() -> f64 {
10863 0.15
10864}
10865fn default_grade_a_threshold() -> f64 {
10866 90.0
10867}
10868fn default_grade_b_threshold() -> f64 {
10869 75.0
10870}
10871fn default_grade_c_threshold() -> f64 {
10872 60.0
10873}
10874
10875#[derive(Debug, Clone, Serialize, Deserialize)]
10877pub struct P2PIntegrationConfig {
10878 #[serde(default = "default_off_contract_rate")]
10880 pub off_contract_rate: f64,
10881 #[serde(default = "default_price_tolerance")]
10883 pub price_tolerance: f64,
10884 #[serde(default)]
10886 pub catalog_enforcement: bool,
10887}
10888
10889impl Default for P2PIntegrationConfig {
10890 fn default() -> Self {
10891 Self {
10892 off_contract_rate: default_off_contract_rate(),
10893 price_tolerance: default_price_tolerance(),
10894 catalog_enforcement: false,
10895 }
10896 }
10897}
10898
10899fn default_off_contract_rate() -> f64 {
10900 0.15
10901}
10902fn default_price_tolerance() -> f64 {
10903 0.02
10904}
10905
10906#[derive(Debug, Clone, Serialize, Deserialize)]
10910pub struct FinancialReportingConfig {
10911 #[serde(default)]
10913 pub enabled: bool,
10914 #[serde(default = "default_true")]
10916 pub generate_balance_sheet: bool,
10917 #[serde(default = "default_true")]
10919 pub generate_income_statement: bool,
10920 #[serde(default = "default_true")]
10922 pub generate_cash_flow: bool,
10923 #[serde(default = "default_true")]
10925 pub generate_changes_in_equity: bool,
10926 #[serde(default = "default_comparative_periods")]
10928 pub comparative_periods: u32,
10929 #[serde(default)]
10931 pub management_kpis: ManagementKpisConfig,
10932 #[serde(default)]
10934 pub budgets: BudgetConfig,
10935}
10936
10937impl Default for FinancialReportingConfig {
10938 fn default() -> Self {
10939 Self {
10940 enabled: false,
10941 generate_balance_sheet: true,
10942 generate_income_statement: true,
10943 generate_cash_flow: true,
10944 generate_changes_in_equity: true,
10945 comparative_periods: default_comparative_periods(),
10946 management_kpis: ManagementKpisConfig::default(),
10947 budgets: BudgetConfig::default(),
10948 }
10949 }
10950}
10951
10952fn default_comparative_periods() -> u32 {
10953 1
10954}
10955
10956#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10958pub struct ManagementKpisConfig {
10959 #[serde(default)]
10961 pub enabled: bool,
10962 #[serde(default = "default_kpi_frequency")]
10964 pub frequency: String,
10965}
10966
10967fn default_kpi_frequency() -> String {
10968 "monthly".to_string()
10969}
10970
10971#[derive(Debug, Clone, Serialize, Deserialize)]
10973pub struct BudgetConfig {
10974 #[serde(default)]
10976 pub enabled: bool,
10977 #[serde(default = "default_revenue_growth_rate")]
10979 pub revenue_growth_rate: f64,
10980 #[serde(default = "default_expense_inflation_rate")]
10982 pub expense_inflation_rate: f64,
10983 #[serde(default = "default_variance_noise")]
10985 pub variance_noise: f64,
10986}
10987
10988impl Default for BudgetConfig {
10989 fn default() -> Self {
10990 Self {
10991 enabled: false,
10992 revenue_growth_rate: default_revenue_growth_rate(),
10993 expense_inflation_rate: default_expense_inflation_rate(),
10994 variance_noise: default_variance_noise(),
10995 }
10996 }
10997}
10998
10999fn default_revenue_growth_rate() -> f64 {
11000 0.05
11001}
11002fn default_expense_inflation_rate() -> f64 {
11003 0.03
11004}
11005fn default_variance_noise() -> f64 {
11006 0.10
11007}
11008
11009#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11013pub struct HrConfig {
11014 #[serde(default)]
11016 pub enabled: bool,
11017 #[serde(default)]
11019 pub payroll: PayrollConfig,
11020 #[serde(default)]
11022 pub time_attendance: TimeAttendanceConfig,
11023 #[serde(default)]
11025 pub expenses: ExpenseConfig,
11026}
11027
11028#[derive(Debug, Clone, Serialize, Deserialize)]
11030pub struct PayrollConfig {
11031 #[serde(default = "default_true")]
11033 pub enabled: bool,
11034 #[serde(default = "default_pay_frequency")]
11036 pub pay_frequency: String,
11037 #[serde(default)]
11039 pub salary_ranges: PayrollSalaryRanges,
11040 #[serde(default)]
11042 pub tax_rates: PayrollTaxRates,
11043 #[serde(default = "default_benefits_enrollment_rate")]
11045 pub benefits_enrollment_rate: f64,
11046 #[serde(default = "default_retirement_participation_rate")]
11048 pub retirement_participation_rate: f64,
11049}
11050
11051impl Default for PayrollConfig {
11052 fn default() -> Self {
11053 Self {
11054 enabled: true,
11055 pay_frequency: default_pay_frequency(),
11056 salary_ranges: PayrollSalaryRanges::default(),
11057 tax_rates: PayrollTaxRates::default(),
11058 benefits_enrollment_rate: default_benefits_enrollment_rate(),
11059 retirement_participation_rate: default_retirement_participation_rate(),
11060 }
11061 }
11062}
11063
11064fn default_pay_frequency() -> String {
11065 "monthly".to_string()
11066}
11067fn default_benefits_enrollment_rate() -> f64 {
11068 0.60
11069}
11070fn default_retirement_participation_rate() -> f64 {
11071 0.45
11072}
11073
11074#[derive(Debug, Clone, Serialize, Deserialize)]
11076pub struct PayrollSalaryRanges {
11077 #[serde(default = "default_staff_min")]
11079 pub staff_min: f64,
11080 #[serde(default = "default_staff_max")]
11081 pub staff_max: f64,
11082 #[serde(default = "default_manager_min")]
11084 pub manager_min: f64,
11085 #[serde(default = "default_manager_max")]
11086 pub manager_max: f64,
11087 #[serde(default = "default_director_min")]
11089 pub director_min: f64,
11090 #[serde(default = "default_director_max")]
11091 pub director_max: f64,
11092 #[serde(default = "default_executive_min")]
11094 pub executive_min: f64,
11095 #[serde(default = "default_executive_max")]
11096 pub executive_max: f64,
11097}
11098
11099impl Default for PayrollSalaryRanges {
11100 fn default() -> Self {
11101 Self {
11102 staff_min: default_staff_min(),
11103 staff_max: default_staff_max(),
11104 manager_min: default_manager_min(),
11105 manager_max: default_manager_max(),
11106 director_min: default_director_min(),
11107 director_max: default_director_max(),
11108 executive_min: default_executive_min(),
11109 executive_max: default_executive_max(),
11110 }
11111 }
11112}
11113
11114fn default_staff_min() -> f64 {
11115 50_000.0
11116}
11117fn default_staff_max() -> f64 {
11118 70_000.0
11119}
11120fn default_manager_min() -> f64 {
11121 80_000.0
11122}
11123fn default_manager_max() -> f64 {
11124 120_000.0
11125}
11126fn default_director_min() -> f64 {
11127 120_000.0
11128}
11129fn default_director_max() -> f64 {
11130 180_000.0
11131}
11132fn default_executive_min() -> f64 {
11133 180_000.0
11134}
11135fn default_executive_max() -> f64 {
11136 350_000.0
11137}
11138
11139#[derive(Debug, Clone, Serialize, Deserialize)]
11141pub struct PayrollTaxRates {
11142 #[serde(default = "default_federal_rate")]
11144 pub federal_effective: f64,
11145 #[serde(default = "default_state_rate")]
11147 pub state_effective: f64,
11148 #[serde(default = "default_fica_rate")]
11150 pub fica: f64,
11151}
11152
11153impl Default for PayrollTaxRates {
11154 fn default() -> Self {
11155 Self {
11156 federal_effective: default_federal_rate(),
11157 state_effective: default_state_rate(),
11158 fica: default_fica_rate(),
11159 }
11160 }
11161}
11162
11163fn default_federal_rate() -> f64 {
11164 0.22
11165}
11166fn default_state_rate() -> f64 {
11167 0.05
11168}
11169fn default_fica_rate() -> f64 {
11170 0.0765
11171}
11172
11173#[derive(Debug, Clone, Serialize, Deserialize)]
11175pub struct TimeAttendanceConfig {
11176 #[serde(default = "default_true")]
11178 pub enabled: bool,
11179 #[serde(default = "default_overtime_rate")]
11181 pub overtime_rate: f64,
11182}
11183
11184impl Default for TimeAttendanceConfig {
11185 fn default() -> Self {
11186 Self {
11187 enabled: true,
11188 overtime_rate: default_overtime_rate(),
11189 }
11190 }
11191}
11192
11193fn default_overtime_rate() -> f64 {
11194 0.10
11195}
11196
11197#[derive(Debug, Clone, Serialize, Deserialize)]
11199pub struct ExpenseConfig {
11200 #[serde(default = "default_true")]
11202 pub enabled: bool,
11203 #[serde(default = "default_expense_submission_rate")]
11205 pub submission_rate: f64,
11206 #[serde(default = "default_policy_violation_rate")]
11208 pub policy_violation_rate: f64,
11209}
11210
11211impl Default for ExpenseConfig {
11212 fn default() -> Self {
11213 Self {
11214 enabled: true,
11215 submission_rate: default_expense_submission_rate(),
11216 policy_violation_rate: default_policy_violation_rate(),
11217 }
11218 }
11219}
11220
11221fn default_expense_submission_rate() -> f64 {
11222 0.30
11223}
11224fn default_policy_violation_rate() -> f64 {
11225 0.08
11226}
11227
11228#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11232pub struct ManufacturingProcessConfig {
11233 #[serde(default)]
11235 pub enabled: bool,
11236 #[serde(default)]
11238 pub production_orders: ProductionOrderConfig,
11239 #[serde(default)]
11241 pub costing: ManufacturingCostingConfig,
11242 #[serde(default)]
11244 pub routing: RoutingConfig,
11245}
11246
11247#[derive(Debug, Clone, Serialize, Deserialize)]
11249pub struct ProductionOrderConfig {
11250 #[serde(default = "default_prod_orders_per_month")]
11252 pub orders_per_month: u32,
11253 #[serde(default = "default_prod_avg_batch_size")]
11255 pub avg_batch_size: u32,
11256 #[serde(default = "default_prod_yield_rate")]
11258 pub yield_rate: f64,
11259 #[serde(default = "default_prod_make_to_order_rate")]
11261 pub make_to_order_rate: f64,
11262 #[serde(default = "default_prod_rework_rate")]
11264 pub rework_rate: f64,
11265}
11266
11267impl Default for ProductionOrderConfig {
11268 fn default() -> Self {
11269 Self {
11270 orders_per_month: default_prod_orders_per_month(),
11271 avg_batch_size: default_prod_avg_batch_size(),
11272 yield_rate: default_prod_yield_rate(),
11273 make_to_order_rate: default_prod_make_to_order_rate(),
11274 rework_rate: default_prod_rework_rate(),
11275 }
11276 }
11277}
11278
11279fn default_prod_orders_per_month() -> u32 {
11280 50
11281}
11282fn default_prod_avg_batch_size() -> u32 {
11283 100
11284}
11285fn default_prod_yield_rate() -> f64 {
11286 0.97
11287}
11288fn default_prod_make_to_order_rate() -> f64 {
11289 0.20
11290}
11291fn default_prod_rework_rate() -> f64 {
11292 0.03
11293}
11294
11295#[derive(Debug, Clone, Serialize, Deserialize)]
11297pub struct ManufacturingCostingConfig {
11298 #[serde(default = "default_labor_rate")]
11300 pub labor_rate_per_hour: f64,
11301 #[serde(default = "default_overhead_rate")]
11303 pub overhead_rate: f64,
11304 #[serde(default = "default_cost_update_frequency")]
11306 pub standard_cost_update_frequency: String,
11307}
11308
11309impl Default for ManufacturingCostingConfig {
11310 fn default() -> Self {
11311 Self {
11312 labor_rate_per_hour: default_labor_rate(),
11313 overhead_rate: default_overhead_rate(),
11314 standard_cost_update_frequency: default_cost_update_frequency(),
11315 }
11316 }
11317}
11318
11319fn default_labor_rate() -> f64 {
11320 35.0
11321}
11322fn default_overhead_rate() -> f64 {
11323 1.50
11324}
11325fn default_cost_update_frequency() -> String {
11326 "quarterly".to_string()
11327}
11328
11329#[derive(Debug, Clone, Serialize, Deserialize)]
11331pub struct RoutingConfig {
11332 #[serde(default = "default_avg_operations")]
11334 pub avg_operations: u32,
11335 #[serde(default = "default_setup_time")]
11337 pub setup_time_hours: f64,
11338 #[serde(default = "default_run_time_variation")]
11340 pub run_time_variation: f64,
11341}
11342
11343impl Default for RoutingConfig {
11344 fn default() -> Self {
11345 Self {
11346 avg_operations: default_avg_operations(),
11347 setup_time_hours: default_setup_time(),
11348 run_time_variation: default_run_time_variation(),
11349 }
11350 }
11351}
11352
11353fn default_avg_operations() -> u32 {
11354 4
11355}
11356fn default_setup_time() -> f64 {
11357 1.5
11358}
11359fn default_run_time_variation() -> f64 {
11360 0.15
11361}
11362
11363#[derive(Debug, Clone, Serialize, Deserialize)]
11367pub struct SalesQuoteConfig {
11368 #[serde(default)]
11370 pub enabled: bool,
11371 #[serde(default = "default_quotes_per_month")]
11373 pub quotes_per_month: u32,
11374 #[serde(default = "default_quote_win_rate")]
11376 pub win_rate: f64,
11377 #[serde(default = "default_quote_validity_days")]
11379 pub validity_days: u32,
11380}
11381
11382impl Default for SalesQuoteConfig {
11383 fn default() -> Self {
11384 Self {
11385 enabled: false,
11386 quotes_per_month: default_quotes_per_month(),
11387 win_rate: default_quote_win_rate(),
11388 validity_days: default_quote_validity_days(),
11389 }
11390 }
11391}
11392
11393fn default_quotes_per_month() -> u32 {
11394 30
11395}
11396fn default_quote_win_rate() -> f64 {
11397 0.35
11398}
11399fn default_quote_validity_days() -> u32 {
11400 30
11401}
11402
11403#[derive(Debug, Clone, Serialize, Deserialize)]
11412pub struct TaxConfig {
11413 #[serde(default)]
11415 pub enabled: bool,
11416 #[serde(default)]
11418 pub jurisdictions: TaxJurisdictionConfig,
11419 #[serde(default)]
11421 pub vat_gst: VatGstConfig,
11422 #[serde(default)]
11424 pub sales_tax: SalesTaxConfig,
11425 #[serde(default)]
11427 pub withholding: WithholdingTaxSchemaConfig,
11428 #[serde(default)]
11430 pub provisions: TaxProvisionSchemaConfig,
11431 #[serde(default)]
11433 pub payroll_tax: PayrollTaxSchemaConfig,
11434 #[serde(default = "default_tax_anomaly_rate")]
11436 pub anomaly_rate: f64,
11437}
11438
11439fn default_tax_anomaly_rate() -> f64 {
11440 0.03
11441}
11442
11443impl Default for TaxConfig {
11444 fn default() -> Self {
11445 Self {
11446 enabled: false,
11447 jurisdictions: TaxJurisdictionConfig::default(),
11448 vat_gst: VatGstConfig::default(),
11449 sales_tax: SalesTaxConfig::default(),
11450 withholding: WithholdingTaxSchemaConfig::default(),
11451 provisions: TaxProvisionSchemaConfig::default(),
11452 payroll_tax: PayrollTaxSchemaConfig::default(),
11453 anomaly_rate: default_tax_anomaly_rate(),
11454 }
11455 }
11456}
11457
11458#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11463pub struct TaxJurisdictionConfig {
11464 #[serde(default)]
11466 pub countries: Vec<String>,
11467 #[serde(default)]
11469 pub include_subnational: bool,
11470}
11471
11472#[derive(Debug, Clone, Serialize, Deserialize)]
11477pub struct VatGstConfig {
11478 #[serde(default)]
11480 pub enabled: bool,
11481 #[serde(default)]
11483 pub standard_rates: std::collections::HashMap<String, f64>,
11484 #[serde(default)]
11486 pub reduced_rates: std::collections::HashMap<String, f64>,
11487 #[serde(default)]
11489 pub exempt_categories: Vec<String>,
11490 #[serde(default = "default_true")]
11492 pub reverse_charge: bool,
11493}
11494
11495impl Default for VatGstConfig {
11496 fn default() -> Self {
11497 Self {
11498 enabled: false,
11499 standard_rates: std::collections::HashMap::new(),
11500 reduced_rates: std::collections::HashMap::new(),
11501 exempt_categories: Vec::new(),
11502 reverse_charge: true,
11503 }
11504 }
11505}
11506
11507#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11511pub struct SalesTaxConfig {
11512 #[serde(default)]
11514 pub enabled: bool,
11515 #[serde(default)]
11517 pub nexus_states: Vec<String>,
11518}
11519
11520#[derive(Debug, Clone, Serialize, Deserialize)]
11525pub struct WithholdingTaxSchemaConfig {
11526 #[serde(default)]
11528 pub enabled: bool,
11529 #[serde(default = "default_true")]
11531 pub treaty_network: bool,
11532 #[serde(default = "default_withholding_rate")]
11534 pub default_rate: f64,
11535 #[serde(default = "default_treaty_reduced_rate")]
11537 pub treaty_reduced_rate: f64,
11538}
11539
11540fn default_withholding_rate() -> f64 {
11541 0.30
11542}
11543
11544fn default_treaty_reduced_rate() -> f64 {
11545 0.15
11546}
11547
11548impl Default for WithholdingTaxSchemaConfig {
11549 fn default() -> Self {
11550 Self {
11551 enabled: false,
11552 treaty_network: true,
11553 default_rate: default_withholding_rate(),
11554 treaty_reduced_rate: default_treaty_reduced_rate(),
11555 }
11556 }
11557}
11558
11559#[derive(Debug, Clone, Serialize, Deserialize)]
11564pub struct TaxProvisionSchemaConfig {
11565 #[serde(default = "default_true")]
11568 pub enabled: bool,
11569 #[serde(default = "default_statutory_rate")]
11571 pub statutory_rate: f64,
11572 #[serde(default = "default_true")]
11574 pub uncertain_positions: bool,
11575}
11576
11577fn default_statutory_rate() -> f64 {
11578 0.21
11579}
11580
11581impl Default for TaxProvisionSchemaConfig {
11582 fn default() -> Self {
11583 Self {
11584 enabled: true,
11585 statutory_rate: default_statutory_rate(),
11586 uncertain_positions: true,
11587 }
11588 }
11589}
11590
11591#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11596pub struct PayrollTaxSchemaConfig {
11597 #[serde(default)]
11599 pub enabled: bool,
11600}
11601
11602#[derive(Debug, Clone, Serialize, Deserialize)]
11612pub struct TreasuryConfig {
11613 #[serde(default)]
11615 pub enabled: bool,
11616 #[serde(default)]
11618 pub cash_positioning: CashPositioningConfig,
11619 #[serde(default)]
11621 pub cash_forecasting: CashForecastingConfig,
11622 #[serde(default)]
11624 pub cash_pooling: CashPoolingConfig,
11625 #[serde(default)]
11627 pub hedging: HedgingSchemaConfig,
11628 #[serde(default)]
11630 pub debt: DebtSchemaConfig,
11631 #[serde(default)]
11633 pub netting: NettingSchemaConfig,
11634 #[serde(default)]
11636 pub bank_guarantees: BankGuaranteeSchemaConfig,
11637 #[serde(default = "default_treasury_anomaly_rate")]
11639 pub anomaly_rate: f64,
11640}
11641
11642fn default_treasury_anomaly_rate() -> f64 {
11643 0.02
11644}
11645
11646impl Default for TreasuryConfig {
11647 fn default() -> Self {
11648 Self {
11649 enabled: false,
11650 cash_positioning: CashPositioningConfig::default(),
11651 cash_forecasting: CashForecastingConfig::default(),
11652 cash_pooling: CashPoolingConfig::default(),
11653 hedging: HedgingSchemaConfig::default(),
11654 debt: DebtSchemaConfig::default(),
11655 netting: NettingSchemaConfig::default(),
11656 bank_guarantees: BankGuaranteeSchemaConfig::default(),
11657 anomaly_rate: default_treasury_anomaly_rate(),
11658 }
11659 }
11660}
11661
11662#[derive(Debug, Clone, Serialize, Deserialize)]
11666pub struct CashPositioningConfig {
11667 #[serde(default = "default_true")]
11669 pub enabled: bool,
11670 #[serde(default = "default_cash_frequency")]
11672 pub frequency: String,
11673 #[serde(default = "default_minimum_balance_policy")]
11675 pub minimum_balance_policy: f64,
11676}
11677
11678fn default_cash_frequency() -> String {
11679 "daily".to_string()
11680}
11681
11682fn default_minimum_balance_policy() -> f64 {
11683 100_000.0
11684}
11685
11686impl Default for CashPositioningConfig {
11687 fn default() -> Self {
11688 Self {
11689 enabled: true,
11690 frequency: default_cash_frequency(),
11691 minimum_balance_policy: default_minimum_balance_policy(),
11692 }
11693 }
11694}
11695
11696#[derive(Debug, Clone, Serialize, Deserialize)]
11700pub struct CashForecastingConfig {
11701 #[serde(default = "default_true")]
11703 pub enabled: bool,
11704 #[serde(default = "default_horizon_days")]
11706 pub horizon_days: u32,
11707 #[serde(default = "default_ar_probability_curve")]
11709 pub ar_collection_probability_curve: String,
11710 #[serde(default = "default_confidence_interval")]
11712 pub confidence_interval: f64,
11713}
11714
11715fn default_horizon_days() -> u32 {
11716 90
11717}
11718
11719fn default_ar_probability_curve() -> String {
11720 "aging".to_string()
11721}
11722
11723fn default_confidence_interval() -> f64 {
11724 0.90
11725}
11726
11727impl Default for CashForecastingConfig {
11728 fn default() -> Self {
11729 Self {
11730 enabled: true,
11731 horizon_days: default_horizon_days(),
11732 ar_collection_probability_curve: default_ar_probability_curve(),
11733 confidence_interval: default_confidence_interval(),
11734 }
11735 }
11736}
11737
11738#[derive(Debug, Clone, Serialize, Deserialize)]
11742pub struct CashPoolingConfig {
11743 #[serde(default)]
11745 pub enabled: bool,
11746 #[serde(default = "default_pool_type")]
11748 pub pool_type: String,
11749 #[serde(default = "default_sweep_time")]
11751 pub sweep_time: String,
11752}
11753
11754fn default_pool_type() -> String {
11755 "zero_balancing".to_string()
11756}
11757
11758fn default_sweep_time() -> String {
11759 "16:00".to_string()
11760}
11761
11762impl Default for CashPoolingConfig {
11763 fn default() -> Self {
11764 Self {
11765 enabled: false,
11766 pool_type: default_pool_type(),
11767 sweep_time: default_sweep_time(),
11768 }
11769 }
11770}
11771
11772#[derive(Debug, Clone, Serialize, Deserialize)]
11777pub struct HedgingSchemaConfig {
11778 #[serde(default)]
11780 pub enabled: bool,
11781 #[serde(default = "default_hedge_ratio")]
11783 pub hedge_ratio: f64,
11784 #[serde(default = "default_hedge_instruments")]
11786 pub instruments: Vec<String>,
11787 #[serde(default = "default_true")]
11789 pub hedge_accounting: bool,
11790 #[serde(default = "default_effectiveness_method")]
11792 pub effectiveness_method: String,
11793}
11794
11795fn default_hedge_ratio() -> f64 {
11796 0.75
11797}
11798
11799fn default_hedge_instruments() -> Vec<String> {
11800 vec!["fx_forward".to_string(), "interest_rate_swap".to_string()]
11801}
11802
11803fn default_effectiveness_method() -> String {
11804 "regression".to_string()
11805}
11806
11807impl Default for HedgingSchemaConfig {
11808 fn default() -> Self {
11809 Self {
11810 enabled: false,
11811 hedge_ratio: default_hedge_ratio(),
11812 instruments: default_hedge_instruments(),
11813 hedge_accounting: true,
11814 effectiveness_method: default_effectiveness_method(),
11815 }
11816 }
11817}
11818
11819#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11824pub struct DebtSchemaConfig {
11825 #[serde(default)]
11827 pub enabled: bool,
11828 #[serde(default)]
11830 pub instruments: Vec<DebtInstrumentDef>,
11831 #[serde(default)]
11833 pub covenants: Vec<CovenantDef>,
11834}
11835
11836#[derive(Debug, Clone, Serialize, Deserialize)]
11838pub struct DebtInstrumentDef {
11839 #[serde(rename = "type")]
11841 pub instrument_type: String,
11842 #[serde(default)]
11844 pub principal: Option<f64>,
11845 #[serde(default)]
11847 pub rate: Option<f64>,
11848 #[serde(default)]
11850 pub maturity_months: Option<u32>,
11851 #[serde(default)]
11853 pub facility: Option<f64>,
11854}
11855
11856#[derive(Debug, Clone, Serialize, Deserialize)]
11858pub struct CovenantDef {
11859 #[serde(rename = "type")]
11862 pub covenant_type: String,
11863 pub threshold: f64,
11865}
11866
11867#[derive(Debug, Clone, Serialize, Deserialize)]
11871pub struct NettingSchemaConfig {
11872 #[serde(default)]
11874 pub enabled: bool,
11875 #[serde(default = "default_netting_cycle")]
11877 pub cycle: String,
11878}
11879
11880fn default_netting_cycle() -> String {
11881 "monthly".to_string()
11882}
11883
11884impl Default for NettingSchemaConfig {
11885 fn default() -> Self {
11886 Self {
11887 enabled: false,
11888 cycle: default_netting_cycle(),
11889 }
11890 }
11891}
11892
11893#[derive(Debug, Clone, Serialize, Deserialize)]
11897pub struct BankGuaranteeSchemaConfig {
11898 #[serde(default)]
11900 pub enabled: bool,
11901 #[serde(default = "default_guarantee_count")]
11903 pub count: u32,
11904}
11905
11906fn default_guarantee_count() -> u32 {
11907 5
11908}
11909
11910impl Default for BankGuaranteeSchemaConfig {
11911 fn default() -> Self {
11912 Self {
11913 enabled: false,
11914 count: default_guarantee_count(),
11915 }
11916 }
11917}
11918
11919#[derive(Debug, Clone, Serialize, Deserialize)]
11928pub struct ProjectAccountingConfig {
11929 #[serde(default)]
11931 pub enabled: bool,
11932 #[serde(default = "default_project_count")]
11934 pub project_count: u32,
11935 #[serde(default)]
11937 pub project_types: ProjectTypeDistribution,
11938 #[serde(default)]
11940 pub wbs: WbsSchemaConfig,
11941 #[serde(default)]
11943 pub cost_allocation: CostAllocationConfig,
11944 #[serde(default)]
11946 pub revenue_recognition: ProjectRevenueRecognitionConfig,
11947 #[serde(default)]
11949 pub milestones: MilestoneSchemaConfig,
11950 #[serde(default)]
11952 pub change_orders: ChangeOrderSchemaConfig,
11953 #[serde(default)]
11955 pub retainage: RetainageSchemaConfig,
11956 #[serde(default)]
11958 pub earned_value: EarnedValueSchemaConfig,
11959 #[serde(default = "default_project_anomaly_rate")]
11961 pub anomaly_rate: f64,
11962}
11963
11964fn default_project_count() -> u32 {
11965 10
11966}
11967
11968fn default_project_anomaly_rate() -> f64 {
11969 0.03
11970}
11971
11972impl Default for ProjectAccountingConfig {
11973 fn default() -> Self {
11974 Self {
11975 enabled: false,
11976 project_count: default_project_count(),
11977 project_types: ProjectTypeDistribution::default(),
11978 wbs: WbsSchemaConfig::default(),
11979 cost_allocation: CostAllocationConfig::default(),
11980 revenue_recognition: ProjectRevenueRecognitionConfig::default(),
11981 milestones: MilestoneSchemaConfig::default(),
11982 change_orders: ChangeOrderSchemaConfig::default(),
11983 retainage: RetainageSchemaConfig::default(),
11984 earned_value: EarnedValueSchemaConfig::default(),
11985 anomaly_rate: default_project_anomaly_rate(),
11986 }
11987 }
11988}
11989
11990#[derive(Debug, Clone, Serialize, Deserialize)]
11992pub struct ProjectTypeDistribution {
11993 #[serde(default = "default_capital_weight")]
11995 pub capital: f64,
11996 #[serde(default = "default_internal_weight")]
11998 pub internal: f64,
11999 #[serde(default = "default_customer_weight")]
12001 pub customer: f64,
12002 #[serde(default = "default_rnd_weight")]
12004 pub r_and_d: f64,
12005 #[serde(default = "default_maintenance_weight")]
12007 pub maintenance: f64,
12008 #[serde(default = "default_technology_weight")]
12010 pub technology: f64,
12011}
12012
12013fn default_capital_weight() -> f64 {
12014 0.25
12015}
12016fn default_internal_weight() -> f64 {
12017 0.20
12018}
12019fn default_customer_weight() -> f64 {
12020 0.30
12021}
12022fn default_rnd_weight() -> f64 {
12023 0.10
12024}
12025fn default_maintenance_weight() -> f64 {
12026 0.10
12027}
12028fn default_technology_weight() -> f64 {
12029 0.05
12030}
12031
12032impl Default for ProjectTypeDistribution {
12033 fn default() -> Self {
12034 Self {
12035 capital: default_capital_weight(),
12036 internal: default_internal_weight(),
12037 customer: default_customer_weight(),
12038 r_and_d: default_rnd_weight(),
12039 maintenance: default_maintenance_weight(),
12040 technology: default_technology_weight(),
12041 }
12042 }
12043}
12044
12045#[derive(Debug, Clone, Serialize, Deserialize)]
12047pub struct WbsSchemaConfig {
12048 #[serde(default = "default_wbs_max_depth")]
12050 pub max_depth: u32,
12051 #[serde(default = "default_wbs_min_elements")]
12053 pub min_elements_per_level: u32,
12054 #[serde(default = "default_wbs_max_elements")]
12056 pub max_elements_per_level: u32,
12057}
12058
12059fn default_wbs_max_depth() -> u32 {
12060 3
12061}
12062fn default_wbs_min_elements() -> u32 {
12063 2
12064}
12065fn default_wbs_max_elements() -> u32 {
12066 6
12067}
12068
12069impl Default for WbsSchemaConfig {
12070 fn default() -> Self {
12071 Self {
12072 max_depth: default_wbs_max_depth(),
12073 min_elements_per_level: default_wbs_min_elements(),
12074 max_elements_per_level: default_wbs_max_elements(),
12075 }
12076 }
12077}
12078
12079#[derive(Debug, Clone, Serialize, Deserialize)]
12081pub struct CostAllocationConfig {
12082 #[serde(default = "default_time_entry_rate")]
12084 pub time_entry_project_rate: f64,
12085 #[serde(default = "default_expense_rate")]
12087 pub expense_project_rate: f64,
12088 #[serde(default = "default_po_rate")]
12090 pub purchase_order_project_rate: f64,
12091 #[serde(default = "default_vi_rate")]
12093 pub vendor_invoice_project_rate: f64,
12094}
12095
12096fn default_time_entry_rate() -> f64 {
12097 0.60
12098}
12099fn default_expense_rate() -> f64 {
12100 0.30
12101}
12102fn default_po_rate() -> f64 {
12103 0.40
12104}
12105fn default_vi_rate() -> f64 {
12106 0.35
12107}
12108
12109impl Default for CostAllocationConfig {
12110 fn default() -> Self {
12111 Self {
12112 time_entry_project_rate: default_time_entry_rate(),
12113 expense_project_rate: default_expense_rate(),
12114 purchase_order_project_rate: default_po_rate(),
12115 vendor_invoice_project_rate: default_vi_rate(),
12116 }
12117 }
12118}
12119
12120#[derive(Debug, Clone, Serialize, Deserialize)]
12122pub struct ProjectRevenueRecognitionConfig {
12123 #[serde(default = "default_true")]
12125 pub enabled: bool,
12126 #[serde(default = "default_revenue_method")]
12128 pub method: String,
12129 #[serde(default = "default_completion_measure")]
12131 pub completion_measure: String,
12132 #[serde(default = "default_avg_contract_value")]
12134 pub avg_contract_value: f64,
12135}
12136
12137fn default_revenue_method() -> String {
12138 "percentage_of_completion".to_string()
12139}
12140fn default_completion_measure() -> String {
12141 "cost_to_cost".to_string()
12142}
12143fn default_avg_contract_value() -> f64 {
12144 500_000.0
12145}
12146
12147impl Default for ProjectRevenueRecognitionConfig {
12148 fn default() -> Self {
12149 Self {
12150 enabled: true,
12151 method: default_revenue_method(),
12152 completion_measure: default_completion_measure(),
12153 avg_contract_value: default_avg_contract_value(),
12154 }
12155 }
12156}
12157
12158#[derive(Debug, Clone, Serialize, Deserialize)]
12160pub struct MilestoneSchemaConfig {
12161 #[serde(default = "default_true")]
12163 pub enabled: bool,
12164 #[serde(default = "default_milestones_per_project")]
12166 pub avg_per_project: u32,
12167 #[serde(default = "default_payment_milestone_rate")]
12169 pub payment_milestone_rate: f64,
12170}
12171
12172fn default_milestones_per_project() -> u32 {
12173 4
12174}
12175fn default_payment_milestone_rate() -> f64 {
12176 0.50
12177}
12178
12179impl Default for MilestoneSchemaConfig {
12180 fn default() -> Self {
12181 Self {
12182 enabled: true,
12183 avg_per_project: default_milestones_per_project(),
12184 payment_milestone_rate: default_payment_milestone_rate(),
12185 }
12186 }
12187}
12188
12189#[derive(Debug, Clone, Serialize, Deserialize)]
12191pub struct ChangeOrderSchemaConfig {
12192 #[serde(default = "default_true")]
12194 pub enabled: bool,
12195 #[serde(default = "default_change_order_probability")]
12197 pub probability: f64,
12198 #[serde(default = "default_max_change_orders")]
12200 pub max_per_project: u32,
12201 #[serde(default = "default_change_order_approval_rate")]
12203 pub approval_rate: f64,
12204}
12205
12206fn default_change_order_probability() -> f64 {
12207 0.40
12208}
12209fn default_max_change_orders() -> u32 {
12210 3
12211}
12212fn default_change_order_approval_rate() -> f64 {
12213 0.75
12214}
12215
12216impl Default for ChangeOrderSchemaConfig {
12217 fn default() -> Self {
12218 Self {
12219 enabled: true,
12220 probability: default_change_order_probability(),
12221 max_per_project: default_max_change_orders(),
12222 approval_rate: default_change_order_approval_rate(),
12223 }
12224 }
12225}
12226
12227#[derive(Debug, Clone, Serialize, Deserialize)]
12229pub struct RetainageSchemaConfig {
12230 #[serde(default)]
12232 pub enabled: bool,
12233 #[serde(default = "default_retainage_pct")]
12235 pub default_percentage: f64,
12236}
12237
12238fn default_retainage_pct() -> f64 {
12239 0.10
12240}
12241
12242impl Default for RetainageSchemaConfig {
12243 fn default() -> Self {
12244 Self {
12245 enabled: false,
12246 default_percentage: default_retainage_pct(),
12247 }
12248 }
12249}
12250
12251#[derive(Debug, Clone, Serialize, Deserialize)]
12253pub struct EarnedValueSchemaConfig {
12254 #[serde(default = "default_true")]
12256 pub enabled: bool,
12257 #[serde(default = "default_evm_frequency")]
12259 pub frequency: String,
12260}
12261
12262fn default_evm_frequency() -> String {
12263 "monthly".to_string()
12264}
12265
12266impl Default for EarnedValueSchemaConfig {
12267 fn default() -> Self {
12268 Self {
12269 enabled: true,
12270 frequency: default_evm_frequency(),
12271 }
12272 }
12273}
12274
12275#[derive(Debug, Clone, Serialize, Deserialize)]
12281pub struct EsgConfig {
12282 #[serde(default)]
12284 pub enabled: bool,
12285 #[serde(default)]
12287 pub environmental: EnvironmentalConfig,
12288 #[serde(default)]
12290 pub social: SocialConfig,
12291 #[serde(default)]
12293 pub governance: GovernanceSchemaConfig,
12294 #[serde(default)]
12296 pub supply_chain_esg: SupplyChainEsgConfig,
12297 #[serde(default)]
12299 pub reporting: EsgReportingConfig,
12300 #[serde(default)]
12302 pub climate_scenarios: ClimateScenarioConfig,
12303 #[serde(default = "default_esg_anomaly_rate")]
12305 pub anomaly_rate: f64,
12306}
12307
12308fn default_esg_anomaly_rate() -> f64 {
12309 0.02
12310}
12311
12312impl Default for EsgConfig {
12313 fn default() -> Self {
12314 Self {
12315 enabled: false,
12316 environmental: EnvironmentalConfig::default(),
12317 social: SocialConfig::default(),
12318 governance: GovernanceSchemaConfig::default(),
12319 supply_chain_esg: SupplyChainEsgConfig::default(),
12320 reporting: EsgReportingConfig::default(),
12321 climate_scenarios: ClimateScenarioConfig::default(),
12322 anomaly_rate: default_esg_anomaly_rate(),
12323 }
12324 }
12325}
12326
12327#[derive(Debug, Clone, Serialize, Deserialize, Default)]
12332pub struct CountryPacksSchemaConfig {
12333 #[serde(default)]
12335 pub external_dir: Option<PathBuf>,
12336 #[serde(default)]
12340 pub overrides: std::collections::HashMap<String, serde_json::Value>,
12341}
12342
12343#[derive(Debug, Clone, Serialize, Deserialize)]
12345pub struct EnvironmentalConfig {
12346 #[serde(default = "default_true")]
12348 pub enabled: bool,
12349 #[serde(default)]
12351 pub scope1: EmissionScopeConfig,
12352 #[serde(default)]
12354 pub scope2: EmissionScopeConfig,
12355 #[serde(default)]
12357 pub scope3: Scope3Config,
12358 #[serde(default)]
12360 pub energy: EnergySchemaConfig,
12361 #[serde(default)]
12363 pub water: WaterSchemaConfig,
12364 #[serde(default)]
12366 pub waste: WasteSchemaConfig,
12367}
12368
12369impl Default for EnvironmentalConfig {
12370 fn default() -> Self {
12371 Self {
12372 enabled: true,
12373 scope1: EmissionScopeConfig::default(),
12374 scope2: EmissionScopeConfig::default(),
12375 scope3: Scope3Config::default(),
12376 energy: EnergySchemaConfig::default(),
12377 water: WaterSchemaConfig::default(),
12378 waste: WasteSchemaConfig::default(),
12379 }
12380 }
12381}
12382
12383#[derive(Debug, Clone, Serialize, Deserialize)]
12385pub struct EmissionScopeConfig {
12386 #[serde(default = "default_true")]
12388 pub enabled: bool,
12389 #[serde(default = "default_emission_region")]
12391 pub factor_region: String,
12392}
12393
12394fn default_emission_region() -> String {
12395 "US".to_string()
12396}
12397
12398impl Default for EmissionScopeConfig {
12399 fn default() -> Self {
12400 Self {
12401 enabled: true,
12402 factor_region: default_emission_region(),
12403 }
12404 }
12405}
12406
12407#[derive(Debug, Clone, Serialize, Deserialize)]
12409pub struct Scope3Config {
12410 #[serde(default = "default_true")]
12412 pub enabled: bool,
12413 #[serde(default = "default_scope3_categories")]
12415 pub categories: Vec<String>,
12416 #[serde(default = "default_spend_intensity")]
12418 pub default_spend_intensity_kg_per_usd: f64,
12419}
12420
12421fn default_scope3_categories() -> Vec<String> {
12422 vec![
12423 "purchased_goods".to_string(),
12424 "business_travel".to_string(),
12425 "employee_commuting".to_string(),
12426 ]
12427}
12428
12429fn default_spend_intensity() -> f64 {
12430 0.5
12431}
12432
12433impl Default for Scope3Config {
12434 fn default() -> Self {
12435 Self {
12436 enabled: true,
12437 categories: default_scope3_categories(),
12438 default_spend_intensity_kg_per_usd: default_spend_intensity(),
12439 }
12440 }
12441}
12442
12443#[derive(Debug, Clone, Serialize, Deserialize)]
12445pub struct EnergySchemaConfig {
12446 #[serde(default = "default_true")]
12448 pub enabled: bool,
12449 #[serde(default = "default_facility_count")]
12451 pub facility_count: u32,
12452 #[serde(default = "default_renewable_target")]
12454 pub renewable_target: f64,
12455}
12456
12457fn default_facility_count() -> u32 {
12458 5
12459}
12460
12461fn default_renewable_target() -> f64 {
12462 0.30
12463}
12464
12465impl Default for EnergySchemaConfig {
12466 fn default() -> Self {
12467 Self {
12468 enabled: true,
12469 facility_count: default_facility_count(),
12470 renewable_target: default_renewable_target(),
12471 }
12472 }
12473}
12474
12475#[derive(Debug, Clone, Serialize, Deserialize)]
12477pub struct WaterSchemaConfig {
12478 #[serde(default = "default_true")]
12480 pub enabled: bool,
12481 #[serde(default = "default_water_facility_count")]
12483 pub facility_count: u32,
12484}
12485
12486fn default_water_facility_count() -> u32 {
12487 3
12488}
12489
12490impl Default for WaterSchemaConfig {
12491 fn default() -> Self {
12492 Self {
12493 enabled: true,
12494 facility_count: default_water_facility_count(),
12495 }
12496 }
12497}
12498
12499#[derive(Debug, Clone, Serialize, Deserialize)]
12501pub struct WasteSchemaConfig {
12502 #[serde(default = "default_true")]
12504 pub enabled: bool,
12505 #[serde(default = "default_diversion_target")]
12507 pub diversion_target: f64,
12508}
12509
12510fn default_diversion_target() -> f64 {
12511 0.50
12512}
12513
12514impl Default for WasteSchemaConfig {
12515 fn default() -> Self {
12516 Self {
12517 enabled: true,
12518 diversion_target: default_diversion_target(),
12519 }
12520 }
12521}
12522
12523#[derive(Debug, Clone, Serialize, Deserialize)]
12525pub struct SocialConfig {
12526 #[serde(default = "default_true")]
12528 pub enabled: bool,
12529 #[serde(default)]
12531 pub diversity: DiversitySchemaConfig,
12532 #[serde(default)]
12534 pub pay_equity: PayEquitySchemaConfig,
12535 #[serde(default)]
12537 pub safety: SafetySchemaConfig,
12538}
12539
12540impl Default for SocialConfig {
12541 fn default() -> Self {
12542 Self {
12543 enabled: true,
12544 diversity: DiversitySchemaConfig::default(),
12545 pay_equity: PayEquitySchemaConfig::default(),
12546 safety: SafetySchemaConfig::default(),
12547 }
12548 }
12549}
12550
12551#[derive(Debug, Clone, Serialize, Deserialize)]
12553pub struct DiversitySchemaConfig {
12554 #[serde(default = "default_true")]
12556 pub enabled: bool,
12557 #[serde(default = "default_diversity_dimensions")]
12559 pub dimensions: Vec<String>,
12560}
12561
12562fn default_diversity_dimensions() -> Vec<String> {
12563 vec![
12564 "gender".to_string(),
12565 "ethnicity".to_string(),
12566 "age_group".to_string(),
12567 ]
12568}
12569
12570impl Default for DiversitySchemaConfig {
12571 fn default() -> Self {
12572 Self {
12573 enabled: true,
12574 dimensions: default_diversity_dimensions(),
12575 }
12576 }
12577}
12578
12579#[derive(Debug, Clone, Serialize, Deserialize)]
12581pub struct PayEquitySchemaConfig {
12582 #[serde(default = "default_true")]
12584 pub enabled: bool,
12585 #[serde(default = "default_pay_gap_threshold")]
12587 pub gap_threshold: f64,
12588}
12589
12590fn default_pay_gap_threshold() -> f64 {
12591 0.05
12592}
12593
12594impl Default for PayEquitySchemaConfig {
12595 fn default() -> Self {
12596 Self {
12597 enabled: true,
12598 gap_threshold: default_pay_gap_threshold(),
12599 }
12600 }
12601}
12602
12603#[derive(Debug, Clone, Serialize, Deserialize)]
12605pub struct SafetySchemaConfig {
12606 #[serde(default = "default_true")]
12608 pub enabled: bool,
12609 #[serde(default = "default_trir_target")]
12611 pub target_trir: f64,
12612 #[serde(default = "default_incident_count")]
12614 pub incident_count: u32,
12615}
12616
12617fn default_trir_target() -> f64 {
12618 2.5
12619}
12620
12621fn default_incident_count() -> u32 {
12622 20
12623}
12624
12625impl Default for SafetySchemaConfig {
12626 fn default() -> Self {
12627 Self {
12628 enabled: true,
12629 target_trir: default_trir_target(),
12630 incident_count: default_incident_count(),
12631 }
12632 }
12633}
12634
12635#[derive(Debug, Clone, Serialize, Deserialize)]
12637pub struct GovernanceSchemaConfig {
12638 #[serde(default = "default_true")]
12640 pub enabled: bool,
12641 #[serde(default = "default_board_size")]
12643 pub board_size: u32,
12644 #[serde(default = "default_independence_target")]
12646 pub independence_target: f64,
12647}
12648
12649fn default_board_size() -> u32 {
12650 11
12651}
12652
12653fn default_independence_target() -> f64 {
12654 0.67
12655}
12656
12657impl Default for GovernanceSchemaConfig {
12658 fn default() -> Self {
12659 Self {
12660 enabled: true,
12661 board_size: default_board_size(),
12662 independence_target: default_independence_target(),
12663 }
12664 }
12665}
12666
12667#[derive(Debug, Clone, Serialize, Deserialize)]
12669pub struct SupplyChainEsgConfig {
12670 #[serde(default = "default_true")]
12672 pub enabled: bool,
12673 #[serde(default = "default_assessment_coverage")]
12675 pub assessment_coverage: f64,
12676 #[serde(default = "default_high_risk_countries")]
12678 pub high_risk_countries: Vec<String>,
12679}
12680
12681fn default_assessment_coverage() -> f64 {
12682 0.80
12683}
12684
12685fn default_high_risk_countries() -> Vec<String> {
12686 vec!["CN".to_string(), "BD".to_string(), "MM".to_string()]
12687}
12688
12689impl Default for SupplyChainEsgConfig {
12690 fn default() -> Self {
12691 Self {
12692 enabled: true,
12693 assessment_coverage: default_assessment_coverage(),
12694 high_risk_countries: default_high_risk_countries(),
12695 }
12696 }
12697}
12698
12699#[derive(Debug, Clone, Serialize, Deserialize)]
12701pub struct EsgReportingConfig {
12702 #[serde(default = "default_true")]
12704 pub enabled: bool,
12705 #[serde(default = "default_esg_frameworks")]
12707 pub frameworks: Vec<String>,
12708 #[serde(default = "default_true")]
12710 pub materiality_assessment: bool,
12711 #[serde(default = "default_materiality_threshold")]
12713 pub impact_threshold: f64,
12714 #[serde(default = "default_materiality_threshold")]
12716 pub financial_threshold: f64,
12717}
12718
12719fn default_esg_frameworks() -> Vec<String> {
12720 vec!["GRI".to_string(), "ESRS".to_string()]
12721}
12722
12723fn default_materiality_threshold() -> f64 {
12724 0.6
12725}
12726
12727impl Default for EsgReportingConfig {
12728 fn default() -> Self {
12729 Self {
12730 enabled: true,
12731 frameworks: default_esg_frameworks(),
12732 materiality_assessment: true,
12733 impact_threshold: default_materiality_threshold(),
12734 financial_threshold: default_materiality_threshold(),
12735 }
12736 }
12737}
12738
12739#[derive(Debug, Clone, Serialize, Deserialize)]
12741pub struct ClimateScenarioConfig {
12742 #[serde(default)]
12744 pub enabled: bool,
12745 #[serde(default = "default_climate_scenarios")]
12747 pub scenarios: Vec<String>,
12748 #[serde(default = "default_time_horizons")]
12750 pub time_horizons: Vec<u32>,
12751}
12752
12753fn default_climate_scenarios() -> Vec<String> {
12754 vec![
12755 "net_zero_2050".to_string(),
12756 "stated_policies".to_string(),
12757 "current_trajectory".to_string(),
12758 ]
12759}
12760
12761fn default_time_horizons() -> Vec<u32> {
12762 vec![5, 10, 30]
12763}
12764
12765impl Default for ClimateScenarioConfig {
12766 fn default() -> Self {
12767 Self {
12768 enabled: false,
12769 scenarios: default_climate_scenarios(),
12770 time_horizons: default_time_horizons(),
12771 }
12772 }
12773}
12774
12775#[derive(Debug, Clone, Serialize, Deserialize, Default)]
12779pub struct ScenariosConfig {
12780 #[serde(default)]
12782 pub enabled: bool,
12783 #[serde(default)]
12785 pub scenarios: Vec<ScenarioSchemaConfig>,
12786 #[serde(default)]
12788 pub causal_model: CausalModelSchemaConfig,
12789 #[serde(default)]
12791 pub defaults: ScenarioDefaultsConfig,
12792 #[serde(default)]
12795 pub generate_counterfactuals: bool,
12796}
12797
12798#[derive(Debug, Clone, Serialize, Deserialize)]
12800pub struct ScenarioSchemaConfig {
12801 pub name: String,
12803 #[serde(default)]
12805 pub description: String,
12806 #[serde(default)]
12808 pub tags: Vec<String>,
12809 pub base: Option<String>,
12811 pub probability_weight: Option<f64>,
12813 #[serde(default)]
12815 pub interventions: Vec<InterventionSchemaConfig>,
12816 #[serde(default)]
12818 pub constraints: ScenarioConstraintsSchemaConfig,
12819 #[serde(default)]
12821 pub output: ScenarioOutputSchemaConfig,
12822 #[serde(default)]
12824 pub metadata: std::collections::HashMap<String, String>,
12825}
12826
12827#[derive(Debug, Clone, Serialize, Deserialize)]
12829pub struct InterventionSchemaConfig {
12830 #[serde(flatten)]
12832 pub intervention_type: serde_json::Value,
12833 #[serde(default)]
12835 pub timing: InterventionTimingSchemaConfig,
12836 pub label: Option<String>,
12838 #[serde(default)]
12840 pub priority: u32,
12841}
12842
12843#[derive(Debug, Clone, Serialize, Deserialize)]
12845pub struct InterventionTimingSchemaConfig {
12846 #[serde(default = "default_start_month")]
12848 pub start_month: u32,
12849 pub duration_months: Option<u32>,
12851 #[serde(default = "default_onset")]
12853 pub onset: String,
12854 pub ramp_months: Option<u32>,
12856}
12857
12858fn default_start_month() -> u32 {
12859 1
12860}
12861
12862fn default_onset() -> String {
12863 "sudden".to_string()
12864}
12865
12866impl Default for InterventionTimingSchemaConfig {
12867 fn default() -> Self {
12868 Self {
12869 start_month: 1,
12870 duration_months: None,
12871 onset: "sudden".to_string(),
12872 ramp_months: None,
12873 }
12874 }
12875}
12876
12877#[derive(Debug, Clone, Serialize, Deserialize)]
12879pub struct ScenarioConstraintsSchemaConfig {
12880 #[serde(default = "default_true")]
12881 pub preserve_accounting_identity: bool,
12882 #[serde(default = "default_true")]
12883 pub preserve_document_chains: bool,
12884 #[serde(default = "default_true")]
12885 pub preserve_period_close: bool,
12886 #[serde(default = "default_true")]
12887 pub preserve_balance_coherence: bool,
12888 #[serde(default)]
12889 pub custom: Vec<CustomConstraintSchemaConfig>,
12890}
12891
12892impl Default for ScenarioConstraintsSchemaConfig {
12893 fn default() -> Self {
12894 Self {
12895 preserve_accounting_identity: true,
12896 preserve_document_chains: true,
12897 preserve_period_close: true,
12898 preserve_balance_coherence: true,
12899 custom: Vec::new(),
12900 }
12901 }
12902}
12903
12904#[derive(Debug, Clone, Serialize, Deserialize)]
12906pub struct CustomConstraintSchemaConfig {
12907 pub config_path: String,
12908 pub min: Option<f64>,
12909 pub max: Option<f64>,
12910 #[serde(default)]
12911 pub description: String,
12912}
12913
12914#[derive(Debug, Clone, Serialize, Deserialize)]
12916pub struct ScenarioOutputSchemaConfig {
12917 #[serde(default = "default_true")]
12918 pub paired: bool,
12919 #[serde(default = "default_diff_formats_schema")]
12920 pub diff_formats: Vec<String>,
12921 #[serde(default)]
12922 pub diff_scope: Vec<String>,
12923}
12924
12925fn default_diff_formats_schema() -> Vec<String> {
12926 vec!["summary".to_string(), "aggregate".to_string()]
12927}
12928
12929impl Default for ScenarioOutputSchemaConfig {
12930 fn default() -> Self {
12931 Self {
12932 paired: true,
12933 diff_formats: default_diff_formats_schema(),
12934 diff_scope: Vec::new(),
12935 }
12936 }
12937}
12938
12939#[derive(Debug, Clone, Serialize, Deserialize)]
12941pub struct CausalModelSchemaConfig {
12942 #[serde(default = "default_causal_preset")]
12944 pub preset: String,
12945 #[serde(default)]
12947 pub nodes: Vec<serde_json::Value>,
12948 #[serde(default)]
12950 pub edges: Vec<serde_json::Value>,
12951}
12952
12953fn default_causal_preset() -> String {
12954 "default".to_string()
12955}
12956
12957impl Default for CausalModelSchemaConfig {
12958 fn default() -> Self {
12959 Self {
12960 preset: "default".to_string(),
12961 nodes: Vec::new(),
12962 edges: Vec::new(),
12963 }
12964 }
12965}
12966
12967#[derive(Debug, Clone, Serialize, Deserialize, Default)]
12969pub struct ScenarioDefaultsConfig {
12970 #[serde(default)]
12971 pub constraints: ScenarioConstraintsSchemaConfig,
12972 #[serde(default)]
12973 pub output: ScenarioOutputSchemaConfig,
12974}
12975
12976#[derive(Debug, Clone, Default, Serialize, Deserialize)]
13009pub struct ComplianceRegulationsConfig {
13010 #[serde(default)]
13012 pub enabled: bool,
13013 #[serde(default)]
13016 pub jurisdictions: Vec<String>,
13017 #[serde(default)]
13020 pub reference_date: Option<String>,
13021 #[serde(default)]
13023 pub standards_selection: StandardsSelectionConfig,
13024 #[serde(default)]
13026 pub audit_procedures: AuditProcedureGenConfig,
13027 #[serde(default)]
13029 pub findings: ComplianceFindingGenConfig,
13030 #[serde(default)]
13032 pub filings: ComplianceFilingGenConfig,
13033 #[serde(default)]
13035 pub graph: ComplianceGraphConfig,
13036 #[serde(default)]
13038 pub output: ComplianceOutputConfig,
13039}
13040
13041#[derive(Debug, Clone, Default, Serialize, Deserialize)]
13043pub struct StandardsSelectionConfig {
13044 #[serde(default)]
13047 pub categories: Vec<String>,
13048 #[serde(default)]
13051 pub include: Vec<String>,
13052 #[serde(default)]
13054 pub exclude: Vec<String>,
13055 #[serde(default)]
13057 pub include_superseded: bool,
13058}
13059
13060#[derive(Debug, Clone, Serialize, Deserialize)]
13062pub struct AuditProcedureGenConfig {
13063 #[serde(default)]
13065 pub enabled: bool,
13066 #[serde(default = "default_procedures_per_standard")]
13068 pub procedures_per_standard: usize,
13069 #[serde(default = "default_sampling_method")]
13071 pub sampling_method: String,
13072 #[serde(default = "default_confidence_level")]
13074 pub confidence_level: f64,
13075 #[serde(default = "default_tolerable_misstatement")]
13077 pub tolerable_misstatement: f64,
13078}
13079
13080fn default_procedures_per_standard() -> usize {
13081 3
13082}
13083
13084fn default_sampling_method() -> String {
13085 "statistical".to_string()
13086}
13087
13088fn default_confidence_level() -> f64 {
13089 0.95
13090}
13091
13092fn default_tolerable_misstatement() -> f64 {
13093 0.05
13094}
13095
13096impl Default for AuditProcedureGenConfig {
13097 fn default() -> Self {
13098 Self {
13099 enabled: false,
13100 procedures_per_standard: default_procedures_per_standard(),
13101 sampling_method: default_sampling_method(),
13102 confidence_level: default_confidence_level(),
13103 tolerable_misstatement: default_tolerable_misstatement(),
13104 }
13105 }
13106}
13107
13108#[derive(Debug, Clone, Serialize, Deserialize)]
13110pub struct ComplianceFindingGenConfig {
13111 #[serde(default)]
13113 pub enabled: bool,
13114 #[serde(default = "default_finding_rate")]
13116 pub finding_rate: f64,
13117 #[serde(default = "default_cr_material_weakness_rate")]
13119 pub material_weakness_rate: f64,
13120 #[serde(default = "default_cr_significant_deficiency_rate")]
13122 pub significant_deficiency_rate: f64,
13123 #[serde(default = "default_true")]
13125 pub generate_remediation: bool,
13126}
13127
13128fn default_finding_rate() -> f64 {
13129 0.05
13130}
13131
13132fn default_cr_material_weakness_rate() -> f64 {
13133 0.02
13134}
13135
13136fn default_cr_significant_deficiency_rate() -> f64 {
13137 0.08
13138}
13139
13140impl Default for ComplianceFindingGenConfig {
13141 fn default() -> Self {
13142 Self {
13143 enabled: false,
13144 finding_rate: default_finding_rate(),
13145 material_weakness_rate: default_cr_material_weakness_rate(),
13146 significant_deficiency_rate: default_cr_significant_deficiency_rate(),
13147 generate_remediation: true,
13148 }
13149 }
13150}
13151
13152#[derive(Debug, Clone, Serialize, Deserialize)]
13154pub struct ComplianceFilingGenConfig {
13155 #[serde(default)]
13157 pub enabled: bool,
13158 #[serde(default)]
13161 pub filing_types: Vec<String>,
13162 #[serde(default = "default_true")]
13164 pub generate_status_progression: bool,
13165}
13166
13167impl Default for ComplianceFilingGenConfig {
13168 fn default() -> Self {
13169 Self {
13170 enabled: false,
13171 filing_types: Vec::new(),
13172 generate_status_progression: true,
13173 }
13174 }
13175}
13176
13177#[derive(Debug, Clone, Serialize, Deserialize)]
13179pub struct ComplianceGraphConfig {
13180 #[serde(default)]
13182 pub enabled: bool,
13183 #[serde(default = "default_true")]
13185 pub include_compliance_nodes: bool,
13186 #[serde(default = "default_true")]
13188 pub include_compliance_edges: bool,
13189 #[serde(default = "default_true")]
13191 pub include_cross_references: bool,
13192 #[serde(default)]
13194 pub include_supersession_edges: bool,
13195 #[serde(default = "default_true")]
13197 pub include_account_links: bool,
13198 #[serde(default = "default_true")]
13200 pub include_control_links: bool,
13201 #[serde(default = "default_true")]
13203 pub include_company_links: bool,
13204}
13205
13206impl Default for ComplianceGraphConfig {
13207 fn default() -> Self {
13208 Self {
13209 enabled: false,
13210 include_compliance_nodes: true,
13211 include_compliance_edges: true,
13212 include_cross_references: true,
13213 include_supersession_edges: false,
13214 include_account_links: true,
13215 include_control_links: true,
13216 include_company_links: true,
13217 }
13218 }
13219}
13220
13221#[derive(Debug, Clone, Serialize, Deserialize)]
13223pub struct ComplianceOutputConfig {
13224 #[serde(default = "default_true")]
13226 pub export_registry: bool,
13227 #[serde(default = "default_true")]
13229 pub export_jurisdictions: bool,
13230 #[serde(default = "default_true")]
13232 pub export_cross_references: bool,
13233 #[serde(default)]
13235 pub export_version_history: bool,
13236}
13237
13238impl Default for ComplianceOutputConfig {
13239 fn default() -> Self {
13240 Self {
13241 export_registry: true,
13242 export_jurisdictions: true,
13243 export_cross_references: true,
13244 export_version_history: false,
13245 }
13246 }
13247}
13248
13249#[cfg(test)]
13250#[allow(clippy::unwrap_used)]
13251mod tests {
13252 use super::*;
13253 use crate::presets::demo_preset;
13254
13255 #[test]
13260 fn test_config_yaml_roundtrip() {
13261 let config = demo_preset();
13262 let yaml = serde_yaml::to_string(&config).expect("Failed to serialize to YAML");
13263 let deserialized: GeneratorConfig =
13264 serde_yaml::from_str(&yaml).expect("Failed to deserialize from YAML");
13265
13266 assert_eq!(
13267 config.global.period_months,
13268 deserialized.global.period_months
13269 );
13270 assert_eq!(config.global.industry, deserialized.global.industry);
13271 assert_eq!(config.companies.len(), deserialized.companies.len());
13272 assert_eq!(config.companies[0].code, deserialized.companies[0].code);
13273 }
13274
13275 #[test]
13276 fn test_config_json_roundtrip() {
13277 let mut config = demo_preset();
13279 config.master_data.employees.approval_limits.executive = 1e12;
13281
13282 let json = serde_json::to_string(&config).expect("Failed to serialize to JSON");
13283 let deserialized: GeneratorConfig =
13284 serde_json::from_str(&json).expect("Failed to deserialize from JSON");
13285
13286 assert_eq!(
13287 config.global.period_months,
13288 deserialized.global.period_months
13289 );
13290 assert_eq!(config.global.industry, deserialized.global.industry);
13291 assert_eq!(config.companies.len(), deserialized.companies.len());
13292 }
13293
13294 #[test]
13295 fn test_transaction_volume_serialization() {
13296 let volumes = vec![
13298 (TransactionVolume::TenK, "ten_k"),
13299 (TransactionVolume::HundredK, "hundred_k"),
13300 (TransactionVolume::OneM, "one_m"),
13301 (TransactionVolume::TenM, "ten_m"),
13302 (TransactionVolume::HundredM, "hundred_m"),
13303 ];
13304
13305 for (volume, expected_key) in volumes {
13306 let json = serde_json::to_string(&volume).expect("Failed to serialize");
13307 assert!(
13308 json.contains(expected_key),
13309 "Expected {} in JSON: {}",
13310 expected_key,
13311 json
13312 );
13313 }
13314 }
13315
13316 #[test]
13317 fn test_transaction_volume_custom_serialization() {
13318 let volume = TransactionVolume::Custom(12345);
13319 let json = serde_json::to_string(&volume).expect("Failed to serialize");
13320 let deserialized: TransactionVolume =
13321 serde_json::from_str(&json).expect("Failed to deserialize");
13322 assert_eq!(deserialized.count(), 12345);
13323 }
13324
13325 #[test]
13326 fn test_output_mode_serialization() {
13327 let modes = vec![
13328 OutputMode::Streaming,
13329 OutputMode::FlatFile,
13330 OutputMode::Both,
13331 ];
13332
13333 for mode in modes {
13334 let json = serde_json::to_string(&mode).expect("Failed to serialize");
13335 let deserialized: OutputMode =
13336 serde_json::from_str(&json).expect("Failed to deserialize");
13337 assert!(format!("{:?}", mode) == format!("{:?}", deserialized));
13338 }
13339 }
13340
13341 #[test]
13342 fn test_file_format_serialization() {
13343 let formats = vec![
13344 FileFormat::Csv,
13345 FileFormat::Parquet,
13346 FileFormat::Json,
13347 FileFormat::JsonLines,
13348 ];
13349
13350 for format in formats {
13351 let json = serde_json::to_string(&format).expect("Failed to serialize");
13352 let deserialized: FileFormat =
13353 serde_json::from_str(&json).expect("Failed to deserialize");
13354 assert!(format!("{:?}", format) == format!("{:?}", deserialized));
13355 }
13356 }
13357
13358 #[test]
13359 fn test_compression_algorithm_serialization() {
13360 let algos = vec![
13361 CompressionAlgorithm::Gzip,
13362 CompressionAlgorithm::Zstd,
13363 CompressionAlgorithm::Lz4,
13364 CompressionAlgorithm::Snappy,
13365 ];
13366
13367 for algo in algos {
13368 let json = serde_json::to_string(&algo).expect("Failed to serialize");
13369 let deserialized: CompressionAlgorithm =
13370 serde_json::from_str(&json).expect("Failed to deserialize");
13371 assert!(format!("{:?}", algo) == format!("{:?}", deserialized));
13372 }
13373 }
13374
13375 #[test]
13376 fn test_transfer_pricing_method_serialization() {
13377 let methods = vec![
13378 TransferPricingMethod::CostPlus,
13379 TransferPricingMethod::ComparableUncontrolled,
13380 TransferPricingMethod::ResalePrice,
13381 TransferPricingMethod::TransactionalNetMargin,
13382 TransferPricingMethod::ProfitSplit,
13383 ];
13384
13385 for method in methods {
13386 let json = serde_json::to_string(&method).expect("Failed to serialize");
13387 let deserialized: TransferPricingMethod =
13388 serde_json::from_str(&json).expect("Failed to deserialize");
13389 assert!(format!("{:?}", method) == format!("{:?}", deserialized));
13390 }
13391 }
13392
13393 #[test]
13394 fn test_benford_exemption_serialization() {
13395 let exemptions = vec![
13396 BenfordExemption::Recurring,
13397 BenfordExemption::Payroll,
13398 BenfordExemption::FixedFees,
13399 BenfordExemption::RoundAmounts,
13400 ];
13401
13402 for exemption in exemptions {
13403 let json = serde_json::to_string(&exemption).expect("Failed to serialize");
13404 let deserialized: BenfordExemption =
13405 serde_json::from_str(&json).expect("Failed to deserialize");
13406 assert!(format!("{:?}", exemption) == format!("{:?}", deserialized));
13407 }
13408 }
13409
13410 #[test]
13415 fn test_global_config_defaults() {
13416 let yaml = r#"
13417 industry: manufacturing
13418 start_date: "2024-01-01"
13419 period_months: 6
13420 "#;
13421 let config: GlobalConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13422 assert_eq!(config.group_currency, "USD");
13423 assert!(config.parallel);
13424 assert_eq!(config.worker_threads, 0);
13425 assert_eq!(config.memory_limit_mb, 0);
13426 }
13427
13428 #[test]
13429 fn test_fraud_config_defaults() {
13430 let config = FraudConfig::default();
13431 assert!(!config.enabled);
13432 assert_eq!(config.fraud_rate, 0.005);
13433 assert!(!config.clustering_enabled);
13434 }
13435
13436 #[test]
13437 fn test_internal_controls_config_defaults() {
13438 let config = InternalControlsConfig::default();
13439 assert!(!config.enabled);
13440 assert_eq!(config.exception_rate, 0.02);
13441 assert_eq!(config.sod_violation_rate, 0.01);
13442 assert!(config.export_control_master_data);
13443 assert_eq!(config.sox_materiality_threshold, 10000.0);
13444 assert!(config.coso_enabled);
13446 assert!(!config.include_entity_level_controls);
13447 assert_eq!(config.target_maturity_level, "mixed");
13448 }
13449
13450 #[test]
13451 fn test_output_config_defaults() {
13452 let config = OutputConfig::default();
13453 assert!(matches!(config.mode, OutputMode::FlatFile));
13454 assert_eq!(config.formats, vec![FileFormat::Parquet]);
13455 assert!(config.compression.enabled);
13456 assert!(matches!(
13457 config.compression.algorithm,
13458 CompressionAlgorithm::Zstd
13459 ));
13460 assert!(config.include_acdoca);
13461 assert!(!config.include_bseg);
13462 assert!(config.partition_by_period);
13463 assert!(!config.partition_by_company);
13464 }
13465
13466 #[test]
13467 fn test_approval_config_defaults() {
13468 let config = ApprovalConfig::default();
13469 assert!(!config.enabled);
13470 assert_eq!(config.auto_approve_threshold, 1000.0);
13471 assert_eq!(config.rejection_rate, 0.02);
13472 assert_eq!(config.revision_rate, 0.05);
13473 assert_eq!(config.average_approval_delay_hours, 4.0);
13474 assert_eq!(config.thresholds.len(), 4);
13475 }
13476
13477 #[test]
13478 fn test_p2p_flow_config_defaults() {
13479 let config = P2PFlowConfig::default();
13480 assert!(config.enabled);
13481 assert_eq!(config.three_way_match_rate, 0.95);
13482 assert_eq!(config.partial_delivery_rate, 0.15);
13483 assert_eq!(config.average_po_to_gr_days, 14);
13484 }
13485
13486 #[test]
13487 fn test_o2c_flow_config_defaults() {
13488 let config = O2CFlowConfig::default();
13489 assert!(config.enabled);
13490 assert_eq!(config.credit_check_failure_rate, 0.02);
13491 assert_eq!(config.return_rate, 0.03);
13492 assert_eq!(config.bad_debt_rate, 0.01);
13493 }
13494
13495 #[test]
13496 fn test_balance_config_defaults() {
13497 let config = BalanceConfig::default();
13498 assert!(!config.generate_opening_balances);
13499 assert!(config.generate_trial_balances);
13500 assert_eq!(config.target_gross_margin, 0.35);
13501 assert!(config.validate_balance_equation);
13502 assert!(config.reconcile_subledgers);
13503 }
13504
13505 #[test]
13510 fn test_partial_config_with_defaults() {
13511 let yaml = r#"
13513 global:
13514 industry: manufacturing
13515 start_date: "2024-01-01"
13516 period_months: 3
13517 companies:
13518 - code: "TEST"
13519 name: "Test Company"
13520 currency: "USD"
13521 country: "US"
13522 annual_transaction_volume: ten_k
13523 chart_of_accounts:
13524 complexity: small
13525 output:
13526 output_directory: "./output"
13527 "#;
13528
13529 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13530 assert_eq!(config.global.period_months, 3);
13531 assert_eq!(config.companies.len(), 1);
13532 assert!(!config.fraud.enabled); assert!(!config.internal_controls.enabled); }
13535
13536 #[test]
13537 fn test_config_with_fraud_enabled() {
13538 let yaml = r#"
13539 global:
13540 industry: retail
13541 start_date: "2024-01-01"
13542 period_months: 12
13543 companies:
13544 - code: "RETAIL"
13545 name: "Retail Co"
13546 currency: "USD"
13547 country: "US"
13548 annual_transaction_volume: hundred_k
13549 chart_of_accounts:
13550 complexity: medium
13551 output:
13552 output_directory: "./output"
13553 fraud:
13554 enabled: true
13555 fraud_rate: 0.05
13556 clustering_enabled: true
13557 "#;
13558
13559 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13560 assert!(config.fraud.enabled);
13561 assert_eq!(config.fraud.fraud_rate, 0.05);
13562 assert!(config.fraud.clustering_enabled);
13563 }
13564
13565 #[test]
13566 fn test_config_with_multiple_companies() {
13567 let yaml = r#"
13568 global:
13569 industry: manufacturing
13570 start_date: "2024-01-01"
13571 period_months: 6
13572 companies:
13573 - code: "HQ"
13574 name: "Headquarters"
13575 currency: "USD"
13576 country: "US"
13577 annual_transaction_volume: hundred_k
13578 volume_weight: 1.0
13579 - code: "EU"
13580 name: "European Subsidiary"
13581 currency: "EUR"
13582 country: "DE"
13583 annual_transaction_volume: hundred_k
13584 volume_weight: 0.5
13585 - code: "APAC"
13586 name: "Asia Pacific"
13587 currency: "JPY"
13588 country: "JP"
13589 annual_transaction_volume: ten_k
13590 volume_weight: 0.3
13591 chart_of_accounts:
13592 complexity: large
13593 output:
13594 output_directory: "./output"
13595 "#;
13596
13597 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13598 assert_eq!(config.companies.len(), 3);
13599 assert_eq!(config.companies[0].code, "HQ");
13600 assert_eq!(config.companies[1].currency, "EUR");
13601 assert_eq!(config.companies[2].volume_weight, 0.3);
13602 }
13603
13604 #[test]
13605 fn test_intercompany_config() {
13606 let yaml = r#"
13607 enabled: true
13608 ic_transaction_rate: 0.20
13609 transfer_pricing_method: cost_plus
13610 markup_percent: 0.08
13611 generate_matched_pairs: true
13612 generate_eliminations: true
13613 "#;
13614
13615 let config: IntercompanyConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13616 assert!(config.enabled);
13617 assert_eq!(config.ic_transaction_rate, 0.20);
13618 assert!(matches!(
13619 config.transfer_pricing_method,
13620 TransferPricingMethod::CostPlus
13621 ));
13622 assert_eq!(config.markup_percent, 0.08);
13623 assert!(config.generate_eliminations);
13624 }
13625
13626 #[test]
13631 fn test_company_config_defaults() {
13632 let yaml = r#"
13633 code: "TEST"
13634 name: "Test Company"
13635 currency: "USD"
13636 country: "US"
13637 annual_transaction_volume: ten_k
13638 "#;
13639
13640 let config: CompanyConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13641 assert_eq!(config.fiscal_year_variant, "K4"); assert_eq!(config.volume_weight, 1.0); }
13644
13645 #[test]
13650 fn test_coa_config_defaults() {
13651 let yaml = r#"
13652 complexity: medium
13653 "#;
13654
13655 let config: ChartOfAccountsConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13656 assert!(config.industry_specific); assert!(config.custom_accounts.is_none());
13658 assert_eq!(config.min_hierarchy_depth, 2); assert_eq!(config.max_hierarchy_depth, 5); }
13661
13662 #[test]
13667 fn test_accounting_standards_config_defaults() {
13668 let config = AccountingStandardsConfig::default();
13669 assert!(!config.enabled);
13670 assert!(config.framework.is_none());
13671 assert!(!config.revenue_recognition.enabled);
13672 assert!(!config.leases.enabled);
13673 assert!(!config.fair_value.enabled);
13674 assert!(!config.impairment.enabled);
13675 assert!(!config.generate_differences);
13676 }
13677
13678 #[test]
13679 fn test_accounting_standards_config_yaml() {
13680 let yaml = r#"
13681 enabled: true
13682 framework: ifrs
13683 revenue_recognition:
13684 enabled: true
13685 generate_contracts: true
13686 avg_obligations_per_contract: 2.5
13687 variable_consideration_rate: 0.20
13688 over_time_recognition_rate: 0.35
13689 contract_count: 150
13690 leases:
13691 enabled: true
13692 lease_count: 75
13693 finance_lease_percent: 0.25
13694 avg_lease_term_months: 48
13695 generate_differences: true
13696 "#;
13697
13698 let config: AccountingStandardsConfig =
13699 serde_yaml::from_str(yaml).expect("Failed to parse");
13700 assert!(config.enabled);
13701 assert!(matches!(
13702 config.framework,
13703 Some(AccountingFrameworkConfig::Ifrs)
13704 ));
13705 assert!(config.revenue_recognition.enabled);
13706 assert_eq!(config.revenue_recognition.contract_count, 150);
13707 assert_eq!(config.revenue_recognition.avg_obligations_per_contract, 2.5);
13708 assert!(config.leases.enabled);
13709 assert_eq!(config.leases.lease_count, 75);
13710 assert_eq!(config.leases.finance_lease_percent, 0.25);
13711 assert!(config.generate_differences);
13712 }
13713
13714 #[test]
13715 fn test_accounting_framework_serialization() {
13716 let frameworks = [
13717 AccountingFrameworkConfig::UsGaap,
13718 AccountingFrameworkConfig::Ifrs,
13719 AccountingFrameworkConfig::DualReporting,
13720 AccountingFrameworkConfig::FrenchGaap,
13721 AccountingFrameworkConfig::GermanGaap,
13722 ];
13723
13724 for framework in frameworks {
13725 let json = serde_json::to_string(&framework).expect("Failed to serialize");
13726 let deserialized: AccountingFrameworkConfig =
13727 serde_json::from_str(&json).expect("Failed to deserialize");
13728 assert!(format!("{:?}", framework) == format!("{:?}", deserialized));
13729 }
13730 }
13731
13732 #[test]
13733 fn test_revenue_recognition_config_defaults() {
13734 let config = RevenueRecognitionConfig::default();
13735 assert!(!config.enabled);
13736 assert!(config.generate_contracts);
13737 assert_eq!(config.avg_obligations_per_contract, 2.0);
13738 assert_eq!(config.variable_consideration_rate, 0.15);
13739 assert_eq!(config.over_time_recognition_rate, 0.30);
13740 assert_eq!(config.contract_count, 100);
13741 }
13742
13743 #[test]
13744 fn test_lease_accounting_config_defaults() {
13745 let config = LeaseAccountingConfig::default();
13746 assert!(!config.enabled);
13747 assert_eq!(config.lease_count, 50);
13748 assert_eq!(config.finance_lease_percent, 0.30);
13749 assert_eq!(config.avg_lease_term_months, 60);
13750 assert!(config.generate_amortization);
13751 assert_eq!(config.real_estate_percent, 0.40);
13752 }
13753
13754 #[test]
13755 fn test_fair_value_config_defaults() {
13756 let config = FairValueConfig::default();
13757 assert!(!config.enabled);
13758 assert_eq!(config.measurement_count, 25);
13759 assert_eq!(config.level1_percent, 0.40);
13760 assert_eq!(config.level2_percent, 0.35);
13761 assert_eq!(config.level3_percent, 0.25);
13762 assert!(!config.include_sensitivity_analysis);
13763 }
13764
13765 #[test]
13766 fn test_impairment_config_defaults() {
13767 let config = ImpairmentConfig::default();
13768 assert!(!config.enabled);
13769 assert_eq!(config.test_count, 15);
13770 assert_eq!(config.impairment_rate, 0.10);
13771 assert!(config.generate_projections);
13772 assert!(!config.include_goodwill);
13773 }
13774
13775 #[test]
13780 fn test_audit_standards_config_defaults() {
13781 let config = AuditStandardsConfig::default();
13782 assert!(!config.enabled);
13783 assert!(!config.isa_compliance.enabled);
13784 assert!(!config.analytical_procedures.enabled);
13785 assert!(!config.confirmations.enabled);
13786 assert!(!config.opinion.enabled);
13787 assert!(!config.generate_audit_trail);
13788 assert!(!config.sox.enabled);
13789 assert!(!config.pcaob.enabled);
13790 }
13791
13792 #[test]
13793 fn test_audit_standards_config_yaml() {
13794 let yaml = r#"
13795 enabled: true
13796 isa_compliance:
13797 enabled: true
13798 compliance_level: comprehensive
13799 generate_isa_mappings: true
13800 include_pcaob: true
13801 framework: dual
13802 analytical_procedures:
13803 enabled: true
13804 procedures_per_account: 5
13805 variance_probability: 0.25
13806 confirmations:
13807 enabled: true
13808 confirmation_count: 75
13809 positive_response_rate: 0.90
13810 exception_rate: 0.08
13811 opinion:
13812 enabled: true
13813 generate_kam: true
13814 average_kam_count: 4
13815 sox:
13816 enabled: true
13817 generate_302_certifications: true
13818 generate_404_assessments: true
13819 material_weakness_rate: 0.03
13820 pcaob:
13821 enabled: true
13822 is_pcaob_audit: true
13823 include_icfr_opinion: true
13824 generate_audit_trail: true
13825 "#;
13826
13827 let config: AuditStandardsConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13828 assert!(config.enabled);
13829 assert!(config.isa_compliance.enabled);
13830 assert_eq!(config.isa_compliance.compliance_level, "comprehensive");
13831 assert!(config.isa_compliance.include_pcaob);
13832 assert_eq!(config.isa_compliance.framework, "dual");
13833 assert!(config.analytical_procedures.enabled);
13834 assert_eq!(config.analytical_procedures.procedures_per_account, 5);
13835 assert!(config.confirmations.enabled);
13836 assert_eq!(config.confirmations.confirmation_count, 75);
13837 assert!(config.opinion.enabled);
13838 assert_eq!(config.opinion.average_kam_count, 4);
13839 assert!(config.sox.enabled);
13840 assert!(config.sox.generate_302_certifications);
13841 assert_eq!(config.sox.material_weakness_rate, 0.03);
13842 assert!(config.pcaob.enabled);
13843 assert!(config.pcaob.is_pcaob_audit);
13844 assert!(config.pcaob.include_icfr_opinion);
13845 assert!(config.generate_audit_trail);
13846 }
13847
13848 #[test]
13849 fn test_isa_compliance_config_defaults() {
13850 let config = IsaComplianceConfig::default();
13851 assert!(!config.enabled);
13852 assert_eq!(config.compliance_level, "standard");
13853 assert!(config.generate_isa_mappings);
13854 assert!(config.generate_coverage_summary);
13855 assert!(!config.include_pcaob);
13856 assert_eq!(config.framework, "isa");
13857 }
13858
13859 #[test]
13860 fn test_sox_compliance_config_defaults() {
13861 let config = SoxComplianceConfig::default();
13862 assert!(!config.enabled);
13863 assert!(config.generate_302_certifications);
13864 assert!(config.generate_404_assessments);
13865 assert_eq!(config.materiality_threshold, 10000.0);
13866 assert_eq!(config.material_weakness_rate, 0.02);
13867 assert_eq!(config.significant_deficiency_rate, 0.08);
13868 }
13869
13870 #[test]
13871 fn test_pcaob_config_defaults() {
13872 let config = PcaobConfig::default();
13873 assert!(!config.enabled);
13874 assert!(!config.is_pcaob_audit);
13875 assert!(config.generate_cam);
13876 assert!(!config.include_icfr_opinion);
13877 assert!(!config.generate_standard_mappings);
13878 }
13879
13880 #[test]
13881 fn test_config_with_standards_enabled() {
13882 let yaml = r#"
13883 global:
13884 industry: financial_services
13885 start_date: "2024-01-01"
13886 period_months: 12
13887 companies:
13888 - code: "BANK"
13889 name: "Test Bank"
13890 currency: "USD"
13891 country: "US"
13892 annual_transaction_volume: hundred_k
13893 chart_of_accounts:
13894 complexity: large
13895 output:
13896 output_directory: "./output"
13897 accounting_standards:
13898 enabled: true
13899 framework: us_gaap
13900 revenue_recognition:
13901 enabled: true
13902 leases:
13903 enabled: true
13904 audit_standards:
13905 enabled: true
13906 isa_compliance:
13907 enabled: true
13908 sox:
13909 enabled: true
13910 "#;
13911
13912 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13913 assert!(config.accounting_standards.enabled);
13914 assert!(matches!(
13915 config.accounting_standards.framework,
13916 Some(AccountingFrameworkConfig::UsGaap)
13917 ));
13918 assert!(config.accounting_standards.revenue_recognition.enabled);
13919 assert!(config.accounting_standards.leases.enabled);
13920 assert!(config.audit_standards.enabled);
13921 assert!(config.audit_standards.isa_compliance.enabled);
13922 assert!(config.audit_standards.sox.enabled);
13923 }
13924
13925 #[test]
13930 fn test_industry_specific_config_defaults() {
13931 let config = IndustrySpecificConfig::default();
13932 assert!(!config.enabled);
13933 assert!(!config.manufacturing.enabled);
13934 assert!(!config.retail.enabled);
13935 assert!(!config.healthcare.enabled);
13936 assert!(!config.technology.enabled);
13937 assert!(!config.financial_services.enabled);
13938 assert!(!config.professional_services.enabled);
13939 }
13940
13941 #[test]
13942 fn test_manufacturing_config_defaults() {
13943 let config = ManufacturingConfig::default();
13944 assert!(!config.enabled);
13945 assert_eq!(config.bom_depth, 4);
13946 assert!(!config.just_in_time);
13947 assert_eq!(config.supplier_tiers, 2);
13948 assert_eq!(config.target_yield_rate, 0.97);
13949 assert_eq!(config.scrap_alert_threshold, 0.03);
13950 }
13951
13952 #[test]
13953 fn test_retail_config_defaults() {
13954 let config = RetailConfig::default();
13955 assert!(!config.enabled);
13956 assert_eq!(config.avg_daily_transactions, 500);
13957 assert!(config.loss_prevention);
13958 assert_eq!(config.shrinkage_rate, 0.015);
13959 }
13960
13961 #[test]
13962 fn test_healthcare_config_defaults() {
13963 let config = HealthcareConfig::default();
13964 assert!(!config.enabled);
13965 assert_eq!(config.facility_type, "hospital");
13966 assert_eq!(config.avg_daily_encounters, 150);
13967 assert!(config.compliance.hipaa);
13968 assert!(config.compliance.stark_law);
13969 assert!(config.coding_systems.icd10);
13970 assert!(config.coding_systems.cpt);
13971 }
13972
13973 #[test]
13974 fn test_technology_config_defaults() {
13975 let config = TechnologyConfig::default();
13976 assert!(!config.enabled);
13977 assert_eq!(config.revenue_model, "saas");
13978 assert_eq!(config.subscription_revenue_pct, 0.60);
13979 assert!(config.rd_capitalization.enabled);
13980 }
13981
13982 #[test]
13983 fn test_config_with_industry_specific() {
13984 let yaml = r#"
13985 global:
13986 industry: healthcare
13987 start_date: "2024-01-01"
13988 period_months: 12
13989 companies:
13990 - code: "HOSP"
13991 name: "Test Hospital"
13992 currency: "USD"
13993 country: "US"
13994 annual_transaction_volume: hundred_k
13995 chart_of_accounts:
13996 complexity: medium
13997 output:
13998 output_directory: "./output"
13999 industry_specific:
14000 enabled: true
14001 healthcare:
14002 enabled: true
14003 facility_type: hospital
14004 payer_mix:
14005 medicare: 0.45
14006 medicaid: 0.15
14007 commercial: 0.35
14008 self_pay: 0.05
14009 coding_systems:
14010 icd10: true
14011 cpt: true
14012 drg: true
14013 compliance:
14014 hipaa: true
14015 stark_law: true
14016 anomaly_rates:
14017 upcoding: 0.03
14018 unbundling: 0.02
14019 "#;
14020
14021 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
14022 assert!(config.industry_specific.enabled);
14023 assert!(config.industry_specific.healthcare.enabled);
14024 assert_eq!(
14025 config.industry_specific.healthcare.facility_type,
14026 "hospital"
14027 );
14028 assert_eq!(config.industry_specific.healthcare.payer_mix.medicare, 0.45);
14029 assert_eq!(config.industry_specific.healthcare.payer_mix.self_pay, 0.05);
14030 assert!(config.industry_specific.healthcare.coding_systems.icd10);
14031 assert!(config.industry_specific.healthcare.compliance.hipaa);
14032 assert_eq!(
14033 config.industry_specific.healthcare.anomaly_rates.upcoding,
14034 0.03
14035 );
14036 }
14037
14038 #[test]
14039 fn test_config_with_manufacturing_specific() {
14040 let yaml = r#"
14041 global:
14042 industry: manufacturing
14043 start_date: "2024-01-01"
14044 period_months: 12
14045 companies:
14046 - code: "MFG"
14047 name: "Test Manufacturing"
14048 currency: "USD"
14049 country: "US"
14050 annual_transaction_volume: hundred_k
14051 chart_of_accounts:
14052 complexity: medium
14053 output:
14054 output_directory: "./output"
14055 industry_specific:
14056 enabled: true
14057 manufacturing:
14058 enabled: true
14059 bom_depth: 5
14060 just_in_time: true
14061 supplier_tiers: 3
14062 target_yield_rate: 0.98
14063 anomaly_rates:
14064 yield_manipulation: 0.02
14065 phantom_production: 0.01
14066 "#;
14067
14068 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
14069 assert!(config.industry_specific.enabled);
14070 assert!(config.industry_specific.manufacturing.enabled);
14071 assert_eq!(config.industry_specific.manufacturing.bom_depth, 5);
14072 assert!(config.industry_specific.manufacturing.just_in_time);
14073 assert_eq!(config.industry_specific.manufacturing.supplier_tiers, 3);
14074 assert_eq!(
14075 config.industry_specific.manufacturing.target_yield_rate,
14076 0.98
14077 );
14078 assert_eq!(
14079 config
14080 .industry_specific
14081 .manufacturing
14082 .anomaly_rates
14083 .yield_manipulation,
14084 0.02
14085 );
14086 }
14087
14088 #[test]
14093 fn test_tax_config_defaults() {
14094 let tax = TaxConfig::default();
14095 assert!(!tax.enabled);
14096 assert!(tax.jurisdictions.countries.is_empty());
14097 assert!(!tax.jurisdictions.include_subnational);
14098 assert!(!tax.vat_gst.enabled);
14099 assert!(tax.vat_gst.standard_rates.is_empty());
14100 assert!(tax.vat_gst.reduced_rates.is_empty());
14101 assert!(tax.vat_gst.exempt_categories.is_empty());
14102 assert!(tax.vat_gst.reverse_charge);
14103 assert!(!tax.sales_tax.enabled);
14104 assert!(tax.sales_tax.nexus_states.is_empty());
14105 assert!(!tax.withholding.enabled);
14106 assert!(tax.withholding.treaty_network);
14107 assert_eq!(tax.withholding.default_rate, 0.30);
14108 assert_eq!(tax.withholding.treaty_reduced_rate, 0.15);
14109 assert!(tax.provisions.enabled);
14110 assert_eq!(tax.provisions.statutory_rate, 0.21);
14111 assert!(tax.provisions.uncertain_positions);
14112 assert!(!tax.payroll_tax.enabled);
14113 assert_eq!(tax.anomaly_rate, 0.03);
14114 }
14115
14116 #[test]
14117 fn test_tax_config_from_yaml() {
14118 let yaml = r#"
14119 global:
14120 seed: 42
14121 start_date: "2024-01-01"
14122 period_months: 12
14123 industry: retail
14124 companies:
14125 - code: C001
14126 name: Test Corp
14127 currency: USD
14128 country: US
14129 annual_transaction_volume: ten_k
14130 chart_of_accounts:
14131 complexity: small
14132 output:
14133 output_directory: ./output
14134 tax:
14135 enabled: true
14136 anomaly_rate: 0.05
14137 jurisdictions:
14138 countries: ["US", "DE", "GB"]
14139 include_subnational: true
14140 vat_gst:
14141 enabled: true
14142 standard_rates:
14143 DE: 0.19
14144 GB: 0.20
14145 reduced_rates:
14146 DE: 0.07
14147 GB: 0.05
14148 exempt_categories:
14149 - financial_services
14150 - healthcare
14151 reverse_charge: false
14152 sales_tax:
14153 enabled: true
14154 nexus_states: ["CA", "NY", "TX"]
14155 withholding:
14156 enabled: true
14157 treaty_network: false
14158 default_rate: 0.25
14159 treaty_reduced_rate: 0.10
14160 provisions:
14161 enabled: false
14162 statutory_rate: 0.28
14163 uncertain_positions: false
14164 payroll_tax:
14165 enabled: true
14166 "#;
14167
14168 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
14169 assert!(config.tax.enabled);
14170 assert_eq!(config.tax.anomaly_rate, 0.05);
14171
14172 assert_eq!(config.tax.jurisdictions.countries.len(), 3);
14174 assert!(config
14175 .tax
14176 .jurisdictions
14177 .countries
14178 .contains(&"DE".to_string()));
14179 assert!(config.tax.jurisdictions.include_subnational);
14180
14181 assert!(config.tax.vat_gst.enabled);
14183 assert_eq!(config.tax.vat_gst.standard_rates.get("DE"), Some(&0.19));
14184 assert_eq!(config.tax.vat_gst.standard_rates.get("GB"), Some(&0.20));
14185 assert_eq!(config.tax.vat_gst.reduced_rates.get("DE"), Some(&0.07));
14186 assert_eq!(config.tax.vat_gst.exempt_categories.len(), 2);
14187 assert!(!config.tax.vat_gst.reverse_charge);
14188
14189 assert!(config.tax.sales_tax.enabled);
14191 assert_eq!(config.tax.sales_tax.nexus_states.len(), 3);
14192 assert!(config
14193 .tax
14194 .sales_tax
14195 .nexus_states
14196 .contains(&"CA".to_string()));
14197
14198 assert!(config.tax.withholding.enabled);
14200 assert!(!config.tax.withholding.treaty_network);
14201 assert_eq!(config.tax.withholding.default_rate, 0.25);
14202 assert_eq!(config.tax.withholding.treaty_reduced_rate, 0.10);
14203
14204 assert!(!config.tax.provisions.enabled);
14206 assert_eq!(config.tax.provisions.statutory_rate, 0.28);
14207 assert!(!config.tax.provisions.uncertain_positions);
14208
14209 assert!(config.tax.payroll_tax.enabled);
14211 }
14212
14213 #[test]
14214 fn test_generator_config_with_tax_default() {
14215 let yaml = r#"
14216 global:
14217 seed: 42
14218 start_date: "2024-01-01"
14219 period_months: 12
14220 industry: retail
14221 companies:
14222 - code: C001
14223 name: Test Corp
14224 currency: USD
14225 country: US
14226 annual_transaction_volume: ten_k
14227 chart_of_accounts:
14228 complexity: small
14229 output:
14230 output_directory: ./output
14231 "#;
14232
14233 let config: GeneratorConfig =
14234 serde_yaml::from_str(yaml).expect("Failed to parse config without tax section");
14235 assert!(!config.tax.enabled);
14237 assert!(config.tax.jurisdictions.countries.is_empty());
14238 assert_eq!(config.tax.anomaly_rate, 0.03);
14239 assert!(config.tax.provisions.enabled); assert_eq!(config.tax.provisions.statutory_rate, 0.21);
14241 }
14242
14243 #[test]
14248 fn test_session_config_default_disabled() {
14249 let yaml = "{}";
14250 let config: SessionSchemaConfig =
14251 serde_yaml::from_str(yaml).expect("Failed to parse empty session config");
14252 assert!(!config.enabled);
14253 assert!(config.checkpoint_path.is_none());
14254 assert!(config.per_period_output);
14255 assert!(config.consolidated_output);
14256 }
14257
14258 #[test]
14259 fn test_config_backward_compatible_without_session() {
14260 let yaml = r#"
14261 global:
14262 seed: 42
14263 start_date: "2024-01-01"
14264 period_months: 12
14265 industry: retail
14266 companies:
14267 - code: C001
14268 name: Test Corp
14269 currency: USD
14270 country: US
14271 annual_transaction_volume: ten_k
14272 chart_of_accounts:
14273 complexity: small
14274 output:
14275 output_directory: ./output
14276 "#;
14277
14278 let config: GeneratorConfig =
14279 serde_yaml::from_str(yaml).expect("Failed to parse config without session");
14280 assert!(!config.session.enabled);
14282 assert!(config.session.per_period_output);
14283 assert!(config.session.consolidated_output);
14284 assert!(config.global.fiscal_year_months.is_none());
14286 }
14287
14288 #[test]
14289 fn test_fiscal_year_months_parsed() {
14290 let yaml = r#"
14291 global:
14292 seed: 42
14293 start_date: "2024-01-01"
14294 period_months: 24
14295 industry: retail
14296 fiscal_year_months: 12
14297 companies:
14298 - code: C001
14299 name: Test Corp
14300 currency: USD
14301 country: US
14302 annual_transaction_volume: ten_k
14303 chart_of_accounts:
14304 complexity: small
14305 output:
14306 output_directory: ./output
14307 session:
14308 enabled: true
14309 checkpoint_path: /tmp/checkpoints
14310 per_period_output: true
14311 consolidated_output: false
14312 "#;
14313
14314 let config: GeneratorConfig =
14315 serde_yaml::from_str(yaml).expect("Failed to parse config with fiscal_year_months");
14316 assert_eq!(config.global.fiscal_year_months, Some(12));
14317 assert!(config.session.enabled);
14318 assert_eq!(
14319 config.session.checkpoint_path,
14320 Some("/tmp/checkpoints".to_string())
14321 );
14322 assert!(config.session.per_period_output);
14323 assert!(!config.session.consolidated_output);
14324 }
14325}