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 GermanGaap,
4693}
4694
4695#[derive(Debug, Clone, Serialize, Deserialize)]
4697pub struct RevenueRecognitionConfig {
4698 #[serde(default)]
4700 pub enabled: bool,
4701
4702 #[serde(default = "default_true")]
4704 pub generate_contracts: bool,
4705
4706 #[serde(default = "default_avg_obligations")]
4708 pub avg_obligations_per_contract: f64,
4709
4710 #[serde(default = "default_variable_consideration_rate")]
4712 pub variable_consideration_rate: f64,
4713
4714 #[serde(default = "default_over_time_rate")]
4716 pub over_time_recognition_rate: f64,
4717
4718 #[serde(default = "default_contract_count")]
4720 pub contract_count: usize,
4721}
4722
4723fn default_avg_obligations() -> f64 {
4724 2.0
4725}
4726
4727fn default_variable_consideration_rate() -> f64 {
4728 0.15
4729}
4730
4731fn default_over_time_rate() -> f64 {
4732 0.30
4733}
4734
4735fn default_contract_count() -> usize {
4736 100
4737}
4738
4739impl Default for RevenueRecognitionConfig {
4740 fn default() -> Self {
4741 Self {
4742 enabled: false,
4743 generate_contracts: true,
4744 avg_obligations_per_contract: default_avg_obligations(),
4745 variable_consideration_rate: default_variable_consideration_rate(),
4746 over_time_recognition_rate: default_over_time_rate(),
4747 contract_count: default_contract_count(),
4748 }
4749 }
4750}
4751
4752#[derive(Debug, Clone, Serialize, Deserialize)]
4754pub struct LeaseAccountingConfig {
4755 #[serde(default)]
4757 pub enabled: bool,
4758
4759 #[serde(default = "default_lease_count")]
4761 pub lease_count: usize,
4762
4763 #[serde(default = "default_finance_lease_pct")]
4765 pub finance_lease_percent: f64,
4766
4767 #[serde(default = "default_avg_lease_term")]
4769 pub avg_lease_term_months: u32,
4770
4771 #[serde(default = "default_true")]
4773 pub generate_amortization: bool,
4774
4775 #[serde(default = "default_real_estate_pct")]
4777 pub real_estate_percent: f64,
4778}
4779
4780fn default_lease_count() -> usize {
4781 50
4782}
4783
4784fn default_finance_lease_pct() -> f64 {
4785 0.30
4786}
4787
4788fn default_avg_lease_term() -> u32 {
4789 60
4790}
4791
4792fn default_real_estate_pct() -> f64 {
4793 0.40
4794}
4795
4796impl Default for LeaseAccountingConfig {
4797 fn default() -> Self {
4798 Self {
4799 enabled: false,
4800 lease_count: default_lease_count(),
4801 finance_lease_percent: default_finance_lease_pct(),
4802 avg_lease_term_months: default_avg_lease_term(),
4803 generate_amortization: true,
4804 real_estate_percent: default_real_estate_pct(),
4805 }
4806 }
4807}
4808
4809#[derive(Debug, Clone, Serialize, Deserialize)]
4811pub struct FairValueConfig {
4812 #[serde(default)]
4814 pub enabled: bool,
4815
4816 #[serde(default = "default_fv_count")]
4818 pub measurement_count: usize,
4819
4820 #[serde(default = "default_level1_pct")]
4822 pub level1_percent: f64,
4823
4824 #[serde(default = "default_level2_pct")]
4826 pub level2_percent: f64,
4827
4828 #[serde(default = "default_level3_pct")]
4830 pub level3_percent: f64,
4831
4832 #[serde(default)]
4834 pub include_sensitivity_analysis: bool,
4835}
4836
4837fn default_fv_count() -> usize {
4838 25
4839}
4840
4841fn default_level1_pct() -> f64 {
4842 0.40
4843}
4844
4845fn default_level2_pct() -> f64 {
4846 0.35
4847}
4848
4849fn default_level3_pct() -> f64 {
4850 0.25
4851}
4852
4853impl Default for FairValueConfig {
4854 fn default() -> Self {
4855 Self {
4856 enabled: false,
4857 measurement_count: default_fv_count(),
4858 level1_percent: default_level1_pct(),
4859 level2_percent: default_level2_pct(),
4860 level3_percent: default_level3_pct(),
4861 include_sensitivity_analysis: false,
4862 }
4863 }
4864}
4865
4866#[derive(Debug, Clone, Serialize, Deserialize)]
4868pub struct ImpairmentConfig {
4869 #[serde(default)]
4871 pub enabled: bool,
4872
4873 #[serde(default = "default_impairment_count")]
4875 pub test_count: usize,
4876
4877 #[serde(default = "default_impairment_rate")]
4879 pub impairment_rate: f64,
4880
4881 #[serde(default = "default_true")]
4883 pub generate_projections: bool,
4884
4885 #[serde(default)]
4887 pub include_goodwill: bool,
4888}
4889
4890fn default_impairment_count() -> usize {
4891 15
4892}
4893
4894fn default_impairment_rate() -> f64 {
4895 0.10
4896}
4897
4898impl Default for ImpairmentConfig {
4899 fn default() -> Self {
4900 Self {
4901 enabled: false,
4902 test_count: default_impairment_count(),
4903 impairment_rate: default_impairment_rate(),
4904 generate_projections: true,
4905 include_goodwill: false,
4906 }
4907 }
4908}
4909
4910#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4923pub struct AuditStandardsConfig {
4924 #[serde(default)]
4926 pub enabled: bool,
4927
4928 #[serde(default)]
4930 pub isa_compliance: IsaComplianceConfig,
4931
4932 #[serde(default)]
4934 pub analytical_procedures: AnalyticalProceduresConfig,
4935
4936 #[serde(default)]
4938 pub confirmations: ConfirmationsConfig,
4939
4940 #[serde(default)]
4942 pub opinion: AuditOpinionConfig,
4943
4944 #[serde(default)]
4946 pub generate_audit_trail: bool,
4947
4948 #[serde(default)]
4950 pub sox: SoxComplianceConfig,
4951
4952 #[serde(default)]
4954 pub pcaob: PcaobConfig,
4955}
4956
4957#[derive(Debug, Clone, Serialize, Deserialize)]
4959pub struct IsaComplianceConfig {
4960 #[serde(default)]
4962 pub enabled: bool,
4963
4964 #[serde(default = "default_compliance_level")]
4966 pub compliance_level: String,
4967
4968 #[serde(default = "default_true")]
4970 pub generate_isa_mappings: bool,
4971
4972 #[serde(default = "default_true")]
4974 pub generate_coverage_summary: bool,
4975
4976 #[serde(default)]
4978 pub include_pcaob: bool,
4979
4980 #[serde(default = "default_audit_framework")]
4982 pub framework: String,
4983}
4984
4985fn default_compliance_level() -> String {
4986 "standard".to_string()
4987}
4988
4989fn default_audit_framework() -> String {
4990 "isa".to_string()
4991}
4992
4993impl Default for IsaComplianceConfig {
4994 fn default() -> Self {
4995 Self {
4996 enabled: false,
4997 compliance_level: default_compliance_level(),
4998 generate_isa_mappings: true,
4999 generate_coverage_summary: true,
5000 include_pcaob: false,
5001 framework: default_audit_framework(),
5002 }
5003 }
5004}
5005
5006#[derive(Debug, Clone, Serialize, Deserialize)]
5008pub struct AnalyticalProceduresConfig {
5009 #[serde(default)]
5011 pub enabled: bool,
5012
5013 #[serde(default = "default_procedures_per_account")]
5015 pub procedures_per_account: usize,
5016
5017 #[serde(default = "default_variance_probability")]
5019 pub variance_probability: f64,
5020
5021 #[serde(default = "default_true")]
5023 pub generate_investigations: bool,
5024
5025 #[serde(default = "default_true")]
5027 pub include_ratio_analysis: bool,
5028}
5029
5030fn default_procedures_per_account() -> usize {
5031 3
5032}
5033
5034fn default_variance_probability() -> f64 {
5035 0.20
5036}
5037
5038impl Default for AnalyticalProceduresConfig {
5039 fn default() -> Self {
5040 Self {
5041 enabled: false,
5042 procedures_per_account: default_procedures_per_account(),
5043 variance_probability: default_variance_probability(),
5044 generate_investigations: true,
5045 include_ratio_analysis: true,
5046 }
5047 }
5048}
5049
5050#[derive(Debug, Clone, Serialize, Deserialize)]
5052pub struct ConfirmationsConfig {
5053 #[serde(default)]
5055 pub enabled: bool,
5056
5057 #[serde(default = "default_confirmation_count")]
5059 pub confirmation_count: usize,
5060
5061 #[serde(default = "default_positive_response_rate")]
5063 pub positive_response_rate: f64,
5064
5065 #[serde(default = "default_exception_rate_confirm")]
5067 pub exception_rate: f64,
5068
5069 #[serde(default = "default_non_response_rate")]
5071 pub non_response_rate: f64,
5072
5073 #[serde(default = "default_true")]
5075 pub generate_alternative_procedures: bool,
5076}
5077
5078fn default_confirmation_count() -> usize {
5079 50
5080}
5081
5082fn default_positive_response_rate() -> f64 {
5083 0.85
5084}
5085
5086fn default_exception_rate_confirm() -> f64 {
5087 0.10
5088}
5089
5090fn default_non_response_rate() -> f64 {
5091 0.05
5092}
5093
5094impl Default for ConfirmationsConfig {
5095 fn default() -> Self {
5096 Self {
5097 enabled: false,
5098 confirmation_count: default_confirmation_count(),
5099 positive_response_rate: default_positive_response_rate(),
5100 exception_rate: default_exception_rate_confirm(),
5101 non_response_rate: default_non_response_rate(),
5102 generate_alternative_procedures: true,
5103 }
5104 }
5105}
5106
5107#[derive(Debug, Clone, Serialize, Deserialize)]
5109pub struct AuditOpinionConfig {
5110 #[serde(default)]
5112 pub enabled: bool,
5113
5114 #[serde(default = "default_true")]
5116 pub generate_kam: bool,
5117
5118 #[serde(default = "default_kam_count")]
5120 pub average_kam_count: usize,
5121
5122 #[serde(default = "default_modified_opinion_rate")]
5124 pub modified_opinion_rate: f64,
5125
5126 #[serde(default)]
5128 pub include_emphasis_of_matter: bool,
5129
5130 #[serde(default = "default_true")]
5132 pub include_going_concern: bool,
5133}
5134
5135fn default_kam_count() -> usize {
5136 3
5137}
5138
5139fn default_modified_opinion_rate() -> f64 {
5140 0.05
5141}
5142
5143impl Default for AuditOpinionConfig {
5144 fn default() -> Self {
5145 Self {
5146 enabled: false,
5147 generate_kam: true,
5148 average_kam_count: default_kam_count(),
5149 modified_opinion_rate: default_modified_opinion_rate(),
5150 include_emphasis_of_matter: false,
5151 include_going_concern: true,
5152 }
5153 }
5154}
5155
5156#[derive(Debug, Clone, Serialize, Deserialize)]
5158pub struct SoxComplianceConfig {
5159 #[serde(default)]
5161 pub enabled: bool,
5162
5163 #[serde(default = "default_true")]
5165 pub generate_302_certifications: bool,
5166
5167 #[serde(default = "default_true")]
5169 pub generate_404_assessments: bool,
5170
5171 #[serde(default = "default_sox_materiality_threshold")]
5173 pub materiality_threshold: f64,
5174
5175 #[serde(default = "default_material_weakness_rate")]
5177 pub material_weakness_rate: f64,
5178
5179 #[serde(default = "default_significant_deficiency_rate")]
5181 pub significant_deficiency_rate: f64,
5182}
5183
5184fn default_material_weakness_rate() -> f64 {
5185 0.02
5186}
5187
5188fn default_significant_deficiency_rate() -> f64 {
5189 0.08
5190}
5191
5192impl Default for SoxComplianceConfig {
5193 fn default() -> Self {
5194 Self {
5195 enabled: false,
5196 generate_302_certifications: true,
5197 generate_404_assessments: true,
5198 materiality_threshold: default_sox_materiality_threshold(),
5199 material_weakness_rate: default_material_weakness_rate(),
5200 significant_deficiency_rate: default_significant_deficiency_rate(),
5201 }
5202 }
5203}
5204
5205#[derive(Debug, Clone, Serialize, Deserialize)]
5207pub struct PcaobConfig {
5208 #[serde(default)]
5210 pub enabled: bool,
5211
5212 #[serde(default)]
5214 pub is_pcaob_audit: bool,
5215
5216 #[serde(default = "default_true")]
5218 pub generate_cam: bool,
5219
5220 #[serde(default)]
5222 pub include_icfr_opinion: bool,
5223
5224 #[serde(default)]
5226 pub generate_standard_mappings: bool,
5227}
5228
5229impl Default for PcaobConfig {
5230 fn default() -> Self {
5231 Self {
5232 enabled: false,
5233 is_pcaob_audit: false,
5234 generate_cam: true,
5235 include_icfr_opinion: false,
5236 generate_standard_mappings: false,
5237 }
5238 }
5239}
5240
5241#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5254pub struct AdvancedDistributionConfig {
5255 #[serde(default)]
5257 pub enabled: bool,
5258
5259 #[serde(default)]
5261 pub amounts: MixtureDistributionSchemaConfig,
5262
5263 #[serde(default)]
5265 pub correlations: CorrelationSchemaConfig,
5266
5267 #[serde(default)]
5269 pub conditional: Vec<ConditionalDistributionSchemaConfig>,
5270
5271 #[serde(default)]
5273 pub regime_changes: RegimeChangeSchemaConfig,
5274
5275 #[serde(default)]
5277 pub industry_profile: Option<IndustryProfileType>,
5278
5279 #[serde(default)]
5281 pub validation: StatisticalValidationSchemaConfig,
5282}
5283
5284#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
5286#[serde(rename_all = "snake_case")]
5287pub enum IndustryProfileType {
5288 Retail,
5290 Manufacturing,
5292 FinancialServices,
5294 Healthcare,
5296 Technology,
5298}
5299
5300#[derive(Debug, Clone, Serialize, Deserialize)]
5302pub struct MixtureDistributionSchemaConfig {
5303 #[serde(default)]
5305 pub enabled: bool,
5306
5307 #[serde(default = "default_mixture_type")]
5309 pub distribution_type: MixtureDistributionType,
5310
5311 #[serde(default)]
5313 pub components: Vec<MixtureComponentConfig>,
5314
5315 #[serde(default = "default_min_amount")]
5317 pub min_value: f64,
5318
5319 #[serde(default)]
5321 pub max_value: Option<f64>,
5322
5323 #[serde(default = "default_decimal_places")]
5325 pub decimal_places: u8,
5326}
5327
5328fn default_mixture_type() -> MixtureDistributionType {
5329 MixtureDistributionType::LogNormal
5330}
5331
5332fn default_min_amount() -> f64 {
5333 0.01
5334}
5335
5336fn default_decimal_places() -> u8 {
5337 2
5338}
5339
5340impl Default for MixtureDistributionSchemaConfig {
5341 fn default() -> Self {
5342 Self {
5343 enabled: false,
5344 distribution_type: MixtureDistributionType::LogNormal,
5345 components: Vec::new(),
5346 min_value: 0.01,
5347 max_value: None,
5348 decimal_places: 2,
5349 }
5350 }
5351}
5352
5353#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5355#[serde(rename_all = "snake_case")]
5356pub enum MixtureDistributionType {
5357 Gaussian,
5359 #[default]
5361 LogNormal,
5362}
5363
5364#[derive(Debug, Clone, Serialize, Deserialize)]
5366pub struct MixtureComponentConfig {
5367 pub weight: f64,
5369
5370 pub mu: f64,
5372
5373 pub sigma: f64,
5375
5376 #[serde(default)]
5378 pub label: Option<String>,
5379}
5380
5381#[derive(Debug, Clone, Serialize, Deserialize)]
5383pub struct CorrelationSchemaConfig {
5384 #[serde(default)]
5386 pub enabled: bool,
5387
5388 #[serde(default)]
5390 pub copula_type: CopulaSchemaType,
5391
5392 #[serde(default)]
5394 pub fields: Vec<CorrelatedFieldConfig>,
5395
5396 #[serde(default)]
5399 pub matrix: Vec<f64>,
5400
5401 #[serde(default)]
5403 pub expected_correlations: Vec<ExpectedCorrelationConfig>,
5404}
5405
5406impl Default for CorrelationSchemaConfig {
5407 fn default() -> Self {
5408 Self {
5409 enabled: false,
5410 copula_type: CopulaSchemaType::Gaussian,
5411 fields: Vec::new(),
5412 matrix: Vec::new(),
5413 expected_correlations: Vec::new(),
5414 }
5415 }
5416}
5417
5418#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5420#[serde(rename_all = "snake_case")]
5421pub enum CopulaSchemaType {
5422 #[default]
5424 Gaussian,
5425 Clayton,
5427 Gumbel,
5429 Frank,
5431 StudentT,
5433}
5434
5435#[derive(Debug, Clone, Serialize, Deserialize)]
5437pub struct CorrelatedFieldConfig {
5438 pub name: String,
5440
5441 #[serde(default)]
5443 pub distribution: MarginalDistributionConfig,
5444}
5445
5446#[derive(Debug, Clone, Serialize, Deserialize)]
5448#[serde(tag = "type", rename_all = "snake_case")]
5449pub enum MarginalDistributionConfig {
5450 Normal {
5452 mu: f64,
5454 sigma: f64,
5456 },
5457 LogNormal {
5459 mu: f64,
5461 sigma: f64,
5463 },
5464 Uniform {
5466 min: f64,
5468 max: f64,
5470 },
5471 DiscreteUniform {
5473 min: i32,
5475 max: i32,
5477 },
5478}
5479
5480impl Default for MarginalDistributionConfig {
5481 fn default() -> Self {
5482 Self::Normal {
5483 mu: 0.0,
5484 sigma: 1.0,
5485 }
5486 }
5487}
5488
5489#[derive(Debug, Clone, Serialize, Deserialize)]
5491pub struct ExpectedCorrelationConfig {
5492 pub field1: String,
5494 pub field2: String,
5496 pub expected_r: f64,
5498 #[serde(default = "default_correlation_tolerance")]
5500 pub tolerance: f64,
5501}
5502
5503fn default_correlation_tolerance() -> f64 {
5504 0.10
5505}
5506
5507#[derive(Debug, Clone, Serialize, Deserialize)]
5509pub struct ConditionalDistributionSchemaConfig {
5510 pub output_field: String,
5512
5513 pub input_field: String,
5515
5516 #[serde(default)]
5518 pub breakpoints: Vec<ConditionalBreakpointConfig>,
5519
5520 #[serde(default)]
5522 pub default_distribution: ConditionalDistributionParamsConfig,
5523
5524 #[serde(default)]
5526 pub min_value: Option<f64>,
5527
5528 #[serde(default)]
5530 pub max_value: Option<f64>,
5531
5532 #[serde(default = "default_decimal_places")]
5534 pub decimal_places: u8,
5535}
5536
5537#[derive(Debug, Clone, Serialize, Deserialize)]
5539pub struct ConditionalBreakpointConfig {
5540 pub threshold: f64,
5542
5543 pub distribution: ConditionalDistributionParamsConfig,
5545}
5546
5547#[derive(Debug, Clone, Serialize, Deserialize)]
5549#[serde(tag = "type", rename_all = "snake_case")]
5550pub enum ConditionalDistributionParamsConfig {
5551 Fixed {
5553 value: f64,
5555 },
5556 Normal {
5558 mu: f64,
5560 sigma: f64,
5562 },
5563 LogNormal {
5565 mu: f64,
5567 sigma: f64,
5569 },
5570 Uniform {
5572 min: f64,
5574 max: f64,
5576 },
5577 Beta {
5579 alpha: f64,
5581 beta: f64,
5583 min: f64,
5585 max: f64,
5587 },
5588 Discrete {
5590 values: Vec<f64>,
5592 weights: Vec<f64>,
5594 },
5595}
5596
5597impl Default for ConditionalDistributionParamsConfig {
5598 fn default() -> Self {
5599 Self::Normal {
5600 mu: 0.0,
5601 sigma: 1.0,
5602 }
5603 }
5604}
5605
5606#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5608pub struct RegimeChangeSchemaConfig {
5609 #[serde(default)]
5611 pub enabled: bool,
5612
5613 #[serde(default)]
5615 pub changes: Vec<RegimeChangeEventConfig>,
5616
5617 #[serde(default)]
5619 pub economic_cycle: Option<EconomicCycleSchemaConfig>,
5620
5621 #[serde(default)]
5623 pub parameter_drifts: Vec<ParameterDriftSchemaConfig>,
5624}
5625
5626#[derive(Debug, Clone, Serialize, Deserialize)]
5628pub struct RegimeChangeEventConfig {
5629 pub date: String,
5631
5632 pub change_type: RegimeChangeTypeConfig,
5634
5635 #[serde(default)]
5637 pub description: Option<String>,
5638
5639 #[serde(default)]
5641 pub effects: Vec<RegimeEffectConfig>,
5642}
5643
5644#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
5646#[serde(rename_all = "snake_case")]
5647pub enum RegimeChangeTypeConfig {
5648 Acquisition,
5650 Divestiture,
5652 PriceIncrease,
5654 PriceDecrease,
5656 ProductLaunch,
5658 ProductDiscontinuation,
5660 PolicyChange,
5662 CompetitorEntry,
5664 Custom,
5666}
5667
5668#[derive(Debug, Clone, Serialize, Deserialize)]
5670pub struct RegimeEffectConfig {
5671 pub field: String,
5673
5674 pub multiplier: f64,
5676}
5677
5678#[derive(Debug, Clone, Serialize, Deserialize)]
5680pub struct EconomicCycleSchemaConfig {
5681 #[serde(default)]
5683 pub enabled: bool,
5684
5685 #[serde(default = "default_cycle_period")]
5687 pub period_months: u32,
5688
5689 #[serde(default = "default_cycle_amplitude")]
5691 pub amplitude: f64,
5692
5693 #[serde(default)]
5695 pub phase_offset: u32,
5696
5697 #[serde(default)]
5699 pub recessions: Vec<RecessionPeriodConfig>,
5700}
5701
5702fn default_cycle_period() -> u32 {
5703 48
5704}
5705
5706fn default_cycle_amplitude() -> f64 {
5707 0.15
5708}
5709
5710impl Default for EconomicCycleSchemaConfig {
5711 fn default() -> Self {
5712 Self {
5713 enabled: false,
5714 period_months: 48,
5715 amplitude: 0.15,
5716 phase_offset: 0,
5717 recessions: Vec::new(),
5718 }
5719 }
5720}
5721
5722#[derive(Debug, Clone, Serialize, Deserialize)]
5724pub struct RecessionPeriodConfig {
5725 pub start_month: u32,
5727
5728 pub duration_months: u32,
5730
5731 #[serde(default = "default_recession_severity")]
5733 pub severity: f64,
5734}
5735
5736fn default_recession_severity() -> f64 {
5737 0.20
5738}
5739
5740#[derive(Debug, Clone, Serialize, Deserialize)]
5742pub struct ParameterDriftSchemaConfig {
5743 pub parameter: String,
5745
5746 pub drift_type: ParameterDriftTypeConfig,
5748
5749 pub start_value: f64,
5751
5752 pub end_value: f64,
5754
5755 #[serde(default)]
5757 pub start_period: u32,
5758
5759 #[serde(default)]
5761 pub end_period: Option<u32>,
5762}
5763
5764#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5766#[serde(rename_all = "snake_case")]
5767pub enum ParameterDriftTypeConfig {
5768 #[default]
5770 Linear,
5771 Exponential,
5773 Logistic,
5775 Step,
5777}
5778
5779#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5781pub struct StatisticalValidationSchemaConfig {
5782 #[serde(default)]
5784 pub enabled: bool,
5785
5786 #[serde(default)]
5788 pub tests: Vec<StatisticalTestConfig>,
5789
5790 #[serde(default)]
5792 pub reporting: ValidationReportingConfig,
5793}
5794
5795#[derive(Debug, Clone, Serialize, Deserialize)]
5797#[serde(tag = "type", rename_all = "snake_case")]
5798pub enum StatisticalTestConfig {
5799 BenfordFirstDigit {
5801 #[serde(default = "default_benford_threshold")]
5803 threshold_mad: f64,
5804 #[serde(default = "default_benford_warning")]
5806 warning_mad: f64,
5807 },
5808 DistributionFit {
5810 target: TargetDistributionConfig,
5812 #[serde(default = "default_ks_significance")]
5814 ks_significance: f64,
5815 #[serde(default)]
5817 method: DistributionFitMethod,
5818 },
5819 CorrelationCheck {
5821 expected_correlations: Vec<ExpectedCorrelationConfig>,
5823 },
5824 ChiSquared {
5826 #[serde(default = "default_chi_squared_bins")]
5828 bins: usize,
5829 #[serde(default = "default_chi_squared_significance")]
5831 significance: f64,
5832 },
5833 AndersonDarling {
5835 target: TargetDistributionConfig,
5837 #[serde(default = "default_ad_significance")]
5839 significance: f64,
5840 },
5841}
5842
5843fn default_benford_threshold() -> f64 {
5844 0.015
5845}
5846
5847fn default_benford_warning() -> f64 {
5848 0.010
5849}
5850
5851fn default_ks_significance() -> f64 {
5852 0.05
5853}
5854
5855fn default_chi_squared_bins() -> usize {
5856 10
5857}
5858
5859fn default_chi_squared_significance() -> f64 {
5860 0.05
5861}
5862
5863fn default_ad_significance() -> f64 {
5864 0.05
5865}
5866
5867#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5869#[serde(rename_all = "snake_case")]
5870pub enum TargetDistributionConfig {
5871 Normal,
5873 #[default]
5875 LogNormal,
5876 Exponential,
5878 Uniform,
5880}
5881
5882#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5884#[serde(rename_all = "snake_case")]
5885pub enum DistributionFitMethod {
5886 #[default]
5888 KolmogorovSmirnov,
5889 AndersonDarling,
5891 ChiSquared,
5893}
5894
5895#[derive(Debug, Clone, Serialize, Deserialize)]
5897pub struct ValidationReportingConfig {
5898 #[serde(default)]
5900 pub output_report: bool,
5901
5902 #[serde(default)]
5904 pub format: ValidationReportFormat,
5905
5906 #[serde(default)]
5908 pub fail_on_error: bool,
5909
5910 #[serde(default = "default_true")]
5912 pub include_details: bool,
5913}
5914
5915impl Default for ValidationReportingConfig {
5916 fn default() -> Self {
5917 Self {
5918 output_report: false,
5919 format: ValidationReportFormat::Json,
5920 fail_on_error: false,
5921 include_details: true,
5922 }
5923 }
5924}
5925
5926#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5928#[serde(rename_all = "snake_case")]
5929pub enum ValidationReportFormat {
5930 #[default]
5932 Json,
5933 Yaml,
5935 Html,
5937}
5938
5939#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5951pub struct TemporalPatternsConfig {
5952 #[serde(default)]
5954 pub enabled: bool,
5955
5956 #[serde(default)]
5958 pub business_days: BusinessDaySchemaConfig,
5959
5960 #[serde(default)]
5962 pub calendars: CalendarSchemaConfig,
5963
5964 #[serde(default)]
5966 pub period_end: PeriodEndSchemaConfig,
5967
5968 #[serde(default)]
5970 pub processing_lags: ProcessingLagSchemaConfig,
5971
5972 #[serde(default)]
5974 pub fiscal_calendar: FiscalCalendarSchemaConfig,
5975
5976 #[serde(default)]
5978 pub intraday: IntraDaySchemaConfig,
5979
5980 #[serde(default)]
5982 pub timezones: TimezoneSchemaConfig,
5983}
5984
5985#[derive(Debug, Clone, Serialize, Deserialize)]
5987pub struct BusinessDaySchemaConfig {
5988 #[serde(default = "default_true")]
5990 pub enabled: bool,
5991
5992 #[serde(default = "default_half_day_policy")]
5994 pub half_day_policy: String,
5995
5996 #[serde(default)]
5998 pub settlement_rules: SettlementRulesSchemaConfig,
5999
6000 #[serde(default = "default_month_end_convention")]
6002 pub month_end_convention: String,
6003
6004 #[serde(default)]
6006 pub weekend_days: Option<Vec<String>>,
6007}
6008
6009fn default_half_day_policy() -> String {
6010 "half_day".to_string()
6011}
6012
6013fn default_month_end_convention() -> String {
6014 "modified_following".to_string()
6015}
6016
6017impl Default for BusinessDaySchemaConfig {
6018 fn default() -> Self {
6019 Self {
6020 enabled: true,
6021 half_day_policy: "half_day".to_string(),
6022 settlement_rules: SettlementRulesSchemaConfig::default(),
6023 month_end_convention: "modified_following".to_string(),
6024 weekend_days: None,
6025 }
6026 }
6027}
6028
6029#[derive(Debug, Clone, Serialize, Deserialize)]
6031pub struct SettlementRulesSchemaConfig {
6032 #[serde(default = "default_settlement_2")]
6034 pub equity_days: i32,
6035
6036 #[serde(default = "default_settlement_1")]
6038 pub government_bonds_days: i32,
6039
6040 #[serde(default = "default_settlement_2")]
6042 pub fx_spot_days: i32,
6043
6044 #[serde(default = "default_settlement_2")]
6046 pub corporate_bonds_days: i32,
6047
6048 #[serde(default = "default_wire_cutoff")]
6050 pub wire_cutoff_time: String,
6051
6052 #[serde(default = "default_settlement_1")]
6054 pub wire_international_days: i32,
6055
6056 #[serde(default = "default_settlement_1")]
6058 pub ach_days: i32,
6059}
6060
6061fn default_settlement_1() -> i32 {
6062 1
6063}
6064
6065fn default_settlement_2() -> i32 {
6066 2
6067}
6068
6069fn default_wire_cutoff() -> String {
6070 "14:00".to_string()
6071}
6072
6073impl Default for SettlementRulesSchemaConfig {
6074 fn default() -> Self {
6075 Self {
6076 equity_days: 2,
6077 government_bonds_days: 1,
6078 fx_spot_days: 2,
6079 corporate_bonds_days: 2,
6080 wire_cutoff_time: "14:00".to_string(),
6081 wire_international_days: 1,
6082 ach_days: 1,
6083 }
6084 }
6085}
6086
6087#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6089pub struct CalendarSchemaConfig {
6090 #[serde(default)]
6092 pub regions: Vec<String>,
6093
6094 #[serde(default)]
6096 pub custom_holidays: Vec<CustomHolidaySchemaConfig>,
6097}
6098
6099#[derive(Debug, Clone, Serialize, Deserialize)]
6101pub struct CustomHolidaySchemaConfig {
6102 pub name: String,
6104 pub month: u8,
6106 pub day: u8,
6108 #[serde(default = "default_holiday_multiplier")]
6110 pub activity_multiplier: f64,
6111}
6112
6113fn default_holiday_multiplier() -> f64 {
6114 0.05
6115}
6116
6117#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6119pub struct PeriodEndSchemaConfig {
6120 #[serde(default)]
6122 pub model: Option<String>,
6123
6124 #[serde(default)]
6126 pub month_end: Option<PeriodEndModelSchemaConfig>,
6127
6128 #[serde(default)]
6130 pub quarter_end: Option<PeriodEndModelSchemaConfig>,
6131
6132 #[serde(default)]
6134 pub year_end: Option<PeriodEndModelSchemaConfig>,
6135}
6136
6137#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6139pub struct PeriodEndModelSchemaConfig {
6140 #[serde(default)]
6142 pub inherit_from: Option<String>,
6143
6144 #[serde(default)]
6146 pub additional_multiplier: Option<f64>,
6147
6148 #[serde(default)]
6150 pub start_day: Option<i32>,
6151
6152 #[serde(default)]
6154 pub base_multiplier: Option<f64>,
6155
6156 #[serde(default)]
6158 pub peak_multiplier: Option<f64>,
6159
6160 #[serde(default)]
6162 pub decay_rate: Option<f64>,
6163
6164 #[serde(default)]
6166 pub sustained_high_days: Option<i32>,
6167}
6168
6169#[derive(Debug, Clone, Serialize, Deserialize)]
6171pub struct ProcessingLagSchemaConfig {
6172 #[serde(default = "default_true")]
6174 pub enabled: bool,
6175
6176 #[serde(default)]
6178 pub sales_order_lag: Option<LagDistributionSchemaConfig>,
6179
6180 #[serde(default)]
6182 pub purchase_order_lag: Option<LagDistributionSchemaConfig>,
6183
6184 #[serde(default)]
6186 pub goods_receipt_lag: Option<LagDistributionSchemaConfig>,
6187
6188 #[serde(default)]
6190 pub invoice_receipt_lag: Option<LagDistributionSchemaConfig>,
6191
6192 #[serde(default)]
6194 pub invoice_issue_lag: Option<LagDistributionSchemaConfig>,
6195
6196 #[serde(default)]
6198 pub payment_lag: Option<LagDistributionSchemaConfig>,
6199
6200 #[serde(default)]
6202 pub journal_entry_lag: Option<LagDistributionSchemaConfig>,
6203
6204 #[serde(default)]
6206 pub cross_day_posting: Option<CrossDayPostingSchemaConfig>,
6207}
6208
6209impl Default for ProcessingLagSchemaConfig {
6210 fn default() -> Self {
6211 Self {
6212 enabled: true,
6213 sales_order_lag: None,
6214 purchase_order_lag: None,
6215 goods_receipt_lag: None,
6216 invoice_receipt_lag: None,
6217 invoice_issue_lag: None,
6218 payment_lag: None,
6219 journal_entry_lag: None,
6220 cross_day_posting: None,
6221 }
6222 }
6223}
6224
6225#[derive(Debug, Clone, Serialize, Deserialize)]
6227pub struct LagDistributionSchemaConfig {
6228 pub mu: f64,
6230 pub sigma: f64,
6232 #[serde(default)]
6234 pub min_hours: Option<f64>,
6235 #[serde(default)]
6237 pub max_hours: Option<f64>,
6238}
6239
6240#[derive(Debug, Clone, Serialize, Deserialize)]
6242pub struct CrossDayPostingSchemaConfig {
6243 #[serde(default = "default_true")]
6245 pub enabled: bool,
6246
6247 #[serde(default)]
6250 pub probability_by_hour: std::collections::HashMap<u8, f64>,
6251}
6252
6253impl Default for CrossDayPostingSchemaConfig {
6254 fn default() -> Self {
6255 let mut probability_by_hour = std::collections::HashMap::new();
6256 probability_by_hour.insert(17, 0.3);
6257 probability_by_hour.insert(18, 0.6);
6258 probability_by_hour.insert(19, 0.8);
6259 probability_by_hour.insert(20, 0.9);
6260 probability_by_hour.insert(21, 0.95);
6261 probability_by_hour.insert(22, 0.99);
6262
6263 Self {
6264 enabled: true,
6265 probability_by_hour,
6266 }
6267 }
6268}
6269
6270#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6279pub struct FiscalCalendarSchemaConfig {
6280 #[serde(default)]
6282 pub enabled: bool,
6283
6284 #[serde(default = "default_fiscal_calendar_type")]
6286 pub calendar_type: String,
6287
6288 #[serde(default)]
6290 pub year_start_month: Option<u8>,
6291
6292 #[serde(default)]
6294 pub year_start_day: Option<u8>,
6295
6296 #[serde(default)]
6298 pub four_four_five: Option<FourFourFiveSchemaConfig>,
6299}
6300
6301fn default_fiscal_calendar_type() -> String {
6302 "calendar_year".to_string()
6303}
6304
6305#[derive(Debug, Clone, Serialize, Deserialize)]
6307pub struct FourFourFiveSchemaConfig {
6308 #[serde(default = "default_week_pattern")]
6310 pub pattern: String,
6311
6312 #[serde(default = "default_anchor_type")]
6314 pub anchor_type: String,
6315
6316 #[serde(default = "default_anchor_month")]
6318 pub anchor_month: u8,
6319
6320 #[serde(default = "default_leap_week_placement")]
6322 pub leap_week_placement: String,
6323}
6324
6325fn default_week_pattern() -> String {
6326 "four_four_five".to_string()
6327}
6328
6329fn default_anchor_type() -> String {
6330 "last_saturday".to_string()
6331}
6332
6333fn default_anchor_month() -> u8 {
6334 1 }
6336
6337fn default_leap_week_placement() -> String {
6338 "q4_period3".to_string()
6339}
6340
6341impl Default for FourFourFiveSchemaConfig {
6342 fn default() -> Self {
6343 Self {
6344 pattern: "four_four_five".to_string(),
6345 anchor_type: "last_saturday".to_string(),
6346 anchor_month: 1,
6347 leap_week_placement: "q4_period3".to_string(),
6348 }
6349 }
6350}
6351
6352#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6361pub struct IntraDaySchemaConfig {
6362 #[serde(default)]
6364 pub enabled: bool,
6365
6366 #[serde(default)]
6368 pub segments: Vec<IntraDaySegmentSchemaConfig>,
6369}
6370
6371#[derive(Debug, Clone, Serialize, Deserialize)]
6373pub struct IntraDaySegmentSchemaConfig {
6374 pub name: String,
6376
6377 pub start: String,
6379
6380 pub end: String,
6382
6383 #[serde(default = "default_multiplier")]
6385 pub multiplier: f64,
6386
6387 #[serde(default = "default_posting_type")]
6389 pub posting_type: String,
6390}
6391
6392fn default_multiplier() -> f64 {
6393 1.0
6394}
6395
6396fn default_posting_type() -> String {
6397 "both".to_string()
6398}
6399
6400#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6406pub struct TimezoneSchemaConfig {
6407 #[serde(default)]
6409 pub enabled: bool,
6410
6411 #[serde(default = "default_timezone")]
6413 pub default_timezone: String,
6414
6415 #[serde(default = "default_consolidation_timezone")]
6417 pub consolidation_timezone: String,
6418
6419 #[serde(default)]
6422 pub entity_mappings: Vec<EntityTimezoneMapping>,
6423}
6424
6425fn default_timezone() -> String {
6426 "America/New_York".to_string()
6427}
6428
6429fn default_consolidation_timezone() -> String {
6430 "UTC".to_string()
6431}
6432
6433#[derive(Debug, Clone, Serialize, Deserialize)]
6435pub struct EntityTimezoneMapping {
6436 pub pattern: String,
6438
6439 pub timezone: String,
6441}
6442
6443#[derive(Debug, Clone, Serialize, Deserialize)]
6449pub struct VendorNetworkSchemaConfig {
6450 #[serde(default)]
6452 pub enabled: bool,
6453
6454 #[serde(default = "default_vendor_tier_depth")]
6456 pub depth: u8,
6457
6458 #[serde(default)]
6460 pub tier1: TierCountSchemaConfig,
6461
6462 #[serde(default)]
6464 pub tier2_per_parent: TierCountSchemaConfig,
6465
6466 #[serde(default)]
6468 pub tier3_per_parent: TierCountSchemaConfig,
6469
6470 #[serde(default)]
6472 pub clusters: VendorClusterSchemaConfig,
6473
6474 #[serde(default)]
6476 pub dependencies: DependencySchemaConfig,
6477}
6478
6479fn default_vendor_tier_depth() -> u8 {
6480 3
6481}
6482
6483impl Default for VendorNetworkSchemaConfig {
6484 fn default() -> Self {
6485 Self {
6486 enabled: false,
6487 depth: 3,
6488 tier1: TierCountSchemaConfig { min: 50, max: 100 },
6489 tier2_per_parent: TierCountSchemaConfig { min: 4, max: 10 },
6490 tier3_per_parent: TierCountSchemaConfig { min: 2, max: 5 },
6491 clusters: VendorClusterSchemaConfig::default(),
6492 dependencies: DependencySchemaConfig::default(),
6493 }
6494 }
6495}
6496
6497#[derive(Debug, Clone, Serialize, Deserialize)]
6499pub struct TierCountSchemaConfig {
6500 #[serde(default = "default_tier_min")]
6502 pub min: usize,
6503
6504 #[serde(default = "default_tier_max")]
6506 pub max: usize,
6507}
6508
6509fn default_tier_min() -> usize {
6510 5
6511}
6512
6513fn default_tier_max() -> usize {
6514 20
6515}
6516
6517impl Default for TierCountSchemaConfig {
6518 fn default() -> Self {
6519 Self {
6520 min: default_tier_min(),
6521 max: default_tier_max(),
6522 }
6523 }
6524}
6525
6526#[derive(Debug, Clone, Serialize, Deserialize)]
6528pub struct VendorClusterSchemaConfig {
6529 #[serde(default = "default_reliable_strategic")]
6531 pub reliable_strategic: f64,
6532
6533 #[serde(default = "default_standard_operational")]
6535 pub standard_operational: f64,
6536
6537 #[serde(default = "default_transactional")]
6539 pub transactional: f64,
6540
6541 #[serde(default = "default_problematic")]
6543 pub problematic: f64,
6544}
6545
6546fn default_reliable_strategic() -> f64 {
6547 0.20
6548}
6549
6550fn default_standard_operational() -> f64 {
6551 0.50
6552}
6553
6554fn default_transactional() -> f64 {
6555 0.25
6556}
6557
6558fn default_problematic() -> f64 {
6559 0.05
6560}
6561
6562impl Default for VendorClusterSchemaConfig {
6563 fn default() -> Self {
6564 Self {
6565 reliable_strategic: 0.20,
6566 standard_operational: 0.50,
6567 transactional: 0.25,
6568 problematic: 0.05,
6569 }
6570 }
6571}
6572
6573#[derive(Debug, Clone, Serialize, Deserialize)]
6575pub struct DependencySchemaConfig {
6576 #[serde(default = "default_max_single_vendor")]
6578 pub max_single_vendor_concentration: f64,
6579
6580 #[serde(default = "default_max_top5")]
6582 pub top_5_concentration: f64,
6583
6584 #[serde(default = "default_single_source_percent")]
6586 pub single_source_percent: f64,
6587}
6588
6589fn default_max_single_vendor() -> f64 {
6590 0.15
6591}
6592
6593fn default_max_top5() -> f64 {
6594 0.45
6595}
6596
6597fn default_single_source_percent() -> f64 {
6598 0.05
6599}
6600
6601impl Default for DependencySchemaConfig {
6602 fn default() -> Self {
6603 Self {
6604 max_single_vendor_concentration: 0.15,
6605 top_5_concentration: 0.45,
6606 single_source_percent: 0.05,
6607 }
6608 }
6609}
6610
6611#[derive(Debug, Clone, Default, Serialize, Deserialize)]
6617pub struct CustomerSegmentationSchemaConfig {
6618 #[serde(default)]
6620 pub enabled: bool,
6621
6622 #[serde(default)]
6624 pub value_segments: ValueSegmentsSchemaConfig,
6625
6626 #[serde(default)]
6628 pub lifecycle: LifecycleSchemaConfig,
6629
6630 #[serde(default)]
6632 pub networks: CustomerNetworksSchemaConfig,
6633}
6634
6635#[derive(Debug, Clone, Serialize, Deserialize)]
6637pub struct ValueSegmentsSchemaConfig {
6638 #[serde(default)]
6640 pub enterprise: SegmentDetailSchemaConfig,
6641
6642 #[serde(default)]
6644 pub mid_market: SegmentDetailSchemaConfig,
6645
6646 #[serde(default)]
6648 pub smb: SegmentDetailSchemaConfig,
6649
6650 #[serde(default)]
6652 pub consumer: SegmentDetailSchemaConfig,
6653}
6654
6655impl Default for ValueSegmentsSchemaConfig {
6656 fn default() -> Self {
6657 Self {
6658 enterprise: SegmentDetailSchemaConfig {
6659 revenue_share: 0.40,
6660 customer_share: 0.05,
6661 avg_order_value_range: "50000+".to_string(),
6662 },
6663 mid_market: SegmentDetailSchemaConfig {
6664 revenue_share: 0.35,
6665 customer_share: 0.20,
6666 avg_order_value_range: "5000-50000".to_string(),
6667 },
6668 smb: SegmentDetailSchemaConfig {
6669 revenue_share: 0.20,
6670 customer_share: 0.50,
6671 avg_order_value_range: "500-5000".to_string(),
6672 },
6673 consumer: SegmentDetailSchemaConfig {
6674 revenue_share: 0.05,
6675 customer_share: 0.25,
6676 avg_order_value_range: "50-500".to_string(),
6677 },
6678 }
6679 }
6680}
6681
6682#[derive(Debug, Clone, Serialize, Deserialize)]
6684pub struct SegmentDetailSchemaConfig {
6685 #[serde(default)]
6687 pub revenue_share: f64,
6688
6689 #[serde(default)]
6691 pub customer_share: f64,
6692
6693 #[serde(default)]
6695 pub avg_order_value_range: String,
6696}
6697
6698impl Default for SegmentDetailSchemaConfig {
6699 fn default() -> Self {
6700 Self {
6701 revenue_share: 0.25,
6702 customer_share: 0.25,
6703 avg_order_value_range: "1000-10000".to_string(),
6704 }
6705 }
6706}
6707
6708#[derive(Debug, Clone, Serialize, Deserialize)]
6710pub struct LifecycleSchemaConfig {
6711 #[serde(default)]
6713 pub prospect_rate: f64,
6714
6715 #[serde(default = "default_new_rate")]
6717 pub new_rate: f64,
6718
6719 #[serde(default = "default_growth_rate")]
6721 pub growth_rate: f64,
6722
6723 #[serde(default = "default_mature_rate")]
6725 pub mature_rate: f64,
6726
6727 #[serde(default = "default_at_risk_rate")]
6729 pub at_risk_rate: f64,
6730
6731 #[serde(default = "default_churned_rate")]
6733 pub churned_rate: f64,
6734}
6735
6736fn default_new_rate() -> f64 {
6737 0.10
6738}
6739
6740fn default_growth_rate() -> f64 {
6741 0.15
6742}
6743
6744fn default_mature_rate() -> f64 {
6745 0.60
6746}
6747
6748fn default_at_risk_rate() -> f64 {
6749 0.10
6750}
6751
6752fn default_churned_rate() -> f64 {
6753 0.05
6754}
6755
6756impl Default for LifecycleSchemaConfig {
6757 fn default() -> Self {
6758 Self {
6759 prospect_rate: 0.0,
6760 new_rate: 0.10,
6761 growth_rate: 0.15,
6762 mature_rate: 0.60,
6763 at_risk_rate: 0.10,
6764 churned_rate: 0.05,
6765 }
6766 }
6767}
6768
6769#[derive(Debug, Clone, Default, Serialize, Deserialize)]
6771pub struct CustomerNetworksSchemaConfig {
6772 #[serde(default)]
6774 pub referrals: ReferralSchemaConfig,
6775
6776 #[serde(default)]
6778 pub corporate_hierarchies: HierarchySchemaConfig,
6779}
6780
6781#[derive(Debug, Clone, Serialize, Deserialize)]
6783pub struct ReferralSchemaConfig {
6784 #[serde(default = "default_true")]
6786 pub enabled: bool,
6787
6788 #[serde(default = "default_referral_rate")]
6790 pub referral_rate: f64,
6791}
6792
6793fn default_referral_rate() -> f64 {
6794 0.15
6795}
6796
6797impl Default for ReferralSchemaConfig {
6798 fn default() -> Self {
6799 Self {
6800 enabled: true,
6801 referral_rate: 0.15,
6802 }
6803 }
6804}
6805
6806#[derive(Debug, Clone, Serialize, Deserialize)]
6808pub struct HierarchySchemaConfig {
6809 #[serde(default = "default_true")]
6811 pub enabled: bool,
6812
6813 #[serde(default = "default_hierarchy_rate")]
6815 pub probability: f64,
6816}
6817
6818fn default_hierarchy_rate() -> f64 {
6819 0.30
6820}
6821
6822impl Default for HierarchySchemaConfig {
6823 fn default() -> Self {
6824 Self {
6825 enabled: true,
6826 probability: 0.30,
6827 }
6828 }
6829}
6830
6831#[derive(Debug, Clone, Default, Serialize, Deserialize)]
6837pub struct RelationshipStrengthSchemaConfig {
6838 #[serde(default)]
6840 pub enabled: bool,
6841
6842 #[serde(default)]
6844 pub calculation: StrengthCalculationSchemaConfig,
6845
6846 #[serde(default)]
6848 pub thresholds: StrengthThresholdsSchemaConfig,
6849}
6850
6851#[derive(Debug, Clone, Serialize, Deserialize)]
6853pub struct StrengthCalculationSchemaConfig {
6854 #[serde(default = "default_volume_weight")]
6856 pub transaction_volume_weight: f64,
6857
6858 #[serde(default = "default_count_weight")]
6860 pub transaction_count_weight: f64,
6861
6862 #[serde(default = "default_duration_weight")]
6864 pub relationship_duration_weight: f64,
6865
6866 #[serde(default = "default_recency_weight")]
6868 pub recency_weight: f64,
6869
6870 #[serde(default = "default_mutual_weight")]
6872 pub mutual_connections_weight: f64,
6873
6874 #[serde(default = "default_recency_half_life")]
6876 pub recency_half_life_days: u32,
6877}
6878
6879fn default_volume_weight() -> f64 {
6880 0.30
6881}
6882
6883fn default_count_weight() -> f64 {
6884 0.25
6885}
6886
6887fn default_duration_weight() -> f64 {
6888 0.20
6889}
6890
6891fn default_recency_weight() -> f64 {
6892 0.15
6893}
6894
6895fn default_mutual_weight() -> f64 {
6896 0.10
6897}
6898
6899fn default_recency_half_life() -> u32 {
6900 90
6901}
6902
6903impl Default for StrengthCalculationSchemaConfig {
6904 fn default() -> Self {
6905 Self {
6906 transaction_volume_weight: 0.30,
6907 transaction_count_weight: 0.25,
6908 relationship_duration_weight: 0.20,
6909 recency_weight: 0.15,
6910 mutual_connections_weight: 0.10,
6911 recency_half_life_days: 90,
6912 }
6913 }
6914}
6915
6916#[derive(Debug, Clone, Serialize, Deserialize)]
6918pub struct StrengthThresholdsSchemaConfig {
6919 #[serde(default = "default_strong_threshold")]
6921 pub strong: f64,
6922
6923 #[serde(default = "default_moderate_threshold")]
6925 pub moderate: f64,
6926
6927 #[serde(default = "default_weak_threshold")]
6929 pub weak: f64,
6930}
6931
6932fn default_strong_threshold() -> f64 {
6933 0.7
6934}
6935
6936fn default_moderate_threshold() -> f64 {
6937 0.4
6938}
6939
6940fn default_weak_threshold() -> f64 {
6941 0.1
6942}
6943
6944impl Default for StrengthThresholdsSchemaConfig {
6945 fn default() -> Self {
6946 Self {
6947 strong: 0.7,
6948 moderate: 0.4,
6949 weak: 0.1,
6950 }
6951 }
6952}
6953
6954#[derive(Debug, Clone, Serialize, Deserialize)]
6960pub struct CrossProcessLinksSchemaConfig {
6961 #[serde(default)]
6963 pub enabled: bool,
6964
6965 #[serde(default = "default_true")]
6967 pub inventory_p2p_o2c: bool,
6968
6969 #[serde(default = "default_true")]
6971 pub payment_bank_reconciliation: bool,
6972
6973 #[serde(default = "default_true")]
6975 pub intercompany_bilateral: bool,
6976
6977 #[serde(default = "default_inventory_link_rate")]
6979 pub inventory_link_rate: f64,
6980}
6981
6982fn default_inventory_link_rate() -> f64 {
6983 0.30
6984}
6985
6986impl Default for CrossProcessLinksSchemaConfig {
6987 fn default() -> Self {
6988 Self {
6989 enabled: false,
6990 inventory_p2p_o2c: true,
6991 payment_bank_reconciliation: true,
6992 intercompany_bilateral: true,
6993 inventory_link_rate: 0.30,
6994 }
6995 }
6996}
6997
6998#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7004pub struct OrganizationalEventsSchemaConfig {
7005 #[serde(default)]
7007 pub enabled: bool,
7008
7009 #[serde(default)]
7011 pub effect_blending: EffectBlendingModeConfig,
7012
7013 #[serde(default)]
7015 pub events: Vec<OrganizationalEventSchemaConfig>,
7016
7017 #[serde(default)]
7019 pub process_evolution: Vec<ProcessEvolutionSchemaConfig>,
7020
7021 #[serde(default)]
7023 pub technology_transitions: Vec<TechnologyTransitionSchemaConfig>,
7024}
7025
7026#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
7028#[serde(rename_all = "snake_case")]
7029pub enum EffectBlendingModeConfig {
7030 #[default]
7032 Multiplicative,
7033 Additive,
7035 Maximum,
7037 Minimum,
7039}
7040
7041#[derive(Debug, Clone, Serialize, Deserialize)]
7043pub struct OrganizationalEventSchemaConfig {
7044 pub id: String,
7046
7047 pub event_type: OrganizationalEventTypeSchemaConfig,
7049
7050 pub effective_date: String,
7052
7053 #[serde(default = "default_org_transition_months")]
7055 pub transition_months: u32,
7056
7057 #[serde(default)]
7059 pub description: Option<String>,
7060}
7061
7062fn default_org_transition_months() -> u32 {
7063 6
7064}
7065
7066#[derive(Debug, Clone, Serialize, Deserialize)]
7068#[serde(tag = "type", rename_all = "snake_case")]
7069pub enum OrganizationalEventTypeSchemaConfig {
7070 Acquisition {
7072 acquired_entity: String,
7074 #[serde(default = "default_acquisition_volume")]
7076 volume_increase: f64,
7077 #[serde(default = "default_acquisition_error")]
7079 integration_error_rate: f64,
7080 #[serde(default = "default_parallel_days")]
7082 parallel_posting_days: u32,
7083 },
7084 Divestiture {
7086 divested_entity: String,
7088 #[serde(default = "default_divestiture_volume")]
7090 volume_reduction: f64,
7091 #[serde(default = "default_true_val")]
7093 remove_entity: bool,
7094 },
7095 Reorganization {
7097 #[serde(default)]
7099 cost_center_remapping: std::collections::HashMap<String, String>,
7100 #[serde(default = "default_reorg_error")]
7102 transition_error_rate: f64,
7103 },
7104 LeadershipChange {
7106 role: String,
7108 #[serde(default)]
7110 policy_changes: Vec<String>,
7111 },
7112 WorkforceReduction {
7114 #[serde(default = "default_workforce_reduction")]
7116 reduction_percent: f64,
7117 #[serde(default = "default_workforce_error")]
7119 error_rate_increase: f64,
7120 },
7121 Merger {
7123 merged_entity: String,
7125 #[serde(default = "default_merger_volume")]
7127 volume_increase: f64,
7128 },
7129}
7130
7131fn default_acquisition_volume() -> f64 {
7132 1.35
7133}
7134
7135fn default_acquisition_error() -> f64 {
7136 0.05
7137}
7138
7139fn default_parallel_days() -> u32 {
7140 30
7141}
7142
7143fn default_divestiture_volume() -> f64 {
7144 0.70
7145}
7146
7147fn default_true_val() -> bool {
7148 true
7149}
7150
7151fn default_reorg_error() -> f64 {
7152 0.04
7153}
7154
7155fn default_workforce_reduction() -> f64 {
7156 0.10
7157}
7158
7159fn default_workforce_error() -> f64 {
7160 0.05
7161}
7162
7163fn default_merger_volume() -> f64 {
7164 1.80
7165}
7166
7167#[derive(Debug, Clone, Serialize, Deserialize)]
7169pub struct ProcessEvolutionSchemaConfig {
7170 pub id: String,
7172
7173 pub event_type: ProcessEvolutionTypeSchemaConfig,
7175
7176 pub effective_date: String,
7178
7179 #[serde(default)]
7181 pub description: Option<String>,
7182}
7183
7184#[derive(Debug, Clone, Serialize, Deserialize)]
7186#[serde(tag = "type", rename_all = "snake_case")]
7187pub enum ProcessEvolutionTypeSchemaConfig {
7188 ProcessAutomation {
7190 process_name: String,
7192 #[serde(default = "default_manual_before")]
7194 manual_rate_before: f64,
7195 #[serde(default = "default_manual_after")]
7197 manual_rate_after: f64,
7198 },
7199 ApprovalWorkflowChange {
7201 description: String,
7203 },
7204 ControlEnhancement {
7206 control_id: String,
7208 #[serde(default = "default_error_reduction")]
7210 error_reduction: f64,
7211 },
7212}
7213
7214fn default_manual_before() -> f64 {
7215 0.80
7216}
7217
7218fn default_manual_after() -> f64 {
7219 0.15
7220}
7221
7222fn default_error_reduction() -> f64 {
7223 0.02
7224}
7225
7226#[derive(Debug, Clone, Serialize, Deserialize)]
7228pub struct TechnologyTransitionSchemaConfig {
7229 pub id: String,
7231
7232 pub event_type: TechnologyTransitionTypeSchemaConfig,
7234
7235 #[serde(default)]
7237 pub description: Option<String>,
7238}
7239
7240#[derive(Debug, Clone, Serialize, Deserialize)]
7242#[serde(tag = "type", rename_all = "snake_case")]
7243pub enum TechnologyTransitionTypeSchemaConfig {
7244 ErpMigration {
7246 source_system: String,
7248 target_system: String,
7250 cutover_date: String,
7252 stabilization_end: String,
7254 #[serde(default = "default_erp_duplicate_rate")]
7256 duplicate_rate: f64,
7257 #[serde(default = "default_format_mismatch")]
7259 format_mismatch_rate: f64,
7260 },
7261 ModuleImplementation {
7263 module_name: String,
7265 go_live_date: String,
7267 },
7268}
7269
7270fn default_erp_duplicate_rate() -> f64 {
7271 0.02
7272}
7273
7274fn default_format_mismatch() -> f64 {
7275 0.03
7276}
7277
7278#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7284pub struct BehavioralDriftSchemaConfig {
7285 #[serde(default)]
7287 pub enabled: bool,
7288
7289 #[serde(default)]
7291 pub vendor_behavior: VendorBehaviorSchemaConfig,
7292
7293 #[serde(default)]
7295 pub customer_behavior: CustomerBehaviorSchemaConfig,
7296
7297 #[serde(default)]
7299 pub employee_behavior: EmployeeBehaviorSchemaConfig,
7300
7301 #[serde(default)]
7303 pub collective: CollectiveBehaviorSchemaConfig,
7304}
7305
7306#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7308pub struct VendorBehaviorSchemaConfig {
7309 #[serde(default)]
7311 pub payment_terms_drift: PaymentTermsDriftSchemaConfig,
7312
7313 #[serde(default)]
7315 pub quality_drift: QualityDriftSchemaConfig,
7316}
7317
7318#[derive(Debug, Clone, Serialize, Deserialize)]
7320pub struct PaymentTermsDriftSchemaConfig {
7321 #[serde(default = "default_extension_rate")]
7323 pub extension_rate_per_year: f64,
7324
7325 #[serde(default = "default_economic_sensitivity")]
7327 pub economic_sensitivity: f64,
7328}
7329
7330fn default_extension_rate() -> f64 {
7331 2.5
7332}
7333
7334fn default_economic_sensitivity() -> f64 {
7335 1.0
7336}
7337
7338impl Default for PaymentTermsDriftSchemaConfig {
7339 fn default() -> Self {
7340 Self {
7341 extension_rate_per_year: 2.5,
7342 economic_sensitivity: 1.0,
7343 }
7344 }
7345}
7346
7347#[derive(Debug, Clone, Serialize, Deserialize)]
7349pub struct QualityDriftSchemaConfig {
7350 #[serde(default = "default_improvement_rate")]
7352 pub new_vendor_improvement_rate: f64,
7353
7354 #[serde(default = "default_decline_rate")]
7356 pub complacency_decline_rate: f64,
7357}
7358
7359fn default_improvement_rate() -> f64 {
7360 0.02
7361}
7362
7363fn default_decline_rate() -> f64 {
7364 0.01
7365}
7366
7367impl Default for QualityDriftSchemaConfig {
7368 fn default() -> Self {
7369 Self {
7370 new_vendor_improvement_rate: 0.02,
7371 complacency_decline_rate: 0.01,
7372 }
7373 }
7374}
7375
7376#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7378pub struct CustomerBehaviorSchemaConfig {
7379 #[serde(default)]
7381 pub payment_drift: CustomerPaymentDriftSchemaConfig,
7382
7383 #[serde(default)]
7385 pub order_drift: OrderDriftSchemaConfig,
7386}
7387
7388#[derive(Debug, Clone, Serialize, Deserialize)]
7390pub struct CustomerPaymentDriftSchemaConfig {
7391 #[serde(default = "default_downturn_extension")]
7393 pub downturn_days_extension: (u32, u32),
7394
7395 #[serde(default = "default_bad_debt_increase")]
7397 pub downturn_bad_debt_increase: f64,
7398}
7399
7400fn default_downturn_extension() -> (u32, u32) {
7401 (5, 15)
7402}
7403
7404fn default_bad_debt_increase() -> f64 {
7405 0.02
7406}
7407
7408impl Default for CustomerPaymentDriftSchemaConfig {
7409 fn default() -> Self {
7410 Self {
7411 downturn_days_extension: (5, 15),
7412 downturn_bad_debt_increase: 0.02,
7413 }
7414 }
7415}
7416
7417#[derive(Debug, Clone, Serialize, Deserialize)]
7419pub struct OrderDriftSchemaConfig {
7420 #[serde(default = "default_digital_shift")]
7422 pub digital_shift_rate: f64,
7423}
7424
7425fn default_digital_shift() -> f64 {
7426 0.05
7427}
7428
7429impl Default for OrderDriftSchemaConfig {
7430 fn default() -> Self {
7431 Self {
7432 digital_shift_rate: 0.05,
7433 }
7434 }
7435}
7436
7437#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7439pub struct EmployeeBehaviorSchemaConfig {
7440 #[serde(default)]
7442 pub approval_drift: ApprovalDriftSchemaConfig,
7443
7444 #[serde(default)]
7446 pub error_drift: ErrorDriftSchemaConfig,
7447}
7448
7449#[derive(Debug, Clone, Serialize, Deserialize)]
7451pub struct ApprovalDriftSchemaConfig {
7452 #[serde(default = "default_eom_intensity")]
7454 pub eom_intensity_increase_per_year: f64,
7455
7456 #[serde(default = "default_rubber_stamp")]
7458 pub rubber_stamp_volume_threshold: u32,
7459}
7460
7461fn default_eom_intensity() -> f64 {
7462 0.05
7463}
7464
7465fn default_rubber_stamp() -> u32 {
7466 50
7467}
7468
7469impl Default for ApprovalDriftSchemaConfig {
7470 fn default() -> Self {
7471 Self {
7472 eom_intensity_increase_per_year: 0.05,
7473 rubber_stamp_volume_threshold: 50,
7474 }
7475 }
7476}
7477
7478#[derive(Debug, Clone, Serialize, Deserialize)]
7480pub struct ErrorDriftSchemaConfig {
7481 #[serde(default = "default_new_error")]
7483 pub new_employee_error_rate: f64,
7484
7485 #[serde(default = "default_learning_months")]
7487 pub learning_curve_months: u32,
7488}
7489
7490fn default_new_error() -> f64 {
7491 0.08
7492}
7493
7494fn default_learning_months() -> u32 {
7495 6
7496}
7497
7498impl Default for ErrorDriftSchemaConfig {
7499 fn default() -> Self {
7500 Self {
7501 new_employee_error_rate: 0.08,
7502 learning_curve_months: 6,
7503 }
7504 }
7505}
7506
7507#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7509pub struct CollectiveBehaviorSchemaConfig {
7510 #[serde(default)]
7512 pub automation_adoption: AutomationAdoptionSchemaConfig,
7513}
7514
7515#[derive(Debug, Clone, Serialize, Deserialize)]
7517pub struct AutomationAdoptionSchemaConfig {
7518 #[serde(default)]
7520 pub s_curve_enabled: bool,
7521
7522 #[serde(default = "default_midpoint")]
7524 pub adoption_midpoint_months: u32,
7525
7526 #[serde(default = "default_steepness")]
7528 pub steepness: f64,
7529}
7530
7531fn default_midpoint() -> u32 {
7532 24
7533}
7534
7535fn default_steepness() -> f64 {
7536 0.15
7537}
7538
7539impl Default for AutomationAdoptionSchemaConfig {
7540 fn default() -> Self {
7541 Self {
7542 s_curve_enabled: false,
7543 adoption_midpoint_months: 24,
7544 steepness: 0.15,
7545 }
7546 }
7547}
7548
7549#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7555pub struct MarketDriftSchemaConfig {
7556 #[serde(default)]
7558 pub enabled: bool,
7559
7560 #[serde(default)]
7562 pub economic_cycle: MarketEconomicCycleSchemaConfig,
7563
7564 #[serde(default)]
7566 pub industry_cycles: std::collections::HashMap<String, IndustryCycleSchemaConfig>,
7567
7568 #[serde(default)]
7570 pub commodities: CommoditiesSchemaConfig,
7571}
7572
7573#[derive(Debug, Clone, Serialize, Deserialize)]
7575pub struct MarketEconomicCycleSchemaConfig {
7576 #[serde(default)]
7578 pub enabled: bool,
7579
7580 #[serde(default)]
7582 pub cycle_type: CycleTypeSchemaConfig,
7583
7584 #[serde(default = "default_market_cycle_period")]
7586 pub period_months: u32,
7587
7588 #[serde(default = "default_market_amplitude")]
7590 pub amplitude: f64,
7591
7592 #[serde(default)]
7594 pub recession: RecessionSchemaConfig,
7595}
7596
7597fn default_market_cycle_period() -> u32 {
7598 48
7599}
7600
7601fn default_market_amplitude() -> f64 {
7602 0.15
7603}
7604
7605impl Default for MarketEconomicCycleSchemaConfig {
7606 fn default() -> Self {
7607 Self {
7608 enabled: false,
7609 cycle_type: CycleTypeSchemaConfig::Sinusoidal,
7610 period_months: 48,
7611 amplitude: 0.15,
7612 recession: RecessionSchemaConfig::default(),
7613 }
7614 }
7615}
7616
7617#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
7619#[serde(rename_all = "snake_case")]
7620pub enum CycleTypeSchemaConfig {
7621 #[default]
7623 Sinusoidal,
7624 Asymmetric,
7626 MeanReverting,
7628}
7629
7630#[derive(Debug, Clone, Serialize, Deserialize)]
7632pub struct RecessionSchemaConfig {
7633 #[serde(default)]
7635 pub enabled: bool,
7636
7637 #[serde(default = "default_recession_prob")]
7639 pub probability_per_year: f64,
7640
7641 #[serde(default)]
7643 pub severity: RecessionSeveritySchemaConfig,
7644
7645 #[serde(default)]
7647 pub recession_periods: Vec<RecessionPeriodSchemaConfig>,
7648}
7649
7650fn default_recession_prob() -> f64 {
7651 0.10
7652}
7653
7654impl Default for RecessionSchemaConfig {
7655 fn default() -> Self {
7656 Self {
7657 enabled: false,
7658 probability_per_year: 0.10,
7659 severity: RecessionSeveritySchemaConfig::Moderate,
7660 recession_periods: Vec::new(),
7661 }
7662 }
7663}
7664
7665#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
7667#[serde(rename_all = "snake_case")]
7668pub enum RecessionSeveritySchemaConfig {
7669 Mild,
7671 #[default]
7673 Moderate,
7674 Severe,
7676}
7677
7678#[derive(Debug, Clone, Serialize, Deserialize)]
7680pub struct RecessionPeriodSchemaConfig {
7681 pub start_month: u32,
7683 pub duration_months: u32,
7685}
7686
7687#[derive(Debug, Clone, Serialize, Deserialize)]
7689pub struct IndustryCycleSchemaConfig {
7690 #[serde(default = "default_industry_period")]
7692 pub period_months: u32,
7693
7694 #[serde(default = "default_industry_amp")]
7696 pub amplitude: f64,
7697}
7698
7699fn default_industry_period() -> u32 {
7700 36
7701}
7702
7703fn default_industry_amp() -> f64 {
7704 0.20
7705}
7706
7707#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7709pub struct CommoditiesSchemaConfig {
7710 #[serde(default)]
7712 pub enabled: bool,
7713
7714 #[serde(default)]
7716 pub items: Vec<CommodityItemSchemaConfig>,
7717}
7718
7719#[derive(Debug, Clone, Serialize, Deserialize)]
7721pub struct CommodityItemSchemaConfig {
7722 pub name: String,
7724
7725 #[serde(default = "default_volatility")]
7727 pub volatility: f64,
7728
7729 #[serde(default)]
7731 pub cogs_pass_through: f64,
7732
7733 #[serde(default)]
7735 pub overhead_pass_through: f64,
7736}
7737
7738fn default_volatility() -> f64 {
7739 0.20
7740}
7741
7742#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7748pub struct DriftLabelingSchemaConfig {
7749 #[serde(default)]
7751 pub enabled: bool,
7752
7753 #[serde(default)]
7755 pub statistical: StatisticalDriftLabelingSchemaConfig,
7756
7757 #[serde(default)]
7759 pub categorical: CategoricalDriftLabelingSchemaConfig,
7760
7761 #[serde(default)]
7763 pub temporal: TemporalDriftLabelingSchemaConfig,
7764
7765 #[serde(default)]
7767 pub regulatory_calendar_preset: Option<String>,
7768}
7769
7770#[derive(Debug, Clone, Serialize, Deserialize)]
7772pub struct StatisticalDriftLabelingSchemaConfig {
7773 #[serde(default = "default_true_val")]
7775 pub enabled: bool,
7776
7777 #[serde(default = "default_min_magnitude")]
7779 pub min_magnitude_threshold: f64,
7780}
7781
7782fn default_min_magnitude() -> f64 {
7783 0.05
7784}
7785
7786impl Default for StatisticalDriftLabelingSchemaConfig {
7787 fn default() -> Self {
7788 Self {
7789 enabled: true,
7790 min_magnitude_threshold: 0.05,
7791 }
7792 }
7793}
7794
7795#[derive(Debug, Clone, Serialize, Deserialize)]
7797pub struct CategoricalDriftLabelingSchemaConfig {
7798 #[serde(default = "default_true_val")]
7800 pub enabled: bool,
7801}
7802
7803impl Default for CategoricalDriftLabelingSchemaConfig {
7804 fn default() -> Self {
7805 Self { enabled: true }
7806 }
7807}
7808
7809#[derive(Debug, Clone, Serialize, Deserialize)]
7811pub struct TemporalDriftLabelingSchemaConfig {
7812 #[serde(default = "default_true_val")]
7814 pub enabled: bool,
7815}
7816
7817impl Default for TemporalDriftLabelingSchemaConfig {
7818 fn default() -> Self {
7819 Self { enabled: true }
7820 }
7821}
7822
7823#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7836pub struct EnhancedAnomalyConfig {
7837 #[serde(default)]
7839 pub enabled: bool,
7840
7841 #[serde(default)]
7843 pub rates: AnomalyRateConfig,
7844
7845 #[serde(default)]
7847 pub multi_stage_schemes: MultiStageSchemeConfig,
7848
7849 #[serde(default)]
7851 pub correlated_injection: CorrelatedInjectionConfig,
7852
7853 #[serde(default)]
7855 pub near_miss: NearMissConfig,
7856
7857 #[serde(default)]
7859 pub difficulty_classification: DifficultyClassificationConfig,
7860
7861 #[serde(default)]
7863 pub context_aware: ContextAwareConfig,
7864
7865 #[serde(default)]
7867 pub labeling: EnhancedLabelingConfig,
7868}
7869
7870#[derive(Debug, Clone, Serialize, Deserialize)]
7872pub struct AnomalyRateConfig {
7873 #[serde(default = "default_total_anomaly_rate")]
7875 pub total_rate: f64,
7876
7877 #[serde(default = "default_fraud_anomaly_rate")]
7879 pub fraud_rate: f64,
7880
7881 #[serde(default = "default_error_anomaly_rate")]
7883 pub error_rate: f64,
7884
7885 #[serde(default = "default_process_anomaly_rate")]
7887 pub process_rate: f64,
7888}
7889
7890fn default_total_anomaly_rate() -> f64 {
7891 0.03
7892}
7893fn default_fraud_anomaly_rate() -> f64 {
7894 0.01
7895}
7896fn default_error_anomaly_rate() -> f64 {
7897 0.015
7898}
7899fn default_process_anomaly_rate() -> f64 {
7900 0.005
7901}
7902
7903impl Default for AnomalyRateConfig {
7904 fn default() -> Self {
7905 Self {
7906 total_rate: default_total_anomaly_rate(),
7907 fraud_rate: default_fraud_anomaly_rate(),
7908 error_rate: default_error_anomaly_rate(),
7909 process_rate: default_process_anomaly_rate(),
7910 }
7911 }
7912}
7913
7914#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7916pub struct MultiStageSchemeConfig {
7917 #[serde(default)]
7919 pub enabled: bool,
7920
7921 #[serde(default)]
7923 pub embezzlement: EmbezzlementSchemeConfig,
7924
7925 #[serde(default)]
7927 pub revenue_manipulation: RevenueManipulationSchemeConfig,
7928
7929 #[serde(default)]
7931 pub kickback: KickbackSchemeConfig,
7932}
7933
7934#[derive(Debug, Clone, Serialize, Deserialize)]
7936pub struct EmbezzlementSchemeConfig {
7937 #[serde(default = "default_embezzlement_probability")]
7939 pub probability: f64,
7940
7941 #[serde(default)]
7943 pub testing_stage: SchemeStageConfig,
7944
7945 #[serde(default)]
7947 pub escalation_stage: SchemeStageConfig,
7948
7949 #[serde(default)]
7951 pub acceleration_stage: SchemeStageConfig,
7952
7953 #[serde(default)]
7955 pub desperation_stage: SchemeStageConfig,
7956}
7957
7958fn default_embezzlement_probability() -> f64 {
7959 0.02
7960}
7961
7962impl Default for EmbezzlementSchemeConfig {
7963 fn default() -> Self {
7964 Self {
7965 probability: default_embezzlement_probability(),
7966 testing_stage: SchemeStageConfig {
7967 duration_months: 2,
7968 amount_min: 100.0,
7969 amount_max: 500.0,
7970 transaction_count_min: 2,
7971 transaction_count_max: 5,
7972 difficulty: "hard".to_string(),
7973 },
7974 escalation_stage: SchemeStageConfig {
7975 duration_months: 6,
7976 amount_min: 500.0,
7977 amount_max: 2000.0,
7978 transaction_count_min: 3,
7979 transaction_count_max: 8,
7980 difficulty: "moderate".to_string(),
7981 },
7982 acceleration_stage: SchemeStageConfig {
7983 duration_months: 3,
7984 amount_min: 2000.0,
7985 amount_max: 10000.0,
7986 transaction_count_min: 5,
7987 transaction_count_max: 12,
7988 difficulty: "easy".to_string(),
7989 },
7990 desperation_stage: SchemeStageConfig {
7991 duration_months: 1,
7992 amount_min: 10000.0,
7993 amount_max: 50000.0,
7994 transaction_count_min: 3,
7995 transaction_count_max: 6,
7996 difficulty: "trivial".to_string(),
7997 },
7998 }
7999 }
8000}
8001
8002#[derive(Debug, Clone, Serialize, Deserialize)]
8004pub struct RevenueManipulationSchemeConfig {
8005 #[serde(default = "default_revenue_manipulation_probability")]
8007 pub probability: f64,
8008
8009 #[serde(default = "default_early_recognition_target")]
8011 pub early_recognition_target: f64,
8012
8013 #[serde(default = "default_expense_deferral_target")]
8015 pub expense_deferral_target: f64,
8016
8017 #[serde(default = "default_reserve_release_target")]
8019 pub reserve_release_target: f64,
8020
8021 #[serde(default = "default_channel_stuffing_target")]
8023 pub channel_stuffing_target: f64,
8024}
8025
8026fn default_revenue_manipulation_probability() -> f64 {
8027 0.01
8028}
8029fn default_early_recognition_target() -> f64 {
8030 0.02
8031}
8032fn default_expense_deferral_target() -> f64 {
8033 0.03
8034}
8035fn default_reserve_release_target() -> f64 {
8036 0.02
8037}
8038fn default_channel_stuffing_target() -> f64 {
8039 0.05
8040}
8041
8042impl Default for RevenueManipulationSchemeConfig {
8043 fn default() -> Self {
8044 Self {
8045 probability: default_revenue_manipulation_probability(),
8046 early_recognition_target: default_early_recognition_target(),
8047 expense_deferral_target: default_expense_deferral_target(),
8048 reserve_release_target: default_reserve_release_target(),
8049 channel_stuffing_target: default_channel_stuffing_target(),
8050 }
8051 }
8052}
8053
8054#[derive(Debug, Clone, Serialize, Deserialize)]
8056pub struct KickbackSchemeConfig {
8057 #[serde(default = "default_kickback_probability")]
8059 pub probability: f64,
8060
8061 #[serde(default = "default_kickback_inflation_min")]
8063 pub inflation_min: f64,
8064
8065 #[serde(default = "default_kickback_inflation_max")]
8067 pub inflation_max: f64,
8068
8069 #[serde(default = "default_kickback_percent")]
8071 pub kickback_percent: f64,
8072
8073 #[serde(default = "default_kickback_setup_months")]
8075 pub setup_months: u32,
8076
8077 #[serde(default = "default_kickback_operation_months")]
8079 pub operation_months: u32,
8080}
8081
8082fn default_kickback_probability() -> f64 {
8083 0.01
8084}
8085fn default_kickback_inflation_min() -> f64 {
8086 0.10
8087}
8088fn default_kickback_inflation_max() -> f64 {
8089 0.25
8090}
8091fn default_kickback_percent() -> f64 {
8092 0.50
8093}
8094fn default_kickback_setup_months() -> u32 {
8095 3
8096}
8097fn default_kickback_operation_months() -> u32 {
8098 12
8099}
8100
8101impl Default for KickbackSchemeConfig {
8102 fn default() -> Self {
8103 Self {
8104 probability: default_kickback_probability(),
8105 inflation_min: default_kickback_inflation_min(),
8106 inflation_max: default_kickback_inflation_max(),
8107 kickback_percent: default_kickback_percent(),
8108 setup_months: default_kickback_setup_months(),
8109 operation_months: default_kickback_operation_months(),
8110 }
8111 }
8112}
8113
8114#[derive(Debug, Clone, Serialize, Deserialize)]
8116pub struct SchemeStageConfig {
8117 pub duration_months: u32,
8119
8120 pub amount_min: f64,
8122
8123 pub amount_max: f64,
8125
8126 pub transaction_count_min: u32,
8128
8129 pub transaction_count_max: u32,
8131
8132 pub difficulty: String,
8134}
8135
8136impl Default for SchemeStageConfig {
8137 fn default() -> Self {
8138 Self {
8139 duration_months: 3,
8140 amount_min: 100.0,
8141 amount_max: 1000.0,
8142 transaction_count_min: 2,
8143 transaction_count_max: 10,
8144 difficulty: "moderate".to_string(),
8145 }
8146 }
8147}
8148
8149#[derive(Debug, Clone, Serialize, Deserialize)]
8151pub struct CorrelatedInjectionConfig {
8152 #[serde(default)]
8154 pub enabled: bool,
8155
8156 #[serde(default = "default_true_val")]
8158 pub fraud_concealment: bool,
8159
8160 #[serde(default = "default_true_val")]
8162 pub error_cascade: bool,
8163
8164 #[serde(default = "default_true_val")]
8166 pub temporal_clustering: bool,
8167
8168 #[serde(default)]
8170 pub temporal_clustering_config: TemporalClusteringConfig,
8171
8172 #[serde(default)]
8174 pub co_occurrence_patterns: Vec<CoOccurrencePatternConfig>,
8175}
8176
8177impl Default for CorrelatedInjectionConfig {
8178 fn default() -> Self {
8179 Self {
8180 enabled: false,
8181 fraud_concealment: true,
8182 error_cascade: true,
8183 temporal_clustering: true,
8184 temporal_clustering_config: TemporalClusteringConfig::default(),
8185 co_occurrence_patterns: Vec::new(),
8186 }
8187 }
8188}
8189
8190#[derive(Debug, Clone, Serialize, Deserialize)]
8192pub struct TemporalClusteringConfig {
8193 #[serde(default = "default_period_end_multiplier")]
8195 pub period_end_multiplier: f64,
8196
8197 #[serde(default = "default_period_end_days")]
8199 pub period_end_days: u32,
8200
8201 #[serde(default = "default_quarter_end_multiplier")]
8203 pub quarter_end_multiplier: f64,
8204
8205 #[serde(default = "default_year_end_multiplier")]
8207 pub year_end_multiplier: f64,
8208}
8209
8210fn default_period_end_multiplier() -> f64 {
8211 2.5
8212}
8213fn default_period_end_days() -> u32 {
8214 5
8215}
8216fn default_quarter_end_multiplier() -> f64 {
8217 1.5
8218}
8219fn default_year_end_multiplier() -> f64 {
8220 2.0
8221}
8222
8223impl Default for TemporalClusteringConfig {
8224 fn default() -> Self {
8225 Self {
8226 period_end_multiplier: default_period_end_multiplier(),
8227 period_end_days: default_period_end_days(),
8228 quarter_end_multiplier: default_quarter_end_multiplier(),
8229 year_end_multiplier: default_year_end_multiplier(),
8230 }
8231 }
8232}
8233
8234#[derive(Debug, Clone, Serialize, Deserialize)]
8236pub struct CoOccurrencePatternConfig {
8237 pub name: String,
8239
8240 pub primary_type: String,
8242
8243 pub correlated: Vec<CorrelatedAnomalyConfig>,
8245}
8246
8247#[derive(Debug, Clone, Serialize, Deserialize)]
8249pub struct CorrelatedAnomalyConfig {
8250 pub anomaly_type: String,
8252
8253 pub probability: f64,
8255
8256 pub lag_days_min: i32,
8258
8259 pub lag_days_max: i32,
8261}
8262
8263#[derive(Debug, Clone, Serialize, Deserialize)]
8265pub struct NearMissConfig {
8266 #[serde(default)]
8268 pub enabled: bool,
8269
8270 #[serde(default = "default_near_miss_proportion")]
8272 pub proportion: f64,
8273
8274 #[serde(default = "default_true_val")]
8276 pub near_duplicate: bool,
8277
8278 #[serde(default)]
8280 pub near_duplicate_days: NearDuplicateDaysConfig,
8281
8282 #[serde(default = "default_true_val")]
8284 pub threshold_proximity: bool,
8285
8286 #[serde(default)]
8288 pub threshold_proximity_range: ThresholdProximityRangeConfig,
8289
8290 #[serde(default = "default_true_val")]
8292 pub unusual_legitimate: bool,
8293
8294 #[serde(default = "default_unusual_legitimate_types")]
8296 pub unusual_legitimate_types: Vec<String>,
8297
8298 #[serde(default = "default_true_val")]
8300 pub corrected_errors: bool,
8301
8302 #[serde(default)]
8304 pub corrected_error_lag: CorrectedErrorLagConfig,
8305}
8306
8307fn default_near_miss_proportion() -> f64 {
8308 0.30
8309}
8310
8311fn default_unusual_legitimate_types() -> Vec<String> {
8312 vec![
8313 "year_end_bonus".to_string(),
8314 "contract_prepayment".to_string(),
8315 "insurance_claim".to_string(),
8316 "settlement_payment".to_string(),
8317 ]
8318}
8319
8320impl Default for NearMissConfig {
8321 fn default() -> Self {
8322 Self {
8323 enabled: false,
8324 proportion: default_near_miss_proportion(),
8325 near_duplicate: true,
8326 near_duplicate_days: NearDuplicateDaysConfig::default(),
8327 threshold_proximity: true,
8328 threshold_proximity_range: ThresholdProximityRangeConfig::default(),
8329 unusual_legitimate: true,
8330 unusual_legitimate_types: default_unusual_legitimate_types(),
8331 corrected_errors: true,
8332 corrected_error_lag: CorrectedErrorLagConfig::default(),
8333 }
8334 }
8335}
8336
8337#[derive(Debug, Clone, Serialize, Deserialize)]
8339pub struct NearDuplicateDaysConfig {
8340 #[serde(default = "default_near_duplicate_min")]
8342 pub min: u32,
8343
8344 #[serde(default = "default_near_duplicate_max")]
8346 pub max: u32,
8347}
8348
8349fn default_near_duplicate_min() -> u32 {
8350 1
8351}
8352fn default_near_duplicate_max() -> u32 {
8353 3
8354}
8355
8356impl Default for NearDuplicateDaysConfig {
8357 fn default() -> Self {
8358 Self {
8359 min: default_near_duplicate_min(),
8360 max: default_near_duplicate_max(),
8361 }
8362 }
8363}
8364
8365#[derive(Debug, Clone, Serialize, Deserialize)]
8367pub struct ThresholdProximityRangeConfig {
8368 #[serde(default = "default_threshold_proximity_min")]
8370 pub min: f64,
8371
8372 #[serde(default = "default_threshold_proximity_max")]
8374 pub max: f64,
8375}
8376
8377fn default_threshold_proximity_min() -> f64 {
8378 0.90
8379}
8380fn default_threshold_proximity_max() -> f64 {
8381 0.99
8382}
8383
8384impl Default for ThresholdProximityRangeConfig {
8385 fn default() -> Self {
8386 Self {
8387 min: default_threshold_proximity_min(),
8388 max: default_threshold_proximity_max(),
8389 }
8390 }
8391}
8392
8393#[derive(Debug, Clone, Serialize, Deserialize)]
8395pub struct CorrectedErrorLagConfig {
8396 #[serde(default = "default_corrected_error_lag_min")]
8398 pub min: u32,
8399
8400 #[serde(default = "default_corrected_error_lag_max")]
8402 pub max: u32,
8403}
8404
8405fn default_corrected_error_lag_min() -> u32 {
8406 1
8407}
8408fn default_corrected_error_lag_max() -> u32 {
8409 5
8410}
8411
8412impl Default for CorrectedErrorLagConfig {
8413 fn default() -> Self {
8414 Self {
8415 min: default_corrected_error_lag_min(),
8416 max: default_corrected_error_lag_max(),
8417 }
8418 }
8419}
8420
8421#[derive(Debug, Clone, Serialize, Deserialize)]
8423pub struct DifficultyClassificationConfig {
8424 #[serde(default)]
8426 pub enabled: bool,
8427
8428 #[serde(default)]
8430 pub target_distribution: DifficultyDistributionConfig,
8431}
8432
8433impl Default for DifficultyClassificationConfig {
8434 fn default() -> Self {
8435 Self {
8436 enabled: true,
8437 target_distribution: DifficultyDistributionConfig::default(),
8438 }
8439 }
8440}
8441
8442#[derive(Debug, Clone, Serialize, Deserialize)]
8444pub struct DifficultyDistributionConfig {
8445 #[serde(default = "default_difficulty_trivial")]
8447 pub trivial: f64,
8448
8449 #[serde(default = "default_difficulty_easy")]
8451 pub easy: f64,
8452
8453 #[serde(default = "default_difficulty_moderate")]
8455 pub moderate: f64,
8456
8457 #[serde(default = "default_difficulty_hard")]
8459 pub hard: f64,
8460
8461 #[serde(default = "default_difficulty_expert")]
8463 pub expert: f64,
8464}
8465
8466fn default_difficulty_trivial() -> f64 {
8467 0.15
8468}
8469fn default_difficulty_easy() -> f64 {
8470 0.25
8471}
8472fn default_difficulty_moderate() -> f64 {
8473 0.30
8474}
8475fn default_difficulty_hard() -> f64 {
8476 0.20
8477}
8478fn default_difficulty_expert() -> f64 {
8479 0.10
8480}
8481
8482impl Default for DifficultyDistributionConfig {
8483 fn default() -> Self {
8484 Self {
8485 trivial: default_difficulty_trivial(),
8486 easy: default_difficulty_easy(),
8487 moderate: default_difficulty_moderate(),
8488 hard: default_difficulty_hard(),
8489 expert: default_difficulty_expert(),
8490 }
8491 }
8492}
8493
8494#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8496pub struct ContextAwareConfig {
8497 #[serde(default)]
8499 pub enabled: bool,
8500
8501 #[serde(default)]
8503 pub vendor_rules: VendorAnomalyRulesConfig,
8504
8505 #[serde(default)]
8507 pub employee_rules: EmployeeAnomalyRulesConfig,
8508
8509 #[serde(default)]
8511 pub account_rules: AccountAnomalyRulesConfig,
8512
8513 #[serde(default)]
8515 pub behavioral_baseline: BehavioralBaselineConfig,
8516}
8517
8518#[derive(Debug, Clone, Serialize, Deserialize)]
8520pub struct VendorAnomalyRulesConfig {
8521 #[serde(default = "default_new_vendor_multiplier")]
8523 pub new_vendor_error_multiplier: f64,
8524
8525 #[serde(default = "default_new_vendor_threshold")]
8527 pub new_vendor_threshold_days: u32,
8528
8529 #[serde(default = "default_international_multiplier")]
8531 pub international_error_multiplier: f64,
8532
8533 #[serde(default = "default_strategic_vendor_types")]
8535 pub strategic_vendor_anomaly_types: Vec<String>,
8536}
8537
8538fn default_new_vendor_multiplier() -> f64 {
8539 2.5
8540}
8541fn default_new_vendor_threshold() -> u32 {
8542 90
8543}
8544fn default_international_multiplier() -> f64 {
8545 1.5
8546}
8547fn default_strategic_vendor_types() -> Vec<String> {
8548 vec![
8549 "pricing_dispute".to_string(),
8550 "contract_violation".to_string(),
8551 ]
8552}
8553
8554impl Default for VendorAnomalyRulesConfig {
8555 fn default() -> Self {
8556 Self {
8557 new_vendor_error_multiplier: default_new_vendor_multiplier(),
8558 new_vendor_threshold_days: default_new_vendor_threshold(),
8559 international_error_multiplier: default_international_multiplier(),
8560 strategic_vendor_anomaly_types: default_strategic_vendor_types(),
8561 }
8562 }
8563}
8564
8565#[derive(Debug, Clone, Serialize, Deserialize)]
8567pub struct EmployeeAnomalyRulesConfig {
8568 #[serde(default = "default_new_employee_rate")]
8570 pub new_employee_error_rate: f64,
8571
8572 #[serde(default = "default_new_employee_threshold")]
8574 pub new_employee_threshold_days: u32,
8575
8576 #[serde(default = "default_volume_fatigue_threshold")]
8578 pub volume_fatigue_threshold: u32,
8579
8580 #[serde(default = "default_coverage_multiplier")]
8582 pub coverage_error_multiplier: f64,
8583}
8584
8585fn default_new_employee_rate() -> f64 {
8586 0.05
8587}
8588fn default_new_employee_threshold() -> u32 {
8589 180
8590}
8591fn default_volume_fatigue_threshold() -> u32 {
8592 50
8593}
8594fn default_coverage_multiplier() -> f64 {
8595 1.8
8596}
8597
8598impl Default for EmployeeAnomalyRulesConfig {
8599 fn default() -> Self {
8600 Self {
8601 new_employee_error_rate: default_new_employee_rate(),
8602 new_employee_threshold_days: default_new_employee_threshold(),
8603 volume_fatigue_threshold: default_volume_fatigue_threshold(),
8604 coverage_error_multiplier: default_coverage_multiplier(),
8605 }
8606 }
8607}
8608
8609#[derive(Debug, Clone, Serialize, Deserialize)]
8611pub struct AccountAnomalyRulesConfig {
8612 #[serde(default = "default_high_risk_multiplier")]
8614 pub high_risk_account_multiplier: f64,
8615
8616 #[serde(default = "default_high_risk_accounts")]
8618 pub high_risk_accounts: Vec<String>,
8619
8620 #[serde(default = "default_suspense_multiplier")]
8622 pub suspense_account_multiplier: f64,
8623
8624 #[serde(default = "default_suspense_accounts")]
8626 pub suspense_accounts: Vec<String>,
8627
8628 #[serde(default = "default_intercompany_multiplier")]
8630 pub intercompany_account_multiplier: f64,
8631}
8632
8633fn default_high_risk_multiplier() -> f64 {
8634 2.0
8635}
8636fn default_high_risk_accounts() -> Vec<String> {
8637 vec![
8638 "1100".to_string(), "2000".to_string(), "3000".to_string(), ]
8642}
8643fn default_suspense_multiplier() -> f64 {
8644 3.0
8645}
8646fn default_suspense_accounts() -> Vec<String> {
8647 vec!["9999".to_string(), "9998".to_string()]
8648}
8649fn default_intercompany_multiplier() -> f64 {
8650 1.5
8651}
8652
8653impl Default for AccountAnomalyRulesConfig {
8654 fn default() -> Self {
8655 Self {
8656 high_risk_account_multiplier: default_high_risk_multiplier(),
8657 high_risk_accounts: default_high_risk_accounts(),
8658 suspense_account_multiplier: default_suspense_multiplier(),
8659 suspense_accounts: default_suspense_accounts(),
8660 intercompany_account_multiplier: default_intercompany_multiplier(),
8661 }
8662 }
8663}
8664
8665#[derive(Debug, Clone, Serialize, Deserialize)]
8667pub struct BehavioralBaselineConfig {
8668 #[serde(default)]
8670 pub enabled: bool,
8671
8672 #[serde(default = "default_baseline_period")]
8674 pub baseline_period_days: u32,
8675
8676 #[serde(default = "default_deviation_threshold")]
8678 pub deviation_threshold_std: f64,
8679
8680 #[serde(default = "default_frequency_deviation")]
8682 pub frequency_deviation_threshold: f64,
8683}
8684
8685fn default_baseline_period() -> u32 {
8686 90
8687}
8688fn default_deviation_threshold() -> f64 {
8689 3.0
8690}
8691fn default_frequency_deviation() -> f64 {
8692 2.0
8693}
8694
8695impl Default for BehavioralBaselineConfig {
8696 fn default() -> Self {
8697 Self {
8698 enabled: false,
8699 baseline_period_days: default_baseline_period(),
8700 deviation_threshold_std: default_deviation_threshold(),
8701 frequency_deviation_threshold: default_frequency_deviation(),
8702 }
8703 }
8704}
8705
8706#[derive(Debug, Clone, Serialize, Deserialize)]
8708pub struct EnhancedLabelingConfig {
8709 #[serde(default = "default_true_val")]
8711 pub severity_scoring: bool,
8712
8713 #[serde(default = "default_true_val")]
8715 pub difficulty_classification: bool,
8716
8717 #[serde(default)]
8719 pub materiality_thresholds: MaterialityThresholdsConfig,
8720}
8721
8722impl Default for EnhancedLabelingConfig {
8723 fn default() -> Self {
8724 Self {
8725 severity_scoring: true,
8726 difficulty_classification: true,
8727 materiality_thresholds: MaterialityThresholdsConfig::default(),
8728 }
8729 }
8730}
8731
8732#[derive(Debug, Clone, Serialize, Deserialize)]
8734pub struct MaterialityThresholdsConfig {
8735 #[serde(default = "default_materiality_trivial")]
8737 pub trivial: f64,
8738
8739 #[serde(default = "default_materiality_immaterial")]
8741 pub immaterial: f64,
8742
8743 #[serde(default = "default_materiality_material")]
8745 pub material: f64,
8746
8747 #[serde(default = "default_materiality_highly_material")]
8749 pub highly_material: f64,
8750}
8751
8752fn default_materiality_trivial() -> f64 {
8753 0.001
8754}
8755fn default_materiality_immaterial() -> f64 {
8756 0.01
8757}
8758fn default_materiality_material() -> f64 {
8759 0.05
8760}
8761fn default_materiality_highly_material() -> f64 {
8762 0.10
8763}
8764
8765impl Default for MaterialityThresholdsConfig {
8766 fn default() -> Self {
8767 Self {
8768 trivial: default_materiality_trivial(),
8769 immaterial: default_materiality_immaterial(),
8770 material: default_materiality_material(),
8771 highly_material: default_materiality_highly_material(),
8772 }
8773 }
8774}
8775
8776#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8788pub struct IndustrySpecificConfig {
8789 #[serde(default)]
8791 pub enabled: bool,
8792
8793 #[serde(default)]
8795 pub manufacturing: ManufacturingConfig,
8796
8797 #[serde(default)]
8799 pub retail: RetailConfig,
8800
8801 #[serde(default)]
8803 pub healthcare: HealthcareConfig,
8804
8805 #[serde(default)]
8807 pub technology: TechnologyConfig,
8808
8809 #[serde(default)]
8811 pub financial_services: FinancialServicesConfig,
8812
8813 #[serde(default)]
8815 pub professional_services: ProfessionalServicesConfig,
8816}
8817
8818#[derive(Debug, Clone, Serialize, Deserialize)]
8820pub struct ManufacturingConfig {
8821 #[serde(default)]
8823 pub enabled: bool,
8824
8825 #[serde(default = "default_bom_depth")]
8827 pub bom_depth: u32,
8828
8829 #[serde(default)]
8831 pub just_in_time: bool,
8832
8833 #[serde(default = "default_production_order_types")]
8835 pub production_order_types: Vec<String>,
8836
8837 #[serde(default)]
8839 pub quality_framework: Option<String>,
8840
8841 #[serde(default = "default_supplier_tiers")]
8843 pub supplier_tiers: u32,
8844
8845 #[serde(default = "default_cost_frequency")]
8847 pub standard_cost_frequency: String,
8848
8849 #[serde(default = "default_yield_rate")]
8851 pub target_yield_rate: f64,
8852
8853 #[serde(default = "default_scrap_threshold")]
8855 pub scrap_alert_threshold: f64,
8856
8857 #[serde(default)]
8859 pub anomaly_rates: ManufacturingAnomalyRates,
8860}
8861
8862fn default_bom_depth() -> u32 {
8863 4
8864}
8865
8866fn default_production_order_types() -> Vec<String> {
8867 vec![
8868 "standard".to_string(),
8869 "rework".to_string(),
8870 "prototype".to_string(),
8871 ]
8872}
8873
8874fn default_supplier_tiers() -> u32 {
8875 2
8876}
8877
8878fn default_cost_frequency() -> String {
8879 "quarterly".to_string()
8880}
8881
8882fn default_yield_rate() -> f64 {
8883 0.97
8884}
8885
8886fn default_scrap_threshold() -> f64 {
8887 0.03
8888}
8889
8890impl Default for ManufacturingConfig {
8891 fn default() -> Self {
8892 Self {
8893 enabled: false,
8894 bom_depth: default_bom_depth(),
8895 just_in_time: false,
8896 production_order_types: default_production_order_types(),
8897 quality_framework: Some("ISO_9001".to_string()),
8898 supplier_tiers: default_supplier_tiers(),
8899 standard_cost_frequency: default_cost_frequency(),
8900 target_yield_rate: default_yield_rate(),
8901 scrap_alert_threshold: default_scrap_threshold(),
8902 anomaly_rates: ManufacturingAnomalyRates::default(),
8903 }
8904 }
8905}
8906
8907#[derive(Debug, Clone, Serialize, Deserialize)]
8909pub struct ManufacturingAnomalyRates {
8910 #[serde(default = "default_mfg_yield_rate")]
8912 pub yield_manipulation: f64,
8913
8914 #[serde(default = "default_mfg_labor_rate")]
8916 pub labor_misallocation: f64,
8917
8918 #[serde(default = "default_mfg_phantom_rate")]
8920 pub phantom_production: f64,
8921
8922 #[serde(default = "default_mfg_cost_rate")]
8924 pub standard_cost_manipulation: f64,
8925
8926 #[serde(default = "default_mfg_inventory_rate")]
8928 pub inventory_fraud: f64,
8929}
8930
8931fn default_mfg_yield_rate() -> f64 {
8932 0.015
8933}
8934
8935fn default_mfg_labor_rate() -> f64 {
8936 0.02
8937}
8938
8939fn default_mfg_phantom_rate() -> f64 {
8940 0.005
8941}
8942
8943fn default_mfg_cost_rate() -> f64 {
8944 0.01
8945}
8946
8947fn default_mfg_inventory_rate() -> f64 {
8948 0.008
8949}
8950
8951impl Default for ManufacturingAnomalyRates {
8952 fn default() -> Self {
8953 Self {
8954 yield_manipulation: default_mfg_yield_rate(),
8955 labor_misallocation: default_mfg_labor_rate(),
8956 phantom_production: default_mfg_phantom_rate(),
8957 standard_cost_manipulation: default_mfg_cost_rate(),
8958 inventory_fraud: default_mfg_inventory_rate(),
8959 }
8960 }
8961}
8962
8963#[derive(Debug, Clone, Serialize, Deserialize)]
8965pub struct RetailConfig {
8966 #[serde(default)]
8968 pub enabled: bool,
8969
8970 #[serde(default)]
8972 pub store_types: RetailStoreTypeConfig,
8973
8974 #[serde(default = "default_retail_daily_txns")]
8976 pub avg_daily_transactions: u32,
8977
8978 #[serde(default = "default_true")]
8980 pub loss_prevention: bool,
8981
8982 #[serde(default = "default_shrinkage_rate")]
8984 pub shrinkage_rate: f64,
8985
8986 #[serde(default)]
8988 pub anomaly_rates: RetailAnomalyRates,
8989}
8990
8991fn default_retail_daily_txns() -> u32 {
8992 500
8993}
8994
8995fn default_shrinkage_rate() -> f64 {
8996 0.015
8997}
8998
8999impl Default for RetailConfig {
9000 fn default() -> Self {
9001 Self {
9002 enabled: false,
9003 store_types: RetailStoreTypeConfig::default(),
9004 avg_daily_transactions: default_retail_daily_txns(),
9005 loss_prevention: true,
9006 shrinkage_rate: default_shrinkage_rate(),
9007 anomaly_rates: RetailAnomalyRates::default(),
9008 }
9009 }
9010}
9011
9012#[derive(Debug, Clone, Serialize, Deserialize)]
9014pub struct RetailStoreTypeConfig {
9015 #[serde(default = "default_flagship_pct")]
9017 pub flagship: f64,
9018
9019 #[serde(default = "default_regional_pct")]
9021 pub regional: f64,
9022
9023 #[serde(default = "default_outlet_pct")]
9025 pub outlet: f64,
9026
9027 #[serde(default = "default_ecommerce_pct")]
9029 pub ecommerce: f64,
9030}
9031
9032fn default_flagship_pct() -> f64 {
9033 0.10
9034}
9035
9036fn default_regional_pct() -> f64 {
9037 0.50
9038}
9039
9040fn default_outlet_pct() -> f64 {
9041 0.25
9042}
9043
9044fn default_ecommerce_pct() -> f64 {
9045 0.15
9046}
9047
9048impl Default for RetailStoreTypeConfig {
9049 fn default() -> Self {
9050 Self {
9051 flagship: default_flagship_pct(),
9052 regional: default_regional_pct(),
9053 outlet: default_outlet_pct(),
9054 ecommerce: default_ecommerce_pct(),
9055 }
9056 }
9057}
9058
9059#[derive(Debug, Clone, Serialize, Deserialize)]
9061pub struct RetailAnomalyRates {
9062 #[serde(default = "default_sweethearting_rate")]
9064 pub sweethearting: f64,
9065
9066 #[serde(default = "default_skimming_rate")]
9068 pub skimming: f64,
9069
9070 #[serde(default = "default_refund_fraud_rate")]
9072 pub refund_fraud: f64,
9073
9074 #[serde(default = "default_void_abuse_rate")]
9076 pub void_abuse: f64,
9077
9078 #[serde(default = "default_gift_card_rate")]
9080 pub gift_card_fraud: f64,
9081
9082 #[serde(default = "default_retail_kickback_rate")]
9084 pub vendor_kickback: f64,
9085}
9086
9087fn default_sweethearting_rate() -> f64 {
9088 0.02
9089}
9090
9091fn default_skimming_rate() -> f64 {
9092 0.005
9093}
9094
9095fn default_refund_fraud_rate() -> f64 {
9096 0.015
9097}
9098
9099fn default_void_abuse_rate() -> f64 {
9100 0.01
9101}
9102
9103fn default_gift_card_rate() -> f64 {
9104 0.008
9105}
9106
9107fn default_retail_kickback_rate() -> f64 {
9108 0.003
9109}
9110
9111impl Default for RetailAnomalyRates {
9112 fn default() -> Self {
9113 Self {
9114 sweethearting: default_sweethearting_rate(),
9115 skimming: default_skimming_rate(),
9116 refund_fraud: default_refund_fraud_rate(),
9117 void_abuse: default_void_abuse_rate(),
9118 gift_card_fraud: default_gift_card_rate(),
9119 vendor_kickback: default_retail_kickback_rate(),
9120 }
9121 }
9122}
9123
9124#[derive(Debug, Clone, Serialize, Deserialize)]
9126pub struct HealthcareConfig {
9127 #[serde(default)]
9129 pub enabled: bool,
9130
9131 #[serde(default = "default_facility_type")]
9133 pub facility_type: String,
9134
9135 #[serde(default)]
9137 pub payer_mix: HealthcarePayerMix,
9138
9139 #[serde(default)]
9141 pub coding_systems: HealthcareCodingSystems,
9142
9143 #[serde(default)]
9145 pub compliance: HealthcareComplianceConfig,
9146
9147 #[serde(default = "default_daily_encounters")]
9149 pub avg_daily_encounters: u32,
9150
9151 #[serde(default = "default_charges_per_encounter")]
9153 pub avg_charges_per_encounter: u32,
9154
9155 #[serde(default = "default_hc_denial_rate")]
9157 pub denial_rate: f64,
9158
9159 #[serde(default = "default_hc_bad_debt_rate")]
9161 pub bad_debt_rate: f64,
9162
9163 #[serde(default = "default_hc_charity_care_rate")]
9165 pub charity_care_rate: f64,
9166
9167 #[serde(default)]
9169 pub anomaly_rates: HealthcareAnomalyRates,
9170}
9171
9172fn default_facility_type() -> String {
9173 "hospital".to_string()
9174}
9175
9176fn default_daily_encounters() -> u32 {
9177 150
9178}
9179
9180fn default_charges_per_encounter() -> u32 {
9181 8
9182}
9183
9184fn default_hc_denial_rate() -> f64 {
9185 0.05
9186}
9187
9188fn default_hc_bad_debt_rate() -> f64 {
9189 0.03
9190}
9191
9192fn default_hc_charity_care_rate() -> f64 {
9193 0.02
9194}
9195
9196impl Default for HealthcareConfig {
9197 fn default() -> Self {
9198 Self {
9199 enabled: false,
9200 facility_type: default_facility_type(),
9201 payer_mix: HealthcarePayerMix::default(),
9202 coding_systems: HealthcareCodingSystems::default(),
9203 compliance: HealthcareComplianceConfig::default(),
9204 avg_daily_encounters: default_daily_encounters(),
9205 avg_charges_per_encounter: default_charges_per_encounter(),
9206 denial_rate: default_hc_denial_rate(),
9207 bad_debt_rate: default_hc_bad_debt_rate(),
9208 charity_care_rate: default_hc_charity_care_rate(),
9209 anomaly_rates: HealthcareAnomalyRates::default(),
9210 }
9211 }
9212}
9213
9214#[derive(Debug, Clone, Serialize, Deserialize)]
9216pub struct HealthcarePayerMix {
9217 #[serde(default = "default_medicare_pct")]
9219 pub medicare: f64,
9220
9221 #[serde(default = "default_medicaid_pct")]
9223 pub medicaid: f64,
9224
9225 #[serde(default = "default_commercial_pct")]
9227 pub commercial: f64,
9228
9229 #[serde(default = "default_self_pay_pct")]
9231 pub self_pay: f64,
9232}
9233
9234fn default_medicare_pct() -> f64 {
9235 0.40
9236}
9237
9238fn default_medicaid_pct() -> f64 {
9239 0.20
9240}
9241
9242fn default_commercial_pct() -> f64 {
9243 0.30
9244}
9245
9246fn default_self_pay_pct() -> f64 {
9247 0.10
9248}
9249
9250impl Default for HealthcarePayerMix {
9251 fn default() -> Self {
9252 Self {
9253 medicare: default_medicare_pct(),
9254 medicaid: default_medicaid_pct(),
9255 commercial: default_commercial_pct(),
9256 self_pay: default_self_pay_pct(),
9257 }
9258 }
9259}
9260
9261#[derive(Debug, Clone, Serialize, Deserialize)]
9263pub struct HealthcareCodingSystems {
9264 #[serde(default = "default_true")]
9266 pub icd10: bool,
9267
9268 #[serde(default = "default_true")]
9270 pub cpt: bool,
9271
9272 #[serde(default = "default_true")]
9274 pub drg: bool,
9275
9276 #[serde(default = "default_true")]
9278 pub hcpcs: bool,
9279
9280 #[serde(default = "default_true")]
9282 pub revenue_codes: bool,
9283}
9284
9285impl Default for HealthcareCodingSystems {
9286 fn default() -> Self {
9287 Self {
9288 icd10: true,
9289 cpt: true,
9290 drg: true,
9291 hcpcs: true,
9292 revenue_codes: true,
9293 }
9294 }
9295}
9296
9297#[derive(Debug, Clone, Serialize, Deserialize)]
9299pub struct HealthcareComplianceConfig {
9300 #[serde(default = "default_true")]
9302 pub hipaa: bool,
9303
9304 #[serde(default = "default_true")]
9306 pub stark_law: bool,
9307
9308 #[serde(default = "default_true")]
9310 pub anti_kickback: bool,
9311
9312 #[serde(default = "default_true")]
9314 pub false_claims_act: bool,
9315
9316 #[serde(default = "default_true")]
9318 pub emtala: bool,
9319}
9320
9321impl Default for HealthcareComplianceConfig {
9322 fn default() -> Self {
9323 Self {
9324 hipaa: true,
9325 stark_law: true,
9326 anti_kickback: true,
9327 false_claims_act: true,
9328 emtala: true,
9329 }
9330 }
9331}
9332
9333#[derive(Debug, Clone, Serialize, Deserialize)]
9335pub struct HealthcareAnomalyRates {
9336 #[serde(default = "default_upcoding_rate")]
9338 pub upcoding: f64,
9339
9340 #[serde(default = "default_unbundling_rate")]
9342 pub unbundling: f64,
9343
9344 #[serde(default = "default_phantom_billing_rate")]
9346 pub phantom_billing: f64,
9347
9348 #[serde(default = "default_healthcare_kickback_rate")]
9350 pub kickbacks: f64,
9351
9352 #[serde(default = "default_duplicate_billing_rate")]
9354 pub duplicate_billing: f64,
9355
9356 #[serde(default = "default_med_necessity_rate")]
9358 pub medical_necessity_abuse: f64,
9359}
9360
9361fn default_upcoding_rate() -> f64 {
9362 0.02
9363}
9364
9365fn default_unbundling_rate() -> f64 {
9366 0.015
9367}
9368
9369fn default_phantom_billing_rate() -> f64 {
9370 0.005
9371}
9372
9373fn default_healthcare_kickback_rate() -> f64 {
9374 0.003
9375}
9376
9377fn default_duplicate_billing_rate() -> f64 {
9378 0.008
9379}
9380
9381fn default_med_necessity_rate() -> f64 {
9382 0.01
9383}
9384
9385impl Default for HealthcareAnomalyRates {
9386 fn default() -> Self {
9387 Self {
9388 upcoding: default_upcoding_rate(),
9389 unbundling: default_unbundling_rate(),
9390 phantom_billing: default_phantom_billing_rate(),
9391 kickbacks: default_healthcare_kickback_rate(),
9392 duplicate_billing: default_duplicate_billing_rate(),
9393 medical_necessity_abuse: default_med_necessity_rate(),
9394 }
9395 }
9396}
9397
9398#[derive(Debug, Clone, Serialize, Deserialize)]
9400pub struct TechnologyConfig {
9401 #[serde(default)]
9403 pub enabled: bool,
9404
9405 #[serde(default = "default_revenue_model")]
9407 pub revenue_model: String,
9408
9409 #[serde(default = "default_subscription_pct")]
9411 pub subscription_revenue_pct: f64,
9412
9413 #[serde(default = "default_license_pct")]
9415 pub license_revenue_pct: f64,
9416
9417 #[serde(default = "default_services_pct")]
9419 pub services_revenue_pct: f64,
9420
9421 #[serde(default)]
9423 pub rd_capitalization: RdCapitalizationConfig,
9424
9425 #[serde(default)]
9427 pub anomaly_rates: TechnologyAnomalyRates,
9428}
9429
9430fn default_revenue_model() -> String {
9431 "saas".to_string()
9432}
9433
9434fn default_subscription_pct() -> f64 {
9435 0.60
9436}
9437
9438fn default_license_pct() -> f64 {
9439 0.25
9440}
9441
9442fn default_services_pct() -> f64 {
9443 0.15
9444}
9445
9446impl Default for TechnologyConfig {
9447 fn default() -> Self {
9448 Self {
9449 enabled: false,
9450 revenue_model: default_revenue_model(),
9451 subscription_revenue_pct: default_subscription_pct(),
9452 license_revenue_pct: default_license_pct(),
9453 services_revenue_pct: default_services_pct(),
9454 rd_capitalization: RdCapitalizationConfig::default(),
9455 anomaly_rates: TechnologyAnomalyRates::default(),
9456 }
9457 }
9458}
9459
9460#[derive(Debug, Clone, Serialize, Deserialize)]
9462pub struct RdCapitalizationConfig {
9463 #[serde(default = "default_true")]
9465 pub enabled: bool,
9466
9467 #[serde(default = "default_cap_rate")]
9469 pub capitalization_rate: f64,
9470
9471 #[serde(default = "default_useful_life")]
9473 pub useful_life_years: u32,
9474}
9475
9476fn default_cap_rate() -> f64 {
9477 0.30
9478}
9479
9480fn default_useful_life() -> u32 {
9481 3
9482}
9483
9484impl Default for RdCapitalizationConfig {
9485 fn default() -> Self {
9486 Self {
9487 enabled: true,
9488 capitalization_rate: default_cap_rate(),
9489 useful_life_years: default_useful_life(),
9490 }
9491 }
9492}
9493
9494#[derive(Debug, Clone, Serialize, Deserialize)]
9496pub struct TechnologyAnomalyRates {
9497 #[serde(default = "default_premature_rev_rate")]
9499 pub premature_revenue: f64,
9500
9501 #[serde(default = "default_side_letter_rate")]
9503 pub side_letter_abuse: f64,
9504
9505 #[serde(default = "default_channel_stuffing_rate")]
9507 pub channel_stuffing: f64,
9508
9509 #[serde(default = "default_improper_cap_rate")]
9511 pub improper_capitalization: f64,
9512}
9513
9514fn default_premature_rev_rate() -> f64 {
9515 0.015
9516}
9517
9518fn default_side_letter_rate() -> f64 {
9519 0.008
9520}
9521
9522fn default_channel_stuffing_rate() -> f64 {
9523 0.01
9524}
9525
9526fn default_improper_cap_rate() -> f64 {
9527 0.012
9528}
9529
9530impl Default for TechnologyAnomalyRates {
9531 fn default() -> Self {
9532 Self {
9533 premature_revenue: default_premature_rev_rate(),
9534 side_letter_abuse: default_side_letter_rate(),
9535 channel_stuffing: default_channel_stuffing_rate(),
9536 improper_capitalization: default_improper_cap_rate(),
9537 }
9538 }
9539}
9540
9541#[derive(Debug, Clone, Serialize, Deserialize)]
9543pub struct FinancialServicesConfig {
9544 #[serde(default)]
9546 pub enabled: bool,
9547
9548 #[serde(default = "default_fi_type")]
9550 pub institution_type: String,
9551
9552 #[serde(default = "default_fi_regulatory")]
9554 pub regulatory_framework: String,
9555
9556 #[serde(default)]
9558 pub anomaly_rates: FinancialServicesAnomalyRates,
9559}
9560
9561fn default_fi_type() -> String {
9562 "commercial_bank".to_string()
9563}
9564
9565fn default_fi_regulatory() -> String {
9566 "us_banking".to_string()
9567}
9568
9569impl Default for FinancialServicesConfig {
9570 fn default() -> Self {
9571 Self {
9572 enabled: false,
9573 institution_type: default_fi_type(),
9574 regulatory_framework: default_fi_regulatory(),
9575 anomaly_rates: FinancialServicesAnomalyRates::default(),
9576 }
9577 }
9578}
9579
9580#[derive(Debug, Clone, Serialize, Deserialize)]
9582pub struct FinancialServicesAnomalyRates {
9583 #[serde(default = "default_loan_fraud_rate")]
9585 pub loan_fraud: f64,
9586
9587 #[serde(default = "default_trading_fraud_rate")]
9589 pub trading_fraud: f64,
9590
9591 #[serde(default = "default_insurance_fraud_rate")]
9593 pub insurance_fraud: f64,
9594
9595 #[serde(default = "default_account_manip_rate")]
9597 pub account_manipulation: f64,
9598}
9599
9600fn default_loan_fraud_rate() -> f64 {
9601 0.01
9602}
9603
9604fn default_trading_fraud_rate() -> f64 {
9605 0.008
9606}
9607
9608fn default_insurance_fraud_rate() -> f64 {
9609 0.012
9610}
9611
9612fn default_account_manip_rate() -> f64 {
9613 0.005
9614}
9615
9616impl Default for FinancialServicesAnomalyRates {
9617 fn default() -> Self {
9618 Self {
9619 loan_fraud: default_loan_fraud_rate(),
9620 trading_fraud: default_trading_fraud_rate(),
9621 insurance_fraud: default_insurance_fraud_rate(),
9622 account_manipulation: default_account_manip_rate(),
9623 }
9624 }
9625}
9626
9627#[derive(Debug, Clone, Serialize, Deserialize)]
9629pub struct ProfessionalServicesConfig {
9630 #[serde(default)]
9632 pub enabled: bool,
9633
9634 #[serde(default = "default_firm_type")]
9636 pub firm_type: String,
9637
9638 #[serde(default = "default_billing_model")]
9640 pub billing_model: String,
9641
9642 #[serde(default = "default_hourly_rate")]
9644 pub avg_hourly_rate: f64,
9645
9646 #[serde(default)]
9648 pub trust_accounting: TrustAccountingConfig,
9649
9650 #[serde(default)]
9652 pub anomaly_rates: ProfessionalServicesAnomalyRates,
9653}
9654
9655fn default_firm_type() -> String {
9656 "consulting".to_string()
9657}
9658
9659fn default_billing_model() -> String {
9660 "time_and_materials".to_string()
9661}
9662
9663fn default_hourly_rate() -> f64 {
9664 250.0
9665}
9666
9667impl Default for ProfessionalServicesConfig {
9668 fn default() -> Self {
9669 Self {
9670 enabled: false,
9671 firm_type: default_firm_type(),
9672 billing_model: default_billing_model(),
9673 avg_hourly_rate: default_hourly_rate(),
9674 trust_accounting: TrustAccountingConfig::default(),
9675 anomaly_rates: ProfessionalServicesAnomalyRates::default(),
9676 }
9677 }
9678}
9679
9680#[derive(Debug, Clone, Serialize, Deserialize)]
9682pub struct TrustAccountingConfig {
9683 #[serde(default)]
9685 pub enabled: bool,
9686
9687 #[serde(default = "default_true")]
9689 pub require_three_way_reconciliation: bool,
9690}
9691
9692impl Default for TrustAccountingConfig {
9693 fn default() -> Self {
9694 Self {
9695 enabled: false,
9696 require_three_way_reconciliation: true,
9697 }
9698 }
9699}
9700
9701#[derive(Debug, Clone, Serialize, Deserialize)]
9703pub struct ProfessionalServicesAnomalyRates {
9704 #[serde(default = "default_time_fraud_rate")]
9706 pub time_billing_fraud: f64,
9707
9708 #[serde(default = "default_expense_fraud_rate")]
9710 pub expense_fraud: f64,
9711
9712 #[serde(default = "default_trust_misappropriation_rate")]
9714 pub trust_misappropriation: f64,
9715}
9716
9717fn default_time_fraud_rate() -> f64 {
9718 0.02
9719}
9720
9721fn default_expense_fraud_rate() -> f64 {
9722 0.015
9723}
9724
9725fn default_trust_misappropriation_rate() -> f64 {
9726 0.003
9727}
9728
9729impl Default for ProfessionalServicesAnomalyRates {
9730 fn default() -> Self {
9731 Self {
9732 time_billing_fraud: default_time_fraud_rate(),
9733 expense_fraud: default_expense_fraud_rate(),
9734 trust_misappropriation: default_trust_misappropriation_rate(),
9735 }
9736 }
9737}
9738
9739#[derive(Debug, Clone, Serialize, Deserialize)]
9753pub struct FingerprintPrivacyConfig {
9754 #[serde(default)]
9756 pub level: String,
9757 #[serde(default = "default_epsilon")]
9759 pub epsilon: f64,
9760 #[serde(default = "default_delta")]
9762 pub delta: f64,
9763 #[serde(default = "default_k_anonymity")]
9765 pub k_anonymity: u32,
9766 #[serde(default)]
9768 pub composition_method: String,
9769}
9770
9771fn default_epsilon() -> f64 {
9772 1.0
9773}
9774
9775fn default_delta() -> f64 {
9776 1e-5
9777}
9778
9779fn default_k_anonymity() -> u32 {
9780 5
9781}
9782
9783impl Default for FingerprintPrivacyConfig {
9784 fn default() -> Self {
9785 Self {
9786 level: "standard".to_string(),
9787 epsilon: default_epsilon(),
9788 delta: default_delta(),
9789 k_anonymity: default_k_anonymity(),
9790 composition_method: "naive".to_string(),
9791 }
9792 }
9793}
9794
9795#[derive(Debug, Clone, Serialize, Deserialize)]
9809pub struct QualityGatesSchemaConfig {
9810 #[serde(default)]
9812 pub enabled: bool,
9813 #[serde(default = "default_gate_profile_name")]
9815 pub profile: String,
9816 #[serde(default)]
9818 pub fail_on_violation: bool,
9819 #[serde(default)]
9821 pub custom_gates: Vec<QualityGateEntry>,
9822}
9823
9824fn default_gate_profile_name() -> String {
9825 "default".to_string()
9826}
9827
9828impl Default for QualityGatesSchemaConfig {
9829 fn default() -> Self {
9830 Self {
9831 enabled: false,
9832 profile: default_gate_profile_name(),
9833 fail_on_violation: false,
9834 custom_gates: Vec::new(),
9835 }
9836 }
9837}
9838
9839#[derive(Debug, Clone, Serialize, Deserialize)]
9841pub struct QualityGateEntry {
9842 pub name: String,
9844 pub metric: String,
9848 pub threshold: f64,
9850 #[serde(default)]
9852 pub upper_threshold: Option<f64>,
9853 #[serde(default = "default_gate_comparison")]
9855 pub comparison: String,
9856}
9857
9858fn default_gate_comparison() -> String {
9859 "gte".to_string()
9860}
9861
9862#[derive(Debug, Clone, Default, Serialize, Deserialize)]
9872pub struct ComplianceSchemaConfig {
9873 #[serde(default)]
9875 pub content_marking: ContentMarkingSchemaConfig,
9876 #[serde(default)]
9878 pub article10_report: bool,
9879 #[serde(default)]
9881 pub certificates: CertificateSchemaConfig,
9882}
9883
9884#[derive(Debug, Clone, Default, Serialize, Deserialize)]
9886pub struct CertificateSchemaConfig {
9887 #[serde(default)]
9889 pub enabled: bool,
9890 #[serde(default)]
9892 pub signing_key_env: Option<String>,
9893 #[serde(default)]
9895 pub include_quality_metrics: bool,
9896}
9897
9898#[derive(Debug, Clone, Serialize, Deserialize)]
9900pub struct ContentMarkingSchemaConfig {
9901 #[serde(default = "default_true")]
9903 pub enabled: bool,
9904 #[serde(default = "default_marking_format")]
9906 pub format: String,
9907}
9908
9909fn default_marking_format() -> String {
9910 "embedded".to_string()
9911}
9912
9913impl Default for ContentMarkingSchemaConfig {
9914 fn default() -> Self {
9915 Self {
9916 enabled: true,
9917 format: default_marking_format(),
9918 }
9919 }
9920}
9921
9922#[derive(Debug, Clone, Default, Serialize, Deserialize)]
9924pub struct WebhookSchemaConfig {
9925 #[serde(default)]
9927 pub enabled: bool,
9928 #[serde(default)]
9930 pub endpoints: Vec<WebhookEndpointConfig>,
9931}
9932
9933#[derive(Debug, Clone, Serialize, Deserialize)]
9935pub struct WebhookEndpointConfig {
9936 pub url: String,
9938 #[serde(default)]
9940 pub events: Vec<String>,
9941 #[serde(default)]
9943 pub secret: Option<String>,
9944 #[serde(default = "default_webhook_retries")]
9946 pub max_retries: u32,
9947 #[serde(default = "default_webhook_timeout")]
9949 pub timeout_secs: u64,
9950}
9951
9952fn default_webhook_retries() -> u32 {
9953 3
9954}
9955fn default_webhook_timeout() -> u64 {
9956 10
9957}
9958
9959#[derive(Debug, Clone, Default, Serialize, Deserialize)]
9965pub struct SourceToPayConfig {
9966 #[serde(default)]
9968 pub enabled: bool,
9969 #[serde(default)]
9971 pub spend_analysis: SpendAnalysisConfig,
9972 #[serde(default)]
9974 pub sourcing: SourcingConfig,
9975 #[serde(default)]
9977 pub qualification: QualificationConfig,
9978 #[serde(default)]
9980 pub rfx: RfxConfig,
9981 #[serde(default)]
9983 pub contracts: ContractConfig,
9984 #[serde(default)]
9986 pub catalog: CatalogConfig,
9987 #[serde(default)]
9989 pub scorecards: ScorecardConfig,
9990 #[serde(default)]
9992 pub p2p_integration: P2PIntegrationConfig,
9993}
9994
9995#[derive(Debug, Clone, Serialize, Deserialize)]
9997pub struct SpendAnalysisConfig {
9998 #[serde(default = "default_hhi_threshold")]
10000 pub hhi_threshold: f64,
10001 #[serde(default = "default_contract_coverage_target")]
10003 pub contract_coverage_target: f64,
10004}
10005
10006impl Default for SpendAnalysisConfig {
10007 fn default() -> Self {
10008 Self {
10009 hhi_threshold: default_hhi_threshold(),
10010 contract_coverage_target: default_contract_coverage_target(),
10011 }
10012 }
10013}
10014
10015fn default_hhi_threshold() -> f64 {
10016 2500.0
10017}
10018fn default_contract_coverage_target() -> f64 {
10019 0.80
10020}
10021
10022#[derive(Debug, Clone, Serialize, Deserialize)]
10024pub struct SourcingConfig {
10025 #[serde(default = "default_sourcing_projects_per_year")]
10027 pub projects_per_year: u32,
10028 #[serde(default = "default_renewal_horizon_months")]
10030 pub renewal_horizon_months: u32,
10031 #[serde(default = "default_project_duration_months")]
10033 pub project_duration_months: u32,
10034}
10035
10036impl Default for SourcingConfig {
10037 fn default() -> Self {
10038 Self {
10039 projects_per_year: default_sourcing_projects_per_year(),
10040 renewal_horizon_months: default_renewal_horizon_months(),
10041 project_duration_months: default_project_duration_months(),
10042 }
10043 }
10044}
10045
10046fn default_sourcing_projects_per_year() -> u32 {
10047 10
10048}
10049fn default_renewal_horizon_months() -> u32 {
10050 3
10051}
10052fn default_project_duration_months() -> u32 {
10053 4
10054}
10055
10056#[derive(Debug, Clone, Serialize, Deserialize)]
10058pub struct QualificationConfig {
10059 #[serde(default = "default_qualification_pass_rate")]
10061 pub pass_rate: f64,
10062 #[serde(default = "default_qualification_validity_days")]
10064 pub validity_days: u32,
10065 #[serde(default = "default_financial_weight")]
10067 pub financial_weight: f64,
10068 #[serde(default = "default_quality_weight")]
10070 pub quality_weight: f64,
10071 #[serde(default = "default_delivery_weight")]
10073 pub delivery_weight: f64,
10074 #[serde(default = "default_compliance_weight")]
10076 pub compliance_weight: f64,
10077}
10078
10079impl Default for QualificationConfig {
10080 fn default() -> Self {
10081 Self {
10082 pass_rate: default_qualification_pass_rate(),
10083 validity_days: default_qualification_validity_days(),
10084 financial_weight: default_financial_weight(),
10085 quality_weight: default_quality_weight(),
10086 delivery_weight: default_delivery_weight(),
10087 compliance_weight: default_compliance_weight(),
10088 }
10089 }
10090}
10091
10092fn default_qualification_pass_rate() -> f64 {
10093 0.75
10094}
10095fn default_qualification_validity_days() -> u32 {
10096 365
10097}
10098fn default_financial_weight() -> f64 {
10099 0.25
10100}
10101fn default_quality_weight() -> f64 {
10102 0.30
10103}
10104fn default_delivery_weight() -> f64 {
10105 0.25
10106}
10107fn default_compliance_weight() -> f64 {
10108 0.20
10109}
10110
10111#[derive(Debug, Clone, Serialize, Deserialize)]
10113pub struct RfxConfig {
10114 #[serde(default = "default_rfi_threshold")]
10116 pub rfi_threshold: f64,
10117 #[serde(default = "default_min_invited_vendors")]
10119 pub min_invited_vendors: u32,
10120 #[serde(default = "default_max_invited_vendors")]
10122 pub max_invited_vendors: u32,
10123 #[serde(default = "default_response_rate")]
10125 pub response_rate: f64,
10126 #[serde(default = "default_price_weight")]
10128 pub default_price_weight: f64,
10129 #[serde(default = "default_rfx_quality_weight")]
10131 pub default_quality_weight: f64,
10132 #[serde(default = "default_rfx_delivery_weight")]
10134 pub default_delivery_weight: f64,
10135}
10136
10137impl Default for RfxConfig {
10138 fn default() -> Self {
10139 Self {
10140 rfi_threshold: default_rfi_threshold(),
10141 min_invited_vendors: default_min_invited_vendors(),
10142 max_invited_vendors: default_max_invited_vendors(),
10143 response_rate: default_response_rate(),
10144 default_price_weight: default_price_weight(),
10145 default_quality_weight: default_rfx_quality_weight(),
10146 default_delivery_weight: default_rfx_delivery_weight(),
10147 }
10148 }
10149}
10150
10151fn default_rfi_threshold() -> f64 {
10152 100_000.0
10153}
10154fn default_min_invited_vendors() -> u32 {
10155 3
10156}
10157fn default_max_invited_vendors() -> u32 {
10158 8
10159}
10160fn default_response_rate() -> f64 {
10161 0.70
10162}
10163fn default_price_weight() -> f64 {
10164 0.40
10165}
10166fn default_rfx_quality_weight() -> f64 {
10167 0.35
10168}
10169fn default_rfx_delivery_weight() -> f64 {
10170 0.25
10171}
10172
10173#[derive(Debug, Clone, Serialize, Deserialize)]
10175pub struct ContractConfig {
10176 #[serde(default = "default_min_contract_months")]
10178 pub min_duration_months: u32,
10179 #[serde(default = "default_max_contract_months")]
10181 pub max_duration_months: u32,
10182 #[serde(default = "default_auto_renewal_rate")]
10184 pub auto_renewal_rate: f64,
10185 #[serde(default = "default_amendment_rate")]
10187 pub amendment_rate: f64,
10188 #[serde(default)]
10190 pub type_distribution: ContractTypeDistribution,
10191}
10192
10193impl Default for ContractConfig {
10194 fn default() -> Self {
10195 Self {
10196 min_duration_months: default_min_contract_months(),
10197 max_duration_months: default_max_contract_months(),
10198 auto_renewal_rate: default_auto_renewal_rate(),
10199 amendment_rate: default_amendment_rate(),
10200 type_distribution: ContractTypeDistribution::default(),
10201 }
10202 }
10203}
10204
10205fn default_min_contract_months() -> u32 {
10206 12
10207}
10208fn default_max_contract_months() -> u32 {
10209 36
10210}
10211fn default_auto_renewal_rate() -> f64 {
10212 0.40
10213}
10214fn default_amendment_rate() -> f64 {
10215 0.20
10216}
10217
10218#[derive(Debug, Clone, Serialize, Deserialize)]
10220pub struct ContractTypeDistribution {
10221 #[serde(default = "default_fixed_price_pct")]
10223 pub fixed_price: f64,
10224 #[serde(default = "default_blanket_pct")]
10226 pub blanket: f64,
10227 #[serde(default = "default_time_materials_pct")]
10229 pub time_and_materials: f64,
10230 #[serde(default = "default_service_agreement_pct")]
10232 pub service_agreement: f64,
10233}
10234
10235impl Default for ContractTypeDistribution {
10236 fn default() -> Self {
10237 Self {
10238 fixed_price: default_fixed_price_pct(),
10239 blanket: default_blanket_pct(),
10240 time_and_materials: default_time_materials_pct(),
10241 service_agreement: default_service_agreement_pct(),
10242 }
10243 }
10244}
10245
10246fn default_fixed_price_pct() -> f64 {
10247 0.40
10248}
10249fn default_blanket_pct() -> f64 {
10250 0.30
10251}
10252fn default_time_materials_pct() -> f64 {
10253 0.15
10254}
10255fn default_service_agreement_pct() -> f64 {
10256 0.15
10257}
10258
10259#[derive(Debug, Clone, Serialize, Deserialize)]
10261pub struct CatalogConfig {
10262 #[serde(default = "default_preferred_vendor_flag_rate")]
10264 pub preferred_vendor_flag_rate: f64,
10265 #[serde(default = "default_multi_source_rate")]
10267 pub multi_source_rate: f64,
10268}
10269
10270impl Default for CatalogConfig {
10271 fn default() -> Self {
10272 Self {
10273 preferred_vendor_flag_rate: default_preferred_vendor_flag_rate(),
10274 multi_source_rate: default_multi_source_rate(),
10275 }
10276 }
10277}
10278
10279fn default_preferred_vendor_flag_rate() -> f64 {
10280 0.70
10281}
10282fn default_multi_source_rate() -> f64 {
10283 0.25
10284}
10285
10286#[derive(Debug, Clone, Serialize, Deserialize)]
10288pub struct ScorecardConfig {
10289 #[serde(default = "default_scorecard_frequency")]
10291 pub frequency: String,
10292 #[serde(default = "default_otd_weight")]
10294 pub on_time_delivery_weight: f64,
10295 #[serde(default = "default_quality_score_weight")]
10297 pub quality_weight: f64,
10298 #[serde(default = "default_price_score_weight")]
10300 pub price_weight: f64,
10301 #[serde(default = "default_responsiveness_weight")]
10303 pub responsiveness_weight: f64,
10304 #[serde(default = "default_grade_a_threshold")]
10306 pub grade_a_threshold: f64,
10307 #[serde(default = "default_grade_b_threshold")]
10309 pub grade_b_threshold: f64,
10310 #[serde(default = "default_grade_c_threshold")]
10312 pub grade_c_threshold: f64,
10313}
10314
10315impl Default for ScorecardConfig {
10316 fn default() -> Self {
10317 Self {
10318 frequency: default_scorecard_frequency(),
10319 on_time_delivery_weight: default_otd_weight(),
10320 quality_weight: default_quality_score_weight(),
10321 price_weight: default_price_score_weight(),
10322 responsiveness_weight: default_responsiveness_weight(),
10323 grade_a_threshold: default_grade_a_threshold(),
10324 grade_b_threshold: default_grade_b_threshold(),
10325 grade_c_threshold: default_grade_c_threshold(),
10326 }
10327 }
10328}
10329
10330fn default_scorecard_frequency() -> String {
10331 "quarterly".to_string()
10332}
10333fn default_otd_weight() -> f64 {
10334 0.30
10335}
10336fn default_quality_score_weight() -> f64 {
10337 0.30
10338}
10339fn default_price_score_weight() -> f64 {
10340 0.25
10341}
10342fn default_responsiveness_weight() -> f64 {
10343 0.15
10344}
10345fn default_grade_a_threshold() -> f64 {
10346 90.0
10347}
10348fn default_grade_b_threshold() -> f64 {
10349 75.0
10350}
10351fn default_grade_c_threshold() -> f64 {
10352 60.0
10353}
10354
10355#[derive(Debug, Clone, Serialize, Deserialize)]
10357pub struct P2PIntegrationConfig {
10358 #[serde(default = "default_off_contract_rate")]
10360 pub off_contract_rate: f64,
10361 #[serde(default = "default_price_tolerance")]
10363 pub price_tolerance: f64,
10364 #[serde(default)]
10366 pub catalog_enforcement: bool,
10367}
10368
10369impl Default for P2PIntegrationConfig {
10370 fn default() -> Self {
10371 Self {
10372 off_contract_rate: default_off_contract_rate(),
10373 price_tolerance: default_price_tolerance(),
10374 catalog_enforcement: false,
10375 }
10376 }
10377}
10378
10379fn default_off_contract_rate() -> f64 {
10380 0.15
10381}
10382fn default_price_tolerance() -> f64 {
10383 0.02
10384}
10385
10386#[derive(Debug, Clone, Serialize, Deserialize)]
10390pub struct FinancialReportingConfig {
10391 #[serde(default)]
10393 pub enabled: bool,
10394 #[serde(default = "default_true")]
10396 pub generate_balance_sheet: bool,
10397 #[serde(default = "default_true")]
10399 pub generate_income_statement: bool,
10400 #[serde(default = "default_true")]
10402 pub generate_cash_flow: bool,
10403 #[serde(default = "default_true")]
10405 pub generate_changes_in_equity: bool,
10406 #[serde(default = "default_comparative_periods")]
10408 pub comparative_periods: u32,
10409 #[serde(default)]
10411 pub management_kpis: ManagementKpisConfig,
10412 #[serde(default)]
10414 pub budgets: BudgetConfig,
10415}
10416
10417impl Default for FinancialReportingConfig {
10418 fn default() -> Self {
10419 Self {
10420 enabled: false,
10421 generate_balance_sheet: true,
10422 generate_income_statement: true,
10423 generate_cash_flow: true,
10424 generate_changes_in_equity: true,
10425 comparative_periods: default_comparative_periods(),
10426 management_kpis: ManagementKpisConfig::default(),
10427 budgets: BudgetConfig::default(),
10428 }
10429 }
10430}
10431
10432fn default_comparative_periods() -> u32 {
10433 1
10434}
10435
10436#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10438pub struct ManagementKpisConfig {
10439 #[serde(default)]
10441 pub enabled: bool,
10442 #[serde(default = "default_kpi_frequency")]
10444 pub frequency: String,
10445}
10446
10447fn default_kpi_frequency() -> String {
10448 "monthly".to_string()
10449}
10450
10451#[derive(Debug, Clone, Serialize, Deserialize)]
10453pub struct BudgetConfig {
10454 #[serde(default)]
10456 pub enabled: bool,
10457 #[serde(default = "default_revenue_growth_rate")]
10459 pub revenue_growth_rate: f64,
10460 #[serde(default = "default_expense_inflation_rate")]
10462 pub expense_inflation_rate: f64,
10463 #[serde(default = "default_variance_noise")]
10465 pub variance_noise: f64,
10466}
10467
10468impl Default for BudgetConfig {
10469 fn default() -> Self {
10470 Self {
10471 enabled: false,
10472 revenue_growth_rate: default_revenue_growth_rate(),
10473 expense_inflation_rate: default_expense_inflation_rate(),
10474 variance_noise: default_variance_noise(),
10475 }
10476 }
10477}
10478
10479fn default_revenue_growth_rate() -> f64 {
10480 0.05
10481}
10482fn default_expense_inflation_rate() -> f64 {
10483 0.03
10484}
10485fn default_variance_noise() -> f64 {
10486 0.10
10487}
10488
10489#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10493pub struct HrConfig {
10494 #[serde(default)]
10496 pub enabled: bool,
10497 #[serde(default)]
10499 pub payroll: PayrollConfig,
10500 #[serde(default)]
10502 pub time_attendance: TimeAttendanceConfig,
10503 #[serde(default)]
10505 pub expenses: ExpenseConfig,
10506}
10507
10508#[derive(Debug, Clone, Serialize, Deserialize)]
10510pub struct PayrollConfig {
10511 #[serde(default = "default_true")]
10513 pub enabled: bool,
10514 #[serde(default = "default_pay_frequency")]
10516 pub pay_frequency: String,
10517 #[serde(default)]
10519 pub salary_ranges: PayrollSalaryRanges,
10520 #[serde(default)]
10522 pub tax_rates: PayrollTaxRates,
10523 #[serde(default = "default_benefits_enrollment_rate")]
10525 pub benefits_enrollment_rate: f64,
10526 #[serde(default = "default_retirement_participation_rate")]
10528 pub retirement_participation_rate: f64,
10529}
10530
10531impl Default for PayrollConfig {
10532 fn default() -> Self {
10533 Self {
10534 enabled: true,
10535 pay_frequency: default_pay_frequency(),
10536 salary_ranges: PayrollSalaryRanges::default(),
10537 tax_rates: PayrollTaxRates::default(),
10538 benefits_enrollment_rate: default_benefits_enrollment_rate(),
10539 retirement_participation_rate: default_retirement_participation_rate(),
10540 }
10541 }
10542}
10543
10544fn default_pay_frequency() -> String {
10545 "monthly".to_string()
10546}
10547fn default_benefits_enrollment_rate() -> f64 {
10548 0.60
10549}
10550fn default_retirement_participation_rate() -> f64 {
10551 0.45
10552}
10553
10554#[derive(Debug, Clone, Serialize, Deserialize)]
10556pub struct PayrollSalaryRanges {
10557 #[serde(default = "default_staff_min")]
10559 pub staff_min: f64,
10560 #[serde(default = "default_staff_max")]
10561 pub staff_max: f64,
10562 #[serde(default = "default_manager_min")]
10564 pub manager_min: f64,
10565 #[serde(default = "default_manager_max")]
10566 pub manager_max: f64,
10567 #[serde(default = "default_director_min")]
10569 pub director_min: f64,
10570 #[serde(default = "default_director_max")]
10571 pub director_max: f64,
10572 #[serde(default = "default_executive_min")]
10574 pub executive_min: f64,
10575 #[serde(default = "default_executive_max")]
10576 pub executive_max: f64,
10577}
10578
10579impl Default for PayrollSalaryRanges {
10580 fn default() -> Self {
10581 Self {
10582 staff_min: default_staff_min(),
10583 staff_max: default_staff_max(),
10584 manager_min: default_manager_min(),
10585 manager_max: default_manager_max(),
10586 director_min: default_director_min(),
10587 director_max: default_director_max(),
10588 executive_min: default_executive_min(),
10589 executive_max: default_executive_max(),
10590 }
10591 }
10592}
10593
10594fn default_staff_min() -> f64 {
10595 50_000.0
10596}
10597fn default_staff_max() -> f64 {
10598 70_000.0
10599}
10600fn default_manager_min() -> f64 {
10601 80_000.0
10602}
10603fn default_manager_max() -> f64 {
10604 120_000.0
10605}
10606fn default_director_min() -> f64 {
10607 120_000.0
10608}
10609fn default_director_max() -> f64 {
10610 180_000.0
10611}
10612fn default_executive_min() -> f64 {
10613 180_000.0
10614}
10615fn default_executive_max() -> f64 {
10616 350_000.0
10617}
10618
10619#[derive(Debug, Clone, Serialize, Deserialize)]
10621pub struct PayrollTaxRates {
10622 #[serde(default = "default_federal_rate")]
10624 pub federal_effective: f64,
10625 #[serde(default = "default_state_rate")]
10627 pub state_effective: f64,
10628 #[serde(default = "default_fica_rate")]
10630 pub fica: f64,
10631}
10632
10633impl Default for PayrollTaxRates {
10634 fn default() -> Self {
10635 Self {
10636 federal_effective: default_federal_rate(),
10637 state_effective: default_state_rate(),
10638 fica: default_fica_rate(),
10639 }
10640 }
10641}
10642
10643fn default_federal_rate() -> f64 {
10644 0.22
10645}
10646fn default_state_rate() -> f64 {
10647 0.05
10648}
10649fn default_fica_rate() -> f64 {
10650 0.0765
10651}
10652
10653#[derive(Debug, Clone, Serialize, Deserialize)]
10655pub struct TimeAttendanceConfig {
10656 #[serde(default = "default_true")]
10658 pub enabled: bool,
10659 #[serde(default = "default_overtime_rate")]
10661 pub overtime_rate: f64,
10662}
10663
10664impl Default for TimeAttendanceConfig {
10665 fn default() -> Self {
10666 Self {
10667 enabled: true,
10668 overtime_rate: default_overtime_rate(),
10669 }
10670 }
10671}
10672
10673fn default_overtime_rate() -> f64 {
10674 0.10
10675}
10676
10677#[derive(Debug, Clone, Serialize, Deserialize)]
10679pub struct ExpenseConfig {
10680 #[serde(default = "default_true")]
10682 pub enabled: bool,
10683 #[serde(default = "default_expense_submission_rate")]
10685 pub submission_rate: f64,
10686 #[serde(default = "default_policy_violation_rate")]
10688 pub policy_violation_rate: f64,
10689}
10690
10691impl Default for ExpenseConfig {
10692 fn default() -> Self {
10693 Self {
10694 enabled: true,
10695 submission_rate: default_expense_submission_rate(),
10696 policy_violation_rate: default_policy_violation_rate(),
10697 }
10698 }
10699}
10700
10701fn default_expense_submission_rate() -> f64 {
10702 0.30
10703}
10704fn default_policy_violation_rate() -> f64 {
10705 0.08
10706}
10707
10708#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10712pub struct ManufacturingProcessConfig {
10713 #[serde(default)]
10715 pub enabled: bool,
10716 #[serde(default)]
10718 pub production_orders: ProductionOrderConfig,
10719 #[serde(default)]
10721 pub costing: ManufacturingCostingConfig,
10722 #[serde(default)]
10724 pub routing: RoutingConfig,
10725}
10726
10727#[derive(Debug, Clone, Serialize, Deserialize)]
10729pub struct ProductionOrderConfig {
10730 #[serde(default = "default_prod_orders_per_month")]
10732 pub orders_per_month: u32,
10733 #[serde(default = "default_prod_avg_batch_size")]
10735 pub avg_batch_size: u32,
10736 #[serde(default = "default_prod_yield_rate")]
10738 pub yield_rate: f64,
10739 #[serde(default = "default_prod_make_to_order_rate")]
10741 pub make_to_order_rate: f64,
10742 #[serde(default = "default_prod_rework_rate")]
10744 pub rework_rate: f64,
10745}
10746
10747impl Default for ProductionOrderConfig {
10748 fn default() -> Self {
10749 Self {
10750 orders_per_month: default_prod_orders_per_month(),
10751 avg_batch_size: default_prod_avg_batch_size(),
10752 yield_rate: default_prod_yield_rate(),
10753 make_to_order_rate: default_prod_make_to_order_rate(),
10754 rework_rate: default_prod_rework_rate(),
10755 }
10756 }
10757}
10758
10759fn default_prod_orders_per_month() -> u32 {
10760 50
10761}
10762fn default_prod_avg_batch_size() -> u32 {
10763 100
10764}
10765fn default_prod_yield_rate() -> f64 {
10766 0.97
10767}
10768fn default_prod_make_to_order_rate() -> f64 {
10769 0.20
10770}
10771fn default_prod_rework_rate() -> f64 {
10772 0.03
10773}
10774
10775#[derive(Debug, Clone, Serialize, Deserialize)]
10777pub struct ManufacturingCostingConfig {
10778 #[serde(default = "default_labor_rate")]
10780 pub labor_rate_per_hour: f64,
10781 #[serde(default = "default_overhead_rate")]
10783 pub overhead_rate: f64,
10784 #[serde(default = "default_cost_update_frequency")]
10786 pub standard_cost_update_frequency: String,
10787}
10788
10789impl Default for ManufacturingCostingConfig {
10790 fn default() -> Self {
10791 Self {
10792 labor_rate_per_hour: default_labor_rate(),
10793 overhead_rate: default_overhead_rate(),
10794 standard_cost_update_frequency: default_cost_update_frequency(),
10795 }
10796 }
10797}
10798
10799fn default_labor_rate() -> f64 {
10800 35.0
10801}
10802fn default_overhead_rate() -> f64 {
10803 1.50
10804}
10805fn default_cost_update_frequency() -> String {
10806 "quarterly".to_string()
10807}
10808
10809#[derive(Debug, Clone, Serialize, Deserialize)]
10811pub struct RoutingConfig {
10812 #[serde(default = "default_avg_operations")]
10814 pub avg_operations: u32,
10815 #[serde(default = "default_setup_time")]
10817 pub setup_time_hours: f64,
10818 #[serde(default = "default_run_time_variation")]
10820 pub run_time_variation: f64,
10821}
10822
10823impl Default for RoutingConfig {
10824 fn default() -> Self {
10825 Self {
10826 avg_operations: default_avg_operations(),
10827 setup_time_hours: default_setup_time(),
10828 run_time_variation: default_run_time_variation(),
10829 }
10830 }
10831}
10832
10833fn default_avg_operations() -> u32 {
10834 4
10835}
10836fn default_setup_time() -> f64 {
10837 1.5
10838}
10839fn default_run_time_variation() -> f64 {
10840 0.15
10841}
10842
10843#[derive(Debug, Clone, Serialize, Deserialize)]
10847pub struct SalesQuoteConfig {
10848 #[serde(default)]
10850 pub enabled: bool,
10851 #[serde(default = "default_quotes_per_month")]
10853 pub quotes_per_month: u32,
10854 #[serde(default = "default_quote_win_rate")]
10856 pub win_rate: f64,
10857 #[serde(default = "default_quote_validity_days")]
10859 pub validity_days: u32,
10860}
10861
10862impl Default for SalesQuoteConfig {
10863 fn default() -> Self {
10864 Self {
10865 enabled: false,
10866 quotes_per_month: default_quotes_per_month(),
10867 win_rate: default_quote_win_rate(),
10868 validity_days: default_quote_validity_days(),
10869 }
10870 }
10871}
10872
10873fn default_quotes_per_month() -> u32 {
10874 30
10875}
10876fn default_quote_win_rate() -> f64 {
10877 0.35
10878}
10879fn default_quote_validity_days() -> u32 {
10880 30
10881}
10882
10883#[derive(Debug, Clone, Serialize, Deserialize)]
10892pub struct TaxConfig {
10893 #[serde(default)]
10895 pub enabled: bool,
10896 #[serde(default)]
10898 pub jurisdictions: TaxJurisdictionConfig,
10899 #[serde(default)]
10901 pub vat_gst: VatGstConfig,
10902 #[serde(default)]
10904 pub sales_tax: SalesTaxConfig,
10905 #[serde(default)]
10907 pub withholding: WithholdingTaxSchemaConfig,
10908 #[serde(default)]
10910 pub provisions: TaxProvisionSchemaConfig,
10911 #[serde(default)]
10913 pub payroll_tax: PayrollTaxSchemaConfig,
10914 #[serde(default = "default_tax_anomaly_rate")]
10916 pub anomaly_rate: f64,
10917}
10918
10919fn default_tax_anomaly_rate() -> f64 {
10920 0.03
10921}
10922
10923impl Default for TaxConfig {
10924 fn default() -> Self {
10925 Self {
10926 enabled: false,
10927 jurisdictions: TaxJurisdictionConfig::default(),
10928 vat_gst: VatGstConfig::default(),
10929 sales_tax: SalesTaxConfig::default(),
10930 withholding: WithholdingTaxSchemaConfig::default(),
10931 provisions: TaxProvisionSchemaConfig::default(),
10932 payroll_tax: PayrollTaxSchemaConfig::default(),
10933 anomaly_rate: default_tax_anomaly_rate(),
10934 }
10935 }
10936}
10937
10938#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10943pub struct TaxJurisdictionConfig {
10944 #[serde(default)]
10946 pub countries: Vec<String>,
10947 #[serde(default)]
10949 pub include_subnational: bool,
10950}
10951
10952#[derive(Debug, Clone, Serialize, Deserialize)]
10957pub struct VatGstConfig {
10958 #[serde(default)]
10960 pub enabled: bool,
10961 #[serde(default)]
10963 pub standard_rates: std::collections::HashMap<String, f64>,
10964 #[serde(default)]
10966 pub reduced_rates: std::collections::HashMap<String, f64>,
10967 #[serde(default)]
10969 pub exempt_categories: Vec<String>,
10970 #[serde(default = "default_true")]
10972 pub reverse_charge: bool,
10973}
10974
10975impl Default for VatGstConfig {
10976 fn default() -> Self {
10977 Self {
10978 enabled: false,
10979 standard_rates: std::collections::HashMap::new(),
10980 reduced_rates: std::collections::HashMap::new(),
10981 exempt_categories: Vec::new(),
10982 reverse_charge: true,
10983 }
10984 }
10985}
10986
10987#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10991pub struct SalesTaxConfig {
10992 #[serde(default)]
10994 pub enabled: bool,
10995 #[serde(default)]
10997 pub nexus_states: Vec<String>,
10998}
10999
11000#[derive(Debug, Clone, Serialize, Deserialize)]
11005pub struct WithholdingTaxSchemaConfig {
11006 #[serde(default)]
11008 pub enabled: bool,
11009 #[serde(default = "default_true")]
11011 pub treaty_network: bool,
11012 #[serde(default = "default_withholding_rate")]
11014 pub default_rate: f64,
11015 #[serde(default = "default_treaty_reduced_rate")]
11017 pub treaty_reduced_rate: f64,
11018}
11019
11020fn default_withholding_rate() -> f64 {
11021 0.30
11022}
11023
11024fn default_treaty_reduced_rate() -> f64 {
11025 0.15
11026}
11027
11028impl Default for WithholdingTaxSchemaConfig {
11029 fn default() -> Self {
11030 Self {
11031 enabled: false,
11032 treaty_network: true,
11033 default_rate: default_withholding_rate(),
11034 treaty_reduced_rate: default_treaty_reduced_rate(),
11035 }
11036 }
11037}
11038
11039#[derive(Debug, Clone, Serialize, Deserialize)]
11044pub struct TaxProvisionSchemaConfig {
11045 #[serde(default = "default_true")]
11048 pub enabled: bool,
11049 #[serde(default = "default_statutory_rate")]
11051 pub statutory_rate: f64,
11052 #[serde(default = "default_true")]
11054 pub uncertain_positions: bool,
11055}
11056
11057fn default_statutory_rate() -> f64 {
11058 0.21
11059}
11060
11061impl Default for TaxProvisionSchemaConfig {
11062 fn default() -> Self {
11063 Self {
11064 enabled: true,
11065 statutory_rate: default_statutory_rate(),
11066 uncertain_positions: true,
11067 }
11068 }
11069}
11070
11071#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11076pub struct PayrollTaxSchemaConfig {
11077 #[serde(default)]
11079 pub enabled: bool,
11080}
11081
11082#[derive(Debug, Clone, Serialize, Deserialize)]
11092pub struct TreasuryConfig {
11093 #[serde(default)]
11095 pub enabled: bool,
11096 #[serde(default)]
11098 pub cash_positioning: CashPositioningConfig,
11099 #[serde(default)]
11101 pub cash_forecasting: CashForecastingConfig,
11102 #[serde(default)]
11104 pub cash_pooling: CashPoolingConfig,
11105 #[serde(default)]
11107 pub hedging: HedgingSchemaConfig,
11108 #[serde(default)]
11110 pub debt: DebtSchemaConfig,
11111 #[serde(default)]
11113 pub netting: NettingSchemaConfig,
11114 #[serde(default)]
11116 pub bank_guarantees: BankGuaranteeSchemaConfig,
11117 #[serde(default = "default_treasury_anomaly_rate")]
11119 pub anomaly_rate: f64,
11120}
11121
11122fn default_treasury_anomaly_rate() -> f64 {
11123 0.02
11124}
11125
11126impl Default for TreasuryConfig {
11127 fn default() -> Self {
11128 Self {
11129 enabled: false,
11130 cash_positioning: CashPositioningConfig::default(),
11131 cash_forecasting: CashForecastingConfig::default(),
11132 cash_pooling: CashPoolingConfig::default(),
11133 hedging: HedgingSchemaConfig::default(),
11134 debt: DebtSchemaConfig::default(),
11135 netting: NettingSchemaConfig::default(),
11136 bank_guarantees: BankGuaranteeSchemaConfig::default(),
11137 anomaly_rate: default_treasury_anomaly_rate(),
11138 }
11139 }
11140}
11141
11142#[derive(Debug, Clone, Serialize, Deserialize)]
11146pub struct CashPositioningConfig {
11147 #[serde(default = "default_true")]
11149 pub enabled: bool,
11150 #[serde(default = "default_cash_frequency")]
11152 pub frequency: String,
11153 #[serde(default = "default_minimum_balance_policy")]
11155 pub minimum_balance_policy: f64,
11156}
11157
11158fn default_cash_frequency() -> String {
11159 "daily".to_string()
11160}
11161
11162fn default_minimum_balance_policy() -> f64 {
11163 100_000.0
11164}
11165
11166impl Default for CashPositioningConfig {
11167 fn default() -> Self {
11168 Self {
11169 enabled: true,
11170 frequency: default_cash_frequency(),
11171 minimum_balance_policy: default_minimum_balance_policy(),
11172 }
11173 }
11174}
11175
11176#[derive(Debug, Clone, Serialize, Deserialize)]
11180pub struct CashForecastingConfig {
11181 #[serde(default = "default_true")]
11183 pub enabled: bool,
11184 #[serde(default = "default_horizon_days")]
11186 pub horizon_days: u32,
11187 #[serde(default = "default_ar_probability_curve")]
11189 pub ar_collection_probability_curve: String,
11190 #[serde(default = "default_confidence_interval")]
11192 pub confidence_interval: f64,
11193}
11194
11195fn default_horizon_days() -> u32 {
11196 90
11197}
11198
11199fn default_ar_probability_curve() -> String {
11200 "aging".to_string()
11201}
11202
11203fn default_confidence_interval() -> f64 {
11204 0.90
11205}
11206
11207impl Default for CashForecastingConfig {
11208 fn default() -> Self {
11209 Self {
11210 enabled: true,
11211 horizon_days: default_horizon_days(),
11212 ar_collection_probability_curve: default_ar_probability_curve(),
11213 confidence_interval: default_confidence_interval(),
11214 }
11215 }
11216}
11217
11218#[derive(Debug, Clone, Serialize, Deserialize)]
11222pub struct CashPoolingConfig {
11223 #[serde(default)]
11225 pub enabled: bool,
11226 #[serde(default = "default_pool_type")]
11228 pub pool_type: String,
11229 #[serde(default = "default_sweep_time")]
11231 pub sweep_time: String,
11232}
11233
11234fn default_pool_type() -> String {
11235 "zero_balancing".to_string()
11236}
11237
11238fn default_sweep_time() -> String {
11239 "16:00".to_string()
11240}
11241
11242impl Default for CashPoolingConfig {
11243 fn default() -> Self {
11244 Self {
11245 enabled: false,
11246 pool_type: default_pool_type(),
11247 sweep_time: default_sweep_time(),
11248 }
11249 }
11250}
11251
11252#[derive(Debug, Clone, Serialize, Deserialize)]
11257pub struct HedgingSchemaConfig {
11258 #[serde(default)]
11260 pub enabled: bool,
11261 #[serde(default = "default_hedge_ratio")]
11263 pub hedge_ratio: f64,
11264 #[serde(default = "default_hedge_instruments")]
11266 pub instruments: Vec<String>,
11267 #[serde(default = "default_true")]
11269 pub hedge_accounting: bool,
11270 #[serde(default = "default_effectiveness_method")]
11272 pub effectiveness_method: String,
11273}
11274
11275fn default_hedge_ratio() -> f64 {
11276 0.75
11277}
11278
11279fn default_hedge_instruments() -> Vec<String> {
11280 vec!["fx_forward".to_string(), "interest_rate_swap".to_string()]
11281}
11282
11283fn default_effectiveness_method() -> String {
11284 "regression".to_string()
11285}
11286
11287impl Default for HedgingSchemaConfig {
11288 fn default() -> Self {
11289 Self {
11290 enabled: false,
11291 hedge_ratio: default_hedge_ratio(),
11292 instruments: default_hedge_instruments(),
11293 hedge_accounting: true,
11294 effectiveness_method: default_effectiveness_method(),
11295 }
11296 }
11297}
11298
11299#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11304pub struct DebtSchemaConfig {
11305 #[serde(default)]
11307 pub enabled: bool,
11308 #[serde(default)]
11310 pub instruments: Vec<DebtInstrumentDef>,
11311 #[serde(default)]
11313 pub covenants: Vec<CovenantDef>,
11314}
11315
11316#[derive(Debug, Clone, Serialize, Deserialize)]
11318pub struct DebtInstrumentDef {
11319 #[serde(rename = "type")]
11321 pub instrument_type: String,
11322 #[serde(default)]
11324 pub principal: Option<f64>,
11325 #[serde(default)]
11327 pub rate: Option<f64>,
11328 #[serde(default)]
11330 pub maturity_months: Option<u32>,
11331 #[serde(default)]
11333 pub facility: Option<f64>,
11334}
11335
11336#[derive(Debug, Clone, Serialize, Deserialize)]
11338pub struct CovenantDef {
11339 #[serde(rename = "type")]
11342 pub covenant_type: String,
11343 pub threshold: f64,
11345}
11346
11347#[derive(Debug, Clone, Serialize, Deserialize)]
11351pub struct NettingSchemaConfig {
11352 #[serde(default)]
11354 pub enabled: bool,
11355 #[serde(default = "default_netting_cycle")]
11357 pub cycle: String,
11358}
11359
11360fn default_netting_cycle() -> String {
11361 "monthly".to_string()
11362}
11363
11364impl Default for NettingSchemaConfig {
11365 fn default() -> Self {
11366 Self {
11367 enabled: false,
11368 cycle: default_netting_cycle(),
11369 }
11370 }
11371}
11372
11373#[derive(Debug, Clone, Serialize, Deserialize)]
11377pub struct BankGuaranteeSchemaConfig {
11378 #[serde(default)]
11380 pub enabled: bool,
11381 #[serde(default = "default_guarantee_count")]
11383 pub count: u32,
11384}
11385
11386fn default_guarantee_count() -> u32 {
11387 5
11388}
11389
11390impl Default for BankGuaranteeSchemaConfig {
11391 fn default() -> Self {
11392 Self {
11393 enabled: false,
11394 count: default_guarantee_count(),
11395 }
11396 }
11397}
11398
11399#[derive(Debug, Clone, Serialize, Deserialize)]
11408pub struct ProjectAccountingConfig {
11409 #[serde(default)]
11411 pub enabled: bool,
11412 #[serde(default = "default_project_count")]
11414 pub project_count: u32,
11415 #[serde(default)]
11417 pub project_types: ProjectTypeDistribution,
11418 #[serde(default)]
11420 pub wbs: WbsSchemaConfig,
11421 #[serde(default)]
11423 pub cost_allocation: CostAllocationConfig,
11424 #[serde(default)]
11426 pub revenue_recognition: ProjectRevenueRecognitionConfig,
11427 #[serde(default)]
11429 pub milestones: MilestoneSchemaConfig,
11430 #[serde(default)]
11432 pub change_orders: ChangeOrderSchemaConfig,
11433 #[serde(default)]
11435 pub retainage: RetainageSchemaConfig,
11436 #[serde(default)]
11438 pub earned_value: EarnedValueSchemaConfig,
11439 #[serde(default = "default_project_anomaly_rate")]
11441 pub anomaly_rate: f64,
11442}
11443
11444fn default_project_count() -> u32 {
11445 10
11446}
11447
11448fn default_project_anomaly_rate() -> f64 {
11449 0.03
11450}
11451
11452impl Default for ProjectAccountingConfig {
11453 fn default() -> Self {
11454 Self {
11455 enabled: false,
11456 project_count: default_project_count(),
11457 project_types: ProjectTypeDistribution::default(),
11458 wbs: WbsSchemaConfig::default(),
11459 cost_allocation: CostAllocationConfig::default(),
11460 revenue_recognition: ProjectRevenueRecognitionConfig::default(),
11461 milestones: MilestoneSchemaConfig::default(),
11462 change_orders: ChangeOrderSchemaConfig::default(),
11463 retainage: RetainageSchemaConfig::default(),
11464 earned_value: EarnedValueSchemaConfig::default(),
11465 anomaly_rate: default_project_anomaly_rate(),
11466 }
11467 }
11468}
11469
11470#[derive(Debug, Clone, Serialize, Deserialize)]
11472pub struct ProjectTypeDistribution {
11473 #[serde(default = "default_capital_weight")]
11475 pub capital: f64,
11476 #[serde(default = "default_internal_weight")]
11478 pub internal: f64,
11479 #[serde(default = "default_customer_weight")]
11481 pub customer: f64,
11482 #[serde(default = "default_rnd_weight")]
11484 pub r_and_d: f64,
11485 #[serde(default = "default_maintenance_weight")]
11487 pub maintenance: f64,
11488 #[serde(default = "default_technology_weight")]
11490 pub technology: f64,
11491}
11492
11493fn default_capital_weight() -> f64 {
11494 0.25
11495}
11496fn default_internal_weight() -> f64 {
11497 0.20
11498}
11499fn default_customer_weight() -> f64 {
11500 0.30
11501}
11502fn default_rnd_weight() -> f64 {
11503 0.10
11504}
11505fn default_maintenance_weight() -> f64 {
11506 0.10
11507}
11508fn default_technology_weight() -> f64 {
11509 0.05
11510}
11511
11512impl Default for ProjectTypeDistribution {
11513 fn default() -> Self {
11514 Self {
11515 capital: default_capital_weight(),
11516 internal: default_internal_weight(),
11517 customer: default_customer_weight(),
11518 r_and_d: default_rnd_weight(),
11519 maintenance: default_maintenance_weight(),
11520 technology: default_technology_weight(),
11521 }
11522 }
11523}
11524
11525#[derive(Debug, Clone, Serialize, Deserialize)]
11527pub struct WbsSchemaConfig {
11528 #[serde(default = "default_wbs_max_depth")]
11530 pub max_depth: u32,
11531 #[serde(default = "default_wbs_min_elements")]
11533 pub min_elements_per_level: u32,
11534 #[serde(default = "default_wbs_max_elements")]
11536 pub max_elements_per_level: u32,
11537}
11538
11539fn default_wbs_max_depth() -> u32 {
11540 3
11541}
11542fn default_wbs_min_elements() -> u32 {
11543 2
11544}
11545fn default_wbs_max_elements() -> u32 {
11546 6
11547}
11548
11549impl Default for WbsSchemaConfig {
11550 fn default() -> Self {
11551 Self {
11552 max_depth: default_wbs_max_depth(),
11553 min_elements_per_level: default_wbs_min_elements(),
11554 max_elements_per_level: default_wbs_max_elements(),
11555 }
11556 }
11557}
11558
11559#[derive(Debug, Clone, Serialize, Deserialize)]
11561pub struct CostAllocationConfig {
11562 #[serde(default = "default_time_entry_rate")]
11564 pub time_entry_project_rate: f64,
11565 #[serde(default = "default_expense_rate")]
11567 pub expense_project_rate: f64,
11568 #[serde(default = "default_po_rate")]
11570 pub purchase_order_project_rate: f64,
11571 #[serde(default = "default_vi_rate")]
11573 pub vendor_invoice_project_rate: f64,
11574}
11575
11576fn default_time_entry_rate() -> f64 {
11577 0.60
11578}
11579fn default_expense_rate() -> f64 {
11580 0.30
11581}
11582fn default_po_rate() -> f64 {
11583 0.40
11584}
11585fn default_vi_rate() -> f64 {
11586 0.35
11587}
11588
11589impl Default for CostAllocationConfig {
11590 fn default() -> Self {
11591 Self {
11592 time_entry_project_rate: default_time_entry_rate(),
11593 expense_project_rate: default_expense_rate(),
11594 purchase_order_project_rate: default_po_rate(),
11595 vendor_invoice_project_rate: default_vi_rate(),
11596 }
11597 }
11598}
11599
11600#[derive(Debug, Clone, Serialize, Deserialize)]
11602pub struct ProjectRevenueRecognitionConfig {
11603 #[serde(default = "default_true")]
11605 pub enabled: bool,
11606 #[serde(default = "default_revenue_method")]
11608 pub method: String,
11609 #[serde(default = "default_completion_measure")]
11611 pub completion_measure: String,
11612 #[serde(default = "default_avg_contract_value")]
11614 pub avg_contract_value: f64,
11615}
11616
11617fn default_revenue_method() -> String {
11618 "percentage_of_completion".to_string()
11619}
11620fn default_completion_measure() -> String {
11621 "cost_to_cost".to_string()
11622}
11623fn default_avg_contract_value() -> f64 {
11624 500_000.0
11625}
11626
11627impl Default for ProjectRevenueRecognitionConfig {
11628 fn default() -> Self {
11629 Self {
11630 enabled: true,
11631 method: default_revenue_method(),
11632 completion_measure: default_completion_measure(),
11633 avg_contract_value: default_avg_contract_value(),
11634 }
11635 }
11636}
11637
11638#[derive(Debug, Clone, Serialize, Deserialize)]
11640pub struct MilestoneSchemaConfig {
11641 #[serde(default = "default_true")]
11643 pub enabled: bool,
11644 #[serde(default = "default_milestones_per_project")]
11646 pub avg_per_project: u32,
11647 #[serde(default = "default_payment_milestone_rate")]
11649 pub payment_milestone_rate: f64,
11650}
11651
11652fn default_milestones_per_project() -> u32 {
11653 4
11654}
11655fn default_payment_milestone_rate() -> f64 {
11656 0.50
11657}
11658
11659impl Default for MilestoneSchemaConfig {
11660 fn default() -> Self {
11661 Self {
11662 enabled: true,
11663 avg_per_project: default_milestones_per_project(),
11664 payment_milestone_rate: default_payment_milestone_rate(),
11665 }
11666 }
11667}
11668
11669#[derive(Debug, Clone, Serialize, Deserialize)]
11671pub struct ChangeOrderSchemaConfig {
11672 #[serde(default = "default_true")]
11674 pub enabled: bool,
11675 #[serde(default = "default_change_order_probability")]
11677 pub probability: f64,
11678 #[serde(default = "default_max_change_orders")]
11680 pub max_per_project: u32,
11681 #[serde(default = "default_change_order_approval_rate")]
11683 pub approval_rate: f64,
11684}
11685
11686fn default_change_order_probability() -> f64 {
11687 0.40
11688}
11689fn default_max_change_orders() -> u32 {
11690 3
11691}
11692fn default_change_order_approval_rate() -> f64 {
11693 0.75
11694}
11695
11696impl Default for ChangeOrderSchemaConfig {
11697 fn default() -> Self {
11698 Self {
11699 enabled: true,
11700 probability: default_change_order_probability(),
11701 max_per_project: default_max_change_orders(),
11702 approval_rate: default_change_order_approval_rate(),
11703 }
11704 }
11705}
11706
11707#[derive(Debug, Clone, Serialize, Deserialize)]
11709pub struct RetainageSchemaConfig {
11710 #[serde(default)]
11712 pub enabled: bool,
11713 #[serde(default = "default_retainage_pct")]
11715 pub default_percentage: f64,
11716}
11717
11718fn default_retainage_pct() -> f64 {
11719 0.10
11720}
11721
11722impl Default for RetainageSchemaConfig {
11723 fn default() -> Self {
11724 Self {
11725 enabled: false,
11726 default_percentage: default_retainage_pct(),
11727 }
11728 }
11729}
11730
11731#[derive(Debug, Clone, Serialize, Deserialize)]
11733pub struct EarnedValueSchemaConfig {
11734 #[serde(default = "default_true")]
11736 pub enabled: bool,
11737 #[serde(default = "default_evm_frequency")]
11739 pub frequency: String,
11740}
11741
11742fn default_evm_frequency() -> String {
11743 "monthly".to_string()
11744}
11745
11746impl Default for EarnedValueSchemaConfig {
11747 fn default() -> Self {
11748 Self {
11749 enabled: true,
11750 frequency: default_evm_frequency(),
11751 }
11752 }
11753}
11754
11755#[derive(Debug, Clone, Serialize, Deserialize)]
11761pub struct EsgConfig {
11762 #[serde(default)]
11764 pub enabled: bool,
11765 #[serde(default)]
11767 pub environmental: EnvironmentalConfig,
11768 #[serde(default)]
11770 pub social: SocialConfig,
11771 #[serde(default)]
11773 pub governance: GovernanceSchemaConfig,
11774 #[serde(default)]
11776 pub supply_chain_esg: SupplyChainEsgConfig,
11777 #[serde(default)]
11779 pub reporting: EsgReportingConfig,
11780 #[serde(default)]
11782 pub climate_scenarios: ClimateScenarioConfig,
11783 #[serde(default = "default_esg_anomaly_rate")]
11785 pub anomaly_rate: f64,
11786}
11787
11788fn default_esg_anomaly_rate() -> f64 {
11789 0.02
11790}
11791
11792impl Default for EsgConfig {
11793 fn default() -> Self {
11794 Self {
11795 enabled: false,
11796 environmental: EnvironmentalConfig::default(),
11797 social: SocialConfig::default(),
11798 governance: GovernanceSchemaConfig::default(),
11799 supply_chain_esg: SupplyChainEsgConfig::default(),
11800 reporting: EsgReportingConfig::default(),
11801 climate_scenarios: ClimateScenarioConfig::default(),
11802 anomaly_rate: default_esg_anomaly_rate(),
11803 }
11804 }
11805}
11806
11807#[derive(Debug, Clone, Serialize, Deserialize, Default)]
11812pub struct CountryPacksSchemaConfig {
11813 #[serde(default)]
11815 pub external_dir: Option<PathBuf>,
11816 #[serde(default)]
11820 pub overrides: std::collections::HashMap<String, serde_json::Value>,
11821}
11822
11823#[derive(Debug, Clone, Serialize, Deserialize)]
11825pub struct EnvironmentalConfig {
11826 #[serde(default = "default_true")]
11828 pub enabled: bool,
11829 #[serde(default)]
11831 pub scope1: EmissionScopeConfig,
11832 #[serde(default)]
11834 pub scope2: EmissionScopeConfig,
11835 #[serde(default)]
11837 pub scope3: Scope3Config,
11838 #[serde(default)]
11840 pub energy: EnergySchemaConfig,
11841 #[serde(default)]
11843 pub water: WaterSchemaConfig,
11844 #[serde(default)]
11846 pub waste: WasteSchemaConfig,
11847}
11848
11849impl Default for EnvironmentalConfig {
11850 fn default() -> Self {
11851 Self {
11852 enabled: true,
11853 scope1: EmissionScopeConfig::default(),
11854 scope2: EmissionScopeConfig::default(),
11855 scope3: Scope3Config::default(),
11856 energy: EnergySchemaConfig::default(),
11857 water: WaterSchemaConfig::default(),
11858 waste: WasteSchemaConfig::default(),
11859 }
11860 }
11861}
11862
11863#[derive(Debug, Clone, Serialize, Deserialize)]
11865pub struct EmissionScopeConfig {
11866 #[serde(default = "default_true")]
11868 pub enabled: bool,
11869 #[serde(default = "default_emission_region")]
11871 pub factor_region: String,
11872}
11873
11874fn default_emission_region() -> String {
11875 "US".to_string()
11876}
11877
11878impl Default for EmissionScopeConfig {
11879 fn default() -> Self {
11880 Self {
11881 enabled: true,
11882 factor_region: default_emission_region(),
11883 }
11884 }
11885}
11886
11887#[derive(Debug, Clone, Serialize, Deserialize)]
11889pub struct Scope3Config {
11890 #[serde(default = "default_true")]
11892 pub enabled: bool,
11893 #[serde(default = "default_scope3_categories")]
11895 pub categories: Vec<String>,
11896 #[serde(default = "default_spend_intensity")]
11898 pub default_spend_intensity_kg_per_usd: f64,
11899}
11900
11901fn default_scope3_categories() -> Vec<String> {
11902 vec![
11903 "purchased_goods".to_string(),
11904 "business_travel".to_string(),
11905 "employee_commuting".to_string(),
11906 ]
11907}
11908
11909fn default_spend_intensity() -> f64 {
11910 0.5
11911}
11912
11913impl Default for Scope3Config {
11914 fn default() -> Self {
11915 Self {
11916 enabled: true,
11917 categories: default_scope3_categories(),
11918 default_spend_intensity_kg_per_usd: default_spend_intensity(),
11919 }
11920 }
11921}
11922
11923#[derive(Debug, Clone, Serialize, Deserialize)]
11925pub struct EnergySchemaConfig {
11926 #[serde(default = "default_true")]
11928 pub enabled: bool,
11929 #[serde(default = "default_facility_count")]
11931 pub facility_count: u32,
11932 #[serde(default = "default_renewable_target")]
11934 pub renewable_target: f64,
11935}
11936
11937fn default_facility_count() -> u32 {
11938 5
11939}
11940
11941fn default_renewable_target() -> f64 {
11942 0.30
11943}
11944
11945impl Default for EnergySchemaConfig {
11946 fn default() -> Self {
11947 Self {
11948 enabled: true,
11949 facility_count: default_facility_count(),
11950 renewable_target: default_renewable_target(),
11951 }
11952 }
11953}
11954
11955#[derive(Debug, Clone, Serialize, Deserialize)]
11957pub struct WaterSchemaConfig {
11958 #[serde(default = "default_true")]
11960 pub enabled: bool,
11961 #[serde(default = "default_water_facility_count")]
11963 pub facility_count: u32,
11964}
11965
11966fn default_water_facility_count() -> u32 {
11967 3
11968}
11969
11970impl Default for WaterSchemaConfig {
11971 fn default() -> Self {
11972 Self {
11973 enabled: true,
11974 facility_count: default_water_facility_count(),
11975 }
11976 }
11977}
11978
11979#[derive(Debug, Clone, Serialize, Deserialize)]
11981pub struct WasteSchemaConfig {
11982 #[serde(default = "default_true")]
11984 pub enabled: bool,
11985 #[serde(default = "default_diversion_target")]
11987 pub diversion_target: f64,
11988}
11989
11990fn default_diversion_target() -> f64 {
11991 0.50
11992}
11993
11994impl Default for WasteSchemaConfig {
11995 fn default() -> Self {
11996 Self {
11997 enabled: true,
11998 diversion_target: default_diversion_target(),
11999 }
12000 }
12001}
12002
12003#[derive(Debug, Clone, Serialize, Deserialize)]
12005pub struct SocialConfig {
12006 #[serde(default = "default_true")]
12008 pub enabled: bool,
12009 #[serde(default)]
12011 pub diversity: DiversitySchemaConfig,
12012 #[serde(default)]
12014 pub pay_equity: PayEquitySchemaConfig,
12015 #[serde(default)]
12017 pub safety: SafetySchemaConfig,
12018}
12019
12020impl Default for SocialConfig {
12021 fn default() -> Self {
12022 Self {
12023 enabled: true,
12024 diversity: DiversitySchemaConfig::default(),
12025 pay_equity: PayEquitySchemaConfig::default(),
12026 safety: SafetySchemaConfig::default(),
12027 }
12028 }
12029}
12030
12031#[derive(Debug, Clone, Serialize, Deserialize)]
12033pub struct DiversitySchemaConfig {
12034 #[serde(default = "default_true")]
12036 pub enabled: bool,
12037 #[serde(default = "default_diversity_dimensions")]
12039 pub dimensions: Vec<String>,
12040}
12041
12042fn default_diversity_dimensions() -> Vec<String> {
12043 vec![
12044 "gender".to_string(),
12045 "ethnicity".to_string(),
12046 "age_group".to_string(),
12047 ]
12048}
12049
12050impl Default for DiversitySchemaConfig {
12051 fn default() -> Self {
12052 Self {
12053 enabled: true,
12054 dimensions: default_diversity_dimensions(),
12055 }
12056 }
12057}
12058
12059#[derive(Debug, Clone, Serialize, Deserialize)]
12061pub struct PayEquitySchemaConfig {
12062 #[serde(default = "default_true")]
12064 pub enabled: bool,
12065 #[serde(default = "default_pay_gap_threshold")]
12067 pub gap_threshold: f64,
12068}
12069
12070fn default_pay_gap_threshold() -> f64 {
12071 0.05
12072}
12073
12074impl Default for PayEquitySchemaConfig {
12075 fn default() -> Self {
12076 Self {
12077 enabled: true,
12078 gap_threshold: default_pay_gap_threshold(),
12079 }
12080 }
12081}
12082
12083#[derive(Debug, Clone, Serialize, Deserialize)]
12085pub struct SafetySchemaConfig {
12086 #[serde(default = "default_true")]
12088 pub enabled: bool,
12089 #[serde(default = "default_trir_target")]
12091 pub target_trir: f64,
12092 #[serde(default = "default_incident_count")]
12094 pub incident_count: u32,
12095}
12096
12097fn default_trir_target() -> f64 {
12098 2.5
12099}
12100
12101fn default_incident_count() -> u32 {
12102 20
12103}
12104
12105impl Default for SafetySchemaConfig {
12106 fn default() -> Self {
12107 Self {
12108 enabled: true,
12109 target_trir: default_trir_target(),
12110 incident_count: default_incident_count(),
12111 }
12112 }
12113}
12114
12115#[derive(Debug, Clone, Serialize, Deserialize)]
12117pub struct GovernanceSchemaConfig {
12118 #[serde(default = "default_true")]
12120 pub enabled: bool,
12121 #[serde(default = "default_board_size")]
12123 pub board_size: u32,
12124 #[serde(default = "default_independence_target")]
12126 pub independence_target: f64,
12127}
12128
12129fn default_board_size() -> u32 {
12130 11
12131}
12132
12133fn default_independence_target() -> f64 {
12134 0.67
12135}
12136
12137impl Default for GovernanceSchemaConfig {
12138 fn default() -> Self {
12139 Self {
12140 enabled: true,
12141 board_size: default_board_size(),
12142 independence_target: default_independence_target(),
12143 }
12144 }
12145}
12146
12147#[derive(Debug, Clone, Serialize, Deserialize)]
12149pub struct SupplyChainEsgConfig {
12150 #[serde(default = "default_true")]
12152 pub enabled: bool,
12153 #[serde(default = "default_assessment_coverage")]
12155 pub assessment_coverage: f64,
12156 #[serde(default = "default_high_risk_countries")]
12158 pub high_risk_countries: Vec<String>,
12159}
12160
12161fn default_assessment_coverage() -> f64 {
12162 0.80
12163}
12164
12165fn default_high_risk_countries() -> Vec<String> {
12166 vec!["CN".to_string(), "BD".to_string(), "MM".to_string()]
12167}
12168
12169impl Default for SupplyChainEsgConfig {
12170 fn default() -> Self {
12171 Self {
12172 enabled: true,
12173 assessment_coverage: default_assessment_coverage(),
12174 high_risk_countries: default_high_risk_countries(),
12175 }
12176 }
12177}
12178
12179#[derive(Debug, Clone, Serialize, Deserialize)]
12181pub struct EsgReportingConfig {
12182 #[serde(default = "default_true")]
12184 pub enabled: bool,
12185 #[serde(default = "default_esg_frameworks")]
12187 pub frameworks: Vec<String>,
12188 #[serde(default = "default_true")]
12190 pub materiality_assessment: bool,
12191 #[serde(default = "default_materiality_threshold")]
12193 pub impact_threshold: f64,
12194 #[serde(default = "default_materiality_threshold")]
12196 pub financial_threshold: f64,
12197}
12198
12199fn default_esg_frameworks() -> Vec<String> {
12200 vec!["GRI".to_string(), "ESRS".to_string()]
12201}
12202
12203fn default_materiality_threshold() -> f64 {
12204 0.6
12205}
12206
12207impl Default for EsgReportingConfig {
12208 fn default() -> Self {
12209 Self {
12210 enabled: true,
12211 frameworks: default_esg_frameworks(),
12212 materiality_assessment: true,
12213 impact_threshold: default_materiality_threshold(),
12214 financial_threshold: default_materiality_threshold(),
12215 }
12216 }
12217}
12218
12219#[derive(Debug, Clone, Serialize, Deserialize)]
12221pub struct ClimateScenarioConfig {
12222 #[serde(default)]
12224 pub enabled: bool,
12225 #[serde(default = "default_climate_scenarios")]
12227 pub scenarios: Vec<String>,
12228 #[serde(default = "default_time_horizons")]
12230 pub time_horizons: Vec<u32>,
12231}
12232
12233fn default_climate_scenarios() -> Vec<String> {
12234 vec![
12235 "net_zero_2050".to_string(),
12236 "stated_policies".to_string(),
12237 "current_trajectory".to_string(),
12238 ]
12239}
12240
12241fn default_time_horizons() -> Vec<u32> {
12242 vec![5, 10, 30]
12243}
12244
12245impl Default for ClimateScenarioConfig {
12246 fn default() -> Self {
12247 Self {
12248 enabled: false,
12249 scenarios: default_climate_scenarios(),
12250 time_horizons: default_time_horizons(),
12251 }
12252 }
12253}
12254
12255#[cfg(test)]
12256#[allow(clippy::unwrap_used)]
12257mod tests {
12258 use super::*;
12259 use crate::presets::demo_preset;
12260
12261 #[test]
12266 fn test_config_yaml_roundtrip() {
12267 let config = demo_preset();
12268 let yaml = serde_yaml::to_string(&config).expect("Failed to serialize to YAML");
12269 let deserialized: GeneratorConfig =
12270 serde_yaml::from_str(&yaml).expect("Failed to deserialize from YAML");
12271
12272 assert_eq!(
12273 config.global.period_months,
12274 deserialized.global.period_months
12275 );
12276 assert_eq!(config.global.industry, deserialized.global.industry);
12277 assert_eq!(config.companies.len(), deserialized.companies.len());
12278 assert_eq!(config.companies[0].code, deserialized.companies[0].code);
12279 }
12280
12281 #[test]
12282 fn test_config_json_roundtrip() {
12283 let mut config = demo_preset();
12285 config.master_data.employees.approval_limits.executive = 1e12;
12287
12288 let json = serde_json::to_string(&config).expect("Failed to serialize to JSON");
12289 let deserialized: GeneratorConfig =
12290 serde_json::from_str(&json).expect("Failed to deserialize from JSON");
12291
12292 assert_eq!(
12293 config.global.period_months,
12294 deserialized.global.period_months
12295 );
12296 assert_eq!(config.global.industry, deserialized.global.industry);
12297 assert_eq!(config.companies.len(), deserialized.companies.len());
12298 }
12299
12300 #[test]
12301 fn test_transaction_volume_serialization() {
12302 let volumes = vec![
12304 (TransactionVolume::TenK, "ten_k"),
12305 (TransactionVolume::HundredK, "hundred_k"),
12306 (TransactionVolume::OneM, "one_m"),
12307 (TransactionVolume::TenM, "ten_m"),
12308 (TransactionVolume::HundredM, "hundred_m"),
12309 ];
12310
12311 for (volume, expected_key) in volumes {
12312 let json = serde_json::to_string(&volume).expect("Failed to serialize");
12313 assert!(
12314 json.contains(expected_key),
12315 "Expected {} in JSON: {}",
12316 expected_key,
12317 json
12318 );
12319 }
12320 }
12321
12322 #[test]
12323 fn test_transaction_volume_custom_serialization() {
12324 let volume = TransactionVolume::Custom(12345);
12325 let json = serde_json::to_string(&volume).expect("Failed to serialize");
12326 let deserialized: TransactionVolume =
12327 serde_json::from_str(&json).expect("Failed to deserialize");
12328 assert_eq!(deserialized.count(), 12345);
12329 }
12330
12331 #[test]
12332 fn test_output_mode_serialization() {
12333 let modes = vec![
12334 OutputMode::Streaming,
12335 OutputMode::FlatFile,
12336 OutputMode::Both,
12337 ];
12338
12339 for mode in modes {
12340 let json = serde_json::to_string(&mode).expect("Failed to serialize");
12341 let deserialized: OutputMode =
12342 serde_json::from_str(&json).expect("Failed to deserialize");
12343 assert!(format!("{:?}", mode) == format!("{:?}", deserialized));
12344 }
12345 }
12346
12347 #[test]
12348 fn test_file_format_serialization() {
12349 let formats = vec![
12350 FileFormat::Csv,
12351 FileFormat::Parquet,
12352 FileFormat::Json,
12353 FileFormat::JsonLines,
12354 ];
12355
12356 for format in formats {
12357 let json = serde_json::to_string(&format).expect("Failed to serialize");
12358 let deserialized: FileFormat =
12359 serde_json::from_str(&json).expect("Failed to deserialize");
12360 assert!(format!("{:?}", format) == format!("{:?}", deserialized));
12361 }
12362 }
12363
12364 #[test]
12365 fn test_compression_algorithm_serialization() {
12366 let algos = vec![
12367 CompressionAlgorithm::Gzip,
12368 CompressionAlgorithm::Zstd,
12369 CompressionAlgorithm::Lz4,
12370 CompressionAlgorithm::Snappy,
12371 ];
12372
12373 for algo in algos {
12374 let json = serde_json::to_string(&algo).expect("Failed to serialize");
12375 let deserialized: CompressionAlgorithm =
12376 serde_json::from_str(&json).expect("Failed to deserialize");
12377 assert!(format!("{:?}", algo) == format!("{:?}", deserialized));
12378 }
12379 }
12380
12381 #[test]
12382 fn test_transfer_pricing_method_serialization() {
12383 let methods = vec![
12384 TransferPricingMethod::CostPlus,
12385 TransferPricingMethod::ComparableUncontrolled,
12386 TransferPricingMethod::ResalePrice,
12387 TransferPricingMethod::TransactionalNetMargin,
12388 TransferPricingMethod::ProfitSplit,
12389 ];
12390
12391 for method in methods {
12392 let json = serde_json::to_string(&method).expect("Failed to serialize");
12393 let deserialized: TransferPricingMethod =
12394 serde_json::from_str(&json).expect("Failed to deserialize");
12395 assert!(format!("{:?}", method) == format!("{:?}", deserialized));
12396 }
12397 }
12398
12399 #[test]
12400 fn test_benford_exemption_serialization() {
12401 let exemptions = vec![
12402 BenfordExemption::Recurring,
12403 BenfordExemption::Payroll,
12404 BenfordExemption::FixedFees,
12405 BenfordExemption::RoundAmounts,
12406 ];
12407
12408 for exemption in exemptions {
12409 let json = serde_json::to_string(&exemption).expect("Failed to serialize");
12410 let deserialized: BenfordExemption =
12411 serde_json::from_str(&json).expect("Failed to deserialize");
12412 assert!(format!("{:?}", exemption) == format!("{:?}", deserialized));
12413 }
12414 }
12415
12416 #[test]
12421 fn test_global_config_defaults() {
12422 let yaml = r#"
12423 industry: manufacturing
12424 start_date: "2024-01-01"
12425 period_months: 6
12426 "#;
12427 let config: GlobalConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12428 assert_eq!(config.group_currency, "USD");
12429 assert!(config.parallel);
12430 assert_eq!(config.worker_threads, 0);
12431 assert_eq!(config.memory_limit_mb, 0);
12432 }
12433
12434 #[test]
12435 fn test_fraud_config_defaults() {
12436 let config = FraudConfig::default();
12437 assert!(!config.enabled);
12438 assert_eq!(config.fraud_rate, 0.005);
12439 assert!(!config.clustering_enabled);
12440 }
12441
12442 #[test]
12443 fn test_internal_controls_config_defaults() {
12444 let config = InternalControlsConfig::default();
12445 assert!(!config.enabled);
12446 assert_eq!(config.exception_rate, 0.02);
12447 assert_eq!(config.sod_violation_rate, 0.01);
12448 assert!(config.export_control_master_data);
12449 assert_eq!(config.sox_materiality_threshold, 10000.0);
12450 assert!(config.coso_enabled);
12452 assert!(!config.include_entity_level_controls);
12453 assert_eq!(config.target_maturity_level, "mixed");
12454 }
12455
12456 #[test]
12457 fn test_output_config_defaults() {
12458 let config = OutputConfig::default();
12459 assert!(matches!(config.mode, OutputMode::FlatFile));
12460 assert_eq!(config.formats, vec![FileFormat::Parquet]);
12461 assert!(config.compression.enabled);
12462 assert!(matches!(
12463 config.compression.algorithm,
12464 CompressionAlgorithm::Zstd
12465 ));
12466 assert!(config.include_acdoca);
12467 assert!(!config.include_bseg);
12468 assert!(config.partition_by_period);
12469 assert!(!config.partition_by_company);
12470 }
12471
12472 #[test]
12473 fn test_approval_config_defaults() {
12474 let config = ApprovalConfig::default();
12475 assert!(!config.enabled);
12476 assert_eq!(config.auto_approve_threshold, 1000.0);
12477 assert_eq!(config.rejection_rate, 0.02);
12478 assert_eq!(config.revision_rate, 0.05);
12479 assert_eq!(config.average_approval_delay_hours, 4.0);
12480 assert_eq!(config.thresholds.len(), 4);
12481 }
12482
12483 #[test]
12484 fn test_p2p_flow_config_defaults() {
12485 let config = P2PFlowConfig::default();
12486 assert!(config.enabled);
12487 assert_eq!(config.three_way_match_rate, 0.95);
12488 assert_eq!(config.partial_delivery_rate, 0.15);
12489 assert_eq!(config.average_po_to_gr_days, 14);
12490 }
12491
12492 #[test]
12493 fn test_o2c_flow_config_defaults() {
12494 let config = O2CFlowConfig::default();
12495 assert!(config.enabled);
12496 assert_eq!(config.credit_check_failure_rate, 0.02);
12497 assert_eq!(config.return_rate, 0.03);
12498 assert_eq!(config.bad_debt_rate, 0.01);
12499 }
12500
12501 #[test]
12502 fn test_balance_config_defaults() {
12503 let config = BalanceConfig::default();
12504 assert!(!config.generate_opening_balances);
12505 assert!(config.generate_trial_balances);
12506 assert_eq!(config.target_gross_margin, 0.35);
12507 assert!(config.validate_balance_equation);
12508 assert!(config.reconcile_subledgers);
12509 }
12510
12511 #[test]
12516 fn test_partial_config_with_defaults() {
12517 let yaml = r#"
12519 global:
12520 industry: manufacturing
12521 start_date: "2024-01-01"
12522 period_months: 3
12523 companies:
12524 - code: "TEST"
12525 name: "Test Company"
12526 currency: "USD"
12527 country: "US"
12528 annual_transaction_volume: ten_k
12529 chart_of_accounts:
12530 complexity: small
12531 output:
12532 output_directory: "./output"
12533 "#;
12534
12535 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12536 assert_eq!(config.global.period_months, 3);
12537 assert_eq!(config.companies.len(), 1);
12538 assert!(!config.fraud.enabled); assert!(!config.internal_controls.enabled); }
12541
12542 #[test]
12543 fn test_config_with_fraud_enabled() {
12544 let yaml = r#"
12545 global:
12546 industry: retail
12547 start_date: "2024-01-01"
12548 period_months: 12
12549 companies:
12550 - code: "RETAIL"
12551 name: "Retail Co"
12552 currency: "USD"
12553 country: "US"
12554 annual_transaction_volume: hundred_k
12555 chart_of_accounts:
12556 complexity: medium
12557 output:
12558 output_directory: "./output"
12559 fraud:
12560 enabled: true
12561 fraud_rate: 0.05
12562 clustering_enabled: true
12563 "#;
12564
12565 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12566 assert!(config.fraud.enabled);
12567 assert_eq!(config.fraud.fraud_rate, 0.05);
12568 assert!(config.fraud.clustering_enabled);
12569 }
12570
12571 #[test]
12572 fn test_config_with_multiple_companies() {
12573 let yaml = r#"
12574 global:
12575 industry: manufacturing
12576 start_date: "2024-01-01"
12577 period_months: 6
12578 companies:
12579 - code: "HQ"
12580 name: "Headquarters"
12581 currency: "USD"
12582 country: "US"
12583 annual_transaction_volume: hundred_k
12584 volume_weight: 1.0
12585 - code: "EU"
12586 name: "European Subsidiary"
12587 currency: "EUR"
12588 country: "DE"
12589 annual_transaction_volume: hundred_k
12590 volume_weight: 0.5
12591 - code: "APAC"
12592 name: "Asia Pacific"
12593 currency: "JPY"
12594 country: "JP"
12595 annual_transaction_volume: ten_k
12596 volume_weight: 0.3
12597 chart_of_accounts:
12598 complexity: large
12599 output:
12600 output_directory: "./output"
12601 "#;
12602
12603 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12604 assert_eq!(config.companies.len(), 3);
12605 assert_eq!(config.companies[0].code, "HQ");
12606 assert_eq!(config.companies[1].currency, "EUR");
12607 assert_eq!(config.companies[2].volume_weight, 0.3);
12608 }
12609
12610 #[test]
12611 fn test_intercompany_config() {
12612 let yaml = r#"
12613 enabled: true
12614 ic_transaction_rate: 0.20
12615 transfer_pricing_method: cost_plus
12616 markup_percent: 0.08
12617 generate_matched_pairs: true
12618 generate_eliminations: true
12619 "#;
12620
12621 let config: IntercompanyConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12622 assert!(config.enabled);
12623 assert_eq!(config.ic_transaction_rate, 0.20);
12624 assert!(matches!(
12625 config.transfer_pricing_method,
12626 TransferPricingMethod::CostPlus
12627 ));
12628 assert_eq!(config.markup_percent, 0.08);
12629 assert!(config.generate_eliminations);
12630 }
12631
12632 #[test]
12637 fn test_company_config_defaults() {
12638 let yaml = r#"
12639 code: "TEST"
12640 name: "Test Company"
12641 currency: "USD"
12642 country: "US"
12643 annual_transaction_volume: ten_k
12644 "#;
12645
12646 let config: CompanyConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12647 assert_eq!(config.fiscal_year_variant, "K4"); assert_eq!(config.volume_weight, 1.0); }
12650
12651 #[test]
12656 fn test_coa_config_defaults() {
12657 let yaml = r#"
12658 complexity: medium
12659 "#;
12660
12661 let config: ChartOfAccountsConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12662 assert!(config.industry_specific); assert!(config.custom_accounts.is_none());
12664 assert_eq!(config.min_hierarchy_depth, 2); assert_eq!(config.max_hierarchy_depth, 5); }
12667
12668 #[test]
12673 fn test_accounting_standards_config_defaults() {
12674 let config = AccountingStandardsConfig::default();
12675 assert!(!config.enabled);
12676 assert!(config.framework.is_none());
12677 assert!(!config.revenue_recognition.enabled);
12678 assert!(!config.leases.enabled);
12679 assert!(!config.fair_value.enabled);
12680 assert!(!config.impairment.enabled);
12681 assert!(!config.generate_differences);
12682 }
12683
12684 #[test]
12685 fn test_accounting_standards_config_yaml() {
12686 let yaml = r#"
12687 enabled: true
12688 framework: ifrs
12689 revenue_recognition:
12690 enabled: true
12691 generate_contracts: true
12692 avg_obligations_per_contract: 2.5
12693 variable_consideration_rate: 0.20
12694 over_time_recognition_rate: 0.35
12695 contract_count: 150
12696 leases:
12697 enabled: true
12698 lease_count: 75
12699 finance_lease_percent: 0.25
12700 avg_lease_term_months: 48
12701 generate_differences: true
12702 "#;
12703
12704 let config: AccountingStandardsConfig =
12705 serde_yaml::from_str(yaml).expect("Failed to parse");
12706 assert!(config.enabled);
12707 assert!(matches!(
12708 config.framework,
12709 Some(AccountingFrameworkConfig::Ifrs)
12710 ));
12711 assert!(config.revenue_recognition.enabled);
12712 assert_eq!(config.revenue_recognition.contract_count, 150);
12713 assert_eq!(config.revenue_recognition.avg_obligations_per_contract, 2.5);
12714 assert!(config.leases.enabled);
12715 assert_eq!(config.leases.lease_count, 75);
12716 assert_eq!(config.leases.finance_lease_percent, 0.25);
12717 assert!(config.generate_differences);
12718 }
12719
12720 #[test]
12721 fn test_accounting_framework_serialization() {
12722 let frameworks = [
12723 AccountingFrameworkConfig::UsGaap,
12724 AccountingFrameworkConfig::Ifrs,
12725 AccountingFrameworkConfig::DualReporting,
12726 AccountingFrameworkConfig::FrenchGaap,
12727 AccountingFrameworkConfig::GermanGaap,
12728 ];
12729
12730 for framework in frameworks {
12731 let json = serde_json::to_string(&framework).expect("Failed to serialize");
12732 let deserialized: AccountingFrameworkConfig =
12733 serde_json::from_str(&json).expect("Failed to deserialize");
12734 assert!(format!("{:?}", framework) == format!("{:?}", deserialized));
12735 }
12736 }
12737
12738 #[test]
12739 fn test_revenue_recognition_config_defaults() {
12740 let config = RevenueRecognitionConfig::default();
12741 assert!(!config.enabled);
12742 assert!(config.generate_contracts);
12743 assert_eq!(config.avg_obligations_per_contract, 2.0);
12744 assert_eq!(config.variable_consideration_rate, 0.15);
12745 assert_eq!(config.over_time_recognition_rate, 0.30);
12746 assert_eq!(config.contract_count, 100);
12747 }
12748
12749 #[test]
12750 fn test_lease_accounting_config_defaults() {
12751 let config = LeaseAccountingConfig::default();
12752 assert!(!config.enabled);
12753 assert_eq!(config.lease_count, 50);
12754 assert_eq!(config.finance_lease_percent, 0.30);
12755 assert_eq!(config.avg_lease_term_months, 60);
12756 assert!(config.generate_amortization);
12757 assert_eq!(config.real_estate_percent, 0.40);
12758 }
12759
12760 #[test]
12761 fn test_fair_value_config_defaults() {
12762 let config = FairValueConfig::default();
12763 assert!(!config.enabled);
12764 assert_eq!(config.measurement_count, 25);
12765 assert_eq!(config.level1_percent, 0.40);
12766 assert_eq!(config.level2_percent, 0.35);
12767 assert_eq!(config.level3_percent, 0.25);
12768 assert!(!config.include_sensitivity_analysis);
12769 }
12770
12771 #[test]
12772 fn test_impairment_config_defaults() {
12773 let config = ImpairmentConfig::default();
12774 assert!(!config.enabled);
12775 assert_eq!(config.test_count, 15);
12776 assert_eq!(config.impairment_rate, 0.10);
12777 assert!(config.generate_projections);
12778 assert!(!config.include_goodwill);
12779 }
12780
12781 #[test]
12786 fn test_audit_standards_config_defaults() {
12787 let config = AuditStandardsConfig::default();
12788 assert!(!config.enabled);
12789 assert!(!config.isa_compliance.enabled);
12790 assert!(!config.analytical_procedures.enabled);
12791 assert!(!config.confirmations.enabled);
12792 assert!(!config.opinion.enabled);
12793 assert!(!config.generate_audit_trail);
12794 assert!(!config.sox.enabled);
12795 assert!(!config.pcaob.enabled);
12796 }
12797
12798 #[test]
12799 fn test_audit_standards_config_yaml() {
12800 let yaml = r#"
12801 enabled: true
12802 isa_compliance:
12803 enabled: true
12804 compliance_level: comprehensive
12805 generate_isa_mappings: true
12806 include_pcaob: true
12807 framework: dual
12808 analytical_procedures:
12809 enabled: true
12810 procedures_per_account: 5
12811 variance_probability: 0.25
12812 confirmations:
12813 enabled: true
12814 confirmation_count: 75
12815 positive_response_rate: 0.90
12816 exception_rate: 0.08
12817 opinion:
12818 enabled: true
12819 generate_kam: true
12820 average_kam_count: 4
12821 sox:
12822 enabled: true
12823 generate_302_certifications: true
12824 generate_404_assessments: true
12825 material_weakness_rate: 0.03
12826 pcaob:
12827 enabled: true
12828 is_pcaob_audit: true
12829 include_icfr_opinion: true
12830 generate_audit_trail: true
12831 "#;
12832
12833 let config: AuditStandardsConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12834 assert!(config.enabled);
12835 assert!(config.isa_compliance.enabled);
12836 assert_eq!(config.isa_compliance.compliance_level, "comprehensive");
12837 assert!(config.isa_compliance.include_pcaob);
12838 assert_eq!(config.isa_compliance.framework, "dual");
12839 assert!(config.analytical_procedures.enabled);
12840 assert_eq!(config.analytical_procedures.procedures_per_account, 5);
12841 assert!(config.confirmations.enabled);
12842 assert_eq!(config.confirmations.confirmation_count, 75);
12843 assert!(config.opinion.enabled);
12844 assert_eq!(config.opinion.average_kam_count, 4);
12845 assert!(config.sox.enabled);
12846 assert!(config.sox.generate_302_certifications);
12847 assert_eq!(config.sox.material_weakness_rate, 0.03);
12848 assert!(config.pcaob.enabled);
12849 assert!(config.pcaob.is_pcaob_audit);
12850 assert!(config.pcaob.include_icfr_opinion);
12851 assert!(config.generate_audit_trail);
12852 }
12853
12854 #[test]
12855 fn test_isa_compliance_config_defaults() {
12856 let config = IsaComplianceConfig::default();
12857 assert!(!config.enabled);
12858 assert_eq!(config.compliance_level, "standard");
12859 assert!(config.generate_isa_mappings);
12860 assert!(config.generate_coverage_summary);
12861 assert!(!config.include_pcaob);
12862 assert_eq!(config.framework, "isa");
12863 }
12864
12865 #[test]
12866 fn test_sox_compliance_config_defaults() {
12867 let config = SoxComplianceConfig::default();
12868 assert!(!config.enabled);
12869 assert!(config.generate_302_certifications);
12870 assert!(config.generate_404_assessments);
12871 assert_eq!(config.materiality_threshold, 10000.0);
12872 assert_eq!(config.material_weakness_rate, 0.02);
12873 assert_eq!(config.significant_deficiency_rate, 0.08);
12874 }
12875
12876 #[test]
12877 fn test_pcaob_config_defaults() {
12878 let config = PcaobConfig::default();
12879 assert!(!config.enabled);
12880 assert!(!config.is_pcaob_audit);
12881 assert!(config.generate_cam);
12882 assert!(!config.include_icfr_opinion);
12883 assert!(!config.generate_standard_mappings);
12884 }
12885
12886 #[test]
12887 fn test_config_with_standards_enabled() {
12888 let yaml = r#"
12889 global:
12890 industry: financial_services
12891 start_date: "2024-01-01"
12892 period_months: 12
12893 companies:
12894 - code: "BANK"
12895 name: "Test Bank"
12896 currency: "USD"
12897 country: "US"
12898 annual_transaction_volume: hundred_k
12899 chart_of_accounts:
12900 complexity: large
12901 output:
12902 output_directory: "./output"
12903 accounting_standards:
12904 enabled: true
12905 framework: us_gaap
12906 revenue_recognition:
12907 enabled: true
12908 leases:
12909 enabled: true
12910 audit_standards:
12911 enabled: true
12912 isa_compliance:
12913 enabled: true
12914 sox:
12915 enabled: true
12916 "#;
12917
12918 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12919 assert!(config.accounting_standards.enabled);
12920 assert!(matches!(
12921 config.accounting_standards.framework,
12922 Some(AccountingFrameworkConfig::UsGaap)
12923 ));
12924 assert!(config.accounting_standards.revenue_recognition.enabled);
12925 assert!(config.accounting_standards.leases.enabled);
12926 assert!(config.audit_standards.enabled);
12927 assert!(config.audit_standards.isa_compliance.enabled);
12928 assert!(config.audit_standards.sox.enabled);
12929 }
12930
12931 #[test]
12936 fn test_industry_specific_config_defaults() {
12937 let config = IndustrySpecificConfig::default();
12938 assert!(!config.enabled);
12939 assert!(!config.manufacturing.enabled);
12940 assert!(!config.retail.enabled);
12941 assert!(!config.healthcare.enabled);
12942 assert!(!config.technology.enabled);
12943 assert!(!config.financial_services.enabled);
12944 assert!(!config.professional_services.enabled);
12945 }
12946
12947 #[test]
12948 fn test_manufacturing_config_defaults() {
12949 let config = ManufacturingConfig::default();
12950 assert!(!config.enabled);
12951 assert_eq!(config.bom_depth, 4);
12952 assert!(!config.just_in_time);
12953 assert_eq!(config.supplier_tiers, 2);
12954 assert_eq!(config.target_yield_rate, 0.97);
12955 assert_eq!(config.scrap_alert_threshold, 0.03);
12956 }
12957
12958 #[test]
12959 fn test_retail_config_defaults() {
12960 let config = RetailConfig::default();
12961 assert!(!config.enabled);
12962 assert_eq!(config.avg_daily_transactions, 500);
12963 assert!(config.loss_prevention);
12964 assert_eq!(config.shrinkage_rate, 0.015);
12965 }
12966
12967 #[test]
12968 fn test_healthcare_config_defaults() {
12969 let config = HealthcareConfig::default();
12970 assert!(!config.enabled);
12971 assert_eq!(config.facility_type, "hospital");
12972 assert_eq!(config.avg_daily_encounters, 150);
12973 assert!(config.compliance.hipaa);
12974 assert!(config.compliance.stark_law);
12975 assert!(config.coding_systems.icd10);
12976 assert!(config.coding_systems.cpt);
12977 }
12978
12979 #[test]
12980 fn test_technology_config_defaults() {
12981 let config = TechnologyConfig::default();
12982 assert!(!config.enabled);
12983 assert_eq!(config.revenue_model, "saas");
12984 assert_eq!(config.subscription_revenue_pct, 0.60);
12985 assert!(config.rd_capitalization.enabled);
12986 }
12987
12988 #[test]
12989 fn test_config_with_industry_specific() {
12990 let yaml = r#"
12991 global:
12992 industry: healthcare
12993 start_date: "2024-01-01"
12994 period_months: 12
12995 companies:
12996 - code: "HOSP"
12997 name: "Test Hospital"
12998 currency: "USD"
12999 country: "US"
13000 annual_transaction_volume: hundred_k
13001 chart_of_accounts:
13002 complexity: medium
13003 output:
13004 output_directory: "./output"
13005 industry_specific:
13006 enabled: true
13007 healthcare:
13008 enabled: true
13009 facility_type: hospital
13010 payer_mix:
13011 medicare: 0.45
13012 medicaid: 0.15
13013 commercial: 0.35
13014 self_pay: 0.05
13015 coding_systems:
13016 icd10: true
13017 cpt: true
13018 drg: true
13019 compliance:
13020 hipaa: true
13021 stark_law: true
13022 anomaly_rates:
13023 upcoding: 0.03
13024 unbundling: 0.02
13025 "#;
13026
13027 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13028 assert!(config.industry_specific.enabled);
13029 assert!(config.industry_specific.healthcare.enabled);
13030 assert_eq!(
13031 config.industry_specific.healthcare.facility_type,
13032 "hospital"
13033 );
13034 assert_eq!(config.industry_specific.healthcare.payer_mix.medicare, 0.45);
13035 assert_eq!(config.industry_specific.healthcare.payer_mix.self_pay, 0.05);
13036 assert!(config.industry_specific.healthcare.coding_systems.icd10);
13037 assert!(config.industry_specific.healthcare.compliance.hipaa);
13038 assert_eq!(
13039 config.industry_specific.healthcare.anomaly_rates.upcoding,
13040 0.03
13041 );
13042 }
13043
13044 #[test]
13045 fn test_config_with_manufacturing_specific() {
13046 let yaml = r#"
13047 global:
13048 industry: manufacturing
13049 start_date: "2024-01-01"
13050 period_months: 12
13051 companies:
13052 - code: "MFG"
13053 name: "Test Manufacturing"
13054 currency: "USD"
13055 country: "US"
13056 annual_transaction_volume: hundred_k
13057 chart_of_accounts:
13058 complexity: medium
13059 output:
13060 output_directory: "./output"
13061 industry_specific:
13062 enabled: true
13063 manufacturing:
13064 enabled: true
13065 bom_depth: 5
13066 just_in_time: true
13067 supplier_tiers: 3
13068 target_yield_rate: 0.98
13069 anomaly_rates:
13070 yield_manipulation: 0.02
13071 phantom_production: 0.01
13072 "#;
13073
13074 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13075 assert!(config.industry_specific.enabled);
13076 assert!(config.industry_specific.manufacturing.enabled);
13077 assert_eq!(config.industry_specific.manufacturing.bom_depth, 5);
13078 assert!(config.industry_specific.manufacturing.just_in_time);
13079 assert_eq!(config.industry_specific.manufacturing.supplier_tiers, 3);
13080 assert_eq!(
13081 config.industry_specific.manufacturing.target_yield_rate,
13082 0.98
13083 );
13084 assert_eq!(
13085 config
13086 .industry_specific
13087 .manufacturing
13088 .anomaly_rates
13089 .yield_manipulation,
13090 0.02
13091 );
13092 }
13093
13094 #[test]
13099 fn test_tax_config_defaults() {
13100 let tax = TaxConfig::default();
13101 assert!(!tax.enabled);
13102 assert!(tax.jurisdictions.countries.is_empty());
13103 assert!(!tax.jurisdictions.include_subnational);
13104 assert!(!tax.vat_gst.enabled);
13105 assert!(tax.vat_gst.standard_rates.is_empty());
13106 assert!(tax.vat_gst.reduced_rates.is_empty());
13107 assert!(tax.vat_gst.exempt_categories.is_empty());
13108 assert!(tax.vat_gst.reverse_charge);
13109 assert!(!tax.sales_tax.enabled);
13110 assert!(tax.sales_tax.nexus_states.is_empty());
13111 assert!(!tax.withholding.enabled);
13112 assert!(tax.withholding.treaty_network);
13113 assert_eq!(tax.withholding.default_rate, 0.30);
13114 assert_eq!(tax.withholding.treaty_reduced_rate, 0.15);
13115 assert!(tax.provisions.enabled);
13116 assert_eq!(tax.provisions.statutory_rate, 0.21);
13117 assert!(tax.provisions.uncertain_positions);
13118 assert!(!tax.payroll_tax.enabled);
13119 assert_eq!(tax.anomaly_rate, 0.03);
13120 }
13121
13122 #[test]
13123 fn test_tax_config_from_yaml() {
13124 let yaml = r#"
13125 global:
13126 seed: 42
13127 start_date: "2024-01-01"
13128 period_months: 12
13129 industry: retail
13130 companies:
13131 - code: C001
13132 name: Test Corp
13133 currency: USD
13134 country: US
13135 annual_transaction_volume: ten_k
13136 chart_of_accounts:
13137 complexity: small
13138 output:
13139 output_directory: ./output
13140 tax:
13141 enabled: true
13142 anomaly_rate: 0.05
13143 jurisdictions:
13144 countries: ["US", "DE", "GB"]
13145 include_subnational: true
13146 vat_gst:
13147 enabled: true
13148 standard_rates:
13149 DE: 0.19
13150 GB: 0.20
13151 reduced_rates:
13152 DE: 0.07
13153 GB: 0.05
13154 exempt_categories:
13155 - financial_services
13156 - healthcare
13157 reverse_charge: false
13158 sales_tax:
13159 enabled: true
13160 nexus_states: ["CA", "NY", "TX"]
13161 withholding:
13162 enabled: true
13163 treaty_network: false
13164 default_rate: 0.25
13165 treaty_reduced_rate: 0.10
13166 provisions:
13167 enabled: false
13168 statutory_rate: 0.28
13169 uncertain_positions: false
13170 payroll_tax:
13171 enabled: true
13172 "#;
13173
13174 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13175 assert!(config.tax.enabled);
13176 assert_eq!(config.tax.anomaly_rate, 0.05);
13177
13178 assert_eq!(config.tax.jurisdictions.countries.len(), 3);
13180 assert!(config
13181 .tax
13182 .jurisdictions
13183 .countries
13184 .contains(&"DE".to_string()));
13185 assert!(config.tax.jurisdictions.include_subnational);
13186
13187 assert!(config.tax.vat_gst.enabled);
13189 assert_eq!(config.tax.vat_gst.standard_rates.get("DE"), Some(&0.19));
13190 assert_eq!(config.tax.vat_gst.standard_rates.get("GB"), Some(&0.20));
13191 assert_eq!(config.tax.vat_gst.reduced_rates.get("DE"), Some(&0.07));
13192 assert_eq!(config.tax.vat_gst.exempt_categories.len(), 2);
13193 assert!(!config.tax.vat_gst.reverse_charge);
13194
13195 assert!(config.tax.sales_tax.enabled);
13197 assert_eq!(config.tax.sales_tax.nexus_states.len(), 3);
13198 assert!(config
13199 .tax
13200 .sales_tax
13201 .nexus_states
13202 .contains(&"CA".to_string()));
13203
13204 assert!(config.tax.withholding.enabled);
13206 assert!(!config.tax.withholding.treaty_network);
13207 assert_eq!(config.tax.withholding.default_rate, 0.25);
13208 assert_eq!(config.tax.withholding.treaty_reduced_rate, 0.10);
13209
13210 assert!(!config.tax.provisions.enabled);
13212 assert_eq!(config.tax.provisions.statutory_rate, 0.28);
13213 assert!(!config.tax.provisions.uncertain_positions);
13214
13215 assert!(config.tax.payroll_tax.enabled);
13217 }
13218
13219 #[test]
13220 fn test_generator_config_with_tax_default() {
13221 let yaml = r#"
13222 global:
13223 seed: 42
13224 start_date: "2024-01-01"
13225 period_months: 12
13226 industry: retail
13227 companies:
13228 - code: C001
13229 name: Test Corp
13230 currency: USD
13231 country: US
13232 annual_transaction_volume: ten_k
13233 chart_of_accounts:
13234 complexity: small
13235 output:
13236 output_directory: ./output
13237 "#;
13238
13239 let config: GeneratorConfig =
13240 serde_yaml::from_str(yaml).expect("Failed to parse config without tax section");
13241 assert!(!config.tax.enabled);
13243 assert!(config.tax.jurisdictions.countries.is_empty());
13244 assert_eq!(config.tax.anomaly_rate, 0.03);
13245 assert!(config.tax.provisions.enabled); assert_eq!(config.tax.provisions.statutory_rate, 0.21);
13247 }
13248}