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}
187
188#[derive(Debug, Clone, Serialize, Deserialize)]
194pub struct LlmSchemaConfig {
195 #[serde(default)]
197 pub enabled: bool,
198 #[serde(default = "default_llm_provider")]
200 pub provider: String,
201 #[serde(default = "default_llm_model_name")]
203 pub model: String,
204 #[serde(default = "default_llm_batch_size")]
206 pub max_vendor_enrichments: usize,
207}
208
209fn default_llm_provider() -> String {
210 "mock".to_string()
211}
212
213fn default_llm_model_name() -> String {
214 "gpt-4o-mini".to_string()
215}
216
217fn default_llm_batch_size() -> usize {
218 50
219}
220
221impl Default for LlmSchemaConfig {
222 fn default() -> Self {
223 Self {
224 enabled: false,
225 provider: default_llm_provider(),
226 model: default_llm_model_name(),
227 max_vendor_enrichments: default_llm_batch_size(),
228 }
229 }
230}
231
232#[derive(Debug, Clone, Serialize, Deserialize)]
237pub struct DiffusionSchemaConfig {
238 #[serde(default)]
240 pub enabled: bool,
241 #[serde(default = "default_diffusion_steps")]
243 pub n_steps: usize,
244 #[serde(default = "default_diffusion_schedule")]
246 pub schedule: String,
247 #[serde(default = "default_diffusion_sample_size")]
249 pub sample_size: usize,
250}
251
252fn default_diffusion_steps() -> usize {
253 100
254}
255
256fn default_diffusion_schedule() -> String {
257 "linear".to_string()
258}
259
260fn default_diffusion_sample_size() -> usize {
261 100
262}
263
264impl Default for DiffusionSchemaConfig {
265 fn default() -> Self {
266 Self {
267 enabled: false,
268 n_steps: default_diffusion_steps(),
269 schedule: default_diffusion_schedule(),
270 sample_size: default_diffusion_sample_size(),
271 }
272 }
273}
274
275#[derive(Debug, Clone, Serialize, Deserialize)]
281pub struct CausalSchemaConfig {
282 #[serde(default)]
284 pub enabled: bool,
285 #[serde(default = "default_causal_template")]
287 pub template: String,
288 #[serde(default = "default_causal_sample_size")]
290 pub sample_size: usize,
291 #[serde(default = "default_true")]
293 pub validate: bool,
294}
295
296fn default_causal_template() -> String {
297 "fraud_detection".to_string()
298}
299
300fn default_causal_sample_size() -> usize {
301 500
302}
303
304impl Default for CausalSchemaConfig {
305 fn default() -> Self {
306 Self {
307 enabled: false,
308 template: default_causal_template(),
309 sample_size: default_causal_sample_size(),
310 validate: true,
311 }
312 }
313}
314
315#[derive(Debug, Clone, Serialize, Deserialize)]
322pub struct GraphExportConfig {
323 #[serde(default)]
325 pub enabled: bool,
326
327 #[serde(default = "default_graph_types")]
329 pub graph_types: Vec<GraphTypeConfig>,
330
331 #[serde(default = "default_graph_formats")]
333 pub formats: Vec<GraphExportFormat>,
334
335 #[serde(default = "default_train_ratio")]
337 pub train_ratio: f64,
338
339 #[serde(default = "default_val_ratio")]
341 pub validation_ratio: f64,
342
343 #[serde(default)]
345 pub split_seed: Option<u64>,
346
347 #[serde(default = "default_graph_subdir")]
349 pub output_subdirectory: String,
350
351 #[serde(default)]
353 pub hypergraph: HypergraphExportSettings,
354}
355
356fn default_graph_types() -> Vec<GraphTypeConfig> {
357 vec![GraphTypeConfig::default()]
358}
359
360fn default_graph_formats() -> Vec<GraphExportFormat> {
361 vec![GraphExportFormat::PytorchGeometric]
362}
363
364fn default_train_ratio() -> f64 {
365 0.7
366}
367
368fn default_val_ratio() -> f64 {
369 0.15
370}
371
372fn default_graph_subdir() -> String {
373 "graphs".to_string()
374}
375
376impl Default for GraphExportConfig {
377 fn default() -> Self {
378 Self {
379 enabled: false,
380 graph_types: default_graph_types(),
381 formats: default_graph_formats(),
382 train_ratio: 0.7,
383 validation_ratio: 0.15,
384 split_seed: None,
385 output_subdirectory: "graphs".to_string(),
386 hypergraph: HypergraphExportSettings::default(),
387 }
388 }
389}
390
391#[derive(Debug, Clone, Serialize, Deserialize)]
398pub struct HypergraphExportSettings {
399 #[serde(default)]
401 pub enabled: bool,
402
403 #[serde(default = "default_hypergraph_max_nodes")]
405 pub max_nodes: usize,
406
407 #[serde(default = "default_aggregation_strategy")]
409 pub aggregation_strategy: String,
410
411 #[serde(default)]
413 pub governance_layer: GovernanceLayerSettings,
414
415 #[serde(default)]
417 pub process_layer: ProcessLayerSettings,
418
419 #[serde(default)]
421 pub accounting_layer: AccountingLayerSettings,
422
423 #[serde(default)]
425 pub cross_layer: CrossLayerSettings,
426
427 #[serde(default = "default_hypergraph_subdir")]
429 pub output_subdirectory: String,
430
431 #[serde(default = "default_hypergraph_format")]
433 pub output_format: String,
434
435 #[serde(default)]
437 pub stream_target: Option<String>,
438
439 #[serde(default = "default_stream_batch_size")]
441 pub stream_batch_size: usize,
442}
443
444fn default_hypergraph_max_nodes() -> usize {
445 50_000
446}
447
448fn default_aggregation_strategy() -> String {
449 "pool_by_counterparty".to_string()
450}
451
452fn default_hypergraph_subdir() -> String {
453 "hypergraph".to_string()
454}
455
456fn default_hypergraph_format() -> String {
457 "native".to_string()
458}
459
460fn default_stream_batch_size() -> usize {
461 1000
462}
463
464impl Default for HypergraphExportSettings {
465 fn default() -> Self {
466 Self {
467 enabled: false,
468 max_nodes: 50_000,
469 aggregation_strategy: "pool_by_counterparty".to_string(),
470 governance_layer: GovernanceLayerSettings::default(),
471 process_layer: ProcessLayerSettings::default(),
472 accounting_layer: AccountingLayerSettings::default(),
473 cross_layer: CrossLayerSettings::default(),
474 output_subdirectory: "hypergraph".to_string(),
475 output_format: "native".to_string(),
476 stream_target: None,
477 stream_batch_size: 1000,
478 }
479 }
480}
481
482#[derive(Debug, Clone, Serialize, Deserialize)]
484pub struct GovernanceLayerSettings {
485 #[serde(default = "default_true")]
487 pub include_coso: bool,
488 #[serde(default = "default_true")]
490 pub include_controls: bool,
491 #[serde(default = "default_true")]
493 pub include_sox: bool,
494 #[serde(default = "default_true")]
496 pub include_vendors: bool,
497 #[serde(default = "default_true")]
499 pub include_customers: bool,
500 #[serde(default = "default_true")]
502 pub include_employees: bool,
503}
504
505impl Default for GovernanceLayerSettings {
506 fn default() -> Self {
507 Self {
508 include_coso: true,
509 include_controls: true,
510 include_sox: true,
511 include_vendors: true,
512 include_customers: true,
513 include_employees: true,
514 }
515 }
516}
517
518#[derive(Debug, Clone, Serialize, Deserialize)]
520pub struct ProcessLayerSettings {
521 #[serde(default = "default_true")]
523 pub include_p2p: bool,
524 #[serde(default = "default_true")]
526 pub include_o2c: bool,
527 #[serde(default = "default_true")]
529 pub include_s2c: bool,
530 #[serde(default = "default_true")]
532 pub include_h2r: bool,
533 #[serde(default = "default_true")]
535 pub include_mfg: bool,
536 #[serde(default = "default_true")]
538 pub include_bank: bool,
539 #[serde(default = "default_true")]
541 pub include_audit: bool,
542 #[serde(default = "default_true")]
544 pub include_r2r: bool,
545 #[serde(default = "default_true")]
547 pub events_as_hyperedges: bool,
548 #[serde(default = "default_docs_per_counterparty_threshold")]
550 pub docs_per_counterparty_threshold: usize,
551}
552
553fn default_docs_per_counterparty_threshold() -> usize {
554 20
555}
556
557impl Default for ProcessLayerSettings {
558 fn default() -> Self {
559 Self {
560 include_p2p: true,
561 include_o2c: true,
562 include_s2c: true,
563 include_h2r: true,
564 include_mfg: true,
565 include_bank: true,
566 include_audit: true,
567 include_r2r: true,
568 events_as_hyperedges: true,
569 docs_per_counterparty_threshold: 20,
570 }
571 }
572}
573
574#[derive(Debug, Clone, Serialize, Deserialize)]
576pub struct AccountingLayerSettings {
577 #[serde(default = "default_true")]
579 pub include_accounts: bool,
580 #[serde(default = "default_true")]
582 pub je_as_hyperedges: bool,
583}
584
585impl Default for AccountingLayerSettings {
586 fn default() -> Self {
587 Self {
588 include_accounts: true,
589 je_as_hyperedges: true,
590 }
591 }
592}
593
594#[derive(Debug, Clone, Serialize, Deserialize)]
596pub struct CrossLayerSettings {
597 #[serde(default = "default_true")]
599 pub enabled: bool,
600}
601
602impl Default for CrossLayerSettings {
603 fn default() -> Self {
604 Self { enabled: true }
605 }
606}
607
608#[derive(Debug, Clone, Serialize, Deserialize)]
610pub struct GraphTypeConfig {
611 #[serde(default = "default_graph_name")]
613 pub name: String,
614
615 #[serde(default)]
617 pub aggregate_edges: bool,
618
619 #[serde(default)]
621 pub min_edge_weight: f64,
622
623 #[serde(default)]
625 pub include_document_nodes: bool,
626}
627
628fn default_graph_name() -> String {
629 "accounting_network".to_string()
630}
631
632impl Default for GraphTypeConfig {
633 fn default() -> Self {
634 Self {
635 name: "accounting_network".to_string(),
636 aggregate_edges: false,
637 min_edge_weight: 0.0,
638 include_document_nodes: false,
639 }
640 }
641}
642
643#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
645#[serde(rename_all = "snake_case")]
646pub enum GraphExportFormat {
647 PytorchGeometric,
649 Neo4j,
651 Dgl,
653 RustGraph,
655 RustGraphHypergraph,
657}
658
659#[derive(Debug, Clone, Default, Serialize, Deserialize)]
663pub struct ScenarioConfig {
664 #[serde(default)]
667 pub tags: Vec<String>,
668
669 #[serde(default)]
674 pub profile: Option<String>,
675
676 #[serde(default)]
678 pub description: Option<String>,
679
680 #[serde(default)]
682 pub ml_training: bool,
683
684 #[serde(default)]
687 pub target_anomaly_ratio: Option<f64>,
688
689 #[serde(default)]
691 pub metadata: std::collections::HashMap<String, String>,
692}
693
694#[derive(Debug, Clone, Serialize, Deserialize)]
699pub struct TemporalDriftConfig {
700 #[serde(default)]
702 pub enabled: bool,
703
704 #[serde(default = "default_amount_drift")]
707 pub amount_mean_drift: f64,
708
709 #[serde(default)]
712 pub amount_variance_drift: f64,
713
714 #[serde(default)]
717 pub anomaly_rate_drift: f64,
718
719 #[serde(default = "default_concept_drift")]
722 pub concept_drift_rate: f64,
723
724 #[serde(default)]
726 pub sudden_drift_probability: f64,
727
728 #[serde(default = "default_sudden_drift_magnitude")]
730 pub sudden_drift_magnitude: f64,
731
732 #[serde(default)]
734 pub seasonal_drift: bool,
735
736 #[serde(default)]
738 pub drift_start_period: u32,
739
740 #[serde(default = "default_drift_type")]
742 pub drift_type: DriftType,
743}
744
745fn default_amount_drift() -> f64 {
746 0.02
747}
748
749fn default_concept_drift() -> f64 {
750 0.01
751}
752
753fn default_sudden_drift_magnitude() -> f64 {
754 2.0
755}
756
757fn default_drift_type() -> DriftType {
758 DriftType::Gradual
759}
760
761impl Default for TemporalDriftConfig {
762 fn default() -> Self {
763 Self {
764 enabled: false,
765 amount_mean_drift: 0.02,
766 amount_variance_drift: 0.0,
767 anomaly_rate_drift: 0.0,
768 concept_drift_rate: 0.01,
769 sudden_drift_probability: 0.0,
770 sudden_drift_magnitude: 2.0,
771 seasonal_drift: false,
772 drift_start_period: 0,
773 drift_type: DriftType::Gradual,
774 }
775 }
776}
777
778impl TemporalDriftConfig {
779 pub fn to_core_config(&self) -> datasynth_core::distributions::DriftConfig {
781 datasynth_core::distributions::DriftConfig {
782 enabled: self.enabled,
783 amount_mean_drift: self.amount_mean_drift,
784 amount_variance_drift: self.amount_variance_drift,
785 anomaly_rate_drift: self.anomaly_rate_drift,
786 concept_drift_rate: self.concept_drift_rate,
787 sudden_drift_probability: self.sudden_drift_probability,
788 sudden_drift_magnitude: self.sudden_drift_magnitude,
789 seasonal_drift: self.seasonal_drift,
790 drift_start_period: self.drift_start_period,
791 drift_type: match self.drift_type {
792 DriftType::Gradual => datasynth_core::distributions::DriftType::Gradual,
793 DriftType::Sudden => datasynth_core::distributions::DriftType::Sudden,
794 DriftType::Recurring => datasynth_core::distributions::DriftType::Recurring,
795 DriftType::Mixed => datasynth_core::distributions::DriftType::Mixed,
796 },
797 regime_changes: Vec::new(),
798 economic_cycle: Default::default(),
799 parameter_drifts: Vec::new(),
800 }
801 }
802}
803
804#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
806#[serde(rename_all = "snake_case")]
807pub enum DriftType {
808 #[default]
810 Gradual,
811 Sudden,
813 Recurring,
815 Mixed,
817}
818
819#[derive(Debug, Clone, Serialize, Deserialize)]
825pub struct StreamingSchemaConfig {
826 #[serde(default)]
828 pub enabled: bool,
829 #[serde(default = "default_buffer_size")]
831 pub buffer_size: usize,
832 #[serde(default = "default_true")]
834 pub enable_progress: bool,
835 #[serde(default = "default_progress_interval")]
837 pub progress_interval: u64,
838 #[serde(default)]
840 pub backpressure: BackpressureSchemaStrategy,
841}
842
843fn default_buffer_size() -> usize {
844 1000
845}
846
847fn default_progress_interval() -> u64 {
848 100
849}
850
851impl Default for StreamingSchemaConfig {
852 fn default() -> Self {
853 Self {
854 enabled: false,
855 buffer_size: 1000,
856 enable_progress: true,
857 progress_interval: 100,
858 backpressure: BackpressureSchemaStrategy::Block,
859 }
860 }
861}
862
863#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
865#[serde(rename_all = "snake_case")]
866pub enum BackpressureSchemaStrategy {
867 #[default]
869 Block,
870 DropOldest,
872 DropNewest,
874 Buffer,
876}
877
878#[derive(Debug, Clone, Serialize, Deserialize)]
884pub struct RateLimitSchemaConfig {
885 #[serde(default)]
887 pub enabled: bool,
888 #[serde(default = "default_entities_per_second")]
890 pub entities_per_second: f64,
891 #[serde(default = "default_burst_size")]
893 pub burst_size: u32,
894 #[serde(default)]
896 pub backpressure: RateLimitBackpressureSchema,
897}
898
899fn default_entities_per_second() -> f64 {
900 1000.0
901}
902
903fn default_burst_size() -> u32 {
904 100
905}
906
907impl Default for RateLimitSchemaConfig {
908 fn default() -> Self {
909 Self {
910 enabled: false,
911 entities_per_second: 1000.0,
912 burst_size: 100,
913 backpressure: RateLimitBackpressureSchema::Block,
914 }
915 }
916}
917
918#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
920#[serde(rename_all = "snake_case")]
921pub enum RateLimitBackpressureSchema {
922 #[default]
924 Block,
925 Drop,
927 Buffer,
929}
930
931#[derive(Debug, Clone, Serialize, Deserialize)]
937pub struct TemporalAttributeSchemaConfig {
938 #[serde(default)]
940 pub enabled: bool,
941 #[serde(default)]
943 pub valid_time: ValidTimeSchemaConfig,
944 #[serde(default)]
946 pub transaction_time: TransactionTimeSchemaConfig,
947 #[serde(default)]
949 pub generate_version_chains: bool,
950 #[serde(default = "default_avg_versions")]
952 pub avg_versions_per_entity: f64,
953}
954
955fn default_avg_versions() -> f64 {
956 1.5
957}
958
959impl Default for TemporalAttributeSchemaConfig {
960 fn default() -> Self {
961 Self {
962 enabled: false,
963 valid_time: ValidTimeSchemaConfig::default(),
964 transaction_time: TransactionTimeSchemaConfig::default(),
965 generate_version_chains: false,
966 avg_versions_per_entity: 1.5,
967 }
968 }
969}
970
971#[derive(Debug, Clone, Serialize, Deserialize)]
973pub struct ValidTimeSchemaConfig {
974 #[serde(default = "default_closed_probability")]
976 pub closed_probability: f64,
977 #[serde(default = "default_avg_validity_days")]
979 pub avg_validity_days: u32,
980 #[serde(default = "default_validity_stddev")]
982 pub validity_stddev_days: u32,
983}
984
985fn default_closed_probability() -> f64 {
986 0.1
987}
988
989fn default_avg_validity_days() -> u32 {
990 365
991}
992
993fn default_validity_stddev() -> u32 {
994 90
995}
996
997impl Default for ValidTimeSchemaConfig {
998 fn default() -> Self {
999 Self {
1000 closed_probability: 0.1,
1001 avg_validity_days: 365,
1002 validity_stddev_days: 90,
1003 }
1004 }
1005}
1006
1007#[derive(Debug, Clone, Serialize, Deserialize)]
1009pub struct TransactionTimeSchemaConfig {
1010 #[serde(default)]
1012 pub avg_recording_delay_seconds: u32,
1013 #[serde(default)]
1015 pub allow_backdating: bool,
1016 #[serde(default = "default_backdating_probability")]
1018 pub backdating_probability: f64,
1019 #[serde(default = "default_max_backdate_days")]
1021 pub max_backdate_days: u32,
1022}
1023
1024fn default_backdating_probability() -> f64 {
1025 0.01
1026}
1027
1028fn default_max_backdate_days() -> u32 {
1029 30
1030}
1031
1032impl Default for TransactionTimeSchemaConfig {
1033 fn default() -> Self {
1034 Self {
1035 avg_recording_delay_seconds: 0,
1036 allow_backdating: false,
1037 backdating_probability: 0.01,
1038 max_backdate_days: 30,
1039 }
1040 }
1041}
1042
1043#[derive(Debug, Clone, Serialize, Deserialize)]
1049pub struct RelationshipSchemaConfig {
1050 #[serde(default)]
1052 pub relationship_types: Vec<RelationshipTypeSchemaConfig>,
1053 #[serde(default = "default_true")]
1055 pub allow_orphans: bool,
1056 #[serde(default = "default_orphan_probability")]
1058 pub orphan_probability: f64,
1059 #[serde(default)]
1061 pub allow_circular: bool,
1062 #[serde(default = "default_max_circular_depth")]
1064 pub max_circular_depth: u32,
1065}
1066
1067fn default_orphan_probability() -> f64 {
1068 0.01
1069}
1070
1071fn default_max_circular_depth() -> u32 {
1072 3
1073}
1074
1075impl Default for RelationshipSchemaConfig {
1076 fn default() -> Self {
1077 Self {
1078 relationship_types: Vec::new(),
1079 allow_orphans: true,
1080 orphan_probability: 0.01,
1081 allow_circular: false,
1082 max_circular_depth: 3,
1083 }
1084 }
1085}
1086
1087#[derive(Debug, Clone, Serialize, Deserialize)]
1089pub struct RelationshipTypeSchemaConfig {
1090 pub name: String,
1092 pub source_type: String,
1094 pub target_type: String,
1096 #[serde(default)]
1098 pub cardinality: CardinalitySchemaRule,
1099 #[serde(default = "default_relationship_weight")]
1101 pub weight: f64,
1102 #[serde(default)]
1104 pub required: bool,
1105 #[serde(default = "default_true")]
1107 pub directed: bool,
1108}
1109
1110fn default_relationship_weight() -> f64 {
1111 1.0
1112}
1113
1114impl Default for RelationshipTypeSchemaConfig {
1115 fn default() -> Self {
1116 Self {
1117 name: String::new(),
1118 source_type: String::new(),
1119 target_type: String::new(),
1120 cardinality: CardinalitySchemaRule::default(),
1121 weight: 1.0,
1122 required: false,
1123 directed: true,
1124 }
1125 }
1126}
1127
1128#[derive(Debug, Clone, Serialize, Deserialize)]
1130#[serde(rename_all = "snake_case")]
1131pub enum CardinalitySchemaRule {
1132 OneToOne,
1134 OneToMany {
1136 min: u32,
1138 max: u32,
1140 },
1141 ManyToOne {
1143 min: u32,
1145 max: u32,
1147 },
1148 ManyToMany {
1150 min_per_source: u32,
1152 max_per_source: u32,
1154 },
1155}
1156
1157impl Default for CardinalitySchemaRule {
1158 fn default() -> Self {
1159 Self::OneToMany { min: 1, max: 5 }
1160 }
1161}
1162
1163#[derive(Debug, Clone, Serialize, Deserialize)]
1165pub struct GlobalConfig {
1166 pub seed: Option<u64>,
1168 pub industry: IndustrySector,
1170 pub start_date: String,
1172 pub period_months: u32,
1174 #[serde(default = "default_currency")]
1176 pub group_currency: String,
1177 #[serde(default = "default_true")]
1179 pub parallel: bool,
1180 #[serde(default)]
1182 pub worker_threads: usize,
1183 #[serde(default)]
1185 pub memory_limit_mb: usize,
1186}
1187
1188fn default_currency() -> String {
1189 "USD".to_string()
1190}
1191fn default_true() -> bool {
1192 true
1193}
1194
1195#[derive(Debug, Clone, Serialize, Deserialize)]
1197pub struct CompanyConfig {
1198 pub code: String,
1200 pub name: String,
1202 pub currency: String,
1204 pub country: String,
1206 #[serde(default = "default_fiscal_variant")]
1208 pub fiscal_year_variant: String,
1209 pub annual_transaction_volume: TransactionVolume,
1211 #[serde(default = "default_weight")]
1213 pub volume_weight: f64,
1214}
1215
1216fn default_fiscal_variant() -> String {
1217 "K4".to_string()
1218}
1219fn default_weight() -> f64 {
1220 1.0
1221}
1222
1223#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1225#[serde(rename_all = "snake_case")]
1226pub enum TransactionVolume {
1227 TenK,
1229 HundredK,
1231 OneM,
1233 TenM,
1235 HundredM,
1237 Custom(u64),
1239}
1240
1241impl TransactionVolume {
1242 pub fn count(&self) -> u64 {
1244 match self {
1245 Self::TenK => 10_000,
1246 Self::HundredK => 100_000,
1247 Self::OneM => 1_000_000,
1248 Self::TenM => 10_000_000,
1249 Self::HundredM => 100_000_000,
1250 Self::Custom(n) => *n,
1251 }
1252 }
1253}
1254
1255#[derive(Debug, Clone, Serialize, Deserialize)]
1257pub struct ChartOfAccountsConfig {
1258 pub complexity: CoAComplexity,
1260 #[serde(default = "default_true")]
1262 pub industry_specific: bool,
1263 pub custom_accounts: Option<PathBuf>,
1265 #[serde(default = "default_min_depth")]
1267 pub min_hierarchy_depth: u8,
1268 #[serde(default = "default_max_depth")]
1270 pub max_hierarchy_depth: u8,
1271}
1272
1273fn default_min_depth() -> u8 {
1274 2
1275}
1276fn default_max_depth() -> u8 {
1277 5
1278}
1279
1280impl Default for ChartOfAccountsConfig {
1281 fn default() -> Self {
1282 Self {
1283 complexity: CoAComplexity::Small,
1284 industry_specific: true,
1285 custom_accounts: None,
1286 min_hierarchy_depth: default_min_depth(),
1287 max_hierarchy_depth: default_max_depth(),
1288 }
1289 }
1290}
1291
1292#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1294pub struct TransactionConfig {
1295 #[serde(default)]
1297 pub line_item_distribution: LineItemDistributionConfig,
1298 #[serde(default)]
1300 pub debit_credit_distribution: DebitCreditDistributionConfig,
1301 #[serde(default)]
1303 pub even_odd_distribution: EvenOddDistributionConfig,
1304 #[serde(default)]
1306 pub source_distribution: SourceDistribution,
1307 #[serde(default)]
1309 pub seasonality: SeasonalityConfig,
1310 #[serde(default)]
1312 pub amounts: AmountDistributionConfig,
1313 #[serde(default)]
1315 pub benford: BenfordConfig,
1316}
1317
1318#[derive(Debug, Clone, Serialize, Deserialize)]
1320pub struct BenfordConfig {
1321 #[serde(default = "default_true")]
1323 pub enabled: bool,
1324 #[serde(default = "default_benford_tolerance")]
1326 pub tolerance: f64,
1327 #[serde(default)]
1329 pub exempt_sources: Vec<BenfordExemption>,
1330}
1331
1332fn default_benford_tolerance() -> f64 {
1333 0.05
1334}
1335
1336impl Default for BenfordConfig {
1337 fn default() -> Self {
1338 Self {
1339 enabled: true,
1340 tolerance: default_benford_tolerance(),
1341 exempt_sources: vec![BenfordExemption::Recurring, BenfordExemption::Payroll],
1342 }
1343 }
1344}
1345
1346#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1348#[serde(rename_all = "snake_case")]
1349pub enum BenfordExemption {
1350 Recurring,
1352 Payroll,
1354 FixedFees,
1356 RoundAmounts,
1358}
1359
1360#[derive(Debug, Clone, Serialize, Deserialize)]
1362pub struct SourceDistribution {
1363 pub manual: f64,
1365 pub automated: f64,
1367 pub recurring: f64,
1369 pub adjustment: f64,
1371}
1372
1373impl Default for SourceDistribution {
1374 fn default() -> Self {
1375 Self {
1376 manual: 0.20,
1377 automated: 0.70,
1378 recurring: 0.07,
1379 adjustment: 0.03,
1380 }
1381 }
1382}
1383
1384#[derive(Debug, Clone, Serialize, Deserialize)]
1386pub struct OutputConfig {
1387 #[serde(default)]
1389 pub mode: OutputMode,
1390 pub output_directory: PathBuf,
1392 #[serde(default = "default_formats")]
1394 pub formats: Vec<FileFormat>,
1395 #[serde(default)]
1397 pub compression: CompressionConfig,
1398 #[serde(default = "default_batch_size")]
1400 pub batch_size: usize,
1401 #[serde(default = "default_true")]
1403 pub include_acdoca: bool,
1404 #[serde(default)]
1406 pub include_bseg: bool,
1407 #[serde(default = "default_true")]
1409 pub partition_by_period: bool,
1410 #[serde(default)]
1412 pub partition_by_company: bool,
1413}
1414
1415fn default_formats() -> Vec<FileFormat> {
1416 vec![FileFormat::Parquet]
1417}
1418fn default_batch_size() -> usize {
1419 100_000
1420}
1421
1422impl Default for OutputConfig {
1423 fn default() -> Self {
1424 Self {
1425 mode: OutputMode::FlatFile,
1426 output_directory: PathBuf::from("./output"),
1427 formats: default_formats(),
1428 compression: CompressionConfig::default(),
1429 batch_size: default_batch_size(),
1430 include_acdoca: true,
1431 include_bseg: false,
1432 partition_by_period: true,
1433 partition_by_company: false,
1434 }
1435 }
1436}
1437
1438#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
1440#[serde(rename_all = "snake_case")]
1441pub enum OutputMode {
1442 Streaming,
1444 #[default]
1446 FlatFile,
1447 Both,
1449}
1450
1451#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1453#[serde(rename_all = "snake_case")]
1454pub enum FileFormat {
1455 Csv,
1456 Parquet,
1457 Json,
1458 JsonLines,
1459}
1460
1461#[derive(Debug, Clone, Serialize, Deserialize)]
1463pub struct CompressionConfig {
1464 #[serde(default = "default_true")]
1466 pub enabled: bool,
1467 #[serde(default)]
1469 pub algorithm: CompressionAlgorithm,
1470 #[serde(default = "default_compression_level")]
1472 pub level: u8,
1473}
1474
1475fn default_compression_level() -> u8 {
1476 3
1477}
1478
1479impl Default for CompressionConfig {
1480 fn default() -> Self {
1481 Self {
1482 enabled: true,
1483 algorithm: CompressionAlgorithm::default(),
1484 level: default_compression_level(),
1485 }
1486 }
1487}
1488
1489#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
1491#[serde(rename_all = "snake_case")]
1492pub enum CompressionAlgorithm {
1493 Gzip,
1494 #[default]
1495 Zstd,
1496 Lz4,
1497 Snappy,
1498}
1499
1500#[derive(Debug, Clone, Serialize, Deserialize)]
1502pub struct FraudConfig {
1503 #[serde(default)]
1505 pub enabled: bool,
1506 #[serde(default = "default_fraud_rate")]
1508 pub fraud_rate: f64,
1509 #[serde(default)]
1511 pub fraud_type_distribution: FraudTypeDistribution,
1512 #[serde(default)]
1514 pub clustering_enabled: bool,
1515 #[serde(default = "default_clustering_factor")]
1517 pub clustering_factor: f64,
1518 #[serde(default = "default_approval_thresholds")]
1520 pub approval_thresholds: Vec<f64>,
1521}
1522
1523fn default_approval_thresholds() -> Vec<f64> {
1524 vec![1000.0, 5000.0, 10000.0, 25000.0, 50000.0, 100000.0]
1525}
1526
1527fn default_fraud_rate() -> f64 {
1528 0.005
1529}
1530fn default_clustering_factor() -> f64 {
1531 3.0
1532}
1533
1534impl Default for FraudConfig {
1535 fn default() -> Self {
1536 Self {
1537 enabled: false,
1538 fraud_rate: default_fraud_rate(),
1539 fraud_type_distribution: FraudTypeDistribution::default(),
1540 clustering_enabled: false,
1541 clustering_factor: default_clustering_factor(),
1542 approval_thresholds: default_approval_thresholds(),
1543 }
1544 }
1545}
1546
1547#[derive(Debug, Clone, Serialize, Deserialize)]
1549pub struct FraudTypeDistribution {
1550 pub suspense_account_abuse: f64,
1551 pub fictitious_transaction: f64,
1552 pub revenue_manipulation: f64,
1553 pub expense_capitalization: f64,
1554 pub split_transaction: f64,
1555 pub timing_anomaly: f64,
1556 pub unauthorized_access: f64,
1557 pub duplicate_payment: f64,
1558}
1559
1560impl Default for FraudTypeDistribution {
1561 fn default() -> Self {
1562 Self {
1563 suspense_account_abuse: 0.25,
1564 fictitious_transaction: 0.15,
1565 revenue_manipulation: 0.10,
1566 expense_capitalization: 0.10,
1567 split_transaction: 0.15,
1568 timing_anomaly: 0.10,
1569 unauthorized_access: 0.10,
1570 duplicate_payment: 0.05,
1571 }
1572 }
1573}
1574
1575#[derive(Debug, Clone, Serialize, Deserialize)]
1577pub struct InternalControlsConfig {
1578 #[serde(default)]
1580 pub enabled: bool,
1581 #[serde(default = "default_exception_rate")]
1583 pub exception_rate: f64,
1584 #[serde(default = "default_sod_violation_rate")]
1586 pub sod_violation_rate: f64,
1587 #[serde(default = "default_true")]
1589 pub export_control_master_data: bool,
1590 #[serde(default = "default_sox_materiality_threshold")]
1592 pub sox_materiality_threshold: f64,
1593 #[serde(default = "default_true")]
1595 pub coso_enabled: bool,
1596 #[serde(default)]
1598 pub include_entity_level_controls: bool,
1599 #[serde(default = "default_target_maturity_level")]
1602 pub target_maturity_level: String,
1603}
1604
1605fn default_exception_rate() -> f64 {
1606 0.02
1607}
1608
1609fn default_sod_violation_rate() -> f64 {
1610 0.01
1611}
1612
1613fn default_sox_materiality_threshold() -> f64 {
1614 10000.0
1615}
1616
1617fn default_target_maturity_level() -> String {
1618 "mixed".to_string()
1619}
1620
1621impl Default for InternalControlsConfig {
1622 fn default() -> Self {
1623 Self {
1624 enabled: false,
1625 exception_rate: default_exception_rate(),
1626 sod_violation_rate: default_sod_violation_rate(),
1627 export_control_master_data: true,
1628 sox_materiality_threshold: default_sox_materiality_threshold(),
1629 coso_enabled: true,
1630 include_entity_level_controls: false,
1631 target_maturity_level: default_target_maturity_level(),
1632 }
1633 }
1634}
1635
1636#[derive(Debug, Clone, Serialize, Deserialize)]
1638pub struct BusinessProcessConfig {
1639 #[serde(default = "default_o2c")]
1641 pub o2c_weight: f64,
1642 #[serde(default = "default_p2p")]
1644 pub p2p_weight: f64,
1645 #[serde(default = "default_r2r")]
1647 pub r2r_weight: f64,
1648 #[serde(default = "default_h2r")]
1650 pub h2r_weight: f64,
1651 #[serde(default = "default_a2r")]
1653 pub a2r_weight: f64,
1654}
1655
1656fn default_o2c() -> f64 {
1657 0.35
1658}
1659fn default_p2p() -> f64 {
1660 0.30
1661}
1662fn default_r2r() -> f64 {
1663 0.20
1664}
1665fn default_h2r() -> f64 {
1666 0.10
1667}
1668fn default_a2r() -> f64 {
1669 0.05
1670}
1671
1672impl Default for BusinessProcessConfig {
1673 fn default() -> Self {
1674 Self {
1675 o2c_weight: default_o2c(),
1676 p2p_weight: default_p2p(),
1677 r2r_weight: default_r2r(),
1678 h2r_weight: default_h2r(),
1679 a2r_weight: default_a2r(),
1680 }
1681 }
1682}
1683
1684#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1686pub struct UserPersonaConfig {
1687 #[serde(default)]
1689 pub persona_distribution: PersonaDistribution,
1690 #[serde(default)]
1692 pub users_per_persona: UsersPerPersona,
1693}
1694
1695#[derive(Debug, Clone, Serialize, Deserialize)]
1697pub struct PersonaDistribution {
1698 pub junior_accountant: f64,
1699 pub senior_accountant: f64,
1700 pub controller: f64,
1701 pub manager: f64,
1702 pub automated_system: f64,
1703}
1704
1705impl Default for PersonaDistribution {
1706 fn default() -> Self {
1707 Self {
1708 junior_accountant: 0.15,
1709 senior_accountant: 0.15,
1710 controller: 0.05,
1711 manager: 0.05,
1712 automated_system: 0.60,
1713 }
1714 }
1715}
1716
1717#[derive(Debug, Clone, Serialize, Deserialize)]
1719pub struct UsersPerPersona {
1720 pub junior_accountant: usize,
1721 pub senior_accountant: usize,
1722 pub controller: usize,
1723 pub manager: usize,
1724 pub automated_system: usize,
1725}
1726
1727impl Default for UsersPerPersona {
1728 fn default() -> Self {
1729 Self {
1730 junior_accountant: 10,
1731 senior_accountant: 5,
1732 controller: 2,
1733 manager: 3,
1734 automated_system: 20,
1735 }
1736 }
1737}
1738
1739#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1741pub struct TemplateConfig {
1742 #[serde(default)]
1744 pub names: NameTemplateConfig,
1745 #[serde(default)]
1747 pub descriptions: DescriptionTemplateConfig,
1748 #[serde(default)]
1750 pub references: ReferenceTemplateConfig,
1751}
1752
1753#[derive(Debug, Clone, Serialize, Deserialize)]
1755pub struct NameTemplateConfig {
1756 #[serde(default)]
1758 pub culture_distribution: CultureDistribution,
1759 #[serde(default = "default_email_domain")]
1761 pub email_domain: String,
1762 #[serde(default = "default_true")]
1764 pub generate_realistic_names: bool,
1765}
1766
1767fn default_email_domain() -> String {
1768 "company.com".to_string()
1769}
1770
1771impl Default for NameTemplateConfig {
1772 fn default() -> Self {
1773 Self {
1774 culture_distribution: CultureDistribution::default(),
1775 email_domain: default_email_domain(),
1776 generate_realistic_names: true,
1777 }
1778 }
1779}
1780
1781#[derive(Debug, Clone, Serialize, Deserialize)]
1783pub struct CultureDistribution {
1784 pub western_us: f64,
1785 pub hispanic: f64,
1786 pub german: f64,
1787 pub french: f64,
1788 pub chinese: f64,
1789 pub japanese: f64,
1790 pub indian: f64,
1791}
1792
1793impl Default for CultureDistribution {
1794 fn default() -> Self {
1795 Self {
1796 western_us: 0.40,
1797 hispanic: 0.20,
1798 german: 0.10,
1799 french: 0.05,
1800 chinese: 0.10,
1801 japanese: 0.05,
1802 indian: 0.10,
1803 }
1804 }
1805}
1806
1807#[derive(Debug, Clone, Serialize, Deserialize)]
1809pub struct DescriptionTemplateConfig {
1810 #[serde(default = "default_true")]
1812 pub generate_header_text: bool,
1813 #[serde(default = "default_true")]
1815 pub generate_line_text: bool,
1816}
1817
1818impl Default for DescriptionTemplateConfig {
1819 fn default() -> Self {
1820 Self {
1821 generate_header_text: true,
1822 generate_line_text: true,
1823 }
1824 }
1825}
1826
1827#[derive(Debug, Clone, Serialize, Deserialize)]
1829pub struct ReferenceTemplateConfig {
1830 #[serde(default = "default_true")]
1832 pub generate_references: bool,
1833 #[serde(default = "default_invoice_prefix")]
1835 pub invoice_prefix: String,
1836 #[serde(default = "default_po_prefix")]
1838 pub po_prefix: String,
1839 #[serde(default = "default_so_prefix")]
1841 pub so_prefix: String,
1842}
1843
1844fn default_invoice_prefix() -> String {
1845 "INV".to_string()
1846}
1847fn default_po_prefix() -> String {
1848 "PO".to_string()
1849}
1850fn default_so_prefix() -> String {
1851 "SO".to_string()
1852}
1853
1854impl Default for ReferenceTemplateConfig {
1855 fn default() -> Self {
1856 Self {
1857 generate_references: true,
1858 invoice_prefix: default_invoice_prefix(),
1859 po_prefix: default_po_prefix(),
1860 so_prefix: default_so_prefix(),
1861 }
1862 }
1863}
1864
1865#[derive(Debug, Clone, Serialize, Deserialize)]
1867pub struct ApprovalConfig {
1868 #[serde(default)]
1870 pub enabled: bool,
1871 #[serde(default = "default_auto_approve_threshold")]
1873 pub auto_approve_threshold: f64,
1874 #[serde(default = "default_rejection_rate")]
1876 pub rejection_rate: f64,
1877 #[serde(default = "default_revision_rate")]
1879 pub revision_rate: f64,
1880 #[serde(default = "default_approval_delay_hours")]
1882 pub average_approval_delay_hours: f64,
1883 #[serde(default)]
1885 pub thresholds: Vec<ApprovalThresholdConfig>,
1886}
1887
1888fn default_auto_approve_threshold() -> f64 {
1889 1000.0
1890}
1891fn default_rejection_rate() -> f64 {
1892 0.02
1893}
1894fn default_revision_rate() -> f64 {
1895 0.05
1896}
1897fn default_approval_delay_hours() -> f64 {
1898 4.0
1899}
1900
1901impl Default for ApprovalConfig {
1902 fn default() -> Self {
1903 Self {
1904 enabled: false,
1905 auto_approve_threshold: default_auto_approve_threshold(),
1906 rejection_rate: default_rejection_rate(),
1907 revision_rate: default_revision_rate(),
1908 average_approval_delay_hours: default_approval_delay_hours(),
1909 thresholds: vec![
1910 ApprovalThresholdConfig {
1911 amount: 1000.0,
1912 level: 1,
1913 roles: vec!["senior_accountant".to_string()],
1914 },
1915 ApprovalThresholdConfig {
1916 amount: 10000.0,
1917 level: 2,
1918 roles: vec!["senior_accountant".to_string(), "controller".to_string()],
1919 },
1920 ApprovalThresholdConfig {
1921 amount: 100000.0,
1922 level: 3,
1923 roles: vec![
1924 "senior_accountant".to_string(),
1925 "controller".to_string(),
1926 "manager".to_string(),
1927 ],
1928 },
1929 ApprovalThresholdConfig {
1930 amount: 500000.0,
1931 level: 4,
1932 roles: vec![
1933 "senior_accountant".to_string(),
1934 "controller".to_string(),
1935 "manager".to_string(),
1936 "executive".to_string(),
1937 ],
1938 },
1939 ],
1940 }
1941 }
1942}
1943
1944#[derive(Debug, Clone, Serialize, Deserialize)]
1946pub struct ApprovalThresholdConfig {
1947 pub amount: f64,
1949 pub level: u8,
1951 pub roles: Vec<String>,
1953}
1954
1955#[derive(Debug, Clone, Serialize, Deserialize)]
1957pub struct DepartmentConfig {
1958 #[serde(default)]
1960 pub enabled: bool,
1961 #[serde(default = "default_headcount_multiplier")]
1963 pub headcount_multiplier: f64,
1964 #[serde(default)]
1966 pub custom_departments: Vec<CustomDepartmentConfig>,
1967}
1968
1969fn default_headcount_multiplier() -> f64 {
1970 1.0
1971}
1972
1973impl Default for DepartmentConfig {
1974 fn default() -> Self {
1975 Self {
1976 enabled: false,
1977 headcount_multiplier: default_headcount_multiplier(),
1978 custom_departments: Vec::new(),
1979 }
1980 }
1981}
1982
1983#[derive(Debug, Clone, Serialize, Deserialize)]
1985pub struct CustomDepartmentConfig {
1986 pub code: String,
1988 pub name: String,
1990 #[serde(default)]
1992 pub cost_center: Option<String>,
1993 #[serde(default)]
1995 pub primary_processes: Vec<String>,
1996 #[serde(default)]
1998 pub parent_code: Option<String>,
1999}
2000
2001#[derive(Debug, Clone, Default, Serialize, Deserialize)]
2007pub struct MasterDataConfig {
2008 #[serde(default)]
2010 pub vendors: VendorMasterConfig,
2011 #[serde(default)]
2013 pub customers: CustomerMasterConfig,
2014 #[serde(default)]
2016 pub materials: MaterialMasterConfig,
2017 #[serde(default)]
2019 pub fixed_assets: FixedAssetMasterConfig,
2020 #[serde(default)]
2022 pub employees: EmployeeMasterConfig,
2023 #[serde(default)]
2025 pub cost_centers: CostCenterMasterConfig,
2026}
2027
2028#[derive(Debug, Clone, Serialize, Deserialize)]
2030pub struct VendorMasterConfig {
2031 #[serde(default = "default_vendor_count")]
2033 pub count: usize,
2034 #[serde(default = "default_intercompany_percent")]
2036 pub intercompany_percent: f64,
2037 #[serde(default)]
2039 pub payment_terms_distribution: PaymentTermsDistribution,
2040 #[serde(default)]
2042 pub behavior_distribution: VendorBehaviorDistribution,
2043 #[serde(default = "default_true")]
2045 pub generate_bank_accounts: bool,
2046 #[serde(default = "default_true")]
2048 pub generate_tax_ids: bool,
2049}
2050
2051fn default_vendor_count() -> usize {
2052 500
2053}
2054
2055fn default_intercompany_percent() -> f64 {
2056 0.05
2057}
2058
2059impl Default for VendorMasterConfig {
2060 fn default() -> Self {
2061 Self {
2062 count: default_vendor_count(),
2063 intercompany_percent: default_intercompany_percent(),
2064 payment_terms_distribution: PaymentTermsDistribution::default(),
2065 behavior_distribution: VendorBehaviorDistribution::default(),
2066 generate_bank_accounts: true,
2067 generate_tax_ids: true,
2068 }
2069 }
2070}
2071
2072#[derive(Debug, Clone, Serialize, Deserialize)]
2074pub struct PaymentTermsDistribution {
2075 pub net_30: f64,
2077 pub net_60: f64,
2079 pub net_90: f64,
2081 pub two_ten_net_30: f64,
2083 pub due_on_receipt: f64,
2085 pub end_of_month: f64,
2087}
2088
2089impl Default for PaymentTermsDistribution {
2090 fn default() -> Self {
2091 Self {
2092 net_30: 0.40,
2093 net_60: 0.20,
2094 net_90: 0.10,
2095 two_ten_net_30: 0.15,
2096 due_on_receipt: 0.05,
2097 end_of_month: 0.10,
2098 }
2099 }
2100}
2101
2102#[derive(Debug, Clone, Serialize, Deserialize)]
2104pub struct VendorBehaviorDistribution {
2105 pub reliable: f64,
2107 pub sometimes_late: f64,
2109 pub inconsistent_quality: f64,
2111 pub premium: f64,
2113 pub budget: f64,
2115}
2116
2117impl Default for VendorBehaviorDistribution {
2118 fn default() -> Self {
2119 Self {
2120 reliable: 0.50,
2121 sometimes_late: 0.20,
2122 inconsistent_quality: 0.10,
2123 premium: 0.10,
2124 budget: 0.10,
2125 }
2126 }
2127}
2128
2129#[derive(Debug, Clone, Serialize, Deserialize)]
2131pub struct CustomerMasterConfig {
2132 #[serde(default = "default_customer_count")]
2134 pub count: usize,
2135 #[serde(default = "default_intercompany_percent")]
2137 pub intercompany_percent: f64,
2138 #[serde(default)]
2140 pub credit_rating_distribution: CreditRatingDistribution,
2141 #[serde(default)]
2143 pub payment_behavior_distribution: PaymentBehaviorDistribution,
2144 #[serde(default = "default_true")]
2146 pub generate_credit_limits: bool,
2147}
2148
2149fn default_customer_count() -> usize {
2150 2000
2151}
2152
2153impl Default for CustomerMasterConfig {
2154 fn default() -> Self {
2155 Self {
2156 count: default_customer_count(),
2157 intercompany_percent: default_intercompany_percent(),
2158 credit_rating_distribution: CreditRatingDistribution::default(),
2159 payment_behavior_distribution: PaymentBehaviorDistribution::default(),
2160 generate_credit_limits: true,
2161 }
2162 }
2163}
2164
2165#[derive(Debug, Clone, Serialize, Deserialize)]
2167pub struct CreditRatingDistribution {
2168 pub aaa: f64,
2170 pub aa: f64,
2172 pub a: f64,
2174 pub bbb: f64,
2176 pub bb: f64,
2178 pub b: f64,
2180 pub below_b: f64,
2182}
2183
2184impl Default for CreditRatingDistribution {
2185 fn default() -> Self {
2186 Self {
2187 aaa: 0.05,
2188 aa: 0.10,
2189 a: 0.20,
2190 bbb: 0.30,
2191 bb: 0.20,
2192 b: 0.10,
2193 below_b: 0.05,
2194 }
2195 }
2196}
2197
2198#[derive(Debug, Clone, Serialize, Deserialize)]
2200pub struct PaymentBehaviorDistribution {
2201 pub early_payer: f64,
2203 pub on_time: f64,
2205 pub occasional_late: f64,
2207 pub frequent_late: f64,
2209 pub discount_taker: f64,
2211}
2212
2213impl Default for PaymentBehaviorDistribution {
2214 fn default() -> Self {
2215 Self {
2216 early_payer: 0.10,
2217 on_time: 0.50,
2218 occasional_late: 0.25,
2219 frequent_late: 0.10,
2220 discount_taker: 0.05,
2221 }
2222 }
2223}
2224
2225#[derive(Debug, Clone, Serialize, Deserialize)]
2227pub struct MaterialMasterConfig {
2228 #[serde(default = "default_material_count")]
2230 pub count: usize,
2231 #[serde(default)]
2233 pub type_distribution: MaterialTypeDistribution,
2234 #[serde(default)]
2236 pub valuation_distribution: ValuationMethodDistribution,
2237 #[serde(default = "default_bom_percent")]
2239 pub bom_percent: f64,
2240 #[serde(default = "default_max_bom_depth")]
2242 pub max_bom_depth: u8,
2243}
2244
2245fn default_material_count() -> usize {
2246 5000
2247}
2248
2249fn default_bom_percent() -> f64 {
2250 0.20
2251}
2252
2253fn default_max_bom_depth() -> u8 {
2254 3
2255}
2256
2257impl Default for MaterialMasterConfig {
2258 fn default() -> Self {
2259 Self {
2260 count: default_material_count(),
2261 type_distribution: MaterialTypeDistribution::default(),
2262 valuation_distribution: ValuationMethodDistribution::default(),
2263 bom_percent: default_bom_percent(),
2264 max_bom_depth: default_max_bom_depth(),
2265 }
2266 }
2267}
2268
2269#[derive(Debug, Clone, Serialize, Deserialize)]
2271pub struct MaterialTypeDistribution {
2272 pub raw_material: f64,
2274 pub semi_finished: f64,
2276 pub finished_good: f64,
2278 pub trading_good: f64,
2280 pub operating_supply: f64,
2282 pub service: f64,
2284}
2285
2286impl Default for MaterialTypeDistribution {
2287 fn default() -> Self {
2288 Self {
2289 raw_material: 0.30,
2290 semi_finished: 0.15,
2291 finished_good: 0.25,
2292 trading_good: 0.15,
2293 operating_supply: 0.10,
2294 service: 0.05,
2295 }
2296 }
2297}
2298
2299#[derive(Debug, Clone, Serialize, Deserialize)]
2301pub struct ValuationMethodDistribution {
2302 pub standard_cost: f64,
2304 pub moving_average: f64,
2306 pub fifo: f64,
2308 pub lifo: f64,
2310}
2311
2312impl Default for ValuationMethodDistribution {
2313 fn default() -> Self {
2314 Self {
2315 standard_cost: 0.50,
2316 moving_average: 0.30,
2317 fifo: 0.15,
2318 lifo: 0.05,
2319 }
2320 }
2321}
2322
2323#[derive(Debug, Clone, Serialize, Deserialize)]
2325pub struct FixedAssetMasterConfig {
2326 #[serde(default = "default_asset_count")]
2328 pub count: usize,
2329 #[serde(default)]
2331 pub class_distribution: AssetClassDistribution,
2332 #[serde(default)]
2334 pub depreciation_distribution: DepreciationMethodDistribution,
2335 #[serde(default = "default_fully_depreciated_percent")]
2337 pub fully_depreciated_percent: f64,
2338 #[serde(default = "default_true")]
2340 pub generate_acquisition_history: bool,
2341}
2342
2343fn default_asset_count() -> usize {
2344 800
2345}
2346
2347fn default_fully_depreciated_percent() -> f64 {
2348 0.15
2349}
2350
2351impl Default for FixedAssetMasterConfig {
2352 fn default() -> Self {
2353 Self {
2354 count: default_asset_count(),
2355 class_distribution: AssetClassDistribution::default(),
2356 depreciation_distribution: DepreciationMethodDistribution::default(),
2357 fully_depreciated_percent: default_fully_depreciated_percent(),
2358 generate_acquisition_history: true,
2359 }
2360 }
2361}
2362
2363#[derive(Debug, Clone, Serialize, Deserialize)]
2365pub struct AssetClassDistribution {
2366 pub buildings: f64,
2368 pub machinery: f64,
2370 pub vehicles: f64,
2372 pub it_equipment: f64,
2374 pub furniture: f64,
2376 pub land: f64,
2378 pub leasehold: f64,
2380}
2381
2382impl Default for AssetClassDistribution {
2383 fn default() -> Self {
2384 Self {
2385 buildings: 0.15,
2386 machinery: 0.30,
2387 vehicles: 0.15,
2388 it_equipment: 0.20,
2389 furniture: 0.10,
2390 land: 0.05,
2391 leasehold: 0.05,
2392 }
2393 }
2394}
2395
2396#[derive(Debug, Clone, Serialize, Deserialize)]
2398pub struct DepreciationMethodDistribution {
2399 pub straight_line: f64,
2401 pub declining_balance: f64,
2403 pub double_declining: f64,
2405 pub sum_of_years: f64,
2407 pub units_of_production: f64,
2409}
2410
2411impl Default for DepreciationMethodDistribution {
2412 fn default() -> Self {
2413 Self {
2414 straight_line: 0.60,
2415 declining_balance: 0.20,
2416 double_declining: 0.10,
2417 sum_of_years: 0.05,
2418 units_of_production: 0.05,
2419 }
2420 }
2421}
2422
2423#[derive(Debug, Clone, Serialize, Deserialize)]
2425pub struct EmployeeMasterConfig {
2426 #[serde(default = "default_employee_count")]
2428 pub count: usize,
2429 #[serde(default = "default_true")]
2431 pub generate_hierarchy: bool,
2432 #[serde(default = "default_hierarchy_depth")]
2434 pub max_hierarchy_depth: u8,
2435 #[serde(default = "default_span_of_control")]
2437 pub average_span_of_control: f64,
2438 #[serde(default)]
2440 pub approval_limits: ApprovalLimitDistribution,
2441 #[serde(default)]
2443 pub department_distribution: EmployeeDepartmentDistribution,
2444}
2445
2446fn default_employee_count() -> usize {
2447 1500
2448}
2449
2450fn default_hierarchy_depth() -> u8 {
2451 6
2452}
2453
2454fn default_span_of_control() -> f64 {
2455 5.0
2456}
2457
2458impl Default for EmployeeMasterConfig {
2459 fn default() -> Self {
2460 Self {
2461 count: default_employee_count(),
2462 generate_hierarchy: true,
2463 max_hierarchy_depth: default_hierarchy_depth(),
2464 average_span_of_control: default_span_of_control(),
2465 approval_limits: ApprovalLimitDistribution::default(),
2466 department_distribution: EmployeeDepartmentDistribution::default(),
2467 }
2468 }
2469}
2470
2471#[derive(Debug, Clone, Serialize, Deserialize)]
2473pub struct ApprovalLimitDistribution {
2474 #[serde(default = "default_staff_limit")]
2476 pub staff: f64,
2477 #[serde(default = "default_senior_limit")]
2479 pub senior: f64,
2480 #[serde(default = "default_manager_limit")]
2482 pub manager: f64,
2483 #[serde(default = "default_director_limit")]
2485 pub director: f64,
2486 #[serde(default = "default_vp_limit")]
2488 pub vp: f64,
2489 #[serde(default = "default_executive_limit")]
2491 pub executive: f64,
2492}
2493
2494fn default_staff_limit() -> f64 {
2495 1000.0
2496}
2497fn default_senior_limit() -> f64 {
2498 5000.0
2499}
2500fn default_manager_limit() -> f64 {
2501 25000.0
2502}
2503fn default_director_limit() -> f64 {
2504 100000.0
2505}
2506fn default_vp_limit() -> f64 {
2507 500000.0
2508}
2509fn default_executive_limit() -> f64 {
2510 f64::INFINITY
2511}
2512
2513impl Default for ApprovalLimitDistribution {
2514 fn default() -> Self {
2515 Self {
2516 staff: default_staff_limit(),
2517 senior: default_senior_limit(),
2518 manager: default_manager_limit(),
2519 director: default_director_limit(),
2520 vp: default_vp_limit(),
2521 executive: default_executive_limit(),
2522 }
2523 }
2524}
2525
2526#[derive(Debug, Clone, Serialize, Deserialize)]
2528pub struct EmployeeDepartmentDistribution {
2529 pub finance: f64,
2531 pub procurement: f64,
2533 pub sales: f64,
2535 pub warehouse: f64,
2537 pub it: f64,
2539 pub hr: f64,
2541 pub operations: f64,
2543 pub executive: f64,
2545}
2546
2547impl Default for EmployeeDepartmentDistribution {
2548 fn default() -> Self {
2549 Self {
2550 finance: 0.12,
2551 procurement: 0.10,
2552 sales: 0.25,
2553 warehouse: 0.15,
2554 it: 0.10,
2555 hr: 0.05,
2556 operations: 0.20,
2557 executive: 0.03,
2558 }
2559 }
2560}
2561
2562#[derive(Debug, Clone, Serialize, Deserialize)]
2564pub struct CostCenterMasterConfig {
2565 #[serde(default = "default_cost_center_count")]
2567 pub count: usize,
2568 #[serde(default = "default_true")]
2570 pub generate_hierarchy: bool,
2571 #[serde(default = "default_cc_hierarchy_depth")]
2573 pub max_hierarchy_depth: u8,
2574}
2575
2576fn default_cost_center_count() -> usize {
2577 50
2578}
2579
2580fn default_cc_hierarchy_depth() -> u8 {
2581 3
2582}
2583
2584impl Default for CostCenterMasterConfig {
2585 fn default() -> Self {
2586 Self {
2587 count: default_cost_center_count(),
2588 generate_hierarchy: true,
2589 max_hierarchy_depth: default_cc_hierarchy_depth(),
2590 }
2591 }
2592}
2593
2594#[derive(Debug, Clone, Serialize, Deserialize)]
2600pub struct DocumentFlowConfig {
2601 #[serde(default)]
2603 pub p2p: P2PFlowConfig,
2604 #[serde(default)]
2606 pub o2c: O2CFlowConfig,
2607 #[serde(default = "default_true")]
2609 pub generate_document_references: bool,
2610 #[serde(default)]
2612 pub export_flow_graph: bool,
2613}
2614
2615impl Default for DocumentFlowConfig {
2616 fn default() -> Self {
2617 Self {
2618 p2p: P2PFlowConfig::default(),
2619 o2c: O2CFlowConfig::default(),
2620 generate_document_references: true,
2621 export_flow_graph: false,
2622 }
2623 }
2624}
2625
2626#[derive(Debug, Clone, Serialize, Deserialize)]
2628pub struct P2PFlowConfig {
2629 #[serde(default = "default_true")]
2631 pub enabled: bool,
2632 #[serde(default = "default_three_way_match_rate")]
2634 pub three_way_match_rate: f64,
2635 #[serde(default = "default_partial_delivery_rate")]
2637 pub partial_delivery_rate: f64,
2638 #[serde(default = "default_price_variance_rate")]
2640 pub price_variance_rate: f64,
2641 #[serde(default = "default_max_price_variance")]
2643 pub max_price_variance_percent: f64,
2644 #[serde(default = "default_quantity_variance_rate")]
2646 pub quantity_variance_rate: f64,
2647 #[serde(default = "default_po_to_gr_days")]
2649 pub average_po_to_gr_days: u32,
2650 #[serde(default = "default_gr_to_invoice_days")]
2652 pub average_gr_to_invoice_days: u32,
2653 #[serde(default = "default_invoice_to_payment_days")]
2655 pub average_invoice_to_payment_days: u32,
2656 #[serde(default)]
2658 pub line_count_distribution: DocumentLineCountDistribution,
2659 #[serde(default)]
2661 pub payment_behavior: P2PPaymentBehaviorConfig,
2662}
2663
2664fn default_three_way_match_rate() -> f64 {
2665 0.95
2666}
2667
2668fn default_partial_delivery_rate() -> f64 {
2669 0.15
2670}
2671
2672fn default_price_variance_rate() -> f64 {
2673 0.08
2674}
2675
2676fn default_max_price_variance() -> f64 {
2677 0.05
2678}
2679
2680fn default_quantity_variance_rate() -> f64 {
2681 0.05
2682}
2683
2684fn default_po_to_gr_days() -> u32 {
2685 14
2686}
2687
2688fn default_gr_to_invoice_days() -> u32 {
2689 5
2690}
2691
2692fn default_invoice_to_payment_days() -> u32 {
2693 30
2694}
2695
2696impl Default for P2PFlowConfig {
2697 fn default() -> Self {
2698 Self {
2699 enabled: true,
2700 three_way_match_rate: default_three_way_match_rate(),
2701 partial_delivery_rate: default_partial_delivery_rate(),
2702 price_variance_rate: default_price_variance_rate(),
2703 max_price_variance_percent: default_max_price_variance(),
2704 quantity_variance_rate: default_quantity_variance_rate(),
2705 average_po_to_gr_days: default_po_to_gr_days(),
2706 average_gr_to_invoice_days: default_gr_to_invoice_days(),
2707 average_invoice_to_payment_days: default_invoice_to_payment_days(),
2708 line_count_distribution: DocumentLineCountDistribution::default(),
2709 payment_behavior: P2PPaymentBehaviorConfig::default(),
2710 }
2711 }
2712}
2713
2714#[derive(Debug, Clone, Serialize, Deserialize)]
2720pub struct P2PPaymentBehaviorConfig {
2721 #[serde(default = "default_p2p_late_payment_rate")]
2723 pub late_payment_rate: f64,
2724 #[serde(default)]
2726 pub late_payment_days_distribution: LatePaymentDaysDistribution,
2727 #[serde(default = "default_p2p_partial_payment_rate")]
2729 pub partial_payment_rate: f64,
2730 #[serde(default = "default_p2p_payment_correction_rate")]
2732 pub payment_correction_rate: f64,
2733}
2734
2735fn default_p2p_late_payment_rate() -> f64 {
2736 0.15
2737}
2738
2739fn default_p2p_partial_payment_rate() -> f64 {
2740 0.05
2741}
2742
2743fn default_p2p_payment_correction_rate() -> f64 {
2744 0.02
2745}
2746
2747impl Default for P2PPaymentBehaviorConfig {
2748 fn default() -> Self {
2749 Self {
2750 late_payment_rate: default_p2p_late_payment_rate(),
2751 late_payment_days_distribution: LatePaymentDaysDistribution::default(),
2752 partial_payment_rate: default_p2p_partial_payment_rate(),
2753 payment_correction_rate: default_p2p_payment_correction_rate(),
2754 }
2755 }
2756}
2757
2758#[derive(Debug, Clone, Serialize, Deserialize)]
2760pub struct LatePaymentDaysDistribution {
2761 #[serde(default = "default_slightly_late")]
2763 pub slightly_late_1_to_7: f64,
2764 #[serde(default = "default_late_8_14")]
2766 pub late_8_to_14: f64,
2767 #[serde(default = "default_very_late")]
2769 pub very_late_15_to_30: f64,
2770 #[serde(default = "default_severely_late")]
2772 pub severely_late_31_to_60: f64,
2773 #[serde(default = "default_extremely_late")]
2775 pub extremely_late_over_60: f64,
2776}
2777
2778fn default_slightly_late() -> f64 {
2779 0.50
2780}
2781
2782fn default_late_8_14() -> f64 {
2783 0.25
2784}
2785
2786fn default_very_late() -> f64 {
2787 0.15
2788}
2789
2790fn default_severely_late() -> f64 {
2791 0.07
2792}
2793
2794fn default_extremely_late() -> f64 {
2795 0.03
2796}
2797
2798impl Default for LatePaymentDaysDistribution {
2799 fn default() -> Self {
2800 Self {
2801 slightly_late_1_to_7: default_slightly_late(),
2802 late_8_to_14: default_late_8_14(),
2803 very_late_15_to_30: default_very_late(),
2804 severely_late_31_to_60: default_severely_late(),
2805 extremely_late_over_60: default_extremely_late(),
2806 }
2807 }
2808}
2809
2810#[derive(Debug, Clone, Serialize, Deserialize)]
2812pub struct O2CFlowConfig {
2813 #[serde(default = "default_true")]
2815 pub enabled: bool,
2816 #[serde(default = "default_credit_check_failure_rate")]
2818 pub credit_check_failure_rate: f64,
2819 #[serde(default = "default_partial_shipment_rate")]
2821 pub partial_shipment_rate: f64,
2822 #[serde(default = "default_return_rate")]
2824 pub return_rate: f64,
2825 #[serde(default = "default_bad_debt_rate")]
2827 pub bad_debt_rate: f64,
2828 #[serde(default = "default_so_to_delivery_days")]
2830 pub average_so_to_delivery_days: u32,
2831 #[serde(default = "default_delivery_to_invoice_days")]
2833 pub average_delivery_to_invoice_days: u32,
2834 #[serde(default = "default_invoice_to_receipt_days")]
2836 pub average_invoice_to_receipt_days: u32,
2837 #[serde(default)]
2839 pub line_count_distribution: DocumentLineCountDistribution,
2840 #[serde(default)]
2842 pub cash_discount: CashDiscountConfig,
2843 #[serde(default)]
2845 pub payment_behavior: O2CPaymentBehaviorConfig,
2846}
2847
2848fn default_credit_check_failure_rate() -> f64 {
2849 0.02
2850}
2851
2852fn default_partial_shipment_rate() -> f64 {
2853 0.10
2854}
2855
2856fn default_return_rate() -> f64 {
2857 0.03
2858}
2859
2860fn default_bad_debt_rate() -> f64 {
2861 0.01
2862}
2863
2864fn default_so_to_delivery_days() -> u32 {
2865 7
2866}
2867
2868fn default_delivery_to_invoice_days() -> u32 {
2869 1
2870}
2871
2872fn default_invoice_to_receipt_days() -> u32 {
2873 45
2874}
2875
2876impl Default for O2CFlowConfig {
2877 fn default() -> Self {
2878 Self {
2879 enabled: true,
2880 credit_check_failure_rate: default_credit_check_failure_rate(),
2881 partial_shipment_rate: default_partial_shipment_rate(),
2882 return_rate: default_return_rate(),
2883 bad_debt_rate: default_bad_debt_rate(),
2884 average_so_to_delivery_days: default_so_to_delivery_days(),
2885 average_delivery_to_invoice_days: default_delivery_to_invoice_days(),
2886 average_invoice_to_receipt_days: default_invoice_to_receipt_days(),
2887 line_count_distribution: DocumentLineCountDistribution::default(),
2888 cash_discount: CashDiscountConfig::default(),
2889 payment_behavior: O2CPaymentBehaviorConfig::default(),
2890 }
2891 }
2892}
2893
2894#[derive(Debug, Clone, Serialize, Deserialize, Default)]
2900pub struct O2CPaymentBehaviorConfig {
2901 #[serde(default)]
2903 pub dunning: DunningConfig,
2904 #[serde(default)]
2906 pub partial_payments: PartialPaymentConfig,
2907 #[serde(default)]
2909 pub short_payments: ShortPaymentConfig,
2910 #[serde(default)]
2912 pub on_account_payments: OnAccountPaymentConfig,
2913 #[serde(default)]
2915 pub payment_corrections: PaymentCorrectionConfig,
2916}
2917
2918#[derive(Debug, Clone, Serialize, Deserialize)]
2920pub struct DunningConfig {
2921 #[serde(default)]
2923 pub enabled: bool,
2924 #[serde(default = "default_dunning_level_1_days")]
2926 pub level_1_days_overdue: u32,
2927 #[serde(default = "default_dunning_level_2_days")]
2929 pub level_2_days_overdue: u32,
2930 #[serde(default = "default_dunning_level_3_days")]
2932 pub level_3_days_overdue: u32,
2933 #[serde(default = "default_collection_days")]
2935 pub collection_days_overdue: u32,
2936 #[serde(default)]
2938 pub payment_after_dunning_rates: DunningPaymentRates,
2939 #[serde(default = "default_dunning_block_rate")]
2941 pub dunning_block_rate: f64,
2942 #[serde(default = "default_dunning_interest_rate")]
2944 pub interest_rate_per_year: f64,
2945 #[serde(default = "default_dunning_charge")]
2947 pub dunning_charge: f64,
2948}
2949
2950fn default_dunning_level_1_days() -> u32 {
2951 14
2952}
2953
2954fn default_dunning_level_2_days() -> u32 {
2955 28
2956}
2957
2958fn default_dunning_level_3_days() -> u32 {
2959 42
2960}
2961
2962fn default_collection_days() -> u32 {
2963 60
2964}
2965
2966fn default_dunning_block_rate() -> f64 {
2967 0.05
2968}
2969
2970fn default_dunning_interest_rate() -> f64 {
2971 0.09
2972}
2973
2974fn default_dunning_charge() -> f64 {
2975 25.0
2976}
2977
2978impl Default for DunningConfig {
2979 fn default() -> Self {
2980 Self {
2981 enabled: false,
2982 level_1_days_overdue: default_dunning_level_1_days(),
2983 level_2_days_overdue: default_dunning_level_2_days(),
2984 level_3_days_overdue: default_dunning_level_3_days(),
2985 collection_days_overdue: default_collection_days(),
2986 payment_after_dunning_rates: DunningPaymentRates::default(),
2987 dunning_block_rate: default_dunning_block_rate(),
2988 interest_rate_per_year: default_dunning_interest_rate(),
2989 dunning_charge: default_dunning_charge(),
2990 }
2991 }
2992}
2993
2994#[derive(Debug, Clone, Serialize, Deserialize)]
2996pub struct DunningPaymentRates {
2997 #[serde(default = "default_after_level_1")]
2999 pub after_level_1: f64,
3000 #[serde(default = "default_after_level_2")]
3002 pub after_level_2: f64,
3003 #[serde(default = "default_after_level_3")]
3005 pub after_level_3: f64,
3006 #[serde(default = "default_during_collection")]
3008 pub during_collection: f64,
3009 #[serde(default = "default_never_pay")]
3011 pub never_pay: f64,
3012}
3013
3014fn default_after_level_1() -> f64 {
3015 0.40
3016}
3017
3018fn default_after_level_2() -> f64 {
3019 0.30
3020}
3021
3022fn default_after_level_3() -> f64 {
3023 0.15
3024}
3025
3026fn default_during_collection() -> f64 {
3027 0.05
3028}
3029
3030fn default_never_pay() -> f64 {
3031 0.10
3032}
3033
3034impl Default for DunningPaymentRates {
3035 fn default() -> Self {
3036 Self {
3037 after_level_1: default_after_level_1(),
3038 after_level_2: default_after_level_2(),
3039 after_level_3: default_after_level_3(),
3040 during_collection: default_during_collection(),
3041 never_pay: default_never_pay(),
3042 }
3043 }
3044}
3045
3046#[derive(Debug, Clone, Serialize, Deserialize)]
3048pub struct PartialPaymentConfig {
3049 #[serde(default = "default_partial_payment_rate")]
3051 pub rate: f64,
3052 #[serde(default)]
3054 pub percentage_distribution: PartialPaymentPercentageDistribution,
3055 #[serde(default = "default_avg_days_until_remainder")]
3057 pub avg_days_until_remainder: u32,
3058}
3059
3060fn default_partial_payment_rate() -> f64 {
3061 0.08
3062}
3063
3064fn default_avg_days_until_remainder() -> u32 {
3065 30
3066}
3067
3068impl Default for PartialPaymentConfig {
3069 fn default() -> Self {
3070 Self {
3071 rate: default_partial_payment_rate(),
3072 percentage_distribution: PartialPaymentPercentageDistribution::default(),
3073 avg_days_until_remainder: default_avg_days_until_remainder(),
3074 }
3075 }
3076}
3077
3078#[derive(Debug, Clone, Serialize, Deserialize)]
3080pub struct PartialPaymentPercentageDistribution {
3081 #[serde(default = "default_partial_25")]
3083 pub pay_25_percent: f64,
3084 #[serde(default = "default_partial_50")]
3086 pub pay_50_percent: f64,
3087 #[serde(default = "default_partial_75")]
3089 pub pay_75_percent: f64,
3090 #[serde(default = "default_partial_random")]
3092 pub pay_random_percent: f64,
3093}
3094
3095fn default_partial_25() -> f64 {
3096 0.15
3097}
3098
3099fn default_partial_50() -> f64 {
3100 0.50
3101}
3102
3103fn default_partial_75() -> f64 {
3104 0.25
3105}
3106
3107fn default_partial_random() -> f64 {
3108 0.10
3109}
3110
3111impl Default for PartialPaymentPercentageDistribution {
3112 fn default() -> Self {
3113 Self {
3114 pay_25_percent: default_partial_25(),
3115 pay_50_percent: default_partial_50(),
3116 pay_75_percent: default_partial_75(),
3117 pay_random_percent: default_partial_random(),
3118 }
3119 }
3120}
3121
3122#[derive(Debug, Clone, Serialize, Deserialize)]
3124pub struct ShortPaymentConfig {
3125 #[serde(default = "default_short_payment_rate")]
3127 pub rate: f64,
3128 #[serde(default)]
3130 pub reason_distribution: ShortPaymentReasonDistribution,
3131 #[serde(default = "default_max_short_percent")]
3133 pub max_short_percent: f64,
3134}
3135
3136fn default_short_payment_rate() -> f64 {
3137 0.03
3138}
3139
3140fn default_max_short_percent() -> f64 {
3141 0.10
3142}
3143
3144impl Default for ShortPaymentConfig {
3145 fn default() -> Self {
3146 Self {
3147 rate: default_short_payment_rate(),
3148 reason_distribution: ShortPaymentReasonDistribution::default(),
3149 max_short_percent: default_max_short_percent(),
3150 }
3151 }
3152}
3153
3154#[derive(Debug, Clone, Serialize, Deserialize)]
3156pub struct ShortPaymentReasonDistribution {
3157 #[serde(default = "default_pricing_dispute")]
3159 pub pricing_dispute: f64,
3160 #[serde(default = "default_quality_issue")]
3162 pub quality_issue: f64,
3163 #[serde(default = "default_quantity_discrepancy")]
3165 pub quantity_discrepancy: f64,
3166 #[serde(default = "default_unauthorized_deduction")]
3168 pub unauthorized_deduction: f64,
3169 #[serde(default = "default_incorrect_discount")]
3171 pub incorrect_discount: f64,
3172}
3173
3174fn default_pricing_dispute() -> f64 {
3175 0.30
3176}
3177
3178fn default_quality_issue() -> f64 {
3179 0.20
3180}
3181
3182fn default_quantity_discrepancy() -> f64 {
3183 0.20
3184}
3185
3186fn default_unauthorized_deduction() -> f64 {
3187 0.15
3188}
3189
3190fn default_incorrect_discount() -> f64 {
3191 0.15
3192}
3193
3194impl Default for ShortPaymentReasonDistribution {
3195 fn default() -> Self {
3196 Self {
3197 pricing_dispute: default_pricing_dispute(),
3198 quality_issue: default_quality_issue(),
3199 quantity_discrepancy: default_quantity_discrepancy(),
3200 unauthorized_deduction: default_unauthorized_deduction(),
3201 incorrect_discount: default_incorrect_discount(),
3202 }
3203 }
3204}
3205
3206#[derive(Debug, Clone, Serialize, Deserialize)]
3208pub struct OnAccountPaymentConfig {
3209 #[serde(default = "default_on_account_rate")]
3211 pub rate: f64,
3212 #[serde(default = "default_avg_days_until_applied")]
3214 pub avg_days_until_applied: u32,
3215}
3216
3217fn default_on_account_rate() -> f64 {
3218 0.02
3219}
3220
3221fn default_avg_days_until_applied() -> u32 {
3222 14
3223}
3224
3225impl Default for OnAccountPaymentConfig {
3226 fn default() -> Self {
3227 Self {
3228 rate: default_on_account_rate(),
3229 avg_days_until_applied: default_avg_days_until_applied(),
3230 }
3231 }
3232}
3233
3234#[derive(Debug, Clone, Serialize, Deserialize)]
3236pub struct PaymentCorrectionConfig {
3237 #[serde(default = "default_payment_correction_rate")]
3239 pub rate: f64,
3240 #[serde(default)]
3242 pub type_distribution: PaymentCorrectionTypeDistribution,
3243}
3244
3245fn default_payment_correction_rate() -> f64 {
3246 0.02
3247}
3248
3249impl Default for PaymentCorrectionConfig {
3250 fn default() -> Self {
3251 Self {
3252 rate: default_payment_correction_rate(),
3253 type_distribution: PaymentCorrectionTypeDistribution::default(),
3254 }
3255 }
3256}
3257
3258#[derive(Debug, Clone, Serialize, Deserialize)]
3260pub struct PaymentCorrectionTypeDistribution {
3261 #[serde(default = "default_nsf_rate")]
3263 pub nsf: f64,
3264 #[serde(default = "default_chargeback_rate")]
3266 pub chargeback: f64,
3267 #[serde(default = "default_wrong_amount_rate")]
3269 pub wrong_amount: f64,
3270 #[serde(default = "default_wrong_customer_rate")]
3272 pub wrong_customer: f64,
3273 #[serde(default = "default_duplicate_payment_rate")]
3275 pub duplicate_payment: f64,
3276}
3277
3278fn default_nsf_rate() -> f64 {
3279 0.30
3280}
3281
3282fn default_chargeback_rate() -> f64 {
3283 0.20
3284}
3285
3286fn default_wrong_amount_rate() -> f64 {
3287 0.20
3288}
3289
3290fn default_wrong_customer_rate() -> f64 {
3291 0.15
3292}
3293
3294fn default_duplicate_payment_rate() -> f64 {
3295 0.15
3296}
3297
3298impl Default for PaymentCorrectionTypeDistribution {
3299 fn default() -> Self {
3300 Self {
3301 nsf: default_nsf_rate(),
3302 chargeback: default_chargeback_rate(),
3303 wrong_amount: default_wrong_amount_rate(),
3304 wrong_customer: default_wrong_customer_rate(),
3305 duplicate_payment: default_duplicate_payment_rate(),
3306 }
3307 }
3308}
3309
3310#[derive(Debug, Clone, Serialize, Deserialize)]
3312pub struct DocumentLineCountDistribution {
3313 #[serde(default = "default_min_lines")]
3315 pub min_lines: u32,
3316 #[serde(default = "default_max_lines")]
3318 pub max_lines: u32,
3319 #[serde(default = "default_mode_lines")]
3321 pub mode_lines: u32,
3322}
3323
3324fn default_min_lines() -> u32 {
3325 1
3326}
3327
3328fn default_max_lines() -> u32 {
3329 20
3330}
3331
3332fn default_mode_lines() -> u32 {
3333 3
3334}
3335
3336impl Default for DocumentLineCountDistribution {
3337 fn default() -> Self {
3338 Self {
3339 min_lines: default_min_lines(),
3340 max_lines: default_max_lines(),
3341 mode_lines: default_mode_lines(),
3342 }
3343 }
3344}
3345
3346#[derive(Debug, Clone, Serialize, Deserialize)]
3348pub struct CashDiscountConfig {
3349 #[serde(default = "default_discount_eligible_rate")]
3351 pub eligible_rate: f64,
3352 #[serde(default = "default_discount_taken_rate")]
3354 pub taken_rate: f64,
3355 #[serde(default = "default_discount_percent")]
3357 pub discount_percent: f64,
3358 #[serde(default = "default_discount_days")]
3360 pub discount_days: u32,
3361}
3362
3363fn default_discount_eligible_rate() -> f64 {
3364 0.30
3365}
3366
3367fn default_discount_taken_rate() -> f64 {
3368 0.60
3369}
3370
3371fn default_discount_percent() -> f64 {
3372 0.02
3373}
3374
3375fn default_discount_days() -> u32 {
3376 10
3377}
3378
3379impl Default for CashDiscountConfig {
3380 fn default() -> Self {
3381 Self {
3382 eligible_rate: default_discount_eligible_rate(),
3383 taken_rate: default_discount_taken_rate(),
3384 discount_percent: default_discount_percent(),
3385 discount_days: default_discount_days(),
3386 }
3387 }
3388}
3389
3390#[derive(Debug, Clone, Serialize, Deserialize)]
3396pub struct IntercompanyConfig {
3397 #[serde(default)]
3399 pub enabled: bool,
3400 #[serde(default = "default_ic_transaction_rate")]
3402 pub ic_transaction_rate: f64,
3403 #[serde(default)]
3405 pub transfer_pricing_method: TransferPricingMethod,
3406 #[serde(default = "default_markup_percent")]
3408 pub markup_percent: f64,
3409 #[serde(default = "default_true")]
3411 pub generate_matched_pairs: bool,
3412 #[serde(default)]
3414 pub transaction_type_distribution: ICTransactionTypeDistribution,
3415 #[serde(default)]
3417 pub generate_eliminations: bool,
3418}
3419
3420fn default_ic_transaction_rate() -> f64 {
3421 0.15
3422}
3423
3424fn default_markup_percent() -> f64 {
3425 0.05
3426}
3427
3428impl Default for IntercompanyConfig {
3429 fn default() -> Self {
3430 Self {
3431 enabled: false,
3432 ic_transaction_rate: default_ic_transaction_rate(),
3433 transfer_pricing_method: TransferPricingMethod::default(),
3434 markup_percent: default_markup_percent(),
3435 generate_matched_pairs: true,
3436 transaction_type_distribution: ICTransactionTypeDistribution::default(),
3437 generate_eliminations: false,
3438 }
3439 }
3440}
3441
3442#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
3444#[serde(rename_all = "snake_case")]
3445pub enum TransferPricingMethod {
3446 #[default]
3448 CostPlus,
3449 ComparableUncontrolled,
3451 ResalePrice,
3453 TransactionalNetMargin,
3455 ProfitSplit,
3457}
3458
3459#[derive(Debug, Clone, Serialize, Deserialize)]
3461pub struct ICTransactionTypeDistribution {
3462 pub goods_sale: f64,
3464 pub service_provided: f64,
3466 pub loan: f64,
3468 pub dividend: f64,
3470 pub management_fee: f64,
3472 pub royalty: f64,
3474 pub cost_sharing: f64,
3476}
3477
3478impl Default for ICTransactionTypeDistribution {
3479 fn default() -> Self {
3480 Self {
3481 goods_sale: 0.35,
3482 service_provided: 0.20,
3483 loan: 0.10,
3484 dividend: 0.05,
3485 management_fee: 0.15,
3486 royalty: 0.10,
3487 cost_sharing: 0.05,
3488 }
3489 }
3490}
3491
3492#[derive(Debug, Clone, Serialize, Deserialize)]
3498pub struct BalanceConfig {
3499 #[serde(default)]
3501 pub generate_opening_balances: bool,
3502 #[serde(default = "default_true")]
3504 pub generate_trial_balances: bool,
3505 #[serde(default = "default_gross_margin")]
3507 pub target_gross_margin: f64,
3508 #[serde(default = "default_dso")]
3510 pub target_dso_days: u32,
3511 #[serde(default = "default_dpo")]
3513 pub target_dpo_days: u32,
3514 #[serde(default = "default_current_ratio")]
3516 pub target_current_ratio: f64,
3517 #[serde(default = "default_debt_equity")]
3519 pub target_debt_to_equity: f64,
3520 #[serde(default = "default_true")]
3522 pub validate_balance_equation: bool,
3523 #[serde(default = "default_true")]
3525 pub reconcile_subledgers: bool,
3526}
3527
3528fn default_gross_margin() -> f64 {
3529 0.35
3530}
3531
3532fn default_dso() -> u32 {
3533 45
3534}
3535
3536fn default_dpo() -> u32 {
3537 30
3538}
3539
3540fn default_current_ratio() -> f64 {
3541 1.5
3542}
3543
3544fn default_debt_equity() -> f64 {
3545 0.5
3546}
3547
3548impl Default for BalanceConfig {
3549 fn default() -> Self {
3550 Self {
3551 generate_opening_balances: false,
3552 generate_trial_balances: true,
3553 target_gross_margin: default_gross_margin(),
3554 target_dso_days: default_dso(),
3555 target_dpo_days: default_dpo(),
3556 target_current_ratio: default_current_ratio(),
3557 target_debt_to_equity: default_debt_equity(),
3558 validate_balance_equation: true,
3559 reconcile_subledgers: true,
3560 }
3561 }
3562}
3563
3564#[derive(Debug, Clone, Serialize, Deserialize)]
3573pub struct OcpmConfig {
3574 #[serde(default)]
3576 pub enabled: bool,
3577
3578 #[serde(default = "default_true")]
3580 pub generate_lifecycle_events: bool,
3581
3582 #[serde(default = "default_true")]
3584 pub include_object_relationships: bool,
3585
3586 #[serde(default = "default_true")]
3588 pub compute_variants: bool,
3589
3590 #[serde(default)]
3592 pub max_variants: usize,
3593
3594 #[serde(default)]
3596 pub p2p_process: OcpmProcessConfig,
3597
3598 #[serde(default)]
3600 pub o2c_process: OcpmProcessConfig,
3601
3602 #[serde(default)]
3604 pub output: OcpmOutputConfig,
3605}
3606
3607impl Default for OcpmConfig {
3608 fn default() -> Self {
3609 Self {
3610 enabled: false,
3611 generate_lifecycle_events: true,
3612 include_object_relationships: true,
3613 compute_variants: true,
3614 max_variants: 0,
3615 p2p_process: OcpmProcessConfig::default(),
3616 o2c_process: OcpmProcessConfig::default(),
3617 output: OcpmOutputConfig::default(),
3618 }
3619 }
3620}
3621
3622#[derive(Debug, Clone, Serialize, Deserialize)]
3624pub struct OcpmProcessConfig {
3625 #[serde(default = "default_rework_probability")]
3627 pub rework_probability: f64,
3628
3629 #[serde(default = "default_skip_probability")]
3631 pub skip_step_probability: f64,
3632
3633 #[serde(default = "default_out_of_order_probability")]
3635 pub out_of_order_probability: f64,
3636}
3637
3638fn default_rework_probability() -> f64 {
3639 0.05
3640}
3641
3642fn default_skip_probability() -> f64 {
3643 0.02
3644}
3645
3646fn default_out_of_order_probability() -> f64 {
3647 0.03
3648}
3649
3650impl Default for OcpmProcessConfig {
3651 fn default() -> Self {
3652 Self {
3653 rework_probability: default_rework_probability(),
3654 skip_step_probability: default_skip_probability(),
3655 out_of_order_probability: default_out_of_order_probability(),
3656 }
3657 }
3658}
3659
3660#[derive(Debug, Clone, Serialize, Deserialize)]
3662pub struct OcpmOutputConfig {
3663 #[serde(default = "default_true")]
3665 pub ocel_json: bool,
3666
3667 #[serde(default)]
3669 pub ocel_xml: bool,
3670
3671 #[serde(default)]
3673 pub xes: bool,
3674
3675 #[serde(default = "default_true")]
3677 pub xes_include_lifecycle: bool,
3678
3679 #[serde(default = "default_true")]
3681 pub xes_include_resources: bool,
3682
3683 #[serde(default = "default_true")]
3685 pub flattened_csv: bool,
3686
3687 #[serde(default = "default_true")]
3689 pub event_object_csv: bool,
3690
3691 #[serde(default = "default_true")]
3693 pub object_relationship_csv: bool,
3694
3695 #[serde(default = "default_true")]
3697 pub variants_csv: bool,
3698
3699 #[serde(default)]
3701 pub export_reference_models: bool,
3702}
3703
3704impl Default for OcpmOutputConfig {
3705 fn default() -> Self {
3706 Self {
3707 ocel_json: true,
3708 ocel_xml: false,
3709 xes: false,
3710 xes_include_lifecycle: true,
3711 xes_include_resources: true,
3712 flattened_csv: true,
3713 event_object_csv: true,
3714 object_relationship_csv: true,
3715 variants_csv: true,
3716 export_reference_models: false,
3717 }
3718 }
3719}
3720
3721#[derive(Debug, Clone, Serialize, Deserialize)]
3723pub struct AuditGenerationConfig {
3724 #[serde(default)]
3726 pub enabled: bool,
3727
3728 #[serde(default = "default_true")]
3730 pub generate_workpapers: bool,
3731
3732 #[serde(default)]
3734 pub engagement_types: AuditEngagementTypesConfig,
3735
3736 #[serde(default)]
3738 pub workpapers: WorkpaperConfig,
3739
3740 #[serde(default)]
3742 pub team: AuditTeamConfig,
3743
3744 #[serde(default)]
3746 pub review: ReviewWorkflowConfig,
3747}
3748
3749impl Default for AuditGenerationConfig {
3750 fn default() -> Self {
3751 Self {
3752 enabled: false,
3753 generate_workpapers: true,
3754 engagement_types: AuditEngagementTypesConfig::default(),
3755 workpapers: WorkpaperConfig::default(),
3756 team: AuditTeamConfig::default(),
3757 review: ReviewWorkflowConfig::default(),
3758 }
3759 }
3760}
3761
3762#[derive(Debug, Clone, Serialize, Deserialize)]
3764pub struct AuditEngagementTypesConfig {
3765 #[serde(default = "default_financial_audit_prob")]
3767 pub financial_statement: f64,
3768 #[serde(default = "default_sox_audit_prob")]
3770 pub sox_icfr: f64,
3771 #[serde(default = "default_integrated_audit_prob")]
3773 pub integrated: f64,
3774 #[serde(default = "default_review_prob")]
3776 pub review: f64,
3777 #[serde(default = "default_aup_prob")]
3779 pub agreed_upon_procedures: f64,
3780}
3781
3782fn default_financial_audit_prob() -> f64 {
3783 0.40
3784}
3785fn default_sox_audit_prob() -> f64 {
3786 0.20
3787}
3788fn default_integrated_audit_prob() -> f64 {
3789 0.25
3790}
3791fn default_review_prob() -> f64 {
3792 0.10
3793}
3794fn default_aup_prob() -> f64 {
3795 0.05
3796}
3797
3798impl Default for AuditEngagementTypesConfig {
3799 fn default() -> Self {
3800 Self {
3801 financial_statement: default_financial_audit_prob(),
3802 sox_icfr: default_sox_audit_prob(),
3803 integrated: default_integrated_audit_prob(),
3804 review: default_review_prob(),
3805 agreed_upon_procedures: default_aup_prob(),
3806 }
3807 }
3808}
3809
3810#[derive(Debug, Clone, Serialize, Deserialize)]
3812pub struct WorkpaperConfig {
3813 #[serde(default = "default_workpapers_per_phase")]
3815 pub average_per_phase: usize,
3816
3817 #[serde(default = "default_true")]
3819 pub include_isa_references: bool,
3820
3821 #[serde(default = "default_true")]
3823 pub include_sample_details: bool,
3824
3825 #[serde(default = "default_true")]
3827 pub include_cross_references: bool,
3828
3829 #[serde(default)]
3831 pub sampling: SamplingConfig,
3832}
3833
3834fn default_workpapers_per_phase() -> usize {
3835 5
3836}
3837
3838impl Default for WorkpaperConfig {
3839 fn default() -> Self {
3840 Self {
3841 average_per_phase: default_workpapers_per_phase(),
3842 include_isa_references: true,
3843 include_sample_details: true,
3844 include_cross_references: true,
3845 sampling: SamplingConfig::default(),
3846 }
3847 }
3848}
3849
3850#[derive(Debug, Clone, Serialize, Deserialize)]
3852pub struct SamplingConfig {
3853 #[serde(default = "default_statistical_rate")]
3855 pub statistical_rate: f64,
3856 #[serde(default = "default_judgmental_rate")]
3858 pub judgmental_rate: f64,
3859 #[serde(default = "default_haphazard_rate")]
3861 pub haphazard_rate: f64,
3862 #[serde(default = "default_complete_examination_rate")]
3864 pub complete_examination_rate: f64,
3865}
3866
3867fn default_statistical_rate() -> f64 {
3868 0.40
3869}
3870fn default_judgmental_rate() -> f64 {
3871 0.30
3872}
3873fn default_haphazard_rate() -> f64 {
3874 0.20
3875}
3876fn default_complete_examination_rate() -> f64 {
3877 0.10
3878}
3879
3880impl Default for SamplingConfig {
3881 fn default() -> Self {
3882 Self {
3883 statistical_rate: default_statistical_rate(),
3884 judgmental_rate: default_judgmental_rate(),
3885 haphazard_rate: default_haphazard_rate(),
3886 complete_examination_rate: default_complete_examination_rate(),
3887 }
3888 }
3889}
3890
3891#[derive(Debug, Clone, Serialize, Deserialize)]
3893pub struct AuditTeamConfig {
3894 #[serde(default = "default_min_team_size")]
3896 pub min_team_size: usize,
3897 #[serde(default = "default_max_team_size")]
3899 pub max_team_size: usize,
3900 #[serde(default = "default_specialist_probability")]
3902 pub specialist_probability: f64,
3903}
3904
3905fn default_min_team_size() -> usize {
3906 3
3907}
3908fn default_max_team_size() -> usize {
3909 8
3910}
3911fn default_specialist_probability() -> f64 {
3912 0.30
3913}
3914
3915impl Default for AuditTeamConfig {
3916 fn default() -> Self {
3917 Self {
3918 min_team_size: default_min_team_size(),
3919 max_team_size: default_max_team_size(),
3920 specialist_probability: default_specialist_probability(),
3921 }
3922 }
3923}
3924
3925#[derive(Debug, Clone, Serialize, Deserialize)]
3927pub struct ReviewWorkflowConfig {
3928 #[serde(default = "default_review_delay_days")]
3930 pub average_review_delay_days: u32,
3931 #[serde(default = "default_rework_probability_review")]
3933 pub rework_probability: f64,
3934 #[serde(default = "default_true")]
3936 pub require_partner_signoff: bool,
3937}
3938
3939fn default_review_delay_days() -> u32 {
3940 2
3941}
3942fn default_rework_probability_review() -> f64 {
3943 0.15
3944}
3945
3946impl Default for ReviewWorkflowConfig {
3947 fn default() -> Self {
3948 Self {
3949 average_review_delay_days: default_review_delay_days(),
3950 rework_probability: default_rework_probability_review(),
3951 require_partner_signoff: true,
3952 }
3953 }
3954}
3955
3956#[derive(Debug, Clone, Serialize, Deserialize)]
3962pub struct DataQualitySchemaConfig {
3963 #[serde(default)]
3965 pub enabled: bool,
3966 #[serde(default)]
3968 pub preset: DataQualityPreset,
3969 #[serde(default)]
3971 pub missing_values: MissingValuesSchemaConfig,
3972 #[serde(default)]
3974 pub typos: TypoSchemaConfig,
3975 #[serde(default)]
3977 pub format_variations: FormatVariationSchemaConfig,
3978 #[serde(default)]
3980 pub duplicates: DuplicateSchemaConfig,
3981 #[serde(default)]
3983 pub encoding_issues: EncodingIssueSchemaConfig,
3984 #[serde(default)]
3986 pub generate_labels: bool,
3987 #[serde(default)]
3989 pub sink_profiles: SinkQualityProfiles,
3990}
3991
3992impl Default for DataQualitySchemaConfig {
3993 fn default() -> Self {
3994 Self {
3995 enabled: false,
3996 preset: DataQualityPreset::None,
3997 missing_values: MissingValuesSchemaConfig::default(),
3998 typos: TypoSchemaConfig::default(),
3999 format_variations: FormatVariationSchemaConfig::default(),
4000 duplicates: DuplicateSchemaConfig::default(),
4001 encoding_issues: EncodingIssueSchemaConfig::default(),
4002 generate_labels: true,
4003 sink_profiles: SinkQualityProfiles::default(),
4004 }
4005 }
4006}
4007
4008impl DataQualitySchemaConfig {
4009 pub fn with_preset(preset: DataQualityPreset) -> Self {
4011 let mut config = Self {
4012 preset,
4013 ..Default::default()
4014 };
4015 config.apply_preset();
4016 config
4017 }
4018
4019 pub fn apply_preset(&mut self) {
4022 if !self.preset.overrides_settings() {
4023 return;
4024 }
4025
4026 self.enabled = true;
4027
4028 self.missing_values.enabled = self.preset.missing_rate() > 0.0;
4030 self.missing_values.rate = self.preset.missing_rate();
4031
4032 self.typos.enabled = self.preset.typo_rate() > 0.0;
4034 self.typos.char_error_rate = self.preset.typo_rate();
4035
4036 self.duplicates.enabled = self.preset.duplicate_rate() > 0.0;
4038 self.duplicates.exact_duplicate_ratio = self.preset.duplicate_rate() * 0.4;
4039 self.duplicates.near_duplicate_ratio = self.preset.duplicate_rate() * 0.4;
4040 self.duplicates.fuzzy_duplicate_ratio = self.preset.duplicate_rate() * 0.2;
4041
4042 self.format_variations.enabled = self.preset.format_variations_enabled();
4044
4045 self.encoding_issues.enabled = self.preset.encoding_issues_enabled();
4047 self.encoding_issues.rate = self.preset.encoding_issue_rate();
4048
4049 if self.preset.ocr_errors_enabled() {
4051 self.typos.type_weights.ocr_errors = 0.3;
4052 }
4053 }
4054
4055 pub fn effective_missing_rate(&self) -> f64 {
4057 if self.preset.overrides_settings() {
4058 self.preset.missing_rate()
4059 } else {
4060 self.missing_values.rate
4061 }
4062 }
4063
4064 pub fn effective_typo_rate(&self) -> f64 {
4066 if self.preset.overrides_settings() {
4067 self.preset.typo_rate()
4068 } else {
4069 self.typos.char_error_rate
4070 }
4071 }
4072
4073 pub fn effective_duplicate_rate(&self) -> f64 {
4075 if self.preset.overrides_settings() {
4076 self.preset.duplicate_rate()
4077 } else {
4078 self.duplicates.exact_duplicate_ratio
4079 + self.duplicates.near_duplicate_ratio
4080 + self.duplicates.fuzzy_duplicate_ratio
4081 }
4082 }
4083
4084 pub fn clean() -> Self {
4086 Self::with_preset(DataQualityPreset::Clean)
4087 }
4088
4089 pub fn noisy() -> Self {
4091 Self::with_preset(DataQualityPreset::Noisy)
4092 }
4093
4094 pub fn legacy() -> Self {
4096 Self::with_preset(DataQualityPreset::Legacy)
4097 }
4098}
4099
4100#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
4102#[serde(rename_all = "snake_case")]
4103pub enum DataQualityPreset {
4104 #[default]
4106 None,
4107 Minimal,
4109 Normal,
4111 High,
4113 Custom,
4115
4116 Clean,
4122 Noisy,
4125 Legacy,
4128}
4129
4130impl DataQualityPreset {
4131 pub fn missing_rate(&self) -> f64 {
4133 match self {
4134 DataQualityPreset::None => 0.0,
4135 DataQualityPreset::Minimal => 0.005,
4136 DataQualityPreset::Normal => 0.02,
4137 DataQualityPreset::High => 0.08,
4138 DataQualityPreset::Custom => 0.01, DataQualityPreset::Clean => 0.001,
4140 DataQualityPreset::Noisy => 0.05,
4141 DataQualityPreset::Legacy => 0.10,
4142 }
4143 }
4144
4145 pub fn typo_rate(&self) -> f64 {
4147 match self {
4148 DataQualityPreset::None => 0.0,
4149 DataQualityPreset::Minimal => 0.0005,
4150 DataQualityPreset::Normal => 0.002,
4151 DataQualityPreset::High => 0.01,
4152 DataQualityPreset::Custom => 0.001, DataQualityPreset::Clean => 0.0005,
4154 DataQualityPreset::Noisy => 0.02,
4155 DataQualityPreset::Legacy => 0.05,
4156 }
4157 }
4158
4159 pub fn duplicate_rate(&self) -> f64 {
4161 match self {
4162 DataQualityPreset::None => 0.0,
4163 DataQualityPreset::Minimal => 0.001,
4164 DataQualityPreset::Normal => 0.005,
4165 DataQualityPreset::High => 0.02,
4166 DataQualityPreset::Custom => 0.0, DataQualityPreset::Clean => 0.0,
4168 DataQualityPreset::Noisy => 0.01,
4169 DataQualityPreset::Legacy => 0.03,
4170 }
4171 }
4172
4173 pub fn format_variations_enabled(&self) -> bool {
4175 match self {
4176 DataQualityPreset::None | DataQualityPreset::Clean => false,
4177 DataQualityPreset::Minimal => true,
4178 DataQualityPreset::Normal => true,
4179 DataQualityPreset::High => true,
4180 DataQualityPreset::Custom => true,
4181 DataQualityPreset::Noisy => true,
4182 DataQualityPreset::Legacy => true,
4183 }
4184 }
4185
4186 pub fn ocr_errors_enabled(&self) -> bool {
4188 matches!(self, DataQualityPreset::Legacy | DataQualityPreset::High)
4189 }
4190
4191 pub fn encoding_issues_enabled(&self) -> bool {
4193 matches!(
4194 self,
4195 DataQualityPreset::Legacy | DataQualityPreset::High | DataQualityPreset::Noisy
4196 )
4197 }
4198
4199 pub fn encoding_issue_rate(&self) -> f64 {
4201 match self {
4202 DataQualityPreset::None | DataQualityPreset::Clean | DataQualityPreset::Minimal => 0.0,
4203 DataQualityPreset::Normal => 0.002,
4204 DataQualityPreset::High => 0.01,
4205 DataQualityPreset::Custom => 0.0,
4206 DataQualityPreset::Noisy => 0.005,
4207 DataQualityPreset::Legacy => 0.02,
4208 }
4209 }
4210
4211 pub fn overrides_settings(&self) -> bool {
4213 !matches!(self, DataQualityPreset::Custom | DataQualityPreset::None)
4214 }
4215
4216 pub fn description(&self) -> &'static str {
4218 match self {
4219 DataQualityPreset::None => "No data quality issues (pristine data)",
4220 DataQualityPreset::Minimal => "Very rare data quality issues",
4221 DataQualityPreset::Normal => "Realistic enterprise data quality",
4222 DataQualityPreset::High => "Messy data for stress testing",
4223 DataQualityPreset::Custom => "Custom settings from configuration",
4224 DataQualityPreset::Clean => "ML-ready clean data with minimal issues",
4225 DataQualityPreset::Noisy => "Typical production data with moderate issues",
4226 DataQualityPreset::Legacy => "Legacy/migrated data with heavy issues and OCR errors",
4227 }
4228 }
4229}
4230
4231#[derive(Debug, Clone, Serialize, Deserialize)]
4233pub struct MissingValuesSchemaConfig {
4234 #[serde(default)]
4236 pub enabled: bool,
4237 #[serde(default = "default_missing_rate")]
4239 pub rate: f64,
4240 #[serde(default)]
4242 pub strategy: MissingValueStrategy,
4243 #[serde(default)]
4245 pub field_rates: std::collections::HashMap<String, f64>,
4246 #[serde(default)]
4248 pub protected_fields: Vec<String>,
4249}
4250
4251fn default_missing_rate() -> f64 {
4252 0.01
4253}
4254
4255impl Default for MissingValuesSchemaConfig {
4256 fn default() -> Self {
4257 Self {
4258 enabled: false,
4259 rate: default_missing_rate(),
4260 strategy: MissingValueStrategy::Mcar,
4261 field_rates: std::collections::HashMap::new(),
4262 protected_fields: vec![
4263 "document_id".to_string(),
4264 "company_code".to_string(),
4265 "posting_date".to_string(),
4266 ],
4267 }
4268 }
4269}
4270
4271#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
4273#[serde(rename_all = "snake_case")]
4274pub enum MissingValueStrategy {
4275 #[default]
4277 Mcar,
4278 Mar,
4280 Mnar,
4282 Systematic,
4284}
4285
4286#[derive(Debug, Clone, Serialize, Deserialize)]
4288pub struct TypoSchemaConfig {
4289 #[serde(default)]
4291 pub enabled: bool,
4292 #[serde(default = "default_typo_rate")]
4294 pub char_error_rate: f64,
4295 #[serde(default)]
4297 pub type_weights: TypoTypeWeights,
4298 #[serde(default)]
4300 pub protected_fields: Vec<String>,
4301}
4302
4303fn default_typo_rate() -> f64 {
4304 0.001
4305}
4306
4307impl Default for TypoSchemaConfig {
4308 fn default() -> Self {
4309 Self {
4310 enabled: false,
4311 char_error_rate: default_typo_rate(),
4312 type_weights: TypoTypeWeights::default(),
4313 protected_fields: vec![
4314 "document_id".to_string(),
4315 "gl_account".to_string(),
4316 "company_code".to_string(),
4317 ],
4318 }
4319 }
4320}
4321
4322#[derive(Debug, Clone, Serialize, Deserialize)]
4324pub struct TypoTypeWeights {
4325 #[serde(default = "default_substitution_weight")]
4327 pub substitution: f64,
4328 #[serde(default = "default_transposition_weight")]
4330 pub transposition: f64,
4331 #[serde(default = "default_insertion_weight")]
4333 pub insertion: f64,
4334 #[serde(default = "default_deletion_weight")]
4336 pub deletion: f64,
4337 #[serde(default = "default_ocr_weight")]
4339 pub ocr_errors: f64,
4340 #[serde(default = "default_homophone_weight")]
4342 pub homophones: f64,
4343}
4344
4345fn default_substitution_weight() -> f64 {
4346 0.35
4347}
4348fn default_transposition_weight() -> f64 {
4349 0.25
4350}
4351fn default_insertion_weight() -> f64 {
4352 0.10
4353}
4354fn default_deletion_weight() -> f64 {
4355 0.15
4356}
4357fn default_ocr_weight() -> f64 {
4358 0.10
4359}
4360fn default_homophone_weight() -> f64 {
4361 0.05
4362}
4363
4364impl Default for TypoTypeWeights {
4365 fn default() -> Self {
4366 Self {
4367 substitution: default_substitution_weight(),
4368 transposition: default_transposition_weight(),
4369 insertion: default_insertion_weight(),
4370 deletion: default_deletion_weight(),
4371 ocr_errors: default_ocr_weight(),
4372 homophones: default_homophone_weight(),
4373 }
4374 }
4375}
4376
4377#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4379pub struct FormatVariationSchemaConfig {
4380 #[serde(default)]
4382 pub enabled: bool,
4383 #[serde(default)]
4385 pub dates: DateFormatVariationConfig,
4386 #[serde(default)]
4388 pub amounts: AmountFormatVariationConfig,
4389 #[serde(default)]
4391 pub identifiers: IdentifierFormatVariationConfig,
4392}
4393
4394#[derive(Debug, Clone, Serialize, Deserialize)]
4396pub struct DateFormatVariationConfig {
4397 #[serde(default)]
4399 pub enabled: bool,
4400 #[serde(default = "default_date_variation_rate")]
4402 pub rate: f64,
4403 #[serde(default = "default_true")]
4405 pub iso_format: bool,
4406 #[serde(default)]
4408 pub us_format: bool,
4409 #[serde(default)]
4411 pub eu_format: bool,
4412 #[serde(default)]
4414 pub long_format: bool,
4415}
4416
4417fn default_date_variation_rate() -> f64 {
4418 0.05
4419}
4420
4421impl Default for DateFormatVariationConfig {
4422 fn default() -> Self {
4423 Self {
4424 enabled: false,
4425 rate: default_date_variation_rate(),
4426 iso_format: true,
4427 us_format: false,
4428 eu_format: false,
4429 long_format: false,
4430 }
4431 }
4432}
4433
4434#[derive(Debug, Clone, Serialize, Deserialize)]
4436pub struct AmountFormatVariationConfig {
4437 #[serde(default)]
4439 pub enabled: bool,
4440 #[serde(default = "default_amount_variation_rate")]
4442 pub rate: f64,
4443 #[serde(default)]
4445 pub us_comma_format: bool,
4446 #[serde(default)]
4448 pub eu_format: bool,
4449 #[serde(default)]
4451 pub currency_prefix: bool,
4452 #[serde(default)]
4454 pub accounting_format: bool,
4455}
4456
4457fn default_amount_variation_rate() -> f64 {
4458 0.02
4459}
4460
4461impl Default for AmountFormatVariationConfig {
4462 fn default() -> Self {
4463 Self {
4464 enabled: false,
4465 rate: default_amount_variation_rate(),
4466 us_comma_format: false,
4467 eu_format: false,
4468 currency_prefix: false,
4469 accounting_format: false,
4470 }
4471 }
4472}
4473
4474#[derive(Debug, Clone, Serialize, Deserialize)]
4476pub struct IdentifierFormatVariationConfig {
4477 #[serde(default)]
4479 pub enabled: bool,
4480 #[serde(default = "default_identifier_variation_rate")]
4482 pub rate: f64,
4483 #[serde(default)]
4485 pub case_variations: bool,
4486 #[serde(default)]
4488 pub padding_variations: bool,
4489 #[serde(default)]
4491 pub separator_variations: bool,
4492}
4493
4494fn default_identifier_variation_rate() -> f64 {
4495 0.02
4496}
4497
4498impl Default for IdentifierFormatVariationConfig {
4499 fn default() -> Self {
4500 Self {
4501 enabled: false,
4502 rate: default_identifier_variation_rate(),
4503 case_variations: false,
4504 padding_variations: false,
4505 separator_variations: false,
4506 }
4507 }
4508}
4509
4510#[derive(Debug, Clone, Serialize, Deserialize)]
4512pub struct DuplicateSchemaConfig {
4513 #[serde(default)]
4515 pub enabled: bool,
4516 #[serde(default = "default_duplicate_rate")]
4518 pub rate: f64,
4519 #[serde(default = "default_exact_duplicate_ratio")]
4521 pub exact_duplicate_ratio: f64,
4522 #[serde(default = "default_near_duplicate_ratio")]
4524 pub near_duplicate_ratio: f64,
4525 #[serde(default = "default_fuzzy_duplicate_ratio")]
4527 pub fuzzy_duplicate_ratio: f64,
4528 #[serde(default = "default_max_date_offset")]
4530 pub max_date_offset_days: u32,
4531 #[serde(default = "default_max_amount_variance")]
4533 pub max_amount_variance: f64,
4534}
4535
4536fn default_duplicate_rate() -> f64 {
4537 0.005
4538}
4539fn default_exact_duplicate_ratio() -> f64 {
4540 0.4
4541}
4542fn default_near_duplicate_ratio() -> f64 {
4543 0.35
4544}
4545fn default_fuzzy_duplicate_ratio() -> f64 {
4546 0.25
4547}
4548fn default_max_date_offset() -> u32 {
4549 3
4550}
4551fn default_max_amount_variance() -> f64 {
4552 0.01
4553}
4554
4555impl Default for DuplicateSchemaConfig {
4556 fn default() -> Self {
4557 Self {
4558 enabled: false,
4559 rate: default_duplicate_rate(),
4560 exact_duplicate_ratio: default_exact_duplicate_ratio(),
4561 near_duplicate_ratio: default_near_duplicate_ratio(),
4562 fuzzy_duplicate_ratio: default_fuzzy_duplicate_ratio(),
4563 max_date_offset_days: default_max_date_offset(),
4564 max_amount_variance: default_max_amount_variance(),
4565 }
4566 }
4567}
4568
4569#[derive(Debug, Clone, Serialize, Deserialize)]
4571pub struct EncodingIssueSchemaConfig {
4572 #[serde(default)]
4574 pub enabled: bool,
4575 #[serde(default = "default_encoding_rate")]
4577 pub rate: f64,
4578 #[serde(default)]
4580 pub mojibake: bool,
4581 #[serde(default)]
4583 pub html_entities: bool,
4584 #[serde(default)]
4586 pub bom_issues: bool,
4587}
4588
4589fn default_encoding_rate() -> f64 {
4590 0.001
4591}
4592
4593impl Default for EncodingIssueSchemaConfig {
4594 fn default() -> Self {
4595 Self {
4596 enabled: false,
4597 rate: default_encoding_rate(),
4598 mojibake: false,
4599 html_entities: false,
4600 bom_issues: false,
4601 }
4602 }
4603}
4604
4605#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4607pub struct SinkQualityProfiles {
4608 #[serde(default)]
4610 pub csv: Option<SinkQualityOverride>,
4611 #[serde(default)]
4613 pub json: Option<SinkQualityOverride>,
4614 #[serde(default)]
4616 pub parquet: Option<SinkQualityOverride>,
4617}
4618
4619#[derive(Debug, Clone, Serialize, Deserialize)]
4621pub struct SinkQualityOverride {
4622 pub enabled: Option<bool>,
4624 pub missing_rate: Option<f64>,
4626 pub typo_rate: Option<f64>,
4628 pub format_variation_rate: Option<f64>,
4630 pub duplicate_rate: Option<f64>,
4632}
4633
4634#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4646pub struct AccountingStandardsConfig {
4647 #[serde(default)]
4649 pub enabled: bool,
4650
4651 #[serde(default, skip_serializing_if = "Option::is_none")]
4655 pub framework: Option<AccountingFrameworkConfig>,
4656
4657 #[serde(default)]
4659 pub revenue_recognition: RevenueRecognitionConfig,
4660
4661 #[serde(default)]
4663 pub leases: LeaseAccountingConfig,
4664
4665 #[serde(default)]
4667 pub fair_value: FairValueConfig,
4668
4669 #[serde(default)]
4671 pub impairment: ImpairmentConfig,
4672
4673 #[serde(default)]
4675 pub generate_differences: bool,
4676}
4677
4678#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
4680#[serde(rename_all = "snake_case")]
4681pub enum AccountingFrameworkConfig {
4682 #[default]
4684 UsGaap,
4685 Ifrs,
4687 DualReporting,
4689 FrenchGaap,
4691}
4692
4693#[derive(Debug, Clone, Serialize, Deserialize)]
4695pub struct RevenueRecognitionConfig {
4696 #[serde(default)]
4698 pub enabled: bool,
4699
4700 #[serde(default = "default_true")]
4702 pub generate_contracts: bool,
4703
4704 #[serde(default = "default_avg_obligations")]
4706 pub avg_obligations_per_contract: f64,
4707
4708 #[serde(default = "default_variable_consideration_rate")]
4710 pub variable_consideration_rate: f64,
4711
4712 #[serde(default = "default_over_time_rate")]
4714 pub over_time_recognition_rate: f64,
4715
4716 #[serde(default = "default_contract_count")]
4718 pub contract_count: usize,
4719}
4720
4721fn default_avg_obligations() -> f64 {
4722 2.0
4723}
4724
4725fn default_variable_consideration_rate() -> f64 {
4726 0.15
4727}
4728
4729fn default_over_time_rate() -> f64 {
4730 0.30
4731}
4732
4733fn default_contract_count() -> usize {
4734 100
4735}
4736
4737impl Default for RevenueRecognitionConfig {
4738 fn default() -> Self {
4739 Self {
4740 enabled: false,
4741 generate_contracts: true,
4742 avg_obligations_per_contract: default_avg_obligations(),
4743 variable_consideration_rate: default_variable_consideration_rate(),
4744 over_time_recognition_rate: default_over_time_rate(),
4745 contract_count: default_contract_count(),
4746 }
4747 }
4748}
4749
4750#[derive(Debug, Clone, Serialize, Deserialize)]
4752pub struct LeaseAccountingConfig {
4753 #[serde(default)]
4755 pub enabled: bool,
4756
4757 #[serde(default = "default_lease_count")]
4759 pub lease_count: usize,
4760
4761 #[serde(default = "default_finance_lease_pct")]
4763 pub finance_lease_percent: f64,
4764
4765 #[serde(default = "default_avg_lease_term")]
4767 pub avg_lease_term_months: u32,
4768
4769 #[serde(default = "default_true")]
4771 pub generate_amortization: bool,
4772
4773 #[serde(default = "default_real_estate_pct")]
4775 pub real_estate_percent: f64,
4776}
4777
4778fn default_lease_count() -> usize {
4779 50
4780}
4781
4782fn default_finance_lease_pct() -> f64 {
4783 0.30
4784}
4785
4786fn default_avg_lease_term() -> u32 {
4787 60
4788}
4789
4790fn default_real_estate_pct() -> f64 {
4791 0.40
4792}
4793
4794impl Default for LeaseAccountingConfig {
4795 fn default() -> Self {
4796 Self {
4797 enabled: false,
4798 lease_count: default_lease_count(),
4799 finance_lease_percent: default_finance_lease_pct(),
4800 avg_lease_term_months: default_avg_lease_term(),
4801 generate_amortization: true,
4802 real_estate_percent: default_real_estate_pct(),
4803 }
4804 }
4805}
4806
4807#[derive(Debug, Clone, Serialize, Deserialize)]
4809pub struct FairValueConfig {
4810 #[serde(default)]
4812 pub enabled: bool,
4813
4814 #[serde(default = "default_fv_count")]
4816 pub measurement_count: usize,
4817
4818 #[serde(default = "default_level1_pct")]
4820 pub level1_percent: f64,
4821
4822 #[serde(default = "default_level2_pct")]
4824 pub level2_percent: f64,
4825
4826 #[serde(default = "default_level3_pct")]
4828 pub level3_percent: f64,
4829
4830 #[serde(default)]
4832 pub include_sensitivity_analysis: bool,
4833}
4834
4835fn default_fv_count() -> usize {
4836 25
4837}
4838
4839fn default_level1_pct() -> f64 {
4840 0.40
4841}
4842
4843fn default_level2_pct() -> f64 {
4844 0.35
4845}
4846
4847fn default_level3_pct() -> f64 {
4848 0.25
4849}
4850
4851impl Default for FairValueConfig {
4852 fn default() -> Self {
4853 Self {
4854 enabled: false,
4855 measurement_count: default_fv_count(),
4856 level1_percent: default_level1_pct(),
4857 level2_percent: default_level2_pct(),
4858 level3_percent: default_level3_pct(),
4859 include_sensitivity_analysis: false,
4860 }
4861 }
4862}
4863
4864#[derive(Debug, Clone, Serialize, Deserialize)]
4866pub struct ImpairmentConfig {
4867 #[serde(default)]
4869 pub enabled: bool,
4870
4871 #[serde(default = "default_impairment_count")]
4873 pub test_count: usize,
4874
4875 #[serde(default = "default_impairment_rate")]
4877 pub impairment_rate: f64,
4878
4879 #[serde(default = "default_true")]
4881 pub generate_projections: bool,
4882
4883 #[serde(default)]
4885 pub include_goodwill: bool,
4886}
4887
4888fn default_impairment_count() -> usize {
4889 15
4890}
4891
4892fn default_impairment_rate() -> f64 {
4893 0.10
4894}
4895
4896impl Default for ImpairmentConfig {
4897 fn default() -> Self {
4898 Self {
4899 enabled: false,
4900 test_count: default_impairment_count(),
4901 impairment_rate: default_impairment_rate(),
4902 generate_projections: true,
4903 include_goodwill: false,
4904 }
4905 }
4906}
4907
4908#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4921pub struct AuditStandardsConfig {
4922 #[serde(default)]
4924 pub enabled: bool,
4925
4926 #[serde(default)]
4928 pub isa_compliance: IsaComplianceConfig,
4929
4930 #[serde(default)]
4932 pub analytical_procedures: AnalyticalProceduresConfig,
4933
4934 #[serde(default)]
4936 pub confirmations: ConfirmationsConfig,
4937
4938 #[serde(default)]
4940 pub opinion: AuditOpinionConfig,
4941
4942 #[serde(default)]
4944 pub generate_audit_trail: bool,
4945
4946 #[serde(default)]
4948 pub sox: SoxComplianceConfig,
4949
4950 #[serde(default)]
4952 pub pcaob: PcaobConfig,
4953}
4954
4955#[derive(Debug, Clone, Serialize, Deserialize)]
4957pub struct IsaComplianceConfig {
4958 #[serde(default)]
4960 pub enabled: bool,
4961
4962 #[serde(default = "default_compliance_level")]
4964 pub compliance_level: String,
4965
4966 #[serde(default = "default_true")]
4968 pub generate_isa_mappings: bool,
4969
4970 #[serde(default = "default_true")]
4972 pub generate_coverage_summary: bool,
4973
4974 #[serde(default)]
4976 pub include_pcaob: bool,
4977
4978 #[serde(default = "default_audit_framework")]
4980 pub framework: String,
4981}
4982
4983fn default_compliance_level() -> String {
4984 "standard".to_string()
4985}
4986
4987fn default_audit_framework() -> String {
4988 "isa".to_string()
4989}
4990
4991impl Default for IsaComplianceConfig {
4992 fn default() -> Self {
4993 Self {
4994 enabled: false,
4995 compliance_level: default_compliance_level(),
4996 generate_isa_mappings: true,
4997 generate_coverage_summary: true,
4998 include_pcaob: false,
4999 framework: default_audit_framework(),
5000 }
5001 }
5002}
5003
5004#[derive(Debug, Clone, Serialize, Deserialize)]
5006pub struct AnalyticalProceduresConfig {
5007 #[serde(default)]
5009 pub enabled: bool,
5010
5011 #[serde(default = "default_procedures_per_account")]
5013 pub procedures_per_account: usize,
5014
5015 #[serde(default = "default_variance_probability")]
5017 pub variance_probability: f64,
5018
5019 #[serde(default = "default_true")]
5021 pub generate_investigations: bool,
5022
5023 #[serde(default = "default_true")]
5025 pub include_ratio_analysis: bool,
5026}
5027
5028fn default_procedures_per_account() -> usize {
5029 3
5030}
5031
5032fn default_variance_probability() -> f64 {
5033 0.20
5034}
5035
5036impl Default for AnalyticalProceduresConfig {
5037 fn default() -> Self {
5038 Self {
5039 enabled: false,
5040 procedures_per_account: default_procedures_per_account(),
5041 variance_probability: default_variance_probability(),
5042 generate_investigations: true,
5043 include_ratio_analysis: true,
5044 }
5045 }
5046}
5047
5048#[derive(Debug, Clone, Serialize, Deserialize)]
5050pub struct ConfirmationsConfig {
5051 #[serde(default)]
5053 pub enabled: bool,
5054
5055 #[serde(default = "default_confirmation_count")]
5057 pub confirmation_count: usize,
5058
5059 #[serde(default = "default_positive_response_rate")]
5061 pub positive_response_rate: f64,
5062
5063 #[serde(default = "default_exception_rate_confirm")]
5065 pub exception_rate: f64,
5066
5067 #[serde(default = "default_non_response_rate")]
5069 pub non_response_rate: f64,
5070
5071 #[serde(default = "default_true")]
5073 pub generate_alternative_procedures: bool,
5074}
5075
5076fn default_confirmation_count() -> usize {
5077 50
5078}
5079
5080fn default_positive_response_rate() -> f64 {
5081 0.85
5082}
5083
5084fn default_exception_rate_confirm() -> f64 {
5085 0.10
5086}
5087
5088fn default_non_response_rate() -> f64 {
5089 0.05
5090}
5091
5092impl Default for ConfirmationsConfig {
5093 fn default() -> Self {
5094 Self {
5095 enabled: false,
5096 confirmation_count: default_confirmation_count(),
5097 positive_response_rate: default_positive_response_rate(),
5098 exception_rate: default_exception_rate_confirm(),
5099 non_response_rate: default_non_response_rate(),
5100 generate_alternative_procedures: true,
5101 }
5102 }
5103}
5104
5105#[derive(Debug, Clone, Serialize, Deserialize)]
5107pub struct AuditOpinionConfig {
5108 #[serde(default)]
5110 pub enabled: bool,
5111
5112 #[serde(default = "default_true")]
5114 pub generate_kam: bool,
5115
5116 #[serde(default = "default_kam_count")]
5118 pub average_kam_count: usize,
5119
5120 #[serde(default = "default_modified_opinion_rate")]
5122 pub modified_opinion_rate: f64,
5123
5124 #[serde(default)]
5126 pub include_emphasis_of_matter: bool,
5127
5128 #[serde(default = "default_true")]
5130 pub include_going_concern: bool,
5131}
5132
5133fn default_kam_count() -> usize {
5134 3
5135}
5136
5137fn default_modified_opinion_rate() -> f64 {
5138 0.05
5139}
5140
5141impl Default for AuditOpinionConfig {
5142 fn default() -> Self {
5143 Self {
5144 enabled: false,
5145 generate_kam: true,
5146 average_kam_count: default_kam_count(),
5147 modified_opinion_rate: default_modified_opinion_rate(),
5148 include_emphasis_of_matter: false,
5149 include_going_concern: true,
5150 }
5151 }
5152}
5153
5154#[derive(Debug, Clone, Serialize, Deserialize)]
5156pub struct SoxComplianceConfig {
5157 #[serde(default)]
5159 pub enabled: bool,
5160
5161 #[serde(default = "default_true")]
5163 pub generate_302_certifications: bool,
5164
5165 #[serde(default = "default_true")]
5167 pub generate_404_assessments: bool,
5168
5169 #[serde(default = "default_sox_materiality_threshold")]
5171 pub materiality_threshold: f64,
5172
5173 #[serde(default = "default_material_weakness_rate")]
5175 pub material_weakness_rate: f64,
5176
5177 #[serde(default = "default_significant_deficiency_rate")]
5179 pub significant_deficiency_rate: f64,
5180}
5181
5182fn default_material_weakness_rate() -> f64 {
5183 0.02
5184}
5185
5186fn default_significant_deficiency_rate() -> f64 {
5187 0.08
5188}
5189
5190impl Default for SoxComplianceConfig {
5191 fn default() -> Self {
5192 Self {
5193 enabled: false,
5194 generate_302_certifications: true,
5195 generate_404_assessments: true,
5196 materiality_threshold: default_sox_materiality_threshold(),
5197 material_weakness_rate: default_material_weakness_rate(),
5198 significant_deficiency_rate: default_significant_deficiency_rate(),
5199 }
5200 }
5201}
5202
5203#[derive(Debug, Clone, Serialize, Deserialize)]
5205pub struct PcaobConfig {
5206 #[serde(default)]
5208 pub enabled: bool,
5209
5210 #[serde(default)]
5212 pub is_pcaob_audit: bool,
5213
5214 #[serde(default = "default_true")]
5216 pub generate_cam: bool,
5217
5218 #[serde(default)]
5220 pub include_icfr_opinion: bool,
5221
5222 #[serde(default)]
5224 pub generate_standard_mappings: bool,
5225}
5226
5227impl Default for PcaobConfig {
5228 fn default() -> Self {
5229 Self {
5230 enabled: false,
5231 is_pcaob_audit: false,
5232 generate_cam: true,
5233 include_icfr_opinion: false,
5234 generate_standard_mappings: false,
5235 }
5236 }
5237}
5238
5239#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5252pub struct AdvancedDistributionConfig {
5253 #[serde(default)]
5255 pub enabled: bool,
5256
5257 #[serde(default)]
5259 pub amounts: MixtureDistributionSchemaConfig,
5260
5261 #[serde(default)]
5263 pub correlations: CorrelationSchemaConfig,
5264
5265 #[serde(default)]
5267 pub conditional: Vec<ConditionalDistributionSchemaConfig>,
5268
5269 #[serde(default)]
5271 pub regime_changes: RegimeChangeSchemaConfig,
5272
5273 #[serde(default)]
5275 pub industry_profile: Option<IndustryProfileType>,
5276
5277 #[serde(default)]
5279 pub validation: StatisticalValidationSchemaConfig,
5280}
5281
5282#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
5284#[serde(rename_all = "snake_case")]
5285pub enum IndustryProfileType {
5286 Retail,
5288 Manufacturing,
5290 FinancialServices,
5292 Healthcare,
5294 Technology,
5296}
5297
5298#[derive(Debug, Clone, Serialize, Deserialize)]
5300pub struct MixtureDistributionSchemaConfig {
5301 #[serde(default)]
5303 pub enabled: bool,
5304
5305 #[serde(default = "default_mixture_type")]
5307 pub distribution_type: MixtureDistributionType,
5308
5309 #[serde(default)]
5311 pub components: Vec<MixtureComponentConfig>,
5312
5313 #[serde(default = "default_min_amount")]
5315 pub min_value: f64,
5316
5317 #[serde(default)]
5319 pub max_value: Option<f64>,
5320
5321 #[serde(default = "default_decimal_places")]
5323 pub decimal_places: u8,
5324}
5325
5326fn default_mixture_type() -> MixtureDistributionType {
5327 MixtureDistributionType::LogNormal
5328}
5329
5330fn default_min_amount() -> f64 {
5331 0.01
5332}
5333
5334fn default_decimal_places() -> u8 {
5335 2
5336}
5337
5338impl Default for MixtureDistributionSchemaConfig {
5339 fn default() -> Self {
5340 Self {
5341 enabled: false,
5342 distribution_type: MixtureDistributionType::LogNormal,
5343 components: Vec::new(),
5344 min_value: 0.01,
5345 max_value: None,
5346 decimal_places: 2,
5347 }
5348 }
5349}
5350
5351#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5353#[serde(rename_all = "snake_case")]
5354pub enum MixtureDistributionType {
5355 Gaussian,
5357 #[default]
5359 LogNormal,
5360}
5361
5362#[derive(Debug, Clone, Serialize, Deserialize)]
5364pub struct MixtureComponentConfig {
5365 pub weight: f64,
5367
5368 pub mu: f64,
5370
5371 pub sigma: f64,
5373
5374 #[serde(default)]
5376 pub label: Option<String>,
5377}
5378
5379#[derive(Debug, Clone, Serialize, Deserialize)]
5381pub struct CorrelationSchemaConfig {
5382 #[serde(default)]
5384 pub enabled: bool,
5385
5386 #[serde(default)]
5388 pub copula_type: CopulaSchemaType,
5389
5390 #[serde(default)]
5392 pub fields: Vec<CorrelatedFieldConfig>,
5393
5394 #[serde(default)]
5397 pub matrix: Vec<f64>,
5398
5399 #[serde(default)]
5401 pub expected_correlations: Vec<ExpectedCorrelationConfig>,
5402}
5403
5404impl Default for CorrelationSchemaConfig {
5405 fn default() -> Self {
5406 Self {
5407 enabled: false,
5408 copula_type: CopulaSchemaType::Gaussian,
5409 fields: Vec::new(),
5410 matrix: Vec::new(),
5411 expected_correlations: Vec::new(),
5412 }
5413 }
5414}
5415
5416#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5418#[serde(rename_all = "snake_case")]
5419pub enum CopulaSchemaType {
5420 #[default]
5422 Gaussian,
5423 Clayton,
5425 Gumbel,
5427 Frank,
5429 StudentT,
5431}
5432
5433#[derive(Debug, Clone, Serialize, Deserialize)]
5435pub struct CorrelatedFieldConfig {
5436 pub name: String,
5438
5439 #[serde(default)]
5441 pub distribution: MarginalDistributionConfig,
5442}
5443
5444#[derive(Debug, Clone, Serialize, Deserialize)]
5446#[serde(tag = "type", rename_all = "snake_case")]
5447pub enum MarginalDistributionConfig {
5448 Normal {
5450 mu: f64,
5452 sigma: f64,
5454 },
5455 LogNormal {
5457 mu: f64,
5459 sigma: f64,
5461 },
5462 Uniform {
5464 min: f64,
5466 max: f64,
5468 },
5469 DiscreteUniform {
5471 min: i32,
5473 max: i32,
5475 },
5476}
5477
5478impl Default for MarginalDistributionConfig {
5479 fn default() -> Self {
5480 Self::Normal {
5481 mu: 0.0,
5482 sigma: 1.0,
5483 }
5484 }
5485}
5486
5487#[derive(Debug, Clone, Serialize, Deserialize)]
5489pub struct ExpectedCorrelationConfig {
5490 pub field1: String,
5492 pub field2: String,
5494 pub expected_r: f64,
5496 #[serde(default = "default_correlation_tolerance")]
5498 pub tolerance: f64,
5499}
5500
5501fn default_correlation_tolerance() -> f64 {
5502 0.10
5503}
5504
5505#[derive(Debug, Clone, Serialize, Deserialize)]
5507pub struct ConditionalDistributionSchemaConfig {
5508 pub output_field: String,
5510
5511 pub input_field: String,
5513
5514 #[serde(default)]
5516 pub breakpoints: Vec<ConditionalBreakpointConfig>,
5517
5518 #[serde(default)]
5520 pub default_distribution: ConditionalDistributionParamsConfig,
5521
5522 #[serde(default)]
5524 pub min_value: Option<f64>,
5525
5526 #[serde(default)]
5528 pub max_value: Option<f64>,
5529
5530 #[serde(default = "default_decimal_places")]
5532 pub decimal_places: u8,
5533}
5534
5535#[derive(Debug, Clone, Serialize, Deserialize)]
5537pub struct ConditionalBreakpointConfig {
5538 pub threshold: f64,
5540
5541 pub distribution: ConditionalDistributionParamsConfig,
5543}
5544
5545#[derive(Debug, Clone, Serialize, Deserialize)]
5547#[serde(tag = "type", rename_all = "snake_case")]
5548pub enum ConditionalDistributionParamsConfig {
5549 Fixed {
5551 value: f64,
5553 },
5554 Normal {
5556 mu: f64,
5558 sigma: f64,
5560 },
5561 LogNormal {
5563 mu: f64,
5565 sigma: f64,
5567 },
5568 Uniform {
5570 min: f64,
5572 max: f64,
5574 },
5575 Beta {
5577 alpha: f64,
5579 beta: f64,
5581 min: f64,
5583 max: f64,
5585 },
5586 Discrete {
5588 values: Vec<f64>,
5590 weights: Vec<f64>,
5592 },
5593}
5594
5595impl Default for ConditionalDistributionParamsConfig {
5596 fn default() -> Self {
5597 Self::Normal {
5598 mu: 0.0,
5599 sigma: 1.0,
5600 }
5601 }
5602}
5603
5604#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5606pub struct RegimeChangeSchemaConfig {
5607 #[serde(default)]
5609 pub enabled: bool,
5610
5611 #[serde(default)]
5613 pub changes: Vec<RegimeChangeEventConfig>,
5614
5615 #[serde(default)]
5617 pub economic_cycle: Option<EconomicCycleSchemaConfig>,
5618
5619 #[serde(default)]
5621 pub parameter_drifts: Vec<ParameterDriftSchemaConfig>,
5622}
5623
5624#[derive(Debug, Clone, Serialize, Deserialize)]
5626pub struct RegimeChangeEventConfig {
5627 pub date: String,
5629
5630 pub change_type: RegimeChangeTypeConfig,
5632
5633 #[serde(default)]
5635 pub description: Option<String>,
5636
5637 #[serde(default)]
5639 pub effects: Vec<RegimeEffectConfig>,
5640}
5641
5642#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
5644#[serde(rename_all = "snake_case")]
5645pub enum RegimeChangeTypeConfig {
5646 Acquisition,
5648 Divestiture,
5650 PriceIncrease,
5652 PriceDecrease,
5654 ProductLaunch,
5656 ProductDiscontinuation,
5658 PolicyChange,
5660 CompetitorEntry,
5662 Custom,
5664}
5665
5666#[derive(Debug, Clone, Serialize, Deserialize)]
5668pub struct RegimeEffectConfig {
5669 pub field: String,
5671
5672 pub multiplier: f64,
5674}
5675
5676#[derive(Debug, Clone, Serialize, Deserialize)]
5678pub struct EconomicCycleSchemaConfig {
5679 #[serde(default)]
5681 pub enabled: bool,
5682
5683 #[serde(default = "default_cycle_period")]
5685 pub period_months: u32,
5686
5687 #[serde(default = "default_cycle_amplitude")]
5689 pub amplitude: f64,
5690
5691 #[serde(default)]
5693 pub phase_offset: u32,
5694
5695 #[serde(default)]
5697 pub recessions: Vec<RecessionPeriodConfig>,
5698}
5699
5700fn default_cycle_period() -> u32 {
5701 48
5702}
5703
5704fn default_cycle_amplitude() -> f64 {
5705 0.15
5706}
5707
5708impl Default for EconomicCycleSchemaConfig {
5709 fn default() -> Self {
5710 Self {
5711 enabled: false,
5712 period_months: 48,
5713 amplitude: 0.15,
5714 phase_offset: 0,
5715 recessions: Vec::new(),
5716 }
5717 }
5718}
5719
5720#[derive(Debug, Clone, Serialize, Deserialize)]
5722pub struct RecessionPeriodConfig {
5723 pub start_month: u32,
5725
5726 pub duration_months: u32,
5728
5729 #[serde(default = "default_recession_severity")]
5731 pub severity: f64,
5732}
5733
5734fn default_recession_severity() -> f64 {
5735 0.20
5736}
5737
5738#[derive(Debug, Clone, Serialize, Deserialize)]
5740pub struct ParameterDriftSchemaConfig {
5741 pub parameter: String,
5743
5744 pub drift_type: ParameterDriftTypeConfig,
5746
5747 pub start_value: f64,
5749
5750 pub end_value: f64,
5752
5753 #[serde(default)]
5755 pub start_period: u32,
5756
5757 #[serde(default)]
5759 pub end_period: Option<u32>,
5760}
5761
5762#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5764#[serde(rename_all = "snake_case")]
5765pub enum ParameterDriftTypeConfig {
5766 #[default]
5768 Linear,
5769 Exponential,
5771 Logistic,
5773 Step,
5775}
5776
5777#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5779pub struct StatisticalValidationSchemaConfig {
5780 #[serde(default)]
5782 pub enabled: bool,
5783
5784 #[serde(default)]
5786 pub tests: Vec<StatisticalTestConfig>,
5787
5788 #[serde(default)]
5790 pub reporting: ValidationReportingConfig,
5791}
5792
5793#[derive(Debug, Clone, Serialize, Deserialize)]
5795#[serde(tag = "type", rename_all = "snake_case")]
5796pub enum StatisticalTestConfig {
5797 BenfordFirstDigit {
5799 #[serde(default = "default_benford_threshold")]
5801 threshold_mad: f64,
5802 #[serde(default = "default_benford_warning")]
5804 warning_mad: f64,
5805 },
5806 DistributionFit {
5808 target: TargetDistributionConfig,
5810 #[serde(default = "default_ks_significance")]
5812 ks_significance: f64,
5813 #[serde(default)]
5815 method: DistributionFitMethod,
5816 },
5817 CorrelationCheck {
5819 expected_correlations: Vec<ExpectedCorrelationConfig>,
5821 },
5822 ChiSquared {
5824 #[serde(default = "default_chi_squared_bins")]
5826 bins: usize,
5827 #[serde(default = "default_chi_squared_significance")]
5829 significance: f64,
5830 },
5831 AndersonDarling {
5833 target: TargetDistributionConfig,
5835 #[serde(default = "default_ad_significance")]
5837 significance: f64,
5838 },
5839}
5840
5841fn default_benford_threshold() -> f64 {
5842 0.015
5843}
5844
5845fn default_benford_warning() -> f64 {
5846 0.010
5847}
5848
5849fn default_ks_significance() -> f64 {
5850 0.05
5851}
5852
5853fn default_chi_squared_bins() -> usize {
5854 10
5855}
5856
5857fn default_chi_squared_significance() -> f64 {
5858 0.05
5859}
5860
5861fn default_ad_significance() -> f64 {
5862 0.05
5863}
5864
5865#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5867#[serde(rename_all = "snake_case")]
5868pub enum TargetDistributionConfig {
5869 Normal,
5871 #[default]
5873 LogNormal,
5874 Exponential,
5876 Uniform,
5878}
5879
5880#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5882#[serde(rename_all = "snake_case")]
5883pub enum DistributionFitMethod {
5884 #[default]
5886 KolmogorovSmirnov,
5887 AndersonDarling,
5889 ChiSquared,
5891}
5892
5893#[derive(Debug, Clone, Serialize, Deserialize)]
5895pub struct ValidationReportingConfig {
5896 #[serde(default)]
5898 pub output_report: bool,
5899
5900 #[serde(default)]
5902 pub format: ValidationReportFormat,
5903
5904 #[serde(default)]
5906 pub fail_on_error: bool,
5907
5908 #[serde(default = "default_true")]
5910 pub include_details: bool,
5911}
5912
5913impl Default for ValidationReportingConfig {
5914 fn default() -> Self {
5915 Self {
5916 output_report: false,
5917 format: ValidationReportFormat::Json,
5918 fail_on_error: false,
5919 include_details: true,
5920 }
5921 }
5922}
5923
5924#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5926#[serde(rename_all = "snake_case")]
5927pub enum ValidationReportFormat {
5928 #[default]
5930 Json,
5931 Yaml,
5933 Html,
5935}
5936
5937#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5949pub struct TemporalPatternsConfig {
5950 #[serde(default)]
5952 pub enabled: bool,
5953
5954 #[serde(default)]
5956 pub business_days: BusinessDaySchemaConfig,
5957
5958 #[serde(default)]
5960 pub calendars: CalendarSchemaConfig,
5961
5962 #[serde(default)]
5964 pub period_end: PeriodEndSchemaConfig,
5965
5966 #[serde(default)]
5968 pub processing_lags: ProcessingLagSchemaConfig,
5969
5970 #[serde(default)]
5972 pub fiscal_calendar: FiscalCalendarSchemaConfig,
5973
5974 #[serde(default)]
5976 pub intraday: IntraDaySchemaConfig,
5977
5978 #[serde(default)]
5980 pub timezones: TimezoneSchemaConfig,
5981}
5982
5983#[derive(Debug, Clone, Serialize, Deserialize)]
5985pub struct BusinessDaySchemaConfig {
5986 #[serde(default = "default_true")]
5988 pub enabled: bool,
5989
5990 #[serde(default = "default_half_day_policy")]
5992 pub half_day_policy: String,
5993
5994 #[serde(default)]
5996 pub settlement_rules: SettlementRulesSchemaConfig,
5997
5998 #[serde(default = "default_month_end_convention")]
6000 pub month_end_convention: String,
6001
6002 #[serde(default)]
6004 pub weekend_days: Option<Vec<String>>,
6005}
6006
6007fn default_half_day_policy() -> String {
6008 "half_day".to_string()
6009}
6010
6011fn default_month_end_convention() -> String {
6012 "modified_following".to_string()
6013}
6014
6015impl Default for BusinessDaySchemaConfig {
6016 fn default() -> Self {
6017 Self {
6018 enabled: true,
6019 half_day_policy: "half_day".to_string(),
6020 settlement_rules: SettlementRulesSchemaConfig::default(),
6021 month_end_convention: "modified_following".to_string(),
6022 weekend_days: None,
6023 }
6024 }
6025}
6026
6027#[derive(Debug, Clone, Serialize, Deserialize)]
6029pub struct SettlementRulesSchemaConfig {
6030 #[serde(default = "default_settlement_2")]
6032 pub equity_days: i32,
6033
6034 #[serde(default = "default_settlement_1")]
6036 pub government_bonds_days: i32,
6037
6038 #[serde(default = "default_settlement_2")]
6040 pub fx_spot_days: i32,
6041
6042 #[serde(default = "default_settlement_2")]
6044 pub corporate_bonds_days: i32,
6045
6046 #[serde(default = "default_wire_cutoff")]
6048 pub wire_cutoff_time: String,
6049
6050 #[serde(default = "default_settlement_1")]
6052 pub wire_international_days: i32,
6053
6054 #[serde(default = "default_settlement_1")]
6056 pub ach_days: i32,
6057}
6058
6059fn default_settlement_1() -> i32 {
6060 1
6061}
6062
6063fn default_settlement_2() -> i32 {
6064 2
6065}
6066
6067fn default_wire_cutoff() -> String {
6068 "14:00".to_string()
6069}
6070
6071impl Default for SettlementRulesSchemaConfig {
6072 fn default() -> Self {
6073 Self {
6074 equity_days: 2,
6075 government_bonds_days: 1,
6076 fx_spot_days: 2,
6077 corporate_bonds_days: 2,
6078 wire_cutoff_time: "14:00".to_string(),
6079 wire_international_days: 1,
6080 ach_days: 1,
6081 }
6082 }
6083}
6084
6085#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6087pub struct CalendarSchemaConfig {
6088 #[serde(default)]
6090 pub regions: Vec<String>,
6091
6092 #[serde(default)]
6094 pub custom_holidays: Vec<CustomHolidaySchemaConfig>,
6095}
6096
6097#[derive(Debug, Clone, Serialize, Deserialize)]
6099pub struct CustomHolidaySchemaConfig {
6100 pub name: String,
6102 pub month: u8,
6104 pub day: u8,
6106 #[serde(default = "default_holiday_multiplier")]
6108 pub activity_multiplier: f64,
6109}
6110
6111fn default_holiday_multiplier() -> f64 {
6112 0.05
6113}
6114
6115#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6117pub struct PeriodEndSchemaConfig {
6118 #[serde(default)]
6120 pub model: Option<String>,
6121
6122 #[serde(default)]
6124 pub month_end: Option<PeriodEndModelSchemaConfig>,
6125
6126 #[serde(default)]
6128 pub quarter_end: Option<PeriodEndModelSchemaConfig>,
6129
6130 #[serde(default)]
6132 pub year_end: Option<PeriodEndModelSchemaConfig>,
6133}
6134
6135#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6137pub struct PeriodEndModelSchemaConfig {
6138 #[serde(default)]
6140 pub inherit_from: Option<String>,
6141
6142 #[serde(default)]
6144 pub additional_multiplier: Option<f64>,
6145
6146 #[serde(default)]
6148 pub start_day: Option<i32>,
6149
6150 #[serde(default)]
6152 pub base_multiplier: Option<f64>,
6153
6154 #[serde(default)]
6156 pub peak_multiplier: Option<f64>,
6157
6158 #[serde(default)]
6160 pub decay_rate: Option<f64>,
6161
6162 #[serde(default)]
6164 pub sustained_high_days: Option<i32>,
6165}
6166
6167#[derive(Debug, Clone, Serialize, Deserialize)]
6169pub struct ProcessingLagSchemaConfig {
6170 #[serde(default = "default_true")]
6172 pub enabled: bool,
6173
6174 #[serde(default)]
6176 pub sales_order_lag: Option<LagDistributionSchemaConfig>,
6177
6178 #[serde(default)]
6180 pub purchase_order_lag: Option<LagDistributionSchemaConfig>,
6181
6182 #[serde(default)]
6184 pub goods_receipt_lag: Option<LagDistributionSchemaConfig>,
6185
6186 #[serde(default)]
6188 pub invoice_receipt_lag: Option<LagDistributionSchemaConfig>,
6189
6190 #[serde(default)]
6192 pub invoice_issue_lag: Option<LagDistributionSchemaConfig>,
6193
6194 #[serde(default)]
6196 pub payment_lag: Option<LagDistributionSchemaConfig>,
6197
6198 #[serde(default)]
6200 pub journal_entry_lag: Option<LagDistributionSchemaConfig>,
6201
6202 #[serde(default)]
6204 pub cross_day_posting: Option<CrossDayPostingSchemaConfig>,
6205}
6206
6207impl Default for ProcessingLagSchemaConfig {
6208 fn default() -> Self {
6209 Self {
6210 enabled: true,
6211 sales_order_lag: None,
6212 purchase_order_lag: None,
6213 goods_receipt_lag: None,
6214 invoice_receipt_lag: None,
6215 invoice_issue_lag: None,
6216 payment_lag: None,
6217 journal_entry_lag: None,
6218 cross_day_posting: None,
6219 }
6220 }
6221}
6222
6223#[derive(Debug, Clone, Serialize, Deserialize)]
6225pub struct LagDistributionSchemaConfig {
6226 pub mu: f64,
6228 pub sigma: f64,
6230 #[serde(default)]
6232 pub min_hours: Option<f64>,
6233 #[serde(default)]
6235 pub max_hours: Option<f64>,
6236}
6237
6238#[derive(Debug, Clone, Serialize, Deserialize)]
6240pub struct CrossDayPostingSchemaConfig {
6241 #[serde(default = "default_true")]
6243 pub enabled: bool,
6244
6245 #[serde(default)]
6248 pub probability_by_hour: std::collections::HashMap<u8, f64>,
6249}
6250
6251impl Default for CrossDayPostingSchemaConfig {
6252 fn default() -> Self {
6253 let mut probability_by_hour = std::collections::HashMap::new();
6254 probability_by_hour.insert(17, 0.3);
6255 probability_by_hour.insert(18, 0.6);
6256 probability_by_hour.insert(19, 0.8);
6257 probability_by_hour.insert(20, 0.9);
6258 probability_by_hour.insert(21, 0.95);
6259 probability_by_hour.insert(22, 0.99);
6260
6261 Self {
6262 enabled: true,
6263 probability_by_hour,
6264 }
6265 }
6266}
6267
6268#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6277pub struct FiscalCalendarSchemaConfig {
6278 #[serde(default)]
6280 pub enabled: bool,
6281
6282 #[serde(default = "default_fiscal_calendar_type")]
6284 pub calendar_type: String,
6285
6286 #[serde(default)]
6288 pub year_start_month: Option<u8>,
6289
6290 #[serde(default)]
6292 pub year_start_day: Option<u8>,
6293
6294 #[serde(default)]
6296 pub four_four_five: Option<FourFourFiveSchemaConfig>,
6297}
6298
6299fn default_fiscal_calendar_type() -> String {
6300 "calendar_year".to_string()
6301}
6302
6303#[derive(Debug, Clone, Serialize, Deserialize)]
6305pub struct FourFourFiveSchemaConfig {
6306 #[serde(default = "default_week_pattern")]
6308 pub pattern: String,
6309
6310 #[serde(default = "default_anchor_type")]
6312 pub anchor_type: String,
6313
6314 #[serde(default = "default_anchor_month")]
6316 pub anchor_month: u8,
6317
6318 #[serde(default = "default_leap_week_placement")]
6320 pub leap_week_placement: String,
6321}
6322
6323fn default_week_pattern() -> String {
6324 "four_four_five".to_string()
6325}
6326
6327fn default_anchor_type() -> String {
6328 "last_saturday".to_string()
6329}
6330
6331fn default_anchor_month() -> u8 {
6332 1 }
6334
6335fn default_leap_week_placement() -> String {
6336 "q4_period3".to_string()
6337}
6338
6339impl Default for FourFourFiveSchemaConfig {
6340 fn default() -> Self {
6341 Self {
6342 pattern: "four_four_five".to_string(),
6343 anchor_type: "last_saturday".to_string(),
6344 anchor_month: 1,
6345 leap_week_placement: "q4_period3".to_string(),
6346 }
6347 }
6348}
6349
6350#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6359pub struct IntraDaySchemaConfig {
6360 #[serde(default)]
6362 pub enabled: bool,
6363
6364 #[serde(default)]
6366 pub segments: Vec<IntraDaySegmentSchemaConfig>,
6367}
6368
6369#[derive(Debug, Clone, Serialize, Deserialize)]
6371pub struct IntraDaySegmentSchemaConfig {
6372 pub name: String,
6374
6375 pub start: String,
6377
6378 pub end: String,
6380
6381 #[serde(default = "default_multiplier")]
6383 pub multiplier: f64,
6384
6385 #[serde(default = "default_posting_type")]
6387 pub posting_type: String,
6388}
6389
6390fn default_multiplier() -> f64 {
6391 1.0
6392}
6393
6394fn default_posting_type() -> String {
6395 "both".to_string()
6396}
6397
6398#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6404pub struct TimezoneSchemaConfig {
6405 #[serde(default)]
6407 pub enabled: bool,
6408
6409 #[serde(default = "default_timezone")]
6411 pub default_timezone: String,
6412
6413 #[serde(default = "default_consolidation_timezone")]
6415 pub consolidation_timezone: String,
6416
6417 #[serde(default)]
6420 pub entity_mappings: Vec<EntityTimezoneMapping>,
6421}
6422
6423fn default_timezone() -> String {
6424 "America/New_York".to_string()
6425}
6426
6427fn default_consolidation_timezone() -> String {
6428 "UTC".to_string()
6429}
6430
6431#[derive(Debug, Clone, Serialize, Deserialize)]
6433pub struct EntityTimezoneMapping {
6434 pub pattern: String,
6436
6437 pub timezone: String,
6439}
6440
6441#[derive(Debug, Clone, Serialize, Deserialize)]
6447pub struct VendorNetworkSchemaConfig {
6448 #[serde(default)]
6450 pub enabled: bool,
6451
6452 #[serde(default = "default_vendor_tier_depth")]
6454 pub depth: u8,
6455
6456 #[serde(default)]
6458 pub tier1: TierCountSchemaConfig,
6459
6460 #[serde(default)]
6462 pub tier2_per_parent: TierCountSchemaConfig,
6463
6464 #[serde(default)]
6466 pub tier3_per_parent: TierCountSchemaConfig,
6467
6468 #[serde(default)]
6470 pub clusters: VendorClusterSchemaConfig,
6471
6472 #[serde(default)]
6474 pub dependencies: DependencySchemaConfig,
6475}
6476
6477fn default_vendor_tier_depth() -> u8 {
6478 3
6479}
6480
6481impl Default for VendorNetworkSchemaConfig {
6482 fn default() -> Self {
6483 Self {
6484 enabled: false,
6485 depth: 3,
6486 tier1: TierCountSchemaConfig { min: 50, max: 100 },
6487 tier2_per_parent: TierCountSchemaConfig { min: 4, max: 10 },
6488 tier3_per_parent: TierCountSchemaConfig { min: 2, max: 5 },
6489 clusters: VendorClusterSchemaConfig::default(),
6490 dependencies: DependencySchemaConfig::default(),
6491 }
6492 }
6493}
6494
6495#[derive(Debug, Clone, Serialize, Deserialize)]
6497pub struct TierCountSchemaConfig {
6498 #[serde(default = "default_tier_min")]
6500 pub min: usize,
6501
6502 #[serde(default = "default_tier_max")]
6504 pub max: usize,
6505}
6506
6507fn default_tier_min() -> usize {
6508 5
6509}
6510
6511fn default_tier_max() -> usize {
6512 20
6513}
6514
6515impl Default for TierCountSchemaConfig {
6516 fn default() -> Self {
6517 Self {
6518 min: default_tier_min(),
6519 max: default_tier_max(),
6520 }
6521 }
6522}
6523
6524#[derive(Debug, Clone, Serialize, Deserialize)]
6526pub struct VendorClusterSchemaConfig {
6527 #[serde(default = "default_reliable_strategic")]
6529 pub reliable_strategic: f64,
6530
6531 #[serde(default = "default_standard_operational")]
6533 pub standard_operational: f64,
6534
6535 #[serde(default = "default_transactional")]
6537 pub transactional: f64,
6538
6539 #[serde(default = "default_problematic")]
6541 pub problematic: f64,
6542}
6543
6544fn default_reliable_strategic() -> f64 {
6545 0.20
6546}
6547
6548fn default_standard_operational() -> f64 {
6549 0.50
6550}
6551
6552fn default_transactional() -> f64 {
6553 0.25
6554}
6555
6556fn default_problematic() -> f64 {
6557 0.05
6558}
6559
6560impl Default for VendorClusterSchemaConfig {
6561 fn default() -> Self {
6562 Self {
6563 reliable_strategic: 0.20,
6564 standard_operational: 0.50,
6565 transactional: 0.25,
6566 problematic: 0.05,
6567 }
6568 }
6569}
6570
6571#[derive(Debug, Clone, Serialize, Deserialize)]
6573pub struct DependencySchemaConfig {
6574 #[serde(default = "default_max_single_vendor")]
6576 pub max_single_vendor_concentration: f64,
6577
6578 #[serde(default = "default_max_top5")]
6580 pub top_5_concentration: f64,
6581
6582 #[serde(default = "default_single_source_percent")]
6584 pub single_source_percent: f64,
6585}
6586
6587fn default_max_single_vendor() -> f64 {
6588 0.15
6589}
6590
6591fn default_max_top5() -> f64 {
6592 0.45
6593}
6594
6595fn default_single_source_percent() -> f64 {
6596 0.05
6597}
6598
6599impl Default for DependencySchemaConfig {
6600 fn default() -> Self {
6601 Self {
6602 max_single_vendor_concentration: 0.15,
6603 top_5_concentration: 0.45,
6604 single_source_percent: 0.05,
6605 }
6606 }
6607}
6608
6609#[derive(Debug, Clone, Default, Serialize, Deserialize)]
6615pub struct CustomerSegmentationSchemaConfig {
6616 #[serde(default)]
6618 pub enabled: bool,
6619
6620 #[serde(default)]
6622 pub value_segments: ValueSegmentsSchemaConfig,
6623
6624 #[serde(default)]
6626 pub lifecycle: LifecycleSchemaConfig,
6627
6628 #[serde(default)]
6630 pub networks: CustomerNetworksSchemaConfig,
6631}
6632
6633#[derive(Debug, Clone, Serialize, Deserialize)]
6635pub struct ValueSegmentsSchemaConfig {
6636 #[serde(default)]
6638 pub enterprise: SegmentDetailSchemaConfig,
6639
6640 #[serde(default)]
6642 pub mid_market: SegmentDetailSchemaConfig,
6643
6644 #[serde(default)]
6646 pub smb: SegmentDetailSchemaConfig,
6647
6648 #[serde(default)]
6650 pub consumer: SegmentDetailSchemaConfig,
6651}
6652
6653impl Default for ValueSegmentsSchemaConfig {
6654 fn default() -> Self {
6655 Self {
6656 enterprise: SegmentDetailSchemaConfig {
6657 revenue_share: 0.40,
6658 customer_share: 0.05,
6659 avg_order_value_range: "50000+".to_string(),
6660 },
6661 mid_market: SegmentDetailSchemaConfig {
6662 revenue_share: 0.35,
6663 customer_share: 0.20,
6664 avg_order_value_range: "5000-50000".to_string(),
6665 },
6666 smb: SegmentDetailSchemaConfig {
6667 revenue_share: 0.20,
6668 customer_share: 0.50,
6669 avg_order_value_range: "500-5000".to_string(),
6670 },
6671 consumer: SegmentDetailSchemaConfig {
6672 revenue_share: 0.05,
6673 customer_share: 0.25,
6674 avg_order_value_range: "50-500".to_string(),
6675 },
6676 }
6677 }
6678}
6679
6680#[derive(Debug, Clone, Serialize, Deserialize)]
6682pub struct SegmentDetailSchemaConfig {
6683 #[serde(default)]
6685 pub revenue_share: f64,
6686
6687 #[serde(default)]
6689 pub customer_share: f64,
6690
6691 #[serde(default)]
6693 pub avg_order_value_range: String,
6694}
6695
6696impl Default for SegmentDetailSchemaConfig {
6697 fn default() -> Self {
6698 Self {
6699 revenue_share: 0.25,
6700 customer_share: 0.25,
6701 avg_order_value_range: "1000-10000".to_string(),
6702 }
6703 }
6704}
6705
6706#[derive(Debug, Clone, Serialize, Deserialize)]
6708pub struct LifecycleSchemaConfig {
6709 #[serde(default)]
6711 pub prospect_rate: f64,
6712
6713 #[serde(default = "default_new_rate")]
6715 pub new_rate: f64,
6716
6717 #[serde(default = "default_growth_rate")]
6719 pub growth_rate: f64,
6720
6721 #[serde(default = "default_mature_rate")]
6723 pub mature_rate: f64,
6724
6725 #[serde(default = "default_at_risk_rate")]
6727 pub at_risk_rate: f64,
6728
6729 #[serde(default = "default_churned_rate")]
6731 pub churned_rate: f64,
6732}
6733
6734fn default_new_rate() -> f64 {
6735 0.10
6736}
6737
6738fn default_growth_rate() -> f64 {
6739 0.15
6740}
6741
6742fn default_mature_rate() -> f64 {
6743 0.60
6744}
6745
6746fn default_at_risk_rate() -> f64 {
6747 0.10
6748}
6749
6750fn default_churned_rate() -> f64 {
6751 0.05
6752}
6753
6754impl Default for LifecycleSchemaConfig {
6755 fn default() -> Self {
6756 Self {
6757 prospect_rate: 0.0,
6758 new_rate: 0.10,
6759 growth_rate: 0.15,
6760 mature_rate: 0.60,
6761 at_risk_rate: 0.10,
6762 churned_rate: 0.05,
6763 }
6764 }
6765}
6766
6767#[derive(Debug, Clone, Default, Serialize, Deserialize)]
6769pub struct CustomerNetworksSchemaConfig {
6770 #[serde(default)]
6772 pub referrals: ReferralSchemaConfig,
6773
6774 #[serde(default)]
6776 pub corporate_hierarchies: HierarchySchemaConfig,
6777}
6778
6779#[derive(Debug, Clone, Serialize, Deserialize)]
6781pub struct ReferralSchemaConfig {
6782 #[serde(default = "default_true")]
6784 pub enabled: bool,
6785
6786 #[serde(default = "default_referral_rate")]
6788 pub referral_rate: f64,
6789}
6790
6791fn default_referral_rate() -> f64 {
6792 0.15
6793}
6794
6795impl Default for ReferralSchemaConfig {
6796 fn default() -> Self {
6797 Self {
6798 enabled: true,
6799 referral_rate: 0.15,
6800 }
6801 }
6802}
6803
6804#[derive(Debug, Clone, Serialize, Deserialize)]
6806pub struct HierarchySchemaConfig {
6807 #[serde(default = "default_true")]
6809 pub enabled: bool,
6810
6811 #[serde(default = "default_hierarchy_rate")]
6813 pub probability: f64,
6814}
6815
6816fn default_hierarchy_rate() -> f64 {
6817 0.30
6818}
6819
6820impl Default for HierarchySchemaConfig {
6821 fn default() -> Self {
6822 Self {
6823 enabled: true,
6824 probability: 0.30,
6825 }
6826 }
6827}
6828
6829#[derive(Debug, Clone, Default, Serialize, Deserialize)]
6835pub struct RelationshipStrengthSchemaConfig {
6836 #[serde(default)]
6838 pub enabled: bool,
6839
6840 #[serde(default)]
6842 pub calculation: StrengthCalculationSchemaConfig,
6843
6844 #[serde(default)]
6846 pub thresholds: StrengthThresholdsSchemaConfig,
6847}
6848
6849#[derive(Debug, Clone, Serialize, Deserialize)]
6851pub struct StrengthCalculationSchemaConfig {
6852 #[serde(default = "default_volume_weight")]
6854 pub transaction_volume_weight: f64,
6855
6856 #[serde(default = "default_count_weight")]
6858 pub transaction_count_weight: f64,
6859
6860 #[serde(default = "default_duration_weight")]
6862 pub relationship_duration_weight: f64,
6863
6864 #[serde(default = "default_recency_weight")]
6866 pub recency_weight: f64,
6867
6868 #[serde(default = "default_mutual_weight")]
6870 pub mutual_connections_weight: f64,
6871
6872 #[serde(default = "default_recency_half_life")]
6874 pub recency_half_life_days: u32,
6875}
6876
6877fn default_volume_weight() -> f64 {
6878 0.30
6879}
6880
6881fn default_count_weight() -> f64 {
6882 0.25
6883}
6884
6885fn default_duration_weight() -> f64 {
6886 0.20
6887}
6888
6889fn default_recency_weight() -> f64 {
6890 0.15
6891}
6892
6893fn default_mutual_weight() -> f64 {
6894 0.10
6895}
6896
6897fn default_recency_half_life() -> u32 {
6898 90
6899}
6900
6901impl Default for StrengthCalculationSchemaConfig {
6902 fn default() -> Self {
6903 Self {
6904 transaction_volume_weight: 0.30,
6905 transaction_count_weight: 0.25,
6906 relationship_duration_weight: 0.20,
6907 recency_weight: 0.15,
6908 mutual_connections_weight: 0.10,
6909 recency_half_life_days: 90,
6910 }
6911 }
6912}
6913
6914#[derive(Debug, Clone, Serialize, Deserialize)]
6916pub struct StrengthThresholdsSchemaConfig {
6917 #[serde(default = "default_strong_threshold")]
6919 pub strong: f64,
6920
6921 #[serde(default = "default_moderate_threshold")]
6923 pub moderate: f64,
6924
6925 #[serde(default = "default_weak_threshold")]
6927 pub weak: f64,
6928}
6929
6930fn default_strong_threshold() -> f64 {
6931 0.7
6932}
6933
6934fn default_moderate_threshold() -> f64 {
6935 0.4
6936}
6937
6938fn default_weak_threshold() -> f64 {
6939 0.1
6940}
6941
6942impl Default for StrengthThresholdsSchemaConfig {
6943 fn default() -> Self {
6944 Self {
6945 strong: 0.7,
6946 moderate: 0.4,
6947 weak: 0.1,
6948 }
6949 }
6950}
6951
6952#[derive(Debug, Clone, Serialize, Deserialize)]
6958pub struct CrossProcessLinksSchemaConfig {
6959 #[serde(default)]
6961 pub enabled: bool,
6962
6963 #[serde(default = "default_true")]
6965 pub inventory_p2p_o2c: bool,
6966
6967 #[serde(default = "default_true")]
6969 pub payment_bank_reconciliation: bool,
6970
6971 #[serde(default = "default_true")]
6973 pub intercompany_bilateral: bool,
6974
6975 #[serde(default = "default_inventory_link_rate")]
6977 pub inventory_link_rate: f64,
6978}
6979
6980fn default_inventory_link_rate() -> f64 {
6981 0.30
6982}
6983
6984impl Default for CrossProcessLinksSchemaConfig {
6985 fn default() -> Self {
6986 Self {
6987 enabled: false,
6988 inventory_p2p_o2c: true,
6989 payment_bank_reconciliation: true,
6990 intercompany_bilateral: true,
6991 inventory_link_rate: 0.30,
6992 }
6993 }
6994}
6995
6996#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7002pub struct OrganizationalEventsSchemaConfig {
7003 #[serde(default)]
7005 pub enabled: bool,
7006
7007 #[serde(default)]
7009 pub effect_blending: EffectBlendingModeConfig,
7010
7011 #[serde(default)]
7013 pub events: Vec<OrganizationalEventSchemaConfig>,
7014
7015 #[serde(default)]
7017 pub process_evolution: Vec<ProcessEvolutionSchemaConfig>,
7018
7019 #[serde(default)]
7021 pub technology_transitions: Vec<TechnologyTransitionSchemaConfig>,
7022}
7023
7024#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
7026#[serde(rename_all = "snake_case")]
7027pub enum EffectBlendingModeConfig {
7028 #[default]
7030 Multiplicative,
7031 Additive,
7033 Maximum,
7035 Minimum,
7037}
7038
7039#[derive(Debug, Clone, Serialize, Deserialize)]
7041pub struct OrganizationalEventSchemaConfig {
7042 pub id: String,
7044
7045 pub event_type: OrganizationalEventTypeSchemaConfig,
7047
7048 pub effective_date: String,
7050
7051 #[serde(default = "default_org_transition_months")]
7053 pub transition_months: u32,
7054
7055 #[serde(default)]
7057 pub description: Option<String>,
7058}
7059
7060fn default_org_transition_months() -> u32 {
7061 6
7062}
7063
7064#[derive(Debug, Clone, Serialize, Deserialize)]
7066#[serde(tag = "type", rename_all = "snake_case")]
7067pub enum OrganizationalEventTypeSchemaConfig {
7068 Acquisition {
7070 acquired_entity: String,
7072 #[serde(default = "default_acquisition_volume")]
7074 volume_increase: f64,
7075 #[serde(default = "default_acquisition_error")]
7077 integration_error_rate: f64,
7078 #[serde(default = "default_parallel_days")]
7080 parallel_posting_days: u32,
7081 },
7082 Divestiture {
7084 divested_entity: String,
7086 #[serde(default = "default_divestiture_volume")]
7088 volume_reduction: f64,
7089 #[serde(default = "default_true_val")]
7091 remove_entity: bool,
7092 },
7093 Reorganization {
7095 #[serde(default)]
7097 cost_center_remapping: std::collections::HashMap<String, String>,
7098 #[serde(default = "default_reorg_error")]
7100 transition_error_rate: f64,
7101 },
7102 LeadershipChange {
7104 role: String,
7106 #[serde(default)]
7108 policy_changes: Vec<String>,
7109 },
7110 WorkforceReduction {
7112 #[serde(default = "default_workforce_reduction")]
7114 reduction_percent: f64,
7115 #[serde(default = "default_workforce_error")]
7117 error_rate_increase: f64,
7118 },
7119 Merger {
7121 merged_entity: String,
7123 #[serde(default = "default_merger_volume")]
7125 volume_increase: f64,
7126 },
7127}
7128
7129fn default_acquisition_volume() -> f64 {
7130 1.35
7131}
7132
7133fn default_acquisition_error() -> f64 {
7134 0.05
7135}
7136
7137fn default_parallel_days() -> u32 {
7138 30
7139}
7140
7141fn default_divestiture_volume() -> f64 {
7142 0.70
7143}
7144
7145fn default_true_val() -> bool {
7146 true
7147}
7148
7149fn default_reorg_error() -> f64 {
7150 0.04
7151}
7152
7153fn default_workforce_reduction() -> f64 {
7154 0.10
7155}
7156
7157fn default_workforce_error() -> f64 {
7158 0.05
7159}
7160
7161fn default_merger_volume() -> f64 {
7162 1.80
7163}
7164
7165#[derive(Debug, Clone, Serialize, Deserialize)]
7167pub struct ProcessEvolutionSchemaConfig {
7168 pub id: String,
7170
7171 pub event_type: ProcessEvolutionTypeSchemaConfig,
7173
7174 pub effective_date: String,
7176
7177 #[serde(default)]
7179 pub description: Option<String>,
7180}
7181
7182#[derive(Debug, Clone, Serialize, Deserialize)]
7184#[serde(tag = "type", rename_all = "snake_case")]
7185pub enum ProcessEvolutionTypeSchemaConfig {
7186 ProcessAutomation {
7188 process_name: String,
7190 #[serde(default = "default_manual_before")]
7192 manual_rate_before: f64,
7193 #[serde(default = "default_manual_after")]
7195 manual_rate_after: f64,
7196 },
7197 ApprovalWorkflowChange {
7199 description: String,
7201 },
7202 ControlEnhancement {
7204 control_id: String,
7206 #[serde(default = "default_error_reduction")]
7208 error_reduction: f64,
7209 },
7210}
7211
7212fn default_manual_before() -> f64 {
7213 0.80
7214}
7215
7216fn default_manual_after() -> f64 {
7217 0.15
7218}
7219
7220fn default_error_reduction() -> f64 {
7221 0.02
7222}
7223
7224#[derive(Debug, Clone, Serialize, Deserialize)]
7226pub struct TechnologyTransitionSchemaConfig {
7227 pub id: String,
7229
7230 pub event_type: TechnologyTransitionTypeSchemaConfig,
7232
7233 #[serde(default)]
7235 pub description: Option<String>,
7236}
7237
7238#[derive(Debug, Clone, Serialize, Deserialize)]
7240#[serde(tag = "type", rename_all = "snake_case")]
7241pub enum TechnologyTransitionTypeSchemaConfig {
7242 ErpMigration {
7244 source_system: String,
7246 target_system: String,
7248 cutover_date: String,
7250 stabilization_end: String,
7252 #[serde(default = "default_erp_duplicate_rate")]
7254 duplicate_rate: f64,
7255 #[serde(default = "default_format_mismatch")]
7257 format_mismatch_rate: f64,
7258 },
7259 ModuleImplementation {
7261 module_name: String,
7263 go_live_date: String,
7265 },
7266}
7267
7268fn default_erp_duplicate_rate() -> f64 {
7269 0.02
7270}
7271
7272fn default_format_mismatch() -> f64 {
7273 0.03
7274}
7275
7276#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7282pub struct BehavioralDriftSchemaConfig {
7283 #[serde(default)]
7285 pub enabled: bool,
7286
7287 #[serde(default)]
7289 pub vendor_behavior: VendorBehaviorSchemaConfig,
7290
7291 #[serde(default)]
7293 pub customer_behavior: CustomerBehaviorSchemaConfig,
7294
7295 #[serde(default)]
7297 pub employee_behavior: EmployeeBehaviorSchemaConfig,
7298
7299 #[serde(default)]
7301 pub collective: CollectiveBehaviorSchemaConfig,
7302}
7303
7304#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7306pub struct VendorBehaviorSchemaConfig {
7307 #[serde(default)]
7309 pub payment_terms_drift: PaymentTermsDriftSchemaConfig,
7310
7311 #[serde(default)]
7313 pub quality_drift: QualityDriftSchemaConfig,
7314}
7315
7316#[derive(Debug, Clone, Serialize, Deserialize)]
7318pub struct PaymentTermsDriftSchemaConfig {
7319 #[serde(default = "default_extension_rate")]
7321 pub extension_rate_per_year: f64,
7322
7323 #[serde(default = "default_economic_sensitivity")]
7325 pub economic_sensitivity: f64,
7326}
7327
7328fn default_extension_rate() -> f64 {
7329 2.5
7330}
7331
7332fn default_economic_sensitivity() -> f64 {
7333 1.0
7334}
7335
7336impl Default for PaymentTermsDriftSchemaConfig {
7337 fn default() -> Self {
7338 Self {
7339 extension_rate_per_year: 2.5,
7340 economic_sensitivity: 1.0,
7341 }
7342 }
7343}
7344
7345#[derive(Debug, Clone, Serialize, Deserialize)]
7347pub struct QualityDriftSchemaConfig {
7348 #[serde(default = "default_improvement_rate")]
7350 pub new_vendor_improvement_rate: f64,
7351
7352 #[serde(default = "default_decline_rate")]
7354 pub complacency_decline_rate: f64,
7355}
7356
7357fn default_improvement_rate() -> f64 {
7358 0.02
7359}
7360
7361fn default_decline_rate() -> f64 {
7362 0.01
7363}
7364
7365impl Default for QualityDriftSchemaConfig {
7366 fn default() -> Self {
7367 Self {
7368 new_vendor_improvement_rate: 0.02,
7369 complacency_decline_rate: 0.01,
7370 }
7371 }
7372}
7373
7374#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7376pub struct CustomerBehaviorSchemaConfig {
7377 #[serde(default)]
7379 pub payment_drift: CustomerPaymentDriftSchemaConfig,
7380
7381 #[serde(default)]
7383 pub order_drift: OrderDriftSchemaConfig,
7384}
7385
7386#[derive(Debug, Clone, Serialize, Deserialize)]
7388pub struct CustomerPaymentDriftSchemaConfig {
7389 #[serde(default = "default_downturn_extension")]
7391 pub downturn_days_extension: (u32, u32),
7392
7393 #[serde(default = "default_bad_debt_increase")]
7395 pub downturn_bad_debt_increase: f64,
7396}
7397
7398fn default_downturn_extension() -> (u32, u32) {
7399 (5, 15)
7400}
7401
7402fn default_bad_debt_increase() -> f64 {
7403 0.02
7404}
7405
7406impl Default for CustomerPaymentDriftSchemaConfig {
7407 fn default() -> Self {
7408 Self {
7409 downturn_days_extension: (5, 15),
7410 downturn_bad_debt_increase: 0.02,
7411 }
7412 }
7413}
7414
7415#[derive(Debug, Clone, Serialize, Deserialize)]
7417pub struct OrderDriftSchemaConfig {
7418 #[serde(default = "default_digital_shift")]
7420 pub digital_shift_rate: f64,
7421}
7422
7423fn default_digital_shift() -> f64 {
7424 0.05
7425}
7426
7427impl Default for OrderDriftSchemaConfig {
7428 fn default() -> Self {
7429 Self {
7430 digital_shift_rate: 0.05,
7431 }
7432 }
7433}
7434
7435#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7437pub struct EmployeeBehaviorSchemaConfig {
7438 #[serde(default)]
7440 pub approval_drift: ApprovalDriftSchemaConfig,
7441
7442 #[serde(default)]
7444 pub error_drift: ErrorDriftSchemaConfig,
7445}
7446
7447#[derive(Debug, Clone, Serialize, Deserialize)]
7449pub struct ApprovalDriftSchemaConfig {
7450 #[serde(default = "default_eom_intensity")]
7452 pub eom_intensity_increase_per_year: f64,
7453
7454 #[serde(default = "default_rubber_stamp")]
7456 pub rubber_stamp_volume_threshold: u32,
7457}
7458
7459fn default_eom_intensity() -> f64 {
7460 0.05
7461}
7462
7463fn default_rubber_stamp() -> u32 {
7464 50
7465}
7466
7467impl Default for ApprovalDriftSchemaConfig {
7468 fn default() -> Self {
7469 Self {
7470 eom_intensity_increase_per_year: 0.05,
7471 rubber_stamp_volume_threshold: 50,
7472 }
7473 }
7474}
7475
7476#[derive(Debug, Clone, Serialize, Deserialize)]
7478pub struct ErrorDriftSchemaConfig {
7479 #[serde(default = "default_new_error")]
7481 pub new_employee_error_rate: f64,
7482
7483 #[serde(default = "default_learning_months")]
7485 pub learning_curve_months: u32,
7486}
7487
7488fn default_new_error() -> f64 {
7489 0.08
7490}
7491
7492fn default_learning_months() -> u32 {
7493 6
7494}
7495
7496impl Default for ErrorDriftSchemaConfig {
7497 fn default() -> Self {
7498 Self {
7499 new_employee_error_rate: 0.08,
7500 learning_curve_months: 6,
7501 }
7502 }
7503}
7504
7505#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7507pub struct CollectiveBehaviorSchemaConfig {
7508 #[serde(default)]
7510 pub automation_adoption: AutomationAdoptionSchemaConfig,
7511}
7512
7513#[derive(Debug, Clone, Serialize, Deserialize)]
7515pub struct AutomationAdoptionSchemaConfig {
7516 #[serde(default)]
7518 pub s_curve_enabled: bool,
7519
7520 #[serde(default = "default_midpoint")]
7522 pub adoption_midpoint_months: u32,
7523
7524 #[serde(default = "default_steepness")]
7526 pub steepness: f64,
7527}
7528
7529fn default_midpoint() -> u32 {
7530 24
7531}
7532
7533fn default_steepness() -> f64 {
7534 0.15
7535}
7536
7537impl Default for AutomationAdoptionSchemaConfig {
7538 fn default() -> Self {
7539 Self {
7540 s_curve_enabled: false,
7541 adoption_midpoint_months: 24,
7542 steepness: 0.15,
7543 }
7544 }
7545}
7546
7547#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7553pub struct MarketDriftSchemaConfig {
7554 #[serde(default)]
7556 pub enabled: bool,
7557
7558 #[serde(default)]
7560 pub economic_cycle: MarketEconomicCycleSchemaConfig,
7561
7562 #[serde(default)]
7564 pub industry_cycles: std::collections::HashMap<String, IndustryCycleSchemaConfig>,
7565
7566 #[serde(default)]
7568 pub commodities: CommoditiesSchemaConfig,
7569}
7570
7571#[derive(Debug, Clone, Serialize, Deserialize)]
7573pub struct MarketEconomicCycleSchemaConfig {
7574 #[serde(default)]
7576 pub enabled: bool,
7577
7578 #[serde(default)]
7580 pub cycle_type: CycleTypeSchemaConfig,
7581
7582 #[serde(default = "default_market_cycle_period")]
7584 pub period_months: u32,
7585
7586 #[serde(default = "default_market_amplitude")]
7588 pub amplitude: f64,
7589
7590 #[serde(default)]
7592 pub recession: RecessionSchemaConfig,
7593}
7594
7595fn default_market_cycle_period() -> u32 {
7596 48
7597}
7598
7599fn default_market_amplitude() -> f64 {
7600 0.15
7601}
7602
7603impl Default for MarketEconomicCycleSchemaConfig {
7604 fn default() -> Self {
7605 Self {
7606 enabled: false,
7607 cycle_type: CycleTypeSchemaConfig::Sinusoidal,
7608 period_months: 48,
7609 amplitude: 0.15,
7610 recession: RecessionSchemaConfig::default(),
7611 }
7612 }
7613}
7614
7615#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
7617#[serde(rename_all = "snake_case")]
7618pub enum CycleTypeSchemaConfig {
7619 #[default]
7621 Sinusoidal,
7622 Asymmetric,
7624 MeanReverting,
7626}
7627
7628#[derive(Debug, Clone, Serialize, Deserialize)]
7630pub struct RecessionSchemaConfig {
7631 #[serde(default)]
7633 pub enabled: bool,
7634
7635 #[serde(default = "default_recession_prob")]
7637 pub probability_per_year: f64,
7638
7639 #[serde(default)]
7641 pub severity: RecessionSeveritySchemaConfig,
7642
7643 #[serde(default)]
7645 pub recession_periods: Vec<RecessionPeriodSchemaConfig>,
7646}
7647
7648fn default_recession_prob() -> f64 {
7649 0.10
7650}
7651
7652impl Default for RecessionSchemaConfig {
7653 fn default() -> Self {
7654 Self {
7655 enabled: false,
7656 probability_per_year: 0.10,
7657 severity: RecessionSeveritySchemaConfig::Moderate,
7658 recession_periods: Vec::new(),
7659 }
7660 }
7661}
7662
7663#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
7665#[serde(rename_all = "snake_case")]
7666pub enum RecessionSeveritySchemaConfig {
7667 Mild,
7669 #[default]
7671 Moderate,
7672 Severe,
7674}
7675
7676#[derive(Debug, Clone, Serialize, Deserialize)]
7678pub struct RecessionPeriodSchemaConfig {
7679 pub start_month: u32,
7681 pub duration_months: u32,
7683}
7684
7685#[derive(Debug, Clone, Serialize, Deserialize)]
7687pub struct IndustryCycleSchemaConfig {
7688 #[serde(default = "default_industry_period")]
7690 pub period_months: u32,
7691
7692 #[serde(default = "default_industry_amp")]
7694 pub amplitude: f64,
7695}
7696
7697fn default_industry_period() -> u32 {
7698 36
7699}
7700
7701fn default_industry_amp() -> f64 {
7702 0.20
7703}
7704
7705#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7707pub struct CommoditiesSchemaConfig {
7708 #[serde(default)]
7710 pub enabled: bool,
7711
7712 #[serde(default)]
7714 pub items: Vec<CommodityItemSchemaConfig>,
7715}
7716
7717#[derive(Debug, Clone, Serialize, Deserialize)]
7719pub struct CommodityItemSchemaConfig {
7720 pub name: String,
7722
7723 #[serde(default = "default_volatility")]
7725 pub volatility: f64,
7726
7727 #[serde(default)]
7729 pub cogs_pass_through: f64,
7730
7731 #[serde(default)]
7733 pub overhead_pass_through: f64,
7734}
7735
7736fn default_volatility() -> f64 {
7737 0.20
7738}
7739
7740#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7746pub struct DriftLabelingSchemaConfig {
7747 #[serde(default)]
7749 pub enabled: bool,
7750
7751 #[serde(default)]
7753 pub statistical: StatisticalDriftLabelingSchemaConfig,
7754
7755 #[serde(default)]
7757 pub categorical: CategoricalDriftLabelingSchemaConfig,
7758
7759 #[serde(default)]
7761 pub temporal: TemporalDriftLabelingSchemaConfig,
7762
7763 #[serde(default)]
7765 pub regulatory_calendar_preset: Option<String>,
7766}
7767
7768#[derive(Debug, Clone, Serialize, Deserialize)]
7770pub struct StatisticalDriftLabelingSchemaConfig {
7771 #[serde(default = "default_true_val")]
7773 pub enabled: bool,
7774
7775 #[serde(default = "default_min_magnitude")]
7777 pub min_magnitude_threshold: f64,
7778}
7779
7780fn default_min_magnitude() -> f64 {
7781 0.05
7782}
7783
7784impl Default for StatisticalDriftLabelingSchemaConfig {
7785 fn default() -> Self {
7786 Self {
7787 enabled: true,
7788 min_magnitude_threshold: 0.05,
7789 }
7790 }
7791}
7792
7793#[derive(Debug, Clone, Serialize, Deserialize)]
7795pub struct CategoricalDriftLabelingSchemaConfig {
7796 #[serde(default = "default_true_val")]
7798 pub enabled: bool,
7799}
7800
7801impl Default for CategoricalDriftLabelingSchemaConfig {
7802 fn default() -> Self {
7803 Self { enabled: true }
7804 }
7805}
7806
7807#[derive(Debug, Clone, Serialize, Deserialize)]
7809pub struct TemporalDriftLabelingSchemaConfig {
7810 #[serde(default = "default_true_val")]
7812 pub enabled: bool,
7813}
7814
7815impl Default for TemporalDriftLabelingSchemaConfig {
7816 fn default() -> Self {
7817 Self { enabled: true }
7818 }
7819}
7820
7821#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7834pub struct EnhancedAnomalyConfig {
7835 #[serde(default)]
7837 pub enabled: bool,
7838
7839 #[serde(default)]
7841 pub rates: AnomalyRateConfig,
7842
7843 #[serde(default)]
7845 pub multi_stage_schemes: MultiStageSchemeConfig,
7846
7847 #[serde(default)]
7849 pub correlated_injection: CorrelatedInjectionConfig,
7850
7851 #[serde(default)]
7853 pub near_miss: NearMissConfig,
7854
7855 #[serde(default)]
7857 pub difficulty_classification: DifficultyClassificationConfig,
7858
7859 #[serde(default)]
7861 pub context_aware: ContextAwareConfig,
7862
7863 #[serde(default)]
7865 pub labeling: EnhancedLabelingConfig,
7866}
7867
7868#[derive(Debug, Clone, Serialize, Deserialize)]
7870pub struct AnomalyRateConfig {
7871 #[serde(default = "default_total_anomaly_rate")]
7873 pub total_rate: f64,
7874
7875 #[serde(default = "default_fraud_anomaly_rate")]
7877 pub fraud_rate: f64,
7878
7879 #[serde(default = "default_error_anomaly_rate")]
7881 pub error_rate: f64,
7882
7883 #[serde(default = "default_process_anomaly_rate")]
7885 pub process_rate: f64,
7886}
7887
7888fn default_total_anomaly_rate() -> f64 {
7889 0.03
7890}
7891fn default_fraud_anomaly_rate() -> f64 {
7892 0.01
7893}
7894fn default_error_anomaly_rate() -> f64 {
7895 0.015
7896}
7897fn default_process_anomaly_rate() -> f64 {
7898 0.005
7899}
7900
7901impl Default for AnomalyRateConfig {
7902 fn default() -> Self {
7903 Self {
7904 total_rate: default_total_anomaly_rate(),
7905 fraud_rate: default_fraud_anomaly_rate(),
7906 error_rate: default_error_anomaly_rate(),
7907 process_rate: default_process_anomaly_rate(),
7908 }
7909 }
7910}
7911
7912#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7914pub struct MultiStageSchemeConfig {
7915 #[serde(default)]
7917 pub enabled: bool,
7918
7919 #[serde(default)]
7921 pub embezzlement: EmbezzlementSchemeConfig,
7922
7923 #[serde(default)]
7925 pub revenue_manipulation: RevenueManipulationSchemeConfig,
7926
7927 #[serde(default)]
7929 pub kickback: KickbackSchemeConfig,
7930}
7931
7932#[derive(Debug, Clone, Serialize, Deserialize)]
7934pub struct EmbezzlementSchemeConfig {
7935 #[serde(default = "default_embezzlement_probability")]
7937 pub probability: f64,
7938
7939 #[serde(default)]
7941 pub testing_stage: SchemeStageConfig,
7942
7943 #[serde(default)]
7945 pub escalation_stage: SchemeStageConfig,
7946
7947 #[serde(default)]
7949 pub acceleration_stage: SchemeStageConfig,
7950
7951 #[serde(default)]
7953 pub desperation_stage: SchemeStageConfig,
7954}
7955
7956fn default_embezzlement_probability() -> f64 {
7957 0.02
7958}
7959
7960impl Default for EmbezzlementSchemeConfig {
7961 fn default() -> Self {
7962 Self {
7963 probability: default_embezzlement_probability(),
7964 testing_stage: SchemeStageConfig {
7965 duration_months: 2,
7966 amount_min: 100.0,
7967 amount_max: 500.0,
7968 transaction_count_min: 2,
7969 transaction_count_max: 5,
7970 difficulty: "hard".to_string(),
7971 },
7972 escalation_stage: SchemeStageConfig {
7973 duration_months: 6,
7974 amount_min: 500.0,
7975 amount_max: 2000.0,
7976 transaction_count_min: 3,
7977 transaction_count_max: 8,
7978 difficulty: "moderate".to_string(),
7979 },
7980 acceleration_stage: SchemeStageConfig {
7981 duration_months: 3,
7982 amount_min: 2000.0,
7983 amount_max: 10000.0,
7984 transaction_count_min: 5,
7985 transaction_count_max: 12,
7986 difficulty: "easy".to_string(),
7987 },
7988 desperation_stage: SchemeStageConfig {
7989 duration_months: 1,
7990 amount_min: 10000.0,
7991 amount_max: 50000.0,
7992 transaction_count_min: 3,
7993 transaction_count_max: 6,
7994 difficulty: "trivial".to_string(),
7995 },
7996 }
7997 }
7998}
7999
8000#[derive(Debug, Clone, Serialize, Deserialize)]
8002pub struct RevenueManipulationSchemeConfig {
8003 #[serde(default = "default_revenue_manipulation_probability")]
8005 pub probability: f64,
8006
8007 #[serde(default = "default_early_recognition_target")]
8009 pub early_recognition_target: f64,
8010
8011 #[serde(default = "default_expense_deferral_target")]
8013 pub expense_deferral_target: f64,
8014
8015 #[serde(default = "default_reserve_release_target")]
8017 pub reserve_release_target: f64,
8018
8019 #[serde(default = "default_channel_stuffing_target")]
8021 pub channel_stuffing_target: f64,
8022}
8023
8024fn default_revenue_manipulation_probability() -> f64 {
8025 0.01
8026}
8027fn default_early_recognition_target() -> f64 {
8028 0.02
8029}
8030fn default_expense_deferral_target() -> f64 {
8031 0.03
8032}
8033fn default_reserve_release_target() -> f64 {
8034 0.02
8035}
8036fn default_channel_stuffing_target() -> f64 {
8037 0.05
8038}
8039
8040impl Default for RevenueManipulationSchemeConfig {
8041 fn default() -> Self {
8042 Self {
8043 probability: default_revenue_manipulation_probability(),
8044 early_recognition_target: default_early_recognition_target(),
8045 expense_deferral_target: default_expense_deferral_target(),
8046 reserve_release_target: default_reserve_release_target(),
8047 channel_stuffing_target: default_channel_stuffing_target(),
8048 }
8049 }
8050}
8051
8052#[derive(Debug, Clone, Serialize, Deserialize)]
8054pub struct KickbackSchemeConfig {
8055 #[serde(default = "default_kickback_probability")]
8057 pub probability: f64,
8058
8059 #[serde(default = "default_kickback_inflation_min")]
8061 pub inflation_min: f64,
8062
8063 #[serde(default = "default_kickback_inflation_max")]
8065 pub inflation_max: f64,
8066
8067 #[serde(default = "default_kickback_percent")]
8069 pub kickback_percent: f64,
8070
8071 #[serde(default = "default_kickback_setup_months")]
8073 pub setup_months: u32,
8074
8075 #[serde(default = "default_kickback_operation_months")]
8077 pub operation_months: u32,
8078}
8079
8080fn default_kickback_probability() -> f64 {
8081 0.01
8082}
8083fn default_kickback_inflation_min() -> f64 {
8084 0.10
8085}
8086fn default_kickback_inflation_max() -> f64 {
8087 0.25
8088}
8089fn default_kickback_percent() -> f64 {
8090 0.50
8091}
8092fn default_kickback_setup_months() -> u32 {
8093 3
8094}
8095fn default_kickback_operation_months() -> u32 {
8096 12
8097}
8098
8099impl Default for KickbackSchemeConfig {
8100 fn default() -> Self {
8101 Self {
8102 probability: default_kickback_probability(),
8103 inflation_min: default_kickback_inflation_min(),
8104 inflation_max: default_kickback_inflation_max(),
8105 kickback_percent: default_kickback_percent(),
8106 setup_months: default_kickback_setup_months(),
8107 operation_months: default_kickback_operation_months(),
8108 }
8109 }
8110}
8111
8112#[derive(Debug, Clone, Serialize, Deserialize)]
8114pub struct SchemeStageConfig {
8115 pub duration_months: u32,
8117
8118 pub amount_min: f64,
8120
8121 pub amount_max: f64,
8123
8124 pub transaction_count_min: u32,
8126
8127 pub transaction_count_max: u32,
8129
8130 pub difficulty: String,
8132}
8133
8134impl Default for SchemeStageConfig {
8135 fn default() -> Self {
8136 Self {
8137 duration_months: 3,
8138 amount_min: 100.0,
8139 amount_max: 1000.0,
8140 transaction_count_min: 2,
8141 transaction_count_max: 10,
8142 difficulty: "moderate".to_string(),
8143 }
8144 }
8145}
8146
8147#[derive(Debug, Clone, Serialize, Deserialize)]
8149pub struct CorrelatedInjectionConfig {
8150 #[serde(default)]
8152 pub enabled: bool,
8153
8154 #[serde(default = "default_true_val")]
8156 pub fraud_concealment: bool,
8157
8158 #[serde(default = "default_true_val")]
8160 pub error_cascade: bool,
8161
8162 #[serde(default = "default_true_val")]
8164 pub temporal_clustering: bool,
8165
8166 #[serde(default)]
8168 pub temporal_clustering_config: TemporalClusteringConfig,
8169
8170 #[serde(default)]
8172 pub co_occurrence_patterns: Vec<CoOccurrencePatternConfig>,
8173}
8174
8175impl Default for CorrelatedInjectionConfig {
8176 fn default() -> Self {
8177 Self {
8178 enabled: false,
8179 fraud_concealment: true,
8180 error_cascade: true,
8181 temporal_clustering: true,
8182 temporal_clustering_config: TemporalClusteringConfig::default(),
8183 co_occurrence_patterns: Vec::new(),
8184 }
8185 }
8186}
8187
8188#[derive(Debug, Clone, Serialize, Deserialize)]
8190pub struct TemporalClusteringConfig {
8191 #[serde(default = "default_period_end_multiplier")]
8193 pub period_end_multiplier: f64,
8194
8195 #[serde(default = "default_period_end_days")]
8197 pub period_end_days: u32,
8198
8199 #[serde(default = "default_quarter_end_multiplier")]
8201 pub quarter_end_multiplier: f64,
8202
8203 #[serde(default = "default_year_end_multiplier")]
8205 pub year_end_multiplier: f64,
8206}
8207
8208fn default_period_end_multiplier() -> f64 {
8209 2.5
8210}
8211fn default_period_end_days() -> u32 {
8212 5
8213}
8214fn default_quarter_end_multiplier() -> f64 {
8215 1.5
8216}
8217fn default_year_end_multiplier() -> f64 {
8218 2.0
8219}
8220
8221impl Default for TemporalClusteringConfig {
8222 fn default() -> Self {
8223 Self {
8224 period_end_multiplier: default_period_end_multiplier(),
8225 period_end_days: default_period_end_days(),
8226 quarter_end_multiplier: default_quarter_end_multiplier(),
8227 year_end_multiplier: default_year_end_multiplier(),
8228 }
8229 }
8230}
8231
8232#[derive(Debug, Clone, Serialize, Deserialize)]
8234pub struct CoOccurrencePatternConfig {
8235 pub name: String,
8237
8238 pub primary_type: String,
8240
8241 pub correlated: Vec<CorrelatedAnomalyConfig>,
8243}
8244
8245#[derive(Debug, Clone, Serialize, Deserialize)]
8247pub struct CorrelatedAnomalyConfig {
8248 pub anomaly_type: String,
8250
8251 pub probability: f64,
8253
8254 pub lag_days_min: i32,
8256
8257 pub lag_days_max: i32,
8259}
8260
8261#[derive(Debug, Clone, Serialize, Deserialize)]
8263pub struct NearMissConfig {
8264 #[serde(default)]
8266 pub enabled: bool,
8267
8268 #[serde(default = "default_near_miss_proportion")]
8270 pub proportion: f64,
8271
8272 #[serde(default = "default_true_val")]
8274 pub near_duplicate: bool,
8275
8276 #[serde(default)]
8278 pub near_duplicate_days: NearDuplicateDaysConfig,
8279
8280 #[serde(default = "default_true_val")]
8282 pub threshold_proximity: bool,
8283
8284 #[serde(default)]
8286 pub threshold_proximity_range: ThresholdProximityRangeConfig,
8287
8288 #[serde(default = "default_true_val")]
8290 pub unusual_legitimate: bool,
8291
8292 #[serde(default = "default_unusual_legitimate_types")]
8294 pub unusual_legitimate_types: Vec<String>,
8295
8296 #[serde(default = "default_true_val")]
8298 pub corrected_errors: bool,
8299
8300 #[serde(default)]
8302 pub corrected_error_lag: CorrectedErrorLagConfig,
8303}
8304
8305fn default_near_miss_proportion() -> f64 {
8306 0.30
8307}
8308
8309fn default_unusual_legitimate_types() -> Vec<String> {
8310 vec![
8311 "year_end_bonus".to_string(),
8312 "contract_prepayment".to_string(),
8313 "insurance_claim".to_string(),
8314 "settlement_payment".to_string(),
8315 ]
8316}
8317
8318impl Default for NearMissConfig {
8319 fn default() -> Self {
8320 Self {
8321 enabled: false,
8322 proportion: default_near_miss_proportion(),
8323 near_duplicate: true,
8324 near_duplicate_days: NearDuplicateDaysConfig::default(),
8325 threshold_proximity: true,
8326 threshold_proximity_range: ThresholdProximityRangeConfig::default(),
8327 unusual_legitimate: true,
8328 unusual_legitimate_types: default_unusual_legitimate_types(),
8329 corrected_errors: true,
8330 corrected_error_lag: CorrectedErrorLagConfig::default(),
8331 }
8332 }
8333}
8334
8335#[derive(Debug, Clone, Serialize, Deserialize)]
8337pub struct NearDuplicateDaysConfig {
8338 #[serde(default = "default_near_duplicate_min")]
8340 pub min: u32,
8341
8342 #[serde(default = "default_near_duplicate_max")]
8344 pub max: u32,
8345}
8346
8347fn default_near_duplicate_min() -> u32 {
8348 1
8349}
8350fn default_near_duplicate_max() -> u32 {
8351 3
8352}
8353
8354impl Default for NearDuplicateDaysConfig {
8355 fn default() -> Self {
8356 Self {
8357 min: default_near_duplicate_min(),
8358 max: default_near_duplicate_max(),
8359 }
8360 }
8361}
8362
8363#[derive(Debug, Clone, Serialize, Deserialize)]
8365pub struct ThresholdProximityRangeConfig {
8366 #[serde(default = "default_threshold_proximity_min")]
8368 pub min: f64,
8369
8370 #[serde(default = "default_threshold_proximity_max")]
8372 pub max: f64,
8373}
8374
8375fn default_threshold_proximity_min() -> f64 {
8376 0.90
8377}
8378fn default_threshold_proximity_max() -> f64 {
8379 0.99
8380}
8381
8382impl Default for ThresholdProximityRangeConfig {
8383 fn default() -> Self {
8384 Self {
8385 min: default_threshold_proximity_min(),
8386 max: default_threshold_proximity_max(),
8387 }
8388 }
8389}
8390
8391#[derive(Debug, Clone, Serialize, Deserialize)]
8393pub struct CorrectedErrorLagConfig {
8394 #[serde(default = "default_corrected_error_lag_min")]
8396 pub min: u32,
8397
8398 #[serde(default = "default_corrected_error_lag_max")]
8400 pub max: u32,
8401}
8402
8403fn default_corrected_error_lag_min() -> u32 {
8404 1
8405}
8406fn default_corrected_error_lag_max() -> u32 {
8407 5
8408}
8409
8410impl Default for CorrectedErrorLagConfig {
8411 fn default() -> Self {
8412 Self {
8413 min: default_corrected_error_lag_min(),
8414 max: default_corrected_error_lag_max(),
8415 }
8416 }
8417}
8418
8419#[derive(Debug, Clone, Serialize, Deserialize)]
8421pub struct DifficultyClassificationConfig {
8422 #[serde(default)]
8424 pub enabled: bool,
8425
8426 #[serde(default)]
8428 pub target_distribution: DifficultyDistributionConfig,
8429}
8430
8431impl Default for DifficultyClassificationConfig {
8432 fn default() -> Self {
8433 Self {
8434 enabled: true,
8435 target_distribution: DifficultyDistributionConfig::default(),
8436 }
8437 }
8438}
8439
8440#[derive(Debug, Clone, Serialize, Deserialize)]
8442pub struct DifficultyDistributionConfig {
8443 #[serde(default = "default_difficulty_trivial")]
8445 pub trivial: f64,
8446
8447 #[serde(default = "default_difficulty_easy")]
8449 pub easy: f64,
8450
8451 #[serde(default = "default_difficulty_moderate")]
8453 pub moderate: f64,
8454
8455 #[serde(default = "default_difficulty_hard")]
8457 pub hard: f64,
8458
8459 #[serde(default = "default_difficulty_expert")]
8461 pub expert: f64,
8462}
8463
8464fn default_difficulty_trivial() -> f64 {
8465 0.15
8466}
8467fn default_difficulty_easy() -> f64 {
8468 0.25
8469}
8470fn default_difficulty_moderate() -> f64 {
8471 0.30
8472}
8473fn default_difficulty_hard() -> f64 {
8474 0.20
8475}
8476fn default_difficulty_expert() -> f64 {
8477 0.10
8478}
8479
8480impl Default for DifficultyDistributionConfig {
8481 fn default() -> Self {
8482 Self {
8483 trivial: default_difficulty_trivial(),
8484 easy: default_difficulty_easy(),
8485 moderate: default_difficulty_moderate(),
8486 hard: default_difficulty_hard(),
8487 expert: default_difficulty_expert(),
8488 }
8489 }
8490}
8491
8492#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8494pub struct ContextAwareConfig {
8495 #[serde(default)]
8497 pub enabled: bool,
8498
8499 #[serde(default)]
8501 pub vendor_rules: VendorAnomalyRulesConfig,
8502
8503 #[serde(default)]
8505 pub employee_rules: EmployeeAnomalyRulesConfig,
8506
8507 #[serde(default)]
8509 pub account_rules: AccountAnomalyRulesConfig,
8510
8511 #[serde(default)]
8513 pub behavioral_baseline: BehavioralBaselineConfig,
8514}
8515
8516#[derive(Debug, Clone, Serialize, Deserialize)]
8518pub struct VendorAnomalyRulesConfig {
8519 #[serde(default = "default_new_vendor_multiplier")]
8521 pub new_vendor_error_multiplier: f64,
8522
8523 #[serde(default = "default_new_vendor_threshold")]
8525 pub new_vendor_threshold_days: u32,
8526
8527 #[serde(default = "default_international_multiplier")]
8529 pub international_error_multiplier: f64,
8530
8531 #[serde(default = "default_strategic_vendor_types")]
8533 pub strategic_vendor_anomaly_types: Vec<String>,
8534}
8535
8536fn default_new_vendor_multiplier() -> f64 {
8537 2.5
8538}
8539fn default_new_vendor_threshold() -> u32 {
8540 90
8541}
8542fn default_international_multiplier() -> f64 {
8543 1.5
8544}
8545fn default_strategic_vendor_types() -> Vec<String> {
8546 vec![
8547 "pricing_dispute".to_string(),
8548 "contract_violation".to_string(),
8549 ]
8550}
8551
8552impl Default for VendorAnomalyRulesConfig {
8553 fn default() -> Self {
8554 Self {
8555 new_vendor_error_multiplier: default_new_vendor_multiplier(),
8556 new_vendor_threshold_days: default_new_vendor_threshold(),
8557 international_error_multiplier: default_international_multiplier(),
8558 strategic_vendor_anomaly_types: default_strategic_vendor_types(),
8559 }
8560 }
8561}
8562
8563#[derive(Debug, Clone, Serialize, Deserialize)]
8565pub struct EmployeeAnomalyRulesConfig {
8566 #[serde(default = "default_new_employee_rate")]
8568 pub new_employee_error_rate: f64,
8569
8570 #[serde(default = "default_new_employee_threshold")]
8572 pub new_employee_threshold_days: u32,
8573
8574 #[serde(default = "default_volume_fatigue_threshold")]
8576 pub volume_fatigue_threshold: u32,
8577
8578 #[serde(default = "default_coverage_multiplier")]
8580 pub coverage_error_multiplier: f64,
8581}
8582
8583fn default_new_employee_rate() -> f64 {
8584 0.05
8585}
8586fn default_new_employee_threshold() -> u32 {
8587 180
8588}
8589fn default_volume_fatigue_threshold() -> u32 {
8590 50
8591}
8592fn default_coverage_multiplier() -> f64 {
8593 1.8
8594}
8595
8596impl Default for EmployeeAnomalyRulesConfig {
8597 fn default() -> Self {
8598 Self {
8599 new_employee_error_rate: default_new_employee_rate(),
8600 new_employee_threshold_days: default_new_employee_threshold(),
8601 volume_fatigue_threshold: default_volume_fatigue_threshold(),
8602 coverage_error_multiplier: default_coverage_multiplier(),
8603 }
8604 }
8605}
8606
8607#[derive(Debug, Clone, Serialize, Deserialize)]
8609pub struct AccountAnomalyRulesConfig {
8610 #[serde(default = "default_high_risk_multiplier")]
8612 pub high_risk_account_multiplier: f64,
8613
8614 #[serde(default = "default_high_risk_accounts")]
8616 pub high_risk_accounts: Vec<String>,
8617
8618 #[serde(default = "default_suspense_multiplier")]
8620 pub suspense_account_multiplier: f64,
8621
8622 #[serde(default = "default_suspense_accounts")]
8624 pub suspense_accounts: Vec<String>,
8625
8626 #[serde(default = "default_intercompany_multiplier")]
8628 pub intercompany_account_multiplier: f64,
8629}
8630
8631fn default_high_risk_multiplier() -> f64 {
8632 2.0
8633}
8634fn default_high_risk_accounts() -> Vec<String> {
8635 vec![
8636 "1100".to_string(), "2000".to_string(), "3000".to_string(), ]
8640}
8641fn default_suspense_multiplier() -> f64 {
8642 3.0
8643}
8644fn default_suspense_accounts() -> Vec<String> {
8645 vec!["9999".to_string(), "9998".to_string()]
8646}
8647fn default_intercompany_multiplier() -> f64 {
8648 1.5
8649}
8650
8651impl Default for AccountAnomalyRulesConfig {
8652 fn default() -> Self {
8653 Self {
8654 high_risk_account_multiplier: default_high_risk_multiplier(),
8655 high_risk_accounts: default_high_risk_accounts(),
8656 suspense_account_multiplier: default_suspense_multiplier(),
8657 suspense_accounts: default_suspense_accounts(),
8658 intercompany_account_multiplier: default_intercompany_multiplier(),
8659 }
8660 }
8661}
8662
8663#[derive(Debug, Clone, Serialize, Deserialize)]
8665pub struct BehavioralBaselineConfig {
8666 #[serde(default)]
8668 pub enabled: bool,
8669
8670 #[serde(default = "default_baseline_period")]
8672 pub baseline_period_days: u32,
8673
8674 #[serde(default = "default_deviation_threshold")]
8676 pub deviation_threshold_std: f64,
8677
8678 #[serde(default = "default_frequency_deviation")]
8680 pub frequency_deviation_threshold: f64,
8681}
8682
8683fn default_baseline_period() -> u32 {
8684 90
8685}
8686fn default_deviation_threshold() -> f64 {
8687 3.0
8688}
8689fn default_frequency_deviation() -> f64 {
8690 2.0
8691}
8692
8693impl Default for BehavioralBaselineConfig {
8694 fn default() -> Self {
8695 Self {
8696 enabled: false,
8697 baseline_period_days: default_baseline_period(),
8698 deviation_threshold_std: default_deviation_threshold(),
8699 frequency_deviation_threshold: default_frequency_deviation(),
8700 }
8701 }
8702}
8703
8704#[derive(Debug, Clone, Serialize, Deserialize)]
8706pub struct EnhancedLabelingConfig {
8707 #[serde(default = "default_true_val")]
8709 pub severity_scoring: bool,
8710
8711 #[serde(default = "default_true_val")]
8713 pub difficulty_classification: bool,
8714
8715 #[serde(default)]
8717 pub materiality_thresholds: MaterialityThresholdsConfig,
8718}
8719
8720impl Default for EnhancedLabelingConfig {
8721 fn default() -> Self {
8722 Self {
8723 severity_scoring: true,
8724 difficulty_classification: true,
8725 materiality_thresholds: MaterialityThresholdsConfig::default(),
8726 }
8727 }
8728}
8729
8730#[derive(Debug, Clone, Serialize, Deserialize)]
8732pub struct MaterialityThresholdsConfig {
8733 #[serde(default = "default_materiality_trivial")]
8735 pub trivial: f64,
8736
8737 #[serde(default = "default_materiality_immaterial")]
8739 pub immaterial: f64,
8740
8741 #[serde(default = "default_materiality_material")]
8743 pub material: f64,
8744
8745 #[serde(default = "default_materiality_highly_material")]
8747 pub highly_material: f64,
8748}
8749
8750fn default_materiality_trivial() -> f64 {
8751 0.001
8752}
8753fn default_materiality_immaterial() -> f64 {
8754 0.01
8755}
8756fn default_materiality_material() -> f64 {
8757 0.05
8758}
8759fn default_materiality_highly_material() -> f64 {
8760 0.10
8761}
8762
8763impl Default for MaterialityThresholdsConfig {
8764 fn default() -> Self {
8765 Self {
8766 trivial: default_materiality_trivial(),
8767 immaterial: default_materiality_immaterial(),
8768 material: default_materiality_material(),
8769 highly_material: default_materiality_highly_material(),
8770 }
8771 }
8772}
8773
8774#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8786pub struct IndustrySpecificConfig {
8787 #[serde(default)]
8789 pub enabled: bool,
8790
8791 #[serde(default)]
8793 pub manufacturing: ManufacturingConfig,
8794
8795 #[serde(default)]
8797 pub retail: RetailConfig,
8798
8799 #[serde(default)]
8801 pub healthcare: HealthcareConfig,
8802
8803 #[serde(default)]
8805 pub technology: TechnologyConfig,
8806
8807 #[serde(default)]
8809 pub financial_services: FinancialServicesConfig,
8810
8811 #[serde(default)]
8813 pub professional_services: ProfessionalServicesConfig,
8814}
8815
8816#[derive(Debug, Clone, Serialize, Deserialize)]
8818pub struct ManufacturingConfig {
8819 #[serde(default)]
8821 pub enabled: bool,
8822
8823 #[serde(default = "default_bom_depth")]
8825 pub bom_depth: u32,
8826
8827 #[serde(default)]
8829 pub just_in_time: bool,
8830
8831 #[serde(default = "default_production_order_types")]
8833 pub production_order_types: Vec<String>,
8834
8835 #[serde(default)]
8837 pub quality_framework: Option<String>,
8838
8839 #[serde(default = "default_supplier_tiers")]
8841 pub supplier_tiers: u32,
8842
8843 #[serde(default = "default_cost_frequency")]
8845 pub standard_cost_frequency: String,
8846
8847 #[serde(default = "default_yield_rate")]
8849 pub target_yield_rate: f64,
8850
8851 #[serde(default = "default_scrap_threshold")]
8853 pub scrap_alert_threshold: f64,
8854
8855 #[serde(default)]
8857 pub anomaly_rates: ManufacturingAnomalyRates,
8858}
8859
8860fn default_bom_depth() -> u32 {
8861 4
8862}
8863
8864fn default_production_order_types() -> Vec<String> {
8865 vec![
8866 "standard".to_string(),
8867 "rework".to_string(),
8868 "prototype".to_string(),
8869 ]
8870}
8871
8872fn default_supplier_tiers() -> u32 {
8873 2
8874}
8875
8876fn default_cost_frequency() -> String {
8877 "quarterly".to_string()
8878}
8879
8880fn default_yield_rate() -> f64 {
8881 0.97
8882}
8883
8884fn default_scrap_threshold() -> f64 {
8885 0.03
8886}
8887
8888impl Default for ManufacturingConfig {
8889 fn default() -> Self {
8890 Self {
8891 enabled: false,
8892 bom_depth: default_bom_depth(),
8893 just_in_time: false,
8894 production_order_types: default_production_order_types(),
8895 quality_framework: Some("ISO_9001".to_string()),
8896 supplier_tiers: default_supplier_tiers(),
8897 standard_cost_frequency: default_cost_frequency(),
8898 target_yield_rate: default_yield_rate(),
8899 scrap_alert_threshold: default_scrap_threshold(),
8900 anomaly_rates: ManufacturingAnomalyRates::default(),
8901 }
8902 }
8903}
8904
8905#[derive(Debug, Clone, Serialize, Deserialize)]
8907pub struct ManufacturingAnomalyRates {
8908 #[serde(default = "default_mfg_yield_rate")]
8910 pub yield_manipulation: f64,
8911
8912 #[serde(default = "default_mfg_labor_rate")]
8914 pub labor_misallocation: f64,
8915
8916 #[serde(default = "default_mfg_phantom_rate")]
8918 pub phantom_production: f64,
8919
8920 #[serde(default = "default_mfg_cost_rate")]
8922 pub standard_cost_manipulation: f64,
8923
8924 #[serde(default = "default_mfg_inventory_rate")]
8926 pub inventory_fraud: f64,
8927}
8928
8929fn default_mfg_yield_rate() -> f64 {
8930 0.015
8931}
8932
8933fn default_mfg_labor_rate() -> f64 {
8934 0.02
8935}
8936
8937fn default_mfg_phantom_rate() -> f64 {
8938 0.005
8939}
8940
8941fn default_mfg_cost_rate() -> f64 {
8942 0.01
8943}
8944
8945fn default_mfg_inventory_rate() -> f64 {
8946 0.008
8947}
8948
8949impl Default for ManufacturingAnomalyRates {
8950 fn default() -> Self {
8951 Self {
8952 yield_manipulation: default_mfg_yield_rate(),
8953 labor_misallocation: default_mfg_labor_rate(),
8954 phantom_production: default_mfg_phantom_rate(),
8955 standard_cost_manipulation: default_mfg_cost_rate(),
8956 inventory_fraud: default_mfg_inventory_rate(),
8957 }
8958 }
8959}
8960
8961#[derive(Debug, Clone, Serialize, Deserialize)]
8963pub struct RetailConfig {
8964 #[serde(default)]
8966 pub enabled: bool,
8967
8968 #[serde(default)]
8970 pub store_types: RetailStoreTypeConfig,
8971
8972 #[serde(default = "default_retail_daily_txns")]
8974 pub avg_daily_transactions: u32,
8975
8976 #[serde(default = "default_true")]
8978 pub loss_prevention: bool,
8979
8980 #[serde(default = "default_shrinkage_rate")]
8982 pub shrinkage_rate: f64,
8983
8984 #[serde(default)]
8986 pub anomaly_rates: RetailAnomalyRates,
8987}
8988
8989fn default_retail_daily_txns() -> u32 {
8990 500
8991}
8992
8993fn default_shrinkage_rate() -> f64 {
8994 0.015
8995}
8996
8997impl Default for RetailConfig {
8998 fn default() -> Self {
8999 Self {
9000 enabled: false,
9001 store_types: RetailStoreTypeConfig::default(),
9002 avg_daily_transactions: default_retail_daily_txns(),
9003 loss_prevention: true,
9004 shrinkage_rate: default_shrinkage_rate(),
9005 anomaly_rates: RetailAnomalyRates::default(),
9006 }
9007 }
9008}
9009
9010#[derive(Debug, Clone, Serialize, Deserialize)]
9012pub struct RetailStoreTypeConfig {
9013 #[serde(default = "default_flagship_pct")]
9015 pub flagship: f64,
9016
9017 #[serde(default = "default_regional_pct")]
9019 pub regional: f64,
9020
9021 #[serde(default = "default_outlet_pct")]
9023 pub outlet: f64,
9024
9025 #[serde(default = "default_ecommerce_pct")]
9027 pub ecommerce: f64,
9028}
9029
9030fn default_flagship_pct() -> f64 {
9031 0.10
9032}
9033
9034fn default_regional_pct() -> f64 {
9035 0.50
9036}
9037
9038fn default_outlet_pct() -> f64 {
9039 0.25
9040}
9041
9042fn default_ecommerce_pct() -> f64 {
9043 0.15
9044}
9045
9046impl Default for RetailStoreTypeConfig {
9047 fn default() -> Self {
9048 Self {
9049 flagship: default_flagship_pct(),
9050 regional: default_regional_pct(),
9051 outlet: default_outlet_pct(),
9052 ecommerce: default_ecommerce_pct(),
9053 }
9054 }
9055}
9056
9057#[derive(Debug, Clone, Serialize, Deserialize)]
9059pub struct RetailAnomalyRates {
9060 #[serde(default = "default_sweethearting_rate")]
9062 pub sweethearting: f64,
9063
9064 #[serde(default = "default_skimming_rate")]
9066 pub skimming: f64,
9067
9068 #[serde(default = "default_refund_fraud_rate")]
9070 pub refund_fraud: f64,
9071
9072 #[serde(default = "default_void_abuse_rate")]
9074 pub void_abuse: f64,
9075
9076 #[serde(default = "default_gift_card_rate")]
9078 pub gift_card_fraud: f64,
9079
9080 #[serde(default = "default_retail_kickback_rate")]
9082 pub vendor_kickback: f64,
9083}
9084
9085fn default_sweethearting_rate() -> f64 {
9086 0.02
9087}
9088
9089fn default_skimming_rate() -> f64 {
9090 0.005
9091}
9092
9093fn default_refund_fraud_rate() -> f64 {
9094 0.015
9095}
9096
9097fn default_void_abuse_rate() -> f64 {
9098 0.01
9099}
9100
9101fn default_gift_card_rate() -> f64 {
9102 0.008
9103}
9104
9105fn default_retail_kickback_rate() -> f64 {
9106 0.003
9107}
9108
9109impl Default for RetailAnomalyRates {
9110 fn default() -> Self {
9111 Self {
9112 sweethearting: default_sweethearting_rate(),
9113 skimming: default_skimming_rate(),
9114 refund_fraud: default_refund_fraud_rate(),
9115 void_abuse: default_void_abuse_rate(),
9116 gift_card_fraud: default_gift_card_rate(),
9117 vendor_kickback: default_retail_kickback_rate(),
9118 }
9119 }
9120}
9121
9122#[derive(Debug, Clone, Serialize, Deserialize)]
9124pub struct HealthcareConfig {
9125 #[serde(default)]
9127 pub enabled: bool,
9128
9129 #[serde(default = "default_facility_type")]
9131 pub facility_type: String,
9132
9133 #[serde(default)]
9135 pub payer_mix: HealthcarePayerMix,
9136
9137 #[serde(default)]
9139 pub coding_systems: HealthcareCodingSystems,
9140
9141 #[serde(default)]
9143 pub compliance: HealthcareComplianceConfig,
9144
9145 #[serde(default = "default_daily_encounters")]
9147 pub avg_daily_encounters: u32,
9148
9149 #[serde(default = "default_charges_per_encounter")]
9151 pub avg_charges_per_encounter: u32,
9152
9153 #[serde(default = "default_hc_denial_rate")]
9155 pub denial_rate: f64,
9156
9157 #[serde(default = "default_hc_bad_debt_rate")]
9159 pub bad_debt_rate: f64,
9160
9161 #[serde(default = "default_hc_charity_care_rate")]
9163 pub charity_care_rate: f64,
9164
9165 #[serde(default)]
9167 pub anomaly_rates: HealthcareAnomalyRates,
9168}
9169
9170fn default_facility_type() -> String {
9171 "hospital".to_string()
9172}
9173
9174fn default_daily_encounters() -> u32 {
9175 150
9176}
9177
9178fn default_charges_per_encounter() -> u32 {
9179 8
9180}
9181
9182fn default_hc_denial_rate() -> f64 {
9183 0.05
9184}
9185
9186fn default_hc_bad_debt_rate() -> f64 {
9187 0.03
9188}
9189
9190fn default_hc_charity_care_rate() -> f64 {
9191 0.02
9192}
9193
9194impl Default for HealthcareConfig {
9195 fn default() -> Self {
9196 Self {
9197 enabled: false,
9198 facility_type: default_facility_type(),
9199 payer_mix: HealthcarePayerMix::default(),
9200 coding_systems: HealthcareCodingSystems::default(),
9201 compliance: HealthcareComplianceConfig::default(),
9202 avg_daily_encounters: default_daily_encounters(),
9203 avg_charges_per_encounter: default_charges_per_encounter(),
9204 denial_rate: default_hc_denial_rate(),
9205 bad_debt_rate: default_hc_bad_debt_rate(),
9206 charity_care_rate: default_hc_charity_care_rate(),
9207 anomaly_rates: HealthcareAnomalyRates::default(),
9208 }
9209 }
9210}
9211
9212#[derive(Debug, Clone, Serialize, Deserialize)]
9214pub struct HealthcarePayerMix {
9215 #[serde(default = "default_medicare_pct")]
9217 pub medicare: f64,
9218
9219 #[serde(default = "default_medicaid_pct")]
9221 pub medicaid: f64,
9222
9223 #[serde(default = "default_commercial_pct")]
9225 pub commercial: f64,
9226
9227 #[serde(default = "default_self_pay_pct")]
9229 pub self_pay: f64,
9230}
9231
9232fn default_medicare_pct() -> f64 {
9233 0.40
9234}
9235
9236fn default_medicaid_pct() -> f64 {
9237 0.20
9238}
9239
9240fn default_commercial_pct() -> f64 {
9241 0.30
9242}
9243
9244fn default_self_pay_pct() -> f64 {
9245 0.10
9246}
9247
9248impl Default for HealthcarePayerMix {
9249 fn default() -> Self {
9250 Self {
9251 medicare: default_medicare_pct(),
9252 medicaid: default_medicaid_pct(),
9253 commercial: default_commercial_pct(),
9254 self_pay: default_self_pay_pct(),
9255 }
9256 }
9257}
9258
9259#[derive(Debug, Clone, Serialize, Deserialize)]
9261pub struct HealthcareCodingSystems {
9262 #[serde(default = "default_true")]
9264 pub icd10: bool,
9265
9266 #[serde(default = "default_true")]
9268 pub cpt: bool,
9269
9270 #[serde(default = "default_true")]
9272 pub drg: bool,
9273
9274 #[serde(default = "default_true")]
9276 pub hcpcs: bool,
9277
9278 #[serde(default = "default_true")]
9280 pub revenue_codes: bool,
9281}
9282
9283impl Default for HealthcareCodingSystems {
9284 fn default() -> Self {
9285 Self {
9286 icd10: true,
9287 cpt: true,
9288 drg: true,
9289 hcpcs: true,
9290 revenue_codes: true,
9291 }
9292 }
9293}
9294
9295#[derive(Debug, Clone, Serialize, Deserialize)]
9297pub struct HealthcareComplianceConfig {
9298 #[serde(default = "default_true")]
9300 pub hipaa: bool,
9301
9302 #[serde(default = "default_true")]
9304 pub stark_law: bool,
9305
9306 #[serde(default = "default_true")]
9308 pub anti_kickback: bool,
9309
9310 #[serde(default = "default_true")]
9312 pub false_claims_act: bool,
9313
9314 #[serde(default = "default_true")]
9316 pub emtala: bool,
9317}
9318
9319impl Default for HealthcareComplianceConfig {
9320 fn default() -> Self {
9321 Self {
9322 hipaa: true,
9323 stark_law: true,
9324 anti_kickback: true,
9325 false_claims_act: true,
9326 emtala: true,
9327 }
9328 }
9329}
9330
9331#[derive(Debug, Clone, Serialize, Deserialize)]
9333pub struct HealthcareAnomalyRates {
9334 #[serde(default = "default_upcoding_rate")]
9336 pub upcoding: f64,
9337
9338 #[serde(default = "default_unbundling_rate")]
9340 pub unbundling: f64,
9341
9342 #[serde(default = "default_phantom_billing_rate")]
9344 pub phantom_billing: f64,
9345
9346 #[serde(default = "default_healthcare_kickback_rate")]
9348 pub kickbacks: f64,
9349
9350 #[serde(default = "default_duplicate_billing_rate")]
9352 pub duplicate_billing: f64,
9353
9354 #[serde(default = "default_med_necessity_rate")]
9356 pub medical_necessity_abuse: f64,
9357}
9358
9359fn default_upcoding_rate() -> f64 {
9360 0.02
9361}
9362
9363fn default_unbundling_rate() -> f64 {
9364 0.015
9365}
9366
9367fn default_phantom_billing_rate() -> f64 {
9368 0.005
9369}
9370
9371fn default_healthcare_kickback_rate() -> f64 {
9372 0.003
9373}
9374
9375fn default_duplicate_billing_rate() -> f64 {
9376 0.008
9377}
9378
9379fn default_med_necessity_rate() -> f64 {
9380 0.01
9381}
9382
9383impl Default for HealthcareAnomalyRates {
9384 fn default() -> Self {
9385 Self {
9386 upcoding: default_upcoding_rate(),
9387 unbundling: default_unbundling_rate(),
9388 phantom_billing: default_phantom_billing_rate(),
9389 kickbacks: default_healthcare_kickback_rate(),
9390 duplicate_billing: default_duplicate_billing_rate(),
9391 medical_necessity_abuse: default_med_necessity_rate(),
9392 }
9393 }
9394}
9395
9396#[derive(Debug, Clone, Serialize, Deserialize)]
9398pub struct TechnologyConfig {
9399 #[serde(default)]
9401 pub enabled: bool,
9402
9403 #[serde(default = "default_revenue_model")]
9405 pub revenue_model: String,
9406
9407 #[serde(default = "default_subscription_pct")]
9409 pub subscription_revenue_pct: f64,
9410
9411 #[serde(default = "default_license_pct")]
9413 pub license_revenue_pct: f64,
9414
9415 #[serde(default = "default_services_pct")]
9417 pub services_revenue_pct: f64,
9418
9419 #[serde(default)]
9421 pub rd_capitalization: RdCapitalizationConfig,
9422
9423 #[serde(default)]
9425 pub anomaly_rates: TechnologyAnomalyRates,
9426}
9427
9428fn default_revenue_model() -> String {
9429 "saas".to_string()
9430}
9431
9432fn default_subscription_pct() -> f64 {
9433 0.60
9434}
9435
9436fn default_license_pct() -> f64 {
9437 0.25
9438}
9439
9440fn default_services_pct() -> f64 {
9441 0.15
9442}
9443
9444impl Default for TechnologyConfig {
9445 fn default() -> Self {
9446 Self {
9447 enabled: false,
9448 revenue_model: default_revenue_model(),
9449 subscription_revenue_pct: default_subscription_pct(),
9450 license_revenue_pct: default_license_pct(),
9451 services_revenue_pct: default_services_pct(),
9452 rd_capitalization: RdCapitalizationConfig::default(),
9453 anomaly_rates: TechnologyAnomalyRates::default(),
9454 }
9455 }
9456}
9457
9458#[derive(Debug, Clone, Serialize, Deserialize)]
9460pub struct RdCapitalizationConfig {
9461 #[serde(default = "default_true")]
9463 pub enabled: bool,
9464
9465 #[serde(default = "default_cap_rate")]
9467 pub capitalization_rate: f64,
9468
9469 #[serde(default = "default_useful_life")]
9471 pub useful_life_years: u32,
9472}
9473
9474fn default_cap_rate() -> f64 {
9475 0.30
9476}
9477
9478fn default_useful_life() -> u32 {
9479 3
9480}
9481
9482impl Default for RdCapitalizationConfig {
9483 fn default() -> Self {
9484 Self {
9485 enabled: true,
9486 capitalization_rate: default_cap_rate(),
9487 useful_life_years: default_useful_life(),
9488 }
9489 }
9490}
9491
9492#[derive(Debug, Clone, Serialize, Deserialize)]
9494pub struct TechnologyAnomalyRates {
9495 #[serde(default = "default_premature_rev_rate")]
9497 pub premature_revenue: f64,
9498
9499 #[serde(default = "default_side_letter_rate")]
9501 pub side_letter_abuse: f64,
9502
9503 #[serde(default = "default_channel_stuffing_rate")]
9505 pub channel_stuffing: f64,
9506
9507 #[serde(default = "default_improper_cap_rate")]
9509 pub improper_capitalization: f64,
9510}
9511
9512fn default_premature_rev_rate() -> f64 {
9513 0.015
9514}
9515
9516fn default_side_letter_rate() -> f64 {
9517 0.008
9518}
9519
9520fn default_channel_stuffing_rate() -> f64 {
9521 0.01
9522}
9523
9524fn default_improper_cap_rate() -> f64 {
9525 0.012
9526}
9527
9528impl Default for TechnologyAnomalyRates {
9529 fn default() -> Self {
9530 Self {
9531 premature_revenue: default_premature_rev_rate(),
9532 side_letter_abuse: default_side_letter_rate(),
9533 channel_stuffing: default_channel_stuffing_rate(),
9534 improper_capitalization: default_improper_cap_rate(),
9535 }
9536 }
9537}
9538
9539#[derive(Debug, Clone, Serialize, Deserialize)]
9541pub struct FinancialServicesConfig {
9542 #[serde(default)]
9544 pub enabled: bool,
9545
9546 #[serde(default = "default_fi_type")]
9548 pub institution_type: String,
9549
9550 #[serde(default = "default_fi_regulatory")]
9552 pub regulatory_framework: String,
9553
9554 #[serde(default)]
9556 pub anomaly_rates: FinancialServicesAnomalyRates,
9557}
9558
9559fn default_fi_type() -> String {
9560 "commercial_bank".to_string()
9561}
9562
9563fn default_fi_regulatory() -> String {
9564 "us_banking".to_string()
9565}
9566
9567impl Default for FinancialServicesConfig {
9568 fn default() -> Self {
9569 Self {
9570 enabled: false,
9571 institution_type: default_fi_type(),
9572 regulatory_framework: default_fi_regulatory(),
9573 anomaly_rates: FinancialServicesAnomalyRates::default(),
9574 }
9575 }
9576}
9577
9578#[derive(Debug, Clone, Serialize, Deserialize)]
9580pub struct FinancialServicesAnomalyRates {
9581 #[serde(default = "default_loan_fraud_rate")]
9583 pub loan_fraud: f64,
9584
9585 #[serde(default = "default_trading_fraud_rate")]
9587 pub trading_fraud: f64,
9588
9589 #[serde(default = "default_insurance_fraud_rate")]
9591 pub insurance_fraud: f64,
9592
9593 #[serde(default = "default_account_manip_rate")]
9595 pub account_manipulation: f64,
9596}
9597
9598fn default_loan_fraud_rate() -> f64 {
9599 0.01
9600}
9601
9602fn default_trading_fraud_rate() -> f64 {
9603 0.008
9604}
9605
9606fn default_insurance_fraud_rate() -> f64 {
9607 0.012
9608}
9609
9610fn default_account_manip_rate() -> f64 {
9611 0.005
9612}
9613
9614impl Default for FinancialServicesAnomalyRates {
9615 fn default() -> Self {
9616 Self {
9617 loan_fraud: default_loan_fraud_rate(),
9618 trading_fraud: default_trading_fraud_rate(),
9619 insurance_fraud: default_insurance_fraud_rate(),
9620 account_manipulation: default_account_manip_rate(),
9621 }
9622 }
9623}
9624
9625#[derive(Debug, Clone, Serialize, Deserialize)]
9627pub struct ProfessionalServicesConfig {
9628 #[serde(default)]
9630 pub enabled: bool,
9631
9632 #[serde(default = "default_firm_type")]
9634 pub firm_type: String,
9635
9636 #[serde(default = "default_billing_model")]
9638 pub billing_model: String,
9639
9640 #[serde(default = "default_hourly_rate")]
9642 pub avg_hourly_rate: f64,
9643
9644 #[serde(default)]
9646 pub trust_accounting: TrustAccountingConfig,
9647
9648 #[serde(default)]
9650 pub anomaly_rates: ProfessionalServicesAnomalyRates,
9651}
9652
9653fn default_firm_type() -> String {
9654 "consulting".to_string()
9655}
9656
9657fn default_billing_model() -> String {
9658 "time_and_materials".to_string()
9659}
9660
9661fn default_hourly_rate() -> f64 {
9662 250.0
9663}
9664
9665impl Default for ProfessionalServicesConfig {
9666 fn default() -> Self {
9667 Self {
9668 enabled: false,
9669 firm_type: default_firm_type(),
9670 billing_model: default_billing_model(),
9671 avg_hourly_rate: default_hourly_rate(),
9672 trust_accounting: TrustAccountingConfig::default(),
9673 anomaly_rates: ProfessionalServicesAnomalyRates::default(),
9674 }
9675 }
9676}
9677
9678#[derive(Debug, Clone, Serialize, Deserialize)]
9680pub struct TrustAccountingConfig {
9681 #[serde(default)]
9683 pub enabled: bool,
9684
9685 #[serde(default = "default_true")]
9687 pub require_three_way_reconciliation: bool,
9688}
9689
9690impl Default for TrustAccountingConfig {
9691 fn default() -> Self {
9692 Self {
9693 enabled: false,
9694 require_three_way_reconciliation: true,
9695 }
9696 }
9697}
9698
9699#[derive(Debug, Clone, Serialize, Deserialize)]
9701pub struct ProfessionalServicesAnomalyRates {
9702 #[serde(default = "default_time_fraud_rate")]
9704 pub time_billing_fraud: f64,
9705
9706 #[serde(default = "default_expense_fraud_rate")]
9708 pub expense_fraud: f64,
9709
9710 #[serde(default = "default_trust_misappropriation_rate")]
9712 pub trust_misappropriation: f64,
9713}
9714
9715fn default_time_fraud_rate() -> f64 {
9716 0.02
9717}
9718
9719fn default_expense_fraud_rate() -> f64 {
9720 0.015
9721}
9722
9723fn default_trust_misappropriation_rate() -> f64 {
9724 0.003
9725}
9726
9727impl Default for ProfessionalServicesAnomalyRates {
9728 fn default() -> Self {
9729 Self {
9730 time_billing_fraud: default_time_fraud_rate(),
9731 expense_fraud: default_expense_fraud_rate(),
9732 trust_misappropriation: default_trust_misappropriation_rate(),
9733 }
9734 }
9735}
9736
9737#[derive(Debug, Clone, Serialize, Deserialize)]
9751pub struct FingerprintPrivacyConfig {
9752 #[serde(default)]
9754 pub level: String,
9755 #[serde(default = "default_epsilon")]
9757 pub epsilon: f64,
9758 #[serde(default = "default_delta")]
9760 pub delta: f64,
9761 #[serde(default = "default_k_anonymity")]
9763 pub k_anonymity: u32,
9764 #[serde(default)]
9766 pub composition_method: String,
9767}
9768
9769fn default_epsilon() -> f64 {
9770 1.0
9771}
9772
9773fn default_delta() -> f64 {
9774 1e-5
9775}
9776
9777fn default_k_anonymity() -> u32 {
9778 5
9779}
9780
9781impl Default for FingerprintPrivacyConfig {
9782 fn default() -> Self {
9783 Self {
9784 level: "standard".to_string(),
9785 epsilon: default_epsilon(),
9786 delta: default_delta(),
9787 k_anonymity: default_k_anonymity(),
9788 composition_method: "naive".to_string(),
9789 }
9790 }
9791}
9792
9793#[derive(Debug, Clone, Serialize, Deserialize)]
9807pub struct QualityGatesSchemaConfig {
9808 #[serde(default)]
9810 pub enabled: bool,
9811 #[serde(default = "default_gate_profile_name")]
9813 pub profile: String,
9814 #[serde(default)]
9816 pub fail_on_violation: bool,
9817 #[serde(default)]
9819 pub custom_gates: Vec<QualityGateEntry>,
9820}
9821
9822fn default_gate_profile_name() -> String {
9823 "default".to_string()
9824}
9825
9826impl Default for QualityGatesSchemaConfig {
9827 fn default() -> Self {
9828 Self {
9829 enabled: false,
9830 profile: default_gate_profile_name(),
9831 fail_on_violation: false,
9832 custom_gates: Vec::new(),
9833 }
9834 }
9835}
9836
9837#[derive(Debug, Clone, Serialize, Deserialize)]
9839pub struct QualityGateEntry {
9840 pub name: String,
9842 pub metric: String,
9846 pub threshold: f64,
9848 #[serde(default)]
9850 pub upper_threshold: Option<f64>,
9851 #[serde(default = "default_gate_comparison")]
9853 pub comparison: String,
9854}
9855
9856fn default_gate_comparison() -> String {
9857 "gte".to_string()
9858}
9859
9860#[derive(Debug, Clone, Default, Serialize, Deserialize)]
9870pub struct ComplianceSchemaConfig {
9871 #[serde(default)]
9873 pub content_marking: ContentMarkingSchemaConfig,
9874 #[serde(default)]
9876 pub article10_report: bool,
9877 #[serde(default)]
9879 pub certificates: CertificateSchemaConfig,
9880}
9881
9882#[derive(Debug, Clone, Default, Serialize, Deserialize)]
9884pub struct CertificateSchemaConfig {
9885 #[serde(default)]
9887 pub enabled: bool,
9888 #[serde(default)]
9890 pub signing_key_env: Option<String>,
9891 #[serde(default)]
9893 pub include_quality_metrics: bool,
9894}
9895
9896#[derive(Debug, Clone, Serialize, Deserialize)]
9898pub struct ContentMarkingSchemaConfig {
9899 #[serde(default = "default_true")]
9901 pub enabled: bool,
9902 #[serde(default = "default_marking_format")]
9904 pub format: String,
9905}
9906
9907fn default_marking_format() -> String {
9908 "embedded".to_string()
9909}
9910
9911impl Default for ContentMarkingSchemaConfig {
9912 fn default() -> Self {
9913 Self {
9914 enabled: true,
9915 format: default_marking_format(),
9916 }
9917 }
9918}
9919
9920#[derive(Debug, Clone, Default, Serialize, Deserialize)]
9922pub struct WebhookSchemaConfig {
9923 #[serde(default)]
9925 pub enabled: bool,
9926 #[serde(default)]
9928 pub endpoints: Vec<WebhookEndpointConfig>,
9929}
9930
9931#[derive(Debug, Clone, Serialize, Deserialize)]
9933pub struct WebhookEndpointConfig {
9934 pub url: String,
9936 #[serde(default)]
9938 pub events: Vec<String>,
9939 #[serde(default)]
9941 pub secret: Option<String>,
9942 #[serde(default = "default_webhook_retries")]
9944 pub max_retries: u32,
9945 #[serde(default = "default_webhook_timeout")]
9947 pub timeout_secs: u64,
9948}
9949
9950fn default_webhook_retries() -> u32 {
9951 3
9952}
9953fn default_webhook_timeout() -> u64 {
9954 10
9955}
9956
9957#[derive(Debug, Clone, Default, Serialize, Deserialize)]
9963pub struct SourceToPayConfig {
9964 #[serde(default)]
9966 pub enabled: bool,
9967 #[serde(default)]
9969 pub spend_analysis: SpendAnalysisConfig,
9970 #[serde(default)]
9972 pub sourcing: SourcingConfig,
9973 #[serde(default)]
9975 pub qualification: QualificationConfig,
9976 #[serde(default)]
9978 pub rfx: RfxConfig,
9979 #[serde(default)]
9981 pub contracts: ContractConfig,
9982 #[serde(default)]
9984 pub catalog: CatalogConfig,
9985 #[serde(default)]
9987 pub scorecards: ScorecardConfig,
9988 #[serde(default)]
9990 pub p2p_integration: P2PIntegrationConfig,
9991}
9992
9993#[derive(Debug, Clone, Serialize, Deserialize)]
9995pub struct SpendAnalysisConfig {
9996 #[serde(default = "default_hhi_threshold")]
9998 pub hhi_threshold: f64,
9999 #[serde(default = "default_contract_coverage_target")]
10001 pub contract_coverage_target: f64,
10002}
10003
10004impl Default for SpendAnalysisConfig {
10005 fn default() -> Self {
10006 Self {
10007 hhi_threshold: default_hhi_threshold(),
10008 contract_coverage_target: default_contract_coverage_target(),
10009 }
10010 }
10011}
10012
10013fn default_hhi_threshold() -> f64 {
10014 2500.0
10015}
10016fn default_contract_coverage_target() -> f64 {
10017 0.80
10018}
10019
10020#[derive(Debug, Clone, Serialize, Deserialize)]
10022pub struct SourcingConfig {
10023 #[serde(default = "default_sourcing_projects_per_year")]
10025 pub projects_per_year: u32,
10026 #[serde(default = "default_renewal_horizon_months")]
10028 pub renewal_horizon_months: u32,
10029 #[serde(default = "default_project_duration_months")]
10031 pub project_duration_months: u32,
10032}
10033
10034impl Default for SourcingConfig {
10035 fn default() -> Self {
10036 Self {
10037 projects_per_year: default_sourcing_projects_per_year(),
10038 renewal_horizon_months: default_renewal_horizon_months(),
10039 project_duration_months: default_project_duration_months(),
10040 }
10041 }
10042}
10043
10044fn default_sourcing_projects_per_year() -> u32 {
10045 10
10046}
10047fn default_renewal_horizon_months() -> u32 {
10048 3
10049}
10050fn default_project_duration_months() -> u32 {
10051 4
10052}
10053
10054#[derive(Debug, Clone, Serialize, Deserialize)]
10056pub struct QualificationConfig {
10057 #[serde(default = "default_qualification_pass_rate")]
10059 pub pass_rate: f64,
10060 #[serde(default = "default_qualification_validity_days")]
10062 pub validity_days: u32,
10063 #[serde(default = "default_financial_weight")]
10065 pub financial_weight: f64,
10066 #[serde(default = "default_quality_weight")]
10068 pub quality_weight: f64,
10069 #[serde(default = "default_delivery_weight")]
10071 pub delivery_weight: f64,
10072 #[serde(default = "default_compliance_weight")]
10074 pub compliance_weight: f64,
10075}
10076
10077impl Default for QualificationConfig {
10078 fn default() -> Self {
10079 Self {
10080 pass_rate: default_qualification_pass_rate(),
10081 validity_days: default_qualification_validity_days(),
10082 financial_weight: default_financial_weight(),
10083 quality_weight: default_quality_weight(),
10084 delivery_weight: default_delivery_weight(),
10085 compliance_weight: default_compliance_weight(),
10086 }
10087 }
10088}
10089
10090fn default_qualification_pass_rate() -> f64 {
10091 0.75
10092}
10093fn default_qualification_validity_days() -> u32 {
10094 365
10095}
10096fn default_financial_weight() -> f64 {
10097 0.25
10098}
10099fn default_quality_weight() -> f64 {
10100 0.30
10101}
10102fn default_delivery_weight() -> f64 {
10103 0.25
10104}
10105fn default_compliance_weight() -> f64 {
10106 0.20
10107}
10108
10109#[derive(Debug, Clone, Serialize, Deserialize)]
10111pub struct RfxConfig {
10112 #[serde(default = "default_rfi_threshold")]
10114 pub rfi_threshold: f64,
10115 #[serde(default = "default_min_invited_vendors")]
10117 pub min_invited_vendors: u32,
10118 #[serde(default = "default_max_invited_vendors")]
10120 pub max_invited_vendors: u32,
10121 #[serde(default = "default_response_rate")]
10123 pub response_rate: f64,
10124 #[serde(default = "default_price_weight")]
10126 pub default_price_weight: f64,
10127 #[serde(default = "default_rfx_quality_weight")]
10129 pub default_quality_weight: f64,
10130 #[serde(default = "default_rfx_delivery_weight")]
10132 pub default_delivery_weight: f64,
10133}
10134
10135impl Default for RfxConfig {
10136 fn default() -> Self {
10137 Self {
10138 rfi_threshold: default_rfi_threshold(),
10139 min_invited_vendors: default_min_invited_vendors(),
10140 max_invited_vendors: default_max_invited_vendors(),
10141 response_rate: default_response_rate(),
10142 default_price_weight: default_price_weight(),
10143 default_quality_weight: default_rfx_quality_weight(),
10144 default_delivery_weight: default_rfx_delivery_weight(),
10145 }
10146 }
10147}
10148
10149fn default_rfi_threshold() -> f64 {
10150 100_000.0
10151}
10152fn default_min_invited_vendors() -> u32 {
10153 3
10154}
10155fn default_max_invited_vendors() -> u32 {
10156 8
10157}
10158fn default_response_rate() -> f64 {
10159 0.70
10160}
10161fn default_price_weight() -> f64 {
10162 0.40
10163}
10164fn default_rfx_quality_weight() -> f64 {
10165 0.35
10166}
10167fn default_rfx_delivery_weight() -> f64 {
10168 0.25
10169}
10170
10171#[derive(Debug, Clone, Serialize, Deserialize)]
10173pub struct ContractConfig {
10174 #[serde(default = "default_min_contract_months")]
10176 pub min_duration_months: u32,
10177 #[serde(default = "default_max_contract_months")]
10179 pub max_duration_months: u32,
10180 #[serde(default = "default_auto_renewal_rate")]
10182 pub auto_renewal_rate: f64,
10183 #[serde(default = "default_amendment_rate")]
10185 pub amendment_rate: f64,
10186 #[serde(default)]
10188 pub type_distribution: ContractTypeDistribution,
10189}
10190
10191impl Default for ContractConfig {
10192 fn default() -> Self {
10193 Self {
10194 min_duration_months: default_min_contract_months(),
10195 max_duration_months: default_max_contract_months(),
10196 auto_renewal_rate: default_auto_renewal_rate(),
10197 amendment_rate: default_amendment_rate(),
10198 type_distribution: ContractTypeDistribution::default(),
10199 }
10200 }
10201}
10202
10203fn default_min_contract_months() -> u32 {
10204 12
10205}
10206fn default_max_contract_months() -> u32 {
10207 36
10208}
10209fn default_auto_renewal_rate() -> f64 {
10210 0.40
10211}
10212fn default_amendment_rate() -> f64 {
10213 0.20
10214}
10215
10216#[derive(Debug, Clone, Serialize, Deserialize)]
10218pub struct ContractTypeDistribution {
10219 #[serde(default = "default_fixed_price_pct")]
10221 pub fixed_price: f64,
10222 #[serde(default = "default_blanket_pct")]
10224 pub blanket: f64,
10225 #[serde(default = "default_time_materials_pct")]
10227 pub time_and_materials: f64,
10228 #[serde(default = "default_service_agreement_pct")]
10230 pub service_agreement: f64,
10231}
10232
10233impl Default for ContractTypeDistribution {
10234 fn default() -> Self {
10235 Self {
10236 fixed_price: default_fixed_price_pct(),
10237 blanket: default_blanket_pct(),
10238 time_and_materials: default_time_materials_pct(),
10239 service_agreement: default_service_agreement_pct(),
10240 }
10241 }
10242}
10243
10244fn default_fixed_price_pct() -> f64 {
10245 0.40
10246}
10247fn default_blanket_pct() -> f64 {
10248 0.30
10249}
10250fn default_time_materials_pct() -> f64 {
10251 0.15
10252}
10253fn default_service_agreement_pct() -> f64 {
10254 0.15
10255}
10256
10257#[derive(Debug, Clone, Serialize, Deserialize)]
10259pub struct CatalogConfig {
10260 #[serde(default = "default_preferred_vendor_flag_rate")]
10262 pub preferred_vendor_flag_rate: f64,
10263 #[serde(default = "default_multi_source_rate")]
10265 pub multi_source_rate: f64,
10266}
10267
10268impl Default for CatalogConfig {
10269 fn default() -> Self {
10270 Self {
10271 preferred_vendor_flag_rate: default_preferred_vendor_flag_rate(),
10272 multi_source_rate: default_multi_source_rate(),
10273 }
10274 }
10275}
10276
10277fn default_preferred_vendor_flag_rate() -> f64 {
10278 0.70
10279}
10280fn default_multi_source_rate() -> f64 {
10281 0.25
10282}
10283
10284#[derive(Debug, Clone, Serialize, Deserialize)]
10286pub struct ScorecardConfig {
10287 #[serde(default = "default_scorecard_frequency")]
10289 pub frequency: String,
10290 #[serde(default = "default_otd_weight")]
10292 pub on_time_delivery_weight: f64,
10293 #[serde(default = "default_quality_score_weight")]
10295 pub quality_weight: f64,
10296 #[serde(default = "default_price_score_weight")]
10298 pub price_weight: f64,
10299 #[serde(default = "default_responsiveness_weight")]
10301 pub responsiveness_weight: f64,
10302 #[serde(default = "default_grade_a_threshold")]
10304 pub grade_a_threshold: f64,
10305 #[serde(default = "default_grade_b_threshold")]
10307 pub grade_b_threshold: f64,
10308 #[serde(default = "default_grade_c_threshold")]
10310 pub grade_c_threshold: f64,
10311}
10312
10313impl Default for ScorecardConfig {
10314 fn default() -> Self {
10315 Self {
10316 frequency: default_scorecard_frequency(),
10317 on_time_delivery_weight: default_otd_weight(),
10318 quality_weight: default_quality_score_weight(),
10319 price_weight: default_price_score_weight(),
10320 responsiveness_weight: default_responsiveness_weight(),
10321 grade_a_threshold: default_grade_a_threshold(),
10322 grade_b_threshold: default_grade_b_threshold(),
10323 grade_c_threshold: default_grade_c_threshold(),
10324 }
10325 }
10326}
10327
10328fn default_scorecard_frequency() -> String {
10329 "quarterly".to_string()
10330}
10331fn default_otd_weight() -> f64 {
10332 0.30
10333}
10334fn default_quality_score_weight() -> f64 {
10335 0.30
10336}
10337fn default_price_score_weight() -> f64 {
10338 0.25
10339}
10340fn default_responsiveness_weight() -> f64 {
10341 0.15
10342}
10343fn default_grade_a_threshold() -> f64 {
10344 90.0
10345}
10346fn default_grade_b_threshold() -> f64 {
10347 75.0
10348}
10349fn default_grade_c_threshold() -> f64 {
10350 60.0
10351}
10352
10353#[derive(Debug, Clone, Serialize, Deserialize)]
10355pub struct P2PIntegrationConfig {
10356 #[serde(default = "default_off_contract_rate")]
10358 pub off_contract_rate: f64,
10359 #[serde(default = "default_price_tolerance")]
10361 pub price_tolerance: f64,
10362 #[serde(default)]
10364 pub catalog_enforcement: bool,
10365}
10366
10367impl Default for P2PIntegrationConfig {
10368 fn default() -> Self {
10369 Self {
10370 off_contract_rate: default_off_contract_rate(),
10371 price_tolerance: default_price_tolerance(),
10372 catalog_enforcement: false,
10373 }
10374 }
10375}
10376
10377fn default_off_contract_rate() -> f64 {
10378 0.15
10379}
10380fn default_price_tolerance() -> f64 {
10381 0.02
10382}
10383
10384#[derive(Debug, Clone, Serialize, Deserialize)]
10388pub struct FinancialReportingConfig {
10389 #[serde(default)]
10391 pub enabled: bool,
10392 #[serde(default = "default_true")]
10394 pub generate_balance_sheet: bool,
10395 #[serde(default = "default_true")]
10397 pub generate_income_statement: bool,
10398 #[serde(default = "default_true")]
10400 pub generate_cash_flow: bool,
10401 #[serde(default = "default_true")]
10403 pub generate_changes_in_equity: bool,
10404 #[serde(default = "default_comparative_periods")]
10406 pub comparative_periods: u32,
10407 #[serde(default)]
10409 pub management_kpis: ManagementKpisConfig,
10410 #[serde(default)]
10412 pub budgets: BudgetConfig,
10413}
10414
10415impl Default for FinancialReportingConfig {
10416 fn default() -> Self {
10417 Self {
10418 enabled: false,
10419 generate_balance_sheet: true,
10420 generate_income_statement: true,
10421 generate_cash_flow: true,
10422 generate_changes_in_equity: true,
10423 comparative_periods: default_comparative_periods(),
10424 management_kpis: ManagementKpisConfig::default(),
10425 budgets: BudgetConfig::default(),
10426 }
10427 }
10428}
10429
10430fn default_comparative_periods() -> u32 {
10431 1
10432}
10433
10434#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10436pub struct ManagementKpisConfig {
10437 #[serde(default)]
10439 pub enabled: bool,
10440 #[serde(default = "default_kpi_frequency")]
10442 pub frequency: String,
10443}
10444
10445fn default_kpi_frequency() -> String {
10446 "monthly".to_string()
10447}
10448
10449#[derive(Debug, Clone, Serialize, Deserialize)]
10451pub struct BudgetConfig {
10452 #[serde(default)]
10454 pub enabled: bool,
10455 #[serde(default = "default_revenue_growth_rate")]
10457 pub revenue_growth_rate: f64,
10458 #[serde(default = "default_expense_inflation_rate")]
10460 pub expense_inflation_rate: f64,
10461 #[serde(default = "default_variance_noise")]
10463 pub variance_noise: f64,
10464}
10465
10466impl Default for BudgetConfig {
10467 fn default() -> Self {
10468 Self {
10469 enabled: false,
10470 revenue_growth_rate: default_revenue_growth_rate(),
10471 expense_inflation_rate: default_expense_inflation_rate(),
10472 variance_noise: default_variance_noise(),
10473 }
10474 }
10475}
10476
10477fn default_revenue_growth_rate() -> f64 {
10478 0.05
10479}
10480fn default_expense_inflation_rate() -> f64 {
10481 0.03
10482}
10483fn default_variance_noise() -> f64 {
10484 0.10
10485}
10486
10487#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10491pub struct HrConfig {
10492 #[serde(default)]
10494 pub enabled: bool,
10495 #[serde(default)]
10497 pub payroll: PayrollConfig,
10498 #[serde(default)]
10500 pub time_attendance: TimeAttendanceConfig,
10501 #[serde(default)]
10503 pub expenses: ExpenseConfig,
10504}
10505
10506#[derive(Debug, Clone, Serialize, Deserialize)]
10508pub struct PayrollConfig {
10509 #[serde(default = "default_true")]
10511 pub enabled: bool,
10512 #[serde(default = "default_pay_frequency")]
10514 pub pay_frequency: String,
10515 #[serde(default)]
10517 pub salary_ranges: PayrollSalaryRanges,
10518 #[serde(default)]
10520 pub tax_rates: PayrollTaxRates,
10521 #[serde(default = "default_benefits_enrollment_rate")]
10523 pub benefits_enrollment_rate: f64,
10524 #[serde(default = "default_retirement_participation_rate")]
10526 pub retirement_participation_rate: f64,
10527}
10528
10529impl Default for PayrollConfig {
10530 fn default() -> Self {
10531 Self {
10532 enabled: true,
10533 pay_frequency: default_pay_frequency(),
10534 salary_ranges: PayrollSalaryRanges::default(),
10535 tax_rates: PayrollTaxRates::default(),
10536 benefits_enrollment_rate: default_benefits_enrollment_rate(),
10537 retirement_participation_rate: default_retirement_participation_rate(),
10538 }
10539 }
10540}
10541
10542fn default_pay_frequency() -> String {
10543 "monthly".to_string()
10544}
10545fn default_benefits_enrollment_rate() -> f64 {
10546 0.60
10547}
10548fn default_retirement_participation_rate() -> f64 {
10549 0.45
10550}
10551
10552#[derive(Debug, Clone, Serialize, Deserialize)]
10554pub struct PayrollSalaryRanges {
10555 #[serde(default = "default_staff_min")]
10557 pub staff_min: f64,
10558 #[serde(default = "default_staff_max")]
10559 pub staff_max: f64,
10560 #[serde(default = "default_manager_min")]
10562 pub manager_min: f64,
10563 #[serde(default = "default_manager_max")]
10564 pub manager_max: f64,
10565 #[serde(default = "default_director_min")]
10567 pub director_min: f64,
10568 #[serde(default = "default_director_max")]
10569 pub director_max: f64,
10570 #[serde(default = "default_executive_min")]
10572 pub executive_min: f64,
10573 #[serde(default = "default_executive_max")]
10574 pub executive_max: f64,
10575}
10576
10577impl Default for PayrollSalaryRanges {
10578 fn default() -> Self {
10579 Self {
10580 staff_min: default_staff_min(),
10581 staff_max: default_staff_max(),
10582 manager_min: default_manager_min(),
10583 manager_max: default_manager_max(),
10584 director_min: default_director_min(),
10585 director_max: default_director_max(),
10586 executive_min: default_executive_min(),
10587 executive_max: default_executive_max(),
10588 }
10589 }
10590}
10591
10592fn default_staff_min() -> f64 {
10593 50_000.0
10594}
10595fn default_staff_max() -> f64 {
10596 70_000.0
10597}
10598fn default_manager_min() -> f64 {
10599 80_000.0
10600}
10601fn default_manager_max() -> f64 {
10602 120_000.0
10603}
10604fn default_director_min() -> f64 {
10605 120_000.0
10606}
10607fn default_director_max() -> f64 {
10608 180_000.0
10609}
10610fn default_executive_min() -> f64 {
10611 180_000.0
10612}
10613fn default_executive_max() -> f64 {
10614 350_000.0
10615}
10616
10617#[derive(Debug, Clone, Serialize, Deserialize)]
10619pub struct PayrollTaxRates {
10620 #[serde(default = "default_federal_rate")]
10622 pub federal_effective: f64,
10623 #[serde(default = "default_state_rate")]
10625 pub state_effective: f64,
10626 #[serde(default = "default_fica_rate")]
10628 pub fica: f64,
10629}
10630
10631impl Default for PayrollTaxRates {
10632 fn default() -> Self {
10633 Self {
10634 federal_effective: default_federal_rate(),
10635 state_effective: default_state_rate(),
10636 fica: default_fica_rate(),
10637 }
10638 }
10639}
10640
10641fn default_federal_rate() -> f64 {
10642 0.22
10643}
10644fn default_state_rate() -> f64 {
10645 0.05
10646}
10647fn default_fica_rate() -> f64 {
10648 0.0765
10649}
10650
10651#[derive(Debug, Clone, Serialize, Deserialize)]
10653pub struct TimeAttendanceConfig {
10654 #[serde(default = "default_true")]
10656 pub enabled: bool,
10657 #[serde(default = "default_overtime_rate")]
10659 pub overtime_rate: f64,
10660}
10661
10662impl Default for TimeAttendanceConfig {
10663 fn default() -> Self {
10664 Self {
10665 enabled: true,
10666 overtime_rate: default_overtime_rate(),
10667 }
10668 }
10669}
10670
10671fn default_overtime_rate() -> f64 {
10672 0.10
10673}
10674
10675#[derive(Debug, Clone, Serialize, Deserialize)]
10677pub struct ExpenseConfig {
10678 #[serde(default = "default_true")]
10680 pub enabled: bool,
10681 #[serde(default = "default_expense_submission_rate")]
10683 pub submission_rate: f64,
10684 #[serde(default = "default_policy_violation_rate")]
10686 pub policy_violation_rate: f64,
10687}
10688
10689impl Default for ExpenseConfig {
10690 fn default() -> Self {
10691 Self {
10692 enabled: true,
10693 submission_rate: default_expense_submission_rate(),
10694 policy_violation_rate: default_policy_violation_rate(),
10695 }
10696 }
10697}
10698
10699fn default_expense_submission_rate() -> f64 {
10700 0.30
10701}
10702fn default_policy_violation_rate() -> f64 {
10703 0.08
10704}
10705
10706#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10710pub struct ManufacturingProcessConfig {
10711 #[serde(default)]
10713 pub enabled: bool,
10714 #[serde(default)]
10716 pub production_orders: ProductionOrderConfig,
10717 #[serde(default)]
10719 pub costing: ManufacturingCostingConfig,
10720 #[serde(default)]
10722 pub routing: RoutingConfig,
10723}
10724
10725#[derive(Debug, Clone, Serialize, Deserialize)]
10727pub struct ProductionOrderConfig {
10728 #[serde(default = "default_prod_orders_per_month")]
10730 pub orders_per_month: u32,
10731 #[serde(default = "default_prod_avg_batch_size")]
10733 pub avg_batch_size: u32,
10734 #[serde(default = "default_prod_yield_rate")]
10736 pub yield_rate: f64,
10737 #[serde(default = "default_prod_make_to_order_rate")]
10739 pub make_to_order_rate: f64,
10740 #[serde(default = "default_prod_rework_rate")]
10742 pub rework_rate: f64,
10743}
10744
10745impl Default for ProductionOrderConfig {
10746 fn default() -> Self {
10747 Self {
10748 orders_per_month: default_prod_orders_per_month(),
10749 avg_batch_size: default_prod_avg_batch_size(),
10750 yield_rate: default_prod_yield_rate(),
10751 make_to_order_rate: default_prod_make_to_order_rate(),
10752 rework_rate: default_prod_rework_rate(),
10753 }
10754 }
10755}
10756
10757fn default_prod_orders_per_month() -> u32 {
10758 50
10759}
10760fn default_prod_avg_batch_size() -> u32 {
10761 100
10762}
10763fn default_prod_yield_rate() -> f64 {
10764 0.97
10765}
10766fn default_prod_make_to_order_rate() -> f64 {
10767 0.20
10768}
10769fn default_prod_rework_rate() -> f64 {
10770 0.03
10771}
10772
10773#[derive(Debug, Clone, Serialize, Deserialize)]
10775pub struct ManufacturingCostingConfig {
10776 #[serde(default = "default_labor_rate")]
10778 pub labor_rate_per_hour: f64,
10779 #[serde(default = "default_overhead_rate")]
10781 pub overhead_rate: f64,
10782 #[serde(default = "default_cost_update_frequency")]
10784 pub standard_cost_update_frequency: String,
10785}
10786
10787impl Default for ManufacturingCostingConfig {
10788 fn default() -> Self {
10789 Self {
10790 labor_rate_per_hour: default_labor_rate(),
10791 overhead_rate: default_overhead_rate(),
10792 standard_cost_update_frequency: default_cost_update_frequency(),
10793 }
10794 }
10795}
10796
10797fn default_labor_rate() -> f64 {
10798 35.0
10799}
10800fn default_overhead_rate() -> f64 {
10801 1.50
10802}
10803fn default_cost_update_frequency() -> String {
10804 "quarterly".to_string()
10805}
10806
10807#[derive(Debug, Clone, Serialize, Deserialize)]
10809pub struct RoutingConfig {
10810 #[serde(default = "default_avg_operations")]
10812 pub avg_operations: u32,
10813 #[serde(default = "default_setup_time")]
10815 pub setup_time_hours: f64,
10816 #[serde(default = "default_run_time_variation")]
10818 pub run_time_variation: f64,
10819}
10820
10821impl Default for RoutingConfig {
10822 fn default() -> Self {
10823 Self {
10824 avg_operations: default_avg_operations(),
10825 setup_time_hours: default_setup_time(),
10826 run_time_variation: default_run_time_variation(),
10827 }
10828 }
10829}
10830
10831fn default_avg_operations() -> u32 {
10832 4
10833}
10834fn default_setup_time() -> f64 {
10835 1.5
10836}
10837fn default_run_time_variation() -> f64 {
10838 0.15
10839}
10840
10841#[derive(Debug, Clone, Serialize, Deserialize)]
10845pub struct SalesQuoteConfig {
10846 #[serde(default)]
10848 pub enabled: bool,
10849 #[serde(default = "default_quotes_per_month")]
10851 pub quotes_per_month: u32,
10852 #[serde(default = "default_quote_win_rate")]
10854 pub win_rate: f64,
10855 #[serde(default = "default_quote_validity_days")]
10857 pub validity_days: u32,
10858}
10859
10860impl Default for SalesQuoteConfig {
10861 fn default() -> Self {
10862 Self {
10863 enabled: false,
10864 quotes_per_month: default_quotes_per_month(),
10865 win_rate: default_quote_win_rate(),
10866 validity_days: default_quote_validity_days(),
10867 }
10868 }
10869}
10870
10871fn default_quotes_per_month() -> u32 {
10872 30
10873}
10874fn default_quote_win_rate() -> f64 {
10875 0.35
10876}
10877fn default_quote_validity_days() -> u32 {
10878 30
10879}
10880
10881#[derive(Debug, Clone, Serialize, Deserialize)]
10890pub struct TaxConfig {
10891 #[serde(default)]
10893 pub enabled: bool,
10894 #[serde(default)]
10896 pub jurisdictions: TaxJurisdictionConfig,
10897 #[serde(default)]
10899 pub vat_gst: VatGstConfig,
10900 #[serde(default)]
10902 pub sales_tax: SalesTaxConfig,
10903 #[serde(default)]
10905 pub withholding: WithholdingTaxSchemaConfig,
10906 #[serde(default)]
10908 pub provisions: TaxProvisionSchemaConfig,
10909 #[serde(default)]
10911 pub payroll_tax: PayrollTaxSchemaConfig,
10912 #[serde(default = "default_tax_anomaly_rate")]
10914 pub anomaly_rate: f64,
10915}
10916
10917fn default_tax_anomaly_rate() -> f64 {
10918 0.03
10919}
10920
10921impl Default for TaxConfig {
10922 fn default() -> Self {
10923 Self {
10924 enabled: false,
10925 jurisdictions: TaxJurisdictionConfig::default(),
10926 vat_gst: VatGstConfig::default(),
10927 sales_tax: SalesTaxConfig::default(),
10928 withholding: WithholdingTaxSchemaConfig::default(),
10929 provisions: TaxProvisionSchemaConfig::default(),
10930 payroll_tax: PayrollTaxSchemaConfig::default(),
10931 anomaly_rate: default_tax_anomaly_rate(),
10932 }
10933 }
10934}
10935
10936#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10941pub struct TaxJurisdictionConfig {
10942 #[serde(default)]
10944 pub countries: Vec<String>,
10945 #[serde(default)]
10947 pub include_subnational: bool,
10948}
10949
10950#[derive(Debug, Clone, Serialize, Deserialize)]
10955pub struct VatGstConfig {
10956 #[serde(default)]
10958 pub enabled: bool,
10959 #[serde(default)]
10961 pub standard_rates: std::collections::HashMap<String, f64>,
10962 #[serde(default)]
10964 pub reduced_rates: std::collections::HashMap<String, f64>,
10965 #[serde(default)]
10967 pub exempt_categories: Vec<String>,
10968 #[serde(default = "default_true")]
10970 pub reverse_charge: bool,
10971}
10972
10973impl Default for VatGstConfig {
10974 fn default() -> Self {
10975 Self {
10976 enabled: false,
10977 standard_rates: std::collections::HashMap::new(),
10978 reduced_rates: std::collections::HashMap::new(),
10979 exempt_categories: Vec::new(),
10980 reverse_charge: true,
10981 }
10982 }
10983}
10984
10985#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10989pub struct SalesTaxConfig {
10990 #[serde(default)]
10992 pub enabled: bool,
10993 #[serde(default)]
10995 pub nexus_states: Vec<String>,
10996}
10997
10998#[derive(Debug, Clone, Serialize, Deserialize)]
11003pub struct WithholdingTaxSchemaConfig {
11004 #[serde(default)]
11006 pub enabled: bool,
11007 #[serde(default = "default_true")]
11009 pub treaty_network: bool,
11010 #[serde(default = "default_withholding_rate")]
11012 pub default_rate: f64,
11013 #[serde(default = "default_treaty_reduced_rate")]
11015 pub treaty_reduced_rate: f64,
11016}
11017
11018fn default_withholding_rate() -> f64 {
11019 0.30
11020}
11021
11022fn default_treaty_reduced_rate() -> f64 {
11023 0.15
11024}
11025
11026impl Default for WithholdingTaxSchemaConfig {
11027 fn default() -> Self {
11028 Self {
11029 enabled: false,
11030 treaty_network: true,
11031 default_rate: default_withholding_rate(),
11032 treaty_reduced_rate: default_treaty_reduced_rate(),
11033 }
11034 }
11035}
11036
11037#[derive(Debug, Clone, Serialize, Deserialize)]
11042pub struct TaxProvisionSchemaConfig {
11043 #[serde(default = "default_true")]
11046 pub enabled: bool,
11047 #[serde(default = "default_statutory_rate")]
11049 pub statutory_rate: f64,
11050 #[serde(default = "default_true")]
11052 pub uncertain_positions: bool,
11053}
11054
11055fn default_statutory_rate() -> f64 {
11056 0.21
11057}
11058
11059impl Default for TaxProvisionSchemaConfig {
11060 fn default() -> Self {
11061 Self {
11062 enabled: true,
11063 statutory_rate: default_statutory_rate(),
11064 uncertain_positions: true,
11065 }
11066 }
11067}
11068
11069#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11074pub struct PayrollTaxSchemaConfig {
11075 #[serde(default)]
11077 pub enabled: bool,
11078}
11079
11080#[derive(Debug, Clone, Serialize, Deserialize)]
11090pub struct TreasuryConfig {
11091 #[serde(default)]
11093 pub enabled: bool,
11094 #[serde(default)]
11096 pub cash_positioning: CashPositioningConfig,
11097 #[serde(default)]
11099 pub cash_forecasting: CashForecastingConfig,
11100 #[serde(default)]
11102 pub cash_pooling: CashPoolingConfig,
11103 #[serde(default)]
11105 pub hedging: HedgingSchemaConfig,
11106 #[serde(default)]
11108 pub debt: DebtSchemaConfig,
11109 #[serde(default)]
11111 pub netting: NettingSchemaConfig,
11112 #[serde(default)]
11114 pub bank_guarantees: BankGuaranteeSchemaConfig,
11115 #[serde(default = "default_treasury_anomaly_rate")]
11117 pub anomaly_rate: f64,
11118}
11119
11120fn default_treasury_anomaly_rate() -> f64 {
11121 0.02
11122}
11123
11124impl Default for TreasuryConfig {
11125 fn default() -> Self {
11126 Self {
11127 enabled: false,
11128 cash_positioning: CashPositioningConfig::default(),
11129 cash_forecasting: CashForecastingConfig::default(),
11130 cash_pooling: CashPoolingConfig::default(),
11131 hedging: HedgingSchemaConfig::default(),
11132 debt: DebtSchemaConfig::default(),
11133 netting: NettingSchemaConfig::default(),
11134 bank_guarantees: BankGuaranteeSchemaConfig::default(),
11135 anomaly_rate: default_treasury_anomaly_rate(),
11136 }
11137 }
11138}
11139
11140#[derive(Debug, Clone, Serialize, Deserialize)]
11144pub struct CashPositioningConfig {
11145 #[serde(default = "default_true")]
11147 pub enabled: bool,
11148 #[serde(default = "default_cash_frequency")]
11150 pub frequency: String,
11151 #[serde(default = "default_minimum_balance_policy")]
11153 pub minimum_balance_policy: f64,
11154}
11155
11156fn default_cash_frequency() -> String {
11157 "daily".to_string()
11158}
11159
11160fn default_minimum_balance_policy() -> f64 {
11161 100_000.0
11162}
11163
11164impl Default for CashPositioningConfig {
11165 fn default() -> Self {
11166 Self {
11167 enabled: true,
11168 frequency: default_cash_frequency(),
11169 minimum_balance_policy: default_minimum_balance_policy(),
11170 }
11171 }
11172}
11173
11174#[derive(Debug, Clone, Serialize, Deserialize)]
11178pub struct CashForecastingConfig {
11179 #[serde(default = "default_true")]
11181 pub enabled: bool,
11182 #[serde(default = "default_horizon_days")]
11184 pub horizon_days: u32,
11185 #[serde(default = "default_ar_probability_curve")]
11187 pub ar_collection_probability_curve: String,
11188 #[serde(default = "default_confidence_interval")]
11190 pub confidence_interval: f64,
11191}
11192
11193fn default_horizon_days() -> u32 {
11194 90
11195}
11196
11197fn default_ar_probability_curve() -> String {
11198 "aging".to_string()
11199}
11200
11201fn default_confidence_interval() -> f64 {
11202 0.90
11203}
11204
11205impl Default for CashForecastingConfig {
11206 fn default() -> Self {
11207 Self {
11208 enabled: true,
11209 horizon_days: default_horizon_days(),
11210 ar_collection_probability_curve: default_ar_probability_curve(),
11211 confidence_interval: default_confidence_interval(),
11212 }
11213 }
11214}
11215
11216#[derive(Debug, Clone, Serialize, Deserialize)]
11220pub struct CashPoolingConfig {
11221 #[serde(default)]
11223 pub enabled: bool,
11224 #[serde(default = "default_pool_type")]
11226 pub pool_type: String,
11227 #[serde(default = "default_sweep_time")]
11229 pub sweep_time: String,
11230}
11231
11232fn default_pool_type() -> String {
11233 "zero_balancing".to_string()
11234}
11235
11236fn default_sweep_time() -> String {
11237 "16:00".to_string()
11238}
11239
11240impl Default for CashPoolingConfig {
11241 fn default() -> Self {
11242 Self {
11243 enabled: false,
11244 pool_type: default_pool_type(),
11245 sweep_time: default_sweep_time(),
11246 }
11247 }
11248}
11249
11250#[derive(Debug, Clone, Serialize, Deserialize)]
11255pub struct HedgingSchemaConfig {
11256 #[serde(default)]
11258 pub enabled: bool,
11259 #[serde(default = "default_hedge_ratio")]
11261 pub hedge_ratio: f64,
11262 #[serde(default = "default_hedge_instruments")]
11264 pub instruments: Vec<String>,
11265 #[serde(default = "default_true")]
11267 pub hedge_accounting: bool,
11268 #[serde(default = "default_effectiveness_method")]
11270 pub effectiveness_method: String,
11271}
11272
11273fn default_hedge_ratio() -> f64 {
11274 0.75
11275}
11276
11277fn default_hedge_instruments() -> Vec<String> {
11278 vec!["fx_forward".to_string(), "interest_rate_swap".to_string()]
11279}
11280
11281fn default_effectiveness_method() -> String {
11282 "regression".to_string()
11283}
11284
11285impl Default for HedgingSchemaConfig {
11286 fn default() -> Self {
11287 Self {
11288 enabled: false,
11289 hedge_ratio: default_hedge_ratio(),
11290 instruments: default_hedge_instruments(),
11291 hedge_accounting: true,
11292 effectiveness_method: default_effectiveness_method(),
11293 }
11294 }
11295}
11296
11297#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11302pub struct DebtSchemaConfig {
11303 #[serde(default)]
11305 pub enabled: bool,
11306 #[serde(default)]
11308 pub instruments: Vec<DebtInstrumentDef>,
11309 #[serde(default)]
11311 pub covenants: Vec<CovenantDef>,
11312}
11313
11314#[derive(Debug, Clone, Serialize, Deserialize)]
11316pub struct DebtInstrumentDef {
11317 #[serde(rename = "type")]
11319 pub instrument_type: String,
11320 #[serde(default)]
11322 pub principal: Option<f64>,
11323 #[serde(default)]
11325 pub rate: Option<f64>,
11326 #[serde(default)]
11328 pub maturity_months: Option<u32>,
11329 #[serde(default)]
11331 pub facility: Option<f64>,
11332}
11333
11334#[derive(Debug, Clone, Serialize, Deserialize)]
11336pub struct CovenantDef {
11337 #[serde(rename = "type")]
11340 pub covenant_type: String,
11341 pub threshold: f64,
11343}
11344
11345#[derive(Debug, Clone, Serialize, Deserialize)]
11349pub struct NettingSchemaConfig {
11350 #[serde(default)]
11352 pub enabled: bool,
11353 #[serde(default = "default_netting_cycle")]
11355 pub cycle: String,
11356}
11357
11358fn default_netting_cycle() -> String {
11359 "monthly".to_string()
11360}
11361
11362impl Default for NettingSchemaConfig {
11363 fn default() -> Self {
11364 Self {
11365 enabled: false,
11366 cycle: default_netting_cycle(),
11367 }
11368 }
11369}
11370
11371#[derive(Debug, Clone, Serialize, Deserialize)]
11375pub struct BankGuaranteeSchemaConfig {
11376 #[serde(default)]
11378 pub enabled: bool,
11379 #[serde(default = "default_guarantee_count")]
11381 pub count: u32,
11382}
11383
11384fn default_guarantee_count() -> u32 {
11385 5
11386}
11387
11388impl Default for BankGuaranteeSchemaConfig {
11389 fn default() -> Self {
11390 Self {
11391 enabled: false,
11392 count: default_guarantee_count(),
11393 }
11394 }
11395}
11396
11397#[derive(Debug, Clone, Serialize, Deserialize)]
11406pub struct ProjectAccountingConfig {
11407 #[serde(default)]
11409 pub enabled: bool,
11410 #[serde(default = "default_project_count")]
11412 pub project_count: u32,
11413 #[serde(default)]
11415 pub project_types: ProjectTypeDistribution,
11416 #[serde(default)]
11418 pub wbs: WbsSchemaConfig,
11419 #[serde(default)]
11421 pub cost_allocation: CostAllocationConfig,
11422 #[serde(default)]
11424 pub revenue_recognition: ProjectRevenueRecognitionConfig,
11425 #[serde(default)]
11427 pub milestones: MilestoneSchemaConfig,
11428 #[serde(default)]
11430 pub change_orders: ChangeOrderSchemaConfig,
11431 #[serde(default)]
11433 pub retainage: RetainageSchemaConfig,
11434 #[serde(default)]
11436 pub earned_value: EarnedValueSchemaConfig,
11437 #[serde(default = "default_project_anomaly_rate")]
11439 pub anomaly_rate: f64,
11440}
11441
11442fn default_project_count() -> u32 {
11443 10
11444}
11445
11446fn default_project_anomaly_rate() -> f64 {
11447 0.03
11448}
11449
11450impl Default for ProjectAccountingConfig {
11451 fn default() -> Self {
11452 Self {
11453 enabled: false,
11454 project_count: default_project_count(),
11455 project_types: ProjectTypeDistribution::default(),
11456 wbs: WbsSchemaConfig::default(),
11457 cost_allocation: CostAllocationConfig::default(),
11458 revenue_recognition: ProjectRevenueRecognitionConfig::default(),
11459 milestones: MilestoneSchemaConfig::default(),
11460 change_orders: ChangeOrderSchemaConfig::default(),
11461 retainage: RetainageSchemaConfig::default(),
11462 earned_value: EarnedValueSchemaConfig::default(),
11463 anomaly_rate: default_project_anomaly_rate(),
11464 }
11465 }
11466}
11467
11468#[derive(Debug, Clone, Serialize, Deserialize)]
11470pub struct ProjectTypeDistribution {
11471 #[serde(default = "default_capital_weight")]
11473 pub capital: f64,
11474 #[serde(default = "default_internal_weight")]
11476 pub internal: f64,
11477 #[serde(default = "default_customer_weight")]
11479 pub customer: f64,
11480 #[serde(default = "default_rnd_weight")]
11482 pub r_and_d: f64,
11483 #[serde(default = "default_maintenance_weight")]
11485 pub maintenance: f64,
11486 #[serde(default = "default_technology_weight")]
11488 pub technology: f64,
11489}
11490
11491fn default_capital_weight() -> f64 {
11492 0.25
11493}
11494fn default_internal_weight() -> f64 {
11495 0.20
11496}
11497fn default_customer_weight() -> f64 {
11498 0.30
11499}
11500fn default_rnd_weight() -> f64 {
11501 0.10
11502}
11503fn default_maintenance_weight() -> f64 {
11504 0.10
11505}
11506fn default_technology_weight() -> f64 {
11507 0.05
11508}
11509
11510impl Default for ProjectTypeDistribution {
11511 fn default() -> Self {
11512 Self {
11513 capital: default_capital_weight(),
11514 internal: default_internal_weight(),
11515 customer: default_customer_weight(),
11516 r_and_d: default_rnd_weight(),
11517 maintenance: default_maintenance_weight(),
11518 technology: default_technology_weight(),
11519 }
11520 }
11521}
11522
11523#[derive(Debug, Clone, Serialize, Deserialize)]
11525pub struct WbsSchemaConfig {
11526 #[serde(default = "default_wbs_max_depth")]
11528 pub max_depth: u32,
11529 #[serde(default = "default_wbs_min_elements")]
11531 pub min_elements_per_level: u32,
11532 #[serde(default = "default_wbs_max_elements")]
11534 pub max_elements_per_level: u32,
11535}
11536
11537fn default_wbs_max_depth() -> u32 {
11538 3
11539}
11540fn default_wbs_min_elements() -> u32 {
11541 2
11542}
11543fn default_wbs_max_elements() -> u32 {
11544 6
11545}
11546
11547impl Default for WbsSchemaConfig {
11548 fn default() -> Self {
11549 Self {
11550 max_depth: default_wbs_max_depth(),
11551 min_elements_per_level: default_wbs_min_elements(),
11552 max_elements_per_level: default_wbs_max_elements(),
11553 }
11554 }
11555}
11556
11557#[derive(Debug, Clone, Serialize, Deserialize)]
11559pub struct CostAllocationConfig {
11560 #[serde(default = "default_time_entry_rate")]
11562 pub time_entry_project_rate: f64,
11563 #[serde(default = "default_expense_rate")]
11565 pub expense_project_rate: f64,
11566 #[serde(default = "default_po_rate")]
11568 pub purchase_order_project_rate: f64,
11569 #[serde(default = "default_vi_rate")]
11571 pub vendor_invoice_project_rate: f64,
11572}
11573
11574fn default_time_entry_rate() -> f64 {
11575 0.60
11576}
11577fn default_expense_rate() -> f64 {
11578 0.30
11579}
11580fn default_po_rate() -> f64 {
11581 0.40
11582}
11583fn default_vi_rate() -> f64 {
11584 0.35
11585}
11586
11587impl Default for CostAllocationConfig {
11588 fn default() -> Self {
11589 Self {
11590 time_entry_project_rate: default_time_entry_rate(),
11591 expense_project_rate: default_expense_rate(),
11592 purchase_order_project_rate: default_po_rate(),
11593 vendor_invoice_project_rate: default_vi_rate(),
11594 }
11595 }
11596}
11597
11598#[derive(Debug, Clone, Serialize, Deserialize)]
11600pub struct ProjectRevenueRecognitionConfig {
11601 #[serde(default = "default_true")]
11603 pub enabled: bool,
11604 #[serde(default = "default_revenue_method")]
11606 pub method: String,
11607 #[serde(default = "default_completion_measure")]
11609 pub completion_measure: String,
11610 #[serde(default = "default_avg_contract_value")]
11612 pub avg_contract_value: f64,
11613}
11614
11615fn default_revenue_method() -> String {
11616 "percentage_of_completion".to_string()
11617}
11618fn default_completion_measure() -> String {
11619 "cost_to_cost".to_string()
11620}
11621fn default_avg_contract_value() -> f64 {
11622 500_000.0
11623}
11624
11625impl Default for ProjectRevenueRecognitionConfig {
11626 fn default() -> Self {
11627 Self {
11628 enabled: true,
11629 method: default_revenue_method(),
11630 completion_measure: default_completion_measure(),
11631 avg_contract_value: default_avg_contract_value(),
11632 }
11633 }
11634}
11635
11636#[derive(Debug, Clone, Serialize, Deserialize)]
11638pub struct MilestoneSchemaConfig {
11639 #[serde(default = "default_true")]
11641 pub enabled: bool,
11642 #[serde(default = "default_milestones_per_project")]
11644 pub avg_per_project: u32,
11645 #[serde(default = "default_payment_milestone_rate")]
11647 pub payment_milestone_rate: f64,
11648}
11649
11650fn default_milestones_per_project() -> u32 {
11651 4
11652}
11653fn default_payment_milestone_rate() -> f64 {
11654 0.50
11655}
11656
11657impl Default for MilestoneSchemaConfig {
11658 fn default() -> Self {
11659 Self {
11660 enabled: true,
11661 avg_per_project: default_milestones_per_project(),
11662 payment_milestone_rate: default_payment_milestone_rate(),
11663 }
11664 }
11665}
11666
11667#[derive(Debug, Clone, Serialize, Deserialize)]
11669pub struct ChangeOrderSchemaConfig {
11670 #[serde(default = "default_true")]
11672 pub enabled: bool,
11673 #[serde(default = "default_change_order_probability")]
11675 pub probability: f64,
11676 #[serde(default = "default_max_change_orders")]
11678 pub max_per_project: u32,
11679 #[serde(default = "default_change_order_approval_rate")]
11681 pub approval_rate: f64,
11682}
11683
11684fn default_change_order_probability() -> f64 {
11685 0.40
11686}
11687fn default_max_change_orders() -> u32 {
11688 3
11689}
11690fn default_change_order_approval_rate() -> f64 {
11691 0.75
11692}
11693
11694impl Default for ChangeOrderSchemaConfig {
11695 fn default() -> Self {
11696 Self {
11697 enabled: true,
11698 probability: default_change_order_probability(),
11699 max_per_project: default_max_change_orders(),
11700 approval_rate: default_change_order_approval_rate(),
11701 }
11702 }
11703}
11704
11705#[derive(Debug, Clone, Serialize, Deserialize)]
11707pub struct RetainageSchemaConfig {
11708 #[serde(default)]
11710 pub enabled: bool,
11711 #[serde(default = "default_retainage_pct")]
11713 pub default_percentage: f64,
11714}
11715
11716fn default_retainage_pct() -> f64 {
11717 0.10
11718}
11719
11720impl Default for RetainageSchemaConfig {
11721 fn default() -> Self {
11722 Self {
11723 enabled: false,
11724 default_percentage: default_retainage_pct(),
11725 }
11726 }
11727}
11728
11729#[derive(Debug, Clone, Serialize, Deserialize)]
11731pub struct EarnedValueSchemaConfig {
11732 #[serde(default = "default_true")]
11734 pub enabled: bool,
11735 #[serde(default = "default_evm_frequency")]
11737 pub frequency: String,
11738}
11739
11740fn default_evm_frequency() -> String {
11741 "monthly".to_string()
11742}
11743
11744impl Default for EarnedValueSchemaConfig {
11745 fn default() -> Self {
11746 Self {
11747 enabled: true,
11748 frequency: default_evm_frequency(),
11749 }
11750 }
11751}
11752
11753#[derive(Debug, Clone, Serialize, Deserialize)]
11759pub struct EsgConfig {
11760 #[serde(default)]
11762 pub enabled: bool,
11763 #[serde(default)]
11765 pub environmental: EnvironmentalConfig,
11766 #[serde(default)]
11768 pub social: SocialConfig,
11769 #[serde(default)]
11771 pub governance: GovernanceSchemaConfig,
11772 #[serde(default)]
11774 pub supply_chain_esg: SupplyChainEsgConfig,
11775 #[serde(default)]
11777 pub reporting: EsgReportingConfig,
11778 #[serde(default)]
11780 pub climate_scenarios: ClimateScenarioConfig,
11781 #[serde(default = "default_esg_anomaly_rate")]
11783 pub anomaly_rate: f64,
11784}
11785
11786fn default_esg_anomaly_rate() -> f64 {
11787 0.02
11788}
11789
11790impl Default for EsgConfig {
11791 fn default() -> Self {
11792 Self {
11793 enabled: false,
11794 environmental: EnvironmentalConfig::default(),
11795 social: SocialConfig::default(),
11796 governance: GovernanceSchemaConfig::default(),
11797 supply_chain_esg: SupplyChainEsgConfig::default(),
11798 reporting: EsgReportingConfig::default(),
11799 climate_scenarios: ClimateScenarioConfig::default(),
11800 anomaly_rate: default_esg_anomaly_rate(),
11801 }
11802 }
11803}
11804
11805#[derive(Debug, Clone, Serialize, Deserialize, Default)]
11810pub struct CountryPacksSchemaConfig {
11811 #[serde(default)]
11813 pub external_dir: Option<PathBuf>,
11814 #[serde(default)]
11818 pub overrides: std::collections::HashMap<String, serde_json::Value>,
11819}
11820
11821#[derive(Debug, Clone, Serialize, Deserialize)]
11823pub struct EnvironmentalConfig {
11824 #[serde(default = "default_true")]
11826 pub enabled: bool,
11827 #[serde(default)]
11829 pub scope1: EmissionScopeConfig,
11830 #[serde(default)]
11832 pub scope2: EmissionScopeConfig,
11833 #[serde(default)]
11835 pub scope3: Scope3Config,
11836 #[serde(default)]
11838 pub energy: EnergySchemaConfig,
11839 #[serde(default)]
11841 pub water: WaterSchemaConfig,
11842 #[serde(default)]
11844 pub waste: WasteSchemaConfig,
11845}
11846
11847impl Default for EnvironmentalConfig {
11848 fn default() -> Self {
11849 Self {
11850 enabled: true,
11851 scope1: EmissionScopeConfig::default(),
11852 scope2: EmissionScopeConfig::default(),
11853 scope3: Scope3Config::default(),
11854 energy: EnergySchemaConfig::default(),
11855 water: WaterSchemaConfig::default(),
11856 waste: WasteSchemaConfig::default(),
11857 }
11858 }
11859}
11860
11861#[derive(Debug, Clone, Serialize, Deserialize)]
11863pub struct EmissionScopeConfig {
11864 #[serde(default = "default_true")]
11866 pub enabled: bool,
11867 #[serde(default = "default_emission_region")]
11869 pub factor_region: String,
11870}
11871
11872fn default_emission_region() -> String {
11873 "US".to_string()
11874}
11875
11876impl Default for EmissionScopeConfig {
11877 fn default() -> Self {
11878 Self {
11879 enabled: true,
11880 factor_region: default_emission_region(),
11881 }
11882 }
11883}
11884
11885#[derive(Debug, Clone, Serialize, Deserialize)]
11887pub struct Scope3Config {
11888 #[serde(default = "default_true")]
11890 pub enabled: bool,
11891 #[serde(default = "default_scope3_categories")]
11893 pub categories: Vec<String>,
11894 #[serde(default = "default_spend_intensity")]
11896 pub default_spend_intensity_kg_per_usd: f64,
11897}
11898
11899fn default_scope3_categories() -> Vec<String> {
11900 vec![
11901 "purchased_goods".to_string(),
11902 "business_travel".to_string(),
11903 "employee_commuting".to_string(),
11904 ]
11905}
11906
11907fn default_spend_intensity() -> f64 {
11908 0.5
11909}
11910
11911impl Default for Scope3Config {
11912 fn default() -> Self {
11913 Self {
11914 enabled: true,
11915 categories: default_scope3_categories(),
11916 default_spend_intensity_kg_per_usd: default_spend_intensity(),
11917 }
11918 }
11919}
11920
11921#[derive(Debug, Clone, Serialize, Deserialize)]
11923pub struct EnergySchemaConfig {
11924 #[serde(default = "default_true")]
11926 pub enabled: bool,
11927 #[serde(default = "default_facility_count")]
11929 pub facility_count: u32,
11930 #[serde(default = "default_renewable_target")]
11932 pub renewable_target: f64,
11933}
11934
11935fn default_facility_count() -> u32 {
11936 5
11937}
11938
11939fn default_renewable_target() -> f64 {
11940 0.30
11941}
11942
11943impl Default for EnergySchemaConfig {
11944 fn default() -> Self {
11945 Self {
11946 enabled: true,
11947 facility_count: default_facility_count(),
11948 renewable_target: default_renewable_target(),
11949 }
11950 }
11951}
11952
11953#[derive(Debug, Clone, Serialize, Deserialize)]
11955pub struct WaterSchemaConfig {
11956 #[serde(default = "default_true")]
11958 pub enabled: bool,
11959 #[serde(default = "default_water_facility_count")]
11961 pub facility_count: u32,
11962}
11963
11964fn default_water_facility_count() -> u32 {
11965 3
11966}
11967
11968impl Default for WaterSchemaConfig {
11969 fn default() -> Self {
11970 Self {
11971 enabled: true,
11972 facility_count: default_water_facility_count(),
11973 }
11974 }
11975}
11976
11977#[derive(Debug, Clone, Serialize, Deserialize)]
11979pub struct WasteSchemaConfig {
11980 #[serde(default = "default_true")]
11982 pub enabled: bool,
11983 #[serde(default = "default_diversion_target")]
11985 pub diversion_target: f64,
11986}
11987
11988fn default_diversion_target() -> f64 {
11989 0.50
11990}
11991
11992impl Default for WasteSchemaConfig {
11993 fn default() -> Self {
11994 Self {
11995 enabled: true,
11996 diversion_target: default_diversion_target(),
11997 }
11998 }
11999}
12000
12001#[derive(Debug, Clone, Serialize, Deserialize)]
12003pub struct SocialConfig {
12004 #[serde(default = "default_true")]
12006 pub enabled: bool,
12007 #[serde(default)]
12009 pub diversity: DiversitySchemaConfig,
12010 #[serde(default)]
12012 pub pay_equity: PayEquitySchemaConfig,
12013 #[serde(default)]
12015 pub safety: SafetySchemaConfig,
12016}
12017
12018impl Default for SocialConfig {
12019 fn default() -> Self {
12020 Self {
12021 enabled: true,
12022 diversity: DiversitySchemaConfig::default(),
12023 pay_equity: PayEquitySchemaConfig::default(),
12024 safety: SafetySchemaConfig::default(),
12025 }
12026 }
12027}
12028
12029#[derive(Debug, Clone, Serialize, Deserialize)]
12031pub struct DiversitySchemaConfig {
12032 #[serde(default = "default_true")]
12034 pub enabled: bool,
12035 #[serde(default = "default_diversity_dimensions")]
12037 pub dimensions: Vec<String>,
12038}
12039
12040fn default_diversity_dimensions() -> Vec<String> {
12041 vec![
12042 "gender".to_string(),
12043 "ethnicity".to_string(),
12044 "age_group".to_string(),
12045 ]
12046}
12047
12048impl Default for DiversitySchemaConfig {
12049 fn default() -> Self {
12050 Self {
12051 enabled: true,
12052 dimensions: default_diversity_dimensions(),
12053 }
12054 }
12055}
12056
12057#[derive(Debug, Clone, Serialize, Deserialize)]
12059pub struct PayEquitySchemaConfig {
12060 #[serde(default = "default_true")]
12062 pub enabled: bool,
12063 #[serde(default = "default_pay_gap_threshold")]
12065 pub gap_threshold: f64,
12066}
12067
12068fn default_pay_gap_threshold() -> f64 {
12069 0.05
12070}
12071
12072impl Default for PayEquitySchemaConfig {
12073 fn default() -> Self {
12074 Self {
12075 enabled: true,
12076 gap_threshold: default_pay_gap_threshold(),
12077 }
12078 }
12079}
12080
12081#[derive(Debug, Clone, Serialize, Deserialize)]
12083pub struct SafetySchemaConfig {
12084 #[serde(default = "default_true")]
12086 pub enabled: bool,
12087 #[serde(default = "default_trir_target")]
12089 pub target_trir: f64,
12090 #[serde(default = "default_incident_count")]
12092 pub incident_count: u32,
12093}
12094
12095fn default_trir_target() -> f64 {
12096 2.5
12097}
12098
12099fn default_incident_count() -> u32 {
12100 20
12101}
12102
12103impl Default for SafetySchemaConfig {
12104 fn default() -> Self {
12105 Self {
12106 enabled: true,
12107 target_trir: default_trir_target(),
12108 incident_count: default_incident_count(),
12109 }
12110 }
12111}
12112
12113#[derive(Debug, Clone, Serialize, Deserialize)]
12115pub struct GovernanceSchemaConfig {
12116 #[serde(default = "default_true")]
12118 pub enabled: bool,
12119 #[serde(default = "default_board_size")]
12121 pub board_size: u32,
12122 #[serde(default = "default_independence_target")]
12124 pub independence_target: f64,
12125}
12126
12127fn default_board_size() -> u32 {
12128 11
12129}
12130
12131fn default_independence_target() -> f64 {
12132 0.67
12133}
12134
12135impl Default for GovernanceSchemaConfig {
12136 fn default() -> Self {
12137 Self {
12138 enabled: true,
12139 board_size: default_board_size(),
12140 independence_target: default_independence_target(),
12141 }
12142 }
12143}
12144
12145#[derive(Debug, Clone, Serialize, Deserialize)]
12147pub struct SupplyChainEsgConfig {
12148 #[serde(default = "default_true")]
12150 pub enabled: bool,
12151 #[serde(default = "default_assessment_coverage")]
12153 pub assessment_coverage: f64,
12154 #[serde(default = "default_high_risk_countries")]
12156 pub high_risk_countries: Vec<String>,
12157}
12158
12159fn default_assessment_coverage() -> f64 {
12160 0.80
12161}
12162
12163fn default_high_risk_countries() -> Vec<String> {
12164 vec!["CN".to_string(), "BD".to_string(), "MM".to_string()]
12165}
12166
12167impl Default for SupplyChainEsgConfig {
12168 fn default() -> Self {
12169 Self {
12170 enabled: true,
12171 assessment_coverage: default_assessment_coverage(),
12172 high_risk_countries: default_high_risk_countries(),
12173 }
12174 }
12175}
12176
12177#[derive(Debug, Clone, Serialize, Deserialize)]
12179pub struct EsgReportingConfig {
12180 #[serde(default = "default_true")]
12182 pub enabled: bool,
12183 #[serde(default = "default_esg_frameworks")]
12185 pub frameworks: Vec<String>,
12186 #[serde(default = "default_true")]
12188 pub materiality_assessment: bool,
12189 #[serde(default = "default_materiality_threshold")]
12191 pub impact_threshold: f64,
12192 #[serde(default = "default_materiality_threshold")]
12194 pub financial_threshold: f64,
12195}
12196
12197fn default_esg_frameworks() -> Vec<String> {
12198 vec!["GRI".to_string(), "ESRS".to_string()]
12199}
12200
12201fn default_materiality_threshold() -> f64 {
12202 0.6
12203}
12204
12205impl Default for EsgReportingConfig {
12206 fn default() -> Self {
12207 Self {
12208 enabled: true,
12209 frameworks: default_esg_frameworks(),
12210 materiality_assessment: true,
12211 impact_threshold: default_materiality_threshold(),
12212 financial_threshold: default_materiality_threshold(),
12213 }
12214 }
12215}
12216
12217#[derive(Debug, Clone, Serialize, Deserialize)]
12219pub struct ClimateScenarioConfig {
12220 #[serde(default)]
12222 pub enabled: bool,
12223 #[serde(default = "default_climate_scenarios")]
12225 pub scenarios: Vec<String>,
12226 #[serde(default = "default_time_horizons")]
12228 pub time_horizons: Vec<u32>,
12229}
12230
12231fn default_climate_scenarios() -> Vec<String> {
12232 vec![
12233 "net_zero_2050".to_string(),
12234 "stated_policies".to_string(),
12235 "current_trajectory".to_string(),
12236 ]
12237}
12238
12239fn default_time_horizons() -> Vec<u32> {
12240 vec![5, 10, 30]
12241}
12242
12243impl Default for ClimateScenarioConfig {
12244 fn default() -> Self {
12245 Self {
12246 enabled: false,
12247 scenarios: default_climate_scenarios(),
12248 time_horizons: default_time_horizons(),
12249 }
12250 }
12251}
12252
12253#[cfg(test)]
12254#[allow(clippy::unwrap_used)]
12255mod tests {
12256 use super::*;
12257 use crate::presets::demo_preset;
12258
12259 #[test]
12264 fn test_config_yaml_roundtrip() {
12265 let config = demo_preset();
12266 let yaml = serde_yaml::to_string(&config).expect("Failed to serialize to YAML");
12267 let deserialized: GeneratorConfig =
12268 serde_yaml::from_str(&yaml).expect("Failed to deserialize from YAML");
12269
12270 assert_eq!(
12271 config.global.period_months,
12272 deserialized.global.period_months
12273 );
12274 assert_eq!(config.global.industry, deserialized.global.industry);
12275 assert_eq!(config.companies.len(), deserialized.companies.len());
12276 assert_eq!(config.companies[0].code, deserialized.companies[0].code);
12277 }
12278
12279 #[test]
12280 fn test_config_json_roundtrip() {
12281 let mut config = demo_preset();
12283 config.master_data.employees.approval_limits.executive = 1e12;
12285
12286 let json = serde_json::to_string(&config).expect("Failed to serialize to JSON");
12287 let deserialized: GeneratorConfig =
12288 serde_json::from_str(&json).expect("Failed to deserialize from JSON");
12289
12290 assert_eq!(
12291 config.global.period_months,
12292 deserialized.global.period_months
12293 );
12294 assert_eq!(config.global.industry, deserialized.global.industry);
12295 assert_eq!(config.companies.len(), deserialized.companies.len());
12296 }
12297
12298 #[test]
12299 fn test_transaction_volume_serialization() {
12300 let volumes = vec![
12302 (TransactionVolume::TenK, "ten_k"),
12303 (TransactionVolume::HundredK, "hundred_k"),
12304 (TransactionVolume::OneM, "one_m"),
12305 (TransactionVolume::TenM, "ten_m"),
12306 (TransactionVolume::HundredM, "hundred_m"),
12307 ];
12308
12309 for (volume, expected_key) in volumes {
12310 let json = serde_json::to_string(&volume).expect("Failed to serialize");
12311 assert!(
12312 json.contains(expected_key),
12313 "Expected {} in JSON: {}",
12314 expected_key,
12315 json
12316 );
12317 }
12318 }
12319
12320 #[test]
12321 fn test_transaction_volume_custom_serialization() {
12322 let volume = TransactionVolume::Custom(12345);
12323 let json = serde_json::to_string(&volume).expect("Failed to serialize");
12324 let deserialized: TransactionVolume =
12325 serde_json::from_str(&json).expect("Failed to deserialize");
12326 assert_eq!(deserialized.count(), 12345);
12327 }
12328
12329 #[test]
12330 fn test_output_mode_serialization() {
12331 let modes = vec![
12332 OutputMode::Streaming,
12333 OutputMode::FlatFile,
12334 OutputMode::Both,
12335 ];
12336
12337 for mode in modes {
12338 let json = serde_json::to_string(&mode).expect("Failed to serialize");
12339 let deserialized: OutputMode =
12340 serde_json::from_str(&json).expect("Failed to deserialize");
12341 assert!(format!("{:?}", mode) == format!("{:?}", deserialized));
12342 }
12343 }
12344
12345 #[test]
12346 fn test_file_format_serialization() {
12347 let formats = vec![
12348 FileFormat::Csv,
12349 FileFormat::Parquet,
12350 FileFormat::Json,
12351 FileFormat::JsonLines,
12352 ];
12353
12354 for format in formats {
12355 let json = serde_json::to_string(&format).expect("Failed to serialize");
12356 let deserialized: FileFormat =
12357 serde_json::from_str(&json).expect("Failed to deserialize");
12358 assert!(format!("{:?}", format) == format!("{:?}", deserialized));
12359 }
12360 }
12361
12362 #[test]
12363 fn test_compression_algorithm_serialization() {
12364 let algos = vec![
12365 CompressionAlgorithm::Gzip,
12366 CompressionAlgorithm::Zstd,
12367 CompressionAlgorithm::Lz4,
12368 CompressionAlgorithm::Snappy,
12369 ];
12370
12371 for algo in algos {
12372 let json = serde_json::to_string(&algo).expect("Failed to serialize");
12373 let deserialized: CompressionAlgorithm =
12374 serde_json::from_str(&json).expect("Failed to deserialize");
12375 assert!(format!("{:?}", algo) == format!("{:?}", deserialized));
12376 }
12377 }
12378
12379 #[test]
12380 fn test_transfer_pricing_method_serialization() {
12381 let methods = vec![
12382 TransferPricingMethod::CostPlus,
12383 TransferPricingMethod::ComparableUncontrolled,
12384 TransferPricingMethod::ResalePrice,
12385 TransferPricingMethod::TransactionalNetMargin,
12386 TransferPricingMethod::ProfitSplit,
12387 ];
12388
12389 for method in methods {
12390 let json = serde_json::to_string(&method).expect("Failed to serialize");
12391 let deserialized: TransferPricingMethod =
12392 serde_json::from_str(&json).expect("Failed to deserialize");
12393 assert!(format!("{:?}", method) == format!("{:?}", deserialized));
12394 }
12395 }
12396
12397 #[test]
12398 fn test_benford_exemption_serialization() {
12399 let exemptions = vec![
12400 BenfordExemption::Recurring,
12401 BenfordExemption::Payroll,
12402 BenfordExemption::FixedFees,
12403 BenfordExemption::RoundAmounts,
12404 ];
12405
12406 for exemption in exemptions {
12407 let json = serde_json::to_string(&exemption).expect("Failed to serialize");
12408 let deserialized: BenfordExemption =
12409 serde_json::from_str(&json).expect("Failed to deserialize");
12410 assert!(format!("{:?}", exemption) == format!("{:?}", deserialized));
12411 }
12412 }
12413
12414 #[test]
12419 fn test_global_config_defaults() {
12420 let yaml = r#"
12421 industry: manufacturing
12422 start_date: "2024-01-01"
12423 period_months: 6
12424 "#;
12425 let config: GlobalConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12426 assert_eq!(config.group_currency, "USD");
12427 assert!(config.parallel);
12428 assert_eq!(config.worker_threads, 0);
12429 assert_eq!(config.memory_limit_mb, 0);
12430 }
12431
12432 #[test]
12433 fn test_fraud_config_defaults() {
12434 let config = FraudConfig::default();
12435 assert!(!config.enabled);
12436 assert_eq!(config.fraud_rate, 0.005);
12437 assert!(!config.clustering_enabled);
12438 }
12439
12440 #[test]
12441 fn test_internal_controls_config_defaults() {
12442 let config = InternalControlsConfig::default();
12443 assert!(!config.enabled);
12444 assert_eq!(config.exception_rate, 0.02);
12445 assert_eq!(config.sod_violation_rate, 0.01);
12446 assert!(config.export_control_master_data);
12447 assert_eq!(config.sox_materiality_threshold, 10000.0);
12448 assert!(config.coso_enabled);
12450 assert!(!config.include_entity_level_controls);
12451 assert_eq!(config.target_maturity_level, "mixed");
12452 }
12453
12454 #[test]
12455 fn test_output_config_defaults() {
12456 let config = OutputConfig::default();
12457 assert!(matches!(config.mode, OutputMode::FlatFile));
12458 assert_eq!(config.formats, vec![FileFormat::Parquet]);
12459 assert!(config.compression.enabled);
12460 assert!(matches!(
12461 config.compression.algorithm,
12462 CompressionAlgorithm::Zstd
12463 ));
12464 assert!(config.include_acdoca);
12465 assert!(!config.include_bseg);
12466 assert!(config.partition_by_period);
12467 assert!(!config.partition_by_company);
12468 }
12469
12470 #[test]
12471 fn test_approval_config_defaults() {
12472 let config = ApprovalConfig::default();
12473 assert!(!config.enabled);
12474 assert_eq!(config.auto_approve_threshold, 1000.0);
12475 assert_eq!(config.rejection_rate, 0.02);
12476 assert_eq!(config.revision_rate, 0.05);
12477 assert_eq!(config.average_approval_delay_hours, 4.0);
12478 assert_eq!(config.thresholds.len(), 4);
12479 }
12480
12481 #[test]
12482 fn test_p2p_flow_config_defaults() {
12483 let config = P2PFlowConfig::default();
12484 assert!(config.enabled);
12485 assert_eq!(config.three_way_match_rate, 0.95);
12486 assert_eq!(config.partial_delivery_rate, 0.15);
12487 assert_eq!(config.average_po_to_gr_days, 14);
12488 }
12489
12490 #[test]
12491 fn test_o2c_flow_config_defaults() {
12492 let config = O2CFlowConfig::default();
12493 assert!(config.enabled);
12494 assert_eq!(config.credit_check_failure_rate, 0.02);
12495 assert_eq!(config.return_rate, 0.03);
12496 assert_eq!(config.bad_debt_rate, 0.01);
12497 }
12498
12499 #[test]
12500 fn test_balance_config_defaults() {
12501 let config = BalanceConfig::default();
12502 assert!(!config.generate_opening_balances);
12503 assert!(config.generate_trial_balances);
12504 assert_eq!(config.target_gross_margin, 0.35);
12505 assert!(config.validate_balance_equation);
12506 assert!(config.reconcile_subledgers);
12507 }
12508
12509 #[test]
12514 fn test_partial_config_with_defaults() {
12515 let yaml = r#"
12517 global:
12518 industry: manufacturing
12519 start_date: "2024-01-01"
12520 period_months: 3
12521 companies:
12522 - code: "TEST"
12523 name: "Test Company"
12524 currency: "USD"
12525 country: "US"
12526 annual_transaction_volume: ten_k
12527 chart_of_accounts:
12528 complexity: small
12529 output:
12530 output_directory: "./output"
12531 "#;
12532
12533 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12534 assert_eq!(config.global.period_months, 3);
12535 assert_eq!(config.companies.len(), 1);
12536 assert!(!config.fraud.enabled); assert!(!config.internal_controls.enabled); }
12539
12540 #[test]
12541 fn test_config_with_fraud_enabled() {
12542 let yaml = r#"
12543 global:
12544 industry: retail
12545 start_date: "2024-01-01"
12546 period_months: 12
12547 companies:
12548 - code: "RETAIL"
12549 name: "Retail Co"
12550 currency: "USD"
12551 country: "US"
12552 annual_transaction_volume: hundred_k
12553 chart_of_accounts:
12554 complexity: medium
12555 output:
12556 output_directory: "./output"
12557 fraud:
12558 enabled: true
12559 fraud_rate: 0.05
12560 clustering_enabled: true
12561 "#;
12562
12563 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12564 assert!(config.fraud.enabled);
12565 assert_eq!(config.fraud.fraud_rate, 0.05);
12566 assert!(config.fraud.clustering_enabled);
12567 }
12568
12569 #[test]
12570 fn test_config_with_multiple_companies() {
12571 let yaml = r#"
12572 global:
12573 industry: manufacturing
12574 start_date: "2024-01-01"
12575 period_months: 6
12576 companies:
12577 - code: "HQ"
12578 name: "Headquarters"
12579 currency: "USD"
12580 country: "US"
12581 annual_transaction_volume: hundred_k
12582 volume_weight: 1.0
12583 - code: "EU"
12584 name: "European Subsidiary"
12585 currency: "EUR"
12586 country: "DE"
12587 annual_transaction_volume: hundred_k
12588 volume_weight: 0.5
12589 - code: "APAC"
12590 name: "Asia Pacific"
12591 currency: "JPY"
12592 country: "JP"
12593 annual_transaction_volume: ten_k
12594 volume_weight: 0.3
12595 chart_of_accounts:
12596 complexity: large
12597 output:
12598 output_directory: "./output"
12599 "#;
12600
12601 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12602 assert_eq!(config.companies.len(), 3);
12603 assert_eq!(config.companies[0].code, "HQ");
12604 assert_eq!(config.companies[1].currency, "EUR");
12605 assert_eq!(config.companies[2].volume_weight, 0.3);
12606 }
12607
12608 #[test]
12609 fn test_intercompany_config() {
12610 let yaml = r#"
12611 enabled: true
12612 ic_transaction_rate: 0.20
12613 transfer_pricing_method: cost_plus
12614 markup_percent: 0.08
12615 generate_matched_pairs: true
12616 generate_eliminations: true
12617 "#;
12618
12619 let config: IntercompanyConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12620 assert!(config.enabled);
12621 assert_eq!(config.ic_transaction_rate, 0.20);
12622 assert!(matches!(
12623 config.transfer_pricing_method,
12624 TransferPricingMethod::CostPlus
12625 ));
12626 assert_eq!(config.markup_percent, 0.08);
12627 assert!(config.generate_eliminations);
12628 }
12629
12630 #[test]
12635 fn test_company_config_defaults() {
12636 let yaml = r#"
12637 code: "TEST"
12638 name: "Test Company"
12639 currency: "USD"
12640 country: "US"
12641 annual_transaction_volume: ten_k
12642 "#;
12643
12644 let config: CompanyConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12645 assert_eq!(config.fiscal_year_variant, "K4"); assert_eq!(config.volume_weight, 1.0); }
12648
12649 #[test]
12654 fn test_coa_config_defaults() {
12655 let yaml = r#"
12656 complexity: medium
12657 "#;
12658
12659 let config: ChartOfAccountsConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12660 assert!(config.industry_specific); assert!(config.custom_accounts.is_none());
12662 assert_eq!(config.min_hierarchy_depth, 2); assert_eq!(config.max_hierarchy_depth, 5); }
12665
12666 #[test]
12671 fn test_accounting_standards_config_defaults() {
12672 let config = AccountingStandardsConfig::default();
12673 assert!(!config.enabled);
12674 assert!(config.framework.is_none());
12675 assert!(!config.revenue_recognition.enabled);
12676 assert!(!config.leases.enabled);
12677 assert!(!config.fair_value.enabled);
12678 assert!(!config.impairment.enabled);
12679 assert!(!config.generate_differences);
12680 }
12681
12682 #[test]
12683 fn test_accounting_standards_config_yaml() {
12684 let yaml = r#"
12685 enabled: true
12686 framework: ifrs
12687 revenue_recognition:
12688 enabled: true
12689 generate_contracts: true
12690 avg_obligations_per_contract: 2.5
12691 variable_consideration_rate: 0.20
12692 over_time_recognition_rate: 0.35
12693 contract_count: 150
12694 leases:
12695 enabled: true
12696 lease_count: 75
12697 finance_lease_percent: 0.25
12698 avg_lease_term_months: 48
12699 generate_differences: true
12700 "#;
12701
12702 let config: AccountingStandardsConfig =
12703 serde_yaml::from_str(yaml).expect("Failed to parse");
12704 assert!(config.enabled);
12705 assert!(matches!(
12706 config.framework,
12707 Some(AccountingFrameworkConfig::Ifrs)
12708 ));
12709 assert!(config.revenue_recognition.enabled);
12710 assert_eq!(config.revenue_recognition.contract_count, 150);
12711 assert_eq!(config.revenue_recognition.avg_obligations_per_contract, 2.5);
12712 assert!(config.leases.enabled);
12713 assert_eq!(config.leases.lease_count, 75);
12714 assert_eq!(config.leases.finance_lease_percent, 0.25);
12715 assert!(config.generate_differences);
12716 }
12717
12718 #[test]
12719 fn test_accounting_framework_serialization() {
12720 let frameworks = [
12721 AccountingFrameworkConfig::UsGaap,
12722 AccountingFrameworkConfig::Ifrs,
12723 AccountingFrameworkConfig::DualReporting,
12724 AccountingFrameworkConfig::FrenchGaap,
12725 ];
12726
12727 for framework in frameworks {
12728 let json = serde_json::to_string(&framework).expect("Failed to serialize");
12729 let deserialized: AccountingFrameworkConfig =
12730 serde_json::from_str(&json).expect("Failed to deserialize");
12731 assert!(format!("{:?}", framework) == format!("{:?}", deserialized));
12732 }
12733 }
12734
12735 #[test]
12736 fn test_revenue_recognition_config_defaults() {
12737 let config = RevenueRecognitionConfig::default();
12738 assert!(!config.enabled);
12739 assert!(config.generate_contracts);
12740 assert_eq!(config.avg_obligations_per_contract, 2.0);
12741 assert_eq!(config.variable_consideration_rate, 0.15);
12742 assert_eq!(config.over_time_recognition_rate, 0.30);
12743 assert_eq!(config.contract_count, 100);
12744 }
12745
12746 #[test]
12747 fn test_lease_accounting_config_defaults() {
12748 let config = LeaseAccountingConfig::default();
12749 assert!(!config.enabled);
12750 assert_eq!(config.lease_count, 50);
12751 assert_eq!(config.finance_lease_percent, 0.30);
12752 assert_eq!(config.avg_lease_term_months, 60);
12753 assert!(config.generate_amortization);
12754 assert_eq!(config.real_estate_percent, 0.40);
12755 }
12756
12757 #[test]
12758 fn test_fair_value_config_defaults() {
12759 let config = FairValueConfig::default();
12760 assert!(!config.enabled);
12761 assert_eq!(config.measurement_count, 25);
12762 assert_eq!(config.level1_percent, 0.40);
12763 assert_eq!(config.level2_percent, 0.35);
12764 assert_eq!(config.level3_percent, 0.25);
12765 assert!(!config.include_sensitivity_analysis);
12766 }
12767
12768 #[test]
12769 fn test_impairment_config_defaults() {
12770 let config = ImpairmentConfig::default();
12771 assert!(!config.enabled);
12772 assert_eq!(config.test_count, 15);
12773 assert_eq!(config.impairment_rate, 0.10);
12774 assert!(config.generate_projections);
12775 assert!(!config.include_goodwill);
12776 }
12777
12778 #[test]
12783 fn test_audit_standards_config_defaults() {
12784 let config = AuditStandardsConfig::default();
12785 assert!(!config.enabled);
12786 assert!(!config.isa_compliance.enabled);
12787 assert!(!config.analytical_procedures.enabled);
12788 assert!(!config.confirmations.enabled);
12789 assert!(!config.opinion.enabled);
12790 assert!(!config.generate_audit_trail);
12791 assert!(!config.sox.enabled);
12792 assert!(!config.pcaob.enabled);
12793 }
12794
12795 #[test]
12796 fn test_audit_standards_config_yaml() {
12797 let yaml = r#"
12798 enabled: true
12799 isa_compliance:
12800 enabled: true
12801 compliance_level: comprehensive
12802 generate_isa_mappings: true
12803 include_pcaob: true
12804 framework: dual
12805 analytical_procedures:
12806 enabled: true
12807 procedures_per_account: 5
12808 variance_probability: 0.25
12809 confirmations:
12810 enabled: true
12811 confirmation_count: 75
12812 positive_response_rate: 0.90
12813 exception_rate: 0.08
12814 opinion:
12815 enabled: true
12816 generate_kam: true
12817 average_kam_count: 4
12818 sox:
12819 enabled: true
12820 generate_302_certifications: true
12821 generate_404_assessments: true
12822 material_weakness_rate: 0.03
12823 pcaob:
12824 enabled: true
12825 is_pcaob_audit: true
12826 include_icfr_opinion: true
12827 generate_audit_trail: true
12828 "#;
12829
12830 let config: AuditStandardsConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12831 assert!(config.enabled);
12832 assert!(config.isa_compliance.enabled);
12833 assert_eq!(config.isa_compliance.compliance_level, "comprehensive");
12834 assert!(config.isa_compliance.include_pcaob);
12835 assert_eq!(config.isa_compliance.framework, "dual");
12836 assert!(config.analytical_procedures.enabled);
12837 assert_eq!(config.analytical_procedures.procedures_per_account, 5);
12838 assert!(config.confirmations.enabled);
12839 assert_eq!(config.confirmations.confirmation_count, 75);
12840 assert!(config.opinion.enabled);
12841 assert_eq!(config.opinion.average_kam_count, 4);
12842 assert!(config.sox.enabled);
12843 assert!(config.sox.generate_302_certifications);
12844 assert_eq!(config.sox.material_weakness_rate, 0.03);
12845 assert!(config.pcaob.enabled);
12846 assert!(config.pcaob.is_pcaob_audit);
12847 assert!(config.pcaob.include_icfr_opinion);
12848 assert!(config.generate_audit_trail);
12849 }
12850
12851 #[test]
12852 fn test_isa_compliance_config_defaults() {
12853 let config = IsaComplianceConfig::default();
12854 assert!(!config.enabled);
12855 assert_eq!(config.compliance_level, "standard");
12856 assert!(config.generate_isa_mappings);
12857 assert!(config.generate_coverage_summary);
12858 assert!(!config.include_pcaob);
12859 assert_eq!(config.framework, "isa");
12860 }
12861
12862 #[test]
12863 fn test_sox_compliance_config_defaults() {
12864 let config = SoxComplianceConfig::default();
12865 assert!(!config.enabled);
12866 assert!(config.generate_302_certifications);
12867 assert!(config.generate_404_assessments);
12868 assert_eq!(config.materiality_threshold, 10000.0);
12869 assert_eq!(config.material_weakness_rate, 0.02);
12870 assert_eq!(config.significant_deficiency_rate, 0.08);
12871 }
12872
12873 #[test]
12874 fn test_pcaob_config_defaults() {
12875 let config = PcaobConfig::default();
12876 assert!(!config.enabled);
12877 assert!(!config.is_pcaob_audit);
12878 assert!(config.generate_cam);
12879 assert!(!config.include_icfr_opinion);
12880 assert!(!config.generate_standard_mappings);
12881 }
12882
12883 #[test]
12884 fn test_config_with_standards_enabled() {
12885 let yaml = r#"
12886 global:
12887 industry: financial_services
12888 start_date: "2024-01-01"
12889 period_months: 12
12890 companies:
12891 - code: "BANK"
12892 name: "Test Bank"
12893 currency: "USD"
12894 country: "US"
12895 annual_transaction_volume: hundred_k
12896 chart_of_accounts:
12897 complexity: large
12898 output:
12899 output_directory: "./output"
12900 accounting_standards:
12901 enabled: true
12902 framework: us_gaap
12903 revenue_recognition:
12904 enabled: true
12905 leases:
12906 enabled: true
12907 audit_standards:
12908 enabled: true
12909 isa_compliance:
12910 enabled: true
12911 sox:
12912 enabled: true
12913 "#;
12914
12915 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12916 assert!(config.accounting_standards.enabled);
12917 assert!(matches!(
12918 config.accounting_standards.framework,
12919 Some(AccountingFrameworkConfig::UsGaap)
12920 ));
12921 assert!(config.accounting_standards.revenue_recognition.enabled);
12922 assert!(config.accounting_standards.leases.enabled);
12923 assert!(config.audit_standards.enabled);
12924 assert!(config.audit_standards.isa_compliance.enabled);
12925 assert!(config.audit_standards.sox.enabled);
12926 }
12927
12928 #[test]
12933 fn test_industry_specific_config_defaults() {
12934 let config = IndustrySpecificConfig::default();
12935 assert!(!config.enabled);
12936 assert!(!config.manufacturing.enabled);
12937 assert!(!config.retail.enabled);
12938 assert!(!config.healthcare.enabled);
12939 assert!(!config.technology.enabled);
12940 assert!(!config.financial_services.enabled);
12941 assert!(!config.professional_services.enabled);
12942 }
12943
12944 #[test]
12945 fn test_manufacturing_config_defaults() {
12946 let config = ManufacturingConfig::default();
12947 assert!(!config.enabled);
12948 assert_eq!(config.bom_depth, 4);
12949 assert!(!config.just_in_time);
12950 assert_eq!(config.supplier_tiers, 2);
12951 assert_eq!(config.target_yield_rate, 0.97);
12952 assert_eq!(config.scrap_alert_threshold, 0.03);
12953 }
12954
12955 #[test]
12956 fn test_retail_config_defaults() {
12957 let config = RetailConfig::default();
12958 assert!(!config.enabled);
12959 assert_eq!(config.avg_daily_transactions, 500);
12960 assert!(config.loss_prevention);
12961 assert_eq!(config.shrinkage_rate, 0.015);
12962 }
12963
12964 #[test]
12965 fn test_healthcare_config_defaults() {
12966 let config = HealthcareConfig::default();
12967 assert!(!config.enabled);
12968 assert_eq!(config.facility_type, "hospital");
12969 assert_eq!(config.avg_daily_encounters, 150);
12970 assert!(config.compliance.hipaa);
12971 assert!(config.compliance.stark_law);
12972 assert!(config.coding_systems.icd10);
12973 assert!(config.coding_systems.cpt);
12974 }
12975
12976 #[test]
12977 fn test_technology_config_defaults() {
12978 let config = TechnologyConfig::default();
12979 assert!(!config.enabled);
12980 assert_eq!(config.revenue_model, "saas");
12981 assert_eq!(config.subscription_revenue_pct, 0.60);
12982 assert!(config.rd_capitalization.enabled);
12983 }
12984
12985 #[test]
12986 fn test_config_with_industry_specific() {
12987 let yaml = r#"
12988 global:
12989 industry: healthcare
12990 start_date: "2024-01-01"
12991 period_months: 12
12992 companies:
12993 - code: "HOSP"
12994 name: "Test Hospital"
12995 currency: "USD"
12996 country: "US"
12997 annual_transaction_volume: hundred_k
12998 chart_of_accounts:
12999 complexity: medium
13000 output:
13001 output_directory: "./output"
13002 industry_specific:
13003 enabled: true
13004 healthcare:
13005 enabled: true
13006 facility_type: hospital
13007 payer_mix:
13008 medicare: 0.45
13009 medicaid: 0.15
13010 commercial: 0.35
13011 self_pay: 0.05
13012 coding_systems:
13013 icd10: true
13014 cpt: true
13015 drg: true
13016 compliance:
13017 hipaa: true
13018 stark_law: true
13019 anomaly_rates:
13020 upcoding: 0.03
13021 unbundling: 0.02
13022 "#;
13023
13024 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13025 assert!(config.industry_specific.enabled);
13026 assert!(config.industry_specific.healthcare.enabled);
13027 assert_eq!(
13028 config.industry_specific.healthcare.facility_type,
13029 "hospital"
13030 );
13031 assert_eq!(config.industry_specific.healthcare.payer_mix.medicare, 0.45);
13032 assert_eq!(config.industry_specific.healthcare.payer_mix.self_pay, 0.05);
13033 assert!(config.industry_specific.healthcare.coding_systems.icd10);
13034 assert!(config.industry_specific.healthcare.compliance.hipaa);
13035 assert_eq!(
13036 config.industry_specific.healthcare.anomaly_rates.upcoding,
13037 0.03
13038 );
13039 }
13040
13041 #[test]
13042 fn test_config_with_manufacturing_specific() {
13043 let yaml = r#"
13044 global:
13045 industry: manufacturing
13046 start_date: "2024-01-01"
13047 period_months: 12
13048 companies:
13049 - code: "MFG"
13050 name: "Test Manufacturing"
13051 currency: "USD"
13052 country: "US"
13053 annual_transaction_volume: hundred_k
13054 chart_of_accounts:
13055 complexity: medium
13056 output:
13057 output_directory: "./output"
13058 industry_specific:
13059 enabled: true
13060 manufacturing:
13061 enabled: true
13062 bom_depth: 5
13063 just_in_time: true
13064 supplier_tiers: 3
13065 target_yield_rate: 0.98
13066 anomaly_rates:
13067 yield_manipulation: 0.02
13068 phantom_production: 0.01
13069 "#;
13070
13071 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13072 assert!(config.industry_specific.enabled);
13073 assert!(config.industry_specific.manufacturing.enabled);
13074 assert_eq!(config.industry_specific.manufacturing.bom_depth, 5);
13075 assert!(config.industry_specific.manufacturing.just_in_time);
13076 assert_eq!(config.industry_specific.manufacturing.supplier_tiers, 3);
13077 assert_eq!(
13078 config.industry_specific.manufacturing.target_yield_rate,
13079 0.98
13080 );
13081 assert_eq!(
13082 config
13083 .industry_specific
13084 .manufacturing
13085 .anomaly_rates
13086 .yield_manipulation,
13087 0.02
13088 );
13089 }
13090
13091 #[test]
13096 fn test_tax_config_defaults() {
13097 let tax = TaxConfig::default();
13098 assert!(!tax.enabled);
13099 assert!(tax.jurisdictions.countries.is_empty());
13100 assert!(!tax.jurisdictions.include_subnational);
13101 assert!(!tax.vat_gst.enabled);
13102 assert!(tax.vat_gst.standard_rates.is_empty());
13103 assert!(tax.vat_gst.reduced_rates.is_empty());
13104 assert!(tax.vat_gst.exempt_categories.is_empty());
13105 assert!(tax.vat_gst.reverse_charge);
13106 assert!(!tax.sales_tax.enabled);
13107 assert!(tax.sales_tax.nexus_states.is_empty());
13108 assert!(!tax.withholding.enabled);
13109 assert!(tax.withholding.treaty_network);
13110 assert_eq!(tax.withholding.default_rate, 0.30);
13111 assert_eq!(tax.withholding.treaty_reduced_rate, 0.15);
13112 assert!(tax.provisions.enabled);
13113 assert_eq!(tax.provisions.statutory_rate, 0.21);
13114 assert!(tax.provisions.uncertain_positions);
13115 assert!(!tax.payroll_tax.enabled);
13116 assert_eq!(tax.anomaly_rate, 0.03);
13117 }
13118
13119 #[test]
13120 fn test_tax_config_from_yaml() {
13121 let yaml = r#"
13122 global:
13123 seed: 42
13124 start_date: "2024-01-01"
13125 period_months: 12
13126 industry: retail
13127 companies:
13128 - code: C001
13129 name: Test Corp
13130 currency: USD
13131 country: US
13132 annual_transaction_volume: ten_k
13133 chart_of_accounts:
13134 complexity: small
13135 output:
13136 output_directory: ./output
13137 tax:
13138 enabled: true
13139 anomaly_rate: 0.05
13140 jurisdictions:
13141 countries: ["US", "DE", "GB"]
13142 include_subnational: true
13143 vat_gst:
13144 enabled: true
13145 standard_rates:
13146 DE: 0.19
13147 GB: 0.20
13148 reduced_rates:
13149 DE: 0.07
13150 GB: 0.05
13151 exempt_categories:
13152 - financial_services
13153 - healthcare
13154 reverse_charge: false
13155 sales_tax:
13156 enabled: true
13157 nexus_states: ["CA", "NY", "TX"]
13158 withholding:
13159 enabled: true
13160 treaty_network: false
13161 default_rate: 0.25
13162 treaty_reduced_rate: 0.10
13163 provisions:
13164 enabled: false
13165 statutory_rate: 0.28
13166 uncertain_positions: false
13167 payroll_tax:
13168 enabled: true
13169 "#;
13170
13171 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13172 assert!(config.tax.enabled);
13173 assert_eq!(config.tax.anomaly_rate, 0.05);
13174
13175 assert_eq!(config.tax.jurisdictions.countries.len(), 3);
13177 assert!(config
13178 .tax
13179 .jurisdictions
13180 .countries
13181 .contains(&"DE".to_string()));
13182 assert!(config.tax.jurisdictions.include_subnational);
13183
13184 assert!(config.tax.vat_gst.enabled);
13186 assert_eq!(config.tax.vat_gst.standard_rates.get("DE"), Some(&0.19));
13187 assert_eq!(config.tax.vat_gst.standard_rates.get("GB"), Some(&0.20));
13188 assert_eq!(config.tax.vat_gst.reduced_rates.get("DE"), Some(&0.07));
13189 assert_eq!(config.tax.vat_gst.exempt_categories.len(), 2);
13190 assert!(!config.tax.vat_gst.reverse_charge);
13191
13192 assert!(config.tax.sales_tax.enabled);
13194 assert_eq!(config.tax.sales_tax.nexus_states.len(), 3);
13195 assert!(config
13196 .tax
13197 .sales_tax
13198 .nexus_states
13199 .contains(&"CA".to_string()));
13200
13201 assert!(config.tax.withholding.enabled);
13203 assert!(!config.tax.withholding.treaty_network);
13204 assert_eq!(config.tax.withholding.default_rate, 0.25);
13205 assert_eq!(config.tax.withholding.treaty_reduced_rate, 0.10);
13206
13207 assert!(!config.tax.provisions.enabled);
13209 assert_eq!(config.tax.provisions.statutory_rate, 0.28);
13210 assert!(!config.tax.provisions.uncertain_positions);
13211
13212 assert!(config.tax.payroll_tax.enabled);
13214 }
13215
13216 #[test]
13217 fn test_generator_config_with_tax_default() {
13218 let yaml = r#"
13219 global:
13220 seed: 42
13221 start_date: "2024-01-01"
13222 period_months: 12
13223 industry: retail
13224 companies:
13225 - code: C001
13226 name: Test Corp
13227 currency: USD
13228 country: US
13229 annual_transaction_volume: ten_k
13230 chart_of_accounts:
13231 complexity: small
13232 output:
13233 output_directory: ./output
13234 "#;
13235
13236 let config: GeneratorConfig =
13237 serde_yaml::from_str(yaml).expect("Failed to parse config without tax section");
13238 assert!(!config.tax.enabled);
13240 assert!(config.tax.jurisdictions.countries.is_empty());
13241 assert_eq!(config.tax.anomaly_rate, 0.03);
13242 assert!(config.tax.provisions.enabled); assert_eq!(config.tax.provisions.statutory_rate, 0.21);
13244 }
13245}