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}
172
173#[derive(Debug, Clone, Serialize, Deserialize)]
179pub struct LlmSchemaConfig {
180 #[serde(default)]
182 pub enabled: bool,
183 #[serde(default = "default_llm_provider")]
185 pub provider: String,
186 #[serde(default = "default_llm_model_name")]
188 pub model: String,
189 #[serde(default = "default_llm_batch_size")]
191 pub max_vendor_enrichments: usize,
192}
193
194fn default_llm_provider() -> String {
195 "mock".to_string()
196}
197
198fn default_llm_model_name() -> String {
199 "gpt-4o-mini".to_string()
200}
201
202fn default_llm_batch_size() -> usize {
203 50
204}
205
206impl Default for LlmSchemaConfig {
207 fn default() -> Self {
208 Self {
209 enabled: false,
210 provider: default_llm_provider(),
211 model: default_llm_model_name(),
212 max_vendor_enrichments: default_llm_batch_size(),
213 }
214 }
215}
216
217#[derive(Debug, Clone, Serialize, Deserialize)]
222pub struct DiffusionSchemaConfig {
223 #[serde(default)]
225 pub enabled: bool,
226 #[serde(default = "default_diffusion_steps")]
228 pub n_steps: usize,
229 #[serde(default = "default_diffusion_schedule")]
231 pub schedule: String,
232 #[serde(default = "default_diffusion_sample_size")]
234 pub sample_size: usize,
235}
236
237fn default_diffusion_steps() -> usize {
238 100
239}
240
241fn default_diffusion_schedule() -> String {
242 "linear".to_string()
243}
244
245fn default_diffusion_sample_size() -> usize {
246 100
247}
248
249impl Default for DiffusionSchemaConfig {
250 fn default() -> Self {
251 Self {
252 enabled: false,
253 n_steps: default_diffusion_steps(),
254 schedule: default_diffusion_schedule(),
255 sample_size: default_diffusion_sample_size(),
256 }
257 }
258}
259
260#[derive(Debug, Clone, Serialize, Deserialize)]
266pub struct CausalSchemaConfig {
267 #[serde(default)]
269 pub enabled: bool,
270 #[serde(default = "default_causal_template")]
272 pub template: String,
273 #[serde(default = "default_causal_sample_size")]
275 pub sample_size: usize,
276 #[serde(default = "default_true")]
278 pub validate: bool,
279}
280
281fn default_causal_template() -> String {
282 "fraud_detection".to_string()
283}
284
285fn default_causal_sample_size() -> usize {
286 500
287}
288
289impl Default for CausalSchemaConfig {
290 fn default() -> Self {
291 Self {
292 enabled: false,
293 template: default_causal_template(),
294 sample_size: default_causal_sample_size(),
295 validate: true,
296 }
297 }
298}
299
300#[derive(Debug, Clone, Serialize, Deserialize)]
307pub struct GraphExportConfig {
308 #[serde(default)]
310 pub enabled: bool,
311
312 #[serde(default = "default_graph_types")]
314 pub graph_types: Vec<GraphTypeConfig>,
315
316 #[serde(default = "default_graph_formats")]
318 pub formats: Vec<GraphExportFormat>,
319
320 #[serde(default = "default_train_ratio")]
322 pub train_ratio: f64,
323
324 #[serde(default = "default_val_ratio")]
326 pub validation_ratio: f64,
327
328 #[serde(default)]
330 pub split_seed: Option<u64>,
331
332 #[serde(default = "default_graph_subdir")]
334 pub output_subdirectory: String,
335
336 #[serde(default)]
338 pub hypergraph: HypergraphExportSettings,
339}
340
341fn default_graph_types() -> Vec<GraphTypeConfig> {
342 vec![GraphTypeConfig::default()]
343}
344
345fn default_graph_formats() -> Vec<GraphExportFormat> {
346 vec![GraphExportFormat::PytorchGeometric]
347}
348
349fn default_train_ratio() -> f64 {
350 0.7
351}
352
353fn default_val_ratio() -> f64 {
354 0.15
355}
356
357fn default_graph_subdir() -> String {
358 "graphs".to_string()
359}
360
361impl Default for GraphExportConfig {
362 fn default() -> Self {
363 Self {
364 enabled: false,
365 graph_types: default_graph_types(),
366 formats: default_graph_formats(),
367 train_ratio: 0.7,
368 validation_ratio: 0.15,
369 split_seed: None,
370 output_subdirectory: "graphs".to_string(),
371 hypergraph: HypergraphExportSettings::default(),
372 }
373 }
374}
375
376#[derive(Debug, Clone, Serialize, Deserialize)]
383pub struct HypergraphExportSettings {
384 #[serde(default)]
386 pub enabled: bool,
387
388 #[serde(default = "default_hypergraph_max_nodes")]
390 pub max_nodes: usize,
391
392 #[serde(default = "default_aggregation_strategy")]
394 pub aggregation_strategy: String,
395
396 #[serde(default)]
398 pub governance_layer: GovernanceLayerSettings,
399
400 #[serde(default)]
402 pub process_layer: ProcessLayerSettings,
403
404 #[serde(default)]
406 pub accounting_layer: AccountingLayerSettings,
407
408 #[serde(default)]
410 pub cross_layer: CrossLayerSettings,
411
412 #[serde(default = "default_hypergraph_subdir")]
414 pub output_subdirectory: String,
415
416 #[serde(default = "default_hypergraph_format")]
418 pub output_format: String,
419
420 #[serde(default)]
422 pub stream_target: Option<String>,
423
424 #[serde(default = "default_stream_batch_size")]
426 pub stream_batch_size: usize,
427}
428
429fn default_hypergraph_max_nodes() -> usize {
430 50_000
431}
432
433fn default_aggregation_strategy() -> String {
434 "pool_by_counterparty".to_string()
435}
436
437fn default_hypergraph_subdir() -> String {
438 "hypergraph".to_string()
439}
440
441fn default_hypergraph_format() -> String {
442 "native".to_string()
443}
444
445fn default_stream_batch_size() -> usize {
446 1000
447}
448
449impl Default for HypergraphExportSettings {
450 fn default() -> Self {
451 Self {
452 enabled: false,
453 max_nodes: 50_000,
454 aggregation_strategy: "pool_by_counterparty".to_string(),
455 governance_layer: GovernanceLayerSettings::default(),
456 process_layer: ProcessLayerSettings::default(),
457 accounting_layer: AccountingLayerSettings::default(),
458 cross_layer: CrossLayerSettings::default(),
459 output_subdirectory: "hypergraph".to_string(),
460 output_format: "native".to_string(),
461 stream_target: None,
462 stream_batch_size: 1000,
463 }
464 }
465}
466
467#[derive(Debug, Clone, Serialize, Deserialize)]
469pub struct GovernanceLayerSettings {
470 #[serde(default = "default_true")]
472 pub include_coso: bool,
473 #[serde(default = "default_true")]
475 pub include_controls: bool,
476 #[serde(default = "default_true")]
478 pub include_sox: bool,
479 #[serde(default = "default_true")]
481 pub include_vendors: bool,
482 #[serde(default = "default_true")]
484 pub include_customers: bool,
485 #[serde(default = "default_true")]
487 pub include_employees: bool,
488}
489
490impl Default for GovernanceLayerSettings {
491 fn default() -> Self {
492 Self {
493 include_coso: true,
494 include_controls: true,
495 include_sox: true,
496 include_vendors: true,
497 include_customers: true,
498 include_employees: true,
499 }
500 }
501}
502
503#[derive(Debug, Clone, Serialize, Deserialize)]
505pub struct ProcessLayerSettings {
506 #[serde(default = "default_true")]
508 pub include_p2p: bool,
509 #[serde(default = "default_true")]
511 pub include_o2c: bool,
512 #[serde(default = "default_true")]
514 pub include_s2c: bool,
515 #[serde(default = "default_true")]
517 pub include_h2r: bool,
518 #[serde(default = "default_true")]
520 pub include_mfg: bool,
521 #[serde(default = "default_true")]
523 pub include_bank: bool,
524 #[serde(default = "default_true")]
526 pub include_audit: bool,
527 #[serde(default = "default_true")]
529 pub include_r2r: bool,
530 #[serde(default = "default_true")]
532 pub events_as_hyperedges: bool,
533 #[serde(default = "default_docs_per_counterparty_threshold")]
535 pub docs_per_counterparty_threshold: usize,
536}
537
538fn default_docs_per_counterparty_threshold() -> usize {
539 20
540}
541
542impl Default for ProcessLayerSettings {
543 fn default() -> Self {
544 Self {
545 include_p2p: true,
546 include_o2c: true,
547 include_s2c: true,
548 include_h2r: true,
549 include_mfg: true,
550 include_bank: true,
551 include_audit: true,
552 include_r2r: true,
553 events_as_hyperedges: true,
554 docs_per_counterparty_threshold: 20,
555 }
556 }
557}
558
559#[derive(Debug, Clone, Serialize, Deserialize)]
561pub struct AccountingLayerSettings {
562 #[serde(default = "default_true")]
564 pub include_accounts: bool,
565 #[serde(default = "default_true")]
567 pub je_as_hyperedges: bool,
568}
569
570impl Default for AccountingLayerSettings {
571 fn default() -> Self {
572 Self {
573 include_accounts: true,
574 je_as_hyperedges: true,
575 }
576 }
577}
578
579#[derive(Debug, Clone, Serialize, Deserialize)]
581pub struct CrossLayerSettings {
582 #[serde(default = "default_true")]
584 pub enabled: bool,
585}
586
587impl Default for CrossLayerSettings {
588 fn default() -> Self {
589 Self { enabled: true }
590 }
591}
592
593#[derive(Debug, Clone, Serialize, Deserialize)]
595pub struct GraphTypeConfig {
596 #[serde(default = "default_graph_name")]
598 pub name: String,
599
600 #[serde(default)]
602 pub aggregate_edges: bool,
603
604 #[serde(default)]
606 pub min_edge_weight: f64,
607
608 #[serde(default)]
610 pub include_document_nodes: bool,
611}
612
613fn default_graph_name() -> String {
614 "accounting_network".to_string()
615}
616
617impl Default for GraphTypeConfig {
618 fn default() -> Self {
619 Self {
620 name: "accounting_network".to_string(),
621 aggregate_edges: false,
622 min_edge_weight: 0.0,
623 include_document_nodes: false,
624 }
625 }
626}
627
628#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
630#[serde(rename_all = "snake_case")]
631pub enum GraphExportFormat {
632 PytorchGeometric,
634 Neo4j,
636 Dgl,
638 RustGraph,
640 RustGraphHypergraph,
642}
643
644#[derive(Debug, Clone, Default, Serialize, Deserialize)]
648pub struct ScenarioConfig {
649 #[serde(default)]
652 pub tags: Vec<String>,
653
654 #[serde(default)]
659 pub profile: Option<String>,
660
661 #[serde(default)]
663 pub description: Option<String>,
664
665 #[serde(default)]
667 pub ml_training: bool,
668
669 #[serde(default)]
672 pub target_anomaly_ratio: Option<f64>,
673
674 #[serde(default)]
676 pub metadata: std::collections::HashMap<String, String>,
677}
678
679#[derive(Debug, Clone, Serialize, Deserialize)]
684pub struct TemporalDriftConfig {
685 #[serde(default)]
687 pub enabled: bool,
688
689 #[serde(default = "default_amount_drift")]
692 pub amount_mean_drift: f64,
693
694 #[serde(default)]
697 pub amount_variance_drift: f64,
698
699 #[serde(default)]
702 pub anomaly_rate_drift: f64,
703
704 #[serde(default = "default_concept_drift")]
707 pub concept_drift_rate: f64,
708
709 #[serde(default)]
711 pub sudden_drift_probability: f64,
712
713 #[serde(default = "default_sudden_drift_magnitude")]
715 pub sudden_drift_magnitude: f64,
716
717 #[serde(default)]
719 pub seasonal_drift: bool,
720
721 #[serde(default)]
723 pub drift_start_period: u32,
724
725 #[serde(default = "default_drift_type")]
727 pub drift_type: DriftType,
728}
729
730fn default_amount_drift() -> f64 {
731 0.02
732}
733
734fn default_concept_drift() -> f64 {
735 0.01
736}
737
738fn default_sudden_drift_magnitude() -> f64 {
739 2.0
740}
741
742fn default_drift_type() -> DriftType {
743 DriftType::Gradual
744}
745
746impl Default for TemporalDriftConfig {
747 fn default() -> Self {
748 Self {
749 enabled: false,
750 amount_mean_drift: 0.02,
751 amount_variance_drift: 0.0,
752 anomaly_rate_drift: 0.0,
753 concept_drift_rate: 0.01,
754 sudden_drift_probability: 0.0,
755 sudden_drift_magnitude: 2.0,
756 seasonal_drift: false,
757 drift_start_period: 0,
758 drift_type: DriftType::Gradual,
759 }
760 }
761}
762
763impl TemporalDriftConfig {
764 pub fn to_core_config(&self) -> datasynth_core::distributions::DriftConfig {
766 datasynth_core::distributions::DriftConfig {
767 enabled: self.enabled,
768 amount_mean_drift: self.amount_mean_drift,
769 amount_variance_drift: self.amount_variance_drift,
770 anomaly_rate_drift: self.anomaly_rate_drift,
771 concept_drift_rate: self.concept_drift_rate,
772 sudden_drift_probability: self.sudden_drift_probability,
773 sudden_drift_magnitude: self.sudden_drift_magnitude,
774 seasonal_drift: self.seasonal_drift,
775 drift_start_period: self.drift_start_period,
776 drift_type: match self.drift_type {
777 DriftType::Gradual => datasynth_core::distributions::DriftType::Gradual,
778 DriftType::Sudden => datasynth_core::distributions::DriftType::Sudden,
779 DriftType::Recurring => datasynth_core::distributions::DriftType::Recurring,
780 DriftType::Mixed => datasynth_core::distributions::DriftType::Mixed,
781 },
782 regime_changes: Vec::new(),
783 economic_cycle: Default::default(),
784 parameter_drifts: Vec::new(),
785 }
786 }
787}
788
789#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
791#[serde(rename_all = "snake_case")]
792pub enum DriftType {
793 #[default]
795 Gradual,
796 Sudden,
798 Recurring,
800 Mixed,
802}
803
804#[derive(Debug, Clone, Serialize, Deserialize)]
810pub struct StreamingSchemaConfig {
811 #[serde(default)]
813 pub enabled: bool,
814 #[serde(default = "default_buffer_size")]
816 pub buffer_size: usize,
817 #[serde(default = "default_true")]
819 pub enable_progress: bool,
820 #[serde(default = "default_progress_interval")]
822 pub progress_interval: u64,
823 #[serde(default)]
825 pub backpressure: BackpressureSchemaStrategy,
826}
827
828fn default_buffer_size() -> usize {
829 1000
830}
831
832fn default_progress_interval() -> u64 {
833 100
834}
835
836impl Default for StreamingSchemaConfig {
837 fn default() -> Self {
838 Self {
839 enabled: false,
840 buffer_size: 1000,
841 enable_progress: true,
842 progress_interval: 100,
843 backpressure: BackpressureSchemaStrategy::Block,
844 }
845 }
846}
847
848#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
850#[serde(rename_all = "snake_case")]
851pub enum BackpressureSchemaStrategy {
852 #[default]
854 Block,
855 DropOldest,
857 DropNewest,
859 Buffer,
861}
862
863#[derive(Debug, Clone, Serialize, Deserialize)]
869pub struct RateLimitSchemaConfig {
870 #[serde(default)]
872 pub enabled: bool,
873 #[serde(default = "default_entities_per_second")]
875 pub entities_per_second: f64,
876 #[serde(default = "default_burst_size")]
878 pub burst_size: u32,
879 #[serde(default)]
881 pub backpressure: RateLimitBackpressureSchema,
882}
883
884fn default_entities_per_second() -> f64 {
885 1000.0
886}
887
888fn default_burst_size() -> u32 {
889 100
890}
891
892impl Default for RateLimitSchemaConfig {
893 fn default() -> Self {
894 Self {
895 enabled: false,
896 entities_per_second: 1000.0,
897 burst_size: 100,
898 backpressure: RateLimitBackpressureSchema::Block,
899 }
900 }
901}
902
903#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
905#[serde(rename_all = "snake_case")]
906pub enum RateLimitBackpressureSchema {
907 #[default]
909 Block,
910 Drop,
912 Buffer,
914}
915
916#[derive(Debug, Clone, Serialize, Deserialize)]
922pub struct TemporalAttributeSchemaConfig {
923 #[serde(default)]
925 pub enabled: bool,
926 #[serde(default)]
928 pub valid_time: ValidTimeSchemaConfig,
929 #[serde(default)]
931 pub transaction_time: TransactionTimeSchemaConfig,
932 #[serde(default)]
934 pub generate_version_chains: bool,
935 #[serde(default = "default_avg_versions")]
937 pub avg_versions_per_entity: f64,
938}
939
940fn default_avg_versions() -> f64 {
941 1.5
942}
943
944impl Default for TemporalAttributeSchemaConfig {
945 fn default() -> Self {
946 Self {
947 enabled: false,
948 valid_time: ValidTimeSchemaConfig::default(),
949 transaction_time: TransactionTimeSchemaConfig::default(),
950 generate_version_chains: false,
951 avg_versions_per_entity: 1.5,
952 }
953 }
954}
955
956#[derive(Debug, Clone, Serialize, Deserialize)]
958pub struct ValidTimeSchemaConfig {
959 #[serde(default = "default_closed_probability")]
961 pub closed_probability: f64,
962 #[serde(default = "default_avg_validity_days")]
964 pub avg_validity_days: u32,
965 #[serde(default = "default_validity_stddev")]
967 pub validity_stddev_days: u32,
968}
969
970fn default_closed_probability() -> f64 {
971 0.1
972}
973
974fn default_avg_validity_days() -> u32 {
975 365
976}
977
978fn default_validity_stddev() -> u32 {
979 90
980}
981
982impl Default for ValidTimeSchemaConfig {
983 fn default() -> Self {
984 Self {
985 closed_probability: 0.1,
986 avg_validity_days: 365,
987 validity_stddev_days: 90,
988 }
989 }
990}
991
992#[derive(Debug, Clone, Serialize, Deserialize)]
994pub struct TransactionTimeSchemaConfig {
995 #[serde(default)]
997 pub avg_recording_delay_seconds: u32,
998 #[serde(default)]
1000 pub allow_backdating: bool,
1001 #[serde(default = "default_backdating_probability")]
1003 pub backdating_probability: f64,
1004 #[serde(default = "default_max_backdate_days")]
1006 pub max_backdate_days: u32,
1007}
1008
1009fn default_backdating_probability() -> f64 {
1010 0.01
1011}
1012
1013fn default_max_backdate_days() -> u32 {
1014 30
1015}
1016
1017impl Default for TransactionTimeSchemaConfig {
1018 fn default() -> Self {
1019 Self {
1020 avg_recording_delay_seconds: 0,
1021 allow_backdating: false,
1022 backdating_probability: 0.01,
1023 max_backdate_days: 30,
1024 }
1025 }
1026}
1027
1028#[derive(Debug, Clone, Serialize, Deserialize)]
1034pub struct RelationshipSchemaConfig {
1035 #[serde(default)]
1037 pub relationship_types: Vec<RelationshipTypeSchemaConfig>,
1038 #[serde(default = "default_true")]
1040 pub allow_orphans: bool,
1041 #[serde(default = "default_orphan_probability")]
1043 pub orphan_probability: f64,
1044 #[serde(default)]
1046 pub allow_circular: bool,
1047 #[serde(default = "default_max_circular_depth")]
1049 pub max_circular_depth: u32,
1050}
1051
1052fn default_orphan_probability() -> f64 {
1053 0.01
1054}
1055
1056fn default_max_circular_depth() -> u32 {
1057 3
1058}
1059
1060impl Default for RelationshipSchemaConfig {
1061 fn default() -> Self {
1062 Self {
1063 relationship_types: Vec::new(),
1064 allow_orphans: true,
1065 orphan_probability: 0.01,
1066 allow_circular: false,
1067 max_circular_depth: 3,
1068 }
1069 }
1070}
1071
1072#[derive(Debug, Clone, Serialize, Deserialize)]
1074pub struct RelationshipTypeSchemaConfig {
1075 pub name: String,
1077 pub source_type: String,
1079 pub target_type: String,
1081 #[serde(default)]
1083 pub cardinality: CardinalitySchemaRule,
1084 #[serde(default = "default_relationship_weight")]
1086 pub weight: f64,
1087 #[serde(default)]
1089 pub required: bool,
1090 #[serde(default = "default_true")]
1092 pub directed: bool,
1093}
1094
1095fn default_relationship_weight() -> f64 {
1096 1.0
1097}
1098
1099impl Default for RelationshipTypeSchemaConfig {
1100 fn default() -> Self {
1101 Self {
1102 name: String::new(),
1103 source_type: String::new(),
1104 target_type: String::new(),
1105 cardinality: CardinalitySchemaRule::default(),
1106 weight: 1.0,
1107 required: false,
1108 directed: true,
1109 }
1110 }
1111}
1112
1113#[derive(Debug, Clone, Serialize, Deserialize)]
1115#[serde(rename_all = "snake_case")]
1116pub enum CardinalitySchemaRule {
1117 OneToOne,
1119 OneToMany {
1121 min: u32,
1123 max: u32,
1125 },
1126 ManyToOne {
1128 min: u32,
1130 max: u32,
1132 },
1133 ManyToMany {
1135 min_per_source: u32,
1137 max_per_source: u32,
1139 },
1140}
1141
1142impl Default for CardinalitySchemaRule {
1143 fn default() -> Self {
1144 Self::OneToMany { min: 1, max: 5 }
1145 }
1146}
1147
1148#[derive(Debug, Clone, Serialize, Deserialize)]
1150pub struct GlobalConfig {
1151 pub seed: Option<u64>,
1153 pub industry: IndustrySector,
1155 pub start_date: String,
1157 pub period_months: u32,
1159 #[serde(default = "default_currency")]
1161 pub group_currency: String,
1162 #[serde(default = "default_true")]
1164 pub parallel: bool,
1165 #[serde(default)]
1167 pub worker_threads: usize,
1168 #[serde(default)]
1170 pub memory_limit_mb: usize,
1171}
1172
1173fn default_currency() -> String {
1174 "USD".to_string()
1175}
1176fn default_true() -> bool {
1177 true
1178}
1179
1180#[derive(Debug, Clone, Serialize, Deserialize)]
1182pub struct CompanyConfig {
1183 pub code: String,
1185 pub name: String,
1187 pub currency: String,
1189 pub country: String,
1191 #[serde(default = "default_fiscal_variant")]
1193 pub fiscal_year_variant: String,
1194 pub annual_transaction_volume: TransactionVolume,
1196 #[serde(default = "default_weight")]
1198 pub volume_weight: f64,
1199}
1200
1201fn default_fiscal_variant() -> String {
1202 "K4".to_string()
1203}
1204fn default_weight() -> f64 {
1205 1.0
1206}
1207
1208#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1210#[serde(rename_all = "snake_case")]
1211pub enum TransactionVolume {
1212 TenK,
1214 HundredK,
1216 OneM,
1218 TenM,
1220 HundredM,
1222 Custom(u64),
1224}
1225
1226impl TransactionVolume {
1227 pub fn count(&self) -> u64 {
1229 match self {
1230 Self::TenK => 10_000,
1231 Self::HundredK => 100_000,
1232 Self::OneM => 1_000_000,
1233 Self::TenM => 10_000_000,
1234 Self::HundredM => 100_000_000,
1235 Self::Custom(n) => *n,
1236 }
1237 }
1238}
1239
1240#[derive(Debug, Clone, Serialize, Deserialize)]
1242pub struct ChartOfAccountsConfig {
1243 pub complexity: CoAComplexity,
1245 #[serde(default = "default_true")]
1247 pub industry_specific: bool,
1248 pub custom_accounts: Option<PathBuf>,
1250 #[serde(default = "default_min_depth")]
1252 pub min_hierarchy_depth: u8,
1253 #[serde(default = "default_max_depth")]
1255 pub max_hierarchy_depth: u8,
1256}
1257
1258fn default_min_depth() -> u8 {
1259 2
1260}
1261fn default_max_depth() -> u8 {
1262 5
1263}
1264
1265impl Default for ChartOfAccountsConfig {
1266 fn default() -> Self {
1267 Self {
1268 complexity: CoAComplexity::Small,
1269 industry_specific: true,
1270 custom_accounts: None,
1271 min_hierarchy_depth: default_min_depth(),
1272 max_hierarchy_depth: default_max_depth(),
1273 }
1274 }
1275}
1276
1277#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1279pub struct TransactionConfig {
1280 #[serde(default)]
1282 pub line_item_distribution: LineItemDistributionConfig,
1283 #[serde(default)]
1285 pub debit_credit_distribution: DebitCreditDistributionConfig,
1286 #[serde(default)]
1288 pub even_odd_distribution: EvenOddDistributionConfig,
1289 #[serde(default)]
1291 pub source_distribution: SourceDistribution,
1292 #[serde(default)]
1294 pub seasonality: SeasonalityConfig,
1295 #[serde(default)]
1297 pub amounts: AmountDistributionConfig,
1298 #[serde(default)]
1300 pub benford: BenfordConfig,
1301}
1302
1303#[derive(Debug, Clone, Serialize, Deserialize)]
1305pub struct BenfordConfig {
1306 #[serde(default = "default_true")]
1308 pub enabled: bool,
1309 #[serde(default = "default_benford_tolerance")]
1311 pub tolerance: f64,
1312 #[serde(default)]
1314 pub exempt_sources: Vec<BenfordExemption>,
1315}
1316
1317fn default_benford_tolerance() -> f64 {
1318 0.05
1319}
1320
1321impl Default for BenfordConfig {
1322 fn default() -> Self {
1323 Self {
1324 enabled: true,
1325 tolerance: default_benford_tolerance(),
1326 exempt_sources: vec![BenfordExemption::Recurring, BenfordExemption::Payroll],
1327 }
1328 }
1329}
1330
1331#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1333#[serde(rename_all = "snake_case")]
1334pub enum BenfordExemption {
1335 Recurring,
1337 Payroll,
1339 FixedFees,
1341 RoundAmounts,
1343}
1344
1345#[derive(Debug, Clone, Serialize, Deserialize)]
1347pub struct SourceDistribution {
1348 pub manual: f64,
1350 pub automated: f64,
1352 pub recurring: f64,
1354 pub adjustment: f64,
1356}
1357
1358impl Default for SourceDistribution {
1359 fn default() -> Self {
1360 Self {
1361 manual: 0.20,
1362 automated: 0.70,
1363 recurring: 0.07,
1364 adjustment: 0.03,
1365 }
1366 }
1367}
1368
1369#[derive(Debug, Clone, Serialize, Deserialize)]
1371pub struct OutputConfig {
1372 #[serde(default)]
1374 pub mode: OutputMode,
1375 pub output_directory: PathBuf,
1377 #[serde(default = "default_formats")]
1379 pub formats: Vec<FileFormat>,
1380 #[serde(default)]
1382 pub compression: CompressionConfig,
1383 #[serde(default = "default_batch_size")]
1385 pub batch_size: usize,
1386 #[serde(default = "default_true")]
1388 pub include_acdoca: bool,
1389 #[serde(default)]
1391 pub include_bseg: bool,
1392 #[serde(default = "default_true")]
1394 pub partition_by_period: bool,
1395 #[serde(default)]
1397 pub partition_by_company: bool,
1398}
1399
1400fn default_formats() -> Vec<FileFormat> {
1401 vec![FileFormat::Parquet]
1402}
1403fn default_batch_size() -> usize {
1404 100_000
1405}
1406
1407impl Default for OutputConfig {
1408 fn default() -> Self {
1409 Self {
1410 mode: OutputMode::FlatFile,
1411 output_directory: PathBuf::from("./output"),
1412 formats: default_formats(),
1413 compression: CompressionConfig::default(),
1414 batch_size: default_batch_size(),
1415 include_acdoca: true,
1416 include_bseg: false,
1417 partition_by_period: true,
1418 partition_by_company: false,
1419 }
1420 }
1421}
1422
1423#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
1425#[serde(rename_all = "snake_case")]
1426pub enum OutputMode {
1427 Streaming,
1429 #[default]
1431 FlatFile,
1432 Both,
1434}
1435
1436#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1438#[serde(rename_all = "snake_case")]
1439pub enum FileFormat {
1440 Csv,
1441 Parquet,
1442 Json,
1443 JsonLines,
1444}
1445
1446#[derive(Debug, Clone, Serialize, Deserialize)]
1448pub struct CompressionConfig {
1449 #[serde(default = "default_true")]
1451 pub enabled: bool,
1452 #[serde(default)]
1454 pub algorithm: CompressionAlgorithm,
1455 #[serde(default = "default_compression_level")]
1457 pub level: u8,
1458}
1459
1460fn default_compression_level() -> u8 {
1461 3
1462}
1463
1464impl Default for CompressionConfig {
1465 fn default() -> Self {
1466 Self {
1467 enabled: true,
1468 algorithm: CompressionAlgorithm::default(),
1469 level: default_compression_level(),
1470 }
1471 }
1472}
1473
1474#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
1476#[serde(rename_all = "snake_case")]
1477pub enum CompressionAlgorithm {
1478 Gzip,
1479 #[default]
1480 Zstd,
1481 Lz4,
1482 Snappy,
1483}
1484
1485#[derive(Debug, Clone, Serialize, Deserialize)]
1487pub struct FraudConfig {
1488 #[serde(default)]
1490 pub enabled: bool,
1491 #[serde(default = "default_fraud_rate")]
1493 pub fraud_rate: f64,
1494 #[serde(default)]
1496 pub fraud_type_distribution: FraudTypeDistribution,
1497 #[serde(default)]
1499 pub clustering_enabled: bool,
1500 #[serde(default = "default_clustering_factor")]
1502 pub clustering_factor: f64,
1503 #[serde(default = "default_approval_thresholds")]
1505 pub approval_thresholds: Vec<f64>,
1506}
1507
1508fn default_approval_thresholds() -> Vec<f64> {
1509 vec![1000.0, 5000.0, 10000.0, 25000.0, 50000.0, 100000.0]
1510}
1511
1512fn default_fraud_rate() -> f64 {
1513 0.005
1514}
1515fn default_clustering_factor() -> f64 {
1516 3.0
1517}
1518
1519impl Default for FraudConfig {
1520 fn default() -> Self {
1521 Self {
1522 enabled: false,
1523 fraud_rate: default_fraud_rate(),
1524 fraud_type_distribution: FraudTypeDistribution::default(),
1525 clustering_enabled: false,
1526 clustering_factor: default_clustering_factor(),
1527 approval_thresholds: default_approval_thresholds(),
1528 }
1529 }
1530}
1531
1532#[derive(Debug, Clone, Serialize, Deserialize)]
1534pub struct FraudTypeDistribution {
1535 pub suspense_account_abuse: f64,
1536 pub fictitious_transaction: f64,
1537 pub revenue_manipulation: f64,
1538 pub expense_capitalization: f64,
1539 pub split_transaction: f64,
1540 pub timing_anomaly: f64,
1541 pub unauthorized_access: f64,
1542 pub duplicate_payment: f64,
1543}
1544
1545impl Default for FraudTypeDistribution {
1546 fn default() -> Self {
1547 Self {
1548 suspense_account_abuse: 0.25,
1549 fictitious_transaction: 0.15,
1550 revenue_manipulation: 0.10,
1551 expense_capitalization: 0.10,
1552 split_transaction: 0.15,
1553 timing_anomaly: 0.10,
1554 unauthorized_access: 0.10,
1555 duplicate_payment: 0.05,
1556 }
1557 }
1558}
1559
1560#[derive(Debug, Clone, Serialize, Deserialize)]
1562pub struct InternalControlsConfig {
1563 #[serde(default)]
1565 pub enabled: bool,
1566 #[serde(default = "default_exception_rate")]
1568 pub exception_rate: f64,
1569 #[serde(default = "default_sod_violation_rate")]
1571 pub sod_violation_rate: f64,
1572 #[serde(default = "default_true")]
1574 pub export_control_master_data: bool,
1575 #[serde(default = "default_sox_materiality_threshold")]
1577 pub sox_materiality_threshold: f64,
1578 #[serde(default = "default_true")]
1580 pub coso_enabled: bool,
1581 #[serde(default)]
1583 pub include_entity_level_controls: bool,
1584 #[serde(default = "default_target_maturity_level")]
1587 pub target_maturity_level: String,
1588}
1589
1590fn default_exception_rate() -> f64 {
1591 0.02
1592}
1593
1594fn default_sod_violation_rate() -> f64 {
1595 0.01
1596}
1597
1598fn default_sox_materiality_threshold() -> f64 {
1599 10000.0
1600}
1601
1602fn default_target_maturity_level() -> String {
1603 "mixed".to_string()
1604}
1605
1606impl Default for InternalControlsConfig {
1607 fn default() -> Self {
1608 Self {
1609 enabled: false,
1610 exception_rate: default_exception_rate(),
1611 sod_violation_rate: default_sod_violation_rate(),
1612 export_control_master_data: true,
1613 sox_materiality_threshold: default_sox_materiality_threshold(),
1614 coso_enabled: true,
1615 include_entity_level_controls: false,
1616 target_maturity_level: default_target_maturity_level(),
1617 }
1618 }
1619}
1620
1621#[derive(Debug, Clone, Serialize, Deserialize)]
1623pub struct BusinessProcessConfig {
1624 #[serde(default = "default_o2c")]
1626 pub o2c_weight: f64,
1627 #[serde(default = "default_p2p")]
1629 pub p2p_weight: f64,
1630 #[serde(default = "default_r2r")]
1632 pub r2r_weight: f64,
1633 #[serde(default = "default_h2r")]
1635 pub h2r_weight: f64,
1636 #[serde(default = "default_a2r")]
1638 pub a2r_weight: f64,
1639}
1640
1641fn default_o2c() -> f64 {
1642 0.35
1643}
1644fn default_p2p() -> f64 {
1645 0.30
1646}
1647fn default_r2r() -> f64 {
1648 0.20
1649}
1650fn default_h2r() -> f64 {
1651 0.10
1652}
1653fn default_a2r() -> f64 {
1654 0.05
1655}
1656
1657impl Default for BusinessProcessConfig {
1658 fn default() -> Self {
1659 Self {
1660 o2c_weight: default_o2c(),
1661 p2p_weight: default_p2p(),
1662 r2r_weight: default_r2r(),
1663 h2r_weight: default_h2r(),
1664 a2r_weight: default_a2r(),
1665 }
1666 }
1667}
1668
1669#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1671pub struct UserPersonaConfig {
1672 #[serde(default)]
1674 pub persona_distribution: PersonaDistribution,
1675 #[serde(default)]
1677 pub users_per_persona: UsersPerPersona,
1678}
1679
1680#[derive(Debug, Clone, Serialize, Deserialize)]
1682pub struct PersonaDistribution {
1683 pub junior_accountant: f64,
1684 pub senior_accountant: f64,
1685 pub controller: f64,
1686 pub manager: f64,
1687 pub automated_system: f64,
1688}
1689
1690impl Default for PersonaDistribution {
1691 fn default() -> Self {
1692 Self {
1693 junior_accountant: 0.15,
1694 senior_accountant: 0.15,
1695 controller: 0.05,
1696 manager: 0.05,
1697 automated_system: 0.60,
1698 }
1699 }
1700}
1701
1702#[derive(Debug, Clone, Serialize, Deserialize)]
1704pub struct UsersPerPersona {
1705 pub junior_accountant: usize,
1706 pub senior_accountant: usize,
1707 pub controller: usize,
1708 pub manager: usize,
1709 pub automated_system: usize,
1710}
1711
1712impl Default for UsersPerPersona {
1713 fn default() -> Self {
1714 Self {
1715 junior_accountant: 10,
1716 senior_accountant: 5,
1717 controller: 2,
1718 manager: 3,
1719 automated_system: 20,
1720 }
1721 }
1722}
1723
1724#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1726pub struct TemplateConfig {
1727 #[serde(default)]
1729 pub names: NameTemplateConfig,
1730 #[serde(default)]
1732 pub descriptions: DescriptionTemplateConfig,
1733 #[serde(default)]
1735 pub references: ReferenceTemplateConfig,
1736}
1737
1738#[derive(Debug, Clone, Serialize, Deserialize)]
1740pub struct NameTemplateConfig {
1741 #[serde(default)]
1743 pub culture_distribution: CultureDistribution,
1744 #[serde(default = "default_email_domain")]
1746 pub email_domain: String,
1747 #[serde(default = "default_true")]
1749 pub generate_realistic_names: bool,
1750}
1751
1752fn default_email_domain() -> String {
1753 "company.com".to_string()
1754}
1755
1756impl Default for NameTemplateConfig {
1757 fn default() -> Self {
1758 Self {
1759 culture_distribution: CultureDistribution::default(),
1760 email_domain: default_email_domain(),
1761 generate_realistic_names: true,
1762 }
1763 }
1764}
1765
1766#[derive(Debug, Clone, Serialize, Deserialize)]
1768pub struct CultureDistribution {
1769 pub western_us: f64,
1770 pub hispanic: f64,
1771 pub german: f64,
1772 pub french: f64,
1773 pub chinese: f64,
1774 pub japanese: f64,
1775 pub indian: f64,
1776}
1777
1778impl Default for CultureDistribution {
1779 fn default() -> Self {
1780 Self {
1781 western_us: 0.40,
1782 hispanic: 0.20,
1783 german: 0.10,
1784 french: 0.05,
1785 chinese: 0.10,
1786 japanese: 0.05,
1787 indian: 0.10,
1788 }
1789 }
1790}
1791
1792#[derive(Debug, Clone, Serialize, Deserialize)]
1794pub struct DescriptionTemplateConfig {
1795 #[serde(default = "default_true")]
1797 pub generate_header_text: bool,
1798 #[serde(default = "default_true")]
1800 pub generate_line_text: bool,
1801}
1802
1803impl Default for DescriptionTemplateConfig {
1804 fn default() -> Self {
1805 Self {
1806 generate_header_text: true,
1807 generate_line_text: true,
1808 }
1809 }
1810}
1811
1812#[derive(Debug, Clone, Serialize, Deserialize)]
1814pub struct ReferenceTemplateConfig {
1815 #[serde(default = "default_true")]
1817 pub generate_references: bool,
1818 #[serde(default = "default_invoice_prefix")]
1820 pub invoice_prefix: String,
1821 #[serde(default = "default_po_prefix")]
1823 pub po_prefix: String,
1824 #[serde(default = "default_so_prefix")]
1826 pub so_prefix: String,
1827}
1828
1829fn default_invoice_prefix() -> String {
1830 "INV".to_string()
1831}
1832fn default_po_prefix() -> String {
1833 "PO".to_string()
1834}
1835fn default_so_prefix() -> String {
1836 "SO".to_string()
1837}
1838
1839impl Default for ReferenceTemplateConfig {
1840 fn default() -> Self {
1841 Self {
1842 generate_references: true,
1843 invoice_prefix: default_invoice_prefix(),
1844 po_prefix: default_po_prefix(),
1845 so_prefix: default_so_prefix(),
1846 }
1847 }
1848}
1849
1850#[derive(Debug, Clone, Serialize, Deserialize)]
1852pub struct ApprovalConfig {
1853 #[serde(default)]
1855 pub enabled: bool,
1856 #[serde(default = "default_auto_approve_threshold")]
1858 pub auto_approve_threshold: f64,
1859 #[serde(default = "default_rejection_rate")]
1861 pub rejection_rate: f64,
1862 #[serde(default = "default_revision_rate")]
1864 pub revision_rate: f64,
1865 #[serde(default = "default_approval_delay_hours")]
1867 pub average_approval_delay_hours: f64,
1868 #[serde(default)]
1870 pub thresholds: Vec<ApprovalThresholdConfig>,
1871}
1872
1873fn default_auto_approve_threshold() -> f64 {
1874 1000.0
1875}
1876fn default_rejection_rate() -> f64 {
1877 0.02
1878}
1879fn default_revision_rate() -> f64 {
1880 0.05
1881}
1882fn default_approval_delay_hours() -> f64 {
1883 4.0
1884}
1885
1886impl Default for ApprovalConfig {
1887 fn default() -> Self {
1888 Self {
1889 enabled: false,
1890 auto_approve_threshold: default_auto_approve_threshold(),
1891 rejection_rate: default_rejection_rate(),
1892 revision_rate: default_revision_rate(),
1893 average_approval_delay_hours: default_approval_delay_hours(),
1894 thresholds: vec![
1895 ApprovalThresholdConfig {
1896 amount: 1000.0,
1897 level: 1,
1898 roles: vec!["senior_accountant".to_string()],
1899 },
1900 ApprovalThresholdConfig {
1901 amount: 10000.0,
1902 level: 2,
1903 roles: vec!["senior_accountant".to_string(), "controller".to_string()],
1904 },
1905 ApprovalThresholdConfig {
1906 amount: 100000.0,
1907 level: 3,
1908 roles: vec![
1909 "senior_accountant".to_string(),
1910 "controller".to_string(),
1911 "manager".to_string(),
1912 ],
1913 },
1914 ApprovalThresholdConfig {
1915 amount: 500000.0,
1916 level: 4,
1917 roles: vec![
1918 "senior_accountant".to_string(),
1919 "controller".to_string(),
1920 "manager".to_string(),
1921 "executive".to_string(),
1922 ],
1923 },
1924 ],
1925 }
1926 }
1927}
1928
1929#[derive(Debug, Clone, Serialize, Deserialize)]
1931pub struct ApprovalThresholdConfig {
1932 pub amount: f64,
1934 pub level: u8,
1936 pub roles: Vec<String>,
1938}
1939
1940#[derive(Debug, Clone, Serialize, Deserialize)]
1942pub struct DepartmentConfig {
1943 #[serde(default)]
1945 pub enabled: bool,
1946 #[serde(default = "default_headcount_multiplier")]
1948 pub headcount_multiplier: f64,
1949 #[serde(default)]
1951 pub custom_departments: Vec<CustomDepartmentConfig>,
1952}
1953
1954fn default_headcount_multiplier() -> f64 {
1955 1.0
1956}
1957
1958impl Default for DepartmentConfig {
1959 fn default() -> Self {
1960 Self {
1961 enabled: false,
1962 headcount_multiplier: default_headcount_multiplier(),
1963 custom_departments: Vec::new(),
1964 }
1965 }
1966}
1967
1968#[derive(Debug, Clone, Serialize, Deserialize)]
1970pub struct CustomDepartmentConfig {
1971 pub code: String,
1973 pub name: String,
1975 #[serde(default)]
1977 pub cost_center: Option<String>,
1978 #[serde(default)]
1980 pub primary_processes: Vec<String>,
1981 #[serde(default)]
1983 pub parent_code: Option<String>,
1984}
1985
1986#[derive(Debug, Clone, Default, Serialize, Deserialize)]
1992pub struct MasterDataConfig {
1993 #[serde(default)]
1995 pub vendors: VendorMasterConfig,
1996 #[serde(default)]
1998 pub customers: CustomerMasterConfig,
1999 #[serde(default)]
2001 pub materials: MaterialMasterConfig,
2002 #[serde(default)]
2004 pub fixed_assets: FixedAssetMasterConfig,
2005 #[serde(default)]
2007 pub employees: EmployeeMasterConfig,
2008 #[serde(default)]
2010 pub cost_centers: CostCenterMasterConfig,
2011}
2012
2013#[derive(Debug, Clone, Serialize, Deserialize)]
2015pub struct VendorMasterConfig {
2016 #[serde(default = "default_vendor_count")]
2018 pub count: usize,
2019 #[serde(default = "default_intercompany_percent")]
2021 pub intercompany_percent: f64,
2022 #[serde(default)]
2024 pub payment_terms_distribution: PaymentTermsDistribution,
2025 #[serde(default)]
2027 pub behavior_distribution: VendorBehaviorDistribution,
2028 #[serde(default = "default_true")]
2030 pub generate_bank_accounts: bool,
2031 #[serde(default = "default_true")]
2033 pub generate_tax_ids: bool,
2034}
2035
2036fn default_vendor_count() -> usize {
2037 500
2038}
2039
2040fn default_intercompany_percent() -> f64 {
2041 0.05
2042}
2043
2044impl Default for VendorMasterConfig {
2045 fn default() -> Self {
2046 Self {
2047 count: default_vendor_count(),
2048 intercompany_percent: default_intercompany_percent(),
2049 payment_terms_distribution: PaymentTermsDistribution::default(),
2050 behavior_distribution: VendorBehaviorDistribution::default(),
2051 generate_bank_accounts: true,
2052 generate_tax_ids: true,
2053 }
2054 }
2055}
2056
2057#[derive(Debug, Clone, Serialize, Deserialize)]
2059pub struct PaymentTermsDistribution {
2060 pub net_30: f64,
2062 pub net_60: f64,
2064 pub net_90: f64,
2066 pub two_ten_net_30: f64,
2068 pub due_on_receipt: f64,
2070 pub end_of_month: f64,
2072}
2073
2074impl Default for PaymentTermsDistribution {
2075 fn default() -> Self {
2076 Self {
2077 net_30: 0.40,
2078 net_60: 0.20,
2079 net_90: 0.10,
2080 two_ten_net_30: 0.15,
2081 due_on_receipt: 0.05,
2082 end_of_month: 0.10,
2083 }
2084 }
2085}
2086
2087#[derive(Debug, Clone, Serialize, Deserialize)]
2089pub struct VendorBehaviorDistribution {
2090 pub reliable: f64,
2092 pub sometimes_late: f64,
2094 pub inconsistent_quality: f64,
2096 pub premium: f64,
2098 pub budget: f64,
2100}
2101
2102impl Default for VendorBehaviorDistribution {
2103 fn default() -> Self {
2104 Self {
2105 reliable: 0.50,
2106 sometimes_late: 0.20,
2107 inconsistent_quality: 0.10,
2108 premium: 0.10,
2109 budget: 0.10,
2110 }
2111 }
2112}
2113
2114#[derive(Debug, Clone, Serialize, Deserialize)]
2116pub struct CustomerMasterConfig {
2117 #[serde(default = "default_customer_count")]
2119 pub count: usize,
2120 #[serde(default = "default_intercompany_percent")]
2122 pub intercompany_percent: f64,
2123 #[serde(default)]
2125 pub credit_rating_distribution: CreditRatingDistribution,
2126 #[serde(default)]
2128 pub payment_behavior_distribution: PaymentBehaviorDistribution,
2129 #[serde(default = "default_true")]
2131 pub generate_credit_limits: bool,
2132}
2133
2134fn default_customer_count() -> usize {
2135 2000
2136}
2137
2138impl Default for CustomerMasterConfig {
2139 fn default() -> Self {
2140 Self {
2141 count: default_customer_count(),
2142 intercompany_percent: default_intercompany_percent(),
2143 credit_rating_distribution: CreditRatingDistribution::default(),
2144 payment_behavior_distribution: PaymentBehaviorDistribution::default(),
2145 generate_credit_limits: true,
2146 }
2147 }
2148}
2149
2150#[derive(Debug, Clone, Serialize, Deserialize)]
2152pub struct CreditRatingDistribution {
2153 pub aaa: f64,
2155 pub aa: f64,
2157 pub a: f64,
2159 pub bbb: f64,
2161 pub bb: f64,
2163 pub b: f64,
2165 pub below_b: f64,
2167}
2168
2169impl Default for CreditRatingDistribution {
2170 fn default() -> Self {
2171 Self {
2172 aaa: 0.05,
2173 aa: 0.10,
2174 a: 0.20,
2175 bbb: 0.30,
2176 bb: 0.20,
2177 b: 0.10,
2178 below_b: 0.05,
2179 }
2180 }
2181}
2182
2183#[derive(Debug, Clone, Serialize, Deserialize)]
2185pub struct PaymentBehaviorDistribution {
2186 pub early_payer: f64,
2188 pub on_time: f64,
2190 pub occasional_late: f64,
2192 pub frequent_late: f64,
2194 pub discount_taker: f64,
2196}
2197
2198impl Default for PaymentBehaviorDistribution {
2199 fn default() -> Self {
2200 Self {
2201 early_payer: 0.10,
2202 on_time: 0.50,
2203 occasional_late: 0.25,
2204 frequent_late: 0.10,
2205 discount_taker: 0.05,
2206 }
2207 }
2208}
2209
2210#[derive(Debug, Clone, Serialize, Deserialize)]
2212pub struct MaterialMasterConfig {
2213 #[serde(default = "default_material_count")]
2215 pub count: usize,
2216 #[serde(default)]
2218 pub type_distribution: MaterialTypeDistribution,
2219 #[serde(default)]
2221 pub valuation_distribution: ValuationMethodDistribution,
2222 #[serde(default = "default_bom_percent")]
2224 pub bom_percent: f64,
2225 #[serde(default = "default_max_bom_depth")]
2227 pub max_bom_depth: u8,
2228}
2229
2230fn default_material_count() -> usize {
2231 5000
2232}
2233
2234fn default_bom_percent() -> f64 {
2235 0.20
2236}
2237
2238fn default_max_bom_depth() -> u8 {
2239 3
2240}
2241
2242impl Default for MaterialMasterConfig {
2243 fn default() -> Self {
2244 Self {
2245 count: default_material_count(),
2246 type_distribution: MaterialTypeDistribution::default(),
2247 valuation_distribution: ValuationMethodDistribution::default(),
2248 bom_percent: default_bom_percent(),
2249 max_bom_depth: default_max_bom_depth(),
2250 }
2251 }
2252}
2253
2254#[derive(Debug, Clone, Serialize, Deserialize)]
2256pub struct MaterialTypeDistribution {
2257 pub raw_material: f64,
2259 pub semi_finished: f64,
2261 pub finished_good: f64,
2263 pub trading_good: f64,
2265 pub operating_supply: f64,
2267 pub service: f64,
2269}
2270
2271impl Default for MaterialTypeDistribution {
2272 fn default() -> Self {
2273 Self {
2274 raw_material: 0.30,
2275 semi_finished: 0.15,
2276 finished_good: 0.25,
2277 trading_good: 0.15,
2278 operating_supply: 0.10,
2279 service: 0.05,
2280 }
2281 }
2282}
2283
2284#[derive(Debug, Clone, Serialize, Deserialize)]
2286pub struct ValuationMethodDistribution {
2287 pub standard_cost: f64,
2289 pub moving_average: f64,
2291 pub fifo: f64,
2293 pub lifo: f64,
2295}
2296
2297impl Default for ValuationMethodDistribution {
2298 fn default() -> Self {
2299 Self {
2300 standard_cost: 0.50,
2301 moving_average: 0.30,
2302 fifo: 0.15,
2303 lifo: 0.05,
2304 }
2305 }
2306}
2307
2308#[derive(Debug, Clone, Serialize, Deserialize)]
2310pub struct FixedAssetMasterConfig {
2311 #[serde(default = "default_asset_count")]
2313 pub count: usize,
2314 #[serde(default)]
2316 pub class_distribution: AssetClassDistribution,
2317 #[serde(default)]
2319 pub depreciation_distribution: DepreciationMethodDistribution,
2320 #[serde(default = "default_fully_depreciated_percent")]
2322 pub fully_depreciated_percent: f64,
2323 #[serde(default = "default_true")]
2325 pub generate_acquisition_history: bool,
2326}
2327
2328fn default_asset_count() -> usize {
2329 800
2330}
2331
2332fn default_fully_depreciated_percent() -> f64 {
2333 0.15
2334}
2335
2336impl Default for FixedAssetMasterConfig {
2337 fn default() -> Self {
2338 Self {
2339 count: default_asset_count(),
2340 class_distribution: AssetClassDistribution::default(),
2341 depreciation_distribution: DepreciationMethodDistribution::default(),
2342 fully_depreciated_percent: default_fully_depreciated_percent(),
2343 generate_acquisition_history: true,
2344 }
2345 }
2346}
2347
2348#[derive(Debug, Clone, Serialize, Deserialize)]
2350pub struct AssetClassDistribution {
2351 pub buildings: f64,
2353 pub machinery: f64,
2355 pub vehicles: f64,
2357 pub it_equipment: f64,
2359 pub furniture: f64,
2361 pub land: f64,
2363 pub leasehold: f64,
2365}
2366
2367impl Default for AssetClassDistribution {
2368 fn default() -> Self {
2369 Self {
2370 buildings: 0.15,
2371 machinery: 0.30,
2372 vehicles: 0.15,
2373 it_equipment: 0.20,
2374 furniture: 0.10,
2375 land: 0.05,
2376 leasehold: 0.05,
2377 }
2378 }
2379}
2380
2381#[derive(Debug, Clone, Serialize, Deserialize)]
2383pub struct DepreciationMethodDistribution {
2384 pub straight_line: f64,
2386 pub declining_balance: f64,
2388 pub double_declining: f64,
2390 pub sum_of_years: f64,
2392 pub units_of_production: f64,
2394}
2395
2396impl Default for DepreciationMethodDistribution {
2397 fn default() -> Self {
2398 Self {
2399 straight_line: 0.60,
2400 declining_balance: 0.20,
2401 double_declining: 0.10,
2402 sum_of_years: 0.05,
2403 units_of_production: 0.05,
2404 }
2405 }
2406}
2407
2408#[derive(Debug, Clone, Serialize, Deserialize)]
2410pub struct EmployeeMasterConfig {
2411 #[serde(default = "default_employee_count")]
2413 pub count: usize,
2414 #[serde(default = "default_true")]
2416 pub generate_hierarchy: bool,
2417 #[serde(default = "default_hierarchy_depth")]
2419 pub max_hierarchy_depth: u8,
2420 #[serde(default = "default_span_of_control")]
2422 pub average_span_of_control: f64,
2423 #[serde(default)]
2425 pub approval_limits: ApprovalLimitDistribution,
2426 #[serde(default)]
2428 pub department_distribution: EmployeeDepartmentDistribution,
2429}
2430
2431fn default_employee_count() -> usize {
2432 1500
2433}
2434
2435fn default_hierarchy_depth() -> u8 {
2436 6
2437}
2438
2439fn default_span_of_control() -> f64 {
2440 5.0
2441}
2442
2443impl Default for EmployeeMasterConfig {
2444 fn default() -> Self {
2445 Self {
2446 count: default_employee_count(),
2447 generate_hierarchy: true,
2448 max_hierarchy_depth: default_hierarchy_depth(),
2449 average_span_of_control: default_span_of_control(),
2450 approval_limits: ApprovalLimitDistribution::default(),
2451 department_distribution: EmployeeDepartmentDistribution::default(),
2452 }
2453 }
2454}
2455
2456#[derive(Debug, Clone, Serialize, Deserialize)]
2458pub struct ApprovalLimitDistribution {
2459 #[serde(default = "default_staff_limit")]
2461 pub staff: f64,
2462 #[serde(default = "default_senior_limit")]
2464 pub senior: f64,
2465 #[serde(default = "default_manager_limit")]
2467 pub manager: f64,
2468 #[serde(default = "default_director_limit")]
2470 pub director: f64,
2471 #[serde(default = "default_vp_limit")]
2473 pub vp: f64,
2474 #[serde(default = "default_executive_limit")]
2476 pub executive: f64,
2477}
2478
2479fn default_staff_limit() -> f64 {
2480 1000.0
2481}
2482fn default_senior_limit() -> f64 {
2483 5000.0
2484}
2485fn default_manager_limit() -> f64 {
2486 25000.0
2487}
2488fn default_director_limit() -> f64 {
2489 100000.0
2490}
2491fn default_vp_limit() -> f64 {
2492 500000.0
2493}
2494fn default_executive_limit() -> f64 {
2495 f64::INFINITY
2496}
2497
2498impl Default for ApprovalLimitDistribution {
2499 fn default() -> Self {
2500 Self {
2501 staff: default_staff_limit(),
2502 senior: default_senior_limit(),
2503 manager: default_manager_limit(),
2504 director: default_director_limit(),
2505 vp: default_vp_limit(),
2506 executive: default_executive_limit(),
2507 }
2508 }
2509}
2510
2511#[derive(Debug, Clone, Serialize, Deserialize)]
2513pub struct EmployeeDepartmentDistribution {
2514 pub finance: f64,
2516 pub procurement: f64,
2518 pub sales: f64,
2520 pub warehouse: f64,
2522 pub it: f64,
2524 pub hr: f64,
2526 pub operations: f64,
2528 pub executive: f64,
2530}
2531
2532impl Default for EmployeeDepartmentDistribution {
2533 fn default() -> Self {
2534 Self {
2535 finance: 0.12,
2536 procurement: 0.10,
2537 sales: 0.25,
2538 warehouse: 0.15,
2539 it: 0.10,
2540 hr: 0.05,
2541 operations: 0.20,
2542 executive: 0.03,
2543 }
2544 }
2545}
2546
2547#[derive(Debug, Clone, Serialize, Deserialize)]
2549pub struct CostCenterMasterConfig {
2550 #[serde(default = "default_cost_center_count")]
2552 pub count: usize,
2553 #[serde(default = "default_true")]
2555 pub generate_hierarchy: bool,
2556 #[serde(default = "default_cc_hierarchy_depth")]
2558 pub max_hierarchy_depth: u8,
2559}
2560
2561fn default_cost_center_count() -> usize {
2562 50
2563}
2564
2565fn default_cc_hierarchy_depth() -> u8 {
2566 3
2567}
2568
2569impl Default for CostCenterMasterConfig {
2570 fn default() -> Self {
2571 Self {
2572 count: default_cost_center_count(),
2573 generate_hierarchy: true,
2574 max_hierarchy_depth: default_cc_hierarchy_depth(),
2575 }
2576 }
2577}
2578
2579#[derive(Debug, Clone, Serialize, Deserialize)]
2585pub struct DocumentFlowConfig {
2586 #[serde(default)]
2588 pub p2p: P2PFlowConfig,
2589 #[serde(default)]
2591 pub o2c: O2CFlowConfig,
2592 #[serde(default = "default_true")]
2594 pub generate_document_references: bool,
2595 #[serde(default)]
2597 pub export_flow_graph: bool,
2598}
2599
2600impl Default for DocumentFlowConfig {
2601 fn default() -> Self {
2602 Self {
2603 p2p: P2PFlowConfig::default(),
2604 o2c: O2CFlowConfig::default(),
2605 generate_document_references: true,
2606 export_flow_graph: false,
2607 }
2608 }
2609}
2610
2611#[derive(Debug, Clone, Serialize, Deserialize)]
2613pub struct P2PFlowConfig {
2614 #[serde(default = "default_true")]
2616 pub enabled: bool,
2617 #[serde(default = "default_three_way_match_rate")]
2619 pub three_way_match_rate: f64,
2620 #[serde(default = "default_partial_delivery_rate")]
2622 pub partial_delivery_rate: f64,
2623 #[serde(default = "default_price_variance_rate")]
2625 pub price_variance_rate: f64,
2626 #[serde(default = "default_max_price_variance")]
2628 pub max_price_variance_percent: f64,
2629 #[serde(default = "default_quantity_variance_rate")]
2631 pub quantity_variance_rate: f64,
2632 #[serde(default = "default_po_to_gr_days")]
2634 pub average_po_to_gr_days: u32,
2635 #[serde(default = "default_gr_to_invoice_days")]
2637 pub average_gr_to_invoice_days: u32,
2638 #[serde(default = "default_invoice_to_payment_days")]
2640 pub average_invoice_to_payment_days: u32,
2641 #[serde(default)]
2643 pub line_count_distribution: DocumentLineCountDistribution,
2644 #[serde(default)]
2646 pub payment_behavior: P2PPaymentBehaviorConfig,
2647}
2648
2649fn default_three_way_match_rate() -> f64 {
2650 0.95
2651}
2652
2653fn default_partial_delivery_rate() -> f64 {
2654 0.15
2655}
2656
2657fn default_price_variance_rate() -> f64 {
2658 0.08
2659}
2660
2661fn default_max_price_variance() -> f64 {
2662 0.05
2663}
2664
2665fn default_quantity_variance_rate() -> f64 {
2666 0.05
2667}
2668
2669fn default_po_to_gr_days() -> u32 {
2670 14
2671}
2672
2673fn default_gr_to_invoice_days() -> u32 {
2674 5
2675}
2676
2677fn default_invoice_to_payment_days() -> u32 {
2678 30
2679}
2680
2681impl Default for P2PFlowConfig {
2682 fn default() -> Self {
2683 Self {
2684 enabled: true,
2685 three_way_match_rate: default_three_way_match_rate(),
2686 partial_delivery_rate: default_partial_delivery_rate(),
2687 price_variance_rate: default_price_variance_rate(),
2688 max_price_variance_percent: default_max_price_variance(),
2689 quantity_variance_rate: default_quantity_variance_rate(),
2690 average_po_to_gr_days: default_po_to_gr_days(),
2691 average_gr_to_invoice_days: default_gr_to_invoice_days(),
2692 average_invoice_to_payment_days: default_invoice_to_payment_days(),
2693 line_count_distribution: DocumentLineCountDistribution::default(),
2694 payment_behavior: P2PPaymentBehaviorConfig::default(),
2695 }
2696 }
2697}
2698
2699#[derive(Debug, Clone, Serialize, Deserialize)]
2705pub struct P2PPaymentBehaviorConfig {
2706 #[serde(default = "default_p2p_late_payment_rate")]
2708 pub late_payment_rate: f64,
2709 #[serde(default)]
2711 pub late_payment_days_distribution: LatePaymentDaysDistribution,
2712 #[serde(default = "default_p2p_partial_payment_rate")]
2714 pub partial_payment_rate: f64,
2715 #[serde(default = "default_p2p_payment_correction_rate")]
2717 pub payment_correction_rate: f64,
2718}
2719
2720fn default_p2p_late_payment_rate() -> f64 {
2721 0.15
2722}
2723
2724fn default_p2p_partial_payment_rate() -> f64 {
2725 0.05
2726}
2727
2728fn default_p2p_payment_correction_rate() -> f64 {
2729 0.02
2730}
2731
2732impl Default for P2PPaymentBehaviorConfig {
2733 fn default() -> Self {
2734 Self {
2735 late_payment_rate: default_p2p_late_payment_rate(),
2736 late_payment_days_distribution: LatePaymentDaysDistribution::default(),
2737 partial_payment_rate: default_p2p_partial_payment_rate(),
2738 payment_correction_rate: default_p2p_payment_correction_rate(),
2739 }
2740 }
2741}
2742
2743#[derive(Debug, Clone, Serialize, Deserialize)]
2745pub struct LatePaymentDaysDistribution {
2746 #[serde(default = "default_slightly_late")]
2748 pub slightly_late_1_to_7: f64,
2749 #[serde(default = "default_late_8_14")]
2751 pub late_8_to_14: f64,
2752 #[serde(default = "default_very_late")]
2754 pub very_late_15_to_30: f64,
2755 #[serde(default = "default_severely_late")]
2757 pub severely_late_31_to_60: f64,
2758 #[serde(default = "default_extremely_late")]
2760 pub extremely_late_over_60: f64,
2761}
2762
2763fn default_slightly_late() -> f64 {
2764 0.50
2765}
2766
2767fn default_late_8_14() -> f64 {
2768 0.25
2769}
2770
2771fn default_very_late() -> f64 {
2772 0.15
2773}
2774
2775fn default_severely_late() -> f64 {
2776 0.07
2777}
2778
2779fn default_extremely_late() -> f64 {
2780 0.03
2781}
2782
2783impl Default for LatePaymentDaysDistribution {
2784 fn default() -> Self {
2785 Self {
2786 slightly_late_1_to_7: default_slightly_late(),
2787 late_8_to_14: default_late_8_14(),
2788 very_late_15_to_30: default_very_late(),
2789 severely_late_31_to_60: default_severely_late(),
2790 extremely_late_over_60: default_extremely_late(),
2791 }
2792 }
2793}
2794
2795#[derive(Debug, Clone, Serialize, Deserialize)]
2797pub struct O2CFlowConfig {
2798 #[serde(default = "default_true")]
2800 pub enabled: bool,
2801 #[serde(default = "default_credit_check_failure_rate")]
2803 pub credit_check_failure_rate: f64,
2804 #[serde(default = "default_partial_shipment_rate")]
2806 pub partial_shipment_rate: f64,
2807 #[serde(default = "default_return_rate")]
2809 pub return_rate: f64,
2810 #[serde(default = "default_bad_debt_rate")]
2812 pub bad_debt_rate: f64,
2813 #[serde(default = "default_so_to_delivery_days")]
2815 pub average_so_to_delivery_days: u32,
2816 #[serde(default = "default_delivery_to_invoice_days")]
2818 pub average_delivery_to_invoice_days: u32,
2819 #[serde(default = "default_invoice_to_receipt_days")]
2821 pub average_invoice_to_receipt_days: u32,
2822 #[serde(default)]
2824 pub line_count_distribution: DocumentLineCountDistribution,
2825 #[serde(default)]
2827 pub cash_discount: CashDiscountConfig,
2828 #[serde(default)]
2830 pub payment_behavior: O2CPaymentBehaviorConfig,
2831}
2832
2833fn default_credit_check_failure_rate() -> f64 {
2834 0.02
2835}
2836
2837fn default_partial_shipment_rate() -> f64 {
2838 0.10
2839}
2840
2841fn default_return_rate() -> f64 {
2842 0.03
2843}
2844
2845fn default_bad_debt_rate() -> f64 {
2846 0.01
2847}
2848
2849fn default_so_to_delivery_days() -> u32 {
2850 7
2851}
2852
2853fn default_delivery_to_invoice_days() -> u32 {
2854 1
2855}
2856
2857fn default_invoice_to_receipt_days() -> u32 {
2858 45
2859}
2860
2861impl Default for O2CFlowConfig {
2862 fn default() -> Self {
2863 Self {
2864 enabled: true,
2865 credit_check_failure_rate: default_credit_check_failure_rate(),
2866 partial_shipment_rate: default_partial_shipment_rate(),
2867 return_rate: default_return_rate(),
2868 bad_debt_rate: default_bad_debt_rate(),
2869 average_so_to_delivery_days: default_so_to_delivery_days(),
2870 average_delivery_to_invoice_days: default_delivery_to_invoice_days(),
2871 average_invoice_to_receipt_days: default_invoice_to_receipt_days(),
2872 line_count_distribution: DocumentLineCountDistribution::default(),
2873 cash_discount: CashDiscountConfig::default(),
2874 payment_behavior: O2CPaymentBehaviorConfig::default(),
2875 }
2876 }
2877}
2878
2879#[derive(Debug, Clone, Serialize, Deserialize, Default)]
2885pub struct O2CPaymentBehaviorConfig {
2886 #[serde(default)]
2888 pub dunning: DunningConfig,
2889 #[serde(default)]
2891 pub partial_payments: PartialPaymentConfig,
2892 #[serde(default)]
2894 pub short_payments: ShortPaymentConfig,
2895 #[serde(default)]
2897 pub on_account_payments: OnAccountPaymentConfig,
2898 #[serde(default)]
2900 pub payment_corrections: PaymentCorrectionConfig,
2901}
2902
2903#[derive(Debug, Clone, Serialize, Deserialize)]
2905pub struct DunningConfig {
2906 #[serde(default)]
2908 pub enabled: bool,
2909 #[serde(default = "default_dunning_level_1_days")]
2911 pub level_1_days_overdue: u32,
2912 #[serde(default = "default_dunning_level_2_days")]
2914 pub level_2_days_overdue: u32,
2915 #[serde(default = "default_dunning_level_3_days")]
2917 pub level_3_days_overdue: u32,
2918 #[serde(default = "default_collection_days")]
2920 pub collection_days_overdue: u32,
2921 #[serde(default)]
2923 pub payment_after_dunning_rates: DunningPaymentRates,
2924 #[serde(default = "default_dunning_block_rate")]
2926 pub dunning_block_rate: f64,
2927 #[serde(default = "default_dunning_interest_rate")]
2929 pub interest_rate_per_year: f64,
2930 #[serde(default = "default_dunning_charge")]
2932 pub dunning_charge: f64,
2933}
2934
2935fn default_dunning_level_1_days() -> u32 {
2936 14
2937}
2938
2939fn default_dunning_level_2_days() -> u32 {
2940 28
2941}
2942
2943fn default_dunning_level_3_days() -> u32 {
2944 42
2945}
2946
2947fn default_collection_days() -> u32 {
2948 60
2949}
2950
2951fn default_dunning_block_rate() -> f64 {
2952 0.05
2953}
2954
2955fn default_dunning_interest_rate() -> f64 {
2956 0.09
2957}
2958
2959fn default_dunning_charge() -> f64 {
2960 25.0
2961}
2962
2963impl Default for DunningConfig {
2964 fn default() -> Self {
2965 Self {
2966 enabled: false,
2967 level_1_days_overdue: default_dunning_level_1_days(),
2968 level_2_days_overdue: default_dunning_level_2_days(),
2969 level_3_days_overdue: default_dunning_level_3_days(),
2970 collection_days_overdue: default_collection_days(),
2971 payment_after_dunning_rates: DunningPaymentRates::default(),
2972 dunning_block_rate: default_dunning_block_rate(),
2973 interest_rate_per_year: default_dunning_interest_rate(),
2974 dunning_charge: default_dunning_charge(),
2975 }
2976 }
2977}
2978
2979#[derive(Debug, Clone, Serialize, Deserialize)]
2981pub struct DunningPaymentRates {
2982 #[serde(default = "default_after_level_1")]
2984 pub after_level_1: f64,
2985 #[serde(default = "default_after_level_2")]
2987 pub after_level_2: f64,
2988 #[serde(default = "default_after_level_3")]
2990 pub after_level_3: f64,
2991 #[serde(default = "default_during_collection")]
2993 pub during_collection: f64,
2994 #[serde(default = "default_never_pay")]
2996 pub never_pay: f64,
2997}
2998
2999fn default_after_level_1() -> f64 {
3000 0.40
3001}
3002
3003fn default_after_level_2() -> f64 {
3004 0.30
3005}
3006
3007fn default_after_level_3() -> f64 {
3008 0.15
3009}
3010
3011fn default_during_collection() -> f64 {
3012 0.05
3013}
3014
3015fn default_never_pay() -> f64 {
3016 0.10
3017}
3018
3019impl Default for DunningPaymentRates {
3020 fn default() -> Self {
3021 Self {
3022 after_level_1: default_after_level_1(),
3023 after_level_2: default_after_level_2(),
3024 after_level_3: default_after_level_3(),
3025 during_collection: default_during_collection(),
3026 never_pay: default_never_pay(),
3027 }
3028 }
3029}
3030
3031#[derive(Debug, Clone, Serialize, Deserialize)]
3033pub struct PartialPaymentConfig {
3034 #[serde(default = "default_partial_payment_rate")]
3036 pub rate: f64,
3037 #[serde(default)]
3039 pub percentage_distribution: PartialPaymentPercentageDistribution,
3040 #[serde(default = "default_avg_days_until_remainder")]
3042 pub avg_days_until_remainder: u32,
3043}
3044
3045fn default_partial_payment_rate() -> f64 {
3046 0.08
3047}
3048
3049fn default_avg_days_until_remainder() -> u32 {
3050 30
3051}
3052
3053impl Default for PartialPaymentConfig {
3054 fn default() -> Self {
3055 Self {
3056 rate: default_partial_payment_rate(),
3057 percentage_distribution: PartialPaymentPercentageDistribution::default(),
3058 avg_days_until_remainder: default_avg_days_until_remainder(),
3059 }
3060 }
3061}
3062
3063#[derive(Debug, Clone, Serialize, Deserialize)]
3065pub struct PartialPaymentPercentageDistribution {
3066 #[serde(default = "default_partial_25")]
3068 pub pay_25_percent: f64,
3069 #[serde(default = "default_partial_50")]
3071 pub pay_50_percent: f64,
3072 #[serde(default = "default_partial_75")]
3074 pub pay_75_percent: f64,
3075 #[serde(default = "default_partial_random")]
3077 pub pay_random_percent: f64,
3078}
3079
3080fn default_partial_25() -> f64 {
3081 0.15
3082}
3083
3084fn default_partial_50() -> f64 {
3085 0.50
3086}
3087
3088fn default_partial_75() -> f64 {
3089 0.25
3090}
3091
3092fn default_partial_random() -> f64 {
3093 0.10
3094}
3095
3096impl Default for PartialPaymentPercentageDistribution {
3097 fn default() -> Self {
3098 Self {
3099 pay_25_percent: default_partial_25(),
3100 pay_50_percent: default_partial_50(),
3101 pay_75_percent: default_partial_75(),
3102 pay_random_percent: default_partial_random(),
3103 }
3104 }
3105}
3106
3107#[derive(Debug, Clone, Serialize, Deserialize)]
3109pub struct ShortPaymentConfig {
3110 #[serde(default = "default_short_payment_rate")]
3112 pub rate: f64,
3113 #[serde(default)]
3115 pub reason_distribution: ShortPaymentReasonDistribution,
3116 #[serde(default = "default_max_short_percent")]
3118 pub max_short_percent: f64,
3119}
3120
3121fn default_short_payment_rate() -> f64 {
3122 0.03
3123}
3124
3125fn default_max_short_percent() -> f64 {
3126 0.10
3127}
3128
3129impl Default for ShortPaymentConfig {
3130 fn default() -> Self {
3131 Self {
3132 rate: default_short_payment_rate(),
3133 reason_distribution: ShortPaymentReasonDistribution::default(),
3134 max_short_percent: default_max_short_percent(),
3135 }
3136 }
3137}
3138
3139#[derive(Debug, Clone, Serialize, Deserialize)]
3141pub struct ShortPaymentReasonDistribution {
3142 #[serde(default = "default_pricing_dispute")]
3144 pub pricing_dispute: f64,
3145 #[serde(default = "default_quality_issue")]
3147 pub quality_issue: f64,
3148 #[serde(default = "default_quantity_discrepancy")]
3150 pub quantity_discrepancy: f64,
3151 #[serde(default = "default_unauthorized_deduction")]
3153 pub unauthorized_deduction: f64,
3154 #[serde(default = "default_incorrect_discount")]
3156 pub incorrect_discount: f64,
3157}
3158
3159fn default_pricing_dispute() -> f64 {
3160 0.30
3161}
3162
3163fn default_quality_issue() -> f64 {
3164 0.20
3165}
3166
3167fn default_quantity_discrepancy() -> f64 {
3168 0.20
3169}
3170
3171fn default_unauthorized_deduction() -> f64 {
3172 0.15
3173}
3174
3175fn default_incorrect_discount() -> f64 {
3176 0.15
3177}
3178
3179impl Default for ShortPaymentReasonDistribution {
3180 fn default() -> Self {
3181 Self {
3182 pricing_dispute: default_pricing_dispute(),
3183 quality_issue: default_quality_issue(),
3184 quantity_discrepancy: default_quantity_discrepancy(),
3185 unauthorized_deduction: default_unauthorized_deduction(),
3186 incorrect_discount: default_incorrect_discount(),
3187 }
3188 }
3189}
3190
3191#[derive(Debug, Clone, Serialize, Deserialize)]
3193pub struct OnAccountPaymentConfig {
3194 #[serde(default = "default_on_account_rate")]
3196 pub rate: f64,
3197 #[serde(default = "default_avg_days_until_applied")]
3199 pub avg_days_until_applied: u32,
3200}
3201
3202fn default_on_account_rate() -> f64 {
3203 0.02
3204}
3205
3206fn default_avg_days_until_applied() -> u32 {
3207 14
3208}
3209
3210impl Default for OnAccountPaymentConfig {
3211 fn default() -> Self {
3212 Self {
3213 rate: default_on_account_rate(),
3214 avg_days_until_applied: default_avg_days_until_applied(),
3215 }
3216 }
3217}
3218
3219#[derive(Debug, Clone, Serialize, Deserialize)]
3221pub struct PaymentCorrectionConfig {
3222 #[serde(default = "default_payment_correction_rate")]
3224 pub rate: f64,
3225 #[serde(default)]
3227 pub type_distribution: PaymentCorrectionTypeDistribution,
3228}
3229
3230fn default_payment_correction_rate() -> f64 {
3231 0.02
3232}
3233
3234impl Default for PaymentCorrectionConfig {
3235 fn default() -> Self {
3236 Self {
3237 rate: default_payment_correction_rate(),
3238 type_distribution: PaymentCorrectionTypeDistribution::default(),
3239 }
3240 }
3241}
3242
3243#[derive(Debug, Clone, Serialize, Deserialize)]
3245pub struct PaymentCorrectionTypeDistribution {
3246 #[serde(default = "default_nsf_rate")]
3248 pub nsf: f64,
3249 #[serde(default = "default_chargeback_rate")]
3251 pub chargeback: f64,
3252 #[serde(default = "default_wrong_amount_rate")]
3254 pub wrong_amount: f64,
3255 #[serde(default = "default_wrong_customer_rate")]
3257 pub wrong_customer: f64,
3258 #[serde(default = "default_duplicate_payment_rate")]
3260 pub duplicate_payment: f64,
3261}
3262
3263fn default_nsf_rate() -> f64 {
3264 0.30
3265}
3266
3267fn default_chargeback_rate() -> f64 {
3268 0.20
3269}
3270
3271fn default_wrong_amount_rate() -> f64 {
3272 0.20
3273}
3274
3275fn default_wrong_customer_rate() -> f64 {
3276 0.15
3277}
3278
3279fn default_duplicate_payment_rate() -> f64 {
3280 0.15
3281}
3282
3283impl Default for PaymentCorrectionTypeDistribution {
3284 fn default() -> Self {
3285 Self {
3286 nsf: default_nsf_rate(),
3287 chargeback: default_chargeback_rate(),
3288 wrong_amount: default_wrong_amount_rate(),
3289 wrong_customer: default_wrong_customer_rate(),
3290 duplicate_payment: default_duplicate_payment_rate(),
3291 }
3292 }
3293}
3294
3295#[derive(Debug, Clone, Serialize, Deserialize)]
3297pub struct DocumentLineCountDistribution {
3298 #[serde(default = "default_min_lines")]
3300 pub min_lines: u32,
3301 #[serde(default = "default_max_lines")]
3303 pub max_lines: u32,
3304 #[serde(default = "default_mode_lines")]
3306 pub mode_lines: u32,
3307}
3308
3309fn default_min_lines() -> u32 {
3310 1
3311}
3312
3313fn default_max_lines() -> u32 {
3314 20
3315}
3316
3317fn default_mode_lines() -> u32 {
3318 3
3319}
3320
3321impl Default for DocumentLineCountDistribution {
3322 fn default() -> Self {
3323 Self {
3324 min_lines: default_min_lines(),
3325 max_lines: default_max_lines(),
3326 mode_lines: default_mode_lines(),
3327 }
3328 }
3329}
3330
3331#[derive(Debug, Clone, Serialize, Deserialize)]
3333pub struct CashDiscountConfig {
3334 #[serde(default = "default_discount_eligible_rate")]
3336 pub eligible_rate: f64,
3337 #[serde(default = "default_discount_taken_rate")]
3339 pub taken_rate: f64,
3340 #[serde(default = "default_discount_percent")]
3342 pub discount_percent: f64,
3343 #[serde(default = "default_discount_days")]
3345 pub discount_days: u32,
3346}
3347
3348fn default_discount_eligible_rate() -> f64 {
3349 0.30
3350}
3351
3352fn default_discount_taken_rate() -> f64 {
3353 0.60
3354}
3355
3356fn default_discount_percent() -> f64 {
3357 0.02
3358}
3359
3360fn default_discount_days() -> u32 {
3361 10
3362}
3363
3364impl Default for CashDiscountConfig {
3365 fn default() -> Self {
3366 Self {
3367 eligible_rate: default_discount_eligible_rate(),
3368 taken_rate: default_discount_taken_rate(),
3369 discount_percent: default_discount_percent(),
3370 discount_days: default_discount_days(),
3371 }
3372 }
3373}
3374
3375#[derive(Debug, Clone, Serialize, Deserialize)]
3381pub struct IntercompanyConfig {
3382 #[serde(default)]
3384 pub enabled: bool,
3385 #[serde(default = "default_ic_transaction_rate")]
3387 pub ic_transaction_rate: f64,
3388 #[serde(default)]
3390 pub transfer_pricing_method: TransferPricingMethod,
3391 #[serde(default = "default_markup_percent")]
3393 pub markup_percent: f64,
3394 #[serde(default = "default_true")]
3396 pub generate_matched_pairs: bool,
3397 #[serde(default)]
3399 pub transaction_type_distribution: ICTransactionTypeDistribution,
3400 #[serde(default)]
3402 pub generate_eliminations: bool,
3403}
3404
3405fn default_ic_transaction_rate() -> f64 {
3406 0.15
3407}
3408
3409fn default_markup_percent() -> f64 {
3410 0.05
3411}
3412
3413impl Default for IntercompanyConfig {
3414 fn default() -> Self {
3415 Self {
3416 enabled: false,
3417 ic_transaction_rate: default_ic_transaction_rate(),
3418 transfer_pricing_method: TransferPricingMethod::default(),
3419 markup_percent: default_markup_percent(),
3420 generate_matched_pairs: true,
3421 transaction_type_distribution: ICTransactionTypeDistribution::default(),
3422 generate_eliminations: false,
3423 }
3424 }
3425}
3426
3427#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
3429#[serde(rename_all = "snake_case")]
3430pub enum TransferPricingMethod {
3431 #[default]
3433 CostPlus,
3434 ComparableUncontrolled,
3436 ResalePrice,
3438 TransactionalNetMargin,
3440 ProfitSplit,
3442}
3443
3444#[derive(Debug, Clone, Serialize, Deserialize)]
3446pub struct ICTransactionTypeDistribution {
3447 pub goods_sale: f64,
3449 pub service_provided: f64,
3451 pub loan: f64,
3453 pub dividend: f64,
3455 pub management_fee: f64,
3457 pub royalty: f64,
3459 pub cost_sharing: f64,
3461}
3462
3463impl Default for ICTransactionTypeDistribution {
3464 fn default() -> Self {
3465 Self {
3466 goods_sale: 0.35,
3467 service_provided: 0.20,
3468 loan: 0.10,
3469 dividend: 0.05,
3470 management_fee: 0.15,
3471 royalty: 0.10,
3472 cost_sharing: 0.05,
3473 }
3474 }
3475}
3476
3477#[derive(Debug, Clone, Serialize, Deserialize)]
3483pub struct BalanceConfig {
3484 #[serde(default)]
3486 pub generate_opening_balances: bool,
3487 #[serde(default = "default_true")]
3489 pub generate_trial_balances: bool,
3490 #[serde(default = "default_gross_margin")]
3492 pub target_gross_margin: f64,
3493 #[serde(default = "default_dso")]
3495 pub target_dso_days: u32,
3496 #[serde(default = "default_dpo")]
3498 pub target_dpo_days: u32,
3499 #[serde(default = "default_current_ratio")]
3501 pub target_current_ratio: f64,
3502 #[serde(default = "default_debt_equity")]
3504 pub target_debt_to_equity: f64,
3505 #[serde(default = "default_true")]
3507 pub validate_balance_equation: bool,
3508 #[serde(default = "default_true")]
3510 pub reconcile_subledgers: bool,
3511}
3512
3513fn default_gross_margin() -> f64 {
3514 0.35
3515}
3516
3517fn default_dso() -> u32 {
3518 45
3519}
3520
3521fn default_dpo() -> u32 {
3522 30
3523}
3524
3525fn default_current_ratio() -> f64 {
3526 1.5
3527}
3528
3529fn default_debt_equity() -> f64 {
3530 0.5
3531}
3532
3533impl Default for BalanceConfig {
3534 fn default() -> Self {
3535 Self {
3536 generate_opening_balances: false,
3537 generate_trial_balances: true,
3538 target_gross_margin: default_gross_margin(),
3539 target_dso_days: default_dso(),
3540 target_dpo_days: default_dpo(),
3541 target_current_ratio: default_current_ratio(),
3542 target_debt_to_equity: default_debt_equity(),
3543 validate_balance_equation: true,
3544 reconcile_subledgers: true,
3545 }
3546 }
3547}
3548
3549#[derive(Debug, Clone, Serialize, Deserialize)]
3558pub struct OcpmConfig {
3559 #[serde(default)]
3561 pub enabled: bool,
3562
3563 #[serde(default = "default_true")]
3565 pub generate_lifecycle_events: bool,
3566
3567 #[serde(default = "default_true")]
3569 pub include_object_relationships: bool,
3570
3571 #[serde(default = "default_true")]
3573 pub compute_variants: bool,
3574
3575 #[serde(default)]
3577 pub max_variants: usize,
3578
3579 #[serde(default)]
3581 pub p2p_process: OcpmProcessConfig,
3582
3583 #[serde(default)]
3585 pub o2c_process: OcpmProcessConfig,
3586
3587 #[serde(default)]
3589 pub output: OcpmOutputConfig,
3590}
3591
3592impl Default for OcpmConfig {
3593 fn default() -> Self {
3594 Self {
3595 enabled: false,
3596 generate_lifecycle_events: true,
3597 include_object_relationships: true,
3598 compute_variants: true,
3599 max_variants: 0,
3600 p2p_process: OcpmProcessConfig::default(),
3601 o2c_process: OcpmProcessConfig::default(),
3602 output: OcpmOutputConfig::default(),
3603 }
3604 }
3605}
3606
3607#[derive(Debug, Clone, Serialize, Deserialize)]
3609pub struct OcpmProcessConfig {
3610 #[serde(default = "default_rework_probability")]
3612 pub rework_probability: f64,
3613
3614 #[serde(default = "default_skip_probability")]
3616 pub skip_step_probability: f64,
3617
3618 #[serde(default = "default_out_of_order_probability")]
3620 pub out_of_order_probability: f64,
3621}
3622
3623fn default_rework_probability() -> f64 {
3624 0.05
3625}
3626
3627fn default_skip_probability() -> f64 {
3628 0.02
3629}
3630
3631fn default_out_of_order_probability() -> f64 {
3632 0.03
3633}
3634
3635impl Default for OcpmProcessConfig {
3636 fn default() -> Self {
3637 Self {
3638 rework_probability: default_rework_probability(),
3639 skip_step_probability: default_skip_probability(),
3640 out_of_order_probability: default_out_of_order_probability(),
3641 }
3642 }
3643}
3644
3645#[derive(Debug, Clone, Serialize, Deserialize)]
3647pub struct OcpmOutputConfig {
3648 #[serde(default = "default_true")]
3650 pub ocel_json: bool,
3651
3652 #[serde(default)]
3654 pub ocel_xml: bool,
3655
3656 #[serde(default)]
3658 pub xes: bool,
3659
3660 #[serde(default = "default_true")]
3662 pub xes_include_lifecycle: bool,
3663
3664 #[serde(default = "default_true")]
3666 pub xes_include_resources: bool,
3667
3668 #[serde(default = "default_true")]
3670 pub flattened_csv: bool,
3671
3672 #[serde(default = "default_true")]
3674 pub event_object_csv: bool,
3675
3676 #[serde(default = "default_true")]
3678 pub object_relationship_csv: bool,
3679
3680 #[serde(default = "default_true")]
3682 pub variants_csv: bool,
3683
3684 #[serde(default)]
3686 pub export_reference_models: bool,
3687}
3688
3689impl Default for OcpmOutputConfig {
3690 fn default() -> Self {
3691 Self {
3692 ocel_json: true,
3693 ocel_xml: false,
3694 xes: false,
3695 xes_include_lifecycle: true,
3696 xes_include_resources: true,
3697 flattened_csv: true,
3698 event_object_csv: true,
3699 object_relationship_csv: true,
3700 variants_csv: true,
3701 export_reference_models: false,
3702 }
3703 }
3704}
3705
3706#[derive(Debug, Clone, Serialize, Deserialize)]
3708pub struct AuditGenerationConfig {
3709 #[serde(default)]
3711 pub enabled: bool,
3712
3713 #[serde(default = "default_true")]
3715 pub generate_workpapers: bool,
3716
3717 #[serde(default)]
3719 pub engagement_types: AuditEngagementTypesConfig,
3720
3721 #[serde(default)]
3723 pub workpapers: WorkpaperConfig,
3724
3725 #[serde(default)]
3727 pub team: AuditTeamConfig,
3728
3729 #[serde(default)]
3731 pub review: ReviewWorkflowConfig,
3732}
3733
3734impl Default for AuditGenerationConfig {
3735 fn default() -> Self {
3736 Self {
3737 enabled: false,
3738 generate_workpapers: true,
3739 engagement_types: AuditEngagementTypesConfig::default(),
3740 workpapers: WorkpaperConfig::default(),
3741 team: AuditTeamConfig::default(),
3742 review: ReviewWorkflowConfig::default(),
3743 }
3744 }
3745}
3746
3747#[derive(Debug, Clone, Serialize, Deserialize)]
3749pub struct AuditEngagementTypesConfig {
3750 #[serde(default = "default_financial_audit_prob")]
3752 pub financial_statement: f64,
3753 #[serde(default = "default_sox_audit_prob")]
3755 pub sox_icfr: f64,
3756 #[serde(default = "default_integrated_audit_prob")]
3758 pub integrated: f64,
3759 #[serde(default = "default_review_prob")]
3761 pub review: f64,
3762 #[serde(default = "default_aup_prob")]
3764 pub agreed_upon_procedures: f64,
3765}
3766
3767fn default_financial_audit_prob() -> f64 {
3768 0.40
3769}
3770fn default_sox_audit_prob() -> f64 {
3771 0.20
3772}
3773fn default_integrated_audit_prob() -> f64 {
3774 0.25
3775}
3776fn default_review_prob() -> f64 {
3777 0.10
3778}
3779fn default_aup_prob() -> f64 {
3780 0.05
3781}
3782
3783impl Default for AuditEngagementTypesConfig {
3784 fn default() -> Self {
3785 Self {
3786 financial_statement: default_financial_audit_prob(),
3787 sox_icfr: default_sox_audit_prob(),
3788 integrated: default_integrated_audit_prob(),
3789 review: default_review_prob(),
3790 agreed_upon_procedures: default_aup_prob(),
3791 }
3792 }
3793}
3794
3795#[derive(Debug, Clone, Serialize, Deserialize)]
3797pub struct WorkpaperConfig {
3798 #[serde(default = "default_workpapers_per_phase")]
3800 pub average_per_phase: usize,
3801
3802 #[serde(default = "default_true")]
3804 pub include_isa_references: bool,
3805
3806 #[serde(default = "default_true")]
3808 pub include_sample_details: bool,
3809
3810 #[serde(default = "default_true")]
3812 pub include_cross_references: bool,
3813
3814 #[serde(default)]
3816 pub sampling: SamplingConfig,
3817}
3818
3819fn default_workpapers_per_phase() -> usize {
3820 5
3821}
3822
3823impl Default for WorkpaperConfig {
3824 fn default() -> Self {
3825 Self {
3826 average_per_phase: default_workpapers_per_phase(),
3827 include_isa_references: true,
3828 include_sample_details: true,
3829 include_cross_references: true,
3830 sampling: SamplingConfig::default(),
3831 }
3832 }
3833}
3834
3835#[derive(Debug, Clone, Serialize, Deserialize)]
3837pub struct SamplingConfig {
3838 #[serde(default = "default_statistical_rate")]
3840 pub statistical_rate: f64,
3841 #[serde(default = "default_judgmental_rate")]
3843 pub judgmental_rate: f64,
3844 #[serde(default = "default_haphazard_rate")]
3846 pub haphazard_rate: f64,
3847 #[serde(default = "default_complete_examination_rate")]
3849 pub complete_examination_rate: f64,
3850}
3851
3852fn default_statistical_rate() -> f64 {
3853 0.40
3854}
3855fn default_judgmental_rate() -> f64 {
3856 0.30
3857}
3858fn default_haphazard_rate() -> f64 {
3859 0.20
3860}
3861fn default_complete_examination_rate() -> f64 {
3862 0.10
3863}
3864
3865impl Default for SamplingConfig {
3866 fn default() -> Self {
3867 Self {
3868 statistical_rate: default_statistical_rate(),
3869 judgmental_rate: default_judgmental_rate(),
3870 haphazard_rate: default_haphazard_rate(),
3871 complete_examination_rate: default_complete_examination_rate(),
3872 }
3873 }
3874}
3875
3876#[derive(Debug, Clone, Serialize, Deserialize)]
3878pub struct AuditTeamConfig {
3879 #[serde(default = "default_min_team_size")]
3881 pub min_team_size: usize,
3882 #[serde(default = "default_max_team_size")]
3884 pub max_team_size: usize,
3885 #[serde(default = "default_specialist_probability")]
3887 pub specialist_probability: f64,
3888}
3889
3890fn default_min_team_size() -> usize {
3891 3
3892}
3893fn default_max_team_size() -> usize {
3894 8
3895}
3896fn default_specialist_probability() -> f64 {
3897 0.30
3898}
3899
3900impl Default for AuditTeamConfig {
3901 fn default() -> Self {
3902 Self {
3903 min_team_size: default_min_team_size(),
3904 max_team_size: default_max_team_size(),
3905 specialist_probability: default_specialist_probability(),
3906 }
3907 }
3908}
3909
3910#[derive(Debug, Clone, Serialize, Deserialize)]
3912pub struct ReviewWorkflowConfig {
3913 #[serde(default = "default_review_delay_days")]
3915 pub average_review_delay_days: u32,
3916 #[serde(default = "default_rework_probability_review")]
3918 pub rework_probability: f64,
3919 #[serde(default = "default_true")]
3921 pub require_partner_signoff: bool,
3922}
3923
3924fn default_review_delay_days() -> u32 {
3925 2
3926}
3927fn default_rework_probability_review() -> f64 {
3928 0.15
3929}
3930
3931impl Default for ReviewWorkflowConfig {
3932 fn default() -> Self {
3933 Self {
3934 average_review_delay_days: default_review_delay_days(),
3935 rework_probability: default_rework_probability_review(),
3936 require_partner_signoff: true,
3937 }
3938 }
3939}
3940
3941#[derive(Debug, Clone, Serialize, Deserialize)]
3947pub struct DataQualitySchemaConfig {
3948 #[serde(default)]
3950 pub enabled: bool,
3951 #[serde(default)]
3953 pub preset: DataQualityPreset,
3954 #[serde(default)]
3956 pub missing_values: MissingValuesSchemaConfig,
3957 #[serde(default)]
3959 pub typos: TypoSchemaConfig,
3960 #[serde(default)]
3962 pub format_variations: FormatVariationSchemaConfig,
3963 #[serde(default)]
3965 pub duplicates: DuplicateSchemaConfig,
3966 #[serde(default)]
3968 pub encoding_issues: EncodingIssueSchemaConfig,
3969 #[serde(default)]
3971 pub generate_labels: bool,
3972 #[serde(default)]
3974 pub sink_profiles: SinkQualityProfiles,
3975}
3976
3977impl Default for DataQualitySchemaConfig {
3978 fn default() -> Self {
3979 Self {
3980 enabled: false,
3981 preset: DataQualityPreset::None,
3982 missing_values: MissingValuesSchemaConfig::default(),
3983 typos: TypoSchemaConfig::default(),
3984 format_variations: FormatVariationSchemaConfig::default(),
3985 duplicates: DuplicateSchemaConfig::default(),
3986 encoding_issues: EncodingIssueSchemaConfig::default(),
3987 generate_labels: true,
3988 sink_profiles: SinkQualityProfiles::default(),
3989 }
3990 }
3991}
3992
3993impl DataQualitySchemaConfig {
3994 pub fn with_preset(preset: DataQualityPreset) -> Self {
3996 let mut config = Self {
3997 preset,
3998 ..Default::default()
3999 };
4000 config.apply_preset();
4001 config
4002 }
4003
4004 pub fn apply_preset(&mut self) {
4007 if !self.preset.overrides_settings() {
4008 return;
4009 }
4010
4011 self.enabled = true;
4012
4013 self.missing_values.enabled = self.preset.missing_rate() > 0.0;
4015 self.missing_values.rate = self.preset.missing_rate();
4016
4017 self.typos.enabled = self.preset.typo_rate() > 0.0;
4019 self.typos.char_error_rate = self.preset.typo_rate();
4020
4021 self.duplicates.enabled = self.preset.duplicate_rate() > 0.0;
4023 self.duplicates.exact_duplicate_ratio = self.preset.duplicate_rate() * 0.4;
4024 self.duplicates.near_duplicate_ratio = self.preset.duplicate_rate() * 0.4;
4025 self.duplicates.fuzzy_duplicate_ratio = self.preset.duplicate_rate() * 0.2;
4026
4027 self.format_variations.enabled = self.preset.format_variations_enabled();
4029
4030 self.encoding_issues.enabled = self.preset.encoding_issues_enabled();
4032 self.encoding_issues.rate = self.preset.encoding_issue_rate();
4033
4034 if self.preset.ocr_errors_enabled() {
4036 self.typos.type_weights.ocr_errors = 0.3;
4037 }
4038 }
4039
4040 pub fn effective_missing_rate(&self) -> f64 {
4042 if self.preset.overrides_settings() {
4043 self.preset.missing_rate()
4044 } else {
4045 self.missing_values.rate
4046 }
4047 }
4048
4049 pub fn effective_typo_rate(&self) -> f64 {
4051 if self.preset.overrides_settings() {
4052 self.preset.typo_rate()
4053 } else {
4054 self.typos.char_error_rate
4055 }
4056 }
4057
4058 pub fn effective_duplicate_rate(&self) -> f64 {
4060 if self.preset.overrides_settings() {
4061 self.preset.duplicate_rate()
4062 } else {
4063 self.duplicates.exact_duplicate_ratio
4064 + self.duplicates.near_duplicate_ratio
4065 + self.duplicates.fuzzy_duplicate_ratio
4066 }
4067 }
4068
4069 pub fn clean() -> Self {
4071 Self::with_preset(DataQualityPreset::Clean)
4072 }
4073
4074 pub fn noisy() -> Self {
4076 Self::with_preset(DataQualityPreset::Noisy)
4077 }
4078
4079 pub fn legacy() -> Self {
4081 Self::with_preset(DataQualityPreset::Legacy)
4082 }
4083}
4084
4085#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
4087#[serde(rename_all = "snake_case")]
4088pub enum DataQualityPreset {
4089 #[default]
4091 None,
4092 Minimal,
4094 Normal,
4096 High,
4098 Custom,
4100
4101 Clean,
4107 Noisy,
4110 Legacy,
4113}
4114
4115impl DataQualityPreset {
4116 pub fn missing_rate(&self) -> f64 {
4118 match self {
4119 DataQualityPreset::None => 0.0,
4120 DataQualityPreset::Minimal => 0.005,
4121 DataQualityPreset::Normal => 0.02,
4122 DataQualityPreset::High => 0.08,
4123 DataQualityPreset::Custom => 0.01, DataQualityPreset::Clean => 0.001,
4125 DataQualityPreset::Noisy => 0.05,
4126 DataQualityPreset::Legacy => 0.10,
4127 }
4128 }
4129
4130 pub fn typo_rate(&self) -> f64 {
4132 match self {
4133 DataQualityPreset::None => 0.0,
4134 DataQualityPreset::Minimal => 0.0005,
4135 DataQualityPreset::Normal => 0.002,
4136 DataQualityPreset::High => 0.01,
4137 DataQualityPreset::Custom => 0.001, DataQualityPreset::Clean => 0.0005,
4139 DataQualityPreset::Noisy => 0.02,
4140 DataQualityPreset::Legacy => 0.05,
4141 }
4142 }
4143
4144 pub fn duplicate_rate(&self) -> f64 {
4146 match self {
4147 DataQualityPreset::None => 0.0,
4148 DataQualityPreset::Minimal => 0.001,
4149 DataQualityPreset::Normal => 0.005,
4150 DataQualityPreset::High => 0.02,
4151 DataQualityPreset::Custom => 0.0, DataQualityPreset::Clean => 0.0,
4153 DataQualityPreset::Noisy => 0.01,
4154 DataQualityPreset::Legacy => 0.03,
4155 }
4156 }
4157
4158 pub fn format_variations_enabled(&self) -> bool {
4160 match self {
4161 DataQualityPreset::None | DataQualityPreset::Clean => false,
4162 DataQualityPreset::Minimal => true,
4163 DataQualityPreset::Normal => true,
4164 DataQualityPreset::High => true,
4165 DataQualityPreset::Custom => true,
4166 DataQualityPreset::Noisy => true,
4167 DataQualityPreset::Legacy => true,
4168 }
4169 }
4170
4171 pub fn ocr_errors_enabled(&self) -> bool {
4173 matches!(self, DataQualityPreset::Legacy | DataQualityPreset::High)
4174 }
4175
4176 pub fn encoding_issues_enabled(&self) -> bool {
4178 matches!(
4179 self,
4180 DataQualityPreset::Legacy | DataQualityPreset::High | DataQualityPreset::Noisy
4181 )
4182 }
4183
4184 pub fn encoding_issue_rate(&self) -> f64 {
4186 match self {
4187 DataQualityPreset::None | DataQualityPreset::Clean | DataQualityPreset::Minimal => 0.0,
4188 DataQualityPreset::Normal => 0.002,
4189 DataQualityPreset::High => 0.01,
4190 DataQualityPreset::Custom => 0.0,
4191 DataQualityPreset::Noisy => 0.005,
4192 DataQualityPreset::Legacy => 0.02,
4193 }
4194 }
4195
4196 pub fn overrides_settings(&self) -> bool {
4198 !matches!(self, DataQualityPreset::Custom | DataQualityPreset::None)
4199 }
4200
4201 pub fn description(&self) -> &'static str {
4203 match self {
4204 DataQualityPreset::None => "No data quality issues (pristine data)",
4205 DataQualityPreset::Minimal => "Very rare data quality issues",
4206 DataQualityPreset::Normal => "Realistic enterprise data quality",
4207 DataQualityPreset::High => "Messy data for stress testing",
4208 DataQualityPreset::Custom => "Custom settings from configuration",
4209 DataQualityPreset::Clean => "ML-ready clean data with minimal issues",
4210 DataQualityPreset::Noisy => "Typical production data with moderate issues",
4211 DataQualityPreset::Legacy => "Legacy/migrated data with heavy issues and OCR errors",
4212 }
4213 }
4214}
4215
4216#[derive(Debug, Clone, Serialize, Deserialize)]
4218pub struct MissingValuesSchemaConfig {
4219 #[serde(default)]
4221 pub enabled: bool,
4222 #[serde(default = "default_missing_rate")]
4224 pub rate: f64,
4225 #[serde(default)]
4227 pub strategy: MissingValueStrategy,
4228 #[serde(default)]
4230 pub field_rates: std::collections::HashMap<String, f64>,
4231 #[serde(default)]
4233 pub protected_fields: Vec<String>,
4234}
4235
4236fn default_missing_rate() -> f64 {
4237 0.01
4238}
4239
4240impl Default for MissingValuesSchemaConfig {
4241 fn default() -> Self {
4242 Self {
4243 enabled: false,
4244 rate: default_missing_rate(),
4245 strategy: MissingValueStrategy::Mcar,
4246 field_rates: std::collections::HashMap::new(),
4247 protected_fields: vec![
4248 "document_id".to_string(),
4249 "company_code".to_string(),
4250 "posting_date".to_string(),
4251 ],
4252 }
4253 }
4254}
4255
4256#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
4258#[serde(rename_all = "snake_case")]
4259pub enum MissingValueStrategy {
4260 #[default]
4262 Mcar,
4263 Mar,
4265 Mnar,
4267 Systematic,
4269}
4270
4271#[derive(Debug, Clone, Serialize, Deserialize)]
4273pub struct TypoSchemaConfig {
4274 #[serde(default)]
4276 pub enabled: bool,
4277 #[serde(default = "default_typo_rate")]
4279 pub char_error_rate: f64,
4280 #[serde(default)]
4282 pub type_weights: TypoTypeWeights,
4283 #[serde(default)]
4285 pub protected_fields: Vec<String>,
4286}
4287
4288fn default_typo_rate() -> f64 {
4289 0.001
4290}
4291
4292impl Default for TypoSchemaConfig {
4293 fn default() -> Self {
4294 Self {
4295 enabled: false,
4296 char_error_rate: default_typo_rate(),
4297 type_weights: TypoTypeWeights::default(),
4298 protected_fields: vec![
4299 "document_id".to_string(),
4300 "gl_account".to_string(),
4301 "company_code".to_string(),
4302 ],
4303 }
4304 }
4305}
4306
4307#[derive(Debug, Clone, Serialize, Deserialize)]
4309pub struct TypoTypeWeights {
4310 #[serde(default = "default_substitution_weight")]
4312 pub substitution: f64,
4313 #[serde(default = "default_transposition_weight")]
4315 pub transposition: f64,
4316 #[serde(default = "default_insertion_weight")]
4318 pub insertion: f64,
4319 #[serde(default = "default_deletion_weight")]
4321 pub deletion: f64,
4322 #[serde(default = "default_ocr_weight")]
4324 pub ocr_errors: f64,
4325 #[serde(default = "default_homophone_weight")]
4327 pub homophones: f64,
4328}
4329
4330fn default_substitution_weight() -> f64 {
4331 0.35
4332}
4333fn default_transposition_weight() -> f64 {
4334 0.25
4335}
4336fn default_insertion_weight() -> f64 {
4337 0.10
4338}
4339fn default_deletion_weight() -> f64 {
4340 0.15
4341}
4342fn default_ocr_weight() -> f64 {
4343 0.10
4344}
4345fn default_homophone_weight() -> f64 {
4346 0.05
4347}
4348
4349impl Default for TypoTypeWeights {
4350 fn default() -> Self {
4351 Self {
4352 substitution: default_substitution_weight(),
4353 transposition: default_transposition_weight(),
4354 insertion: default_insertion_weight(),
4355 deletion: default_deletion_weight(),
4356 ocr_errors: default_ocr_weight(),
4357 homophones: default_homophone_weight(),
4358 }
4359 }
4360}
4361
4362#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4364pub struct FormatVariationSchemaConfig {
4365 #[serde(default)]
4367 pub enabled: bool,
4368 #[serde(default)]
4370 pub dates: DateFormatVariationConfig,
4371 #[serde(default)]
4373 pub amounts: AmountFormatVariationConfig,
4374 #[serde(default)]
4376 pub identifiers: IdentifierFormatVariationConfig,
4377}
4378
4379#[derive(Debug, Clone, Serialize, Deserialize)]
4381pub struct DateFormatVariationConfig {
4382 #[serde(default)]
4384 pub enabled: bool,
4385 #[serde(default = "default_date_variation_rate")]
4387 pub rate: f64,
4388 #[serde(default = "default_true")]
4390 pub iso_format: bool,
4391 #[serde(default)]
4393 pub us_format: bool,
4394 #[serde(default)]
4396 pub eu_format: bool,
4397 #[serde(default)]
4399 pub long_format: bool,
4400}
4401
4402fn default_date_variation_rate() -> f64 {
4403 0.05
4404}
4405
4406impl Default for DateFormatVariationConfig {
4407 fn default() -> Self {
4408 Self {
4409 enabled: false,
4410 rate: default_date_variation_rate(),
4411 iso_format: true,
4412 us_format: false,
4413 eu_format: false,
4414 long_format: false,
4415 }
4416 }
4417}
4418
4419#[derive(Debug, Clone, Serialize, Deserialize)]
4421pub struct AmountFormatVariationConfig {
4422 #[serde(default)]
4424 pub enabled: bool,
4425 #[serde(default = "default_amount_variation_rate")]
4427 pub rate: f64,
4428 #[serde(default)]
4430 pub us_comma_format: bool,
4431 #[serde(default)]
4433 pub eu_format: bool,
4434 #[serde(default)]
4436 pub currency_prefix: bool,
4437 #[serde(default)]
4439 pub accounting_format: bool,
4440}
4441
4442fn default_amount_variation_rate() -> f64 {
4443 0.02
4444}
4445
4446impl Default for AmountFormatVariationConfig {
4447 fn default() -> Self {
4448 Self {
4449 enabled: false,
4450 rate: default_amount_variation_rate(),
4451 us_comma_format: false,
4452 eu_format: false,
4453 currency_prefix: false,
4454 accounting_format: false,
4455 }
4456 }
4457}
4458
4459#[derive(Debug, Clone, Serialize, Deserialize)]
4461pub struct IdentifierFormatVariationConfig {
4462 #[serde(default)]
4464 pub enabled: bool,
4465 #[serde(default = "default_identifier_variation_rate")]
4467 pub rate: f64,
4468 #[serde(default)]
4470 pub case_variations: bool,
4471 #[serde(default)]
4473 pub padding_variations: bool,
4474 #[serde(default)]
4476 pub separator_variations: bool,
4477}
4478
4479fn default_identifier_variation_rate() -> f64 {
4480 0.02
4481}
4482
4483impl Default for IdentifierFormatVariationConfig {
4484 fn default() -> Self {
4485 Self {
4486 enabled: false,
4487 rate: default_identifier_variation_rate(),
4488 case_variations: false,
4489 padding_variations: false,
4490 separator_variations: false,
4491 }
4492 }
4493}
4494
4495#[derive(Debug, Clone, Serialize, Deserialize)]
4497pub struct DuplicateSchemaConfig {
4498 #[serde(default)]
4500 pub enabled: bool,
4501 #[serde(default = "default_duplicate_rate")]
4503 pub rate: f64,
4504 #[serde(default = "default_exact_duplicate_ratio")]
4506 pub exact_duplicate_ratio: f64,
4507 #[serde(default = "default_near_duplicate_ratio")]
4509 pub near_duplicate_ratio: f64,
4510 #[serde(default = "default_fuzzy_duplicate_ratio")]
4512 pub fuzzy_duplicate_ratio: f64,
4513 #[serde(default = "default_max_date_offset")]
4515 pub max_date_offset_days: u32,
4516 #[serde(default = "default_max_amount_variance")]
4518 pub max_amount_variance: f64,
4519}
4520
4521fn default_duplicate_rate() -> f64 {
4522 0.005
4523}
4524fn default_exact_duplicate_ratio() -> f64 {
4525 0.4
4526}
4527fn default_near_duplicate_ratio() -> f64 {
4528 0.35
4529}
4530fn default_fuzzy_duplicate_ratio() -> f64 {
4531 0.25
4532}
4533fn default_max_date_offset() -> u32 {
4534 3
4535}
4536fn default_max_amount_variance() -> f64 {
4537 0.01
4538}
4539
4540impl Default for DuplicateSchemaConfig {
4541 fn default() -> Self {
4542 Self {
4543 enabled: false,
4544 rate: default_duplicate_rate(),
4545 exact_duplicate_ratio: default_exact_duplicate_ratio(),
4546 near_duplicate_ratio: default_near_duplicate_ratio(),
4547 fuzzy_duplicate_ratio: default_fuzzy_duplicate_ratio(),
4548 max_date_offset_days: default_max_date_offset(),
4549 max_amount_variance: default_max_amount_variance(),
4550 }
4551 }
4552}
4553
4554#[derive(Debug, Clone, Serialize, Deserialize)]
4556pub struct EncodingIssueSchemaConfig {
4557 #[serde(default)]
4559 pub enabled: bool,
4560 #[serde(default = "default_encoding_rate")]
4562 pub rate: f64,
4563 #[serde(default)]
4565 pub mojibake: bool,
4566 #[serde(default)]
4568 pub html_entities: bool,
4569 #[serde(default)]
4571 pub bom_issues: bool,
4572}
4573
4574fn default_encoding_rate() -> f64 {
4575 0.001
4576}
4577
4578impl Default for EncodingIssueSchemaConfig {
4579 fn default() -> Self {
4580 Self {
4581 enabled: false,
4582 rate: default_encoding_rate(),
4583 mojibake: false,
4584 html_entities: false,
4585 bom_issues: false,
4586 }
4587 }
4588}
4589
4590#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4592pub struct SinkQualityProfiles {
4593 #[serde(default)]
4595 pub csv: Option<SinkQualityOverride>,
4596 #[serde(default)]
4598 pub json: Option<SinkQualityOverride>,
4599 #[serde(default)]
4601 pub parquet: Option<SinkQualityOverride>,
4602}
4603
4604#[derive(Debug, Clone, Serialize, Deserialize)]
4606pub struct SinkQualityOverride {
4607 pub enabled: Option<bool>,
4609 pub missing_rate: Option<f64>,
4611 pub typo_rate: Option<f64>,
4613 pub format_variation_rate: Option<f64>,
4615 pub duplicate_rate: Option<f64>,
4617}
4618
4619#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4631pub struct AccountingStandardsConfig {
4632 #[serde(default)]
4634 pub enabled: bool,
4635
4636 #[serde(default)]
4638 pub framework: AccountingFrameworkConfig,
4639
4640 #[serde(default)]
4642 pub revenue_recognition: RevenueRecognitionConfig,
4643
4644 #[serde(default)]
4646 pub leases: LeaseAccountingConfig,
4647
4648 #[serde(default)]
4650 pub fair_value: FairValueConfig,
4651
4652 #[serde(default)]
4654 pub impairment: ImpairmentConfig,
4655
4656 #[serde(default)]
4658 pub generate_differences: bool,
4659}
4660
4661#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
4663#[serde(rename_all = "snake_case")]
4664pub enum AccountingFrameworkConfig {
4665 #[default]
4667 UsGaap,
4668 Ifrs,
4670 DualReporting,
4672}
4673
4674#[derive(Debug, Clone, Serialize, Deserialize)]
4676pub struct RevenueRecognitionConfig {
4677 #[serde(default)]
4679 pub enabled: bool,
4680
4681 #[serde(default = "default_true")]
4683 pub generate_contracts: bool,
4684
4685 #[serde(default = "default_avg_obligations")]
4687 pub avg_obligations_per_contract: f64,
4688
4689 #[serde(default = "default_variable_consideration_rate")]
4691 pub variable_consideration_rate: f64,
4692
4693 #[serde(default = "default_over_time_rate")]
4695 pub over_time_recognition_rate: f64,
4696
4697 #[serde(default = "default_contract_count")]
4699 pub contract_count: usize,
4700}
4701
4702fn default_avg_obligations() -> f64 {
4703 2.0
4704}
4705
4706fn default_variable_consideration_rate() -> f64 {
4707 0.15
4708}
4709
4710fn default_over_time_rate() -> f64 {
4711 0.30
4712}
4713
4714fn default_contract_count() -> usize {
4715 100
4716}
4717
4718impl Default for RevenueRecognitionConfig {
4719 fn default() -> Self {
4720 Self {
4721 enabled: false,
4722 generate_contracts: true,
4723 avg_obligations_per_contract: default_avg_obligations(),
4724 variable_consideration_rate: default_variable_consideration_rate(),
4725 over_time_recognition_rate: default_over_time_rate(),
4726 contract_count: default_contract_count(),
4727 }
4728 }
4729}
4730
4731#[derive(Debug, Clone, Serialize, Deserialize)]
4733pub struct LeaseAccountingConfig {
4734 #[serde(default)]
4736 pub enabled: bool,
4737
4738 #[serde(default = "default_lease_count")]
4740 pub lease_count: usize,
4741
4742 #[serde(default = "default_finance_lease_pct")]
4744 pub finance_lease_percent: f64,
4745
4746 #[serde(default = "default_avg_lease_term")]
4748 pub avg_lease_term_months: u32,
4749
4750 #[serde(default = "default_true")]
4752 pub generate_amortization: bool,
4753
4754 #[serde(default = "default_real_estate_pct")]
4756 pub real_estate_percent: f64,
4757}
4758
4759fn default_lease_count() -> usize {
4760 50
4761}
4762
4763fn default_finance_lease_pct() -> f64 {
4764 0.30
4765}
4766
4767fn default_avg_lease_term() -> u32 {
4768 60
4769}
4770
4771fn default_real_estate_pct() -> f64 {
4772 0.40
4773}
4774
4775impl Default for LeaseAccountingConfig {
4776 fn default() -> Self {
4777 Self {
4778 enabled: false,
4779 lease_count: default_lease_count(),
4780 finance_lease_percent: default_finance_lease_pct(),
4781 avg_lease_term_months: default_avg_lease_term(),
4782 generate_amortization: true,
4783 real_estate_percent: default_real_estate_pct(),
4784 }
4785 }
4786}
4787
4788#[derive(Debug, Clone, Serialize, Deserialize)]
4790pub struct FairValueConfig {
4791 #[serde(default)]
4793 pub enabled: bool,
4794
4795 #[serde(default = "default_fv_count")]
4797 pub measurement_count: usize,
4798
4799 #[serde(default = "default_level1_pct")]
4801 pub level1_percent: f64,
4802
4803 #[serde(default = "default_level2_pct")]
4805 pub level2_percent: f64,
4806
4807 #[serde(default = "default_level3_pct")]
4809 pub level3_percent: f64,
4810
4811 #[serde(default)]
4813 pub include_sensitivity_analysis: bool,
4814}
4815
4816fn default_fv_count() -> usize {
4817 25
4818}
4819
4820fn default_level1_pct() -> f64 {
4821 0.40
4822}
4823
4824fn default_level2_pct() -> f64 {
4825 0.35
4826}
4827
4828fn default_level3_pct() -> f64 {
4829 0.25
4830}
4831
4832impl Default for FairValueConfig {
4833 fn default() -> Self {
4834 Self {
4835 enabled: false,
4836 measurement_count: default_fv_count(),
4837 level1_percent: default_level1_pct(),
4838 level2_percent: default_level2_pct(),
4839 level3_percent: default_level3_pct(),
4840 include_sensitivity_analysis: false,
4841 }
4842 }
4843}
4844
4845#[derive(Debug, Clone, Serialize, Deserialize)]
4847pub struct ImpairmentConfig {
4848 #[serde(default)]
4850 pub enabled: bool,
4851
4852 #[serde(default = "default_impairment_count")]
4854 pub test_count: usize,
4855
4856 #[serde(default = "default_impairment_rate")]
4858 pub impairment_rate: f64,
4859
4860 #[serde(default = "default_true")]
4862 pub generate_projections: bool,
4863
4864 #[serde(default)]
4866 pub include_goodwill: bool,
4867}
4868
4869fn default_impairment_count() -> usize {
4870 15
4871}
4872
4873fn default_impairment_rate() -> f64 {
4874 0.10
4875}
4876
4877impl Default for ImpairmentConfig {
4878 fn default() -> Self {
4879 Self {
4880 enabled: false,
4881 test_count: default_impairment_count(),
4882 impairment_rate: default_impairment_rate(),
4883 generate_projections: true,
4884 include_goodwill: false,
4885 }
4886 }
4887}
4888
4889#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4902pub struct AuditStandardsConfig {
4903 #[serde(default)]
4905 pub enabled: bool,
4906
4907 #[serde(default)]
4909 pub isa_compliance: IsaComplianceConfig,
4910
4911 #[serde(default)]
4913 pub analytical_procedures: AnalyticalProceduresConfig,
4914
4915 #[serde(default)]
4917 pub confirmations: ConfirmationsConfig,
4918
4919 #[serde(default)]
4921 pub opinion: AuditOpinionConfig,
4922
4923 #[serde(default)]
4925 pub generate_audit_trail: bool,
4926
4927 #[serde(default)]
4929 pub sox: SoxComplianceConfig,
4930
4931 #[serde(default)]
4933 pub pcaob: PcaobConfig,
4934}
4935
4936#[derive(Debug, Clone, Serialize, Deserialize)]
4938pub struct IsaComplianceConfig {
4939 #[serde(default)]
4941 pub enabled: bool,
4942
4943 #[serde(default = "default_compliance_level")]
4945 pub compliance_level: String,
4946
4947 #[serde(default = "default_true")]
4949 pub generate_isa_mappings: bool,
4950
4951 #[serde(default = "default_true")]
4953 pub generate_coverage_summary: bool,
4954
4955 #[serde(default)]
4957 pub include_pcaob: bool,
4958
4959 #[serde(default = "default_audit_framework")]
4961 pub framework: String,
4962}
4963
4964fn default_compliance_level() -> String {
4965 "standard".to_string()
4966}
4967
4968fn default_audit_framework() -> String {
4969 "isa".to_string()
4970}
4971
4972impl Default for IsaComplianceConfig {
4973 fn default() -> Self {
4974 Self {
4975 enabled: false,
4976 compliance_level: default_compliance_level(),
4977 generate_isa_mappings: true,
4978 generate_coverage_summary: true,
4979 include_pcaob: false,
4980 framework: default_audit_framework(),
4981 }
4982 }
4983}
4984
4985#[derive(Debug, Clone, Serialize, Deserialize)]
4987pub struct AnalyticalProceduresConfig {
4988 #[serde(default)]
4990 pub enabled: bool,
4991
4992 #[serde(default = "default_procedures_per_account")]
4994 pub procedures_per_account: usize,
4995
4996 #[serde(default = "default_variance_probability")]
4998 pub variance_probability: f64,
4999
5000 #[serde(default = "default_true")]
5002 pub generate_investigations: bool,
5003
5004 #[serde(default = "default_true")]
5006 pub include_ratio_analysis: bool,
5007}
5008
5009fn default_procedures_per_account() -> usize {
5010 3
5011}
5012
5013fn default_variance_probability() -> f64 {
5014 0.20
5015}
5016
5017impl Default for AnalyticalProceduresConfig {
5018 fn default() -> Self {
5019 Self {
5020 enabled: false,
5021 procedures_per_account: default_procedures_per_account(),
5022 variance_probability: default_variance_probability(),
5023 generate_investigations: true,
5024 include_ratio_analysis: true,
5025 }
5026 }
5027}
5028
5029#[derive(Debug, Clone, Serialize, Deserialize)]
5031pub struct ConfirmationsConfig {
5032 #[serde(default)]
5034 pub enabled: bool,
5035
5036 #[serde(default = "default_confirmation_count")]
5038 pub confirmation_count: usize,
5039
5040 #[serde(default = "default_positive_response_rate")]
5042 pub positive_response_rate: f64,
5043
5044 #[serde(default = "default_exception_rate_confirm")]
5046 pub exception_rate: f64,
5047
5048 #[serde(default = "default_non_response_rate")]
5050 pub non_response_rate: f64,
5051
5052 #[serde(default = "default_true")]
5054 pub generate_alternative_procedures: bool,
5055}
5056
5057fn default_confirmation_count() -> usize {
5058 50
5059}
5060
5061fn default_positive_response_rate() -> f64 {
5062 0.85
5063}
5064
5065fn default_exception_rate_confirm() -> f64 {
5066 0.10
5067}
5068
5069fn default_non_response_rate() -> f64 {
5070 0.05
5071}
5072
5073impl Default for ConfirmationsConfig {
5074 fn default() -> Self {
5075 Self {
5076 enabled: false,
5077 confirmation_count: default_confirmation_count(),
5078 positive_response_rate: default_positive_response_rate(),
5079 exception_rate: default_exception_rate_confirm(),
5080 non_response_rate: default_non_response_rate(),
5081 generate_alternative_procedures: true,
5082 }
5083 }
5084}
5085
5086#[derive(Debug, Clone, Serialize, Deserialize)]
5088pub struct AuditOpinionConfig {
5089 #[serde(default)]
5091 pub enabled: bool,
5092
5093 #[serde(default = "default_true")]
5095 pub generate_kam: bool,
5096
5097 #[serde(default = "default_kam_count")]
5099 pub average_kam_count: usize,
5100
5101 #[serde(default = "default_modified_opinion_rate")]
5103 pub modified_opinion_rate: f64,
5104
5105 #[serde(default)]
5107 pub include_emphasis_of_matter: bool,
5108
5109 #[serde(default = "default_true")]
5111 pub include_going_concern: bool,
5112}
5113
5114fn default_kam_count() -> usize {
5115 3
5116}
5117
5118fn default_modified_opinion_rate() -> f64 {
5119 0.05
5120}
5121
5122impl Default for AuditOpinionConfig {
5123 fn default() -> Self {
5124 Self {
5125 enabled: false,
5126 generate_kam: true,
5127 average_kam_count: default_kam_count(),
5128 modified_opinion_rate: default_modified_opinion_rate(),
5129 include_emphasis_of_matter: false,
5130 include_going_concern: true,
5131 }
5132 }
5133}
5134
5135#[derive(Debug, Clone, Serialize, Deserialize)]
5137pub struct SoxComplianceConfig {
5138 #[serde(default)]
5140 pub enabled: bool,
5141
5142 #[serde(default = "default_true")]
5144 pub generate_302_certifications: bool,
5145
5146 #[serde(default = "default_true")]
5148 pub generate_404_assessments: bool,
5149
5150 #[serde(default = "default_sox_materiality_threshold")]
5152 pub materiality_threshold: f64,
5153
5154 #[serde(default = "default_material_weakness_rate")]
5156 pub material_weakness_rate: f64,
5157
5158 #[serde(default = "default_significant_deficiency_rate")]
5160 pub significant_deficiency_rate: f64,
5161}
5162
5163fn default_material_weakness_rate() -> f64 {
5164 0.02
5165}
5166
5167fn default_significant_deficiency_rate() -> f64 {
5168 0.08
5169}
5170
5171impl Default for SoxComplianceConfig {
5172 fn default() -> Self {
5173 Self {
5174 enabled: false,
5175 generate_302_certifications: true,
5176 generate_404_assessments: true,
5177 materiality_threshold: default_sox_materiality_threshold(),
5178 material_weakness_rate: default_material_weakness_rate(),
5179 significant_deficiency_rate: default_significant_deficiency_rate(),
5180 }
5181 }
5182}
5183
5184#[derive(Debug, Clone, Serialize, Deserialize)]
5186pub struct PcaobConfig {
5187 #[serde(default)]
5189 pub enabled: bool,
5190
5191 #[serde(default)]
5193 pub is_pcaob_audit: bool,
5194
5195 #[serde(default = "default_true")]
5197 pub generate_cam: bool,
5198
5199 #[serde(default)]
5201 pub include_icfr_opinion: bool,
5202
5203 #[serde(default)]
5205 pub generate_standard_mappings: bool,
5206}
5207
5208impl Default for PcaobConfig {
5209 fn default() -> Self {
5210 Self {
5211 enabled: false,
5212 is_pcaob_audit: false,
5213 generate_cam: true,
5214 include_icfr_opinion: false,
5215 generate_standard_mappings: false,
5216 }
5217 }
5218}
5219
5220#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5233pub struct AdvancedDistributionConfig {
5234 #[serde(default)]
5236 pub enabled: bool,
5237
5238 #[serde(default)]
5240 pub amounts: MixtureDistributionSchemaConfig,
5241
5242 #[serde(default)]
5244 pub correlations: CorrelationSchemaConfig,
5245
5246 #[serde(default)]
5248 pub conditional: Vec<ConditionalDistributionSchemaConfig>,
5249
5250 #[serde(default)]
5252 pub regime_changes: RegimeChangeSchemaConfig,
5253
5254 #[serde(default)]
5256 pub industry_profile: Option<IndustryProfileType>,
5257
5258 #[serde(default)]
5260 pub validation: StatisticalValidationSchemaConfig,
5261}
5262
5263#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
5265#[serde(rename_all = "snake_case")]
5266pub enum IndustryProfileType {
5267 Retail,
5269 Manufacturing,
5271 FinancialServices,
5273 Healthcare,
5275 Technology,
5277}
5278
5279#[derive(Debug, Clone, Serialize, Deserialize)]
5281pub struct MixtureDistributionSchemaConfig {
5282 #[serde(default)]
5284 pub enabled: bool,
5285
5286 #[serde(default = "default_mixture_type")]
5288 pub distribution_type: MixtureDistributionType,
5289
5290 #[serde(default)]
5292 pub components: Vec<MixtureComponentConfig>,
5293
5294 #[serde(default = "default_min_amount")]
5296 pub min_value: f64,
5297
5298 #[serde(default)]
5300 pub max_value: Option<f64>,
5301
5302 #[serde(default = "default_decimal_places")]
5304 pub decimal_places: u8,
5305}
5306
5307fn default_mixture_type() -> MixtureDistributionType {
5308 MixtureDistributionType::LogNormal
5309}
5310
5311fn default_min_amount() -> f64 {
5312 0.01
5313}
5314
5315fn default_decimal_places() -> u8 {
5316 2
5317}
5318
5319impl Default for MixtureDistributionSchemaConfig {
5320 fn default() -> Self {
5321 Self {
5322 enabled: false,
5323 distribution_type: MixtureDistributionType::LogNormal,
5324 components: Vec::new(),
5325 min_value: 0.01,
5326 max_value: None,
5327 decimal_places: 2,
5328 }
5329 }
5330}
5331
5332#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5334#[serde(rename_all = "snake_case")]
5335pub enum MixtureDistributionType {
5336 Gaussian,
5338 #[default]
5340 LogNormal,
5341}
5342
5343#[derive(Debug, Clone, Serialize, Deserialize)]
5345pub struct MixtureComponentConfig {
5346 pub weight: f64,
5348
5349 pub mu: f64,
5351
5352 pub sigma: f64,
5354
5355 #[serde(default)]
5357 pub label: Option<String>,
5358}
5359
5360#[derive(Debug, Clone, Serialize, Deserialize)]
5362pub struct CorrelationSchemaConfig {
5363 #[serde(default)]
5365 pub enabled: bool,
5366
5367 #[serde(default)]
5369 pub copula_type: CopulaSchemaType,
5370
5371 #[serde(default)]
5373 pub fields: Vec<CorrelatedFieldConfig>,
5374
5375 #[serde(default)]
5378 pub matrix: Vec<f64>,
5379
5380 #[serde(default)]
5382 pub expected_correlations: Vec<ExpectedCorrelationConfig>,
5383}
5384
5385impl Default for CorrelationSchemaConfig {
5386 fn default() -> Self {
5387 Self {
5388 enabled: false,
5389 copula_type: CopulaSchemaType::Gaussian,
5390 fields: Vec::new(),
5391 matrix: Vec::new(),
5392 expected_correlations: Vec::new(),
5393 }
5394 }
5395}
5396
5397#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5399#[serde(rename_all = "snake_case")]
5400pub enum CopulaSchemaType {
5401 #[default]
5403 Gaussian,
5404 Clayton,
5406 Gumbel,
5408 Frank,
5410 StudentT,
5412}
5413
5414#[derive(Debug, Clone, Serialize, Deserialize)]
5416pub struct CorrelatedFieldConfig {
5417 pub name: String,
5419
5420 #[serde(default)]
5422 pub distribution: MarginalDistributionConfig,
5423}
5424
5425#[derive(Debug, Clone, Serialize, Deserialize)]
5427#[serde(tag = "type", rename_all = "snake_case")]
5428pub enum MarginalDistributionConfig {
5429 Normal {
5431 mu: f64,
5433 sigma: f64,
5435 },
5436 LogNormal {
5438 mu: f64,
5440 sigma: f64,
5442 },
5443 Uniform {
5445 min: f64,
5447 max: f64,
5449 },
5450 DiscreteUniform {
5452 min: i32,
5454 max: i32,
5456 },
5457}
5458
5459impl Default for MarginalDistributionConfig {
5460 fn default() -> Self {
5461 Self::Normal {
5462 mu: 0.0,
5463 sigma: 1.0,
5464 }
5465 }
5466}
5467
5468#[derive(Debug, Clone, Serialize, Deserialize)]
5470pub struct ExpectedCorrelationConfig {
5471 pub field1: String,
5473 pub field2: String,
5475 pub expected_r: f64,
5477 #[serde(default = "default_correlation_tolerance")]
5479 pub tolerance: f64,
5480}
5481
5482fn default_correlation_tolerance() -> f64 {
5483 0.10
5484}
5485
5486#[derive(Debug, Clone, Serialize, Deserialize)]
5488pub struct ConditionalDistributionSchemaConfig {
5489 pub output_field: String,
5491
5492 pub input_field: String,
5494
5495 #[serde(default)]
5497 pub breakpoints: Vec<ConditionalBreakpointConfig>,
5498
5499 #[serde(default)]
5501 pub default_distribution: ConditionalDistributionParamsConfig,
5502
5503 #[serde(default)]
5505 pub min_value: Option<f64>,
5506
5507 #[serde(default)]
5509 pub max_value: Option<f64>,
5510
5511 #[serde(default = "default_decimal_places")]
5513 pub decimal_places: u8,
5514}
5515
5516#[derive(Debug, Clone, Serialize, Deserialize)]
5518pub struct ConditionalBreakpointConfig {
5519 pub threshold: f64,
5521
5522 pub distribution: ConditionalDistributionParamsConfig,
5524}
5525
5526#[derive(Debug, Clone, Serialize, Deserialize)]
5528#[serde(tag = "type", rename_all = "snake_case")]
5529pub enum ConditionalDistributionParamsConfig {
5530 Fixed {
5532 value: f64,
5534 },
5535 Normal {
5537 mu: f64,
5539 sigma: f64,
5541 },
5542 LogNormal {
5544 mu: f64,
5546 sigma: f64,
5548 },
5549 Uniform {
5551 min: f64,
5553 max: f64,
5555 },
5556 Beta {
5558 alpha: f64,
5560 beta: f64,
5562 min: f64,
5564 max: f64,
5566 },
5567 Discrete {
5569 values: Vec<f64>,
5571 weights: Vec<f64>,
5573 },
5574}
5575
5576impl Default for ConditionalDistributionParamsConfig {
5577 fn default() -> Self {
5578 Self::Normal {
5579 mu: 0.0,
5580 sigma: 1.0,
5581 }
5582 }
5583}
5584
5585#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5587pub struct RegimeChangeSchemaConfig {
5588 #[serde(default)]
5590 pub enabled: bool,
5591
5592 #[serde(default)]
5594 pub changes: Vec<RegimeChangeEventConfig>,
5595
5596 #[serde(default)]
5598 pub economic_cycle: Option<EconomicCycleSchemaConfig>,
5599
5600 #[serde(default)]
5602 pub parameter_drifts: Vec<ParameterDriftSchemaConfig>,
5603}
5604
5605#[derive(Debug, Clone, Serialize, Deserialize)]
5607pub struct RegimeChangeEventConfig {
5608 pub date: String,
5610
5611 pub change_type: RegimeChangeTypeConfig,
5613
5614 #[serde(default)]
5616 pub description: Option<String>,
5617
5618 #[serde(default)]
5620 pub effects: Vec<RegimeEffectConfig>,
5621}
5622
5623#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
5625#[serde(rename_all = "snake_case")]
5626pub enum RegimeChangeTypeConfig {
5627 Acquisition,
5629 Divestiture,
5631 PriceIncrease,
5633 PriceDecrease,
5635 ProductLaunch,
5637 ProductDiscontinuation,
5639 PolicyChange,
5641 CompetitorEntry,
5643 Custom,
5645}
5646
5647#[derive(Debug, Clone, Serialize, Deserialize)]
5649pub struct RegimeEffectConfig {
5650 pub field: String,
5652
5653 pub multiplier: f64,
5655}
5656
5657#[derive(Debug, Clone, Serialize, Deserialize)]
5659pub struct EconomicCycleSchemaConfig {
5660 #[serde(default)]
5662 pub enabled: bool,
5663
5664 #[serde(default = "default_cycle_period")]
5666 pub period_months: u32,
5667
5668 #[serde(default = "default_cycle_amplitude")]
5670 pub amplitude: f64,
5671
5672 #[serde(default)]
5674 pub phase_offset: u32,
5675
5676 #[serde(default)]
5678 pub recessions: Vec<RecessionPeriodConfig>,
5679}
5680
5681fn default_cycle_period() -> u32 {
5682 48
5683}
5684
5685fn default_cycle_amplitude() -> f64 {
5686 0.15
5687}
5688
5689impl Default for EconomicCycleSchemaConfig {
5690 fn default() -> Self {
5691 Self {
5692 enabled: false,
5693 period_months: 48,
5694 amplitude: 0.15,
5695 phase_offset: 0,
5696 recessions: Vec::new(),
5697 }
5698 }
5699}
5700
5701#[derive(Debug, Clone, Serialize, Deserialize)]
5703pub struct RecessionPeriodConfig {
5704 pub start_month: u32,
5706
5707 pub duration_months: u32,
5709
5710 #[serde(default = "default_recession_severity")]
5712 pub severity: f64,
5713}
5714
5715fn default_recession_severity() -> f64 {
5716 0.20
5717}
5718
5719#[derive(Debug, Clone, Serialize, Deserialize)]
5721pub struct ParameterDriftSchemaConfig {
5722 pub parameter: String,
5724
5725 pub drift_type: ParameterDriftTypeConfig,
5727
5728 pub start_value: f64,
5730
5731 pub end_value: f64,
5733
5734 #[serde(default)]
5736 pub start_period: u32,
5737
5738 #[serde(default)]
5740 pub end_period: Option<u32>,
5741}
5742
5743#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5745#[serde(rename_all = "snake_case")]
5746pub enum ParameterDriftTypeConfig {
5747 #[default]
5749 Linear,
5750 Exponential,
5752 Logistic,
5754 Step,
5756}
5757
5758#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5760pub struct StatisticalValidationSchemaConfig {
5761 #[serde(default)]
5763 pub enabled: bool,
5764
5765 #[serde(default)]
5767 pub tests: Vec<StatisticalTestConfig>,
5768
5769 #[serde(default)]
5771 pub reporting: ValidationReportingConfig,
5772}
5773
5774#[derive(Debug, Clone, Serialize, Deserialize)]
5776#[serde(tag = "type", rename_all = "snake_case")]
5777pub enum StatisticalTestConfig {
5778 BenfordFirstDigit {
5780 #[serde(default = "default_benford_threshold")]
5782 threshold_mad: f64,
5783 #[serde(default = "default_benford_warning")]
5785 warning_mad: f64,
5786 },
5787 DistributionFit {
5789 target: TargetDistributionConfig,
5791 #[serde(default = "default_ks_significance")]
5793 ks_significance: f64,
5794 #[serde(default)]
5796 method: DistributionFitMethod,
5797 },
5798 CorrelationCheck {
5800 expected_correlations: Vec<ExpectedCorrelationConfig>,
5802 },
5803 ChiSquared {
5805 #[serde(default = "default_chi_squared_bins")]
5807 bins: usize,
5808 #[serde(default = "default_chi_squared_significance")]
5810 significance: f64,
5811 },
5812 AndersonDarling {
5814 target: TargetDistributionConfig,
5816 #[serde(default = "default_ad_significance")]
5818 significance: f64,
5819 },
5820}
5821
5822fn default_benford_threshold() -> f64 {
5823 0.015
5824}
5825
5826fn default_benford_warning() -> f64 {
5827 0.010
5828}
5829
5830fn default_ks_significance() -> f64 {
5831 0.05
5832}
5833
5834fn default_chi_squared_bins() -> usize {
5835 10
5836}
5837
5838fn default_chi_squared_significance() -> f64 {
5839 0.05
5840}
5841
5842fn default_ad_significance() -> f64 {
5843 0.05
5844}
5845
5846#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5848#[serde(rename_all = "snake_case")]
5849pub enum TargetDistributionConfig {
5850 Normal,
5852 #[default]
5854 LogNormal,
5855 Exponential,
5857 Uniform,
5859}
5860
5861#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5863#[serde(rename_all = "snake_case")]
5864pub enum DistributionFitMethod {
5865 #[default]
5867 KolmogorovSmirnov,
5868 AndersonDarling,
5870 ChiSquared,
5872}
5873
5874#[derive(Debug, Clone, Serialize, Deserialize)]
5876pub struct ValidationReportingConfig {
5877 #[serde(default)]
5879 pub output_report: bool,
5880
5881 #[serde(default)]
5883 pub format: ValidationReportFormat,
5884
5885 #[serde(default)]
5887 pub fail_on_error: bool,
5888
5889 #[serde(default = "default_true")]
5891 pub include_details: bool,
5892}
5893
5894impl Default for ValidationReportingConfig {
5895 fn default() -> Self {
5896 Self {
5897 output_report: false,
5898 format: ValidationReportFormat::Json,
5899 fail_on_error: false,
5900 include_details: true,
5901 }
5902 }
5903}
5904
5905#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5907#[serde(rename_all = "snake_case")]
5908pub enum ValidationReportFormat {
5909 #[default]
5911 Json,
5912 Yaml,
5914 Html,
5916}
5917
5918#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5930pub struct TemporalPatternsConfig {
5931 #[serde(default)]
5933 pub enabled: bool,
5934
5935 #[serde(default)]
5937 pub business_days: BusinessDaySchemaConfig,
5938
5939 #[serde(default)]
5941 pub calendars: CalendarSchemaConfig,
5942
5943 #[serde(default)]
5945 pub period_end: PeriodEndSchemaConfig,
5946
5947 #[serde(default)]
5949 pub processing_lags: ProcessingLagSchemaConfig,
5950
5951 #[serde(default)]
5953 pub fiscal_calendar: FiscalCalendarSchemaConfig,
5954
5955 #[serde(default)]
5957 pub intraday: IntraDaySchemaConfig,
5958
5959 #[serde(default)]
5961 pub timezones: TimezoneSchemaConfig,
5962}
5963
5964#[derive(Debug, Clone, Serialize, Deserialize)]
5966pub struct BusinessDaySchemaConfig {
5967 #[serde(default = "default_true")]
5969 pub enabled: bool,
5970
5971 #[serde(default = "default_half_day_policy")]
5973 pub half_day_policy: String,
5974
5975 #[serde(default)]
5977 pub settlement_rules: SettlementRulesSchemaConfig,
5978
5979 #[serde(default = "default_month_end_convention")]
5981 pub month_end_convention: String,
5982
5983 #[serde(default)]
5985 pub weekend_days: Option<Vec<String>>,
5986}
5987
5988fn default_half_day_policy() -> String {
5989 "half_day".to_string()
5990}
5991
5992fn default_month_end_convention() -> String {
5993 "modified_following".to_string()
5994}
5995
5996impl Default for BusinessDaySchemaConfig {
5997 fn default() -> Self {
5998 Self {
5999 enabled: true,
6000 half_day_policy: "half_day".to_string(),
6001 settlement_rules: SettlementRulesSchemaConfig::default(),
6002 month_end_convention: "modified_following".to_string(),
6003 weekend_days: None,
6004 }
6005 }
6006}
6007
6008#[derive(Debug, Clone, Serialize, Deserialize)]
6010pub struct SettlementRulesSchemaConfig {
6011 #[serde(default = "default_settlement_2")]
6013 pub equity_days: i32,
6014
6015 #[serde(default = "default_settlement_1")]
6017 pub government_bonds_days: i32,
6018
6019 #[serde(default = "default_settlement_2")]
6021 pub fx_spot_days: i32,
6022
6023 #[serde(default = "default_settlement_2")]
6025 pub corporate_bonds_days: i32,
6026
6027 #[serde(default = "default_wire_cutoff")]
6029 pub wire_cutoff_time: String,
6030
6031 #[serde(default = "default_settlement_1")]
6033 pub wire_international_days: i32,
6034
6035 #[serde(default = "default_settlement_1")]
6037 pub ach_days: i32,
6038}
6039
6040fn default_settlement_1() -> i32 {
6041 1
6042}
6043
6044fn default_settlement_2() -> i32 {
6045 2
6046}
6047
6048fn default_wire_cutoff() -> String {
6049 "14:00".to_string()
6050}
6051
6052impl Default for SettlementRulesSchemaConfig {
6053 fn default() -> Self {
6054 Self {
6055 equity_days: 2,
6056 government_bonds_days: 1,
6057 fx_spot_days: 2,
6058 corporate_bonds_days: 2,
6059 wire_cutoff_time: "14:00".to_string(),
6060 wire_international_days: 1,
6061 ach_days: 1,
6062 }
6063 }
6064}
6065
6066#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6068pub struct CalendarSchemaConfig {
6069 #[serde(default)]
6071 pub regions: Vec<String>,
6072
6073 #[serde(default)]
6075 pub custom_holidays: Vec<CustomHolidaySchemaConfig>,
6076}
6077
6078#[derive(Debug, Clone, Serialize, Deserialize)]
6080pub struct CustomHolidaySchemaConfig {
6081 pub name: String,
6083 pub month: u8,
6085 pub day: u8,
6087 #[serde(default = "default_holiday_multiplier")]
6089 pub activity_multiplier: f64,
6090}
6091
6092fn default_holiday_multiplier() -> f64 {
6093 0.05
6094}
6095
6096#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6098pub struct PeriodEndSchemaConfig {
6099 #[serde(default)]
6101 pub model: Option<String>,
6102
6103 #[serde(default)]
6105 pub month_end: Option<PeriodEndModelSchemaConfig>,
6106
6107 #[serde(default)]
6109 pub quarter_end: Option<PeriodEndModelSchemaConfig>,
6110
6111 #[serde(default)]
6113 pub year_end: Option<PeriodEndModelSchemaConfig>,
6114}
6115
6116#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6118pub struct PeriodEndModelSchemaConfig {
6119 #[serde(default)]
6121 pub inherit_from: Option<String>,
6122
6123 #[serde(default)]
6125 pub additional_multiplier: Option<f64>,
6126
6127 #[serde(default)]
6129 pub start_day: Option<i32>,
6130
6131 #[serde(default)]
6133 pub base_multiplier: Option<f64>,
6134
6135 #[serde(default)]
6137 pub peak_multiplier: Option<f64>,
6138
6139 #[serde(default)]
6141 pub decay_rate: Option<f64>,
6142
6143 #[serde(default)]
6145 pub sustained_high_days: Option<i32>,
6146}
6147
6148#[derive(Debug, Clone, Serialize, Deserialize)]
6150pub struct ProcessingLagSchemaConfig {
6151 #[serde(default = "default_true")]
6153 pub enabled: bool,
6154
6155 #[serde(default)]
6157 pub sales_order_lag: Option<LagDistributionSchemaConfig>,
6158
6159 #[serde(default)]
6161 pub purchase_order_lag: Option<LagDistributionSchemaConfig>,
6162
6163 #[serde(default)]
6165 pub goods_receipt_lag: Option<LagDistributionSchemaConfig>,
6166
6167 #[serde(default)]
6169 pub invoice_receipt_lag: Option<LagDistributionSchemaConfig>,
6170
6171 #[serde(default)]
6173 pub invoice_issue_lag: Option<LagDistributionSchemaConfig>,
6174
6175 #[serde(default)]
6177 pub payment_lag: Option<LagDistributionSchemaConfig>,
6178
6179 #[serde(default)]
6181 pub journal_entry_lag: Option<LagDistributionSchemaConfig>,
6182
6183 #[serde(default)]
6185 pub cross_day_posting: Option<CrossDayPostingSchemaConfig>,
6186}
6187
6188impl Default for ProcessingLagSchemaConfig {
6189 fn default() -> Self {
6190 Self {
6191 enabled: true,
6192 sales_order_lag: None,
6193 purchase_order_lag: None,
6194 goods_receipt_lag: None,
6195 invoice_receipt_lag: None,
6196 invoice_issue_lag: None,
6197 payment_lag: None,
6198 journal_entry_lag: None,
6199 cross_day_posting: None,
6200 }
6201 }
6202}
6203
6204#[derive(Debug, Clone, Serialize, Deserialize)]
6206pub struct LagDistributionSchemaConfig {
6207 pub mu: f64,
6209 pub sigma: f64,
6211 #[serde(default)]
6213 pub min_hours: Option<f64>,
6214 #[serde(default)]
6216 pub max_hours: Option<f64>,
6217}
6218
6219#[derive(Debug, Clone, Serialize, Deserialize)]
6221pub struct CrossDayPostingSchemaConfig {
6222 #[serde(default = "default_true")]
6224 pub enabled: bool,
6225
6226 #[serde(default)]
6229 pub probability_by_hour: std::collections::HashMap<u8, f64>,
6230}
6231
6232impl Default for CrossDayPostingSchemaConfig {
6233 fn default() -> Self {
6234 let mut probability_by_hour = std::collections::HashMap::new();
6235 probability_by_hour.insert(17, 0.3);
6236 probability_by_hour.insert(18, 0.6);
6237 probability_by_hour.insert(19, 0.8);
6238 probability_by_hour.insert(20, 0.9);
6239 probability_by_hour.insert(21, 0.95);
6240 probability_by_hour.insert(22, 0.99);
6241
6242 Self {
6243 enabled: true,
6244 probability_by_hour,
6245 }
6246 }
6247}
6248
6249#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6258pub struct FiscalCalendarSchemaConfig {
6259 #[serde(default)]
6261 pub enabled: bool,
6262
6263 #[serde(default = "default_fiscal_calendar_type")]
6265 pub calendar_type: String,
6266
6267 #[serde(default)]
6269 pub year_start_month: Option<u8>,
6270
6271 #[serde(default)]
6273 pub year_start_day: Option<u8>,
6274
6275 #[serde(default)]
6277 pub four_four_five: Option<FourFourFiveSchemaConfig>,
6278}
6279
6280fn default_fiscal_calendar_type() -> String {
6281 "calendar_year".to_string()
6282}
6283
6284#[derive(Debug, Clone, Serialize, Deserialize)]
6286pub struct FourFourFiveSchemaConfig {
6287 #[serde(default = "default_week_pattern")]
6289 pub pattern: String,
6290
6291 #[serde(default = "default_anchor_type")]
6293 pub anchor_type: String,
6294
6295 #[serde(default = "default_anchor_month")]
6297 pub anchor_month: u8,
6298
6299 #[serde(default = "default_leap_week_placement")]
6301 pub leap_week_placement: String,
6302}
6303
6304fn default_week_pattern() -> String {
6305 "four_four_five".to_string()
6306}
6307
6308fn default_anchor_type() -> String {
6309 "last_saturday".to_string()
6310}
6311
6312fn default_anchor_month() -> u8 {
6313 1 }
6315
6316fn default_leap_week_placement() -> String {
6317 "q4_period3".to_string()
6318}
6319
6320impl Default for FourFourFiveSchemaConfig {
6321 fn default() -> Self {
6322 Self {
6323 pattern: "four_four_five".to_string(),
6324 anchor_type: "last_saturday".to_string(),
6325 anchor_month: 1,
6326 leap_week_placement: "q4_period3".to_string(),
6327 }
6328 }
6329}
6330
6331#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6340pub struct IntraDaySchemaConfig {
6341 #[serde(default)]
6343 pub enabled: bool,
6344
6345 #[serde(default)]
6347 pub segments: Vec<IntraDaySegmentSchemaConfig>,
6348}
6349
6350#[derive(Debug, Clone, Serialize, Deserialize)]
6352pub struct IntraDaySegmentSchemaConfig {
6353 pub name: String,
6355
6356 pub start: String,
6358
6359 pub end: String,
6361
6362 #[serde(default = "default_multiplier")]
6364 pub multiplier: f64,
6365
6366 #[serde(default = "default_posting_type")]
6368 pub posting_type: String,
6369}
6370
6371fn default_multiplier() -> f64 {
6372 1.0
6373}
6374
6375fn default_posting_type() -> String {
6376 "both".to_string()
6377}
6378
6379#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6385pub struct TimezoneSchemaConfig {
6386 #[serde(default)]
6388 pub enabled: bool,
6389
6390 #[serde(default = "default_timezone")]
6392 pub default_timezone: String,
6393
6394 #[serde(default = "default_consolidation_timezone")]
6396 pub consolidation_timezone: String,
6397
6398 #[serde(default)]
6401 pub entity_mappings: Vec<EntityTimezoneMapping>,
6402}
6403
6404fn default_timezone() -> String {
6405 "America/New_York".to_string()
6406}
6407
6408fn default_consolidation_timezone() -> String {
6409 "UTC".to_string()
6410}
6411
6412#[derive(Debug, Clone, Serialize, Deserialize)]
6414pub struct EntityTimezoneMapping {
6415 pub pattern: String,
6417
6418 pub timezone: String,
6420}
6421
6422#[derive(Debug, Clone, Serialize, Deserialize)]
6428pub struct VendorNetworkSchemaConfig {
6429 #[serde(default)]
6431 pub enabled: bool,
6432
6433 #[serde(default = "default_vendor_tier_depth")]
6435 pub depth: u8,
6436
6437 #[serde(default)]
6439 pub tier1: TierCountSchemaConfig,
6440
6441 #[serde(default)]
6443 pub tier2_per_parent: TierCountSchemaConfig,
6444
6445 #[serde(default)]
6447 pub tier3_per_parent: TierCountSchemaConfig,
6448
6449 #[serde(default)]
6451 pub clusters: VendorClusterSchemaConfig,
6452
6453 #[serde(default)]
6455 pub dependencies: DependencySchemaConfig,
6456}
6457
6458fn default_vendor_tier_depth() -> u8 {
6459 3
6460}
6461
6462impl Default for VendorNetworkSchemaConfig {
6463 fn default() -> Self {
6464 Self {
6465 enabled: false,
6466 depth: 3,
6467 tier1: TierCountSchemaConfig { min: 50, max: 100 },
6468 tier2_per_parent: TierCountSchemaConfig { min: 4, max: 10 },
6469 tier3_per_parent: TierCountSchemaConfig { min: 2, max: 5 },
6470 clusters: VendorClusterSchemaConfig::default(),
6471 dependencies: DependencySchemaConfig::default(),
6472 }
6473 }
6474}
6475
6476#[derive(Debug, Clone, Serialize, Deserialize)]
6478pub struct TierCountSchemaConfig {
6479 #[serde(default = "default_tier_min")]
6481 pub min: usize,
6482
6483 #[serde(default = "default_tier_max")]
6485 pub max: usize,
6486}
6487
6488fn default_tier_min() -> usize {
6489 5
6490}
6491
6492fn default_tier_max() -> usize {
6493 20
6494}
6495
6496impl Default for TierCountSchemaConfig {
6497 fn default() -> Self {
6498 Self {
6499 min: default_tier_min(),
6500 max: default_tier_max(),
6501 }
6502 }
6503}
6504
6505#[derive(Debug, Clone, Serialize, Deserialize)]
6507pub struct VendorClusterSchemaConfig {
6508 #[serde(default = "default_reliable_strategic")]
6510 pub reliable_strategic: f64,
6511
6512 #[serde(default = "default_standard_operational")]
6514 pub standard_operational: f64,
6515
6516 #[serde(default = "default_transactional")]
6518 pub transactional: f64,
6519
6520 #[serde(default = "default_problematic")]
6522 pub problematic: f64,
6523}
6524
6525fn default_reliable_strategic() -> f64 {
6526 0.20
6527}
6528
6529fn default_standard_operational() -> f64 {
6530 0.50
6531}
6532
6533fn default_transactional() -> f64 {
6534 0.25
6535}
6536
6537fn default_problematic() -> f64 {
6538 0.05
6539}
6540
6541impl Default for VendorClusterSchemaConfig {
6542 fn default() -> Self {
6543 Self {
6544 reliable_strategic: 0.20,
6545 standard_operational: 0.50,
6546 transactional: 0.25,
6547 problematic: 0.05,
6548 }
6549 }
6550}
6551
6552#[derive(Debug, Clone, Serialize, Deserialize)]
6554pub struct DependencySchemaConfig {
6555 #[serde(default = "default_max_single_vendor")]
6557 pub max_single_vendor_concentration: f64,
6558
6559 #[serde(default = "default_max_top5")]
6561 pub top_5_concentration: f64,
6562
6563 #[serde(default = "default_single_source_percent")]
6565 pub single_source_percent: f64,
6566}
6567
6568fn default_max_single_vendor() -> f64 {
6569 0.15
6570}
6571
6572fn default_max_top5() -> f64 {
6573 0.45
6574}
6575
6576fn default_single_source_percent() -> f64 {
6577 0.05
6578}
6579
6580impl Default for DependencySchemaConfig {
6581 fn default() -> Self {
6582 Self {
6583 max_single_vendor_concentration: 0.15,
6584 top_5_concentration: 0.45,
6585 single_source_percent: 0.05,
6586 }
6587 }
6588}
6589
6590#[derive(Debug, Clone, Default, Serialize, Deserialize)]
6596pub struct CustomerSegmentationSchemaConfig {
6597 #[serde(default)]
6599 pub enabled: bool,
6600
6601 #[serde(default)]
6603 pub value_segments: ValueSegmentsSchemaConfig,
6604
6605 #[serde(default)]
6607 pub lifecycle: LifecycleSchemaConfig,
6608
6609 #[serde(default)]
6611 pub networks: CustomerNetworksSchemaConfig,
6612}
6613
6614#[derive(Debug, Clone, Serialize, Deserialize)]
6616pub struct ValueSegmentsSchemaConfig {
6617 #[serde(default)]
6619 pub enterprise: SegmentDetailSchemaConfig,
6620
6621 #[serde(default)]
6623 pub mid_market: SegmentDetailSchemaConfig,
6624
6625 #[serde(default)]
6627 pub smb: SegmentDetailSchemaConfig,
6628
6629 #[serde(default)]
6631 pub consumer: SegmentDetailSchemaConfig,
6632}
6633
6634impl Default for ValueSegmentsSchemaConfig {
6635 fn default() -> Self {
6636 Self {
6637 enterprise: SegmentDetailSchemaConfig {
6638 revenue_share: 0.40,
6639 customer_share: 0.05,
6640 avg_order_value_range: "50000+".to_string(),
6641 },
6642 mid_market: SegmentDetailSchemaConfig {
6643 revenue_share: 0.35,
6644 customer_share: 0.20,
6645 avg_order_value_range: "5000-50000".to_string(),
6646 },
6647 smb: SegmentDetailSchemaConfig {
6648 revenue_share: 0.20,
6649 customer_share: 0.50,
6650 avg_order_value_range: "500-5000".to_string(),
6651 },
6652 consumer: SegmentDetailSchemaConfig {
6653 revenue_share: 0.05,
6654 customer_share: 0.25,
6655 avg_order_value_range: "50-500".to_string(),
6656 },
6657 }
6658 }
6659}
6660
6661#[derive(Debug, Clone, Serialize, Deserialize)]
6663pub struct SegmentDetailSchemaConfig {
6664 #[serde(default)]
6666 pub revenue_share: f64,
6667
6668 #[serde(default)]
6670 pub customer_share: f64,
6671
6672 #[serde(default)]
6674 pub avg_order_value_range: String,
6675}
6676
6677impl Default for SegmentDetailSchemaConfig {
6678 fn default() -> Self {
6679 Self {
6680 revenue_share: 0.25,
6681 customer_share: 0.25,
6682 avg_order_value_range: "1000-10000".to_string(),
6683 }
6684 }
6685}
6686
6687#[derive(Debug, Clone, Serialize, Deserialize)]
6689pub struct LifecycleSchemaConfig {
6690 #[serde(default)]
6692 pub prospect_rate: f64,
6693
6694 #[serde(default = "default_new_rate")]
6696 pub new_rate: f64,
6697
6698 #[serde(default = "default_growth_rate")]
6700 pub growth_rate: f64,
6701
6702 #[serde(default = "default_mature_rate")]
6704 pub mature_rate: f64,
6705
6706 #[serde(default = "default_at_risk_rate")]
6708 pub at_risk_rate: f64,
6709
6710 #[serde(default = "default_churned_rate")]
6712 pub churned_rate: f64,
6713}
6714
6715fn default_new_rate() -> f64 {
6716 0.10
6717}
6718
6719fn default_growth_rate() -> f64 {
6720 0.15
6721}
6722
6723fn default_mature_rate() -> f64 {
6724 0.60
6725}
6726
6727fn default_at_risk_rate() -> f64 {
6728 0.10
6729}
6730
6731fn default_churned_rate() -> f64 {
6732 0.05
6733}
6734
6735impl Default for LifecycleSchemaConfig {
6736 fn default() -> Self {
6737 Self {
6738 prospect_rate: 0.0,
6739 new_rate: 0.10,
6740 growth_rate: 0.15,
6741 mature_rate: 0.60,
6742 at_risk_rate: 0.10,
6743 churned_rate: 0.05,
6744 }
6745 }
6746}
6747
6748#[derive(Debug, Clone, Default, Serialize, Deserialize)]
6750pub struct CustomerNetworksSchemaConfig {
6751 #[serde(default)]
6753 pub referrals: ReferralSchemaConfig,
6754
6755 #[serde(default)]
6757 pub corporate_hierarchies: HierarchySchemaConfig,
6758}
6759
6760#[derive(Debug, Clone, Serialize, Deserialize)]
6762pub struct ReferralSchemaConfig {
6763 #[serde(default = "default_true")]
6765 pub enabled: bool,
6766
6767 #[serde(default = "default_referral_rate")]
6769 pub referral_rate: f64,
6770}
6771
6772fn default_referral_rate() -> f64 {
6773 0.15
6774}
6775
6776impl Default for ReferralSchemaConfig {
6777 fn default() -> Self {
6778 Self {
6779 enabled: true,
6780 referral_rate: 0.15,
6781 }
6782 }
6783}
6784
6785#[derive(Debug, Clone, Serialize, Deserialize)]
6787pub struct HierarchySchemaConfig {
6788 #[serde(default = "default_true")]
6790 pub enabled: bool,
6791
6792 #[serde(default = "default_hierarchy_rate")]
6794 pub probability: f64,
6795}
6796
6797fn default_hierarchy_rate() -> f64 {
6798 0.30
6799}
6800
6801impl Default for HierarchySchemaConfig {
6802 fn default() -> Self {
6803 Self {
6804 enabled: true,
6805 probability: 0.30,
6806 }
6807 }
6808}
6809
6810#[derive(Debug, Clone, Default, Serialize, Deserialize)]
6816pub struct RelationshipStrengthSchemaConfig {
6817 #[serde(default)]
6819 pub enabled: bool,
6820
6821 #[serde(default)]
6823 pub calculation: StrengthCalculationSchemaConfig,
6824
6825 #[serde(default)]
6827 pub thresholds: StrengthThresholdsSchemaConfig,
6828}
6829
6830#[derive(Debug, Clone, Serialize, Deserialize)]
6832pub struct StrengthCalculationSchemaConfig {
6833 #[serde(default = "default_volume_weight")]
6835 pub transaction_volume_weight: f64,
6836
6837 #[serde(default = "default_count_weight")]
6839 pub transaction_count_weight: f64,
6840
6841 #[serde(default = "default_duration_weight")]
6843 pub relationship_duration_weight: f64,
6844
6845 #[serde(default = "default_recency_weight")]
6847 pub recency_weight: f64,
6848
6849 #[serde(default = "default_mutual_weight")]
6851 pub mutual_connections_weight: f64,
6852
6853 #[serde(default = "default_recency_half_life")]
6855 pub recency_half_life_days: u32,
6856}
6857
6858fn default_volume_weight() -> f64 {
6859 0.30
6860}
6861
6862fn default_count_weight() -> f64 {
6863 0.25
6864}
6865
6866fn default_duration_weight() -> f64 {
6867 0.20
6868}
6869
6870fn default_recency_weight() -> f64 {
6871 0.15
6872}
6873
6874fn default_mutual_weight() -> f64 {
6875 0.10
6876}
6877
6878fn default_recency_half_life() -> u32 {
6879 90
6880}
6881
6882impl Default for StrengthCalculationSchemaConfig {
6883 fn default() -> Self {
6884 Self {
6885 transaction_volume_weight: 0.30,
6886 transaction_count_weight: 0.25,
6887 relationship_duration_weight: 0.20,
6888 recency_weight: 0.15,
6889 mutual_connections_weight: 0.10,
6890 recency_half_life_days: 90,
6891 }
6892 }
6893}
6894
6895#[derive(Debug, Clone, Serialize, Deserialize)]
6897pub struct StrengthThresholdsSchemaConfig {
6898 #[serde(default = "default_strong_threshold")]
6900 pub strong: f64,
6901
6902 #[serde(default = "default_moderate_threshold")]
6904 pub moderate: f64,
6905
6906 #[serde(default = "default_weak_threshold")]
6908 pub weak: f64,
6909}
6910
6911fn default_strong_threshold() -> f64 {
6912 0.7
6913}
6914
6915fn default_moderate_threshold() -> f64 {
6916 0.4
6917}
6918
6919fn default_weak_threshold() -> f64 {
6920 0.1
6921}
6922
6923impl Default for StrengthThresholdsSchemaConfig {
6924 fn default() -> Self {
6925 Self {
6926 strong: 0.7,
6927 moderate: 0.4,
6928 weak: 0.1,
6929 }
6930 }
6931}
6932
6933#[derive(Debug, Clone, Serialize, Deserialize)]
6939pub struct CrossProcessLinksSchemaConfig {
6940 #[serde(default)]
6942 pub enabled: bool,
6943
6944 #[serde(default = "default_true")]
6946 pub inventory_p2p_o2c: bool,
6947
6948 #[serde(default = "default_true")]
6950 pub payment_bank_reconciliation: bool,
6951
6952 #[serde(default = "default_true")]
6954 pub intercompany_bilateral: bool,
6955
6956 #[serde(default = "default_inventory_link_rate")]
6958 pub inventory_link_rate: f64,
6959}
6960
6961fn default_inventory_link_rate() -> f64 {
6962 0.30
6963}
6964
6965impl Default for CrossProcessLinksSchemaConfig {
6966 fn default() -> Self {
6967 Self {
6968 enabled: false,
6969 inventory_p2p_o2c: true,
6970 payment_bank_reconciliation: true,
6971 intercompany_bilateral: true,
6972 inventory_link_rate: 0.30,
6973 }
6974 }
6975}
6976
6977#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6983pub struct OrganizationalEventsSchemaConfig {
6984 #[serde(default)]
6986 pub enabled: bool,
6987
6988 #[serde(default)]
6990 pub effect_blending: EffectBlendingModeConfig,
6991
6992 #[serde(default)]
6994 pub events: Vec<OrganizationalEventSchemaConfig>,
6995
6996 #[serde(default)]
6998 pub process_evolution: Vec<ProcessEvolutionSchemaConfig>,
6999
7000 #[serde(default)]
7002 pub technology_transitions: Vec<TechnologyTransitionSchemaConfig>,
7003}
7004
7005#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
7007#[serde(rename_all = "snake_case")]
7008pub enum EffectBlendingModeConfig {
7009 #[default]
7011 Multiplicative,
7012 Additive,
7014 Maximum,
7016 Minimum,
7018}
7019
7020#[derive(Debug, Clone, Serialize, Deserialize)]
7022pub struct OrganizationalEventSchemaConfig {
7023 pub id: String,
7025
7026 pub event_type: OrganizationalEventTypeSchemaConfig,
7028
7029 pub effective_date: String,
7031
7032 #[serde(default = "default_org_transition_months")]
7034 pub transition_months: u32,
7035
7036 #[serde(default)]
7038 pub description: Option<String>,
7039}
7040
7041fn default_org_transition_months() -> u32 {
7042 6
7043}
7044
7045#[derive(Debug, Clone, Serialize, Deserialize)]
7047#[serde(tag = "type", rename_all = "snake_case")]
7048pub enum OrganizationalEventTypeSchemaConfig {
7049 Acquisition {
7051 acquired_entity: String,
7053 #[serde(default = "default_acquisition_volume")]
7055 volume_increase: f64,
7056 #[serde(default = "default_acquisition_error")]
7058 integration_error_rate: f64,
7059 #[serde(default = "default_parallel_days")]
7061 parallel_posting_days: u32,
7062 },
7063 Divestiture {
7065 divested_entity: String,
7067 #[serde(default = "default_divestiture_volume")]
7069 volume_reduction: f64,
7070 #[serde(default = "default_true_val")]
7072 remove_entity: bool,
7073 },
7074 Reorganization {
7076 #[serde(default)]
7078 cost_center_remapping: std::collections::HashMap<String, String>,
7079 #[serde(default = "default_reorg_error")]
7081 transition_error_rate: f64,
7082 },
7083 LeadershipChange {
7085 role: String,
7087 #[serde(default)]
7089 policy_changes: Vec<String>,
7090 },
7091 WorkforceReduction {
7093 #[serde(default = "default_workforce_reduction")]
7095 reduction_percent: f64,
7096 #[serde(default = "default_workforce_error")]
7098 error_rate_increase: f64,
7099 },
7100 Merger {
7102 merged_entity: String,
7104 #[serde(default = "default_merger_volume")]
7106 volume_increase: f64,
7107 },
7108}
7109
7110fn default_acquisition_volume() -> f64 {
7111 1.35
7112}
7113
7114fn default_acquisition_error() -> f64 {
7115 0.05
7116}
7117
7118fn default_parallel_days() -> u32 {
7119 30
7120}
7121
7122fn default_divestiture_volume() -> f64 {
7123 0.70
7124}
7125
7126fn default_true_val() -> bool {
7127 true
7128}
7129
7130fn default_reorg_error() -> f64 {
7131 0.04
7132}
7133
7134fn default_workforce_reduction() -> f64 {
7135 0.10
7136}
7137
7138fn default_workforce_error() -> f64 {
7139 0.05
7140}
7141
7142fn default_merger_volume() -> f64 {
7143 1.80
7144}
7145
7146#[derive(Debug, Clone, Serialize, Deserialize)]
7148pub struct ProcessEvolutionSchemaConfig {
7149 pub id: String,
7151
7152 pub event_type: ProcessEvolutionTypeSchemaConfig,
7154
7155 pub effective_date: String,
7157
7158 #[serde(default)]
7160 pub description: Option<String>,
7161}
7162
7163#[derive(Debug, Clone, Serialize, Deserialize)]
7165#[serde(tag = "type", rename_all = "snake_case")]
7166pub enum ProcessEvolutionTypeSchemaConfig {
7167 ProcessAutomation {
7169 process_name: String,
7171 #[serde(default = "default_manual_before")]
7173 manual_rate_before: f64,
7174 #[serde(default = "default_manual_after")]
7176 manual_rate_after: f64,
7177 },
7178 ApprovalWorkflowChange {
7180 description: String,
7182 },
7183 ControlEnhancement {
7185 control_id: String,
7187 #[serde(default = "default_error_reduction")]
7189 error_reduction: f64,
7190 },
7191}
7192
7193fn default_manual_before() -> f64 {
7194 0.80
7195}
7196
7197fn default_manual_after() -> f64 {
7198 0.15
7199}
7200
7201fn default_error_reduction() -> f64 {
7202 0.02
7203}
7204
7205#[derive(Debug, Clone, Serialize, Deserialize)]
7207pub struct TechnologyTransitionSchemaConfig {
7208 pub id: String,
7210
7211 pub event_type: TechnologyTransitionTypeSchemaConfig,
7213
7214 #[serde(default)]
7216 pub description: Option<String>,
7217}
7218
7219#[derive(Debug, Clone, Serialize, Deserialize)]
7221#[serde(tag = "type", rename_all = "snake_case")]
7222pub enum TechnologyTransitionTypeSchemaConfig {
7223 ErpMigration {
7225 source_system: String,
7227 target_system: String,
7229 cutover_date: String,
7231 stabilization_end: String,
7233 #[serde(default = "default_erp_duplicate_rate")]
7235 duplicate_rate: f64,
7236 #[serde(default = "default_format_mismatch")]
7238 format_mismatch_rate: f64,
7239 },
7240 ModuleImplementation {
7242 module_name: String,
7244 go_live_date: String,
7246 },
7247}
7248
7249fn default_erp_duplicate_rate() -> f64 {
7250 0.02
7251}
7252
7253fn default_format_mismatch() -> f64 {
7254 0.03
7255}
7256
7257#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7263pub struct BehavioralDriftSchemaConfig {
7264 #[serde(default)]
7266 pub enabled: bool,
7267
7268 #[serde(default)]
7270 pub vendor_behavior: VendorBehaviorSchemaConfig,
7271
7272 #[serde(default)]
7274 pub customer_behavior: CustomerBehaviorSchemaConfig,
7275
7276 #[serde(default)]
7278 pub employee_behavior: EmployeeBehaviorSchemaConfig,
7279
7280 #[serde(default)]
7282 pub collective: CollectiveBehaviorSchemaConfig,
7283}
7284
7285#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7287pub struct VendorBehaviorSchemaConfig {
7288 #[serde(default)]
7290 pub payment_terms_drift: PaymentTermsDriftSchemaConfig,
7291
7292 #[serde(default)]
7294 pub quality_drift: QualityDriftSchemaConfig,
7295}
7296
7297#[derive(Debug, Clone, Serialize, Deserialize)]
7299pub struct PaymentTermsDriftSchemaConfig {
7300 #[serde(default = "default_extension_rate")]
7302 pub extension_rate_per_year: f64,
7303
7304 #[serde(default = "default_economic_sensitivity")]
7306 pub economic_sensitivity: f64,
7307}
7308
7309fn default_extension_rate() -> f64 {
7310 2.5
7311}
7312
7313fn default_economic_sensitivity() -> f64 {
7314 1.0
7315}
7316
7317impl Default for PaymentTermsDriftSchemaConfig {
7318 fn default() -> Self {
7319 Self {
7320 extension_rate_per_year: 2.5,
7321 economic_sensitivity: 1.0,
7322 }
7323 }
7324}
7325
7326#[derive(Debug, Clone, Serialize, Deserialize)]
7328pub struct QualityDriftSchemaConfig {
7329 #[serde(default = "default_improvement_rate")]
7331 pub new_vendor_improvement_rate: f64,
7332
7333 #[serde(default = "default_decline_rate")]
7335 pub complacency_decline_rate: f64,
7336}
7337
7338fn default_improvement_rate() -> f64 {
7339 0.02
7340}
7341
7342fn default_decline_rate() -> f64 {
7343 0.01
7344}
7345
7346impl Default for QualityDriftSchemaConfig {
7347 fn default() -> Self {
7348 Self {
7349 new_vendor_improvement_rate: 0.02,
7350 complacency_decline_rate: 0.01,
7351 }
7352 }
7353}
7354
7355#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7357pub struct CustomerBehaviorSchemaConfig {
7358 #[serde(default)]
7360 pub payment_drift: CustomerPaymentDriftSchemaConfig,
7361
7362 #[serde(default)]
7364 pub order_drift: OrderDriftSchemaConfig,
7365}
7366
7367#[derive(Debug, Clone, Serialize, Deserialize)]
7369pub struct CustomerPaymentDriftSchemaConfig {
7370 #[serde(default = "default_downturn_extension")]
7372 pub downturn_days_extension: (u32, u32),
7373
7374 #[serde(default = "default_bad_debt_increase")]
7376 pub downturn_bad_debt_increase: f64,
7377}
7378
7379fn default_downturn_extension() -> (u32, u32) {
7380 (5, 15)
7381}
7382
7383fn default_bad_debt_increase() -> f64 {
7384 0.02
7385}
7386
7387impl Default for CustomerPaymentDriftSchemaConfig {
7388 fn default() -> Self {
7389 Self {
7390 downturn_days_extension: (5, 15),
7391 downturn_bad_debt_increase: 0.02,
7392 }
7393 }
7394}
7395
7396#[derive(Debug, Clone, Serialize, Deserialize)]
7398pub struct OrderDriftSchemaConfig {
7399 #[serde(default = "default_digital_shift")]
7401 pub digital_shift_rate: f64,
7402}
7403
7404fn default_digital_shift() -> f64 {
7405 0.05
7406}
7407
7408impl Default for OrderDriftSchemaConfig {
7409 fn default() -> Self {
7410 Self {
7411 digital_shift_rate: 0.05,
7412 }
7413 }
7414}
7415
7416#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7418pub struct EmployeeBehaviorSchemaConfig {
7419 #[serde(default)]
7421 pub approval_drift: ApprovalDriftSchemaConfig,
7422
7423 #[serde(default)]
7425 pub error_drift: ErrorDriftSchemaConfig,
7426}
7427
7428#[derive(Debug, Clone, Serialize, Deserialize)]
7430pub struct ApprovalDriftSchemaConfig {
7431 #[serde(default = "default_eom_intensity")]
7433 pub eom_intensity_increase_per_year: f64,
7434
7435 #[serde(default = "default_rubber_stamp")]
7437 pub rubber_stamp_volume_threshold: u32,
7438}
7439
7440fn default_eom_intensity() -> f64 {
7441 0.05
7442}
7443
7444fn default_rubber_stamp() -> u32 {
7445 50
7446}
7447
7448impl Default for ApprovalDriftSchemaConfig {
7449 fn default() -> Self {
7450 Self {
7451 eom_intensity_increase_per_year: 0.05,
7452 rubber_stamp_volume_threshold: 50,
7453 }
7454 }
7455}
7456
7457#[derive(Debug, Clone, Serialize, Deserialize)]
7459pub struct ErrorDriftSchemaConfig {
7460 #[serde(default = "default_new_error")]
7462 pub new_employee_error_rate: f64,
7463
7464 #[serde(default = "default_learning_months")]
7466 pub learning_curve_months: u32,
7467}
7468
7469fn default_new_error() -> f64 {
7470 0.08
7471}
7472
7473fn default_learning_months() -> u32 {
7474 6
7475}
7476
7477impl Default for ErrorDriftSchemaConfig {
7478 fn default() -> Self {
7479 Self {
7480 new_employee_error_rate: 0.08,
7481 learning_curve_months: 6,
7482 }
7483 }
7484}
7485
7486#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7488pub struct CollectiveBehaviorSchemaConfig {
7489 #[serde(default)]
7491 pub automation_adoption: AutomationAdoptionSchemaConfig,
7492}
7493
7494#[derive(Debug, Clone, Serialize, Deserialize)]
7496pub struct AutomationAdoptionSchemaConfig {
7497 #[serde(default)]
7499 pub s_curve_enabled: bool,
7500
7501 #[serde(default = "default_midpoint")]
7503 pub adoption_midpoint_months: u32,
7504
7505 #[serde(default = "default_steepness")]
7507 pub steepness: f64,
7508}
7509
7510fn default_midpoint() -> u32 {
7511 24
7512}
7513
7514fn default_steepness() -> f64 {
7515 0.15
7516}
7517
7518impl Default for AutomationAdoptionSchemaConfig {
7519 fn default() -> Self {
7520 Self {
7521 s_curve_enabled: false,
7522 adoption_midpoint_months: 24,
7523 steepness: 0.15,
7524 }
7525 }
7526}
7527
7528#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7534pub struct MarketDriftSchemaConfig {
7535 #[serde(default)]
7537 pub enabled: bool,
7538
7539 #[serde(default)]
7541 pub economic_cycle: MarketEconomicCycleSchemaConfig,
7542
7543 #[serde(default)]
7545 pub industry_cycles: std::collections::HashMap<String, IndustryCycleSchemaConfig>,
7546
7547 #[serde(default)]
7549 pub commodities: CommoditiesSchemaConfig,
7550}
7551
7552#[derive(Debug, Clone, Serialize, Deserialize)]
7554pub struct MarketEconomicCycleSchemaConfig {
7555 #[serde(default)]
7557 pub enabled: bool,
7558
7559 #[serde(default)]
7561 pub cycle_type: CycleTypeSchemaConfig,
7562
7563 #[serde(default = "default_market_cycle_period")]
7565 pub period_months: u32,
7566
7567 #[serde(default = "default_market_amplitude")]
7569 pub amplitude: f64,
7570
7571 #[serde(default)]
7573 pub recession: RecessionSchemaConfig,
7574}
7575
7576fn default_market_cycle_period() -> u32 {
7577 48
7578}
7579
7580fn default_market_amplitude() -> f64 {
7581 0.15
7582}
7583
7584impl Default for MarketEconomicCycleSchemaConfig {
7585 fn default() -> Self {
7586 Self {
7587 enabled: false,
7588 cycle_type: CycleTypeSchemaConfig::Sinusoidal,
7589 period_months: 48,
7590 amplitude: 0.15,
7591 recession: RecessionSchemaConfig::default(),
7592 }
7593 }
7594}
7595
7596#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
7598#[serde(rename_all = "snake_case")]
7599pub enum CycleTypeSchemaConfig {
7600 #[default]
7602 Sinusoidal,
7603 Asymmetric,
7605 MeanReverting,
7607}
7608
7609#[derive(Debug, Clone, Serialize, Deserialize)]
7611pub struct RecessionSchemaConfig {
7612 #[serde(default)]
7614 pub enabled: bool,
7615
7616 #[serde(default = "default_recession_prob")]
7618 pub probability_per_year: f64,
7619
7620 #[serde(default)]
7622 pub severity: RecessionSeveritySchemaConfig,
7623
7624 #[serde(default)]
7626 pub recession_periods: Vec<RecessionPeriodSchemaConfig>,
7627}
7628
7629fn default_recession_prob() -> f64 {
7630 0.10
7631}
7632
7633impl Default for RecessionSchemaConfig {
7634 fn default() -> Self {
7635 Self {
7636 enabled: false,
7637 probability_per_year: 0.10,
7638 severity: RecessionSeveritySchemaConfig::Moderate,
7639 recession_periods: Vec::new(),
7640 }
7641 }
7642}
7643
7644#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
7646#[serde(rename_all = "snake_case")]
7647pub enum RecessionSeveritySchemaConfig {
7648 Mild,
7650 #[default]
7652 Moderate,
7653 Severe,
7655}
7656
7657#[derive(Debug, Clone, Serialize, Deserialize)]
7659pub struct RecessionPeriodSchemaConfig {
7660 pub start_month: u32,
7662 pub duration_months: u32,
7664}
7665
7666#[derive(Debug, Clone, Serialize, Deserialize)]
7668pub struct IndustryCycleSchemaConfig {
7669 #[serde(default = "default_industry_period")]
7671 pub period_months: u32,
7672
7673 #[serde(default = "default_industry_amp")]
7675 pub amplitude: f64,
7676}
7677
7678fn default_industry_period() -> u32 {
7679 36
7680}
7681
7682fn default_industry_amp() -> f64 {
7683 0.20
7684}
7685
7686#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7688pub struct CommoditiesSchemaConfig {
7689 #[serde(default)]
7691 pub enabled: bool,
7692
7693 #[serde(default)]
7695 pub items: Vec<CommodityItemSchemaConfig>,
7696}
7697
7698#[derive(Debug, Clone, Serialize, Deserialize)]
7700pub struct CommodityItemSchemaConfig {
7701 pub name: String,
7703
7704 #[serde(default = "default_volatility")]
7706 pub volatility: f64,
7707
7708 #[serde(default)]
7710 pub cogs_pass_through: f64,
7711
7712 #[serde(default)]
7714 pub overhead_pass_through: f64,
7715}
7716
7717fn default_volatility() -> f64 {
7718 0.20
7719}
7720
7721#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7727pub struct DriftLabelingSchemaConfig {
7728 #[serde(default)]
7730 pub enabled: bool,
7731
7732 #[serde(default)]
7734 pub statistical: StatisticalDriftLabelingSchemaConfig,
7735
7736 #[serde(default)]
7738 pub categorical: CategoricalDriftLabelingSchemaConfig,
7739
7740 #[serde(default)]
7742 pub temporal: TemporalDriftLabelingSchemaConfig,
7743
7744 #[serde(default)]
7746 pub regulatory_calendar_preset: Option<String>,
7747}
7748
7749#[derive(Debug, Clone, Serialize, Deserialize)]
7751pub struct StatisticalDriftLabelingSchemaConfig {
7752 #[serde(default = "default_true_val")]
7754 pub enabled: bool,
7755
7756 #[serde(default = "default_min_magnitude")]
7758 pub min_magnitude_threshold: f64,
7759}
7760
7761fn default_min_magnitude() -> f64 {
7762 0.05
7763}
7764
7765impl Default for StatisticalDriftLabelingSchemaConfig {
7766 fn default() -> Self {
7767 Self {
7768 enabled: true,
7769 min_magnitude_threshold: 0.05,
7770 }
7771 }
7772}
7773
7774#[derive(Debug, Clone, Serialize, Deserialize)]
7776pub struct CategoricalDriftLabelingSchemaConfig {
7777 #[serde(default = "default_true_val")]
7779 pub enabled: bool,
7780}
7781
7782impl Default for CategoricalDriftLabelingSchemaConfig {
7783 fn default() -> Self {
7784 Self { enabled: true }
7785 }
7786}
7787
7788#[derive(Debug, Clone, Serialize, Deserialize)]
7790pub struct TemporalDriftLabelingSchemaConfig {
7791 #[serde(default = "default_true_val")]
7793 pub enabled: bool,
7794}
7795
7796impl Default for TemporalDriftLabelingSchemaConfig {
7797 fn default() -> Self {
7798 Self { enabled: true }
7799 }
7800}
7801
7802#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7815pub struct EnhancedAnomalyConfig {
7816 #[serde(default)]
7818 pub enabled: bool,
7819
7820 #[serde(default)]
7822 pub rates: AnomalyRateConfig,
7823
7824 #[serde(default)]
7826 pub multi_stage_schemes: MultiStageSchemeConfig,
7827
7828 #[serde(default)]
7830 pub correlated_injection: CorrelatedInjectionConfig,
7831
7832 #[serde(default)]
7834 pub near_miss: NearMissConfig,
7835
7836 #[serde(default)]
7838 pub difficulty_classification: DifficultyClassificationConfig,
7839
7840 #[serde(default)]
7842 pub context_aware: ContextAwareConfig,
7843
7844 #[serde(default)]
7846 pub labeling: EnhancedLabelingConfig,
7847}
7848
7849#[derive(Debug, Clone, Serialize, Deserialize)]
7851pub struct AnomalyRateConfig {
7852 #[serde(default = "default_total_anomaly_rate")]
7854 pub total_rate: f64,
7855
7856 #[serde(default = "default_fraud_anomaly_rate")]
7858 pub fraud_rate: f64,
7859
7860 #[serde(default = "default_error_anomaly_rate")]
7862 pub error_rate: f64,
7863
7864 #[serde(default = "default_process_anomaly_rate")]
7866 pub process_rate: f64,
7867}
7868
7869fn default_total_anomaly_rate() -> f64 {
7870 0.03
7871}
7872fn default_fraud_anomaly_rate() -> f64 {
7873 0.01
7874}
7875fn default_error_anomaly_rate() -> f64 {
7876 0.015
7877}
7878fn default_process_anomaly_rate() -> f64 {
7879 0.005
7880}
7881
7882impl Default for AnomalyRateConfig {
7883 fn default() -> Self {
7884 Self {
7885 total_rate: default_total_anomaly_rate(),
7886 fraud_rate: default_fraud_anomaly_rate(),
7887 error_rate: default_error_anomaly_rate(),
7888 process_rate: default_process_anomaly_rate(),
7889 }
7890 }
7891}
7892
7893#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7895pub struct MultiStageSchemeConfig {
7896 #[serde(default)]
7898 pub enabled: bool,
7899
7900 #[serde(default)]
7902 pub embezzlement: EmbezzlementSchemeConfig,
7903
7904 #[serde(default)]
7906 pub revenue_manipulation: RevenueManipulationSchemeConfig,
7907
7908 #[serde(default)]
7910 pub kickback: KickbackSchemeConfig,
7911}
7912
7913#[derive(Debug, Clone, Serialize, Deserialize)]
7915pub struct EmbezzlementSchemeConfig {
7916 #[serde(default = "default_embezzlement_probability")]
7918 pub probability: f64,
7919
7920 #[serde(default)]
7922 pub testing_stage: SchemeStageConfig,
7923
7924 #[serde(default)]
7926 pub escalation_stage: SchemeStageConfig,
7927
7928 #[serde(default)]
7930 pub acceleration_stage: SchemeStageConfig,
7931
7932 #[serde(default)]
7934 pub desperation_stage: SchemeStageConfig,
7935}
7936
7937fn default_embezzlement_probability() -> f64 {
7938 0.02
7939}
7940
7941impl Default for EmbezzlementSchemeConfig {
7942 fn default() -> Self {
7943 Self {
7944 probability: default_embezzlement_probability(),
7945 testing_stage: SchemeStageConfig {
7946 duration_months: 2,
7947 amount_min: 100.0,
7948 amount_max: 500.0,
7949 transaction_count_min: 2,
7950 transaction_count_max: 5,
7951 difficulty: "hard".to_string(),
7952 },
7953 escalation_stage: SchemeStageConfig {
7954 duration_months: 6,
7955 amount_min: 500.0,
7956 amount_max: 2000.0,
7957 transaction_count_min: 3,
7958 transaction_count_max: 8,
7959 difficulty: "moderate".to_string(),
7960 },
7961 acceleration_stage: SchemeStageConfig {
7962 duration_months: 3,
7963 amount_min: 2000.0,
7964 amount_max: 10000.0,
7965 transaction_count_min: 5,
7966 transaction_count_max: 12,
7967 difficulty: "easy".to_string(),
7968 },
7969 desperation_stage: SchemeStageConfig {
7970 duration_months: 1,
7971 amount_min: 10000.0,
7972 amount_max: 50000.0,
7973 transaction_count_min: 3,
7974 transaction_count_max: 6,
7975 difficulty: "trivial".to_string(),
7976 },
7977 }
7978 }
7979}
7980
7981#[derive(Debug, Clone, Serialize, Deserialize)]
7983pub struct RevenueManipulationSchemeConfig {
7984 #[serde(default = "default_revenue_manipulation_probability")]
7986 pub probability: f64,
7987
7988 #[serde(default = "default_early_recognition_target")]
7990 pub early_recognition_target: f64,
7991
7992 #[serde(default = "default_expense_deferral_target")]
7994 pub expense_deferral_target: f64,
7995
7996 #[serde(default = "default_reserve_release_target")]
7998 pub reserve_release_target: f64,
7999
8000 #[serde(default = "default_channel_stuffing_target")]
8002 pub channel_stuffing_target: f64,
8003}
8004
8005fn default_revenue_manipulation_probability() -> f64 {
8006 0.01
8007}
8008fn default_early_recognition_target() -> f64 {
8009 0.02
8010}
8011fn default_expense_deferral_target() -> f64 {
8012 0.03
8013}
8014fn default_reserve_release_target() -> f64 {
8015 0.02
8016}
8017fn default_channel_stuffing_target() -> f64 {
8018 0.05
8019}
8020
8021impl Default for RevenueManipulationSchemeConfig {
8022 fn default() -> Self {
8023 Self {
8024 probability: default_revenue_manipulation_probability(),
8025 early_recognition_target: default_early_recognition_target(),
8026 expense_deferral_target: default_expense_deferral_target(),
8027 reserve_release_target: default_reserve_release_target(),
8028 channel_stuffing_target: default_channel_stuffing_target(),
8029 }
8030 }
8031}
8032
8033#[derive(Debug, Clone, Serialize, Deserialize)]
8035pub struct KickbackSchemeConfig {
8036 #[serde(default = "default_kickback_probability")]
8038 pub probability: f64,
8039
8040 #[serde(default = "default_kickback_inflation_min")]
8042 pub inflation_min: f64,
8043
8044 #[serde(default = "default_kickback_inflation_max")]
8046 pub inflation_max: f64,
8047
8048 #[serde(default = "default_kickback_percent")]
8050 pub kickback_percent: f64,
8051
8052 #[serde(default = "default_kickback_setup_months")]
8054 pub setup_months: u32,
8055
8056 #[serde(default = "default_kickback_operation_months")]
8058 pub operation_months: u32,
8059}
8060
8061fn default_kickback_probability() -> f64 {
8062 0.01
8063}
8064fn default_kickback_inflation_min() -> f64 {
8065 0.10
8066}
8067fn default_kickback_inflation_max() -> f64 {
8068 0.25
8069}
8070fn default_kickback_percent() -> f64 {
8071 0.50
8072}
8073fn default_kickback_setup_months() -> u32 {
8074 3
8075}
8076fn default_kickback_operation_months() -> u32 {
8077 12
8078}
8079
8080impl Default for KickbackSchemeConfig {
8081 fn default() -> Self {
8082 Self {
8083 probability: default_kickback_probability(),
8084 inflation_min: default_kickback_inflation_min(),
8085 inflation_max: default_kickback_inflation_max(),
8086 kickback_percent: default_kickback_percent(),
8087 setup_months: default_kickback_setup_months(),
8088 operation_months: default_kickback_operation_months(),
8089 }
8090 }
8091}
8092
8093#[derive(Debug, Clone, Serialize, Deserialize)]
8095pub struct SchemeStageConfig {
8096 pub duration_months: u32,
8098
8099 pub amount_min: f64,
8101
8102 pub amount_max: f64,
8104
8105 pub transaction_count_min: u32,
8107
8108 pub transaction_count_max: u32,
8110
8111 pub difficulty: String,
8113}
8114
8115impl Default for SchemeStageConfig {
8116 fn default() -> Self {
8117 Self {
8118 duration_months: 3,
8119 amount_min: 100.0,
8120 amount_max: 1000.0,
8121 transaction_count_min: 2,
8122 transaction_count_max: 10,
8123 difficulty: "moderate".to_string(),
8124 }
8125 }
8126}
8127
8128#[derive(Debug, Clone, Serialize, Deserialize)]
8130pub struct CorrelatedInjectionConfig {
8131 #[serde(default)]
8133 pub enabled: bool,
8134
8135 #[serde(default = "default_true_val")]
8137 pub fraud_concealment: bool,
8138
8139 #[serde(default = "default_true_val")]
8141 pub error_cascade: bool,
8142
8143 #[serde(default = "default_true_val")]
8145 pub temporal_clustering: bool,
8146
8147 #[serde(default)]
8149 pub temporal_clustering_config: TemporalClusteringConfig,
8150
8151 #[serde(default)]
8153 pub co_occurrence_patterns: Vec<CoOccurrencePatternConfig>,
8154}
8155
8156impl Default for CorrelatedInjectionConfig {
8157 fn default() -> Self {
8158 Self {
8159 enabled: false,
8160 fraud_concealment: true,
8161 error_cascade: true,
8162 temporal_clustering: true,
8163 temporal_clustering_config: TemporalClusteringConfig::default(),
8164 co_occurrence_patterns: Vec::new(),
8165 }
8166 }
8167}
8168
8169#[derive(Debug, Clone, Serialize, Deserialize)]
8171pub struct TemporalClusteringConfig {
8172 #[serde(default = "default_period_end_multiplier")]
8174 pub period_end_multiplier: f64,
8175
8176 #[serde(default = "default_period_end_days")]
8178 pub period_end_days: u32,
8179
8180 #[serde(default = "default_quarter_end_multiplier")]
8182 pub quarter_end_multiplier: f64,
8183
8184 #[serde(default = "default_year_end_multiplier")]
8186 pub year_end_multiplier: f64,
8187}
8188
8189fn default_period_end_multiplier() -> f64 {
8190 2.5
8191}
8192fn default_period_end_days() -> u32 {
8193 5
8194}
8195fn default_quarter_end_multiplier() -> f64 {
8196 1.5
8197}
8198fn default_year_end_multiplier() -> f64 {
8199 2.0
8200}
8201
8202impl Default for TemporalClusteringConfig {
8203 fn default() -> Self {
8204 Self {
8205 period_end_multiplier: default_period_end_multiplier(),
8206 period_end_days: default_period_end_days(),
8207 quarter_end_multiplier: default_quarter_end_multiplier(),
8208 year_end_multiplier: default_year_end_multiplier(),
8209 }
8210 }
8211}
8212
8213#[derive(Debug, Clone, Serialize, Deserialize)]
8215pub struct CoOccurrencePatternConfig {
8216 pub name: String,
8218
8219 pub primary_type: String,
8221
8222 pub correlated: Vec<CorrelatedAnomalyConfig>,
8224}
8225
8226#[derive(Debug, Clone, Serialize, Deserialize)]
8228pub struct CorrelatedAnomalyConfig {
8229 pub anomaly_type: String,
8231
8232 pub probability: f64,
8234
8235 pub lag_days_min: i32,
8237
8238 pub lag_days_max: i32,
8240}
8241
8242#[derive(Debug, Clone, Serialize, Deserialize)]
8244pub struct NearMissConfig {
8245 #[serde(default)]
8247 pub enabled: bool,
8248
8249 #[serde(default = "default_near_miss_proportion")]
8251 pub proportion: f64,
8252
8253 #[serde(default = "default_true_val")]
8255 pub near_duplicate: bool,
8256
8257 #[serde(default)]
8259 pub near_duplicate_days: NearDuplicateDaysConfig,
8260
8261 #[serde(default = "default_true_val")]
8263 pub threshold_proximity: bool,
8264
8265 #[serde(default)]
8267 pub threshold_proximity_range: ThresholdProximityRangeConfig,
8268
8269 #[serde(default = "default_true_val")]
8271 pub unusual_legitimate: bool,
8272
8273 #[serde(default = "default_unusual_legitimate_types")]
8275 pub unusual_legitimate_types: Vec<String>,
8276
8277 #[serde(default = "default_true_val")]
8279 pub corrected_errors: bool,
8280
8281 #[serde(default)]
8283 pub corrected_error_lag: CorrectedErrorLagConfig,
8284}
8285
8286fn default_near_miss_proportion() -> f64 {
8287 0.30
8288}
8289
8290fn default_unusual_legitimate_types() -> Vec<String> {
8291 vec![
8292 "year_end_bonus".to_string(),
8293 "contract_prepayment".to_string(),
8294 "insurance_claim".to_string(),
8295 "settlement_payment".to_string(),
8296 ]
8297}
8298
8299impl Default for NearMissConfig {
8300 fn default() -> Self {
8301 Self {
8302 enabled: false,
8303 proportion: default_near_miss_proportion(),
8304 near_duplicate: true,
8305 near_duplicate_days: NearDuplicateDaysConfig::default(),
8306 threshold_proximity: true,
8307 threshold_proximity_range: ThresholdProximityRangeConfig::default(),
8308 unusual_legitimate: true,
8309 unusual_legitimate_types: default_unusual_legitimate_types(),
8310 corrected_errors: true,
8311 corrected_error_lag: CorrectedErrorLagConfig::default(),
8312 }
8313 }
8314}
8315
8316#[derive(Debug, Clone, Serialize, Deserialize)]
8318pub struct NearDuplicateDaysConfig {
8319 #[serde(default = "default_near_duplicate_min")]
8321 pub min: u32,
8322
8323 #[serde(default = "default_near_duplicate_max")]
8325 pub max: u32,
8326}
8327
8328fn default_near_duplicate_min() -> u32 {
8329 1
8330}
8331fn default_near_duplicate_max() -> u32 {
8332 3
8333}
8334
8335impl Default for NearDuplicateDaysConfig {
8336 fn default() -> Self {
8337 Self {
8338 min: default_near_duplicate_min(),
8339 max: default_near_duplicate_max(),
8340 }
8341 }
8342}
8343
8344#[derive(Debug, Clone, Serialize, Deserialize)]
8346pub struct ThresholdProximityRangeConfig {
8347 #[serde(default = "default_threshold_proximity_min")]
8349 pub min: f64,
8350
8351 #[serde(default = "default_threshold_proximity_max")]
8353 pub max: f64,
8354}
8355
8356fn default_threshold_proximity_min() -> f64 {
8357 0.90
8358}
8359fn default_threshold_proximity_max() -> f64 {
8360 0.99
8361}
8362
8363impl Default for ThresholdProximityRangeConfig {
8364 fn default() -> Self {
8365 Self {
8366 min: default_threshold_proximity_min(),
8367 max: default_threshold_proximity_max(),
8368 }
8369 }
8370}
8371
8372#[derive(Debug, Clone, Serialize, Deserialize)]
8374pub struct CorrectedErrorLagConfig {
8375 #[serde(default = "default_corrected_error_lag_min")]
8377 pub min: u32,
8378
8379 #[serde(default = "default_corrected_error_lag_max")]
8381 pub max: u32,
8382}
8383
8384fn default_corrected_error_lag_min() -> u32 {
8385 1
8386}
8387fn default_corrected_error_lag_max() -> u32 {
8388 5
8389}
8390
8391impl Default for CorrectedErrorLagConfig {
8392 fn default() -> Self {
8393 Self {
8394 min: default_corrected_error_lag_min(),
8395 max: default_corrected_error_lag_max(),
8396 }
8397 }
8398}
8399
8400#[derive(Debug, Clone, Serialize, Deserialize)]
8402pub struct DifficultyClassificationConfig {
8403 #[serde(default)]
8405 pub enabled: bool,
8406
8407 #[serde(default)]
8409 pub target_distribution: DifficultyDistributionConfig,
8410}
8411
8412impl Default for DifficultyClassificationConfig {
8413 fn default() -> Self {
8414 Self {
8415 enabled: true,
8416 target_distribution: DifficultyDistributionConfig::default(),
8417 }
8418 }
8419}
8420
8421#[derive(Debug, Clone, Serialize, Deserialize)]
8423pub struct DifficultyDistributionConfig {
8424 #[serde(default = "default_difficulty_trivial")]
8426 pub trivial: f64,
8427
8428 #[serde(default = "default_difficulty_easy")]
8430 pub easy: f64,
8431
8432 #[serde(default = "default_difficulty_moderate")]
8434 pub moderate: f64,
8435
8436 #[serde(default = "default_difficulty_hard")]
8438 pub hard: f64,
8439
8440 #[serde(default = "default_difficulty_expert")]
8442 pub expert: f64,
8443}
8444
8445fn default_difficulty_trivial() -> f64 {
8446 0.15
8447}
8448fn default_difficulty_easy() -> f64 {
8449 0.25
8450}
8451fn default_difficulty_moderate() -> f64 {
8452 0.30
8453}
8454fn default_difficulty_hard() -> f64 {
8455 0.20
8456}
8457fn default_difficulty_expert() -> f64 {
8458 0.10
8459}
8460
8461impl Default for DifficultyDistributionConfig {
8462 fn default() -> Self {
8463 Self {
8464 trivial: default_difficulty_trivial(),
8465 easy: default_difficulty_easy(),
8466 moderate: default_difficulty_moderate(),
8467 hard: default_difficulty_hard(),
8468 expert: default_difficulty_expert(),
8469 }
8470 }
8471}
8472
8473#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8475pub struct ContextAwareConfig {
8476 #[serde(default)]
8478 pub enabled: bool,
8479
8480 #[serde(default)]
8482 pub vendor_rules: VendorAnomalyRulesConfig,
8483
8484 #[serde(default)]
8486 pub employee_rules: EmployeeAnomalyRulesConfig,
8487
8488 #[serde(default)]
8490 pub account_rules: AccountAnomalyRulesConfig,
8491
8492 #[serde(default)]
8494 pub behavioral_baseline: BehavioralBaselineConfig,
8495}
8496
8497#[derive(Debug, Clone, Serialize, Deserialize)]
8499pub struct VendorAnomalyRulesConfig {
8500 #[serde(default = "default_new_vendor_multiplier")]
8502 pub new_vendor_error_multiplier: f64,
8503
8504 #[serde(default = "default_new_vendor_threshold")]
8506 pub new_vendor_threshold_days: u32,
8507
8508 #[serde(default = "default_international_multiplier")]
8510 pub international_error_multiplier: f64,
8511
8512 #[serde(default = "default_strategic_vendor_types")]
8514 pub strategic_vendor_anomaly_types: Vec<String>,
8515}
8516
8517fn default_new_vendor_multiplier() -> f64 {
8518 2.5
8519}
8520fn default_new_vendor_threshold() -> u32 {
8521 90
8522}
8523fn default_international_multiplier() -> f64 {
8524 1.5
8525}
8526fn default_strategic_vendor_types() -> Vec<String> {
8527 vec![
8528 "pricing_dispute".to_string(),
8529 "contract_violation".to_string(),
8530 ]
8531}
8532
8533impl Default for VendorAnomalyRulesConfig {
8534 fn default() -> Self {
8535 Self {
8536 new_vendor_error_multiplier: default_new_vendor_multiplier(),
8537 new_vendor_threshold_days: default_new_vendor_threshold(),
8538 international_error_multiplier: default_international_multiplier(),
8539 strategic_vendor_anomaly_types: default_strategic_vendor_types(),
8540 }
8541 }
8542}
8543
8544#[derive(Debug, Clone, Serialize, Deserialize)]
8546pub struct EmployeeAnomalyRulesConfig {
8547 #[serde(default = "default_new_employee_rate")]
8549 pub new_employee_error_rate: f64,
8550
8551 #[serde(default = "default_new_employee_threshold")]
8553 pub new_employee_threshold_days: u32,
8554
8555 #[serde(default = "default_volume_fatigue_threshold")]
8557 pub volume_fatigue_threshold: u32,
8558
8559 #[serde(default = "default_coverage_multiplier")]
8561 pub coverage_error_multiplier: f64,
8562}
8563
8564fn default_new_employee_rate() -> f64 {
8565 0.05
8566}
8567fn default_new_employee_threshold() -> u32 {
8568 180
8569}
8570fn default_volume_fatigue_threshold() -> u32 {
8571 50
8572}
8573fn default_coverage_multiplier() -> f64 {
8574 1.8
8575}
8576
8577impl Default for EmployeeAnomalyRulesConfig {
8578 fn default() -> Self {
8579 Self {
8580 new_employee_error_rate: default_new_employee_rate(),
8581 new_employee_threshold_days: default_new_employee_threshold(),
8582 volume_fatigue_threshold: default_volume_fatigue_threshold(),
8583 coverage_error_multiplier: default_coverage_multiplier(),
8584 }
8585 }
8586}
8587
8588#[derive(Debug, Clone, Serialize, Deserialize)]
8590pub struct AccountAnomalyRulesConfig {
8591 #[serde(default = "default_high_risk_multiplier")]
8593 pub high_risk_account_multiplier: f64,
8594
8595 #[serde(default = "default_high_risk_accounts")]
8597 pub high_risk_accounts: Vec<String>,
8598
8599 #[serde(default = "default_suspense_multiplier")]
8601 pub suspense_account_multiplier: f64,
8602
8603 #[serde(default = "default_suspense_accounts")]
8605 pub suspense_accounts: Vec<String>,
8606
8607 #[serde(default = "default_intercompany_multiplier")]
8609 pub intercompany_account_multiplier: f64,
8610}
8611
8612fn default_high_risk_multiplier() -> f64 {
8613 2.0
8614}
8615fn default_high_risk_accounts() -> Vec<String> {
8616 vec![
8617 "1100".to_string(), "2000".to_string(), "3000".to_string(), ]
8621}
8622fn default_suspense_multiplier() -> f64 {
8623 3.0
8624}
8625fn default_suspense_accounts() -> Vec<String> {
8626 vec!["9999".to_string(), "9998".to_string()]
8627}
8628fn default_intercompany_multiplier() -> f64 {
8629 1.5
8630}
8631
8632impl Default for AccountAnomalyRulesConfig {
8633 fn default() -> Self {
8634 Self {
8635 high_risk_account_multiplier: default_high_risk_multiplier(),
8636 high_risk_accounts: default_high_risk_accounts(),
8637 suspense_account_multiplier: default_suspense_multiplier(),
8638 suspense_accounts: default_suspense_accounts(),
8639 intercompany_account_multiplier: default_intercompany_multiplier(),
8640 }
8641 }
8642}
8643
8644#[derive(Debug, Clone, Serialize, Deserialize)]
8646pub struct BehavioralBaselineConfig {
8647 #[serde(default)]
8649 pub enabled: bool,
8650
8651 #[serde(default = "default_baseline_period")]
8653 pub baseline_period_days: u32,
8654
8655 #[serde(default = "default_deviation_threshold")]
8657 pub deviation_threshold_std: f64,
8658
8659 #[serde(default = "default_frequency_deviation")]
8661 pub frequency_deviation_threshold: f64,
8662}
8663
8664fn default_baseline_period() -> u32 {
8665 90
8666}
8667fn default_deviation_threshold() -> f64 {
8668 3.0
8669}
8670fn default_frequency_deviation() -> f64 {
8671 2.0
8672}
8673
8674impl Default for BehavioralBaselineConfig {
8675 fn default() -> Self {
8676 Self {
8677 enabled: false,
8678 baseline_period_days: default_baseline_period(),
8679 deviation_threshold_std: default_deviation_threshold(),
8680 frequency_deviation_threshold: default_frequency_deviation(),
8681 }
8682 }
8683}
8684
8685#[derive(Debug, Clone, Serialize, Deserialize)]
8687pub struct EnhancedLabelingConfig {
8688 #[serde(default = "default_true_val")]
8690 pub severity_scoring: bool,
8691
8692 #[serde(default = "default_true_val")]
8694 pub difficulty_classification: bool,
8695
8696 #[serde(default)]
8698 pub materiality_thresholds: MaterialityThresholdsConfig,
8699}
8700
8701impl Default for EnhancedLabelingConfig {
8702 fn default() -> Self {
8703 Self {
8704 severity_scoring: true,
8705 difficulty_classification: true,
8706 materiality_thresholds: MaterialityThresholdsConfig::default(),
8707 }
8708 }
8709}
8710
8711#[derive(Debug, Clone, Serialize, Deserialize)]
8713pub struct MaterialityThresholdsConfig {
8714 #[serde(default = "default_materiality_trivial")]
8716 pub trivial: f64,
8717
8718 #[serde(default = "default_materiality_immaterial")]
8720 pub immaterial: f64,
8721
8722 #[serde(default = "default_materiality_material")]
8724 pub material: f64,
8725
8726 #[serde(default = "default_materiality_highly_material")]
8728 pub highly_material: f64,
8729}
8730
8731fn default_materiality_trivial() -> f64 {
8732 0.001
8733}
8734fn default_materiality_immaterial() -> f64 {
8735 0.01
8736}
8737fn default_materiality_material() -> f64 {
8738 0.05
8739}
8740fn default_materiality_highly_material() -> f64 {
8741 0.10
8742}
8743
8744impl Default for MaterialityThresholdsConfig {
8745 fn default() -> Self {
8746 Self {
8747 trivial: default_materiality_trivial(),
8748 immaterial: default_materiality_immaterial(),
8749 material: default_materiality_material(),
8750 highly_material: default_materiality_highly_material(),
8751 }
8752 }
8753}
8754
8755#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8767pub struct IndustrySpecificConfig {
8768 #[serde(default)]
8770 pub enabled: bool,
8771
8772 #[serde(default)]
8774 pub manufacturing: ManufacturingConfig,
8775
8776 #[serde(default)]
8778 pub retail: RetailConfig,
8779
8780 #[serde(default)]
8782 pub healthcare: HealthcareConfig,
8783
8784 #[serde(default)]
8786 pub technology: TechnologyConfig,
8787
8788 #[serde(default)]
8790 pub financial_services: FinancialServicesConfig,
8791
8792 #[serde(default)]
8794 pub professional_services: ProfessionalServicesConfig,
8795}
8796
8797#[derive(Debug, Clone, Serialize, Deserialize)]
8799pub struct ManufacturingConfig {
8800 #[serde(default)]
8802 pub enabled: bool,
8803
8804 #[serde(default = "default_bom_depth")]
8806 pub bom_depth: u32,
8807
8808 #[serde(default)]
8810 pub just_in_time: bool,
8811
8812 #[serde(default = "default_production_order_types")]
8814 pub production_order_types: Vec<String>,
8815
8816 #[serde(default)]
8818 pub quality_framework: Option<String>,
8819
8820 #[serde(default = "default_supplier_tiers")]
8822 pub supplier_tiers: u32,
8823
8824 #[serde(default = "default_cost_frequency")]
8826 pub standard_cost_frequency: String,
8827
8828 #[serde(default = "default_yield_rate")]
8830 pub target_yield_rate: f64,
8831
8832 #[serde(default = "default_scrap_threshold")]
8834 pub scrap_alert_threshold: f64,
8835
8836 #[serde(default)]
8838 pub anomaly_rates: ManufacturingAnomalyRates,
8839}
8840
8841fn default_bom_depth() -> u32 {
8842 4
8843}
8844
8845fn default_production_order_types() -> Vec<String> {
8846 vec![
8847 "standard".to_string(),
8848 "rework".to_string(),
8849 "prototype".to_string(),
8850 ]
8851}
8852
8853fn default_supplier_tiers() -> u32 {
8854 2
8855}
8856
8857fn default_cost_frequency() -> String {
8858 "quarterly".to_string()
8859}
8860
8861fn default_yield_rate() -> f64 {
8862 0.97
8863}
8864
8865fn default_scrap_threshold() -> f64 {
8866 0.03
8867}
8868
8869impl Default for ManufacturingConfig {
8870 fn default() -> Self {
8871 Self {
8872 enabled: false,
8873 bom_depth: default_bom_depth(),
8874 just_in_time: false,
8875 production_order_types: default_production_order_types(),
8876 quality_framework: Some("ISO_9001".to_string()),
8877 supplier_tiers: default_supplier_tiers(),
8878 standard_cost_frequency: default_cost_frequency(),
8879 target_yield_rate: default_yield_rate(),
8880 scrap_alert_threshold: default_scrap_threshold(),
8881 anomaly_rates: ManufacturingAnomalyRates::default(),
8882 }
8883 }
8884}
8885
8886#[derive(Debug, Clone, Serialize, Deserialize)]
8888pub struct ManufacturingAnomalyRates {
8889 #[serde(default = "default_mfg_yield_rate")]
8891 pub yield_manipulation: f64,
8892
8893 #[serde(default = "default_mfg_labor_rate")]
8895 pub labor_misallocation: f64,
8896
8897 #[serde(default = "default_mfg_phantom_rate")]
8899 pub phantom_production: f64,
8900
8901 #[serde(default = "default_mfg_cost_rate")]
8903 pub standard_cost_manipulation: f64,
8904
8905 #[serde(default = "default_mfg_inventory_rate")]
8907 pub inventory_fraud: f64,
8908}
8909
8910fn default_mfg_yield_rate() -> f64 {
8911 0.015
8912}
8913
8914fn default_mfg_labor_rate() -> f64 {
8915 0.02
8916}
8917
8918fn default_mfg_phantom_rate() -> f64 {
8919 0.005
8920}
8921
8922fn default_mfg_cost_rate() -> f64 {
8923 0.01
8924}
8925
8926fn default_mfg_inventory_rate() -> f64 {
8927 0.008
8928}
8929
8930impl Default for ManufacturingAnomalyRates {
8931 fn default() -> Self {
8932 Self {
8933 yield_manipulation: default_mfg_yield_rate(),
8934 labor_misallocation: default_mfg_labor_rate(),
8935 phantom_production: default_mfg_phantom_rate(),
8936 standard_cost_manipulation: default_mfg_cost_rate(),
8937 inventory_fraud: default_mfg_inventory_rate(),
8938 }
8939 }
8940}
8941
8942#[derive(Debug, Clone, Serialize, Deserialize)]
8944pub struct RetailConfig {
8945 #[serde(default)]
8947 pub enabled: bool,
8948
8949 #[serde(default)]
8951 pub store_types: RetailStoreTypeConfig,
8952
8953 #[serde(default = "default_retail_daily_txns")]
8955 pub avg_daily_transactions: u32,
8956
8957 #[serde(default = "default_true")]
8959 pub loss_prevention: bool,
8960
8961 #[serde(default = "default_shrinkage_rate")]
8963 pub shrinkage_rate: f64,
8964
8965 #[serde(default)]
8967 pub anomaly_rates: RetailAnomalyRates,
8968}
8969
8970fn default_retail_daily_txns() -> u32 {
8971 500
8972}
8973
8974fn default_shrinkage_rate() -> f64 {
8975 0.015
8976}
8977
8978impl Default for RetailConfig {
8979 fn default() -> Self {
8980 Self {
8981 enabled: false,
8982 store_types: RetailStoreTypeConfig::default(),
8983 avg_daily_transactions: default_retail_daily_txns(),
8984 loss_prevention: true,
8985 shrinkage_rate: default_shrinkage_rate(),
8986 anomaly_rates: RetailAnomalyRates::default(),
8987 }
8988 }
8989}
8990
8991#[derive(Debug, Clone, Serialize, Deserialize)]
8993pub struct RetailStoreTypeConfig {
8994 #[serde(default = "default_flagship_pct")]
8996 pub flagship: f64,
8997
8998 #[serde(default = "default_regional_pct")]
9000 pub regional: f64,
9001
9002 #[serde(default = "default_outlet_pct")]
9004 pub outlet: f64,
9005
9006 #[serde(default = "default_ecommerce_pct")]
9008 pub ecommerce: f64,
9009}
9010
9011fn default_flagship_pct() -> f64 {
9012 0.10
9013}
9014
9015fn default_regional_pct() -> f64 {
9016 0.50
9017}
9018
9019fn default_outlet_pct() -> f64 {
9020 0.25
9021}
9022
9023fn default_ecommerce_pct() -> f64 {
9024 0.15
9025}
9026
9027impl Default for RetailStoreTypeConfig {
9028 fn default() -> Self {
9029 Self {
9030 flagship: default_flagship_pct(),
9031 regional: default_regional_pct(),
9032 outlet: default_outlet_pct(),
9033 ecommerce: default_ecommerce_pct(),
9034 }
9035 }
9036}
9037
9038#[derive(Debug, Clone, Serialize, Deserialize)]
9040pub struct RetailAnomalyRates {
9041 #[serde(default = "default_sweethearting_rate")]
9043 pub sweethearting: f64,
9044
9045 #[serde(default = "default_skimming_rate")]
9047 pub skimming: f64,
9048
9049 #[serde(default = "default_refund_fraud_rate")]
9051 pub refund_fraud: f64,
9052
9053 #[serde(default = "default_void_abuse_rate")]
9055 pub void_abuse: f64,
9056
9057 #[serde(default = "default_gift_card_rate")]
9059 pub gift_card_fraud: f64,
9060
9061 #[serde(default = "default_retail_kickback_rate")]
9063 pub vendor_kickback: f64,
9064}
9065
9066fn default_sweethearting_rate() -> f64 {
9067 0.02
9068}
9069
9070fn default_skimming_rate() -> f64 {
9071 0.005
9072}
9073
9074fn default_refund_fraud_rate() -> f64 {
9075 0.015
9076}
9077
9078fn default_void_abuse_rate() -> f64 {
9079 0.01
9080}
9081
9082fn default_gift_card_rate() -> f64 {
9083 0.008
9084}
9085
9086fn default_retail_kickback_rate() -> f64 {
9087 0.003
9088}
9089
9090impl Default for RetailAnomalyRates {
9091 fn default() -> Self {
9092 Self {
9093 sweethearting: default_sweethearting_rate(),
9094 skimming: default_skimming_rate(),
9095 refund_fraud: default_refund_fraud_rate(),
9096 void_abuse: default_void_abuse_rate(),
9097 gift_card_fraud: default_gift_card_rate(),
9098 vendor_kickback: default_retail_kickback_rate(),
9099 }
9100 }
9101}
9102
9103#[derive(Debug, Clone, Serialize, Deserialize)]
9105pub struct HealthcareConfig {
9106 #[serde(default)]
9108 pub enabled: bool,
9109
9110 #[serde(default = "default_facility_type")]
9112 pub facility_type: String,
9113
9114 #[serde(default)]
9116 pub payer_mix: HealthcarePayerMix,
9117
9118 #[serde(default)]
9120 pub coding_systems: HealthcareCodingSystems,
9121
9122 #[serde(default)]
9124 pub compliance: HealthcareComplianceConfig,
9125
9126 #[serde(default = "default_daily_encounters")]
9128 pub avg_daily_encounters: u32,
9129
9130 #[serde(default = "default_charges_per_encounter")]
9132 pub avg_charges_per_encounter: u32,
9133
9134 #[serde(default = "default_hc_denial_rate")]
9136 pub denial_rate: f64,
9137
9138 #[serde(default = "default_hc_bad_debt_rate")]
9140 pub bad_debt_rate: f64,
9141
9142 #[serde(default = "default_hc_charity_care_rate")]
9144 pub charity_care_rate: f64,
9145
9146 #[serde(default)]
9148 pub anomaly_rates: HealthcareAnomalyRates,
9149}
9150
9151fn default_facility_type() -> String {
9152 "hospital".to_string()
9153}
9154
9155fn default_daily_encounters() -> u32 {
9156 150
9157}
9158
9159fn default_charges_per_encounter() -> u32 {
9160 8
9161}
9162
9163fn default_hc_denial_rate() -> f64 {
9164 0.05
9165}
9166
9167fn default_hc_bad_debt_rate() -> f64 {
9168 0.03
9169}
9170
9171fn default_hc_charity_care_rate() -> f64 {
9172 0.02
9173}
9174
9175impl Default for HealthcareConfig {
9176 fn default() -> Self {
9177 Self {
9178 enabled: false,
9179 facility_type: default_facility_type(),
9180 payer_mix: HealthcarePayerMix::default(),
9181 coding_systems: HealthcareCodingSystems::default(),
9182 compliance: HealthcareComplianceConfig::default(),
9183 avg_daily_encounters: default_daily_encounters(),
9184 avg_charges_per_encounter: default_charges_per_encounter(),
9185 denial_rate: default_hc_denial_rate(),
9186 bad_debt_rate: default_hc_bad_debt_rate(),
9187 charity_care_rate: default_hc_charity_care_rate(),
9188 anomaly_rates: HealthcareAnomalyRates::default(),
9189 }
9190 }
9191}
9192
9193#[derive(Debug, Clone, Serialize, Deserialize)]
9195pub struct HealthcarePayerMix {
9196 #[serde(default = "default_medicare_pct")]
9198 pub medicare: f64,
9199
9200 #[serde(default = "default_medicaid_pct")]
9202 pub medicaid: f64,
9203
9204 #[serde(default = "default_commercial_pct")]
9206 pub commercial: f64,
9207
9208 #[serde(default = "default_self_pay_pct")]
9210 pub self_pay: f64,
9211}
9212
9213fn default_medicare_pct() -> f64 {
9214 0.40
9215}
9216
9217fn default_medicaid_pct() -> f64 {
9218 0.20
9219}
9220
9221fn default_commercial_pct() -> f64 {
9222 0.30
9223}
9224
9225fn default_self_pay_pct() -> f64 {
9226 0.10
9227}
9228
9229impl Default for HealthcarePayerMix {
9230 fn default() -> Self {
9231 Self {
9232 medicare: default_medicare_pct(),
9233 medicaid: default_medicaid_pct(),
9234 commercial: default_commercial_pct(),
9235 self_pay: default_self_pay_pct(),
9236 }
9237 }
9238}
9239
9240#[derive(Debug, Clone, Serialize, Deserialize)]
9242pub struct HealthcareCodingSystems {
9243 #[serde(default = "default_true")]
9245 pub icd10: bool,
9246
9247 #[serde(default = "default_true")]
9249 pub cpt: bool,
9250
9251 #[serde(default = "default_true")]
9253 pub drg: bool,
9254
9255 #[serde(default = "default_true")]
9257 pub hcpcs: bool,
9258
9259 #[serde(default = "default_true")]
9261 pub revenue_codes: bool,
9262}
9263
9264impl Default for HealthcareCodingSystems {
9265 fn default() -> Self {
9266 Self {
9267 icd10: true,
9268 cpt: true,
9269 drg: true,
9270 hcpcs: true,
9271 revenue_codes: true,
9272 }
9273 }
9274}
9275
9276#[derive(Debug, Clone, Serialize, Deserialize)]
9278pub struct HealthcareComplianceConfig {
9279 #[serde(default = "default_true")]
9281 pub hipaa: bool,
9282
9283 #[serde(default = "default_true")]
9285 pub stark_law: bool,
9286
9287 #[serde(default = "default_true")]
9289 pub anti_kickback: bool,
9290
9291 #[serde(default = "default_true")]
9293 pub false_claims_act: bool,
9294
9295 #[serde(default = "default_true")]
9297 pub emtala: bool,
9298}
9299
9300impl Default for HealthcareComplianceConfig {
9301 fn default() -> Self {
9302 Self {
9303 hipaa: true,
9304 stark_law: true,
9305 anti_kickback: true,
9306 false_claims_act: true,
9307 emtala: true,
9308 }
9309 }
9310}
9311
9312#[derive(Debug, Clone, Serialize, Deserialize)]
9314pub struct HealthcareAnomalyRates {
9315 #[serde(default = "default_upcoding_rate")]
9317 pub upcoding: f64,
9318
9319 #[serde(default = "default_unbundling_rate")]
9321 pub unbundling: f64,
9322
9323 #[serde(default = "default_phantom_billing_rate")]
9325 pub phantom_billing: f64,
9326
9327 #[serde(default = "default_healthcare_kickback_rate")]
9329 pub kickbacks: f64,
9330
9331 #[serde(default = "default_duplicate_billing_rate")]
9333 pub duplicate_billing: f64,
9334
9335 #[serde(default = "default_med_necessity_rate")]
9337 pub medical_necessity_abuse: f64,
9338}
9339
9340fn default_upcoding_rate() -> f64 {
9341 0.02
9342}
9343
9344fn default_unbundling_rate() -> f64 {
9345 0.015
9346}
9347
9348fn default_phantom_billing_rate() -> f64 {
9349 0.005
9350}
9351
9352fn default_healthcare_kickback_rate() -> f64 {
9353 0.003
9354}
9355
9356fn default_duplicate_billing_rate() -> f64 {
9357 0.008
9358}
9359
9360fn default_med_necessity_rate() -> f64 {
9361 0.01
9362}
9363
9364impl Default for HealthcareAnomalyRates {
9365 fn default() -> Self {
9366 Self {
9367 upcoding: default_upcoding_rate(),
9368 unbundling: default_unbundling_rate(),
9369 phantom_billing: default_phantom_billing_rate(),
9370 kickbacks: default_healthcare_kickback_rate(),
9371 duplicate_billing: default_duplicate_billing_rate(),
9372 medical_necessity_abuse: default_med_necessity_rate(),
9373 }
9374 }
9375}
9376
9377#[derive(Debug, Clone, Serialize, Deserialize)]
9379pub struct TechnologyConfig {
9380 #[serde(default)]
9382 pub enabled: bool,
9383
9384 #[serde(default = "default_revenue_model")]
9386 pub revenue_model: String,
9387
9388 #[serde(default = "default_subscription_pct")]
9390 pub subscription_revenue_pct: f64,
9391
9392 #[serde(default = "default_license_pct")]
9394 pub license_revenue_pct: f64,
9395
9396 #[serde(default = "default_services_pct")]
9398 pub services_revenue_pct: f64,
9399
9400 #[serde(default)]
9402 pub rd_capitalization: RdCapitalizationConfig,
9403
9404 #[serde(default)]
9406 pub anomaly_rates: TechnologyAnomalyRates,
9407}
9408
9409fn default_revenue_model() -> String {
9410 "saas".to_string()
9411}
9412
9413fn default_subscription_pct() -> f64 {
9414 0.60
9415}
9416
9417fn default_license_pct() -> f64 {
9418 0.25
9419}
9420
9421fn default_services_pct() -> f64 {
9422 0.15
9423}
9424
9425impl Default for TechnologyConfig {
9426 fn default() -> Self {
9427 Self {
9428 enabled: false,
9429 revenue_model: default_revenue_model(),
9430 subscription_revenue_pct: default_subscription_pct(),
9431 license_revenue_pct: default_license_pct(),
9432 services_revenue_pct: default_services_pct(),
9433 rd_capitalization: RdCapitalizationConfig::default(),
9434 anomaly_rates: TechnologyAnomalyRates::default(),
9435 }
9436 }
9437}
9438
9439#[derive(Debug, Clone, Serialize, Deserialize)]
9441pub struct RdCapitalizationConfig {
9442 #[serde(default = "default_true")]
9444 pub enabled: bool,
9445
9446 #[serde(default = "default_cap_rate")]
9448 pub capitalization_rate: f64,
9449
9450 #[serde(default = "default_useful_life")]
9452 pub useful_life_years: u32,
9453}
9454
9455fn default_cap_rate() -> f64 {
9456 0.30
9457}
9458
9459fn default_useful_life() -> u32 {
9460 3
9461}
9462
9463impl Default for RdCapitalizationConfig {
9464 fn default() -> Self {
9465 Self {
9466 enabled: true,
9467 capitalization_rate: default_cap_rate(),
9468 useful_life_years: default_useful_life(),
9469 }
9470 }
9471}
9472
9473#[derive(Debug, Clone, Serialize, Deserialize)]
9475pub struct TechnologyAnomalyRates {
9476 #[serde(default = "default_premature_rev_rate")]
9478 pub premature_revenue: f64,
9479
9480 #[serde(default = "default_side_letter_rate")]
9482 pub side_letter_abuse: f64,
9483
9484 #[serde(default = "default_channel_stuffing_rate")]
9486 pub channel_stuffing: f64,
9487
9488 #[serde(default = "default_improper_cap_rate")]
9490 pub improper_capitalization: f64,
9491}
9492
9493fn default_premature_rev_rate() -> f64 {
9494 0.015
9495}
9496
9497fn default_side_letter_rate() -> f64 {
9498 0.008
9499}
9500
9501fn default_channel_stuffing_rate() -> f64 {
9502 0.01
9503}
9504
9505fn default_improper_cap_rate() -> f64 {
9506 0.012
9507}
9508
9509impl Default for TechnologyAnomalyRates {
9510 fn default() -> Self {
9511 Self {
9512 premature_revenue: default_premature_rev_rate(),
9513 side_letter_abuse: default_side_letter_rate(),
9514 channel_stuffing: default_channel_stuffing_rate(),
9515 improper_capitalization: default_improper_cap_rate(),
9516 }
9517 }
9518}
9519
9520#[derive(Debug, Clone, Serialize, Deserialize)]
9522pub struct FinancialServicesConfig {
9523 #[serde(default)]
9525 pub enabled: bool,
9526
9527 #[serde(default = "default_fi_type")]
9529 pub institution_type: String,
9530
9531 #[serde(default = "default_fi_regulatory")]
9533 pub regulatory_framework: String,
9534
9535 #[serde(default)]
9537 pub anomaly_rates: FinancialServicesAnomalyRates,
9538}
9539
9540fn default_fi_type() -> String {
9541 "commercial_bank".to_string()
9542}
9543
9544fn default_fi_regulatory() -> String {
9545 "us_banking".to_string()
9546}
9547
9548impl Default for FinancialServicesConfig {
9549 fn default() -> Self {
9550 Self {
9551 enabled: false,
9552 institution_type: default_fi_type(),
9553 regulatory_framework: default_fi_regulatory(),
9554 anomaly_rates: FinancialServicesAnomalyRates::default(),
9555 }
9556 }
9557}
9558
9559#[derive(Debug, Clone, Serialize, Deserialize)]
9561pub struct FinancialServicesAnomalyRates {
9562 #[serde(default = "default_loan_fraud_rate")]
9564 pub loan_fraud: f64,
9565
9566 #[serde(default = "default_trading_fraud_rate")]
9568 pub trading_fraud: f64,
9569
9570 #[serde(default = "default_insurance_fraud_rate")]
9572 pub insurance_fraud: f64,
9573
9574 #[serde(default = "default_account_manip_rate")]
9576 pub account_manipulation: f64,
9577}
9578
9579fn default_loan_fraud_rate() -> f64 {
9580 0.01
9581}
9582
9583fn default_trading_fraud_rate() -> f64 {
9584 0.008
9585}
9586
9587fn default_insurance_fraud_rate() -> f64 {
9588 0.012
9589}
9590
9591fn default_account_manip_rate() -> f64 {
9592 0.005
9593}
9594
9595impl Default for FinancialServicesAnomalyRates {
9596 fn default() -> Self {
9597 Self {
9598 loan_fraud: default_loan_fraud_rate(),
9599 trading_fraud: default_trading_fraud_rate(),
9600 insurance_fraud: default_insurance_fraud_rate(),
9601 account_manipulation: default_account_manip_rate(),
9602 }
9603 }
9604}
9605
9606#[derive(Debug, Clone, Serialize, Deserialize)]
9608pub struct ProfessionalServicesConfig {
9609 #[serde(default)]
9611 pub enabled: bool,
9612
9613 #[serde(default = "default_firm_type")]
9615 pub firm_type: String,
9616
9617 #[serde(default = "default_billing_model")]
9619 pub billing_model: String,
9620
9621 #[serde(default = "default_hourly_rate")]
9623 pub avg_hourly_rate: f64,
9624
9625 #[serde(default)]
9627 pub trust_accounting: TrustAccountingConfig,
9628
9629 #[serde(default)]
9631 pub anomaly_rates: ProfessionalServicesAnomalyRates,
9632}
9633
9634fn default_firm_type() -> String {
9635 "consulting".to_string()
9636}
9637
9638fn default_billing_model() -> String {
9639 "time_and_materials".to_string()
9640}
9641
9642fn default_hourly_rate() -> f64 {
9643 250.0
9644}
9645
9646impl Default for ProfessionalServicesConfig {
9647 fn default() -> Self {
9648 Self {
9649 enabled: false,
9650 firm_type: default_firm_type(),
9651 billing_model: default_billing_model(),
9652 avg_hourly_rate: default_hourly_rate(),
9653 trust_accounting: TrustAccountingConfig::default(),
9654 anomaly_rates: ProfessionalServicesAnomalyRates::default(),
9655 }
9656 }
9657}
9658
9659#[derive(Debug, Clone, Serialize, Deserialize)]
9661pub struct TrustAccountingConfig {
9662 #[serde(default)]
9664 pub enabled: bool,
9665
9666 #[serde(default = "default_true")]
9668 pub require_three_way_reconciliation: bool,
9669}
9670
9671impl Default for TrustAccountingConfig {
9672 fn default() -> Self {
9673 Self {
9674 enabled: false,
9675 require_three_way_reconciliation: true,
9676 }
9677 }
9678}
9679
9680#[derive(Debug, Clone, Serialize, Deserialize)]
9682pub struct ProfessionalServicesAnomalyRates {
9683 #[serde(default = "default_time_fraud_rate")]
9685 pub time_billing_fraud: f64,
9686
9687 #[serde(default = "default_expense_fraud_rate")]
9689 pub expense_fraud: f64,
9690
9691 #[serde(default = "default_trust_misappropriation_rate")]
9693 pub trust_misappropriation: f64,
9694}
9695
9696fn default_time_fraud_rate() -> f64 {
9697 0.02
9698}
9699
9700fn default_expense_fraud_rate() -> f64 {
9701 0.015
9702}
9703
9704fn default_trust_misappropriation_rate() -> f64 {
9705 0.003
9706}
9707
9708impl Default for ProfessionalServicesAnomalyRates {
9709 fn default() -> Self {
9710 Self {
9711 time_billing_fraud: default_time_fraud_rate(),
9712 expense_fraud: default_expense_fraud_rate(),
9713 trust_misappropriation: default_trust_misappropriation_rate(),
9714 }
9715 }
9716}
9717
9718#[derive(Debug, Clone, Serialize, Deserialize)]
9732pub struct FingerprintPrivacyConfig {
9733 #[serde(default)]
9735 pub level: String,
9736 #[serde(default = "default_epsilon")]
9738 pub epsilon: f64,
9739 #[serde(default = "default_delta")]
9741 pub delta: f64,
9742 #[serde(default = "default_k_anonymity")]
9744 pub k_anonymity: u32,
9745 #[serde(default)]
9747 pub composition_method: String,
9748}
9749
9750fn default_epsilon() -> f64 {
9751 1.0
9752}
9753
9754fn default_delta() -> f64 {
9755 1e-5
9756}
9757
9758fn default_k_anonymity() -> u32 {
9759 5
9760}
9761
9762impl Default for FingerprintPrivacyConfig {
9763 fn default() -> Self {
9764 Self {
9765 level: "standard".to_string(),
9766 epsilon: default_epsilon(),
9767 delta: default_delta(),
9768 k_anonymity: default_k_anonymity(),
9769 composition_method: "naive".to_string(),
9770 }
9771 }
9772}
9773
9774#[derive(Debug, Clone, Serialize, Deserialize)]
9788pub struct QualityGatesSchemaConfig {
9789 #[serde(default)]
9791 pub enabled: bool,
9792 #[serde(default = "default_gate_profile_name")]
9794 pub profile: String,
9795 #[serde(default)]
9797 pub fail_on_violation: bool,
9798 #[serde(default)]
9800 pub custom_gates: Vec<QualityGateEntry>,
9801}
9802
9803fn default_gate_profile_name() -> String {
9804 "default".to_string()
9805}
9806
9807impl Default for QualityGatesSchemaConfig {
9808 fn default() -> Self {
9809 Self {
9810 enabled: false,
9811 profile: default_gate_profile_name(),
9812 fail_on_violation: false,
9813 custom_gates: Vec::new(),
9814 }
9815 }
9816}
9817
9818#[derive(Debug, Clone, Serialize, Deserialize)]
9820pub struct QualityGateEntry {
9821 pub name: String,
9823 pub metric: String,
9827 pub threshold: f64,
9829 #[serde(default)]
9831 pub upper_threshold: Option<f64>,
9832 #[serde(default = "default_gate_comparison")]
9834 pub comparison: String,
9835}
9836
9837fn default_gate_comparison() -> String {
9838 "gte".to_string()
9839}
9840
9841#[derive(Debug, Clone, Default, Serialize, Deserialize)]
9851pub struct ComplianceSchemaConfig {
9852 #[serde(default)]
9854 pub content_marking: ContentMarkingSchemaConfig,
9855 #[serde(default)]
9857 pub article10_report: bool,
9858 #[serde(default)]
9860 pub certificates: CertificateSchemaConfig,
9861}
9862
9863#[derive(Debug, Clone, Default, Serialize, Deserialize)]
9865pub struct CertificateSchemaConfig {
9866 #[serde(default)]
9868 pub enabled: bool,
9869 #[serde(default)]
9871 pub signing_key_env: Option<String>,
9872 #[serde(default)]
9874 pub include_quality_metrics: bool,
9875}
9876
9877#[derive(Debug, Clone, Serialize, Deserialize)]
9879pub struct ContentMarkingSchemaConfig {
9880 #[serde(default = "default_true")]
9882 pub enabled: bool,
9883 #[serde(default = "default_marking_format")]
9885 pub format: String,
9886}
9887
9888fn default_marking_format() -> String {
9889 "embedded".to_string()
9890}
9891
9892impl Default for ContentMarkingSchemaConfig {
9893 fn default() -> Self {
9894 Self {
9895 enabled: true,
9896 format: default_marking_format(),
9897 }
9898 }
9899}
9900
9901#[derive(Debug, Clone, Default, Serialize, Deserialize)]
9903pub struct WebhookSchemaConfig {
9904 #[serde(default)]
9906 pub enabled: bool,
9907 #[serde(default)]
9909 pub endpoints: Vec<WebhookEndpointConfig>,
9910}
9911
9912#[derive(Debug, Clone, Serialize, Deserialize)]
9914pub struct WebhookEndpointConfig {
9915 pub url: String,
9917 #[serde(default)]
9919 pub events: Vec<String>,
9920 #[serde(default)]
9922 pub secret: Option<String>,
9923 #[serde(default = "default_webhook_retries")]
9925 pub max_retries: u32,
9926 #[serde(default = "default_webhook_timeout")]
9928 pub timeout_secs: u64,
9929}
9930
9931fn default_webhook_retries() -> u32 {
9932 3
9933}
9934fn default_webhook_timeout() -> u64 {
9935 10
9936}
9937
9938#[derive(Debug, Clone, Default, Serialize, Deserialize)]
9944pub struct SourceToPayConfig {
9945 #[serde(default)]
9947 pub enabled: bool,
9948 #[serde(default)]
9950 pub spend_analysis: SpendAnalysisConfig,
9951 #[serde(default)]
9953 pub sourcing: SourcingConfig,
9954 #[serde(default)]
9956 pub qualification: QualificationConfig,
9957 #[serde(default)]
9959 pub rfx: RfxConfig,
9960 #[serde(default)]
9962 pub contracts: ContractConfig,
9963 #[serde(default)]
9965 pub catalog: CatalogConfig,
9966 #[serde(default)]
9968 pub scorecards: ScorecardConfig,
9969 #[serde(default)]
9971 pub p2p_integration: P2PIntegrationConfig,
9972}
9973
9974#[derive(Debug, Clone, Serialize, Deserialize)]
9976pub struct SpendAnalysisConfig {
9977 #[serde(default = "default_hhi_threshold")]
9979 pub hhi_threshold: f64,
9980 #[serde(default = "default_contract_coverage_target")]
9982 pub contract_coverage_target: f64,
9983}
9984
9985impl Default for SpendAnalysisConfig {
9986 fn default() -> Self {
9987 Self {
9988 hhi_threshold: default_hhi_threshold(),
9989 contract_coverage_target: default_contract_coverage_target(),
9990 }
9991 }
9992}
9993
9994fn default_hhi_threshold() -> f64 {
9995 2500.0
9996}
9997fn default_contract_coverage_target() -> f64 {
9998 0.80
9999}
10000
10001#[derive(Debug, Clone, Serialize, Deserialize)]
10003pub struct SourcingConfig {
10004 #[serde(default = "default_sourcing_projects_per_year")]
10006 pub projects_per_year: u32,
10007 #[serde(default = "default_renewal_horizon_months")]
10009 pub renewal_horizon_months: u32,
10010 #[serde(default = "default_project_duration_months")]
10012 pub project_duration_months: u32,
10013}
10014
10015impl Default for SourcingConfig {
10016 fn default() -> Self {
10017 Self {
10018 projects_per_year: default_sourcing_projects_per_year(),
10019 renewal_horizon_months: default_renewal_horizon_months(),
10020 project_duration_months: default_project_duration_months(),
10021 }
10022 }
10023}
10024
10025fn default_sourcing_projects_per_year() -> u32 {
10026 10
10027}
10028fn default_renewal_horizon_months() -> u32 {
10029 3
10030}
10031fn default_project_duration_months() -> u32 {
10032 4
10033}
10034
10035#[derive(Debug, Clone, Serialize, Deserialize)]
10037pub struct QualificationConfig {
10038 #[serde(default = "default_qualification_pass_rate")]
10040 pub pass_rate: f64,
10041 #[serde(default = "default_qualification_validity_days")]
10043 pub validity_days: u32,
10044 #[serde(default = "default_financial_weight")]
10046 pub financial_weight: f64,
10047 #[serde(default = "default_quality_weight")]
10049 pub quality_weight: f64,
10050 #[serde(default = "default_delivery_weight")]
10052 pub delivery_weight: f64,
10053 #[serde(default = "default_compliance_weight")]
10055 pub compliance_weight: f64,
10056}
10057
10058impl Default for QualificationConfig {
10059 fn default() -> Self {
10060 Self {
10061 pass_rate: default_qualification_pass_rate(),
10062 validity_days: default_qualification_validity_days(),
10063 financial_weight: default_financial_weight(),
10064 quality_weight: default_quality_weight(),
10065 delivery_weight: default_delivery_weight(),
10066 compliance_weight: default_compliance_weight(),
10067 }
10068 }
10069}
10070
10071fn default_qualification_pass_rate() -> f64 {
10072 0.75
10073}
10074fn default_qualification_validity_days() -> u32 {
10075 365
10076}
10077fn default_financial_weight() -> f64 {
10078 0.25
10079}
10080fn default_quality_weight() -> f64 {
10081 0.30
10082}
10083fn default_delivery_weight() -> f64 {
10084 0.25
10085}
10086fn default_compliance_weight() -> f64 {
10087 0.20
10088}
10089
10090#[derive(Debug, Clone, Serialize, Deserialize)]
10092pub struct RfxConfig {
10093 #[serde(default = "default_rfi_threshold")]
10095 pub rfi_threshold: f64,
10096 #[serde(default = "default_min_invited_vendors")]
10098 pub min_invited_vendors: u32,
10099 #[serde(default = "default_max_invited_vendors")]
10101 pub max_invited_vendors: u32,
10102 #[serde(default = "default_response_rate")]
10104 pub response_rate: f64,
10105 #[serde(default = "default_price_weight")]
10107 pub default_price_weight: f64,
10108 #[serde(default = "default_rfx_quality_weight")]
10110 pub default_quality_weight: f64,
10111 #[serde(default = "default_rfx_delivery_weight")]
10113 pub default_delivery_weight: f64,
10114}
10115
10116impl Default for RfxConfig {
10117 fn default() -> Self {
10118 Self {
10119 rfi_threshold: default_rfi_threshold(),
10120 min_invited_vendors: default_min_invited_vendors(),
10121 max_invited_vendors: default_max_invited_vendors(),
10122 response_rate: default_response_rate(),
10123 default_price_weight: default_price_weight(),
10124 default_quality_weight: default_rfx_quality_weight(),
10125 default_delivery_weight: default_rfx_delivery_weight(),
10126 }
10127 }
10128}
10129
10130fn default_rfi_threshold() -> f64 {
10131 100_000.0
10132}
10133fn default_min_invited_vendors() -> u32 {
10134 3
10135}
10136fn default_max_invited_vendors() -> u32 {
10137 8
10138}
10139fn default_response_rate() -> f64 {
10140 0.70
10141}
10142fn default_price_weight() -> f64 {
10143 0.40
10144}
10145fn default_rfx_quality_weight() -> f64 {
10146 0.35
10147}
10148fn default_rfx_delivery_weight() -> f64 {
10149 0.25
10150}
10151
10152#[derive(Debug, Clone, Serialize, Deserialize)]
10154pub struct ContractConfig {
10155 #[serde(default = "default_min_contract_months")]
10157 pub min_duration_months: u32,
10158 #[serde(default = "default_max_contract_months")]
10160 pub max_duration_months: u32,
10161 #[serde(default = "default_auto_renewal_rate")]
10163 pub auto_renewal_rate: f64,
10164 #[serde(default = "default_amendment_rate")]
10166 pub amendment_rate: f64,
10167 #[serde(default)]
10169 pub type_distribution: ContractTypeDistribution,
10170}
10171
10172impl Default for ContractConfig {
10173 fn default() -> Self {
10174 Self {
10175 min_duration_months: default_min_contract_months(),
10176 max_duration_months: default_max_contract_months(),
10177 auto_renewal_rate: default_auto_renewal_rate(),
10178 amendment_rate: default_amendment_rate(),
10179 type_distribution: ContractTypeDistribution::default(),
10180 }
10181 }
10182}
10183
10184fn default_min_contract_months() -> u32 {
10185 12
10186}
10187fn default_max_contract_months() -> u32 {
10188 36
10189}
10190fn default_auto_renewal_rate() -> f64 {
10191 0.40
10192}
10193fn default_amendment_rate() -> f64 {
10194 0.20
10195}
10196
10197#[derive(Debug, Clone, Serialize, Deserialize)]
10199pub struct ContractTypeDistribution {
10200 #[serde(default = "default_fixed_price_pct")]
10202 pub fixed_price: f64,
10203 #[serde(default = "default_blanket_pct")]
10205 pub blanket: f64,
10206 #[serde(default = "default_time_materials_pct")]
10208 pub time_and_materials: f64,
10209 #[serde(default = "default_service_agreement_pct")]
10211 pub service_agreement: f64,
10212}
10213
10214impl Default for ContractTypeDistribution {
10215 fn default() -> Self {
10216 Self {
10217 fixed_price: default_fixed_price_pct(),
10218 blanket: default_blanket_pct(),
10219 time_and_materials: default_time_materials_pct(),
10220 service_agreement: default_service_agreement_pct(),
10221 }
10222 }
10223}
10224
10225fn default_fixed_price_pct() -> f64 {
10226 0.40
10227}
10228fn default_blanket_pct() -> f64 {
10229 0.30
10230}
10231fn default_time_materials_pct() -> f64 {
10232 0.15
10233}
10234fn default_service_agreement_pct() -> f64 {
10235 0.15
10236}
10237
10238#[derive(Debug, Clone, Serialize, Deserialize)]
10240pub struct CatalogConfig {
10241 #[serde(default = "default_preferred_vendor_flag_rate")]
10243 pub preferred_vendor_flag_rate: f64,
10244 #[serde(default = "default_multi_source_rate")]
10246 pub multi_source_rate: f64,
10247}
10248
10249impl Default for CatalogConfig {
10250 fn default() -> Self {
10251 Self {
10252 preferred_vendor_flag_rate: default_preferred_vendor_flag_rate(),
10253 multi_source_rate: default_multi_source_rate(),
10254 }
10255 }
10256}
10257
10258fn default_preferred_vendor_flag_rate() -> f64 {
10259 0.70
10260}
10261fn default_multi_source_rate() -> f64 {
10262 0.25
10263}
10264
10265#[derive(Debug, Clone, Serialize, Deserialize)]
10267pub struct ScorecardConfig {
10268 #[serde(default = "default_scorecard_frequency")]
10270 pub frequency: String,
10271 #[serde(default = "default_otd_weight")]
10273 pub on_time_delivery_weight: f64,
10274 #[serde(default = "default_quality_score_weight")]
10276 pub quality_weight: f64,
10277 #[serde(default = "default_price_score_weight")]
10279 pub price_weight: f64,
10280 #[serde(default = "default_responsiveness_weight")]
10282 pub responsiveness_weight: f64,
10283 #[serde(default = "default_grade_a_threshold")]
10285 pub grade_a_threshold: f64,
10286 #[serde(default = "default_grade_b_threshold")]
10288 pub grade_b_threshold: f64,
10289 #[serde(default = "default_grade_c_threshold")]
10291 pub grade_c_threshold: f64,
10292}
10293
10294impl Default for ScorecardConfig {
10295 fn default() -> Self {
10296 Self {
10297 frequency: default_scorecard_frequency(),
10298 on_time_delivery_weight: default_otd_weight(),
10299 quality_weight: default_quality_score_weight(),
10300 price_weight: default_price_score_weight(),
10301 responsiveness_weight: default_responsiveness_weight(),
10302 grade_a_threshold: default_grade_a_threshold(),
10303 grade_b_threshold: default_grade_b_threshold(),
10304 grade_c_threshold: default_grade_c_threshold(),
10305 }
10306 }
10307}
10308
10309fn default_scorecard_frequency() -> String {
10310 "quarterly".to_string()
10311}
10312fn default_otd_weight() -> f64 {
10313 0.30
10314}
10315fn default_quality_score_weight() -> f64 {
10316 0.30
10317}
10318fn default_price_score_weight() -> f64 {
10319 0.25
10320}
10321fn default_responsiveness_weight() -> f64 {
10322 0.15
10323}
10324fn default_grade_a_threshold() -> f64 {
10325 90.0
10326}
10327fn default_grade_b_threshold() -> f64 {
10328 75.0
10329}
10330fn default_grade_c_threshold() -> f64 {
10331 60.0
10332}
10333
10334#[derive(Debug, Clone, Serialize, Deserialize)]
10336pub struct P2PIntegrationConfig {
10337 #[serde(default = "default_off_contract_rate")]
10339 pub off_contract_rate: f64,
10340 #[serde(default = "default_price_tolerance")]
10342 pub price_tolerance: f64,
10343 #[serde(default)]
10345 pub catalog_enforcement: bool,
10346}
10347
10348impl Default for P2PIntegrationConfig {
10349 fn default() -> Self {
10350 Self {
10351 off_contract_rate: default_off_contract_rate(),
10352 price_tolerance: default_price_tolerance(),
10353 catalog_enforcement: false,
10354 }
10355 }
10356}
10357
10358fn default_off_contract_rate() -> f64 {
10359 0.15
10360}
10361fn default_price_tolerance() -> f64 {
10362 0.02
10363}
10364
10365#[derive(Debug, Clone, Serialize, Deserialize)]
10369pub struct FinancialReportingConfig {
10370 #[serde(default)]
10372 pub enabled: bool,
10373 #[serde(default = "default_true")]
10375 pub generate_balance_sheet: bool,
10376 #[serde(default = "default_true")]
10378 pub generate_income_statement: bool,
10379 #[serde(default = "default_true")]
10381 pub generate_cash_flow: bool,
10382 #[serde(default = "default_true")]
10384 pub generate_changes_in_equity: bool,
10385 #[serde(default = "default_comparative_periods")]
10387 pub comparative_periods: u32,
10388 #[serde(default)]
10390 pub management_kpis: ManagementKpisConfig,
10391 #[serde(default)]
10393 pub budgets: BudgetConfig,
10394}
10395
10396impl Default for FinancialReportingConfig {
10397 fn default() -> Self {
10398 Self {
10399 enabled: false,
10400 generate_balance_sheet: true,
10401 generate_income_statement: true,
10402 generate_cash_flow: true,
10403 generate_changes_in_equity: true,
10404 comparative_periods: default_comparative_periods(),
10405 management_kpis: ManagementKpisConfig::default(),
10406 budgets: BudgetConfig::default(),
10407 }
10408 }
10409}
10410
10411fn default_comparative_periods() -> u32 {
10412 1
10413}
10414
10415#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10417pub struct ManagementKpisConfig {
10418 #[serde(default)]
10420 pub enabled: bool,
10421 #[serde(default = "default_kpi_frequency")]
10423 pub frequency: String,
10424}
10425
10426fn default_kpi_frequency() -> String {
10427 "monthly".to_string()
10428}
10429
10430#[derive(Debug, Clone, Serialize, Deserialize)]
10432pub struct BudgetConfig {
10433 #[serde(default)]
10435 pub enabled: bool,
10436 #[serde(default = "default_revenue_growth_rate")]
10438 pub revenue_growth_rate: f64,
10439 #[serde(default = "default_expense_inflation_rate")]
10441 pub expense_inflation_rate: f64,
10442 #[serde(default = "default_variance_noise")]
10444 pub variance_noise: f64,
10445}
10446
10447impl Default for BudgetConfig {
10448 fn default() -> Self {
10449 Self {
10450 enabled: false,
10451 revenue_growth_rate: default_revenue_growth_rate(),
10452 expense_inflation_rate: default_expense_inflation_rate(),
10453 variance_noise: default_variance_noise(),
10454 }
10455 }
10456}
10457
10458fn default_revenue_growth_rate() -> f64 {
10459 0.05
10460}
10461fn default_expense_inflation_rate() -> f64 {
10462 0.03
10463}
10464fn default_variance_noise() -> f64 {
10465 0.10
10466}
10467
10468#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10472pub struct HrConfig {
10473 #[serde(default)]
10475 pub enabled: bool,
10476 #[serde(default)]
10478 pub payroll: PayrollConfig,
10479 #[serde(default)]
10481 pub time_attendance: TimeAttendanceConfig,
10482 #[serde(default)]
10484 pub expenses: ExpenseConfig,
10485}
10486
10487#[derive(Debug, Clone, Serialize, Deserialize)]
10489pub struct PayrollConfig {
10490 #[serde(default = "default_true")]
10492 pub enabled: bool,
10493 #[serde(default = "default_pay_frequency")]
10495 pub pay_frequency: String,
10496 #[serde(default)]
10498 pub salary_ranges: PayrollSalaryRanges,
10499 #[serde(default)]
10501 pub tax_rates: PayrollTaxRates,
10502 #[serde(default = "default_benefits_enrollment_rate")]
10504 pub benefits_enrollment_rate: f64,
10505 #[serde(default = "default_retirement_participation_rate")]
10507 pub retirement_participation_rate: f64,
10508}
10509
10510impl Default for PayrollConfig {
10511 fn default() -> Self {
10512 Self {
10513 enabled: true,
10514 pay_frequency: default_pay_frequency(),
10515 salary_ranges: PayrollSalaryRanges::default(),
10516 tax_rates: PayrollTaxRates::default(),
10517 benefits_enrollment_rate: default_benefits_enrollment_rate(),
10518 retirement_participation_rate: default_retirement_participation_rate(),
10519 }
10520 }
10521}
10522
10523fn default_pay_frequency() -> String {
10524 "monthly".to_string()
10525}
10526fn default_benefits_enrollment_rate() -> f64 {
10527 0.60
10528}
10529fn default_retirement_participation_rate() -> f64 {
10530 0.45
10531}
10532
10533#[derive(Debug, Clone, Serialize, Deserialize)]
10535pub struct PayrollSalaryRanges {
10536 #[serde(default = "default_staff_min")]
10538 pub staff_min: f64,
10539 #[serde(default = "default_staff_max")]
10540 pub staff_max: f64,
10541 #[serde(default = "default_manager_min")]
10543 pub manager_min: f64,
10544 #[serde(default = "default_manager_max")]
10545 pub manager_max: f64,
10546 #[serde(default = "default_director_min")]
10548 pub director_min: f64,
10549 #[serde(default = "default_director_max")]
10550 pub director_max: f64,
10551 #[serde(default = "default_executive_min")]
10553 pub executive_min: f64,
10554 #[serde(default = "default_executive_max")]
10555 pub executive_max: f64,
10556}
10557
10558impl Default for PayrollSalaryRanges {
10559 fn default() -> Self {
10560 Self {
10561 staff_min: default_staff_min(),
10562 staff_max: default_staff_max(),
10563 manager_min: default_manager_min(),
10564 manager_max: default_manager_max(),
10565 director_min: default_director_min(),
10566 director_max: default_director_max(),
10567 executive_min: default_executive_min(),
10568 executive_max: default_executive_max(),
10569 }
10570 }
10571}
10572
10573fn default_staff_min() -> f64 {
10574 50_000.0
10575}
10576fn default_staff_max() -> f64 {
10577 70_000.0
10578}
10579fn default_manager_min() -> f64 {
10580 80_000.0
10581}
10582fn default_manager_max() -> f64 {
10583 120_000.0
10584}
10585fn default_director_min() -> f64 {
10586 120_000.0
10587}
10588fn default_director_max() -> f64 {
10589 180_000.0
10590}
10591fn default_executive_min() -> f64 {
10592 180_000.0
10593}
10594fn default_executive_max() -> f64 {
10595 350_000.0
10596}
10597
10598#[derive(Debug, Clone, Serialize, Deserialize)]
10600pub struct PayrollTaxRates {
10601 #[serde(default = "default_federal_rate")]
10603 pub federal_effective: f64,
10604 #[serde(default = "default_state_rate")]
10606 pub state_effective: f64,
10607 #[serde(default = "default_fica_rate")]
10609 pub fica: f64,
10610}
10611
10612impl Default for PayrollTaxRates {
10613 fn default() -> Self {
10614 Self {
10615 federal_effective: default_federal_rate(),
10616 state_effective: default_state_rate(),
10617 fica: default_fica_rate(),
10618 }
10619 }
10620}
10621
10622fn default_federal_rate() -> f64 {
10623 0.22
10624}
10625fn default_state_rate() -> f64 {
10626 0.05
10627}
10628fn default_fica_rate() -> f64 {
10629 0.0765
10630}
10631
10632#[derive(Debug, Clone, Serialize, Deserialize)]
10634pub struct TimeAttendanceConfig {
10635 #[serde(default = "default_true")]
10637 pub enabled: bool,
10638 #[serde(default = "default_overtime_rate")]
10640 pub overtime_rate: f64,
10641}
10642
10643impl Default for TimeAttendanceConfig {
10644 fn default() -> Self {
10645 Self {
10646 enabled: true,
10647 overtime_rate: default_overtime_rate(),
10648 }
10649 }
10650}
10651
10652fn default_overtime_rate() -> f64 {
10653 0.10
10654}
10655
10656#[derive(Debug, Clone, Serialize, Deserialize)]
10658pub struct ExpenseConfig {
10659 #[serde(default = "default_true")]
10661 pub enabled: bool,
10662 #[serde(default = "default_expense_submission_rate")]
10664 pub submission_rate: f64,
10665 #[serde(default = "default_policy_violation_rate")]
10667 pub policy_violation_rate: f64,
10668}
10669
10670impl Default for ExpenseConfig {
10671 fn default() -> Self {
10672 Self {
10673 enabled: true,
10674 submission_rate: default_expense_submission_rate(),
10675 policy_violation_rate: default_policy_violation_rate(),
10676 }
10677 }
10678}
10679
10680fn default_expense_submission_rate() -> f64 {
10681 0.30
10682}
10683fn default_policy_violation_rate() -> f64 {
10684 0.08
10685}
10686
10687#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10691pub struct ManufacturingProcessConfig {
10692 #[serde(default)]
10694 pub enabled: bool,
10695 #[serde(default)]
10697 pub production_orders: ProductionOrderConfig,
10698 #[serde(default)]
10700 pub costing: ManufacturingCostingConfig,
10701 #[serde(default)]
10703 pub routing: RoutingConfig,
10704}
10705
10706#[derive(Debug, Clone, Serialize, Deserialize)]
10708pub struct ProductionOrderConfig {
10709 #[serde(default = "default_prod_orders_per_month")]
10711 pub orders_per_month: u32,
10712 #[serde(default = "default_prod_avg_batch_size")]
10714 pub avg_batch_size: u32,
10715 #[serde(default = "default_prod_yield_rate")]
10717 pub yield_rate: f64,
10718 #[serde(default = "default_prod_make_to_order_rate")]
10720 pub make_to_order_rate: f64,
10721 #[serde(default = "default_prod_rework_rate")]
10723 pub rework_rate: f64,
10724}
10725
10726impl Default for ProductionOrderConfig {
10727 fn default() -> Self {
10728 Self {
10729 orders_per_month: default_prod_orders_per_month(),
10730 avg_batch_size: default_prod_avg_batch_size(),
10731 yield_rate: default_prod_yield_rate(),
10732 make_to_order_rate: default_prod_make_to_order_rate(),
10733 rework_rate: default_prod_rework_rate(),
10734 }
10735 }
10736}
10737
10738fn default_prod_orders_per_month() -> u32 {
10739 50
10740}
10741fn default_prod_avg_batch_size() -> u32 {
10742 100
10743}
10744fn default_prod_yield_rate() -> f64 {
10745 0.97
10746}
10747fn default_prod_make_to_order_rate() -> f64 {
10748 0.20
10749}
10750fn default_prod_rework_rate() -> f64 {
10751 0.03
10752}
10753
10754#[derive(Debug, Clone, Serialize, Deserialize)]
10756pub struct ManufacturingCostingConfig {
10757 #[serde(default = "default_labor_rate")]
10759 pub labor_rate_per_hour: f64,
10760 #[serde(default = "default_overhead_rate")]
10762 pub overhead_rate: f64,
10763 #[serde(default = "default_cost_update_frequency")]
10765 pub standard_cost_update_frequency: String,
10766}
10767
10768impl Default for ManufacturingCostingConfig {
10769 fn default() -> Self {
10770 Self {
10771 labor_rate_per_hour: default_labor_rate(),
10772 overhead_rate: default_overhead_rate(),
10773 standard_cost_update_frequency: default_cost_update_frequency(),
10774 }
10775 }
10776}
10777
10778fn default_labor_rate() -> f64 {
10779 35.0
10780}
10781fn default_overhead_rate() -> f64 {
10782 1.50
10783}
10784fn default_cost_update_frequency() -> String {
10785 "quarterly".to_string()
10786}
10787
10788#[derive(Debug, Clone, Serialize, Deserialize)]
10790pub struct RoutingConfig {
10791 #[serde(default = "default_avg_operations")]
10793 pub avg_operations: u32,
10794 #[serde(default = "default_setup_time")]
10796 pub setup_time_hours: f64,
10797 #[serde(default = "default_run_time_variation")]
10799 pub run_time_variation: f64,
10800}
10801
10802impl Default for RoutingConfig {
10803 fn default() -> Self {
10804 Self {
10805 avg_operations: default_avg_operations(),
10806 setup_time_hours: default_setup_time(),
10807 run_time_variation: default_run_time_variation(),
10808 }
10809 }
10810}
10811
10812fn default_avg_operations() -> u32 {
10813 4
10814}
10815fn default_setup_time() -> f64 {
10816 1.5
10817}
10818fn default_run_time_variation() -> f64 {
10819 0.15
10820}
10821
10822#[derive(Debug, Clone, Serialize, Deserialize)]
10826pub struct SalesQuoteConfig {
10827 #[serde(default)]
10829 pub enabled: bool,
10830 #[serde(default = "default_quotes_per_month")]
10832 pub quotes_per_month: u32,
10833 #[serde(default = "default_quote_win_rate")]
10835 pub win_rate: f64,
10836 #[serde(default = "default_quote_validity_days")]
10838 pub validity_days: u32,
10839}
10840
10841impl Default for SalesQuoteConfig {
10842 fn default() -> Self {
10843 Self {
10844 enabled: false,
10845 quotes_per_month: default_quotes_per_month(),
10846 win_rate: default_quote_win_rate(),
10847 validity_days: default_quote_validity_days(),
10848 }
10849 }
10850}
10851
10852fn default_quotes_per_month() -> u32 {
10853 30
10854}
10855fn default_quote_win_rate() -> f64 {
10856 0.35
10857}
10858fn default_quote_validity_days() -> u32 {
10859 30
10860}
10861
10862#[cfg(test)]
10863#[allow(clippy::unwrap_used)]
10864mod tests {
10865 use super::*;
10866 use crate::presets::demo_preset;
10867
10868 #[test]
10873 fn test_config_yaml_roundtrip() {
10874 let config = demo_preset();
10875 let yaml = serde_yaml::to_string(&config).expect("Failed to serialize to YAML");
10876 let deserialized: GeneratorConfig =
10877 serde_yaml::from_str(&yaml).expect("Failed to deserialize from YAML");
10878
10879 assert_eq!(
10880 config.global.period_months,
10881 deserialized.global.period_months
10882 );
10883 assert_eq!(config.global.industry, deserialized.global.industry);
10884 assert_eq!(config.companies.len(), deserialized.companies.len());
10885 assert_eq!(config.companies[0].code, deserialized.companies[0].code);
10886 }
10887
10888 #[test]
10889 fn test_config_json_roundtrip() {
10890 let mut config = demo_preset();
10892 config.master_data.employees.approval_limits.executive = 1e12;
10894
10895 let json = serde_json::to_string(&config).expect("Failed to serialize to JSON");
10896 let deserialized: GeneratorConfig =
10897 serde_json::from_str(&json).expect("Failed to deserialize from JSON");
10898
10899 assert_eq!(
10900 config.global.period_months,
10901 deserialized.global.period_months
10902 );
10903 assert_eq!(config.global.industry, deserialized.global.industry);
10904 assert_eq!(config.companies.len(), deserialized.companies.len());
10905 }
10906
10907 #[test]
10908 fn test_transaction_volume_serialization() {
10909 let volumes = vec![
10911 (TransactionVolume::TenK, "ten_k"),
10912 (TransactionVolume::HundredK, "hundred_k"),
10913 (TransactionVolume::OneM, "one_m"),
10914 (TransactionVolume::TenM, "ten_m"),
10915 (TransactionVolume::HundredM, "hundred_m"),
10916 ];
10917
10918 for (volume, expected_key) in volumes {
10919 let json = serde_json::to_string(&volume).expect("Failed to serialize");
10920 assert!(
10921 json.contains(expected_key),
10922 "Expected {} in JSON: {}",
10923 expected_key,
10924 json
10925 );
10926 }
10927 }
10928
10929 #[test]
10930 fn test_transaction_volume_custom_serialization() {
10931 let volume = TransactionVolume::Custom(12345);
10932 let json = serde_json::to_string(&volume).expect("Failed to serialize");
10933 let deserialized: TransactionVolume =
10934 serde_json::from_str(&json).expect("Failed to deserialize");
10935 assert_eq!(deserialized.count(), 12345);
10936 }
10937
10938 #[test]
10939 fn test_output_mode_serialization() {
10940 let modes = vec![
10941 OutputMode::Streaming,
10942 OutputMode::FlatFile,
10943 OutputMode::Both,
10944 ];
10945
10946 for mode in modes {
10947 let json = serde_json::to_string(&mode).expect("Failed to serialize");
10948 let deserialized: OutputMode =
10949 serde_json::from_str(&json).expect("Failed to deserialize");
10950 assert!(format!("{:?}", mode) == format!("{:?}", deserialized));
10951 }
10952 }
10953
10954 #[test]
10955 fn test_file_format_serialization() {
10956 let formats = vec![
10957 FileFormat::Csv,
10958 FileFormat::Parquet,
10959 FileFormat::Json,
10960 FileFormat::JsonLines,
10961 ];
10962
10963 for format in formats {
10964 let json = serde_json::to_string(&format).expect("Failed to serialize");
10965 let deserialized: FileFormat =
10966 serde_json::from_str(&json).expect("Failed to deserialize");
10967 assert!(format!("{:?}", format) == format!("{:?}", deserialized));
10968 }
10969 }
10970
10971 #[test]
10972 fn test_compression_algorithm_serialization() {
10973 let algos = vec![
10974 CompressionAlgorithm::Gzip,
10975 CompressionAlgorithm::Zstd,
10976 CompressionAlgorithm::Lz4,
10977 CompressionAlgorithm::Snappy,
10978 ];
10979
10980 for algo in algos {
10981 let json = serde_json::to_string(&algo).expect("Failed to serialize");
10982 let deserialized: CompressionAlgorithm =
10983 serde_json::from_str(&json).expect("Failed to deserialize");
10984 assert!(format!("{:?}", algo) == format!("{:?}", deserialized));
10985 }
10986 }
10987
10988 #[test]
10989 fn test_transfer_pricing_method_serialization() {
10990 let methods = vec![
10991 TransferPricingMethod::CostPlus,
10992 TransferPricingMethod::ComparableUncontrolled,
10993 TransferPricingMethod::ResalePrice,
10994 TransferPricingMethod::TransactionalNetMargin,
10995 TransferPricingMethod::ProfitSplit,
10996 ];
10997
10998 for method in methods {
10999 let json = serde_json::to_string(&method).expect("Failed to serialize");
11000 let deserialized: TransferPricingMethod =
11001 serde_json::from_str(&json).expect("Failed to deserialize");
11002 assert!(format!("{:?}", method) == format!("{:?}", deserialized));
11003 }
11004 }
11005
11006 #[test]
11007 fn test_benford_exemption_serialization() {
11008 let exemptions = vec![
11009 BenfordExemption::Recurring,
11010 BenfordExemption::Payroll,
11011 BenfordExemption::FixedFees,
11012 BenfordExemption::RoundAmounts,
11013 ];
11014
11015 for exemption in exemptions {
11016 let json = serde_json::to_string(&exemption).expect("Failed to serialize");
11017 let deserialized: BenfordExemption =
11018 serde_json::from_str(&json).expect("Failed to deserialize");
11019 assert!(format!("{:?}", exemption) == format!("{:?}", deserialized));
11020 }
11021 }
11022
11023 #[test]
11028 fn test_global_config_defaults() {
11029 let yaml = r#"
11030 industry: manufacturing
11031 start_date: "2024-01-01"
11032 period_months: 6
11033 "#;
11034 let config: GlobalConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
11035 assert_eq!(config.group_currency, "USD");
11036 assert!(config.parallel);
11037 assert_eq!(config.worker_threads, 0);
11038 assert_eq!(config.memory_limit_mb, 0);
11039 }
11040
11041 #[test]
11042 fn test_fraud_config_defaults() {
11043 let config = FraudConfig::default();
11044 assert!(!config.enabled);
11045 assert_eq!(config.fraud_rate, 0.005);
11046 assert!(!config.clustering_enabled);
11047 }
11048
11049 #[test]
11050 fn test_internal_controls_config_defaults() {
11051 let config = InternalControlsConfig::default();
11052 assert!(!config.enabled);
11053 assert_eq!(config.exception_rate, 0.02);
11054 assert_eq!(config.sod_violation_rate, 0.01);
11055 assert!(config.export_control_master_data);
11056 assert_eq!(config.sox_materiality_threshold, 10000.0);
11057 assert!(config.coso_enabled);
11059 assert!(!config.include_entity_level_controls);
11060 assert_eq!(config.target_maturity_level, "mixed");
11061 }
11062
11063 #[test]
11064 fn test_output_config_defaults() {
11065 let config = OutputConfig::default();
11066 assert!(matches!(config.mode, OutputMode::FlatFile));
11067 assert_eq!(config.formats, vec![FileFormat::Parquet]);
11068 assert!(config.compression.enabled);
11069 assert!(matches!(
11070 config.compression.algorithm,
11071 CompressionAlgorithm::Zstd
11072 ));
11073 assert!(config.include_acdoca);
11074 assert!(!config.include_bseg);
11075 assert!(config.partition_by_period);
11076 assert!(!config.partition_by_company);
11077 }
11078
11079 #[test]
11080 fn test_approval_config_defaults() {
11081 let config = ApprovalConfig::default();
11082 assert!(!config.enabled);
11083 assert_eq!(config.auto_approve_threshold, 1000.0);
11084 assert_eq!(config.rejection_rate, 0.02);
11085 assert_eq!(config.revision_rate, 0.05);
11086 assert_eq!(config.average_approval_delay_hours, 4.0);
11087 assert_eq!(config.thresholds.len(), 4);
11088 }
11089
11090 #[test]
11091 fn test_p2p_flow_config_defaults() {
11092 let config = P2PFlowConfig::default();
11093 assert!(config.enabled);
11094 assert_eq!(config.three_way_match_rate, 0.95);
11095 assert_eq!(config.partial_delivery_rate, 0.15);
11096 assert_eq!(config.average_po_to_gr_days, 14);
11097 }
11098
11099 #[test]
11100 fn test_o2c_flow_config_defaults() {
11101 let config = O2CFlowConfig::default();
11102 assert!(config.enabled);
11103 assert_eq!(config.credit_check_failure_rate, 0.02);
11104 assert_eq!(config.return_rate, 0.03);
11105 assert_eq!(config.bad_debt_rate, 0.01);
11106 }
11107
11108 #[test]
11109 fn test_balance_config_defaults() {
11110 let config = BalanceConfig::default();
11111 assert!(!config.generate_opening_balances);
11112 assert!(config.generate_trial_balances);
11113 assert_eq!(config.target_gross_margin, 0.35);
11114 assert!(config.validate_balance_equation);
11115 assert!(config.reconcile_subledgers);
11116 }
11117
11118 #[test]
11123 fn test_partial_config_with_defaults() {
11124 let yaml = r#"
11126 global:
11127 industry: manufacturing
11128 start_date: "2024-01-01"
11129 period_months: 3
11130 companies:
11131 - code: "TEST"
11132 name: "Test Company"
11133 currency: "USD"
11134 country: "US"
11135 annual_transaction_volume: ten_k
11136 chart_of_accounts:
11137 complexity: small
11138 output:
11139 output_directory: "./output"
11140 "#;
11141
11142 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
11143 assert_eq!(config.global.period_months, 3);
11144 assert_eq!(config.companies.len(), 1);
11145 assert!(!config.fraud.enabled); assert!(!config.internal_controls.enabled); }
11148
11149 #[test]
11150 fn test_config_with_fraud_enabled() {
11151 let yaml = r#"
11152 global:
11153 industry: retail
11154 start_date: "2024-01-01"
11155 period_months: 12
11156 companies:
11157 - code: "RETAIL"
11158 name: "Retail Co"
11159 currency: "USD"
11160 country: "US"
11161 annual_transaction_volume: hundred_k
11162 chart_of_accounts:
11163 complexity: medium
11164 output:
11165 output_directory: "./output"
11166 fraud:
11167 enabled: true
11168 fraud_rate: 0.05
11169 clustering_enabled: true
11170 "#;
11171
11172 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
11173 assert!(config.fraud.enabled);
11174 assert_eq!(config.fraud.fraud_rate, 0.05);
11175 assert!(config.fraud.clustering_enabled);
11176 }
11177
11178 #[test]
11179 fn test_config_with_multiple_companies() {
11180 let yaml = r#"
11181 global:
11182 industry: manufacturing
11183 start_date: "2024-01-01"
11184 period_months: 6
11185 companies:
11186 - code: "HQ"
11187 name: "Headquarters"
11188 currency: "USD"
11189 country: "US"
11190 annual_transaction_volume: hundred_k
11191 volume_weight: 1.0
11192 - code: "EU"
11193 name: "European Subsidiary"
11194 currency: "EUR"
11195 country: "DE"
11196 annual_transaction_volume: hundred_k
11197 volume_weight: 0.5
11198 - code: "APAC"
11199 name: "Asia Pacific"
11200 currency: "JPY"
11201 country: "JP"
11202 annual_transaction_volume: ten_k
11203 volume_weight: 0.3
11204 chart_of_accounts:
11205 complexity: large
11206 output:
11207 output_directory: "./output"
11208 "#;
11209
11210 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
11211 assert_eq!(config.companies.len(), 3);
11212 assert_eq!(config.companies[0].code, "HQ");
11213 assert_eq!(config.companies[1].currency, "EUR");
11214 assert_eq!(config.companies[2].volume_weight, 0.3);
11215 }
11216
11217 #[test]
11218 fn test_intercompany_config() {
11219 let yaml = r#"
11220 enabled: true
11221 ic_transaction_rate: 0.20
11222 transfer_pricing_method: cost_plus
11223 markup_percent: 0.08
11224 generate_matched_pairs: true
11225 generate_eliminations: true
11226 "#;
11227
11228 let config: IntercompanyConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
11229 assert!(config.enabled);
11230 assert_eq!(config.ic_transaction_rate, 0.20);
11231 assert!(matches!(
11232 config.transfer_pricing_method,
11233 TransferPricingMethod::CostPlus
11234 ));
11235 assert_eq!(config.markup_percent, 0.08);
11236 assert!(config.generate_eliminations);
11237 }
11238
11239 #[test]
11244 fn test_company_config_defaults() {
11245 let yaml = r#"
11246 code: "TEST"
11247 name: "Test Company"
11248 currency: "USD"
11249 country: "US"
11250 annual_transaction_volume: ten_k
11251 "#;
11252
11253 let config: CompanyConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
11254 assert_eq!(config.fiscal_year_variant, "K4"); assert_eq!(config.volume_weight, 1.0); }
11257
11258 #[test]
11263 fn test_coa_config_defaults() {
11264 let yaml = r#"
11265 complexity: medium
11266 "#;
11267
11268 let config: ChartOfAccountsConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
11269 assert!(config.industry_specific); assert!(config.custom_accounts.is_none());
11271 assert_eq!(config.min_hierarchy_depth, 2); assert_eq!(config.max_hierarchy_depth, 5); }
11274
11275 #[test]
11280 fn test_accounting_standards_config_defaults() {
11281 let config = AccountingStandardsConfig::default();
11282 assert!(!config.enabled);
11283 assert!(matches!(
11284 config.framework,
11285 AccountingFrameworkConfig::UsGaap
11286 ));
11287 assert!(!config.revenue_recognition.enabled);
11288 assert!(!config.leases.enabled);
11289 assert!(!config.fair_value.enabled);
11290 assert!(!config.impairment.enabled);
11291 assert!(!config.generate_differences);
11292 }
11293
11294 #[test]
11295 fn test_accounting_standards_config_yaml() {
11296 let yaml = r#"
11297 enabled: true
11298 framework: ifrs
11299 revenue_recognition:
11300 enabled: true
11301 generate_contracts: true
11302 avg_obligations_per_contract: 2.5
11303 variable_consideration_rate: 0.20
11304 over_time_recognition_rate: 0.35
11305 contract_count: 150
11306 leases:
11307 enabled: true
11308 lease_count: 75
11309 finance_lease_percent: 0.25
11310 avg_lease_term_months: 48
11311 generate_differences: true
11312 "#;
11313
11314 let config: AccountingStandardsConfig =
11315 serde_yaml::from_str(yaml).expect("Failed to parse");
11316 assert!(config.enabled);
11317 assert!(matches!(config.framework, AccountingFrameworkConfig::Ifrs));
11318 assert!(config.revenue_recognition.enabled);
11319 assert_eq!(config.revenue_recognition.contract_count, 150);
11320 assert_eq!(config.revenue_recognition.avg_obligations_per_contract, 2.5);
11321 assert!(config.leases.enabled);
11322 assert_eq!(config.leases.lease_count, 75);
11323 assert_eq!(config.leases.finance_lease_percent, 0.25);
11324 assert!(config.generate_differences);
11325 }
11326
11327 #[test]
11328 fn test_accounting_framework_serialization() {
11329 let frameworks = [
11330 AccountingFrameworkConfig::UsGaap,
11331 AccountingFrameworkConfig::Ifrs,
11332 AccountingFrameworkConfig::DualReporting,
11333 ];
11334
11335 for framework in frameworks {
11336 let json = serde_json::to_string(&framework).expect("Failed to serialize");
11337 let deserialized: AccountingFrameworkConfig =
11338 serde_json::from_str(&json).expect("Failed to deserialize");
11339 assert!(format!("{:?}", framework) == format!("{:?}", deserialized));
11340 }
11341 }
11342
11343 #[test]
11344 fn test_revenue_recognition_config_defaults() {
11345 let config = RevenueRecognitionConfig::default();
11346 assert!(!config.enabled);
11347 assert!(config.generate_contracts);
11348 assert_eq!(config.avg_obligations_per_contract, 2.0);
11349 assert_eq!(config.variable_consideration_rate, 0.15);
11350 assert_eq!(config.over_time_recognition_rate, 0.30);
11351 assert_eq!(config.contract_count, 100);
11352 }
11353
11354 #[test]
11355 fn test_lease_accounting_config_defaults() {
11356 let config = LeaseAccountingConfig::default();
11357 assert!(!config.enabled);
11358 assert_eq!(config.lease_count, 50);
11359 assert_eq!(config.finance_lease_percent, 0.30);
11360 assert_eq!(config.avg_lease_term_months, 60);
11361 assert!(config.generate_amortization);
11362 assert_eq!(config.real_estate_percent, 0.40);
11363 }
11364
11365 #[test]
11366 fn test_fair_value_config_defaults() {
11367 let config = FairValueConfig::default();
11368 assert!(!config.enabled);
11369 assert_eq!(config.measurement_count, 25);
11370 assert_eq!(config.level1_percent, 0.40);
11371 assert_eq!(config.level2_percent, 0.35);
11372 assert_eq!(config.level3_percent, 0.25);
11373 assert!(!config.include_sensitivity_analysis);
11374 }
11375
11376 #[test]
11377 fn test_impairment_config_defaults() {
11378 let config = ImpairmentConfig::default();
11379 assert!(!config.enabled);
11380 assert_eq!(config.test_count, 15);
11381 assert_eq!(config.impairment_rate, 0.10);
11382 assert!(config.generate_projections);
11383 assert!(!config.include_goodwill);
11384 }
11385
11386 #[test]
11391 fn test_audit_standards_config_defaults() {
11392 let config = AuditStandardsConfig::default();
11393 assert!(!config.enabled);
11394 assert!(!config.isa_compliance.enabled);
11395 assert!(!config.analytical_procedures.enabled);
11396 assert!(!config.confirmations.enabled);
11397 assert!(!config.opinion.enabled);
11398 assert!(!config.generate_audit_trail);
11399 assert!(!config.sox.enabled);
11400 assert!(!config.pcaob.enabled);
11401 }
11402
11403 #[test]
11404 fn test_audit_standards_config_yaml() {
11405 let yaml = r#"
11406 enabled: true
11407 isa_compliance:
11408 enabled: true
11409 compliance_level: comprehensive
11410 generate_isa_mappings: true
11411 include_pcaob: true
11412 framework: dual
11413 analytical_procedures:
11414 enabled: true
11415 procedures_per_account: 5
11416 variance_probability: 0.25
11417 confirmations:
11418 enabled: true
11419 confirmation_count: 75
11420 positive_response_rate: 0.90
11421 exception_rate: 0.08
11422 opinion:
11423 enabled: true
11424 generate_kam: true
11425 average_kam_count: 4
11426 sox:
11427 enabled: true
11428 generate_302_certifications: true
11429 generate_404_assessments: true
11430 material_weakness_rate: 0.03
11431 pcaob:
11432 enabled: true
11433 is_pcaob_audit: true
11434 include_icfr_opinion: true
11435 generate_audit_trail: true
11436 "#;
11437
11438 let config: AuditStandardsConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
11439 assert!(config.enabled);
11440 assert!(config.isa_compliance.enabled);
11441 assert_eq!(config.isa_compliance.compliance_level, "comprehensive");
11442 assert!(config.isa_compliance.include_pcaob);
11443 assert_eq!(config.isa_compliance.framework, "dual");
11444 assert!(config.analytical_procedures.enabled);
11445 assert_eq!(config.analytical_procedures.procedures_per_account, 5);
11446 assert!(config.confirmations.enabled);
11447 assert_eq!(config.confirmations.confirmation_count, 75);
11448 assert!(config.opinion.enabled);
11449 assert_eq!(config.opinion.average_kam_count, 4);
11450 assert!(config.sox.enabled);
11451 assert!(config.sox.generate_302_certifications);
11452 assert_eq!(config.sox.material_weakness_rate, 0.03);
11453 assert!(config.pcaob.enabled);
11454 assert!(config.pcaob.is_pcaob_audit);
11455 assert!(config.pcaob.include_icfr_opinion);
11456 assert!(config.generate_audit_trail);
11457 }
11458
11459 #[test]
11460 fn test_isa_compliance_config_defaults() {
11461 let config = IsaComplianceConfig::default();
11462 assert!(!config.enabled);
11463 assert_eq!(config.compliance_level, "standard");
11464 assert!(config.generate_isa_mappings);
11465 assert!(config.generate_coverage_summary);
11466 assert!(!config.include_pcaob);
11467 assert_eq!(config.framework, "isa");
11468 }
11469
11470 #[test]
11471 fn test_sox_compliance_config_defaults() {
11472 let config = SoxComplianceConfig::default();
11473 assert!(!config.enabled);
11474 assert!(config.generate_302_certifications);
11475 assert!(config.generate_404_assessments);
11476 assert_eq!(config.materiality_threshold, 10000.0);
11477 assert_eq!(config.material_weakness_rate, 0.02);
11478 assert_eq!(config.significant_deficiency_rate, 0.08);
11479 }
11480
11481 #[test]
11482 fn test_pcaob_config_defaults() {
11483 let config = PcaobConfig::default();
11484 assert!(!config.enabled);
11485 assert!(!config.is_pcaob_audit);
11486 assert!(config.generate_cam);
11487 assert!(!config.include_icfr_opinion);
11488 assert!(!config.generate_standard_mappings);
11489 }
11490
11491 #[test]
11492 fn test_config_with_standards_enabled() {
11493 let yaml = r#"
11494 global:
11495 industry: financial_services
11496 start_date: "2024-01-01"
11497 period_months: 12
11498 companies:
11499 - code: "BANK"
11500 name: "Test Bank"
11501 currency: "USD"
11502 country: "US"
11503 annual_transaction_volume: hundred_k
11504 chart_of_accounts:
11505 complexity: large
11506 output:
11507 output_directory: "./output"
11508 accounting_standards:
11509 enabled: true
11510 framework: us_gaap
11511 revenue_recognition:
11512 enabled: true
11513 leases:
11514 enabled: true
11515 audit_standards:
11516 enabled: true
11517 isa_compliance:
11518 enabled: true
11519 sox:
11520 enabled: true
11521 "#;
11522
11523 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
11524 assert!(config.accounting_standards.enabled);
11525 assert!(matches!(
11526 config.accounting_standards.framework,
11527 AccountingFrameworkConfig::UsGaap
11528 ));
11529 assert!(config.accounting_standards.revenue_recognition.enabled);
11530 assert!(config.accounting_standards.leases.enabled);
11531 assert!(config.audit_standards.enabled);
11532 assert!(config.audit_standards.isa_compliance.enabled);
11533 assert!(config.audit_standards.sox.enabled);
11534 }
11535
11536 #[test]
11541 fn test_industry_specific_config_defaults() {
11542 let config = IndustrySpecificConfig::default();
11543 assert!(!config.enabled);
11544 assert!(!config.manufacturing.enabled);
11545 assert!(!config.retail.enabled);
11546 assert!(!config.healthcare.enabled);
11547 assert!(!config.technology.enabled);
11548 assert!(!config.financial_services.enabled);
11549 assert!(!config.professional_services.enabled);
11550 }
11551
11552 #[test]
11553 fn test_manufacturing_config_defaults() {
11554 let config = ManufacturingConfig::default();
11555 assert!(!config.enabled);
11556 assert_eq!(config.bom_depth, 4);
11557 assert!(!config.just_in_time);
11558 assert_eq!(config.supplier_tiers, 2);
11559 assert_eq!(config.target_yield_rate, 0.97);
11560 assert_eq!(config.scrap_alert_threshold, 0.03);
11561 }
11562
11563 #[test]
11564 fn test_retail_config_defaults() {
11565 let config = RetailConfig::default();
11566 assert!(!config.enabled);
11567 assert_eq!(config.avg_daily_transactions, 500);
11568 assert!(config.loss_prevention);
11569 assert_eq!(config.shrinkage_rate, 0.015);
11570 }
11571
11572 #[test]
11573 fn test_healthcare_config_defaults() {
11574 let config = HealthcareConfig::default();
11575 assert!(!config.enabled);
11576 assert_eq!(config.facility_type, "hospital");
11577 assert_eq!(config.avg_daily_encounters, 150);
11578 assert!(config.compliance.hipaa);
11579 assert!(config.compliance.stark_law);
11580 assert!(config.coding_systems.icd10);
11581 assert!(config.coding_systems.cpt);
11582 }
11583
11584 #[test]
11585 fn test_technology_config_defaults() {
11586 let config = TechnologyConfig::default();
11587 assert!(!config.enabled);
11588 assert_eq!(config.revenue_model, "saas");
11589 assert_eq!(config.subscription_revenue_pct, 0.60);
11590 assert!(config.rd_capitalization.enabled);
11591 }
11592
11593 #[test]
11594 fn test_config_with_industry_specific() {
11595 let yaml = r#"
11596 global:
11597 industry: healthcare
11598 start_date: "2024-01-01"
11599 period_months: 12
11600 companies:
11601 - code: "HOSP"
11602 name: "Test Hospital"
11603 currency: "USD"
11604 country: "US"
11605 annual_transaction_volume: hundred_k
11606 chart_of_accounts:
11607 complexity: medium
11608 output:
11609 output_directory: "./output"
11610 industry_specific:
11611 enabled: true
11612 healthcare:
11613 enabled: true
11614 facility_type: hospital
11615 payer_mix:
11616 medicare: 0.45
11617 medicaid: 0.15
11618 commercial: 0.35
11619 self_pay: 0.05
11620 coding_systems:
11621 icd10: true
11622 cpt: true
11623 drg: true
11624 compliance:
11625 hipaa: true
11626 stark_law: true
11627 anomaly_rates:
11628 upcoding: 0.03
11629 unbundling: 0.02
11630 "#;
11631
11632 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
11633 assert!(config.industry_specific.enabled);
11634 assert!(config.industry_specific.healthcare.enabled);
11635 assert_eq!(
11636 config.industry_specific.healthcare.facility_type,
11637 "hospital"
11638 );
11639 assert_eq!(config.industry_specific.healthcare.payer_mix.medicare, 0.45);
11640 assert_eq!(config.industry_specific.healthcare.payer_mix.self_pay, 0.05);
11641 assert!(config.industry_specific.healthcare.coding_systems.icd10);
11642 assert!(config.industry_specific.healthcare.compliance.hipaa);
11643 assert_eq!(
11644 config.industry_specific.healthcare.anomaly_rates.upcoding,
11645 0.03
11646 );
11647 }
11648
11649 #[test]
11650 fn test_config_with_manufacturing_specific() {
11651 let yaml = r#"
11652 global:
11653 industry: manufacturing
11654 start_date: "2024-01-01"
11655 period_months: 12
11656 companies:
11657 - code: "MFG"
11658 name: "Test Manufacturing"
11659 currency: "USD"
11660 country: "US"
11661 annual_transaction_volume: hundred_k
11662 chart_of_accounts:
11663 complexity: medium
11664 output:
11665 output_directory: "./output"
11666 industry_specific:
11667 enabled: true
11668 manufacturing:
11669 enabled: true
11670 bom_depth: 5
11671 just_in_time: true
11672 supplier_tiers: 3
11673 target_yield_rate: 0.98
11674 anomaly_rates:
11675 yield_manipulation: 0.02
11676 phantom_production: 0.01
11677 "#;
11678
11679 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
11680 assert!(config.industry_specific.enabled);
11681 assert!(config.industry_specific.manufacturing.enabled);
11682 assert_eq!(config.industry_specific.manufacturing.bom_depth, 5);
11683 assert!(config.industry_specific.manufacturing.just_in_time);
11684 assert_eq!(config.industry_specific.manufacturing.supplier_tiers, 3);
11685 assert_eq!(
11686 config.industry_specific.manufacturing.target_yield_rate,
11687 0.98
11688 );
11689 assert_eq!(
11690 config
11691 .industry_specific
11692 .manufacturing
11693 .anomaly_rates
11694 .yield_manipulation,
11695 0.02
11696 );
11697 }
11698}