1use datasynth_core::distributions::{
4 AmountDistributionConfig, DebitCreditDistributionConfig, EvenOddDistributionConfig,
5 LineItemDistributionConfig, SeasonalityConfig,
6};
7use datasynth_core::models::{CoAComplexity, IndustrySector};
8use serde::{Deserialize, Serialize};
9use std::path::PathBuf;
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct GeneratorConfig {
14 pub global: GlobalConfig,
16 pub companies: Vec<CompanyConfig>,
18 pub chart_of_accounts: ChartOfAccountsConfig,
20 #[serde(default)]
22 pub transactions: TransactionConfig,
23 pub output: OutputConfig,
25 #[serde(default)]
27 pub fraud: FraudConfig,
28 #[serde(default)]
30 pub data_quality: DataQualitySchemaConfig,
31 #[serde(default)]
33 pub internal_controls: InternalControlsConfig,
34 #[serde(default)]
36 pub business_processes: BusinessProcessConfig,
37 #[serde(default)]
39 pub user_personas: UserPersonaConfig,
40 #[serde(default)]
42 pub templates: TemplateConfig,
43 #[serde(default)]
45 pub approval: ApprovalConfig,
46 #[serde(default)]
48 pub departments: DepartmentConfig,
49 #[serde(default)]
51 pub master_data: MasterDataConfig,
52 #[serde(default)]
54 pub document_flows: DocumentFlowConfig,
55 #[serde(default)]
57 pub intercompany: IntercompanyConfig,
58 #[serde(default)]
60 pub balance: BalanceConfig,
61 #[serde(default)]
63 pub ocpm: OcpmConfig,
64 #[serde(default)]
66 pub audit: AuditGenerationConfig,
67 #[serde(default)]
69 pub banking: datasynth_banking::BankingConfig,
70 #[serde(default)]
72 pub scenario: ScenarioConfig,
73 #[serde(default)]
75 pub temporal: TemporalDriftConfig,
76 #[serde(default)]
78 pub graph_export: GraphExportConfig,
79 #[serde(default)]
81 pub streaming: StreamingSchemaConfig,
82 #[serde(default)]
84 pub rate_limit: RateLimitSchemaConfig,
85 #[serde(default)]
87 pub temporal_attributes: TemporalAttributeSchemaConfig,
88 #[serde(default)]
90 pub relationships: RelationshipSchemaConfig,
91 #[serde(default)]
93 pub accounting_standards: AccountingStandardsConfig,
94 #[serde(default)]
96 pub audit_standards: AuditStandardsConfig,
97 #[serde(default)]
99 pub distributions: AdvancedDistributionConfig,
100 #[serde(default)]
102 pub temporal_patterns: TemporalPatternsConfig,
103 #[serde(default)]
105 pub vendor_network: VendorNetworkSchemaConfig,
106 #[serde(default)]
108 pub customer_segmentation: CustomerSegmentationSchemaConfig,
109 #[serde(default)]
111 pub relationship_strength: RelationshipStrengthSchemaConfig,
112 #[serde(default)]
114 pub cross_process_links: CrossProcessLinksSchemaConfig,
115 #[serde(default)]
117 pub organizational_events: OrganizationalEventsSchemaConfig,
118 #[serde(default)]
120 pub behavioral_drift: BehavioralDriftSchemaConfig,
121 #[serde(default)]
123 pub market_drift: MarketDriftSchemaConfig,
124 #[serde(default)]
126 pub drift_labeling: DriftLabelingSchemaConfig,
127 #[serde(default)]
129 pub anomaly_injection: EnhancedAnomalyConfig,
130 #[serde(default)]
132 pub industry_specific: IndustrySpecificConfig,
133 #[serde(default)]
135 pub fingerprint_privacy: FingerprintPrivacyConfig,
136 #[serde(default)]
138 pub quality_gates: QualityGatesSchemaConfig,
139 #[serde(default)]
141 pub compliance: ComplianceSchemaConfig,
142 #[serde(default)]
144 pub webhooks: WebhookSchemaConfig,
145 #[serde(default)]
147 pub llm: LlmSchemaConfig,
148 #[serde(default)]
150 pub diffusion: DiffusionSchemaConfig,
151 #[serde(default)]
153 pub causal: CausalSchemaConfig,
154
155 #[serde(default)]
158 pub source_to_pay: SourceToPayConfig,
159 #[serde(default)]
161 pub financial_reporting: FinancialReportingConfig,
162 #[serde(default)]
164 pub hr: HrConfig,
165 #[serde(default)]
167 pub manufacturing: ManufacturingProcessConfig,
168 #[serde(default)]
170 pub sales_quotes: SalesQuoteConfig,
171 #[serde(default)]
173 pub tax: TaxConfig,
174 #[serde(default)]
176 pub treasury: TreasuryConfig,
177 #[serde(default)]
179 pub project_accounting: ProjectAccountingConfig,
180 #[serde(default)]
182 pub esg: EsgConfig,
183 #[serde(default)]
185 pub country_packs: Option<CountryPacksSchemaConfig>,
186 #[serde(default)]
188 pub scenarios: ScenariosConfig,
189 #[serde(default)]
191 pub session: SessionSchemaConfig,
192}
193
194#[derive(Debug, Clone, Serialize, Deserialize)]
200pub struct LlmSchemaConfig {
201 #[serde(default)]
203 pub enabled: bool,
204 #[serde(default = "default_llm_provider")]
206 pub provider: String,
207 #[serde(default = "default_llm_model_name")]
209 pub model: String,
210 #[serde(default = "default_llm_batch_size")]
212 pub max_vendor_enrichments: usize,
213}
214
215fn default_llm_provider() -> String {
216 "mock".to_string()
217}
218
219fn default_llm_model_name() -> String {
220 "gpt-4o-mini".to_string()
221}
222
223fn default_llm_batch_size() -> usize {
224 50
225}
226
227impl Default for LlmSchemaConfig {
228 fn default() -> Self {
229 Self {
230 enabled: false,
231 provider: default_llm_provider(),
232 model: default_llm_model_name(),
233 max_vendor_enrichments: default_llm_batch_size(),
234 }
235 }
236}
237
238#[derive(Debug, Clone, Serialize, Deserialize)]
243pub struct DiffusionSchemaConfig {
244 #[serde(default)]
246 pub enabled: bool,
247 #[serde(default = "default_diffusion_steps")]
249 pub n_steps: usize,
250 #[serde(default = "default_diffusion_schedule")]
252 pub schedule: String,
253 #[serde(default = "default_diffusion_sample_size")]
255 pub sample_size: usize,
256}
257
258fn default_diffusion_steps() -> usize {
259 100
260}
261
262fn default_diffusion_schedule() -> String {
263 "linear".to_string()
264}
265
266fn default_diffusion_sample_size() -> usize {
267 100
268}
269
270impl Default for DiffusionSchemaConfig {
271 fn default() -> Self {
272 Self {
273 enabled: false,
274 n_steps: default_diffusion_steps(),
275 schedule: default_diffusion_schedule(),
276 sample_size: default_diffusion_sample_size(),
277 }
278 }
279}
280
281#[derive(Debug, Clone, Serialize, Deserialize)]
287pub struct CausalSchemaConfig {
288 #[serde(default)]
290 pub enabled: bool,
291 #[serde(default = "default_causal_template")]
293 pub template: String,
294 #[serde(default = "default_causal_sample_size")]
296 pub sample_size: usize,
297 #[serde(default = "default_true")]
299 pub validate: bool,
300}
301
302fn default_causal_template() -> String {
303 "fraud_detection".to_string()
304}
305
306fn default_causal_sample_size() -> usize {
307 500
308}
309
310impl Default for CausalSchemaConfig {
311 fn default() -> Self {
312 Self {
313 enabled: false,
314 template: default_causal_template(),
315 sample_size: default_causal_sample_size(),
316 validate: true,
317 }
318 }
319}
320
321#[derive(Debug, Clone, Serialize, Deserialize)]
328pub struct GraphExportConfig {
329 #[serde(default)]
331 pub enabled: bool,
332
333 #[serde(default = "default_graph_types")]
335 pub graph_types: Vec<GraphTypeConfig>,
336
337 #[serde(default = "default_graph_formats")]
339 pub formats: Vec<GraphExportFormat>,
340
341 #[serde(default = "default_train_ratio")]
343 pub train_ratio: f64,
344
345 #[serde(default = "default_val_ratio")]
347 pub validation_ratio: f64,
348
349 #[serde(default)]
351 pub split_seed: Option<u64>,
352
353 #[serde(default = "default_graph_subdir")]
355 pub output_subdirectory: String,
356
357 #[serde(default)]
359 pub hypergraph: HypergraphExportSettings,
360}
361
362fn default_graph_types() -> Vec<GraphTypeConfig> {
363 vec![GraphTypeConfig::default()]
364}
365
366fn default_graph_formats() -> Vec<GraphExportFormat> {
367 vec![GraphExportFormat::PytorchGeometric]
368}
369
370fn default_train_ratio() -> f64 {
371 0.7
372}
373
374fn default_val_ratio() -> f64 {
375 0.15
376}
377
378fn default_graph_subdir() -> String {
379 "graphs".to_string()
380}
381
382impl Default for GraphExportConfig {
383 fn default() -> Self {
384 Self {
385 enabled: false,
386 graph_types: default_graph_types(),
387 formats: default_graph_formats(),
388 train_ratio: 0.7,
389 validation_ratio: 0.15,
390 split_seed: None,
391 output_subdirectory: "graphs".to_string(),
392 hypergraph: HypergraphExportSettings::default(),
393 }
394 }
395}
396
397#[derive(Debug, Clone, Serialize, Deserialize)]
404pub struct HypergraphExportSettings {
405 #[serde(default)]
407 pub enabled: bool,
408
409 #[serde(default = "default_hypergraph_max_nodes")]
411 pub max_nodes: usize,
412
413 #[serde(default = "default_aggregation_strategy")]
415 pub aggregation_strategy: String,
416
417 #[serde(default)]
419 pub governance_layer: GovernanceLayerSettings,
420
421 #[serde(default)]
423 pub process_layer: ProcessLayerSettings,
424
425 #[serde(default)]
427 pub accounting_layer: AccountingLayerSettings,
428
429 #[serde(default)]
431 pub cross_layer: CrossLayerSettings,
432
433 #[serde(default = "default_hypergraph_subdir")]
435 pub output_subdirectory: String,
436
437 #[serde(default = "default_hypergraph_format")]
439 pub output_format: String,
440
441 #[serde(default)]
443 pub stream_target: Option<String>,
444
445 #[serde(default = "default_stream_batch_size")]
447 pub stream_batch_size: usize,
448}
449
450fn default_hypergraph_max_nodes() -> usize {
451 50_000
452}
453
454fn default_aggregation_strategy() -> String {
455 "pool_by_counterparty".to_string()
456}
457
458fn default_hypergraph_subdir() -> String {
459 "hypergraph".to_string()
460}
461
462fn default_hypergraph_format() -> String {
463 "native".to_string()
464}
465
466fn default_stream_batch_size() -> usize {
467 1000
468}
469
470impl Default for HypergraphExportSettings {
471 fn default() -> Self {
472 Self {
473 enabled: false,
474 max_nodes: 50_000,
475 aggregation_strategy: "pool_by_counterparty".to_string(),
476 governance_layer: GovernanceLayerSettings::default(),
477 process_layer: ProcessLayerSettings::default(),
478 accounting_layer: AccountingLayerSettings::default(),
479 cross_layer: CrossLayerSettings::default(),
480 output_subdirectory: "hypergraph".to_string(),
481 output_format: "native".to_string(),
482 stream_target: None,
483 stream_batch_size: 1000,
484 }
485 }
486}
487
488#[derive(Debug, Clone, Serialize, Deserialize)]
490pub struct GovernanceLayerSettings {
491 #[serde(default = "default_true")]
493 pub include_coso: bool,
494 #[serde(default = "default_true")]
496 pub include_controls: bool,
497 #[serde(default = "default_true")]
499 pub include_sox: bool,
500 #[serde(default = "default_true")]
502 pub include_vendors: bool,
503 #[serde(default = "default_true")]
505 pub include_customers: bool,
506 #[serde(default = "default_true")]
508 pub include_employees: bool,
509}
510
511impl Default for GovernanceLayerSettings {
512 fn default() -> Self {
513 Self {
514 include_coso: true,
515 include_controls: true,
516 include_sox: true,
517 include_vendors: true,
518 include_customers: true,
519 include_employees: true,
520 }
521 }
522}
523
524#[derive(Debug, Clone, Serialize, Deserialize)]
526pub struct ProcessLayerSettings {
527 #[serde(default = "default_true")]
529 pub include_p2p: bool,
530 #[serde(default = "default_true")]
532 pub include_o2c: bool,
533 #[serde(default = "default_true")]
535 pub include_s2c: bool,
536 #[serde(default = "default_true")]
538 pub include_h2r: bool,
539 #[serde(default = "default_true")]
541 pub include_mfg: bool,
542 #[serde(default = "default_true")]
544 pub include_bank: bool,
545 #[serde(default = "default_true")]
547 pub include_audit: bool,
548 #[serde(default = "default_true")]
550 pub include_r2r: bool,
551 #[serde(default = "default_true")]
553 pub events_as_hyperedges: bool,
554 #[serde(default = "default_docs_per_counterparty_threshold")]
556 pub docs_per_counterparty_threshold: usize,
557}
558
559fn default_docs_per_counterparty_threshold() -> usize {
560 20
561}
562
563impl Default for ProcessLayerSettings {
564 fn default() -> Self {
565 Self {
566 include_p2p: true,
567 include_o2c: true,
568 include_s2c: true,
569 include_h2r: true,
570 include_mfg: true,
571 include_bank: true,
572 include_audit: true,
573 include_r2r: true,
574 events_as_hyperedges: true,
575 docs_per_counterparty_threshold: 20,
576 }
577 }
578}
579
580#[derive(Debug, Clone, Serialize, Deserialize)]
582pub struct AccountingLayerSettings {
583 #[serde(default = "default_true")]
585 pub include_accounts: bool,
586 #[serde(default = "default_true")]
588 pub je_as_hyperedges: bool,
589}
590
591impl Default for AccountingLayerSettings {
592 fn default() -> Self {
593 Self {
594 include_accounts: true,
595 je_as_hyperedges: true,
596 }
597 }
598}
599
600#[derive(Debug, Clone, Serialize, Deserialize)]
602pub struct CrossLayerSettings {
603 #[serde(default = "default_true")]
605 pub enabled: bool,
606}
607
608impl Default for CrossLayerSettings {
609 fn default() -> Self {
610 Self { enabled: true }
611 }
612}
613
614#[derive(Debug, Clone, Serialize, Deserialize)]
616pub struct GraphTypeConfig {
617 #[serde(default = "default_graph_name")]
619 pub name: String,
620
621 #[serde(default)]
623 pub aggregate_edges: bool,
624
625 #[serde(default)]
627 pub min_edge_weight: f64,
628
629 #[serde(default)]
631 pub include_document_nodes: bool,
632}
633
634fn default_graph_name() -> String {
635 "accounting_network".to_string()
636}
637
638impl Default for GraphTypeConfig {
639 fn default() -> Self {
640 Self {
641 name: "accounting_network".to_string(),
642 aggregate_edges: false,
643 min_edge_weight: 0.0,
644 include_document_nodes: false,
645 }
646 }
647}
648
649#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
651#[serde(rename_all = "snake_case")]
652pub enum GraphExportFormat {
653 PytorchGeometric,
655 Neo4j,
657 Dgl,
659 RustGraph,
661 RustGraphHypergraph,
663}
664
665#[derive(Debug, Clone, Default, Serialize, Deserialize)]
669pub struct ScenarioConfig {
670 #[serde(default)]
673 pub tags: Vec<String>,
674
675 #[serde(default)]
680 pub profile: Option<String>,
681
682 #[serde(default)]
684 pub description: Option<String>,
685
686 #[serde(default)]
688 pub ml_training: bool,
689
690 #[serde(default)]
693 pub target_anomaly_ratio: Option<f64>,
694
695 #[serde(default)]
697 pub metadata: std::collections::HashMap<String, String>,
698}
699
700#[derive(Debug, Clone, Serialize, Deserialize)]
705pub struct TemporalDriftConfig {
706 #[serde(default)]
708 pub enabled: bool,
709
710 #[serde(default = "default_amount_drift")]
713 pub amount_mean_drift: f64,
714
715 #[serde(default)]
718 pub amount_variance_drift: f64,
719
720 #[serde(default)]
723 pub anomaly_rate_drift: f64,
724
725 #[serde(default = "default_concept_drift")]
728 pub concept_drift_rate: f64,
729
730 #[serde(default)]
732 pub sudden_drift_probability: f64,
733
734 #[serde(default = "default_sudden_drift_magnitude")]
736 pub sudden_drift_magnitude: f64,
737
738 #[serde(default)]
740 pub seasonal_drift: bool,
741
742 #[serde(default)]
744 pub drift_start_period: u32,
745
746 #[serde(default = "default_drift_type")]
748 pub drift_type: DriftType,
749}
750
751fn default_amount_drift() -> f64 {
752 0.02
753}
754
755fn default_concept_drift() -> f64 {
756 0.01
757}
758
759fn default_sudden_drift_magnitude() -> f64 {
760 2.0
761}
762
763fn default_drift_type() -> DriftType {
764 DriftType::Gradual
765}
766
767impl Default for TemporalDriftConfig {
768 fn default() -> Self {
769 Self {
770 enabled: false,
771 amount_mean_drift: 0.02,
772 amount_variance_drift: 0.0,
773 anomaly_rate_drift: 0.0,
774 concept_drift_rate: 0.01,
775 sudden_drift_probability: 0.0,
776 sudden_drift_magnitude: 2.0,
777 seasonal_drift: false,
778 drift_start_period: 0,
779 drift_type: DriftType::Gradual,
780 }
781 }
782}
783
784impl TemporalDriftConfig {
785 pub fn to_core_config(&self) -> datasynth_core::distributions::DriftConfig {
787 datasynth_core::distributions::DriftConfig {
788 enabled: self.enabled,
789 amount_mean_drift: self.amount_mean_drift,
790 amount_variance_drift: self.amount_variance_drift,
791 anomaly_rate_drift: self.anomaly_rate_drift,
792 concept_drift_rate: self.concept_drift_rate,
793 sudden_drift_probability: self.sudden_drift_probability,
794 sudden_drift_magnitude: self.sudden_drift_magnitude,
795 seasonal_drift: self.seasonal_drift,
796 drift_start_period: self.drift_start_period,
797 drift_type: match self.drift_type {
798 DriftType::Gradual => datasynth_core::distributions::DriftType::Gradual,
799 DriftType::Sudden => datasynth_core::distributions::DriftType::Sudden,
800 DriftType::Recurring => datasynth_core::distributions::DriftType::Recurring,
801 DriftType::Mixed => datasynth_core::distributions::DriftType::Mixed,
802 },
803 regime_changes: Vec::new(),
804 economic_cycle: Default::default(),
805 parameter_drifts: Vec::new(),
806 }
807 }
808}
809
810#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
812#[serde(rename_all = "snake_case")]
813pub enum DriftType {
814 #[default]
816 Gradual,
817 Sudden,
819 Recurring,
821 Mixed,
823}
824
825#[derive(Debug, Clone, Serialize, Deserialize)]
831pub struct StreamingSchemaConfig {
832 #[serde(default)]
834 pub enabled: bool,
835 #[serde(default = "default_buffer_size")]
837 pub buffer_size: usize,
838 #[serde(default = "default_true")]
840 pub enable_progress: bool,
841 #[serde(default = "default_progress_interval")]
843 pub progress_interval: u64,
844 #[serde(default)]
846 pub backpressure: BackpressureSchemaStrategy,
847}
848
849fn default_buffer_size() -> usize {
850 1000
851}
852
853fn default_progress_interval() -> u64 {
854 100
855}
856
857impl Default for StreamingSchemaConfig {
858 fn default() -> Self {
859 Self {
860 enabled: false,
861 buffer_size: 1000,
862 enable_progress: true,
863 progress_interval: 100,
864 backpressure: BackpressureSchemaStrategy::Block,
865 }
866 }
867}
868
869#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
871#[serde(rename_all = "snake_case")]
872pub enum BackpressureSchemaStrategy {
873 #[default]
875 Block,
876 DropOldest,
878 DropNewest,
880 Buffer,
882}
883
884#[derive(Debug, Clone, Serialize, Deserialize)]
890pub struct RateLimitSchemaConfig {
891 #[serde(default)]
893 pub enabled: bool,
894 #[serde(default = "default_entities_per_second")]
896 pub entities_per_second: f64,
897 #[serde(default = "default_burst_size")]
899 pub burst_size: u32,
900 #[serde(default)]
902 pub backpressure: RateLimitBackpressureSchema,
903}
904
905fn default_entities_per_second() -> f64 {
906 1000.0
907}
908
909fn default_burst_size() -> u32 {
910 100
911}
912
913impl Default for RateLimitSchemaConfig {
914 fn default() -> Self {
915 Self {
916 enabled: false,
917 entities_per_second: 1000.0,
918 burst_size: 100,
919 backpressure: RateLimitBackpressureSchema::Block,
920 }
921 }
922}
923
924#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
926#[serde(rename_all = "snake_case")]
927pub enum RateLimitBackpressureSchema {
928 #[default]
930 Block,
931 Drop,
933 Buffer,
935}
936
937#[derive(Debug, Clone, Serialize, Deserialize)]
943pub struct TemporalAttributeSchemaConfig {
944 #[serde(default)]
946 pub enabled: bool,
947 #[serde(default)]
949 pub valid_time: ValidTimeSchemaConfig,
950 #[serde(default)]
952 pub transaction_time: TransactionTimeSchemaConfig,
953 #[serde(default)]
955 pub generate_version_chains: bool,
956 #[serde(default = "default_avg_versions")]
958 pub avg_versions_per_entity: f64,
959}
960
961fn default_avg_versions() -> f64 {
962 1.5
963}
964
965impl Default for TemporalAttributeSchemaConfig {
966 fn default() -> Self {
967 Self {
968 enabled: false,
969 valid_time: ValidTimeSchemaConfig::default(),
970 transaction_time: TransactionTimeSchemaConfig::default(),
971 generate_version_chains: false,
972 avg_versions_per_entity: 1.5,
973 }
974 }
975}
976
977#[derive(Debug, Clone, Serialize, Deserialize)]
979pub struct ValidTimeSchemaConfig {
980 #[serde(default = "default_closed_probability")]
982 pub closed_probability: f64,
983 #[serde(default = "default_avg_validity_days")]
985 pub avg_validity_days: u32,
986 #[serde(default = "default_validity_stddev")]
988 pub validity_stddev_days: u32,
989}
990
991fn default_closed_probability() -> f64 {
992 0.1
993}
994
995fn default_avg_validity_days() -> u32 {
996 365
997}
998
999fn default_validity_stddev() -> u32 {
1000 90
1001}
1002
1003impl Default for ValidTimeSchemaConfig {
1004 fn default() -> Self {
1005 Self {
1006 closed_probability: 0.1,
1007 avg_validity_days: 365,
1008 validity_stddev_days: 90,
1009 }
1010 }
1011}
1012
1013#[derive(Debug, Clone, Serialize, Deserialize)]
1015pub struct TransactionTimeSchemaConfig {
1016 #[serde(default)]
1018 pub avg_recording_delay_seconds: u32,
1019 #[serde(default)]
1021 pub allow_backdating: bool,
1022 #[serde(default = "default_backdating_probability")]
1024 pub backdating_probability: f64,
1025 #[serde(default = "default_max_backdate_days")]
1027 pub max_backdate_days: u32,
1028}
1029
1030fn default_backdating_probability() -> f64 {
1031 0.01
1032}
1033
1034fn default_max_backdate_days() -> u32 {
1035 30
1036}
1037
1038impl Default for TransactionTimeSchemaConfig {
1039 fn default() -> Self {
1040 Self {
1041 avg_recording_delay_seconds: 0,
1042 allow_backdating: false,
1043 backdating_probability: 0.01,
1044 max_backdate_days: 30,
1045 }
1046 }
1047}
1048
1049#[derive(Debug, Clone, Serialize, Deserialize)]
1055pub struct RelationshipSchemaConfig {
1056 #[serde(default)]
1058 pub relationship_types: Vec<RelationshipTypeSchemaConfig>,
1059 #[serde(default = "default_true")]
1061 pub allow_orphans: bool,
1062 #[serde(default = "default_orphan_probability")]
1064 pub orphan_probability: f64,
1065 #[serde(default)]
1067 pub allow_circular: bool,
1068 #[serde(default = "default_max_circular_depth")]
1070 pub max_circular_depth: u32,
1071}
1072
1073fn default_orphan_probability() -> f64 {
1074 0.01
1075}
1076
1077fn default_max_circular_depth() -> u32 {
1078 3
1079}
1080
1081impl Default for RelationshipSchemaConfig {
1082 fn default() -> Self {
1083 Self {
1084 relationship_types: Vec::new(),
1085 allow_orphans: true,
1086 orphan_probability: 0.01,
1087 allow_circular: false,
1088 max_circular_depth: 3,
1089 }
1090 }
1091}
1092
1093#[derive(Debug, Clone, Serialize, Deserialize)]
1095pub struct RelationshipTypeSchemaConfig {
1096 pub name: String,
1098 pub source_type: String,
1100 pub target_type: String,
1102 #[serde(default)]
1104 pub cardinality: CardinalitySchemaRule,
1105 #[serde(default = "default_relationship_weight")]
1107 pub weight: f64,
1108 #[serde(default)]
1110 pub required: bool,
1111 #[serde(default = "default_true")]
1113 pub directed: bool,
1114}
1115
1116fn default_relationship_weight() -> f64 {
1117 1.0
1118}
1119
1120impl Default for RelationshipTypeSchemaConfig {
1121 fn default() -> Self {
1122 Self {
1123 name: String::new(),
1124 source_type: String::new(),
1125 target_type: String::new(),
1126 cardinality: CardinalitySchemaRule::default(),
1127 weight: 1.0,
1128 required: false,
1129 directed: true,
1130 }
1131 }
1132}
1133
1134#[derive(Debug, Clone, Serialize, Deserialize)]
1136#[serde(rename_all = "snake_case")]
1137pub enum CardinalitySchemaRule {
1138 OneToOne,
1140 OneToMany {
1142 min: u32,
1144 max: u32,
1146 },
1147 ManyToOne {
1149 min: u32,
1151 max: u32,
1153 },
1154 ManyToMany {
1156 min_per_source: u32,
1158 max_per_source: u32,
1160 },
1161}
1162
1163impl Default for CardinalitySchemaRule {
1164 fn default() -> Self {
1165 Self::OneToMany { min: 1, max: 5 }
1166 }
1167}
1168
1169#[derive(Debug, Clone, Serialize, Deserialize)]
1171pub struct GlobalConfig {
1172 pub seed: Option<u64>,
1174 pub industry: IndustrySector,
1176 pub start_date: String,
1178 pub period_months: u32,
1180 #[serde(default = "default_currency")]
1182 pub group_currency: String,
1183 #[serde(default = "default_true")]
1185 pub parallel: bool,
1186 #[serde(default)]
1188 pub worker_threads: usize,
1189 #[serde(default)]
1191 pub memory_limit_mb: usize,
1192 #[serde(default)]
1195 pub fiscal_year_months: Option<u32>,
1196}
1197
1198fn default_currency() -> String {
1199 "USD".to_string()
1200}
1201fn default_true() -> bool {
1202 true
1203}
1204
1205#[derive(Debug, Clone, Serialize, Deserialize)]
1210pub struct SessionSchemaConfig {
1211 #[serde(default)]
1213 pub enabled: bool,
1214 #[serde(default)]
1216 pub checkpoint_path: Option<String>,
1217 #[serde(default = "default_true")]
1219 pub per_period_output: bool,
1220 #[serde(default = "default_true")]
1222 pub consolidated_output: bool,
1223}
1224
1225impl Default for SessionSchemaConfig {
1226 fn default() -> Self {
1227 Self {
1228 enabled: false,
1229 checkpoint_path: None,
1230 per_period_output: true,
1231 consolidated_output: true,
1232 }
1233 }
1234}
1235
1236#[derive(Debug, Clone, Serialize, Deserialize)]
1238pub struct CompanyConfig {
1239 pub code: String,
1241 pub name: String,
1243 pub currency: String,
1245 pub country: String,
1247 #[serde(default = "default_fiscal_variant")]
1249 pub fiscal_year_variant: String,
1250 pub annual_transaction_volume: TransactionVolume,
1252 #[serde(default = "default_weight")]
1254 pub volume_weight: f64,
1255}
1256
1257fn default_fiscal_variant() -> String {
1258 "K4".to_string()
1259}
1260fn default_weight() -> f64 {
1261 1.0
1262}
1263
1264#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1266#[serde(rename_all = "snake_case")]
1267pub enum TransactionVolume {
1268 TenK,
1270 HundredK,
1272 OneM,
1274 TenM,
1276 HundredM,
1278 Custom(u64),
1280}
1281
1282impl TransactionVolume {
1283 pub fn count(&self) -> u64 {
1285 match self {
1286 Self::TenK => 10_000,
1287 Self::HundredK => 100_000,
1288 Self::OneM => 1_000_000,
1289 Self::TenM => 10_000_000,
1290 Self::HundredM => 100_000_000,
1291 Self::Custom(n) => *n,
1292 }
1293 }
1294}
1295
1296#[derive(Debug, Clone, Serialize, Deserialize)]
1298pub struct ChartOfAccountsConfig {
1299 pub complexity: CoAComplexity,
1301 #[serde(default = "default_true")]
1303 pub industry_specific: bool,
1304 pub custom_accounts: Option<PathBuf>,
1306 #[serde(default = "default_min_depth")]
1308 pub min_hierarchy_depth: u8,
1309 #[serde(default = "default_max_depth")]
1311 pub max_hierarchy_depth: u8,
1312}
1313
1314fn default_min_depth() -> u8 {
1315 2
1316}
1317fn default_max_depth() -> u8 {
1318 5
1319}
1320
1321impl Default for ChartOfAccountsConfig {
1322 fn default() -> Self {
1323 Self {
1324 complexity: CoAComplexity::Small,
1325 industry_specific: true,
1326 custom_accounts: None,
1327 min_hierarchy_depth: default_min_depth(),
1328 max_hierarchy_depth: default_max_depth(),
1329 }
1330 }
1331}
1332
1333#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1335pub struct TransactionConfig {
1336 #[serde(default)]
1338 pub line_item_distribution: LineItemDistributionConfig,
1339 #[serde(default)]
1341 pub debit_credit_distribution: DebitCreditDistributionConfig,
1342 #[serde(default)]
1344 pub even_odd_distribution: EvenOddDistributionConfig,
1345 #[serde(default)]
1347 pub source_distribution: SourceDistribution,
1348 #[serde(default)]
1350 pub seasonality: SeasonalityConfig,
1351 #[serde(default)]
1353 pub amounts: AmountDistributionConfig,
1354 #[serde(default)]
1356 pub benford: BenfordConfig,
1357}
1358
1359#[derive(Debug, Clone, Serialize, Deserialize)]
1361pub struct BenfordConfig {
1362 #[serde(default = "default_true")]
1364 pub enabled: bool,
1365 #[serde(default = "default_benford_tolerance")]
1367 pub tolerance: f64,
1368 #[serde(default)]
1370 pub exempt_sources: Vec<BenfordExemption>,
1371}
1372
1373fn default_benford_tolerance() -> f64 {
1374 0.05
1375}
1376
1377impl Default for BenfordConfig {
1378 fn default() -> Self {
1379 Self {
1380 enabled: true,
1381 tolerance: default_benford_tolerance(),
1382 exempt_sources: vec![BenfordExemption::Recurring, BenfordExemption::Payroll],
1383 }
1384 }
1385}
1386
1387#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1389#[serde(rename_all = "snake_case")]
1390pub enum BenfordExemption {
1391 Recurring,
1393 Payroll,
1395 FixedFees,
1397 RoundAmounts,
1399}
1400
1401#[derive(Debug, Clone, Serialize, Deserialize)]
1403pub struct SourceDistribution {
1404 pub manual: f64,
1406 pub automated: f64,
1408 pub recurring: f64,
1410 pub adjustment: f64,
1412}
1413
1414impl Default for SourceDistribution {
1415 fn default() -> Self {
1416 Self {
1417 manual: 0.20,
1418 automated: 0.70,
1419 recurring: 0.07,
1420 adjustment: 0.03,
1421 }
1422 }
1423}
1424
1425#[derive(Debug, Clone, Serialize, Deserialize)]
1427pub struct OutputConfig {
1428 #[serde(default)]
1430 pub mode: OutputMode,
1431 pub output_directory: PathBuf,
1433 #[serde(default = "default_formats")]
1435 pub formats: Vec<FileFormat>,
1436 #[serde(default)]
1438 pub compression: CompressionConfig,
1439 #[serde(default = "default_batch_size")]
1441 pub batch_size: usize,
1442 #[serde(default = "default_true")]
1444 pub include_acdoca: bool,
1445 #[serde(default)]
1447 pub include_bseg: bool,
1448 #[serde(default = "default_true")]
1450 pub partition_by_period: bool,
1451 #[serde(default)]
1453 pub partition_by_company: bool,
1454}
1455
1456fn default_formats() -> Vec<FileFormat> {
1457 vec![FileFormat::Parquet]
1458}
1459fn default_batch_size() -> usize {
1460 100_000
1461}
1462
1463impl Default for OutputConfig {
1464 fn default() -> Self {
1465 Self {
1466 mode: OutputMode::FlatFile,
1467 output_directory: PathBuf::from("./output"),
1468 formats: default_formats(),
1469 compression: CompressionConfig::default(),
1470 batch_size: default_batch_size(),
1471 include_acdoca: true,
1472 include_bseg: false,
1473 partition_by_period: true,
1474 partition_by_company: false,
1475 }
1476 }
1477}
1478
1479#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
1481#[serde(rename_all = "snake_case")]
1482pub enum OutputMode {
1483 Streaming,
1485 #[default]
1487 FlatFile,
1488 Both,
1490}
1491
1492#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1494#[serde(rename_all = "snake_case")]
1495pub enum FileFormat {
1496 Csv,
1497 Parquet,
1498 Json,
1499 JsonLines,
1500}
1501
1502#[derive(Debug, Clone, Serialize, Deserialize)]
1504pub struct CompressionConfig {
1505 #[serde(default = "default_true")]
1507 pub enabled: bool,
1508 #[serde(default)]
1510 pub algorithm: CompressionAlgorithm,
1511 #[serde(default = "default_compression_level")]
1513 pub level: u8,
1514}
1515
1516fn default_compression_level() -> u8 {
1517 3
1518}
1519
1520impl Default for CompressionConfig {
1521 fn default() -> Self {
1522 Self {
1523 enabled: true,
1524 algorithm: CompressionAlgorithm::default(),
1525 level: default_compression_level(),
1526 }
1527 }
1528}
1529
1530#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
1532#[serde(rename_all = "snake_case")]
1533pub enum CompressionAlgorithm {
1534 Gzip,
1535 #[default]
1536 Zstd,
1537 Lz4,
1538 Snappy,
1539}
1540
1541#[derive(Debug, Clone, Serialize, Deserialize)]
1543pub struct FraudConfig {
1544 #[serde(default)]
1546 pub enabled: bool,
1547 #[serde(default = "default_fraud_rate")]
1549 pub fraud_rate: f64,
1550 #[serde(default)]
1552 pub fraud_type_distribution: FraudTypeDistribution,
1553 #[serde(default)]
1555 pub clustering_enabled: bool,
1556 #[serde(default = "default_clustering_factor")]
1558 pub clustering_factor: f64,
1559 #[serde(default = "default_approval_thresholds")]
1561 pub approval_thresholds: Vec<f64>,
1562}
1563
1564fn default_approval_thresholds() -> Vec<f64> {
1565 vec![1000.0, 5000.0, 10000.0, 25000.0, 50000.0, 100000.0]
1566}
1567
1568fn default_fraud_rate() -> f64 {
1569 0.005
1570}
1571fn default_clustering_factor() -> f64 {
1572 3.0
1573}
1574
1575impl Default for FraudConfig {
1576 fn default() -> Self {
1577 Self {
1578 enabled: false,
1579 fraud_rate: default_fraud_rate(),
1580 fraud_type_distribution: FraudTypeDistribution::default(),
1581 clustering_enabled: false,
1582 clustering_factor: default_clustering_factor(),
1583 approval_thresholds: default_approval_thresholds(),
1584 }
1585 }
1586}
1587
1588#[derive(Debug, Clone, Serialize, Deserialize)]
1590pub struct FraudTypeDistribution {
1591 pub suspense_account_abuse: f64,
1592 pub fictitious_transaction: f64,
1593 pub revenue_manipulation: f64,
1594 pub expense_capitalization: f64,
1595 pub split_transaction: f64,
1596 pub timing_anomaly: f64,
1597 pub unauthorized_access: f64,
1598 pub duplicate_payment: f64,
1599}
1600
1601impl Default for FraudTypeDistribution {
1602 fn default() -> Self {
1603 Self {
1604 suspense_account_abuse: 0.25,
1605 fictitious_transaction: 0.15,
1606 revenue_manipulation: 0.10,
1607 expense_capitalization: 0.10,
1608 split_transaction: 0.15,
1609 timing_anomaly: 0.10,
1610 unauthorized_access: 0.10,
1611 duplicate_payment: 0.05,
1612 }
1613 }
1614}
1615
1616#[derive(Debug, Clone, Serialize, Deserialize)]
1618pub struct InternalControlsConfig {
1619 #[serde(default)]
1621 pub enabled: bool,
1622 #[serde(default = "default_exception_rate")]
1624 pub exception_rate: f64,
1625 #[serde(default = "default_sod_violation_rate")]
1627 pub sod_violation_rate: f64,
1628 #[serde(default = "default_true")]
1630 pub export_control_master_data: bool,
1631 #[serde(default = "default_sox_materiality_threshold")]
1633 pub sox_materiality_threshold: f64,
1634 #[serde(default = "default_true")]
1636 pub coso_enabled: bool,
1637 #[serde(default)]
1639 pub include_entity_level_controls: bool,
1640 #[serde(default = "default_target_maturity_level")]
1643 pub target_maturity_level: String,
1644}
1645
1646fn default_exception_rate() -> f64 {
1647 0.02
1648}
1649
1650fn default_sod_violation_rate() -> f64 {
1651 0.01
1652}
1653
1654fn default_sox_materiality_threshold() -> f64 {
1655 10000.0
1656}
1657
1658fn default_target_maturity_level() -> String {
1659 "mixed".to_string()
1660}
1661
1662impl Default for InternalControlsConfig {
1663 fn default() -> Self {
1664 Self {
1665 enabled: false,
1666 exception_rate: default_exception_rate(),
1667 sod_violation_rate: default_sod_violation_rate(),
1668 export_control_master_data: true,
1669 sox_materiality_threshold: default_sox_materiality_threshold(),
1670 coso_enabled: true,
1671 include_entity_level_controls: false,
1672 target_maturity_level: default_target_maturity_level(),
1673 }
1674 }
1675}
1676
1677#[derive(Debug, Clone, Serialize, Deserialize)]
1679pub struct BusinessProcessConfig {
1680 #[serde(default = "default_o2c")]
1682 pub o2c_weight: f64,
1683 #[serde(default = "default_p2p")]
1685 pub p2p_weight: f64,
1686 #[serde(default = "default_r2r")]
1688 pub r2r_weight: f64,
1689 #[serde(default = "default_h2r")]
1691 pub h2r_weight: f64,
1692 #[serde(default = "default_a2r")]
1694 pub a2r_weight: f64,
1695}
1696
1697fn default_o2c() -> f64 {
1698 0.35
1699}
1700fn default_p2p() -> f64 {
1701 0.30
1702}
1703fn default_r2r() -> f64 {
1704 0.20
1705}
1706fn default_h2r() -> f64 {
1707 0.10
1708}
1709fn default_a2r() -> f64 {
1710 0.05
1711}
1712
1713impl Default for BusinessProcessConfig {
1714 fn default() -> Self {
1715 Self {
1716 o2c_weight: default_o2c(),
1717 p2p_weight: default_p2p(),
1718 r2r_weight: default_r2r(),
1719 h2r_weight: default_h2r(),
1720 a2r_weight: default_a2r(),
1721 }
1722 }
1723}
1724
1725#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1727pub struct UserPersonaConfig {
1728 #[serde(default)]
1730 pub persona_distribution: PersonaDistribution,
1731 #[serde(default)]
1733 pub users_per_persona: UsersPerPersona,
1734}
1735
1736#[derive(Debug, Clone, Serialize, Deserialize)]
1738pub struct PersonaDistribution {
1739 pub junior_accountant: f64,
1740 pub senior_accountant: f64,
1741 pub controller: f64,
1742 pub manager: f64,
1743 pub automated_system: f64,
1744}
1745
1746impl Default for PersonaDistribution {
1747 fn default() -> Self {
1748 Self {
1749 junior_accountant: 0.15,
1750 senior_accountant: 0.15,
1751 controller: 0.05,
1752 manager: 0.05,
1753 automated_system: 0.60,
1754 }
1755 }
1756}
1757
1758#[derive(Debug, Clone, Serialize, Deserialize)]
1760pub struct UsersPerPersona {
1761 pub junior_accountant: usize,
1762 pub senior_accountant: usize,
1763 pub controller: usize,
1764 pub manager: usize,
1765 pub automated_system: usize,
1766}
1767
1768impl Default for UsersPerPersona {
1769 fn default() -> Self {
1770 Self {
1771 junior_accountant: 10,
1772 senior_accountant: 5,
1773 controller: 2,
1774 manager: 3,
1775 automated_system: 20,
1776 }
1777 }
1778}
1779
1780#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1782pub struct TemplateConfig {
1783 #[serde(default)]
1785 pub names: NameTemplateConfig,
1786 #[serde(default)]
1788 pub descriptions: DescriptionTemplateConfig,
1789 #[serde(default)]
1791 pub references: ReferenceTemplateConfig,
1792}
1793
1794#[derive(Debug, Clone, Serialize, Deserialize)]
1796pub struct NameTemplateConfig {
1797 #[serde(default)]
1799 pub culture_distribution: CultureDistribution,
1800 #[serde(default = "default_email_domain")]
1802 pub email_domain: String,
1803 #[serde(default = "default_true")]
1805 pub generate_realistic_names: bool,
1806}
1807
1808fn default_email_domain() -> String {
1809 "company.com".to_string()
1810}
1811
1812impl Default for NameTemplateConfig {
1813 fn default() -> Self {
1814 Self {
1815 culture_distribution: CultureDistribution::default(),
1816 email_domain: default_email_domain(),
1817 generate_realistic_names: true,
1818 }
1819 }
1820}
1821
1822#[derive(Debug, Clone, Serialize, Deserialize)]
1824pub struct CultureDistribution {
1825 pub western_us: f64,
1826 pub hispanic: f64,
1827 pub german: f64,
1828 pub french: f64,
1829 pub chinese: f64,
1830 pub japanese: f64,
1831 pub indian: f64,
1832}
1833
1834impl Default for CultureDistribution {
1835 fn default() -> Self {
1836 Self {
1837 western_us: 0.40,
1838 hispanic: 0.20,
1839 german: 0.10,
1840 french: 0.05,
1841 chinese: 0.10,
1842 japanese: 0.05,
1843 indian: 0.10,
1844 }
1845 }
1846}
1847
1848#[derive(Debug, Clone, Serialize, Deserialize)]
1850pub struct DescriptionTemplateConfig {
1851 #[serde(default = "default_true")]
1853 pub generate_header_text: bool,
1854 #[serde(default = "default_true")]
1856 pub generate_line_text: bool,
1857}
1858
1859impl Default for DescriptionTemplateConfig {
1860 fn default() -> Self {
1861 Self {
1862 generate_header_text: true,
1863 generate_line_text: true,
1864 }
1865 }
1866}
1867
1868#[derive(Debug, Clone, Serialize, Deserialize)]
1870pub struct ReferenceTemplateConfig {
1871 #[serde(default = "default_true")]
1873 pub generate_references: bool,
1874 #[serde(default = "default_invoice_prefix")]
1876 pub invoice_prefix: String,
1877 #[serde(default = "default_po_prefix")]
1879 pub po_prefix: String,
1880 #[serde(default = "default_so_prefix")]
1882 pub so_prefix: String,
1883}
1884
1885fn default_invoice_prefix() -> String {
1886 "INV".to_string()
1887}
1888fn default_po_prefix() -> String {
1889 "PO".to_string()
1890}
1891fn default_so_prefix() -> String {
1892 "SO".to_string()
1893}
1894
1895impl Default for ReferenceTemplateConfig {
1896 fn default() -> Self {
1897 Self {
1898 generate_references: true,
1899 invoice_prefix: default_invoice_prefix(),
1900 po_prefix: default_po_prefix(),
1901 so_prefix: default_so_prefix(),
1902 }
1903 }
1904}
1905
1906#[derive(Debug, Clone, Serialize, Deserialize)]
1908pub struct ApprovalConfig {
1909 #[serde(default)]
1911 pub enabled: bool,
1912 #[serde(default = "default_auto_approve_threshold")]
1914 pub auto_approve_threshold: f64,
1915 #[serde(default = "default_rejection_rate")]
1917 pub rejection_rate: f64,
1918 #[serde(default = "default_revision_rate")]
1920 pub revision_rate: f64,
1921 #[serde(default = "default_approval_delay_hours")]
1923 pub average_approval_delay_hours: f64,
1924 #[serde(default)]
1926 pub thresholds: Vec<ApprovalThresholdConfig>,
1927}
1928
1929fn default_auto_approve_threshold() -> f64 {
1930 1000.0
1931}
1932fn default_rejection_rate() -> f64 {
1933 0.02
1934}
1935fn default_revision_rate() -> f64 {
1936 0.05
1937}
1938fn default_approval_delay_hours() -> f64 {
1939 4.0
1940}
1941
1942impl Default for ApprovalConfig {
1943 fn default() -> Self {
1944 Self {
1945 enabled: false,
1946 auto_approve_threshold: default_auto_approve_threshold(),
1947 rejection_rate: default_rejection_rate(),
1948 revision_rate: default_revision_rate(),
1949 average_approval_delay_hours: default_approval_delay_hours(),
1950 thresholds: vec![
1951 ApprovalThresholdConfig {
1952 amount: 1000.0,
1953 level: 1,
1954 roles: vec!["senior_accountant".to_string()],
1955 },
1956 ApprovalThresholdConfig {
1957 amount: 10000.0,
1958 level: 2,
1959 roles: vec!["senior_accountant".to_string(), "controller".to_string()],
1960 },
1961 ApprovalThresholdConfig {
1962 amount: 100000.0,
1963 level: 3,
1964 roles: vec![
1965 "senior_accountant".to_string(),
1966 "controller".to_string(),
1967 "manager".to_string(),
1968 ],
1969 },
1970 ApprovalThresholdConfig {
1971 amount: 500000.0,
1972 level: 4,
1973 roles: vec![
1974 "senior_accountant".to_string(),
1975 "controller".to_string(),
1976 "manager".to_string(),
1977 "executive".to_string(),
1978 ],
1979 },
1980 ],
1981 }
1982 }
1983}
1984
1985#[derive(Debug, Clone, Serialize, Deserialize)]
1987pub struct ApprovalThresholdConfig {
1988 pub amount: f64,
1990 pub level: u8,
1992 pub roles: Vec<String>,
1994}
1995
1996#[derive(Debug, Clone, Serialize, Deserialize)]
1998pub struct DepartmentConfig {
1999 #[serde(default)]
2001 pub enabled: bool,
2002 #[serde(default = "default_headcount_multiplier")]
2004 pub headcount_multiplier: f64,
2005 #[serde(default)]
2007 pub custom_departments: Vec<CustomDepartmentConfig>,
2008}
2009
2010fn default_headcount_multiplier() -> f64 {
2011 1.0
2012}
2013
2014impl Default for DepartmentConfig {
2015 fn default() -> Self {
2016 Self {
2017 enabled: false,
2018 headcount_multiplier: default_headcount_multiplier(),
2019 custom_departments: Vec::new(),
2020 }
2021 }
2022}
2023
2024#[derive(Debug, Clone, Serialize, Deserialize)]
2026pub struct CustomDepartmentConfig {
2027 pub code: String,
2029 pub name: String,
2031 #[serde(default)]
2033 pub cost_center: Option<String>,
2034 #[serde(default)]
2036 pub primary_processes: Vec<String>,
2037 #[serde(default)]
2039 pub parent_code: Option<String>,
2040}
2041
2042#[derive(Debug, Clone, Default, Serialize, Deserialize)]
2048pub struct MasterDataConfig {
2049 #[serde(default)]
2051 pub vendors: VendorMasterConfig,
2052 #[serde(default)]
2054 pub customers: CustomerMasterConfig,
2055 #[serde(default)]
2057 pub materials: MaterialMasterConfig,
2058 #[serde(default)]
2060 pub fixed_assets: FixedAssetMasterConfig,
2061 #[serde(default)]
2063 pub employees: EmployeeMasterConfig,
2064 #[serde(default)]
2066 pub cost_centers: CostCenterMasterConfig,
2067}
2068
2069#[derive(Debug, Clone, Serialize, Deserialize)]
2071pub struct VendorMasterConfig {
2072 #[serde(default = "default_vendor_count")]
2074 pub count: usize,
2075 #[serde(default = "default_intercompany_percent")]
2077 pub intercompany_percent: f64,
2078 #[serde(default)]
2080 pub payment_terms_distribution: PaymentTermsDistribution,
2081 #[serde(default)]
2083 pub behavior_distribution: VendorBehaviorDistribution,
2084 #[serde(default = "default_true")]
2086 pub generate_bank_accounts: bool,
2087 #[serde(default = "default_true")]
2089 pub generate_tax_ids: bool,
2090}
2091
2092fn default_vendor_count() -> usize {
2093 500
2094}
2095
2096fn default_intercompany_percent() -> f64 {
2097 0.05
2098}
2099
2100impl Default for VendorMasterConfig {
2101 fn default() -> Self {
2102 Self {
2103 count: default_vendor_count(),
2104 intercompany_percent: default_intercompany_percent(),
2105 payment_terms_distribution: PaymentTermsDistribution::default(),
2106 behavior_distribution: VendorBehaviorDistribution::default(),
2107 generate_bank_accounts: true,
2108 generate_tax_ids: true,
2109 }
2110 }
2111}
2112
2113#[derive(Debug, Clone, Serialize, Deserialize)]
2115pub struct PaymentTermsDistribution {
2116 pub net_30: f64,
2118 pub net_60: f64,
2120 pub net_90: f64,
2122 pub two_ten_net_30: f64,
2124 pub due_on_receipt: f64,
2126 pub end_of_month: f64,
2128}
2129
2130impl Default for PaymentTermsDistribution {
2131 fn default() -> Self {
2132 Self {
2133 net_30: 0.40,
2134 net_60: 0.20,
2135 net_90: 0.10,
2136 two_ten_net_30: 0.15,
2137 due_on_receipt: 0.05,
2138 end_of_month: 0.10,
2139 }
2140 }
2141}
2142
2143#[derive(Debug, Clone, Serialize, Deserialize)]
2145pub struct VendorBehaviorDistribution {
2146 pub reliable: f64,
2148 pub sometimes_late: f64,
2150 pub inconsistent_quality: f64,
2152 pub premium: f64,
2154 pub budget: f64,
2156}
2157
2158impl Default for VendorBehaviorDistribution {
2159 fn default() -> Self {
2160 Self {
2161 reliable: 0.50,
2162 sometimes_late: 0.20,
2163 inconsistent_quality: 0.10,
2164 premium: 0.10,
2165 budget: 0.10,
2166 }
2167 }
2168}
2169
2170#[derive(Debug, Clone, Serialize, Deserialize)]
2172pub struct CustomerMasterConfig {
2173 #[serde(default = "default_customer_count")]
2175 pub count: usize,
2176 #[serde(default = "default_intercompany_percent")]
2178 pub intercompany_percent: f64,
2179 #[serde(default)]
2181 pub credit_rating_distribution: CreditRatingDistribution,
2182 #[serde(default)]
2184 pub payment_behavior_distribution: PaymentBehaviorDistribution,
2185 #[serde(default = "default_true")]
2187 pub generate_credit_limits: bool,
2188}
2189
2190fn default_customer_count() -> usize {
2191 2000
2192}
2193
2194impl Default for CustomerMasterConfig {
2195 fn default() -> Self {
2196 Self {
2197 count: default_customer_count(),
2198 intercompany_percent: default_intercompany_percent(),
2199 credit_rating_distribution: CreditRatingDistribution::default(),
2200 payment_behavior_distribution: PaymentBehaviorDistribution::default(),
2201 generate_credit_limits: true,
2202 }
2203 }
2204}
2205
2206#[derive(Debug, Clone, Serialize, Deserialize)]
2208pub struct CreditRatingDistribution {
2209 pub aaa: f64,
2211 pub aa: f64,
2213 pub a: f64,
2215 pub bbb: f64,
2217 pub bb: f64,
2219 pub b: f64,
2221 pub below_b: f64,
2223}
2224
2225impl Default for CreditRatingDistribution {
2226 fn default() -> Self {
2227 Self {
2228 aaa: 0.05,
2229 aa: 0.10,
2230 a: 0.20,
2231 bbb: 0.30,
2232 bb: 0.20,
2233 b: 0.10,
2234 below_b: 0.05,
2235 }
2236 }
2237}
2238
2239#[derive(Debug, Clone, Serialize, Deserialize)]
2241pub struct PaymentBehaviorDistribution {
2242 pub early_payer: f64,
2244 pub on_time: f64,
2246 pub occasional_late: f64,
2248 pub frequent_late: f64,
2250 pub discount_taker: f64,
2252}
2253
2254impl Default for PaymentBehaviorDistribution {
2255 fn default() -> Self {
2256 Self {
2257 early_payer: 0.10,
2258 on_time: 0.50,
2259 occasional_late: 0.25,
2260 frequent_late: 0.10,
2261 discount_taker: 0.05,
2262 }
2263 }
2264}
2265
2266#[derive(Debug, Clone, Serialize, Deserialize)]
2268pub struct MaterialMasterConfig {
2269 #[serde(default = "default_material_count")]
2271 pub count: usize,
2272 #[serde(default)]
2274 pub type_distribution: MaterialTypeDistribution,
2275 #[serde(default)]
2277 pub valuation_distribution: ValuationMethodDistribution,
2278 #[serde(default = "default_bom_percent")]
2280 pub bom_percent: f64,
2281 #[serde(default = "default_max_bom_depth")]
2283 pub max_bom_depth: u8,
2284}
2285
2286fn default_material_count() -> usize {
2287 5000
2288}
2289
2290fn default_bom_percent() -> f64 {
2291 0.20
2292}
2293
2294fn default_max_bom_depth() -> u8 {
2295 3
2296}
2297
2298impl Default for MaterialMasterConfig {
2299 fn default() -> Self {
2300 Self {
2301 count: default_material_count(),
2302 type_distribution: MaterialTypeDistribution::default(),
2303 valuation_distribution: ValuationMethodDistribution::default(),
2304 bom_percent: default_bom_percent(),
2305 max_bom_depth: default_max_bom_depth(),
2306 }
2307 }
2308}
2309
2310#[derive(Debug, Clone, Serialize, Deserialize)]
2312pub struct MaterialTypeDistribution {
2313 pub raw_material: f64,
2315 pub semi_finished: f64,
2317 pub finished_good: f64,
2319 pub trading_good: f64,
2321 pub operating_supply: f64,
2323 pub service: f64,
2325}
2326
2327impl Default for MaterialTypeDistribution {
2328 fn default() -> Self {
2329 Self {
2330 raw_material: 0.30,
2331 semi_finished: 0.15,
2332 finished_good: 0.25,
2333 trading_good: 0.15,
2334 operating_supply: 0.10,
2335 service: 0.05,
2336 }
2337 }
2338}
2339
2340#[derive(Debug, Clone, Serialize, Deserialize)]
2342pub struct ValuationMethodDistribution {
2343 pub standard_cost: f64,
2345 pub moving_average: f64,
2347 pub fifo: f64,
2349 pub lifo: f64,
2351}
2352
2353impl Default for ValuationMethodDistribution {
2354 fn default() -> Self {
2355 Self {
2356 standard_cost: 0.50,
2357 moving_average: 0.30,
2358 fifo: 0.15,
2359 lifo: 0.05,
2360 }
2361 }
2362}
2363
2364#[derive(Debug, Clone, Serialize, Deserialize)]
2366pub struct FixedAssetMasterConfig {
2367 #[serde(default = "default_asset_count")]
2369 pub count: usize,
2370 #[serde(default)]
2372 pub class_distribution: AssetClassDistribution,
2373 #[serde(default)]
2375 pub depreciation_distribution: DepreciationMethodDistribution,
2376 #[serde(default = "default_fully_depreciated_percent")]
2378 pub fully_depreciated_percent: f64,
2379 #[serde(default = "default_true")]
2381 pub generate_acquisition_history: bool,
2382}
2383
2384fn default_asset_count() -> usize {
2385 800
2386}
2387
2388fn default_fully_depreciated_percent() -> f64 {
2389 0.15
2390}
2391
2392impl Default for FixedAssetMasterConfig {
2393 fn default() -> Self {
2394 Self {
2395 count: default_asset_count(),
2396 class_distribution: AssetClassDistribution::default(),
2397 depreciation_distribution: DepreciationMethodDistribution::default(),
2398 fully_depreciated_percent: default_fully_depreciated_percent(),
2399 generate_acquisition_history: true,
2400 }
2401 }
2402}
2403
2404#[derive(Debug, Clone, Serialize, Deserialize)]
2406pub struct AssetClassDistribution {
2407 pub buildings: f64,
2409 pub machinery: f64,
2411 pub vehicles: f64,
2413 pub it_equipment: f64,
2415 pub furniture: f64,
2417 pub land: f64,
2419 pub leasehold: f64,
2421}
2422
2423impl Default for AssetClassDistribution {
2424 fn default() -> Self {
2425 Self {
2426 buildings: 0.15,
2427 machinery: 0.30,
2428 vehicles: 0.15,
2429 it_equipment: 0.20,
2430 furniture: 0.10,
2431 land: 0.05,
2432 leasehold: 0.05,
2433 }
2434 }
2435}
2436
2437#[derive(Debug, Clone, Serialize, Deserialize)]
2439pub struct DepreciationMethodDistribution {
2440 pub straight_line: f64,
2442 pub declining_balance: f64,
2444 pub double_declining: f64,
2446 pub sum_of_years: f64,
2448 pub units_of_production: f64,
2450}
2451
2452impl Default for DepreciationMethodDistribution {
2453 fn default() -> Self {
2454 Self {
2455 straight_line: 0.60,
2456 declining_balance: 0.20,
2457 double_declining: 0.10,
2458 sum_of_years: 0.05,
2459 units_of_production: 0.05,
2460 }
2461 }
2462}
2463
2464#[derive(Debug, Clone, Serialize, Deserialize)]
2466pub struct EmployeeMasterConfig {
2467 #[serde(default = "default_employee_count")]
2469 pub count: usize,
2470 #[serde(default = "default_true")]
2472 pub generate_hierarchy: bool,
2473 #[serde(default = "default_hierarchy_depth")]
2475 pub max_hierarchy_depth: u8,
2476 #[serde(default = "default_span_of_control")]
2478 pub average_span_of_control: f64,
2479 #[serde(default)]
2481 pub approval_limits: ApprovalLimitDistribution,
2482 #[serde(default)]
2484 pub department_distribution: EmployeeDepartmentDistribution,
2485}
2486
2487fn default_employee_count() -> usize {
2488 1500
2489}
2490
2491fn default_hierarchy_depth() -> u8 {
2492 6
2493}
2494
2495fn default_span_of_control() -> f64 {
2496 5.0
2497}
2498
2499impl Default for EmployeeMasterConfig {
2500 fn default() -> Self {
2501 Self {
2502 count: default_employee_count(),
2503 generate_hierarchy: true,
2504 max_hierarchy_depth: default_hierarchy_depth(),
2505 average_span_of_control: default_span_of_control(),
2506 approval_limits: ApprovalLimitDistribution::default(),
2507 department_distribution: EmployeeDepartmentDistribution::default(),
2508 }
2509 }
2510}
2511
2512#[derive(Debug, Clone, Serialize, Deserialize)]
2514pub struct ApprovalLimitDistribution {
2515 #[serde(default = "default_staff_limit")]
2517 pub staff: f64,
2518 #[serde(default = "default_senior_limit")]
2520 pub senior: f64,
2521 #[serde(default = "default_manager_limit")]
2523 pub manager: f64,
2524 #[serde(default = "default_director_limit")]
2526 pub director: f64,
2527 #[serde(default = "default_vp_limit")]
2529 pub vp: f64,
2530 #[serde(default = "default_executive_limit")]
2532 pub executive: f64,
2533}
2534
2535fn default_staff_limit() -> f64 {
2536 1000.0
2537}
2538fn default_senior_limit() -> f64 {
2539 5000.0
2540}
2541fn default_manager_limit() -> f64 {
2542 25000.0
2543}
2544fn default_director_limit() -> f64 {
2545 100000.0
2546}
2547fn default_vp_limit() -> f64 {
2548 500000.0
2549}
2550fn default_executive_limit() -> f64 {
2551 f64::INFINITY
2552}
2553
2554impl Default for ApprovalLimitDistribution {
2555 fn default() -> Self {
2556 Self {
2557 staff: default_staff_limit(),
2558 senior: default_senior_limit(),
2559 manager: default_manager_limit(),
2560 director: default_director_limit(),
2561 vp: default_vp_limit(),
2562 executive: default_executive_limit(),
2563 }
2564 }
2565}
2566
2567#[derive(Debug, Clone, Serialize, Deserialize)]
2569pub struct EmployeeDepartmentDistribution {
2570 pub finance: f64,
2572 pub procurement: f64,
2574 pub sales: f64,
2576 pub warehouse: f64,
2578 pub it: f64,
2580 pub hr: f64,
2582 pub operations: f64,
2584 pub executive: f64,
2586}
2587
2588impl Default for EmployeeDepartmentDistribution {
2589 fn default() -> Self {
2590 Self {
2591 finance: 0.12,
2592 procurement: 0.10,
2593 sales: 0.25,
2594 warehouse: 0.15,
2595 it: 0.10,
2596 hr: 0.05,
2597 operations: 0.20,
2598 executive: 0.03,
2599 }
2600 }
2601}
2602
2603#[derive(Debug, Clone, Serialize, Deserialize)]
2605pub struct CostCenterMasterConfig {
2606 #[serde(default = "default_cost_center_count")]
2608 pub count: usize,
2609 #[serde(default = "default_true")]
2611 pub generate_hierarchy: bool,
2612 #[serde(default = "default_cc_hierarchy_depth")]
2614 pub max_hierarchy_depth: u8,
2615}
2616
2617fn default_cost_center_count() -> usize {
2618 50
2619}
2620
2621fn default_cc_hierarchy_depth() -> u8 {
2622 3
2623}
2624
2625impl Default for CostCenterMasterConfig {
2626 fn default() -> Self {
2627 Self {
2628 count: default_cost_center_count(),
2629 generate_hierarchy: true,
2630 max_hierarchy_depth: default_cc_hierarchy_depth(),
2631 }
2632 }
2633}
2634
2635#[derive(Debug, Clone, Serialize, Deserialize)]
2641pub struct DocumentFlowConfig {
2642 #[serde(default)]
2644 pub p2p: P2PFlowConfig,
2645 #[serde(default)]
2647 pub o2c: O2CFlowConfig,
2648 #[serde(default = "default_true")]
2650 pub generate_document_references: bool,
2651 #[serde(default)]
2653 pub export_flow_graph: bool,
2654}
2655
2656impl Default for DocumentFlowConfig {
2657 fn default() -> Self {
2658 Self {
2659 p2p: P2PFlowConfig::default(),
2660 o2c: O2CFlowConfig::default(),
2661 generate_document_references: true,
2662 export_flow_graph: false,
2663 }
2664 }
2665}
2666
2667#[derive(Debug, Clone, Serialize, Deserialize)]
2669pub struct P2PFlowConfig {
2670 #[serde(default = "default_true")]
2672 pub enabled: bool,
2673 #[serde(default = "default_three_way_match_rate")]
2675 pub three_way_match_rate: f64,
2676 #[serde(default = "default_partial_delivery_rate")]
2678 pub partial_delivery_rate: f64,
2679 #[serde(default = "default_price_variance_rate")]
2681 pub price_variance_rate: f64,
2682 #[serde(default = "default_max_price_variance")]
2684 pub max_price_variance_percent: f64,
2685 #[serde(default = "default_quantity_variance_rate")]
2687 pub quantity_variance_rate: f64,
2688 #[serde(default = "default_po_to_gr_days")]
2690 pub average_po_to_gr_days: u32,
2691 #[serde(default = "default_gr_to_invoice_days")]
2693 pub average_gr_to_invoice_days: u32,
2694 #[serde(default = "default_invoice_to_payment_days")]
2696 pub average_invoice_to_payment_days: u32,
2697 #[serde(default)]
2699 pub line_count_distribution: DocumentLineCountDistribution,
2700 #[serde(default)]
2702 pub payment_behavior: P2PPaymentBehaviorConfig,
2703 #[serde(default)]
2705 pub over_delivery_rate: Option<f64>,
2706 #[serde(default)]
2708 pub early_payment_discount_rate: Option<f64>,
2709}
2710
2711fn default_three_way_match_rate() -> f64 {
2712 0.95
2713}
2714
2715fn default_partial_delivery_rate() -> f64 {
2716 0.15
2717}
2718
2719fn default_price_variance_rate() -> f64 {
2720 0.08
2721}
2722
2723fn default_max_price_variance() -> f64 {
2724 0.05
2725}
2726
2727fn default_quantity_variance_rate() -> f64 {
2728 0.05
2729}
2730
2731fn default_po_to_gr_days() -> u32 {
2732 14
2733}
2734
2735fn default_gr_to_invoice_days() -> u32 {
2736 5
2737}
2738
2739fn default_invoice_to_payment_days() -> u32 {
2740 30
2741}
2742
2743impl Default for P2PFlowConfig {
2744 fn default() -> Self {
2745 Self {
2746 enabled: true,
2747 three_way_match_rate: default_three_way_match_rate(),
2748 partial_delivery_rate: default_partial_delivery_rate(),
2749 price_variance_rate: default_price_variance_rate(),
2750 max_price_variance_percent: default_max_price_variance(),
2751 quantity_variance_rate: default_quantity_variance_rate(),
2752 average_po_to_gr_days: default_po_to_gr_days(),
2753 average_gr_to_invoice_days: default_gr_to_invoice_days(),
2754 average_invoice_to_payment_days: default_invoice_to_payment_days(),
2755 line_count_distribution: DocumentLineCountDistribution::default(),
2756 payment_behavior: P2PPaymentBehaviorConfig::default(),
2757 over_delivery_rate: None,
2758 early_payment_discount_rate: None,
2759 }
2760 }
2761}
2762
2763#[derive(Debug, Clone, Serialize, Deserialize)]
2769pub struct P2PPaymentBehaviorConfig {
2770 #[serde(default = "default_p2p_late_payment_rate")]
2772 pub late_payment_rate: f64,
2773 #[serde(default)]
2775 pub late_payment_days_distribution: LatePaymentDaysDistribution,
2776 #[serde(default = "default_p2p_partial_payment_rate")]
2778 pub partial_payment_rate: f64,
2779 #[serde(default = "default_p2p_payment_correction_rate")]
2781 pub payment_correction_rate: f64,
2782 #[serde(default = "default_p2p_avg_days_until_remainder")]
2784 pub avg_days_until_remainder: u32,
2785}
2786
2787fn default_p2p_late_payment_rate() -> f64 {
2788 0.15
2789}
2790
2791fn default_p2p_partial_payment_rate() -> f64 {
2792 0.05
2793}
2794
2795fn default_p2p_payment_correction_rate() -> f64 {
2796 0.02
2797}
2798
2799fn default_p2p_avg_days_until_remainder() -> u32 {
2800 30
2801}
2802
2803impl Default for P2PPaymentBehaviorConfig {
2804 fn default() -> Self {
2805 Self {
2806 late_payment_rate: default_p2p_late_payment_rate(),
2807 late_payment_days_distribution: LatePaymentDaysDistribution::default(),
2808 partial_payment_rate: default_p2p_partial_payment_rate(),
2809 payment_correction_rate: default_p2p_payment_correction_rate(),
2810 avg_days_until_remainder: default_p2p_avg_days_until_remainder(),
2811 }
2812 }
2813}
2814
2815#[derive(Debug, Clone, Serialize, Deserialize)]
2817pub struct LatePaymentDaysDistribution {
2818 #[serde(default = "default_slightly_late")]
2820 pub slightly_late_1_to_7: f64,
2821 #[serde(default = "default_late_8_14")]
2823 pub late_8_to_14: f64,
2824 #[serde(default = "default_very_late")]
2826 pub very_late_15_to_30: f64,
2827 #[serde(default = "default_severely_late")]
2829 pub severely_late_31_to_60: f64,
2830 #[serde(default = "default_extremely_late")]
2832 pub extremely_late_over_60: f64,
2833}
2834
2835fn default_slightly_late() -> f64 {
2836 0.50
2837}
2838
2839fn default_late_8_14() -> f64 {
2840 0.25
2841}
2842
2843fn default_very_late() -> f64 {
2844 0.15
2845}
2846
2847fn default_severely_late() -> f64 {
2848 0.07
2849}
2850
2851fn default_extremely_late() -> f64 {
2852 0.03
2853}
2854
2855impl Default for LatePaymentDaysDistribution {
2856 fn default() -> Self {
2857 Self {
2858 slightly_late_1_to_7: default_slightly_late(),
2859 late_8_to_14: default_late_8_14(),
2860 very_late_15_to_30: default_very_late(),
2861 severely_late_31_to_60: default_severely_late(),
2862 extremely_late_over_60: default_extremely_late(),
2863 }
2864 }
2865}
2866
2867#[derive(Debug, Clone, Serialize, Deserialize)]
2869pub struct O2CFlowConfig {
2870 #[serde(default = "default_true")]
2872 pub enabled: bool,
2873 #[serde(default = "default_credit_check_failure_rate")]
2875 pub credit_check_failure_rate: f64,
2876 #[serde(default = "default_partial_shipment_rate")]
2878 pub partial_shipment_rate: f64,
2879 #[serde(default = "default_return_rate")]
2881 pub return_rate: f64,
2882 #[serde(default = "default_bad_debt_rate")]
2884 pub bad_debt_rate: f64,
2885 #[serde(default = "default_so_to_delivery_days")]
2887 pub average_so_to_delivery_days: u32,
2888 #[serde(default = "default_delivery_to_invoice_days")]
2890 pub average_delivery_to_invoice_days: u32,
2891 #[serde(default = "default_invoice_to_receipt_days")]
2893 pub average_invoice_to_receipt_days: u32,
2894 #[serde(default)]
2896 pub line_count_distribution: DocumentLineCountDistribution,
2897 #[serde(default)]
2899 pub cash_discount: CashDiscountConfig,
2900 #[serde(default)]
2902 pub payment_behavior: O2CPaymentBehaviorConfig,
2903 #[serde(default)]
2905 pub late_payment_rate: Option<f64>,
2906}
2907
2908fn default_credit_check_failure_rate() -> f64 {
2909 0.02
2910}
2911
2912fn default_partial_shipment_rate() -> f64 {
2913 0.10
2914}
2915
2916fn default_return_rate() -> f64 {
2917 0.03
2918}
2919
2920fn default_bad_debt_rate() -> f64 {
2921 0.01
2922}
2923
2924fn default_so_to_delivery_days() -> u32 {
2925 7
2926}
2927
2928fn default_delivery_to_invoice_days() -> u32 {
2929 1
2930}
2931
2932fn default_invoice_to_receipt_days() -> u32 {
2933 45
2934}
2935
2936impl Default for O2CFlowConfig {
2937 fn default() -> Self {
2938 Self {
2939 enabled: true,
2940 credit_check_failure_rate: default_credit_check_failure_rate(),
2941 partial_shipment_rate: default_partial_shipment_rate(),
2942 return_rate: default_return_rate(),
2943 bad_debt_rate: default_bad_debt_rate(),
2944 average_so_to_delivery_days: default_so_to_delivery_days(),
2945 average_delivery_to_invoice_days: default_delivery_to_invoice_days(),
2946 average_invoice_to_receipt_days: default_invoice_to_receipt_days(),
2947 line_count_distribution: DocumentLineCountDistribution::default(),
2948 cash_discount: CashDiscountConfig::default(),
2949 payment_behavior: O2CPaymentBehaviorConfig::default(),
2950 late_payment_rate: None,
2951 }
2952 }
2953}
2954
2955#[derive(Debug, Clone, Serialize, Deserialize, Default)]
2961pub struct O2CPaymentBehaviorConfig {
2962 #[serde(default)]
2964 pub dunning: DunningConfig,
2965 #[serde(default)]
2967 pub partial_payments: PartialPaymentConfig,
2968 #[serde(default)]
2970 pub short_payments: ShortPaymentConfig,
2971 #[serde(default)]
2973 pub on_account_payments: OnAccountPaymentConfig,
2974 #[serde(default)]
2976 pub payment_corrections: PaymentCorrectionConfig,
2977}
2978
2979#[derive(Debug, Clone, Serialize, Deserialize)]
2981pub struct DunningConfig {
2982 #[serde(default)]
2984 pub enabled: bool,
2985 #[serde(default = "default_dunning_level_1_days")]
2987 pub level_1_days_overdue: u32,
2988 #[serde(default = "default_dunning_level_2_days")]
2990 pub level_2_days_overdue: u32,
2991 #[serde(default = "default_dunning_level_3_days")]
2993 pub level_3_days_overdue: u32,
2994 #[serde(default = "default_collection_days")]
2996 pub collection_days_overdue: u32,
2997 #[serde(default)]
2999 pub payment_after_dunning_rates: DunningPaymentRates,
3000 #[serde(default = "default_dunning_block_rate")]
3002 pub dunning_block_rate: f64,
3003 #[serde(default = "default_dunning_interest_rate")]
3005 pub interest_rate_per_year: f64,
3006 #[serde(default = "default_dunning_charge")]
3008 pub dunning_charge: f64,
3009}
3010
3011fn default_dunning_level_1_days() -> u32 {
3012 14
3013}
3014
3015fn default_dunning_level_2_days() -> u32 {
3016 28
3017}
3018
3019fn default_dunning_level_3_days() -> u32 {
3020 42
3021}
3022
3023fn default_collection_days() -> u32 {
3024 60
3025}
3026
3027fn default_dunning_block_rate() -> f64 {
3028 0.05
3029}
3030
3031fn default_dunning_interest_rate() -> f64 {
3032 0.09
3033}
3034
3035fn default_dunning_charge() -> f64 {
3036 25.0
3037}
3038
3039impl Default for DunningConfig {
3040 fn default() -> Self {
3041 Self {
3042 enabled: false,
3043 level_1_days_overdue: default_dunning_level_1_days(),
3044 level_2_days_overdue: default_dunning_level_2_days(),
3045 level_3_days_overdue: default_dunning_level_3_days(),
3046 collection_days_overdue: default_collection_days(),
3047 payment_after_dunning_rates: DunningPaymentRates::default(),
3048 dunning_block_rate: default_dunning_block_rate(),
3049 interest_rate_per_year: default_dunning_interest_rate(),
3050 dunning_charge: default_dunning_charge(),
3051 }
3052 }
3053}
3054
3055#[derive(Debug, Clone, Serialize, Deserialize)]
3057pub struct DunningPaymentRates {
3058 #[serde(default = "default_after_level_1")]
3060 pub after_level_1: f64,
3061 #[serde(default = "default_after_level_2")]
3063 pub after_level_2: f64,
3064 #[serde(default = "default_after_level_3")]
3066 pub after_level_3: f64,
3067 #[serde(default = "default_during_collection")]
3069 pub during_collection: f64,
3070 #[serde(default = "default_never_pay")]
3072 pub never_pay: f64,
3073}
3074
3075fn default_after_level_1() -> f64 {
3076 0.40
3077}
3078
3079fn default_after_level_2() -> f64 {
3080 0.30
3081}
3082
3083fn default_after_level_3() -> f64 {
3084 0.15
3085}
3086
3087fn default_during_collection() -> f64 {
3088 0.05
3089}
3090
3091fn default_never_pay() -> f64 {
3092 0.10
3093}
3094
3095impl Default for DunningPaymentRates {
3096 fn default() -> Self {
3097 Self {
3098 after_level_1: default_after_level_1(),
3099 after_level_2: default_after_level_2(),
3100 after_level_3: default_after_level_3(),
3101 during_collection: default_during_collection(),
3102 never_pay: default_never_pay(),
3103 }
3104 }
3105}
3106
3107#[derive(Debug, Clone, Serialize, Deserialize)]
3109pub struct PartialPaymentConfig {
3110 #[serde(default = "default_partial_payment_rate")]
3112 pub rate: f64,
3113 #[serde(default)]
3115 pub percentage_distribution: PartialPaymentPercentageDistribution,
3116 #[serde(default = "default_avg_days_until_remainder")]
3118 pub avg_days_until_remainder: u32,
3119}
3120
3121fn default_partial_payment_rate() -> f64 {
3122 0.08
3123}
3124
3125fn default_avg_days_until_remainder() -> u32 {
3126 30
3127}
3128
3129impl Default for PartialPaymentConfig {
3130 fn default() -> Self {
3131 Self {
3132 rate: default_partial_payment_rate(),
3133 percentage_distribution: PartialPaymentPercentageDistribution::default(),
3134 avg_days_until_remainder: default_avg_days_until_remainder(),
3135 }
3136 }
3137}
3138
3139#[derive(Debug, Clone, Serialize, Deserialize)]
3141pub struct PartialPaymentPercentageDistribution {
3142 #[serde(default = "default_partial_25")]
3144 pub pay_25_percent: f64,
3145 #[serde(default = "default_partial_50")]
3147 pub pay_50_percent: f64,
3148 #[serde(default = "default_partial_75")]
3150 pub pay_75_percent: f64,
3151 #[serde(default = "default_partial_random")]
3153 pub pay_random_percent: f64,
3154}
3155
3156fn default_partial_25() -> f64 {
3157 0.15
3158}
3159
3160fn default_partial_50() -> f64 {
3161 0.50
3162}
3163
3164fn default_partial_75() -> f64 {
3165 0.25
3166}
3167
3168fn default_partial_random() -> f64 {
3169 0.10
3170}
3171
3172impl Default for PartialPaymentPercentageDistribution {
3173 fn default() -> Self {
3174 Self {
3175 pay_25_percent: default_partial_25(),
3176 pay_50_percent: default_partial_50(),
3177 pay_75_percent: default_partial_75(),
3178 pay_random_percent: default_partial_random(),
3179 }
3180 }
3181}
3182
3183#[derive(Debug, Clone, Serialize, Deserialize)]
3185pub struct ShortPaymentConfig {
3186 #[serde(default = "default_short_payment_rate")]
3188 pub rate: f64,
3189 #[serde(default)]
3191 pub reason_distribution: ShortPaymentReasonDistribution,
3192 #[serde(default = "default_max_short_percent")]
3194 pub max_short_percent: f64,
3195}
3196
3197fn default_short_payment_rate() -> f64 {
3198 0.03
3199}
3200
3201fn default_max_short_percent() -> f64 {
3202 0.10
3203}
3204
3205impl Default for ShortPaymentConfig {
3206 fn default() -> Self {
3207 Self {
3208 rate: default_short_payment_rate(),
3209 reason_distribution: ShortPaymentReasonDistribution::default(),
3210 max_short_percent: default_max_short_percent(),
3211 }
3212 }
3213}
3214
3215#[derive(Debug, Clone, Serialize, Deserialize)]
3217pub struct ShortPaymentReasonDistribution {
3218 #[serde(default = "default_pricing_dispute")]
3220 pub pricing_dispute: f64,
3221 #[serde(default = "default_quality_issue")]
3223 pub quality_issue: f64,
3224 #[serde(default = "default_quantity_discrepancy")]
3226 pub quantity_discrepancy: f64,
3227 #[serde(default = "default_unauthorized_deduction")]
3229 pub unauthorized_deduction: f64,
3230 #[serde(default = "default_incorrect_discount")]
3232 pub incorrect_discount: f64,
3233}
3234
3235fn default_pricing_dispute() -> f64 {
3236 0.30
3237}
3238
3239fn default_quality_issue() -> f64 {
3240 0.20
3241}
3242
3243fn default_quantity_discrepancy() -> f64 {
3244 0.20
3245}
3246
3247fn default_unauthorized_deduction() -> f64 {
3248 0.15
3249}
3250
3251fn default_incorrect_discount() -> f64 {
3252 0.15
3253}
3254
3255impl Default for ShortPaymentReasonDistribution {
3256 fn default() -> Self {
3257 Self {
3258 pricing_dispute: default_pricing_dispute(),
3259 quality_issue: default_quality_issue(),
3260 quantity_discrepancy: default_quantity_discrepancy(),
3261 unauthorized_deduction: default_unauthorized_deduction(),
3262 incorrect_discount: default_incorrect_discount(),
3263 }
3264 }
3265}
3266
3267#[derive(Debug, Clone, Serialize, Deserialize)]
3269pub struct OnAccountPaymentConfig {
3270 #[serde(default = "default_on_account_rate")]
3272 pub rate: f64,
3273 #[serde(default = "default_avg_days_until_applied")]
3275 pub avg_days_until_applied: u32,
3276}
3277
3278fn default_on_account_rate() -> f64 {
3279 0.02
3280}
3281
3282fn default_avg_days_until_applied() -> u32 {
3283 14
3284}
3285
3286impl Default for OnAccountPaymentConfig {
3287 fn default() -> Self {
3288 Self {
3289 rate: default_on_account_rate(),
3290 avg_days_until_applied: default_avg_days_until_applied(),
3291 }
3292 }
3293}
3294
3295#[derive(Debug, Clone, Serialize, Deserialize)]
3297pub struct PaymentCorrectionConfig {
3298 #[serde(default = "default_payment_correction_rate")]
3300 pub rate: f64,
3301 #[serde(default)]
3303 pub type_distribution: PaymentCorrectionTypeDistribution,
3304}
3305
3306fn default_payment_correction_rate() -> f64 {
3307 0.02
3308}
3309
3310impl Default for PaymentCorrectionConfig {
3311 fn default() -> Self {
3312 Self {
3313 rate: default_payment_correction_rate(),
3314 type_distribution: PaymentCorrectionTypeDistribution::default(),
3315 }
3316 }
3317}
3318
3319#[derive(Debug, Clone, Serialize, Deserialize)]
3321pub struct PaymentCorrectionTypeDistribution {
3322 #[serde(default = "default_nsf_rate")]
3324 pub nsf: f64,
3325 #[serde(default = "default_chargeback_rate")]
3327 pub chargeback: f64,
3328 #[serde(default = "default_wrong_amount_rate")]
3330 pub wrong_amount: f64,
3331 #[serde(default = "default_wrong_customer_rate")]
3333 pub wrong_customer: f64,
3334 #[serde(default = "default_duplicate_payment_rate")]
3336 pub duplicate_payment: f64,
3337}
3338
3339fn default_nsf_rate() -> f64 {
3340 0.30
3341}
3342
3343fn default_chargeback_rate() -> f64 {
3344 0.20
3345}
3346
3347fn default_wrong_amount_rate() -> f64 {
3348 0.20
3349}
3350
3351fn default_wrong_customer_rate() -> f64 {
3352 0.15
3353}
3354
3355fn default_duplicate_payment_rate() -> f64 {
3356 0.15
3357}
3358
3359impl Default for PaymentCorrectionTypeDistribution {
3360 fn default() -> Self {
3361 Self {
3362 nsf: default_nsf_rate(),
3363 chargeback: default_chargeback_rate(),
3364 wrong_amount: default_wrong_amount_rate(),
3365 wrong_customer: default_wrong_customer_rate(),
3366 duplicate_payment: default_duplicate_payment_rate(),
3367 }
3368 }
3369}
3370
3371#[derive(Debug, Clone, Serialize, Deserialize)]
3373pub struct DocumentLineCountDistribution {
3374 #[serde(default = "default_min_lines")]
3376 pub min_lines: u32,
3377 #[serde(default = "default_max_lines")]
3379 pub max_lines: u32,
3380 #[serde(default = "default_mode_lines")]
3382 pub mode_lines: u32,
3383}
3384
3385fn default_min_lines() -> u32 {
3386 1
3387}
3388
3389fn default_max_lines() -> u32 {
3390 20
3391}
3392
3393fn default_mode_lines() -> u32 {
3394 3
3395}
3396
3397impl Default for DocumentLineCountDistribution {
3398 fn default() -> Self {
3399 Self {
3400 min_lines: default_min_lines(),
3401 max_lines: default_max_lines(),
3402 mode_lines: default_mode_lines(),
3403 }
3404 }
3405}
3406
3407#[derive(Debug, Clone, Serialize, Deserialize)]
3409pub struct CashDiscountConfig {
3410 #[serde(default = "default_discount_eligible_rate")]
3412 pub eligible_rate: f64,
3413 #[serde(default = "default_discount_taken_rate")]
3415 pub taken_rate: f64,
3416 #[serde(default = "default_discount_percent")]
3418 pub discount_percent: f64,
3419 #[serde(default = "default_discount_days")]
3421 pub discount_days: u32,
3422}
3423
3424fn default_discount_eligible_rate() -> f64 {
3425 0.30
3426}
3427
3428fn default_discount_taken_rate() -> f64 {
3429 0.60
3430}
3431
3432fn default_discount_percent() -> f64 {
3433 0.02
3434}
3435
3436fn default_discount_days() -> u32 {
3437 10
3438}
3439
3440impl Default for CashDiscountConfig {
3441 fn default() -> Self {
3442 Self {
3443 eligible_rate: default_discount_eligible_rate(),
3444 taken_rate: default_discount_taken_rate(),
3445 discount_percent: default_discount_percent(),
3446 discount_days: default_discount_days(),
3447 }
3448 }
3449}
3450
3451#[derive(Debug, Clone, Serialize, Deserialize)]
3457pub struct IntercompanyConfig {
3458 #[serde(default)]
3460 pub enabled: bool,
3461 #[serde(default = "default_ic_transaction_rate")]
3463 pub ic_transaction_rate: f64,
3464 #[serde(default)]
3466 pub transfer_pricing_method: TransferPricingMethod,
3467 #[serde(default = "default_markup_percent")]
3469 pub markup_percent: f64,
3470 #[serde(default = "default_true")]
3472 pub generate_matched_pairs: bool,
3473 #[serde(default)]
3475 pub transaction_type_distribution: ICTransactionTypeDistribution,
3476 #[serde(default)]
3478 pub generate_eliminations: bool,
3479}
3480
3481fn default_ic_transaction_rate() -> f64 {
3482 0.15
3483}
3484
3485fn default_markup_percent() -> f64 {
3486 0.05
3487}
3488
3489impl Default for IntercompanyConfig {
3490 fn default() -> Self {
3491 Self {
3492 enabled: false,
3493 ic_transaction_rate: default_ic_transaction_rate(),
3494 transfer_pricing_method: TransferPricingMethod::default(),
3495 markup_percent: default_markup_percent(),
3496 generate_matched_pairs: true,
3497 transaction_type_distribution: ICTransactionTypeDistribution::default(),
3498 generate_eliminations: false,
3499 }
3500 }
3501}
3502
3503#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
3505#[serde(rename_all = "snake_case")]
3506pub enum TransferPricingMethod {
3507 #[default]
3509 CostPlus,
3510 ComparableUncontrolled,
3512 ResalePrice,
3514 TransactionalNetMargin,
3516 ProfitSplit,
3518}
3519
3520#[derive(Debug, Clone, Serialize, Deserialize)]
3522pub struct ICTransactionTypeDistribution {
3523 pub goods_sale: f64,
3525 pub service_provided: f64,
3527 pub loan: f64,
3529 pub dividend: f64,
3531 pub management_fee: f64,
3533 pub royalty: f64,
3535 pub cost_sharing: f64,
3537}
3538
3539impl Default for ICTransactionTypeDistribution {
3540 fn default() -> Self {
3541 Self {
3542 goods_sale: 0.35,
3543 service_provided: 0.20,
3544 loan: 0.10,
3545 dividend: 0.05,
3546 management_fee: 0.15,
3547 royalty: 0.10,
3548 cost_sharing: 0.05,
3549 }
3550 }
3551}
3552
3553#[derive(Debug, Clone, Serialize, Deserialize)]
3559pub struct BalanceConfig {
3560 #[serde(default)]
3562 pub generate_opening_balances: bool,
3563 #[serde(default = "default_true")]
3565 pub generate_trial_balances: bool,
3566 #[serde(default = "default_gross_margin")]
3568 pub target_gross_margin: f64,
3569 #[serde(default = "default_dso")]
3571 pub target_dso_days: u32,
3572 #[serde(default = "default_dpo")]
3574 pub target_dpo_days: u32,
3575 #[serde(default = "default_current_ratio")]
3577 pub target_current_ratio: f64,
3578 #[serde(default = "default_debt_equity")]
3580 pub target_debt_to_equity: f64,
3581 #[serde(default = "default_true")]
3583 pub validate_balance_equation: bool,
3584 #[serde(default = "default_true")]
3586 pub reconcile_subledgers: bool,
3587}
3588
3589fn default_gross_margin() -> f64 {
3590 0.35
3591}
3592
3593fn default_dso() -> u32 {
3594 45
3595}
3596
3597fn default_dpo() -> u32 {
3598 30
3599}
3600
3601fn default_current_ratio() -> f64 {
3602 1.5
3603}
3604
3605fn default_debt_equity() -> f64 {
3606 0.5
3607}
3608
3609impl Default for BalanceConfig {
3610 fn default() -> Self {
3611 Self {
3612 generate_opening_balances: false,
3613 generate_trial_balances: true,
3614 target_gross_margin: default_gross_margin(),
3615 target_dso_days: default_dso(),
3616 target_dpo_days: default_dpo(),
3617 target_current_ratio: default_current_ratio(),
3618 target_debt_to_equity: default_debt_equity(),
3619 validate_balance_equation: true,
3620 reconcile_subledgers: true,
3621 }
3622 }
3623}
3624
3625#[derive(Debug, Clone, Serialize, Deserialize)]
3634pub struct OcpmConfig {
3635 #[serde(default)]
3637 pub enabled: bool,
3638
3639 #[serde(default = "default_true")]
3641 pub generate_lifecycle_events: bool,
3642
3643 #[serde(default = "default_true")]
3645 pub include_object_relationships: bool,
3646
3647 #[serde(default = "default_true")]
3649 pub compute_variants: bool,
3650
3651 #[serde(default)]
3653 pub max_variants: usize,
3654
3655 #[serde(default)]
3657 pub p2p_process: OcpmProcessConfig,
3658
3659 #[serde(default)]
3661 pub o2c_process: OcpmProcessConfig,
3662
3663 #[serde(default)]
3665 pub output: OcpmOutputConfig,
3666}
3667
3668impl Default for OcpmConfig {
3669 fn default() -> Self {
3670 Self {
3671 enabled: false,
3672 generate_lifecycle_events: true,
3673 include_object_relationships: true,
3674 compute_variants: true,
3675 max_variants: 0,
3676 p2p_process: OcpmProcessConfig::default(),
3677 o2c_process: OcpmProcessConfig::default(),
3678 output: OcpmOutputConfig::default(),
3679 }
3680 }
3681}
3682
3683#[derive(Debug, Clone, Serialize, Deserialize)]
3685pub struct OcpmProcessConfig {
3686 #[serde(default = "default_rework_probability")]
3688 pub rework_probability: f64,
3689
3690 #[serde(default = "default_skip_probability")]
3692 pub skip_step_probability: f64,
3693
3694 #[serde(default = "default_out_of_order_probability")]
3696 pub out_of_order_probability: f64,
3697}
3698
3699fn default_rework_probability() -> f64 {
3700 0.05
3701}
3702
3703fn default_skip_probability() -> f64 {
3704 0.02
3705}
3706
3707fn default_out_of_order_probability() -> f64 {
3708 0.03
3709}
3710
3711impl Default for OcpmProcessConfig {
3712 fn default() -> Self {
3713 Self {
3714 rework_probability: default_rework_probability(),
3715 skip_step_probability: default_skip_probability(),
3716 out_of_order_probability: default_out_of_order_probability(),
3717 }
3718 }
3719}
3720
3721#[derive(Debug, Clone, Serialize, Deserialize)]
3723pub struct OcpmOutputConfig {
3724 #[serde(default = "default_true")]
3726 pub ocel_json: bool,
3727
3728 #[serde(default)]
3730 pub ocel_xml: bool,
3731
3732 #[serde(default)]
3734 pub xes: bool,
3735
3736 #[serde(default = "default_true")]
3738 pub xes_include_lifecycle: bool,
3739
3740 #[serde(default = "default_true")]
3742 pub xes_include_resources: bool,
3743
3744 #[serde(default = "default_true")]
3746 pub flattened_csv: bool,
3747
3748 #[serde(default = "default_true")]
3750 pub event_object_csv: bool,
3751
3752 #[serde(default = "default_true")]
3754 pub object_relationship_csv: bool,
3755
3756 #[serde(default = "default_true")]
3758 pub variants_csv: bool,
3759
3760 #[serde(default)]
3762 pub export_reference_models: bool,
3763}
3764
3765impl Default for OcpmOutputConfig {
3766 fn default() -> Self {
3767 Self {
3768 ocel_json: true,
3769 ocel_xml: false,
3770 xes: false,
3771 xes_include_lifecycle: true,
3772 xes_include_resources: true,
3773 flattened_csv: true,
3774 event_object_csv: true,
3775 object_relationship_csv: true,
3776 variants_csv: true,
3777 export_reference_models: false,
3778 }
3779 }
3780}
3781
3782#[derive(Debug, Clone, Serialize, Deserialize)]
3784pub struct AuditGenerationConfig {
3785 #[serde(default)]
3787 pub enabled: bool,
3788
3789 #[serde(default = "default_true")]
3791 pub generate_workpapers: bool,
3792
3793 #[serde(default)]
3795 pub engagement_types: AuditEngagementTypesConfig,
3796
3797 #[serde(default)]
3799 pub workpapers: WorkpaperConfig,
3800
3801 #[serde(default)]
3803 pub team: AuditTeamConfig,
3804
3805 #[serde(default)]
3807 pub review: ReviewWorkflowConfig,
3808}
3809
3810impl Default for AuditGenerationConfig {
3811 fn default() -> Self {
3812 Self {
3813 enabled: false,
3814 generate_workpapers: true,
3815 engagement_types: AuditEngagementTypesConfig::default(),
3816 workpapers: WorkpaperConfig::default(),
3817 team: AuditTeamConfig::default(),
3818 review: ReviewWorkflowConfig::default(),
3819 }
3820 }
3821}
3822
3823#[derive(Debug, Clone, Serialize, Deserialize)]
3825pub struct AuditEngagementTypesConfig {
3826 #[serde(default = "default_financial_audit_prob")]
3828 pub financial_statement: f64,
3829 #[serde(default = "default_sox_audit_prob")]
3831 pub sox_icfr: f64,
3832 #[serde(default = "default_integrated_audit_prob")]
3834 pub integrated: f64,
3835 #[serde(default = "default_review_prob")]
3837 pub review: f64,
3838 #[serde(default = "default_aup_prob")]
3840 pub agreed_upon_procedures: f64,
3841}
3842
3843fn default_financial_audit_prob() -> f64 {
3844 0.40
3845}
3846fn default_sox_audit_prob() -> f64 {
3847 0.20
3848}
3849fn default_integrated_audit_prob() -> f64 {
3850 0.25
3851}
3852fn default_review_prob() -> f64 {
3853 0.10
3854}
3855fn default_aup_prob() -> f64 {
3856 0.05
3857}
3858
3859impl Default for AuditEngagementTypesConfig {
3860 fn default() -> Self {
3861 Self {
3862 financial_statement: default_financial_audit_prob(),
3863 sox_icfr: default_sox_audit_prob(),
3864 integrated: default_integrated_audit_prob(),
3865 review: default_review_prob(),
3866 agreed_upon_procedures: default_aup_prob(),
3867 }
3868 }
3869}
3870
3871#[derive(Debug, Clone, Serialize, Deserialize)]
3873pub struct WorkpaperConfig {
3874 #[serde(default = "default_workpapers_per_phase")]
3876 pub average_per_phase: usize,
3877
3878 #[serde(default = "default_true")]
3880 pub include_isa_references: bool,
3881
3882 #[serde(default = "default_true")]
3884 pub include_sample_details: bool,
3885
3886 #[serde(default = "default_true")]
3888 pub include_cross_references: bool,
3889
3890 #[serde(default)]
3892 pub sampling: SamplingConfig,
3893}
3894
3895fn default_workpapers_per_phase() -> usize {
3896 5
3897}
3898
3899impl Default for WorkpaperConfig {
3900 fn default() -> Self {
3901 Self {
3902 average_per_phase: default_workpapers_per_phase(),
3903 include_isa_references: true,
3904 include_sample_details: true,
3905 include_cross_references: true,
3906 sampling: SamplingConfig::default(),
3907 }
3908 }
3909}
3910
3911#[derive(Debug, Clone, Serialize, Deserialize)]
3913pub struct SamplingConfig {
3914 #[serde(default = "default_statistical_rate")]
3916 pub statistical_rate: f64,
3917 #[serde(default = "default_judgmental_rate")]
3919 pub judgmental_rate: f64,
3920 #[serde(default = "default_haphazard_rate")]
3922 pub haphazard_rate: f64,
3923 #[serde(default = "default_complete_examination_rate")]
3925 pub complete_examination_rate: f64,
3926}
3927
3928fn default_statistical_rate() -> f64 {
3929 0.40
3930}
3931fn default_judgmental_rate() -> f64 {
3932 0.30
3933}
3934fn default_haphazard_rate() -> f64 {
3935 0.20
3936}
3937fn default_complete_examination_rate() -> f64 {
3938 0.10
3939}
3940
3941impl Default for SamplingConfig {
3942 fn default() -> Self {
3943 Self {
3944 statistical_rate: default_statistical_rate(),
3945 judgmental_rate: default_judgmental_rate(),
3946 haphazard_rate: default_haphazard_rate(),
3947 complete_examination_rate: default_complete_examination_rate(),
3948 }
3949 }
3950}
3951
3952#[derive(Debug, Clone, Serialize, Deserialize)]
3954pub struct AuditTeamConfig {
3955 #[serde(default = "default_min_team_size")]
3957 pub min_team_size: usize,
3958 #[serde(default = "default_max_team_size")]
3960 pub max_team_size: usize,
3961 #[serde(default = "default_specialist_probability")]
3963 pub specialist_probability: f64,
3964}
3965
3966fn default_min_team_size() -> usize {
3967 3
3968}
3969fn default_max_team_size() -> usize {
3970 8
3971}
3972fn default_specialist_probability() -> f64 {
3973 0.30
3974}
3975
3976impl Default for AuditTeamConfig {
3977 fn default() -> Self {
3978 Self {
3979 min_team_size: default_min_team_size(),
3980 max_team_size: default_max_team_size(),
3981 specialist_probability: default_specialist_probability(),
3982 }
3983 }
3984}
3985
3986#[derive(Debug, Clone, Serialize, Deserialize)]
3988pub struct ReviewWorkflowConfig {
3989 #[serde(default = "default_review_delay_days")]
3991 pub average_review_delay_days: u32,
3992 #[serde(default = "default_rework_probability_review")]
3994 pub rework_probability: f64,
3995 #[serde(default = "default_true")]
3997 pub require_partner_signoff: bool,
3998}
3999
4000fn default_review_delay_days() -> u32 {
4001 2
4002}
4003fn default_rework_probability_review() -> f64 {
4004 0.15
4005}
4006
4007impl Default for ReviewWorkflowConfig {
4008 fn default() -> Self {
4009 Self {
4010 average_review_delay_days: default_review_delay_days(),
4011 rework_probability: default_rework_probability_review(),
4012 require_partner_signoff: true,
4013 }
4014 }
4015}
4016
4017#[derive(Debug, Clone, Serialize, Deserialize)]
4023pub struct DataQualitySchemaConfig {
4024 #[serde(default)]
4026 pub enabled: bool,
4027 #[serde(default)]
4029 pub preset: DataQualityPreset,
4030 #[serde(default)]
4032 pub missing_values: MissingValuesSchemaConfig,
4033 #[serde(default)]
4035 pub typos: TypoSchemaConfig,
4036 #[serde(default)]
4038 pub format_variations: FormatVariationSchemaConfig,
4039 #[serde(default)]
4041 pub duplicates: DuplicateSchemaConfig,
4042 #[serde(default)]
4044 pub encoding_issues: EncodingIssueSchemaConfig,
4045 #[serde(default)]
4047 pub generate_labels: bool,
4048 #[serde(default)]
4050 pub sink_profiles: SinkQualityProfiles,
4051}
4052
4053impl Default for DataQualitySchemaConfig {
4054 fn default() -> Self {
4055 Self {
4056 enabled: false,
4057 preset: DataQualityPreset::None,
4058 missing_values: MissingValuesSchemaConfig::default(),
4059 typos: TypoSchemaConfig::default(),
4060 format_variations: FormatVariationSchemaConfig::default(),
4061 duplicates: DuplicateSchemaConfig::default(),
4062 encoding_issues: EncodingIssueSchemaConfig::default(),
4063 generate_labels: true,
4064 sink_profiles: SinkQualityProfiles::default(),
4065 }
4066 }
4067}
4068
4069impl DataQualitySchemaConfig {
4070 pub fn with_preset(preset: DataQualityPreset) -> Self {
4072 let mut config = Self {
4073 preset,
4074 ..Default::default()
4075 };
4076 config.apply_preset();
4077 config
4078 }
4079
4080 pub fn apply_preset(&mut self) {
4083 if !self.preset.overrides_settings() {
4084 return;
4085 }
4086
4087 self.enabled = true;
4088
4089 self.missing_values.enabled = self.preset.missing_rate() > 0.0;
4091 self.missing_values.rate = self.preset.missing_rate();
4092
4093 self.typos.enabled = self.preset.typo_rate() > 0.0;
4095 self.typos.char_error_rate = self.preset.typo_rate();
4096
4097 self.duplicates.enabled = self.preset.duplicate_rate() > 0.0;
4099 self.duplicates.exact_duplicate_ratio = self.preset.duplicate_rate() * 0.4;
4100 self.duplicates.near_duplicate_ratio = self.preset.duplicate_rate() * 0.4;
4101 self.duplicates.fuzzy_duplicate_ratio = self.preset.duplicate_rate() * 0.2;
4102
4103 self.format_variations.enabled = self.preset.format_variations_enabled();
4105
4106 self.encoding_issues.enabled = self.preset.encoding_issues_enabled();
4108 self.encoding_issues.rate = self.preset.encoding_issue_rate();
4109
4110 if self.preset.ocr_errors_enabled() {
4112 self.typos.type_weights.ocr_errors = 0.3;
4113 }
4114 }
4115
4116 pub fn effective_missing_rate(&self) -> f64 {
4118 if self.preset.overrides_settings() {
4119 self.preset.missing_rate()
4120 } else {
4121 self.missing_values.rate
4122 }
4123 }
4124
4125 pub fn effective_typo_rate(&self) -> f64 {
4127 if self.preset.overrides_settings() {
4128 self.preset.typo_rate()
4129 } else {
4130 self.typos.char_error_rate
4131 }
4132 }
4133
4134 pub fn effective_duplicate_rate(&self) -> f64 {
4136 if self.preset.overrides_settings() {
4137 self.preset.duplicate_rate()
4138 } else {
4139 self.duplicates.exact_duplicate_ratio
4140 + self.duplicates.near_duplicate_ratio
4141 + self.duplicates.fuzzy_duplicate_ratio
4142 }
4143 }
4144
4145 pub fn clean() -> Self {
4147 Self::with_preset(DataQualityPreset::Clean)
4148 }
4149
4150 pub fn noisy() -> Self {
4152 Self::with_preset(DataQualityPreset::Noisy)
4153 }
4154
4155 pub fn legacy() -> Self {
4157 Self::with_preset(DataQualityPreset::Legacy)
4158 }
4159}
4160
4161#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
4163#[serde(rename_all = "snake_case")]
4164pub enum DataQualityPreset {
4165 #[default]
4167 None,
4168 Minimal,
4170 Normal,
4172 High,
4174 Custom,
4176
4177 Clean,
4183 Noisy,
4186 Legacy,
4189}
4190
4191impl DataQualityPreset {
4192 pub fn missing_rate(&self) -> f64 {
4194 match self {
4195 DataQualityPreset::None => 0.0,
4196 DataQualityPreset::Minimal => 0.005,
4197 DataQualityPreset::Normal => 0.02,
4198 DataQualityPreset::High => 0.08,
4199 DataQualityPreset::Custom => 0.01, DataQualityPreset::Clean => 0.001,
4201 DataQualityPreset::Noisy => 0.05,
4202 DataQualityPreset::Legacy => 0.10,
4203 }
4204 }
4205
4206 pub fn typo_rate(&self) -> f64 {
4208 match self {
4209 DataQualityPreset::None => 0.0,
4210 DataQualityPreset::Minimal => 0.0005,
4211 DataQualityPreset::Normal => 0.002,
4212 DataQualityPreset::High => 0.01,
4213 DataQualityPreset::Custom => 0.001, DataQualityPreset::Clean => 0.0005,
4215 DataQualityPreset::Noisy => 0.02,
4216 DataQualityPreset::Legacy => 0.05,
4217 }
4218 }
4219
4220 pub fn duplicate_rate(&self) -> f64 {
4222 match self {
4223 DataQualityPreset::None => 0.0,
4224 DataQualityPreset::Minimal => 0.001,
4225 DataQualityPreset::Normal => 0.005,
4226 DataQualityPreset::High => 0.02,
4227 DataQualityPreset::Custom => 0.0, DataQualityPreset::Clean => 0.0,
4229 DataQualityPreset::Noisy => 0.01,
4230 DataQualityPreset::Legacy => 0.03,
4231 }
4232 }
4233
4234 pub fn format_variations_enabled(&self) -> bool {
4236 match self {
4237 DataQualityPreset::None | DataQualityPreset::Clean => false,
4238 DataQualityPreset::Minimal => true,
4239 DataQualityPreset::Normal => true,
4240 DataQualityPreset::High => true,
4241 DataQualityPreset::Custom => true,
4242 DataQualityPreset::Noisy => true,
4243 DataQualityPreset::Legacy => true,
4244 }
4245 }
4246
4247 pub fn ocr_errors_enabled(&self) -> bool {
4249 matches!(self, DataQualityPreset::Legacy | DataQualityPreset::High)
4250 }
4251
4252 pub fn encoding_issues_enabled(&self) -> bool {
4254 matches!(
4255 self,
4256 DataQualityPreset::Legacy | DataQualityPreset::High | DataQualityPreset::Noisy
4257 )
4258 }
4259
4260 pub fn encoding_issue_rate(&self) -> f64 {
4262 match self {
4263 DataQualityPreset::None | DataQualityPreset::Clean | DataQualityPreset::Minimal => 0.0,
4264 DataQualityPreset::Normal => 0.002,
4265 DataQualityPreset::High => 0.01,
4266 DataQualityPreset::Custom => 0.0,
4267 DataQualityPreset::Noisy => 0.005,
4268 DataQualityPreset::Legacy => 0.02,
4269 }
4270 }
4271
4272 pub fn overrides_settings(&self) -> bool {
4274 !matches!(self, DataQualityPreset::Custom | DataQualityPreset::None)
4275 }
4276
4277 pub fn description(&self) -> &'static str {
4279 match self {
4280 DataQualityPreset::None => "No data quality issues (pristine data)",
4281 DataQualityPreset::Minimal => "Very rare data quality issues",
4282 DataQualityPreset::Normal => "Realistic enterprise data quality",
4283 DataQualityPreset::High => "Messy data for stress testing",
4284 DataQualityPreset::Custom => "Custom settings from configuration",
4285 DataQualityPreset::Clean => "ML-ready clean data with minimal issues",
4286 DataQualityPreset::Noisy => "Typical production data with moderate issues",
4287 DataQualityPreset::Legacy => "Legacy/migrated data with heavy issues and OCR errors",
4288 }
4289 }
4290}
4291
4292#[derive(Debug, Clone, Serialize, Deserialize)]
4294pub struct MissingValuesSchemaConfig {
4295 #[serde(default)]
4297 pub enabled: bool,
4298 #[serde(default = "default_missing_rate")]
4300 pub rate: f64,
4301 #[serde(default)]
4303 pub strategy: MissingValueStrategy,
4304 #[serde(default)]
4306 pub field_rates: std::collections::HashMap<String, f64>,
4307 #[serde(default)]
4309 pub protected_fields: Vec<String>,
4310}
4311
4312fn default_missing_rate() -> f64 {
4313 0.01
4314}
4315
4316impl Default for MissingValuesSchemaConfig {
4317 fn default() -> Self {
4318 Self {
4319 enabled: false,
4320 rate: default_missing_rate(),
4321 strategy: MissingValueStrategy::Mcar,
4322 field_rates: std::collections::HashMap::new(),
4323 protected_fields: vec![
4324 "document_id".to_string(),
4325 "company_code".to_string(),
4326 "posting_date".to_string(),
4327 ],
4328 }
4329 }
4330}
4331
4332#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
4334#[serde(rename_all = "snake_case")]
4335pub enum MissingValueStrategy {
4336 #[default]
4338 Mcar,
4339 Mar,
4341 Mnar,
4343 Systematic,
4345}
4346
4347#[derive(Debug, Clone, Serialize, Deserialize)]
4349pub struct TypoSchemaConfig {
4350 #[serde(default)]
4352 pub enabled: bool,
4353 #[serde(default = "default_typo_rate")]
4355 pub char_error_rate: f64,
4356 #[serde(default)]
4358 pub type_weights: TypoTypeWeights,
4359 #[serde(default)]
4361 pub protected_fields: Vec<String>,
4362}
4363
4364fn default_typo_rate() -> f64 {
4365 0.001
4366}
4367
4368impl Default for TypoSchemaConfig {
4369 fn default() -> Self {
4370 Self {
4371 enabled: false,
4372 char_error_rate: default_typo_rate(),
4373 type_weights: TypoTypeWeights::default(),
4374 protected_fields: vec![
4375 "document_id".to_string(),
4376 "gl_account".to_string(),
4377 "company_code".to_string(),
4378 ],
4379 }
4380 }
4381}
4382
4383#[derive(Debug, Clone, Serialize, Deserialize)]
4385pub struct TypoTypeWeights {
4386 #[serde(default = "default_substitution_weight")]
4388 pub substitution: f64,
4389 #[serde(default = "default_transposition_weight")]
4391 pub transposition: f64,
4392 #[serde(default = "default_insertion_weight")]
4394 pub insertion: f64,
4395 #[serde(default = "default_deletion_weight")]
4397 pub deletion: f64,
4398 #[serde(default = "default_ocr_weight")]
4400 pub ocr_errors: f64,
4401 #[serde(default = "default_homophone_weight")]
4403 pub homophones: f64,
4404}
4405
4406fn default_substitution_weight() -> f64 {
4407 0.35
4408}
4409fn default_transposition_weight() -> f64 {
4410 0.25
4411}
4412fn default_insertion_weight() -> f64 {
4413 0.10
4414}
4415fn default_deletion_weight() -> f64 {
4416 0.15
4417}
4418fn default_ocr_weight() -> f64 {
4419 0.10
4420}
4421fn default_homophone_weight() -> f64 {
4422 0.05
4423}
4424
4425impl Default for TypoTypeWeights {
4426 fn default() -> Self {
4427 Self {
4428 substitution: default_substitution_weight(),
4429 transposition: default_transposition_weight(),
4430 insertion: default_insertion_weight(),
4431 deletion: default_deletion_weight(),
4432 ocr_errors: default_ocr_weight(),
4433 homophones: default_homophone_weight(),
4434 }
4435 }
4436}
4437
4438#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4440pub struct FormatVariationSchemaConfig {
4441 #[serde(default)]
4443 pub enabled: bool,
4444 #[serde(default)]
4446 pub dates: DateFormatVariationConfig,
4447 #[serde(default)]
4449 pub amounts: AmountFormatVariationConfig,
4450 #[serde(default)]
4452 pub identifiers: IdentifierFormatVariationConfig,
4453}
4454
4455#[derive(Debug, Clone, Serialize, Deserialize)]
4457pub struct DateFormatVariationConfig {
4458 #[serde(default)]
4460 pub enabled: bool,
4461 #[serde(default = "default_date_variation_rate")]
4463 pub rate: f64,
4464 #[serde(default = "default_true")]
4466 pub iso_format: bool,
4467 #[serde(default)]
4469 pub us_format: bool,
4470 #[serde(default)]
4472 pub eu_format: bool,
4473 #[serde(default)]
4475 pub long_format: bool,
4476}
4477
4478fn default_date_variation_rate() -> f64 {
4479 0.05
4480}
4481
4482impl Default for DateFormatVariationConfig {
4483 fn default() -> Self {
4484 Self {
4485 enabled: false,
4486 rate: default_date_variation_rate(),
4487 iso_format: true,
4488 us_format: false,
4489 eu_format: false,
4490 long_format: false,
4491 }
4492 }
4493}
4494
4495#[derive(Debug, Clone, Serialize, Deserialize)]
4497pub struct AmountFormatVariationConfig {
4498 #[serde(default)]
4500 pub enabled: bool,
4501 #[serde(default = "default_amount_variation_rate")]
4503 pub rate: f64,
4504 #[serde(default)]
4506 pub us_comma_format: bool,
4507 #[serde(default)]
4509 pub eu_format: bool,
4510 #[serde(default)]
4512 pub currency_prefix: bool,
4513 #[serde(default)]
4515 pub accounting_format: bool,
4516}
4517
4518fn default_amount_variation_rate() -> f64 {
4519 0.02
4520}
4521
4522impl Default for AmountFormatVariationConfig {
4523 fn default() -> Self {
4524 Self {
4525 enabled: false,
4526 rate: default_amount_variation_rate(),
4527 us_comma_format: false,
4528 eu_format: false,
4529 currency_prefix: false,
4530 accounting_format: false,
4531 }
4532 }
4533}
4534
4535#[derive(Debug, Clone, Serialize, Deserialize)]
4537pub struct IdentifierFormatVariationConfig {
4538 #[serde(default)]
4540 pub enabled: bool,
4541 #[serde(default = "default_identifier_variation_rate")]
4543 pub rate: f64,
4544 #[serde(default)]
4546 pub case_variations: bool,
4547 #[serde(default)]
4549 pub padding_variations: bool,
4550 #[serde(default)]
4552 pub separator_variations: bool,
4553}
4554
4555fn default_identifier_variation_rate() -> f64 {
4556 0.02
4557}
4558
4559impl Default for IdentifierFormatVariationConfig {
4560 fn default() -> Self {
4561 Self {
4562 enabled: false,
4563 rate: default_identifier_variation_rate(),
4564 case_variations: false,
4565 padding_variations: false,
4566 separator_variations: false,
4567 }
4568 }
4569}
4570
4571#[derive(Debug, Clone, Serialize, Deserialize)]
4573pub struct DuplicateSchemaConfig {
4574 #[serde(default)]
4576 pub enabled: bool,
4577 #[serde(default = "default_duplicate_rate")]
4579 pub rate: f64,
4580 #[serde(default = "default_exact_duplicate_ratio")]
4582 pub exact_duplicate_ratio: f64,
4583 #[serde(default = "default_near_duplicate_ratio")]
4585 pub near_duplicate_ratio: f64,
4586 #[serde(default = "default_fuzzy_duplicate_ratio")]
4588 pub fuzzy_duplicate_ratio: f64,
4589 #[serde(default = "default_max_date_offset")]
4591 pub max_date_offset_days: u32,
4592 #[serde(default = "default_max_amount_variance")]
4594 pub max_amount_variance: f64,
4595}
4596
4597fn default_duplicate_rate() -> f64 {
4598 0.005
4599}
4600fn default_exact_duplicate_ratio() -> f64 {
4601 0.4
4602}
4603fn default_near_duplicate_ratio() -> f64 {
4604 0.35
4605}
4606fn default_fuzzy_duplicate_ratio() -> f64 {
4607 0.25
4608}
4609fn default_max_date_offset() -> u32 {
4610 3
4611}
4612fn default_max_amount_variance() -> f64 {
4613 0.01
4614}
4615
4616impl Default for DuplicateSchemaConfig {
4617 fn default() -> Self {
4618 Self {
4619 enabled: false,
4620 rate: default_duplicate_rate(),
4621 exact_duplicate_ratio: default_exact_duplicate_ratio(),
4622 near_duplicate_ratio: default_near_duplicate_ratio(),
4623 fuzzy_duplicate_ratio: default_fuzzy_duplicate_ratio(),
4624 max_date_offset_days: default_max_date_offset(),
4625 max_amount_variance: default_max_amount_variance(),
4626 }
4627 }
4628}
4629
4630#[derive(Debug, Clone, Serialize, Deserialize)]
4632pub struct EncodingIssueSchemaConfig {
4633 #[serde(default)]
4635 pub enabled: bool,
4636 #[serde(default = "default_encoding_rate")]
4638 pub rate: f64,
4639 #[serde(default)]
4641 pub mojibake: bool,
4642 #[serde(default)]
4644 pub html_entities: bool,
4645 #[serde(default)]
4647 pub bom_issues: bool,
4648}
4649
4650fn default_encoding_rate() -> f64 {
4651 0.001
4652}
4653
4654impl Default for EncodingIssueSchemaConfig {
4655 fn default() -> Self {
4656 Self {
4657 enabled: false,
4658 rate: default_encoding_rate(),
4659 mojibake: false,
4660 html_entities: false,
4661 bom_issues: false,
4662 }
4663 }
4664}
4665
4666#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4668pub struct SinkQualityProfiles {
4669 #[serde(default)]
4671 pub csv: Option<SinkQualityOverride>,
4672 #[serde(default)]
4674 pub json: Option<SinkQualityOverride>,
4675 #[serde(default)]
4677 pub parquet: Option<SinkQualityOverride>,
4678}
4679
4680#[derive(Debug, Clone, Serialize, Deserialize)]
4682pub struct SinkQualityOverride {
4683 pub enabled: Option<bool>,
4685 pub missing_rate: Option<f64>,
4687 pub typo_rate: Option<f64>,
4689 pub format_variation_rate: Option<f64>,
4691 pub duplicate_rate: Option<f64>,
4693}
4694
4695#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4707pub struct AccountingStandardsConfig {
4708 #[serde(default)]
4710 pub enabled: bool,
4711
4712 #[serde(default, skip_serializing_if = "Option::is_none")]
4716 pub framework: Option<AccountingFrameworkConfig>,
4717
4718 #[serde(default)]
4720 pub revenue_recognition: RevenueRecognitionConfig,
4721
4722 #[serde(default)]
4724 pub leases: LeaseAccountingConfig,
4725
4726 #[serde(default)]
4728 pub fair_value: FairValueConfig,
4729
4730 #[serde(default)]
4732 pub impairment: ImpairmentConfig,
4733
4734 #[serde(default)]
4736 pub generate_differences: bool,
4737}
4738
4739#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
4741#[serde(rename_all = "snake_case")]
4742pub enum AccountingFrameworkConfig {
4743 #[default]
4745 UsGaap,
4746 Ifrs,
4748 DualReporting,
4750 FrenchGaap,
4752 GermanGaap,
4754}
4755
4756#[derive(Debug, Clone, Serialize, Deserialize)]
4758pub struct RevenueRecognitionConfig {
4759 #[serde(default)]
4761 pub enabled: bool,
4762
4763 #[serde(default = "default_true")]
4765 pub generate_contracts: bool,
4766
4767 #[serde(default = "default_avg_obligations")]
4769 pub avg_obligations_per_contract: f64,
4770
4771 #[serde(default = "default_variable_consideration_rate")]
4773 pub variable_consideration_rate: f64,
4774
4775 #[serde(default = "default_over_time_rate")]
4777 pub over_time_recognition_rate: f64,
4778
4779 #[serde(default = "default_contract_count")]
4781 pub contract_count: usize,
4782}
4783
4784fn default_avg_obligations() -> f64 {
4785 2.0
4786}
4787
4788fn default_variable_consideration_rate() -> f64 {
4789 0.15
4790}
4791
4792fn default_over_time_rate() -> f64 {
4793 0.30
4794}
4795
4796fn default_contract_count() -> usize {
4797 100
4798}
4799
4800impl Default for RevenueRecognitionConfig {
4801 fn default() -> Self {
4802 Self {
4803 enabled: false,
4804 generate_contracts: true,
4805 avg_obligations_per_contract: default_avg_obligations(),
4806 variable_consideration_rate: default_variable_consideration_rate(),
4807 over_time_recognition_rate: default_over_time_rate(),
4808 contract_count: default_contract_count(),
4809 }
4810 }
4811}
4812
4813#[derive(Debug, Clone, Serialize, Deserialize)]
4815pub struct LeaseAccountingConfig {
4816 #[serde(default)]
4818 pub enabled: bool,
4819
4820 #[serde(default = "default_lease_count")]
4822 pub lease_count: usize,
4823
4824 #[serde(default = "default_finance_lease_pct")]
4826 pub finance_lease_percent: f64,
4827
4828 #[serde(default = "default_avg_lease_term")]
4830 pub avg_lease_term_months: u32,
4831
4832 #[serde(default = "default_true")]
4834 pub generate_amortization: bool,
4835
4836 #[serde(default = "default_real_estate_pct")]
4838 pub real_estate_percent: f64,
4839}
4840
4841fn default_lease_count() -> usize {
4842 50
4843}
4844
4845fn default_finance_lease_pct() -> f64 {
4846 0.30
4847}
4848
4849fn default_avg_lease_term() -> u32 {
4850 60
4851}
4852
4853fn default_real_estate_pct() -> f64 {
4854 0.40
4855}
4856
4857impl Default for LeaseAccountingConfig {
4858 fn default() -> Self {
4859 Self {
4860 enabled: false,
4861 lease_count: default_lease_count(),
4862 finance_lease_percent: default_finance_lease_pct(),
4863 avg_lease_term_months: default_avg_lease_term(),
4864 generate_amortization: true,
4865 real_estate_percent: default_real_estate_pct(),
4866 }
4867 }
4868}
4869
4870#[derive(Debug, Clone, Serialize, Deserialize)]
4872pub struct FairValueConfig {
4873 #[serde(default)]
4875 pub enabled: bool,
4876
4877 #[serde(default = "default_fv_count")]
4879 pub measurement_count: usize,
4880
4881 #[serde(default = "default_level1_pct")]
4883 pub level1_percent: f64,
4884
4885 #[serde(default = "default_level2_pct")]
4887 pub level2_percent: f64,
4888
4889 #[serde(default = "default_level3_pct")]
4891 pub level3_percent: f64,
4892
4893 #[serde(default)]
4895 pub include_sensitivity_analysis: bool,
4896}
4897
4898fn default_fv_count() -> usize {
4899 25
4900}
4901
4902fn default_level1_pct() -> f64 {
4903 0.40
4904}
4905
4906fn default_level2_pct() -> f64 {
4907 0.35
4908}
4909
4910fn default_level3_pct() -> f64 {
4911 0.25
4912}
4913
4914impl Default for FairValueConfig {
4915 fn default() -> Self {
4916 Self {
4917 enabled: false,
4918 measurement_count: default_fv_count(),
4919 level1_percent: default_level1_pct(),
4920 level2_percent: default_level2_pct(),
4921 level3_percent: default_level3_pct(),
4922 include_sensitivity_analysis: false,
4923 }
4924 }
4925}
4926
4927#[derive(Debug, Clone, Serialize, Deserialize)]
4929pub struct ImpairmentConfig {
4930 #[serde(default)]
4932 pub enabled: bool,
4933
4934 #[serde(default = "default_impairment_count")]
4936 pub test_count: usize,
4937
4938 #[serde(default = "default_impairment_rate")]
4940 pub impairment_rate: f64,
4941
4942 #[serde(default = "default_true")]
4944 pub generate_projections: bool,
4945
4946 #[serde(default)]
4948 pub include_goodwill: bool,
4949}
4950
4951fn default_impairment_count() -> usize {
4952 15
4953}
4954
4955fn default_impairment_rate() -> f64 {
4956 0.10
4957}
4958
4959impl Default for ImpairmentConfig {
4960 fn default() -> Self {
4961 Self {
4962 enabled: false,
4963 test_count: default_impairment_count(),
4964 impairment_rate: default_impairment_rate(),
4965 generate_projections: true,
4966 include_goodwill: false,
4967 }
4968 }
4969}
4970
4971#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4984pub struct AuditStandardsConfig {
4985 #[serde(default)]
4987 pub enabled: bool,
4988
4989 #[serde(default)]
4991 pub isa_compliance: IsaComplianceConfig,
4992
4993 #[serde(default)]
4995 pub analytical_procedures: AnalyticalProceduresConfig,
4996
4997 #[serde(default)]
4999 pub confirmations: ConfirmationsConfig,
5000
5001 #[serde(default)]
5003 pub opinion: AuditOpinionConfig,
5004
5005 #[serde(default)]
5007 pub generate_audit_trail: bool,
5008
5009 #[serde(default)]
5011 pub sox: SoxComplianceConfig,
5012
5013 #[serde(default)]
5015 pub pcaob: PcaobConfig,
5016}
5017
5018#[derive(Debug, Clone, Serialize, Deserialize)]
5020pub struct IsaComplianceConfig {
5021 #[serde(default)]
5023 pub enabled: bool,
5024
5025 #[serde(default = "default_compliance_level")]
5027 pub compliance_level: String,
5028
5029 #[serde(default = "default_true")]
5031 pub generate_isa_mappings: bool,
5032
5033 #[serde(default = "default_true")]
5035 pub generate_coverage_summary: bool,
5036
5037 #[serde(default)]
5039 pub include_pcaob: bool,
5040
5041 #[serde(default = "default_audit_framework")]
5043 pub framework: String,
5044}
5045
5046fn default_compliance_level() -> String {
5047 "standard".to_string()
5048}
5049
5050fn default_audit_framework() -> String {
5051 "isa".to_string()
5052}
5053
5054impl Default for IsaComplianceConfig {
5055 fn default() -> Self {
5056 Self {
5057 enabled: false,
5058 compliance_level: default_compliance_level(),
5059 generate_isa_mappings: true,
5060 generate_coverage_summary: true,
5061 include_pcaob: false,
5062 framework: default_audit_framework(),
5063 }
5064 }
5065}
5066
5067#[derive(Debug, Clone, Serialize, Deserialize)]
5069pub struct AnalyticalProceduresConfig {
5070 #[serde(default)]
5072 pub enabled: bool,
5073
5074 #[serde(default = "default_procedures_per_account")]
5076 pub procedures_per_account: usize,
5077
5078 #[serde(default = "default_variance_probability")]
5080 pub variance_probability: f64,
5081
5082 #[serde(default = "default_true")]
5084 pub generate_investigations: bool,
5085
5086 #[serde(default = "default_true")]
5088 pub include_ratio_analysis: bool,
5089}
5090
5091fn default_procedures_per_account() -> usize {
5092 3
5093}
5094
5095fn default_variance_probability() -> f64 {
5096 0.20
5097}
5098
5099impl Default for AnalyticalProceduresConfig {
5100 fn default() -> Self {
5101 Self {
5102 enabled: false,
5103 procedures_per_account: default_procedures_per_account(),
5104 variance_probability: default_variance_probability(),
5105 generate_investigations: true,
5106 include_ratio_analysis: true,
5107 }
5108 }
5109}
5110
5111#[derive(Debug, Clone, Serialize, Deserialize)]
5113pub struct ConfirmationsConfig {
5114 #[serde(default)]
5116 pub enabled: bool,
5117
5118 #[serde(default = "default_confirmation_count")]
5120 pub confirmation_count: usize,
5121
5122 #[serde(default = "default_positive_response_rate")]
5124 pub positive_response_rate: f64,
5125
5126 #[serde(default = "default_exception_rate_confirm")]
5128 pub exception_rate: f64,
5129
5130 #[serde(default = "default_non_response_rate")]
5132 pub non_response_rate: f64,
5133
5134 #[serde(default = "default_true")]
5136 pub generate_alternative_procedures: bool,
5137}
5138
5139fn default_confirmation_count() -> usize {
5140 50
5141}
5142
5143fn default_positive_response_rate() -> f64 {
5144 0.85
5145}
5146
5147fn default_exception_rate_confirm() -> f64 {
5148 0.10
5149}
5150
5151fn default_non_response_rate() -> f64 {
5152 0.05
5153}
5154
5155impl Default for ConfirmationsConfig {
5156 fn default() -> Self {
5157 Self {
5158 enabled: false,
5159 confirmation_count: default_confirmation_count(),
5160 positive_response_rate: default_positive_response_rate(),
5161 exception_rate: default_exception_rate_confirm(),
5162 non_response_rate: default_non_response_rate(),
5163 generate_alternative_procedures: true,
5164 }
5165 }
5166}
5167
5168#[derive(Debug, Clone, Serialize, Deserialize)]
5170pub struct AuditOpinionConfig {
5171 #[serde(default)]
5173 pub enabled: bool,
5174
5175 #[serde(default = "default_true")]
5177 pub generate_kam: bool,
5178
5179 #[serde(default = "default_kam_count")]
5181 pub average_kam_count: usize,
5182
5183 #[serde(default = "default_modified_opinion_rate")]
5185 pub modified_opinion_rate: f64,
5186
5187 #[serde(default)]
5189 pub include_emphasis_of_matter: bool,
5190
5191 #[serde(default = "default_true")]
5193 pub include_going_concern: bool,
5194}
5195
5196fn default_kam_count() -> usize {
5197 3
5198}
5199
5200fn default_modified_opinion_rate() -> f64 {
5201 0.05
5202}
5203
5204impl Default for AuditOpinionConfig {
5205 fn default() -> Self {
5206 Self {
5207 enabled: false,
5208 generate_kam: true,
5209 average_kam_count: default_kam_count(),
5210 modified_opinion_rate: default_modified_opinion_rate(),
5211 include_emphasis_of_matter: false,
5212 include_going_concern: true,
5213 }
5214 }
5215}
5216
5217#[derive(Debug, Clone, Serialize, Deserialize)]
5219pub struct SoxComplianceConfig {
5220 #[serde(default)]
5222 pub enabled: bool,
5223
5224 #[serde(default = "default_true")]
5226 pub generate_302_certifications: bool,
5227
5228 #[serde(default = "default_true")]
5230 pub generate_404_assessments: bool,
5231
5232 #[serde(default = "default_sox_materiality_threshold")]
5234 pub materiality_threshold: f64,
5235
5236 #[serde(default = "default_material_weakness_rate")]
5238 pub material_weakness_rate: f64,
5239
5240 #[serde(default = "default_significant_deficiency_rate")]
5242 pub significant_deficiency_rate: f64,
5243}
5244
5245fn default_material_weakness_rate() -> f64 {
5246 0.02
5247}
5248
5249fn default_significant_deficiency_rate() -> f64 {
5250 0.08
5251}
5252
5253impl Default for SoxComplianceConfig {
5254 fn default() -> Self {
5255 Self {
5256 enabled: false,
5257 generate_302_certifications: true,
5258 generate_404_assessments: true,
5259 materiality_threshold: default_sox_materiality_threshold(),
5260 material_weakness_rate: default_material_weakness_rate(),
5261 significant_deficiency_rate: default_significant_deficiency_rate(),
5262 }
5263 }
5264}
5265
5266#[derive(Debug, Clone, Serialize, Deserialize)]
5268pub struct PcaobConfig {
5269 #[serde(default)]
5271 pub enabled: bool,
5272
5273 #[serde(default)]
5275 pub is_pcaob_audit: bool,
5276
5277 #[serde(default = "default_true")]
5279 pub generate_cam: bool,
5280
5281 #[serde(default)]
5283 pub include_icfr_opinion: bool,
5284
5285 #[serde(default)]
5287 pub generate_standard_mappings: bool,
5288}
5289
5290impl Default for PcaobConfig {
5291 fn default() -> Self {
5292 Self {
5293 enabled: false,
5294 is_pcaob_audit: false,
5295 generate_cam: true,
5296 include_icfr_opinion: false,
5297 generate_standard_mappings: false,
5298 }
5299 }
5300}
5301
5302#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5315pub struct AdvancedDistributionConfig {
5316 #[serde(default)]
5318 pub enabled: bool,
5319
5320 #[serde(default)]
5322 pub amounts: MixtureDistributionSchemaConfig,
5323
5324 #[serde(default)]
5326 pub correlations: CorrelationSchemaConfig,
5327
5328 #[serde(default)]
5330 pub conditional: Vec<ConditionalDistributionSchemaConfig>,
5331
5332 #[serde(default)]
5334 pub regime_changes: RegimeChangeSchemaConfig,
5335
5336 #[serde(default)]
5338 pub industry_profile: Option<IndustryProfileType>,
5339
5340 #[serde(default)]
5342 pub validation: StatisticalValidationSchemaConfig,
5343}
5344
5345#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
5347#[serde(rename_all = "snake_case")]
5348pub enum IndustryProfileType {
5349 Retail,
5351 Manufacturing,
5353 FinancialServices,
5355 Healthcare,
5357 Technology,
5359}
5360
5361#[derive(Debug, Clone, Serialize, Deserialize)]
5363pub struct MixtureDistributionSchemaConfig {
5364 #[serde(default)]
5366 pub enabled: bool,
5367
5368 #[serde(default = "default_mixture_type")]
5370 pub distribution_type: MixtureDistributionType,
5371
5372 #[serde(default)]
5374 pub components: Vec<MixtureComponentConfig>,
5375
5376 #[serde(default = "default_min_amount")]
5378 pub min_value: f64,
5379
5380 #[serde(default)]
5382 pub max_value: Option<f64>,
5383
5384 #[serde(default = "default_decimal_places")]
5386 pub decimal_places: u8,
5387}
5388
5389fn default_mixture_type() -> MixtureDistributionType {
5390 MixtureDistributionType::LogNormal
5391}
5392
5393fn default_min_amount() -> f64 {
5394 0.01
5395}
5396
5397fn default_decimal_places() -> u8 {
5398 2
5399}
5400
5401impl Default for MixtureDistributionSchemaConfig {
5402 fn default() -> Self {
5403 Self {
5404 enabled: false,
5405 distribution_type: MixtureDistributionType::LogNormal,
5406 components: Vec::new(),
5407 min_value: 0.01,
5408 max_value: None,
5409 decimal_places: 2,
5410 }
5411 }
5412}
5413
5414#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5416#[serde(rename_all = "snake_case")]
5417pub enum MixtureDistributionType {
5418 Gaussian,
5420 #[default]
5422 LogNormal,
5423}
5424
5425#[derive(Debug, Clone, Serialize, Deserialize)]
5427pub struct MixtureComponentConfig {
5428 pub weight: f64,
5430
5431 pub mu: f64,
5433
5434 pub sigma: f64,
5436
5437 #[serde(default)]
5439 pub label: Option<String>,
5440}
5441
5442#[derive(Debug, Clone, Serialize, Deserialize)]
5444pub struct CorrelationSchemaConfig {
5445 #[serde(default)]
5447 pub enabled: bool,
5448
5449 #[serde(default)]
5451 pub copula_type: CopulaSchemaType,
5452
5453 #[serde(default)]
5455 pub fields: Vec<CorrelatedFieldConfig>,
5456
5457 #[serde(default)]
5460 pub matrix: Vec<f64>,
5461
5462 #[serde(default)]
5464 pub expected_correlations: Vec<ExpectedCorrelationConfig>,
5465}
5466
5467impl Default for CorrelationSchemaConfig {
5468 fn default() -> Self {
5469 Self {
5470 enabled: false,
5471 copula_type: CopulaSchemaType::Gaussian,
5472 fields: Vec::new(),
5473 matrix: Vec::new(),
5474 expected_correlations: Vec::new(),
5475 }
5476 }
5477}
5478
5479#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5481#[serde(rename_all = "snake_case")]
5482pub enum CopulaSchemaType {
5483 #[default]
5485 Gaussian,
5486 Clayton,
5488 Gumbel,
5490 Frank,
5492 StudentT,
5494}
5495
5496#[derive(Debug, Clone, Serialize, Deserialize)]
5498pub struct CorrelatedFieldConfig {
5499 pub name: String,
5501
5502 #[serde(default)]
5504 pub distribution: MarginalDistributionConfig,
5505}
5506
5507#[derive(Debug, Clone, Serialize, Deserialize)]
5509#[serde(tag = "type", rename_all = "snake_case")]
5510pub enum MarginalDistributionConfig {
5511 Normal {
5513 mu: f64,
5515 sigma: f64,
5517 },
5518 LogNormal {
5520 mu: f64,
5522 sigma: f64,
5524 },
5525 Uniform {
5527 min: f64,
5529 max: f64,
5531 },
5532 DiscreteUniform {
5534 min: i32,
5536 max: i32,
5538 },
5539}
5540
5541impl Default for MarginalDistributionConfig {
5542 fn default() -> Self {
5543 Self::Normal {
5544 mu: 0.0,
5545 sigma: 1.0,
5546 }
5547 }
5548}
5549
5550#[derive(Debug, Clone, Serialize, Deserialize)]
5552pub struct ExpectedCorrelationConfig {
5553 pub field1: String,
5555 pub field2: String,
5557 pub expected_r: f64,
5559 #[serde(default = "default_correlation_tolerance")]
5561 pub tolerance: f64,
5562}
5563
5564fn default_correlation_tolerance() -> f64 {
5565 0.10
5566}
5567
5568#[derive(Debug, Clone, Serialize, Deserialize)]
5570pub struct ConditionalDistributionSchemaConfig {
5571 pub output_field: String,
5573
5574 pub input_field: String,
5576
5577 #[serde(default)]
5579 pub breakpoints: Vec<ConditionalBreakpointConfig>,
5580
5581 #[serde(default)]
5583 pub default_distribution: ConditionalDistributionParamsConfig,
5584
5585 #[serde(default)]
5587 pub min_value: Option<f64>,
5588
5589 #[serde(default)]
5591 pub max_value: Option<f64>,
5592
5593 #[serde(default = "default_decimal_places")]
5595 pub decimal_places: u8,
5596}
5597
5598#[derive(Debug, Clone, Serialize, Deserialize)]
5600pub struct ConditionalBreakpointConfig {
5601 pub threshold: f64,
5603
5604 pub distribution: ConditionalDistributionParamsConfig,
5606}
5607
5608#[derive(Debug, Clone, Serialize, Deserialize)]
5610#[serde(tag = "type", rename_all = "snake_case")]
5611pub enum ConditionalDistributionParamsConfig {
5612 Fixed {
5614 value: f64,
5616 },
5617 Normal {
5619 mu: f64,
5621 sigma: f64,
5623 },
5624 LogNormal {
5626 mu: f64,
5628 sigma: f64,
5630 },
5631 Uniform {
5633 min: f64,
5635 max: f64,
5637 },
5638 Beta {
5640 alpha: f64,
5642 beta: f64,
5644 min: f64,
5646 max: f64,
5648 },
5649 Discrete {
5651 values: Vec<f64>,
5653 weights: Vec<f64>,
5655 },
5656}
5657
5658impl Default for ConditionalDistributionParamsConfig {
5659 fn default() -> Self {
5660 Self::Normal {
5661 mu: 0.0,
5662 sigma: 1.0,
5663 }
5664 }
5665}
5666
5667#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5669pub struct RegimeChangeSchemaConfig {
5670 #[serde(default)]
5672 pub enabled: bool,
5673
5674 #[serde(default)]
5676 pub changes: Vec<RegimeChangeEventConfig>,
5677
5678 #[serde(default)]
5680 pub economic_cycle: Option<EconomicCycleSchemaConfig>,
5681
5682 #[serde(default)]
5684 pub parameter_drifts: Vec<ParameterDriftSchemaConfig>,
5685}
5686
5687#[derive(Debug, Clone, Serialize, Deserialize)]
5689pub struct RegimeChangeEventConfig {
5690 pub date: String,
5692
5693 pub change_type: RegimeChangeTypeConfig,
5695
5696 #[serde(default)]
5698 pub description: Option<String>,
5699
5700 #[serde(default)]
5702 pub effects: Vec<RegimeEffectConfig>,
5703}
5704
5705#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
5707#[serde(rename_all = "snake_case")]
5708pub enum RegimeChangeTypeConfig {
5709 Acquisition,
5711 Divestiture,
5713 PriceIncrease,
5715 PriceDecrease,
5717 ProductLaunch,
5719 ProductDiscontinuation,
5721 PolicyChange,
5723 CompetitorEntry,
5725 Custom,
5727}
5728
5729#[derive(Debug, Clone, Serialize, Deserialize)]
5731pub struct RegimeEffectConfig {
5732 pub field: String,
5734
5735 pub multiplier: f64,
5737}
5738
5739#[derive(Debug, Clone, Serialize, Deserialize)]
5741pub struct EconomicCycleSchemaConfig {
5742 #[serde(default)]
5744 pub enabled: bool,
5745
5746 #[serde(default = "default_cycle_period")]
5748 pub period_months: u32,
5749
5750 #[serde(default = "default_cycle_amplitude")]
5752 pub amplitude: f64,
5753
5754 #[serde(default)]
5756 pub phase_offset: u32,
5757
5758 #[serde(default)]
5760 pub recessions: Vec<RecessionPeriodConfig>,
5761}
5762
5763fn default_cycle_period() -> u32 {
5764 48
5765}
5766
5767fn default_cycle_amplitude() -> f64 {
5768 0.15
5769}
5770
5771impl Default for EconomicCycleSchemaConfig {
5772 fn default() -> Self {
5773 Self {
5774 enabled: false,
5775 period_months: 48,
5776 amplitude: 0.15,
5777 phase_offset: 0,
5778 recessions: Vec::new(),
5779 }
5780 }
5781}
5782
5783#[derive(Debug, Clone, Serialize, Deserialize)]
5785pub struct RecessionPeriodConfig {
5786 pub start_month: u32,
5788
5789 pub duration_months: u32,
5791
5792 #[serde(default = "default_recession_severity")]
5794 pub severity: f64,
5795}
5796
5797fn default_recession_severity() -> f64 {
5798 0.20
5799}
5800
5801#[derive(Debug, Clone, Serialize, Deserialize)]
5803pub struct ParameterDriftSchemaConfig {
5804 pub parameter: String,
5806
5807 pub drift_type: ParameterDriftTypeConfig,
5809
5810 pub start_value: f64,
5812
5813 pub end_value: f64,
5815
5816 #[serde(default)]
5818 pub start_period: u32,
5819
5820 #[serde(default)]
5822 pub end_period: Option<u32>,
5823}
5824
5825#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5827#[serde(rename_all = "snake_case")]
5828pub enum ParameterDriftTypeConfig {
5829 #[default]
5831 Linear,
5832 Exponential,
5834 Logistic,
5836 Step,
5838}
5839
5840#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5842pub struct StatisticalValidationSchemaConfig {
5843 #[serde(default)]
5845 pub enabled: bool,
5846
5847 #[serde(default)]
5849 pub tests: Vec<StatisticalTestConfig>,
5850
5851 #[serde(default)]
5853 pub reporting: ValidationReportingConfig,
5854}
5855
5856#[derive(Debug, Clone, Serialize, Deserialize)]
5858#[serde(tag = "type", rename_all = "snake_case")]
5859pub enum StatisticalTestConfig {
5860 BenfordFirstDigit {
5862 #[serde(default = "default_benford_threshold")]
5864 threshold_mad: f64,
5865 #[serde(default = "default_benford_warning")]
5867 warning_mad: f64,
5868 },
5869 DistributionFit {
5871 target: TargetDistributionConfig,
5873 #[serde(default = "default_ks_significance")]
5875 ks_significance: f64,
5876 #[serde(default)]
5878 method: DistributionFitMethod,
5879 },
5880 CorrelationCheck {
5882 expected_correlations: Vec<ExpectedCorrelationConfig>,
5884 },
5885 ChiSquared {
5887 #[serde(default = "default_chi_squared_bins")]
5889 bins: usize,
5890 #[serde(default = "default_chi_squared_significance")]
5892 significance: f64,
5893 },
5894 AndersonDarling {
5896 target: TargetDistributionConfig,
5898 #[serde(default = "default_ad_significance")]
5900 significance: f64,
5901 },
5902}
5903
5904fn default_benford_threshold() -> f64 {
5905 0.015
5906}
5907
5908fn default_benford_warning() -> f64 {
5909 0.010
5910}
5911
5912fn default_ks_significance() -> f64 {
5913 0.05
5914}
5915
5916fn default_chi_squared_bins() -> usize {
5917 10
5918}
5919
5920fn default_chi_squared_significance() -> f64 {
5921 0.05
5922}
5923
5924fn default_ad_significance() -> f64 {
5925 0.05
5926}
5927
5928#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5930#[serde(rename_all = "snake_case")]
5931pub enum TargetDistributionConfig {
5932 Normal,
5934 #[default]
5936 LogNormal,
5937 Exponential,
5939 Uniform,
5941}
5942
5943#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5945#[serde(rename_all = "snake_case")]
5946pub enum DistributionFitMethod {
5947 #[default]
5949 KolmogorovSmirnov,
5950 AndersonDarling,
5952 ChiSquared,
5954}
5955
5956#[derive(Debug, Clone, Serialize, Deserialize)]
5958pub struct ValidationReportingConfig {
5959 #[serde(default)]
5961 pub output_report: bool,
5962
5963 #[serde(default)]
5965 pub format: ValidationReportFormat,
5966
5967 #[serde(default)]
5969 pub fail_on_error: bool,
5970
5971 #[serde(default = "default_true")]
5973 pub include_details: bool,
5974}
5975
5976impl Default for ValidationReportingConfig {
5977 fn default() -> Self {
5978 Self {
5979 output_report: false,
5980 format: ValidationReportFormat::Json,
5981 fail_on_error: false,
5982 include_details: true,
5983 }
5984 }
5985}
5986
5987#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5989#[serde(rename_all = "snake_case")]
5990pub enum ValidationReportFormat {
5991 #[default]
5993 Json,
5994 Yaml,
5996 Html,
5998}
5999
6000#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6012pub struct TemporalPatternsConfig {
6013 #[serde(default)]
6015 pub enabled: bool,
6016
6017 #[serde(default)]
6019 pub business_days: BusinessDaySchemaConfig,
6020
6021 #[serde(default)]
6023 pub calendars: CalendarSchemaConfig,
6024
6025 #[serde(default)]
6027 pub period_end: PeriodEndSchemaConfig,
6028
6029 #[serde(default)]
6031 pub processing_lags: ProcessingLagSchemaConfig,
6032
6033 #[serde(default)]
6035 pub fiscal_calendar: FiscalCalendarSchemaConfig,
6036
6037 #[serde(default)]
6039 pub intraday: IntraDaySchemaConfig,
6040
6041 #[serde(default)]
6043 pub timezones: TimezoneSchemaConfig,
6044}
6045
6046#[derive(Debug, Clone, Serialize, Deserialize)]
6048pub struct BusinessDaySchemaConfig {
6049 #[serde(default = "default_true")]
6051 pub enabled: bool,
6052
6053 #[serde(default = "default_half_day_policy")]
6055 pub half_day_policy: String,
6056
6057 #[serde(default)]
6059 pub settlement_rules: SettlementRulesSchemaConfig,
6060
6061 #[serde(default = "default_month_end_convention")]
6063 pub month_end_convention: String,
6064
6065 #[serde(default)]
6067 pub weekend_days: Option<Vec<String>>,
6068}
6069
6070fn default_half_day_policy() -> String {
6071 "half_day".to_string()
6072}
6073
6074fn default_month_end_convention() -> String {
6075 "modified_following".to_string()
6076}
6077
6078impl Default for BusinessDaySchemaConfig {
6079 fn default() -> Self {
6080 Self {
6081 enabled: true,
6082 half_day_policy: "half_day".to_string(),
6083 settlement_rules: SettlementRulesSchemaConfig::default(),
6084 month_end_convention: "modified_following".to_string(),
6085 weekend_days: None,
6086 }
6087 }
6088}
6089
6090#[derive(Debug, Clone, Serialize, Deserialize)]
6092pub struct SettlementRulesSchemaConfig {
6093 #[serde(default = "default_settlement_2")]
6095 pub equity_days: i32,
6096
6097 #[serde(default = "default_settlement_1")]
6099 pub government_bonds_days: i32,
6100
6101 #[serde(default = "default_settlement_2")]
6103 pub fx_spot_days: i32,
6104
6105 #[serde(default = "default_settlement_2")]
6107 pub corporate_bonds_days: i32,
6108
6109 #[serde(default = "default_wire_cutoff")]
6111 pub wire_cutoff_time: String,
6112
6113 #[serde(default = "default_settlement_1")]
6115 pub wire_international_days: i32,
6116
6117 #[serde(default = "default_settlement_1")]
6119 pub ach_days: i32,
6120}
6121
6122fn default_settlement_1() -> i32 {
6123 1
6124}
6125
6126fn default_settlement_2() -> i32 {
6127 2
6128}
6129
6130fn default_wire_cutoff() -> String {
6131 "14:00".to_string()
6132}
6133
6134impl Default for SettlementRulesSchemaConfig {
6135 fn default() -> Self {
6136 Self {
6137 equity_days: 2,
6138 government_bonds_days: 1,
6139 fx_spot_days: 2,
6140 corporate_bonds_days: 2,
6141 wire_cutoff_time: "14:00".to_string(),
6142 wire_international_days: 1,
6143 ach_days: 1,
6144 }
6145 }
6146}
6147
6148#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6150pub struct CalendarSchemaConfig {
6151 #[serde(default)]
6153 pub regions: Vec<String>,
6154
6155 #[serde(default)]
6157 pub custom_holidays: Vec<CustomHolidaySchemaConfig>,
6158}
6159
6160#[derive(Debug, Clone, Serialize, Deserialize)]
6162pub struct CustomHolidaySchemaConfig {
6163 pub name: String,
6165 pub month: u8,
6167 pub day: u8,
6169 #[serde(default = "default_holiday_multiplier")]
6171 pub activity_multiplier: f64,
6172}
6173
6174fn default_holiday_multiplier() -> f64 {
6175 0.05
6176}
6177
6178#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6180pub struct PeriodEndSchemaConfig {
6181 #[serde(default)]
6183 pub model: Option<String>,
6184
6185 #[serde(default)]
6187 pub month_end: Option<PeriodEndModelSchemaConfig>,
6188
6189 #[serde(default)]
6191 pub quarter_end: Option<PeriodEndModelSchemaConfig>,
6192
6193 #[serde(default)]
6195 pub year_end: Option<PeriodEndModelSchemaConfig>,
6196}
6197
6198#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6200pub struct PeriodEndModelSchemaConfig {
6201 #[serde(default)]
6203 pub inherit_from: Option<String>,
6204
6205 #[serde(default)]
6207 pub additional_multiplier: Option<f64>,
6208
6209 #[serde(default)]
6211 pub start_day: Option<i32>,
6212
6213 #[serde(default)]
6215 pub base_multiplier: Option<f64>,
6216
6217 #[serde(default)]
6219 pub peak_multiplier: Option<f64>,
6220
6221 #[serde(default)]
6223 pub decay_rate: Option<f64>,
6224
6225 #[serde(default)]
6227 pub sustained_high_days: Option<i32>,
6228}
6229
6230#[derive(Debug, Clone, Serialize, Deserialize)]
6232pub struct ProcessingLagSchemaConfig {
6233 #[serde(default = "default_true")]
6235 pub enabled: bool,
6236
6237 #[serde(default)]
6239 pub sales_order_lag: Option<LagDistributionSchemaConfig>,
6240
6241 #[serde(default)]
6243 pub purchase_order_lag: Option<LagDistributionSchemaConfig>,
6244
6245 #[serde(default)]
6247 pub goods_receipt_lag: Option<LagDistributionSchemaConfig>,
6248
6249 #[serde(default)]
6251 pub invoice_receipt_lag: Option<LagDistributionSchemaConfig>,
6252
6253 #[serde(default)]
6255 pub invoice_issue_lag: Option<LagDistributionSchemaConfig>,
6256
6257 #[serde(default)]
6259 pub payment_lag: Option<LagDistributionSchemaConfig>,
6260
6261 #[serde(default)]
6263 pub journal_entry_lag: Option<LagDistributionSchemaConfig>,
6264
6265 #[serde(default)]
6267 pub cross_day_posting: Option<CrossDayPostingSchemaConfig>,
6268}
6269
6270impl Default for ProcessingLagSchemaConfig {
6271 fn default() -> Self {
6272 Self {
6273 enabled: true,
6274 sales_order_lag: None,
6275 purchase_order_lag: None,
6276 goods_receipt_lag: None,
6277 invoice_receipt_lag: None,
6278 invoice_issue_lag: None,
6279 payment_lag: None,
6280 journal_entry_lag: None,
6281 cross_day_posting: None,
6282 }
6283 }
6284}
6285
6286#[derive(Debug, Clone, Serialize, Deserialize)]
6288pub struct LagDistributionSchemaConfig {
6289 pub mu: f64,
6291 pub sigma: f64,
6293 #[serde(default)]
6295 pub min_hours: Option<f64>,
6296 #[serde(default)]
6298 pub max_hours: Option<f64>,
6299}
6300
6301#[derive(Debug, Clone, Serialize, Deserialize)]
6303pub struct CrossDayPostingSchemaConfig {
6304 #[serde(default = "default_true")]
6306 pub enabled: bool,
6307
6308 #[serde(default)]
6311 pub probability_by_hour: std::collections::HashMap<u8, f64>,
6312}
6313
6314impl Default for CrossDayPostingSchemaConfig {
6315 fn default() -> Self {
6316 let mut probability_by_hour = std::collections::HashMap::new();
6317 probability_by_hour.insert(17, 0.3);
6318 probability_by_hour.insert(18, 0.6);
6319 probability_by_hour.insert(19, 0.8);
6320 probability_by_hour.insert(20, 0.9);
6321 probability_by_hour.insert(21, 0.95);
6322 probability_by_hour.insert(22, 0.99);
6323
6324 Self {
6325 enabled: true,
6326 probability_by_hour,
6327 }
6328 }
6329}
6330
6331#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6340pub struct FiscalCalendarSchemaConfig {
6341 #[serde(default)]
6343 pub enabled: bool,
6344
6345 #[serde(default = "default_fiscal_calendar_type")]
6347 pub calendar_type: String,
6348
6349 #[serde(default)]
6351 pub year_start_month: Option<u8>,
6352
6353 #[serde(default)]
6355 pub year_start_day: Option<u8>,
6356
6357 #[serde(default)]
6359 pub four_four_five: Option<FourFourFiveSchemaConfig>,
6360}
6361
6362fn default_fiscal_calendar_type() -> String {
6363 "calendar_year".to_string()
6364}
6365
6366#[derive(Debug, Clone, Serialize, Deserialize)]
6368pub struct FourFourFiveSchemaConfig {
6369 #[serde(default = "default_week_pattern")]
6371 pub pattern: String,
6372
6373 #[serde(default = "default_anchor_type")]
6375 pub anchor_type: String,
6376
6377 #[serde(default = "default_anchor_month")]
6379 pub anchor_month: u8,
6380
6381 #[serde(default = "default_leap_week_placement")]
6383 pub leap_week_placement: String,
6384}
6385
6386fn default_week_pattern() -> String {
6387 "four_four_five".to_string()
6388}
6389
6390fn default_anchor_type() -> String {
6391 "last_saturday".to_string()
6392}
6393
6394fn default_anchor_month() -> u8 {
6395 1 }
6397
6398fn default_leap_week_placement() -> String {
6399 "q4_period3".to_string()
6400}
6401
6402impl Default for FourFourFiveSchemaConfig {
6403 fn default() -> Self {
6404 Self {
6405 pattern: "four_four_five".to_string(),
6406 anchor_type: "last_saturday".to_string(),
6407 anchor_month: 1,
6408 leap_week_placement: "q4_period3".to_string(),
6409 }
6410 }
6411}
6412
6413#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6422pub struct IntraDaySchemaConfig {
6423 #[serde(default)]
6425 pub enabled: bool,
6426
6427 #[serde(default)]
6429 pub segments: Vec<IntraDaySegmentSchemaConfig>,
6430}
6431
6432#[derive(Debug, Clone, Serialize, Deserialize)]
6434pub struct IntraDaySegmentSchemaConfig {
6435 pub name: String,
6437
6438 pub start: String,
6440
6441 pub end: String,
6443
6444 #[serde(default = "default_multiplier")]
6446 pub multiplier: f64,
6447
6448 #[serde(default = "default_posting_type")]
6450 pub posting_type: String,
6451}
6452
6453fn default_multiplier() -> f64 {
6454 1.0
6455}
6456
6457fn default_posting_type() -> String {
6458 "both".to_string()
6459}
6460
6461#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6467pub struct TimezoneSchemaConfig {
6468 #[serde(default)]
6470 pub enabled: bool,
6471
6472 #[serde(default = "default_timezone")]
6474 pub default_timezone: String,
6475
6476 #[serde(default = "default_consolidation_timezone")]
6478 pub consolidation_timezone: String,
6479
6480 #[serde(default)]
6483 pub entity_mappings: Vec<EntityTimezoneMapping>,
6484}
6485
6486fn default_timezone() -> String {
6487 "America/New_York".to_string()
6488}
6489
6490fn default_consolidation_timezone() -> String {
6491 "UTC".to_string()
6492}
6493
6494#[derive(Debug, Clone, Serialize, Deserialize)]
6496pub struct EntityTimezoneMapping {
6497 pub pattern: String,
6499
6500 pub timezone: String,
6502}
6503
6504#[derive(Debug, Clone, Serialize, Deserialize)]
6510pub struct VendorNetworkSchemaConfig {
6511 #[serde(default)]
6513 pub enabled: bool,
6514
6515 #[serde(default = "default_vendor_tier_depth")]
6517 pub depth: u8,
6518
6519 #[serde(default)]
6521 pub tier1: TierCountSchemaConfig,
6522
6523 #[serde(default)]
6525 pub tier2_per_parent: TierCountSchemaConfig,
6526
6527 #[serde(default)]
6529 pub tier3_per_parent: TierCountSchemaConfig,
6530
6531 #[serde(default)]
6533 pub clusters: VendorClusterSchemaConfig,
6534
6535 #[serde(default)]
6537 pub dependencies: DependencySchemaConfig,
6538}
6539
6540fn default_vendor_tier_depth() -> u8 {
6541 3
6542}
6543
6544impl Default for VendorNetworkSchemaConfig {
6545 fn default() -> Self {
6546 Self {
6547 enabled: false,
6548 depth: 3,
6549 tier1: TierCountSchemaConfig { min: 50, max: 100 },
6550 tier2_per_parent: TierCountSchemaConfig { min: 4, max: 10 },
6551 tier3_per_parent: TierCountSchemaConfig { min: 2, max: 5 },
6552 clusters: VendorClusterSchemaConfig::default(),
6553 dependencies: DependencySchemaConfig::default(),
6554 }
6555 }
6556}
6557
6558#[derive(Debug, Clone, Serialize, Deserialize)]
6560pub struct TierCountSchemaConfig {
6561 #[serde(default = "default_tier_min")]
6563 pub min: usize,
6564
6565 #[serde(default = "default_tier_max")]
6567 pub max: usize,
6568}
6569
6570fn default_tier_min() -> usize {
6571 5
6572}
6573
6574fn default_tier_max() -> usize {
6575 20
6576}
6577
6578impl Default for TierCountSchemaConfig {
6579 fn default() -> Self {
6580 Self {
6581 min: default_tier_min(),
6582 max: default_tier_max(),
6583 }
6584 }
6585}
6586
6587#[derive(Debug, Clone, Serialize, Deserialize)]
6589pub struct VendorClusterSchemaConfig {
6590 #[serde(default = "default_reliable_strategic")]
6592 pub reliable_strategic: f64,
6593
6594 #[serde(default = "default_standard_operational")]
6596 pub standard_operational: f64,
6597
6598 #[serde(default = "default_transactional")]
6600 pub transactional: f64,
6601
6602 #[serde(default = "default_problematic")]
6604 pub problematic: f64,
6605}
6606
6607fn default_reliable_strategic() -> f64 {
6608 0.20
6609}
6610
6611fn default_standard_operational() -> f64 {
6612 0.50
6613}
6614
6615fn default_transactional() -> f64 {
6616 0.25
6617}
6618
6619fn default_problematic() -> f64 {
6620 0.05
6621}
6622
6623impl Default for VendorClusterSchemaConfig {
6624 fn default() -> Self {
6625 Self {
6626 reliable_strategic: 0.20,
6627 standard_operational: 0.50,
6628 transactional: 0.25,
6629 problematic: 0.05,
6630 }
6631 }
6632}
6633
6634#[derive(Debug, Clone, Serialize, Deserialize)]
6636pub struct DependencySchemaConfig {
6637 #[serde(default = "default_max_single_vendor")]
6639 pub max_single_vendor_concentration: f64,
6640
6641 #[serde(default = "default_max_top5")]
6643 pub top_5_concentration: f64,
6644
6645 #[serde(default = "default_single_source_percent")]
6647 pub single_source_percent: f64,
6648}
6649
6650fn default_max_single_vendor() -> f64 {
6651 0.15
6652}
6653
6654fn default_max_top5() -> f64 {
6655 0.45
6656}
6657
6658fn default_single_source_percent() -> f64 {
6659 0.05
6660}
6661
6662impl Default for DependencySchemaConfig {
6663 fn default() -> Self {
6664 Self {
6665 max_single_vendor_concentration: 0.15,
6666 top_5_concentration: 0.45,
6667 single_source_percent: 0.05,
6668 }
6669 }
6670}
6671
6672#[derive(Debug, Clone, Default, Serialize, Deserialize)]
6678pub struct CustomerSegmentationSchemaConfig {
6679 #[serde(default)]
6681 pub enabled: bool,
6682
6683 #[serde(default)]
6685 pub value_segments: ValueSegmentsSchemaConfig,
6686
6687 #[serde(default)]
6689 pub lifecycle: LifecycleSchemaConfig,
6690
6691 #[serde(default)]
6693 pub networks: CustomerNetworksSchemaConfig,
6694}
6695
6696#[derive(Debug, Clone, Serialize, Deserialize)]
6698pub struct ValueSegmentsSchemaConfig {
6699 #[serde(default)]
6701 pub enterprise: SegmentDetailSchemaConfig,
6702
6703 #[serde(default)]
6705 pub mid_market: SegmentDetailSchemaConfig,
6706
6707 #[serde(default)]
6709 pub smb: SegmentDetailSchemaConfig,
6710
6711 #[serde(default)]
6713 pub consumer: SegmentDetailSchemaConfig,
6714}
6715
6716impl Default for ValueSegmentsSchemaConfig {
6717 fn default() -> Self {
6718 Self {
6719 enterprise: SegmentDetailSchemaConfig {
6720 revenue_share: 0.40,
6721 customer_share: 0.05,
6722 avg_order_value_range: "50000+".to_string(),
6723 },
6724 mid_market: SegmentDetailSchemaConfig {
6725 revenue_share: 0.35,
6726 customer_share: 0.20,
6727 avg_order_value_range: "5000-50000".to_string(),
6728 },
6729 smb: SegmentDetailSchemaConfig {
6730 revenue_share: 0.20,
6731 customer_share: 0.50,
6732 avg_order_value_range: "500-5000".to_string(),
6733 },
6734 consumer: SegmentDetailSchemaConfig {
6735 revenue_share: 0.05,
6736 customer_share: 0.25,
6737 avg_order_value_range: "50-500".to_string(),
6738 },
6739 }
6740 }
6741}
6742
6743#[derive(Debug, Clone, Serialize, Deserialize)]
6745pub struct SegmentDetailSchemaConfig {
6746 #[serde(default)]
6748 pub revenue_share: f64,
6749
6750 #[serde(default)]
6752 pub customer_share: f64,
6753
6754 #[serde(default)]
6756 pub avg_order_value_range: String,
6757}
6758
6759impl Default for SegmentDetailSchemaConfig {
6760 fn default() -> Self {
6761 Self {
6762 revenue_share: 0.25,
6763 customer_share: 0.25,
6764 avg_order_value_range: "1000-10000".to_string(),
6765 }
6766 }
6767}
6768
6769#[derive(Debug, Clone, Serialize, Deserialize)]
6771pub struct LifecycleSchemaConfig {
6772 #[serde(default)]
6774 pub prospect_rate: f64,
6775
6776 #[serde(default = "default_new_rate")]
6778 pub new_rate: f64,
6779
6780 #[serde(default = "default_growth_rate")]
6782 pub growth_rate: f64,
6783
6784 #[serde(default = "default_mature_rate")]
6786 pub mature_rate: f64,
6787
6788 #[serde(default = "default_at_risk_rate")]
6790 pub at_risk_rate: f64,
6791
6792 #[serde(default = "default_churned_rate")]
6794 pub churned_rate: f64,
6795}
6796
6797fn default_new_rate() -> f64 {
6798 0.10
6799}
6800
6801fn default_growth_rate() -> f64 {
6802 0.15
6803}
6804
6805fn default_mature_rate() -> f64 {
6806 0.60
6807}
6808
6809fn default_at_risk_rate() -> f64 {
6810 0.10
6811}
6812
6813fn default_churned_rate() -> f64 {
6814 0.05
6815}
6816
6817impl Default for LifecycleSchemaConfig {
6818 fn default() -> Self {
6819 Self {
6820 prospect_rate: 0.0,
6821 new_rate: 0.10,
6822 growth_rate: 0.15,
6823 mature_rate: 0.60,
6824 at_risk_rate: 0.10,
6825 churned_rate: 0.05,
6826 }
6827 }
6828}
6829
6830#[derive(Debug, Clone, Default, Serialize, Deserialize)]
6832pub struct CustomerNetworksSchemaConfig {
6833 #[serde(default)]
6835 pub referrals: ReferralSchemaConfig,
6836
6837 #[serde(default)]
6839 pub corporate_hierarchies: HierarchySchemaConfig,
6840}
6841
6842#[derive(Debug, Clone, Serialize, Deserialize)]
6844pub struct ReferralSchemaConfig {
6845 #[serde(default = "default_true")]
6847 pub enabled: bool,
6848
6849 #[serde(default = "default_referral_rate")]
6851 pub referral_rate: f64,
6852}
6853
6854fn default_referral_rate() -> f64 {
6855 0.15
6856}
6857
6858impl Default for ReferralSchemaConfig {
6859 fn default() -> Self {
6860 Self {
6861 enabled: true,
6862 referral_rate: 0.15,
6863 }
6864 }
6865}
6866
6867#[derive(Debug, Clone, Serialize, Deserialize)]
6869pub struct HierarchySchemaConfig {
6870 #[serde(default = "default_true")]
6872 pub enabled: bool,
6873
6874 #[serde(default = "default_hierarchy_rate")]
6876 pub probability: f64,
6877}
6878
6879fn default_hierarchy_rate() -> f64 {
6880 0.30
6881}
6882
6883impl Default for HierarchySchemaConfig {
6884 fn default() -> Self {
6885 Self {
6886 enabled: true,
6887 probability: 0.30,
6888 }
6889 }
6890}
6891
6892#[derive(Debug, Clone, Default, Serialize, Deserialize)]
6898pub struct RelationshipStrengthSchemaConfig {
6899 #[serde(default)]
6901 pub enabled: bool,
6902
6903 #[serde(default)]
6905 pub calculation: StrengthCalculationSchemaConfig,
6906
6907 #[serde(default)]
6909 pub thresholds: StrengthThresholdsSchemaConfig,
6910}
6911
6912#[derive(Debug, Clone, Serialize, Deserialize)]
6914pub struct StrengthCalculationSchemaConfig {
6915 #[serde(default = "default_volume_weight")]
6917 pub transaction_volume_weight: f64,
6918
6919 #[serde(default = "default_count_weight")]
6921 pub transaction_count_weight: f64,
6922
6923 #[serde(default = "default_duration_weight")]
6925 pub relationship_duration_weight: f64,
6926
6927 #[serde(default = "default_recency_weight")]
6929 pub recency_weight: f64,
6930
6931 #[serde(default = "default_mutual_weight")]
6933 pub mutual_connections_weight: f64,
6934
6935 #[serde(default = "default_recency_half_life")]
6937 pub recency_half_life_days: u32,
6938}
6939
6940fn default_volume_weight() -> f64 {
6941 0.30
6942}
6943
6944fn default_count_weight() -> f64 {
6945 0.25
6946}
6947
6948fn default_duration_weight() -> f64 {
6949 0.20
6950}
6951
6952fn default_recency_weight() -> f64 {
6953 0.15
6954}
6955
6956fn default_mutual_weight() -> f64 {
6957 0.10
6958}
6959
6960fn default_recency_half_life() -> u32 {
6961 90
6962}
6963
6964impl Default for StrengthCalculationSchemaConfig {
6965 fn default() -> Self {
6966 Self {
6967 transaction_volume_weight: 0.30,
6968 transaction_count_weight: 0.25,
6969 relationship_duration_weight: 0.20,
6970 recency_weight: 0.15,
6971 mutual_connections_weight: 0.10,
6972 recency_half_life_days: 90,
6973 }
6974 }
6975}
6976
6977#[derive(Debug, Clone, Serialize, Deserialize)]
6979pub struct StrengthThresholdsSchemaConfig {
6980 #[serde(default = "default_strong_threshold")]
6982 pub strong: f64,
6983
6984 #[serde(default = "default_moderate_threshold")]
6986 pub moderate: f64,
6987
6988 #[serde(default = "default_weak_threshold")]
6990 pub weak: f64,
6991}
6992
6993fn default_strong_threshold() -> f64 {
6994 0.7
6995}
6996
6997fn default_moderate_threshold() -> f64 {
6998 0.4
6999}
7000
7001fn default_weak_threshold() -> f64 {
7002 0.1
7003}
7004
7005impl Default for StrengthThresholdsSchemaConfig {
7006 fn default() -> Self {
7007 Self {
7008 strong: 0.7,
7009 moderate: 0.4,
7010 weak: 0.1,
7011 }
7012 }
7013}
7014
7015#[derive(Debug, Clone, Serialize, Deserialize)]
7021pub struct CrossProcessLinksSchemaConfig {
7022 #[serde(default)]
7024 pub enabled: bool,
7025
7026 #[serde(default = "default_true")]
7028 pub inventory_p2p_o2c: bool,
7029
7030 #[serde(default = "default_true")]
7032 pub payment_bank_reconciliation: bool,
7033
7034 #[serde(default = "default_true")]
7036 pub intercompany_bilateral: bool,
7037
7038 #[serde(default = "default_inventory_link_rate")]
7040 pub inventory_link_rate: f64,
7041}
7042
7043fn default_inventory_link_rate() -> f64 {
7044 0.30
7045}
7046
7047impl Default for CrossProcessLinksSchemaConfig {
7048 fn default() -> Self {
7049 Self {
7050 enabled: false,
7051 inventory_p2p_o2c: true,
7052 payment_bank_reconciliation: true,
7053 intercompany_bilateral: true,
7054 inventory_link_rate: 0.30,
7055 }
7056 }
7057}
7058
7059#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7065pub struct OrganizationalEventsSchemaConfig {
7066 #[serde(default)]
7068 pub enabled: bool,
7069
7070 #[serde(default)]
7072 pub effect_blending: EffectBlendingModeConfig,
7073
7074 #[serde(default)]
7076 pub events: Vec<OrganizationalEventSchemaConfig>,
7077
7078 #[serde(default)]
7080 pub process_evolution: Vec<ProcessEvolutionSchemaConfig>,
7081
7082 #[serde(default)]
7084 pub technology_transitions: Vec<TechnologyTransitionSchemaConfig>,
7085}
7086
7087#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
7089#[serde(rename_all = "snake_case")]
7090pub enum EffectBlendingModeConfig {
7091 #[default]
7093 Multiplicative,
7094 Additive,
7096 Maximum,
7098 Minimum,
7100}
7101
7102#[derive(Debug, Clone, Serialize, Deserialize)]
7104pub struct OrganizationalEventSchemaConfig {
7105 pub id: String,
7107
7108 pub event_type: OrganizationalEventTypeSchemaConfig,
7110
7111 pub effective_date: String,
7113
7114 #[serde(default = "default_org_transition_months")]
7116 pub transition_months: u32,
7117
7118 #[serde(default)]
7120 pub description: Option<String>,
7121}
7122
7123fn default_org_transition_months() -> u32 {
7124 6
7125}
7126
7127#[derive(Debug, Clone, Serialize, Deserialize)]
7129#[serde(tag = "type", rename_all = "snake_case")]
7130pub enum OrganizationalEventTypeSchemaConfig {
7131 Acquisition {
7133 acquired_entity: String,
7135 #[serde(default = "default_acquisition_volume")]
7137 volume_increase: f64,
7138 #[serde(default = "default_acquisition_error")]
7140 integration_error_rate: f64,
7141 #[serde(default = "default_parallel_days")]
7143 parallel_posting_days: u32,
7144 },
7145 Divestiture {
7147 divested_entity: String,
7149 #[serde(default = "default_divestiture_volume")]
7151 volume_reduction: f64,
7152 #[serde(default = "default_true_val")]
7154 remove_entity: bool,
7155 },
7156 Reorganization {
7158 #[serde(default)]
7160 cost_center_remapping: std::collections::HashMap<String, String>,
7161 #[serde(default = "default_reorg_error")]
7163 transition_error_rate: f64,
7164 },
7165 LeadershipChange {
7167 role: String,
7169 #[serde(default)]
7171 policy_changes: Vec<String>,
7172 },
7173 WorkforceReduction {
7175 #[serde(default = "default_workforce_reduction")]
7177 reduction_percent: f64,
7178 #[serde(default = "default_workforce_error")]
7180 error_rate_increase: f64,
7181 },
7182 Merger {
7184 merged_entity: String,
7186 #[serde(default = "default_merger_volume")]
7188 volume_increase: f64,
7189 },
7190}
7191
7192fn default_acquisition_volume() -> f64 {
7193 1.35
7194}
7195
7196fn default_acquisition_error() -> f64 {
7197 0.05
7198}
7199
7200fn default_parallel_days() -> u32 {
7201 30
7202}
7203
7204fn default_divestiture_volume() -> f64 {
7205 0.70
7206}
7207
7208fn default_true_val() -> bool {
7209 true
7210}
7211
7212fn default_reorg_error() -> f64 {
7213 0.04
7214}
7215
7216fn default_workforce_reduction() -> f64 {
7217 0.10
7218}
7219
7220fn default_workforce_error() -> f64 {
7221 0.05
7222}
7223
7224fn default_merger_volume() -> f64 {
7225 1.80
7226}
7227
7228#[derive(Debug, Clone, Serialize, Deserialize)]
7230pub struct ProcessEvolutionSchemaConfig {
7231 pub id: String,
7233
7234 pub event_type: ProcessEvolutionTypeSchemaConfig,
7236
7237 pub effective_date: String,
7239
7240 #[serde(default)]
7242 pub description: Option<String>,
7243}
7244
7245#[derive(Debug, Clone, Serialize, Deserialize)]
7247#[serde(tag = "type", rename_all = "snake_case")]
7248pub enum ProcessEvolutionTypeSchemaConfig {
7249 ProcessAutomation {
7251 process_name: String,
7253 #[serde(default = "default_manual_before")]
7255 manual_rate_before: f64,
7256 #[serde(default = "default_manual_after")]
7258 manual_rate_after: f64,
7259 },
7260 ApprovalWorkflowChange {
7262 description: String,
7264 },
7265 ControlEnhancement {
7267 control_id: String,
7269 #[serde(default = "default_error_reduction")]
7271 error_reduction: f64,
7272 },
7273}
7274
7275fn default_manual_before() -> f64 {
7276 0.80
7277}
7278
7279fn default_manual_after() -> f64 {
7280 0.15
7281}
7282
7283fn default_error_reduction() -> f64 {
7284 0.02
7285}
7286
7287#[derive(Debug, Clone, Serialize, Deserialize)]
7289pub struct TechnologyTransitionSchemaConfig {
7290 pub id: String,
7292
7293 pub event_type: TechnologyTransitionTypeSchemaConfig,
7295
7296 #[serde(default)]
7298 pub description: Option<String>,
7299}
7300
7301#[derive(Debug, Clone, Serialize, Deserialize)]
7303#[serde(tag = "type", rename_all = "snake_case")]
7304pub enum TechnologyTransitionTypeSchemaConfig {
7305 ErpMigration {
7307 source_system: String,
7309 target_system: String,
7311 cutover_date: String,
7313 stabilization_end: String,
7315 #[serde(default = "default_erp_duplicate_rate")]
7317 duplicate_rate: f64,
7318 #[serde(default = "default_format_mismatch")]
7320 format_mismatch_rate: f64,
7321 },
7322 ModuleImplementation {
7324 module_name: String,
7326 go_live_date: String,
7328 },
7329}
7330
7331fn default_erp_duplicate_rate() -> f64 {
7332 0.02
7333}
7334
7335fn default_format_mismatch() -> f64 {
7336 0.03
7337}
7338
7339#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7345pub struct BehavioralDriftSchemaConfig {
7346 #[serde(default)]
7348 pub enabled: bool,
7349
7350 #[serde(default)]
7352 pub vendor_behavior: VendorBehaviorSchemaConfig,
7353
7354 #[serde(default)]
7356 pub customer_behavior: CustomerBehaviorSchemaConfig,
7357
7358 #[serde(default)]
7360 pub employee_behavior: EmployeeBehaviorSchemaConfig,
7361
7362 #[serde(default)]
7364 pub collective: CollectiveBehaviorSchemaConfig,
7365}
7366
7367#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7369pub struct VendorBehaviorSchemaConfig {
7370 #[serde(default)]
7372 pub payment_terms_drift: PaymentTermsDriftSchemaConfig,
7373
7374 #[serde(default)]
7376 pub quality_drift: QualityDriftSchemaConfig,
7377}
7378
7379#[derive(Debug, Clone, Serialize, Deserialize)]
7381pub struct PaymentTermsDriftSchemaConfig {
7382 #[serde(default = "default_extension_rate")]
7384 pub extension_rate_per_year: f64,
7385
7386 #[serde(default = "default_economic_sensitivity")]
7388 pub economic_sensitivity: f64,
7389}
7390
7391fn default_extension_rate() -> f64 {
7392 2.5
7393}
7394
7395fn default_economic_sensitivity() -> f64 {
7396 1.0
7397}
7398
7399impl Default for PaymentTermsDriftSchemaConfig {
7400 fn default() -> Self {
7401 Self {
7402 extension_rate_per_year: 2.5,
7403 economic_sensitivity: 1.0,
7404 }
7405 }
7406}
7407
7408#[derive(Debug, Clone, Serialize, Deserialize)]
7410pub struct QualityDriftSchemaConfig {
7411 #[serde(default = "default_improvement_rate")]
7413 pub new_vendor_improvement_rate: f64,
7414
7415 #[serde(default = "default_decline_rate")]
7417 pub complacency_decline_rate: f64,
7418}
7419
7420fn default_improvement_rate() -> f64 {
7421 0.02
7422}
7423
7424fn default_decline_rate() -> f64 {
7425 0.01
7426}
7427
7428impl Default for QualityDriftSchemaConfig {
7429 fn default() -> Self {
7430 Self {
7431 new_vendor_improvement_rate: 0.02,
7432 complacency_decline_rate: 0.01,
7433 }
7434 }
7435}
7436
7437#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7439pub struct CustomerBehaviorSchemaConfig {
7440 #[serde(default)]
7442 pub payment_drift: CustomerPaymentDriftSchemaConfig,
7443
7444 #[serde(default)]
7446 pub order_drift: OrderDriftSchemaConfig,
7447}
7448
7449#[derive(Debug, Clone, Serialize, Deserialize)]
7451pub struct CustomerPaymentDriftSchemaConfig {
7452 #[serde(default = "default_downturn_extension")]
7454 pub downturn_days_extension: (u32, u32),
7455
7456 #[serde(default = "default_bad_debt_increase")]
7458 pub downturn_bad_debt_increase: f64,
7459}
7460
7461fn default_downturn_extension() -> (u32, u32) {
7462 (5, 15)
7463}
7464
7465fn default_bad_debt_increase() -> f64 {
7466 0.02
7467}
7468
7469impl Default for CustomerPaymentDriftSchemaConfig {
7470 fn default() -> Self {
7471 Self {
7472 downturn_days_extension: (5, 15),
7473 downturn_bad_debt_increase: 0.02,
7474 }
7475 }
7476}
7477
7478#[derive(Debug, Clone, Serialize, Deserialize)]
7480pub struct OrderDriftSchemaConfig {
7481 #[serde(default = "default_digital_shift")]
7483 pub digital_shift_rate: f64,
7484}
7485
7486fn default_digital_shift() -> f64 {
7487 0.05
7488}
7489
7490impl Default for OrderDriftSchemaConfig {
7491 fn default() -> Self {
7492 Self {
7493 digital_shift_rate: 0.05,
7494 }
7495 }
7496}
7497
7498#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7500pub struct EmployeeBehaviorSchemaConfig {
7501 #[serde(default)]
7503 pub approval_drift: ApprovalDriftSchemaConfig,
7504
7505 #[serde(default)]
7507 pub error_drift: ErrorDriftSchemaConfig,
7508}
7509
7510#[derive(Debug, Clone, Serialize, Deserialize)]
7512pub struct ApprovalDriftSchemaConfig {
7513 #[serde(default = "default_eom_intensity")]
7515 pub eom_intensity_increase_per_year: f64,
7516
7517 #[serde(default = "default_rubber_stamp")]
7519 pub rubber_stamp_volume_threshold: u32,
7520}
7521
7522fn default_eom_intensity() -> f64 {
7523 0.05
7524}
7525
7526fn default_rubber_stamp() -> u32 {
7527 50
7528}
7529
7530impl Default for ApprovalDriftSchemaConfig {
7531 fn default() -> Self {
7532 Self {
7533 eom_intensity_increase_per_year: 0.05,
7534 rubber_stamp_volume_threshold: 50,
7535 }
7536 }
7537}
7538
7539#[derive(Debug, Clone, Serialize, Deserialize)]
7541pub struct ErrorDriftSchemaConfig {
7542 #[serde(default = "default_new_error")]
7544 pub new_employee_error_rate: f64,
7545
7546 #[serde(default = "default_learning_months")]
7548 pub learning_curve_months: u32,
7549}
7550
7551fn default_new_error() -> f64 {
7552 0.08
7553}
7554
7555fn default_learning_months() -> u32 {
7556 6
7557}
7558
7559impl Default for ErrorDriftSchemaConfig {
7560 fn default() -> Self {
7561 Self {
7562 new_employee_error_rate: 0.08,
7563 learning_curve_months: 6,
7564 }
7565 }
7566}
7567
7568#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7570pub struct CollectiveBehaviorSchemaConfig {
7571 #[serde(default)]
7573 pub automation_adoption: AutomationAdoptionSchemaConfig,
7574}
7575
7576#[derive(Debug, Clone, Serialize, Deserialize)]
7578pub struct AutomationAdoptionSchemaConfig {
7579 #[serde(default)]
7581 pub s_curve_enabled: bool,
7582
7583 #[serde(default = "default_midpoint")]
7585 pub adoption_midpoint_months: u32,
7586
7587 #[serde(default = "default_steepness")]
7589 pub steepness: f64,
7590}
7591
7592fn default_midpoint() -> u32 {
7593 24
7594}
7595
7596fn default_steepness() -> f64 {
7597 0.15
7598}
7599
7600impl Default for AutomationAdoptionSchemaConfig {
7601 fn default() -> Self {
7602 Self {
7603 s_curve_enabled: false,
7604 adoption_midpoint_months: 24,
7605 steepness: 0.15,
7606 }
7607 }
7608}
7609
7610#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7616pub struct MarketDriftSchemaConfig {
7617 #[serde(default)]
7619 pub enabled: bool,
7620
7621 #[serde(default)]
7623 pub economic_cycle: MarketEconomicCycleSchemaConfig,
7624
7625 #[serde(default)]
7627 pub industry_cycles: std::collections::HashMap<String, IndustryCycleSchemaConfig>,
7628
7629 #[serde(default)]
7631 pub commodities: CommoditiesSchemaConfig,
7632}
7633
7634#[derive(Debug, Clone, Serialize, Deserialize)]
7636pub struct MarketEconomicCycleSchemaConfig {
7637 #[serde(default)]
7639 pub enabled: bool,
7640
7641 #[serde(default)]
7643 pub cycle_type: CycleTypeSchemaConfig,
7644
7645 #[serde(default = "default_market_cycle_period")]
7647 pub period_months: u32,
7648
7649 #[serde(default = "default_market_amplitude")]
7651 pub amplitude: f64,
7652
7653 #[serde(default)]
7655 pub recession: RecessionSchemaConfig,
7656}
7657
7658fn default_market_cycle_period() -> u32 {
7659 48
7660}
7661
7662fn default_market_amplitude() -> f64 {
7663 0.15
7664}
7665
7666impl Default for MarketEconomicCycleSchemaConfig {
7667 fn default() -> Self {
7668 Self {
7669 enabled: false,
7670 cycle_type: CycleTypeSchemaConfig::Sinusoidal,
7671 period_months: 48,
7672 amplitude: 0.15,
7673 recession: RecessionSchemaConfig::default(),
7674 }
7675 }
7676}
7677
7678#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
7680#[serde(rename_all = "snake_case")]
7681pub enum CycleTypeSchemaConfig {
7682 #[default]
7684 Sinusoidal,
7685 Asymmetric,
7687 MeanReverting,
7689}
7690
7691#[derive(Debug, Clone, Serialize, Deserialize)]
7693pub struct RecessionSchemaConfig {
7694 #[serde(default)]
7696 pub enabled: bool,
7697
7698 #[serde(default = "default_recession_prob")]
7700 pub probability_per_year: f64,
7701
7702 #[serde(default)]
7704 pub severity: RecessionSeveritySchemaConfig,
7705
7706 #[serde(default)]
7708 pub recession_periods: Vec<RecessionPeriodSchemaConfig>,
7709}
7710
7711fn default_recession_prob() -> f64 {
7712 0.10
7713}
7714
7715impl Default for RecessionSchemaConfig {
7716 fn default() -> Self {
7717 Self {
7718 enabled: false,
7719 probability_per_year: 0.10,
7720 severity: RecessionSeveritySchemaConfig::Moderate,
7721 recession_periods: Vec::new(),
7722 }
7723 }
7724}
7725
7726#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
7728#[serde(rename_all = "snake_case")]
7729pub enum RecessionSeveritySchemaConfig {
7730 Mild,
7732 #[default]
7734 Moderate,
7735 Severe,
7737}
7738
7739#[derive(Debug, Clone, Serialize, Deserialize)]
7741pub struct RecessionPeriodSchemaConfig {
7742 pub start_month: u32,
7744 pub duration_months: u32,
7746}
7747
7748#[derive(Debug, Clone, Serialize, Deserialize)]
7750pub struct IndustryCycleSchemaConfig {
7751 #[serde(default = "default_industry_period")]
7753 pub period_months: u32,
7754
7755 #[serde(default = "default_industry_amp")]
7757 pub amplitude: f64,
7758}
7759
7760fn default_industry_period() -> u32 {
7761 36
7762}
7763
7764fn default_industry_amp() -> f64 {
7765 0.20
7766}
7767
7768#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7770pub struct CommoditiesSchemaConfig {
7771 #[serde(default)]
7773 pub enabled: bool,
7774
7775 #[serde(default)]
7777 pub items: Vec<CommodityItemSchemaConfig>,
7778}
7779
7780#[derive(Debug, Clone, Serialize, Deserialize)]
7782pub struct CommodityItemSchemaConfig {
7783 pub name: String,
7785
7786 #[serde(default = "default_volatility")]
7788 pub volatility: f64,
7789
7790 #[serde(default)]
7792 pub cogs_pass_through: f64,
7793
7794 #[serde(default)]
7796 pub overhead_pass_through: f64,
7797}
7798
7799fn default_volatility() -> f64 {
7800 0.20
7801}
7802
7803#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7809pub struct DriftLabelingSchemaConfig {
7810 #[serde(default)]
7812 pub enabled: bool,
7813
7814 #[serde(default)]
7816 pub statistical: StatisticalDriftLabelingSchemaConfig,
7817
7818 #[serde(default)]
7820 pub categorical: CategoricalDriftLabelingSchemaConfig,
7821
7822 #[serde(default)]
7824 pub temporal: TemporalDriftLabelingSchemaConfig,
7825
7826 #[serde(default)]
7828 pub regulatory_calendar_preset: Option<String>,
7829}
7830
7831#[derive(Debug, Clone, Serialize, Deserialize)]
7833pub struct StatisticalDriftLabelingSchemaConfig {
7834 #[serde(default = "default_true_val")]
7836 pub enabled: bool,
7837
7838 #[serde(default = "default_min_magnitude")]
7840 pub min_magnitude_threshold: f64,
7841}
7842
7843fn default_min_magnitude() -> f64 {
7844 0.05
7845}
7846
7847impl Default for StatisticalDriftLabelingSchemaConfig {
7848 fn default() -> Self {
7849 Self {
7850 enabled: true,
7851 min_magnitude_threshold: 0.05,
7852 }
7853 }
7854}
7855
7856#[derive(Debug, Clone, Serialize, Deserialize)]
7858pub struct CategoricalDriftLabelingSchemaConfig {
7859 #[serde(default = "default_true_val")]
7861 pub enabled: bool,
7862}
7863
7864impl Default for CategoricalDriftLabelingSchemaConfig {
7865 fn default() -> Self {
7866 Self { enabled: true }
7867 }
7868}
7869
7870#[derive(Debug, Clone, Serialize, Deserialize)]
7872pub struct TemporalDriftLabelingSchemaConfig {
7873 #[serde(default = "default_true_val")]
7875 pub enabled: bool,
7876}
7877
7878impl Default for TemporalDriftLabelingSchemaConfig {
7879 fn default() -> Self {
7880 Self { enabled: true }
7881 }
7882}
7883
7884#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7897pub struct EnhancedAnomalyConfig {
7898 #[serde(default)]
7900 pub enabled: bool,
7901
7902 #[serde(default)]
7904 pub rates: AnomalyRateConfig,
7905
7906 #[serde(default)]
7908 pub multi_stage_schemes: MultiStageSchemeConfig,
7909
7910 #[serde(default)]
7912 pub correlated_injection: CorrelatedInjectionConfig,
7913
7914 #[serde(default)]
7916 pub near_miss: NearMissConfig,
7917
7918 #[serde(default)]
7920 pub difficulty_classification: DifficultyClassificationConfig,
7921
7922 #[serde(default)]
7924 pub context_aware: ContextAwareConfig,
7925
7926 #[serde(default)]
7928 pub labeling: EnhancedLabelingConfig,
7929}
7930
7931#[derive(Debug, Clone, Serialize, Deserialize)]
7933pub struct AnomalyRateConfig {
7934 #[serde(default = "default_total_anomaly_rate")]
7936 pub total_rate: f64,
7937
7938 #[serde(default = "default_fraud_anomaly_rate")]
7940 pub fraud_rate: f64,
7941
7942 #[serde(default = "default_error_anomaly_rate")]
7944 pub error_rate: f64,
7945
7946 #[serde(default = "default_process_anomaly_rate")]
7948 pub process_rate: f64,
7949}
7950
7951fn default_total_anomaly_rate() -> f64 {
7952 0.03
7953}
7954fn default_fraud_anomaly_rate() -> f64 {
7955 0.01
7956}
7957fn default_error_anomaly_rate() -> f64 {
7958 0.015
7959}
7960fn default_process_anomaly_rate() -> f64 {
7961 0.005
7962}
7963
7964impl Default for AnomalyRateConfig {
7965 fn default() -> Self {
7966 Self {
7967 total_rate: default_total_anomaly_rate(),
7968 fraud_rate: default_fraud_anomaly_rate(),
7969 error_rate: default_error_anomaly_rate(),
7970 process_rate: default_process_anomaly_rate(),
7971 }
7972 }
7973}
7974
7975#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7977pub struct MultiStageSchemeConfig {
7978 #[serde(default)]
7980 pub enabled: bool,
7981
7982 #[serde(default)]
7984 pub embezzlement: EmbezzlementSchemeConfig,
7985
7986 #[serde(default)]
7988 pub revenue_manipulation: RevenueManipulationSchemeConfig,
7989
7990 #[serde(default)]
7992 pub kickback: KickbackSchemeConfig,
7993}
7994
7995#[derive(Debug, Clone, Serialize, Deserialize)]
7997pub struct EmbezzlementSchemeConfig {
7998 #[serde(default = "default_embezzlement_probability")]
8000 pub probability: f64,
8001
8002 #[serde(default)]
8004 pub testing_stage: SchemeStageConfig,
8005
8006 #[serde(default)]
8008 pub escalation_stage: SchemeStageConfig,
8009
8010 #[serde(default)]
8012 pub acceleration_stage: SchemeStageConfig,
8013
8014 #[serde(default)]
8016 pub desperation_stage: SchemeStageConfig,
8017}
8018
8019fn default_embezzlement_probability() -> f64 {
8020 0.02
8021}
8022
8023impl Default for EmbezzlementSchemeConfig {
8024 fn default() -> Self {
8025 Self {
8026 probability: default_embezzlement_probability(),
8027 testing_stage: SchemeStageConfig {
8028 duration_months: 2,
8029 amount_min: 100.0,
8030 amount_max: 500.0,
8031 transaction_count_min: 2,
8032 transaction_count_max: 5,
8033 difficulty: "hard".to_string(),
8034 },
8035 escalation_stage: SchemeStageConfig {
8036 duration_months: 6,
8037 amount_min: 500.0,
8038 amount_max: 2000.0,
8039 transaction_count_min: 3,
8040 transaction_count_max: 8,
8041 difficulty: "moderate".to_string(),
8042 },
8043 acceleration_stage: SchemeStageConfig {
8044 duration_months: 3,
8045 amount_min: 2000.0,
8046 amount_max: 10000.0,
8047 transaction_count_min: 5,
8048 transaction_count_max: 12,
8049 difficulty: "easy".to_string(),
8050 },
8051 desperation_stage: SchemeStageConfig {
8052 duration_months: 1,
8053 amount_min: 10000.0,
8054 amount_max: 50000.0,
8055 transaction_count_min: 3,
8056 transaction_count_max: 6,
8057 difficulty: "trivial".to_string(),
8058 },
8059 }
8060 }
8061}
8062
8063#[derive(Debug, Clone, Serialize, Deserialize)]
8065pub struct RevenueManipulationSchemeConfig {
8066 #[serde(default = "default_revenue_manipulation_probability")]
8068 pub probability: f64,
8069
8070 #[serde(default = "default_early_recognition_target")]
8072 pub early_recognition_target: f64,
8073
8074 #[serde(default = "default_expense_deferral_target")]
8076 pub expense_deferral_target: f64,
8077
8078 #[serde(default = "default_reserve_release_target")]
8080 pub reserve_release_target: f64,
8081
8082 #[serde(default = "default_channel_stuffing_target")]
8084 pub channel_stuffing_target: f64,
8085}
8086
8087fn default_revenue_manipulation_probability() -> f64 {
8088 0.01
8089}
8090fn default_early_recognition_target() -> f64 {
8091 0.02
8092}
8093fn default_expense_deferral_target() -> f64 {
8094 0.03
8095}
8096fn default_reserve_release_target() -> f64 {
8097 0.02
8098}
8099fn default_channel_stuffing_target() -> f64 {
8100 0.05
8101}
8102
8103impl Default for RevenueManipulationSchemeConfig {
8104 fn default() -> Self {
8105 Self {
8106 probability: default_revenue_manipulation_probability(),
8107 early_recognition_target: default_early_recognition_target(),
8108 expense_deferral_target: default_expense_deferral_target(),
8109 reserve_release_target: default_reserve_release_target(),
8110 channel_stuffing_target: default_channel_stuffing_target(),
8111 }
8112 }
8113}
8114
8115#[derive(Debug, Clone, Serialize, Deserialize)]
8117pub struct KickbackSchemeConfig {
8118 #[serde(default = "default_kickback_probability")]
8120 pub probability: f64,
8121
8122 #[serde(default = "default_kickback_inflation_min")]
8124 pub inflation_min: f64,
8125
8126 #[serde(default = "default_kickback_inflation_max")]
8128 pub inflation_max: f64,
8129
8130 #[serde(default = "default_kickback_percent")]
8132 pub kickback_percent: f64,
8133
8134 #[serde(default = "default_kickback_setup_months")]
8136 pub setup_months: u32,
8137
8138 #[serde(default = "default_kickback_operation_months")]
8140 pub operation_months: u32,
8141}
8142
8143fn default_kickback_probability() -> f64 {
8144 0.01
8145}
8146fn default_kickback_inflation_min() -> f64 {
8147 0.10
8148}
8149fn default_kickback_inflation_max() -> f64 {
8150 0.25
8151}
8152fn default_kickback_percent() -> f64 {
8153 0.50
8154}
8155fn default_kickback_setup_months() -> u32 {
8156 3
8157}
8158fn default_kickback_operation_months() -> u32 {
8159 12
8160}
8161
8162impl Default for KickbackSchemeConfig {
8163 fn default() -> Self {
8164 Self {
8165 probability: default_kickback_probability(),
8166 inflation_min: default_kickback_inflation_min(),
8167 inflation_max: default_kickback_inflation_max(),
8168 kickback_percent: default_kickback_percent(),
8169 setup_months: default_kickback_setup_months(),
8170 operation_months: default_kickback_operation_months(),
8171 }
8172 }
8173}
8174
8175#[derive(Debug, Clone, Serialize, Deserialize)]
8177pub struct SchemeStageConfig {
8178 pub duration_months: u32,
8180
8181 pub amount_min: f64,
8183
8184 pub amount_max: f64,
8186
8187 pub transaction_count_min: u32,
8189
8190 pub transaction_count_max: u32,
8192
8193 pub difficulty: String,
8195}
8196
8197impl Default for SchemeStageConfig {
8198 fn default() -> Self {
8199 Self {
8200 duration_months: 3,
8201 amount_min: 100.0,
8202 amount_max: 1000.0,
8203 transaction_count_min: 2,
8204 transaction_count_max: 10,
8205 difficulty: "moderate".to_string(),
8206 }
8207 }
8208}
8209
8210#[derive(Debug, Clone, Serialize, Deserialize)]
8212pub struct CorrelatedInjectionConfig {
8213 #[serde(default)]
8215 pub enabled: bool,
8216
8217 #[serde(default = "default_true_val")]
8219 pub fraud_concealment: bool,
8220
8221 #[serde(default = "default_true_val")]
8223 pub error_cascade: bool,
8224
8225 #[serde(default = "default_true_val")]
8227 pub temporal_clustering: bool,
8228
8229 #[serde(default)]
8231 pub temporal_clustering_config: TemporalClusteringConfig,
8232
8233 #[serde(default)]
8235 pub co_occurrence_patterns: Vec<CoOccurrencePatternConfig>,
8236}
8237
8238impl Default for CorrelatedInjectionConfig {
8239 fn default() -> Self {
8240 Self {
8241 enabled: false,
8242 fraud_concealment: true,
8243 error_cascade: true,
8244 temporal_clustering: true,
8245 temporal_clustering_config: TemporalClusteringConfig::default(),
8246 co_occurrence_patterns: Vec::new(),
8247 }
8248 }
8249}
8250
8251#[derive(Debug, Clone, Serialize, Deserialize)]
8253pub struct TemporalClusteringConfig {
8254 #[serde(default = "default_period_end_multiplier")]
8256 pub period_end_multiplier: f64,
8257
8258 #[serde(default = "default_period_end_days")]
8260 pub period_end_days: u32,
8261
8262 #[serde(default = "default_quarter_end_multiplier")]
8264 pub quarter_end_multiplier: f64,
8265
8266 #[serde(default = "default_year_end_multiplier")]
8268 pub year_end_multiplier: f64,
8269}
8270
8271fn default_period_end_multiplier() -> f64 {
8272 2.5
8273}
8274fn default_period_end_days() -> u32 {
8275 5
8276}
8277fn default_quarter_end_multiplier() -> f64 {
8278 1.5
8279}
8280fn default_year_end_multiplier() -> f64 {
8281 2.0
8282}
8283
8284impl Default for TemporalClusteringConfig {
8285 fn default() -> Self {
8286 Self {
8287 period_end_multiplier: default_period_end_multiplier(),
8288 period_end_days: default_period_end_days(),
8289 quarter_end_multiplier: default_quarter_end_multiplier(),
8290 year_end_multiplier: default_year_end_multiplier(),
8291 }
8292 }
8293}
8294
8295#[derive(Debug, Clone, Serialize, Deserialize)]
8297pub struct CoOccurrencePatternConfig {
8298 pub name: String,
8300
8301 pub primary_type: String,
8303
8304 pub correlated: Vec<CorrelatedAnomalyConfig>,
8306}
8307
8308#[derive(Debug, Clone, Serialize, Deserialize)]
8310pub struct CorrelatedAnomalyConfig {
8311 pub anomaly_type: String,
8313
8314 pub probability: f64,
8316
8317 pub lag_days_min: i32,
8319
8320 pub lag_days_max: i32,
8322}
8323
8324#[derive(Debug, Clone, Serialize, Deserialize)]
8326pub struct NearMissConfig {
8327 #[serde(default)]
8329 pub enabled: bool,
8330
8331 #[serde(default = "default_near_miss_proportion")]
8333 pub proportion: f64,
8334
8335 #[serde(default = "default_true_val")]
8337 pub near_duplicate: bool,
8338
8339 #[serde(default)]
8341 pub near_duplicate_days: NearDuplicateDaysConfig,
8342
8343 #[serde(default = "default_true_val")]
8345 pub threshold_proximity: bool,
8346
8347 #[serde(default)]
8349 pub threshold_proximity_range: ThresholdProximityRangeConfig,
8350
8351 #[serde(default = "default_true_val")]
8353 pub unusual_legitimate: bool,
8354
8355 #[serde(default = "default_unusual_legitimate_types")]
8357 pub unusual_legitimate_types: Vec<String>,
8358
8359 #[serde(default = "default_true_val")]
8361 pub corrected_errors: bool,
8362
8363 #[serde(default)]
8365 pub corrected_error_lag: CorrectedErrorLagConfig,
8366}
8367
8368fn default_near_miss_proportion() -> f64 {
8369 0.30
8370}
8371
8372fn default_unusual_legitimate_types() -> Vec<String> {
8373 vec![
8374 "year_end_bonus".to_string(),
8375 "contract_prepayment".to_string(),
8376 "insurance_claim".to_string(),
8377 "settlement_payment".to_string(),
8378 ]
8379}
8380
8381impl Default for NearMissConfig {
8382 fn default() -> Self {
8383 Self {
8384 enabled: false,
8385 proportion: default_near_miss_proportion(),
8386 near_duplicate: true,
8387 near_duplicate_days: NearDuplicateDaysConfig::default(),
8388 threshold_proximity: true,
8389 threshold_proximity_range: ThresholdProximityRangeConfig::default(),
8390 unusual_legitimate: true,
8391 unusual_legitimate_types: default_unusual_legitimate_types(),
8392 corrected_errors: true,
8393 corrected_error_lag: CorrectedErrorLagConfig::default(),
8394 }
8395 }
8396}
8397
8398#[derive(Debug, Clone, Serialize, Deserialize)]
8400pub struct NearDuplicateDaysConfig {
8401 #[serde(default = "default_near_duplicate_min")]
8403 pub min: u32,
8404
8405 #[serde(default = "default_near_duplicate_max")]
8407 pub max: u32,
8408}
8409
8410fn default_near_duplicate_min() -> u32 {
8411 1
8412}
8413fn default_near_duplicate_max() -> u32 {
8414 3
8415}
8416
8417impl Default for NearDuplicateDaysConfig {
8418 fn default() -> Self {
8419 Self {
8420 min: default_near_duplicate_min(),
8421 max: default_near_duplicate_max(),
8422 }
8423 }
8424}
8425
8426#[derive(Debug, Clone, Serialize, Deserialize)]
8428pub struct ThresholdProximityRangeConfig {
8429 #[serde(default = "default_threshold_proximity_min")]
8431 pub min: f64,
8432
8433 #[serde(default = "default_threshold_proximity_max")]
8435 pub max: f64,
8436}
8437
8438fn default_threshold_proximity_min() -> f64 {
8439 0.90
8440}
8441fn default_threshold_proximity_max() -> f64 {
8442 0.99
8443}
8444
8445impl Default for ThresholdProximityRangeConfig {
8446 fn default() -> Self {
8447 Self {
8448 min: default_threshold_proximity_min(),
8449 max: default_threshold_proximity_max(),
8450 }
8451 }
8452}
8453
8454#[derive(Debug, Clone, Serialize, Deserialize)]
8456pub struct CorrectedErrorLagConfig {
8457 #[serde(default = "default_corrected_error_lag_min")]
8459 pub min: u32,
8460
8461 #[serde(default = "default_corrected_error_lag_max")]
8463 pub max: u32,
8464}
8465
8466fn default_corrected_error_lag_min() -> u32 {
8467 1
8468}
8469fn default_corrected_error_lag_max() -> u32 {
8470 5
8471}
8472
8473impl Default for CorrectedErrorLagConfig {
8474 fn default() -> Self {
8475 Self {
8476 min: default_corrected_error_lag_min(),
8477 max: default_corrected_error_lag_max(),
8478 }
8479 }
8480}
8481
8482#[derive(Debug, Clone, Serialize, Deserialize)]
8484pub struct DifficultyClassificationConfig {
8485 #[serde(default)]
8487 pub enabled: bool,
8488
8489 #[serde(default)]
8491 pub target_distribution: DifficultyDistributionConfig,
8492}
8493
8494impl Default for DifficultyClassificationConfig {
8495 fn default() -> Self {
8496 Self {
8497 enabled: true,
8498 target_distribution: DifficultyDistributionConfig::default(),
8499 }
8500 }
8501}
8502
8503#[derive(Debug, Clone, Serialize, Deserialize)]
8505pub struct DifficultyDistributionConfig {
8506 #[serde(default = "default_difficulty_trivial")]
8508 pub trivial: f64,
8509
8510 #[serde(default = "default_difficulty_easy")]
8512 pub easy: f64,
8513
8514 #[serde(default = "default_difficulty_moderate")]
8516 pub moderate: f64,
8517
8518 #[serde(default = "default_difficulty_hard")]
8520 pub hard: f64,
8521
8522 #[serde(default = "default_difficulty_expert")]
8524 pub expert: f64,
8525}
8526
8527fn default_difficulty_trivial() -> f64 {
8528 0.15
8529}
8530fn default_difficulty_easy() -> f64 {
8531 0.25
8532}
8533fn default_difficulty_moderate() -> f64 {
8534 0.30
8535}
8536fn default_difficulty_hard() -> f64 {
8537 0.20
8538}
8539fn default_difficulty_expert() -> f64 {
8540 0.10
8541}
8542
8543impl Default for DifficultyDistributionConfig {
8544 fn default() -> Self {
8545 Self {
8546 trivial: default_difficulty_trivial(),
8547 easy: default_difficulty_easy(),
8548 moderate: default_difficulty_moderate(),
8549 hard: default_difficulty_hard(),
8550 expert: default_difficulty_expert(),
8551 }
8552 }
8553}
8554
8555#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8557pub struct ContextAwareConfig {
8558 #[serde(default)]
8560 pub enabled: bool,
8561
8562 #[serde(default)]
8564 pub vendor_rules: VendorAnomalyRulesConfig,
8565
8566 #[serde(default)]
8568 pub employee_rules: EmployeeAnomalyRulesConfig,
8569
8570 #[serde(default)]
8572 pub account_rules: AccountAnomalyRulesConfig,
8573
8574 #[serde(default)]
8576 pub behavioral_baseline: BehavioralBaselineConfig,
8577}
8578
8579#[derive(Debug, Clone, Serialize, Deserialize)]
8581pub struct VendorAnomalyRulesConfig {
8582 #[serde(default = "default_new_vendor_multiplier")]
8584 pub new_vendor_error_multiplier: f64,
8585
8586 #[serde(default = "default_new_vendor_threshold")]
8588 pub new_vendor_threshold_days: u32,
8589
8590 #[serde(default = "default_international_multiplier")]
8592 pub international_error_multiplier: f64,
8593
8594 #[serde(default = "default_strategic_vendor_types")]
8596 pub strategic_vendor_anomaly_types: Vec<String>,
8597}
8598
8599fn default_new_vendor_multiplier() -> f64 {
8600 2.5
8601}
8602fn default_new_vendor_threshold() -> u32 {
8603 90
8604}
8605fn default_international_multiplier() -> f64 {
8606 1.5
8607}
8608fn default_strategic_vendor_types() -> Vec<String> {
8609 vec![
8610 "pricing_dispute".to_string(),
8611 "contract_violation".to_string(),
8612 ]
8613}
8614
8615impl Default for VendorAnomalyRulesConfig {
8616 fn default() -> Self {
8617 Self {
8618 new_vendor_error_multiplier: default_new_vendor_multiplier(),
8619 new_vendor_threshold_days: default_new_vendor_threshold(),
8620 international_error_multiplier: default_international_multiplier(),
8621 strategic_vendor_anomaly_types: default_strategic_vendor_types(),
8622 }
8623 }
8624}
8625
8626#[derive(Debug, Clone, Serialize, Deserialize)]
8628pub struct EmployeeAnomalyRulesConfig {
8629 #[serde(default = "default_new_employee_rate")]
8631 pub new_employee_error_rate: f64,
8632
8633 #[serde(default = "default_new_employee_threshold")]
8635 pub new_employee_threshold_days: u32,
8636
8637 #[serde(default = "default_volume_fatigue_threshold")]
8639 pub volume_fatigue_threshold: u32,
8640
8641 #[serde(default = "default_coverage_multiplier")]
8643 pub coverage_error_multiplier: f64,
8644}
8645
8646fn default_new_employee_rate() -> f64 {
8647 0.05
8648}
8649fn default_new_employee_threshold() -> u32 {
8650 180
8651}
8652fn default_volume_fatigue_threshold() -> u32 {
8653 50
8654}
8655fn default_coverage_multiplier() -> f64 {
8656 1.8
8657}
8658
8659impl Default for EmployeeAnomalyRulesConfig {
8660 fn default() -> Self {
8661 Self {
8662 new_employee_error_rate: default_new_employee_rate(),
8663 new_employee_threshold_days: default_new_employee_threshold(),
8664 volume_fatigue_threshold: default_volume_fatigue_threshold(),
8665 coverage_error_multiplier: default_coverage_multiplier(),
8666 }
8667 }
8668}
8669
8670#[derive(Debug, Clone, Serialize, Deserialize)]
8672pub struct AccountAnomalyRulesConfig {
8673 #[serde(default = "default_high_risk_multiplier")]
8675 pub high_risk_account_multiplier: f64,
8676
8677 #[serde(default = "default_high_risk_accounts")]
8679 pub high_risk_accounts: Vec<String>,
8680
8681 #[serde(default = "default_suspense_multiplier")]
8683 pub suspense_account_multiplier: f64,
8684
8685 #[serde(default = "default_suspense_accounts")]
8687 pub suspense_accounts: Vec<String>,
8688
8689 #[serde(default = "default_intercompany_multiplier")]
8691 pub intercompany_account_multiplier: f64,
8692}
8693
8694fn default_high_risk_multiplier() -> f64 {
8695 2.0
8696}
8697fn default_high_risk_accounts() -> Vec<String> {
8698 vec![
8699 "1100".to_string(), "2000".to_string(), "3000".to_string(), ]
8703}
8704fn default_suspense_multiplier() -> f64 {
8705 3.0
8706}
8707fn default_suspense_accounts() -> Vec<String> {
8708 vec!["9999".to_string(), "9998".to_string()]
8709}
8710fn default_intercompany_multiplier() -> f64 {
8711 1.5
8712}
8713
8714impl Default for AccountAnomalyRulesConfig {
8715 fn default() -> Self {
8716 Self {
8717 high_risk_account_multiplier: default_high_risk_multiplier(),
8718 high_risk_accounts: default_high_risk_accounts(),
8719 suspense_account_multiplier: default_suspense_multiplier(),
8720 suspense_accounts: default_suspense_accounts(),
8721 intercompany_account_multiplier: default_intercompany_multiplier(),
8722 }
8723 }
8724}
8725
8726#[derive(Debug, Clone, Serialize, Deserialize)]
8728pub struct BehavioralBaselineConfig {
8729 #[serde(default)]
8731 pub enabled: bool,
8732
8733 #[serde(default = "default_baseline_period")]
8735 pub baseline_period_days: u32,
8736
8737 #[serde(default = "default_deviation_threshold")]
8739 pub deviation_threshold_std: f64,
8740
8741 #[serde(default = "default_frequency_deviation")]
8743 pub frequency_deviation_threshold: f64,
8744}
8745
8746fn default_baseline_period() -> u32 {
8747 90
8748}
8749fn default_deviation_threshold() -> f64 {
8750 3.0
8751}
8752fn default_frequency_deviation() -> f64 {
8753 2.0
8754}
8755
8756impl Default for BehavioralBaselineConfig {
8757 fn default() -> Self {
8758 Self {
8759 enabled: false,
8760 baseline_period_days: default_baseline_period(),
8761 deviation_threshold_std: default_deviation_threshold(),
8762 frequency_deviation_threshold: default_frequency_deviation(),
8763 }
8764 }
8765}
8766
8767#[derive(Debug, Clone, Serialize, Deserialize)]
8769pub struct EnhancedLabelingConfig {
8770 #[serde(default = "default_true_val")]
8772 pub severity_scoring: bool,
8773
8774 #[serde(default = "default_true_val")]
8776 pub difficulty_classification: bool,
8777
8778 #[serde(default)]
8780 pub materiality_thresholds: MaterialityThresholdsConfig,
8781}
8782
8783impl Default for EnhancedLabelingConfig {
8784 fn default() -> Self {
8785 Self {
8786 severity_scoring: true,
8787 difficulty_classification: true,
8788 materiality_thresholds: MaterialityThresholdsConfig::default(),
8789 }
8790 }
8791}
8792
8793#[derive(Debug, Clone, Serialize, Deserialize)]
8795pub struct MaterialityThresholdsConfig {
8796 #[serde(default = "default_materiality_trivial")]
8798 pub trivial: f64,
8799
8800 #[serde(default = "default_materiality_immaterial")]
8802 pub immaterial: f64,
8803
8804 #[serde(default = "default_materiality_material")]
8806 pub material: f64,
8807
8808 #[serde(default = "default_materiality_highly_material")]
8810 pub highly_material: f64,
8811}
8812
8813fn default_materiality_trivial() -> f64 {
8814 0.001
8815}
8816fn default_materiality_immaterial() -> f64 {
8817 0.01
8818}
8819fn default_materiality_material() -> f64 {
8820 0.05
8821}
8822fn default_materiality_highly_material() -> f64 {
8823 0.10
8824}
8825
8826impl Default for MaterialityThresholdsConfig {
8827 fn default() -> Self {
8828 Self {
8829 trivial: default_materiality_trivial(),
8830 immaterial: default_materiality_immaterial(),
8831 material: default_materiality_material(),
8832 highly_material: default_materiality_highly_material(),
8833 }
8834 }
8835}
8836
8837#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8849pub struct IndustrySpecificConfig {
8850 #[serde(default)]
8852 pub enabled: bool,
8853
8854 #[serde(default)]
8856 pub manufacturing: ManufacturingConfig,
8857
8858 #[serde(default)]
8860 pub retail: RetailConfig,
8861
8862 #[serde(default)]
8864 pub healthcare: HealthcareConfig,
8865
8866 #[serde(default)]
8868 pub technology: TechnologyConfig,
8869
8870 #[serde(default)]
8872 pub financial_services: FinancialServicesConfig,
8873
8874 #[serde(default)]
8876 pub professional_services: ProfessionalServicesConfig,
8877}
8878
8879#[derive(Debug, Clone, Serialize, Deserialize)]
8881pub struct ManufacturingConfig {
8882 #[serde(default)]
8884 pub enabled: bool,
8885
8886 #[serde(default = "default_bom_depth")]
8888 pub bom_depth: u32,
8889
8890 #[serde(default)]
8892 pub just_in_time: bool,
8893
8894 #[serde(default = "default_production_order_types")]
8896 pub production_order_types: Vec<String>,
8897
8898 #[serde(default)]
8900 pub quality_framework: Option<String>,
8901
8902 #[serde(default = "default_supplier_tiers")]
8904 pub supplier_tiers: u32,
8905
8906 #[serde(default = "default_cost_frequency")]
8908 pub standard_cost_frequency: String,
8909
8910 #[serde(default = "default_yield_rate")]
8912 pub target_yield_rate: f64,
8913
8914 #[serde(default = "default_scrap_threshold")]
8916 pub scrap_alert_threshold: f64,
8917
8918 #[serde(default)]
8920 pub anomaly_rates: ManufacturingAnomalyRates,
8921}
8922
8923fn default_bom_depth() -> u32 {
8924 4
8925}
8926
8927fn default_production_order_types() -> Vec<String> {
8928 vec![
8929 "standard".to_string(),
8930 "rework".to_string(),
8931 "prototype".to_string(),
8932 ]
8933}
8934
8935fn default_supplier_tiers() -> u32 {
8936 2
8937}
8938
8939fn default_cost_frequency() -> String {
8940 "quarterly".to_string()
8941}
8942
8943fn default_yield_rate() -> f64 {
8944 0.97
8945}
8946
8947fn default_scrap_threshold() -> f64 {
8948 0.03
8949}
8950
8951impl Default for ManufacturingConfig {
8952 fn default() -> Self {
8953 Self {
8954 enabled: false,
8955 bom_depth: default_bom_depth(),
8956 just_in_time: false,
8957 production_order_types: default_production_order_types(),
8958 quality_framework: Some("ISO_9001".to_string()),
8959 supplier_tiers: default_supplier_tiers(),
8960 standard_cost_frequency: default_cost_frequency(),
8961 target_yield_rate: default_yield_rate(),
8962 scrap_alert_threshold: default_scrap_threshold(),
8963 anomaly_rates: ManufacturingAnomalyRates::default(),
8964 }
8965 }
8966}
8967
8968#[derive(Debug, Clone, Serialize, Deserialize)]
8970pub struct ManufacturingAnomalyRates {
8971 #[serde(default = "default_mfg_yield_rate")]
8973 pub yield_manipulation: f64,
8974
8975 #[serde(default = "default_mfg_labor_rate")]
8977 pub labor_misallocation: f64,
8978
8979 #[serde(default = "default_mfg_phantom_rate")]
8981 pub phantom_production: f64,
8982
8983 #[serde(default = "default_mfg_cost_rate")]
8985 pub standard_cost_manipulation: f64,
8986
8987 #[serde(default = "default_mfg_inventory_rate")]
8989 pub inventory_fraud: f64,
8990}
8991
8992fn default_mfg_yield_rate() -> f64 {
8993 0.015
8994}
8995
8996fn default_mfg_labor_rate() -> f64 {
8997 0.02
8998}
8999
9000fn default_mfg_phantom_rate() -> f64 {
9001 0.005
9002}
9003
9004fn default_mfg_cost_rate() -> f64 {
9005 0.01
9006}
9007
9008fn default_mfg_inventory_rate() -> f64 {
9009 0.008
9010}
9011
9012impl Default for ManufacturingAnomalyRates {
9013 fn default() -> Self {
9014 Self {
9015 yield_manipulation: default_mfg_yield_rate(),
9016 labor_misallocation: default_mfg_labor_rate(),
9017 phantom_production: default_mfg_phantom_rate(),
9018 standard_cost_manipulation: default_mfg_cost_rate(),
9019 inventory_fraud: default_mfg_inventory_rate(),
9020 }
9021 }
9022}
9023
9024#[derive(Debug, Clone, Serialize, Deserialize)]
9026pub struct RetailConfig {
9027 #[serde(default)]
9029 pub enabled: bool,
9030
9031 #[serde(default)]
9033 pub store_types: RetailStoreTypeConfig,
9034
9035 #[serde(default = "default_retail_daily_txns")]
9037 pub avg_daily_transactions: u32,
9038
9039 #[serde(default = "default_true")]
9041 pub loss_prevention: bool,
9042
9043 #[serde(default = "default_shrinkage_rate")]
9045 pub shrinkage_rate: f64,
9046
9047 #[serde(default)]
9049 pub anomaly_rates: RetailAnomalyRates,
9050}
9051
9052fn default_retail_daily_txns() -> u32 {
9053 500
9054}
9055
9056fn default_shrinkage_rate() -> f64 {
9057 0.015
9058}
9059
9060impl Default for RetailConfig {
9061 fn default() -> Self {
9062 Self {
9063 enabled: false,
9064 store_types: RetailStoreTypeConfig::default(),
9065 avg_daily_transactions: default_retail_daily_txns(),
9066 loss_prevention: true,
9067 shrinkage_rate: default_shrinkage_rate(),
9068 anomaly_rates: RetailAnomalyRates::default(),
9069 }
9070 }
9071}
9072
9073#[derive(Debug, Clone, Serialize, Deserialize)]
9075pub struct RetailStoreTypeConfig {
9076 #[serde(default = "default_flagship_pct")]
9078 pub flagship: f64,
9079
9080 #[serde(default = "default_regional_pct")]
9082 pub regional: f64,
9083
9084 #[serde(default = "default_outlet_pct")]
9086 pub outlet: f64,
9087
9088 #[serde(default = "default_ecommerce_pct")]
9090 pub ecommerce: f64,
9091}
9092
9093fn default_flagship_pct() -> f64 {
9094 0.10
9095}
9096
9097fn default_regional_pct() -> f64 {
9098 0.50
9099}
9100
9101fn default_outlet_pct() -> f64 {
9102 0.25
9103}
9104
9105fn default_ecommerce_pct() -> f64 {
9106 0.15
9107}
9108
9109impl Default for RetailStoreTypeConfig {
9110 fn default() -> Self {
9111 Self {
9112 flagship: default_flagship_pct(),
9113 regional: default_regional_pct(),
9114 outlet: default_outlet_pct(),
9115 ecommerce: default_ecommerce_pct(),
9116 }
9117 }
9118}
9119
9120#[derive(Debug, Clone, Serialize, Deserialize)]
9122pub struct RetailAnomalyRates {
9123 #[serde(default = "default_sweethearting_rate")]
9125 pub sweethearting: f64,
9126
9127 #[serde(default = "default_skimming_rate")]
9129 pub skimming: f64,
9130
9131 #[serde(default = "default_refund_fraud_rate")]
9133 pub refund_fraud: f64,
9134
9135 #[serde(default = "default_void_abuse_rate")]
9137 pub void_abuse: f64,
9138
9139 #[serde(default = "default_gift_card_rate")]
9141 pub gift_card_fraud: f64,
9142
9143 #[serde(default = "default_retail_kickback_rate")]
9145 pub vendor_kickback: f64,
9146}
9147
9148fn default_sweethearting_rate() -> f64 {
9149 0.02
9150}
9151
9152fn default_skimming_rate() -> f64 {
9153 0.005
9154}
9155
9156fn default_refund_fraud_rate() -> f64 {
9157 0.015
9158}
9159
9160fn default_void_abuse_rate() -> f64 {
9161 0.01
9162}
9163
9164fn default_gift_card_rate() -> f64 {
9165 0.008
9166}
9167
9168fn default_retail_kickback_rate() -> f64 {
9169 0.003
9170}
9171
9172impl Default for RetailAnomalyRates {
9173 fn default() -> Self {
9174 Self {
9175 sweethearting: default_sweethearting_rate(),
9176 skimming: default_skimming_rate(),
9177 refund_fraud: default_refund_fraud_rate(),
9178 void_abuse: default_void_abuse_rate(),
9179 gift_card_fraud: default_gift_card_rate(),
9180 vendor_kickback: default_retail_kickback_rate(),
9181 }
9182 }
9183}
9184
9185#[derive(Debug, Clone, Serialize, Deserialize)]
9187pub struct HealthcareConfig {
9188 #[serde(default)]
9190 pub enabled: bool,
9191
9192 #[serde(default = "default_facility_type")]
9194 pub facility_type: String,
9195
9196 #[serde(default)]
9198 pub payer_mix: HealthcarePayerMix,
9199
9200 #[serde(default)]
9202 pub coding_systems: HealthcareCodingSystems,
9203
9204 #[serde(default)]
9206 pub compliance: HealthcareComplianceConfig,
9207
9208 #[serde(default = "default_daily_encounters")]
9210 pub avg_daily_encounters: u32,
9211
9212 #[serde(default = "default_charges_per_encounter")]
9214 pub avg_charges_per_encounter: u32,
9215
9216 #[serde(default = "default_hc_denial_rate")]
9218 pub denial_rate: f64,
9219
9220 #[serde(default = "default_hc_bad_debt_rate")]
9222 pub bad_debt_rate: f64,
9223
9224 #[serde(default = "default_hc_charity_care_rate")]
9226 pub charity_care_rate: f64,
9227
9228 #[serde(default)]
9230 pub anomaly_rates: HealthcareAnomalyRates,
9231}
9232
9233fn default_facility_type() -> String {
9234 "hospital".to_string()
9235}
9236
9237fn default_daily_encounters() -> u32 {
9238 150
9239}
9240
9241fn default_charges_per_encounter() -> u32 {
9242 8
9243}
9244
9245fn default_hc_denial_rate() -> f64 {
9246 0.05
9247}
9248
9249fn default_hc_bad_debt_rate() -> f64 {
9250 0.03
9251}
9252
9253fn default_hc_charity_care_rate() -> f64 {
9254 0.02
9255}
9256
9257impl Default for HealthcareConfig {
9258 fn default() -> Self {
9259 Self {
9260 enabled: false,
9261 facility_type: default_facility_type(),
9262 payer_mix: HealthcarePayerMix::default(),
9263 coding_systems: HealthcareCodingSystems::default(),
9264 compliance: HealthcareComplianceConfig::default(),
9265 avg_daily_encounters: default_daily_encounters(),
9266 avg_charges_per_encounter: default_charges_per_encounter(),
9267 denial_rate: default_hc_denial_rate(),
9268 bad_debt_rate: default_hc_bad_debt_rate(),
9269 charity_care_rate: default_hc_charity_care_rate(),
9270 anomaly_rates: HealthcareAnomalyRates::default(),
9271 }
9272 }
9273}
9274
9275#[derive(Debug, Clone, Serialize, Deserialize)]
9277pub struct HealthcarePayerMix {
9278 #[serde(default = "default_medicare_pct")]
9280 pub medicare: f64,
9281
9282 #[serde(default = "default_medicaid_pct")]
9284 pub medicaid: f64,
9285
9286 #[serde(default = "default_commercial_pct")]
9288 pub commercial: f64,
9289
9290 #[serde(default = "default_self_pay_pct")]
9292 pub self_pay: f64,
9293}
9294
9295fn default_medicare_pct() -> f64 {
9296 0.40
9297}
9298
9299fn default_medicaid_pct() -> f64 {
9300 0.20
9301}
9302
9303fn default_commercial_pct() -> f64 {
9304 0.30
9305}
9306
9307fn default_self_pay_pct() -> f64 {
9308 0.10
9309}
9310
9311impl Default for HealthcarePayerMix {
9312 fn default() -> Self {
9313 Self {
9314 medicare: default_medicare_pct(),
9315 medicaid: default_medicaid_pct(),
9316 commercial: default_commercial_pct(),
9317 self_pay: default_self_pay_pct(),
9318 }
9319 }
9320}
9321
9322#[derive(Debug, Clone, Serialize, Deserialize)]
9324pub struct HealthcareCodingSystems {
9325 #[serde(default = "default_true")]
9327 pub icd10: bool,
9328
9329 #[serde(default = "default_true")]
9331 pub cpt: bool,
9332
9333 #[serde(default = "default_true")]
9335 pub drg: bool,
9336
9337 #[serde(default = "default_true")]
9339 pub hcpcs: bool,
9340
9341 #[serde(default = "default_true")]
9343 pub revenue_codes: bool,
9344}
9345
9346impl Default for HealthcareCodingSystems {
9347 fn default() -> Self {
9348 Self {
9349 icd10: true,
9350 cpt: true,
9351 drg: true,
9352 hcpcs: true,
9353 revenue_codes: true,
9354 }
9355 }
9356}
9357
9358#[derive(Debug, Clone, Serialize, Deserialize)]
9360pub struct HealthcareComplianceConfig {
9361 #[serde(default = "default_true")]
9363 pub hipaa: bool,
9364
9365 #[serde(default = "default_true")]
9367 pub stark_law: bool,
9368
9369 #[serde(default = "default_true")]
9371 pub anti_kickback: bool,
9372
9373 #[serde(default = "default_true")]
9375 pub false_claims_act: bool,
9376
9377 #[serde(default = "default_true")]
9379 pub emtala: bool,
9380}
9381
9382impl Default for HealthcareComplianceConfig {
9383 fn default() -> Self {
9384 Self {
9385 hipaa: true,
9386 stark_law: true,
9387 anti_kickback: true,
9388 false_claims_act: true,
9389 emtala: true,
9390 }
9391 }
9392}
9393
9394#[derive(Debug, Clone, Serialize, Deserialize)]
9396pub struct HealthcareAnomalyRates {
9397 #[serde(default = "default_upcoding_rate")]
9399 pub upcoding: f64,
9400
9401 #[serde(default = "default_unbundling_rate")]
9403 pub unbundling: f64,
9404
9405 #[serde(default = "default_phantom_billing_rate")]
9407 pub phantom_billing: f64,
9408
9409 #[serde(default = "default_healthcare_kickback_rate")]
9411 pub kickbacks: f64,
9412
9413 #[serde(default = "default_duplicate_billing_rate")]
9415 pub duplicate_billing: f64,
9416
9417 #[serde(default = "default_med_necessity_rate")]
9419 pub medical_necessity_abuse: f64,
9420}
9421
9422fn default_upcoding_rate() -> f64 {
9423 0.02
9424}
9425
9426fn default_unbundling_rate() -> f64 {
9427 0.015
9428}
9429
9430fn default_phantom_billing_rate() -> f64 {
9431 0.005
9432}
9433
9434fn default_healthcare_kickback_rate() -> f64 {
9435 0.003
9436}
9437
9438fn default_duplicate_billing_rate() -> f64 {
9439 0.008
9440}
9441
9442fn default_med_necessity_rate() -> f64 {
9443 0.01
9444}
9445
9446impl Default for HealthcareAnomalyRates {
9447 fn default() -> Self {
9448 Self {
9449 upcoding: default_upcoding_rate(),
9450 unbundling: default_unbundling_rate(),
9451 phantom_billing: default_phantom_billing_rate(),
9452 kickbacks: default_healthcare_kickback_rate(),
9453 duplicate_billing: default_duplicate_billing_rate(),
9454 medical_necessity_abuse: default_med_necessity_rate(),
9455 }
9456 }
9457}
9458
9459#[derive(Debug, Clone, Serialize, Deserialize)]
9461pub struct TechnologyConfig {
9462 #[serde(default)]
9464 pub enabled: bool,
9465
9466 #[serde(default = "default_revenue_model")]
9468 pub revenue_model: String,
9469
9470 #[serde(default = "default_subscription_pct")]
9472 pub subscription_revenue_pct: f64,
9473
9474 #[serde(default = "default_license_pct")]
9476 pub license_revenue_pct: f64,
9477
9478 #[serde(default = "default_services_pct")]
9480 pub services_revenue_pct: f64,
9481
9482 #[serde(default)]
9484 pub rd_capitalization: RdCapitalizationConfig,
9485
9486 #[serde(default)]
9488 pub anomaly_rates: TechnologyAnomalyRates,
9489}
9490
9491fn default_revenue_model() -> String {
9492 "saas".to_string()
9493}
9494
9495fn default_subscription_pct() -> f64 {
9496 0.60
9497}
9498
9499fn default_license_pct() -> f64 {
9500 0.25
9501}
9502
9503fn default_services_pct() -> f64 {
9504 0.15
9505}
9506
9507impl Default for TechnologyConfig {
9508 fn default() -> Self {
9509 Self {
9510 enabled: false,
9511 revenue_model: default_revenue_model(),
9512 subscription_revenue_pct: default_subscription_pct(),
9513 license_revenue_pct: default_license_pct(),
9514 services_revenue_pct: default_services_pct(),
9515 rd_capitalization: RdCapitalizationConfig::default(),
9516 anomaly_rates: TechnologyAnomalyRates::default(),
9517 }
9518 }
9519}
9520
9521#[derive(Debug, Clone, Serialize, Deserialize)]
9523pub struct RdCapitalizationConfig {
9524 #[serde(default = "default_true")]
9526 pub enabled: bool,
9527
9528 #[serde(default = "default_cap_rate")]
9530 pub capitalization_rate: f64,
9531
9532 #[serde(default = "default_useful_life")]
9534 pub useful_life_years: u32,
9535}
9536
9537fn default_cap_rate() -> f64 {
9538 0.30
9539}
9540
9541fn default_useful_life() -> u32 {
9542 3
9543}
9544
9545impl Default for RdCapitalizationConfig {
9546 fn default() -> Self {
9547 Self {
9548 enabled: true,
9549 capitalization_rate: default_cap_rate(),
9550 useful_life_years: default_useful_life(),
9551 }
9552 }
9553}
9554
9555#[derive(Debug, Clone, Serialize, Deserialize)]
9557pub struct TechnologyAnomalyRates {
9558 #[serde(default = "default_premature_rev_rate")]
9560 pub premature_revenue: f64,
9561
9562 #[serde(default = "default_side_letter_rate")]
9564 pub side_letter_abuse: f64,
9565
9566 #[serde(default = "default_channel_stuffing_rate")]
9568 pub channel_stuffing: f64,
9569
9570 #[serde(default = "default_improper_cap_rate")]
9572 pub improper_capitalization: f64,
9573}
9574
9575fn default_premature_rev_rate() -> f64 {
9576 0.015
9577}
9578
9579fn default_side_letter_rate() -> f64 {
9580 0.008
9581}
9582
9583fn default_channel_stuffing_rate() -> f64 {
9584 0.01
9585}
9586
9587fn default_improper_cap_rate() -> f64 {
9588 0.012
9589}
9590
9591impl Default for TechnologyAnomalyRates {
9592 fn default() -> Self {
9593 Self {
9594 premature_revenue: default_premature_rev_rate(),
9595 side_letter_abuse: default_side_letter_rate(),
9596 channel_stuffing: default_channel_stuffing_rate(),
9597 improper_capitalization: default_improper_cap_rate(),
9598 }
9599 }
9600}
9601
9602#[derive(Debug, Clone, Serialize, Deserialize)]
9604pub struct FinancialServicesConfig {
9605 #[serde(default)]
9607 pub enabled: bool,
9608
9609 #[serde(default = "default_fi_type")]
9611 pub institution_type: String,
9612
9613 #[serde(default = "default_fi_regulatory")]
9615 pub regulatory_framework: String,
9616
9617 #[serde(default)]
9619 pub anomaly_rates: FinancialServicesAnomalyRates,
9620}
9621
9622fn default_fi_type() -> String {
9623 "commercial_bank".to_string()
9624}
9625
9626fn default_fi_regulatory() -> String {
9627 "us_banking".to_string()
9628}
9629
9630impl Default for FinancialServicesConfig {
9631 fn default() -> Self {
9632 Self {
9633 enabled: false,
9634 institution_type: default_fi_type(),
9635 regulatory_framework: default_fi_regulatory(),
9636 anomaly_rates: FinancialServicesAnomalyRates::default(),
9637 }
9638 }
9639}
9640
9641#[derive(Debug, Clone, Serialize, Deserialize)]
9643pub struct FinancialServicesAnomalyRates {
9644 #[serde(default = "default_loan_fraud_rate")]
9646 pub loan_fraud: f64,
9647
9648 #[serde(default = "default_trading_fraud_rate")]
9650 pub trading_fraud: f64,
9651
9652 #[serde(default = "default_insurance_fraud_rate")]
9654 pub insurance_fraud: f64,
9655
9656 #[serde(default = "default_account_manip_rate")]
9658 pub account_manipulation: f64,
9659}
9660
9661fn default_loan_fraud_rate() -> f64 {
9662 0.01
9663}
9664
9665fn default_trading_fraud_rate() -> f64 {
9666 0.008
9667}
9668
9669fn default_insurance_fraud_rate() -> f64 {
9670 0.012
9671}
9672
9673fn default_account_manip_rate() -> f64 {
9674 0.005
9675}
9676
9677impl Default for FinancialServicesAnomalyRates {
9678 fn default() -> Self {
9679 Self {
9680 loan_fraud: default_loan_fraud_rate(),
9681 trading_fraud: default_trading_fraud_rate(),
9682 insurance_fraud: default_insurance_fraud_rate(),
9683 account_manipulation: default_account_manip_rate(),
9684 }
9685 }
9686}
9687
9688#[derive(Debug, Clone, Serialize, Deserialize)]
9690pub struct ProfessionalServicesConfig {
9691 #[serde(default)]
9693 pub enabled: bool,
9694
9695 #[serde(default = "default_firm_type")]
9697 pub firm_type: String,
9698
9699 #[serde(default = "default_billing_model")]
9701 pub billing_model: String,
9702
9703 #[serde(default = "default_hourly_rate")]
9705 pub avg_hourly_rate: f64,
9706
9707 #[serde(default)]
9709 pub trust_accounting: TrustAccountingConfig,
9710
9711 #[serde(default)]
9713 pub anomaly_rates: ProfessionalServicesAnomalyRates,
9714}
9715
9716fn default_firm_type() -> String {
9717 "consulting".to_string()
9718}
9719
9720fn default_billing_model() -> String {
9721 "time_and_materials".to_string()
9722}
9723
9724fn default_hourly_rate() -> f64 {
9725 250.0
9726}
9727
9728impl Default for ProfessionalServicesConfig {
9729 fn default() -> Self {
9730 Self {
9731 enabled: false,
9732 firm_type: default_firm_type(),
9733 billing_model: default_billing_model(),
9734 avg_hourly_rate: default_hourly_rate(),
9735 trust_accounting: TrustAccountingConfig::default(),
9736 anomaly_rates: ProfessionalServicesAnomalyRates::default(),
9737 }
9738 }
9739}
9740
9741#[derive(Debug, Clone, Serialize, Deserialize)]
9743pub struct TrustAccountingConfig {
9744 #[serde(default)]
9746 pub enabled: bool,
9747
9748 #[serde(default = "default_true")]
9750 pub require_three_way_reconciliation: bool,
9751}
9752
9753impl Default for TrustAccountingConfig {
9754 fn default() -> Self {
9755 Self {
9756 enabled: false,
9757 require_three_way_reconciliation: true,
9758 }
9759 }
9760}
9761
9762#[derive(Debug, Clone, Serialize, Deserialize)]
9764pub struct ProfessionalServicesAnomalyRates {
9765 #[serde(default = "default_time_fraud_rate")]
9767 pub time_billing_fraud: f64,
9768
9769 #[serde(default = "default_expense_fraud_rate")]
9771 pub expense_fraud: f64,
9772
9773 #[serde(default = "default_trust_misappropriation_rate")]
9775 pub trust_misappropriation: f64,
9776}
9777
9778fn default_time_fraud_rate() -> f64 {
9779 0.02
9780}
9781
9782fn default_expense_fraud_rate() -> f64 {
9783 0.015
9784}
9785
9786fn default_trust_misappropriation_rate() -> f64 {
9787 0.003
9788}
9789
9790impl Default for ProfessionalServicesAnomalyRates {
9791 fn default() -> Self {
9792 Self {
9793 time_billing_fraud: default_time_fraud_rate(),
9794 expense_fraud: default_expense_fraud_rate(),
9795 trust_misappropriation: default_trust_misappropriation_rate(),
9796 }
9797 }
9798}
9799
9800#[derive(Debug, Clone, Serialize, Deserialize)]
9814pub struct FingerprintPrivacyConfig {
9815 #[serde(default)]
9817 pub level: String,
9818 #[serde(default = "default_epsilon")]
9820 pub epsilon: f64,
9821 #[serde(default = "default_delta")]
9823 pub delta: f64,
9824 #[serde(default = "default_k_anonymity")]
9826 pub k_anonymity: u32,
9827 #[serde(default)]
9829 pub composition_method: String,
9830}
9831
9832fn default_epsilon() -> f64 {
9833 1.0
9834}
9835
9836fn default_delta() -> f64 {
9837 1e-5
9838}
9839
9840fn default_k_anonymity() -> u32 {
9841 5
9842}
9843
9844impl Default for FingerprintPrivacyConfig {
9845 fn default() -> Self {
9846 Self {
9847 level: "standard".to_string(),
9848 epsilon: default_epsilon(),
9849 delta: default_delta(),
9850 k_anonymity: default_k_anonymity(),
9851 composition_method: "naive".to_string(),
9852 }
9853 }
9854}
9855
9856#[derive(Debug, Clone, Serialize, Deserialize)]
9870pub struct QualityGatesSchemaConfig {
9871 #[serde(default)]
9873 pub enabled: bool,
9874 #[serde(default = "default_gate_profile_name")]
9876 pub profile: String,
9877 #[serde(default)]
9879 pub fail_on_violation: bool,
9880 #[serde(default)]
9882 pub custom_gates: Vec<QualityGateEntry>,
9883}
9884
9885fn default_gate_profile_name() -> String {
9886 "default".to_string()
9887}
9888
9889impl Default for QualityGatesSchemaConfig {
9890 fn default() -> Self {
9891 Self {
9892 enabled: false,
9893 profile: default_gate_profile_name(),
9894 fail_on_violation: false,
9895 custom_gates: Vec::new(),
9896 }
9897 }
9898}
9899
9900#[derive(Debug, Clone, Serialize, Deserialize)]
9902pub struct QualityGateEntry {
9903 pub name: String,
9905 pub metric: String,
9909 pub threshold: f64,
9911 #[serde(default)]
9913 pub upper_threshold: Option<f64>,
9914 #[serde(default = "default_gate_comparison")]
9916 pub comparison: String,
9917}
9918
9919fn default_gate_comparison() -> String {
9920 "gte".to_string()
9921}
9922
9923#[derive(Debug, Clone, Default, Serialize, Deserialize)]
9933pub struct ComplianceSchemaConfig {
9934 #[serde(default)]
9936 pub content_marking: ContentMarkingSchemaConfig,
9937 #[serde(default)]
9939 pub article10_report: bool,
9940 #[serde(default)]
9942 pub certificates: CertificateSchemaConfig,
9943}
9944
9945#[derive(Debug, Clone, Default, Serialize, Deserialize)]
9947pub struct CertificateSchemaConfig {
9948 #[serde(default)]
9950 pub enabled: bool,
9951 #[serde(default)]
9953 pub signing_key_env: Option<String>,
9954 #[serde(default)]
9956 pub include_quality_metrics: bool,
9957}
9958
9959#[derive(Debug, Clone, Serialize, Deserialize)]
9961pub struct ContentMarkingSchemaConfig {
9962 #[serde(default = "default_true")]
9964 pub enabled: bool,
9965 #[serde(default = "default_marking_format")]
9967 pub format: String,
9968}
9969
9970fn default_marking_format() -> String {
9971 "embedded".to_string()
9972}
9973
9974impl Default for ContentMarkingSchemaConfig {
9975 fn default() -> Self {
9976 Self {
9977 enabled: true,
9978 format: default_marking_format(),
9979 }
9980 }
9981}
9982
9983#[derive(Debug, Clone, Default, Serialize, Deserialize)]
9985pub struct WebhookSchemaConfig {
9986 #[serde(default)]
9988 pub enabled: bool,
9989 #[serde(default)]
9991 pub endpoints: Vec<WebhookEndpointConfig>,
9992}
9993
9994#[derive(Debug, Clone, Serialize, Deserialize)]
9996pub struct WebhookEndpointConfig {
9997 pub url: String,
9999 #[serde(default)]
10001 pub events: Vec<String>,
10002 #[serde(default)]
10004 pub secret: Option<String>,
10005 #[serde(default = "default_webhook_retries")]
10007 pub max_retries: u32,
10008 #[serde(default = "default_webhook_timeout")]
10010 pub timeout_secs: u64,
10011}
10012
10013fn default_webhook_retries() -> u32 {
10014 3
10015}
10016fn default_webhook_timeout() -> u64 {
10017 10
10018}
10019
10020#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10026pub struct SourceToPayConfig {
10027 #[serde(default)]
10029 pub enabled: bool,
10030 #[serde(default)]
10032 pub spend_analysis: SpendAnalysisConfig,
10033 #[serde(default)]
10035 pub sourcing: SourcingConfig,
10036 #[serde(default)]
10038 pub qualification: QualificationConfig,
10039 #[serde(default)]
10041 pub rfx: RfxConfig,
10042 #[serde(default)]
10044 pub contracts: ContractConfig,
10045 #[serde(default)]
10047 pub catalog: CatalogConfig,
10048 #[serde(default)]
10050 pub scorecards: ScorecardConfig,
10051 #[serde(default)]
10053 pub p2p_integration: P2PIntegrationConfig,
10054}
10055
10056#[derive(Debug, Clone, Serialize, Deserialize)]
10058pub struct SpendAnalysisConfig {
10059 #[serde(default = "default_hhi_threshold")]
10061 pub hhi_threshold: f64,
10062 #[serde(default = "default_contract_coverage_target")]
10064 pub contract_coverage_target: f64,
10065}
10066
10067impl Default for SpendAnalysisConfig {
10068 fn default() -> Self {
10069 Self {
10070 hhi_threshold: default_hhi_threshold(),
10071 contract_coverage_target: default_contract_coverage_target(),
10072 }
10073 }
10074}
10075
10076fn default_hhi_threshold() -> f64 {
10077 2500.0
10078}
10079fn default_contract_coverage_target() -> f64 {
10080 0.80
10081}
10082
10083#[derive(Debug, Clone, Serialize, Deserialize)]
10085pub struct SourcingConfig {
10086 #[serde(default = "default_sourcing_projects_per_year")]
10088 pub projects_per_year: u32,
10089 #[serde(default = "default_renewal_horizon_months")]
10091 pub renewal_horizon_months: u32,
10092 #[serde(default = "default_project_duration_months")]
10094 pub project_duration_months: u32,
10095}
10096
10097impl Default for SourcingConfig {
10098 fn default() -> Self {
10099 Self {
10100 projects_per_year: default_sourcing_projects_per_year(),
10101 renewal_horizon_months: default_renewal_horizon_months(),
10102 project_duration_months: default_project_duration_months(),
10103 }
10104 }
10105}
10106
10107fn default_sourcing_projects_per_year() -> u32 {
10108 10
10109}
10110fn default_renewal_horizon_months() -> u32 {
10111 3
10112}
10113fn default_project_duration_months() -> u32 {
10114 4
10115}
10116
10117#[derive(Debug, Clone, Serialize, Deserialize)]
10119pub struct QualificationConfig {
10120 #[serde(default = "default_qualification_pass_rate")]
10122 pub pass_rate: f64,
10123 #[serde(default = "default_qualification_validity_days")]
10125 pub validity_days: u32,
10126 #[serde(default = "default_financial_weight")]
10128 pub financial_weight: f64,
10129 #[serde(default = "default_quality_weight")]
10131 pub quality_weight: f64,
10132 #[serde(default = "default_delivery_weight")]
10134 pub delivery_weight: f64,
10135 #[serde(default = "default_compliance_weight")]
10137 pub compliance_weight: f64,
10138}
10139
10140impl Default for QualificationConfig {
10141 fn default() -> Self {
10142 Self {
10143 pass_rate: default_qualification_pass_rate(),
10144 validity_days: default_qualification_validity_days(),
10145 financial_weight: default_financial_weight(),
10146 quality_weight: default_quality_weight(),
10147 delivery_weight: default_delivery_weight(),
10148 compliance_weight: default_compliance_weight(),
10149 }
10150 }
10151}
10152
10153fn default_qualification_pass_rate() -> f64 {
10154 0.75
10155}
10156fn default_qualification_validity_days() -> u32 {
10157 365
10158}
10159fn default_financial_weight() -> f64 {
10160 0.25
10161}
10162fn default_quality_weight() -> f64 {
10163 0.30
10164}
10165fn default_delivery_weight() -> f64 {
10166 0.25
10167}
10168fn default_compliance_weight() -> f64 {
10169 0.20
10170}
10171
10172#[derive(Debug, Clone, Serialize, Deserialize)]
10174pub struct RfxConfig {
10175 #[serde(default = "default_rfi_threshold")]
10177 pub rfi_threshold: f64,
10178 #[serde(default = "default_min_invited_vendors")]
10180 pub min_invited_vendors: u32,
10181 #[serde(default = "default_max_invited_vendors")]
10183 pub max_invited_vendors: u32,
10184 #[serde(default = "default_response_rate")]
10186 pub response_rate: f64,
10187 #[serde(default = "default_price_weight")]
10189 pub default_price_weight: f64,
10190 #[serde(default = "default_rfx_quality_weight")]
10192 pub default_quality_weight: f64,
10193 #[serde(default = "default_rfx_delivery_weight")]
10195 pub default_delivery_weight: f64,
10196}
10197
10198impl Default for RfxConfig {
10199 fn default() -> Self {
10200 Self {
10201 rfi_threshold: default_rfi_threshold(),
10202 min_invited_vendors: default_min_invited_vendors(),
10203 max_invited_vendors: default_max_invited_vendors(),
10204 response_rate: default_response_rate(),
10205 default_price_weight: default_price_weight(),
10206 default_quality_weight: default_rfx_quality_weight(),
10207 default_delivery_weight: default_rfx_delivery_weight(),
10208 }
10209 }
10210}
10211
10212fn default_rfi_threshold() -> f64 {
10213 100_000.0
10214}
10215fn default_min_invited_vendors() -> u32 {
10216 3
10217}
10218fn default_max_invited_vendors() -> u32 {
10219 8
10220}
10221fn default_response_rate() -> f64 {
10222 0.70
10223}
10224fn default_price_weight() -> f64 {
10225 0.40
10226}
10227fn default_rfx_quality_weight() -> f64 {
10228 0.35
10229}
10230fn default_rfx_delivery_weight() -> f64 {
10231 0.25
10232}
10233
10234#[derive(Debug, Clone, Serialize, Deserialize)]
10236pub struct ContractConfig {
10237 #[serde(default = "default_min_contract_months")]
10239 pub min_duration_months: u32,
10240 #[serde(default = "default_max_contract_months")]
10242 pub max_duration_months: u32,
10243 #[serde(default = "default_auto_renewal_rate")]
10245 pub auto_renewal_rate: f64,
10246 #[serde(default = "default_amendment_rate")]
10248 pub amendment_rate: f64,
10249 #[serde(default)]
10251 pub type_distribution: ContractTypeDistribution,
10252}
10253
10254impl Default for ContractConfig {
10255 fn default() -> Self {
10256 Self {
10257 min_duration_months: default_min_contract_months(),
10258 max_duration_months: default_max_contract_months(),
10259 auto_renewal_rate: default_auto_renewal_rate(),
10260 amendment_rate: default_amendment_rate(),
10261 type_distribution: ContractTypeDistribution::default(),
10262 }
10263 }
10264}
10265
10266fn default_min_contract_months() -> u32 {
10267 12
10268}
10269fn default_max_contract_months() -> u32 {
10270 36
10271}
10272fn default_auto_renewal_rate() -> f64 {
10273 0.40
10274}
10275fn default_amendment_rate() -> f64 {
10276 0.20
10277}
10278
10279#[derive(Debug, Clone, Serialize, Deserialize)]
10281pub struct ContractTypeDistribution {
10282 #[serde(default = "default_fixed_price_pct")]
10284 pub fixed_price: f64,
10285 #[serde(default = "default_blanket_pct")]
10287 pub blanket: f64,
10288 #[serde(default = "default_time_materials_pct")]
10290 pub time_and_materials: f64,
10291 #[serde(default = "default_service_agreement_pct")]
10293 pub service_agreement: f64,
10294}
10295
10296impl Default for ContractTypeDistribution {
10297 fn default() -> Self {
10298 Self {
10299 fixed_price: default_fixed_price_pct(),
10300 blanket: default_blanket_pct(),
10301 time_and_materials: default_time_materials_pct(),
10302 service_agreement: default_service_agreement_pct(),
10303 }
10304 }
10305}
10306
10307fn default_fixed_price_pct() -> f64 {
10308 0.40
10309}
10310fn default_blanket_pct() -> f64 {
10311 0.30
10312}
10313fn default_time_materials_pct() -> f64 {
10314 0.15
10315}
10316fn default_service_agreement_pct() -> f64 {
10317 0.15
10318}
10319
10320#[derive(Debug, Clone, Serialize, Deserialize)]
10322pub struct CatalogConfig {
10323 #[serde(default = "default_preferred_vendor_flag_rate")]
10325 pub preferred_vendor_flag_rate: f64,
10326 #[serde(default = "default_multi_source_rate")]
10328 pub multi_source_rate: f64,
10329}
10330
10331impl Default for CatalogConfig {
10332 fn default() -> Self {
10333 Self {
10334 preferred_vendor_flag_rate: default_preferred_vendor_flag_rate(),
10335 multi_source_rate: default_multi_source_rate(),
10336 }
10337 }
10338}
10339
10340fn default_preferred_vendor_flag_rate() -> f64 {
10341 0.70
10342}
10343fn default_multi_source_rate() -> f64 {
10344 0.25
10345}
10346
10347#[derive(Debug, Clone, Serialize, Deserialize)]
10349pub struct ScorecardConfig {
10350 #[serde(default = "default_scorecard_frequency")]
10352 pub frequency: String,
10353 #[serde(default = "default_otd_weight")]
10355 pub on_time_delivery_weight: f64,
10356 #[serde(default = "default_quality_score_weight")]
10358 pub quality_weight: f64,
10359 #[serde(default = "default_price_score_weight")]
10361 pub price_weight: f64,
10362 #[serde(default = "default_responsiveness_weight")]
10364 pub responsiveness_weight: f64,
10365 #[serde(default = "default_grade_a_threshold")]
10367 pub grade_a_threshold: f64,
10368 #[serde(default = "default_grade_b_threshold")]
10370 pub grade_b_threshold: f64,
10371 #[serde(default = "default_grade_c_threshold")]
10373 pub grade_c_threshold: f64,
10374}
10375
10376impl Default for ScorecardConfig {
10377 fn default() -> Self {
10378 Self {
10379 frequency: default_scorecard_frequency(),
10380 on_time_delivery_weight: default_otd_weight(),
10381 quality_weight: default_quality_score_weight(),
10382 price_weight: default_price_score_weight(),
10383 responsiveness_weight: default_responsiveness_weight(),
10384 grade_a_threshold: default_grade_a_threshold(),
10385 grade_b_threshold: default_grade_b_threshold(),
10386 grade_c_threshold: default_grade_c_threshold(),
10387 }
10388 }
10389}
10390
10391fn default_scorecard_frequency() -> String {
10392 "quarterly".to_string()
10393}
10394fn default_otd_weight() -> f64 {
10395 0.30
10396}
10397fn default_quality_score_weight() -> f64 {
10398 0.30
10399}
10400fn default_price_score_weight() -> f64 {
10401 0.25
10402}
10403fn default_responsiveness_weight() -> f64 {
10404 0.15
10405}
10406fn default_grade_a_threshold() -> f64 {
10407 90.0
10408}
10409fn default_grade_b_threshold() -> f64 {
10410 75.0
10411}
10412fn default_grade_c_threshold() -> f64 {
10413 60.0
10414}
10415
10416#[derive(Debug, Clone, Serialize, Deserialize)]
10418pub struct P2PIntegrationConfig {
10419 #[serde(default = "default_off_contract_rate")]
10421 pub off_contract_rate: f64,
10422 #[serde(default = "default_price_tolerance")]
10424 pub price_tolerance: f64,
10425 #[serde(default)]
10427 pub catalog_enforcement: bool,
10428}
10429
10430impl Default for P2PIntegrationConfig {
10431 fn default() -> Self {
10432 Self {
10433 off_contract_rate: default_off_contract_rate(),
10434 price_tolerance: default_price_tolerance(),
10435 catalog_enforcement: false,
10436 }
10437 }
10438}
10439
10440fn default_off_contract_rate() -> f64 {
10441 0.15
10442}
10443fn default_price_tolerance() -> f64 {
10444 0.02
10445}
10446
10447#[derive(Debug, Clone, Serialize, Deserialize)]
10451pub struct FinancialReportingConfig {
10452 #[serde(default)]
10454 pub enabled: bool,
10455 #[serde(default = "default_true")]
10457 pub generate_balance_sheet: bool,
10458 #[serde(default = "default_true")]
10460 pub generate_income_statement: bool,
10461 #[serde(default = "default_true")]
10463 pub generate_cash_flow: bool,
10464 #[serde(default = "default_true")]
10466 pub generate_changes_in_equity: bool,
10467 #[serde(default = "default_comparative_periods")]
10469 pub comparative_periods: u32,
10470 #[serde(default)]
10472 pub management_kpis: ManagementKpisConfig,
10473 #[serde(default)]
10475 pub budgets: BudgetConfig,
10476}
10477
10478impl Default for FinancialReportingConfig {
10479 fn default() -> Self {
10480 Self {
10481 enabled: false,
10482 generate_balance_sheet: true,
10483 generate_income_statement: true,
10484 generate_cash_flow: true,
10485 generate_changes_in_equity: true,
10486 comparative_periods: default_comparative_periods(),
10487 management_kpis: ManagementKpisConfig::default(),
10488 budgets: BudgetConfig::default(),
10489 }
10490 }
10491}
10492
10493fn default_comparative_periods() -> u32 {
10494 1
10495}
10496
10497#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10499pub struct ManagementKpisConfig {
10500 #[serde(default)]
10502 pub enabled: bool,
10503 #[serde(default = "default_kpi_frequency")]
10505 pub frequency: String,
10506}
10507
10508fn default_kpi_frequency() -> String {
10509 "monthly".to_string()
10510}
10511
10512#[derive(Debug, Clone, Serialize, Deserialize)]
10514pub struct BudgetConfig {
10515 #[serde(default)]
10517 pub enabled: bool,
10518 #[serde(default = "default_revenue_growth_rate")]
10520 pub revenue_growth_rate: f64,
10521 #[serde(default = "default_expense_inflation_rate")]
10523 pub expense_inflation_rate: f64,
10524 #[serde(default = "default_variance_noise")]
10526 pub variance_noise: f64,
10527}
10528
10529impl Default for BudgetConfig {
10530 fn default() -> Self {
10531 Self {
10532 enabled: false,
10533 revenue_growth_rate: default_revenue_growth_rate(),
10534 expense_inflation_rate: default_expense_inflation_rate(),
10535 variance_noise: default_variance_noise(),
10536 }
10537 }
10538}
10539
10540fn default_revenue_growth_rate() -> f64 {
10541 0.05
10542}
10543fn default_expense_inflation_rate() -> f64 {
10544 0.03
10545}
10546fn default_variance_noise() -> f64 {
10547 0.10
10548}
10549
10550#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10554pub struct HrConfig {
10555 #[serde(default)]
10557 pub enabled: bool,
10558 #[serde(default)]
10560 pub payroll: PayrollConfig,
10561 #[serde(default)]
10563 pub time_attendance: TimeAttendanceConfig,
10564 #[serde(default)]
10566 pub expenses: ExpenseConfig,
10567}
10568
10569#[derive(Debug, Clone, Serialize, Deserialize)]
10571pub struct PayrollConfig {
10572 #[serde(default = "default_true")]
10574 pub enabled: bool,
10575 #[serde(default = "default_pay_frequency")]
10577 pub pay_frequency: String,
10578 #[serde(default)]
10580 pub salary_ranges: PayrollSalaryRanges,
10581 #[serde(default)]
10583 pub tax_rates: PayrollTaxRates,
10584 #[serde(default = "default_benefits_enrollment_rate")]
10586 pub benefits_enrollment_rate: f64,
10587 #[serde(default = "default_retirement_participation_rate")]
10589 pub retirement_participation_rate: f64,
10590}
10591
10592impl Default for PayrollConfig {
10593 fn default() -> Self {
10594 Self {
10595 enabled: true,
10596 pay_frequency: default_pay_frequency(),
10597 salary_ranges: PayrollSalaryRanges::default(),
10598 tax_rates: PayrollTaxRates::default(),
10599 benefits_enrollment_rate: default_benefits_enrollment_rate(),
10600 retirement_participation_rate: default_retirement_participation_rate(),
10601 }
10602 }
10603}
10604
10605fn default_pay_frequency() -> String {
10606 "monthly".to_string()
10607}
10608fn default_benefits_enrollment_rate() -> f64 {
10609 0.60
10610}
10611fn default_retirement_participation_rate() -> f64 {
10612 0.45
10613}
10614
10615#[derive(Debug, Clone, Serialize, Deserialize)]
10617pub struct PayrollSalaryRanges {
10618 #[serde(default = "default_staff_min")]
10620 pub staff_min: f64,
10621 #[serde(default = "default_staff_max")]
10622 pub staff_max: f64,
10623 #[serde(default = "default_manager_min")]
10625 pub manager_min: f64,
10626 #[serde(default = "default_manager_max")]
10627 pub manager_max: f64,
10628 #[serde(default = "default_director_min")]
10630 pub director_min: f64,
10631 #[serde(default = "default_director_max")]
10632 pub director_max: f64,
10633 #[serde(default = "default_executive_min")]
10635 pub executive_min: f64,
10636 #[serde(default = "default_executive_max")]
10637 pub executive_max: f64,
10638}
10639
10640impl Default for PayrollSalaryRanges {
10641 fn default() -> Self {
10642 Self {
10643 staff_min: default_staff_min(),
10644 staff_max: default_staff_max(),
10645 manager_min: default_manager_min(),
10646 manager_max: default_manager_max(),
10647 director_min: default_director_min(),
10648 director_max: default_director_max(),
10649 executive_min: default_executive_min(),
10650 executive_max: default_executive_max(),
10651 }
10652 }
10653}
10654
10655fn default_staff_min() -> f64 {
10656 50_000.0
10657}
10658fn default_staff_max() -> f64 {
10659 70_000.0
10660}
10661fn default_manager_min() -> f64 {
10662 80_000.0
10663}
10664fn default_manager_max() -> f64 {
10665 120_000.0
10666}
10667fn default_director_min() -> f64 {
10668 120_000.0
10669}
10670fn default_director_max() -> f64 {
10671 180_000.0
10672}
10673fn default_executive_min() -> f64 {
10674 180_000.0
10675}
10676fn default_executive_max() -> f64 {
10677 350_000.0
10678}
10679
10680#[derive(Debug, Clone, Serialize, Deserialize)]
10682pub struct PayrollTaxRates {
10683 #[serde(default = "default_federal_rate")]
10685 pub federal_effective: f64,
10686 #[serde(default = "default_state_rate")]
10688 pub state_effective: f64,
10689 #[serde(default = "default_fica_rate")]
10691 pub fica: f64,
10692}
10693
10694impl Default for PayrollTaxRates {
10695 fn default() -> Self {
10696 Self {
10697 federal_effective: default_federal_rate(),
10698 state_effective: default_state_rate(),
10699 fica: default_fica_rate(),
10700 }
10701 }
10702}
10703
10704fn default_federal_rate() -> f64 {
10705 0.22
10706}
10707fn default_state_rate() -> f64 {
10708 0.05
10709}
10710fn default_fica_rate() -> f64 {
10711 0.0765
10712}
10713
10714#[derive(Debug, Clone, Serialize, Deserialize)]
10716pub struct TimeAttendanceConfig {
10717 #[serde(default = "default_true")]
10719 pub enabled: bool,
10720 #[serde(default = "default_overtime_rate")]
10722 pub overtime_rate: f64,
10723}
10724
10725impl Default for TimeAttendanceConfig {
10726 fn default() -> Self {
10727 Self {
10728 enabled: true,
10729 overtime_rate: default_overtime_rate(),
10730 }
10731 }
10732}
10733
10734fn default_overtime_rate() -> f64 {
10735 0.10
10736}
10737
10738#[derive(Debug, Clone, Serialize, Deserialize)]
10740pub struct ExpenseConfig {
10741 #[serde(default = "default_true")]
10743 pub enabled: bool,
10744 #[serde(default = "default_expense_submission_rate")]
10746 pub submission_rate: f64,
10747 #[serde(default = "default_policy_violation_rate")]
10749 pub policy_violation_rate: f64,
10750}
10751
10752impl Default for ExpenseConfig {
10753 fn default() -> Self {
10754 Self {
10755 enabled: true,
10756 submission_rate: default_expense_submission_rate(),
10757 policy_violation_rate: default_policy_violation_rate(),
10758 }
10759 }
10760}
10761
10762fn default_expense_submission_rate() -> f64 {
10763 0.30
10764}
10765fn default_policy_violation_rate() -> f64 {
10766 0.08
10767}
10768
10769#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10773pub struct ManufacturingProcessConfig {
10774 #[serde(default)]
10776 pub enabled: bool,
10777 #[serde(default)]
10779 pub production_orders: ProductionOrderConfig,
10780 #[serde(default)]
10782 pub costing: ManufacturingCostingConfig,
10783 #[serde(default)]
10785 pub routing: RoutingConfig,
10786}
10787
10788#[derive(Debug, Clone, Serialize, Deserialize)]
10790pub struct ProductionOrderConfig {
10791 #[serde(default = "default_prod_orders_per_month")]
10793 pub orders_per_month: u32,
10794 #[serde(default = "default_prod_avg_batch_size")]
10796 pub avg_batch_size: u32,
10797 #[serde(default = "default_prod_yield_rate")]
10799 pub yield_rate: f64,
10800 #[serde(default = "default_prod_make_to_order_rate")]
10802 pub make_to_order_rate: f64,
10803 #[serde(default = "default_prod_rework_rate")]
10805 pub rework_rate: f64,
10806}
10807
10808impl Default for ProductionOrderConfig {
10809 fn default() -> Self {
10810 Self {
10811 orders_per_month: default_prod_orders_per_month(),
10812 avg_batch_size: default_prod_avg_batch_size(),
10813 yield_rate: default_prod_yield_rate(),
10814 make_to_order_rate: default_prod_make_to_order_rate(),
10815 rework_rate: default_prod_rework_rate(),
10816 }
10817 }
10818}
10819
10820fn default_prod_orders_per_month() -> u32 {
10821 50
10822}
10823fn default_prod_avg_batch_size() -> u32 {
10824 100
10825}
10826fn default_prod_yield_rate() -> f64 {
10827 0.97
10828}
10829fn default_prod_make_to_order_rate() -> f64 {
10830 0.20
10831}
10832fn default_prod_rework_rate() -> f64 {
10833 0.03
10834}
10835
10836#[derive(Debug, Clone, Serialize, Deserialize)]
10838pub struct ManufacturingCostingConfig {
10839 #[serde(default = "default_labor_rate")]
10841 pub labor_rate_per_hour: f64,
10842 #[serde(default = "default_overhead_rate")]
10844 pub overhead_rate: f64,
10845 #[serde(default = "default_cost_update_frequency")]
10847 pub standard_cost_update_frequency: String,
10848}
10849
10850impl Default for ManufacturingCostingConfig {
10851 fn default() -> Self {
10852 Self {
10853 labor_rate_per_hour: default_labor_rate(),
10854 overhead_rate: default_overhead_rate(),
10855 standard_cost_update_frequency: default_cost_update_frequency(),
10856 }
10857 }
10858}
10859
10860fn default_labor_rate() -> f64 {
10861 35.0
10862}
10863fn default_overhead_rate() -> f64 {
10864 1.50
10865}
10866fn default_cost_update_frequency() -> String {
10867 "quarterly".to_string()
10868}
10869
10870#[derive(Debug, Clone, Serialize, Deserialize)]
10872pub struct RoutingConfig {
10873 #[serde(default = "default_avg_operations")]
10875 pub avg_operations: u32,
10876 #[serde(default = "default_setup_time")]
10878 pub setup_time_hours: f64,
10879 #[serde(default = "default_run_time_variation")]
10881 pub run_time_variation: f64,
10882}
10883
10884impl Default for RoutingConfig {
10885 fn default() -> Self {
10886 Self {
10887 avg_operations: default_avg_operations(),
10888 setup_time_hours: default_setup_time(),
10889 run_time_variation: default_run_time_variation(),
10890 }
10891 }
10892}
10893
10894fn default_avg_operations() -> u32 {
10895 4
10896}
10897fn default_setup_time() -> f64 {
10898 1.5
10899}
10900fn default_run_time_variation() -> f64 {
10901 0.15
10902}
10903
10904#[derive(Debug, Clone, Serialize, Deserialize)]
10908pub struct SalesQuoteConfig {
10909 #[serde(default)]
10911 pub enabled: bool,
10912 #[serde(default = "default_quotes_per_month")]
10914 pub quotes_per_month: u32,
10915 #[serde(default = "default_quote_win_rate")]
10917 pub win_rate: f64,
10918 #[serde(default = "default_quote_validity_days")]
10920 pub validity_days: u32,
10921}
10922
10923impl Default for SalesQuoteConfig {
10924 fn default() -> Self {
10925 Self {
10926 enabled: false,
10927 quotes_per_month: default_quotes_per_month(),
10928 win_rate: default_quote_win_rate(),
10929 validity_days: default_quote_validity_days(),
10930 }
10931 }
10932}
10933
10934fn default_quotes_per_month() -> u32 {
10935 30
10936}
10937fn default_quote_win_rate() -> f64 {
10938 0.35
10939}
10940fn default_quote_validity_days() -> u32 {
10941 30
10942}
10943
10944#[derive(Debug, Clone, Serialize, Deserialize)]
10953pub struct TaxConfig {
10954 #[serde(default)]
10956 pub enabled: bool,
10957 #[serde(default)]
10959 pub jurisdictions: TaxJurisdictionConfig,
10960 #[serde(default)]
10962 pub vat_gst: VatGstConfig,
10963 #[serde(default)]
10965 pub sales_tax: SalesTaxConfig,
10966 #[serde(default)]
10968 pub withholding: WithholdingTaxSchemaConfig,
10969 #[serde(default)]
10971 pub provisions: TaxProvisionSchemaConfig,
10972 #[serde(default)]
10974 pub payroll_tax: PayrollTaxSchemaConfig,
10975 #[serde(default = "default_tax_anomaly_rate")]
10977 pub anomaly_rate: f64,
10978}
10979
10980fn default_tax_anomaly_rate() -> f64 {
10981 0.03
10982}
10983
10984impl Default for TaxConfig {
10985 fn default() -> Self {
10986 Self {
10987 enabled: false,
10988 jurisdictions: TaxJurisdictionConfig::default(),
10989 vat_gst: VatGstConfig::default(),
10990 sales_tax: SalesTaxConfig::default(),
10991 withholding: WithholdingTaxSchemaConfig::default(),
10992 provisions: TaxProvisionSchemaConfig::default(),
10993 payroll_tax: PayrollTaxSchemaConfig::default(),
10994 anomaly_rate: default_tax_anomaly_rate(),
10995 }
10996 }
10997}
10998
10999#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11004pub struct TaxJurisdictionConfig {
11005 #[serde(default)]
11007 pub countries: Vec<String>,
11008 #[serde(default)]
11010 pub include_subnational: bool,
11011}
11012
11013#[derive(Debug, Clone, Serialize, Deserialize)]
11018pub struct VatGstConfig {
11019 #[serde(default)]
11021 pub enabled: bool,
11022 #[serde(default)]
11024 pub standard_rates: std::collections::HashMap<String, f64>,
11025 #[serde(default)]
11027 pub reduced_rates: std::collections::HashMap<String, f64>,
11028 #[serde(default)]
11030 pub exempt_categories: Vec<String>,
11031 #[serde(default = "default_true")]
11033 pub reverse_charge: bool,
11034}
11035
11036impl Default for VatGstConfig {
11037 fn default() -> Self {
11038 Self {
11039 enabled: false,
11040 standard_rates: std::collections::HashMap::new(),
11041 reduced_rates: std::collections::HashMap::new(),
11042 exempt_categories: Vec::new(),
11043 reverse_charge: true,
11044 }
11045 }
11046}
11047
11048#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11052pub struct SalesTaxConfig {
11053 #[serde(default)]
11055 pub enabled: bool,
11056 #[serde(default)]
11058 pub nexus_states: Vec<String>,
11059}
11060
11061#[derive(Debug, Clone, Serialize, Deserialize)]
11066pub struct WithholdingTaxSchemaConfig {
11067 #[serde(default)]
11069 pub enabled: bool,
11070 #[serde(default = "default_true")]
11072 pub treaty_network: bool,
11073 #[serde(default = "default_withholding_rate")]
11075 pub default_rate: f64,
11076 #[serde(default = "default_treaty_reduced_rate")]
11078 pub treaty_reduced_rate: f64,
11079}
11080
11081fn default_withholding_rate() -> f64 {
11082 0.30
11083}
11084
11085fn default_treaty_reduced_rate() -> f64 {
11086 0.15
11087}
11088
11089impl Default for WithholdingTaxSchemaConfig {
11090 fn default() -> Self {
11091 Self {
11092 enabled: false,
11093 treaty_network: true,
11094 default_rate: default_withholding_rate(),
11095 treaty_reduced_rate: default_treaty_reduced_rate(),
11096 }
11097 }
11098}
11099
11100#[derive(Debug, Clone, Serialize, Deserialize)]
11105pub struct TaxProvisionSchemaConfig {
11106 #[serde(default = "default_true")]
11109 pub enabled: bool,
11110 #[serde(default = "default_statutory_rate")]
11112 pub statutory_rate: f64,
11113 #[serde(default = "default_true")]
11115 pub uncertain_positions: bool,
11116}
11117
11118fn default_statutory_rate() -> f64 {
11119 0.21
11120}
11121
11122impl Default for TaxProvisionSchemaConfig {
11123 fn default() -> Self {
11124 Self {
11125 enabled: true,
11126 statutory_rate: default_statutory_rate(),
11127 uncertain_positions: true,
11128 }
11129 }
11130}
11131
11132#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11137pub struct PayrollTaxSchemaConfig {
11138 #[serde(default)]
11140 pub enabled: bool,
11141}
11142
11143#[derive(Debug, Clone, Serialize, Deserialize)]
11153pub struct TreasuryConfig {
11154 #[serde(default)]
11156 pub enabled: bool,
11157 #[serde(default)]
11159 pub cash_positioning: CashPositioningConfig,
11160 #[serde(default)]
11162 pub cash_forecasting: CashForecastingConfig,
11163 #[serde(default)]
11165 pub cash_pooling: CashPoolingConfig,
11166 #[serde(default)]
11168 pub hedging: HedgingSchemaConfig,
11169 #[serde(default)]
11171 pub debt: DebtSchemaConfig,
11172 #[serde(default)]
11174 pub netting: NettingSchemaConfig,
11175 #[serde(default)]
11177 pub bank_guarantees: BankGuaranteeSchemaConfig,
11178 #[serde(default = "default_treasury_anomaly_rate")]
11180 pub anomaly_rate: f64,
11181}
11182
11183fn default_treasury_anomaly_rate() -> f64 {
11184 0.02
11185}
11186
11187impl Default for TreasuryConfig {
11188 fn default() -> Self {
11189 Self {
11190 enabled: false,
11191 cash_positioning: CashPositioningConfig::default(),
11192 cash_forecasting: CashForecastingConfig::default(),
11193 cash_pooling: CashPoolingConfig::default(),
11194 hedging: HedgingSchemaConfig::default(),
11195 debt: DebtSchemaConfig::default(),
11196 netting: NettingSchemaConfig::default(),
11197 bank_guarantees: BankGuaranteeSchemaConfig::default(),
11198 anomaly_rate: default_treasury_anomaly_rate(),
11199 }
11200 }
11201}
11202
11203#[derive(Debug, Clone, Serialize, Deserialize)]
11207pub struct CashPositioningConfig {
11208 #[serde(default = "default_true")]
11210 pub enabled: bool,
11211 #[serde(default = "default_cash_frequency")]
11213 pub frequency: String,
11214 #[serde(default = "default_minimum_balance_policy")]
11216 pub minimum_balance_policy: f64,
11217}
11218
11219fn default_cash_frequency() -> String {
11220 "daily".to_string()
11221}
11222
11223fn default_minimum_balance_policy() -> f64 {
11224 100_000.0
11225}
11226
11227impl Default for CashPositioningConfig {
11228 fn default() -> Self {
11229 Self {
11230 enabled: true,
11231 frequency: default_cash_frequency(),
11232 minimum_balance_policy: default_minimum_balance_policy(),
11233 }
11234 }
11235}
11236
11237#[derive(Debug, Clone, Serialize, Deserialize)]
11241pub struct CashForecastingConfig {
11242 #[serde(default = "default_true")]
11244 pub enabled: bool,
11245 #[serde(default = "default_horizon_days")]
11247 pub horizon_days: u32,
11248 #[serde(default = "default_ar_probability_curve")]
11250 pub ar_collection_probability_curve: String,
11251 #[serde(default = "default_confidence_interval")]
11253 pub confidence_interval: f64,
11254}
11255
11256fn default_horizon_days() -> u32 {
11257 90
11258}
11259
11260fn default_ar_probability_curve() -> String {
11261 "aging".to_string()
11262}
11263
11264fn default_confidence_interval() -> f64 {
11265 0.90
11266}
11267
11268impl Default for CashForecastingConfig {
11269 fn default() -> Self {
11270 Self {
11271 enabled: true,
11272 horizon_days: default_horizon_days(),
11273 ar_collection_probability_curve: default_ar_probability_curve(),
11274 confidence_interval: default_confidence_interval(),
11275 }
11276 }
11277}
11278
11279#[derive(Debug, Clone, Serialize, Deserialize)]
11283pub struct CashPoolingConfig {
11284 #[serde(default)]
11286 pub enabled: bool,
11287 #[serde(default = "default_pool_type")]
11289 pub pool_type: String,
11290 #[serde(default = "default_sweep_time")]
11292 pub sweep_time: String,
11293}
11294
11295fn default_pool_type() -> String {
11296 "zero_balancing".to_string()
11297}
11298
11299fn default_sweep_time() -> String {
11300 "16:00".to_string()
11301}
11302
11303impl Default for CashPoolingConfig {
11304 fn default() -> Self {
11305 Self {
11306 enabled: false,
11307 pool_type: default_pool_type(),
11308 sweep_time: default_sweep_time(),
11309 }
11310 }
11311}
11312
11313#[derive(Debug, Clone, Serialize, Deserialize)]
11318pub struct HedgingSchemaConfig {
11319 #[serde(default)]
11321 pub enabled: bool,
11322 #[serde(default = "default_hedge_ratio")]
11324 pub hedge_ratio: f64,
11325 #[serde(default = "default_hedge_instruments")]
11327 pub instruments: Vec<String>,
11328 #[serde(default = "default_true")]
11330 pub hedge_accounting: bool,
11331 #[serde(default = "default_effectiveness_method")]
11333 pub effectiveness_method: String,
11334}
11335
11336fn default_hedge_ratio() -> f64 {
11337 0.75
11338}
11339
11340fn default_hedge_instruments() -> Vec<String> {
11341 vec!["fx_forward".to_string(), "interest_rate_swap".to_string()]
11342}
11343
11344fn default_effectiveness_method() -> String {
11345 "regression".to_string()
11346}
11347
11348impl Default for HedgingSchemaConfig {
11349 fn default() -> Self {
11350 Self {
11351 enabled: false,
11352 hedge_ratio: default_hedge_ratio(),
11353 instruments: default_hedge_instruments(),
11354 hedge_accounting: true,
11355 effectiveness_method: default_effectiveness_method(),
11356 }
11357 }
11358}
11359
11360#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11365pub struct DebtSchemaConfig {
11366 #[serde(default)]
11368 pub enabled: bool,
11369 #[serde(default)]
11371 pub instruments: Vec<DebtInstrumentDef>,
11372 #[serde(default)]
11374 pub covenants: Vec<CovenantDef>,
11375}
11376
11377#[derive(Debug, Clone, Serialize, Deserialize)]
11379pub struct DebtInstrumentDef {
11380 #[serde(rename = "type")]
11382 pub instrument_type: String,
11383 #[serde(default)]
11385 pub principal: Option<f64>,
11386 #[serde(default)]
11388 pub rate: Option<f64>,
11389 #[serde(default)]
11391 pub maturity_months: Option<u32>,
11392 #[serde(default)]
11394 pub facility: Option<f64>,
11395}
11396
11397#[derive(Debug, Clone, Serialize, Deserialize)]
11399pub struct CovenantDef {
11400 #[serde(rename = "type")]
11403 pub covenant_type: String,
11404 pub threshold: f64,
11406}
11407
11408#[derive(Debug, Clone, Serialize, Deserialize)]
11412pub struct NettingSchemaConfig {
11413 #[serde(default)]
11415 pub enabled: bool,
11416 #[serde(default = "default_netting_cycle")]
11418 pub cycle: String,
11419}
11420
11421fn default_netting_cycle() -> String {
11422 "monthly".to_string()
11423}
11424
11425impl Default for NettingSchemaConfig {
11426 fn default() -> Self {
11427 Self {
11428 enabled: false,
11429 cycle: default_netting_cycle(),
11430 }
11431 }
11432}
11433
11434#[derive(Debug, Clone, Serialize, Deserialize)]
11438pub struct BankGuaranteeSchemaConfig {
11439 #[serde(default)]
11441 pub enabled: bool,
11442 #[serde(default = "default_guarantee_count")]
11444 pub count: u32,
11445}
11446
11447fn default_guarantee_count() -> u32 {
11448 5
11449}
11450
11451impl Default for BankGuaranteeSchemaConfig {
11452 fn default() -> Self {
11453 Self {
11454 enabled: false,
11455 count: default_guarantee_count(),
11456 }
11457 }
11458}
11459
11460#[derive(Debug, Clone, Serialize, Deserialize)]
11469pub struct ProjectAccountingConfig {
11470 #[serde(default)]
11472 pub enabled: bool,
11473 #[serde(default = "default_project_count")]
11475 pub project_count: u32,
11476 #[serde(default)]
11478 pub project_types: ProjectTypeDistribution,
11479 #[serde(default)]
11481 pub wbs: WbsSchemaConfig,
11482 #[serde(default)]
11484 pub cost_allocation: CostAllocationConfig,
11485 #[serde(default)]
11487 pub revenue_recognition: ProjectRevenueRecognitionConfig,
11488 #[serde(default)]
11490 pub milestones: MilestoneSchemaConfig,
11491 #[serde(default)]
11493 pub change_orders: ChangeOrderSchemaConfig,
11494 #[serde(default)]
11496 pub retainage: RetainageSchemaConfig,
11497 #[serde(default)]
11499 pub earned_value: EarnedValueSchemaConfig,
11500 #[serde(default = "default_project_anomaly_rate")]
11502 pub anomaly_rate: f64,
11503}
11504
11505fn default_project_count() -> u32 {
11506 10
11507}
11508
11509fn default_project_anomaly_rate() -> f64 {
11510 0.03
11511}
11512
11513impl Default for ProjectAccountingConfig {
11514 fn default() -> Self {
11515 Self {
11516 enabled: false,
11517 project_count: default_project_count(),
11518 project_types: ProjectTypeDistribution::default(),
11519 wbs: WbsSchemaConfig::default(),
11520 cost_allocation: CostAllocationConfig::default(),
11521 revenue_recognition: ProjectRevenueRecognitionConfig::default(),
11522 milestones: MilestoneSchemaConfig::default(),
11523 change_orders: ChangeOrderSchemaConfig::default(),
11524 retainage: RetainageSchemaConfig::default(),
11525 earned_value: EarnedValueSchemaConfig::default(),
11526 anomaly_rate: default_project_anomaly_rate(),
11527 }
11528 }
11529}
11530
11531#[derive(Debug, Clone, Serialize, Deserialize)]
11533pub struct ProjectTypeDistribution {
11534 #[serde(default = "default_capital_weight")]
11536 pub capital: f64,
11537 #[serde(default = "default_internal_weight")]
11539 pub internal: f64,
11540 #[serde(default = "default_customer_weight")]
11542 pub customer: f64,
11543 #[serde(default = "default_rnd_weight")]
11545 pub r_and_d: f64,
11546 #[serde(default = "default_maintenance_weight")]
11548 pub maintenance: f64,
11549 #[serde(default = "default_technology_weight")]
11551 pub technology: f64,
11552}
11553
11554fn default_capital_weight() -> f64 {
11555 0.25
11556}
11557fn default_internal_weight() -> f64 {
11558 0.20
11559}
11560fn default_customer_weight() -> f64 {
11561 0.30
11562}
11563fn default_rnd_weight() -> f64 {
11564 0.10
11565}
11566fn default_maintenance_weight() -> f64 {
11567 0.10
11568}
11569fn default_technology_weight() -> f64 {
11570 0.05
11571}
11572
11573impl Default for ProjectTypeDistribution {
11574 fn default() -> Self {
11575 Self {
11576 capital: default_capital_weight(),
11577 internal: default_internal_weight(),
11578 customer: default_customer_weight(),
11579 r_and_d: default_rnd_weight(),
11580 maintenance: default_maintenance_weight(),
11581 technology: default_technology_weight(),
11582 }
11583 }
11584}
11585
11586#[derive(Debug, Clone, Serialize, Deserialize)]
11588pub struct WbsSchemaConfig {
11589 #[serde(default = "default_wbs_max_depth")]
11591 pub max_depth: u32,
11592 #[serde(default = "default_wbs_min_elements")]
11594 pub min_elements_per_level: u32,
11595 #[serde(default = "default_wbs_max_elements")]
11597 pub max_elements_per_level: u32,
11598}
11599
11600fn default_wbs_max_depth() -> u32 {
11601 3
11602}
11603fn default_wbs_min_elements() -> u32 {
11604 2
11605}
11606fn default_wbs_max_elements() -> u32 {
11607 6
11608}
11609
11610impl Default for WbsSchemaConfig {
11611 fn default() -> Self {
11612 Self {
11613 max_depth: default_wbs_max_depth(),
11614 min_elements_per_level: default_wbs_min_elements(),
11615 max_elements_per_level: default_wbs_max_elements(),
11616 }
11617 }
11618}
11619
11620#[derive(Debug, Clone, Serialize, Deserialize)]
11622pub struct CostAllocationConfig {
11623 #[serde(default = "default_time_entry_rate")]
11625 pub time_entry_project_rate: f64,
11626 #[serde(default = "default_expense_rate")]
11628 pub expense_project_rate: f64,
11629 #[serde(default = "default_po_rate")]
11631 pub purchase_order_project_rate: f64,
11632 #[serde(default = "default_vi_rate")]
11634 pub vendor_invoice_project_rate: f64,
11635}
11636
11637fn default_time_entry_rate() -> f64 {
11638 0.60
11639}
11640fn default_expense_rate() -> f64 {
11641 0.30
11642}
11643fn default_po_rate() -> f64 {
11644 0.40
11645}
11646fn default_vi_rate() -> f64 {
11647 0.35
11648}
11649
11650impl Default for CostAllocationConfig {
11651 fn default() -> Self {
11652 Self {
11653 time_entry_project_rate: default_time_entry_rate(),
11654 expense_project_rate: default_expense_rate(),
11655 purchase_order_project_rate: default_po_rate(),
11656 vendor_invoice_project_rate: default_vi_rate(),
11657 }
11658 }
11659}
11660
11661#[derive(Debug, Clone, Serialize, Deserialize)]
11663pub struct ProjectRevenueRecognitionConfig {
11664 #[serde(default = "default_true")]
11666 pub enabled: bool,
11667 #[serde(default = "default_revenue_method")]
11669 pub method: String,
11670 #[serde(default = "default_completion_measure")]
11672 pub completion_measure: String,
11673 #[serde(default = "default_avg_contract_value")]
11675 pub avg_contract_value: f64,
11676}
11677
11678fn default_revenue_method() -> String {
11679 "percentage_of_completion".to_string()
11680}
11681fn default_completion_measure() -> String {
11682 "cost_to_cost".to_string()
11683}
11684fn default_avg_contract_value() -> f64 {
11685 500_000.0
11686}
11687
11688impl Default for ProjectRevenueRecognitionConfig {
11689 fn default() -> Self {
11690 Self {
11691 enabled: true,
11692 method: default_revenue_method(),
11693 completion_measure: default_completion_measure(),
11694 avg_contract_value: default_avg_contract_value(),
11695 }
11696 }
11697}
11698
11699#[derive(Debug, Clone, Serialize, Deserialize)]
11701pub struct MilestoneSchemaConfig {
11702 #[serde(default = "default_true")]
11704 pub enabled: bool,
11705 #[serde(default = "default_milestones_per_project")]
11707 pub avg_per_project: u32,
11708 #[serde(default = "default_payment_milestone_rate")]
11710 pub payment_milestone_rate: f64,
11711}
11712
11713fn default_milestones_per_project() -> u32 {
11714 4
11715}
11716fn default_payment_milestone_rate() -> f64 {
11717 0.50
11718}
11719
11720impl Default for MilestoneSchemaConfig {
11721 fn default() -> Self {
11722 Self {
11723 enabled: true,
11724 avg_per_project: default_milestones_per_project(),
11725 payment_milestone_rate: default_payment_milestone_rate(),
11726 }
11727 }
11728}
11729
11730#[derive(Debug, Clone, Serialize, Deserialize)]
11732pub struct ChangeOrderSchemaConfig {
11733 #[serde(default = "default_true")]
11735 pub enabled: bool,
11736 #[serde(default = "default_change_order_probability")]
11738 pub probability: f64,
11739 #[serde(default = "default_max_change_orders")]
11741 pub max_per_project: u32,
11742 #[serde(default = "default_change_order_approval_rate")]
11744 pub approval_rate: f64,
11745}
11746
11747fn default_change_order_probability() -> f64 {
11748 0.40
11749}
11750fn default_max_change_orders() -> u32 {
11751 3
11752}
11753fn default_change_order_approval_rate() -> f64 {
11754 0.75
11755}
11756
11757impl Default for ChangeOrderSchemaConfig {
11758 fn default() -> Self {
11759 Self {
11760 enabled: true,
11761 probability: default_change_order_probability(),
11762 max_per_project: default_max_change_orders(),
11763 approval_rate: default_change_order_approval_rate(),
11764 }
11765 }
11766}
11767
11768#[derive(Debug, Clone, Serialize, Deserialize)]
11770pub struct RetainageSchemaConfig {
11771 #[serde(default)]
11773 pub enabled: bool,
11774 #[serde(default = "default_retainage_pct")]
11776 pub default_percentage: f64,
11777}
11778
11779fn default_retainage_pct() -> f64 {
11780 0.10
11781}
11782
11783impl Default for RetainageSchemaConfig {
11784 fn default() -> Self {
11785 Self {
11786 enabled: false,
11787 default_percentage: default_retainage_pct(),
11788 }
11789 }
11790}
11791
11792#[derive(Debug, Clone, Serialize, Deserialize)]
11794pub struct EarnedValueSchemaConfig {
11795 #[serde(default = "default_true")]
11797 pub enabled: bool,
11798 #[serde(default = "default_evm_frequency")]
11800 pub frequency: String,
11801}
11802
11803fn default_evm_frequency() -> String {
11804 "monthly".to_string()
11805}
11806
11807impl Default for EarnedValueSchemaConfig {
11808 fn default() -> Self {
11809 Self {
11810 enabled: true,
11811 frequency: default_evm_frequency(),
11812 }
11813 }
11814}
11815
11816#[derive(Debug, Clone, Serialize, Deserialize)]
11822pub struct EsgConfig {
11823 #[serde(default)]
11825 pub enabled: bool,
11826 #[serde(default)]
11828 pub environmental: EnvironmentalConfig,
11829 #[serde(default)]
11831 pub social: SocialConfig,
11832 #[serde(default)]
11834 pub governance: GovernanceSchemaConfig,
11835 #[serde(default)]
11837 pub supply_chain_esg: SupplyChainEsgConfig,
11838 #[serde(default)]
11840 pub reporting: EsgReportingConfig,
11841 #[serde(default)]
11843 pub climate_scenarios: ClimateScenarioConfig,
11844 #[serde(default = "default_esg_anomaly_rate")]
11846 pub anomaly_rate: f64,
11847}
11848
11849fn default_esg_anomaly_rate() -> f64 {
11850 0.02
11851}
11852
11853impl Default for EsgConfig {
11854 fn default() -> Self {
11855 Self {
11856 enabled: false,
11857 environmental: EnvironmentalConfig::default(),
11858 social: SocialConfig::default(),
11859 governance: GovernanceSchemaConfig::default(),
11860 supply_chain_esg: SupplyChainEsgConfig::default(),
11861 reporting: EsgReportingConfig::default(),
11862 climate_scenarios: ClimateScenarioConfig::default(),
11863 anomaly_rate: default_esg_anomaly_rate(),
11864 }
11865 }
11866}
11867
11868#[derive(Debug, Clone, Serialize, Deserialize, Default)]
11873pub struct CountryPacksSchemaConfig {
11874 #[serde(default)]
11876 pub external_dir: Option<PathBuf>,
11877 #[serde(default)]
11881 pub overrides: std::collections::HashMap<String, serde_json::Value>,
11882}
11883
11884#[derive(Debug, Clone, Serialize, Deserialize)]
11886pub struct EnvironmentalConfig {
11887 #[serde(default = "default_true")]
11889 pub enabled: bool,
11890 #[serde(default)]
11892 pub scope1: EmissionScopeConfig,
11893 #[serde(default)]
11895 pub scope2: EmissionScopeConfig,
11896 #[serde(default)]
11898 pub scope3: Scope3Config,
11899 #[serde(default)]
11901 pub energy: EnergySchemaConfig,
11902 #[serde(default)]
11904 pub water: WaterSchemaConfig,
11905 #[serde(default)]
11907 pub waste: WasteSchemaConfig,
11908}
11909
11910impl Default for EnvironmentalConfig {
11911 fn default() -> Self {
11912 Self {
11913 enabled: true,
11914 scope1: EmissionScopeConfig::default(),
11915 scope2: EmissionScopeConfig::default(),
11916 scope3: Scope3Config::default(),
11917 energy: EnergySchemaConfig::default(),
11918 water: WaterSchemaConfig::default(),
11919 waste: WasteSchemaConfig::default(),
11920 }
11921 }
11922}
11923
11924#[derive(Debug, Clone, Serialize, Deserialize)]
11926pub struct EmissionScopeConfig {
11927 #[serde(default = "default_true")]
11929 pub enabled: bool,
11930 #[serde(default = "default_emission_region")]
11932 pub factor_region: String,
11933}
11934
11935fn default_emission_region() -> String {
11936 "US".to_string()
11937}
11938
11939impl Default for EmissionScopeConfig {
11940 fn default() -> Self {
11941 Self {
11942 enabled: true,
11943 factor_region: default_emission_region(),
11944 }
11945 }
11946}
11947
11948#[derive(Debug, Clone, Serialize, Deserialize)]
11950pub struct Scope3Config {
11951 #[serde(default = "default_true")]
11953 pub enabled: bool,
11954 #[serde(default = "default_scope3_categories")]
11956 pub categories: Vec<String>,
11957 #[serde(default = "default_spend_intensity")]
11959 pub default_spend_intensity_kg_per_usd: f64,
11960}
11961
11962fn default_scope3_categories() -> Vec<String> {
11963 vec![
11964 "purchased_goods".to_string(),
11965 "business_travel".to_string(),
11966 "employee_commuting".to_string(),
11967 ]
11968}
11969
11970fn default_spend_intensity() -> f64 {
11971 0.5
11972}
11973
11974impl Default for Scope3Config {
11975 fn default() -> Self {
11976 Self {
11977 enabled: true,
11978 categories: default_scope3_categories(),
11979 default_spend_intensity_kg_per_usd: default_spend_intensity(),
11980 }
11981 }
11982}
11983
11984#[derive(Debug, Clone, Serialize, Deserialize)]
11986pub struct EnergySchemaConfig {
11987 #[serde(default = "default_true")]
11989 pub enabled: bool,
11990 #[serde(default = "default_facility_count")]
11992 pub facility_count: u32,
11993 #[serde(default = "default_renewable_target")]
11995 pub renewable_target: f64,
11996}
11997
11998fn default_facility_count() -> u32 {
11999 5
12000}
12001
12002fn default_renewable_target() -> f64 {
12003 0.30
12004}
12005
12006impl Default for EnergySchemaConfig {
12007 fn default() -> Self {
12008 Self {
12009 enabled: true,
12010 facility_count: default_facility_count(),
12011 renewable_target: default_renewable_target(),
12012 }
12013 }
12014}
12015
12016#[derive(Debug, Clone, Serialize, Deserialize)]
12018pub struct WaterSchemaConfig {
12019 #[serde(default = "default_true")]
12021 pub enabled: bool,
12022 #[serde(default = "default_water_facility_count")]
12024 pub facility_count: u32,
12025}
12026
12027fn default_water_facility_count() -> u32 {
12028 3
12029}
12030
12031impl Default for WaterSchemaConfig {
12032 fn default() -> Self {
12033 Self {
12034 enabled: true,
12035 facility_count: default_water_facility_count(),
12036 }
12037 }
12038}
12039
12040#[derive(Debug, Clone, Serialize, Deserialize)]
12042pub struct WasteSchemaConfig {
12043 #[serde(default = "default_true")]
12045 pub enabled: bool,
12046 #[serde(default = "default_diversion_target")]
12048 pub diversion_target: f64,
12049}
12050
12051fn default_diversion_target() -> f64 {
12052 0.50
12053}
12054
12055impl Default for WasteSchemaConfig {
12056 fn default() -> Self {
12057 Self {
12058 enabled: true,
12059 diversion_target: default_diversion_target(),
12060 }
12061 }
12062}
12063
12064#[derive(Debug, Clone, Serialize, Deserialize)]
12066pub struct SocialConfig {
12067 #[serde(default = "default_true")]
12069 pub enabled: bool,
12070 #[serde(default)]
12072 pub diversity: DiversitySchemaConfig,
12073 #[serde(default)]
12075 pub pay_equity: PayEquitySchemaConfig,
12076 #[serde(default)]
12078 pub safety: SafetySchemaConfig,
12079}
12080
12081impl Default for SocialConfig {
12082 fn default() -> Self {
12083 Self {
12084 enabled: true,
12085 diversity: DiversitySchemaConfig::default(),
12086 pay_equity: PayEquitySchemaConfig::default(),
12087 safety: SafetySchemaConfig::default(),
12088 }
12089 }
12090}
12091
12092#[derive(Debug, Clone, Serialize, Deserialize)]
12094pub struct DiversitySchemaConfig {
12095 #[serde(default = "default_true")]
12097 pub enabled: bool,
12098 #[serde(default = "default_diversity_dimensions")]
12100 pub dimensions: Vec<String>,
12101}
12102
12103fn default_diversity_dimensions() -> Vec<String> {
12104 vec![
12105 "gender".to_string(),
12106 "ethnicity".to_string(),
12107 "age_group".to_string(),
12108 ]
12109}
12110
12111impl Default for DiversitySchemaConfig {
12112 fn default() -> Self {
12113 Self {
12114 enabled: true,
12115 dimensions: default_diversity_dimensions(),
12116 }
12117 }
12118}
12119
12120#[derive(Debug, Clone, Serialize, Deserialize)]
12122pub struct PayEquitySchemaConfig {
12123 #[serde(default = "default_true")]
12125 pub enabled: bool,
12126 #[serde(default = "default_pay_gap_threshold")]
12128 pub gap_threshold: f64,
12129}
12130
12131fn default_pay_gap_threshold() -> f64 {
12132 0.05
12133}
12134
12135impl Default for PayEquitySchemaConfig {
12136 fn default() -> Self {
12137 Self {
12138 enabled: true,
12139 gap_threshold: default_pay_gap_threshold(),
12140 }
12141 }
12142}
12143
12144#[derive(Debug, Clone, Serialize, Deserialize)]
12146pub struct SafetySchemaConfig {
12147 #[serde(default = "default_true")]
12149 pub enabled: bool,
12150 #[serde(default = "default_trir_target")]
12152 pub target_trir: f64,
12153 #[serde(default = "default_incident_count")]
12155 pub incident_count: u32,
12156}
12157
12158fn default_trir_target() -> f64 {
12159 2.5
12160}
12161
12162fn default_incident_count() -> u32 {
12163 20
12164}
12165
12166impl Default for SafetySchemaConfig {
12167 fn default() -> Self {
12168 Self {
12169 enabled: true,
12170 target_trir: default_trir_target(),
12171 incident_count: default_incident_count(),
12172 }
12173 }
12174}
12175
12176#[derive(Debug, Clone, Serialize, Deserialize)]
12178pub struct GovernanceSchemaConfig {
12179 #[serde(default = "default_true")]
12181 pub enabled: bool,
12182 #[serde(default = "default_board_size")]
12184 pub board_size: u32,
12185 #[serde(default = "default_independence_target")]
12187 pub independence_target: f64,
12188}
12189
12190fn default_board_size() -> u32 {
12191 11
12192}
12193
12194fn default_independence_target() -> f64 {
12195 0.67
12196}
12197
12198impl Default for GovernanceSchemaConfig {
12199 fn default() -> Self {
12200 Self {
12201 enabled: true,
12202 board_size: default_board_size(),
12203 independence_target: default_independence_target(),
12204 }
12205 }
12206}
12207
12208#[derive(Debug, Clone, Serialize, Deserialize)]
12210pub struct SupplyChainEsgConfig {
12211 #[serde(default = "default_true")]
12213 pub enabled: bool,
12214 #[serde(default = "default_assessment_coverage")]
12216 pub assessment_coverage: f64,
12217 #[serde(default = "default_high_risk_countries")]
12219 pub high_risk_countries: Vec<String>,
12220}
12221
12222fn default_assessment_coverage() -> f64 {
12223 0.80
12224}
12225
12226fn default_high_risk_countries() -> Vec<String> {
12227 vec!["CN".to_string(), "BD".to_string(), "MM".to_string()]
12228}
12229
12230impl Default for SupplyChainEsgConfig {
12231 fn default() -> Self {
12232 Self {
12233 enabled: true,
12234 assessment_coverage: default_assessment_coverage(),
12235 high_risk_countries: default_high_risk_countries(),
12236 }
12237 }
12238}
12239
12240#[derive(Debug, Clone, Serialize, Deserialize)]
12242pub struct EsgReportingConfig {
12243 #[serde(default = "default_true")]
12245 pub enabled: bool,
12246 #[serde(default = "default_esg_frameworks")]
12248 pub frameworks: Vec<String>,
12249 #[serde(default = "default_true")]
12251 pub materiality_assessment: bool,
12252 #[serde(default = "default_materiality_threshold")]
12254 pub impact_threshold: f64,
12255 #[serde(default = "default_materiality_threshold")]
12257 pub financial_threshold: f64,
12258}
12259
12260fn default_esg_frameworks() -> Vec<String> {
12261 vec!["GRI".to_string(), "ESRS".to_string()]
12262}
12263
12264fn default_materiality_threshold() -> f64 {
12265 0.6
12266}
12267
12268impl Default for EsgReportingConfig {
12269 fn default() -> Self {
12270 Self {
12271 enabled: true,
12272 frameworks: default_esg_frameworks(),
12273 materiality_assessment: true,
12274 impact_threshold: default_materiality_threshold(),
12275 financial_threshold: default_materiality_threshold(),
12276 }
12277 }
12278}
12279
12280#[derive(Debug, Clone, Serialize, Deserialize)]
12282pub struct ClimateScenarioConfig {
12283 #[serde(default)]
12285 pub enabled: bool,
12286 #[serde(default = "default_climate_scenarios")]
12288 pub scenarios: Vec<String>,
12289 #[serde(default = "default_time_horizons")]
12291 pub time_horizons: Vec<u32>,
12292}
12293
12294fn default_climate_scenarios() -> Vec<String> {
12295 vec![
12296 "net_zero_2050".to_string(),
12297 "stated_policies".to_string(),
12298 "current_trajectory".to_string(),
12299 ]
12300}
12301
12302fn default_time_horizons() -> Vec<u32> {
12303 vec![5, 10, 30]
12304}
12305
12306impl Default for ClimateScenarioConfig {
12307 fn default() -> Self {
12308 Self {
12309 enabled: false,
12310 scenarios: default_climate_scenarios(),
12311 time_horizons: default_time_horizons(),
12312 }
12313 }
12314}
12315
12316#[derive(Debug, Clone, Serialize, Deserialize, Default)]
12320pub struct ScenariosConfig {
12321 #[serde(default)]
12323 pub enabled: bool,
12324 #[serde(default)]
12326 pub scenarios: Vec<ScenarioSchemaConfig>,
12327 #[serde(default)]
12329 pub causal_model: CausalModelSchemaConfig,
12330 #[serde(default)]
12332 pub defaults: ScenarioDefaultsConfig,
12333}
12334
12335#[derive(Debug, Clone, Serialize, Deserialize)]
12337pub struct ScenarioSchemaConfig {
12338 pub name: String,
12340 #[serde(default)]
12342 pub description: String,
12343 #[serde(default)]
12345 pub tags: Vec<String>,
12346 pub base: Option<String>,
12348 pub probability_weight: Option<f64>,
12350 #[serde(default)]
12352 pub interventions: Vec<InterventionSchemaConfig>,
12353 #[serde(default)]
12355 pub constraints: ScenarioConstraintsSchemaConfig,
12356 #[serde(default)]
12358 pub output: ScenarioOutputSchemaConfig,
12359 #[serde(default)]
12361 pub metadata: std::collections::HashMap<String, String>,
12362}
12363
12364#[derive(Debug, Clone, Serialize, Deserialize)]
12366pub struct InterventionSchemaConfig {
12367 #[serde(flatten)]
12369 pub intervention_type: serde_json::Value,
12370 #[serde(default)]
12372 pub timing: InterventionTimingSchemaConfig,
12373 pub label: Option<String>,
12375 #[serde(default)]
12377 pub priority: u32,
12378}
12379
12380#[derive(Debug, Clone, Serialize, Deserialize)]
12382pub struct InterventionTimingSchemaConfig {
12383 #[serde(default = "default_start_month")]
12385 pub start_month: u32,
12386 pub duration_months: Option<u32>,
12388 #[serde(default = "default_onset")]
12390 pub onset: String,
12391 pub ramp_months: Option<u32>,
12393}
12394
12395fn default_start_month() -> u32 {
12396 1
12397}
12398
12399fn default_onset() -> String {
12400 "sudden".to_string()
12401}
12402
12403impl Default for InterventionTimingSchemaConfig {
12404 fn default() -> Self {
12405 Self {
12406 start_month: 1,
12407 duration_months: None,
12408 onset: "sudden".to_string(),
12409 ramp_months: None,
12410 }
12411 }
12412}
12413
12414#[derive(Debug, Clone, Serialize, Deserialize)]
12416pub struct ScenarioConstraintsSchemaConfig {
12417 #[serde(default = "default_true")]
12418 pub preserve_accounting_identity: bool,
12419 #[serde(default = "default_true")]
12420 pub preserve_document_chains: bool,
12421 #[serde(default = "default_true")]
12422 pub preserve_period_close: bool,
12423 #[serde(default = "default_true")]
12424 pub preserve_balance_coherence: bool,
12425 #[serde(default)]
12426 pub custom: Vec<CustomConstraintSchemaConfig>,
12427}
12428
12429impl Default for ScenarioConstraintsSchemaConfig {
12430 fn default() -> Self {
12431 Self {
12432 preserve_accounting_identity: true,
12433 preserve_document_chains: true,
12434 preserve_period_close: true,
12435 preserve_balance_coherence: true,
12436 custom: Vec::new(),
12437 }
12438 }
12439}
12440
12441#[derive(Debug, Clone, Serialize, Deserialize)]
12443pub struct CustomConstraintSchemaConfig {
12444 pub config_path: String,
12445 pub min: Option<f64>,
12446 pub max: Option<f64>,
12447 #[serde(default)]
12448 pub description: String,
12449}
12450
12451#[derive(Debug, Clone, Serialize, Deserialize)]
12453pub struct ScenarioOutputSchemaConfig {
12454 #[serde(default = "default_true")]
12455 pub paired: bool,
12456 #[serde(default = "default_diff_formats_schema")]
12457 pub diff_formats: Vec<String>,
12458 #[serde(default)]
12459 pub diff_scope: Vec<String>,
12460}
12461
12462fn default_diff_formats_schema() -> Vec<String> {
12463 vec!["summary".to_string(), "aggregate".to_string()]
12464}
12465
12466impl Default for ScenarioOutputSchemaConfig {
12467 fn default() -> Self {
12468 Self {
12469 paired: true,
12470 diff_formats: default_diff_formats_schema(),
12471 diff_scope: Vec::new(),
12472 }
12473 }
12474}
12475
12476#[derive(Debug, Clone, Serialize, Deserialize)]
12478pub struct CausalModelSchemaConfig {
12479 #[serde(default = "default_causal_preset")]
12481 pub preset: String,
12482 #[serde(default)]
12484 pub nodes: Vec<serde_json::Value>,
12485 #[serde(default)]
12487 pub edges: Vec<serde_json::Value>,
12488}
12489
12490fn default_causal_preset() -> String {
12491 "default".to_string()
12492}
12493
12494impl Default for CausalModelSchemaConfig {
12495 fn default() -> Self {
12496 Self {
12497 preset: "default".to_string(),
12498 nodes: Vec::new(),
12499 edges: Vec::new(),
12500 }
12501 }
12502}
12503
12504#[derive(Debug, Clone, Serialize, Deserialize, Default)]
12506pub struct ScenarioDefaultsConfig {
12507 #[serde(default)]
12508 pub constraints: ScenarioConstraintsSchemaConfig,
12509 #[serde(default)]
12510 pub output: ScenarioOutputSchemaConfig,
12511}
12512
12513#[cfg(test)]
12514#[allow(clippy::unwrap_used)]
12515mod tests {
12516 use super::*;
12517 use crate::presets::demo_preset;
12518
12519 #[test]
12524 fn test_config_yaml_roundtrip() {
12525 let config = demo_preset();
12526 let yaml = serde_yaml::to_string(&config).expect("Failed to serialize to YAML");
12527 let deserialized: GeneratorConfig =
12528 serde_yaml::from_str(&yaml).expect("Failed to deserialize from YAML");
12529
12530 assert_eq!(
12531 config.global.period_months,
12532 deserialized.global.period_months
12533 );
12534 assert_eq!(config.global.industry, deserialized.global.industry);
12535 assert_eq!(config.companies.len(), deserialized.companies.len());
12536 assert_eq!(config.companies[0].code, deserialized.companies[0].code);
12537 }
12538
12539 #[test]
12540 fn test_config_json_roundtrip() {
12541 let mut config = demo_preset();
12543 config.master_data.employees.approval_limits.executive = 1e12;
12545
12546 let json = serde_json::to_string(&config).expect("Failed to serialize to JSON");
12547 let deserialized: GeneratorConfig =
12548 serde_json::from_str(&json).expect("Failed to deserialize from JSON");
12549
12550 assert_eq!(
12551 config.global.period_months,
12552 deserialized.global.period_months
12553 );
12554 assert_eq!(config.global.industry, deserialized.global.industry);
12555 assert_eq!(config.companies.len(), deserialized.companies.len());
12556 }
12557
12558 #[test]
12559 fn test_transaction_volume_serialization() {
12560 let volumes = vec![
12562 (TransactionVolume::TenK, "ten_k"),
12563 (TransactionVolume::HundredK, "hundred_k"),
12564 (TransactionVolume::OneM, "one_m"),
12565 (TransactionVolume::TenM, "ten_m"),
12566 (TransactionVolume::HundredM, "hundred_m"),
12567 ];
12568
12569 for (volume, expected_key) in volumes {
12570 let json = serde_json::to_string(&volume).expect("Failed to serialize");
12571 assert!(
12572 json.contains(expected_key),
12573 "Expected {} in JSON: {}",
12574 expected_key,
12575 json
12576 );
12577 }
12578 }
12579
12580 #[test]
12581 fn test_transaction_volume_custom_serialization() {
12582 let volume = TransactionVolume::Custom(12345);
12583 let json = serde_json::to_string(&volume).expect("Failed to serialize");
12584 let deserialized: TransactionVolume =
12585 serde_json::from_str(&json).expect("Failed to deserialize");
12586 assert_eq!(deserialized.count(), 12345);
12587 }
12588
12589 #[test]
12590 fn test_output_mode_serialization() {
12591 let modes = vec![
12592 OutputMode::Streaming,
12593 OutputMode::FlatFile,
12594 OutputMode::Both,
12595 ];
12596
12597 for mode in modes {
12598 let json = serde_json::to_string(&mode).expect("Failed to serialize");
12599 let deserialized: OutputMode =
12600 serde_json::from_str(&json).expect("Failed to deserialize");
12601 assert!(format!("{:?}", mode) == format!("{:?}", deserialized));
12602 }
12603 }
12604
12605 #[test]
12606 fn test_file_format_serialization() {
12607 let formats = vec![
12608 FileFormat::Csv,
12609 FileFormat::Parquet,
12610 FileFormat::Json,
12611 FileFormat::JsonLines,
12612 ];
12613
12614 for format in formats {
12615 let json = serde_json::to_string(&format).expect("Failed to serialize");
12616 let deserialized: FileFormat =
12617 serde_json::from_str(&json).expect("Failed to deserialize");
12618 assert!(format!("{:?}", format) == format!("{:?}", deserialized));
12619 }
12620 }
12621
12622 #[test]
12623 fn test_compression_algorithm_serialization() {
12624 let algos = vec![
12625 CompressionAlgorithm::Gzip,
12626 CompressionAlgorithm::Zstd,
12627 CompressionAlgorithm::Lz4,
12628 CompressionAlgorithm::Snappy,
12629 ];
12630
12631 for algo in algos {
12632 let json = serde_json::to_string(&algo).expect("Failed to serialize");
12633 let deserialized: CompressionAlgorithm =
12634 serde_json::from_str(&json).expect("Failed to deserialize");
12635 assert!(format!("{:?}", algo) == format!("{:?}", deserialized));
12636 }
12637 }
12638
12639 #[test]
12640 fn test_transfer_pricing_method_serialization() {
12641 let methods = vec![
12642 TransferPricingMethod::CostPlus,
12643 TransferPricingMethod::ComparableUncontrolled,
12644 TransferPricingMethod::ResalePrice,
12645 TransferPricingMethod::TransactionalNetMargin,
12646 TransferPricingMethod::ProfitSplit,
12647 ];
12648
12649 for method in methods {
12650 let json = serde_json::to_string(&method).expect("Failed to serialize");
12651 let deserialized: TransferPricingMethod =
12652 serde_json::from_str(&json).expect("Failed to deserialize");
12653 assert!(format!("{:?}", method) == format!("{:?}", deserialized));
12654 }
12655 }
12656
12657 #[test]
12658 fn test_benford_exemption_serialization() {
12659 let exemptions = vec![
12660 BenfordExemption::Recurring,
12661 BenfordExemption::Payroll,
12662 BenfordExemption::FixedFees,
12663 BenfordExemption::RoundAmounts,
12664 ];
12665
12666 for exemption in exemptions {
12667 let json = serde_json::to_string(&exemption).expect("Failed to serialize");
12668 let deserialized: BenfordExemption =
12669 serde_json::from_str(&json).expect("Failed to deserialize");
12670 assert!(format!("{:?}", exemption) == format!("{:?}", deserialized));
12671 }
12672 }
12673
12674 #[test]
12679 fn test_global_config_defaults() {
12680 let yaml = r#"
12681 industry: manufacturing
12682 start_date: "2024-01-01"
12683 period_months: 6
12684 "#;
12685 let config: GlobalConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12686 assert_eq!(config.group_currency, "USD");
12687 assert!(config.parallel);
12688 assert_eq!(config.worker_threads, 0);
12689 assert_eq!(config.memory_limit_mb, 0);
12690 }
12691
12692 #[test]
12693 fn test_fraud_config_defaults() {
12694 let config = FraudConfig::default();
12695 assert!(!config.enabled);
12696 assert_eq!(config.fraud_rate, 0.005);
12697 assert!(!config.clustering_enabled);
12698 }
12699
12700 #[test]
12701 fn test_internal_controls_config_defaults() {
12702 let config = InternalControlsConfig::default();
12703 assert!(!config.enabled);
12704 assert_eq!(config.exception_rate, 0.02);
12705 assert_eq!(config.sod_violation_rate, 0.01);
12706 assert!(config.export_control_master_data);
12707 assert_eq!(config.sox_materiality_threshold, 10000.0);
12708 assert!(config.coso_enabled);
12710 assert!(!config.include_entity_level_controls);
12711 assert_eq!(config.target_maturity_level, "mixed");
12712 }
12713
12714 #[test]
12715 fn test_output_config_defaults() {
12716 let config = OutputConfig::default();
12717 assert!(matches!(config.mode, OutputMode::FlatFile));
12718 assert_eq!(config.formats, vec![FileFormat::Parquet]);
12719 assert!(config.compression.enabled);
12720 assert!(matches!(
12721 config.compression.algorithm,
12722 CompressionAlgorithm::Zstd
12723 ));
12724 assert!(config.include_acdoca);
12725 assert!(!config.include_bseg);
12726 assert!(config.partition_by_period);
12727 assert!(!config.partition_by_company);
12728 }
12729
12730 #[test]
12731 fn test_approval_config_defaults() {
12732 let config = ApprovalConfig::default();
12733 assert!(!config.enabled);
12734 assert_eq!(config.auto_approve_threshold, 1000.0);
12735 assert_eq!(config.rejection_rate, 0.02);
12736 assert_eq!(config.revision_rate, 0.05);
12737 assert_eq!(config.average_approval_delay_hours, 4.0);
12738 assert_eq!(config.thresholds.len(), 4);
12739 }
12740
12741 #[test]
12742 fn test_p2p_flow_config_defaults() {
12743 let config = P2PFlowConfig::default();
12744 assert!(config.enabled);
12745 assert_eq!(config.three_way_match_rate, 0.95);
12746 assert_eq!(config.partial_delivery_rate, 0.15);
12747 assert_eq!(config.average_po_to_gr_days, 14);
12748 }
12749
12750 #[test]
12751 fn test_o2c_flow_config_defaults() {
12752 let config = O2CFlowConfig::default();
12753 assert!(config.enabled);
12754 assert_eq!(config.credit_check_failure_rate, 0.02);
12755 assert_eq!(config.return_rate, 0.03);
12756 assert_eq!(config.bad_debt_rate, 0.01);
12757 }
12758
12759 #[test]
12760 fn test_balance_config_defaults() {
12761 let config = BalanceConfig::default();
12762 assert!(!config.generate_opening_balances);
12763 assert!(config.generate_trial_balances);
12764 assert_eq!(config.target_gross_margin, 0.35);
12765 assert!(config.validate_balance_equation);
12766 assert!(config.reconcile_subledgers);
12767 }
12768
12769 #[test]
12774 fn test_partial_config_with_defaults() {
12775 let yaml = r#"
12777 global:
12778 industry: manufacturing
12779 start_date: "2024-01-01"
12780 period_months: 3
12781 companies:
12782 - code: "TEST"
12783 name: "Test Company"
12784 currency: "USD"
12785 country: "US"
12786 annual_transaction_volume: ten_k
12787 chart_of_accounts:
12788 complexity: small
12789 output:
12790 output_directory: "./output"
12791 "#;
12792
12793 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12794 assert_eq!(config.global.period_months, 3);
12795 assert_eq!(config.companies.len(), 1);
12796 assert!(!config.fraud.enabled); assert!(!config.internal_controls.enabled); }
12799
12800 #[test]
12801 fn test_config_with_fraud_enabled() {
12802 let yaml = r#"
12803 global:
12804 industry: retail
12805 start_date: "2024-01-01"
12806 period_months: 12
12807 companies:
12808 - code: "RETAIL"
12809 name: "Retail Co"
12810 currency: "USD"
12811 country: "US"
12812 annual_transaction_volume: hundred_k
12813 chart_of_accounts:
12814 complexity: medium
12815 output:
12816 output_directory: "./output"
12817 fraud:
12818 enabled: true
12819 fraud_rate: 0.05
12820 clustering_enabled: true
12821 "#;
12822
12823 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12824 assert!(config.fraud.enabled);
12825 assert_eq!(config.fraud.fraud_rate, 0.05);
12826 assert!(config.fraud.clustering_enabled);
12827 }
12828
12829 #[test]
12830 fn test_config_with_multiple_companies() {
12831 let yaml = r#"
12832 global:
12833 industry: manufacturing
12834 start_date: "2024-01-01"
12835 period_months: 6
12836 companies:
12837 - code: "HQ"
12838 name: "Headquarters"
12839 currency: "USD"
12840 country: "US"
12841 annual_transaction_volume: hundred_k
12842 volume_weight: 1.0
12843 - code: "EU"
12844 name: "European Subsidiary"
12845 currency: "EUR"
12846 country: "DE"
12847 annual_transaction_volume: hundred_k
12848 volume_weight: 0.5
12849 - code: "APAC"
12850 name: "Asia Pacific"
12851 currency: "JPY"
12852 country: "JP"
12853 annual_transaction_volume: ten_k
12854 volume_weight: 0.3
12855 chart_of_accounts:
12856 complexity: large
12857 output:
12858 output_directory: "./output"
12859 "#;
12860
12861 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12862 assert_eq!(config.companies.len(), 3);
12863 assert_eq!(config.companies[0].code, "HQ");
12864 assert_eq!(config.companies[1].currency, "EUR");
12865 assert_eq!(config.companies[2].volume_weight, 0.3);
12866 }
12867
12868 #[test]
12869 fn test_intercompany_config() {
12870 let yaml = r#"
12871 enabled: true
12872 ic_transaction_rate: 0.20
12873 transfer_pricing_method: cost_plus
12874 markup_percent: 0.08
12875 generate_matched_pairs: true
12876 generate_eliminations: true
12877 "#;
12878
12879 let config: IntercompanyConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12880 assert!(config.enabled);
12881 assert_eq!(config.ic_transaction_rate, 0.20);
12882 assert!(matches!(
12883 config.transfer_pricing_method,
12884 TransferPricingMethod::CostPlus
12885 ));
12886 assert_eq!(config.markup_percent, 0.08);
12887 assert!(config.generate_eliminations);
12888 }
12889
12890 #[test]
12895 fn test_company_config_defaults() {
12896 let yaml = r#"
12897 code: "TEST"
12898 name: "Test Company"
12899 currency: "USD"
12900 country: "US"
12901 annual_transaction_volume: ten_k
12902 "#;
12903
12904 let config: CompanyConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12905 assert_eq!(config.fiscal_year_variant, "K4"); assert_eq!(config.volume_weight, 1.0); }
12908
12909 #[test]
12914 fn test_coa_config_defaults() {
12915 let yaml = r#"
12916 complexity: medium
12917 "#;
12918
12919 let config: ChartOfAccountsConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12920 assert!(config.industry_specific); assert!(config.custom_accounts.is_none());
12922 assert_eq!(config.min_hierarchy_depth, 2); assert_eq!(config.max_hierarchy_depth, 5); }
12925
12926 #[test]
12931 fn test_accounting_standards_config_defaults() {
12932 let config = AccountingStandardsConfig::default();
12933 assert!(!config.enabled);
12934 assert!(config.framework.is_none());
12935 assert!(!config.revenue_recognition.enabled);
12936 assert!(!config.leases.enabled);
12937 assert!(!config.fair_value.enabled);
12938 assert!(!config.impairment.enabled);
12939 assert!(!config.generate_differences);
12940 }
12941
12942 #[test]
12943 fn test_accounting_standards_config_yaml() {
12944 let yaml = r#"
12945 enabled: true
12946 framework: ifrs
12947 revenue_recognition:
12948 enabled: true
12949 generate_contracts: true
12950 avg_obligations_per_contract: 2.5
12951 variable_consideration_rate: 0.20
12952 over_time_recognition_rate: 0.35
12953 contract_count: 150
12954 leases:
12955 enabled: true
12956 lease_count: 75
12957 finance_lease_percent: 0.25
12958 avg_lease_term_months: 48
12959 generate_differences: true
12960 "#;
12961
12962 let config: AccountingStandardsConfig =
12963 serde_yaml::from_str(yaml).expect("Failed to parse");
12964 assert!(config.enabled);
12965 assert!(matches!(
12966 config.framework,
12967 Some(AccountingFrameworkConfig::Ifrs)
12968 ));
12969 assert!(config.revenue_recognition.enabled);
12970 assert_eq!(config.revenue_recognition.contract_count, 150);
12971 assert_eq!(config.revenue_recognition.avg_obligations_per_contract, 2.5);
12972 assert!(config.leases.enabled);
12973 assert_eq!(config.leases.lease_count, 75);
12974 assert_eq!(config.leases.finance_lease_percent, 0.25);
12975 assert!(config.generate_differences);
12976 }
12977
12978 #[test]
12979 fn test_accounting_framework_serialization() {
12980 let frameworks = [
12981 AccountingFrameworkConfig::UsGaap,
12982 AccountingFrameworkConfig::Ifrs,
12983 AccountingFrameworkConfig::DualReporting,
12984 AccountingFrameworkConfig::FrenchGaap,
12985 AccountingFrameworkConfig::GermanGaap,
12986 ];
12987
12988 for framework in frameworks {
12989 let json = serde_json::to_string(&framework).expect("Failed to serialize");
12990 let deserialized: AccountingFrameworkConfig =
12991 serde_json::from_str(&json).expect("Failed to deserialize");
12992 assert!(format!("{:?}", framework) == format!("{:?}", deserialized));
12993 }
12994 }
12995
12996 #[test]
12997 fn test_revenue_recognition_config_defaults() {
12998 let config = RevenueRecognitionConfig::default();
12999 assert!(!config.enabled);
13000 assert!(config.generate_contracts);
13001 assert_eq!(config.avg_obligations_per_contract, 2.0);
13002 assert_eq!(config.variable_consideration_rate, 0.15);
13003 assert_eq!(config.over_time_recognition_rate, 0.30);
13004 assert_eq!(config.contract_count, 100);
13005 }
13006
13007 #[test]
13008 fn test_lease_accounting_config_defaults() {
13009 let config = LeaseAccountingConfig::default();
13010 assert!(!config.enabled);
13011 assert_eq!(config.lease_count, 50);
13012 assert_eq!(config.finance_lease_percent, 0.30);
13013 assert_eq!(config.avg_lease_term_months, 60);
13014 assert!(config.generate_amortization);
13015 assert_eq!(config.real_estate_percent, 0.40);
13016 }
13017
13018 #[test]
13019 fn test_fair_value_config_defaults() {
13020 let config = FairValueConfig::default();
13021 assert!(!config.enabled);
13022 assert_eq!(config.measurement_count, 25);
13023 assert_eq!(config.level1_percent, 0.40);
13024 assert_eq!(config.level2_percent, 0.35);
13025 assert_eq!(config.level3_percent, 0.25);
13026 assert!(!config.include_sensitivity_analysis);
13027 }
13028
13029 #[test]
13030 fn test_impairment_config_defaults() {
13031 let config = ImpairmentConfig::default();
13032 assert!(!config.enabled);
13033 assert_eq!(config.test_count, 15);
13034 assert_eq!(config.impairment_rate, 0.10);
13035 assert!(config.generate_projections);
13036 assert!(!config.include_goodwill);
13037 }
13038
13039 #[test]
13044 fn test_audit_standards_config_defaults() {
13045 let config = AuditStandardsConfig::default();
13046 assert!(!config.enabled);
13047 assert!(!config.isa_compliance.enabled);
13048 assert!(!config.analytical_procedures.enabled);
13049 assert!(!config.confirmations.enabled);
13050 assert!(!config.opinion.enabled);
13051 assert!(!config.generate_audit_trail);
13052 assert!(!config.sox.enabled);
13053 assert!(!config.pcaob.enabled);
13054 }
13055
13056 #[test]
13057 fn test_audit_standards_config_yaml() {
13058 let yaml = r#"
13059 enabled: true
13060 isa_compliance:
13061 enabled: true
13062 compliance_level: comprehensive
13063 generate_isa_mappings: true
13064 include_pcaob: true
13065 framework: dual
13066 analytical_procedures:
13067 enabled: true
13068 procedures_per_account: 5
13069 variance_probability: 0.25
13070 confirmations:
13071 enabled: true
13072 confirmation_count: 75
13073 positive_response_rate: 0.90
13074 exception_rate: 0.08
13075 opinion:
13076 enabled: true
13077 generate_kam: true
13078 average_kam_count: 4
13079 sox:
13080 enabled: true
13081 generate_302_certifications: true
13082 generate_404_assessments: true
13083 material_weakness_rate: 0.03
13084 pcaob:
13085 enabled: true
13086 is_pcaob_audit: true
13087 include_icfr_opinion: true
13088 generate_audit_trail: true
13089 "#;
13090
13091 let config: AuditStandardsConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13092 assert!(config.enabled);
13093 assert!(config.isa_compliance.enabled);
13094 assert_eq!(config.isa_compliance.compliance_level, "comprehensive");
13095 assert!(config.isa_compliance.include_pcaob);
13096 assert_eq!(config.isa_compliance.framework, "dual");
13097 assert!(config.analytical_procedures.enabled);
13098 assert_eq!(config.analytical_procedures.procedures_per_account, 5);
13099 assert!(config.confirmations.enabled);
13100 assert_eq!(config.confirmations.confirmation_count, 75);
13101 assert!(config.opinion.enabled);
13102 assert_eq!(config.opinion.average_kam_count, 4);
13103 assert!(config.sox.enabled);
13104 assert!(config.sox.generate_302_certifications);
13105 assert_eq!(config.sox.material_weakness_rate, 0.03);
13106 assert!(config.pcaob.enabled);
13107 assert!(config.pcaob.is_pcaob_audit);
13108 assert!(config.pcaob.include_icfr_opinion);
13109 assert!(config.generate_audit_trail);
13110 }
13111
13112 #[test]
13113 fn test_isa_compliance_config_defaults() {
13114 let config = IsaComplianceConfig::default();
13115 assert!(!config.enabled);
13116 assert_eq!(config.compliance_level, "standard");
13117 assert!(config.generate_isa_mappings);
13118 assert!(config.generate_coverage_summary);
13119 assert!(!config.include_pcaob);
13120 assert_eq!(config.framework, "isa");
13121 }
13122
13123 #[test]
13124 fn test_sox_compliance_config_defaults() {
13125 let config = SoxComplianceConfig::default();
13126 assert!(!config.enabled);
13127 assert!(config.generate_302_certifications);
13128 assert!(config.generate_404_assessments);
13129 assert_eq!(config.materiality_threshold, 10000.0);
13130 assert_eq!(config.material_weakness_rate, 0.02);
13131 assert_eq!(config.significant_deficiency_rate, 0.08);
13132 }
13133
13134 #[test]
13135 fn test_pcaob_config_defaults() {
13136 let config = PcaobConfig::default();
13137 assert!(!config.enabled);
13138 assert!(!config.is_pcaob_audit);
13139 assert!(config.generate_cam);
13140 assert!(!config.include_icfr_opinion);
13141 assert!(!config.generate_standard_mappings);
13142 }
13143
13144 #[test]
13145 fn test_config_with_standards_enabled() {
13146 let yaml = r#"
13147 global:
13148 industry: financial_services
13149 start_date: "2024-01-01"
13150 period_months: 12
13151 companies:
13152 - code: "BANK"
13153 name: "Test Bank"
13154 currency: "USD"
13155 country: "US"
13156 annual_transaction_volume: hundred_k
13157 chart_of_accounts:
13158 complexity: large
13159 output:
13160 output_directory: "./output"
13161 accounting_standards:
13162 enabled: true
13163 framework: us_gaap
13164 revenue_recognition:
13165 enabled: true
13166 leases:
13167 enabled: true
13168 audit_standards:
13169 enabled: true
13170 isa_compliance:
13171 enabled: true
13172 sox:
13173 enabled: true
13174 "#;
13175
13176 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13177 assert!(config.accounting_standards.enabled);
13178 assert!(matches!(
13179 config.accounting_standards.framework,
13180 Some(AccountingFrameworkConfig::UsGaap)
13181 ));
13182 assert!(config.accounting_standards.revenue_recognition.enabled);
13183 assert!(config.accounting_standards.leases.enabled);
13184 assert!(config.audit_standards.enabled);
13185 assert!(config.audit_standards.isa_compliance.enabled);
13186 assert!(config.audit_standards.sox.enabled);
13187 }
13188
13189 #[test]
13194 fn test_industry_specific_config_defaults() {
13195 let config = IndustrySpecificConfig::default();
13196 assert!(!config.enabled);
13197 assert!(!config.manufacturing.enabled);
13198 assert!(!config.retail.enabled);
13199 assert!(!config.healthcare.enabled);
13200 assert!(!config.technology.enabled);
13201 assert!(!config.financial_services.enabled);
13202 assert!(!config.professional_services.enabled);
13203 }
13204
13205 #[test]
13206 fn test_manufacturing_config_defaults() {
13207 let config = ManufacturingConfig::default();
13208 assert!(!config.enabled);
13209 assert_eq!(config.bom_depth, 4);
13210 assert!(!config.just_in_time);
13211 assert_eq!(config.supplier_tiers, 2);
13212 assert_eq!(config.target_yield_rate, 0.97);
13213 assert_eq!(config.scrap_alert_threshold, 0.03);
13214 }
13215
13216 #[test]
13217 fn test_retail_config_defaults() {
13218 let config = RetailConfig::default();
13219 assert!(!config.enabled);
13220 assert_eq!(config.avg_daily_transactions, 500);
13221 assert!(config.loss_prevention);
13222 assert_eq!(config.shrinkage_rate, 0.015);
13223 }
13224
13225 #[test]
13226 fn test_healthcare_config_defaults() {
13227 let config = HealthcareConfig::default();
13228 assert!(!config.enabled);
13229 assert_eq!(config.facility_type, "hospital");
13230 assert_eq!(config.avg_daily_encounters, 150);
13231 assert!(config.compliance.hipaa);
13232 assert!(config.compliance.stark_law);
13233 assert!(config.coding_systems.icd10);
13234 assert!(config.coding_systems.cpt);
13235 }
13236
13237 #[test]
13238 fn test_technology_config_defaults() {
13239 let config = TechnologyConfig::default();
13240 assert!(!config.enabled);
13241 assert_eq!(config.revenue_model, "saas");
13242 assert_eq!(config.subscription_revenue_pct, 0.60);
13243 assert!(config.rd_capitalization.enabled);
13244 }
13245
13246 #[test]
13247 fn test_config_with_industry_specific() {
13248 let yaml = r#"
13249 global:
13250 industry: healthcare
13251 start_date: "2024-01-01"
13252 period_months: 12
13253 companies:
13254 - code: "HOSP"
13255 name: "Test Hospital"
13256 currency: "USD"
13257 country: "US"
13258 annual_transaction_volume: hundred_k
13259 chart_of_accounts:
13260 complexity: medium
13261 output:
13262 output_directory: "./output"
13263 industry_specific:
13264 enabled: true
13265 healthcare:
13266 enabled: true
13267 facility_type: hospital
13268 payer_mix:
13269 medicare: 0.45
13270 medicaid: 0.15
13271 commercial: 0.35
13272 self_pay: 0.05
13273 coding_systems:
13274 icd10: true
13275 cpt: true
13276 drg: true
13277 compliance:
13278 hipaa: true
13279 stark_law: true
13280 anomaly_rates:
13281 upcoding: 0.03
13282 unbundling: 0.02
13283 "#;
13284
13285 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13286 assert!(config.industry_specific.enabled);
13287 assert!(config.industry_specific.healthcare.enabled);
13288 assert_eq!(
13289 config.industry_specific.healthcare.facility_type,
13290 "hospital"
13291 );
13292 assert_eq!(config.industry_specific.healthcare.payer_mix.medicare, 0.45);
13293 assert_eq!(config.industry_specific.healthcare.payer_mix.self_pay, 0.05);
13294 assert!(config.industry_specific.healthcare.coding_systems.icd10);
13295 assert!(config.industry_specific.healthcare.compliance.hipaa);
13296 assert_eq!(
13297 config.industry_specific.healthcare.anomaly_rates.upcoding,
13298 0.03
13299 );
13300 }
13301
13302 #[test]
13303 fn test_config_with_manufacturing_specific() {
13304 let yaml = r#"
13305 global:
13306 industry: manufacturing
13307 start_date: "2024-01-01"
13308 period_months: 12
13309 companies:
13310 - code: "MFG"
13311 name: "Test Manufacturing"
13312 currency: "USD"
13313 country: "US"
13314 annual_transaction_volume: hundred_k
13315 chart_of_accounts:
13316 complexity: medium
13317 output:
13318 output_directory: "./output"
13319 industry_specific:
13320 enabled: true
13321 manufacturing:
13322 enabled: true
13323 bom_depth: 5
13324 just_in_time: true
13325 supplier_tiers: 3
13326 target_yield_rate: 0.98
13327 anomaly_rates:
13328 yield_manipulation: 0.02
13329 phantom_production: 0.01
13330 "#;
13331
13332 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13333 assert!(config.industry_specific.enabled);
13334 assert!(config.industry_specific.manufacturing.enabled);
13335 assert_eq!(config.industry_specific.manufacturing.bom_depth, 5);
13336 assert!(config.industry_specific.manufacturing.just_in_time);
13337 assert_eq!(config.industry_specific.manufacturing.supplier_tiers, 3);
13338 assert_eq!(
13339 config.industry_specific.manufacturing.target_yield_rate,
13340 0.98
13341 );
13342 assert_eq!(
13343 config
13344 .industry_specific
13345 .manufacturing
13346 .anomaly_rates
13347 .yield_manipulation,
13348 0.02
13349 );
13350 }
13351
13352 #[test]
13357 fn test_tax_config_defaults() {
13358 let tax = TaxConfig::default();
13359 assert!(!tax.enabled);
13360 assert!(tax.jurisdictions.countries.is_empty());
13361 assert!(!tax.jurisdictions.include_subnational);
13362 assert!(!tax.vat_gst.enabled);
13363 assert!(tax.vat_gst.standard_rates.is_empty());
13364 assert!(tax.vat_gst.reduced_rates.is_empty());
13365 assert!(tax.vat_gst.exempt_categories.is_empty());
13366 assert!(tax.vat_gst.reverse_charge);
13367 assert!(!tax.sales_tax.enabled);
13368 assert!(tax.sales_tax.nexus_states.is_empty());
13369 assert!(!tax.withholding.enabled);
13370 assert!(tax.withholding.treaty_network);
13371 assert_eq!(tax.withholding.default_rate, 0.30);
13372 assert_eq!(tax.withholding.treaty_reduced_rate, 0.15);
13373 assert!(tax.provisions.enabled);
13374 assert_eq!(tax.provisions.statutory_rate, 0.21);
13375 assert!(tax.provisions.uncertain_positions);
13376 assert!(!tax.payroll_tax.enabled);
13377 assert_eq!(tax.anomaly_rate, 0.03);
13378 }
13379
13380 #[test]
13381 fn test_tax_config_from_yaml() {
13382 let yaml = r#"
13383 global:
13384 seed: 42
13385 start_date: "2024-01-01"
13386 period_months: 12
13387 industry: retail
13388 companies:
13389 - code: C001
13390 name: Test Corp
13391 currency: USD
13392 country: US
13393 annual_transaction_volume: ten_k
13394 chart_of_accounts:
13395 complexity: small
13396 output:
13397 output_directory: ./output
13398 tax:
13399 enabled: true
13400 anomaly_rate: 0.05
13401 jurisdictions:
13402 countries: ["US", "DE", "GB"]
13403 include_subnational: true
13404 vat_gst:
13405 enabled: true
13406 standard_rates:
13407 DE: 0.19
13408 GB: 0.20
13409 reduced_rates:
13410 DE: 0.07
13411 GB: 0.05
13412 exempt_categories:
13413 - financial_services
13414 - healthcare
13415 reverse_charge: false
13416 sales_tax:
13417 enabled: true
13418 nexus_states: ["CA", "NY", "TX"]
13419 withholding:
13420 enabled: true
13421 treaty_network: false
13422 default_rate: 0.25
13423 treaty_reduced_rate: 0.10
13424 provisions:
13425 enabled: false
13426 statutory_rate: 0.28
13427 uncertain_positions: false
13428 payroll_tax:
13429 enabled: true
13430 "#;
13431
13432 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13433 assert!(config.tax.enabled);
13434 assert_eq!(config.tax.anomaly_rate, 0.05);
13435
13436 assert_eq!(config.tax.jurisdictions.countries.len(), 3);
13438 assert!(config
13439 .tax
13440 .jurisdictions
13441 .countries
13442 .contains(&"DE".to_string()));
13443 assert!(config.tax.jurisdictions.include_subnational);
13444
13445 assert!(config.tax.vat_gst.enabled);
13447 assert_eq!(config.tax.vat_gst.standard_rates.get("DE"), Some(&0.19));
13448 assert_eq!(config.tax.vat_gst.standard_rates.get("GB"), Some(&0.20));
13449 assert_eq!(config.tax.vat_gst.reduced_rates.get("DE"), Some(&0.07));
13450 assert_eq!(config.tax.vat_gst.exempt_categories.len(), 2);
13451 assert!(!config.tax.vat_gst.reverse_charge);
13452
13453 assert!(config.tax.sales_tax.enabled);
13455 assert_eq!(config.tax.sales_tax.nexus_states.len(), 3);
13456 assert!(config
13457 .tax
13458 .sales_tax
13459 .nexus_states
13460 .contains(&"CA".to_string()));
13461
13462 assert!(config.tax.withholding.enabled);
13464 assert!(!config.tax.withholding.treaty_network);
13465 assert_eq!(config.tax.withholding.default_rate, 0.25);
13466 assert_eq!(config.tax.withholding.treaty_reduced_rate, 0.10);
13467
13468 assert!(!config.tax.provisions.enabled);
13470 assert_eq!(config.tax.provisions.statutory_rate, 0.28);
13471 assert!(!config.tax.provisions.uncertain_positions);
13472
13473 assert!(config.tax.payroll_tax.enabled);
13475 }
13476
13477 #[test]
13478 fn test_generator_config_with_tax_default() {
13479 let yaml = r#"
13480 global:
13481 seed: 42
13482 start_date: "2024-01-01"
13483 period_months: 12
13484 industry: retail
13485 companies:
13486 - code: C001
13487 name: Test Corp
13488 currency: USD
13489 country: US
13490 annual_transaction_volume: ten_k
13491 chart_of_accounts:
13492 complexity: small
13493 output:
13494 output_directory: ./output
13495 "#;
13496
13497 let config: GeneratorConfig =
13498 serde_yaml::from_str(yaml).expect("Failed to parse config without tax section");
13499 assert!(!config.tax.enabled);
13501 assert!(config.tax.jurisdictions.countries.is_empty());
13502 assert_eq!(config.tax.anomaly_rate, 0.03);
13503 assert!(config.tax.provisions.enabled); assert_eq!(config.tax.provisions.statutory_rate, 0.21);
13505 }
13506
13507 #[test]
13512 fn test_session_config_default_disabled() {
13513 let yaml = "{}";
13514 let config: SessionSchemaConfig =
13515 serde_yaml::from_str(yaml).expect("Failed to parse empty session config");
13516 assert!(!config.enabled);
13517 assert!(config.checkpoint_path.is_none());
13518 assert!(config.per_period_output);
13519 assert!(config.consolidated_output);
13520 }
13521
13522 #[test]
13523 fn test_config_backward_compatible_without_session() {
13524 let yaml = r#"
13525 global:
13526 seed: 42
13527 start_date: "2024-01-01"
13528 period_months: 12
13529 industry: retail
13530 companies:
13531 - code: C001
13532 name: Test Corp
13533 currency: USD
13534 country: US
13535 annual_transaction_volume: ten_k
13536 chart_of_accounts:
13537 complexity: small
13538 output:
13539 output_directory: ./output
13540 "#;
13541
13542 let config: GeneratorConfig =
13543 serde_yaml::from_str(yaml).expect("Failed to parse config without session");
13544 assert!(!config.session.enabled);
13546 assert!(config.session.per_period_output);
13547 assert!(config.session.consolidated_output);
13548 assert!(config.global.fiscal_year_months.is_none());
13550 }
13551
13552 #[test]
13553 fn test_fiscal_year_months_parsed() {
13554 let yaml = r#"
13555 global:
13556 seed: 42
13557 start_date: "2024-01-01"
13558 period_months: 24
13559 industry: retail
13560 fiscal_year_months: 12
13561 companies:
13562 - code: C001
13563 name: Test Corp
13564 currency: USD
13565 country: US
13566 annual_transaction_volume: ten_k
13567 chart_of_accounts:
13568 complexity: small
13569 output:
13570 output_directory: ./output
13571 session:
13572 enabled: true
13573 checkpoint_path: /tmp/checkpoints
13574 per_period_output: true
13575 consolidated_output: false
13576 "#;
13577
13578 let config: GeneratorConfig =
13579 serde_yaml::from_str(yaml).expect("Failed to parse config with fiscal_year_months");
13580 assert_eq!(config.global.fiscal_year_months, Some(12));
13581 assert!(config.session.enabled);
13582 assert_eq!(
13583 config.session.checkpoint_path,
13584 Some("/tmp/checkpoints".to_string())
13585 );
13586 assert!(config.session.per_period_output);
13587 assert!(!config.session.consolidated_output);
13588 }
13589}