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 #[serde(default)]
2664 pub over_delivery_rate: Option<f64>,
2665 #[serde(default)]
2667 pub early_payment_discount_rate: Option<f64>,
2668}
2669
2670fn default_three_way_match_rate() -> f64 {
2671 0.95
2672}
2673
2674fn default_partial_delivery_rate() -> f64 {
2675 0.15
2676}
2677
2678fn default_price_variance_rate() -> f64 {
2679 0.08
2680}
2681
2682fn default_max_price_variance() -> f64 {
2683 0.05
2684}
2685
2686fn default_quantity_variance_rate() -> f64 {
2687 0.05
2688}
2689
2690fn default_po_to_gr_days() -> u32 {
2691 14
2692}
2693
2694fn default_gr_to_invoice_days() -> u32 {
2695 5
2696}
2697
2698fn default_invoice_to_payment_days() -> u32 {
2699 30
2700}
2701
2702impl Default for P2PFlowConfig {
2703 fn default() -> Self {
2704 Self {
2705 enabled: true,
2706 three_way_match_rate: default_three_way_match_rate(),
2707 partial_delivery_rate: default_partial_delivery_rate(),
2708 price_variance_rate: default_price_variance_rate(),
2709 max_price_variance_percent: default_max_price_variance(),
2710 quantity_variance_rate: default_quantity_variance_rate(),
2711 average_po_to_gr_days: default_po_to_gr_days(),
2712 average_gr_to_invoice_days: default_gr_to_invoice_days(),
2713 average_invoice_to_payment_days: default_invoice_to_payment_days(),
2714 line_count_distribution: DocumentLineCountDistribution::default(),
2715 payment_behavior: P2PPaymentBehaviorConfig::default(),
2716 over_delivery_rate: None,
2717 early_payment_discount_rate: None,
2718 }
2719 }
2720}
2721
2722#[derive(Debug, Clone, Serialize, Deserialize)]
2728pub struct P2PPaymentBehaviorConfig {
2729 #[serde(default = "default_p2p_late_payment_rate")]
2731 pub late_payment_rate: f64,
2732 #[serde(default)]
2734 pub late_payment_days_distribution: LatePaymentDaysDistribution,
2735 #[serde(default = "default_p2p_partial_payment_rate")]
2737 pub partial_payment_rate: f64,
2738 #[serde(default = "default_p2p_payment_correction_rate")]
2740 pub payment_correction_rate: f64,
2741 #[serde(default = "default_p2p_avg_days_until_remainder")]
2743 pub avg_days_until_remainder: u32,
2744}
2745
2746fn default_p2p_late_payment_rate() -> f64 {
2747 0.15
2748}
2749
2750fn default_p2p_partial_payment_rate() -> f64 {
2751 0.05
2752}
2753
2754fn default_p2p_payment_correction_rate() -> f64 {
2755 0.02
2756}
2757
2758fn default_p2p_avg_days_until_remainder() -> u32 {
2759 30
2760}
2761
2762impl Default for P2PPaymentBehaviorConfig {
2763 fn default() -> Self {
2764 Self {
2765 late_payment_rate: default_p2p_late_payment_rate(),
2766 late_payment_days_distribution: LatePaymentDaysDistribution::default(),
2767 partial_payment_rate: default_p2p_partial_payment_rate(),
2768 payment_correction_rate: default_p2p_payment_correction_rate(),
2769 avg_days_until_remainder: default_p2p_avg_days_until_remainder(),
2770 }
2771 }
2772}
2773
2774#[derive(Debug, Clone, Serialize, Deserialize)]
2776pub struct LatePaymentDaysDistribution {
2777 #[serde(default = "default_slightly_late")]
2779 pub slightly_late_1_to_7: f64,
2780 #[serde(default = "default_late_8_14")]
2782 pub late_8_to_14: f64,
2783 #[serde(default = "default_very_late")]
2785 pub very_late_15_to_30: f64,
2786 #[serde(default = "default_severely_late")]
2788 pub severely_late_31_to_60: f64,
2789 #[serde(default = "default_extremely_late")]
2791 pub extremely_late_over_60: f64,
2792}
2793
2794fn default_slightly_late() -> f64 {
2795 0.50
2796}
2797
2798fn default_late_8_14() -> f64 {
2799 0.25
2800}
2801
2802fn default_very_late() -> f64 {
2803 0.15
2804}
2805
2806fn default_severely_late() -> f64 {
2807 0.07
2808}
2809
2810fn default_extremely_late() -> f64 {
2811 0.03
2812}
2813
2814impl Default for LatePaymentDaysDistribution {
2815 fn default() -> Self {
2816 Self {
2817 slightly_late_1_to_7: default_slightly_late(),
2818 late_8_to_14: default_late_8_14(),
2819 very_late_15_to_30: default_very_late(),
2820 severely_late_31_to_60: default_severely_late(),
2821 extremely_late_over_60: default_extremely_late(),
2822 }
2823 }
2824}
2825
2826#[derive(Debug, Clone, Serialize, Deserialize)]
2828pub struct O2CFlowConfig {
2829 #[serde(default = "default_true")]
2831 pub enabled: bool,
2832 #[serde(default = "default_credit_check_failure_rate")]
2834 pub credit_check_failure_rate: f64,
2835 #[serde(default = "default_partial_shipment_rate")]
2837 pub partial_shipment_rate: f64,
2838 #[serde(default = "default_return_rate")]
2840 pub return_rate: f64,
2841 #[serde(default = "default_bad_debt_rate")]
2843 pub bad_debt_rate: f64,
2844 #[serde(default = "default_so_to_delivery_days")]
2846 pub average_so_to_delivery_days: u32,
2847 #[serde(default = "default_delivery_to_invoice_days")]
2849 pub average_delivery_to_invoice_days: u32,
2850 #[serde(default = "default_invoice_to_receipt_days")]
2852 pub average_invoice_to_receipt_days: u32,
2853 #[serde(default)]
2855 pub line_count_distribution: DocumentLineCountDistribution,
2856 #[serde(default)]
2858 pub cash_discount: CashDiscountConfig,
2859 #[serde(default)]
2861 pub payment_behavior: O2CPaymentBehaviorConfig,
2862 #[serde(default)]
2864 pub late_payment_rate: Option<f64>,
2865}
2866
2867fn default_credit_check_failure_rate() -> f64 {
2868 0.02
2869}
2870
2871fn default_partial_shipment_rate() -> f64 {
2872 0.10
2873}
2874
2875fn default_return_rate() -> f64 {
2876 0.03
2877}
2878
2879fn default_bad_debt_rate() -> f64 {
2880 0.01
2881}
2882
2883fn default_so_to_delivery_days() -> u32 {
2884 7
2885}
2886
2887fn default_delivery_to_invoice_days() -> u32 {
2888 1
2889}
2890
2891fn default_invoice_to_receipt_days() -> u32 {
2892 45
2893}
2894
2895impl Default for O2CFlowConfig {
2896 fn default() -> Self {
2897 Self {
2898 enabled: true,
2899 credit_check_failure_rate: default_credit_check_failure_rate(),
2900 partial_shipment_rate: default_partial_shipment_rate(),
2901 return_rate: default_return_rate(),
2902 bad_debt_rate: default_bad_debt_rate(),
2903 average_so_to_delivery_days: default_so_to_delivery_days(),
2904 average_delivery_to_invoice_days: default_delivery_to_invoice_days(),
2905 average_invoice_to_receipt_days: default_invoice_to_receipt_days(),
2906 line_count_distribution: DocumentLineCountDistribution::default(),
2907 cash_discount: CashDiscountConfig::default(),
2908 payment_behavior: O2CPaymentBehaviorConfig::default(),
2909 late_payment_rate: None,
2910 }
2911 }
2912}
2913
2914#[derive(Debug, Clone, Serialize, Deserialize, Default)]
2920pub struct O2CPaymentBehaviorConfig {
2921 #[serde(default)]
2923 pub dunning: DunningConfig,
2924 #[serde(default)]
2926 pub partial_payments: PartialPaymentConfig,
2927 #[serde(default)]
2929 pub short_payments: ShortPaymentConfig,
2930 #[serde(default)]
2932 pub on_account_payments: OnAccountPaymentConfig,
2933 #[serde(default)]
2935 pub payment_corrections: PaymentCorrectionConfig,
2936}
2937
2938#[derive(Debug, Clone, Serialize, Deserialize)]
2940pub struct DunningConfig {
2941 #[serde(default)]
2943 pub enabled: bool,
2944 #[serde(default = "default_dunning_level_1_days")]
2946 pub level_1_days_overdue: u32,
2947 #[serde(default = "default_dunning_level_2_days")]
2949 pub level_2_days_overdue: u32,
2950 #[serde(default = "default_dunning_level_3_days")]
2952 pub level_3_days_overdue: u32,
2953 #[serde(default = "default_collection_days")]
2955 pub collection_days_overdue: u32,
2956 #[serde(default)]
2958 pub payment_after_dunning_rates: DunningPaymentRates,
2959 #[serde(default = "default_dunning_block_rate")]
2961 pub dunning_block_rate: f64,
2962 #[serde(default = "default_dunning_interest_rate")]
2964 pub interest_rate_per_year: f64,
2965 #[serde(default = "default_dunning_charge")]
2967 pub dunning_charge: f64,
2968}
2969
2970fn default_dunning_level_1_days() -> u32 {
2971 14
2972}
2973
2974fn default_dunning_level_2_days() -> u32 {
2975 28
2976}
2977
2978fn default_dunning_level_3_days() -> u32 {
2979 42
2980}
2981
2982fn default_collection_days() -> u32 {
2983 60
2984}
2985
2986fn default_dunning_block_rate() -> f64 {
2987 0.05
2988}
2989
2990fn default_dunning_interest_rate() -> f64 {
2991 0.09
2992}
2993
2994fn default_dunning_charge() -> f64 {
2995 25.0
2996}
2997
2998impl Default for DunningConfig {
2999 fn default() -> Self {
3000 Self {
3001 enabled: false,
3002 level_1_days_overdue: default_dunning_level_1_days(),
3003 level_2_days_overdue: default_dunning_level_2_days(),
3004 level_3_days_overdue: default_dunning_level_3_days(),
3005 collection_days_overdue: default_collection_days(),
3006 payment_after_dunning_rates: DunningPaymentRates::default(),
3007 dunning_block_rate: default_dunning_block_rate(),
3008 interest_rate_per_year: default_dunning_interest_rate(),
3009 dunning_charge: default_dunning_charge(),
3010 }
3011 }
3012}
3013
3014#[derive(Debug, Clone, Serialize, Deserialize)]
3016pub struct DunningPaymentRates {
3017 #[serde(default = "default_after_level_1")]
3019 pub after_level_1: f64,
3020 #[serde(default = "default_after_level_2")]
3022 pub after_level_2: f64,
3023 #[serde(default = "default_after_level_3")]
3025 pub after_level_3: f64,
3026 #[serde(default = "default_during_collection")]
3028 pub during_collection: f64,
3029 #[serde(default = "default_never_pay")]
3031 pub never_pay: f64,
3032}
3033
3034fn default_after_level_1() -> f64 {
3035 0.40
3036}
3037
3038fn default_after_level_2() -> f64 {
3039 0.30
3040}
3041
3042fn default_after_level_3() -> f64 {
3043 0.15
3044}
3045
3046fn default_during_collection() -> f64 {
3047 0.05
3048}
3049
3050fn default_never_pay() -> f64 {
3051 0.10
3052}
3053
3054impl Default for DunningPaymentRates {
3055 fn default() -> Self {
3056 Self {
3057 after_level_1: default_after_level_1(),
3058 after_level_2: default_after_level_2(),
3059 after_level_3: default_after_level_3(),
3060 during_collection: default_during_collection(),
3061 never_pay: default_never_pay(),
3062 }
3063 }
3064}
3065
3066#[derive(Debug, Clone, Serialize, Deserialize)]
3068pub struct PartialPaymentConfig {
3069 #[serde(default = "default_partial_payment_rate")]
3071 pub rate: f64,
3072 #[serde(default)]
3074 pub percentage_distribution: PartialPaymentPercentageDistribution,
3075 #[serde(default = "default_avg_days_until_remainder")]
3077 pub avg_days_until_remainder: u32,
3078}
3079
3080fn default_partial_payment_rate() -> f64 {
3081 0.08
3082}
3083
3084fn default_avg_days_until_remainder() -> u32 {
3085 30
3086}
3087
3088impl Default for PartialPaymentConfig {
3089 fn default() -> Self {
3090 Self {
3091 rate: default_partial_payment_rate(),
3092 percentage_distribution: PartialPaymentPercentageDistribution::default(),
3093 avg_days_until_remainder: default_avg_days_until_remainder(),
3094 }
3095 }
3096}
3097
3098#[derive(Debug, Clone, Serialize, Deserialize)]
3100pub struct PartialPaymentPercentageDistribution {
3101 #[serde(default = "default_partial_25")]
3103 pub pay_25_percent: f64,
3104 #[serde(default = "default_partial_50")]
3106 pub pay_50_percent: f64,
3107 #[serde(default = "default_partial_75")]
3109 pub pay_75_percent: f64,
3110 #[serde(default = "default_partial_random")]
3112 pub pay_random_percent: f64,
3113}
3114
3115fn default_partial_25() -> f64 {
3116 0.15
3117}
3118
3119fn default_partial_50() -> f64 {
3120 0.50
3121}
3122
3123fn default_partial_75() -> f64 {
3124 0.25
3125}
3126
3127fn default_partial_random() -> f64 {
3128 0.10
3129}
3130
3131impl Default for PartialPaymentPercentageDistribution {
3132 fn default() -> Self {
3133 Self {
3134 pay_25_percent: default_partial_25(),
3135 pay_50_percent: default_partial_50(),
3136 pay_75_percent: default_partial_75(),
3137 pay_random_percent: default_partial_random(),
3138 }
3139 }
3140}
3141
3142#[derive(Debug, Clone, Serialize, Deserialize)]
3144pub struct ShortPaymentConfig {
3145 #[serde(default = "default_short_payment_rate")]
3147 pub rate: f64,
3148 #[serde(default)]
3150 pub reason_distribution: ShortPaymentReasonDistribution,
3151 #[serde(default = "default_max_short_percent")]
3153 pub max_short_percent: f64,
3154}
3155
3156fn default_short_payment_rate() -> f64 {
3157 0.03
3158}
3159
3160fn default_max_short_percent() -> f64 {
3161 0.10
3162}
3163
3164impl Default for ShortPaymentConfig {
3165 fn default() -> Self {
3166 Self {
3167 rate: default_short_payment_rate(),
3168 reason_distribution: ShortPaymentReasonDistribution::default(),
3169 max_short_percent: default_max_short_percent(),
3170 }
3171 }
3172}
3173
3174#[derive(Debug, Clone, Serialize, Deserialize)]
3176pub struct ShortPaymentReasonDistribution {
3177 #[serde(default = "default_pricing_dispute")]
3179 pub pricing_dispute: f64,
3180 #[serde(default = "default_quality_issue")]
3182 pub quality_issue: f64,
3183 #[serde(default = "default_quantity_discrepancy")]
3185 pub quantity_discrepancy: f64,
3186 #[serde(default = "default_unauthorized_deduction")]
3188 pub unauthorized_deduction: f64,
3189 #[serde(default = "default_incorrect_discount")]
3191 pub incorrect_discount: f64,
3192}
3193
3194fn default_pricing_dispute() -> f64 {
3195 0.30
3196}
3197
3198fn default_quality_issue() -> f64 {
3199 0.20
3200}
3201
3202fn default_quantity_discrepancy() -> f64 {
3203 0.20
3204}
3205
3206fn default_unauthorized_deduction() -> f64 {
3207 0.15
3208}
3209
3210fn default_incorrect_discount() -> f64 {
3211 0.15
3212}
3213
3214impl Default for ShortPaymentReasonDistribution {
3215 fn default() -> Self {
3216 Self {
3217 pricing_dispute: default_pricing_dispute(),
3218 quality_issue: default_quality_issue(),
3219 quantity_discrepancy: default_quantity_discrepancy(),
3220 unauthorized_deduction: default_unauthorized_deduction(),
3221 incorrect_discount: default_incorrect_discount(),
3222 }
3223 }
3224}
3225
3226#[derive(Debug, Clone, Serialize, Deserialize)]
3228pub struct OnAccountPaymentConfig {
3229 #[serde(default = "default_on_account_rate")]
3231 pub rate: f64,
3232 #[serde(default = "default_avg_days_until_applied")]
3234 pub avg_days_until_applied: u32,
3235}
3236
3237fn default_on_account_rate() -> f64 {
3238 0.02
3239}
3240
3241fn default_avg_days_until_applied() -> u32 {
3242 14
3243}
3244
3245impl Default for OnAccountPaymentConfig {
3246 fn default() -> Self {
3247 Self {
3248 rate: default_on_account_rate(),
3249 avg_days_until_applied: default_avg_days_until_applied(),
3250 }
3251 }
3252}
3253
3254#[derive(Debug, Clone, Serialize, Deserialize)]
3256pub struct PaymentCorrectionConfig {
3257 #[serde(default = "default_payment_correction_rate")]
3259 pub rate: f64,
3260 #[serde(default)]
3262 pub type_distribution: PaymentCorrectionTypeDistribution,
3263}
3264
3265fn default_payment_correction_rate() -> f64 {
3266 0.02
3267}
3268
3269impl Default for PaymentCorrectionConfig {
3270 fn default() -> Self {
3271 Self {
3272 rate: default_payment_correction_rate(),
3273 type_distribution: PaymentCorrectionTypeDistribution::default(),
3274 }
3275 }
3276}
3277
3278#[derive(Debug, Clone, Serialize, Deserialize)]
3280pub struct PaymentCorrectionTypeDistribution {
3281 #[serde(default = "default_nsf_rate")]
3283 pub nsf: f64,
3284 #[serde(default = "default_chargeback_rate")]
3286 pub chargeback: f64,
3287 #[serde(default = "default_wrong_amount_rate")]
3289 pub wrong_amount: f64,
3290 #[serde(default = "default_wrong_customer_rate")]
3292 pub wrong_customer: f64,
3293 #[serde(default = "default_duplicate_payment_rate")]
3295 pub duplicate_payment: f64,
3296}
3297
3298fn default_nsf_rate() -> f64 {
3299 0.30
3300}
3301
3302fn default_chargeback_rate() -> f64 {
3303 0.20
3304}
3305
3306fn default_wrong_amount_rate() -> f64 {
3307 0.20
3308}
3309
3310fn default_wrong_customer_rate() -> f64 {
3311 0.15
3312}
3313
3314fn default_duplicate_payment_rate() -> f64 {
3315 0.15
3316}
3317
3318impl Default for PaymentCorrectionTypeDistribution {
3319 fn default() -> Self {
3320 Self {
3321 nsf: default_nsf_rate(),
3322 chargeback: default_chargeback_rate(),
3323 wrong_amount: default_wrong_amount_rate(),
3324 wrong_customer: default_wrong_customer_rate(),
3325 duplicate_payment: default_duplicate_payment_rate(),
3326 }
3327 }
3328}
3329
3330#[derive(Debug, Clone, Serialize, Deserialize)]
3332pub struct DocumentLineCountDistribution {
3333 #[serde(default = "default_min_lines")]
3335 pub min_lines: u32,
3336 #[serde(default = "default_max_lines")]
3338 pub max_lines: u32,
3339 #[serde(default = "default_mode_lines")]
3341 pub mode_lines: u32,
3342}
3343
3344fn default_min_lines() -> u32 {
3345 1
3346}
3347
3348fn default_max_lines() -> u32 {
3349 20
3350}
3351
3352fn default_mode_lines() -> u32 {
3353 3
3354}
3355
3356impl Default for DocumentLineCountDistribution {
3357 fn default() -> Self {
3358 Self {
3359 min_lines: default_min_lines(),
3360 max_lines: default_max_lines(),
3361 mode_lines: default_mode_lines(),
3362 }
3363 }
3364}
3365
3366#[derive(Debug, Clone, Serialize, Deserialize)]
3368pub struct CashDiscountConfig {
3369 #[serde(default = "default_discount_eligible_rate")]
3371 pub eligible_rate: f64,
3372 #[serde(default = "default_discount_taken_rate")]
3374 pub taken_rate: f64,
3375 #[serde(default = "default_discount_percent")]
3377 pub discount_percent: f64,
3378 #[serde(default = "default_discount_days")]
3380 pub discount_days: u32,
3381}
3382
3383fn default_discount_eligible_rate() -> f64 {
3384 0.30
3385}
3386
3387fn default_discount_taken_rate() -> f64 {
3388 0.60
3389}
3390
3391fn default_discount_percent() -> f64 {
3392 0.02
3393}
3394
3395fn default_discount_days() -> u32 {
3396 10
3397}
3398
3399impl Default for CashDiscountConfig {
3400 fn default() -> Self {
3401 Self {
3402 eligible_rate: default_discount_eligible_rate(),
3403 taken_rate: default_discount_taken_rate(),
3404 discount_percent: default_discount_percent(),
3405 discount_days: default_discount_days(),
3406 }
3407 }
3408}
3409
3410#[derive(Debug, Clone, Serialize, Deserialize)]
3416pub struct IntercompanyConfig {
3417 #[serde(default)]
3419 pub enabled: bool,
3420 #[serde(default = "default_ic_transaction_rate")]
3422 pub ic_transaction_rate: f64,
3423 #[serde(default)]
3425 pub transfer_pricing_method: TransferPricingMethod,
3426 #[serde(default = "default_markup_percent")]
3428 pub markup_percent: f64,
3429 #[serde(default = "default_true")]
3431 pub generate_matched_pairs: bool,
3432 #[serde(default)]
3434 pub transaction_type_distribution: ICTransactionTypeDistribution,
3435 #[serde(default)]
3437 pub generate_eliminations: bool,
3438}
3439
3440fn default_ic_transaction_rate() -> f64 {
3441 0.15
3442}
3443
3444fn default_markup_percent() -> f64 {
3445 0.05
3446}
3447
3448impl Default for IntercompanyConfig {
3449 fn default() -> Self {
3450 Self {
3451 enabled: false,
3452 ic_transaction_rate: default_ic_transaction_rate(),
3453 transfer_pricing_method: TransferPricingMethod::default(),
3454 markup_percent: default_markup_percent(),
3455 generate_matched_pairs: true,
3456 transaction_type_distribution: ICTransactionTypeDistribution::default(),
3457 generate_eliminations: false,
3458 }
3459 }
3460}
3461
3462#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
3464#[serde(rename_all = "snake_case")]
3465pub enum TransferPricingMethod {
3466 #[default]
3468 CostPlus,
3469 ComparableUncontrolled,
3471 ResalePrice,
3473 TransactionalNetMargin,
3475 ProfitSplit,
3477}
3478
3479#[derive(Debug, Clone, Serialize, Deserialize)]
3481pub struct ICTransactionTypeDistribution {
3482 pub goods_sale: f64,
3484 pub service_provided: f64,
3486 pub loan: f64,
3488 pub dividend: f64,
3490 pub management_fee: f64,
3492 pub royalty: f64,
3494 pub cost_sharing: f64,
3496}
3497
3498impl Default for ICTransactionTypeDistribution {
3499 fn default() -> Self {
3500 Self {
3501 goods_sale: 0.35,
3502 service_provided: 0.20,
3503 loan: 0.10,
3504 dividend: 0.05,
3505 management_fee: 0.15,
3506 royalty: 0.10,
3507 cost_sharing: 0.05,
3508 }
3509 }
3510}
3511
3512#[derive(Debug, Clone, Serialize, Deserialize)]
3518pub struct BalanceConfig {
3519 #[serde(default)]
3521 pub generate_opening_balances: bool,
3522 #[serde(default = "default_true")]
3524 pub generate_trial_balances: bool,
3525 #[serde(default = "default_gross_margin")]
3527 pub target_gross_margin: f64,
3528 #[serde(default = "default_dso")]
3530 pub target_dso_days: u32,
3531 #[serde(default = "default_dpo")]
3533 pub target_dpo_days: u32,
3534 #[serde(default = "default_current_ratio")]
3536 pub target_current_ratio: f64,
3537 #[serde(default = "default_debt_equity")]
3539 pub target_debt_to_equity: f64,
3540 #[serde(default = "default_true")]
3542 pub validate_balance_equation: bool,
3543 #[serde(default = "default_true")]
3545 pub reconcile_subledgers: bool,
3546}
3547
3548fn default_gross_margin() -> f64 {
3549 0.35
3550}
3551
3552fn default_dso() -> u32 {
3553 45
3554}
3555
3556fn default_dpo() -> u32 {
3557 30
3558}
3559
3560fn default_current_ratio() -> f64 {
3561 1.5
3562}
3563
3564fn default_debt_equity() -> f64 {
3565 0.5
3566}
3567
3568impl Default for BalanceConfig {
3569 fn default() -> Self {
3570 Self {
3571 generate_opening_balances: false,
3572 generate_trial_balances: true,
3573 target_gross_margin: default_gross_margin(),
3574 target_dso_days: default_dso(),
3575 target_dpo_days: default_dpo(),
3576 target_current_ratio: default_current_ratio(),
3577 target_debt_to_equity: default_debt_equity(),
3578 validate_balance_equation: true,
3579 reconcile_subledgers: true,
3580 }
3581 }
3582}
3583
3584#[derive(Debug, Clone, Serialize, Deserialize)]
3593pub struct OcpmConfig {
3594 #[serde(default)]
3596 pub enabled: bool,
3597
3598 #[serde(default = "default_true")]
3600 pub generate_lifecycle_events: bool,
3601
3602 #[serde(default = "default_true")]
3604 pub include_object_relationships: bool,
3605
3606 #[serde(default = "default_true")]
3608 pub compute_variants: bool,
3609
3610 #[serde(default)]
3612 pub max_variants: usize,
3613
3614 #[serde(default)]
3616 pub p2p_process: OcpmProcessConfig,
3617
3618 #[serde(default)]
3620 pub o2c_process: OcpmProcessConfig,
3621
3622 #[serde(default)]
3624 pub output: OcpmOutputConfig,
3625}
3626
3627impl Default for OcpmConfig {
3628 fn default() -> Self {
3629 Self {
3630 enabled: false,
3631 generate_lifecycle_events: true,
3632 include_object_relationships: true,
3633 compute_variants: true,
3634 max_variants: 0,
3635 p2p_process: OcpmProcessConfig::default(),
3636 o2c_process: OcpmProcessConfig::default(),
3637 output: OcpmOutputConfig::default(),
3638 }
3639 }
3640}
3641
3642#[derive(Debug, Clone, Serialize, Deserialize)]
3644pub struct OcpmProcessConfig {
3645 #[serde(default = "default_rework_probability")]
3647 pub rework_probability: f64,
3648
3649 #[serde(default = "default_skip_probability")]
3651 pub skip_step_probability: f64,
3652
3653 #[serde(default = "default_out_of_order_probability")]
3655 pub out_of_order_probability: f64,
3656}
3657
3658fn default_rework_probability() -> f64 {
3659 0.05
3660}
3661
3662fn default_skip_probability() -> f64 {
3663 0.02
3664}
3665
3666fn default_out_of_order_probability() -> f64 {
3667 0.03
3668}
3669
3670impl Default for OcpmProcessConfig {
3671 fn default() -> Self {
3672 Self {
3673 rework_probability: default_rework_probability(),
3674 skip_step_probability: default_skip_probability(),
3675 out_of_order_probability: default_out_of_order_probability(),
3676 }
3677 }
3678}
3679
3680#[derive(Debug, Clone, Serialize, Deserialize)]
3682pub struct OcpmOutputConfig {
3683 #[serde(default = "default_true")]
3685 pub ocel_json: bool,
3686
3687 #[serde(default)]
3689 pub ocel_xml: bool,
3690
3691 #[serde(default)]
3693 pub xes: bool,
3694
3695 #[serde(default = "default_true")]
3697 pub xes_include_lifecycle: bool,
3698
3699 #[serde(default = "default_true")]
3701 pub xes_include_resources: bool,
3702
3703 #[serde(default = "default_true")]
3705 pub flattened_csv: bool,
3706
3707 #[serde(default = "default_true")]
3709 pub event_object_csv: bool,
3710
3711 #[serde(default = "default_true")]
3713 pub object_relationship_csv: bool,
3714
3715 #[serde(default = "default_true")]
3717 pub variants_csv: bool,
3718
3719 #[serde(default)]
3721 pub export_reference_models: bool,
3722}
3723
3724impl Default for OcpmOutputConfig {
3725 fn default() -> Self {
3726 Self {
3727 ocel_json: true,
3728 ocel_xml: false,
3729 xes: false,
3730 xes_include_lifecycle: true,
3731 xes_include_resources: true,
3732 flattened_csv: true,
3733 event_object_csv: true,
3734 object_relationship_csv: true,
3735 variants_csv: true,
3736 export_reference_models: false,
3737 }
3738 }
3739}
3740
3741#[derive(Debug, Clone, Serialize, Deserialize)]
3743pub struct AuditGenerationConfig {
3744 #[serde(default)]
3746 pub enabled: bool,
3747
3748 #[serde(default = "default_true")]
3750 pub generate_workpapers: bool,
3751
3752 #[serde(default)]
3754 pub engagement_types: AuditEngagementTypesConfig,
3755
3756 #[serde(default)]
3758 pub workpapers: WorkpaperConfig,
3759
3760 #[serde(default)]
3762 pub team: AuditTeamConfig,
3763
3764 #[serde(default)]
3766 pub review: ReviewWorkflowConfig,
3767}
3768
3769impl Default for AuditGenerationConfig {
3770 fn default() -> Self {
3771 Self {
3772 enabled: false,
3773 generate_workpapers: true,
3774 engagement_types: AuditEngagementTypesConfig::default(),
3775 workpapers: WorkpaperConfig::default(),
3776 team: AuditTeamConfig::default(),
3777 review: ReviewWorkflowConfig::default(),
3778 }
3779 }
3780}
3781
3782#[derive(Debug, Clone, Serialize, Deserialize)]
3784pub struct AuditEngagementTypesConfig {
3785 #[serde(default = "default_financial_audit_prob")]
3787 pub financial_statement: f64,
3788 #[serde(default = "default_sox_audit_prob")]
3790 pub sox_icfr: f64,
3791 #[serde(default = "default_integrated_audit_prob")]
3793 pub integrated: f64,
3794 #[serde(default = "default_review_prob")]
3796 pub review: f64,
3797 #[serde(default = "default_aup_prob")]
3799 pub agreed_upon_procedures: f64,
3800}
3801
3802fn default_financial_audit_prob() -> f64 {
3803 0.40
3804}
3805fn default_sox_audit_prob() -> f64 {
3806 0.20
3807}
3808fn default_integrated_audit_prob() -> f64 {
3809 0.25
3810}
3811fn default_review_prob() -> f64 {
3812 0.10
3813}
3814fn default_aup_prob() -> f64 {
3815 0.05
3816}
3817
3818impl Default for AuditEngagementTypesConfig {
3819 fn default() -> Self {
3820 Self {
3821 financial_statement: default_financial_audit_prob(),
3822 sox_icfr: default_sox_audit_prob(),
3823 integrated: default_integrated_audit_prob(),
3824 review: default_review_prob(),
3825 agreed_upon_procedures: default_aup_prob(),
3826 }
3827 }
3828}
3829
3830#[derive(Debug, Clone, Serialize, Deserialize)]
3832pub struct WorkpaperConfig {
3833 #[serde(default = "default_workpapers_per_phase")]
3835 pub average_per_phase: usize,
3836
3837 #[serde(default = "default_true")]
3839 pub include_isa_references: bool,
3840
3841 #[serde(default = "default_true")]
3843 pub include_sample_details: bool,
3844
3845 #[serde(default = "default_true")]
3847 pub include_cross_references: bool,
3848
3849 #[serde(default)]
3851 pub sampling: SamplingConfig,
3852}
3853
3854fn default_workpapers_per_phase() -> usize {
3855 5
3856}
3857
3858impl Default for WorkpaperConfig {
3859 fn default() -> Self {
3860 Self {
3861 average_per_phase: default_workpapers_per_phase(),
3862 include_isa_references: true,
3863 include_sample_details: true,
3864 include_cross_references: true,
3865 sampling: SamplingConfig::default(),
3866 }
3867 }
3868}
3869
3870#[derive(Debug, Clone, Serialize, Deserialize)]
3872pub struct SamplingConfig {
3873 #[serde(default = "default_statistical_rate")]
3875 pub statistical_rate: f64,
3876 #[serde(default = "default_judgmental_rate")]
3878 pub judgmental_rate: f64,
3879 #[serde(default = "default_haphazard_rate")]
3881 pub haphazard_rate: f64,
3882 #[serde(default = "default_complete_examination_rate")]
3884 pub complete_examination_rate: f64,
3885}
3886
3887fn default_statistical_rate() -> f64 {
3888 0.40
3889}
3890fn default_judgmental_rate() -> f64 {
3891 0.30
3892}
3893fn default_haphazard_rate() -> f64 {
3894 0.20
3895}
3896fn default_complete_examination_rate() -> f64 {
3897 0.10
3898}
3899
3900impl Default for SamplingConfig {
3901 fn default() -> Self {
3902 Self {
3903 statistical_rate: default_statistical_rate(),
3904 judgmental_rate: default_judgmental_rate(),
3905 haphazard_rate: default_haphazard_rate(),
3906 complete_examination_rate: default_complete_examination_rate(),
3907 }
3908 }
3909}
3910
3911#[derive(Debug, Clone, Serialize, Deserialize)]
3913pub struct AuditTeamConfig {
3914 #[serde(default = "default_min_team_size")]
3916 pub min_team_size: usize,
3917 #[serde(default = "default_max_team_size")]
3919 pub max_team_size: usize,
3920 #[serde(default = "default_specialist_probability")]
3922 pub specialist_probability: f64,
3923}
3924
3925fn default_min_team_size() -> usize {
3926 3
3927}
3928fn default_max_team_size() -> usize {
3929 8
3930}
3931fn default_specialist_probability() -> f64 {
3932 0.30
3933}
3934
3935impl Default for AuditTeamConfig {
3936 fn default() -> Self {
3937 Self {
3938 min_team_size: default_min_team_size(),
3939 max_team_size: default_max_team_size(),
3940 specialist_probability: default_specialist_probability(),
3941 }
3942 }
3943}
3944
3945#[derive(Debug, Clone, Serialize, Deserialize)]
3947pub struct ReviewWorkflowConfig {
3948 #[serde(default = "default_review_delay_days")]
3950 pub average_review_delay_days: u32,
3951 #[serde(default = "default_rework_probability_review")]
3953 pub rework_probability: f64,
3954 #[serde(default = "default_true")]
3956 pub require_partner_signoff: bool,
3957}
3958
3959fn default_review_delay_days() -> u32 {
3960 2
3961}
3962fn default_rework_probability_review() -> f64 {
3963 0.15
3964}
3965
3966impl Default for ReviewWorkflowConfig {
3967 fn default() -> Self {
3968 Self {
3969 average_review_delay_days: default_review_delay_days(),
3970 rework_probability: default_rework_probability_review(),
3971 require_partner_signoff: true,
3972 }
3973 }
3974}
3975
3976#[derive(Debug, Clone, Serialize, Deserialize)]
3982pub struct DataQualitySchemaConfig {
3983 #[serde(default)]
3985 pub enabled: bool,
3986 #[serde(default)]
3988 pub preset: DataQualityPreset,
3989 #[serde(default)]
3991 pub missing_values: MissingValuesSchemaConfig,
3992 #[serde(default)]
3994 pub typos: TypoSchemaConfig,
3995 #[serde(default)]
3997 pub format_variations: FormatVariationSchemaConfig,
3998 #[serde(default)]
4000 pub duplicates: DuplicateSchemaConfig,
4001 #[serde(default)]
4003 pub encoding_issues: EncodingIssueSchemaConfig,
4004 #[serde(default)]
4006 pub generate_labels: bool,
4007 #[serde(default)]
4009 pub sink_profiles: SinkQualityProfiles,
4010}
4011
4012impl Default for DataQualitySchemaConfig {
4013 fn default() -> Self {
4014 Self {
4015 enabled: false,
4016 preset: DataQualityPreset::None,
4017 missing_values: MissingValuesSchemaConfig::default(),
4018 typos: TypoSchemaConfig::default(),
4019 format_variations: FormatVariationSchemaConfig::default(),
4020 duplicates: DuplicateSchemaConfig::default(),
4021 encoding_issues: EncodingIssueSchemaConfig::default(),
4022 generate_labels: true,
4023 sink_profiles: SinkQualityProfiles::default(),
4024 }
4025 }
4026}
4027
4028impl DataQualitySchemaConfig {
4029 pub fn with_preset(preset: DataQualityPreset) -> Self {
4031 let mut config = Self {
4032 preset,
4033 ..Default::default()
4034 };
4035 config.apply_preset();
4036 config
4037 }
4038
4039 pub fn apply_preset(&mut self) {
4042 if !self.preset.overrides_settings() {
4043 return;
4044 }
4045
4046 self.enabled = true;
4047
4048 self.missing_values.enabled = self.preset.missing_rate() > 0.0;
4050 self.missing_values.rate = self.preset.missing_rate();
4051
4052 self.typos.enabled = self.preset.typo_rate() > 0.0;
4054 self.typos.char_error_rate = self.preset.typo_rate();
4055
4056 self.duplicates.enabled = self.preset.duplicate_rate() > 0.0;
4058 self.duplicates.exact_duplicate_ratio = self.preset.duplicate_rate() * 0.4;
4059 self.duplicates.near_duplicate_ratio = self.preset.duplicate_rate() * 0.4;
4060 self.duplicates.fuzzy_duplicate_ratio = self.preset.duplicate_rate() * 0.2;
4061
4062 self.format_variations.enabled = self.preset.format_variations_enabled();
4064
4065 self.encoding_issues.enabled = self.preset.encoding_issues_enabled();
4067 self.encoding_issues.rate = self.preset.encoding_issue_rate();
4068
4069 if self.preset.ocr_errors_enabled() {
4071 self.typos.type_weights.ocr_errors = 0.3;
4072 }
4073 }
4074
4075 pub fn effective_missing_rate(&self) -> f64 {
4077 if self.preset.overrides_settings() {
4078 self.preset.missing_rate()
4079 } else {
4080 self.missing_values.rate
4081 }
4082 }
4083
4084 pub fn effective_typo_rate(&self) -> f64 {
4086 if self.preset.overrides_settings() {
4087 self.preset.typo_rate()
4088 } else {
4089 self.typos.char_error_rate
4090 }
4091 }
4092
4093 pub fn effective_duplicate_rate(&self) -> f64 {
4095 if self.preset.overrides_settings() {
4096 self.preset.duplicate_rate()
4097 } else {
4098 self.duplicates.exact_duplicate_ratio
4099 + self.duplicates.near_duplicate_ratio
4100 + self.duplicates.fuzzy_duplicate_ratio
4101 }
4102 }
4103
4104 pub fn clean() -> Self {
4106 Self::with_preset(DataQualityPreset::Clean)
4107 }
4108
4109 pub fn noisy() -> Self {
4111 Self::with_preset(DataQualityPreset::Noisy)
4112 }
4113
4114 pub fn legacy() -> Self {
4116 Self::with_preset(DataQualityPreset::Legacy)
4117 }
4118}
4119
4120#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
4122#[serde(rename_all = "snake_case")]
4123pub enum DataQualityPreset {
4124 #[default]
4126 None,
4127 Minimal,
4129 Normal,
4131 High,
4133 Custom,
4135
4136 Clean,
4142 Noisy,
4145 Legacy,
4148}
4149
4150impl DataQualityPreset {
4151 pub fn missing_rate(&self) -> f64 {
4153 match self {
4154 DataQualityPreset::None => 0.0,
4155 DataQualityPreset::Minimal => 0.005,
4156 DataQualityPreset::Normal => 0.02,
4157 DataQualityPreset::High => 0.08,
4158 DataQualityPreset::Custom => 0.01, DataQualityPreset::Clean => 0.001,
4160 DataQualityPreset::Noisy => 0.05,
4161 DataQualityPreset::Legacy => 0.10,
4162 }
4163 }
4164
4165 pub fn typo_rate(&self) -> f64 {
4167 match self {
4168 DataQualityPreset::None => 0.0,
4169 DataQualityPreset::Minimal => 0.0005,
4170 DataQualityPreset::Normal => 0.002,
4171 DataQualityPreset::High => 0.01,
4172 DataQualityPreset::Custom => 0.001, DataQualityPreset::Clean => 0.0005,
4174 DataQualityPreset::Noisy => 0.02,
4175 DataQualityPreset::Legacy => 0.05,
4176 }
4177 }
4178
4179 pub fn duplicate_rate(&self) -> f64 {
4181 match self {
4182 DataQualityPreset::None => 0.0,
4183 DataQualityPreset::Minimal => 0.001,
4184 DataQualityPreset::Normal => 0.005,
4185 DataQualityPreset::High => 0.02,
4186 DataQualityPreset::Custom => 0.0, DataQualityPreset::Clean => 0.0,
4188 DataQualityPreset::Noisy => 0.01,
4189 DataQualityPreset::Legacy => 0.03,
4190 }
4191 }
4192
4193 pub fn format_variations_enabled(&self) -> bool {
4195 match self {
4196 DataQualityPreset::None | DataQualityPreset::Clean => false,
4197 DataQualityPreset::Minimal => true,
4198 DataQualityPreset::Normal => true,
4199 DataQualityPreset::High => true,
4200 DataQualityPreset::Custom => true,
4201 DataQualityPreset::Noisy => true,
4202 DataQualityPreset::Legacy => true,
4203 }
4204 }
4205
4206 pub fn ocr_errors_enabled(&self) -> bool {
4208 matches!(self, DataQualityPreset::Legacy | DataQualityPreset::High)
4209 }
4210
4211 pub fn encoding_issues_enabled(&self) -> bool {
4213 matches!(
4214 self,
4215 DataQualityPreset::Legacy | DataQualityPreset::High | DataQualityPreset::Noisy
4216 )
4217 }
4218
4219 pub fn encoding_issue_rate(&self) -> f64 {
4221 match self {
4222 DataQualityPreset::None | DataQualityPreset::Clean | DataQualityPreset::Minimal => 0.0,
4223 DataQualityPreset::Normal => 0.002,
4224 DataQualityPreset::High => 0.01,
4225 DataQualityPreset::Custom => 0.0,
4226 DataQualityPreset::Noisy => 0.005,
4227 DataQualityPreset::Legacy => 0.02,
4228 }
4229 }
4230
4231 pub fn overrides_settings(&self) -> bool {
4233 !matches!(self, DataQualityPreset::Custom | DataQualityPreset::None)
4234 }
4235
4236 pub fn description(&self) -> &'static str {
4238 match self {
4239 DataQualityPreset::None => "No data quality issues (pristine data)",
4240 DataQualityPreset::Minimal => "Very rare data quality issues",
4241 DataQualityPreset::Normal => "Realistic enterprise data quality",
4242 DataQualityPreset::High => "Messy data for stress testing",
4243 DataQualityPreset::Custom => "Custom settings from configuration",
4244 DataQualityPreset::Clean => "ML-ready clean data with minimal issues",
4245 DataQualityPreset::Noisy => "Typical production data with moderate issues",
4246 DataQualityPreset::Legacy => "Legacy/migrated data with heavy issues and OCR errors",
4247 }
4248 }
4249}
4250
4251#[derive(Debug, Clone, Serialize, Deserialize)]
4253pub struct MissingValuesSchemaConfig {
4254 #[serde(default)]
4256 pub enabled: bool,
4257 #[serde(default = "default_missing_rate")]
4259 pub rate: f64,
4260 #[serde(default)]
4262 pub strategy: MissingValueStrategy,
4263 #[serde(default)]
4265 pub field_rates: std::collections::HashMap<String, f64>,
4266 #[serde(default)]
4268 pub protected_fields: Vec<String>,
4269}
4270
4271fn default_missing_rate() -> f64 {
4272 0.01
4273}
4274
4275impl Default for MissingValuesSchemaConfig {
4276 fn default() -> Self {
4277 Self {
4278 enabled: false,
4279 rate: default_missing_rate(),
4280 strategy: MissingValueStrategy::Mcar,
4281 field_rates: std::collections::HashMap::new(),
4282 protected_fields: vec![
4283 "document_id".to_string(),
4284 "company_code".to_string(),
4285 "posting_date".to_string(),
4286 ],
4287 }
4288 }
4289}
4290
4291#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
4293#[serde(rename_all = "snake_case")]
4294pub enum MissingValueStrategy {
4295 #[default]
4297 Mcar,
4298 Mar,
4300 Mnar,
4302 Systematic,
4304}
4305
4306#[derive(Debug, Clone, Serialize, Deserialize)]
4308pub struct TypoSchemaConfig {
4309 #[serde(default)]
4311 pub enabled: bool,
4312 #[serde(default = "default_typo_rate")]
4314 pub char_error_rate: f64,
4315 #[serde(default)]
4317 pub type_weights: TypoTypeWeights,
4318 #[serde(default)]
4320 pub protected_fields: Vec<String>,
4321}
4322
4323fn default_typo_rate() -> f64 {
4324 0.001
4325}
4326
4327impl Default for TypoSchemaConfig {
4328 fn default() -> Self {
4329 Self {
4330 enabled: false,
4331 char_error_rate: default_typo_rate(),
4332 type_weights: TypoTypeWeights::default(),
4333 protected_fields: vec![
4334 "document_id".to_string(),
4335 "gl_account".to_string(),
4336 "company_code".to_string(),
4337 ],
4338 }
4339 }
4340}
4341
4342#[derive(Debug, Clone, Serialize, Deserialize)]
4344pub struct TypoTypeWeights {
4345 #[serde(default = "default_substitution_weight")]
4347 pub substitution: f64,
4348 #[serde(default = "default_transposition_weight")]
4350 pub transposition: f64,
4351 #[serde(default = "default_insertion_weight")]
4353 pub insertion: f64,
4354 #[serde(default = "default_deletion_weight")]
4356 pub deletion: f64,
4357 #[serde(default = "default_ocr_weight")]
4359 pub ocr_errors: f64,
4360 #[serde(default = "default_homophone_weight")]
4362 pub homophones: f64,
4363}
4364
4365fn default_substitution_weight() -> f64 {
4366 0.35
4367}
4368fn default_transposition_weight() -> f64 {
4369 0.25
4370}
4371fn default_insertion_weight() -> f64 {
4372 0.10
4373}
4374fn default_deletion_weight() -> f64 {
4375 0.15
4376}
4377fn default_ocr_weight() -> f64 {
4378 0.10
4379}
4380fn default_homophone_weight() -> f64 {
4381 0.05
4382}
4383
4384impl Default for TypoTypeWeights {
4385 fn default() -> Self {
4386 Self {
4387 substitution: default_substitution_weight(),
4388 transposition: default_transposition_weight(),
4389 insertion: default_insertion_weight(),
4390 deletion: default_deletion_weight(),
4391 ocr_errors: default_ocr_weight(),
4392 homophones: default_homophone_weight(),
4393 }
4394 }
4395}
4396
4397#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4399pub struct FormatVariationSchemaConfig {
4400 #[serde(default)]
4402 pub enabled: bool,
4403 #[serde(default)]
4405 pub dates: DateFormatVariationConfig,
4406 #[serde(default)]
4408 pub amounts: AmountFormatVariationConfig,
4409 #[serde(default)]
4411 pub identifiers: IdentifierFormatVariationConfig,
4412}
4413
4414#[derive(Debug, Clone, Serialize, Deserialize)]
4416pub struct DateFormatVariationConfig {
4417 #[serde(default)]
4419 pub enabled: bool,
4420 #[serde(default = "default_date_variation_rate")]
4422 pub rate: f64,
4423 #[serde(default = "default_true")]
4425 pub iso_format: bool,
4426 #[serde(default)]
4428 pub us_format: bool,
4429 #[serde(default)]
4431 pub eu_format: bool,
4432 #[serde(default)]
4434 pub long_format: bool,
4435}
4436
4437fn default_date_variation_rate() -> f64 {
4438 0.05
4439}
4440
4441impl Default for DateFormatVariationConfig {
4442 fn default() -> Self {
4443 Self {
4444 enabled: false,
4445 rate: default_date_variation_rate(),
4446 iso_format: true,
4447 us_format: false,
4448 eu_format: false,
4449 long_format: false,
4450 }
4451 }
4452}
4453
4454#[derive(Debug, Clone, Serialize, Deserialize)]
4456pub struct AmountFormatVariationConfig {
4457 #[serde(default)]
4459 pub enabled: bool,
4460 #[serde(default = "default_amount_variation_rate")]
4462 pub rate: f64,
4463 #[serde(default)]
4465 pub us_comma_format: bool,
4466 #[serde(default)]
4468 pub eu_format: bool,
4469 #[serde(default)]
4471 pub currency_prefix: bool,
4472 #[serde(default)]
4474 pub accounting_format: bool,
4475}
4476
4477fn default_amount_variation_rate() -> f64 {
4478 0.02
4479}
4480
4481impl Default for AmountFormatVariationConfig {
4482 fn default() -> Self {
4483 Self {
4484 enabled: false,
4485 rate: default_amount_variation_rate(),
4486 us_comma_format: false,
4487 eu_format: false,
4488 currency_prefix: false,
4489 accounting_format: false,
4490 }
4491 }
4492}
4493
4494#[derive(Debug, Clone, Serialize, Deserialize)]
4496pub struct IdentifierFormatVariationConfig {
4497 #[serde(default)]
4499 pub enabled: bool,
4500 #[serde(default = "default_identifier_variation_rate")]
4502 pub rate: f64,
4503 #[serde(default)]
4505 pub case_variations: bool,
4506 #[serde(default)]
4508 pub padding_variations: bool,
4509 #[serde(default)]
4511 pub separator_variations: bool,
4512}
4513
4514fn default_identifier_variation_rate() -> f64 {
4515 0.02
4516}
4517
4518impl Default for IdentifierFormatVariationConfig {
4519 fn default() -> Self {
4520 Self {
4521 enabled: false,
4522 rate: default_identifier_variation_rate(),
4523 case_variations: false,
4524 padding_variations: false,
4525 separator_variations: false,
4526 }
4527 }
4528}
4529
4530#[derive(Debug, Clone, Serialize, Deserialize)]
4532pub struct DuplicateSchemaConfig {
4533 #[serde(default)]
4535 pub enabled: bool,
4536 #[serde(default = "default_duplicate_rate")]
4538 pub rate: f64,
4539 #[serde(default = "default_exact_duplicate_ratio")]
4541 pub exact_duplicate_ratio: f64,
4542 #[serde(default = "default_near_duplicate_ratio")]
4544 pub near_duplicate_ratio: f64,
4545 #[serde(default = "default_fuzzy_duplicate_ratio")]
4547 pub fuzzy_duplicate_ratio: f64,
4548 #[serde(default = "default_max_date_offset")]
4550 pub max_date_offset_days: u32,
4551 #[serde(default = "default_max_amount_variance")]
4553 pub max_amount_variance: f64,
4554}
4555
4556fn default_duplicate_rate() -> f64 {
4557 0.005
4558}
4559fn default_exact_duplicate_ratio() -> f64 {
4560 0.4
4561}
4562fn default_near_duplicate_ratio() -> f64 {
4563 0.35
4564}
4565fn default_fuzzy_duplicate_ratio() -> f64 {
4566 0.25
4567}
4568fn default_max_date_offset() -> u32 {
4569 3
4570}
4571fn default_max_amount_variance() -> f64 {
4572 0.01
4573}
4574
4575impl Default for DuplicateSchemaConfig {
4576 fn default() -> Self {
4577 Self {
4578 enabled: false,
4579 rate: default_duplicate_rate(),
4580 exact_duplicate_ratio: default_exact_duplicate_ratio(),
4581 near_duplicate_ratio: default_near_duplicate_ratio(),
4582 fuzzy_duplicate_ratio: default_fuzzy_duplicate_ratio(),
4583 max_date_offset_days: default_max_date_offset(),
4584 max_amount_variance: default_max_amount_variance(),
4585 }
4586 }
4587}
4588
4589#[derive(Debug, Clone, Serialize, Deserialize)]
4591pub struct EncodingIssueSchemaConfig {
4592 #[serde(default)]
4594 pub enabled: bool,
4595 #[serde(default = "default_encoding_rate")]
4597 pub rate: f64,
4598 #[serde(default)]
4600 pub mojibake: bool,
4601 #[serde(default)]
4603 pub html_entities: bool,
4604 #[serde(default)]
4606 pub bom_issues: bool,
4607}
4608
4609fn default_encoding_rate() -> f64 {
4610 0.001
4611}
4612
4613impl Default for EncodingIssueSchemaConfig {
4614 fn default() -> Self {
4615 Self {
4616 enabled: false,
4617 rate: default_encoding_rate(),
4618 mojibake: false,
4619 html_entities: false,
4620 bom_issues: false,
4621 }
4622 }
4623}
4624
4625#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4627pub struct SinkQualityProfiles {
4628 #[serde(default)]
4630 pub csv: Option<SinkQualityOverride>,
4631 #[serde(default)]
4633 pub json: Option<SinkQualityOverride>,
4634 #[serde(default)]
4636 pub parquet: Option<SinkQualityOverride>,
4637}
4638
4639#[derive(Debug, Clone, Serialize, Deserialize)]
4641pub struct SinkQualityOverride {
4642 pub enabled: Option<bool>,
4644 pub missing_rate: Option<f64>,
4646 pub typo_rate: Option<f64>,
4648 pub format_variation_rate: Option<f64>,
4650 pub duplicate_rate: Option<f64>,
4652}
4653
4654#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4666pub struct AccountingStandardsConfig {
4667 #[serde(default)]
4669 pub enabled: bool,
4670
4671 #[serde(default, skip_serializing_if = "Option::is_none")]
4675 pub framework: Option<AccountingFrameworkConfig>,
4676
4677 #[serde(default)]
4679 pub revenue_recognition: RevenueRecognitionConfig,
4680
4681 #[serde(default)]
4683 pub leases: LeaseAccountingConfig,
4684
4685 #[serde(default)]
4687 pub fair_value: FairValueConfig,
4688
4689 #[serde(default)]
4691 pub impairment: ImpairmentConfig,
4692
4693 #[serde(default)]
4695 pub generate_differences: bool,
4696}
4697
4698#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
4700#[serde(rename_all = "snake_case")]
4701pub enum AccountingFrameworkConfig {
4702 #[default]
4704 UsGaap,
4705 Ifrs,
4707 DualReporting,
4709 FrenchGaap,
4711 GermanGaap,
4713}
4714
4715#[derive(Debug, Clone, Serialize, Deserialize)]
4717pub struct RevenueRecognitionConfig {
4718 #[serde(default)]
4720 pub enabled: bool,
4721
4722 #[serde(default = "default_true")]
4724 pub generate_contracts: bool,
4725
4726 #[serde(default = "default_avg_obligations")]
4728 pub avg_obligations_per_contract: f64,
4729
4730 #[serde(default = "default_variable_consideration_rate")]
4732 pub variable_consideration_rate: f64,
4733
4734 #[serde(default = "default_over_time_rate")]
4736 pub over_time_recognition_rate: f64,
4737
4738 #[serde(default = "default_contract_count")]
4740 pub contract_count: usize,
4741}
4742
4743fn default_avg_obligations() -> f64 {
4744 2.0
4745}
4746
4747fn default_variable_consideration_rate() -> f64 {
4748 0.15
4749}
4750
4751fn default_over_time_rate() -> f64 {
4752 0.30
4753}
4754
4755fn default_contract_count() -> usize {
4756 100
4757}
4758
4759impl Default for RevenueRecognitionConfig {
4760 fn default() -> Self {
4761 Self {
4762 enabled: false,
4763 generate_contracts: true,
4764 avg_obligations_per_contract: default_avg_obligations(),
4765 variable_consideration_rate: default_variable_consideration_rate(),
4766 over_time_recognition_rate: default_over_time_rate(),
4767 contract_count: default_contract_count(),
4768 }
4769 }
4770}
4771
4772#[derive(Debug, Clone, Serialize, Deserialize)]
4774pub struct LeaseAccountingConfig {
4775 #[serde(default)]
4777 pub enabled: bool,
4778
4779 #[serde(default = "default_lease_count")]
4781 pub lease_count: usize,
4782
4783 #[serde(default = "default_finance_lease_pct")]
4785 pub finance_lease_percent: f64,
4786
4787 #[serde(default = "default_avg_lease_term")]
4789 pub avg_lease_term_months: u32,
4790
4791 #[serde(default = "default_true")]
4793 pub generate_amortization: bool,
4794
4795 #[serde(default = "default_real_estate_pct")]
4797 pub real_estate_percent: f64,
4798}
4799
4800fn default_lease_count() -> usize {
4801 50
4802}
4803
4804fn default_finance_lease_pct() -> f64 {
4805 0.30
4806}
4807
4808fn default_avg_lease_term() -> u32 {
4809 60
4810}
4811
4812fn default_real_estate_pct() -> f64 {
4813 0.40
4814}
4815
4816impl Default for LeaseAccountingConfig {
4817 fn default() -> Self {
4818 Self {
4819 enabled: false,
4820 lease_count: default_lease_count(),
4821 finance_lease_percent: default_finance_lease_pct(),
4822 avg_lease_term_months: default_avg_lease_term(),
4823 generate_amortization: true,
4824 real_estate_percent: default_real_estate_pct(),
4825 }
4826 }
4827}
4828
4829#[derive(Debug, Clone, Serialize, Deserialize)]
4831pub struct FairValueConfig {
4832 #[serde(default)]
4834 pub enabled: bool,
4835
4836 #[serde(default = "default_fv_count")]
4838 pub measurement_count: usize,
4839
4840 #[serde(default = "default_level1_pct")]
4842 pub level1_percent: f64,
4843
4844 #[serde(default = "default_level2_pct")]
4846 pub level2_percent: f64,
4847
4848 #[serde(default = "default_level3_pct")]
4850 pub level3_percent: f64,
4851
4852 #[serde(default)]
4854 pub include_sensitivity_analysis: bool,
4855}
4856
4857fn default_fv_count() -> usize {
4858 25
4859}
4860
4861fn default_level1_pct() -> f64 {
4862 0.40
4863}
4864
4865fn default_level2_pct() -> f64 {
4866 0.35
4867}
4868
4869fn default_level3_pct() -> f64 {
4870 0.25
4871}
4872
4873impl Default for FairValueConfig {
4874 fn default() -> Self {
4875 Self {
4876 enabled: false,
4877 measurement_count: default_fv_count(),
4878 level1_percent: default_level1_pct(),
4879 level2_percent: default_level2_pct(),
4880 level3_percent: default_level3_pct(),
4881 include_sensitivity_analysis: false,
4882 }
4883 }
4884}
4885
4886#[derive(Debug, Clone, Serialize, Deserialize)]
4888pub struct ImpairmentConfig {
4889 #[serde(default)]
4891 pub enabled: bool,
4892
4893 #[serde(default = "default_impairment_count")]
4895 pub test_count: usize,
4896
4897 #[serde(default = "default_impairment_rate")]
4899 pub impairment_rate: f64,
4900
4901 #[serde(default = "default_true")]
4903 pub generate_projections: bool,
4904
4905 #[serde(default)]
4907 pub include_goodwill: bool,
4908}
4909
4910fn default_impairment_count() -> usize {
4911 15
4912}
4913
4914fn default_impairment_rate() -> f64 {
4915 0.10
4916}
4917
4918impl Default for ImpairmentConfig {
4919 fn default() -> Self {
4920 Self {
4921 enabled: false,
4922 test_count: default_impairment_count(),
4923 impairment_rate: default_impairment_rate(),
4924 generate_projections: true,
4925 include_goodwill: false,
4926 }
4927 }
4928}
4929
4930#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4943pub struct AuditStandardsConfig {
4944 #[serde(default)]
4946 pub enabled: bool,
4947
4948 #[serde(default)]
4950 pub isa_compliance: IsaComplianceConfig,
4951
4952 #[serde(default)]
4954 pub analytical_procedures: AnalyticalProceduresConfig,
4955
4956 #[serde(default)]
4958 pub confirmations: ConfirmationsConfig,
4959
4960 #[serde(default)]
4962 pub opinion: AuditOpinionConfig,
4963
4964 #[serde(default)]
4966 pub generate_audit_trail: bool,
4967
4968 #[serde(default)]
4970 pub sox: SoxComplianceConfig,
4971
4972 #[serde(default)]
4974 pub pcaob: PcaobConfig,
4975}
4976
4977#[derive(Debug, Clone, Serialize, Deserialize)]
4979pub struct IsaComplianceConfig {
4980 #[serde(default)]
4982 pub enabled: bool,
4983
4984 #[serde(default = "default_compliance_level")]
4986 pub compliance_level: String,
4987
4988 #[serde(default = "default_true")]
4990 pub generate_isa_mappings: bool,
4991
4992 #[serde(default = "default_true")]
4994 pub generate_coverage_summary: bool,
4995
4996 #[serde(default)]
4998 pub include_pcaob: bool,
4999
5000 #[serde(default = "default_audit_framework")]
5002 pub framework: String,
5003}
5004
5005fn default_compliance_level() -> String {
5006 "standard".to_string()
5007}
5008
5009fn default_audit_framework() -> String {
5010 "isa".to_string()
5011}
5012
5013impl Default for IsaComplianceConfig {
5014 fn default() -> Self {
5015 Self {
5016 enabled: false,
5017 compliance_level: default_compliance_level(),
5018 generate_isa_mappings: true,
5019 generate_coverage_summary: true,
5020 include_pcaob: false,
5021 framework: default_audit_framework(),
5022 }
5023 }
5024}
5025
5026#[derive(Debug, Clone, Serialize, Deserialize)]
5028pub struct AnalyticalProceduresConfig {
5029 #[serde(default)]
5031 pub enabled: bool,
5032
5033 #[serde(default = "default_procedures_per_account")]
5035 pub procedures_per_account: usize,
5036
5037 #[serde(default = "default_variance_probability")]
5039 pub variance_probability: f64,
5040
5041 #[serde(default = "default_true")]
5043 pub generate_investigations: bool,
5044
5045 #[serde(default = "default_true")]
5047 pub include_ratio_analysis: bool,
5048}
5049
5050fn default_procedures_per_account() -> usize {
5051 3
5052}
5053
5054fn default_variance_probability() -> f64 {
5055 0.20
5056}
5057
5058impl Default for AnalyticalProceduresConfig {
5059 fn default() -> Self {
5060 Self {
5061 enabled: false,
5062 procedures_per_account: default_procedures_per_account(),
5063 variance_probability: default_variance_probability(),
5064 generate_investigations: true,
5065 include_ratio_analysis: true,
5066 }
5067 }
5068}
5069
5070#[derive(Debug, Clone, Serialize, Deserialize)]
5072pub struct ConfirmationsConfig {
5073 #[serde(default)]
5075 pub enabled: bool,
5076
5077 #[serde(default = "default_confirmation_count")]
5079 pub confirmation_count: usize,
5080
5081 #[serde(default = "default_positive_response_rate")]
5083 pub positive_response_rate: f64,
5084
5085 #[serde(default = "default_exception_rate_confirm")]
5087 pub exception_rate: f64,
5088
5089 #[serde(default = "default_non_response_rate")]
5091 pub non_response_rate: f64,
5092
5093 #[serde(default = "default_true")]
5095 pub generate_alternative_procedures: bool,
5096}
5097
5098fn default_confirmation_count() -> usize {
5099 50
5100}
5101
5102fn default_positive_response_rate() -> f64 {
5103 0.85
5104}
5105
5106fn default_exception_rate_confirm() -> f64 {
5107 0.10
5108}
5109
5110fn default_non_response_rate() -> f64 {
5111 0.05
5112}
5113
5114impl Default for ConfirmationsConfig {
5115 fn default() -> Self {
5116 Self {
5117 enabled: false,
5118 confirmation_count: default_confirmation_count(),
5119 positive_response_rate: default_positive_response_rate(),
5120 exception_rate: default_exception_rate_confirm(),
5121 non_response_rate: default_non_response_rate(),
5122 generate_alternative_procedures: true,
5123 }
5124 }
5125}
5126
5127#[derive(Debug, Clone, Serialize, Deserialize)]
5129pub struct AuditOpinionConfig {
5130 #[serde(default)]
5132 pub enabled: bool,
5133
5134 #[serde(default = "default_true")]
5136 pub generate_kam: bool,
5137
5138 #[serde(default = "default_kam_count")]
5140 pub average_kam_count: usize,
5141
5142 #[serde(default = "default_modified_opinion_rate")]
5144 pub modified_opinion_rate: f64,
5145
5146 #[serde(default)]
5148 pub include_emphasis_of_matter: bool,
5149
5150 #[serde(default = "default_true")]
5152 pub include_going_concern: bool,
5153}
5154
5155fn default_kam_count() -> usize {
5156 3
5157}
5158
5159fn default_modified_opinion_rate() -> f64 {
5160 0.05
5161}
5162
5163impl Default for AuditOpinionConfig {
5164 fn default() -> Self {
5165 Self {
5166 enabled: false,
5167 generate_kam: true,
5168 average_kam_count: default_kam_count(),
5169 modified_opinion_rate: default_modified_opinion_rate(),
5170 include_emphasis_of_matter: false,
5171 include_going_concern: true,
5172 }
5173 }
5174}
5175
5176#[derive(Debug, Clone, Serialize, Deserialize)]
5178pub struct SoxComplianceConfig {
5179 #[serde(default)]
5181 pub enabled: bool,
5182
5183 #[serde(default = "default_true")]
5185 pub generate_302_certifications: bool,
5186
5187 #[serde(default = "default_true")]
5189 pub generate_404_assessments: bool,
5190
5191 #[serde(default = "default_sox_materiality_threshold")]
5193 pub materiality_threshold: f64,
5194
5195 #[serde(default = "default_material_weakness_rate")]
5197 pub material_weakness_rate: f64,
5198
5199 #[serde(default = "default_significant_deficiency_rate")]
5201 pub significant_deficiency_rate: f64,
5202}
5203
5204fn default_material_weakness_rate() -> f64 {
5205 0.02
5206}
5207
5208fn default_significant_deficiency_rate() -> f64 {
5209 0.08
5210}
5211
5212impl Default for SoxComplianceConfig {
5213 fn default() -> Self {
5214 Self {
5215 enabled: false,
5216 generate_302_certifications: true,
5217 generate_404_assessments: true,
5218 materiality_threshold: default_sox_materiality_threshold(),
5219 material_weakness_rate: default_material_weakness_rate(),
5220 significant_deficiency_rate: default_significant_deficiency_rate(),
5221 }
5222 }
5223}
5224
5225#[derive(Debug, Clone, Serialize, Deserialize)]
5227pub struct PcaobConfig {
5228 #[serde(default)]
5230 pub enabled: bool,
5231
5232 #[serde(default)]
5234 pub is_pcaob_audit: bool,
5235
5236 #[serde(default = "default_true")]
5238 pub generate_cam: bool,
5239
5240 #[serde(default)]
5242 pub include_icfr_opinion: bool,
5243
5244 #[serde(default)]
5246 pub generate_standard_mappings: bool,
5247}
5248
5249impl Default for PcaobConfig {
5250 fn default() -> Self {
5251 Self {
5252 enabled: false,
5253 is_pcaob_audit: false,
5254 generate_cam: true,
5255 include_icfr_opinion: false,
5256 generate_standard_mappings: false,
5257 }
5258 }
5259}
5260
5261#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5274pub struct AdvancedDistributionConfig {
5275 #[serde(default)]
5277 pub enabled: bool,
5278
5279 #[serde(default)]
5281 pub amounts: MixtureDistributionSchemaConfig,
5282
5283 #[serde(default)]
5285 pub correlations: CorrelationSchemaConfig,
5286
5287 #[serde(default)]
5289 pub conditional: Vec<ConditionalDistributionSchemaConfig>,
5290
5291 #[serde(default)]
5293 pub regime_changes: RegimeChangeSchemaConfig,
5294
5295 #[serde(default)]
5297 pub industry_profile: Option<IndustryProfileType>,
5298
5299 #[serde(default)]
5301 pub validation: StatisticalValidationSchemaConfig,
5302}
5303
5304#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
5306#[serde(rename_all = "snake_case")]
5307pub enum IndustryProfileType {
5308 Retail,
5310 Manufacturing,
5312 FinancialServices,
5314 Healthcare,
5316 Technology,
5318}
5319
5320#[derive(Debug, Clone, Serialize, Deserialize)]
5322pub struct MixtureDistributionSchemaConfig {
5323 #[serde(default)]
5325 pub enabled: bool,
5326
5327 #[serde(default = "default_mixture_type")]
5329 pub distribution_type: MixtureDistributionType,
5330
5331 #[serde(default)]
5333 pub components: Vec<MixtureComponentConfig>,
5334
5335 #[serde(default = "default_min_amount")]
5337 pub min_value: f64,
5338
5339 #[serde(default)]
5341 pub max_value: Option<f64>,
5342
5343 #[serde(default = "default_decimal_places")]
5345 pub decimal_places: u8,
5346}
5347
5348fn default_mixture_type() -> MixtureDistributionType {
5349 MixtureDistributionType::LogNormal
5350}
5351
5352fn default_min_amount() -> f64 {
5353 0.01
5354}
5355
5356fn default_decimal_places() -> u8 {
5357 2
5358}
5359
5360impl Default for MixtureDistributionSchemaConfig {
5361 fn default() -> Self {
5362 Self {
5363 enabled: false,
5364 distribution_type: MixtureDistributionType::LogNormal,
5365 components: Vec::new(),
5366 min_value: 0.01,
5367 max_value: None,
5368 decimal_places: 2,
5369 }
5370 }
5371}
5372
5373#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5375#[serde(rename_all = "snake_case")]
5376pub enum MixtureDistributionType {
5377 Gaussian,
5379 #[default]
5381 LogNormal,
5382}
5383
5384#[derive(Debug, Clone, Serialize, Deserialize)]
5386pub struct MixtureComponentConfig {
5387 pub weight: f64,
5389
5390 pub mu: f64,
5392
5393 pub sigma: f64,
5395
5396 #[serde(default)]
5398 pub label: Option<String>,
5399}
5400
5401#[derive(Debug, Clone, Serialize, Deserialize)]
5403pub struct CorrelationSchemaConfig {
5404 #[serde(default)]
5406 pub enabled: bool,
5407
5408 #[serde(default)]
5410 pub copula_type: CopulaSchemaType,
5411
5412 #[serde(default)]
5414 pub fields: Vec<CorrelatedFieldConfig>,
5415
5416 #[serde(default)]
5419 pub matrix: Vec<f64>,
5420
5421 #[serde(default)]
5423 pub expected_correlations: Vec<ExpectedCorrelationConfig>,
5424}
5425
5426impl Default for CorrelationSchemaConfig {
5427 fn default() -> Self {
5428 Self {
5429 enabled: false,
5430 copula_type: CopulaSchemaType::Gaussian,
5431 fields: Vec::new(),
5432 matrix: Vec::new(),
5433 expected_correlations: Vec::new(),
5434 }
5435 }
5436}
5437
5438#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5440#[serde(rename_all = "snake_case")]
5441pub enum CopulaSchemaType {
5442 #[default]
5444 Gaussian,
5445 Clayton,
5447 Gumbel,
5449 Frank,
5451 StudentT,
5453}
5454
5455#[derive(Debug, Clone, Serialize, Deserialize)]
5457pub struct CorrelatedFieldConfig {
5458 pub name: String,
5460
5461 #[serde(default)]
5463 pub distribution: MarginalDistributionConfig,
5464}
5465
5466#[derive(Debug, Clone, Serialize, Deserialize)]
5468#[serde(tag = "type", rename_all = "snake_case")]
5469pub enum MarginalDistributionConfig {
5470 Normal {
5472 mu: f64,
5474 sigma: f64,
5476 },
5477 LogNormal {
5479 mu: f64,
5481 sigma: f64,
5483 },
5484 Uniform {
5486 min: f64,
5488 max: f64,
5490 },
5491 DiscreteUniform {
5493 min: i32,
5495 max: i32,
5497 },
5498}
5499
5500impl Default for MarginalDistributionConfig {
5501 fn default() -> Self {
5502 Self::Normal {
5503 mu: 0.0,
5504 sigma: 1.0,
5505 }
5506 }
5507}
5508
5509#[derive(Debug, Clone, Serialize, Deserialize)]
5511pub struct ExpectedCorrelationConfig {
5512 pub field1: String,
5514 pub field2: String,
5516 pub expected_r: f64,
5518 #[serde(default = "default_correlation_tolerance")]
5520 pub tolerance: f64,
5521}
5522
5523fn default_correlation_tolerance() -> f64 {
5524 0.10
5525}
5526
5527#[derive(Debug, Clone, Serialize, Deserialize)]
5529pub struct ConditionalDistributionSchemaConfig {
5530 pub output_field: String,
5532
5533 pub input_field: String,
5535
5536 #[serde(default)]
5538 pub breakpoints: Vec<ConditionalBreakpointConfig>,
5539
5540 #[serde(default)]
5542 pub default_distribution: ConditionalDistributionParamsConfig,
5543
5544 #[serde(default)]
5546 pub min_value: Option<f64>,
5547
5548 #[serde(default)]
5550 pub max_value: Option<f64>,
5551
5552 #[serde(default = "default_decimal_places")]
5554 pub decimal_places: u8,
5555}
5556
5557#[derive(Debug, Clone, Serialize, Deserialize)]
5559pub struct ConditionalBreakpointConfig {
5560 pub threshold: f64,
5562
5563 pub distribution: ConditionalDistributionParamsConfig,
5565}
5566
5567#[derive(Debug, Clone, Serialize, Deserialize)]
5569#[serde(tag = "type", rename_all = "snake_case")]
5570pub enum ConditionalDistributionParamsConfig {
5571 Fixed {
5573 value: f64,
5575 },
5576 Normal {
5578 mu: f64,
5580 sigma: f64,
5582 },
5583 LogNormal {
5585 mu: f64,
5587 sigma: f64,
5589 },
5590 Uniform {
5592 min: f64,
5594 max: f64,
5596 },
5597 Beta {
5599 alpha: f64,
5601 beta: f64,
5603 min: f64,
5605 max: f64,
5607 },
5608 Discrete {
5610 values: Vec<f64>,
5612 weights: Vec<f64>,
5614 },
5615}
5616
5617impl Default for ConditionalDistributionParamsConfig {
5618 fn default() -> Self {
5619 Self::Normal {
5620 mu: 0.0,
5621 sigma: 1.0,
5622 }
5623 }
5624}
5625
5626#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5628pub struct RegimeChangeSchemaConfig {
5629 #[serde(default)]
5631 pub enabled: bool,
5632
5633 #[serde(default)]
5635 pub changes: Vec<RegimeChangeEventConfig>,
5636
5637 #[serde(default)]
5639 pub economic_cycle: Option<EconomicCycleSchemaConfig>,
5640
5641 #[serde(default)]
5643 pub parameter_drifts: Vec<ParameterDriftSchemaConfig>,
5644}
5645
5646#[derive(Debug, Clone, Serialize, Deserialize)]
5648pub struct RegimeChangeEventConfig {
5649 pub date: String,
5651
5652 pub change_type: RegimeChangeTypeConfig,
5654
5655 #[serde(default)]
5657 pub description: Option<String>,
5658
5659 #[serde(default)]
5661 pub effects: Vec<RegimeEffectConfig>,
5662}
5663
5664#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
5666#[serde(rename_all = "snake_case")]
5667pub enum RegimeChangeTypeConfig {
5668 Acquisition,
5670 Divestiture,
5672 PriceIncrease,
5674 PriceDecrease,
5676 ProductLaunch,
5678 ProductDiscontinuation,
5680 PolicyChange,
5682 CompetitorEntry,
5684 Custom,
5686}
5687
5688#[derive(Debug, Clone, Serialize, Deserialize)]
5690pub struct RegimeEffectConfig {
5691 pub field: String,
5693
5694 pub multiplier: f64,
5696}
5697
5698#[derive(Debug, Clone, Serialize, Deserialize)]
5700pub struct EconomicCycleSchemaConfig {
5701 #[serde(default)]
5703 pub enabled: bool,
5704
5705 #[serde(default = "default_cycle_period")]
5707 pub period_months: u32,
5708
5709 #[serde(default = "default_cycle_amplitude")]
5711 pub amplitude: f64,
5712
5713 #[serde(default)]
5715 pub phase_offset: u32,
5716
5717 #[serde(default)]
5719 pub recessions: Vec<RecessionPeriodConfig>,
5720}
5721
5722fn default_cycle_period() -> u32 {
5723 48
5724}
5725
5726fn default_cycle_amplitude() -> f64 {
5727 0.15
5728}
5729
5730impl Default for EconomicCycleSchemaConfig {
5731 fn default() -> Self {
5732 Self {
5733 enabled: false,
5734 period_months: 48,
5735 amplitude: 0.15,
5736 phase_offset: 0,
5737 recessions: Vec::new(),
5738 }
5739 }
5740}
5741
5742#[derive(Debug, Clone, Serialize, Deserialize)]
5744pub struct RecessionPeriodConfig {
5745 pub start_month: u32,
5747
5748 pub duration_months: u32,
5750
5751 #[serde(default = "default_recession_severity")]
5753 pub severity: f64,
5754}
5755
5756fn default_recession_severity() -> f64 {
5757 0.20
5758}
5759
5760#[derive(Debug, Clone, Serialize, Deserialize)]
5762pub struct ParameterDriftSchemaConfig {
5763 pub parameter: String,
5765
5766 pub drift_type: ParameterDriftTypeConfig,
5768
5769 pub start_value: f64,
5771
5772 pub end_value: f64,
5774
5775 #[serde(default)]
5777 pub start_period: u32,
5778
5779 #[serde(default)]
5781 pub end_period: Option<u32>,
5782}
5783
5784#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5786#[serde(rename_all = "snake_case")]
5787pub enum ParameterDriftTypeConfig {
5788 #[default]
5790 Linear,
5791 Exponential,
5793 Logistic,
5795 Step,
5797}
5798
5799#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5801pub struct StatisticalValidationSchemaConfig {
5802 #[serde(default)]
5804 pub enabled: bool,
5805
5806 #[serde(default)]
5808 pub tests: Vec<StatisticalTestConfig>,
5809
5810 #[serde(default)]
5812 pub reporting: ValidationReportingConfig,
5813}
5814
5815#[derive(Debug, Clone, Serialize, Deserialize)]
5817#[serde(tag = "type", rename_all = "snake_case")]
5818pub enum StatisticalTestConfig {
5819 BenfordFirstDigit {
5821 #[serde(default = "default_benford_threshold")]
5823 threshold_mad: f64,
5824 #[serde(default = "default_benford_warning")]
5826 warning_mad: f64,
5827 },
5828 DistributionFit {
5830 target: TargetDistributionConfig,
5832 #[serde(default = "default_ks_significance")]
5834 ks_significance: f64,
5835 #[serde(default)]
5837 method: DistributionFitMethod,
5838 },
5839 CorrelationCheck {
5841 expected_correlations: Vec<ExpectedCorrelationConfig>,
5843 },
5844 ChiSquared {
5846 #[serde(default = "default_chi_squared_bins")]
5848 bins: usize,
5849 #[serde(default = "default_chi_squared_significance")]
5851 significance: f64,
5852 },
5853 AndersonDarling {
5855 target: TargetDistributionConfig,
5857 #[serde(default = "default_ad_significance")]
5859 significance: f64,
5860 },
5861}
5862
5863fn default_benford_threshold() -> f64 {
5864 0.015
5865}
5866
5867fn default_benford_warning() -> f64 {
5868 0.010
5869}
5870
5871fn default_ks_significance() -> f64 {
5872 0.05
5873}
5874
5875fn default_chi_squared_bins() -> usize {
5876 10
5877}
5878
5879fn default_chi_squared_significance() -> f64 {
5880 0.05
5881}
5882
5883fn default_ad_significance() -> f64 {
5884 0.05
5885}
5886
5887#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5889#[serde(rename_all = "snake_case")]
5890pub enum TargetDistributionConfig {
5891 Normal,
5893 #[default]
5895 LogNormal,
5896 Exponential,
5898 Uniform,
5900}
5901
5902#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5904#[serde(rename_all = "snake_case")]
5905pub enum DistributionFitMethod {
5906 #[default]
5908 KolmogorovSmirnov,
5909 AndersonDarling,
5911 ChiSquared,
5913}
5914
5915#[derive(Debug, Clone, Serialize, Deserialize)]
5917pub struct ValidationReportingConfig {
5918 #[serde(default)]
5920 pub output_report: bool,
5921
5922 #[serde(default)]
5924 pub format: ValidationReportFormat,
5925
5926 #[serde(default)]
5928 pub fail_on_error: bool,
5929
5930 #[serde(default = "default_true")]
5932 pub include_details: bool,
5933}
5934
5935impl Default for ValidationReportingConfig {
5936 fn default() -> Self {
5937 Self {
5938 output_report: false,
5939 format: ValidationReportFormat::Json,
5940 fail_on_error: false,
5941 include_details: true,
5942 }
5943 }
5944}
5945
5946#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5948#[serde(rename_all = "snake_case")]
5949pub enum ValidationReportFormat {
5950 #[default]
5952 Json,
5953 Yaml,
5955 Html,
5957}
5958
5959#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5971pub struct TemporalPatternsConfig {
5972 #[serde(default)]
5974 pub enabled: bool,
5975
5976 #[serde(default)]
5978 pub business_days: BusinessDaySchemaConfig,
5979
5980 #[serde(default)]
5982 pub calendars: CalendarSchemaConfig,
5983
5984 #[serde(default)]
5986 pub period_end: PeriodEndSchemaConfig,
5987
5988 #[serde(default)]
5990 pub processing_lags: ProcessingLagSchemaConfig,
5991
5992 #[serde(default)]
5994 pub fiscal_calendar: FiscalCalendarSchemaConfig,
5995
5996 #[serde(default)]
5998 pub intraday: IntraDaySchemaConfig,
5999
6000 #[serde(default)]
6002 pub timezones: TimezoneSchemaConfig,
6003}
6004
6005#[derive(Debug, Clone, Serialize, Deserialize)]
6007pub struct BusinessDaySchemaConfig {
6008 #[serde(default = "default_true")]
6010 pub enabled: bool,
6011
6012 #[serde(default = "default_half_day_policy")]
6014 pub half_day_policy: String,
6015
6016 #[serde(default)]
6018 pub settlement_rules: SettlementRulesSchemaConfig,
6019
6020 #[serde(default = "default_month_end_convention")]
6022 pub month_end_convention: String,
6023
6024 #[serde(default)]
6026 pub weekend_days: Option<Vec<String>>,
6027}
6028
6029fn default_half_day_policy() -> String {
6030 "half_day".to_string()
6031}
6032
6033fn default_month_end_convention() -> String {
6034 "modified_following".to_string()
6035}
6036
6037impl Default for BusinessDaySchemaConfig {
6038 fn default() -> Self {
6039 Self {
6040 enabled: true,
6041 half_day_policy: "half_day".to_string(),
6042 settlement_rules: SettlementRulesSchemaConfig::default(),
6043 month_end_convention: "modified_following".to_string(),
6044 weekend_days: None,
6045 }
6046 }
6047}
6048
6049#[derive(Debug, Clone, Serialize, Deserialize)]
6051pub struct SettlementRulesSchemaConfig {
6052 #[serde(default = "default_settlement_2")]
6054 pub equity_days: i32,
6055
6056 #[serde(default = "default_settlement_1")]
6058 pub government_bonds_days: i32,
6059
6060 #[serde(default = "default_settlement_2")]
6062 pub fx_spot_days: i32,
6063
6064 #[serde(default = "default_settlement_2")]
6066 pub corporate_bonds_days: i32,
6067
6068 #[serde(default = "default_wire_cutoff")]
6070 pub wire_cutoff_time: String,
6071
6072 #[serde(default = "default_settlement_1")]
6074 pub wire_international_days: i32,
6075
6076 #[serde(default = "default_settlement_1")]
6078 pub ach_days: i32,
6079}
6080
6081fn default_settlement_1() -> i32 {
6082 1
6083}
6084
6085fn default_settlement_2() -> i32 {
6086 2
6087}
6088
6089fn default_wire_cutoff() -> String {
6090 "14:00".to_string()
6091}
6092
6093impl Default for SettlementRulesSchemaConfig {
6094 fn default() -> Self {
6095 Self {
6096 equity_days: 2,
6097 government_bonds_days: 1,
6098 fx_spot_days: 2,
6099 corporate_bonds_days: 2,
6100 wire_cutoff_time: "14:00".to_string(),
6101 wire_international_days: 1,
6102 ach_days: 1,
6103 }
6104 }
6105}
6106
6107#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6109pub struct CalendarSchemaConfig {
6110 #[serde(default)]
6112 pub regions: Vec<String>,
6113
6114 #[serde(default)]
6116 pub custom_holidays: Vec<CustomHolidaySchemaConfig>,
6117}
6118
6119#[derive(Debug, Clone, Serialize, Deserialize)]
6121pub struct CustomHolidaySchemaConfig {
6122 pub name: String,
6124 pub month: u8,
6126 pub day: u8,
6128 #[serde(default = "default_holiday_multiplier")]
6130 pub activity_multiplier: f64,
6131}
6132
6133fn default_holiday_multiplier() -> f64 {
6134 0.05
6135}
6136
6137#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6139pub struct PeriodEndSchemaConfig {
6140 #[serde(default)]
6142 pub model: Option<String>,
6143
6144 #[serde(default)]
6146 pub month_end: Option<PeriodEndModelSchemaConfig>,
6147
6148 #[serde(default)]
6150 pub quarter_end: Option<PeriodEndModelSchemaConfig>,
6151
6152 #[serde(default)]
6154 pub year_end: Option<PeriodEndModelSchemaConfig>,
6155}
6156
6157#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6159pub struct PeriodEndModelSchemaConfig {
6160 #[serde(default)]
6162 pub inherit_from: Option<String>,
6163
6164 #[serde(default)]
6166 pub additional_multiplier: Option<f64>,
6167
6168 #[serde(default)]
6170 pub start_day: Option<i32>,
6171
6172 #[serde(default)]
6174 pub base_multiplier: Option<f64>,
6175
6176 #[serde(default)]
6178 pub peak_multiplier: Option<f64>,
6179
6180 #[serde(default)]
6182 pub decay_rate: Option<f64>,
6183
6184 #[serde(default)]
6186 pub sustained_high_days: Option<i32>,
6187}
6188
6189#[derive(Debug, Clone, Serialize, Deserialize)]
6191pub struct ProcessingLagSchemaConfig {
6192 #[serde(default = "default_true")]
6194 pub enabled: bool,
6195
6196 #[serde(default)]
6198 pub sales_order_lag: Option<LagDistributionSchemaConfig>,
6199
6200 #[serde(default)]
6202 pub purchase_order_lag: Option<LagDistributionSchemaConfig>,
6203
6204 #[serde(default)]
6206 pub goods_receipt_lag: Option<LagDistributionSchemaConfig>,
6207
6208 #[serde(default)]
6210 pub invoice_receipt_lag: Option<LagDistributionSchemaConfig>,
6211
6212 #[serde(default)]
6214 pub invoice_issue_lag: Option<LagDistributionSchemaConfig>,
6215
6216 #[serde(default)]
6218 pub payment_lag: Option<LagDistributionSchemaConfig>,
6219
6220 #[serde(default)]
6222 pub journal_entry_lag: Option<LagDistributionSchemaConfig>,
6223
6224 #[serde(default)]
6226 pub cross_day_posting: Option<CrossDayPostingSchemaConfig>,
6227}
6228
6229impl Default for ProcessingLagSchemaConfig {
6230 fn default() -> Self {
6231 Self {
6232 enabled: true,
6233 sales_order_lag: None,
6234 purchase_order_lag: None,
6235 goods_receipt_lag: None,
6236 invoice_receipt_lag: None,
6237 invoice_issue_lag: None,
6238 payment_lag: None,
6239 journal_entry_lag: None,
6240 cross_day_posting: None,
6241 }
6242 }
6243}
6244
6245#[derive(Debug, Clone, Serialize, Deserialize)]
6247pub struct LagDistributionSchemaConfig {
6248 pub mu: f64,
6250 pub sigma: f64,
6252 #[serde(default)]
6254 pub min_hours: Option<f64>,
6255 #[serde(default)]
6257 pub max_hours: Option<f64>,
6258}
6259
6260#[derive(Debug, Clone, Serialize, Deserialize)]
6262pub struct CrossDayPostingSchemaConfig {
6263 #[serde(default = "default_true")]
6265 pub enabled: bool,
6266
6267 #[serde(default)]
6270 pub probability_by_hour: std::collections::HashMap<u8, f64>,
6271}
6272
6273impl Default for CrossDayPostingSchemaConfig {
6274 fn default() -> Self {
6275 let mut probability_by_hour = std::collections::HashMap::new();
6276 probability_by_hour.insert(17, 0.3);
6277 probability_by_hour.insert(18, 0.6);
6278 probability_by_hour.insert(19, 0.8);
6279 probability_by_hour.insert(20, 0.9);
6280 probability_by_hour.insert(21, 0.95);
6281 probability_by_hour.insert(22, 0.99);
6282
6283 Self {
6284 enabled: true,
6285 probability_by_hour,
6286 }
6287 }
6288}
6289
6290#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6299pub struct FiscalCalendarSchemaConfig {
6300 #[serde(default)]
6302 pub enabled: bool,
6303
6304 #[serde(default = "default_fiscal_calendar_type")]
6306 pub calendar_type: String,
6307
6308 #[serde(default)]
6310 pub year_start_month: Option<u8>,
6311
6312 #[serde(default)]
6314 pub year_start_day: Option<u8>,
6315
6316 #[serde(default)]
6318 pub four_four_five: Option<FourFourFiveSchemaConfig>,
6319}
6320
6321fn default_fiscal_calendar_type() -> String {
6322 "calendar_year".to_string()
6323}
6324
6325#[derive(Debug, Clone, Serialize, Deserialize)]
6327pub struct FourFourFiveSchemaConfig {
6328 #[serde(default = "default_week_pattern")]
6330 pub pattern: String,
6331
6332 #[serde(default = "default_anchor_type")]
6334 pub anchor_type: String,
6335
6336 #[serde(default = "default_anchor_month")]
6338 pub anchor_month: u8,
6339
6340 #[serde(default = "default_leap_week_placement")]
6342 pub leap_week_placement: String,
6343}
6344
6345fn default_week_pattern() -> String {
6346 "four_four_five".to_string()
6347}
6348
6349fn default_anchor_type() -> String {
6350 "last_saturday".to_string()
6351}
6352
6353fn default_anchor_month() -> u8 {
6354 1 }
6356
6357fn default_leap_week_placement() -> String {
6358 "q4_period3".to_string()
6359}
6360
6361impl Default for FourFourFiveSchemaConfig {
6362 fn default() -> Self {
6363 Self {
6364 pattern: "four_four_five".to_string(),
6365 anchor_type: "last_saturday".to_string(),
6366 anchor_month: 1,
6367 leap_week_placement: "q4_period3".to_string(),
6368 }
6369 }
6370}
6371
6372#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6381pub struct IntraDaySchemaConfig {
6382 #[serde(default)]
6384 pub enabled: bool,
6385
6386 #[serde(default)]
6388 pub segments: Vec<IntraDaySegmentSchemaConfig>,
6389}
6390
6391#[derive(Debug, Clone, Serialize, Deserialize)]
6393pub struct IntraDaySegmentSchemaConfig {
6394 pub name: String,
6396
6397 pub start: String,
6399
6400 pub end: String,
6402
6403 #[serde(default = "default_multiplier")]
6405 pub multiplier: f64,
6406
6407 #[serde(default = "default_posting_type")]
6409 pub posting_type: String,
6410}
6411
6412fn default_multiplier() -> f64 {
6413 1.0
6414}
6415
6416fn default_posting_type() -> String {
6417 "both".to_string()
6418}
6419
6420#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6426pub struct TimezoneSchemaConfig {
6427 #[serde(default)]
6429 pub enabled: bool,
6430
6431 #[serde(default = "default_timezone")]
6433 pub default_timezone: String,
6434
6435 #[serde(default = "default_consolidation_timezone")]
6437 pub consolidation_timezone: String,
6438
6439 #[serde(default)]
6442 pub entity_mappings: Vec<EntityTimezoneMapping>,
6443}
6444
6445fn default_timezone() -> String {
6446 "America/New_York".to_string()
6447}
6448
6449fn default_consolidation_timezone() -> String {
6450 "UTC".to_string()
6451}
6452
6453#[derive(Debug, Clone, Serialize, Deserialize)]
6455pub struct EntityTimezoneMapping {
6456 pub pattern: String,
6458
6459 pub timezone: String,
6461}
6462
6463#[derive(Debug, Clone, Serialize, Deserialize)]
6469pub struct VendorNetworkSchemaConfig {
6470 #[serde(default)]
6472 pub enabled: bool,
6473
6474 #[serde(default = "default_vendor_tier_depth")]
6476 pub depth: u8,
6477
6478 #[serde(default)]
6480 pub tier1: TierCountSchemaConfig,
6481
6482 #[serde(default)]
6484 pub tier2_per_parent: TierCountSchemaConfig,
6485
6486 #[serde(default)]
6488 pub tier3_per_parent: TierCountSchemaConfig,
6489
6490 #[serde(default)]
6492 pub clusters: VendorClusterSchemaConfig,
6493
6494 #[serde(default)]
6496 pub dependencies: DependencySchemaConfig,
6497}
6498
6499fn default_vendor_tier_depth() -> u8 {
6500 3
6501}
6502
6503impl Default for VendorNetworkSchemaConfig {
6504 fn default() -> Self {
6505 Self {
6506 enabled: false,
6507 depth: 3,
6508 tier1: TierCountSchemaConfig { min: 50, max: 100 },
6509 tier2_per_parent: TierCountSchemaConfig { min: 4, max: 10 },
6510 tier3_per_parent: TierCountSchemaConfig { min: 2, max: 5 },
6511 clusters: VendorClusterSchemaConfig::default(),
6512 dependencies: DependencySchemaConfig::default(),
6513 }
6514 }
6515}
6516
6517#[derive(Debug, Clone, Serialize, Deserialize)]
6519pub struct TierCountSchemaConfig {
6520 #[serde(default = "default_tier_min")]
6522 pub min: usize,
6523
6524 #[serde(default = "default_tier_max")]
6526 pub max: usize,
6527}
6528
6529fn default_tier_min() -> usize {
6530 5
6531}
6532
6533fn default_tier_max() -> usize {
6534 20
6535}
6536
6537impl Default for TierCountSchemaConfig {
6538 fn default() -> Self {
6539 Self {
6540 min: default_tier_min(),
6541 max: default_tier_max(),
6542 }
6543 }
6544}
6545
6546#[derive(Debug, Clone, Serialize, Deserialize)]
6548pub struct VendorClusterSchemaConfig {
6549 #[serde(default = "default_reliable_strategic")]
6551 pub reliable_strategic: f64,
6552
6553 #[serde(default = "default_standard_operational")]
6555 pub standard_operational: f64,
6556
6557 #[serde(default = "default_transactional")]
6559 pub transactional: f64,
6560
6561 #[serde(default = "default_problematic")]
6563 pub problematic: f64,
6564}
6565
6566fn default_reliable_strategic() -> f64 {
6567 0.20
6568}
6569
6570fn default_standard_operational() -> f64 {
6571 0.50
6572}
6573
6574fn default_transactional() -> f64 {
6575 0.25
6576}
6577
6578fn default_problematic() -> f64 {
6579 0.05
6580}
6581
6582impl Default for VendorClusterSchemaConfig {
6583 fn default() -> Self {
6584 Self {
6585 reliable_strategic: 0.20,
6586 standard_operational: 0.50,
6587 transactional: 0.25,
6588 problematic: 0.05,
6589 }
6590 }
6591}
6592
6593#[derive(Debug, Clone, Serialize, Deserialize)]
6595pub struct DependencySchemaConfig {
6596 #[serde(default = "default_max_single_vendor")]
6598 pub max_single_vendor_concentration: f64,
6599
6600 #[serde(default = "default_max_top5")]
6602 pub top_5_concentration: f64,
6603
6604 #[serde(default = "default_single_source_percent")]
6606 pub single_source_percent: f64,
6607}
6608
6609fn default_max_single_vendor() -> f64 {
6610 0.15
6611}
6612
6613fn default_max_top5() -> f64 {
6614 0.45
6615}
6616
6617fn default_single_source_percent() -> f64 {
6618 0.05
6619}
6620
6621impl Default for DependencySchemaConfig {
6622 fn default() -> Self {
6623 Self {
6624 max_single_vendor_concentration: 0.15,
6625 top_5_concentration: 0.45,
6626 single_source_percent: 0.05,
6627 }
6628 }
6629}
6630
6631#[derive(Debug, Clone, Default, Serialize, Deserialize)]
6637pub struct CustomerSegmentationSchemaConfig {
6638 #[serde(default)]
6640 pub enabled: bool,
6641
6642 #[serde(default)]
6644 pub value_segments: ValueSegmentsSchemaConfig,
6645
6646 #[serde(default)]
6648 pub lifecycle: LifecycleSchemaConfig,
6649
6650 #[serde(default)]
6652 pub networks: CustomerNetworksSchemaConfig,
6653}
6654
6655#[derive(Debug, Clone, Serialize, Deserialize)]
6657pub struct ValueSegmentsSchemaConfig {
6658 #[serde(default)]
6660 pub enterprise: SegmentDetailSchemaConfig,
6661
6662 #[serde(default)]
6664 pub mid_market: SegmentDetailSchemaConfig,
6665
6666 #[serde(default)]
6668 pub smb: SegmentDetailSchemaConfig,
6669
6670 #[serde(default)]
6672 pub consumer: SegmentDetailSchemaConfig,
6673}
6674
6675impl Default for ValueSegmentsSchemaConfig {
6676 fn default() -> Self {
6677 Self {
6678 enterprise: SegmentDetailSchemaConfig {
6679 revenue_share: 0.40,
6680 customer_share: 0.05,
6681 avg_order_value_range: "50000+".to_string(),
6682 },
6683 mid_market: SegmentDetailSchemaConfig {
6684 revenue_share: 0.35,
6685 customer_share: 0.20,
6686 avg_order_value_range: "5000-50000".to_string(),
6687 },
6688 smb: SegmentDetailSchemaConfig {
6689 revenue_share: 0.20,
6690 customer_share: 0.50,
6691 avg_order_value_range: "500-5000".to_string(),
6692 },
6693 consumer: SegmentDetailSchemaConfig {
6694 revenue_share: 0.05,
6695 customer_share: 0.25,
6696 avg_order_value_range: "50-500".to_string(),
6697 },
6698 }
6699 }
6700}
6701
6702#[derive(Debug, Clone, Serialize, Deserialize)]
6704pub struct SegmentDetailSchemaConfig {
6705 #[serde(default)]
6707 pub revenue_share: f64,
6708
6709 #[serde(default)]
6711 pub customer_share: f64,
6712
6713 #[serde(default)]
6715 pub avg_order_value_range: String,
6716}
6717
6718impl Default for SegmentDetailSchemaConfig {
6719 fn default() -> Self {
6720 Self {
6721 revenue_share: 0.25,
6722 customer_share: 0.25,
6723 avg_order_value_range: "1000-10000".to_string(),
6724 }
6725 }
6726}
6727
6728#[derive(Debug, Clone, Serialize, Deserialize)]
6730pub struct LifecycleSchemaConfig {
6731 #[serde(default)]
6733 pub prospect_rate: f64,
6734
6735 #[serde(default = "default_new_rate")]
6737 pub new_rate: f64,
6738
6739 #[serde(default = "default_growth_rate")]
6741 pub growth_rate: f64,
6742
6743 #[serde(default = "default_mature_rate")]
6745 pub mature_rate: f64,
6746
6747 #[serde(default = "default_at_risk_rate")]
6749 pub at_risk_rate: f64,
6750
6751 #[serde(default = "default_churned_rate")]
6753 pub churned_rate: f64,
6754}
6755
6756fn default_new_rate() -> f64 {
6757 0.10
6758}
6759
6760fn default_growth_rate() -> f64 {
6761 0.15
6762}
6763
6764fn default_mature_rate() -> f64 {
6765 0.60
6766}
6767
6768fn default_at_risk_rate() -> f64 {
6769 0.10
6770}
6771
6772fn default_churned_rate() -> f64 {
6773 0.05
6774}
6775
6776impl Default for LifecycleSchemaConfig {
6777 fn default() -> Self {
6778 Self {
6779 prospect_rate: 0.0,
6780 new_rate: 0.10,
6781 growth_rate: 0.15,
6782 mature_rate: 0.60,
6783 at_risk_rate: 0.10,
6784 churned_rate: 0.05,
6785 }
6786 }
6787}
6788
6789#[derive(Debug, Clone, Default, Serialize, Deserialize)]
6791pub struct CustomerNetworksSchemaConfig {
6792 #[serde(default)]
6794 pub referrals: ReferralSchemaConfig,
6795
6796 #[serde(default)]
6798 pub corporate_hierarchies: HierarchySchemaConfig,
6799}
6800
6801#[derive(Debug, Clone, Serialize, Deserialize)]
6803pub struct ReferralSchemaConfig {
6804 #[serde(default = "default_true")]
6806 pub enabled: bool,
6807
6808 #[serde(default = "default_referral_rate")]
6810 pub referral_rate: f64,
6811}
6812
6813fn default_referral_rate() -> f64 {
6814 0.15
6815}
6816
6817impl Default for ReferralSchemaConfig {
6818 fn default() -> Self {
6819 Self {
6820 enabled: true,
6821 referral_rate: 0.15,
6822 }
6823 }
6824}
6825
6826#[derive(Debug, Clone, Serialize, Deserialize)]
6828pub struct HierarchySchemaConfig {
6829 #[serde(default = "default_true")]
6831 pub enabled: bool,
6832
6833 #[serde(default = "default_hierarchy_rate")]
6835 pub probability: f64,
6836}
6837
6838fn default_hierarchy_rate() -> f64 {
6839 0.30
6840}
6841
6842impl Default for HierarchySchemaConfig {
6843 fn default() -> Self {
6844 Self {
6845 enabled: true,
6846 probability: 0.30,
6847 }
6848 }
6849}
6850
6851#[derive(Debug, Clone, Default, Serialize, Deserialize)]
6857pub struct RelationshipStrengthSchemaConfig {
6858 #[serde(default)]
6860 pub enabled: bool,
6861
6862 #[serde(default)]
6864 pub calculation: StrengthCalculationSchemaConfig,
6865
6866 #[serde(default)]
6868 pub thresholds: StrengthThresholdsSchemaConfig,
6869}
6870
6871#[derive(Debug, Clone, Serialize, Deserialize)]
6873pub struct StrengthCalculationSchemaConfig {
6874 #[serde(default = "default_volume_weight")]
6876 pub transaction_volume_weight: f64,
6877
6878 #[serde(default = "default_count_weight")]
6880 pub transaction_count_weight: f64,
6881
6882 #[serde(default = "default_duration_weight")]
6884 pub relationship_duration_weight: f64,
6885
6886 #[serde(default = "default_recency_weight")]
6888 pub recency_weight: f64,
6889
6890 #[serde(default = "default_mutual_weight")]
6892 pub mutual_connections_weight: f64,
6893
6894 #[serde(default = "default_recency_half_life")]
6896 pub recency_half_life_days: u32,
6897}
6898
6899fn default_volume_weight() -> f64 {
6900 0.30
6901}
6902
6903fn default_count_weight() -> f64 {
6904 0.25
6905}
6906
6907fn default_duration_weight() -> f64 {
6908 0.20
6909}
6910
6911fn default_recency_weight() -> f64 {
6912 0.15
6913}
6914
6915fn default_mutual_weight() -> f64 {
6916 0.10
6917}
6918
6919fn default_recency_half_life() -> u32 {
6920 90
6921}
6922
6923impl Default for StrengthCalculationSchemaConfig {
6924 fn default() -> Self {
6925 Self {
6926 transaction_volume_weight: 0.30,
6927 transaction_count_weight: 0.25,
6928 relationship_duration_weight: 0.20,
6929 recency_weight: 0.15,
6930 mutual_connections_weight: 0.10,
6931 recency_half_life_days: 90,
6932 }
6933 }
6934}
6935
6936#[derive(Debug, Clone, Serialize, Deserialize)]
6938pub struct StrengthThresholdsSchemaConfig {
6939 #[serde(default = "default_strong_threshold")]
6941 pub strong: f64,
6942
6943 #[serde(default = "default_moderate_threshold")]
6945 pub moderate: f64,
6946
6947 #[serde(default = "default_weak_threshold")]
6949 pub weak: f64,
6950}
6951
6952fn default_strong_threshold() -> f64 {
6953 0.7
6954}
6955
6956fn default_moderate_threshold() -> f64 {
6957 0.4
6958}
6959
6960fn default_weak_threshold() -> f64 {
6961 0.1
6962}
6963
6964impl Default for StrengthThresholdsSchemaConfig {
6965 fn default() -> Self {
6966 Self {
6967 strong: 0.7,
6968 moderate: 0.4,
6969 weak: 0.1,
6970 }
6971 }
6972}
6973
6974#[derive(Debug, Clone, Serialize, Deserialize)]
6980pub struct CrossProcessLinksSchemaConfig {
6981 #[serde(default)]
6983 pub enabled: bool,
6984
6985 #[serde(default = "default_true")]
6987 pub inventory_p2p_o2c: bool,
6988
6989 #[serde(default = "default_true")]
6991 pub payment_bank_reconciliation: bool,
6992
6993 #[serde(default = "default_true")]
6995 pub intercompany_bilateral: bool,
6996
6997 #[serde(default = "default_inventory_link_rate")]
6999 pub inventory_link_rate: f64,
7000}
7001
7002fn default_inventory_link_rate() -> f64 {
7003 0.30
7004}
7005
7006impl Default for CrossProcessLinksSchemaConfig {
7007 fn default() -> Self {
7008 Self {
7009 enabled: false,
7010 inventory_p2p_o2c: true,
7011 payment_bank_reconciliation: true,
7012 intercompany_bilateral: true,
7013 inventory_link_rate: 0.30,
7014 }
7015 }
7016}
7017
7018#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7024pub struct OrganizationalEventsSchemaConfig {
7025 #[serde(default)]
7027 pub enabled: bool,
7028
7029 #[serde(default)]
7031 pub effect_blending: EffectBlendingModeConfig,
7032
7033 #[serde(default)]
7035 pub events: Vec<OrganizationalEventSchemaConfig>,
7036
7037 #[serde(default)]
7039 pub process_evolution: Vec<ProcessEvolutionSchemaConfig>,
7040
7041 #[serde(default)]
7043 pub technology_transitions: Vec<TechnologyTransitionSchemaConfig>,
7044}
7045
7046#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
7048#[serde(rename_all = "snake_case")]
7049pub enum EffectBlendingModeConfig {
7050 #[default]
7052 Multiplicative,
7053 Additive,
7055 Maximum,
7057 Minimum,
7059}
7060
7061#[derive(Debug, Clone, Serialize, Deserialize)]
7063pub struct OrganizationalEventSchemaConfig {
7064 pub id: String,
7066
7067 pub event_type: OrganizationalEventTypeSchemaConfig,
7069
7070 pub effective_date: String,
7072
7073 #[serde(default = "default_org_transition_months")]
7075 pub transition_months: u32,
7076
7077 #[serde(default)]
7079 pub description: Option<String>,
7080}
7081
7082fn default_org_transition_months() -> u32 {
7083 6
7084}
7085
7086#[derive(Debug, Clone, Serialize, Deserialize)]
7088#[serde(tag = "type", rename_all = "snake_case")]
7089pub enum OrganizationalEventTypeSchemaConfig {
7090 Acquisition {
7092 acquired_entity: String,
7094 #[serde(default = "default_acquisition_volume")]
7096 volume_increase: f64,
7097 #[serde(default = "default_acquisition_error")]
7099 integration_error_rate: f64,
7100 #[serde(default = "default_parallel_days")]
7102 parallel_posting_days: u32,
7103 },
7104 Divestiture {
7106 divested_entity: String,
7108 #[serde(default = "default_divestiture_volume")]
7110 volume_reduction: f64,
7111 #[serde(default = "default_true_val")]
7113 remove_entity: bool,
7114 },
7115 Reorganization {
7117 #[serde(default)]
7119 cost_center_remapping: std::collections::HashMap<String, String>,
7120 #[serde(default = "default_reorg_error")]
7122 transition_error_rate: f64,
7123 },
7124 LeadershipChange {
7126 role: String,
7128 #[serde(default)]
7130 policy_changes: Vec<String>,
7131 },
7132 WorkforceReduction {
7134 #[serde(default = "default_workforce_reduction")]
7136 reduction_percent: f64,
7137 #[serde(default = "default_workforce_error")]
7139 error_rate_increase: f64,
7140 },
7141 Merger {
7143 merged_entity: String,
7145 #[serde(default = "default_merger_volume")]
7147 volume_increase: f64,
7148 },
7149}
7150
7151fn default_acquisition_volume() -> f64 {
7152 1.35
7153}
7154
7155fn default_acquisition_error() -> f64 {
7156 0.05
7157}
7158
7159fn default_parallel_days() -> u32 {
7160 30
7161}
7162
7163fn default_divestiture_volume() -> f64 {
7164 0.70
7165}
7166
7167fn default_true_val() -> bool {
7168 true
7169}
7170
7171fn default_reorg_error() -> f64 {
7172 0.04
7173}
7174
7175fn default_workforce_reduction() -> f64 {
7176 0.10
7177}
7178
7179fn default_workforce_error() -> f64 {
7180 0.05
7181}
7182
7183fn default_merger_volume() -> f64 {
7184 1.80
7185}
7186
7187#[derive(Debug, Clone, Serialize, Deserialize)]
7189pub struct ProcessEvolutionSchemaConfig {
7190 pub id: String,
7192
7193 pub event_type: ProcessEvolutionTypeSchemaConfig,
7195
7196 pub effective_date: String,
7198
7199 #[serde(default)]
7201 pub description: Option<String>,
7202}
7203
7204#[derive(Debug, Clone, Serialize, Deserialize)]
7206#[serde(tag = "type", rename_all = "snake_case")]
7207pub enum ProcessEvolutionTypeSchemaConfig {
7208 ProcessAutomation {
7210 process_name: String,
7212 #[serde(default = "default_manual_before")]
7214 manual_rate_before: f64,
7215 #[serde(default = "default_manual_after")]
7217 manual_rate_after: f64,
7218 },
7219 ApprovalWorkflowChange {
7221 description: String,
7223 },
7224 ControlEnhancement {
7226 control_id: String,
7228 #[serde(default = "default_error_reduction")]
7230 error_reduction: f64,
7231 },
7232}
7233
7234fn default_manual_before() -> f64 {
7235 0.80
7236}
7237
7238fn default_manual_after() -> f64 {
7239 0.15
7240}
7241
7242fn default_error_reduction() -> f64 {
7243 0.02
7244}
7245
7246#[derive(Debug, Clone, Serialize, Deserialize)]
7248pub struct TechnologyTransitionSchemaConfig {
7249 pub id: String,
7251
7252 pub event_type: TechnologyTransitionTypeSchemaConfig,
7254
7255 #[serde(default)]
7257 pub description: Option<String>,
7258}
7259
7260#[derive(Debug, Clone, Serialize, Deserialize)]
7262#[serde(tag = "type", rename_all = "snake_case")]
7263pub enum TechnologyTransitionTypeSchemaConfig {
7264 ErpMigration {
7266 source_system: String,
7268 target_system: String,
7270 cutover_date: String,
7272 stabilization_end: String,
7274 #[serde(default = "default_erp_duplicate_rate")]
7276 duplicate_rate: f64,
7277 #[serde(default = "default_format_mismatch")]
7279 format_mismatch_rate: f64,
7280 },
7281 ModuleImplementation {
7283 module_name: String,
7285 go_live_date: String,
7287 },
7288}
7289
7290fn default_erp_duplicate_rate() -> f64 {
7291 0.02
7292}
7293
7294fn default_format_mismatch() -> f64 {
7295 0.03
7296}
7297
7298#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7304pub struct BehavioralDriftSchemaConfig {
7305 #[serde(default)]
7307 pub enabled: bool,
7308
7309 #[serde(default)]
7311 pub vendor_behavior: VendorBehaviorSchemaConfig,
7312
7313 #[serde(default)]
7315 pub customer_behavior: CustomerBehaviorSchemaConfig,
7316
7317 #[serde(default)]
7319 pub employee_behavior: EmployeeBehaviorSchemaConfig,
7320
7321 #[serde(default)]
7323 pub collective: CollectiveBehaviorSchemaConfig,
7324}
7325
7326#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7328pub struct VendorBehaviorSchemaConfig {
7329 #[serde(default)]
7331 pub payment_terms_drift: PaymentTermsDriftSchemaConfig,
7332
7333 #[serde(default)]
7335 pub quality_drift: QualityDriftSchemaConfig,
7336}
7337
7338#[derive(Debug, Clone, Serialize, Deserialize)]
7340pub struct PaymentTermsDriftSchemaConfig {
7341 #[serde(default = "default_extension_rate")]
7343 pub extension_rate_per_year: f64,
7344
7345 #[serde(default = "default_economic_sensitivity")]
7347 pub economic_sensitivity: f64,
7348}
7349
7350fn default_extension_rate() -> f64 {
7351 2.5
7352}
7353
7354fn default_economic_sensitivity() -> f64 {
7355 1.0
7356}
7357
7358impl Default for PaymentTermsDriftSchemaConfig {
7359 fn default() -> Self {
7360 Self {
7361 extension_rate_per_year: 2.5,
7362 economic_sensitivity: 1.0,
7363 }
7364 }
7365}
7366
7367#[derive(Debug, Clone, Serialize, Deserialize)]
7369pub struct QualityDriftSchemaConfig {
7370 #[serde(default = "default_improvement_rate")]
7372 pub new_vendor_improvement_rate: f64,
7373
7374 #[serde(default = "default_decline_rate")]
7376 pub complacency_decline_rate: f64,
7377}
7378
7379fn default_improvement_rate() -> f64 {
7380 0.02
7381}
7382
7383fn default_decline_rate() -> f64 {
7384 0.01
7385}
7386
7387impl Default for QualityDriftSchemaConfig {
7388 fn default() -> Self {
7389 Self {
7390 new_vendor_improvement_rate: 0.02,
7391 complacency_decline_rate: 0.01,
7392 }
7393 }
7394}
7395
7396#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7398pub struct CustomerBehaviorSchemaConfig {
7399 #[serde(default)]
7401 pub payment_drift: CustomerPaymentDriftSchemaConfig,
7402
7403 #[serde(default)]
7405 pub order_drift: OrderDriftSchemaConfig,
7406}
7407
7408#[derive(Debug, Clone, Serialize, Deserialize)]
7410pub struct CustomerPaymentDriftSchemaConfig {
7411 #[serde(default = "default_downturn_extension")]
7413 pub downturn_days_extension: (u32, u32),
7414
7415 #[serde(default = "default_bad_debt_increase")]
7417 pub downturn_bad_debt_increase: f64,
7418}
7419
7420fn default_downturn_extension() -> (u32, u32) {
7421 (5, 15)
7422}
7423
7424fn default_bad_debt_increase() -> f64 {
7425 0.02
7426}
7427
7428impl Default for CustomerPaymentDriftSchemaConfig {
7429 fn default() -> Self {
7430 Self {
7431 downturn_days_extension: (5, 15),
7432 downturn_bad_debt_increase: 0.02,
7433 }
7434 }
7435}
7436
7437#[derive(Debug, Clone, Serialize, Deserialize)]
7439pub struct OrderDriftSchemaConfig {
7440 #[serde(default = "default_digital_shift")]
7442 pub digital_shift_rate: f64,
7443}
7444
7445fn default_digital_shift() -> f64 {
7446 0.05
7447}
7448
7449impl Default for OrderDriftSchemaConfig {
7450 fn default() -> Self {
7451 Self {
7452 digital_shift_rate: 0.05,
7453 }
7454 }
7455}
7456
7457#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7459pub struct EmployeeBehaviorSchemaConfig {
7460 #[serde(default)]
7462 pub approval_drift: ApprovalDriftSchemaConfig,
7463
7464 #[serde(default)]
7466 pub error_drift: ErrorDriftSchemaConfig,
7467}
7468
7469#[derive(Debug, Clone, Serialize, Deserialize)]
7471pub struct ApprovalDriftSchemaConfig {
7472 #[serde(default = "default_eom_intensity")]
7474 pub eom_intensity_increase_per_year: f64,
7475
7476 #[serde(default = "default_rubber_stamp")]
7478 pub rubber_stamp_volume_threshold: u32,
7479}
7480
7481fn default_eom_intensity() -> f64 {
7482 0.05
7483}
7484
7485fn default_rubber_stamp() -> u32 {
7486 50
7487}
7488
7489impl Default for ApprovalDriftSchemaConfig {
7490 fn default() -> Self {
7491 Self {
7492 eom_intensity_increase_per_year: 0.05,
7493 rubber_stamp_volume_threshold: 50,
7494 }
7495 }
7496}
7497
7498#[derive(Debug, Clone, Serialize, Deserialize)]
7500pub struct ErrorDriftSchemaConfig {
7501 #[serde(default = "default_new_error")]
7503 pub new_employee_error_rate: f64,
7504
7505 #[serde(default = "default_learning_months")]
7507 pub learning_curve_months: u32,
7508}
7509
7510fn default_new_error() -> f64 {
7511 0.08
7512}
7513
7514fn default_learning_months() -> u32 {
7515 6
7516}
7517
7518impl Default for ErrorDriftSchemaConfig {
7519 fn default() -> Self {
7520 Self {
7521 new_employee_error_rate: 0.08,
7522 learning_curve_months: 6,
7523 }
7524 }
7525}
7526
7527#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7529pub struct CollectiveBehaviorSchemaConfig {
7530 #[serde(default)]
7532 pub automation_adoption: AutomationAdoptionSchemaConfig,
7533}
7534
7535#[derive(Debug, Clone, Serialize, Deserialize)]
7537pub struct AutomationAdoptionSchemaConfig {
7538 #[serde(default)]
7540 pub s_curve_enabled: bool,
7541
7542 #[serde(default = "default_midpoint")]
7544 pub adoption_midpoint_months: u32,
7545
7546 #[serde(default = "default_steepness")]
7548 pub steepness: f64,
7549}
7550
7551fn default_midpoint() -> u32 {
7552 24
7553}
7554
7555fn default_steepness() -> f64 {
7556 0.15
7557}
7558
7559impl Default for AutomationAdoptionSchemaConfig {
7560 fn default() -> Self {
7561 Self {
7562 s_curve_enabled: false,
7563 adoption_midpoint_months: 24,
7564 steepness: 0.15,
7565 }
7566 }
7567}
7568
7569#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7575pub struct MarketDriftSchemaConfig {
7576 #[serde(default)]
7578 pub enabled: bool,
7579
7580 #[serde(default)]
7582 pub economic_cycle: MarketEconomicCycleSchemaConfig,
7583
7584 #[serde(default)]
7586 pub industry_cycles: std::collections::HashMap<String, IndustryCycleSchemaConfig>,
7587
7588 #[serde(default)]
7590 pub commodities: CommoditiesSchemaConfig,
7591}
7592
7593#[derive(Debug, Clone, Serialize, Deserialize)]
7595pub struct MarketEconomicCycleSchemaConfig {
7596 #[serde(default)]
7598 pub enabled: bool,
7599
7600 #[serde(default)]
7602 pub cycle_type: CycleTypeSchemaConfig,
7603
7604 #[serde(default = "default_market_cycle_period")]
7606 pub period_months: u32,
7607
7608 #[serde(default = "default_market_amplitude")]
7610 pub amplitude: f64,
7611
7612 #[serde(default)]
7614 pub recession: RecessionSchemaConfig,
7615}
7616
7617fn default_market_cycle_period() -> u32 {
7618 48
7619}
7620
7621fn default_market_amplitude() -> f64 {
7622 0.15
7623}
7624
7625impl Default for MarketEconomicCycleSchemaConfig {
7626 fn default() -> Self {
7627 Self {
7628 enabled: false,
7629 cycle_type: CycleTypeSchemaConfig::Sinusoidal,
7630 period_months: 48,
7631 amplitude: 0.15,
7632 recession: RecessionSchemaConfig::default(),
7633 }
7634 }
7635}
7636
7637#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
7639#[serde(rename_all = "snake_case")]
7640pub enum CycleTypeSchemaConfig {
7641 #[default]
7643 Sinusoidal,
7644 Asymmetric,
7646 MeanReverting,
7648}
7649
7650#[derive(Debug, Clone, Serialize, Deserialize)]
7652pub struct RecessionSchemaConfig {
7653 #[serde(default)]
7655 pub enabled: bool,
7656
7657 #[serde(default = "default_recession_prob")]
7659 pub probability_per_year: f64,
7660
7661 #[serde(default)]
7663 pub severity: RecessionSeveritySchemaConfig,
7664
7665 #[serde(default)]
7667 pub recession_periods: Vec<RecessionPeriodSchemaConfig>,
7668}
7669
7670fn default_recession_prob() -> f64 {
7671 0.10
7672}
7673
7674impl Default for RecessionSchemaConfig {
7675 fn default() -> Self {
7676 Self {
7677 enabled: false,
7678 probability_per_year: 0.10,
7679 severity: RecessionSeveritySchemaConfig::Moderate,
7680 recession_periods: Vec::new(),
7681 }
7682 }
7683}
7684
7685#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
7687#[serde(rename_all = "snake_case")]
7688pub enum RecessionSeveritySchemaConfig {
7689 Mild,
7691 #[default]
7693 Moderate,
7694 Severe,
7696}
7697
7698#[derive(Debug, Clone, Serialize, Deserialize)]
7700pub struct RecessionPeriodSchemaConfig {
7701 pub start_month: u32,
7703 pub duration_months: u32,
7705}
7706
7707#[derive(Debug, Clone, Serialize, Deserialize)]
7709pub struct IndustryCycleSchemaConfig {
7710 #[serde(default = "default_industry_period")]
7712 pub period_months: u32,
7713
7714 #[serde(default = "default_industry_amp")]
7716 pub amplitude: f64,
7717}
7718
7719fn default_industry_period() -> u32 {
7720 36
7721}
7722
7723fn default_industry_amp() -> f64 {
7724 0.20
7725}
7726
7727#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7729pub struct CommoditiesSchemaConfig {
7730 #[serde(default)]
7732 pub enabled: bool,
7733
7734 #[serde(default)]
7736 pub items: Vec<CommodityItemSchemaConfig>,
7737}
7738
7739#[derive(Debug, Clone, Serialize, Deserialize)]
7741pub struct CommodityItemSchemaConfig {
7742 pub name: String,
7744
7745 #[serde(default = "default_volatility")]
7747 pub volatility: f64,
7748
7749 #[serde(default)]
7751 pub cogs_pass_through: f64,
7752
7753 #[serde(default)]
7755 pub overhead_pass_through: f64,
7756}
7757
7758fn default_volatility() -> f64 {
7759 0.20
7760}
7761
7762#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7768pub struct DriftLabelingSchemaConfig {
7769 #[serde(default)]
7771 pub enabled: bool,
7772
7773 #[serde(default)]
7775 pub statistical: StatisticalDriftLabelingSchemaConfig,
7776
7777 #[serde(default)]
7779 pub categorical: CategoricalDriftLabelingSchemaConfig,
7780
7781 #[serde(default)]
7783 pub temporal: TemporalDriftLabelingSchemaConfig,
7784
7785 #[serde(default)]
7787 pub regulatory_calendar_preset: Option<String>,
7788}
7789
7790#[derive(Debug, Clone, Serialize, Deserialize)]
7792pub struct StatisticalDriftLabelingSchemaConfig {
7793 #[serde(default = "default_true_val")]
7795 pub enabled: bool,
7796
7797 #[serde(default = "default_min_magnitude")]
7799 pub min_magnitude_threshold: f64,
7800}
7801
7802fn default_min_magnitude() -> f64 {
7803 0.05
7804}
7805
7806impl Default for StatisticalDriftLabelingSchemaConfig {
7807 fn default() -> Self {
7808 Self {
7809 enabled: true,
7810 min_magnitude_threshold: 0.05,
7811 }
7812 }
7813}
7814
7815#[derive(Debug, Clone, Serialize, Deserialize)]
7817pub struct CategoricalDriftLabelingSchemaConfig {
7818 #[serde(default = "default_true_val")]
7820 pub enabled: bool,
7821}
7822
7823impl Default for CategoricalDriftLabelingSchemaConfig {
7824 fn default() -> Self {
7825 Self { enabled: true }
7826 }
7827}
7828
7829#[derive(Debug, Clone, Serialize, Deserialize)]
7831pub struct TemporalDriftLabelingSchemaConfig {
7832 #[serde(default = "default_true_val")]
7834 pub enabled: bool,
7835}
7836
7837impl Default for TemporalDriftLabelingSchemaConfig {
7838 fn default() -> Self {
7839 Self { enabled: true }
7840 }
7841}
7842
7843#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7856pub struct EnhancedAnomalyConfig {
7857 #[serde(default)]
7859 pub enabled: bool,
7860
7861 #[serde(default)]
7863 pub rates: AnomalyRateConfig,
7864
7865 #[serde(default)]
7867 pub multi_stage_schemes: MultiStageSchemeConfig,
7868
7869 #[serde(default)]
7871 pub correlated_injection: CorrelatedInjectionConfig,
7872
7873 #[serde(default)]
7875 pub near_miss: NearMissConfig,
7876
7877 #[serde(default)]
7879 pub difficulty_classification: DifficultyClassificationConfig,
7880
7881 #[serde(default)]
7883 pub context_aware: ContextAwareConfig,
7884
7885 #[serde(default)]
7887 pub labeling: EnhancedLabelingConfig,
7888}
7889
7890#[derive(Debug, Clone, Serialize, Deserialize)]
7892pub struct AnomalyRateConfig {
7893 #[serde(default = "default_total_anomaly_rate")]
7895 pub total_rate: f64,
7896
7897 #[serde(default = "default_fraud_anomaly_rate")]
7899 pub fraud_rate: f64,
7900
7901 #[serde(default = "default_error_anomaly_rate")]
7903 pub error_rate: f64,
7904
7905 #[serde(default = "default_process_anomaly_rate")]
7907 pub process_rate: f64,
7908}
7909
7910fn default_total_anomaly_rate() -> f64 {
7911 0.03
7912}
7913fn default_fraud_anomaly_rate() -> f64 {
7914 0.01
7915}
7916fn default_error_anomaly_rate() -> f64 {
7917 0.015
7918}
7919fn default_process_anomaly_rate() -> f64 {
7920 0.005
7921}
7922
7923impl Default for AnomalyRateConfig {
7924 fn default() -> Self {
7925 Self {
7926 total_rate: default_total_anomaly_rate(),
7927 fraud_rate: default_fraud_anomaly_rate(),
7928 error_rate: default_error_anomaly_rate(),
7929 process_rate: default_process_anomaly_rate(),
7930 }
7931 }
7932}
7933
7934#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7936pub struct MultiStageSchemeConfig {
7937 #[serde(default)]
7939 pub enabled: bool,
7940
7941 #[serde(default)]
7943 pub embezzlement: EmbezzlementSchemeConfig,
7944
7945 #[serde(default)]
7947 pub revenue_manipulation: RevenueManipulationSchemeConfig,
7948
7949 #[serde(default)]
7951 pub kickback: KickbackSchemeConfig,
7952}
7953
7954#[derive(Debug, Clone, Serialize, Deserialize)]
7956pub struct EmbezzlementSchemeConfig {
7957 #[serde(default = "default_embezzlement_probability")]
7959 pub probability: f64,
7960
7961 #[serde(default)]
7963 pub testing_stage: SchemeStageConfig,
7964
7965 #[serde(default)]
7967 pub escalation_stage: SchemeStageConfig,
7968
7969 #[serde(default)]
7971 pub acceleration_stage: SchemeStageConfig,
7972
7973 #[serde(default)]
7975 pub desperation_stage: SchemeStageConfig,
7976}
7977
7978fn default_embezzlement_probability() -> f64 {
7979 0.02
7980}
7981
7982impl Default for EmbezzlementSchemeConfig {
7983 fn default() -> Self {
7984 Self {
7985 probability: default_embezzlement_probability(),
7986 testing_stage: SchemeStageConfig {
7987 duration_months: 2,
7988 amount_min: 100.0,
7989 amount_max: 500.0,
7990 transaction_count_min: 2,
7991 transaction_count_max: 5,
7992 difficulty: "hard".to_string(),
7993 },
7994 escalation_stage: SchemeStageConfig {
7995 duration_months: 6,
7996 amount_min: 500.0,
7997 amount_max: 2000.0,
7998 transaction_count_min: 3,
7999 transaction_count_max: 8,
8000 difficulty: "moderate".to_string(),
8001 },
8002 acceleration_stage: SchemeStageConfig {
8003 duration_months: 3,
8004 amount_min: 2000.0,
8005 amount_max: 10000.0,
8006 transaction_count_min: 5,
8007 transaction_count_max: 12,
8008 difficulty: "easy".to_string(),
8009 },
8010 desperation_stage: SchemeStageConfig {
8011 duration_months: 1,
8012 amount_min: 10000.0,
8013 amount_max: 50000.0,
8014 transaction_count_min: 3,
8015 transaction_count_max: 6,
8016 difficulty: "trivial".to_string(),
8017 },
8018 }
8019 }
8020}
8021
8022#[derive(Debug, Clone, Serialize, Deserialize)]
8024pub struct RevenueManipulationSchemeConfig {
8025 #[serde(default = "default_revenue_manipulation_probability")]
8027 pub probability: f64,
8028
8029 #[serde(default = "default_early_recognition_target")]
8031 pub early_recognition_target: f64,
8032
8033 #[serde(default = "default_expense_deferral_target")]
8035 pub expense_deferral_target: f64,
8036
8037 #[serde(default = "default_reserve_release_target")]
8039 pub reserve_release_target: f64,
8040
8041 #[serde(default = "default_channel_stuffing_target")]
8043 pub channel_stuffing_target: f64,
8044}
8045
8046fn default_revenue_manipulation_probability() -> f64 {
8047 0.01
8048}
8049fn default_early_recognition_target() -> f64 {
8050 0.02
8051}
8052fn default_expense_deferral_target() -> f64 {
8053 0.03
8054}
8055fn default_reserve_release_target() -> f64 {
8056 0.02
8057}
8058fn default_channel_stuffing_target() -> f64 {
8059 0.05
8060}
8061
8062impl Default for RevenueManipulationSchemeConfig {
8063 fn default() -> Self {
8064 Self {
8065 probability: default_revenue_manipulation_probability(),
8066 early_recognition_target: default_early_recognition_target(),
8067 expense_deferral_target: default_expense_deferral_target(),
8068 reserve_release_target: default_reserve_release_target(),
8069 channel_stuffing_target: default_channel_stuffing_target(),
8070 }
8071 }
8072}
8073
8074#[derive(Debug, Clone, Serialize, Deserialize)]
8076pub struct KickbackSchemeConfig {
8077 #[serde(default = "default_kickback_probability")]
8079 pub probability: f64,
8080
8081 #[serde(default = "default_kickback_inflation_min")]
8083 pub inflation_min: f64,
8084
8085 #[serde(default = "default_kickback_inflation_max")]
8087 pub inflation_max: f64,
8088
8089 #[serde(default = "default_kickback_percent")]
8091 pub kickback_percent: f64,
8092
8093 #[serde(default = "default_kickback_setup_months")]
8095 pub setup_months: u32,
8096
8097 #[serde(default = "default_kickback_operation_months")]
8099 pub operation_months: u32,
8100}
8101
8102fn default_kickback_probability() -> f64 {
8103 0.01
8104}
8105fn default_kickback_inflation_min() -> f64 {
8106 0.10
8107}
8108fn default_kickback_inflation_max() -> f64 {
8109 0.25
8110}
8111fn default_kickback_percent() -> f64 {
8112 0.50
8113}
8114fn default_kickback_setup_months() -> u32 {
8115 3
8116}
8117fn default_kickback_operation_months() -> u32 {
8118 12
8119}
8120
8121impl Default for KickbackSchemeConfig {
8122 fn default() -> Self {
8123 Self {
8124 probability: default_kickback_probability(),
8125 inflation_min: default_kickback_inflation_min(),
8126 inflation_max: default_kickback_inflation_max(),
8127 kickback_percent: default_kickback_percent(),
8128 setup_months: default_kickback_setup_months(),
8129 operation_months: default_kickback_operation_months(),
8130 }
8131 }
8132}
8133
8134#[derive(Debug, Clone, Serialize, Deserialize)]
8136pub struct SchemeStageConfig {
8137 pub duration_months: u32,
8139
8140 pub amount_min: f64,
8142
8143 pub amount_max: f64,
8145
8146 pub transaction_count_min: u32,
8148
8149 pub transaction_count_max: u32,
8151
8152 pub difficulty: String,
8154}
8155
8156impl Default for SchemeStageConfig {
8157 fn default() -> Self {
8158 Self {
8159 duration_months: 3,
8160 amount_min: 100.0,
8161 amount_max: 1000.0,
8162 transaction_count_min: 2,
8163 transaction_count_max: 10,
8164 difficulty: "moderate".to_string(),
8165 }
8166 }
8167}
8168
8169#[derive(Debug, Clone, Serialize, Deserialize)]
8171pub struct CorrelatedInjectionConfig {
8172 #[serde(default)]
8174 pub enabled: bool,
8175
8176 #[serde(default = "default_true_val")]
8178 pub fraud_concealment: bool,
8179
8180 #[serde(default = "default_true_val")]
8182 pub error_cascade: bool,
8183
8184 #[serde(default = "default_true_val")]
8186 pub temporal_clustering: bool,
8187
8188 #[serde(default)]
8190 pub temporal_clustering_config: TemporalClusteringConfig,
8191
8192 #[serde(default)]
8194 pub co_occurrence_patterns: Vec<CoOccurrencePatternConfig>,
8195}
8196
8197impl Default for CorrelatedInjectionConfig {
8198 fn default() -> Self {
8199 Self {
8200 enabled: false,
8201 fraud_concealment: true,
8202 error_cascade: true,
8203 temporal_clustering: true,
8204 temporal_clustering_config: TemporalClusteringConfig::default(),
8205 co_occurrence_patterns: Vec::new(),
8206 }
8207 }
8208}
8209
8210#[derive(Debug, Clone, Serialize, Deserialize)]
8212pub struct TemporalClusteringConfig {
8213 #[serde(default = "default_period_end_multiplier")]
8215 pub period_end_multiplier: f64,
8216
8217 #[serde(default = "default_period_end_days")]
8219 pub period_end_days: u32,
8220
8221 #[serde(default = "default_quarter_end_multiplier")]
8223 pub quarter_end_multiplier: f64,
8224
8225 #[serde(default = "default_year_end_multiplier")]
8227 pub year_end_multiplier: f64,
8228}
8229
8230fn default_period_end_multiplier() -> f64 {
8231 2.5
8232}
8233fn default_period_end_days() -> u32 {
8234 5
8235}
8236fn default_quarter_end_multiplier() -> f64 {
8237 1.5
8238}
8239fn default_year_end_multiplier() -> f64 {
8240 2.0
8241}
8242
8243impl Default for TemporalClusteringConfig {
8244 fn default() -> Self {
8245 Self {
8246 period_end_multiplier: default_period_end_multiplier(),
8247 period_end_days: default_period_end_days(),
8248 quarter_end_multiplier: default_quarter_end_multiplier(),
8249 year_end_multiplier: default_year_end_multiplier(),
8250 }
8251 }
8252}
8253
8254#[derive(Debug, Clone, Serialize, Deserialize)]
8256pub struct CoOccurrencePatternConfig {
8257 pub name: String,
8259
8260 pub primary_type: String,
8262
8263 pub correlated: Vec<CorrelatedAnomalyConfig>,
8265}
8266
8267#[derive(Debug, Clone, Serialize, Deserialize)]
8269pub struct CorrelatedAnomalyConfig {
8270 pub anomaly_type: String,
8272
8273 pub probability: f64,
8275
8276 pub lag_days_min: i32,
8278
8279 pub lag_days_max: i32,
8281}
8282
8283#[derive(Debug, Clone, Serialize, Deserialize)]
8285pub struct NearMissConfig {
8286 #[serde(default)]
8288 pub enabled: bool,
8289
8290 #[serde(default = "default_near_miss_proportion")]
8292 pub proportion: f64,
8293
8294 #[serde(default = "default_true_val")]
8296 pub near_duplicate: bool,
8297
8298 #[serde(default)]
8300 pub near_duplicate_days: NearDuplicateDaysConfig,
8301
8302 #[serde(default = "default_true_val")]
8304 pub threshold_proximity: bool,
8305
8306 #[serde(default)]
8308 pub threshold_proximity_range: ThresholdProximityRangeConfig,
8309
8310 #[serde(default = "default_true_val")]
8312 pub unusual_legitimate: bool,
8313
8314 #[serde(default = "default_unusual_legitimate_types")]
8316 pub unusual_legitimate_types: Vec<String>,
8317
8318 #[serde(default = "default_true_val")]
8320 pub corrected_errors: bool,
8321
8322 #[serde(default)]
8324 pub corrected_error_lag: CorrectedErrorLagConfig,
8325}
8326
8327fn default_near_miss_proportion() -> f64 {
8328 0.30
8329}
8330
8331fn default_unusual_legitimate_types() -> Vec<String> {
8332 vec![
8333 "year_end_bonus".to_string(),
8334 "contract_prepayment".to_string(),
8335 "insurance_claim".to_string(),
8336 "settlement_payment".to_string(),
8337 ]
8338}
8339
8340impl Default for NearMissConfig {
8341 fn default() -> Self {
8342 Self {
8343 enabled: false,
8344 proportion: default_near_miss_proportion(),
8345 near_duplicate: true,
8346 near_duplicate_days: NearDuplicateDaysConfig::default(),
8347 threshold_proximity: true,
8348 threshold_proximity_range: ThresholdProximityRangeConfig::default(),
8349 unusual_legitimate: true,
8350 unusual_legitimate_types: default_unusual_legitimate_types(),
8351 corrected_errors: true,
8352 corrected_error_lag: CorrectedErrorLagConfig::default(),
8353 }
8354 }
8355}
8356
8357#[derive(Debug, Clone, Serialize, Deserialize)]
8359pub struct NearDuplicateDaysConfig {
8360 #[serde(default = "default_near_duplicate_min")]
8362 pub min: u32,
8363
8364 #[serde(default = "default_near_duplicate_max")]
8366 pub max: u32,
8367}
8368
8369fn default_near_duplicate_min() -> u32 {
8370 1
8371}
8372fn default_near_duplicate_max() -> u32 {
8373 3
8374}
8375
8376impl Default for NearDuplicateDaysConfig {
8377 fn default() -> Self {
8378 Self {
8379 min: default_near_duplicate_min(),
8380 max: default_near_duplicate_max(),
8381 }
8382 }
8383}
8384
8385#[derive(Debug, Clone, Serialize, Deserialize)]
8387pub struct ThresholdProximityRangeConfig {
8388 #[serde(default = "default_threshold_proximity_min")]
8390 pub min: f64,
8391
8392 #[serde(default = "default_threshold_proximity_max")]
8394 pub max: f64,
8395}
8396
8397fn default_threshold_proximity_min() -> f64 {
8398 0.90
8399}
8400fn default_threshold_proximity_max() -> f64 {
8401 0.99
8402}
8403
8404impl Default for ThresholdProximityRangeConfig {
8405 fn default() -> Self {
8406 Self {
8407 min: default_threshold_proximity_min(),
8408 max: default_threshold_proximity_max(),
8409 }
8410 }
8411}
8412
8413#[derive(Debug, Clone, Serialize, Deserialize)]
8415pub struct CorrectedErrorLagConfig {
8416 #[serde(default = "default_corrected_error_lag_min")]
8418 pub min: u32,
8419
8420 #[serde(default = "default_corrected_error_lag_max")]
8422 pub max: u32,
8423}
8424
8425fn default_corrected_error_lag_min() -> u32 {
8426 1
8427}
8428fn default_corrected_error_lag_max() -> u32 {
8429 5
8430}
8431
8432impl Default for CorrectedErrorLagConfig {
8433 fn default() -> Self {
8434 Self {
8435 min: default_corrected_error_lag_min(),
8436 max: default_corrected_error_lag_max(),
8437 }
8438 }
8439}
8440
8441#[derive(Debug, Clone, Serialize, Deserialize)]
8443pub struct DifficultyClassificationConfig {
8444 #[serde(default)]
8446 pub enabled: bool,
8447
8448 #[serde(default)]
8450 pub target_distribution: DifficultyDistributionConfig,
8451}
8452
8453impl Default for DifficultyClassificationConfig {
8454 fn default() -> Self {
8455 Self {
8456 enabled: true,
8457 target_distribution: DifficultyDistributionConfig::default(),
8458 }
8459 }
8460}
8461
8462#[derive(Debug, Clone, Serialize, Deserialize)]
8464pub struct DifficultyDistributionConfig {
8465 #[serde(default = "default_difficulty_trivial")]
8467 pub trivial: f64,
8468
8469 #[serde(default = "default_difficulty_easy")]
8471 pub easy: f64,
8472
8473 #[serde(default = "default_difficulty_moderate")]
8475 pub moderate: f64,
8476
8477 #[serde(default = "default_difficulty_hard")]
8479 pub hard: f64,
8480
8481 #[serde(default = "default_difficulty_expert")]
8483 pub expert: f64,
8484}
8485
8486fn default_difficulty_trivial() -> f64 {
8487 0.15
8488}
8489fn default_difficulty_easy() -> f64 {
8490 0.25
8491}
8492fn default_difficulty_moderate() -> f64 {
8493 0.30
8494}
8495fn default_difficulty_hard() -> f64 {
8496 0.20
8497}
8498fn default_difficulty_expert() -> f64 {
8499 0.10
8500}
8501
8502impl Default for DifficultyDistributionConfig {
8503 fn default() -> Self {
8504 Self {
8505 trivial: default_difficulty_trivial(),
8506 easy: default_difficulty_easy(),
8507 moderate: default_difficulty_moderate(),
8508 hard: default_difficulty_hard(),
8509 expert: default_difficulty_expert(),
8510 }
8511 }
8512}
8513
8514#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8516pub struct ContextAwareConfig {
8517 #[serde(default)]
8519 pub enabled: bool,
8520
8521 #[serde(default)]
8523 pub vendor_rules: VendorAnomalyRulesConfig,
8524
8525 #[serde(default)]
8527 pub employee_rules: EmployeeAnomalyRulesConfig,
8528
8529 #[serde(default)]
8531 pub account_rules: AccountAnomalyRulesConfig,
8532
8533 #[serde(default)]
8535 pub behavioral_baseline: BehavioralBaselineConfig,
8536}
8537
8538#[derive(Debug, Clone, Serialize, Deserialize)]
8540pub struct VendorAnomalyRulesConfig {
8541 #[serde(default = "default_new_vendor_multiplier")]
8543 pub new_vendor_error_multiplier: f64,
8544
8545 #[serde(default = "default_new_vendor_threshold")]
8547 pub new_vendor_threshold_days: u32,
8548
8549 #[serde(default = "default_international_multiplier")]
8551 pub international_error_multiplier: f64,
8552
8553 #[serde(default = "default_strategic_vendor_types")]
8555 pub strategic_vendor_anomaly_types: Vec<String>,
8556}
8557
8558fn default_new_vendor_multiplier() -> f64 {
8559 2.5
8560}
8561fn default_new_vendor_threshold() -> u32 {
8562 90
8563}
8564fn default_international_multiplier() -> f64 {
8565 1.5
8566}
8567fn default_strategic_vendor_types() -> Vec<String> {
8568 vec![
8569 "pricing_dispute".to_string(),
8570 "contract_violation".to_string(),
8571 ]
8572}
8573
8574impl Default for VendorAnomalyRulesConfig {
8575 fn default() -> Self {
8576 Self {
8577 new_vendor_error_multiplier: default_new_vendor_multiplier(),
8578 new_vendor_threshold_days: default_new_vendor_threshold(),
8579 international_error_multiplier: default_international_multiplier(),
8580 strategic_vendor_anomaly_types: default_strategic_vendor_types(),
8581 }
8582 }
8583}
8584
8585#[derive(Debug, Clone, Serialize, Deserialize)]
8587pub struct EmployeeAnomalyRulesConfig {
8588 #[serde(default = "default_new_employee_rate")]
8590 pub new_employee_error_rate: f64,
8591
8592 #[serde(default = "default_new_employee_threshold")]
8594 pub new_employee_threshold_days: u32,
8595
8596 #[serde(default = "default_volume_fatigue_threshold")]
8598 pub volume_fatigue_threshold: u32,
8599
8600 #[serde(default = "default_coverage_multiplier")]
8602 pub coverage_error_multiplier: f64,
8603}
8604
8605fn default_new_employee_rate() -> f64 {
8606 0.05
8607}
8608fn default_new_employee_threshold() -> u32 {
8609 180
8610}
8611fn default_volume_fatigue_threshold() -> u32 {
8612 50
8613}
8614fn default_coverage_multiplier() -> f64 {
8615 1.8
8616}
8617
8618impl Default for EmployeeAnomalyRulesConfig {
8619 fn default() -> Self {
8620 Self {
8621 new_employee_error_rate: default_new_employee_rate(),
8622 new_employee_threshold_days: default_new_employee_threshold(),
8623 volume_fatigue_threshold: default_volume_fatigue_threshold(),
8624 coverage_error_multiplier: default_coverage_multiplier(),
8625 }
8626 }
8627}
8628
8629#[derive(Debug, Clone, Serialize, Deserialize)]
8631pub struct AccountAnomalyRulesConfig {
8632 #[serde(default = "default_high_risk_multiplier")]
8634 pub high_risk_account_multiplier: f64,
8635
8636 #[serde(default = "default_high_risk_accounts")]
8638 pub high_risk_accounts: Vec<String>,
8639
8640 #[serde(default = "default_suspense_multiplier")]
8642 pub suspense_account_multiplier: f64,
8643
8644 #[serde(default = "default_suspense_accounts")]
8646 pub suspense_accounts: Vec<String>,
8647
8648 #[serde(default = "default_intercompany_multiplier")]
8650 pub intercompany_account_multiplier: f64,
8651}
8652
8653fn default_high_risk_multiplier() -> f64 {
8654 2.0
8655}
8656fn default_high_risk_accounts() -> Vec<String> {
8657 vec![
8658 "1100".to_string(), "2000".to_string(), "3000".to_string(), ]
8662}
8663fn default_suspense_multiplier() -> f64 {
8664 3.0
8665}
8666fn default_suspense_accounts() -> Vec<String> {
8667 vec!["9999".to_string(), "9998".to_string()]
8668}
8669fn default_intercompany_multiplier() -> f64 {
8670 1.5
8671}
8672
8673impl Default for AccountAnomalyRulesConfig {
8674 fn default() -> Self {
8675 Self {
8676 high_risk_account_multiplier: default_high_risk_multiplier(),
8677 high_risk_accounts: default_high_risk_accounts(),
8678 suspense_account_multiplier: default_suspense_multiplier(),
8679 suspense_accounts: default_suspense_accounts(),
8680 intercompany_account_multiplier: default_intercompany_multiplier(),
8681 }
8682 }
8683}
8684
8685#[derive(Debug, Clone, Serialize, Deserialize)]
8687pub struct BehavioralBaselineConfig {
8688 #[serde(default)]
8690 pub enabled: bool,
8691
8692 #[serde(default = "default_baseline_period")]
8694 pub baseline_period_days: u32,
8695
8696 #[serde(default = "default_deviation_threshold")]
8698 pub deviation_threshold_std: f64,
8699
8700 #[serde(default = "default_frequency_deviation")]
8702 pub frequency_deviation_threshold: f64,
8703}
8704
8705fn default_baseline_period() -> u32 {
8706 90
8707}
8708fn default_deviation_threshold() -> f64 {
8709 3.0
8710}
8711fn default_frequency_deviation() -> f64 {
8712 2.0
8713}
8714
8715impl Default for BehavioralBaselineConfig {
8716 fn default() -> Self {
8717 Self {
8718 enabled: false,
8719 baseline_period_days: default_baseline_period(),
8720 deviation_threshold_std: default_deviation_threshold(),
8721 frequency_deviation_threshold: default_frequency_deviation(),
8722 }
8723 }
8724}
8725
8726#[derive(Debug, Clone, Serialize, Deserialize)]
8728pub struct EnhancedLabelingConfig {
8729 #[serde(default = "default_true_val")]
8731 pub severity_scoring: bool,
8732
8733 #[serde(default = "default_true_val")]
8735 pub difficulty_classification: bool,
8736
8737 #[serde(default)]
8739 pub materiality_thresholds: MaterialityThresholdsConfig,
8740}
8741
8742impl Default for EnhancedLabelingConfig {
8743 fn default() -> Self {
8744 Self {
8745 severity_scoring: true,
8746 difficulty_classification: true,
8747 materiality_thresholds: MaterialityThresholdsConfig::default(),
8748 }
8749 }
8750}
8751
8752#[derive(Debug, Clone, Serialize, Deserialize)]
8754pub struct MaterialityThresholdsConfig {
8755 #[serde(default = "default_materiality_trivial")]
8757 pub trivial: f64,
8758
8759 #[serde(default = "default_materiality_immaterial")]
8761 pub immaterial: f64,
8762
8763 #[serde(default = "default_materiality_material")]
8765 pub material: f64,
8766
8767 #[serde(default = "default_materiality_highly_material")]
8769 pub highly_material: f64,
8770}
8771
8772fn default_materiality_trivial() -> f64 {
8773 0.001
8774}
8775fn default_materiality_immaterial() -> f64 {
8776 0.01
8777}
8778fn default_materiality_material() -> f64 {
8779 0.05
8780}
8781fn default_materiality_highly_material() -> f64 {
8782 0.10
8783}
8784
8785impl Default for MaterialityThresholdsConfig {
8786 fn default() -> Self {
8787 Self {
8788 trivial: default_materiality_trivial(),
8789 immaterial: default_materiality_immaterial(),
8790 material: default_materiality_material(),
8791 highly_material: default_materiality_highly_material(),
8792 }
8793 }
8794}
8795
8796#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8808pub struct IndustrySpecificConfig {
8809 #[serde(default)]
8811 pub enabled: bool,
8812
8813 #[serde(default)]
8815 pub manufacturing: ManufacturingConfig,
8816
8817 #[serde(default)]
8819 pub retail: RetailConfig,
8820
8821 #[serde(default)]
8823 pub healthcare: HealthcareConfig,
8824
8825 #[serde(default)]
8827 pub technology: TechnologyConfig,
8828
8829 #[serde(default)]
8831 pub financial_services: FinancialServicesConfig,
8832
8833 #[serde(default)]
8835 pub professional_services: ProfessionalServicesConfig,
8836}
8837
8838#[derive(Debug, Clone, Serialize, Deserialize)]
8840pub struct ManufacturingConfig {
8841 #[serde(default)]
8843 pub enabled: bool,
8844
8845 #[serde(default = "default_bom_depth")]
8847 pub bom_depth: u32,
8848
8849 #[serde(default)]
8851 pub just_in_time: bool,
8852
8853 #[serde(default = "default_production_order_types")]
8855 pub production_order_types: Vec<String>,
8856
8857 #[serde(default)]
8859 pub quality_framework: Option<String>,
8860
8861 #[serde(default = "default_supplier_tiers")]
8863 pub supplier_tiers: u32,
8864
8865 #[serde(default = "default_cost_frequency")]
8867 pub standard_cost_frequency: String,
8868
8869 #[serde(default = "default_yield_rate")]
8871 pub target_yield_rate: f64,
8872
8873 #[serde(default = "default_scrap_threshold")]
8875 pub scrap_alert_threshold: f64,
8876
8877 #[serde(default)]
8879 pub anomaly_rates: ManufacturingAnomalyRates,
8880}
8881
8882fn default_bom_depth() -> u32 {
8883 4
8884}
8885
8886fn default_production_order_types() -> Vec<String> {
8887 vec![
8888 "standard".to_string(),
8889 "rework".to_string(),
8890 "prototype".to_string(),
8891 ]
8892}
8893
8894fn default_supplier_tiers() -> u32 {
8895 2
8896}
8897
8898fn default_cost_frequency() -> String {
8899 "quarterly".to_string()
8900}
8901
8902fn default_yield_rate() -> f64 {
8903 0.97
8904}
8905
8906fn default_scrap_threshold() -> f64 {
8907 0.03
8908}
8909
8910impl Default for ManufacturingConfig {
8911 fn default() -> Self {
8912 Self {
8913 enabled: false,
8914 bom_depth: default_bom_depth(),
8915 just_in_time: false,
8916 production_order_types: default_production_order_types(),
8917 quality_framework: Some("ISO_9001".to_string()),
8918 supplier_tiers: default_supplier_tiers(),
8919 standard_cost_frequency: default_cost_frequency(),
8920 target_yield_rate: default_yield_rate(),
8921 scrap_alert_threshold: default_scrap_threshold(),
8922 anomaly_rates: ManufacturingAnomalyRates::default(),
8923 }
8924 }
8925}
8926
8927#[derive(Debug, Clone, Serialize, Deserialize)]
8929pub struct ManufacturingAnomalyRates {
8930 #[serde(default = "default_mfg_yield_rate")]
8932 pub yield_manipulation: f64,
8933
8934 #[serde(default = "default_mfg_labor_rate")]
8936 pub labor_misallocation: f64,
8937
8938 #[serde(default = "default_mfg_phantom_rate")]
8940 pub phantom_production: f64,
8941
8942 #[serde(default = "default_mfg_cost_rate")]
8944 pub standard_cost_manipulation: f64,
8945
8946 #[serde(default = "default_mfg_inventory_rate")]
8948 pub inventory_fraud: f64,
8949}
8950
8951fn default_mfg_yield_rate() -> f64 {
8952 0.015
8953}
8954
8955fn default_mfg_labor_rate() -> f64 {
8956 0.02
8957}
8958
8959fn default_mfg_phantom_rate() -> f64 {
8960 0.005
8961}
8962
8963fn default_mfg_cost_rate() -> f64 {
8964 0.01
8965}
8966
8967fn default_mfg_inventory_rate() -> f64 {
8968 0.008
8969}
8970
8971impl Default for ManufacturingAnomalyRates {
8972 fn default() -> Self {
8973 Self {
8974 yield_manipulation: default_mfg_yield_rate(),
8975 labor_misallocation: default_mfg_labor_rate(),
8976 phantom_production: default_mfg_phantom_rate(),
8977 standard_cost_manipulation: default_mfg_cost_rate(),
8978 inventory_fraud: default_mfg_inventory_rate(),
8979 }
8980 }
8981}
8982
8983#[derive(Debug, Clone, Serialize, Deserialize)]
8985pub struct RetailConfig {
8986 #[serde(default)]
8988 pub enabled: bool,
8989
8990 #[serde(default)]
8992 pub store_types: RetailStoreTypeConfig,
8993
8994 #[serde(default = "default_retail_daily_txns")]
8996 pub avg_daily_transactions: u32,
8997
8998 #[serde(default = "default_true")]
9000 pub loss_prevention: bool,
9001
9002 #[serde(default = "default_shrinkage_rate")]
9004 pub shrinkage_rate: f64,
9005
9006 #[serde(default)]
9008 pub anomaly_rates: RetailAnomalyRates,
9009}
9010
9011fn default_retail_daily_txns() -> u32 {
9012 500
9013}
9014
9015fn default_shrinkage_rate() -> f64 {
9016 0.015
9017}
9018
9019impl Default for RetailConfig {
9020 fn default() -> Self {
9021 Self {
9022 enabled: false,
9023 store_types: RetailStoreTypeConfig::default(),
9024 avg_daily_transactions: default_retail_daily_txns(),
9025 loss_prevention: true,
9026 shrinkage_rate: default_shrinkage_rate(),
9027 anomaly_rates: RetailAnomalyRates::default(),
9028 }
9029 }
9030}
9031
9032#[derive(Debug, Clone, Serialize, Deserialize)]
9034pub struct RetailStoreTypeConfig {
9035 #[serde(default = "default_flagship_pct")]
9037 pub flagship: f64,
9038
9039 #[serde(default = "default_regional_pct")]
9041 pub regional: f64,
9042
9043 #[serde(default = "default_outlet_pct")]
9045 pub outlet: f64,
9046
9047 #[serde(default = "default_ecommerce_pct")]
9049 pub ecommerce: f64,
9050}
9051
9052fn default_flagship_pct() -> f64 {
9053 0.10
9054}
9055
9056fn default_regional_pct() -> f64 {
9057 0.50
9058}
9059
9060fn default_outlet_pct() -> f64 {
9061 0.25
9062}
9063
9064fn default_ecommerce_pct() -> f64 {
9065 0.15
9066}
9067
9068impl Default for RetailStoreTypeConfig {
9069 fn default() -> Self {
9070 Self {
9071 flagship: default_flagship_pct(),
9072 regional: default_regional_pct(),
9073 outlet: default_outlet_pct(),
9074 ecommerce: default_ecommerce_pct(),
9075 }
9076 }
9077}
9078
9079#[derive(Debug, Clone, Serialize, Deserialize)]
9081pub struct RetailAnomalyRates {
9082 #[serde(default = "default_sweethearting_rate")]
9084 pub sweethearting: f64,
9085
9086 #[serde(default = "default_skimming_rate")]
9088 pub skimming: f64,
9089
9090 #[serde(default = "default_refund_fraud_rate")]
9092 pub refund_fraud: f64,
9093
9094 #[serde(default = "default_void_abuse_rate")]
9096 pub void_abuse: f64,
9097
9098 #[serde(default = "default_gift_card_rate")]
9100 pub gift_card_fraud: f64,
9101
9102 #[serde(default = "default_retail_kickback_rate")]
9104 pub vendor_kickback: f64,
9105}
9106
9107fn default_sweethearting_rate() -> f64 {
9108 0.02
9109}
9110
9111fn default_skimming_rate() -> f64 {
9112 0.005
9113}
9114
9115fn default_refund_fraud_rate() -> f64 {
9116 0.015
9117}
9118
9119fn default_void_abuse_rate() -> f64 {
9120 0.01
9121}
9122
9123fn default_gift_card_rate() -> f64 {
9124 0.008
9125}
9126
9127fn default_retail_kickback_rate() -> f64 {
9128 0.003
9129}
9130
9131impl Default for RetailAnomalyRates {
9132 fn default() -> Self {
9133 Self {
9134 sweethearting: default_sweethearting_rate(),
9135 skimming: default_skimming_rate(),
9136 refund_fraud: default_refund_fraud_rate(),
9137 void_abuse: default_void_abuse_rate(),
9138 gift_card_fraud: default_gift_card_rate(),
9139 vendor_kickback: default_retail_kickback_rate(),
9140 }
9141 }
9142}
9143
9144#[derive(Debug, Clone, Serialize, Deserialize)]
9146pub struct HealthcareConfig {
9147 #[serde(default)]
9149 pub enabled: bool,
9150
9151 #[serde(default = "default_facility_type")]
9153 pub facility_type: String,
9154
9155 #[serde(default)]
9157 pub payer_mix: HealthcarePayerMix,
9158
9159 #[serde(default)]
9161 pub coding_systems: HealthcareCodingSystems,
9162
9163 #[serde(default)]
9165 pub compliance: HealthcareComplianceConfig,
9166
9167 #[serde(default = "default_daily_encounters")]
9169 pub avg_daily_encounters: u32,
9170
9171 #[serde(default = "default_charges_per_encounter")]
9173 pub avg_charges_per_encounter: u32,
9174
9175 #[serde(default = "default_hc_denial_rate")]
9177 pub denial_rate: f64,
9178
9179 #[serde(default = "default_hc_bad_debt_rate")]
9181 pub bad_debt_rate: f64,
9182
9183 #[serde(default = "default_hc_charity_care_rate")]
9185 pub charity_care_rate: f64,
9186
9187 #[serde(default)]
9189 pub anomaly_rates: HealthcareAnomalyRates,
9190}
9191
9192fn default_facility_type() -> String {
9193 "hospital".to_string()
9194}
9195
9196fn default_daily_encounters() -> u32 {
9197 150
9198}
9199
9200fn default_charges_per_encounter() -> u32 {
9201 8
9202}
9203
9204fn default_hc_denial_rate() -> f64 {
9205 0.05
9206}
9207
9208fn default_hc_bad_debt_rate() -> f64 {
9209 0.03
9210}
9211
9212fn default_hc_charity_care_rate() -> f64 {
9213 0.02
9214}
9215
9216impl Default for HealthcareConfig {
9217 fn default() -> Self {
9218 Self {
9219 enabled: false,
9220 facility_type: default_facility_type(),
9221 payer_mix: HealthcarePayerMix::default(),
9222 coding_systems: HealthcareCodingSystems::default(),
9223 compliance: HealthcareComplianceConfig::default(),
9224 avg_daily_encounters: default_daily_encounters(),
9225 avg_charges_per_encounter: default_charges_per_encounter(),
9226 denial_rate: default_hc_denial_rate(),
9227 bad_debt_rate: default_hc_bad_debt_rate(),
9228 charity_care_rate: default_hc_charity_care_rate(),
9229 anomaly_rates: HealthcareAnomalyRates::default(),
9230 }
9231 }
9232}
9233
9234#[derive(Debug, Clone, Serialize, Deserialize)]
9236pub struct HealthcarePayerMix {
9237 #[serde(default = "default_medicare_pct")]
9239 pub medicare: f64,
9240
9241 #[serde(default = "default_medicaid_pct")]
9243 pub medicaid: f64,
9244
9245 #[serde(default = "default_commercial_pct")]
9247 pub commercial: f64,
9248
9249 #[serde(default = "default_self_pay_pct")]
9251 pub self_pay: f64,
9252}
9253
9254fn default_medicare_pct() -> f64 {
9255 0.40
9256}
9257
9258fn default_medicaid_pct() -> f64 {
9259 0.20
9260}
9261
9262fn default_commercial_pct() -> f64 {
9263 0.30
9264}
9265
9266fn default_self_pay_pct() -> f64 {
9267 0.10
9268}
9269
9270impl Default for HealthcarePayerMix {
9271 fn default() -> Self {
9272 Self {
9273 medicare: default_medicare_pct(),
9274 medicaid: default_medicaid_pct(),
9275 commercial: default_commercial_pct(),
9276 self_pay: default_self_pay_pct(),
9277 }
9278 }
9279}
9280
9281#[derive(Debug, Clone, Serialize, Deserialize)]
9283pub struct HealthcareCodingSystems {
9284 #[serde(default = "default_true")]
9286 pub icd10: bool,
9287
9288 #[serde(default = "default_true")]
9290 pub cpt: bool,
9291
9292 #[serde(default = "default_true")]
9294 pub drg: bool,
9295
9296 #[serde(default = "default_true")]
9298 pub hcpcs: bool,
9299
9300 #[serde(default = "default_true")]
9302 pub revenue_codes: bool,
9303}
9304
9305impl Default for HealthcareCodingSystems {
9306 fn default() -> Self {
9307 Self {
9308 icd10: true,
9309 cpt: true,
9310 drg: true,
9311 hcpcs: true,
9312 revenue_codes: true,
9313 }
9314 }
9315}
9316
9317#[derive(Debug, Clone, Serialize, Deserialize)]
9319pub struct HealthcareComplianceConfig {
9320 #[serde(default = "default_true")]
9322 pub hipaa: bool,
9323
9324 #[serde(default = "default_true")]
9326 pub stark_law: bool,
9327
9328 #[serde(default = "default_true")]
9330 pub anti_kickback: bool,
9331
9332 #[serde(default = "default_true")]
9334 pub false_claims_act: bool,
9335
9336 #[serde(default = "default_true")]
9338 pub emtala: bool,
9339}
9340
9341impl Default for HealthcareComplianceConfig {
9342 fn default() -> Self {
9343 Self {
9344 hipaa: true,
9345 stark_law: true,
9346 anti_kickback: true,
9347 false_claims_act: true,
9348 emtala: true,
9349 }
9350 }
9351}
9352
9353#[derive(Debug, Clone, Serialize, Deserialize)]
9355pub struct HealthcareAnomalyRates {
9356 #[serde(default = "default_upcoding_rate")]
9358 pub upcoding: f64,
9359
9360 #[serde(default = "default_unbundling_rate")]
9362 pub unbundling: f64,
9363
9364 #[serde(default = "default_phantom_billing_rate")]
9366 pub phantom_billing: f64,
9367
9368 #[serde(default = "default_healthcare_kickback_rate")]
9370 pub kickbacks: f64,
9371
9372 #[serde(default = "default_duplicate_billing_rate")]
9374 pub duplicate_billing: f64,
9375
9376 #[serde(default = "default_med_necessity_rate")]
9378 pub medical_necessity_abuse: f64,
9379}
9380
9381fn default_upcoding_rate() -> f64 {
9382 0.02
9383}
9384
9385fn default_unbundling_rate() -> f64 {
9386 0.015
9387}
9388
9389fn default_phantom_billing_rate() -> f64 {
9390 0.005
9391}
9392
9393fn default_healthcare_kickback_rate() -> f64 {
9394 0.003
9395}
9396
9397fn default_duplicate_billing_rate() -> f64 {
9398 0.008
9399}
9400
9401fn default_med_necessity_rate() -> f64 {
9402 0.01
9403}
9404
9405impl Default for HealthcareAnomalyRates {
9406 fn default() -> Self {
9407 Self {
9408 upcoding: default_upcoding_rate(),
9409 unbundling: default_unbundling_rate(),
9410 phantom_billing: default_phantom_billing_rate(),
9411 kickbacks: default_healthcare_kickback_rate(),
9412 duplicate_billing: default_duplicate_billing_rate(),
9413 medical_necessity_abuse: default_med_necessity_rate(),
9414 }
9415 }
9416}
9417
9418#[derive(Debug, Clone, Serialize, Deserialize)]
9420pub struct TechnologyConfig {
9421 #[serde(default)]
9423 pub enabled: bool,
9424
9425 #[serde(default = "default_revenue_model")]
9427 pub revenue_model: String,
9428
9429 #[serde(default = "default_subscription_pct")]
9431 pub subscription_revenue_pct: f64,
9432
9433 #[serde(default = "default_license_pct")]
9435 pub license_revenue_pct: f64,
9436
9437 #[serde(default = "default_services_pct")]
9439 pub services_revenue_pct: f64,
9440
9441 #[serde(default)]
9443 pub rd_capitalization: RdCapitalizationConfig,
9444
9445 #[serde(default)]
9447 pub anomaly_rates: TechnologyAnomalyRates,
9448}
9449
9450fn default_revenue_model() -> String {
9451 "saas".to_string()
9452}
9453
9454fn default_subscription_pct() -> f64 {
9455 0.60
9456}
9457
9458fn default_license_pct() -> f64 {
9459 0.25
9460}
9461
9462fn default_services_pct() -> f64 {
9463 0.15
9464}
9465
9466impl Default for TechnologyConfig {
9467 fn default() -> Self {
9468 Self {
9469 enabled: false,
9470 revenue_model: default_revenue_model(),
9471 subscription_revenue_pct: default_subscription_pct(),
9472 license_revenue_pct: default_license_pct(),
9473 services_revenue_pct: default_services_pct(),
9474 rd_capitalization: RdCapitalizationConfig::default(),
9475 anomaly_rates: TechnologyAnomalyRates::default(),
9476 }
9477 }
9478}
9479
9480#[derive(Debug, Clone, Serialize, Deserialize)]
9482pub struct RdCapitalizationConfig {
9483 #[serde(default = "default_true")]
9485 pub enabled: bool,
9486
9487 #[serde(default = "default_cap_rate")]
9489 pub capitalization_rate: f64,
9490
9491 #[serde(default = "default_useful_life")]
9493 pub useful_life_years: u32,
9494}
9495
9496fn default_cap_rate() -> f64 {
9497 0.30
9498}
9499
9500fn default_useful_life() -> u32 {
9501 3
9502}
9503
9504impl Default for RdCapitalizationConfig {
9505 fn default() -> Self {
9506 Self {
9507 enabled: true,
9508 capitalization_rate: default_cap_rate(),
9509 useful_life_years: default_useful_life(),
9510 }
9511 }
9512}
9513
9514#[derive(Debug, Clone, Serialize, Deserialize)]
9516pub struct TechnologyAnomalyRates {
9517 #[serde(default = "default_premature_rev_rate")]
9519 pub premature_revenue: f64,
9520
9521 #[serde(default = "default_side_letter_rate")]
9523 pub side_letter_abuse: f64,
9524
9525 #[serde(default = "default_channel_stuffing_rate")]
9527 pub channel_stuffing: f64,
9528
9529 #[serde(default = "default_improper_cap_rate")]
9531 pub improper_capitalization: f64,
9532}
9533
9534fn default_premature_rev_rate() -> f64 {
9535 0.015
9536}
9537
9538fn default_side_letter_rate() -> f64 {
9539 0.008
9540}
9541
9542fn default_channel_stuffing_rate() -> f64 {
9543 0.01
9544}
9545
9546fn default_improper_cap_rate() -> f64 {
9547 0.012
9548}
9549
9550impl Default for TechnologyAnomalyRates {
9551 fn default() -> Self {
9552 Self {
9553 premature_revenue: default_premature_rev_rate(),
9554 side_letter_abuse: default_side_letter_rate(),
9555 channel_stuffing: default_channel_stuffing_rate(),
9556 improper_capitalization: default_improper_cap_rate(),
9557 }
9558 }
9559}
9560
9561#[derive(Debug, Clone, Serialize, Deserialize)]
9563pub struct FinancialServicesConfig {
9564 #[serde(default)]
9566 pub enabled: bool,
9567
9568 #[serde(default = "default_fi_type")]
9570 pub institution_type: String,
9571
9572 #[serde(default = "default_fi_regulatory")]
9574 pub regulatory_framework: String,
9575
9576 #[serde(default)]
9578 pub anomaly_rates: FinancialServicesAnomalyRates,
9579}
9580
9581fn default_fi_type() -> String {
9582 "commercial_bank".to_string()
9583}
9584
9585fn default_fi_regulatory() -> String {
9586 "us_banking".to_string()
9587}
9588
9589impl Default for FinancialServicesConfig {
9590 fn default() -> Self {
9591 Self {
9592 enabled: false,
9593 institution_type: default_fi_type(),
9594 regulatory_framework: default_fi_regulatory(),
9595 anomaly_rates: FinancialServicesAnomalyRates::default(),
9596 }
9597 }
9598}
9599
9600#[derive(Debug, Clone, Serialize, Deserialize)]
9602pub struct FinancialServicesAnomalyRates {
9603 #[serde(default = "default_loan_fraud_rate")]
9605 pub loan_fraud: f64,
9606
9607 #[serde(default = "default_trading_fraud_rate")]
9609 pub trading_fraud: f64,
9610
9611 #[serde(default = "default_insurance_fraud_rate")]
9613 pub insurance_fraud: f64,
9614
9615 #[serde(default = "default_account_manip_rate")]
9617 pub account_manipulation: f64,
9618}
9619
9620fn default_loan_fraud_rate() -> f64 {
9621 0.01
9622}
9623
9624fn default_trading_fraud_rate() -> f64 {
9625 0.008
9626}
9627
9628fn default_insurance_fraud_rate() -> f64 {
9629 0.012
9630}
9631
9632fn default_account_manip_rate() -> f64 {
9633 0.005
9634}
9635
9636impl Default for FinancialServicesAnomalyRates {
9637 fn default() -> Self {
9638 Self {
9639 loan_fraud: default_loan_fraud_rate(),
9640 trading_fraud: default_trading_fraud_rate(),
9641 insurance_fraud: default_insurance_fraud_rate(),
9642 account_manipulation: default_account_manip_rate(),
9643 }
9644 }
9645}
9646
9647#[derive(Debug, Clone, Serialize, Deserialize)]
9649pub struct ProfessionalServicesConfig {
9650 #[serde(default)]
9652 pub enabled: bool,
9653
9654 #[serde(default = "default_firm_type")]
9656 pub firm_type: String,
9657
9658 #[serde(default = "default_billing_model")]
9660 pub billing_model: String,
9661
9662 #[serde(default = "default_hourly_rate")]
9664 pub avg_hourly_rate: f64,
9665
9666 #[serde(default)]
9668 pub trust_accounting: TrustAccountingConfig,
9669
9670 #[serde(default)]
9672 pub anomaly_rates: ProfessionalServicesAnomalyRates,
9673}
9674
9675fn default_firm_type() -> String {
9676 "consulting".to_string()
9677}
9678
9679fn default_billing_model() -> String {
9680 "time_and_materials".to_string()
9681}
9682
9683fn default_hourly_rate() -> f64 {
9684 250.0
9685}
9686
9687impl Default for ProfessionalServicesConfig {
9688 fn default() -> Self {
9689 Self {
9690 enabled: false,
9691 firm_type: default_firm_type(),
9692 billing_model: default_billing_model(),
9693 avg_hourly_rate: default_hourly_rate(),
9694 trust_accounting: TrustAccountingConfig::default(),
9695 anomaly_rates: ProfessionalServicesAnomalyRates::default(),
9696 }
9697 }
9698}
9699
9700#[derive(Debug, Clone, Serialize, Deserialize)]
9702pub struct TrustAccountingConfig {
9703 #[serde(default)]
9705 pub enabled: bool,
9706
9707 #[serde(default = "default_true")]
9709 pub require_three_way_reconciliation: bool,
9710}
9711
9712impl Default for TrustAccountingConfig {
9713 fn default() -> Self {
9714 Self {
9715 enabled: false,
9716 require_three_way_reconciliation: true,
9717 }
9718 }
9719}
9720
9721#[derive(Debug, Clone, Serialize, Deserialize)]
9723pub struct ProfessionalServicesAnomalyRates {
9724 #[serde(default = "default_time_fraud_rate")]
9726 pub time_billing_fraud: f64,
9727
9728 #[serde(default = "default_expense_fraud_rate")]
9730 pub expense_fraud: f64,
9731
9732 #[serde(default = "default_trust_misappropriation_rate")]
9734 pub trust_misappropriation: f64,
9735}
9736
9737fn default_time_fraud_rate() -> f64 {
9738 0.02
9739}
9740
9741fn default_expense_fraud_rate() -> f64 {
9742 0.015
9743}
9744
9745fn default_trust_misappropriation_rate() -> f64 {
9746 0.003
9747}
9748
9749impl Default for ProfessionalServicesAnomalyRates {
9750 fn default() -> Self {
9751 Self {
9752 time_billing_fraud: default_time_fraud_rate(),
9753 expense_fraud: default_expense_fraud_rate(),
9754 trust_misappropriation: default_trust_misappropriation_rate(),
9755 }
9756 }
9757}
9758
9759#[derive(Debug, Clone, Serialize, Deserialize)]
9773pub struct FingerprintPrivacyConfig {
9774 #[serde(default)]
9776 pub level: String,
9777 #[serde(default = "default_epsilon")]
9779 pub epsilon: f64,
9780 #[serde(default = "default_delta")]
9782 pub delta: f64,
9783 #[serde(default = "default_k_anonymity")]
9785 pub k_anonymity: u32,
9786 #[serde(default)]
9788 pub composition_method: String,
9789}
9790
9791fn default_epsilon() -> f64 {
9792 1.0
9793}
9794
9795fn default_delta() -> f64 {
9796 1e-5
9797}
9798
9799fn default_k_anonymity() -> u32 {
9800 5
9801}
9802
9803impl Default for FingerprintPrivacyConfig {
9804 fn default() -> Self {
9805 Self {
9806 level: "standard".to_string(),
9807 epsilon: default_epsilon(),
9808 delta: default_delta(),
9809 k_anonymity: default_k_anonymity(),
9810 composition_method: "naive".to_string(),
9811 }
9812 }
9813}
9814
9815#[derive(Debug, Clone, Serialize, Deserialize)]
9829pub struct QualityGatesSchemaConfig {
9830 #[serde(default)]
9832 pub enabled: bool,
9833 #[serde(default = "default_gate_profile_name")]
9835 pub profile: String,
9836 #[serde(default)]
9838 pub fail_on_violation: bool,
9839 #[serde(default)]
9841 pub custom_gates: Vec<QualityGateEntry>,
9842}
9843
9844fn default_gate_profile_name() -> String {
9845 "default".to_string()
9846}
9847
9848impl Default for QualityGatesSchemaConfig {
9849 fn default() -> Self {
9850 Self {
9851 enabled: false,
9852 profile: default_gate_profile_name(),
9853 fail_on_violation: false,
9854 custom_gates: Vec::new(),
9855 }
9856 }
9857}
9858
9859#[derive(Debug, Clone, Serialize, Deserialize)]
9861pub struct QualityGateEntry {
9862 pub name: String,
9864 pub metric: String,
9868 pub threshold: f64,
9870 #[serde(default)]
9872 pub upper_threshold: Option<f64>,
9873 #[serde(default = "default_gate_comparison")]
9875 pub comparison: String,
9876}
9877
9878fn default_gate_comparison() -> String {
9879 "gte".to_string()
9880}
9881
9882#[derive(Debug, Clone, Default, Serialize, Deserialize)]
9892pub struct ComplianceSchemaConfig {
9893 #[serde(default)]
9895 pub content_marking: ContentMarkingSchemaConfig,
9896 #[serde(default)]
9898 pub article10_report: bool,
9899 #[serde(default)]
9901 pub certificates: CertificateSchemaConfig,
9902}
9903
9904#[derive(Debug, Clone, Default, Serialize, Deserialize)]
9906pub struct CertificateSchemaConfig {
9907 #[serde(default)]
9909 pub enabled: bool,
9910 #[serde(default)]
9912 pub signing_key_env: Option<String>,
9913 #[serde(default)]
9915 pub include_quality_metrics: bool,
9916}
9917
9918#[derive(Debug, Clone, Serialize, Deserialize)]
9920pub struct ContentMarkingSchemaConfig {
9921 #[serde(default = "default_true")]
9923 pub enabled: bool,
9924 #[serde(default = "default_marking_format")]
9926 pub format: String,
9927}
9928
9929fn default_marking_format() -> String {
9930 "embedded".to_string()
9931}
9932
9933impl Default for ContentMarkingSchemaConfig {
9934 fn default() -> Self {
9935 Self {
9936 enabled: true,
9937 format: default_marking_format(),
9938 }
9939 }
9940}
9941
9942#[derive(Debug, Clone, Default, Serialize, Deserialize)]
9944pub struct WebhookSchemaConfig {
9945 #[serde(default)]
9947 pub enabled: bool,
9948 #[serde(default)]
9950 pub endpoints: Vec<WebhookEndpointConfig>,
9951}
9952
9953#[derive(Debug, Clone, Serialize, Deserialize)]
9955pub struct WebhookEndpointConfig {
9956 pub url: String,
9958 #[serde(default)]
9960 pub events: Vec<String>,
9961 #[serde(default)]
9963 pub secret: Option<String>,
9964 #[serde(default = "default_webhook_retries")]
9966 pub max_retries: u32,
9967 #[serde(default = "default_webhook_timeout")]
9969 pub timeout_secs: u64,
9970}
9971
9972fn default_webhook_retries() -> u32 {
9973 3
9974}
9975fn default_webhook_timeout() -> u64 {
9976 10
9977}
9978
9979#[derive(Debug, Clone, Default, Serialize, Deserialize)]
9985pub struct SourceToPayConfig {
9986 #[serde(default)]
9988 pub enabled: bool,
9989 #[serde(default)]
9991 pub spend_analysis: SpendAnalysisConfig,
9992 #[serde(default)]
9994 pub sourcing: SourcingConfig,
9995 #[serde(default)]
9997 pub qualification: QualificationConfig,
9998 #[serde(default)]
10000 pub rfx: RfxConfig,
10001 #[serde(default)]
10003 pub contracts: ContractConfig,
10004 #[serde(default)]
10006 pub catalog: CatalogConfig,
10007 #[serde(default)]
10009 pub scorecards: ScorecardConfig,
10010 #[serde(default)]
10012 pub p2p_integration: P2PIntegrationConfig,
10013}
10014
10015#[derive(Debug, Clone, Serialize, Deserialize)]
10017pub struct SpendAnalysisConfig {
10018 #[serde(default = "default_hhi_threshold")]
10020 pub hhi_threshold: f64,
10021 #[serde(default = "default_contract_coverage_target")]
10023 pub contract_coverage_target: f64,
10024}
10025
10026impl Default for SpendAnalysisConfig {
10027 fn default() -> Self {
10028 Self {
10029 hhi_threshold: default_hhi_threshold(),
10030 contract_coverage_target: default_contract_coverage_target(),
10031 }
10032 }
10033}
10034
10035fn default_hhi_threshold() -> f64 {
10036 2500.0
10037}
10038fn default_contract_coverage_target() -> f64 {
10039 0.80
10040}
10041
10042#[derive(Debug, Clone, Serialize, Deserialize)]
10044pub struct SourcingConfig {
10045 #[serde(default = "default_sourcing_projects_per_year")]
10047 pub projects_per_year: u32,
10048 #[serde(default = "default_renewal_horizon_months")]
10050 pub renewal_horizon_months: u32,
10051 #[serde(default = "default_project_duration_months")]
10053 pub project_duration_months: u32,
10054}
10055
10056impl Default for SourcingConfig {
10057 fn default() -> Self {
10058 Self {
10059 projects_per_year: default_sourcing_projects_per_year(),
10060 renewal_horizon_months: default_renewal_horizon_months(),
10061 project_duration_months: default_project_duration_months(),
10062 }
10063 }
10064}
10065
10066fn default_sourcing_projects_per_year() -> u32 {
10067 10
10068}
10069fn default_renewal_horizon_months() -> u32 {
10070 3
10071}
10072fn default_project_duration_months() -> u32 {
10073 4
10074}
10075
10076#[derive(Debug, Clone, Serialize, Deserialize)]
10078pub struct QualificationConfig {
10079 #[serde(default = "default_qualification_pass_rate")]
10081 pub pass_rate: f64,
10082 #[serde(default = "default_qualification_validity_days")]
10084 pub validity_days: u32,
10085 #[serde(default = "default_financial_weight")]
10087 pub financial_weight: f64,
10088 #[serde(default = "default_quality_weight")]
10090 pub quality_weight: f64,
10091 #[serde(default = "default_delivery_weight")]
10093 pub delivery_weight: f64,
10094 #[serde(default = "default_compliance_weight")]
10096 pub compliance_weight: f64,
10097}
10098
10099impl Default for QualificationConfig {
10100 fn default() -> Self {
10101 Self {
10102 pass_rate: default_qualification_pass_rate(),
10103 validity_days: default_qualification_validity_days(),
10104 financial_weight: default_financial_weight(),
10105 quality_weight: default_quality_weight(),
10106 delivery_weight: default_delivery_weight(),
10107 compliance_weight: default_compliance_weight(),
10108 }
10109 }
10110}
10111
10112fn default_qualification_pass_rate() -> f64 {
10113 0.75
10114}
10115fn default_qualification_validity_days() -> u32 {
10116 365
10117}
10118fn default_financial_weight() -> f64 {
10119 0.25
10120}
10121fn default_quality_weight() -> f64 {
10122 0.30
10123}
10124fn default_delivery_weight() -> f64 {
10125 0.25
10126}
10127fn default_compliance_weight() -> f64 {
10128 0.20
10129}
10130
10131#[derive(Debug, Clone, Serialize, Deserialize)]
10133pub struct RfxConfig {
10134 #[serde(default = "default_rfi_threshold")]
10136 pub rfi_threshold: f64,
10137 #[serde(default = "default_min_invited_vendors")]
10139 pub min_invited_vendors: u32,
10140 #[serde(default = "default_max_invited_vendors")]
10142 pub max_invited_vendors: u32,
10143 #[serde(default = "default_response_rate")]
10145 pub response_rate: f64,
10146 #[serde(default = "default_price_weight")]
10148 pub default_price_weight: f64,
10149 #[serde(default = "default_rfx_quality_weight")]
10151 pub default_quality_weight: f64,
10152 #[serde(default = "default_rfx_delivery_weight")]
10154 pub default_delivery_weight: f64,
10155}
10156
10157impl Default for RfxConfig {
10158 fn default() -> Self {
10159 Self {
10160 rfi_threshold: default_rfi_threshold(),
10161 min_invited_vendors: default_min_invited_vendors(),
10162 max_invited_vendors: default_max_invited_vendors(),
10163 response_rate: default_response_rate(),
10164 default_price_weight: default_price_weight(),
10165 default_quality_weight: default_rfx_quality_weight(),
10166 default_delivery_weight: default_rfx_delivery_weight(),
10167 }
10168 }
10169}
10170
10171fn default_rfi_threshold() -> f64 {
10172 100_000.0
10173}
10174fn default_min_invited_vendors() -> u32 {
10175 3
10176}
10177fn default_max_invited_vendors() -> u32 {
10178 8
10179}
10180fn default_response_rate() -> f64 {
10181 0.70
10182}
10183fn default_price_weight() -> f64 {
10184 0.40
10185}
10186fn default_rfx_quality_weight() -> f64 {
10187 0.35
10188}
10189fn default_rfx_delivery_weight() -> f64 {
10190 0.25
10191}
10192
10193#[derive(Debug, Clone, Serialize, Deserialize)]
10195pub struct ContractConfig {
10196 #[serde(default = "default_min_contract_months")]
10198 pub min_duration_months: u32,
10199 #[serde(default = "default_max_contract_months")]
10201 pub max_duration_months: u32,
10202 #[serde(default = "default_auto_renewal_rate")]
10204 pub auto_renewal_rate: f64,
10205 #[serde(default = "default_amendment_rate")]
10207 pub amendment_rate: f64,
10208 #[serde(default)]
10210 pub type_distribution: ContractTypeDistribution,
10211}
10212
10213impl Default for ContractConfig {
10214 fn default() -> Self {
10215 Self {
10216 min_duration_months: default_min_contract_months(),
10217 max_duration_months: default_max_contract_months(),
10218 auto_renewal_rate: default_auto_renewal_rate(),
10219 amendment_rate: default_amendment_rate(),
10220 type_distribution: ContractTypeDistribution::default(),
10221 }
10222 }
10223}
10224
10225fn default_min_contract_months() -> u32 {
10226 12
10227}
10228fn default_max_contract_months() -> u32 {
10229 36
10230}
10231fn default_auto_renewal_rate() -> f64 {
10232 0.40
10233}
10234fn default_amendment_rate() -> f64 {
10235 0.20
10236}
10237
10238#[derive(Debug, Clone, Serialize, Deserialize)]
10240pub struct ContractTypeDistribution {
10241 #[serde(default = "default_fixed_price_pct")]
10243 pub fixed_price: f64,
10244 #[serde(default = "default_blanket_pct")]
10246 pub blanket: f64,
10247 #[serde(default = "default_time_materials_pct")]
10249 pub time_and_materials: f64,
10250 #[serde(default = "default_service_agreement_pct")]
10252 pub service_agreement: f64,
10253}
10254
10255impl Default for ContractTypeDistribution {
10256 fn default() -> Self {
10257 Self {
10258 fixed_price: default_fixed_price_pct(),
10259 blanket: default_blanket_pct(),
10260 time_and_materials: default_time_materials_pct(),
10261 service_agreement: default_service_agreement_pct(),
10262 }
10263 }
10264}
10265
10266fn default_fixed_price_pct() -> f64 {
10267 0.40
10268}
10269fn default_blanket_pct() -> f64 {
10270 0.30
10271}
10272fn default_time_materials_pct() -> f64 {
10273 0.15
10274}
10275fn default_service_agreement_pct() -> f64 {
10276 0.15
10277}
10278
10279#[derive(Debug, Clone, Serialize, Deserialize)]
10281pub struct CatalogConfig {
10282 #[serde(default = "default_preferred_vendor_flag_rate")]
10284 pub preferred_vendor_flag_rate: f64,
10285 #[serde(default = "default_multi_source_rate")]
10287 pub multi_source_rate: f64,
10288}
10289
10290impl Default for CatalogConfig {
10291 fn default() -> Self {
10292 Self {
10293 preferred_vendor_flag_rate: default_preferred_vendor_flag_rate(),
10294 multi_source_rate: default_multi_source_rate(),
10295 }
10296 }
10297}
10298
10299fn default_preferred_vendor_flag_rate() -> f64 {
10300 0.70
10301}
10302fn default_multi_source_rate() -> f64 {
10303 0.25
10304}
10305
10306#[derive(Debug, Clone, Serialize, Deserialize)]
10308pub struct ScorecardConfig {
10309 #[serde(default = "default_scorecard_frequency")]
10311 pub frequency: String,
10312 #[serde(default = "default_otd_weight")]
10314 pub on_time_delivery_weight: f64,
10315 #[serde(default = "default_quality_score_weight")]
10317 pub quality_weight: f64,
10318 #[serde(default = "default_price_score_weight")]
10320 pub price_weight: f64,
10321 #[serde(default = "default_responsiveness_weight")]
10323 pub responsiveness_weight: f64,
10324 #[serde(default = "default_grade_a_threshold")]
10326 pub grade_a_threshold: f64,
10327 #[serde(default = "default_grade_b_threshold")]
10329 pub grade_b_threshold: f64,
10330 #[serde(default = "default_grade_c_threshold")]
10332 pub grade_c_threshold: f64,
10333}
10334
10335impl Default for ScorecardConfig {
10336 fn default() -> Self {
10337 Self {
10338 frequency: default_scorecard_frequency(),
10339 on_time_delivery_weight: default_otd_weight(),
10340 quality_weight: default_quality_score_weight(),
10341 price_weight: default_price_score_weight(),
10342 responsiveness_weight: default_responsiveness_weight(),
10343 grade_a_threshold: default_grade_a_threshold(),
10344 grade_b_threshold: default_grade_b_threshold(),
10345 grade_c_threshold: default_grade_c_threshold(),
10346 }
10347 }
10348}
10349
10350fn default_scorecard_frequency() -> String {
10351 "quarterly".to_string()
10352}
10353fn default_otd_weight() -> f64 {
10354 0.30
10355}
10356fn default_quality_score_weight() -> f64 {
10357 0.30
10358}
10359fn default_price_score_weight() -> f64 {
10360 0.25
10361}
10362fn default_responsiveness_weight() -> f64 {
10363 0.15
10364}
10365fn default_grade_a_threshold() -> f64 {
10366 90.0
10367}
10368fn default_grade_b_threshold() -> f64 {
10369 75.0
10370}
10371fn default_grade_c_threshold() -> f64 {
10372 60.0
10373}
10374
10375#[derive(Debug, Clone, Serialize, Deserialize)]
10377pub struct P2PIntegrationConfig {
10378 #[serde(default = "default_off_contract_rate")]
10380 pub off_contract_rate: f64,
10381 #[serde(default = "default_price_tolerance")]
10383 pub price_tolerance: f64,
10384 #[serde(default)]
10386 pub catalog_enforcement: bool,
10387}
10388
10389impl Default for P2PIntegrationConfig {
10390 fn default() -> Self {
10391 Self {
10392 off_contract_rate: default_off_contract_rate(),
10393 price_tolerance: default_price_tolerance(),
10394 catalog_enforcement: false,
10395 }
10396 }
10397}
10398
10399fn default_off_contract_rate() -> f64 {
10400 0.15
10401}
10402fn default_price_tolerance() -> f64 {
10403 0.02
10404}
10405
10406#[derive(Debug, Clone, Serialize, Deserialize)]
10410pub struct FinancialReportingConfig {
10411 #[serde(default)]
10413 pub enabled: bool,
10414 #[serde(default = "default_true")]
10416 pub generate_balance_sheet: bool,
10417 #[serde(default = "default_true")]
10419 pub generate_income_statement: bool,
10420 #[serde(default = "default_true")]
10422 pub generate_cash_flow: bool,
10423 #[serde(default = "default_true")]
10425 pub generate_changes_in_equity: bool,
10426 #[serde(default = "default_comparative_periods")]
10428 pub comparative_periods: u32,
10429 #[serde(default)]
10431 pub management_kpis: ManagementKpisConfig,
10432 #[serde(default)]
10434 pub budgets: BudgetConfig,
10435}
10436
10437impl Default for FinancialReportingConfig {
10438 fn default() -> Self {
10439 Self {
10440 enabled: false,
10441 generate_balance_sheet: true,
10442 generate_income_statement: true,
10443 generate_cash_flow: true,
10444 generate_changes_in_equity: true,
10445 comparative_periods: default_comparative_periods(),
10446 management_kpis: ManagementKpisConfig::default(),
10447 budgets: BudgetConfig::default(),
10448 }
10449 }
10450}
10451
10452fn default_comparative_periods() -> u32 {
10453 1
10454}
10455
10456#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10458pub struct ManagementKpisConfig {
10459 #[serde(default)]
10461 pub enabled: bool,
10462 #[serde(default = "default_kpi_frequency")]
10464 pub frequency: String,
10465}
10466
10467fn default_kpi_frequency() -> String {
10468 "monthly".to_string()
10469}
10470
10471#[derive(Debug, Clone, Serialize, Deserialize)]
10473pub struct BudgetConfig {
10474 #[serde(default)]
10476 pub enabled: bool,
10477 #[serde(default = "default_revenue_growth_rate")]
10479 pub revenue_growth_rate: f64,
10480 #[serde(default = "default_expense_inflation_rate")]
10482 pub expense_inflation_rate: f64,
10483 #[serde(default = "default_variance_noise")]
10485 pub variance_noise: f64,
10486}
10487
10488impl Default for BudgetConfig {
10489 fn default() -> Self {
10490 Self {
10491 enabled: false,
10492 revenue_growth_rate: default_revenue_growth_rate(),
10493 expense_inflation_rate: default_expense_inflation_rate(),
10494 variance_noise: default_variance_noise(),
10495 }
10496 }
10497}
10498
10499fn default_revenue_growth_rate() -> f64 {
10500 0.05
10501}
10502fn default_expense_inflation_rate() -> f64 {
10503 0.03
10504}
10505fn default_variance_noise() -> f64 {
10506 0.10
10507}
10508
10509#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10513pub struct HrConfig {
10514 #[serde(default)]
10516 pub enabled: bool,
10517 #[serde(default)]
10519 pub payroll: PayrollConfig,
10520 #[serde(default)]
10522 pub time_attendance: TimeAttendanceConfig,
10523 #[serde(default)]
10525 pub expenses: ExpenseConfig,
10526}
10527
10528#[derive(Debug, Clone, Serialize, Deserialize)]
10530pub struct PayrollConfig {
10531 #[serde(default = "default_true")]
10533 pub enabled: bool,
10534 #[serde(default = "default_pay_frequency")]
10536 pub pay_frequency: String,
10537 #[serde(default)]
10539 pub salary_ranges: PayrollSalaryRanges,
10540 #[serde(default)]
10542 pub tax_rates: PayrollTaxRates,
10543 #[serde(default = "default_benefits_enrollment_rate")]
10545 pub benefits_enrollment_rate: f64,
10546 #[serde(default = "default_retirement_participation_rate")]
10548 pub retirement_participation_rate: f64,
10549}
10550
10551impl Default for PayrollConfig {
10552 fn default() -> Self {
10553 Self {
10554 enabled: true,
10555 pay_frequency: default_pay_frequency(),
10556 salary_ranges: PayrollSalaryRanges::default(),
10557 tax_rates: PayrollTaxRates::default(),
10558 benefits_enrollment_rate: default_benefits_enrollment_rate(),
10559 retirement_participation_rate: default_retirement_participation_rate(),
10560 }
10561 }
10562}
10563
10564fn default_pay_frequency() -> String {
10565 "monthly".to_string()
10566}
10567fn default_benefits_enrollment_rate() -> f64 {
10568 0.60
10569}
10570fn default_retirement_participation_rate() -> f64 {
10571 0.45
10572}
10573
10574#[derive(Debug, Clone, Serialize, Deserialize)]
10576pub struct PayrollSalaryRanges {
10577 #[serde(default = "default_staff_min")]
10579 pub staff_min: f64,
10580 #[serde(default = "default_staff_max")]
10581 pub staff_max: f64,
10582 #[serde(default = "default_manager_min")]
10584 pub manager_min: f64,
10585 #[serde(default = "default_manager_max")]
10586 pub manager_max: f64,
10587 #[serde(default = "default_director_min")]
10589 pub director_min: f64,
10590 #[serde(default = "default_director_max")]
10591 pub director_max: f64,
10592 #[serde(default = "default_executive_min")]
10594 pub executive_min: f64,
10595 #[serde(default = "default_executive_max")]
10596 pub executive_max: f64,
10597}
10598
10599impl Default for PayrollSalaryRanges {
10600 fn default() -> Self {
10601 Self {
10602 staff_min: default_staff_min(),
10603 staff_max: default_staff_max(),
10604 manager_min: default_manager_min(),
10605 manager_max: default_manager_max(),
10606 director_min: default_director_min(),
10607 director_max: default_director_max(),
10608 executive_min: default_executive_min(),
10609 executive_max: default_executive_max(),
10610 }
10611 }
10612}
10613
10614fn default_staff_min() -> f64 {
10615 50_000.0
10616}
10617fn default_staff_max() -> f64 {
10618 70_000.0
10619}
10620fn default_manager_min() -> f64 {
10621 80_000.0
10622}
10623fn default_manager_max() -> f64 {
10624 120_000.0
10625}
10626fn default_director_min() -> f64 {
10627 120_000.0
10628}
10629fn default_director_max() -> f64 {
10630 180_000.0
10631}
10632fn default_executive_min() -> f64 {
10633 180_000.0
10634}
10635fn default_executive_max() -> f64 {
10636 350_000.0
10637}
10638
10639#[derive(Debug, Clone, Serialize, Deserialize)]
10641pub struct PayrollTaxRates {
10642 #[serde(default = "default_federal_rate")]
10644 pub federal_effective: f64,
10645 #[serde(default = "default_state_rate")]
10647 pub state_effective: f64,
10648 #[serde(default = "default_fica_rate")]
10650 pub fica: f64,
10651}
10652
10653impl Default for PayrollTaxRates {
10654 fn default() -> Self {
10655 Self {
10656 federal_effective: default_federal_rate(),
10657 state_effective: default_state_rate(),
10658 fica: default_fica_rate(),
10659 }
10660 }
10661}
10662
10663fn default_federal_rate() -> f64 {
10664 0.22
10665}
10666fn default_state_rate() -> f64 {
10667 0.05
10668}
10669fn default_fica_rate() -> f64 {
10670 0.0765
10671}
10672
10673#[derive(Debug, Clone, Serialize, Deserialize)]
10675pub struct TimeAttendanceConfig {
10676 #[serde(default = "default_true")]
10678 pub enabled: bool,
10679 #[serde(default = "default_overtime_rate")]
10681 pub overtime_rate: f64,
10682}
10683
10684impl Default for TimeAttendanceConfig {
10685 fn default() -> Self {
10686 Self {
10687 enabled: true,
10688 overtime_rate: default_overtime_rate(),
10689 }
10690 }
10691}
10692
10693fn default_overtime_rate() -> f64 {
10694 0.10
10695}
10696
10697#[derive(Debug, Clone, Serialize, Deserialize)]
10699pub struct ExpenseConfig {
10700 #[serde(default = "default_true")]
10702 pub enabled: bool,
10703 #[serde(default = "default_expense_submission_rate")]
10705 pub submission_rate: f64,
10706 #[serde(default = "default_policy_violation_rate")]
10708 pub policy_violation_rate: f64,
10709}
10710
10711impl Default for ExpenseConfig {
10712 fn default() -> Self {
10713 Self {
10714 enabled: true,
10715 submission_rate: default_expense_submission_rate(),
10716 policy_violation_rate: default_policy_violation_rate(),
10717 }
10718 }
10719}
10720
10721fn default_expense_submission_rate() -> f64 {
10722 0.30
10723}
10724fn default_policy_violation_rate() -> f64 {
10725 0.08
10726}
10727
10728#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10732pub struct ManufacturingProcessConfig {
10733 #[serde(default)]
10735 pub enabled: bool,
10736 #[serde(default)]
10738 pub production_orders: ProductionOrderConfig,
10739 #[serde(default)]
10741 pub costing: ManufacturingCostingConfig,
10742 #[serde(default)]
10744 pub routing: RoutingConfig,
10745}
10746
10747#[derive(Debug, Clone, Serialize, Deserialize)]
10749pub struct ProductionOrderConfig {
10750 #[serde(default = "default_prod_orders_per_month")]
10752 pub orders_per_month: u32,
10753 #[serde(default = "default_prod_avg_batch_size")]
10755 pub avg_batch_size: u32,
10756 #[serde(default = "default_prod_yield_rate")]
10758 pub yield_rate: f64,
10759 #[serde(default = "default_prod_make_to_order_rate")]
10761 pub make_to_order_rate: f64,
10762 #[serde(default = "default_prod_rework_rate")]
10764 pub rework_rate: f64,
10765}
10766
10767impl Default for ProductionOrderConfig {
10768 fn default() -> Self {
10769 Self {
10770 orders_per_month: default_prod_orders_per_month(),
10771 avg_batch_size: default_prod_avg_batch_size(),
10772 yield_rate: default_prod_yield_rate(),
10773 make_to_order_rate: default_prod_make_to_order_rate(),
10774 rework_rate: default_prod_rework_rate(),
10775 }
10776 }
10777}
10778
10779fn default_prod_orders_per_month() -> u32 {
10780 50
10781}
10782fn default_prod_avg_batch_size() -> u32 {
10783 100
10784}
10785fn default_prod_yield_rate() -> f64 {
10786 0.97
10787}
10788fn default_prod_make_to_order_rate() -> f64 {
10789 0.20
10790}
10791fn default_prod_rework_rate() -> f64 {
10792 0.03
10793}
10794
10795#[derive(Debug, Clone, Serialize, Deserialize)]
10797pub struct ManufacturingCostingConfig {
10798 #[serde(default = "default_labor_rate")]
10800 pub labor_rate_per_hour: f64,
10801 #[serde(default = "default_overhead_rate")]
10803 pub overhead_rate: f64,
10804 #[serde(default = "default_cost_update_frequency")]
10806 pub standard_cost_update_frequency: String,
10807}
10808
10809impl Default for ManufacturingCostingConfig {
10810 fn default() -> Self {
10811 Self {
10812 labor_rate_per_hour: default_labor_rate(),
10813 overhead_rate: default_overhead_rate(),
10814 standard_cost_update_frequency: default_cost_update_frequency(),
10815 }
10816 }
10817}
10818
10819fn default_labor_rate() -> f64 {
10820 35.0
10821}
10822fn default_overhead_rate() -> f64 {
10823 1.50
10824}
10825fn default_cost_update_frequency() -> String {
10826 "quarterly".to_string()
10827}
10828
10829#[derive(Debug, Clone, Serialize, Deserialize)]
10831pub struct RoutingConfig {
10832 #[serde(default = "default_avg_operations")]
10834 pub avg_operations: u32,
10835 #[serde(default = "default_setup_time")]
10837 pub setup_time_hours: f64,
10838 #[serde(default = "default_run_time_variation")]
10840 pub run_time_variation: f64,
10841}
10842
10843impl Default for RoutingConfig {
10844 fn default() -> Self {
10845 Self {
10846 avg_operations: default_avg_operations(),
10847 setup_time_hours: default_setup_time(),
10848 run_time_variation: default_run_time_variation(),
10849 }
10850 }
10851}
10852
10853fn default_avg_operations() -> u32 {
10854 4
10855}
10856fn default_setup_time() -> f64 {
10857 1.5
10858}
10859fn default_run_time_variation() -> f64 {
10860 0.15
10861}
10862
10863#[derive(Debug, Clone, Serialize, Deserialize)]
10867pub struct SalesQuoteConfig {
10868 #[serde(default)]
10870 pub enabled: bool,
10871 #[serde(default = "default_quotes_per_month")]
10873 pub quotes_per_month: u32,
10874 #[serde(default = "default_quote_win_rate")]
10876 pub win_rate: f64,
10877 #[serde(default = "default_quote_validity_days")]
10879 pub validity_days: u32,
10880}
10881
10882impl Default for SalesQuoteConfig {
10883 fn default() -> Self {
10884 Self {
10885 enabled: false,
10886 quotes_per_month: default_quotes_per_month(),
10887 win_rate: default_quote_win_rate(),
10888 validity_days: default_quote_validity_days(),
10889 }
10890 }
10891}
10892
10893fn default_quotes_per_month() -> u32 {
10894 30
10895}
10896fn default_quote_win_rate() -> f64 {
10897 0.35
10898}
10899fn default_quote_validity_days() -> u32 {
10900 30
10901}
10902
10903#[derive(Debug, Clone, Serialize, Deserialize)]
10912pub struct TaxConfig {
10913 #[serde(default)]
10915 pub enabled: bool,
10916 #[serde(default)]
10918 pub jurisdictions: TaxJurisdictionConfig,
10919 #[serde(default)]
10921 pub vat_gst: VatGstConfig,
10922 #[serde(default)]
10924 pub sales_tax: SalesTaxConfig,
10925 #[serde(default)]
10927 pub withholding: WithholdingTaxSchemaConfig,
10928 #[serde(default)]
10930 pub provisions: TaxProvisionSchemaConfig,
10931 #[serde(default)]
10933 pub payroll_tax: PayrollTaxSchemaConfig,
10934 #[serde(default = "default_tax_anomaly_rate")]
10936 pub anomaly_rate: f64,
10937}
10938
10939fn default_tax_anomaly_rate() -> f64 {
10940 0.03
10941}
10942
10943impl Default for TaxConfig {
10944 fn default() -> Self {
10945 Self {
10946 enabled: false,
10947 jurisdictions: TaxJurisdictionConfig::default(),
10948 vat_gst: VatGstConfig::default(),
10949 sales_tax: SalesTaxConfig::default(),
10950 withholding: WithholdingTaxSchemaConfig::default(),
10951 provisions: TaxProvisionSchemaConfig::default(),
10952 payroll_tax: PayrollTaxSchemaConfig::default(),
10953 anomaly_rate: default_tax_anomaly_rate(),
10954 }
10955 }
10956}
10957
10958#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10963pub struct TaxJurisdictionConfig {
10964 #[serde(default)]
10966 pub countries: Vec<String>,
10967 #[serde(default)]
10969 pub include_subnational: bool,
10970}
10971
10972#[derive(Debug, Clone, Serialize, Deserialize)]
10977pub struct VatGstConfig {
10978 #[serde(default)]
10980 pub enabled: bool,
10981 #[serde(default)]
10983 pub standard_rates: std::collections::HashMap<String, f64>,
10984 #[serde(default)]
10986 pub reduced_rates: std::collections::HashMap<String, f64>,
10987 #[serde(default)]
10989 pub exempt_categories: Vec<String>,
10990 #[serde(default = "default_true")]
10992 pub reverse_charge: bool,
10993}
10994
10995impl Default for VatGstConfig {
10996 fn default() -> Self {
10997 Self {
10998 enabled: false,
10999 standard_rates: std::collections::HashMap::new(),
11000 reduced_rates: std::collections::HashMap::new(),
11001 exempt_categories: Vec::new(),
11002 reverse_charge: true,
11003 }
11004 }
11005}
11006
11007#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11011pub struct SalesTaxConfig {
11012 #[serde(default)]
11014 pub enabled: bool,
11015 #[serde(default)]
11017 pub nexus_states: Vec<String>,
11018}
11019
11020#[derive(Debug, Clone, Serialize, Deserialize)]
11025pub struct WithholdingTaxSchemaConfig {
11026 #[serde(default)]
11028 pub enabled: bool,
11029 #[serde(default = "default_true")]
11031 pub treaty_network: bool,
11032 #[serde(default = "default_withholding_rate")]
11034 pub default_rate: f64,
11035 #[serde(default = "default_treaty_reduced_rate")]
11037 pub treaty_reduced_rate: f64,
11038}
11039
11040fn default_withholding_rate() -> f64 {
11041 0.30
11042}
11043
11044fn default_treaty_reduced_rate() -> f64 {
11045 0.15
11046}
11047
11048impl Default for WithholdingTaxSchemaConfig {
11049 fn default() -> Self {
11050 Self {
11051 enabled: false,
11052 treaty_network: true,
11053 default_rate: default_withholding_rate(),
11054 treaty_reduced_rate: default_treaty_reduced_rate(),
11055 }
11056 }
11057}
11058
11059#[derive(Debug, Clone, Serialize, Deserialize)]
11064pub struct TaxProvisionSchemaConfig {
11065 #[serde(default = "default_true")]
11068 pub enabled: bool,
11069 #[serde(default = "default_statutory_rate")]
11071 pub statutory_rate: f64,
11072 #[serde(default = "default_true")]
11074 pub uncertain_positions: bool,
11075}
11076
11077fn default_statutory_rate() -> f64 {
11078 0.21
11079}
11080
11081impl Default for TaxProvisionSchemaConfig {
11082 fn default() -> Self {
11083 Self {
11084 enabled: true,
11085 statutory_rate: default_statutory_rate(),
11086 uncertain_positions: true,
11087 }
11088 }
11089}
11090
11091#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11096pub struct PayrollTaxSchemaConfig {
11097 #[serde(default)]
11099 pub enabled: bool,
11100}
11101
11102#[derive(Debug, Clone, Serialize, Deserialize)]
11112pub struct TreasuryConfig {
11113 #[serde(default)]
11115 pub enabled: bool,
11116 #[serde(default)]
11118 pub cash_positioning: CashPositioningConfig,
11119 #[serde(default)]
11121 pub cash_forecasting: CashForecastingConfig,
11122 #[serde(default)]
11124 pub cash_pooling: CashPoolingConfig,
11125 #[serde(default)]
11127 pub hedging: HedgingSchemaConfig,
11128 #[serde(default)]
11130 pub debt: DebtSchemaConfig,
11131 #[serde(default)]
11133 pub netting: NettingSchemaConfig,
11134 #[serde(default)]
11136 pub bank_guarantees: BankGuaranteeSchemaConfig,
11137 #[serde(default = "default_treasury_anomaly_rate")]
11139 pub anomaly_rate: f64,
11140}
11141
11142fn default_treasury_anomaly_rate() -> f64 {
11143 0.02
11144}
11145
11146impl Default for TreasuryConfig {
11147 fn default() -> Self {
11148 Self {
11149 enabled: false,
11150 cash_positioning: CashPositioningConfig::default(),
11151 cash_forecasting: CashForecastingConfig::default(),
11152 cash_pooling: CashPoolingConfig::default(),
11153 hedging: HedgingSchemaConfig::default(),
11154 debt: DebtSchemaConfig::default(),
11155 netting: NettingSchemaConfig::default(),
11156 bank_guarantees: BankGuaranteeSchemaConfig::default(),
11157 anomaly_rate: default_treasury_anomaly_rate(),
11158 }
11159 }
11160}
11161
11162#[derive(Debug, Clone, Serialize, Deserialize)]
11166pub struct CashPositioningConfig {
11167 #[serde(default = "default_true")]
11169 pub enabled: bool,
11170 #[serde(default = "default_cash_frequency")]
11172 pub frequency: String,
11173 #[serde(default = "default_minimum_balance_policy")]
11175 pub minimum_balance_policy: f64,
11176}
11177
11178fn default_cash_frequency() -> String {
11179 "daily".to_string()
11180}
11181
11182fn default_minimum_balance_policy() -> f64 {
11183 100_000.0
11184}
11185
11186impl Default for CashPositioningConfig {
11187 fn default() -> Self {
11188 Self {
11189 enabled: true,
11190 frequency: default_cash_frequency(),
11191 minimum_balance_policy: default_minimum_balance_policy(),
11192 }
11193 }
11194}
11195
11196#[derive(Debug, Clone, Serialize, Deserialize)]
11200pub struct CashForecastingConfig {
11201 #[serde(default = "default_true")]
11203 pub enabled: bool,
11204 #[serde(default = "default_horizon_days")]
11206 pub horizon_days: u32,
11207 #[serde(default = "default_ar_probability_curve")]
11209 pub ar_collection_probability_curve: String,
11210 #[serde(default = "default_confidence_interval")]
11212 pub confidence_interval: f64,
11213}
11214
11215fn default_horizon_days() -> u32 {
11216 90
11217}
11218
11219fn default_ar_probability_curve() -> String {
11220 "aging".to_string()
11221}
11222
11223fn default_confidence_interval() -> f64 {
11224 0.90
11225}
11226
11227impl Default for CashForecastingConfig {
11228 fn default() -> Self {
11229 Self {
11230 enabled: true,
11231 horizon_days: default_horizon_days(),
11232 ar_collection_probability_curve: default_ar_probability_curve(),
11233 confidence_interval: default_confidence_interval(),
11234 }
11235 }
11236}
11237
11238#[derive(Debug, Clone, Serialize, Deserialize)]
11242pub struct CashPoolingConfig {
11243 #[serde(default)]
11245 pub enabled: bool,
11246 #[serde(default = "default_pool_type")]
11248 pub pool_type: String,
11249 #[serde(default = "default_sweep_time")]
11251 pub sweep_time: String,
11252}
11253
11254fn default_pool_type() -> String {
11255 "zero_balancing".to_string()
11256}
11257
11258fn default_sweep_time() -> String {
11259 "16:00".to_string()
11260}
11261
11262impl Default for CashPoolingConfig {
11263 fn default() -> Self {
11264 Self {
11265 enabled: false,
11266 pool_type: default_pool_type(),
11267 sweep_time: default_sweep_time(),
11268 }
11269 }
11270}
11271
11272#[derive(Debug, Clone, Serialize, Deserialize)]
11277pub struct HedgingSchemaConfig {
11278 #[serde(default)]
11280 pub enabled: bool,
11281 #[serde(default = "default_hedge_ratio")]
11283 pub hedge_ratio: f64,
11284 #[serde(default = "default_hedge_instruments")]
11286 pub instruments: Vec<String>,
11287 #[serde(default = "default_true")]
11289 pub hedge_accounting: bool,
11290 #[serde(default = "default_effectiveness_method")]
11292 pub effectiveness_method: String,
11293}
11294
11295fn default_hedge_ratio() -> f64 {
11296 0.75
11297}
11298
11299fn default_hedge_instruments() -> Vec<String> {
11300 vec!["fx_forward".to_string(), "interest_rate_swap".to_string()]
11301}
11302
11303fn default_effectiveness_method() -> String {
11304 "regression".to_string()
11305}
11306
11307impl Default for HedgingSchemaConfig {
11308 fn default() -> Self {
11309 Self {
11310 enabled: false,
11311 hedge_ratio: default_hedge_ratio(),
11312 instruments: default_hedge_instruments(),
11313 hedge_accounting: true,
11314 effectiveness_method: default_effectiveness_method(),
11315 }
11316 }
11317}
11318
11319#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11324pub struct DebtSchemaConfig {
11325 #[serde(default)]
11327 pub enabled: bool,
11328 #[serde(default)]
11330 pub instruments: Vec<DebtInstrumentDef>,
11331 #[serde(default)]
11333 pub covenants: Vec<CovenantDef>,
11334}
11335
11336#[derive(Debug, Clone, Serialize, Deserialize)]
11338pub struct DebtInstrumentDef {
11339 #[serde(rename = "type")]
11341 pub instrument_type: String,
11342 #[serde(default)]
11344 pub principal: Option<f64>,
11345 #[serde(default)]
11347 pub rate: Option<f64>,
11348 #[serde(default)]
11350 pub maturity_months: Option<u32>,
11351 #[serde(default)]
11353 pub facility: Option<f64>,
11354}
11355
11356#[derive(Debug, Clone, Serialize, Deserialize)]
11358pub struct CovenantDef {
11359 #[serde(rename = "type")]
11362 pub covenant_type: String,
11363 pub threshold: f64,
11365}
11366
11367#[derive(Debug, Clone, Serialize, Deserialize)]
11371pub struct NettingSchemaConfig {
11372 #[serde(default)]
11374 pub enabled: bool,
11375 #[serde(default = "default_netting_cycle")]
11377 pub cycle: String,
11378}
11379
11380fn default_netting_cycle() -> String {
11381 "monthly".to_string()
11382}
11383
11384impl Default for NettingSchemaConfig {
11385 fn default() -> Self {
11386 Self {
11387 enabled: false,
11388 cycle: default_netting_cycle(),
11389 }
11390 }
11391}
11392
11393#[derive(Debug, Clone, Serialize, Deserialize)]
11397pub struct BankGuaranteeSchemaConfig {
11398 #[serde(default)]
11400 pub enabled: bool,
11401 #[serde(default = "default_guarantee_count")]
11403 pub count: u32,
11404}
11405
11406fn default_guarantee_count() -> u32 {
11407 5
11408}
11409
11410impl Default for BankGuaranteeSchemaConfig {
11411 fn default() -> Self {
11412 Self {
11413 enabled: false,
11414 count: default_guarantee_count(),
11415 }
11416 }
11417}
11418
11419#[derive(Debug, Clone, Serialize, Deserialize)]
11428pub struct ProjectAccountingConfig {
11429 #[serde(default)]
11431 pub enabled: bool,
11432 #[serde(default = "default_project_count")]
11434 pub project_count: u32,
11435 #[serde(default)]
11437 pub project_types: ProjectTypeDistribution,
11438 #[serde(default)]
11440 pub wbs: WbsSchemaConfig,
11441 #[serde(default)]
11443 pub cost_allocation: CostAllocationConfig,
11444 #[serde(default)]
11446 pub revenue_recognition: ProjectRevenueRecognitionConfig,
11447 #[serde(default)]
11449 pub milestones: MilestoneSchemaConfig,
11450 #[serde(default)]
11452 pub change_orders: ChangeOrderSchemaConfig,
11453 #[serde(default)]
11455 pub retainage: RetainageSchemaConfig,
11456 #[serde(default)]
11458 pub earned_value: EarnedValueSchemaConfig,
11459 #[serde(default = "default_project_anomaly_rate")]
11461 pub anomaly_rate: f64,
11462}
11463
11464fn default_project_count() -> u32 {
11465 10
11466}
11467
11468fn default_project_anomaly_rate() -> f64 {
11469 0.03
11470}
11471
11472impl Default for ProjectAccountingConfig {
11473 fn default() -> Self {
11474 Self {
11475 enabled: false,
11476 project_count: default_project_count(),
11477 project_types: ProjectTypeDistribution::default(),
11478 wbs: WbsSchemaConfig::default(),
11479 cost_allocation: CostAllocationConfig::default(),
11480 revenue_recognition: ProjectRevenueRecognitionConfig::default(),
11481 milestones: MilestoneSchemaConfig::default(),
11482 change_orders: ChangeOrderSchemaConfig::default(),
11483 retainage: RetainageSchemaConfig::default(),
11484 earned_value: EarnedValueSchemaConfig::default(),
11485 anomaly_rate: default_project_anomaly_rate(),
11486 }
11487 }
11488}
11489
11490#[derive(Debug, Clone, Serialize, Deserialize)]
11492pub struct ProjectTypeDistribution {
11493 #[serde(default = "default_capital_weight")]
11495 pub capital: f64,
11496 #[serde(default = "default_internal_weight")]
11498 pub internal: f64,
11499 #[serde(default = "default_customer_weight")]
11501 pub customer: f64,
11502 #[serde(default = "default_rnd_weight")]
11504 pub r_and_d: f64,
11505 #[serde(default = "default_maintenance_weight")]
11507 pub maintenance: f64,
11508 #[serde(default = "default_technology_weight")]
11510 pub technology: f64,
11511}
11512
11513fn default_capital_weight() -> f64 {
11514 0.25
11515}
11516fn default_internal_weight() -> f64 {
11517 0.20
11518}
11519fn default_customer_weight() -> f64 {
11520 0.30
11521}
11522fn default_rnd_weight() -> f64 {
11523 0.10
11524}
11525fn default_maintenance_weight() -> f64 {
11526 0.10
11527}
11528fn default_technology_weight() -> f64 {
11529 0.05
11530}
11531
11532impl Default for ProjectTypeDistribution {
11533 fn default() -> Self {
11534 Self {
11535 capital: default_capital_weight(),
11536 internal: default_internal_weight(),
11537 customer: default_customer_weight(),
11538 r_and_d: default_rnd_weight(),
11539 maintenance: default_maintenance_weight(),
11540 technology: default_technology_weight(),
11541 }
11542 }
11543}
11544
11545#[derive(Debug, Clone, Serialize, Deserialize)]
11547pub struct WbsSchemaConfig {
11548 #[serde(default = "default_wbs_max_depth")]
11550 pub max_depth: u32,
11551 #[serde(default = "default_wbs_min_elements")]
11553 pub min_elements_per_level: u32,
11554 #[serde(default = "default_wbs_max_elements")]
11556 pub max_elements_per_level: u32,
11557}
11558
11559fn default_wbs_max_depth() -> u32 {
11560 3
11561}
11562fn default_wbs_min_elements() -> u32 {
11563 2
11564}
11565fn default_wbs_max_elements() -> u32 {
11566 6
11567}
11568
11569impl Default for WbsSchemaConfig {
11570 fn default() -> Self {
11571 Self {
11572 max_depth: default_wbs_max_depth(),
11573 min_elements_per_level: default_wbs_min_elements(),
11574 max_elements_per_level: default_wbs_max_elements(),
11575 }
11576 }
11577}
11578
11579#[derive(Debug, Clone, Serialize, Deserialize)]
11581pub struct CostAllocationConfig {
11582 #[serde(default = "default_time_entry_rate")]
11584 pub time_entry_project_rate: f64,
11585 #[serde(default = "default_expense_rate")]
11587 pub expense_project_rate: f64,
11588 #[serde(default = "default_po_rate")]
11590 pub purchase_order_project_rate: f64,
11591 #[serde(default = "default_vi_rate")]
11593 pub vendor_invoice_project_rate: f64,
11594}
11595
11596fn default_time_entry_rate() -> f64 {
11597 0.60
11598}
11599fn default_expense_rate() -> f64 {
11600 0.30
11601}
11602fn default_po_rate() -> f64 {
11603 0.40
11604}
11605fn default_vi_rate() -> f64 {
11606 0.35
11607}
11608
11609impl Default for CostAllocationConfig {
11610 fn default() -> Self {
11611 Self {
11612 time_entry_project_rate: default_time_entry_rate(),
11613 expense_project_rate: default_expense_rate(),
11614 purchase_order_project_rate: default_po_rate(),
11615 vendor_invoice_project_rate: default_vi_rate(),
11616 }
11617 }
11618}
11619
11620#[derive(Debug, Clone, Serialize, Deserialize)]
11622pub struct ProjectRevenueRecognitionConfig {
11623 #[serde(default = "default_true")]
11625 pub enabled: bool,
11626 #[serde(default = "default_revenue_method")]
11628 pub method: String,
11629 #[serde(default = "default_completion_measure")]
11631 pub completion_measure: String,
11632 #[serde(default = "default_avg_contract_value")]
11634 pub avg_contract_value: f64,
11635}
11636
11637fn default_revenue_method() -> String {
11638 "percentage_of_completion".to_string()
11639}
11640fn default_completion_measure() -> String {
11641 "cost_to_cost".to_string()
11642}
11643fn default_avg_contract_value() -> f64 {
11644 500_000.0
11645}
11646
11647impl Default for ProjectRevenueRecognitionConfig {
11648 fn default() -> Self {
11649 Self {
11650 enabled: true,
11651 method: default_revenue_method(),
11652 completion_measure: default_completion_measure(),
11653 avg_contract_value: default_avg_contract_value(),
11654 }
11655 }
11656}
11657
11658#[derive(Debug, Clone, Serialize, Deserialize)]
11660pub struct MilestoneSchemaConfig {
11661 #[serde(default = "default_true")]
11663 pub enabled: bool,
11664 #[serde(default = "default_milestones_per_project")]
11666 pub avg_per_project: u32,
11667 #[serde(default = "default_payment_milestone_rate")]
11669 pub payment_milestone_rate: f64,
11670}
11671
11672fn default_milestones_per_project() -> u32 {
11673 4
11674}
11675fn default_payment_milestone_rate() -> f64 {
11676 0.50
11677}
11678
11679impl Default for MilestoneSchemaConfig {
11680 fn default() -> Self {
11681 Self {
11682 enabled: true,
11683 avg_per_project: default_milestones_per_project(),
11684 payment_milestone_rate: default_payment_milestone_rate(),
11685 }
11686 }
11687}
11688
11689#[derive(Debug, Clone, Serialize, Deserialize)]
11691pub struct ChangeOrderSchemaConfig {
11692 #[serde(default = "default_true")]
11694 pub enabled: bool,
11695 #[serde(default = "default_change_order_probability")]
11697 pub probability: f64,
11698 #[serde(default = "default_max_change_orders")]
11700 pub max_per_project: u32,
11701 #[serde(default = "default_change_order_approval_rate")]
11703 pub approval_rate: f64,
11704}
11705
11706fn default_change_order_probability() -> f64 {
11707 0.40
11708}
11709fn default_max_change_orders() -> u32 {
11710 3
11711}
11712fn default_change_order_approval_rate() -> f64 {
11713 0.75
11714}
11715
11716impl Default for ChangeOrderSchemaConfig {
11717 fn default() -> Self {
11718 Self {
11719 enabled: true,
11720 probability: default_change_order_probability(),
11721 max_per_project: default_max_change_orders(),
11722 approval_rate: default_change_order_approval_rate(),
11723 }
11724 }
11725}
11726
11727#[derive(Debug, Clone, Serialize, Deserialize)]
11729pub struct RetainageSchemaConfig {
11730 #[serde(default)]
11732 pub enabled: bool,
11733 #[serde(default = "default_retainage_pct")]
11735 pub default_percentage: f64,
11736}
11737
11738fn default_retainage_pct() -> f64 {
11739 0.10
11740}
11741
11742impl Default for RetainageSchemaConfig {
11743 fn default() -> Self {
11744 Self {
11745 enabled: false,
11746 default_percentage: default_retainage_pct(),
11747 }
11748 }
11749}
11750
11751#[derive(Debug, Clone, Serialize, Deserialize)]
11753pub struct EarnedValueSchemaConfig {
11754 #[serde(default = "default_true")]
11756 pub enabled: bool,
11757 #[serde(default = "default_evm_frequency")]
11759 pub frequency: String,
11760}
11761
11762fn default_evm_frequency() -> String {
11763 "monthly".to_string()
11764}
11765
11766impl Default for EarnedValueSchemaConfig {
11767 fn default() -> Self {
11768 Self {
11769 enabled: true,
11770 frequency: default_evm_frequency(),
11771 }
11772 }
11773}
11774
11775#[derive(Debug, Clone, Serialize, Deserialize)]
11781pub struct EsgConfig {
11782 #[serde(default)]
11784 pub enabled: bool,
11785 #[serde(default)]
11787 pub environmental: EnvironmentalConfig,
11788 #[serde(default)]
11790 pub social: SocialConfig,
11791 #[serde(default)]
11793 pub governance: GovernanceSchemaConfig,
11794 #[serde(default)]
11796 pub supply_chain_esg: SupplyChainEsgConfig,
11797 #[serde(default)]
11799 pub reporting: EsgReportingConfig,
11800 #[serde(default)]
11802 pub climate_scenarios: ClimateScenarioConfig,
11803 #[serde(default = "default_esg_anomaly_rate")]
11805 pub anomaly_rate: f64,
11806}
11807
11808fn default_esg_anomaly_rate() -> f64 {
11809 0.02
11810}
11811
11812impl Default for EsgConfig {
11813 fn default() -> Self {
11814 Self {
11815 enabled: false,
11816 environmental: EnvironmentalConfig::default(),
11817 social: SocialConfig::default(),
11818 governance: GovernanceSchemaConfig::default(),
11819 supply_chain_esg: SupplyChainEsgConfig::default(),
11820 reporting: EsgReportingConfig::default(),
11821 climate_scenarios: ClimateScenarioConfig::default(),
11822 anomaly_rate: default_esg_anomaly_rate(),
11823 }
11824 }
11825}
11826
11827#[derive(Debug, Clone, Serialize, Deserialize, Default)]
11832pub struct CountryPacksSchemaConfig {
11833 #[serde(default)]
11835 pub external_dir: Option<PathBuf>,
11836 #[serde(default)]
11840 pub overrides: std::collections::HashMap<String, serde_json::Value>,
11841}
11842
11843#[derive(Debug, Clone, Serialize, Deserialize)]
11845pub struct EnvironmentalConfig {
11846 #[serde(default = "default_true")]
11848 pub enabled: bool,
11849 #[serde(default)]
11851 pub scope1: EmissionScopeConfig,
11852 #[serde(default)]
11854 pub scope2: EmissionScopeConfig,
11855 #[serde(default)]
11857 pub scope3: Scope3Config,
11858 #[serde(default)]
11860 pub energy: EnergySchemaConfig,
11861 #[serde(default)]
11863 pub water: WaterSchemaConfig,
11864 #[serde(default)]
11866 pub waste: WasteSchemaConfig,
11867}
11868
11869impl Default for EnvironmentalConfig {
11870 fn default() -> Self {
11871 Self {
11872 enabled: true,
11873 scope1: EmissionScopeConfig::default(),
11874 scope2: EmissionScopeConfig::default(),
11875 scope3: Scope3Config::default(),
11876 energy: EnergySchemaConfig::default(),
11877 water: WaterSchemaConfig::default(),
11878 waste: WasteSchemaConfig::default(),
11879 }
11880 }
11881}
11882
11883#[derive(Debug, Clone, Serialize, Deserialize)]
11885pub struct EmissionScopeConfig {
11886 #[serde(default = "default_true")]
11888 pub enabled: bool,
11889 #[serde(default = "default_emission_region")]
11891 pub factor_region: String,
11892}
11893
11894fn default_emission_region() -> String {
11895 "US".to_string()
11896}
11897
11898impl Default for EmissionScopeConfig {
11899 fn default() -> Self {
11900 Self {
11901 enabled: true,
11902 factor_region: default_emission_region(),
11903 }
11904 }
11905}
11906
11907#[derive(Debug, Clone, Serialize, Deserialize)]
11909pub struct Scope3Config {
11910 #[serde(default = "default_true")]
11912 pub enabled: bool,
11913 #[serde(default = "default_scope3_categories")]
11915 pub categories: Vec<String>,
11916 #[serde(default = "default_spend_intensity")]
11918 pub default_spend_intensity_kg_per_usd: f64,
11919}
11920
11921fn default_scope3_categories() -> Vec<String> {
11922 vec![
11923 "purchased_goods".to_string(),
11924 "business_travel".to_string(),
11925 "employee_commuting".to_string(),
11926 ]
11927}
11928
11929fn default_spend_intensity() -> f64 {
11930 0.5
11931}
11932
11933impl Default for Scope3Config {
11934 fn default() -> Self {
11935 Self {
11936 enabled: true,
11937 categories: default_scope3_categories(),
11938 default_spend_intensity_kg_per_usd: default_spend_intensity(),
11939 }
11940 }
11941}
11942
11943#[derive(Debug, Clone, Serialize, Deserialize)]
11945pub struct EnergySchemaConfig {
11946 #[serde(default = "default_true")]
11948 pub enabled: bool,
11949 #[serde(default = "default_facility_count")]
11951 pub facility_count: u32,
11952 #[serde(default = "default_renewable_target")]
11954 pub renewable_target: f64,
11955}
11956
11957fn default_facility_count() -> u32 {
11958 5
11959}
11960
11961fn default_renewable_target() -> f64 {
11962 0.30
11963}
11964
11965impl Default for EnergySchemaConfig {
11966 fn default() -> Self {
11967 Self {
11968 enabled: true,
11969 facility_count: default_facility_count(),
11970 renewable_target: default_renewable_target(),
11971 }
11972 }
11973}
11974
11975#[derive(Debug, Clone, Serialize, Deserialize)]
11977pub struct WaterSchemaConfig {
11978 #[serde(default = "default_true")]
11980 pub enabled: bool,
11981 #[serde(default = "default_water_facility_count")]
11983 pub facility_count: u32,
11984}
11985
11986fn default_water_facility_count() -> u32 {
11987 3
11988}
11989
11990impl Default for WaterSchemaConfig {
11991 fn default() -> Self {
11992 Self {
11993 enabled: true,
11994 facility_count: default_water_facility_count(),
11995 }
11996 }
11997}
11998
11999#[derive(Debug, Clone, Serialize, Deserialize)]
12001pub struct WasteSchemaConfig {
12002 #[serde(default = "default_true")]
12004 pub enabled: bool,
12005 #[serde(default = "default_diversion_target")]
12007 pub diversion_target: f64,
12008}
12009
12010fn default_diversion_target() -> f64 {
12011 0.50
12012}
12013
12014impl Default for WasteSchemaConfig {
12015 fn default() -> Self {
12016 Self {
12017 enabled: true,
12018 diversion_target: default_diversion_target(),
12019 }
12020 }
12021}
12022
12023#[derive(Debug, Clone, Serialize, Deserialize)]
12025pub struct SocialConfig {
12026 #[serde(default = "default_true")]
12028 pub enabled: bool,
12029 #[serde(default)]
12031 pub diversity: DiversitySchemaConfig,
12032 #[serde(default)]
12034 pub pay_equity: PayEquitySchemaConfig,
12035 #[serde(default)]
12037 pub safety: SafetySchemaConfig,
12038}
12039
12040impl Default for SocialConfig {
12041 fn default() -> Self {
12042 Self {
12043 enabled: true,
12044 diversity: DiversitySchemaConfig::default(),
12045 pay_equity: PayEquitySchemaConfig::default(),
12046 safety: SafetySchemaConfig::default(),
12047 }
12048 }
12049}
12050
12051#[derive(Debug, Clone, Serialize, Deserialize)]
12053pub struct DiversitySchemaConfig {
12054 #[serde(default = "default_true")]
12056 pub enabled: bool,
12057 #[serde(default = "default_diversity_dimensions")]
12059 pub dimensions: Vec<String>,
12060}
12061
12062fn default_diversity_dimensions() -> Vec<String> {
12063 vec![
12064 "gender".to_string(),
12065 "ethnicity".to_string(),
12066 "age_group".to_string(),
12067 ]
12068}
12069
12070impl Default for DiversitySchemaConfig {
12071 fn default() -> Self {
12072 Self {
12073 enabled: true,
12074 dimensions: default_diversity_dimensions(),
12075 }
12076 }
12077}
12078
12079#[derive(Debug, Clone, Serialize, Deserialize)]
12081pub struct PayEquitySchemaConfig {
12082 #[serde(default = "default_true")]
12084 pub enabled: bool,
12085 #[serde(default = "default_pay_gap_threshold")]
12087 pub gap_threshold: f64,
12088}
12089
12090fn default_pay_gap_threshold() -> f64 {
12091 0.05
12092}
12093
12094impl Default for PayEquitySchemaConfig {
12095 fn default() -> Self {
12096 Self {
12097 enabled: true,
12098 gap_threshold: default_pay_gap_threshold(),
12099 }
12100 }
12101}
12102
12103#[derive(Debug, Clone, Serialize, Deserialize)]
12105pub struct SafetySchemaConfig {
12106 #[serde(default = "default_true")]
12108 pub enabled: bool,
12109 #[serde(default = "default_trir_target")]
12111 pub target_trir: f64,
12112 #[serde(default = "default_incident_count")]
12114 pub incident_count: u32,
12115}
12116
12117fn default_trir_target() -> f64 {
12118 2.5
12119}
12120
12121fn default_incident_count() -> u32 {
12122 20
12123}
12124
12125impl Default for SafetySchemaConfig {
12126 fn default() -> Self {
12127 Self {
12128 enabled: true,
12129 target_trir: default_trir_target(),
12130 incident_count: default_incident_count(),
12131 }
12132 }
12133}
12134
12135#[derive(Debug, Clone, Serialize, Deserialize)]
12137pub struct GovernanceSchemaConfig {
12138 #[serde(default = "default_true")]
12140 pub enabled: bool,
12141 #[serde(default = "default_board_size")]
12143 pub board_size: u32,
12144 #[serde(default = "default_independence_target")]
12146 pub independence_target: f64,
12147}
12148
12149fn default_board_size() -> u32 {
12150 11
12151}
12152
12153fn default_independence_target() -> f64 {
12154 0.67
12155}
12156
12157impl Default for GovernanceSchemaConfig {
12158 fn default() -> Self {
12159 Self {
12160 enabled: true,
12161 board_size: default_board_size(),
12162 independence_target: default_independence_target(),
12163 }
12164 }
12165}
12166
12167#[derive(Debug, Clone, Serialize, Deserialize)]
12169pub struct SupplyChainEsgConfig {
12170 #[serde(default = "default_true")]
12172 pub enabled: bool,
12173 #[serde(default = "default_assessment_coverage")]
12175 pub assessment_coverage: f64,
12176 #[serde(default = "default_high_risk_countries")]
12178 pub high_risk_countries: Vec<String>,
12179}
12180
12181fn default_assessment_coverage() -> f64 {
12182 0.80
12183}
12184
12185fn default_high_risk_countries() -> Vec<String> {
12186 vec!["CN".to_string(), "BD".to_string(), "MM".to_string()]
12187}
12188
12189impl Default for SupplyChainEsgConfig {
12190 fn default() -> Self {
12191 Self {
12192 enabled: true,
12193 assessment_coverage: default_assessment_coverage(),
12194 high_risk_countries: default_high_risk_countries(),
12195 }
12196 }
12197}
12198
12199#[derive(Debug, Clone, Serialize, Deserialize)]
12201pub struct EsgReportingConfig {
12202 #[serde(default = "default_true")]
12204 pub enabled: bool,
12205 #[serde(default = "default_esg_frameworks")]
12207 pub frameworks: Vec<String>,
12208 #[serde(default = "default_true")]
12210 pub materiality_assessment: bool,
12211 #[serde(default = "default_materiality_threshold")]
12213 pub impact_threshold: f64,
12214 #[serde(default = "default_materiality_threshold")]
12216 pub financial_threshold: f64,
12217}
12218
12219fn default_esg_frameworks() -> Vec<String> {
12220 vec!["GRI".to_string(), "ESRS".to_string()]
12221}
12222
12223fn default_materiality_threshold() -> f64 {
12224 0.6
12225}
12226
12227impl Default for EsgReportingConfig {
12228 fn default() -> Self {
12229 Self {
12230 enabled: true,
12231 frameworks: default_esg_frameworks(),
12232 materiality_assessment: true,
12233 impact_threshold: default_materiality_threshold(),
12234 financial_threshold: default_materiality_threshold(),
12235 }
12236 }
12237}
12238
12239#[derive(Debug, Clone, Serialize, Deserialize)]
12241pub struct ClimateScenarioConfig {
12242 #[serde(default)]
12244 pub enabled: bool,
12245 #[serde(default = "default_climate_scenarios")]
12247 pub scenarios: Vec<String>,
12248 #[serde(default = "default_time_horizons")]
12250 pub time_horizons: Vec<u32>,
12251}
12252
12253fn default_climate_scenarios() -> Vec<String> {
12254 vec![
12255 "net_zero_2050".to_string(),
12256 "stated_policies".to_string(),
12257 "current_trajectory".to_string(),
12258 ]
12259}
12260
12261fn default_time_horizons() -> Vec<u32> {
12262 vec![5, 10, 30]
12263}
12264
12265impl Default for ClimateScenarioConfig {
12266 fn default() -> Self {
12267 Self {
12268 enabled: false,
12269 scenarios: default_climate_scenarios(),
12270 time_horizons: default_time_horizons(),
12271 }
12272 }
12273}
12274
12275#[cfg(test)]
12276#[allow(clippy::unwrap_used)]
12277mod tests {
12278 use super::*;
12279 use crate::presets::demo_preset;
12280
12281 #[test]
12286 fn test_config_yaml_roundtrip() {
12287 let config = demo_preset();
12288 let yaml = serde_yaml::to_string(&config).expect("Failed to serialize to YAML");
12289 let deserialized: GeneratorConfig =
12290 serde_yaml::from_str(&yaml).expect("Failed to deserialize from YAML");
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 assert_eq!(config.companies[0].code, deserialized.companies[0].code);
12299 }
12300
12301 #[test]
12302 fn test_config_json_roundtrip() {
12303 let mut config = demo_preset();
12305 config.master_data.employees.approval_limits.executive = 1e12;
12307
12308 let json = serde_json::to_string(&config).expect("Failed to serialize to JSON");
12309 let deserialized: GeneratorConfig =
12310 serde_json::from_str(&json).expect("Failed to deserialize from JSON");
12311
12312 assert_eq!(
12313 config.global.period_months,
12314 deserialized.global.period_months
12315 );
12316 assert_eq!(config.global.industry, deserialized.global.industry);
12317 assert_eq!(config.companies.len(), deserialized.companies.len());
12318 }
12319
12320 #[test]
12321 fn test_transaction_volume_serialization() {
12322 let volumes = vec![
12324 (TransactionVolume::TenK, "ten_k"),
12325 (TransactionVolume::HundredK, "hundred_k"),
12326 (TransactionVolume::OneM, "one_m"),
12327 (TransactionVolume::TenM, "ten_m"),
12328 (TransactionVolume::HundredM, "hundred_m"),
12329 ];
12330
12331 for (volume, expected_key) in volumes {
12332 let json = serde_json::to_string(&volume).expect("Failed to serialize");
12333 assert!(
12334 json.contains(expected_key),
12335 "Expected {} in JSON: {}",
12336 expected_key,
12337 json
12338 );
12339 }
12340 }
12341
12342 #[test]
12343 fn test_transaction_volume_custom_serialization() {
12344 let volume = TransactionVolume::Custom(12345);
12345 let json = serde_json::to_string(&volume).expect("Failed to serialize");
12346 let deserialized: TransactionVolume =
12347 serde_json::from_str(&json).expect("Failed to deserialize");
12348 assert_eq!(deserialized.count(), 12345);
12349 }
12350
12351 #[test]
12352 fn test_output_mode_serialization() {
12353 let modes = vec![
12354 OutputMode::Streaming,
12355 OutputMode::FlatFile,
12356 OutputMode::Both,
12357 ];
12358
12359 for mode in modes {
12360 let json = serde_json::to_string(&mode).expect("Failed to serialize");
12361 let deserialized: OutputMode =
12362 serde_json::from_str(&json).expect("Failed to deserialize");
12363 assert!(format!("{:?}", mode) == format!("{:?}", deserialized));
12364 }
12365 }
12366
12367 #[test]
12368 fn test_file_format_serialization() {
12369 let formats = vec![
12370 FileFormat::Csv,
12371 FileFormat::Parquet,
12372 FileFormat::Json,
12373 FileFormat::JsonLines,
12374 ];
12375
12376 for format in formats {
12377 let json = serde_json::to_string(&format).expect("Failed to serialize");
12378 let deserialized: FileFormat =
12379 serde_json::from_str(&json).expect("Failed to deserialize");
12380 assert!(format!("{:?}", format) == format!("{:?}", deserialized));
12381 }
12382 }
12383
12384 #[test]
12385 fn test_compression_algorithm_serialization() {
12386 let algos = vec![
12387 CompressionAlgorithm::Gzip,
12388 CompressionAlgorithm::Zstd,
12389 CompressionAlgorithm::Lz4,
12390 CompressionAlgorithm::Snappy,
12391 ];
12392
12393 for algo in algos {
12394 let json = serde_json::to_string(&algo).expect("Failed to serialize");
12395 let deserialized: CompressionAlgorithm =
12396 serde_json::from_str(&json).expect("Failed to deserialize");
12397 assert!(format!("{:?}", algo) == format!("{:?}", deserialized));
12398 }
12399 }
12400
12401 #[test]
12402 fn test_transfer_pricing_method_serialization() {
12403 let methods = vec![
12404 TransferPricingMethod::CostPlus,
12405 TransferPricingMethod::ComparableUncontrolled,
12406 TransferPricingMethod::ResalePrice,
12407 TransferPricingMethod::TransactionalNetMargin,
12408 TransferPricingMethod::ProfitSplit,
12409 ];
12410
12411 for method in methods {
12412 let json = serde_json::to_string(&method).expect("Failed to serialize");
12413 let deserialized: TransferPricingMethod =
12414 serde_json::from_str(&json).expect("Failed to deserialize");
12415 assert!(format!("{:?}", method) == format!("{:?}", deserialized));
12416 }
12417 }
12418
12419 #[test]
12420 fn test_benford_exemption_serialization() {
12421 let exemptions = vec![
12422 BenfordExemption::Recurring,
12423 BenfordExemption::Payroll,
12424 BenfordExemption::FixedFees,
12425 BenfordExemption::RoundAmounts,
12426 ];
12427
12428 for exemption in exemptions {
12429 let json = serde_json::to_string(&exemption).expect("Failed to serialize");
12430 let deserialized: BenfordExemption =
12431 serde_json::from_str(&json).expect("Failed to deserialize");
12432 assert!(format!("{:?}", exemption) == format!("{:?}", deserialized));
12433 }
12434 }
12435
12436 #[test]
12441 fn test_global_config_defaults() {
12442 let yaml = r#"
12443 industry: manufacturing
12444 start_date: "2024-01-01"
12445 period_months: 6
12446 "#;
12447 let config: GlobalConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12448 assert_eq!(config.group_currency, "USD");
12449 assert!(config.parallel);
12450 assert_eq!(config.worker_threads, 0);
12451 assert_eq!(config.memory_limit_mb, 0);
12452 }
12453
12454 #[test]
12455 fn test_fraud_config_defaults() {
12456 let config = FraudConfig::default();
12457 assert!(!config.enabled);
12458 assert_eq!(config.fraud_rate, 0.005);
12459 assert!(!config.clustering_enabled);
12460 }
12461
12462 #[test]
12463 fn test_internal_controls_config_defaults() {
12464 let config = InternalControlsConfig::default();
12465 assert!(!config.enabled);
12466 assert_eq!(config.exception_rate, 0.02);
12467 assert_eq!(config.sod_violation_rate, 0.01);
12468 assert!(config.export_control_master_data);
12469 assert_eq!(config.sox_materiality_threshold, 10000.0);
12470 assert!(config.coso_enabled);
12472 assert!(!config.include_entity_level_controls);
12473 assert_eq!(config.target_maturity_level, "mixed");
12474 }
12475
12476 #[test]
12477 fn test_output_config_defaults() {
12478 let config = OutputConfig::default();
12479 assert!(matches!(config.mode, OutputMode::FlatFile));
12480 assert_eq!(config.formats, vec![FileFormat::Parquet]);
12481 assert!(config.compression.enabled);
12482 assert!(matches!(
12483 config.compression.algorithm,
12484 CompressionAlgorithm::Zstd
12485 ));
12486 assert!(config.include_acdoca);
12487 assert!(!config.include_bseg);
12488 assert!(config.partition_by_period);
12489 assert!(!config.partition_by_company);
12490 }
12491
12492 #[test]
12493 fn test_approval_config_defaults() {
12494 let config = ApprovalConfig::default();
12495 assert!(!config.enabled);
12496 assert_eq!(config.auto_approve_threshold, 1000.0);
12497 assert_eq!(config.rejection_rate, 0.02);
12498 assert_eq!(config.revision_rate, 0.05);
12499 assert_eq!(config.average_approval_delay_hours, 4.0);
12500 assert_eq!(config.thresholds.len(), 4);
12501 }
12502
12503 #[test]
12504 fn test_p2p_flow_config_defaults() {
12505 let config = P2PFlowConfig::default();
12506 assert!(config.enabled);
12507 assert_eq!(config.three_way_match_rate, 0.95);
12508 assert_eq!(config.partial_delivery_rate, 0.15);
12509 assert_eq!(config.average_po_to_gr_days, 14);
12510 }
12511
12512 #[test]
12513 fn test_o2c_flow_config_defaults() {
12514 let config = O2CFlowConfig::default();
12515 assert!(config.enabled);
12516 assert_eq!(config.credit_check_failure_rate, 0.02);
12517 assert_eq!(config.return_rate, 0.03);
12518 assert_eq!(config.bad_debt_rate, 0.01);
12519 }
12520
12521 #[test]
12522 fn test_balance_config_defaults() {
12523 let config = BalanceConfig::default();
12524 assert!(!config.generate_opening_balances);
12525 assert!(config.generate_trial_balances);
12526 assert_eq!(config.target_gross_margin, 0.35);
12527 assert!(config.validate_balance_equation);
12528 assert!(config.reconcile_subledgers);
12529 }
12530
12531 #[test]
12536 fn test_partial_config_with_defaults() {
12537 let yaml = r#"
12539 global:
12540 industry: manufacturing
12541 start_date: "2024-01-01"
12542 period_months: 3
12543 companies:
12544 - code: "TEST"
12545 name: "Test Company"
12546 currency: "USD"
12547 country: "US"
12548 annual_transaction_volume: ten_k
12549 chart_of_accounts:
12550 complexity: small
12551 output:
12552 output_directory: "./output"
12553 "#;
12554
12555 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12556 assert_eq!(config.global.period_months, 3);
12557 assert_eq!(config.companies.len(), 1);
12558 assert!(!config.fraud.enabled); assert!(!config.internal_controls.enabled); }
12561
12562 #[test]
12563 fn test_config_with_fraud_enabled() {
12564 let yaml = r#"
12565 global:
12566 industry: retail
12567 start_date: "2024-01-01"
12568 period_months: 12
12569 companies:
12570 - code: "RETAIL"
12571 name: "Retail Co"
12572 currency: "USD"
12573 country: "US"
12574 annual_transaction_volume: hundred_k
12575 chart_of_accounts:
12576 complexity: medium
12577 output:
12578 output_directory: "./output"
12579 fraud:
12580 enabled: true
12581 fraud_rate: 0.05
12582 clustering_enabled: true
12583 "#;
12584
12585 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12586 assert!(config.fraud.enabled);
12587 assert_eq!(config.fraud.fraud_rate, 0.05);
12588 assert!(config.fraud.clustering_enabled);
12589 }
12590
12591 #[test]
12592 fn test_config_with_multiple_companies() {
12593 let yaml = r#"
12594 global:
12595 industry: manufacturing
12596 start_date: "2024-01-01"
12597 period_months: 6
12598 companies:
12599 - code: "HQ"
12600 name: "Headquarters"
12601 currency: "USD"
12602 country: "US"
12603 annual_transaction_volume: hundred_k
12604 volume_weight: 1.0
12605 - code: "EU"
12606 name: "European Subsidiary"
12607 currency: "EUR"
12608 country: "DE"
12609 annual_transaction_volume: hundred_k
12610 volume_weight: 0.5
12611 - code: "APAC"
12612 name: "Asia Pacific"
12613 currency: "JPY"
12614 country: "JP"
12615 annual_transaction_volume: ten_k
12616 volume_weight: 0.3
12617 chart_of_accounts:
12618 complexity: large
12619 output:
12620 output_directory: "./output"
12621 "#;
12622
12623 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12624 assert_eq!(config.companies.len(), 3);
12625 assert_eq!(config.companies[0].code, "HQ");
12626 assert_eq!(config.companies[1].currency, "EUR");
12627 assert_eq!(config.companies[2].volume_weight, 0.3);
12628 }
12629
12630 #[test]
12631 fn test_intercompany_config() {
12632 let yaml = r#"
12633 enabled: true
12634 ic_transaction_rate: 0.20
12635 transfer_pricing_method: cost_plus
12636 markup_percent: 0.08
12637 generate_matched_pairs: true
12638 generate_eliminations: true
12639 "#;
12640
12641 let config: IntercompanyConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12642 assert!(config.enabled);
12643 assert_eq!(config.ic_transaction_rate, 0.20);
12644 assert!(matches!(
12645 config.transfer_pricing_method,
12646 TransferPricingMethod::CostPlus
12647 ));
12648 assert_eq!(config.markup_percent, 0.08);
12649 assert!(config.generate_eliminations);
12650 }
12651
12652 #[test]
12657 fn test_company_config_defaults() {
12658 let yaml = r#"
12659 code: "TEST"
12660 name: "Test Company"
12661 currency: "USD"
12662 country: "US"
12663 annual_transaction_volume: ten_k
12664 "#;
12665
12666 let config: CompanyConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12667 assert_eq!(config.fiscal_year_variant, "K4"); assert_eq!(config.volume_weight, 1.0); }
12670
12671 #[test]
12676 fn test_coa_config_defaults() {
12677 let yaml = r#"
12678 complexity: medium
12679 "#;
12680
12681 let config: ChartOfAccountsConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12682 assert!(config.industry_specific); assert!(config.custom_accounts.is_none());
12684 assert_eq!(config.min_hierarchy_depth, 2); assert_eq!(config.max_hierarchy_depth, 5); }
12687
12688 #[test]
12693 fn test_accounting_standards_config_defaults() {
12694 let config = AccountingStandardsConfig::default();
12695 assert!(!config.enabled);
12696 assert!(config.framework.is_none());
12697 assert!(!config.revenue_recognition.enabled);
12698 assert!(!config.leases.enabled);
12699 assert!(!config.fair_value.enabled);
12700 assert!(!config.impairment.enabled);
12701 assert!(!config.generate_differences);
12702 }
12703
12704 #[test]
12705 fn test_accounting_standards_config_yaml() {
12706 let yaml = r#"
12707 enabled: true
12708 framework: ifrs
12709 revenue_recognition:
12710 enabled: true
12711 generate_contracts: true
12712 avg_obligations_per_contract: 2.5
12713 variable_consideration_rate: 0.20
12714 over_time_recognition_rate: 0.35
12715 contract_count: 150
12716 leases:
12717 enabled: true
12718 lease_count: 75
12719 finance_lease_percent: 0.25
12720 avg_lease_term_months: 48
12721 generate_differences: true
12722 "#;
12723
12724 let config: AccountingStandardsConfig =
12725 serde_yaml::from_str(yaml).expect("Failed to parse");
12726 assert!(config.enabled);
12727 assert!(matches!(
12728 config.framework,
12729 Some(AccountingFrameworkConfig::Ifrs)
12730 ));
12731 assert!(config.revenue_recognition.enabled);
12732 assert_eq!(config.revenue_recognition.contract_count, 150);
12733 assert_eq!(config.revenue_recognition.avg_obligations_per_contract, 2.5);
12734 assert!(config.leases.enabled);
12735 assert_eq!(config.leases.lease_count, 75);
12736 assert_eq!(config.leases.finance_lease_percent, 0.25);
12737 assert!(config.generate_differences);
12738 }
12739
12740 #[test]
12741 fn test_accounting_framework_serialization() {
12742 let frameworks = [
12743 AccountingFrameworkConfig::UsGaap,
12744 AccountingFrameworkConfig::Ifrs,
12745 AccountingFrameworkConfig::DualReporting,
12746 AccountingFrameworkConfig::FrenchGaap,
12747 AccountingFrameworkConfig::GermanGaap,
12748 ];
12749
12750 for framework in frameworks {
12751 let json = serde_json::to_string(&framework).expect("Failed to serialize");
12752 let deserialized: AccountingFrameworkConfig =
12753 serde_json::from_str(&json).expect("Failed to deserialize");
12754 assert!(format!("{:?}", framework) == format!("{:?}", deserialized));
12755 }
12756 }
12757
12758 #[test]
12759 fn test_revenue_recognition_config_defaults() {
12760 let config = RevenueRecognitionConfig::default();
12761 assert!(!config.enabled);
12762 assert!(config.generate_contracts);
12763 assert_eq!(config.avg_obligations_per_contract, 2.0);
12764 assert_eq!(config.variable_consideration_rate, 0.15);
12765 assert_eq!(config.over_time_recognition_rate, 0.30);
12766 assert_eq!(config.contract_count, 100);
12767 }
12768
12769 #[test]
12770 fn test_lease_accounting_config_defaults() {
12771 let config = LeaseAccountingConfig::default();
12772 assert!(!config.enabled);
12773 assert_eq!(config.lease_count, 50);
12774 assert_eq!(config.finance_lease_percent, 0.30);
12775 assert_eq!(config.avg_lease_term_months, 60);
12776 assert!(config.generate_amortization);
12777 assert_eq!(config.real_estate_percent, 0.40);
12778 }
12779
12780 #[test]
12781 fn test_fair_value_config_defaults() {
12782 let config = FairValueConfig::default();
12783 assert!(!config.enabled);
12784 assert_eq!(config.measurement_count, 25);
12785 assert_eq!(config.level1_percent, 0.40);
12786 assert_eq!(config.level2_percent, 0.35);
12787 assert_eq!(config.level3_percent, 0.25);
12788 assert!(!config.include_sensitivity_analysis);
12789 }
12790
12791 #[test]
12792 fn test_impairment_config_defaults() {
12793 let config = ImpairmentConfig::default();
12794 assert!(!config.enabled);
12795 assert_eq!(config.test_count, 15);
12796 assert_eq!(config.impairment_rate, 0.10);
12797 assert!(config.generate_projections);
12798 assert!(!config.include_goodwill);
12799 }
12800
12801 #[test]
12806 fn test_audit_standards_config_defaults() {
12807 let config = AuditStandardsConfig::default();
12808 assert!(!config.enabled);
12809 assert!(!config.isa_compliance.enabled);
12810 assert!(!config.analytical_procedures.enabled);
12811 assert!(!config.confirmations.enabled);
12812 assert!(!config.opinion.enabled);
12813 assert!(!config.generate_audit_trail);
12814 assert!(!config.sox.enabled);
12815 assert!(!config.pcaob.enabled);
12816 }
12817
12818 #[test]
12819 fn test_audit_standards_config_yaml() {
12820 let yaml = r#"
12821 enabled: true
12822 isa_compliance:
12823 enabled: true
12824 compliance_level: comprehensive
12825 generate_isa_mappings: true
12826 include_pcaob: true
12827 framework: dual
12828 analytical_procedures:
12829 enabled: true
12830 procedures_per_account: 5
12831 variance_probability: 0.25
12832 confirmations:
12833 enabled: true
12834 confirmation_count: 75
12835 positive_response_rate: 0.90
12836 exception_rate: 0.08
12837 opinion:
12838 enabled: true
12839 generate_kam: true
12840 average_kam_count: 4
12841 sox:
12842 enabled: true
12843 generate_302_certifications: true
12844 generate_404_assessments: true
12845 material_weakness_rate: 0.03
12846 pcaob:
12847 enabled: true
12848 is_pcaob_audit: true
12849 include_icfr_opinion: true
12850 generate_audit_trail: true
12851 "#;
12852
12853 let config: AuditStandardsConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12854 assert!(config.enabled);
12855 assert!(config.isa_compliance.enabled);
12856 assert_eq!(config.isa_compliance.compliance_level, "comprehensive");
12857 assert!(config.isa_compliance.include_pcaob);
12858 assert_eq!(config.isa_compliance.framework, "dual");
12859 assert!(config.analytical_procedures.enabled);
12860 assert_eq!(config.analytical_procedures.procedures_per_account, 5);
12861 assert!(config.confirmations.enabled);
12862 assert_eq!(config.confirmations.confirmation_count, 75);
12863 assert!(config.opinion.enabled);
12864 assert_eq!(config.opinion.average_kam_count, 4);
12865 assert!(config.sox.enabled);
12866 assert!(config.sox.generate_302_certifications);
12867 assert_eq!(config.sox.material_weakness_rate, 0.03);
12868 assert!(config.pcaob.enabled);
12869 assert!(config.pcaob.is_pcaob_audit);
12870 assert!(config.pcaob.include_icfr_opinion);
12871 assert!(config.generate_audit_trail);
12872 }
12873
12874 #[test]
12875 fn test_isa_compliance_config_defaults() {
12876 let config = IsaComplianceConfig::default();
12877 assert!(!config.enabled);
12878 assert_eq!(config.compliance_level, "standard");
12879 assert!(config.generate_isa_mappings);
12880 assert!(config.generate_coverage_summary);
12881 assert!(!config.include_pcaob);
12882 assert_eq!(config.framework, "isa");
12883 }
12884
12885 #[test]
12886 fn test_sox_compliance_config_defaults() {
12887 let config = SoxComplianceConfig::default();
12888 assert!(!config.enabled);
12889 assert!(config.generate_302_certifications);
12890 assert!(config.generate_404_assessments);
12891 assert_eq!(config.materiality_threshold, 10000.0);
12892 assert_eq!(config.material_weakness_rate, 0.02);
12893 assert_eq!(config.significant_deficiency_rate, 0.08);
12894 }
12895
12896 #[test]
12897 fn test_pcaob_config_defaults() {
12898 let config = PcaobConfig::default();
12899 assert!(!config.enabled);
12900 assert!(!config.is_pcaob_audit);
12901 assert!(config.generate_cam);
12902 assert!(!config.include_icfr_opinion);
12903 assert!(!config.generate_standard_mappings);
12904 }
12905
12906 #[test]
12907 fn test_config_with_standards_enabled() {
12908 let yaml = r#"
12909 global:
12910 industry: financial_services
12911 start_date: "2024-01-01"
12912 period_months: 12
12913 companies:
12914 - code: "BANK"
12915 name: "Test Bank"
12916 currency: "USD"
12917 country: "US"
12918 annual_transaction_volume: hundred_k
12919 chart_of_accounts:
12920 complexity: large
12921 output:
12922 output_directory: "./output"
12923 accounting_standards:
12924 enabled: true
12925 framework: us_gaap
12926 revenue_recognition:
12927 enabled: true
12928 leases:
12929 enabled: true
12930 audit_standards:
12931 enabled: true
12932 isa_compliance:
12933 enabled: true
12934 sox:
12935 enabled: true
12936 "#;
12937
12938 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12939 assert!(config.accounting_standards.enabled);
12940 assert!(matches!(
12941 config.accounting_standards.framework,
12942 Some(AccountingFrameworkConfig::UsGaap)
12943 ));
12944 assert!(config.accounting_standards.revenue_recognition.enabled);
12945 assert!(config.accounting_standards.leases.enabled);
12946 assert!(config.audit_standards.enabled);
12947 assert!(config.audit_standards.isa_compliance.enabled);
12948 assert!(config.audit_standards.sox.enabled);
12949 }
12950
12951 #[test]
12956 fn test_industry_specific_config_defaults() {
12957 let config = IndustrySpecificConfig::default();
12958 assert!(!config.enabled);
12959 assert!(!config.manufacturing.enabled);
12960 assert!(!config.retail.enabled);
12961 assert!(!config.healthcare.enabled);
12962 assert!(!config.technology.enabled);
12963 assert!(!config.financial_services.enabled);
12964 assert!(!config.professional_services.enabled);
12965 }
12966
12967 #[test]
12968 fn test_manufacturing_config_defaults() {
12969 let config = ManufacturingConfig::default();
12970 assert!(!config.enabled);
12971 assert_eq!(config.bom_depth, 4);
12972 assert!(!config.just_in_time);
12973 assert_eq!(config.supplier_tiers, 2);
12974 assert_eq!(config.target_yield_rate, 0.97);
12975 assert_eq!(config.scrap_alert_threshold, 0.03);
12976 }
12977
12978 #[test]
12979 fn test_retail_config_defaults() {
12980 let config = RetailConfig::default();
12981 assert!(!config.enabled);
12982 assert_eq!(config.avg_daily_transactions, 500);
12983 assert!(config.loss_prevention);
12984 assert_eq!(config.shrinkage_rate, 0.015);
12985 }
12986
12987 #[test]
12988 fn test_healthcare_config_defaults() {
12989 let config = HealthcareConfig::default();
12990 assert!(!config.enabled);
12991 assert_eq!(config.facility_type, "hospital");
12992 assert_eq!(config.avg_daily_encounters, 150);
12993 assert!(config.compliance.hipaa);
12994 assert!(config.compliance.stark_law);
12995 assert!(config.coding_systems.icd10);
12996 assert!(config.coding_systems.cpt);
12997 }
12998
12999 #[test]
13000 fn test_technology_config_defaults() {
13001 let config = TechnologyConfig::default();
13002 assert!(!config.enabled);
13003 assert_eq!(config.revenue_model, "saas");
13004 assert_eq!(config.subscription_revenue_pct, 0.60);
13005 assert!(config.rd_capitalization.enabled);
13006 }
13007
13008 #[test]
13009 fn test_config_with_industry_specific() {
13010 let yaml = r#"
13011 global:
13012 industry: healthcare
13013 start_date: "2024-01-01"
13014 period_months: 12
13015 companies:
13016 - code: "HOSP"
13017 name: "Test Hospital"
13018 currency: "USD"
13019 country: "US"
13020 annual_transaction_volume: hundred_k
13021 chart_of_accounts:
13022 complexity: medium
13023 output:
13024 output_directory: "./output"
13025 industry_specific:
13026 enabled: true
13027 healthcare:
13028 enabled: true
13029 facility_type: hospital
13030 payer_mix:
13031 medicare: 0.45
13032 medicaid: 0.15
13033 commercial: 0.35
13034 self_pay: 0.05
13035 coding_systems:
13036 icd10: true
13037 cpt: true
13038 drg: true
13039 compliance:
13040 hipaa: true
13041 stark_law: true
13042 anomaly_rates:
13043 upcoding: 0.03
13044 unbundling: 0.02
13045 "#;
13046
13047 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13048 assert!(config.industry_specific.enabled);
13049 assert!(config.industry_specific.healthcare.enabled);
13050 assert_eq!(
13051 config.industry_specific.healthcare.facility_type,
13052 "hospital"
13053 );
13054 assert_eq!(config.industry_specific.healthcare.payer_mix.medicare, 0.45);
13055 assert_eq!(config.industry_specific.healthcare.payer_mix.self_pay, 0.05);
13056 assert!(config.industry_specific.healthcare.coding_systems.icd10);
13057 assert!(config.industry_specific.healthcare.compliance.hipaa);
13058 assert_eq!(
13059 config.industry_specific.healthcare.anomaly_rates.upcoding,
13060 0.03
13061 );
13062 }
13063
13064 #[test]
13065 fn test_config_with_manufacturing_specific() {
13066 let yaml = r#"
13067 global:
13068 industry: manufacturing
13069 start_date: "2024-01-01"
13070 period_months: 12
13071 companies:
13072 - code: "MFG"
13073 name: "Test Manufacturing"
13074 currency: "USD"
13075 country: "US"
13076 annual_transaction_volume: hundred_k
13077 chart_of_accounts:
13078 complexity: medium
13079 output:
13080 output_directory: "./output"
13081 industry_specific:
13082 enabled: true
13083 manufacturing:
13084 enabled: true
13085 bom_depth: 5
13086 just_in_time: true
13087 supplier_tiers: 3
13088 target_yield_rate: 0.98
13089 anomaly_rates:
13090 yield_manipulation: 0.02
13091 phantom_production: 0.01
13092 "#;
13093
13094 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13095 assert!(config.industry_specific.enabled);
13096 assert!(config.industry_specific.manufacturing.enabled);
13097 assert_eq!(config.industry_specific.manufacturing.bom_depth, 5);
13098 assert!(config.industry_specific.manufacturing.just_in_time);
13099 assert_eq!(config.industry_specific.manufacturing.supplier_tiers, 3);
13100 assert_eq!(
13101 config.industry_specific.manufacturing.target_yield_rate,
13102 0.98
13103 );
13104 assert_eq!(
13105 config
13106 .industry_specific
13107 .manufacturing
13108 .anomaly_rates
13109 .yield_manipulation,
13110 0.02
13111 );
13112 }
13113
13114 #[test]
13119 fn test_tax_config_defaults() {
13120 let tax = TaxConfig::default();
13121 assert!(!tax.enabled);
13122 assert!(tax.jurisdictions.countries.is_empty());
13123 assert!(!tax.jurisdictions.include_subnational);
13124 assert!(!tax.vat_gst.enabled);
13125 assert!(tax.vat_gst.standard_rates.is_empty());
13126 assert!(tax.vat_gst.reduced_rates.is_empty());
13127 assert!(tax.vat_gst.exempt_categories.is_empty());
13128 assert!(tax.vat_gst.reverse_charge);
13129 assert!(!tax.sales_tax.enabled);
13130 assert!(tax.sales_tax.nexus_states.is_empty());
13131 assert!(!tax.withholding.enabled);
13132 assert!(tax.withholding.treaty_network);
13133 assert_eq!(tax.withholding.default_rate, 0.30);
13134 assert_eq!(tax.withholding.treaty_reduced_rate, 0.15);
13135 assert!(tax.provisions.enabled);
13136 assert_eq!(tax.provisions.statutory_rate, 0.21);
13137 assert!(tax.provisions.uncertain_positions);
13138 assert!(!tax.payroll_tax.enabled);
13139 assert_eq!(tax.anomaly_rate, 0.03);
13140 }
13141
13142 #[test]
13143 fn test_tax_config_from_yaml() {
13144 let yaml = r#"
13145 global:
13146 seed: 42
13147 start_date: "2024-01-01"
13148 period_months: 12
13149 industry: retail
13150 companies:
13151 - code: C001
13152 name: Test Corp
13153 currency: USD
13154 country: US
13155 annual_transaction_volume: ten_k
13156 chart_of_accounts:
13157 complexity: small
13158 output:
13159 output_directory: ./output
13160 tax:
13161 enabled: true
13162 anomaly_rate: 0.05
13163 jurisdictions:
13164 countries: ["US", "DE", "GB"]
13165 include_subnational: true
13166 vat_gst:
13167 enabled: true
13168 standard_rates:
13169 DE: 0.19
13170 GB: 0.20
13171 reduced_rates:
13172 DE: 0.07
13173 GB: 0.05
13174 exempt_categories:
13175 - financial_services
13176 - healthcare
13177 reverse_charge: false
13178 sales_tax:
13179 enabled: true
13180 nexus_states: ["CA", "NY", "TX"]
13181 withholding:
13182 enabled: true
13183 treaty_network: false
13184 default_rate: 0.25
13185 treaty_reduced_rate: 0.10
13186 provisions:
13187 enabled: false
13188 statutory_rate: 0.28
13189 uncertain_positions: false
13190 payroll_tax:
13191 enabled: true
13192 "#;
13193
13194 let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13195 assert!(config.tax.enabled);
13196 assert_eq!(config.tax.anomaly_rate, 0.05);
13197
13198 assert_eq!(config.tax.jurisdictions.countries.len(), 3);
13200 assert!(config
13201 .tax
13202 .jurisdictions
13203 .countries
13204 .contains(&"DE".to_string()));
13205 assert!(config.tax.jurisdictions.include_subnational);
13206
13207 assert!(config.tax.vat_gst.enabled);
13209 assert_eq!(config.tax.vat_gst.standard_rates.get("DE"), Some(&0.19));
13210 assert_eq!(config.tax.vat_gst.standard_rates.get("GB"), Some(&0.20));
13211 assert_eq!(config.tax.vat_gst.reduced_rates.get("DE"), Some(&0.07));
13212 assert_eq!(config.tax.vat_gst.exempt_categories.len(), 2);
13213 assert!(!config.tax.vat_gst.reverse_charge);
13214
13215 assert!(config.tax.sales_tax.enabled);
13217 assert_eq!(config.tax.sales_tax.nexus_states.len(), 3);
13218 assert!(config
13219 .tax
13220 .sales_tax
13221 .nexus_states
13222 .contains(&"CA".to_string()));
13223
13224 assert!(config.tax.withholding.enabled);
13226 assert!(!config.tax.withholding.treaty_network);
13227 assert_eq!(config.tax.withholding.default_rate, 0.25);
13228 assert_eq!(config.tax.withholding.treaty_reduced_rate, 0.10);
13229
13230 assert!(!config.tax.provisions.enabled);
13232 assert_eq!(config.tax.provisions.statutory_rate, 0.28);
13233 assert!(!config.tax.provisions.uncertain_positions);
13234
13235 assert!(config.tax.payroll_tax.enabled);
13237 }
13238
13239 #[test]
13240 fn test_generator_config_with_tax_default() {
13241 let yaml = r#"
13242 global:
13243 seed: 42
13244 start_date: "2024-01-01"
13245 period_months: 12
13246 industry: retail
13247 companies:
13248 - code: C001
13249 name: Test Corp
13250 currency: USD
13251 country: US
13252 annual_transaction_volume: ten_k
13253 chart_of_accounts:
13254 complexity: small
13255 output:
13256 output_directory: ./output
13257 "#;
13258
13259 let config: GeneratorConfig =
13260 serde_yaml::from_str(yaml).expect("Failed to parse config without tax section");
13261 assert!(!config.tax.enabled);
13263 assert!(config.tax.jurisdictions.countries.is_empty());
13264 assert_eq!(config.tax.anomaly_rate, 0.03);
13265 assert!(config.tax.provisions.enabled); assert_eq!(config.tax.provisions.statutory_rate, 0.21);
13267 }
13268}