Skip to main content

datasynth_config/
schema.rs

1//! Configuration schema for synthetic data generation.
2
3use 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/// Root configuration for the synthetic data generator.
12#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct GeneratorConfig {
14    /// Global settings
15    pub global: GlobalConfig,
16    /// Company configuration
17    pub companies: Vec<CompanyConfig>,
18    /// Chart of Accounts configuration
19    pub chart_of_accounts: ChartOfAccountsConfig,
20    /// Transaction generation settings
21    #[serde(default)]
22    pub transactions: TransactionConfig,
23    /// Output configuration
24    pub output: OutputConfig,
25    /// Fraud simulation settings
26    #[serde(default)]
27    pub fraud: FraudConfig,
28    /// Data quality variation settings
29    #[serde(default)]
30    pub data_quality: DataQualitySchemaConfig,
31    /// Internal Controls System settings
32    #[serde(default)]
33    pub internal_controls: InternalControlsConfig,
34    /// Business process mix
35    #[serde(default)]
36    pub business_processes: BusinessProcessConfig,
37    /// User persona distribution
38    #[serde(default)]
39    pub user_personas: UserPersonaConfig,
40    /// Template configuration for realistic data
41    #[serde(default)]
42    pub templates: TemplateConfig,
43    /// Approval workflow configuration
44    #[serde(default)]
45    pub approval: ApprovalConfig,
46    /// Department structure configuration
47    #[serde(default)]
48    pub departments: DepartmentConfig,
49    /// Master data generation settings
50    #[serde(default)]
51    pub master_data: MasterDataConfig,
52    /// Document flow generation settings
53    #[serde(default)]
54    pub document_flows: DocumentFlowConfig,
55    /// Intercompany transaction settings
56    #[serde(default)]
57    pub intercompany: IntercompanyConfig,
58    /// Balance and trial balance settings
59    #[serde(default)]
60    pub balance: BalanceConfig,
61    /// OCPM (Object-Centric Process Mining) settings
62    #[serde(default)]
63    pub ocpm: OcpmConfig,
64    /// Audit engagement and workpaper generation settings
65    #[serde(default)]
66    pub audit: AuditGenerationConfig,
67    /// Banking KYC/AML transaction generation settings
68    #[serde(default)]
69    pub banking: datasynth_banking::BankingConfig,
70    /// Scenario configuration for metadata and tagging (Phase 1.3)
71    #[serde(default)]
72    pub scenario: ScenarioConfig,
73    /// Temporal drift configuration for simulating distribution changes over time (Phase 2.2)
74    #[serde(default)]
75    pub temporal: TemporalDriftConfig,
76    /// Graph export configuration for accounting network export
77    #[serde(default)]
78    pub graph_export: GraphExportConfig,
79    /// Streaming output API configuration
80    #[serde(default)]
81    pub streaming: StreamingSchemaConfig,
82    /// Rate limiting configuration
83    #[serde(default)]
84    pub rate_limit: RateLimitSchemaConfig,
85    /// Temporal attribute generation configuration
86    #[serde(default)]
87    pub temporal_attributes: TemporalAttributeSchemaConfig,
88    /// Relationship generation configuration
89    #[serde(default)]
90    pub relationships: RelationshipSchemaConfig,
91    /// Accounting standards framework configuration (IFRS, US GAAP)
92    #[serde(default)]
93    pub accounting_standards: AccountingStandardsConfig,
94    /// Audit standards framework configuration (ISA, PCAOB)
95    #[serde(default)]
96    pub audit_standards: AuditStandardsConfig,
97    /// Advanced distribution configuration (mixture models, correlations, regime changes)
98    #[serde(default)]
99    pub distributions: AdvancedDistributionConfig,
100    /// Temporal patterns configuration (business days, period-end dynamics, processing lags)
101    #[serde(default)]
102    pub temporal_patterns: TemporalPatternsConfig,
103    /// Vendor network configuration (multi-tier supply chain modeling)
104    #[serde(default)]
105    pub vendor_network: VendorNetworkSchemaConfig,
106    /// Customer segmentation configuration (value segments, lifecycle stages)
107    #[serde(default)]
108    pub customer_segmentation: CustomerSegmentationSchemaConfig,
109    /// Relationship strength calculation configuration
110    #[serde(default)]
111    pub relationship_strength: RelationshipStrengthSchemaConfig,
112    /// Cross-process link configuration (P2P ↔ O2C via inventory)
113    #[serde(default)]
114    pub cross_process_links: CrossProcessLinksSchemaConfig,
115    /// Organizational events configuration (acquisitions, divestitures, etc.)
116    #[serde(default)]
117    pub organizational_events: OrganizationalEventsSchemaConfig,
118    /// Behavioral drift configuration (vendor, customer, employee behavior)
119    #[serde(default)]
120    pub behavioral_drift: BehavioralDriftSchemaConfig,
121    /// Market drift configuration (economic cycles, commodities, price shocks)
122    #[serde(default)]
123    pub market_drift: MarketDriftSchemaConfig,
124    /// Drift labeling configuration for ground truth generation
125    #[serde(default)]
126    pub drift_labeling: DriftLabelingSchemaConfig,
127    /// Enhanced anomaly injection configuration (multi-stage schemes, correlated injection, near-miss)
128    #[serde(default)]
129    pub anomaly_injection: EnhancedAnomalyConfig,
130    /// Industry-specific transaction and anomaly generation configuration
131    #[serde(default)]
132    pub industry_specific: IndustrySpecificConfig,
133}
134
135/// Graph export configuration for accounting network and ML training exports.
136///
137/// This section enables exporting generated data as graphs for:
138/// - Network reconstruction algorithms
139/// - Graph neural network training
140/// - Neo4j graph database import
141#[derive(Debug, Clone, Serialize, Deserialize)]
142pub struct GraphExportConfig {
143    /// Enable graph export.
144    #[serde(default)]
145    pub enabled: bool,
146
147    /// Graph types to generate.
148    #[serde(default = "default_graph_types")]
149    pub graph_types: Vec<GraphTypeConfig>,
150
151    /// Export formats to generate.
152    #[serde(default = "default_graph_formats")]
153    pub formats: Vec<GraphExportFormat>,
154
155    /// Train split ratio for ML datasets.
156    #[serde(default = "default_train_ratio")]
157    pub train_ratio: f64,
158
159    /// Validation split ratio for ML datasets.
160    #[serde(default = "default_val_ratio")]
161    pub validation_ratio: f64,
162
163    /// Random seed for train/val/test splits.
164    #[serde(default)]
165    pub split_seed: Option<u64>,
166
167    /// Output subdirectory for graph exports (relative to output directory).
168    #[serde(default = "default_graph_subdir")]
169    pub output_subdirectory: String,
170
171    /// Multi-layer hypergraph export settings for RustGraph integration.
172    #[serde(default)]
173    pub hypergraph: HypergraphExportSettings,
174}
175
176fn default_graph_types() -> Vec<GraphTypeConfig> {
177    vec![GraphTypeConfig::default()]
178}
179
180fn default_graph_formats() -> Vec<GraphExportFormat> {
181    vec![GraphExportFormat::PytorchGeometric]
182}
183
184fn default_train_ratio() -> f64 {
185    0.7
186}
187
188fn default_val_ratio() -> f64 {
189    0.15
190}
191
192fn default_graph_subdir() -> String {
193    "graphs".to_string()
194}
195
196impl Default for GraphExportConfig {
197    fn default() -> Self {
198        Self {
199            enabled: false,
200            graph_types: default_graph_types(),
201            formats: default_graph_formats(),
202            train_ratio: 0.7,
203            validation_ratio: 0.15,
204            split_seed: None,
205            output_subdirectory: "graphs".to_string(),
206            hypergraph: HypergraphExportSettings::default(),
207        }
208    }
209}
210
211/// Settings for the multi-layer hypergraph export (RustGraph integration).
212///
213/// Produces a 3-layer hypergraph:
214/// - Layer 1: Governance & Controls (COSO, SOX, internal controls, organizational)
215/// - Layer 2: Process Events (P2P/O2C document flows, OCPM events)
216/// - Layer 3: Accounting Network (GL accounts, journal entries as hyperedges)
217#[derive(Debug, Clone, Serialize, Deserialize)]
218pub struct HypergraphExportSettings {
219    /// Enable hypergraph export.
220    #[serde(default)]
221    pub enabled: bool,
222
223    /// Maximum total nodes across all layers (default 50000).
224    #[serde(default = "default_hypergraph_max_nodes")]
225    pub max_nodes: usize,
226
227    /// Aggregation strategy when node budget is exceeded.
228    #[serde(default = "default_aggregation_strategy")]
229    pub aggregation_strategy: String,
230
231    /// Layer 1 (Governance & Controls) settings.
232    #[serde(default)]
233    pub governance_layer: GovernanceLayerSettings,
234
235    /// Layer 2 (Process Events) settings.
236    #[serde(default)]
237    pub process_layer: ProcessLayerSettings,
238
239    /// Layer 3 (Accounting Network) settings.
240    #[serde(default)]
241    pub accounting_layer: AccountingLayerSettings,
242
243    /// Cross-layer edge generation settings.
244    #[serde(default)]
245    pub cross_layer: CrossLayerSettings,
246
247    /// Output subdirectory for hypergraph files (relative to graph output directory).
248    #[serde(default = "default_hypergraph_subdir")]
249    pub output_subdirectory: String,
250
251    /// Output format: "native" (default) for internal field names, "unified" for RustGraph format.
252    #[serde(default = "default_hypergraph_format")]
253    pub output_format: String,
254
255    /// Optional URL for streaming unified JSONL to a RustGraph ingest endpoint.
256    #[serde(default)]
257    pub stream_target: Option<String>,
258
259    /// Batch size for streaming (number of JSONL lines per HTTP POST). Default: 1000.
260    #[serde(default = "default_stream_batch_size")]
261    pub stream_batch_size: usize,
262}
263
264fn default_hypergraph_max_nodes() -> usize {
265    50_000
266}
267
268fn default_aggregation_strategy() -> String {
269    "pool_by_counterparty".to_string()
270}
271
272fn default_hypergraph_subdir() -> String {
273    "hypergraph".to_string()
274}
275
276fn default_hypergraph_format() -> String {
277    "native".to_string()
278}
279
280fn default_stream_batch_size() -> usize {
281    1000
282}
283
284impl Default for HypergraphExportSettings {
285    fn default() -> Self {
286        Self {
287            enabled: false,
288            max_nodes: 50_000,
289            aggregation_strategy: "pool_by_counterparty".to_string(),
290            governance_layer: GovernanceLayerSettings::default(),
291            process_layer: ProcessLayerSettings::default(),
292            accounting_layer: AccountingLayerSettings::default(),
293            cross_layer: CrossLayerSettings::default(),
294            output_subdirectory: "hypergraph".to_string(),
295            output_format: "native".to_string(),
296            stream_target: None,
297            stream_batch_size: 1000,
298        }
299    }
300}
301
302/// Layer 1: Governance & Controls layer settings.
303#[derive(Debug, Clone, Serialize, Deserialize)]
304pub struct GovernanceLayerSettings {
305    /// Include COSO framework nodes (5 components + 17 principles).
306    #[serde(default = "default_true")]
307    pub include_coso: bool,
308    /// Include internal control nodes.
309    #[serde(default = "default_true")]
310    pub include_controls: bool,
311    /// Include SOX assertion nodes.
312    #[serde(default = "default_true")]
313    pub include_sox: bool,
314    /// Include vendor master data nodes.
315    #[serde(default = "default_true")]
316    pub include_vendors: bool,
317    /// Include customer master data nodes.
318    #[serde(default = "default_true")]
319    pub include_customers: bool,
320    /// Include employee/organizational nodes.
321    #[serde(default = "default_true")]
322    pub include_employees: bool,
323}
324
325impl Default for GovernanceLayerSettings {
326    fn default() -> Self {
327        Self {
328            include_coso: true,
329            include_controls: true,
330            include_sox: true,
331            include_vendors: true,
332            include_customers: true,
333            include_employees: true,
334        }
335    }
336}
337
338/// Layer 2: Process Events layer settings.
339#[derive(Debug, Clone, Serialize, Deserialize)]
340pub struct ProcessLayerSettings {
341    /// Include P2P (Procure-to-Pay) document flow nodes.
342    #[serde(default = "default_true")]
343    pub include_p2p: bool,
344    /// Include O2C (Order-to-Cash) document flow nodes.
345    #[serde(default = "default_true")]
346    pub include_o2c: bool,
347    /// Export OCPM events as hyperedges.
348    #[serde(default = "default_true")]
349    pub events_as_hyperedges: bool,
350    /// Threshold: if a counterparty has more documents than this, aggregate into pool nodes.
351    #[serde(default = "default_docs_per_counterparty_threshold")]
352    pub docs_per_counterparty_threshold: usize,
353}
354
355fn default_docs_per_counterparty_threshold() -> usize {
356    20
357}
358
359impl Default for ProcessLayerSettings {
360    fn default() -> Self {
361        Self {
362            include_p2p: true,
363            include_o2c: true,
364            events_as_hyperedges: true,
365            docs_per_counterparty_threshold: 20,
366        }
367    }
368}
369
370/// Layer 3: Accounting Network layer settings.
371#[derive(Debug, Clone, Serialize, Deserialize)]
372pub struct AccountingLayerSettings {
373    /// Include GL account nodes.
374    #[serde(default = "default_true")]
375    pub include_accounts: bool,
376    /// Export journal entries as hyperedges (debit+credit accounts as participants).
377    #[serde(default = "default_true")]
378    pub je_as_hyperedges: bool,
379}
380
381impl Default for AccountingLayerSettings {
382    fn default() -> Self {
383        Self {
384            include_accounts: true,
385            je_as_hyperedges: true,
386        }
387    }
388}
389
390/// Cross-layer edge generation settings.
391#[derive(Debug, Clone, Serialize, Deserialize)]
392pub struct CrossLayerSettings {
393    /// Generate cross-layer edges (Control→Account, Vendor→PO, etc.).
394    #[serde(default = "default_true")]
395    pub enabled: bool,
396}
397
398impl Default for CrossLayerSettings {
399    fn default() -> Self {
400        Self { enabled: true }
401    }
402}
403
404/// Configuration for a specific graph type to export.
405#[derive(Debug, Clone, Serialize, Deserialize)]
406pub struct GraphTypeConfig {
407    /// Name identifier for this graph configuration.
408    #[serde(default = "default_graph_name")]
409    pub name: String,
410
411    /// Whether to aggregate parallel edges between the same nodes.
412    #[serde(default)]
413    pub aggregate_edges: bool,
414
415    /// Minimum edge weight to include (filters out small transactions).
416    #[serde(default)]
417    pub min_edge_weight: f64,
418
419    /// Whether to include document nodes (creates hub-and-spoke structure).
420    #[serde(default)]
421    pub include_document_nodes: bool,
422}
423
424fn default_graph_name() -> String {
425    "accounting_network".to_string()
426}
427
428impl Default for GraphTypeConfig {
429    fn default() -> Self {
430        Self {
431            name: "accounting_network".to_string(),
432            aggregate_edges: false,
433            min_edge_weight: 0.0,
434            include_document_nodes: false,
435        }
436    }
437}
438
439/// Export format for graph data.
440#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
441#[serde(rename_all = "snake_case")]
442pub enum GraphExportFormat {
443    /// PyTorch Geometric format (.npy files + metadata.json).
444    PytorchGeometric,
445    /// Neo4j format (CSV files + Cypher import scripts).
446    Neo4j,
447    /// Deep Graph Library format.
448    Dgl,
449    /// RustGraph/RustAssureTwin JSON format.
450    RustGraph,
451    /// RustGraph multi-layer hypergraph format (nodes.jsonl + edges.jsonl + hyperedges.jsonl).
452    RustGraphHypergraph,
453}
454
455/// Scenario configuration for metadata, tagging, and ML training setup.
456///
457/// This section enables tracking the purpose and characteristics of a generation run.
458#[derive(Debug, Clone, Default, Serialize, Deserialize)]
459pub struct ScenarioConfig {
460    /// Tags for categorizing and filtering datasets.
461    /// Examples: "fraud_detection", "retail", "month_end_stress", "ml_training"
462    #[serde(default)]
463    pub tags: Vec<String>,
464
465    /// Data quality profile preset.
466    /// - "clean": Minimal data quality issues (0.1% missing, 0.05% typos)
467    /// - "noisy": Moderate issues (5% missing, 2% typos, 1% duplicates)
468    /// - "legacy": Heavy issues simulating legacy system data (10% missing, 5% typos)
469    #[serde(default)]
470    pub profile: Option<String>,
471
472    /// Human-readable description of the scenario purpose.
473    #[serde(default)]
474    pub description: Option<String>,
475
476    /// Whether this run is for ML training (enables balanced labeling).
477    #[serde(default)]
478    pub ml_training: bool,
479
480    /// Target anomaly class balance for ML training.
481    /// If set, anomalies will be injected to achieve this ratio.
482    #[serde(default)]
483    pub target_anomaly_ratio: Option<f64>,
484
485    /// Custom metadata key-value pairs.
486    #[serde(default)]
487    pub metadata: std::collections::HashMap<String, String>,
488}
489
490/// Temporal drift configuration for simulating distribution changes over time.
491///
492/// This enables generation of data that shows realistic temporal evolution,
493/// useful for training drift detection models and testing temporal robustness.
494#[derive(Debug, Clone, Serialize, Deserialize)]
495pub struct TemporalDriftConfig {
496    /// Enable temporal drift simulation.
497    #[serde(default)]
498    pub enabled: bool,
499
500    /// Amount mean drift per period (e.g., 0.02 = 2% mean shift per month).
501    /// Simulates gradual inflation or business growth.
502    #[serde(default = "default_amount_drift")]
503    pub amount_mean_drift: f64,
504
505    /// Amount variance drift per period (e.g., 0.01 = 1% variance increase per month).
506    /// Simulates increasing volatility over time.
507    #[serde(default)]
508    pub amount_variance_drift: f64,
509
510    /// Anomaly rate drift per period (e.g., 0.001 = 0.1% increase per month).
511    /// Simulates increasing fraud attempts or degrading controls.
512    #[serde(default)]
513    pub anomaly_rate_drift: f64,
514
515    /// Concept drift rate - how quickly feature distributions change (0.0-1.0).
516    /// Higher values cause more rapid distribution shifts.
517    #[serde(default = "default_concept_drift")]
518    pub concept_drift_rate: f64,
519
520    /// Sudden drift events - probability of a sudden distribution shift in any period.
521    #[serde(default)]
522    pub sudden_drift_probability: f64,
523
524    /// Magnitude of sudden drift events when they occur (multiplier).
525    #[serde(default = "default_sudden_drift_magnitude")]
526    pub sudden_drift_magnitude: f64,
527
528    /// Seasonal drift - enable cyclic patterns that repeat annually.
529    #[serde(default)]
530    pub seasonal_drift: bool,
531
532    /// Drift start period (0 = from beginning). Use to simulate stable baseline before drift.
533    #[serde(default)]
534    pub drift_start_period: u32,
535
536    /// Drift type: "gradual", "sudden", "recurring", "mixed"
537    #[serde(default = "default_drift_type")]
538    pub drift_type: DriftType,
539}
540
541fn default_amount_drift() -> f64 {
542    0.02
543}
544
545fn default_concept_drift() -> f64 {
546    0.01
547}
548
549fn default_sudden_drift_magnitude() -> f64 {
550    2.0
551}
552
553fn default_drift_type() -> DriftType {
554    DriftType::Gradual
555}
556
557impl Default for TemporalDriftConfig {
558    fn default() -> Self {
559        Self {
560            enabled: false,
561            amount_mean_drift: 0.02,
562            amount_variance_drift: 0.0,
563            anomaly_rate_drift: 0.0,
564            concept_drift_rate: 0.01,
565            sudden_drift_probability: 0.0,
566            sudden_drift_magnitude: 2.0,
567            seasonal_drift: false,
568            drift_start_period: 0,
569            drift_type: DriftType::Gradual,
570        }
571    }
572}
573
574impl TemporalDriftConfig {
575    /// Convert to core DriftConfig for use in generators.
576    pub fn to_core_config(&self) -> datasynth_core::distributions::DriftConfig {
577        datasynth_core::distributions::DriftConfig {
578            enabled: self.enabled,
579            amount_mean_drift: self.amount_mean_drift,
580            amount_variance_drift: self.amount_variance_drift,
581            anomaly_rate_drift: self.anomaly_rate_drift,
582            concept_drift_rate: self.concept_drift_rate,
583            sudden_drift_probability: self.sudden_drift_probability,
584            sudden_drift_magnitude: self.sudden_drift_magnitude,
585            seasonal_drift: self.seasonal_drift,
586            drift_start_period: self.drift_start_period,
587            drift_type: match self.drift_type {
588                DriftType::Gradual => datasynth_core::distributions::DriftType::Gradual,
589                DriftType::Sudden => datasynth_core::distributions::DriftType::Sudden,
590                DriftType::Recurring => datasynth_core::distributions::DriftType::Recurring,
591                DriftType::Mixed => datasynth_core::distributions::DriftType::Mixed,
592            },
593            regime_changes: Vec::new(),
594            economic_cycle: Default::default(),
595            parameter_drifts: Vec::new(),
596        }
597    }
598}
599
600/// Types of temporal drift patterns.
601#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
602#[serde(rename_all = "snake_case")]
603pub enum DriftType {
604    /// Gradual, continuous drift over time (like inflation).
605    #[default]
606    Gradual,
607    /// Sudden, point-in-time shifts (like policy changes).
608    Sudden,
609    /// Recurring patterns that cycle (like seasonal variations).
610    Recurring,
611    /// Combination of gradual background drift with occasional sudden shifts.
612    Mixed,
613}
614
615// ============================================================================
616// Streaming Output API Configuration (Phase 2)
617// ============================================================================
618
619/// Configuration for streaming output API.
620#[derive(Debug, Clone, Serialize, Deserialize)]
621pub struct StreamingSchemaConfig {
622    /// Enable streaming output.
623    #[serde(default)]
624    pub enabled: bool,
625    /// Buffer size for streaming (number of items).
626    #[serde(default = "default_buffer_size")]
627    pub buffer_size: usize,
628    /// Enable progress reporting.
629    #[serde(default = "default_true")]
630    pub enable_progress: bool,
631    /// Progress reporting interval (number of items).
632    #[serde(default = "default_progress_interval")]
633    pub progress_interval: u64,
634    /// Backpressure strategy.
635    #[serde(default)]
636    pub backpressure: BackpressureSchemaStrategy,
637}
638
639fn default_buffer_size() -> usize {
640    1000
641}
642
643fn default_progress_interval() -> u64 {
644    100
645}
646
647impl Default for StreamingSchemaConfig {
648    fn default() -> Self {
649        Self {
650            enabled: false,
651            buffer_size: 1000,
652            enable_progress: true,
653            progress_interval: 100,
654            backpressure: BackpressureSchemaStrategy::Block,
655        }
656    }
657}
658
659/// Backpressure strategy for streaming output.
660#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
661#[serde(rename_all = "snake_case")]
662pub enum BackpressureSchemaStrategy {
663    /// Block until space is available in the buffer.
664    #[default]
665    Block,
666    /// Drop oldest items when buffer is full.
667    DropOldest,
668    /// Drop newest items when buffer is full.
669    DropNewest,
670    /// Buffer overflow items up to a limit, then block.
671    Buffer,
672}
673
674// ============================================================================
675// Rate Limiting Configuration (Phase 5)
676// ============================================================================
677
678/// Configuration for rate limiting.
679#[derive(Debug, Clone, Serialize, Deserialize)]
680pub struct RateLimitSchemaConfig {
681    /// Enable rate limiting.
682    #[serde(default)]
683    pub enabled: bool,
684    /// Entities per second limit.
685    #[serde(default = "default_entities_per_second")]
686    pub entities_per_second: f64,
687    /// Burst size (number of tokens in bucket).
688    #[serde(default = "default_burst_size")]
689    pub burst_size: u32,
690    /// Backpressure strategy for rate limiting.
691    #[serde(default)]
692    pub backpressure: RateLimitBackpressureSchema,
693}
694
695fn default_entities_per_second() -> f64 {
696    1000.0
697}
698
699fn default_burst_size() -> u32 {
700    100
701}
702
703impl Default for RateLimitSchemaConfig {
704    fn default() -> Self {
705        Self {
706            enabled: false,
707            entities_per_second: 1000.0,
708            burst_size: 100,
709            backpressure: RateLimitBackpressureSchema::Block,
710        }
711    }
712}
713
714/// Backpressure strategy for rate limiting.
715#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
716#[serde(rename_all = "snake_case")]
717pub enum RateLimitBackpressureSchema {
718    /// Block until rate allows.
719    #[default]
720    Block,
721    /// Drop items that exceed rate.
722    Drop,
723    /// Buffer items and process when rate allows.
724    Buffer,
725}
726
727// ============================================================================
728// Temporal Attribute Generation Configuration (Phase 3)
729// ============================================================================
730
731/// Configuration for temporal attribute generation.
732#[derive(Debug, Clone, Serialize, Deserialize)]
733pub struct TemporalAttributeSchemaConfig {
734    /// Enable temporal attribute generation.
735    #[serde(default)]
736    pub enabled: bool,
737    /// Valid time configuration.
738    #[serde(default)]
739    pub valid_time: ValidTimeSchemaConfig,
740    /// Transaction time configuration.
741    #[serde(default)]
742    pub transaction_time: TransactionTimeSchemaConfig,
743    /// Generate version chains for entities.
744    #[serde(default)]
745    pub generate_version_chains: bool,
746    /// Average number of versions per entity.
747    #[serde(default = "default_avg_versions")]
748    pub avg_versions_per_entity: f64,
749}
750
751fn default_avg_versions() -> f64 {
752    1.5
753}
754
755impl Default for TemporalAttributeSchemaConfig {
756    fn default() -> Self {
757        Self {
758            enabled: false,
759            valid_time: ValidTimeSchemaConfig::default(),
760            transaction_time: TransactionTimeSchemaConfig::default(),
761            generate_version_chains: false,
762            avg_versions_per_entity: 1.5,
763        }
764    }
765}
766
767/// Configuration for valid time (business time) generation.
768#[derive(Debug, Clone, Serialize, Deserialize)]
769pub struct ValidTimeSchemaConfig {
770    /// Probability that valid_to is set (entity has ended validity).
771    #[serde(default = "default_closed_probability")]
772    pub closed_probability: f64,
773    /// Average validity duration in days.
774    #[serde(default = "default_avg_validity_days")]
775    pub avg_validity_days: u32,
776    /// Standard deviation of validity duration in days.
777    #[serde(default = "default_validity_stddev")]
778    pub validity_stddev_days: u32,
779}
780
781fn default_closed_probability() -> f64 {
782    0.1
783}
784
785fn default_avg_validity_days() -> u32 {
786    365
787}
788
789fn default_validity_stddev() -> u32 {
790    90
791}
792
793impl Default for ValidTimeSchemaConfig {
794    fn default() -> Self {
795        Self {
796            closed_probability: 0.1,
797            avg_validity_days: 365,
798            validity_stddev_days: 90,
799        }
800    }
801}
802
803/// Configuration for transaction time (system time) generation.
804#[derive(Debug, Clone, Serialize, Deserialize)]
805pub struct TransactionTimeSchemaConfig {
806    /// Average recording delay in seconds (0 = immediate).
807    #[serde(default)]
808    pub avg_recording_delay_seconds: u32,
809    /// Allow backdating (recording time before valid time).
810    #[serde(default)]
811    pub allow_backdating: bool,
812    /// Probability of backdating if allowed.
813    #[serde(default = "default_backdating_probability")]
814    pub backdating_probability: f64,
815    /// Maximum backdate days.
816    #[serde(default = "default_max_backdate_days")]
817    pub max_backdate_days: u32,
818}
819
820fn default_backdating_probability() -> f64 {
821    0.01
822}
823
824fn default_max_backdate_days() -> u32 {
825    30
826}
827
828impl Default for TransactionTimeSchemaConfig {
829    fn default() -> Self {
830        Self {
831            avg_recording_delay_seconds: 0,
832            allow_backdating: false,
833            backdating_probability: 0.01,
834            max_backdate_days: 30,
835        }
836    }
837}
838
839// ============================================================================
840// Relationship Generation Configuration (Phase 4)
841// ============================================================================
842
843/// Configuration for relationship generation.
844#[derive(Debug, Clone, Serialize, Deserialize)]
845pub struct RelationshipSchemaConfig {
846    /// Relationship type definitions.
847    #[serde(default)]
848    pub relationship_types: Vec<RelationshipTypeSchemaConfig>,
849    /// Allow orphan entities (entities with no relationships).
850    #[serde(default = "default_true")]
851    pub allow_orphans: bool,
852    /// Probability of creating an orphan entity.
853    #[serde(default = "default_orphan_probability")]
854    pub orphan_probability: f64,
855    /// Allow circular relationships.
856    #[serde(default)]
857    pub allow_circular: bool,
858    /// Maximum depth for circular relationship detection.
859    #[serde(default = "default_max_circular_depth")]
860    pub max_circular_depth: u32,
861}
862
863fn default_orphan_probability() -> f64 {
864    0.01
865}
866
867fn default_max_circular_depth() -> u32 {
868    3
869}
870
871impl Default for RelationshipSchemaConfig {
872    fn default() -> Self {
873        Self {
874            relationship_types: Vec::new(),
875            allow_orphans: true,
876            orphan_probability: 0.01,
877            allow_circular: false,
878            max_circular_depth: 3,
879        }
880    }
881}
882
883/// Configuration for a specific relationship type.
884#[derive(Debug, Clone, Serialize, Deserialize)]
885pub struct RelationshipTypeSchemaConfig {
886    /// Name of the relationship type (e.g., "debits", "credits", "created").
887    pub name: String,
888    /// Source entity type (e.g., "journal_entry").
889    pub source_type: String,
890    /// Target entity type (e.g., "account").
891    pub target_type: String,
892    /// Cardinality rule for this relationship.
893    #[serde(default)]
894    pub cardinality: CardinalitySchemaRule,
895    /// Weight for this relationship in random selection.
896    #[serde(default = "default_relationship_weight")]
897    pub weight: f64,
898    /// Whether this relationship is required.
899    #[serde(default)]
900    pub required: bool,
901    /// Whether this relationship is directed.
902    #[serde(default = "default_true")]
903    pub directed: bool,
904}
905
906fn default_relationship_weight() -> f64 {
907    1.0
908}
909
910impl Default for RelationshipTypeSchemaConfig {
911    fn default() -> Self {
912        Self {
913            name: String::new(),
914            source_type: String::new(),
915            target_type: String::new(),
916            cardinality: CardinalitySchemaRule::default(),
917            weight: 1.0,
918            required: false,
919            directed: true,
920        }
921    }
922}
923
924/// Cardinality rule for relationships in schema config.
925#[derive(Debug, Clone, Serialize, Deserialize)]
926#[serde(rename_all = "snake_case")]
927pub enum CardinalitySchemaRule {
928    /// One source to one target.
929    OneToOne,
930    /// One source to many targets.
931    OneToMany {
932        /// Minimum number of targets.
933        min: u32,
934        /// Maximum number of targets.
935        max: u32,
936    },
937    /// Many sources to one target.
938    ManyToOne {
939        /// Minimum number of sources.
940        min: u32,
941        /// Maximum number of sources.
942        max: u32,
943    },
944    /// Many sources to many targets.
945    ManyToMany {
946        /// Minimum targets per source.
947        min_per_source: u32,
948        /// Maximum targets per source.
949        max_per_source: u32,
950    },
951}
952
953impl Default for CardinalitySchemaRule {
954    fn default() -> Self {
955        Self::OneToMany { min: 1, max: 5 }
956    }
957}
958
959/// Global configuration settings.
960#[derive(Debug, Clone, Serialize, Deserialize)]
961pub struct GlobalConfig {
962    /// Random seed for reproducibility
963    pub seed: Option<u64>,
964    /// Industry sector
965    pub industry: IndustrySector,
966    /// Simulation start date (YYYY-MM-DD)
967    pub start_date: String,
968    /// Simulation period in months
969    pub period_months: u32,
970    /// Base currency for group reporting
971    #[serde(default = "default_currency")]
972    pub group_currency: String,
973    /// Enable parallel generation
974    #[serde(default = "default_true")]
975    pub parallel: bool,
976    /// Number of worker threads (0 = auto-detect)
977    #[serde(default)]
978    pub worker_threads: usize,
979    /// Memory limit in MB (0 = unlimited)
980    #[serde(default)]
981    pub memory_limit_mb: usize,
982}
983
984fn default_currency() -> String {
985    "USD".to_string()
986}
987fn default_true() -> bool {
988    true
989}
990
991/// Company code configuration.
992#[derive(Debug, Clone, Serialize, Deserialize)]
993pub struct CompanyConfig {
994    /// Company code identifier
995    pub code: String,
996    /// Company name
997    pub name: String,
998    /// Local currency (ISO 4217)
999    pub currency: String,
1000    /// Country code (ISO 3166-1 alpha-2)
1001    pub country: String,
1002    /// Fiscal year variant
1003    #[serde(default = "default_fiscal_variant")]
1004    pub fiscal_year_variant: String,
1005    /// Transaction volume per year
1006    pub annual_transaction_volume: TransactionVolume,
1007    /// Company-specific transaction weight
1008    #[serde(default = "default_weight")]
1009    pub volume_weight: f64,
1010}
1011
1012fn default_fiscal_variant() -> String {
1013    "K4".to_string()
1014}
1015fn default_weight() -> f64 {
1016    1.0
1017}
1018
1019/// Transaction volume presets.
1020#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1021#[serde(rename_all = "snake_case")]
1022pub enum TransactionVolume {
1023    /// 10,000 transactions per year
1024    TenK,
1025    /// 100,000 transactions per year
1026    HundredK,
1027    /// 1,000,000 transactions per year
1028    OneM,
1029    /// 10,000,000 transactions per year
1030    TenM,
1031    /// 100,000,000 transactions per year
1032    HundredM,
1033    /// Custom count
1034    Custom(u64),
1035}
1036
1037impl TransactionVolume {
1038    /// Get the transaction count.
1039    pub fn count(&self) -> u64 {
1040        match self {
1041            Self::TenK => 10_000,
1042            Self::HundredK => 100_000,
1043            Self::OneM => 1_000_000,
1044            Self::TenM => 10_000_000,
1045            Self::HundredM => 100_000_000,
1046            Self::Custom(n) => *n,
1047        }
1048    }
1049}
1050
1051/// Chart of Accounts configuration.
1052#[derive(Debug, Clone, Serialize, Deserialize)]
1053pub struct ChartOfAccountsConfig {
1054    /// CoA complexity level
1055    pub complexity: CoAComplexity,
1056    /// Use industry-specific accounts
1057    #[serde(default = "default_true")]
1058    pub industry_specific: bool,
1059    /// Custom account definitions file
1060    pub custom_accounts: Option<PathBuf>,
1061    /// Minimum hierarchy depth
1062    #[serde(default = "default_min_depth")]
1063    pub min_hierarchy_depth: u8,
1064    /// Maximum hierarchy depth
1065    #[serde(default = "default_max_depth")]
1066    pub max_hierarchy_depth: u8,
1067}
1068
1069fn default_min_depth() -> u8 {
1070    2
1071}
1072fn default_max_depth() -> u8 {
1073    5
1074}
1075
1076impl Default for ChartOfAccountsConfig {
1077    fn default() -> Self {
1078        Self {
1079            complexity: CoAComplexity::Small,
1080            industry_specific: true,
1081            custom_accounts: None,
1082            min_hierarchy_depth: default_min_depth(),
1083            max_hierarchy_depth: default_max_depth(),
1084        }
1085    }
1086}
1087
1088/// Transaction generation configuration.
1089#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1090pub struct TransactionConfig {
1091    /// Line item distribution
1092    #[serde(default)]
1093    pub line_item_distribution: LineItemDistributionConfig,
1094    /// Debit/credit balance distribution
1095    #[serde(default)]
1096    pub debit_credit_distribution: DebitCreditDistributionConfig,
1097    /// Even/odd line count distribution
1098    #[serde(default)]
1099    pub even_odd_distribution: EvenOddDistributionConfig,
1100    /// Transaction source distribution
1101    #[serde(default)]
1102    pub source_distribution: SourceDistribution,
1103    /// Seasonality configuration
1104    #[serde(default)]
1105    pub seasonality: SeasonalityConfig,
1106    /// Amount distribution
1107    #[serde(default)]
1108    pub amounts: AmountDistributionConfig,
1109    /// Benford's Law compliance configuration
1110    #[serde(default)]
1111    pub benford: BenfordConfig,
1112}
1113
1114/// Benford's Law compliance configuration.
1115#[derive(Debug, Clone, Serialize, Deserialize)]
1116pub struct BenfordConfig {
1117    /// Enable Benford's Law compliance for amount generation
1118    #[serde(default = "default_true")]
1119    pub enabled: bool,
1120    /// Tolerance for deviation from ideal Benford distribution (0.0-1.0)
1121    #[serde(default = "default_benford_tolerance")]
1122    pub tolerance: f64,
1123    /// Transaction sources exempt from Benford's Law (fixed amounts)
1124    #[serde(default)]
1125    pub exempt_sources: Vec<BenfordExemption>,
1126}
1127
1128fn default_benford_tolerance() -> f64 {
1129    0.05
1130}
1131
1132impl Default for BenfordConfig {
1133    fn default() -> Self {
1134        Self {
1135            enabled: true,
1136            tolerance: default_benford_tolerance(),
1137            exempt_sources: vec![BenfordExemption::Recurring, BenfordExemption::Payroll],
1138        }
1139    }
1140}
1141
1142/// Types of transactions exempt from Benford's Law.
1143#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1144#[serde(rename_all = "snake_case")]
1145pub enum BenfordExemption {
1146    /// Recurring fixed amounts (rent, subscriptions)
1147    Recurring,
1148    /// Payroll (standardized salaries)
1149    Payroll,
1150    /// Fixed fees and charges
1151    FixedFees,
1152    /// Round number purchases (often legitimate)
1153    RoundAmounts,
1154}
1155
1156/// Distribution of transaction sources.
1157#[derive(Debug, Clone, Serialize, Deserialize)]
1158pub struct SourceDistribution {
1159    /// Manual entries percentage
1160    pub manual: f64,
1161    /// Automated system entries
1162    pub automated: f64,
1163    /// Recurring entries
1164    pub recurring: f64,
1165    /// Adjustment entries
1166    pub adjustment: f64,
1167}
1168
1169impl Default for SourceDistribution {
1170    fn default() -> Self {
1171        Self {
1172            manual: 0.20,
1173            automated: 0.70,
1174            recurring: 0.07,
1175            adjustment: 0.03,
1176        }
1177    }
1178}
1179
1180/// Output configuration.
1181#[derive(Debug, Clone, Serialize, Deserialize)]
1182pub struct OutputConfig {
1183    /// Output mode
1184    #[serde(default)]
1185    pub mode: OutputMode,
1186    /// Output directory
1187    pub output_directory: PathBuf,
1188    /// File formats to generate
1189    #[serde(default = "default_formats")]
1190    pub formats: Vec<FileFormat>,
1191    /// Compression settings
1192    #[serde(default)]
1193    pub compression: CompressionConfig,
1194    /// Batch size for writes
1195    #[serde(default = "default_batch_size")]
1196    pub batch_size: usize,
1197    /// Include ACDOCA format
1198    #[serde(default = "default_true")]
1199    pub include_acdoca: bool,
1200    /// Include BSEG format
1201    #[serde(default)]
1202    pub include_bseg: bool,
1203    /// Partition by fiscal period
1204    #[serde(default = "default_true")]
1205    pub partition_by_period: bool,
1206    /// Partition by company code
1207    #[serde(default)]
1208    pub partition_by_company: bool,
1209}
1210
1211fn default_formats() -> Vec<FileFormat> {
1212    vec![FileFormat::Parquet]
1213}
1214fn default_batch_size() -> usize {
1215    100_000
1216}
1217
1218impl Default for OutputConfig {
1219    fn default() -> Self {
1220        Self {
1221            mode: OutputMode::FlatFile,
1222            output_directory: PathBuf::from("./output"),
1223            formats: default_formats(),
1224            compression: CompressionConfig::default(),
1225            batch_size: default_batch_size(),
1226            include_acdoca: true,
1227            include_bseg: false,
1228            partition_by_period: true,
1229            partition_by_company: false,
1230        }
1231    }
1232}
1233
1234/// Output mode.
1235#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
1236#[serde(rename_all = "snake_case")]
1237pub enum OutputMode {
1238    /// Stream records as generated
1239    Streaming,
1240    /// Write to flat files
1241    #[default]
1242    FlatFile,
1243    /// Both streaming and flat file
1244    Both,
1245}
1246
1247/// Supported file formats.
1248#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1249#[serde(rename_all = "snake_case")]
1250pub enum FileFormat {
1251    Csv,
1252    Parquet,
1253    Json,
1254    JsonLines,
1255}
1256
1257/// Compression configuration.
1258#[derive(Debug, Clone, Serialize, Deserialize)]
1259pub struct CompressionConfig {
1260    /// Enable compression
1261    #[serde(default = "default_true")]
1262    pub enabled: bool,
1263    /// Compression algorithm
1264    #[serde(default)]
1265    pub algorithm: CompressionAlgorithm,
1266    /// Compression level (1-9)
1267    #[serde(default = "default_compression_level")]
1268    pub level: u8,
1269}
1270
1271fn default_compression_level() -> u8 {
1272    3
1273}
1274
1275impl Default for CompressionConfig {
1276    fn default() -> Self {
1277        Self {
1278            enabled: true,
1279            algorithm: CompressionAlgorithm::default(),
1280            level: default_compression_level(),
1281        }
1282    }
1283}
1284
1285/// Compression algorithms.
1286#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
1287#[serde(rename_all = "snake_case")]
1288pub enum CompressionAlgorithm {
1289    Gzip,
1290    #[default]
1291    Zstd,
1292    Lz4,
1293    Snappy,
1294}
1295
1296/// Fraud simulation configuration.
1297#[derive(Debug, Clone, Serialize, Deserialize)]
1298pub struct FraudConfig {
1299    /// Enable fraud scenario generation
1300    #[serde(default)]
1301    pub enabled: bool,
1302    /// Overall fraud rate (0.0 to 1.0)
1303    #[serde(default = "default_fraud_rate")]
1304    pub fraud_rate: f64,
1305    /// Fraud type distribution
1306    #[serde(default)]
1307    pub fraud_type_distribution: FraudTypeDistribution,
1308    /// Enable fraud clustering
1309    #[serde(default)]
1310    pub clustering_enabled: bool,
1311    /// Clustering factor
1312    #[serde(default = "default_clustering_factor")]
1313    pub clustering_factor: f64,
1314    /// Approval thresholds for threshold-adjacent fraud pattern
1315    #[serde(default = "default_approval_thresholds")]
1316    pub approval_thresholds: Vec<f64>,
1317}
1318
1319fn default_approval_thresholds() -> Vec<f64> {
1320    vec![1000.0, 5000.0, 10000.0, 25000.0, 50000.0, 100000.0]
1321}
1322
1323fn default_fraud_rate() -> f64 {
1324    0.005
1325}
1326fn default_clustering_factor() -> f64 {
1327    3.0
1328}
1329
1330impl Default for FraudConfig {
1331    fn default() -> Self {
1332        Self {
1333            enabled: false,
1334            fraud_rate: default_fraud_rate(),
1335            fraud_type_distribution: FraudTypeDistribution::default(),
1336            clustering_enabled: false,
1337            clustering_factor: default_clustering_factor(),
1338            approval_thresholds: default_approval_thresholds(),
1339        }
1340    }
1341}
1342
1343/// Distribution of fraud types.
1344#[derive(Debug, Clone, Serialize, Deserialize)]
1345pub struct FraudTypeDistribution {
1346    pub suspense_account_abuse: f64,
1347    pub fictitious_transaction: f64,
1348    pub revenue_manipulation: f64,
1349    pub expense_capitalization: f64,
1350    pub split_transaction: f64,
1351    pub timing_anomaly: f64,
1352    pub unauthorized_access: f64,
1353    pub duplicate_payment: f64,
1354}
1355
1356impl Default for FraudTypeDistribution {
1357    fn default() -> Self {
1358        Self {
1359            suspense_account_abuse: 0.25,
1360            fictitious_transaction: 0.15,
1361            revenue_manipulation: 0.10,
1362            expense_capitalization: 0.10,
1363            split_transaction: 0.15,
1364            timing_anomaly: 0.10,
1365            unauthorized_access: 0.10,
1366            duplicate_payment: 0.05,
1367        }
1368    }
1369}
1370
1371/// Internal Controls System (ICS) configuration.
1372#[derive(Debug, Clone, Serialize, Deserialize)]
1373pub struct InternalControlsConfig {
1374    /// Enable internal controls system
1375    #[serde(default)]
1376    pub enabled: bool,
1377    /// Rate at which controls result in exceptions (0.0 - 1.0)
1378    #[serde(default = "default_exception_rate")]
1379    pub exception_rate: f64,
1380    /// Rate at which SoD violations occur (0.0 - 1.0)
1381    #[serde(default = "default_sod_violation_rate")]
1382    pub sod_violation_rate: f64,
1383    /// Export control master data to separate files
1384    #[serde(default = "default_true")]
1385    pub export_control_master_data: bool,
1386    /// SOX materiality threshold for marking transactions as SOX-relevant
1387    #[serde(default = "default_sox_materiality_threshold")]
1388    pub sox_materiality_threshold: f64,
1389    /// Enable COSO 2013 framework integration
1390    #[serde(default = "default_true")]
1391    pub coso_enabled: bool,
1392    /// Include entity-level controls in generation
1393    #[serde(default)]
1394    pub include_entity_level_controls: bool,
1395    /// Target maturity level for controls
1396    /// Valid values: "ad_hoc", "repeatable", "defined", "managed", "optimized", "mixed"
1397    #[serde(default = "default_target_maturity_level")]
1398    pub target_maturity_level: String,
1399}
1400
1401fn default_exception_rate() -> f64 {
1402    0.02
1403}
1404
1405fn default_sod_violation_rate() -> f64 {
1406    0.01
1407}
1408
1409fn default_sox_materiality_threshold() -> f64 {
1410    10000.0
1411}
1412
1413fn default_target_maturity_level() -> String {
1414    "mixed".to_string()
1415}
1416
1417impl Default for InternalControlsConfig {
1418    fn default() -> Self {
1419        Self {
1420            enabled: false,
1421            exception_rate: default_exception_rate(),
1422            sod_violation_rate: default_sod_violation_rate(),
1423            export_control_master_data: true,
1424            sox_materiality_threshold: default_sox_materiality_threshold(),
1425            coso_enabled: true,
1426            include_entity_level_controls: false,
1427            target_maturity_level: default_target_maturity_level(),
1428        }
1429    }
1430}
1431
1432/// Business process configuration.
1433#[derive(Debug, Clone, Serialize, Deserialize)]
1434pub struct BusinessProcessConfig {
1435    /// Order-to-Cash weight
1436    #[serde(default = "default_o2c")]
1437    pub o2c_weight: f64,
1438    /// Procure-to-Pay weight
1439    #[serde(default = "default_p2p")]
1440    pub p2p_weight: f64,
1441    /// Record-to-Report weight
1442    #[serde(default = "default_r2r")]
1443    pub r2r_weight: f64,
1444    /// Hire-to-Retire weight
1445    #[serde(default = "default_h2r")]
1446    pub h2r_weight: f64,
1447    /// Acquire-to-Retire weight
1448    #[serde(default = "default_a2r")]
1449    pub a2r_weight: f64,
1450}
1451
1452fn default_o2c() -> f64 {
1453    0.35
1454}
1455fn default_p2p() -> f64 {
1456    0.30
1457}
1458fn default_r2r() -> f64 {
1459    0.20
1460}
1461fn default_h2r() -> f64 {
1462    0.10
1463}
1464fn default_a2r() -> f64 {
1465    0.05
1466}
1467
1468impl Default for BusinessProcessConfig {
1469    fn default() -> Self {
1470        Self {
1471            o2c_weight: default_o2c(),
1472            p2p_weight: default_p2p(),
1473            r2r_weight: default_r2r(),
1474            h2r_weight: default_h2r(),
1475            a2r_weight: default_a2r(),
1476        }
1477    }
1478}
1479
1480/// User persona configuration.
1481#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1482pub struct UserPersonaConfig {
1483    /// Distribution of user personas
1484    #[serde(default)]
1485    pub persona_distribution: PersonaDistribution,
1486    /// Users per persona type
1487    #[serde(default)]
1488    pub users_per_persona: UsersPerPersona,
1489}
1490
1491/// Distribution of user personas for transaction generation.
1492#[derive(Debug, Clone, Serialize, Deserialize)]
1493pub struct PersonaDistribution {
1494    pub junior_accountant: f64,
1495    pub senior_accountant: f64,
1496    pub controller: f64,
1497    pub manager: f64,
1498    pub automated_system: f64,
1499}
1500
1501impl Default for PersonaDistribution {
1502    fn default() -> Self {
1503        Self {
1504            junior_accountant: 0.15,
1505            senior_accountant: 0.15,
1506            controller: 0.05,
1507            manager: 0.05,
1508            automated_system: 0.60,
1509        }
1510    }
1511}
1512
1513/// Number of users per persona type.
1514#[derive(Debug, Clone, Serialize, Deserialize)]
1515pub struct UsersPerPersona {
1516    pub junior_accountant: usize,
1517    pub senior_accountant: usize,
1518    pub controller: usize,
1519    pub manager: usize,
1520    pub automated_system: usize,
1521}
1522
1523impl Default for UsersPerPersona {
1524    fn default() -> Self {
1525        Self {
1526            junior_accountant: 10,
1527            senior_accountant: 5,
1528            controller: 2,
1529            manager: 3,
1530            automated_system: 20,
1531        }
1532    }
1533}
1534
1535/// Template configuration for realistic data generation.
1536#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1537pub struct TemplateConfig {
1538    /// Name generation settings
1539    #[serde(default)]
1540    pub names: NameTemplateConfig,
1541    /// Description generation settings
1542    #[serde(default)]
1543    pub descriptions: DescriptionTemplateConfig,
1544    /// Reference number settings
1545    #[serde(default)]
1546    pub references: ReferenceTemplateConfig,
1547}
1548
1549/// Name template configuration.
1550#[derive(Debug, Clone, Serialize, Deserialize)]
1551pub struct NameTemplateConfig {
1552    /// Distribution of name cultures
1553    #[serde(default)]
1554    pub culture_distribution: CultureDistribution,
1555    /// Email domain for generated users
1556    #[serde(default = "default_email_domain")]
1557    pub email_domain: String,
1558    /// Generate realistic display names
1559    #[serde(default = "default_true")]
1560    pub generate_realistic_names: bool,
1561}
1562
1563fn default_email_domain() -> String {
1564    "company.com".to_string()
1565}
1566
1567impl Default for NameTemplateConfig {
1568    fn default() -> Self {
1569        Self {
1570            culture_distribution: CultureDistribution::default(),
1571            email_domain: default_email_domain(),
1572            generate_realistic_names: true,
1573        }
1574    }
1575}
1576
1577/// Distribution of name cultures for generation.
1578#[derive(Debug, Clone, Serialize, Deserialize)]
1579pub struct CultureDistribution {
1580    pub western_us: f64,
1581    pub hispanic: f64,
1582    pub german: f64,
1583    pub french: f64,
1584    pub chinese: f64,
1585    pub japanese: f64,
1586    pub indian: f64,
1587}
1588
1589impl Default for CultureDistribution {
1590    fn default() -> Self {
1591        Self {
1592            western_us: 0.40,
1593            hispanic: 0.20,
1594            german: 0.10,
1595            french: 0.05,
1596            chinese: 0.10,
1597            japanese: 0.05,
1598            indian: 0.10,
1599        }
1600    }
1601}
1602
1603/// Description template configuration.
1604#[derive(Debug, Clone, Serialize, Deserialize)]
1605pub struct DescriptionTemplateConfig {
1606    /// Generate header text for journal entries
1607    #[serde(default = "default_true")]
1608    pub generate_header_text: bool,
1609    /// Generate line text for journal entry lines
1610    #[serde(default = "default_true")]
1611    pub generate_line_text: bool,
1612}
1613
1614impl Default for DescriptionTemplateConfig {
1615    fn default() -> Self {
1616        Self {
1617            generate_header_text: true,
1618            generate_line_text: true,
1619        }
1620    }
1621}
1622
1623/// Reference number template configuration.
1624#[derive(Debug, Clone, Serialize, Deserialize)]
1625pub struct ReferenceTemplateConfig {
1626    /// Generate reference numbers
1627    #[serde(default = "default_true")]
1628    pub generate_references: bool,
1629    /// Invoice prefix
1630    #[serde(default = "default_invoice_prefix")]
1631    pub invoice_prefix: String,
1632    /// Purchase order prefix
1633    #[serde(default = "default_po_prefix")]
1634    pub po_prefix: String,
1635    /// Sales order prefix
1636    #[serde(default = "default_so_prefix")]
1637    pub so_prefix: String,
1638}
1639
1640fn default_invoice_prefix() -> String {
1641    "INV".to_string()
1642}
1643fn default_po_prefix() -> String {
1644    "PO".to_string()
1645}
1646fn default_so_prefix() -> String {
1647    "SO".to_string()
1648}
1649
1650impl Default for ReferenceTemplateConfig {
1651    fn default() -> Self {
1652        Self {
1653            generate_references: true,
1654            invoice_prefix: default_invoice_prefix(),
1655            po_prefix: default_po_prefix(),
1656            so_prefix: default_so_prefix(),
1657        }
1658    }
1659}
1660
1661/// Approval workflow configuration.
1662#[derive(Debug, Clone, Serialize, Deserialize)]
1663pub struct ApprovalConfig {
1664    /// Enable approval workflow generation
1665    #[serde(default)]
1666    pub enabled: bool,
1667    /// Threshold below which transactions are auto-approved
1668    #[serde(default = "default_auto_approve_threshold")]
1669    pub auto_approve_threshold: f64,
1670    /// Rate at which approvals are rejected (0.0 to 1.0)
1671    #[serde(default = "default_rejection_rate")]
1672    pub rejection_rate: f64,
1673    /// Rate at which approvals require revision (0.0 to 1.0)
1674    #[serde(default = "default_revision_rate")]
1675    pub revision_rate: f64,
1676    /// Average delay in hours for approval processing
1677    #[serde(default = "default_approval_delay_hours")]
1678    pub average_approval_delay_hours: f64,
1679    /// Approval chain thresholds
1680    #[serde(default)]
1681    pub thresholds: Vec<ApprovalThresholdConfig>,
1682}
1683
1684fn default_auto_approve_threshold() -> f64 {
1685    1000.0
1686}
1687fn default_rejection_rate() -> f64 {
1688    0.02
1689}
1690fn default_revision_rate() -> f64 {
1691    0.05
1692}
1693fn default_approval_delay_hours() -> f64 {
1694    4.0
1695}
1696
1697impl Default for ApprovalConfig {
1698    fn default() -> Self {
1699        Self {
1700            enabled: false,
1701            auto_approve_threshold: default_auto_approve_threshold(),
1702            rejection_rate: default_rejection_rate(),
1703            revision_rate: default_revision_rate(),
1704            average_approval_delay_hours: default_approval_delay_hours(),
1705            thresholds: vec![
1706                ApprovalThresholdConfig {
1707                    amount: 1000.0,
1708                    level: 1,
1709                    roles: vec!["senior_accountant".to_string()],
1710                },
1711                ApprovalThresholdConfig {
1712                    amount: 10000.0,
1713                    level: 2,
1714                    roles: vec!["senior_accountant".to_string(), "controller".to_string()],
1715                },
1716                ApprovalThresholdConfig {
1717                    amount: 100000.0,
1718                    level: 3,
1719                    roles: vec![
1720                        "senior_accountant".to_string(),
1721                        "controller".to_string(),
1722                        "manager".to_string(),
1723                    ],
1724                },
1725                ApprovalThresholdConfig {
1726                    amount: 500000.0,
1727                    level: 4,
1728                    roles: vec![
1729                        "senior_accountant".to_string(),
1730                        "controller".to_string(),
1731                        "manager".to_string(),
1732                        "executive".to_string(),
1733                    ],
1734                },
1735            ],
1736        }
1737    }
1738}
1739
1740/// Configuration for a single approval threshold.
1741#[derive(Debug, Clone, Serialize, Deserialize)]
1742pub struct ApprovalThresholdConfig {
1743    /// Amount threshold
1744    pub amount: f64,
1745    /// Approval level required
1746    pub level: u8,
1747    /// Roles that can approve at this level
1748    pub roles: Vec<String>,
1749}
1750
1751/// Department configuration.
1752#[derive(Debug, Clone, Serialize, Deserialize)]
1753pub struct DepartmentConfig {
1754    /// Enable department assignment
1755    #[serde(default)]
1756    pub enabled: bool,
1757    /// Multiplier for department headcounts
1758    #[serde(default = "default_headcount_multiplier")]
1759    pub headcount_multiplier: f64,
1760    /// Custom department definitions (optional)
1761    #[serde(default)]
1762    pub custom_departments: Vec<CustomDepartmentConfig>,
1763}
1764
1765fn default_headcount_multiplier() -> f64 {
1766    1.0
1767}
1768
1769impl Default for DepartmentConfig {
1770    fn default() -> Self {
1771        Self {
1772            enabled: false,
1773            headcount_multiplier: default_headcount_multiplier(),
1774            custom_departments: Vec::new(),
1775        }
1776    }
1777}
1778
1779/// Custom department definition.
1780#[derive(Debug, Clone, Serialize, Deserialize)]
1781pub struct CustomDepartmentConfig {
1782    /// Department code
1783    pub code: String,
1784    /// Department name
1785    pub name: String,
1786    /// Associated cost center
1787    #[serde(default)]
1788    pub cost_center: Option<String>,
1789    /// Primary business processes
1790    #[serde(default)]
1791    pub primary_processes: Vec<String>,
1792    /// Parent department code
1793    #[serde(default)]
1794    pub parent_code: Option<String>,
1795}
1796
1797// ============================================================================
1798// Master Data Configuration
1799// ============================================================================
1800
1801/// Master data generation configuration.
1802#[derive(Debug, Clone, Default, Serialize, Deserialize)]
1803pub struct MasterDataConfig {
1804    /// Vendor master data settings
1805    #[serde(default)]
1806    pub vendors: VendorMasterConfig,
1807    /// Customer master data settings
1808    #[serde(default)]
1809    pub customers: CustomerMasterConfig,
1810    /// Material master data settings
1811    #[serde(default)]
1812    pub materials: MaterialMasterConfig,
1813    /// Fixed asset master data settings
1814    #[serde(default)]
1815    pub fixed_assets: FixedAssetMasterConfig,
1816    /// Employee master data settings
1817    #[serde(default)]
1818    pub employees: EmployeeMasterConfig,
1819    /// Cost center master data settings
1820    #[serde(default)]
1821    pub cost_centers: CostCenterMasterConfig,
1822}
1823
1824/// Vendor master data configuration.
1825#[derive(Debug, Clone, Serialize, Deserialize)]
1826pub struct VendorMasterConfig {
1827    /// Number of vendors to generate
1828    #[serde(default = "default_vendor_count")]
1829    pub count: usize,
1830    /// Percentage of vendors that are intercompany (0.0 to 1.0)
1831    #[serde(default = "default_intercompany_percent")]
1832    pub intercompany_percent: f64,
1833    /// Payment terms distribution
1834    #[serde(default)]
1835    pub payment_terms_distribution: PaymentTermsDistribution,
1836    /// Vendor behavior distribution
1837    #[serde(default)]
1838    pub behavior_distribution: VendorBehaviorDistribution,
1839    /// Generate bank account details
1840    #[serde(default = "default_true")]
1841    pub generate_bank_accounts: bool,
1842    /// Generate tax IDs
1843    #[serde(default = "default_true")]
1844    pub generate_tax_ids: bool,
1845}
1846
1847fn default_vendor_count() -> usize {
1848    500
1849}
1850
1851fn default_intercompany_percent() -> f64 {
1852    0.05
1853}
1854
1855impl Default for VendorMasterConfig {
1856    fn default() -> Self {
1857        Self {
1858            count: default_vendor_count(),
1859            intercompany_percent: default_intercompany_percent(),
1860            payment_terms_distribution: PaymentTermsDistribution::default(),
1861            behavior_distribution: VendorBehaviorDistribution::default(),
1862            generate_bank_accounts: true,
1863            generate_tax_ids: true,
1864        }
1865    }
1866}
1867
1868/// Payment terms distribution for vendors.
1869#[derive(Debug, Clone, Serialize, Deserialize)]
1870pub struct PaymentTermsDistribution {
1871    /// Net 30 days
1872    pub net_30: f64,
1873    /// Net 60 days
1874    pub net_60: f64,
1875    /// Net 90 days
1876    pub net_90: f64,
1877    /// 2% 10 Net 30 (early payment discount)
1878    pub two_ten_net_30: f64,
1879    /// Due on receipt
1880    pub due_on_receipt: f64,
1881    /// End of month
1882    pub end_of_month: f64,
1883}
1884
1885impl Default for PaymentTermsDistribution {
1886    fn default() -> Self {
1887        Self {
1888            net_30: 0.40,
1889            net_60: 0.20,
1890            net_90: 0.10,
1891            two_ten_net_30: 0.15,
1892            due_on_receipt: 0.05,
1893            end_of_month: 0.10,
1894        }
1895    }
1896}
1897
1898/// Vendor behavior distribution.
1899#[derive(Debug, Clone, Serialize, Deserialize)]
1900pub struct VendorBehaviorDistribution {
1901    /// Reliable vendors (consistent delivery, quality)
1902    pub reliable: f64,
1903    /// Sometimes late vendors
1904    pub sometimes_late: f64,
1905    /// Inconsistent quality vendors
1906    pub inconsistent_quality: f64,
1907    /// Premium vendors (high quality, premium pricing)
1908    pub premium: f64,
1909    /// Budget vendors (lower quality, lower pricing)
1910    pub budget: f64,
1911}
1912
1913impl Default for VendorBehaviorDistribution {
1914    fn default() -> Self {
1915        Self {
1916            reliable: 0.50,
1917            sometimes_late: 0.20,
1918            inconsistent_quality: 0.10,
1919            premium: 0.10,
1920            budget: 0.10,
1921        }
1922    }
1923}
1924
1925/// Customer master data configuration.
1926#[derive(Debug, Clone, Serialize, Deserialize)]
1927pub struct CustomerMasterConfig {
1928    /// Number of customers to generate
1929    #[serde(default = "default_customer_count")]
1930    pub count: usize,
1931    /// Percentage of customers that are intercompany (0.0 to 1.0)
1932    #[serde(default = "default_intercompany_percent")]
1933    pub intercompany_percent: f64,
1934    /// Credit rating distribution
1935    #[serde(default)]
1936    pub credit_rating_distribution: CreditRatingDistribution,
1937    /// Payment behavior distribution
1938    #[serde(default)]
1939    pub payment_behavior_distribution: PaymentBehaviorDistribution,
1940    /// Generate credit limits based on rating
1941    #[serde(default = "default_true")]
1942    pub generate_credit_limits: bool,
1943}
1944
1945fn default_customer_count() -> usize {
1946    2000
1947}
1948
1949impl Default for CustomerMasterConfig {
1950    fn default() -> Self {
1951        Self {
1952            count: default_customer_count(),
1953            intercompany_percent: default_intercompany_percent(),
1954            credit_rating_distribution: CreditRatingDistribution::default(),
1955            payment_behavior_distribution: PaymentBehaviorDistribution::default(),
1956            generate_credit_limits: true,
1957        }
1958    }
1959}
1960
1961/// Credit rating distribution for customers.
1962#[derive(Debug, Clone, Serialize, Deserialize)]
1963pub struct CreditRatingDistribution {
1964    /// AAA rating
1965    pub aaa: f64,
1966    /// AA rating
1967    pub aa: f64,
1968    /// A rating
1969    pub a: f64,
1970    /// BBB rating
1971    pub bbb: f64,
1972    /// BB rating
1973    pub bb: f64,
1974    /// B rating
1975    pub b: f64,
1976    /// Below B rating
1977    pub below_b: f64,
1978}
1979
1980impl Default for CreditRatingDistribution {
1981    fn default() -> Self {
1982        Self {
1983            aaa: 0.05,
1984            aa: 0.10,
1985            a: 0.20,
1986            bbb: 0.30,
1987            bb: 0.20,
1988            b: 0.10,
1989            below_b: 0.05,
1990        }
1991    }
1992}
1993
1994/// Payment behavior distribution for customers.
1995#[derive(Debug, Clone, Serialize, Deserialize)]
1996pub struct PaymentBehaviorDistribution {
1997    /// Always pays early
1998    pub early_payer: f64,
1999    /// Pays on time
2000    pub on_time: f64,
2001    /// Occasionally late
2002    pub occasional_late: f64,
2003    /// Frequently late
2004    pub frequent_late: f64,
2005    /// Takes early payment discounts
2006    pub discount_taker: f64,
2007}
2008
2009impl Default for PaymentBehaviorDistribution {
2010    fn default() -> Self {
2011        Self {
2012            early_payer: 0.10,
2013            on_time: 0.50,
2014            occasional_late: 0.25,
2015            frequent_late: 0.10,
2016            discount_taker: 0.05,
2017        }
2018    }
2019}
2020
2021/// Material master data configuration.
2022#[derive(Debug, Clone, Serialize, Deserialize)]
2023pub struct MaterialMasterConfig {
2024    /// Number of materials to generate
2025    #[serde(default = "default_material_count")]
2026    pub count: usize,
2027    /// Material type distribution
2028    #[serde(default)]
2029    pub type_distribution: MaterialTypeDistribution,
2030    /// Valuation method distribution
2031    #[serde(default)]
2032    pub valuation_distribution: ValuationMethodDistribution,
2033    /// Percentage of materials with BOM (bill of materials)
2034    #[serde(default = "default_bom_percent")]
2035    pub bom_percent: f64,
2036    /// Maximum BOM depth
2037    #[serde(default = "default_max_bom_depth")]
2038    pub max_bom_depth: u8,
2039}
2040
2041fn default_material_count() -> usize {
2042    5000
2043}
2044
2045fn default_bom_percent() -> f64 {
2046    0.20
2047}
2048
2049fn default_max_bom_depth() -> u8 {
2050    3
2051}
2052
2053impl Default for MaterialMasterConfig {
2054    fn default() -> Self {
2055        Self {
2056            count: default_material_count(),
2057            type_distribution: MaterialTypeDistribution::default(),
2058            valuation_distribution: ValuationMethodDistribution::default(),
2059            bom_percent: default_bom_percent(),
2060            max_bom_depth: default_max_bom_depth(),
2061        }
2062    }
2063}
2064
2065/// Material type distribution.
2066#[derive(Debug, Clone, Serialize, Deserialize)]
2067pub struct MaterialTypeDistribution {
2068    /// Raw materials
2069    pub raw_material: f64,
2070    /// Semi-finished goods
2071    pub semi_finished: f64,
2072    /// Finished goods
2073    pub finished_good: f64,
2074    /// Trading goods (purchased for resale)
2075    pub trading_good: f64,
2076    /// Operating supplies
2077    pub operating_supply: f64,
2078    /// Services
2079    pub service: f64,
2080}
2081
2082impl Default for MaterialTypeDistribution {
2083    fn default() -> Self {
2084        Self {
2085            raw_material: 0.30,
2086            semi_finished: 0.15,
2087            finished_good: 0.25,
2088            trading_good: 0.15,
2089            operating_supply: 0.10,
2090            service: 0.05,
2091        }
2092    }
2093}
2094
2095/// Valuation method distribution for materials.
2096#[derive(Debug, Clone, Serialize, Deserialize)]
2097pub struct ValuationMethodDistribution {
2098    /// Standard cost
2099    pub standard_cost: f64,
2100    /// Moving average
2101    pub moving_average: f64,
2102    /// FIFO (First In, First Out)
2103    pub fifo: f64,
2104    /// LIFO (Last In, First Out)
2105    pub lifo: f64,
2106}
2107
2108impl Default for ValuationMethodDistribution {
2109    fn default() -> Self {
2110        Self {
2111            standard_cost: 0.50,
2112            moving_average: 0.30,
2113            fifo: 0.15,
2114            lifo: 0.05,
2115        }
2116    }
2117}
2118
2119/// Fixed asset master data configuration.
2120#[derive(Debug, Clone, Serialize, Deserialize)]
2121pub struct FixedAssetMasterConfig {
2122    /// Number of fixed assets to generate
2123    #[serde(default = "default_asset_count")]
2124    pub count: usize,
2125    /// Asset class distribution
2126    #[serde(default)]
2127    pub class_distribution: AssetClassDistribution,
2128    /// Depreciation method distribution
2129    #[serde(default)]
2130    pub depreciation_distribution: DepreciationMethodDistribution,
2131    /// Percentage of assets that are fully depreciated
2132    #[serde(default = "default_fully_depreciated_percent")]
2133    pub fully_depreciated_percent: f64,
2134    /// Generate acquisition history
2135    #[serde(default = "default_true")]
2136    pub generate_acquisition_history: bool,
2137}
2138
2139fn default_asset_count() -> usize {
2140    800
2141}
2142
2143fn default_fully_depreciated_percent() -> f64 {
2144    0.15
2145}
2146
2147impl Default for FixedAssetMasterConfig {
2148    fn default() -> Self {
2149        Self {
2150            count: default_asset_count(),
2151            class_distribution: AssetClassDistribution::default(),
2152            depreciation_distribution: DepreciationMethodDistribution::default(),
2153            fully_depreciated_percent: default_fully_depreciated_percent(),
2154            generate_acquisition_history: true,
2155        }
2156    }
2157}
2158
2159/// Asset class distribution.
2160#[derive(Debug, Clone, Serialize, Deserialize)]
2161pub struct AssetClassDistribution {
2162    /// Buildings and structures
2163    pub buildings: f64,
2164    /// Machinery and equipment
2165    pub machinery: f64,
2166    /// Vehicles
2167    pub vehicles: f64,
2168    /// IT equipment
2169    pub it_equipment: f64,
2170    /// Furniture and fixtures
2171    pub furniture: f64,
2172    /// Land (non-depreciable)
2173    pub land: f64,
2174    /// Leasehold improvements
2175    pub leasehold: f64,
2176}
2177
2178impl Default for AssetClassDistribution {
2179    fn default() -> Self {
2180        Self {
2181            buildings: 0.15,
2182            machinery: 0.30,
2183            vehicles: 0.15,
2184            it_equipment: 0.20,
2185            furniture: 0.10,
2186            land: 0.05,
2187            leasehold: 0.05,
2188        }
2189    }
2190}
2191
2192/// Depreciation method distribution.
2193#[derive(Debug, Clone, Serialize, Deserialize)]
2194pub struct DepreciationMethodDistribution {
2195    /// Straight line
2196    pub straight_line: f64,
2197    /// Declining balance
2198    pub declining_balance: f64,
2199    /// Double declining balance
2200    pub double_declining: f64,
2201    /// Sum of years' digits
2202    pub sum_of_years: f64,
2203    /// Units of production
2204    pub units_of_production: f64,
2205}
2206
2207impl Default for DepreciationMethodDistribution {
2208    fn default() -> Self {
2209        Self {
2210            straight_line: 0.60,
2211            declining_balance: 0.20,
2212            double_declining: 0.10,
2213            sum_of_years: 0.05,
2214            units_of_production: 0.05,
2215        }
2216    }
2217}
2218
2219/// Employee master data configuration.
2220#[derive(Debug, Clone, Serialize, Deserialize)]
2221pub struct EmployeeMasterConfig {
2222    /// Number of employees to generate
2223    #[serde(default = "default_employee_count")]
2224    pub count: usize,
2225    /// Generate organizational hierarchy
2226    #[serde(default = "default_true")]
2227    pub generate_hierarchy: bool,
2228    /// Maximum hierarchy depth
2229    #[serde(default = "default_hierarchy_depth")]
2230    pub max_hierarchy_depth: u8,
2231    /// Average span of control (direct reports per manager)
2232    #[serde(default = "default_span_of_control")]
2233    pub average_span_of_control: f64,
2234    /// Approval limit distribution by job level
2235    #[serde(default)]
2236    pub approval_limits: ApprovalLimitDistribution,
2237    /// Department distribution
2238    #[serde(default)]
2239    pub department_distribution: EmployeeDepartmentDistribution,
2240}
2241
2242fn default_employee_count() -> usize {
2243    1500
2244}
2245
2246fn default_hierarchy_depth() -> u8 {
2247    6
2248}
2249
2250fn default_span_of_control() -> f64 {
2251    5.0
2252}
2253
2254impl Default for EmployeeMasterConfig {
2255    fn default() -> Self {
2256        Self {
2257            count: default_employee_count(),
2258            generate_hierarchy: true,
2259            max_hierarchy_depth: default_hierarchy_depth(),
2260            average_span_of_control: default_span_of_control(),
2261            approval_limits: ApprovalLimitDistribution::default(),
2262            department_distribution: EmployeeDepartmentDistribution::default(),
2263        }
2264    }
2265}
2266
2267/// Approval limit distribution by job level.
2268#[derive(Debug, Clone, Serialize, Deserialize)]
2269pub struct ApprovalLimitDistribution {
2270    /// Staff level approval limit
2271    #[serde(default = "default_staff_limit")]
2272    pub staff: f64,
2273    /// Senior staff approval limit
2274    #[serde(default = "default_senior_limit")]
2275    pub senior: f64,
2276    /// Manager approval limit
2277    #[serde(default = "default_manager_limit")]
2278    pub manager: f64,
2279    /// Director approval limit
2280    #[serde(default = "default_director_limit")]
2281    pub director: f64,
2282    /// VP approval limit
2283    #[serde(default = "default_vp_limit")]
2284    pub vp: f64,
2285    /// Executive approval limit
2286    #[serde(default = "default_executive_limit")]
2287    pub executive: f64,
2288}
2289
2290fn default_staff_limit() -> f64 {
2291    1000.0
2292}
2293fn default_senior_limit() -> f64 {
2294    5000.0
2295}
2296fn default_manager_limit() -> f64 {
2297    25000.0
2298}
2299fn default_director_limit() -> f64 {
2300    100000.0
2301}
2302fn default_vp_limit() -> f64 {
2303    500000.0
2304}
2305fn default_executive_limit() -> f64 {
2306    f64::INFINITY
2307}
2308
2309impl Default for ApprovalLimitDistribution {
2310    fn default() -> Self {
2311        Self {
2312            staff: default_staff_limit(),
2313            senior: default_senior_limit(),
2314            manager: default_manager_limit(),
2315            director: default_director_limit(),
2316            vp: default_vp_limit(),
2317            executive: default_executive_limit(),
2318        }
2319    }
2320}
2321
2322/// Employee distribution across departments.
2323#[derive(Debug, Clone, Serialize, Deserialize)]
2324pub struct EmployeeDepartmentDistribution {
2325    /// Finance and Accounting
2326    pub finance: f64,
2327    /// Procurement
2328    pub procurement: f64,
2329    /// Sales
2330    pub sales: f64,
2331    /// Warehouse and Logistics
2332    pub warehouse: f64,
2333    /// IT
2334    pub it: f64,
2335    /// Human Resources
2336    pub hr: f64,
2337    /// Operations
2338    pub operations: f64,
2339    /// Executive
2340    pub executive: f64,
2341}
2342
2343impl Default for EmployeeDepartmentDistribution {
2344    fn default() -> Self {
2345        Self {
2346            finance: 0.12,
2347            procurement: 0.10,
2348            sales: 0.25,
2349            warehouse: 0.15,
2350            it: 0.10,
2351            hr: 0.05,
2352            operations: 0.20,
2353            executive: 0.03,
2354        }
2355    }
2356}
2357
2358/// Cost center master data configuration.
2359#[derive(Debug, Clone, Serialize, Deserialize)]
2360pub struct CostCenterMasterConfig {
2361    /// Number of cost centers to generate
2362    #[serde(default = "default_cost_center_count")]
2363    pub count: usize,
2364    /// Generate cost center hierarchy
2365    #[serde(default = "default_true")]
2366    pub generate_hierarchy: bool,
2367    /// Maximum hierarchy depth
2368    #[serde(default = "default_cc_hierarchy_depth")]
2369    pub max_hierarchy_depth: u8,
2370}
2371
2372fn default_cost_center_count() -> usize {
2373    50
2374}
2375
2376fn default_cc_hierarchy_depth() -> u8 {
2377    3
2378}
2379
2380impl Default for CostCenterMasterConfig {
2381    fn default() -> Self {
2382        Self {
2383            count: default_cost_center_count(),
2384            generate_hierarchy: true,
2385            max_hierarchy_depth: default_cc_hierarchy_depth(),
2386        }
2387    }
2388}
2389
2390// ============================================================================
2391// Document Flow Configuration
2392// ============================================================================
2393
2394/// Document flow generation configuration.
2395#[derive(Debug, Clone, Serialize, Deserialize)]
2396pub struct DocumentFlowConfig {
2397    /// P2P (Procure-to-Pay) flow configuration
2398    #[serde(default)]
2399    pub p2p: P2PFlowConfig,
2400    /// O2C (Order-to-Cash) flow configuration
2401    #[serde(default)]
2402    pub o2c: O2CFlowConfig,
2403    /// Generate document reference chains
2404    #[serde(default = "default_true")]
2405    pub generate_document_references: bool,
2406    /// Export document flow graph
2407    #[serde(default)]
2408    pub export_flow_graph: bool,
2409}
2410
2411impl Default for DocumentFlowConfig {
2412    fn default() -> Self {
2413        Self {
2414            p2p: P2PFlowConfig::default(),
2415            o2c: O2CFlowConfig::default(),
2416            generate_document_references: true,
2417            export_flow_graph: false,
2418        }
2419    }
2420}
2421
2422/// P2P (Procure-to-Pay) flow configuration.
2423#[derive(Debug, Clone, Serialize, Deserialize)]
2424pub struct P2PFlowConfig {
2425    /// Enable P2P document flow generation
2426    #[serde(default = "default_true")]
2427    pub enabled: bool,
2428    /// Three-way match success rate (PO-GR-Invoice)
2429    #[serde(default = "default_three_way_match_rate")]
2430    pub three_way_match_rate: f64,
2431    /// Rate of partial deliveries
2432    #[serde(default = "default_partial_delivery_rate")]
2433    pub partial_delivery_rate: f64,
2434    /// Rate of price variances between PO and Invoice
2435    #[serde(default = "default_price_variance_rate")]
2436    pub price_variance_rate: f64,
2437    /// Maximum price variance percentage
2438    #[serde(default = "default_max_price_variance")]
2439    pub max_price_variance_percent: f64,
2440    /// Rate of quantity variances between PO/GR and Invoice
2441    #[serde(default = "default_quantity_variance_rate")]
2442    pub quantity_variance_rate: f64,
2443    /// Average days from PO to goods receipt
2444    #[serde(default = "default_po_to_gr_days")]
2445    pub average_po_to_gr_days: u32,
2446    /// Average days from GR to invoice
2447    #[serde(default = "default_gr_to_invoice_days")]
2448    pub average_gr_to_invoice_days: u32,
2449    /// Average days from invoice to payment
2450    #[serde(default = "default_invoice_to_payment_days")]
2451    pub average_invoice_to_payment_days: u32,
2452    /// PO line count distribution
2453    #[serde(default)]
2454    pub line_count_distribution: DocumentLineCountDistribution,
2455    /// Payment behavior configuration
2456    #[serde(default)]
2457    pub payment_behavior: P2PPaymentBehaviorConfig,
2458}
2459
2460fn default_three_way_match_rate() -> f64 {
2461    0.95
2462}
2463
2464fn default_partial_delivery_rate() -> f64 {
2465    0.15
2466}
2467
2468fn default_price_variance_rate() -> f64 {
2469    0.08
2470}
2471
2472fn default_max_price_variance() -> f64 {
2473    0.05
2474}
2475
2476fn default_quantity_variance_rate() -> f64 {
2477    0.05
2478}
2479
2480fn default_po_to_gr_days() -> u32 {
2481    14
2482}
2483
2484fn default_gr_to_invoice_days() -> u32 {
2485    5
2486}
2487
2488fn default_invoice_to_payment_days() -> u32 {
2489    30
2490}
2491
2492impl Default for P2PFlowConfig {
2493    fn default() -> Self {
2494        Self {
2495            enabled: true,
2496            three_way_match_rate: default_three_way_match_rate(),
2497            partial_delivery_rate: default_partial_delivery_rate(),
2498            price_variance_rate: default_price_variance_rate(),
2499            max_price_variance_percent: default_max_price_variance(),
2500            quantity_variance_rate: default_quantity_variance_rate(),
2501            average_po_to_gr_days: default_po_to_gr_days(),
2502            average_gr_to_invoice_days: default_gr_to_invoice_days(),
2503            average_invoice_to_payment_days: default_invoice_to_payment_days(),
2504            line_count_distribution: DocumentLineCountDistribution::default(),
2505            payment_behavior: P2PPaymentBehaviorConfig::default(),
2506        }
2507    }
2508}
2509
2510// ============================================================================
2511// P2P Payment Behavior Configuration
2512// ============================================================================
2513
2514/// P2P payment behavior configuration.
2515#[derive(Debug, Clone, Serialize, Deserialize)]
2516pub struct P2PPaymentBehaviorConfig {
2517    /// Rate of late payments (beyond due date)
2518    #[serde(default = "default_p2p_late_payment_rate")]
2519    pub late_payment_rate: f64,
2520    /// Distribution of late payment days
2521    #[serde(default)]
2522    pub late_payment_days_distribution: LatePaymentDaysDistribution,
2523    /// Rate of partial payments
2524    #[serde(default = "default_p2p_partial_payment_rate")]
2525    pub partial_payment_rate: f64,
2526    /// Rate of payment corrections (NSF, chargebacks, reversals)
2527    #[serde(default = "default_p2p_payment_correction_rate")]
2528    pub payment_correction_rate: f64,
2529}
2530
2531fn default_p2p_late_payment_rate() -> f64 {
2532    0.15
2533}
2534
2535fn default_p2p_partial_payment_rate() -> f64 {
2536    0.05
2537}
2538
2539fn default_p2p_payment_correction_rate() -> f64 {
2540    0.02
2541}
2542
2543impl Default for P2PPaymentBehaviorConfig {
2544    fn default() -> Self {
2545        Self {
2546            late_payment_rate: default_p2p_late_payment_rate(),
2547            late_payment_days_distribution: LatePaymentDaysDistribution::default(),
2548            partial_payment_rate: default_p2p_partial_payment_rate(),
2549            payment_correction_rate: default_p2p_payment_correction_rate(),
2550        }
2551    }
2552}
2553
2554/// Distribution of late payment days for P2P.
2555#[derive(Debug, Clone, Serialize, Deserialize)]
2556pub struct LatePaymentDaysDistribution {
2557    /// 1-7 days late (slightly late)
2558    #[serde(default = "default_slightly_late")]
2559    pub slightly_late_1_to_7: f64,
2560    /// 8-14 days late
2561    #[serde(default = "default_late_8_14")]
2562    pub late_8_to_14: f64,
2563    /// 15-30 days late (very late)
2564    #[serde(default = "default_very_late")]
2565    pub very_late_15_to_30: f64,
2566    /// 31-60 days late (severely late)
2567    #[serde(default = "default_severely_late")]
2568    pub severely_late_31_to_60: f64,
2569    /// Over 60 days late (extremely late)
2570    #[serde(default = "default_extremely_late")]
2571    pub extremely_late_over_60: f64,
2572}
2573
2574fn default_slightly_late() -> f64 {
2575    0.50
2576}
2577
2578fn default_late_8_14() -> f64 {
2579    0.25
2580}
2581
2582fn default_very_late() -> f64 {
2583    0.15
2584}
2585
2586fn default_severely_late() -> f64 {
2587    0.07
2588}
2589
2590fn default_extremely_late() -> f64 {
2591    0.03
2592}
2593
2594impl Default for LatePaymentDaysDistribution {
2595    fn default() -> Self {
2596        Self {
2597            slightly_late_1_to_7: default_slightly_late(),
2598            late_8_to_14: default_late_8_14(),
2599            very_late_15_to_30: default_very_late(),
2600            severely_late_31_to_60: default_severely_late(),
2601            extremely_late_over_60: default_extremely_late(),
2602        }
2603    }
2604}
2605
2606/// O2C (Order-to-Cash) flow configuration.
2607#[derive(Debug, Clone, Serialize, Deserialize)]
2608pub struct O2CFlowConfig {
2609    /// Enable O2C document flow generation
2610    #[serde(default = "default_true")]
2611    pub enabled: bool,
2612    /// Credit check failure rate
2613    #[serde(default = "default_credit_check_failure_rate")]
2614    pub credit_check_failure_rate: f64,
2615    /// Rate of partial shipments
2616    #[serde(default = "default_partial_shipment_rate")]
2617    pub partial_shipment_rate: f64,
2618    /// Rate of returns
2619    #[serde(default = "default_return_rate")]
2620    pub return_rate: f64,
2621    /// Bad debt write-off rate
2622    #[serde(default = "default_bad_debt_rate")]
2623    pub bad_debt_rate: f64,
2624    /// Average days from SO to delivery
2625    #[serde(default = "default_so_to_delivery_days")]
2626    pub average_so_to_delivery_days: u32,
2627    /// Average days from delivery to invoice
2628    #[serde(default = "default_delivery_to_invoice_days")]
2629    pub average_delivery_to_invoice_days: u32,
2630    /// Average days from invoice to receipt
2631    #[serde(default = "default_invoice_to_receipt_days")]
2632    pub average_invoice_to_receipt_days: u32,
2633    /// SO line count distribution
2634    #[serde(default)]
2635    pub line_count_distribution: DocumentLineCountDistribution,
2636    /// Cash discount configuration
2637    #[serde(default)]
2638    pub cash_discount: CashDiscountConfig,
2639    /// Payment behavior configuration
2640    #[serde(default)]
2641    pub payment_behavior: O2CPaymentBehaviorConfig,
2642}
2643
2644fn default_credit_check_failure_rate() -> f64 {
2645    0.02
2646}
2647
2648fn default_partial_shipment_rate() -> f64 {
2649    0.10
2650}
2651
2652fn default_return_rate() -> f64 {
2653    0.03
2654}
2655
2656fn default_bad_debt_rate() -> f64 {
2657    0.01
2658}
2659
2660fn default_so_to_delivery_days() -> u32 {
2661    7
2662}
2663
2664fn default_delivery_to_invoice_days() -> u32 {
2665    1
2666}
2667
2668fn default_invoice_to_receipt_days() -> u32 {
2669    45
2670}
2671
2672impl Default for O2CFlowConfig {
2673    fn default() -> Self {
2674        Self {
2675            enabled: true,
2676            credit_check_failure_rate: default_credit_check_failure_rate(),
2677            partial_shipment_rate: default_partial_shipment_rate(),
2678            return_rate: default_return_rate(),
2679            bad_debt_rate: default_bad_debt_rate(),
2680            average_so_to_delivery_days: default_so_to_delivery_days(),
2681            average_delivery_to_invoice_days: default_delivery_to_invoice_days(),
2682            average_invoice_to_receipt_days: default_invoice_to_receipt_days(),
2683            line_count_distribution: DocumentLineCountDistribution::default(),
2684            cash_discount: CashDiscountConfig::default(),
2685            payment_behavior: O2CPaymentBehaviorConfig::default(),
2686        }
2687    }
2688}
2689
2690// ============================================================================
2691// O2C Payment Behavior Configuration
2692// ============================================================================
2693
2694/// O2C payment behavior configuration.
2695#[derive(Debug, Clone, Serialize, Deserialize, Default)]
2696pub struct O2CPaymentBehaviorConfig {
2697    /// Dunning (Mahnung) configuration
2698    #[serde(default)]
2699    pub dunning: DunningConfig,
2700    /// Partial payment configuration
2701    #[serde(default)]
2702    pub partial_payments: PartialPaymentConfig,
2703    /// Short payment configuration (unauthorized deductions)
2704    #[serde(default)]
2705    pub short_payments: ShortPaymentConfig,
2706    /// On-account payment configuration (unapplied payments)
2707    #[serde(default)]
2708    pub on_account_payments: OnAccountPaymentConfig,
2709    /// Payment correction configuration (NSF, chargebacks)
2710    #[serde(default)]
2711    pub payment_corrections: PaymentCorrectionConfig,
2712}
2713
2714/// Dunning (Mahnungen) configuration for AR collections.
2715#[derive(Debug, Clone, Serialize, Deserialize)]
2716pub struct DunningConfig {
2717    /// Enable dunning process
2718    #[serde(default)]
2719    pub enabled: bool,
2720    /// Days overdue for level 1 dunning (1st reminder)
2721    #[serde(default = "default_dunning_level_1_days")]
2722    pub level_1_days_overdue: u32,
2723    /// Days overdue for level 2 dunning (2nd reminder)
2724    #[serde(default = "default_dunning_level_2_days")]
2725    pub level_2_days_overdue: u32,
2726    /// Days overdue for level 3 dunning (final notice)
2727    #[serde(default = "default_dunning_level_3_days")]
2728    pub level_3_days_overdue: u32,
2729    /// Days overdue for collection handover
2730    #[serde(default = "default_collection_days")]
2731    pub collection_days_overdue: u32,
2732    /// Payment rates after each dunning level
2733    #[serde(default)]
2734    pub payment_after_dunning_rates: DunningPaymentRates,
2735    /// Rate of invoices blocked from dunning (disputes)
2736    #[serde(default = "default_dunning_block_rate")]
2737    pub dunning_block_rate: f64,
2738    /// Interest rate per year for overdue amounts
2739    #[serde(default = "default_dunning_interest_rate")]
2740    pub interest_rate_per_year: f64,
2741    /// Fixed dunning charge per letter
2742    #[serde(default = "default_dunning_charge")]
2743    pub dunning_charge: f64,
2744}
2745
2746fn default_dunning_level_1_days() -> u32 {
2747    14
2748}
2749
2750fn default_dunning_level_2_days() -> u32 {
2751    28
2752}
2753
2754fn default_dunning_level_3_days() -> u32 {
2755    42
2756}
2757
2758fn default_collection_days() -> u32 {
2759    60
2760}
2761
2762fn default_dunning_block_rate() -> f64 {
2763    0.05
2764}
2765
2766fn default_dunning_interest_rate() -> f64 {
2767    0.09
2768}
2769
2770fn default_dunning_charge() -> f64 {
2771    25.0
2772}
2773
2774impl Default for DunningConfig {
2775    fn default() -> Self {
2776        Self {
2777            enabled: false,
2778            level_1_days_overdue: default_dunning_level_1_days(),
2779            level_2_days_overdue: default_dunning_level_2_days(),
2780            level_3_days_overdue: default_dunning_level_3_days(),
2781            collection_days_overdue: default_collection_days(),
2782            payment_after_dunning_rates: DunningPaymentRates::default(),
2783            dunning_block_rate: default_dunning_block_rate(),
2784            interest_rate_per_year: default_dunning_interest_rate(),
2785            dunning_charge: default_dunning_charge(),
2786        }
2787    }
2788}
2789
2790/// Payment rates after each dunning level.
2791#[derive(Debug, Clone, Serialize, Deserialize)]
2792pub struct DunningPaymentRates {
2793    /// Rate that pays after level 1 reminder
2794    #[serde(default = "default_after_level_1")]
2795    pub after_level_1: f64,
2796    /// Rate that pays after level 2 reminder
2797    #[serde(default = "default_after_level_2")]
2798    pub after_level_2: f64,
2799    /// Rate that pays after level 3 final notice
2800    #[serde(default = "default_after_level_3")]
2801    pub after_level_3: f64,
2802    /// Rate that pays during collection
2803    #[serde(default = "default_during_collection")]
2804    pub during_collection: f64,
2805    /// Rate that never pays (becomes bad debt)
2806    #[serde(default = "default_never_pay")]
2807    pub never_pay: f64,
2808}
2809
2810fn default_after_level_1() -> f64 {
2811    0.40
2812}
2813
2814fn default_after_level_2() -> f64 {
2815    0.30
2816}
2817
2818fn default_after_level_3() -> f64 {
2819    0.15
2820}
2821
2822fn default_during_collection() -> f64 {
2823    0.05
2824}
2825
2826fn default_never_pay() -> f64 {
2827    0.10
2828}
2829
2830impl Default for DunningPaymentRates {
2831    fn default() -> Self {
2832        Self {
2833            after_level_1: default_after_level_1(),
2834            after_level_2: default_after_level_2(),
2835            after_level_3: default_after_level_3(),
2836            during_collection: default_during_collection(),
2837            never_pay: default_never_pay(),
2838        }
2839    }
2840}
2841
2842/// Partial payment configuration.
2843#[derive(Debug, Clone, Serialize, Deserialize)]
2844pub struct PartialPaymentConfig {
2845    /// Rate of invoices paid partially
2846    #[serde(default = "default_partial_payment_rate")]
2847    pub rate: f64,
2848    /// Distribution of partial payment percentages
2849    #[serde(default)]
2850    pub percentage_distribution: PartialPaymentPercentageDistribution,
2851    /// Average days until remainder is paid
2852    #[serde(default = "default_avg_days_until_remainder")]
2853    pub avg_days_until_remainder: u32,
2854}
2855
2856fn default_partial_payment_rate() -> f64 {
2857    0.08
2858}
2859
2860fn default_avg_days_until_remainder() -> u32 {
2861    30
2862}
2863
2864impl Default for PartialPaymentConfig {
2865    fn default() -> Self {
2866        Self {
2867            rate: default_partial_payment_rate(),
2868            percentage_distribution: PartialPaymentPercentageDistribution::default(),
2869            avg_days_until_remainder: default_avg_days_until_remainder(),
2870        }
2871    }
2872}
2873
2874/// Distribution of partial payment percentages.
2875#[derive(Debug, Clone, Serialize, Deserialize)]
2876pub struct PartialPaymentPercentageDistribution {
2877    /// Pay 25% of invoice
2878    #[serde(default = "default_partial_25")]
2879    pub pay_25_percent: f64,
2880    /// Pay 50% of invoice
2881    #[serde(default = "default_partial_50")]
2882    pub pay_50_percent: f64,
2883    /// Pay 75% of invoice
2884    #[serde(default = "default_partial_75")]
2885    pub pay_75_percent: f64,
2886    /// Pay random percentage
2887    #[serde(default = "default_partial_random")]
2888    pub pay_random_percent: f64,
2889}
2890
2891fn default_partial_25() -> f64 {
2892    0.15
2893}
2894
2895fn default_partial_50() -> f64 {
2896    0.50
2897}
2898
2899fn default_partial_75() -> f64 {
2900    0.25
2901}
2902
2903fn default_partial_random() -> f64 {
2904    0.10
2905}
2906
2907impl Default for PartialPaymentPercentageDistribution {
2908    fn default() -> Self {
2909        Self {
2910            pay_25_percent: default_partial_25(),
2911            pay_50_percent: default_partial_50(),
2912            pay_75_percent: default_partial_75(),
2913            pay_random_percent: default_partial_random(),
2914        }
2915    }
2916}
2917
2918/// Short payment configuration (unauthorized deductions).
2919#[derive(Debug, Clone, Serialize, Deserialize)]
2920pub struct ShortPaymentConfig {
2921    /// Rate of payments that are short
2922    #[serde(default = "default_short_payment_rate")]
2923    pub rate: f64,
2924    /// Distribution of short payment reasons
2925    #[serde(default)]
2926    pub reason_distribution: ShortPaymentReasonDistribution,
2927    /// Maximum percentage that can be short
2928    #[serde(default = "default_max_short_percent")]
2929    pub max_short_percent: f64,
2930}
2931
2932fn default_short_payment_rate() -> f64 {
2933    0.03
2934}
2935
2936fn default_max_short_percent() -> f64 {
2937    0.10
2938}
2939
2940impl Default for ShortPaymentConfig {
2941    fn default() -> Self {
2942        Self {
2943            rate: default_short_payment_rate(),
2944            reason_distribution: ShortPaymentReasonDistribution::default(),
2945            max_short_percent: default_max_short_percent(),
2946        }
2947    }
2948}
2949
2950/// Distribution of short payment reasons.
2951#[derive(Debug, Clone, Serialize, Deserialize)]
2952pub struct ShortPaymentReasonDistribution {
2953    /// Pricing dispute
2954    #[serde(default = "default_pricing_dispute")]
2955    pub pricing_dispute: f64,
2956    /// Quality issue
2957    #[serde(default = "default_quality_issue")]
2958    pub quality_issue: f64,
2959    /// Quantity discrepancy
2960    #[serde(default = "default_quantity_discrepancy")]
2961    pub quantity_discrepancy: f64,
2962    /// Unauthorized deduction
2963    #[serde(default = "default_unauthorized_deduction")]
2964    pub unauthorized_deduction: f64,
2965    /// Early payment discount taken incorrectly
2966    #[serde(default = "default_incorrect_discount")]
2967    pub incorrect_discount: f64,
2968}
2969
2970fn default_pricing_dispute() -> f64 {
2971    0.30
2972}
2973
2974fn default_quality_issue() -> f64 {
2975    0.20
2976}
2977
2978fn default_quantity_discrepancy() -> f64 {
2979    0.20
2980}
2981
2982fn default_unauthorized_deduction() -> f64 {
2983    0.15
2984}
2985
2986fn default_incorrect_discount() -> f64 {
2987    0.15
2988}
2989
2990impl Default for ShortPaymentReasonDistribution {
2991    fn default() -> Self {
2992        Self {
2993            pricing_dispute: default_pricing_dispute(),
2994            quality_issue: default_quality_issue(),
2995            quantity_discrepancy: default_quantity_discrepancy(),
2996            unauthorized_deduction: default_unauthorized_deduction(),
2997            incorrect_discount: default_incorrect_discount(),
2998        }
2999    }
3000}
3001
3002/// On-account payment configuration (unapplied payments).
3003#[derive(Debug, Clone, Serialize, Deserialize)]
3004pub struct OnAccountPaymentConfig {
3005    /// Rate of payments that are on-account (unapplied)
3006    #[serde(default = "default_on_account_rate")]
3007    pub rate: f64,
3008    /// Average days until on-account payments are applied
3009    #[serde(default = "default_avg_days_until_applied")]
3010    pub avg_days_until_applied: u32,
3011}
3012
3013fn default_on_account_rate() -> f64 {
3014    0.02
3015}
3016
3017fn default_avg_days_until_applied() -> u32 {
3018    14
3019}
3020
3021impl Default for OnAccountPaymentConfig {
3022    fn default() -> Self {
3023        Self {
3024            rate: default_on_account_rate(),
3025            avg_days_until_applied: default_avg_days_until_applied(),
3026        }
3027    }
3028}
3029
3030/// Payment correction configuration.
3031#[derive(Debug, Clone, Serialize, Deserialize)]
3032pub struct PaymentCorrectionConfig {
3033    /// Rate of payments requiring correction
3034    #[serde(default = "default_payment_correction_rate")]
3035    pub rate: f64,
3036    /// Distribution of correction types
3037    #[serde(default)]
3038    pub type_distribution: PaymentCorrectionTypeDistribution,
3039}
3040
3041fn default_payment_correction_rate() -> f64 {
3042    0.02
3043}
3044
3045impl Default for PaymentCorrectionConfig {
3046    fn default() -> Self {
3047        Self {
3048            rate: default_payment_correction_rate(),
3049            type_distribution: PaymentCorrectionTypeDistribution::default(),
3050        }
3051    }
3052}
3053
3054/// Distribution of payment correction types.
3055#[derive(Debug, Clone, Serialize, Deserialize)]
3056pub struct PaymentCorrectionTypeDistribution {
3057    /// NSF (Non-sufficient funds) / bounced check
3058    #[serde(default = "default_nsf_rate")]
3059    pub nsf: f64,
3060    /// Chargeback
3061    #[serde(default = "default_chargeback_rate")]
3062    pub chargeback: f64,
3063    /// Wrong amount applied
3064    #[serde(default = "default_wrong_amount_rate")]
3065    pub wrong_amount: f64,
3066    /// Wrong customer applied
3067    #[serde(default = "default_wrong_customer_rate")]
3068    pub wrong_customer: f64,
3069    /// Duplicate payment
3070    #[serde(default = "default_duplicate_payment_rate")]
3071    pub duplicate_payment: f64,
3072}
3073
3074fn default_nsf_rate() -> f64 {
3075    0.30
3076}
3077
3078fn default_chargeback_rate() -> f64 {
3079    0.20
3080}
3081
3082fn default_wrong_amount_rate() -> f64 {
3083    0.20
3084}
3085
3086fn default_wrong_customer_rate() -> f64 {
3087    0.15
3088}
3089
3090fn default_duplicate_payment_rate() -> f64 {
3091    0.15
3092}
3093
3094impl Default for PaymentCorrectionTypeDistribution {
3095    fn default() -> Self {
3096        Self {
3097            nsf: default_nsf_rate(),
3098            chargeback: default_chargeback_rate(),
3099            wrong_amount: default_wrong_amount_rate(),
3100            wrong_customer: default_wrong_customer_rate(),
3101            duplicate_payment: default_duplicate_payment_rate(),
3102        }
3103    }
3104}
3105
3106/// Document line count distribution.
3107#[derive(Debug, Clone, Serialize, Deserialize)]
3108pub struct DocumentLineCountDistribution {
3109    /// Minimum number of lines
3110    #[serde(default = "default_min_lines")]
3111    pub min_lines: u32,
3112    /// Maximum number of lines
3113    #[serde(default = "default_max_lines")]
3114    pub max_lines: u32,
3115    /// Most common line count (mode)
3116    #[serde(default = "default_mode_lines")]
3117    pub mode_lines: u32,
3118}
3119
3120fn default_min_lines() -> u32 {
3121    1
3122}
3123
3124fn default_max_lines() -> u32 {
3125    20
3126}
3127
3128fn default_mode_lines() -> u32 {
3129    3
3130}
3131
3132impl Default for DocumentLineCountDistribution {
3133    fn default() -> Self {
3134        Self {
3135            min_lines: default_min_lines(),
3136            max_lines: default_max_lines(),
3137            mode_lines: default_mode_lines(),
3138        }
3139    }
3140}
3141
3142/// Cash discount configuration.
3143#[derive(Debug, Clone, Serialize, Deserialize)]
3144pub struct CashDiscountConfig {
3145    /// Percentage of invoices eligible for cash discount
3146    #[serde(default = "default_discount_eligible_rate")]
3147    pub eligible_rate: f64,
3148    /// Rate at which customers take the discount
3149    #[serde(default = "default_discount_taken_rate")]
3150    pub taken_rate: f64,
3151    /// Standard discount percentage
3152    #[serde(default = "default_discount_percent")]
3153    pub discount_percent: f64,
3154    /// Days within which discount must be taken
3155    #[serde(default = "default_discount_days")]
3156    pub discount_days: u32,
3157}
3158
3159fn default_discount_eligible_rate() -> f64 {
3160    0.30
3161}
3162
3163fn default_discount_taken_rate() -> f64 {
3164    0.60
3165}
3166
3167fn default_discount_percent() -> f64 {
3168    0.02
3169}
3170
3171fn default_discount_days() -> u32 {
3172    10
3173}
3174
3175impl Default for CashDiscountConfig {
3176    fn default() -> Self {
3177        Self {
3178            eligible_rate: default_discount_eligible_rate(),
3179            taken_rate: default_discount_taken_rate(),
3180            discount_percent: default_discount_percent(),
3181            discount_days: default_discount_days(),
3182        }
3183    }
3184}
3185
3186// ============================================================================
3187// Intercompany Configuration
3188// ============================================================================
3189
3190/// Intercompany transaction configuration.
3191#[derive(Debug, Clone, Serialize, Deserialize)]
3192pub struct IntercompanyConfig {
3193    /// Enable intercompany transaction generation
3194    #[serde(default)]
3195    pub enabled: bool,
3196    /// Rate of transactions that are intercompany
3197    #[serde(default = "default_ic_transaction_rate")]
3198    pub ic_transaction_rate: f64,
3199    /// Transfer pricing method
3200    #[serde(default)]
3201    pub transfer_pricing_method: TransferPricingMethod,
3202    /// Transfer pricing markup percentage (for cost-plus)
3203    #[serde(default = "default_markup_percent")]
3204    pub markup_percent: f64,
3205    /// Generate matched IC pairs (offsetting entries)
3206    #[serde(default = "default_true")]
3207    pub generate_matched_pairs: bool,
3208    /// IC transaction type distribution
3209    #[serde(default)]
3210    pub transaction_type_distribution: ICTransactionTypeDistribution,
3211    /// Generate elimination entries for consolidation
3212    #[serde(default)]
3213    pub generate_eliminations: bool,
3214}
3215
3216fn default_ic_transaction_rate() -> f64 {
3217    0.15
3218}
3219
3220fn default_markup_percent() -> f64 {
3221    0.05
3222}
3223
3224impl Default for IntercompanyConfig {
3225    fn default() -> Self {
3226        Self {
3227            enabled: false,
3228            ic_transaction_rate: default_ic_transaction_rate(),
3229            transfer_pricing_method: TransferPricingMethod::default(),
3230            markup_percent: default_markup_percent(),
3231            generate_matched_pairs: true,
3232            transaction_type_distribution: ICTransactionTypeDistribution::default(),
3233            generate_eliminations: false,
3234        }
3235    }
3236}
3237
3238/// Transfer pricing method.
3239#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
3240#[serde(rename_all = "snake_case")]
3241pub enum TransferPricingMethod {
3242    /// Cost plus a markup
3243    #[default]
3244    CostPlus,
3245    /// Comparable uncontrolled price
3246    ComparableUncontrolled,
3247    /// Resale price method
3248    ResalePrice,
3249    /// Transactional net margin method
3250    TransactionalNetMargin,
3251    /// Profit split method
3252    ProfitSplit,
3253}
3254
3255/// IC transaction type distribution.
3256#[derive(Debug, Clone, Serialize, Deserialize)]
3257pub struct ICTransactionTypeDistribution {
3258    /// Goods sales between entities
3259    pub goods_sale: f64,
3260    /// Services provided
3261    pub service_provided: f64,
3262    /// Intercompany loans
3263    pub loan: f64,
3264    /// Dividends
3265    pub dividend: f64,
3266    /// Management fees
3267    pub management_fee: f64,
3268    /// Royalties
3269    pub royalty: f64,
3270    /// Cost sharing
3271    pub cost_sharing: f64,
3272}
3273
3274impl Default for ICTransactionTypeDistribution {
3275    fn default() -> Self {
3276        Self {
3277            goods_sale: 0.35,
3278            service_provided: 0.20,
3279            loan: 0.10,
3280            dividend: 0.05,
3281            management_fee: 0.15,
3282            royalty: 0.10,
3283            cost_sharing: 0.05,
3284        }
3285    }
3286}
3287
3288// ============================================================================
3289// Balance Configuration
3290// ============================================================================
3291
3292/// Balance and trial balance configuration.
3293#[derive(Debug, Clone, Serialize, Deserialize)]
3294pub struct BalanceConfig {
3295    /// Generate opening balances
3296    #[serde(default)]
3297    pub generate_opening_balances: bool,
3298    /// Generate trial balances
3299    #[serde(default = "default_true")]
3300    pub generate_trial_balances: bool,
3301    /// Target gross margin (for revenue/COGS coherence)
3302    #[serde(default = "default_gross_margin")]
3303    pub target_gross_margin: f64,
3304    /// Target DSO (Days Sales Outstanding)
3305    #[serde(default = "default_dso")]
3306    pub target_dso_days: u32,
3307    /// Target DPO (Days Payable Outstanding)
3308    #[serde(default = "default_dpo")]
3309    pub target_dpo_days: u32,
3310    /// Target current ratio
3311    #[serde(default = "default_current_ratio")]
3312    pub target_current_ratio: f64,
3313    /// Target debt-to-equity ratio
3314    #[serde(default = "default_debt_equity")]
3315    pub target_debt_to_equity: f64,
3316    /// Validate balance sheet equation (A = L + E)
3317    #[serde(default = "default_true")]
3318    pub validate_balance_equation: bool,
3319    /// Reconcile subledgers to GL control accounts
3320    #[serde(default = "default_true")]
3321    pub reconcile_subledgers: bool,
3322}
3323
3324fn default_gross_margin() -> f64 {
3325    0.35
3326}
3327
3328fn default_dso() -> u32 {
3329    45
3330}
3331
3332fn default_dpo() -> u32 {
3333    30
3334}
3335
3336fn default_current_ratio() -> f64 {
3337    1.5
3338}
3339
3340fn default_debt_equity() -> f64 {
3341    0.5
3342}
3343
3344impl Default for BalanceConfig {
3345    fn default() -> Self {
3346        Self {
3347            generate_opening_balances: false,
3348            generate_trial_balances: true,
3349            target_gross_margin: default_gross_margin(),
3350            target_dso_days: default_dso(),
3351            target_dpo_days: default_dpo(),
3352            target_current_ratio: default_current_ratio(),
3353            target_debt_to_equity: default_debt_equity(),
3354            validate_balance_equation: true,
3355            reconcile_subledgers: true,
3356        }
3357    }
3358}
3359
3360// ==========================================================================
3361// OCPM (Object-Centric Process Mining) Configuration
3362// ==========================================================================
3363
3364/// OCPM (Object-Centric Process Mining) configuration.
3365///
3366/// Controls generation of OCEL 2.0 compatible event logs with
3367/// many-to-many event-to-object relationships.
3368#[derive(Debug, Clone, Serialize, Deserialize)]
3369pub struct OcpmConfig {
3370    /// Enable OCPM event log generation
3371    #[serde(default)]
3372    pub enabled: bool,
3373
3374    /// Generate lifecycle events (Start/Complete pairs vs atomic events)
3375    #[serde(default = "default_true")]
3376    pub generate_lifecycle_events: bool,
3377
3378    /// Include object-to-object relationships in output
3379    #[serde(default = "default_true")]
3380    pub include_object_relationships: bool,
3381
3382    /// Compute and export process variants
3383    #[serde(default = "default_true")]
3384    pub compute_variants: bool,
3385
3386    /// Maximum variants to track (0 = unlimited)
3387    #[serde(default)]
3388    pub max_variants: usize,
3389
3390    /// P2P process configuration
3391    #[serde(default)]
3392    pub p2p_process: OcpmProcessConfig,
3393
3394    /// O2C process configuration
3395    #[serde(default)]
3396    pub o2c_process: OcpmProcessConfig,
3397
3398    /// Output format configuration
3399    #[serde(default)]
3400    pub output: OcpmOutputConfig,
3401}
3402
3403impl Default for OcpmConfig {
3404    fn default() -> Self {
3405        Self {
3406            enabled: false,
3407            generate_lifecycle_events: true,
3408            include_object_relationships: true,
3409            compute_variants: true,
3410            max_variants: 0,
3411            p2p_process: OcpmProcessConfig::default(),
3412            o2c_process: OcpmProcessConfig::default(),
3413            output: OcpmOutputConfig::default(),
3414        }
3415    }
3416}
3417
3418/// Process-specific OCPM configuration.
3419#[derive(Debug, Clone, Serialize, Deserialize)]
3420pub struct OcpmProcessConfig {
3421    /// Rework probability (0.0-1.0)
3422    #[serde(default = "default_rework_probability")]
3423    pub rework_probability: f64,
3424
3425    /// Skip step probability (0.0-1.0)
3426    #[serde(default = "default_skip_probability")]
3427    pub skip_step_probability: f64,
3428
3429    /// Out-of-order step probability (0.0-1.0)
3430    #[serde(default = "default_out_of_order_probability")]
3431    pub out_of_order_probability: f64,
3432}
3433
3434fn default_rework_probability() -> f64 {
3435    0.05
3436}
3437
3438fn default_skip_probability() -> f64 {
3439    0.02
3440}
3441
3442fn default_out_of_order_probability() -> f64 {
3443    0.03
3444}
3445
3446impl Default for OcpmProcessConfig {
3447    fn default() -> Self {
3448        Self {
3449            rework_probability: default_rework_probability(),
3450            skip_step_probability: default_skip_probability(),
3451            out_of_order_probability: default_out_of_order_probability(),
3452        }
3453    }
3454}
3455
3456/// OCPM output format configuration.
3457#[derive(Debug, Clone, Serialize, Deserialize)]
3458pub struct OcpmOutputConfig {
3459    /// Export OCEL 2.0 JSON format
3460    #[serde(default = "default_true")]
3461    pub ocel_json: bool,
3462
3463    /// Export OCEL 2.0 XML format
3464    #[serde(default)]
3465    pub ocel_xml: bool,
3466
3467    /// Export XES 2.0 XML format (IEEE standard for process mining tools)
3468    #[serde(default)]
3469    pub xes: bool,
3470
3471    /// Include lifecycle transitions in XES output (start/complete pairs)
3472    #[serde(default = "default_true")]
3473    pub xes_include_lifecycle: bool,
3474
3475    /// Include resource attributes in XES output
3476    #[serde(default = "default_true")]
3477    pub xes_include_resources: bool,
3478
3479    /// Export flattened CSV for each object type
3480    #[serde(default = "default_true")]
3481    pub flattened_csv: bool,
3482
3483    /// Export event-object relationship table
3484    #[serde(default = "default_true")]
3485    pub event_object_csv: bool,
3486
3487    /// Export object-object relationship table
3488    #[serde(default = "default_true")]
3489    pub object_relationship_csv: bool,
3490
3491    /// Export process variants summary
3492    #[serde(default = "default_true")]
3493    pub variants_csv: bool,
3494
3495    /// Export reference process models (canonical P2P, O2C, R2R)
3496    #[serde(default)]
3497    pub export_reference_models: bool,
3498}
3499
3500impl Default for OcpmOutputConfig {
3501    fn default() -> Self {
3502        Self {
3503            ocel_json: true,
3504            ocel_xml: false,
3505            xes: false,
3506            xes_include_lifecycle: true,
3507            xes_include_resources: true,
3508            flattened_csv: true,
3509            event_object_csv: true,
3510            object_relationship_csv: true,
3511            variants_csv: true,
3512            export_reference_models: false,
3513        }
3514    }
3515}
3516
3517/// Audit engagement and workpaper generation configuration.
3518#[derive(Debug, Clone, Serialize, Deserialize)]
3519pub struct AuditGenerationConfig {
3520    /// Enable audit engagement generation
3521    #[serde(default)]
3522    pub enabled: bool,
3523
3524    /// Generate engagement documents and workpapers
3525    #[serde(default = "default_true")]
3526    pub generate_workpapers: bool,
3527
3528    /// Default engagement type distribution
3529    #[serde(default)]
3530    pub engagement_types: AuditEngagementTypesConfig,
3531
3532    /// Workpaper configuration
3533    #[serde(default)]
3534    pub workpapers: WorkpaperConfig,
3535
3536    /// Team configuration
3537    #[serde(default)]
3538    pub team: AuditTeamConfig,
3539
3540    /// Review workflow configuration
3541    #[serde(default)]
3542    pub review: ReviewWorkflowConfig,
3543}
3544
3545impl Default for AuditGenerationConfig {
3546    fn default() -> Self {
3547        Self {
3548            enabled: false,
3549            generate_workpapers: true,
3550            engagement_types: AuditEngagementTypesConfig::default(),
3551            workpapers: WorkpaperConfig::default(),
3552            team: AuditTeamConfig::default(),
3553            review: ReviewWorkflowConfig::default(),
3554        }
3555    }
3556}
3557
3558/// Engagement type distribution configuration.
3559#[derive(Debug, Clone, Serialize, Deserialize)]
3560pub struct AuditEngagementTypesConfig {
3561    /// Financial statement audit probability
3562    #[serde(default = "default_financial_audit_prob")]
3563    pub financial_statement: f64,
3564    /// SOX/ICFR audit probability
3565    #[serde(default = "default_sox_audit_prob")]
3566    pub sox_icfr: f64,
3567    /// Integrated audit probability
3568    #[serde(default = "default_integrated_audit_prob")]
3569    pub integrated: f64,
3570    /// Review engagement probability
3571    #[serde(default = "default_review_prob")]
3572    pub review: f64,
3573    /// Agreed-upon procedures probability
3574    #[serde(default = "default_aup_prob")]
3575    pub agreed_upon_procedures: f64,
3576}
3577
3578fn default_financial_audit_prob() -> f64 {
3579    0.40
3580}
3581fn default_sox_audit_prob() -> f64 {
3582    0.20
3583}
3584fn default_integrated_audit_prob() -> f64 {
3585    0.25
3586}
3587fn default_review_prob() -> f64 {
3588    0.10
3589}
3590fn default_aup_prob() -> f64 {
3591    0.05
3592}
3593
3594impl Default for AuditEngagementTypesConfig {
3595    fn default() -> Self {
3596        Self {
3597            financial_statement: default_financial_audit_prob(),
3598            sox_icfr: default_sox_audit_prob(),
3599            integrated: default_integrated_audit_prob(),
3600            review: default_review_prob(),
3601            agreed_upon_procedures: default_aup_prob(),
3602        }
3603    }
3604}
3605
3606/// Workpaper generation configuration.
3607#[derive(Debug, Clone, Serialize, Deserialize)]
3608pub struct WorkpaperConfig {
3609    /// Average workpapers per engagement phase
3610    #[serde(default = "default_workpapers_per_phase")]
3611    pub average_per_phase: usize,
3612
3613    /// Include ISA compliance references
3614    #[serde(default = "default_true")]
3615    pub include_isa_references: bool,
3616
3617    /// Generate sample details
3618    #[serde(default = "default_true")]
3619    pub include_sample_details: bool,
3620
3621    /// Include cross-references between workpapers
3622    #[serde(default = "default_true")]
3623    pub include_cross_references: bool,
3624
3625    /// Sampling configuration
3626    #[serde(default)]
3627    pub sampling: SamplingConfig,
3628}
3629
3630fn default_workpapers_per_phase() -> usize {
3631    5
3632}
3633
3634impl Default for WorkpaperConfig {
3635    fn default() -> Self {
3636        Self {
3637            average_per_phase: default_workpapers_per_phase(),
3638            include_isa_references: true,
3639            include_sample_details: true,
3640            include_cross_references: true,
3641            sampling: SamplingConfig::default(),
3642        }
3643    }
3644}
3645
3646/// Sampling method configuration.
3647#[derive(Debug, Clone, Serialize, Deserialize)]
3648pub struct SamplingConfig {
3649    /// Statistical sampling rate (0.0-1.0)
3650    #[serde(default = "default_statistical_rate")]
3651    pub statistical_rate: f64,
3652    /// Judgmental sampling rate (0.0-1.0)
3653    #[serde(default = "default_judgmental_rate")]
3654    pub judgmental_rate: f64,
3655    /// Haphazard sampling rate (0.0-1.0)
3656    #[serde(default = "default_haphazard_rate")]
3657    pub haphazard_rate: f64,
3658    /// 100% examination rate (0.0-1.0)
3659    #[serde(default = "default_complete_examination_rate")]
3660    pub complete_examination_rate: f64,
3661}
3662
3663fn default_statistical_rate() -> f64 {
3664    0.40
3665}
3666fn default_judgmental_rate() -> f64 {
3667    0.30
3668}
3669fn default_haphazard_rate() -> f64 {
3670    0.20
3671}
3672fn default_complete_examination_rate() -> f64 {
3673    0.10
3674}
3675
3676impl Default for SamplingConfig {
3677    fn default() -> Self {
3678        Self {
3679            statistical_rate: default_statistical_rate(),
3680            judgmental_rate: default_judgmental_rate(),
3681            haphazard_rate: default_haphazard_rate(),
3682            complete_examination_rate: default_complete_examination_rate(),
3683        }
3684    }
3685}
3686
3687/// Audit team configuration.
3688#[derive(Debug, Clone, Serialize, Deserialize)]
3689pub struct AuditTeamConfig {
3690    /// Minimum team size
3691    #[serde(default = "default_min_team_size")]
3692    pub min_team_size: usize,
3693    /// Maximum team size
3694    #[serde(default = "default_max_team_size")]
3695    pub max_team_size: usize,
3696    /// Probability of having a specialist on the team
3697    #[serde(default = "default_specialist_probability")]
3698    pub specialist_probability: f64,
3699}
3700
3701fn default_min_team_size() -> usize {
3702    3
3703}
3704fn default_max_team_size() -> usize {
3705    8
3706}
3707fn default_specialist_probability() -> f64 {
3708    0.30
3709}
3710
3711impl Default for AuditTeamConfig {
3712    fn default() -> Self {
3713        Self {
3714            min_team_size: default_min_team_size(),
3715            max_team_size: default_max_team_size(),
3716            specialist_probability: default_specialist_probability(),
3717        }
3718    }
3719}
3720
3721/// Review workflow configuration.
3722#[derive(Debug, Clone, Serialize, Deserialize)]
3723pub struct ReviewWorkflowConfig {
3724    /// Average days between preparer completion and first review
3725    #[serde(default = "default_review_delay_days")]
3726    pub average_review_delay_days: u32,
3727    /// Probability of review notes requiring rework
3728    #[serde(default = "default_rework_probability_review")]
3729    pub rework_probability: f64,
3730    /// Require partner sign-off for all workpapers
3731    #[serde(default = "default_true")]
3732    pub require_partner_signoff: bool,
3733}
3734
3735fn default_review_delay_days() -> u32 {
3736    2
3737}
3738fn default_rework_probability_review() -> f64 {
3739    0.15
3740}
3741
3742impl Default for ReviewWorkflowConfig {
3743    fn default() -> Self {
3744        Self {
3745            average_review_delay_days: default_review_delay_days(),
3746            rework_probability: default_rework_probability_review(),
3747            require_partner_signoff: true,
3748        }
3749    }
3750}
3751
3752// =============================================================================
3753// Data Quality Configuration
3754// =============================================================================
3755
3756/// Data quality variation settings for realistic flakiness injection.
3757#[derive(Debug, Clone, Serialize, Deserialize)]
3758pub struct DataQualitySchemaConfig {
3759    /// Enable data quality variations
3760    #[serde(default)]
3761    pub enabled: bool,
3762    /// Preset to use (overrides individual settings if set)
3763    #[serde(default)]
3764    pub preset: DataQualityPreset,
3765    /// Missing value injection settings
3766    #[serde(default)]
3767    pub missing_values: MissingValuesSchemaConfig,
3768    /// Typo injection settings
3769    #[serde(default)]
3770    pub typos: TypoSchemaConfig,
3771    /// Format variation settings
3772    #[serde(default)]
3773    pub format_variations: FormatVariationSchemaConfig,
3774    /// Duplicate injection settings
3775    #[serde(default)]
3776    pub duplicates: DuplicateSchemaConfig,
3777    /// Encoding issue settings
3778    #[serde(default)]
3779    pub encoding_issues: EncodingIssueSchemaConfig,
3780    /// Generate quality issue labels for ML training
3781    #[serde(default)]
3782    pub generate_labels: bool,
3783    /// Per-sink quality profiles (different settings for CSV vs JSON etc.)
3784    #[serde(default)]
3785    pub sink_profiles: SinkQualityProfiles,
3786}
3787
3788impl Default for DataQualitySchemaConfig {
3789    fn default() -> Self {
3790        Self {
3791            enabled: false,
3792            preset: DataQualityPreset::None,
3793            missing_values: MissingValuesSchemaConfig::default(),
3794            typos: TypoSchemaConfig::default(),
3795            format_variations: FormatVariationSchemaConfig::default(),
3796            duplicates: DuplicateSchemaConfig::default(),
3797            encoding_issues: EncodingIssueSchemaConfig::default(),
3798            generate_labels: true,
3799            sink_profiles: SinkQualityProfiles::default(),
3800        }
3801    }
3802}
3803
3804impl DataQualitySchemaConfig {
3805    /// Creates a config for a specific preset profile.
3806    pub fn with_preset(preset: DataQualityPreset) -> Self {
3807        let mut config = Self {
3808            preset,
3809            ..Default::default()
3810        };
3811        config.apply_preset();
3812        config
3813    }
3814
3815    /// Applies the preset settings to the individual configuration fields.
3816    /// Call this after deserializing if preset is not Custom or None.
3817    pub fn apply_preset(&mut self) {
3818        if !self.preset.overrides_settings() {
3819            return;
3820        }
3821
3822        self.enabled = true;
3823
3824        // Missing values
3825        self.missing_values.enabled = self.preset.missing_rate() > 0.0;
3826        self.missing_values.rate = self.preset.missing_rate();
3827
3828        // Typos
3829        self.typos.enabled = self.preset.typo_rate() > 0.0;
3830        self.typos.char_error_rate = self.preset.typo_rate();
3831
3832        // Duplicates
3833        self.duplicates.enabled = self.preset.duplicate_rate() > 0.0;
3834        self.duplicates.exact_duplicate_ratio = self.preset.duplicate_rate() * 0.4;
3835        self.duplicates.near_duplicate_ratio = self.preset.duplicate_rate() * 0.4;
3836        self.duplicates.fuzzy_duplicate_ratio = self.preset.duplicate_rate() * 0.2;
3837
3838        // Format variations
3839        self.format_variations.enabled = self.preset.format_variations_enabled();
3840
3841        // Encoding issues
3842        self.encoding_issues.enabled = self.preset.encoding_issues_enabled();
3843        self.encoding_issues.rate = self.preset.encoding_issue_rate();
3844
3845        // OCR errors for typos in legacy preset
3846        if self.preset.ocr_errors_enabled() {
3847            self.typos.type_weights.ocr_errors = 0.3;
3848        }
3849    }
3850
3851    /// Returns the effective missing value rate (considering preset).
3852    pub fn effective_missing_rate(&self) -> f64 {
3853        if self.preset.overrides_settings() {
3854            self.preset.missing_rate()
3855        } else {
3856            self.missing_values.rate
3857        }
3858    }
3859
3860    /// Returns the effective typo rate (considering preset).
3861    pub fn effective_typo_rate(&self) -> f64 {
3862        if self.preset.overrides_settings() {
3863            self.preset.typo_rate()
3864        } else {
3865            self.typos.char_error_rate
3866        }
3867    }
3868
3869    /// Returns the effective duplicate rate (considering preset).
3870    pub fn effective_duplicate_rate(&self) -> f64 {
3871        if self.preset.overrides_settings() {
3872            self.preset.duplicate_rate()
3873        } else {
3874            self.duplicates.exact_duplicate_ratio
3875                + self.duplicates.near_duplicate_ratio
3876                + self.duplicates.fuzzy_duplicate_ratio
3877        }
3878    }
3879
3880    /// Creates a clean profile config.
3881    pub fn clean() -> Self {
3882        Self::with_preset(DataQualityPreset::Clean)
3883    }
3884
3885    /// Creates a noisy profile config.
3886    pub fn noisy() -> Self {
3887        Self::with_preset(DataQualityPreset::Noisy)
3888    }
3889
3890    /// Creates a legacy profile config.
3891    pub fn legacy() -> Self {
3892        Self::with_preset(DataQualityPreset::Legacy)
3893    }
3894}
3895
3896/// Preset configurations for common data quality scenarios.
3897#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
3898#[serde(rename_all = "snake_case")]
3899pub enum DataQualityPreset {
3900    /// No data quality variations (clean data)
3901    #[default]
3902    None,
3903    /// Minimal variations (very clean data with rare issues)
3904    Minimal,
3905    /// Normal variations (realistic enterprise data quality)
3906    Normal,
3907    /// High variations (messy data for stress testing)
3908    High,
3909    /// Custom (use individual settings)
3910    Custom,
3911
3912    // ========================================
3913    // ML-Oriented Profiles (Phase 2.1)
3914    // ========================================
3915    /// Clean profile for ML training - minimal data quality issues
3916    /// Missing: 0.1%, Typos: 0.05%, Duplicates: 0%, Format: None
3917    Clean,
3918    /// Noisy profile simulating typical production data issues
3919    /// Missing: 5%, Typos: 2%, Duplicates: 1%, Format: Medium
3920    Noisy,
3921    /// Legacy profile simulating migrated/OCR'd historical data
3922    /// Missing: 10%, Typos: 5%, Duplicates: 3%, Format: Heavy + OCR
3923    Legacy,
3924}
3925
3926impl DataQualityPreset {
3927    /// Returns the missing value rate for this preset.
3928    pub fn missing_rate(&self) -> f64 {
3929        match self {
3930            DataQualityPreset::None => 0.0,
3931            DataQualityPreset::Minimal => 0.005,
3932            DataQualityPreset::Normal => 0.02,
3933            DataQualityPreset::High => 0.08,
3934            DataQualityPreset::Custom => 0.01, // Use config value
3935            DataQualityPreset::Clean => 0.001,
3936            DataQualityPreset::Noisy => 0.05,
3937            DataQualityPreset::Legacy => 0.10,
3938        }
3939    }
3940
3941    /// Returns the typo rate for this preset.
3942    pub fn typo_rate(&self) -> f64 {
3943        match self {
3944            DataQualityPreset::None => 0.0,
3945            DataQualityPreset::Minimal => 0.0005,
3946            DataQualityPreset::Normal => 0.002,
3947            DataQualityPreset::High => 0.01,
3948            DataQualityPreset::Custom => 0.001, // Use config value
3949            DataQualityPreset::Clean => 0.0005,
3950            DataQualityPreset::Noisy => 0.02,
3951            DataQualityPreset::Legacy => 0.05,
3952        }
3953    }
3954
3955    /// Returns the duplicate rate for this preset.
3956    pub fn duplicate_rate(&self) -> f64 {
3957        match self {
3958            DataQualityPreset::None => 0.0,
3959            DataQualityPreset::Minimal => 0.001,
3960            DataQualityPreset::Normal => 0.005,
3961            DataQualityPreset::High => 0.02,
3962            DataQualityPreset::Custom => 0.0, // Use config value
3963            DataQualityPreset::Clean => 0.0,
3964            DataQualityPreset::Noisy => 0.01,
3965            DataQualityPreset::Legacy => 0.03,
3966        }
3967    }
3968
3969    /// Returns whether format variations are enabled for this preset.
3970    pub fn format_variations_enabled(&self) -> bool {
3971        match self {
3972            DataQualityPreset::None | DataQualityPreset::Clean => false,
3973            DataQualityPreset::Minimal => true,
3974            DataQualityPreset::Normal => true,
3975            DataQualityPreset::High => true,
3976            DataQualityPreset::Custom => true,
3977            DataQualityPreset::Noisy => true,
3978            DataQualityPreset::Legacy => true,
3979        }
3980    }
3981
3982    /// Returns whether OCR-style errors are enabled for this preset.
3983    pub fn ocr_errors_enabled(&self) -> bool {
3984        matches!(self, DataQualityPreset::Legacy | DataQualityPreset::High)
3985    }
3986
3987    /// Returns whether encoding issues are enabled for this preset.
3988    pub fn encoding_issues_enabled(&self) -> bool {
3989        matches!(
3990            self,
3991            DataQualityPreset::Legacy | DataQualityPreset::High | DataQualityPreset::Noisy
3992        )
3993    }
3994
3995    /// Returns the encoding issue rate for this preset.
3996    pub fn encoding_issue_rate(&self) -> f64 {
3997        match self {
3998            DataQualityPreset::None | DataQualityPreset::Clean | DataQualityPreset::Minimal => 0.0,
3999            DataQualityPreset::Normal => 0.002,
4000            DataQualityPreset::High => 0.01,
4001            DataQualityPreset::Custom => 0.0,
4002            DataQualityPreset::Noisy => 0.005,
4003            DataQualityPreset::Legacy => 0.02,
4004        }
4005    }
4006
4007    /// Returns true if this preset overrides individual settings.
4008    pub fn overrides_settings(&self) -> bool {
4009        !matches!(self, DataQualityPreset::Custom | DataQualityPreset::None)
4010    }
4011
4012    /// Returns a human-readable description of this preset.
4013    pub fn description(&self) -> &'static str {
4014        match self {
4015            DataQualityPreset::None => "No data quality issues (pristine data)",
4016            DataQualityPreset::Minimal => "Very rare data quality issues",
4017            DataQualityPreset::Normal => "Realistic enterprise data quality",
4018            DataQualityPreset::High => "Messy data for stress testing",
4019            DataQualityPreset::Custom => "Custom settings from configuration",
4020            DataQualityPreset::Clean => "ML-ready clean data with minimal issues",
4021            DataQualityPreset::Noisy => "Typical production data with moderate issues",
4022            DataQualityPreset::Legacy => "Legacy/migrated data with heavy issues and OCR errors",
4023        }
4024    }
4025}
4026
4027/// Missing value injection configuration.
4028#[derive(Debug, Clone, Serialize, Deserialize)]
4029pub struct MissingValuesSchemaConfig {
4030    /// Enable missing value injection
4031    #[serde(default)]
4032    pub enabled: bool,
4033    /// Global missing rate (0.0 to 1.0)
4034    #[serde(default = "default_missing_rate")]
4035    pub rate: f64,
4036    /// Missing value strategy
4037    #[serde(default)]
4038    pub strategy: MissingValueStrategy,
4039    /// Field-specific rates (field name -> rate)
4040    #[serde(default)]
4041    pub field_rates: std::collections::HashMap<String, f64>,
4042    /// Fields that should never have missing values
4043    #[serde(default)]
4044    pub protected_fields: Vec<String>,
4045}
4046
4047fn default_missing_rate() -> f64 {
4048    0.01
4049}
4050
4051impl Default for MissingValuesSchemaConfig {
4052    fn default() -> Self {
4053        Self {
4054            enabled: false,
4055            rate: default_missing_rate(),
4056            strategy: MissingValueStrategy::Mcar,
4057            field_rates: std::collections::HashMap::new(),
4058            protected_fields: vec![
4059                "document_id".to_string(),
4060                "company_code".to_string(),
4061                "posting_date".to_string(),
4062            ],
4063        }
4064    }
4065}
4066
4067/// Missing value strategy types.
4068#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
4069#[serde(rename_all = "snake_case")]
4070pub enum MissingValueStrategy {
4071    /// Missing Completely At Random - equal probability for all values
4072    #[default]
4073    Mcar,
4074    /// Missing At Random - depends on other observed values
4075    Mar,
4076    /// Missing Not At Random - depends on the value itself
4077    Mnar,
4078    /// Systematic - entire field groups missing together
4079    Systematic,
4080}
4081
4082/// Typo injection configuration.
4083#[derive(Debug, Clone, Serialize, Deserialize)]
4084pub struct TypoSchemaConfig {
4085    /// Enable typo injection
4086    #[serde(default)]
4087    pub enabled: bool,
4088    /// Character error rate (per character, not per field)
4089    #[serde(default = "default_typo_rate")]
4090    pub char_error_rate: f64,
4091    /// Typo type weights
4092    #[serde(default)]
4093    pub type_weights: TypoTypeWeights,
4094    /// Fields that should never have typos
4095    #[serde(default)]
4096    pub protected_fields: Vec<String>,
4097}
4098
4099fn default_typo_rate() -> f64 {
4100    0.001
4101}
4102
4103impl Default for TypoSchemaConfig {
4104    fn default() -> Self {
4105        Self {
4106            enabled: false,
4107            char_error_rate: default_typo_rate(),
4108            type_weights: TypoTypeWeights::default(),
4109            protected_fields: vec![
4110                "document_id".to_string(),
4111                "gl_account".to_string(),
4112                "company_code".to_string(),
4113            ],
4114        }
4115    }
4116}
4117
4118/// Weights for different typo types.
4119#[derive(Debug, Clone, Serialize, Deserialize)]
4120pub struct TypoTypeWeights {
4121    /// Keyboard-adjacent substitution (e.g., 'a' -> 's')
4122    #[serde(default = "default_substitution_weight")]
4123    pub substitution: f64,
4124    /// Adjacent character transposition (e.g., 'ab' -> 'ba')
4125    #[serde(default = "default_transposition_weight")]
4126    pub transposition: f64,
4127    /// Character insertion
4128    #[serde(default = "default_insertion_weight")]
4129    pub insertion: f64,
4130    /// Character deletion
4131    #[serde(default = "default_deletion_weight")]
4132    pub deletion: f64,
4133    /// OCR-style errors (e.g., '0' -> 'O')
4134    #[serde(default = "default_ocr_weight")]
4135    pub ocr_errors: f64,
4136    /// Homophone substitution (e.g., 'their' -> 'there')
4137    #[serde(default = "default_homophone_weight")]
4138    pub homophones: f64,
4139}
4140
4141fn default_substitution_weight() -> f64 {
4142    0.35
4143}
4144fn default_transposition_weight() -> f64 {
4145    0.25
4146}
4147fn default_insertion_weight() -> f64 {
4148    0.10
4149}
4150fn default_deletion_weight() -> f64 {
4151    0.15
4152}
4153fn default_ocr_weight() -> f64 {
4154    0.10
4155}
4156fn default_homophone_weight() -> f64 {
4157    0.05
4158}
4159
4160impl Default for TypoTypeWeights {
4161    fn default() -> Self {
4162        Self {
4163            substitution: default_substitution_weight(),
4164            transposition: default_transposition_weight(),
4165            insertion: default_insertion_weight(),
4166            deletion: default_deletion_weight(),
4167            ocr_errors: default_ocr_weight(),
4168            homophones: default_homophone_weight(),
4169        }
4170    }
4171}
4172
4173/// Format variation configuration.
4174#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4175pub struct FormatVariationSchemaConfig {
4176    /// Enable format variations
4177    #[serde(default)]
4178    pub enabled: bool,
4179    /// Date format variation settings
4180    #[serde(default)]
4181    pub dates: DateFormatVariationConfig,
4182    /// Amount format variation settings
4183    #[serde(default)]
4184    pub amounts: AmountFormatVariationConfig,
4185    /// Identifier format variation settings
4186    #[serde(default)]
4187    pub identifiers: IdentifierFormatVariationConfig,
4188}
4189
4190/// Date format variation configuration.
4191#[derive(Debug, Clone, Serialize, Deserialize)]
4192pub struct DateFormatVariationConfig {
4193    /// Enable date format variations
4194    #[serde(default)]
4195    pub enabled: bool,
4196    /// Overall variation rate
4197    #[serde(default = "default_date_variation_rate")]
4198    pub rate: f64,
4199    /// Include ISO format (2024-01-15)
4200    #[serde(default = "default_true")]
4201    pub iso_format: bool,
4202    /// Include US format (01/15/2024)
4203    #[serde(default)]
4204    pub us_format: bool,
4205    /// Include EU format (15.01.2024)
4206    #[serde(default)]
4207    pub eu_format: bool,
4208    /// Include long format (January 15, 2024)
4209    #[serde(default)]
4210    pub long_format: bool,
4211}
4212
4213fn default_date_variation_rate() -> f64 {
4214    0.05
4215}
4216
4217impl Default for DateFormatVariationConfig {
4218    fn default() -> Self {
4219        Self {
4220            enabled: false,
4221            rate: default_date_variation_rate(),
4222            iso_format: true,
4223            us_format: false,
4224            eu_format: false,
4225            long_format: false,
4226        }
4227    }
4228}
4229
4230/// Amount format variation configuration.
4231#[derive(Debug, Clone, Serialize, Deserialize)]
4232pub struct AmountFormatVariationConfig {
4233    /// Enable amount format variations
4234    #[serde(default)]
4235    pub enabled: bool,
4236    /// Overall variation rate
4237    #[serde(default = "default_amount_variation_rate")]
4238    pub rate: f64,
4239    /// Include US comma format (1,234.56)
4240    #[serde(default)]
4241    pub us_comma_format: bool,
4242    /// Include EU format (1.234,56)
4243    #[serde(default)]
4244    pub eu_format: bool,
4245    /// Include currency prefix ($1,234.56)
4246    #[serde(default)]
4247    pub currency_prefix: bool,
4248    /// Include accounting format with parentheses for negatives
4249    #[serde(default)]
4250    pub accounting_format: bool,
4251}
4252
4253fn default_amount_variation_rate() -> f64 {
4254    0.02
4255}
4256
4257impl Default for AmountFormatVariationConfig {
4258    fn default() -> Self {
4259        Self {
4260            enabled: false,
4261            rate: default_amount_variation_rate(),
4262            us_comma_format: false,
4263            eu_format: false,
4264            currency_prefix: false,
4265            accounting_format: false,
4266        }
4267    }
4268}
4269
4270/// Identifier format variation configuration.
4271#[derive(Debug, Clone, Serialize, Deserialize)]
4272pub struct IdentifierFormatVariationConfig {
4273    /// Enable identifier format variations
4274    #[serde(default)]
4275    pub enabled: bool,
4276    /// Overall variation rate
4277    #[serde(default = "default_identifier_variation_rate")]
4278    pub rate: f64,
4279    /// Case variations (uppercase, lowercase, mixed)
4280    #[serde(default)]
4281    pub case_variations: bool,
4282    /// Padding variations (leading zeros)
4283    #[serde(default)]
4284    pub padding_variations: bool,
4285    /// Separator variations (dash vs underscore)
4286    #[serde(default)]
4287    pub separator_variations: bool,
4288}
4289
4290fn default_identifier_variation_rate() -> f64 {
4291    0.02
4292}
4293
4294impl Default for IdentifierFormatVariationConfig {
4295    fn default() -> Self {
4296        Self {
4297            enabled: false,
4298            rate: default_identifier_variation_rate(),
4299            case_variations: false,
4300            padding_variations: false,
4301            separator_variations: false,
4302        }
4303    }
4304}
4305
4306/// Duplicate injection configuration.
4307#[derive(Debug, Clone, Serialize, Deserialize)]
4308pub struct DuplicateSchemaConfig {
4309    /// Enable duplicate injection
4310    #[serde(default)]
4311    pub enabled: bool,
4312    /// Overall duplicate rate
4313    #[serde(default = "default_duplicate_rate")]
4314    pub rate: f64,
4315    /// Exact duplicate proportion (out of duplicates)
4316    #[serde(default = "default_exact_duplicate_ratio")]
4317    pub exact_duplicate_ratio: f64,
4318    /// Near duplicate proportion (slight variations)
4319    #[serde(default = "default_near_duplicate_ratio")]
4320    pub near_duplicate_ratio: f64,
4321    /// Fuzzy duplicate proportion (typos in key fields)
4322    #[serde(default = "default_fuzzy_duplicate_ratio")]
4323    pub fuzzy_duplicate_ratio: f64,
4324    /// Maximum date offset for near/fuzzy duplicates (days)
4325    #[serde(default = "default_max_date_offset")]
4326    pub max_date_offset_days: u32,
4327    /// Maximum amount variance for near duplicates (fraction)
4328    #[serde(default = "default_max_amount_variance")]
4329    pub max_amount_variance: f64,
4330}
4331
4332fn default_duplicate_rate() -> f64 {
4333    0.005
4334}
4335fn default_exact_duplicate_ratio() -> f64 {
4336    0.4
4337}
4338fn default_near_duplicate_ratio() -> f64 {
4339    0.35
4340}
4341fn default_fuzzy_duplicate_ratio() -> f64 {
4342    0.25
4343}
4344fn default_max_date_offset() -> u32 {
4345    3
4346}
4347fn default_max_amount_variance() -> f64 {
4348    0.01
4349}
4350
4351impl Default for DuplicateSchemaConfig {
4352    fn default() -> Self {
4353        Self {
4354            enabled: false,
4355            rate: default_duplicate_rate(),
4356            exact_duplicate_ratio: default_exact_duplicate_ratio(),
4357            near_duplicate_ratio: default_near_duplicate_ratio(),
4358            fuzzy_duplicate_ratio: default_fuzzy_duplicate_ratio(),
4359            max_date_offset_days: default_max_date_offset(),
4360            max_amount_variance: default_max_amount_variance(),
4361        }
4362    }
4363}
4364
4365/// Encoding issue configuration.
4366#[derive(Debug, Clone, Serialize, Deserialize)]
4367pub struct EncodingIssueSchemaConfig {
4368    /// Enable encoding issue injection
4369    #[serde(default)]
4370    pub enabled: bool,
4371    /// Overall encoding issue rate
4372    #[serde(default = "default_encoding_rate")]
4373    pub rate: f64,
4374    /// Include mojibake (UTF-8/Latin-1 confusion)
4375    #[serde(default)]
4376    pub mojibake: bool,
4377    /// Include HTML entity corruption
4378    #[serde(default)]
4379    pub html_entities: bool,
4380    /// Include BOM issues
4381    #[serde(default)]
4382    pub bom_issues: bool,
4383}
4384
4385fn default_encoding_rate() -> f64 {
4386    0.001
4387}
4388
4389impl Default for EncodingIssueSchemaConfig {
4390    fn default() -> Self {
4391        Self {
4392            enabled: false,
4393            rate: default_encoding_rate(),
4394            mojibake: false,
4395            html_entities: false,
4396            bom_issues: false,
4397        }
4398    }
4399}
4400
4401/// Per-sink quality profiles for different output formats.
4402#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4403pub struct SinkQualityProfiles {
4404    /// CSV-specific quality settings
4405    #[serde(default)]
4406    pub csv: Option<SinkQualityOverride>,
4407    /// JSON-specific quality settings
4408    #[serde(default)]
4409    pub json: Option<SinkQualityOverride>,
4410    /// Parquet-specific quality settings
4411    #[serde(default)]
4412    pub parquet: Option<SinkQualityOverride>,
4413}
4414
4415/// Quality setting overrides for a specific sink type.
4416#[derive(Debug, Clone, Serialize, Deserialize)]
4417pub struct SinkQualityOverride {
4418    /// Override enabled state
4419    pub enabled: Option<bool>,
4420    /// Override missing value rate
4421    pub missing_rate: Option<f64>,
4422    /// Override typo rate
4423    pub typo_rate: Option<f64>,
4424    /// Override format variation rate
4425    pub format_variation_rate: Option<f64>,
4426    /// Override duplicate rate
4427    pub duplicate_rate: Option<f64>,
4428}
4429
4430// =============================================================================
4431// Accounting Standards Configuration
4432// =============================================================================
4433
4434/// Accounting standards framework configuration for generating standards-compliant data.
4435///
4436/// Supports US GAAP and IFRS frameworks with specific standards:
4437/// - ASC 606/IFRS 15: Revenue Recognition
4438/// - ASC 842/IFRS 16: Leases
4439/// - ASC 820/IFRS 13: Fair Value Measurement
4440/// - ASC 360/IAS 36: Impairment
4441#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4442pub struct AccountingStandardsConfig {
4443    /// Enable accounting standards generation
4444    #[serde(default)]
4445    pub enabled: bool,
4446
4447    /// Accounting framework to use
4448    #[serde(default)]
4449    pub framework: AccountingFrameworkConfig,
4450
4451    /// Revenue recognition configuration (ASC 606/IFRS 15)
4452    #[serde(default)]
4453    pub revenue_recognition: RevenueRecognitionConfig,
4454
4455    /// Lease accounting configuration (ASC 842/IFRS 16)
4456    #[serde(default)]
4457    pub leases: LeaseAccountingConfig,
4458
4459    /// Fair value measurement configuration (ASC 820/IFRS 13)
4460    #[serde(default)]
4461    pub fair_value: FairValueConfig,
4462
4463    /// Impairment testing configuration (ASC 360/IAS 36)
4464    #[serde(default)]
4465    pub impairment: ImpairmentConfig,
4466
4467    /// Generate framework differences for dual reporting
4468    #[serde(default)]
4469    pub generate_differences: bool,
4470}
4471
4472/// Accounting framework selection.
4473#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
4474#[serde(rename_all = "snake_case")]
4475pub enum AccountingFrameworkConfig {
4476    /// US Generally Accepted Accounting Principles
4477    #[default]
4478    UsGaap,
4479    /// International Financial Reporting Standards
4480    Ifrs,
4481    /// Generate data for both frameworks with reconciliation
4482    DualReporting,
4483}
4484
4485/// Revenue recognition configuration (ASC 606/IFRS 15).
4486#[derive(Debug, Clone, Serialize, Deserialize)]
4487pub struct RevenueRecognitionConfig {
4488    /// Enable revenue recognition generation
4489    #[serde(default)]
4490    pub enabled: bool,
4491
4492    /// Generate customer contracts
4493    #[serde(default = "default_true")]
4494    pub generate_contracts: bool,
4495
4496    /// Average number of performance obligations per contract
4497    #[serde(default = "default_avg_obligations")]
4498    pub avg_obligations_per_contract: f64,
4499
4500    /// Rate of contracts with variable consideration
4501    #[serde(default = "default_variable_consideration_rate")]
4502    pub variable_consideration_rate: f64,
4503
4504    /// Rate of over-time revenue recognition (vs point-in-time)
4505    #[serde(default = "default_over_time_rate")]
4506    pub over_time_recognition_rate: f64,
4507
4508    /// Number of contracts to generate
4509    #[serde(default = "default_contract_count")]
4510    pub contract_count: usize,
4511}
4512
4513fn default_avg_obligations() -> f64 {
4514    2.0
4515}
4516
4517fn default_variable_consideration_rate() -> f64 {
4518    0.15
4519}
4520
4521fn default_over_time_rate() -> f64 {
4522    0.30
4523}
4524
4525fn default_contract_count() -> usize {
4526    100
4527}
4528
4529impl Default for RevenueRecognitionConfig {
4530    fn default() -> Self {
4531        Self {
4532            enabled: false,
4533            generate_contracts: true,
4534            avg_obligations_per_contract: default_avg_obligations(),
4535            variable_consideration_rate: default_variable_consideration_rate(),
4536            over_time_recognition_rate: default_over_time_rate(),
4537            contract_count: default_contract_count(),
4538        }
4539    }
4540}
4541
4542/// Lease accounting configuration (ASC 842/IFRS 16).
4543#[derive(Debug, Clone, Serialize, Deserialize)]
4544pub struct LeaseAccountingConfig {
4545    /// Enable lease accounting generation
4546    #[serde(default)]
4547    pub enabled: bool,
4548
4549    /// Number of leases to generate
4550    #[serde(default = "default_lease_count")]
4551    pub lease_count: usize,
4552
4553    /// Percentage of finance leases (vs operating)
4554    #[serde(default = "default_finance_lease_pct")]
4555    pub finance_lease_percent: f64,
4556
4557    /// Average lease term in months
4558    #[serde(default = "default_avg_lease_term")]
4559    pub avg_lease_term_months: u32,
4560
4561    /// Generate amortization schedules
4562    #[serde(default = "default_true")]
4563    pub generate_amortization: bool,
4564
4565    /// Real estate lease percentage
4566    #[serde(default = "default_real_estate_pct")]
4567    pub real_estate_percent: f64,
4568}
4569
4570fn default_lease_count() -> usize {
4571    50
4572}
4573
4574fn default_finance_lease_pct() -> f64 {
4575    0.30
4576}
4577
4578fn default_avg_lease_term() -> u32 {
4579    60
4580}
4581
4582fn default_real_estate_pct() -> f64 {
4583    0.40
4584}
4585
4586impl Default for LeaseAccountingConfig {
4587    fn default() -> Self {
4588        Self {
4589            enabled: false,
4590            lease_count: default_lease_count(),
4591            finance_lease_percent: default_finance_lease_pct(),
4592            avg_lease_term_months: default_avg_lease_term(),
4593            generate_amortization: true,
4594            real_estate_percent: default_real_estate_pct(),
4595        }
4596    }
4597}
4598
4599/// Fair value measurement configuration (ASC 820/IFRS 13).
4600#[derive(Debug, Clone, Serialize, Deserialize)]
4601pub struct FairValueConfig {
4602    /// Enable fair value measurement generation
4603    #[serde(default)]
4604    pub enabled: bool,
4605
4606    /// Number of fair value measurements to generate
4607    #[serde(default = "default_fv_count")]
4608    pub measurement_count: usize,
4609
4610    /// Level 1 (quoted prices) percentage
4611    #[serde(default = "default_level1_pct")]
4612    pub level1_percent: f64,
4613
4614    /// Level 2 (observable inputs) percentage
4615    #[serde(default = "default_level2_pct")]
4616    pub level2_percent: f64,
4617
4618    /// Level 3 (unobservable inputs) percentage
4619    #[serde(default = "default_level3_pct")]
4620    pub level3_percent: f64,
4621
4622    /// Include sensitivity analysis for Level 3
4623    #[serde(default)]
4624    pub include_sensitivity_analysis: bool,
4625}
4626
4627fn default_fv_count() -> usize {
4628    25
4629}
4630
4631fn default_level1_pct() -> f64 {
4632    0.40
4633}
4634
4635fn default_level2_pct() -> f64 {
4636    0.35
4637}
4638
4639fn default_level3_pct() -> f64 {
4640    0.25
4641}
4642
4643impl Default for FairValueConfig {
4644    fn default() -> Self {
4645        Self {
4646            enabled: false,
4647            measurement_count: default_fv_count(),
4648            level1_percent: default_level1_pct(),
4649            level2_percent: default_level2_pct(),
4650            level3_percent: default_level3_pct(),
4651            include_sensitivity_analysis: false,
4652        }
4653    }
4654}
4655
4656/// Impairment testing configuration (ASC 360/IAS 36).
4657#[derive(Debug, Clone, Serialize, Deserialize)]
4658pub struct ImpairmentConfig {
4659    /// Enable impairment testing generation
4660    #[serde(default)]
4661    pub enabled: bool,
4662
4663    /// Number of impairment tests to generate
4664    #[serde(default = "default_impairment_count")]
4665    pub test_count: usize,
4666
4667    /// Rate of tests resulting in impairment
4668    #[serde(default = "default_impairment_rate")]
4669    pub impairment_rate: f64,
4670
4671    /// Generate cash flow projections
4672    #[serde(default = "default_true")]
4673    pub generate_projections: bool,
4674
4675    /// Include goodwill impairment tests
4676    #[serde(default)]
4677    pub include_goodwill: bool,
4678}
4679
4680fn default_impairment_count() -> usize {
4681    15
4682}
4683
4684fn default_impairment_rate() -> f64 {
4685    0.10
4686}
4687
4688impl Default for ImpairmentConfig {
4689    fn default() -> Self {
4690        Self {
4691            enabled: false,
4692            test_count: default_impairment_count(),
4693            impairment_rate: default_impairment_rate(),
4694            generate_projections: true,
4695            include_goodwill: false,
4696        }
4697    }
4698}
4699
4700// =============================================================================
4701// Audit Standards Configuration
4702// =============================================================================
4703
4704/// Audit standards framework configuration for generating standards-compliant audit data.
4705///
4706/// Supports ISA (International Standards on Auditing) and PCAOB standards:
4707/// - ISA 200-720: Complete coverage of audit standards
4708/// - ISA 520: Analytical Procedures
4709/// - ISA 505: External Confirmations
4710/// - ISA 700/705/706/701: Audit Reports
4711/// - PCAOB AS 2201: ICFR Auditing
4712#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4713pub struct AuditStandardsConfig {
4714    /// Enable audit standards generation
4715    #[serde(default)]
4716    pub enabled: bool,
4717
4718    /// ISA compliance configuration
4719    #[serde(default)]
4720    pub isa_compliance: IsaComplianceConfig,
4721
4722    /// Analytical procedures configuration (ISA 520)
4723    #[serde(default)]
4724    pub analytical_procedures: AnalyticalProceduresConfig,
4725
4726    /// External confirmations configuration (ISA 505)
4727    #[serde(default)]
4728    pub confirmations: ConfirmationsConfig,
4729
4730    /// Audit opinion configuration (ISA 700/705/706/701)
4731    #[serde(default)]
4732    pub opinion: AuditOpinionConfig,
4733
4734    /// Generate complete audit trail with traceability
4735    #[serde(default)]
4736    pub generate_audit_trail: bool,
4737
4738    /// SOX 302/404 compliance configuration
4739    #[serde(default)]
4740    pub sox: SoxComplianceConfig,
4741
4742    /// PCAOB-specific configuration
4743    #[serde(default)]
4744    pub pcaob: PcaobConfig,
4745}
4746
4747/// ISA compliance level configuration.
4748#[derive(Debug, Clone, Serialize, Deserialize)]
4749pub struct IsaComplianceConfig {
4750    /// Enable ISA compliance tracking
4751    #[serde(default)]
4752    pub enabled: bool,
4753
4754    /// Compliance level: "basic", "standard", "comprehensive"
4755    #[serde(default = "default_compliance_level")]
4756    pub compliance_level: String,
4757
4758    /// Generate ISA requirement mappings
4759    #[serde(default = "default_true")]
4760    pub generate_isa_mappings: bool,
4761
4762    /// Generate ISA coverage summary
4763    #[serde(default = "default_true")]
4764    pub generate_coverage_summary: bool,
4765
4766    /// Include PCAOB standard mappings (for dual framework)
4767    #[serde(default)]
4768    pub include_pcaob: bool,
4769
4770    /// Framework to use: "isa", "pcaob", "dual"
4771    #[serde(default = "default_audit_framework")]
4772    pub framework: String,
4773}
4774
4775fn default_compliance_level() -> String {
4776    "standard".to_string()
4777}
4778
4779fn default_audit_framework() -> String {
4780    "isa".to_string()
4781}
4782
4783impl Default for IsaComplianceConfig {
4784    fn default() -> Self {
4785        Self {
4786            enabled: false,
4787            compliance_level: default_compliance_level(),
4788            generate_isa_mappings: true,
4789            generate_coverage_summary: true,
4790            include_pcaob: false,
4791            framework: default_audit_framework(),
4792        }
4793    }
4794}
4795
4796/// Analytical procedures configuration (ISA 520).
4797#[derive(Debug, Clone, Serialize, Deserialize)]
4798pub struct AnalyticalProceduresConfig {
4799    /// Enable analytical procedures generation
4800    #[serde(default)]
4801    pub enabled: bool,
4802
4803    /// Number of procedures per account/area
4804    #[serde(default = "default_procedures_per_account")]
4805    pub procedures_per_account: usize,
4806
4807    /// Probability of variance exceeding threshold
4808    #[serde(default = "default_variance_probability")]
4809    pub variance_probability: f64,
4810
4811    /// Include variance investigations
4812    #[serde(default = "default_true")]
4813    pub generate_investigations: bool,
4814
4815    /// Include financial ratio analysis
4816    #[serde(default = "default_true")]
4817    pub include_ratio_analysis: bool,
4818}
4819
4820fn default_procedures_per_account() -> usize {
4821    3
4822}
4823
4824fn default_variance_probability() -> f64 {
4825    0.20
4826}
4827
4828impl Default for AnalyticalProceduresConfig {
4829    fn default() -> Self {
4830        Self {
4831            enabled: false,
4832            procedures_per_account: default_procedures_per_account(),
4833            variance_probability: default_variance_probability(),
4834            generate_investigations: true,
4835            include_ratio_analysis: true,
4836        }
4837    }
4838}
4839
4840/// External confirmations configuration (ISA 505).
4841#[derive(Debug, Clone, Serialize, Deserialize)]
4842pub struct ConfirmationsConfig {
4843    /// Enable confirmation generation
4844    #[serde(default)]
4845    pub enabled: bool,
4846
4847    /// Number of confirmations to generate
4848    #[serde(default = "default_confirmation_count")]
4849    pub confirmation_count: usize,
4850
4851    /// Positive response rate
4852    #[serde(default = "default_positive_response_rate")]
4853    pub positive_response_rate: f64,
4854
4855    /// Exception rate (responses with differences)
4856    #[serde(default = "default_exception_rate_confirm")]
4857    pub exception_rate: f64,
4858
4859    /// Non-response rate
4860    #[serde(default = "default_non_response_rate")]
4861    pub non_response_rate: f64,
4862
4863    /// Generate alternative procedures for non-responses
4864    #[serde(default = "default_true")]
4865    pub generate_alternative_procedures: bool,
4866}
4867
4868fn default_confirmation_count() -> usize {
4869    50
4870}
4871
4872fn default_positive_response_rate() -> f64 {
4873    0.85
4874}
4875
4876fn default_exception_rate_confirm() -> f64 {
4877    0.10
4878}
4879
4880fn default_non_response_rate() -> f64 {
4881    0.05
4882}
4883
4884impl Default for ConfirmationsConfig {
4885    fn default() -> Self {
4886        Self {
4887            enabled: false,
4888            confirmation_count: default_confirmation_count(),
4889            positive_response_rate: default_positive_response_rate(),
4890            exception_rate: default_exception_rate_confirm(),
4891            non_response_rate: default_non_response_rate(),
4892            generate_alternative_procedures: true,
4893        }
4894    }
4895}
4896
4897/// Audit opinion configuration (ISA 700/705/706/701).
4898#[derive(Debug, Clone, Serialize, Deserialize)]
4899pub struct AuditOpinionConfig {
4900    /// Enable audit opinion generation
4901    #[serde(default)]
4902    pub enabled: bool,
4903
4904    /// Generate Key Audit Matters (KAM) / Critical Audit Matters (CAM)
4905    #[serde(default = "default_true")]
4906    pub generate_kam: bool,
4907
4908    /// Average number of KAMs/CAMs per opinion
4909    #[serde(default = "default_kam_count")]
4910    pub average_kam_count: usize,
4911
4912    /// Rate of modified opinions
4913    #[serde(default = "default_modified_opinion_rate")]
4914    pub modified_opinion_rate: f64,
4915
4916    /// Include emphasis of matter paragraphs
4917    #[serde(default)]
4918    pub include_emphasis_of_matter: bool,
4919
4920    /// Include going concern conclusions
4921    #[serde(default = "default_true")]
4922    pub include_going_concern: bool,
4923}
4924
4925fn default_kam_count() -> usize {
4926    3
4927}
4928
4929fn default_modified_opinion_rate() -> f64 {
4930    0.05
4931}
4932
4933impl Default for AuditOpinionConfig {
4934    fn default() -> Self {
4935        Self {
4936            enabled: false,
4937            generate_kam: true,
4938            average_kam_count: default_kam_count(),
4939            modified_opinion_rate: default_modified_opinion_rate(),
4940            include_emphasis_of_matter: false,
4941            include_going_concern: true,
4942        }
4943    }
4944}
4945
4946/// SOX compliance configuration (Sections 302/404).
4947#[derive(Debug, Clone, Serialize, Deserialize)]
4948pub struct SoxComplianceConfig {
4949    /// Enable SOX compliance generation
4950    #[serde(default)]
4951    pub enabled: bool,
4952
4953    /// Generate Section 302 CEO/CFO certifications
4954    #[serde(default = "default_true")]
4955    pub generate_302_certifications: bool,
4956
4957    /// Generate Section 404 ICFR assessments
4958    #[serde(default = "default_true")]
4959    pub generate_404_assessments: bool,
4960
4961    /// Materiality threshold for SOX testing
4962    #[serde(default = "default_sox_materiality_threshold")]
4963    pub materiality_threshold: f64,
4964
4965    /// Rate of material weaknesses
4966    #[serde(default = "default_material_weakness_rate")]
4967    pub material_weakness_rate: f64,
4968
4969    /// Rate of significant deficiencies
4970    #[serde(default = "default_significant_deficiency_rate")]
4971    pub significant_deficiency_rate: f64,
4972}
4973
4974fn default_material_weakness_rate() -> f64 {
4975    0.02
4976}
4977
4978fn default_significant_deficiency_rate() -> f64 {
4979    0.08
4980}
4981
4982impl Default for SoxComplianceConfig {
4983    fn default() -> Self {
4984        Self {
4985            enabled: false,
4986            generate_302_certifications: true,
4987            generate_404_assessments: true,
4988            materiality_threshold: default_sox_materiality_threshold(),
4989            material_weakness_rate: default_material_weakness_rate(),
4990            significant_deficiency_rate: default_significant_deficiency_rate(),
4991        }
4992    }
4993}
4994
4995/// PCAOB-specific configuration.
4996#[derive(Debug, Clone, Serialize, Deserialize)]
4997pub struct PcaobConfig {
4998    /// Enable PCAOB-specific elements
4999    #[serde(default)]
5000    pub enabled: bool,
5001
5002    /// Treat as PCAOB audit (vs ISA-only)
5003    #[serde(default)]
5004    pub is_pcaob_audit: bool,
5005
5006    /// Generate Critical Audit Matters (CAM)
5007    #[serde(default = "default_true")]
5008    pub generate_cam: bool,
5009
5010    /// Include ICFR opinion (for integrated audits)
5011    #[serde(default)]
5012    pub include_icfr_opinion: bool,
5013
5014    /// Generate PCAOB-ISA standard mappings
5015    #[serde(default)]
5016    pub generate_standard_mappings: bool,
5017}
5018
5019impl Default for PcaobConfig {
5020    fn default() -> Self {
5021        Self {
5022            enabled: false,
5023            is_pcaob_audit: false,
5024            generate_cam: true,
5025            include_icfr_opinion: false,
5026            generate_standard_mappings: false,
5027        }
5028    }
5029}
5030
5031// =============================================================================
5032// Advanced Distribution Configuration
5033// =============================================================================
5034
5035/// Advanced distribution configuration for realistic data generation.
5036///
5037/// This section enables sophisticated distribution models including:
5038/// - Mixture models (multi-modal distributions)
5039/// - Cross-field correlations
5040/// - Conditional distributions
5041/// - Regime changes and economic cycles
5042/// - Statistical validation
5043#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5044pub struct AdvancedDistributionConfig {
5045    /// Enable advanced distribution features.
5046    #[serde(default)]
5047    pub enabled: bool,
5048
5049    /// Mixture model configuration for amounts.
5050    #[serde(default)]
5051    pub amounts: MixtureDistributionSchemaConfig,
5052
5053    /// Cross-field correlation configuration.
5054    #[serde(default)]
5055    pub correlations: CorrelationSchemaConfig,
5056
5057    /// Conditional distribution configurations.
5058    #[serde(default)]
5059    pub conditional: Vec<ConditionalDistributionSchemaConfig>,
5060
5061    /// Regime change configuration.
5062    #[serde(default)]
5063    pub regime_changes: RegimeChangeSchemaConfig,
5064
5065    /// Industry-specific distribution profile.
5066    #[serde(default)]
5067    pub industry_profile: Option<IndustryProfileType>,
5068
5069    /// Statistical validation configuration.
5070    #[serde(default)]
5071    pub validation: StatisticalValidationSchemaConfig,
5072}
5073
5074/// Industry profile types for pre-configured distribution settings.
5075#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
5076#[serde(rename_all = "snake_case")]
5077pub enum IndustryProfileType {
5078    /// Retail industry profile (POS sales, inventory, seasonal)
5079    Retail,
5080    /// Manufacturing industry profile (raw materials, maintenance, capital)
5081    Manufacturing,
5082    /// Financial services profile (wire transfers, ACH, fee income)
5083    FinancialServices,
5084    /// Healthcare profile (claims, procedures, supplies)
5085    Healthcare,
5086    /// Technology profile (subscriptions, services, R&D)
5087    Technology,
5088}
5089
5090/// Mixture model distribution configuration.
5091#[derive(Debug, Clone, Serialize, Deserialize)]
5092pub struct MixtureDistributionSchemaConfig {
5093    /// Enable mixture model for amount generation.
5094    #[serde(default)]
5095    pub enabled: bool,
5096
5097    /// Distribution type: "gaussian" or "lognormal".
5098    #[serde(default = "default_mixture_type")]
5099    pub distribution_type: MixtureDistributionType,
5100
5101    /// Mixture components with weights.
5102    #[serde(default)]
5103    pub components: Vec<MixtureComponentConfig>,
5104
5105    /// Minimum value constraint.
5106    #[serde(default = "default_min_amount")]
5107    pub min_value: f64,
5108
5109    /// Maximum value constraint (optional).
5110    #[serde(default)]
5111    pub max_value: Option<f64>,
5112
5113    /// Decimal places for rounding.
5114    #[serde(default = "default_decimal_places")]
5115    pub decimal_places: u8,
5116}
5117
5118fn default_mixture_type() -> MixtureDistributionType {
5119    MixtureDistributionType::LogNormal
5120}
5121
5122fn default_min_amount() -> f64 {
5123    0.01
5124}
5125
5126fn default_decimal_places() -> u8 {
5127    2
5128}
5129
5130impl Default for MixtureDistributionSchemaConfig {
5131    fn default() -> Self {
5132        Self {
5133            enabled: false,
5134            distribution_type: MixtureDistributionType::LogNormal,
5135            components: Vec::new(),
5136            min_value: 0.01,
5137            max_value: None,
5138            decimal_places: 2,
5139        }
5140    }
5141}
5142
5143/// Mixture distribution type.
5144#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5145#[serde(rename_all = "snake_case")]
5146pub enum MixtureDistributionType {
5147    /// Gaussian (normal) mixture
5148    Gaussian,
5149    /// Log-normal mixture (for positive amounts)
5150    #[default]
5151    LogNormal,
5152}
5153
5154/// Configuration for a single mixture component.
5155#[derive(Debug, Clone, Serialize, Deserialize)]
5156pub struct MixtureComponentConfig {
5157    /// Weight of this component (must sum to 1.0 across all components).
5158    pub weight: f64,
5159
5160    /// Location parameter (mean for Gaussian, mu for log-normal).
5161    pub mu: f64,
5162
5163    /// Scale parameter (std dev for Gaussian, sigma for log-normal).
5164    pub sigma: f64,
5165
5166    /// Optional label for this component (e.g., "routine", "significant", "major").
5167    #[serde(default)]
5168    pub label: Option<String>,
5169}
5170
5171/// Cross-field correlation configuration.
5172#[derive(Debug, Clone, Serialize, Deserialize)]
5173pub struct CorrelationSchemaConfig {
5174    /// Enable correlation modeling.
5175    #[serde(default)]
5176    pub enabled: bool,
5177
5178    /// Copula type for dependency modeling.
5179    #[serde(default)]
5180    pub copula_type: CopulaSchemaType,
5181
5182    /// Field definitions for correlation.
5183    #[serde(default)]
5184    pub fields: Vec<CorrelatedFieldConfig>,
5185
5186    /// Correlation matrix (upper triangular, row-major).
5187    /// For n fields, this should have n*(n-1)/2 values.
5188    #[serde(default)]
5189    pub matrix: Vec<f64>,
5190
5191    /// Expected correlations for validation.
5192    #[serde(default)]
5193    pub expected_correlations: Vec<ExpectedCorrelationConfig>,
5194}
5195
5196impl Default for CorrelationSchemaConfig {
5197    fn default() -> Self {
5198        Self {
5199            enabled: false,
5200            copula_type: CopulaSchemaType::Gaussian,
5201            fields: Vec::new(),
5202            matrix: Vec::new(),
5203            expected_correlations: Vec::new(),
5204        }
5205    }
5206}
5207
5208/// Copula type for dependency modeling.
5209#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5210#[serde(rename_all = "snake_case")]
5211pub enum CopulaSchemaType {
5212    /// Gaussian copula (symmetric, no tail dependence)
5213    #[default]
5214    Gaussian,
5215    /// Clayton copula (lower tail dependence)
5216    Clayton,
5217    /// Gumbel copula (upper tail dependence)
5218    Gumbel,
5219    /// Frank copula (symmetric, no tail dependence)
5220    Frank,
5221    /// Student-t copula (both tail dependencies)
5222    StudentT,
5223}
5224
5225/// Configuration for a correlated field.
5226#[derive(Debug, Clone, Serialize, Deserialize)]
5227pub struct CorrelatedFieldConfig {
5228    /// Field name.
5229    pub name: String,
5230
5231    /// Marginal distribution type.
5232    #[serde(default)]
5233    pub distribution: MarginalDistributionConfig,
5234}
5235
5236/// Marginal distribution configuration.
5237#[derive(Debug, Clone, Serialize, Deserialize)]
5238#[serde(tag = "type", rename_all = "snake_case")]
5239pub enum MarginalDistributionConfig {
5240    /// Normal distribution.
5241    Normal {
5242        /// Mean
5243        mu: f64,
5244        /// Standard deviation
5245        sigma: f64,
5246    },
5247    /// Log-normal distribution.
5248    LogNormal {
5249        /// Location parameter
5250        mu: f64,
5251        /// Scale parameter
5252        sigma: f64,
5253    },
5254    /// Uniform distribution.
5255    Uniform {
5256        /// Minimum value
5257        min: f64,
5258        /// Maximum value
5259        max: f64,
5260    },
5261    /// Discrete uniform distribution.
5262    DiscreteUniform {
5263        /// Minimum integer value
5264        min: i32,
5265        /// Maximum integer value
5266        max: i32,
5267    },
5268}
5269
5270impl Default for MarginalDistributionConfig {
5271    fn default() -> Self {
5272        Self::Normal {
5273            mu: 0.0,
5274            sigma: 1.0,
5275        }
5276    }
5277}
5278
5279/// Expected correlation for validation.
5280#[derive(Debug, Clone, Serialize, Deserialize)]
5281pub struct ExpectedCorrelationConfig {
5282    /// First field name.
5283    pub field1: String,
5284    /// Second field name.
5285    pub field2: String,
5286    /// Expected correlation coefficient.
5287    pub expected_r: f64,
5288    /// Acceptable tolerance.
5289    #[serde(default = "default_correlation_tolerance")]
5290    pub tolerance: f64,
5291}
5292
5293fn default_correlation_tolerance() -> f64 {
5294    0.10
5295}
5296
5297/// Conditional distribution configuration.
5298#[derive(Debug, Clone, Serialize, Deserialize)]
5299pub struct ConditionalDistributionSchemaConfig {
5300    /// Output field name to generate.
5301    pub output_field: String,
5302
5303    /// Input field name that conditions the distribution.
5304    pub input_field: String,
5305
5306    /// Breakpoints defining distribution changes.
5307    #[serde(default)]
5308    pub breakpoints: Vec<ConditionalBreakpointConfig>,
5309
5310    /// Default distribution when below all breakpoints.
5311    #[serde(default)]
5312    pub default_distribution: ConditionalDistributionParamsConfig,
5313
5314    /// Minimum output value constraint.
5315    #[serde(default)]
5316    pub min_value: Option<f64>,
5317
5318    /// Maximum output value constraint.
5319    #[serde(default)]
5320    pub max_value: Option<f64>,
5321
5322    /// Decimal places for output rounding.
5323    #[serde(default = "default_decimal_places")]
5324    pub decimal_places: u8,
5325}
5326
5327/// Breakpoint for conditional distribution.
5328#[derive(Debug, Clone, Serialize, Deserialize)]
5329pub struct ConditionalBreakpointConfig {
5330    /// Input value threshold.
5331    pub threshold: f64,
5332
5333    /// Distribution to use when input >= threshold.
5334    pub distribution: ConditionalDistributionParamsConfig,
5335}
5336
5337/// Distribution parameters for conditional distributions.
5338#[derive(Debug, Clone, Serialize, Deserialize)]
5339#[serde(tag = "type", rename_all = "snake_case")]
5340pub enum ConditionalDistributionParamsConfig {
5341    /// Fixed value.
5342    Fixed {
5343        /// The fixed value
5344        value: f64,
5345    },
5346    /// Normal distribution.
5347    Normal {
5348        /// Mean
5349        mu: f64,
5350        /// Standard deviation
5351        sigma: f64,
5352    },
5353    /// Log-normal distribution.
5354    LogNormal {
5355        /// Location parameter
5356        mu: f64,
5357        /// Scale parameter
5358        sigma: f64,
5359    },
5360    /// Uniform distribution.
5361    Uniform {
5362        /// Minimum
5363        min: f64,
5364        /// Maximum
5365        max: f64,
5366    },
5367    /// Beta distribution (scaled).
5368    Beta {
5369        /// Alpha parameter
5370        alpha: f64,
5371        /// Beta parameter
5372        beta: f64,
5373        /// Minimum output value
5374        min: f64,
5375        /// Maximum output value
5376        max: f64,
5377    },
5378    /// Discrete values with weights.
5379    Discrete {
5380        /// Possible values
5381        values: Vec<f64>,
5382        /// Weights (should sum to 1.0)
5383        weights: Vec<f64>,
5384    },
5385}
5386
5387impl Default for ConditionalDistributionParamsConfig {
5388    fn default() -> Self {
5389        Self::Normal {
5390            mu: 0.0,
5391            sigma: 1.0,
5392        }
5393    }
5394}
5395
5396/// Regime change configuration.
5397#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5398pub struct RegimeChangeSchemaConfig {
5399    /// Enable regime change modeling.
5400    #[serde(default)]
5401    pub enabled: bool,
5402
5403    /// List of regime changes.
5404    #[serde(default)]
5405    pub changes: Vec<RegimeChangeEventConfig>,
5406
5407    /// Economic cycle configuration.
5408    #[serde(default)]
5409    pub economic_cycle: Option<EconomicCycleSchemaConfig>,
5410
5411    /// Parameter drift configurations.
5412    #[serde(default)]
5413    pub parameter_drifts: Vec<ParameterDriftSchemaConfig>,
5414}
5415
5416/// A single regime change event.
5417#[derive(Debug, Clone, Serialize, Deserialize)]
5418pub struct RegimeChangeEventConfig {
5419    /// Date when the change occurs (ISO 8601 format).
5420    pub date: String,
5421
5422    /// Type of regime change.
5423    pub change_type: RegimeChangeTypeConfig,
5424
5425    /// Description of the change.
5426    #[serde(default)]
5427    pub description: Option<String>,
5428
5429    /// Effects of this regime change.
5430    #[serde(default)]
5431    pub effects: Vec<RegimeEffectConfig>,
5432}
5433
5434/// Type of regime change.
5435#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
5436#[serde(rename_all = "snake_case")]
5437pub enum RegimeChangeTypeConfig {
5438    /// Acquisition - sudden volume and amount increase
5439    Acquisition,
5440    /// Divestiture - sudden volume and amount decrease
5441    Divestiture,
5442    /// Price increase - amounts increase
5443    PriceIncrease,
5444    /// Price decrease - amounts decrease
5445    PriceDecrease,
5446    /// New product launch - volume ramp-up
5447    ProductLaunch,
5448    /// Product discontinuation - volume ramp-down
5449    ProductDiscontinuation,
5450    /// Policy change - affects patterns
5451    PolicyChange,
5452    /// Competitor entry - market disruption
5453    CompetitorEntry,
5454    /// Custom effect
5455    Custom,
5456}
5457
5458/// Effect of a regime change on a specific field.
5459#[derive(Debug, Clone, Serialize, Deserialize)]
5460pub struct RegimeEffectConfig {
5461    /// Field being affected.
5462    pub field: String,
5463
5464    /// Multiplier to apply (1.0 = no change, 1.5 = 50% increase).
5465    pub multiplier: f64,
5466}
5467
5468/// Economic cycle configuration.
5469#[derive(Debug, Clone, Serialize, Deserialize)]
5470pub struct EconomicCycleSchemaConfig {
5471    /// Enable economic cycle modeling.
5472    #[serde(default)]
5473    pub enabled: bool,
5474
5475    /// Cycle period in months (e.g., 48 for 4-year business cycle).
5476    #[serde(default = "default_cycle_period")]
5477    pub period_months: u32,
5478
5479    /// Amplitude of cycle effect (0.0-1.0).
5480    #[serde(default = "default_cycle_amplitude")]
5481    pub amplitude: f64,
5482
5483    /// Phase offset in months.
5484    #[serde(default)]
5485    pub phase_offset: u32,
5486
5487    /// Recession periods (start_month, duration_months).
5488    #[serde(default)]
5489    pub recessions: Vec<RecessionPeriodConfig>,
5490}
5491
5492fn default_cycle_period() -> u32 {
5493    48
5494}
5495
5496fn default_cycle_amplitude() -> f64 {
5497    0.15
5498}
5499
5500impl Default for EconomicCycleSchemaConfig {
5501    fn default() -> Self {
5502        Self {
5503            enabled: false,
5504            period_months: 48,
5505            amplitude: 0.15,
5506            phase_offset: 0,
5507            recessions: Vec::new(),
5508        }
5509    }
5510}
5511
5512/// Recession period configuration.
5513#[derive(Debug, Clone, Serialize, Deserialize)]
5514pub struct RecessionPeriodConfig {
5515    /// Start month (0-indexed from generation start).
5516    pub start_month: u32,
5517
5518    /// Duration in months.
5519    pub duration_months: u32,
5520
5521    /// Severity (0.0-1.0, affects volume reduction).
5522    #[serde(default = "default_recession_severity")]
5523    pub severity: f64,
5524}
5525
5526fn default_recession_severity() -> f64 {
5527    0.20
5528}
5529
5530/// Parameter drift configuration.
5531#[derive(Debug, Clone, Serialize, Deserialize)]
5532pub struct ParameterDriftSchemaConfig {
5533    /// Parameter being drifted.
5534    pub parameter: String,
5535
5536    /// Drift type.
5537    pub drift_type: ParameterDriftTypeConfig,
5538
5539    /// Start value.
5540    pub start_value: f64,
5541
5542    /// End value.
5543    pub end_value: f64,
5544
5545    /// Start period (month, 0-indexed).
5546    #[serde(default)]
5547    pub start_period: u32,
5548
5549    /// End period (month, optional - defaults to end of generation).
5550    #[serde(default)]
5551    pub end_period: Option<u32>,
5552}
5553
5554/// Parameter drift type.
5555#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5556#[serde(rename_all = "snake_case")]
5557pub enum ParameterDriftTypeConfig {
5558    /// Linear interpolation
5559    #[default]
5560    Linear,
5561    /// Exponential growth/decay
5562    Exponential,
5563    /// S-curve (logistic)
5564    Logistic,
5565    /// Step function
5566    Step,
5567}
5568
5569/// Statistical validation configuration.
5570#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5571pub struct StatisticalValidationSchemaConfig {
5572    /// Enable statistical validation.
5573    #[serde(default)]
5574    pub enabled: bool,
5575
5576    /// Statistical tests to run.
5577    #[serde(default)]
5578    pub tests: Vec<StatisticalTestConfig>,
5579
5580    /// Validation reporting configuration.
5581    #[serde(default)]
5582    pub reporting: ValidationReportingConfig,
5583}
5584
5585/// Statistical test configuration.
5586#[derive(Debug, Clone, Serialize, Deserialize)]
5587#[serde(tag = "type", rename_all = "snake_case")]
5588pub enum StatisticalTestConfig {
5589    /// Benford's Law first digit test.
5590    BenfordFirstDigit {
5591        /// Threshold MAD for failure.
5592        #[serde(default = "default_benford_threshold")]
5593        threshold_mad: f64,
5594        /// Warning MAD threshold.
5595        #[serde(default = "default_benford_warning")]
5596        warning_mad: f64,
5597    },
5598    /// Distribution fit test.
5599    DistributionFit {
5600        /// Target distribution to test.
5601        target: TargetDistributionConfig,
5602        /// K-S test significance level.
5603        #[serde(default = "default_ks_significance")]
5604        ks_significance: f64,
5605        /// Test method (ks, anderson_darling, chi_squared).
5606        #[serde(default)]
5607        method: DistributionFitMethod,
5608    },
5609    /// Correlation check.
5610    CorrelationCheck {
5611        /// Expected correlations to validate.
5612        expected_correlations: Vec<ExpectedCorrelationConfig>,
5613    },
5614    /// Chi-squared test.
5615    ChiSquared {
5616        /// Number of bins.
5617        #[serde(default = "default_chi_squared_bins")]
5618        bins: usize,
5619        /// Significance level.
5620        #[serde(default = "default_chi_squared_significance")]
5621        significance: f64,
5622    },
5623    /// Anderson-Darling test.
5624    AndersonDarling {
5625        /// Target distribution.
5626        target: TargetDistributionConfig,
5627        /// Significance level.
5628        #[serde(default = "default_ad_significance")]
5629        significance: f64,
5630    },
5631}
5632
5633fn default_benford_threshold() -> f64 {
5634    0.015
5635}
5636
5637fn default_benford_warning() -> f64 {
5638    0.010
5639}
5640
5641fn default_ks_significance() -> f64 {
5642    0.05
5643}
5644
5645fn default_chi_squared_bins() -> usize {
5646    10
5647}
5648
5649fn default_chi_squared_significance() -> f64 {
5650    0.05
5651}
5652
5653fn default_ad_significance() -> f64 {
5654    0.05
5655}
5656
5657/// Target distribution for fit tests.
5658#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5659#[serde(rename_all = "snake_case")]
5660pub enum TargetDistributionConfig {
5661    /// Normal distribution
5662    Normal,
5663    /// Log-normal distribution
5664    #[default]
5665    LogNormal,
5666    /// Exponential distribution
5667    Exponential,
5668    /// Uniform distribution
5669    Uniform,
5670}
5671
5672/// Distribution fit test method.
5673#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5674#[serde(rename_all = "snake_case")]
5675pub enum DistributionFitMethod {
5676    /// Kolmogorov-Smirnov test
5677    #[default]
5678    KolmogorovSmirnov,
5679    /// Anderson-Darling test
5680    AndersonDarling,
5681    /// Chi-squared test
5682    ChiSquared,
5683}
5684
5685/// Validation reporting configuration.
5686#[derive(Debug, Clone, Serialize, Deserialize)]
5687pub struct ValidationReportingConfig {
5688    /// Output validation report to file.
5689    #[serde(default)]
5690    pub output_report: bool,
5691
5692    /// Report format.
5693    #[serde(default)]
5694    pub format: ValidationReportFormat,
5695
5696    /// Fail generation if validation fails.
5697    #[serde(default)]
5698    pub fail_on_error: bool,
5699
5700    /// Include detailed statistics in report.
5701    #[serde(default = "default_true")]
5702    pub include_details: bool,
5703}
5704
5705impl Default for ValidationReportingConfig {
5706    fn default() -> Self {
5707        Self {
5708            output_report: false,
5709            format: ValidationReportFormat::Json,
5710            fail_on_error: false,
5711            include_details: true,
5712        }
5713    }
5714}
5715
5716/// Validation report format.
5717#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5718#[serde(rename_all = "snake_case")]
5719pub enum ValidationReportFormat {
5720    /// JSON format
5721    #[default]
5722    Json,
5723    /// YAML format
5724    Yaml,
5725    /// HTML report
5726    Html,
5727}
5728
5729// =============================================================================
5730// Temporal Patterns Configuration
5731// =============================================================================
5732
5733/// Temporal patterns configuration for business days, period-end dynamics, and processing lags.
5734///
5735/// This section enables sophisticated temporal modeling including:
5736/// - Business day calculations and settlement dates
5737/// - Regional holiday calendars
5738/// - Period-end decay curves (non-flat volume spikes)
5739/// - Processing lag modeling (event-to-posting delays)
5740#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5741pub struct TemporalPatternsConfig {
5742    /// Enable temporal patterns features.
5743    #[serde(default)]
5744    pub enabled: bool,
5745
5746    /// Business day calculation configuration.
5747    #[serde(default)]
5748    pub business_days: BusinessDaySchemaConfig,
5749
5750    /// Regional calendar configuration.
5751    #[serde(default)]
5752    pub calendars: CalendarSchemaConfig,
5753
5754    /// Period-end dynamics configuration.
5755    #[serde(default)]
5756    pub period_end: PeriodEndSchemaConfig,
5757
5758    /// Processing lag configuration.
5759    #[serde(default)]
5760    pub processing_lags: ProcessingLagSchemaConfig,
5761
5762    /// Fiscal calendar configuration (custom year start, 4-4-5, 13-period).
5763    #[serde(default)]
5764    pub fiscal_calendar: FiscalCalendarSchemaConfig,
5765
5766    /// Intra-day patterns configuration (morning spike, lunch dip, EOD rush).
5767    #[serde(default)]
5768    pub intraday: IntraDaySchemaConfig,
5769
5770    /// Timezone handling configuration.
5771    #[serde(default)]
5772    pub timezones: TimezoneSchemaConfig,
5773}
5774
5775/// Business day calculation configuration.
5776#[derive(Debug, Clone, Serialize, Deserialize)]
5777pub struct BusinessDaySchemaConfig {
5778    /// Enable business day calculations.
5779    #[serde(default = "default_true")]
5780    pub enabled: bool,
5781
5782    /// Half-day policy: "full_day", "half_day", "non_business_day".
5783    #[serde(default = "default_half_day_policy")]
5784    pub half_day_policy: String,
5785
5786    /// Settlement rules configuration.
5787    #[serde(default)]
5788    pub settlement_rules: SettlementRulesSchemaConfig,
5789
5790    /// Month-end convention: "modified_following", "preceding", "following", "end_of_month".
5791    #[serde(default = "default_month_end_convention")]
5792    pub month_end_convention: String,
5793
5794    /// Weekend days (e.g., ["saturday", "sunday"] or ["friday", "saturday"] for Middle East).
5795    #[serde(default)]
5796    pub weekend_days: Option<Vec<String>>,
5797}
5798
5799fn default_half_day_policy() -> String {
5800    "half_day".to_string()
5801}
5802
5803fn default_month_end_convention() -> String {
5804    "modified_following".to_string()
5805}
5806
5807impl Default for BusinessDaySchemaConfig {
5808    fn default() -> Self {
5809        Self {
5810            enabled: true,
5811            half_day_policy: "half_day".to_string(),
5812            settlement_rules: SettlementRulesSchemaConfig::default(),
5813            month_end_convention: "modified_following".to_string(),
5814            weekend_days: None,
5815        }
5816    }
5817}
5818
5819/// Settlement rules configuration.
5820#[derive(Debug, Clone, Serialize, Deserialize)]
5821pub struct SettlementRulesSchemaConfig {
5822    /// Equity settlement days (T+N).
5823    #[serde(default = "default_settlement_2")]
5824    pub equity_days: i32,
5825
5826    /// Government bonds settlement days.
5827    #[serde(default = "default_settlement_1")]
5828    pub government_bonds_days: i32,
5829
5830    /// FX spot settlement days.
5831    #[serde(default = "default_settlement_2")]
5832    pub fx_spot_days: i32,
5833
5834    /// Corporate bonds settlement days.
5835    #[serde(default = "default_settlement_2")]
5836    pub corporate_bonds_days: i32,
5837
5838    /// Wire transfer cutoff time (HH:MM format).
5839    #[serde(default = "default_wire_cutoff")]
5840    pub wire_cutoff_time: String,
5841
5842    /// International wire settlement days.
5843    #[serde(default = "default_settlement_1")]
5844    pub wire_international_days: i32,
5845
5846    /// ACH settlement days.
5847    #[serde(default = "default_settlement_1")]
5848    pub ach_days: i32,
5849}
5850
5851fn default_settlement_1() -> i32 {
5852    1
5853}
5854
5855fn default_settlement_2() -> i32 {
5856    2
5857}
5858
5859fn default_wire_cutoff() -> String {
5860    "14:00".to_string()
5861}
5862
5863impl Default for SettlementRulesSchemaConfig {
5864    fn default() -> Self {
5865        Self {
5866            equity_days: 2,
5867            government_bonds_days: 1,
5868            fx_spot_days: 2,
5869            corporate_bonds_days: 2,
5870            wire_cutoff_time: "14:00".to_string(),
5871            wire_international_days: 1,
5872            ach_days: 1,
5873        }
5874    }
5875}
5876
5877/// Regional calendar configuration.
5878#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5879pub struct CalendarSchemaConfig {
5880    /// List of regions to include (e.g., ["US", "DE", "BR", "SG", "KR"]).
5881    #[serde(default)]
5882    pub regions: Vec<String>,
5883
5884    /// Custom holidays (in addition to regional calendars).
5885    #[serde(default)]
5886    pub custom_holidays: Vec<CustomHolidaySchemaConfig>,
5887}
5888
5889/// Custom holiday configuration.
5890#[derive(Debug, Clone, Serialize, Deserialize)]
5891pub struct CustomHolidaySchemaConfig {
5892    /// Holiday name.
5893    pub name: String,
5894    /// Month (1-12).
5895    pub month: u8,
5896    /// Day of month.
5897    pub day: u8,
5898    /// Activity multiplier (0.0-1.0, default 0.05).
5899    #[serde(default = "default_holiday_multiplier")]
5900    pub activity_multiplier: f64,
5901}
5902
5903fn default_holiday_multiplier() -> f64 {
5904    0.05
5905}
5906
5907/// Period-end dynamics configuration.
5908#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5909pub struct PeriodEndSchemaConfig {
5910    /// Model type: "flat", "exponential", "extended_crunch", "daily_profile".
5911    #[serde(default)]
5912    pub model: Option<String>,
5913
5914    /// Month-end configuration.
5915    #[serde(default)]
5916    pub month_end: Option<PeriodEndModelSchemaConfig>,
5917
5918    /// Quarter-end configuration.
5919    #[serde(default)]
5920    pub quarter_end: Option<PeriodEndModelSchemaConfig>,
5921
5922    /// Year-end configuration.
5923    #[serde(default)]
5924    pub year_end: Option<PeriodEndModelSchemaConfig>,
5925}
5926
5927/// Period-end model configuration.
5928#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5929pub struct PeriodEndModelSchemaConfig {
5930    /// Inherit configuration from another period (e.g., "month_end").
5931    #[serde(default)]
5932    pub inherit_from: Option<String>,
5933
5934    /// Additional multiplier on top of inherited/base model.
5935    #[serde(default)]
5936    pub additional_multiplier: Option<f64>,
5937
5938    /// Days before period end to start acceleration (negative, e.g., -10).
5939    #[serde(default)]
5940    pub start_day: Option<i32>,
5941
5942    /// Base multiplier at start of acceleration.
5943    #[serde(default)]
5944    pub base_multiplier: Option<f64>,
5945
5946    /// Peak multiplier on last day.
5947    #[serde(default)]
5948    pub peak_multiplier: Option<f64>,
5949
5950    /// Decay rate for exponential model (0.1-0.5 typical).
5951    #[serde(default)]
5952    pub decay_rate: Option<f64>,
5953
5954    /// Sustained high days for crunch model.
5955    #[serde(default)]
5956    pub sustained_high_days: Option<i32>,
5957}
5958
5959/// Processing lag configuration.
5960#[derive(Debug, Clone, Serialize, Deserialize)]
5961pub struct ProcessingLagSchemaConfig {
5962    /// Enable processing lag calculations.
5963    #[serde(default = "default_true")]
5964    pub enabled: bool,
5965
5966    /// Sales order lag configuration (log-normal mu, sigma).
5967    #[serde(default)]
5968    pub sales_order_lag: Option<LagDistributionSchemaConfig>,
5969
5970    /// Purchase order lag configuration.
5971    #[serde(default)]
5972    pub purchase_order_lag: Option<LagDistributionSchemaConfig>,
5973
5974    /// Goods receipt lag configuration.
5975    #[serde(default)]
5976    pub goods_receipt_lag: Option<LagDistributionSchemaConfig>,
5977
5978    /// Invoice receipt lag configuration.
5979    #[serde(default)]
5980    pub invoice_receipt_lag: Option<LagDistributionSchemaConfig>,
5981
5982    /// Invoice issue lag configuration.
5983    #[serde(default)]
5984    pub invoice_issue_lag: Option<LagDistributionSchemaConfig>,
5985
5986    /// Payment lag configuration.
5987    #[serde(default)]
5988    pub payment_lag: Option<LagDistributionSchemaConfig>,
5989
5990    /// Journal entry lag configuration.
5991    #[serde(default)]
5992    pub journal_entry_lag: Option<LagDistributionSchemaConfig>,
5993
5994    /// Cross-day posting configuration.
5995    #[serde(default)]
5996    pub cross_day_posting: Option<CrossDayPostingSchemaConfig>,
5997}
5998
5999impl Default for ProcessingLagSchemaConfig {
6000    fn default() -> Self {
6001        Self {
6002            enabled: true,
6003            sales_order_lag: None,
6004            purchase_order_lag: None,
6005            goods_receipt_lag: None,
6006            invoice_receipt_lag: None,
6007            invoice_issue_lag: None,
6008            payment_lag: None,
6009            journal_entry_lag: None,
6010            cross_day_posting: None,
6011        }
6012    }
6013}
6014
6015/// Lag distribution configuration (log-normal parameters).
6016#[derive(Debug, Clone, Serialize, Deserialize)]
6017pub struct LagDistributionSchemaConfig {
6018    /// Log-scale mean (mu for log-normal).
6019    pub mu: f64,
6020    /// Log-scale standard deviation (sigma for log-normal).
6021    pub sigma: f64,
6022    /// Minimum lag in hours.
6023    #[serde(default)]
6024    pub min_hours: Option<f64>,
6025    /// Maximum lag in hours.
6026    #[serde(default)]
6027    pub max_hours: Option<f64>,
6028}
6029
6030/// Cross-day posting configuration.
6031#[derive(Debug, Clone, Serialize, Deserialize)]
6032pub struct CrossDayPostingSchemaConfig {
6033    /// Enable cross-day posting logic.
6034    #[serde(default = "default_true")]
6035    pub enabled: bool,
6036
6037    /// Probability of next-day posting by hour (map of hour -> probability).
6038    /// E.g., { 17: 0.7, 19: 0.9, 21: 0.99 }
6039    #[serde(default)]
6040    pub probability_by_hour: std::collections::HashMap<u8, f64>,
6041}
6042
6043impl Default for CrossDayPostingSchemaConfig {
6044    fn default() -> Self {
6045        let mut probability_by_hour = std::collections::HashMap::new();
6046        probability_by_hour.insert(17, 0.3);
6047        probability_by_hour.insert(18, 0.6);
6048        probability_by_hour.insert(19, 0.8);
6049        probability_by_hour.insert(20, 0.9);
6050        probability_by_hour.insert(21, 0.95);
6051        probability_by_hour.insert(22, 0.99);
6052
6053        Self {
6054            enabled: true,
6055            probability_by_hour,
6056        }
6057    }
6058}
6059
6060// =============================================================================
6061// Fiscal Calendar Configuration (P2)
6062// =============================================================================
6063
6064/// Fiscal calendar configuration.
6065///
6066/// Supports calendar year, custom year start, 4-4-5 retail calendar,
6067/// and 13-period calendars.
6068#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6069pub struct FiscalCalendarSchemaConfig {
6070    /// Enable non-standard fiscal calendar.
6071    #[serde(default)]
6072    pub enabled: bool,
6073
6074    /// Fiscal calendar type: "calendar_year", "custom", "four_four_five", "thirteen_period".
6075    #[serde(default = "default_fiscal_calendar_type")]
6076    pub calendar_type: String,
6077
6078    /// Month the fiscal year starts (1-12). Used for custom year start.
6079    #[serde(default)]
6080    pub year_start_month: Option<u8>,
6081
6082    /// Day the fiscal year starts (1-31). Used for custom year start.
6083    #[serde(default)]
6084    pub year_start_day: Option<u8>,
6085
6086    /// 4-4-5 calendar configuration (if calendar_type is "four_four_five").
6087    #[serde(default)]
6088    pub four_four_five: Option<FourFourFiveSchemaConfig>,
6089}
6090
6091fn default_fiscal_calendar_type() -> String {
6092    "calendar_year".to_string()
6093}
6094
6095/// 4-4-5 retail calendar configuration.
6096#[derive(Debug, Clone, Serialize, Deserialize)]
6097pub struct FourFourFiveSchemaConfig {
6098    /// Week pattern: "four_four_five", "four_five_four", "five_four_four".
6099    #[serde(default = "default_week_pattern")]
6100    pub pattern: String,
6101
6102    /// Anchor type: "first_sunday", "last_saturday", "nearest_saturday".
6103    #[serde(default = "default_anchor_type")]
6104    pub anchor_type: String,
6105
6106    /// Anchor month (1-12).
6107    #[serde(default = "default_anchor_month")]
6108    pub anchor_month: u8,
6109
6110    /// Where to place leap week: "q4_period3" or "q1_period1".
6111    #[serde(default = "default_leap_week_placement")]
6112    pub leap_week_placement: String,
6113}
6114
6115fn default_week_pattern() -> String {
6116    "four_four_five".to_string()
6117}
6118
6119fn default_anchor_type() -> String {
6120    "last_saturday".to_string()
6121}
6122
6123fn default_anchor_month() -> u8 {
6124    1 // January
6125}
6126
6127fn default_leap_week_placement() -> String {
6128    "q4_period3".to_string()
6129}
6130
6131impl Default for FourFourFiveSchemaConfig {
6132    fn default() -> Self {
6133        Self {
6134            pattern: "four_four_five".to_string(),
6135            anchor_type: "last_saturday".to_string(),
6136            anchor_month: 1,
6137            leap_week_placement: "q4_period3".to_string(),
6138        }
6139    }
6140}
6141
6142// =============================================================================
6143// Intra-Day Patterns Configuration (P2)
6144// =============================================================================
6145
6146/// Intra-day patterns configuration.
6147///
6148/// Defines time-of-day segments with different activity multipliers
6149/// for realistic modeling of morning spikes, lunch dips, and end-of-day rushes.
6150#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6151pub struct IntraDaySchemaConfig {
6152    /// Enable intra-day patterns.
6153    #[serde(default)]
6154    pub enabled: bool,
6155
6156    /// Custom intra-day segments.
6157    #[serde(default)]
6158    pub segments: Vec<IntraDaySegmentSchemaConfig>,
6159}
6160
6161/// Intra-day segment configuration.
6162#[derive(Debug, Clone, Serialize, Deserialize)]
6163pub struct IntraDaySegmentSchemaConfig {
6164    /// Name of the segment (e.g., "morning_spike", "lunch_dip").
6165    pub name: String,
6166
6167    /// Start time (HH:MM format).
6168    pub start: String,
6169
6170    /// End time (HH:MM format).
6171    pub end: String,
6172
6173    /// Activity multiplier (1.0 = normal).
6174    #[serde(default = "default_multiplier")]
6175    pub multiplier: f64,
6176
6177    /// Posting type: "human", "system", "both".
6178    #[serde(default = "default_posting_type")]
6179    pub posting_type: String,
6180}
6181
6182fn default_multiplier() -> f64 {
6183    1.0
6184}
6185
6186fn default_posting_type() -> String {
6187    "both".to_string()
6188}
6189
6190// =============================================================================
6191// Timezone Configuration
6192// =============================================================================
6193
6194/// Timezone handling configuration for multi-region entities.
6195#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6196pub struct TimezoneSchemaConfig {
6197    /// Enable timezone handling.
6198    #[serde(default)]
6199    pub enabled: bool,
6200
6201    /// Default timezone (IANA format, e.g., "America/New_York").
6202    #[serde(default = "default_timezone")]
6203    pub default_timezone: String,
6204
6205    /// Consolidation timezone for group reporting (IANA format).
6206    #[serde(default = "default_consolidation_timezone")]
6207    pub consolidation_timezone: String,
6208
6209    /// Entity-to-timezone mappings.
6210    /// Supports patterns like "EU_*" -> "Europe/London".
6211    #[serde(default)]
6212    pub entity_mappings: Vec<EntityTimezoneMapping>,
6213}
6214
6215fn default_timezone() -> String {
6216    "America/New_York".to_string()
6217}
6218
6219fn default_consolidation_timezone() -> String {
6220    "UTC".to_string()
6221}
6222
6223/// Mapping from entity pattern to timezone.
6224#[derive(Debug, Clone, Serialize, Deserialize)]
6225pub struct EntityTimezoneMapping {
6226    /// Entity code pattern (e.g., "EU_*", "*_APAC", "1000").
6227    pub pattern: String,
6228
6229    /// Timezone (IANA format, e.g., "Europe/London").
6230    pub timezone: String,
6231}
6232
6233// =============================================================================
6234// Vendor Network Configuration
6235// =============================================================================
6236
6237/// Configuration for multi-tier vendor network generation.
6238#[derive(Debug, Clone, Serialize, Deserialize)]
6239pub struct VendorNetworkSchemaConfig {
6240    /// Enable vendor network generation.
6241    #[serde(default)]
6242    pub enabled: bool,
6243
6244    /// Maximum depth of supply chain tiers (1-3).
6245    #[serde(default = "default_vendor_tier_depth")]
6246    pub depth: u8,
6247
6248    /// Tier 1 vendor count configuration.
6249    #[serde(default)]
6250    pub tier1: TierCountSchemaConfig,
6251
6252    /// Tier 2 vendors per Tier 1 parent.
6253    #[serde(default)]
6254    pub tier2_per_parent: TierCountSchemaConfig,
6255
6256    /// Tier 3 vendors per Tier 2 parent.
6257    #[serde(default)]
6258    pub tier3_per_parent: TierCountSchemaConfig,
6259
6260    /// Vendor cluster distribution.
6261    #[serde(default)]
6262    pub clusters: VendorClusterSchemaConfig,
6263
6264    /// Concentration limits.
6265    #[serde(default)]
6266    pub dependencies: DependencySchemaConfig,
6267}
6268
6269fn default_vendor_tier_depth() -> u8 {
6270    3
6271}
6272
6273impl Default for VendorNetworkSchemaConfig {
6274    fn default() -> Self {
6275        Self {
6276            enabled: false,
6277            depth: 3,
6278            tier1: TierCountSchemaConfig { min: 50, max: 100 },
6279            tier2_per_parent: TierCountSchemaConfig { min: 4, max: 10 },
6280            tier3_per_parent: TierCountSchemaConfig { min: 2, max: 5 },
6281            clusters: VendorClusterSchemaConfig::default(),
6282            dependencies: DependencySchemaConfig::default(),
6283        }
6284    }
6285}
6286
6287/// Tier count configuration.
6288#[derive(Debug, Clone, Serialize, Deserialize)]
6289pub struct TierCountSchemaConfig {
6290    /// Minimum count.
6291    #[serde(default = "default_tier_min")]
6292    pub min: usize,
6293
6294    /// Maximum count.
6295    #[serde(default = "default_tier_max")]
6296    pub max: usize,
6297}
6298
6299fn default_tier_min() -> usize {
6300    5
6301}
6302
6303fn default_tier_max() -> usize {
6304    20
6305}
6306
6307impl Default for TierCountSchemaConfig {
6308    fn default() -> Self {
6309        Self {
6310            min: default_tier_min(),
6311            max: default_tier_max(),
6312        }
6313    }
6314}
6315
6316/// Vendor cluster distribution configuration.
6317#[derive(Debug, Clone, Serialize, Deserialize)]
6318pub struct VendorClusterSchemaConfig {
6319    /// Reliable strategic vendors percentage (default: 0.20).
6320    #[serde(default = "default_reliable_strategic")]
6321    pub reliable_strategic: f64,
6322
6323    /// Standard operational vendors percentage (default: 0.50).
6324    #[serde(default = "default_standard_operational")]
6325    pub standard_operational: f64,
6326
6327    /// Transactional vendors percentage (default: 0.25).
6328    #[serde(default = "default_transactional")]
6329    pub transactional: f64,
6330
6331    /// Problematic vendors percentage (default: 0.05).
6332    #[serde(default = "default_problematic")]
6333    pub problematic: f64,
6334}
6335
6336fn default_reliable_strategic() -> f64 {
6337    0.20
6338}
6339
6340fn default_standard_operational() -> f64 {
6341    0.50
6342}
6343
6344fn default_transactional() -> f64 {
6345    0.25
6346}
6347
6348fn default_problematic() -> f64 {
6349    0.05
6350}
6351
6352impl Default for VendorClusterSchemaConfig {
6353    fn default() -> Self {
6354        Self {
6355            reliable_strategic: 0.20,
6356            standard_operational: 0.50,
6357            transactional: 0.25,
6358            problematic: 0.05,
6359        }
6360    }
6361}
6362
6363/// Dependency and concentration limits configuration.
6364#[derive(Debug, Clone, Serialize, Deserialize)]
6365pub struct DependencySchemaConfig {
6366    /// Maximum concentration for a single vendor (default: 0.15).
6367    #[serde(default = "default_max_single_vendor")]
6368    pub max_single_vendor_concentration: f64,
6369
6370    /// Maximum concentration for top 5 vendors (default: 0.45).
6371    #[serde(default = "default_max_top5")]
6372    pub top_5_concentration: f64,
6373
6374    /// Percentage of single-source vendors (default: 0.05).
6375    #[serde(default = "default_single_source_percent")]
6376    pub single_source_percent: f64,
6377}
6378
6379fn default_max_single_vendor() -> f64 {
6380    0.15
6381}
6382
6383fn default_max_top5() -> f64 {
6384    0.45
6385}
6386
6387fn default_single_source_percent() -> f64 {
6388    0.05
6389}
6390
6391impl Default for DependencySchemaConfig {
6392    fn default() -> Self {
6393        Self {
6394            max_single_vendor_concentration: 0.15,
6395            top_5_concentration: 0.45,
6396            single_source_percent: 0.05,
6397        }
6398    }
6399}
6400
6401// =============================================================================
6402// Customer Segmentation Configuration
6403// =============================================================================
6404
6405/// Configuration for customer segmentation generation.
6406#[derive(Debug, Clone, Default, Serialize, Deserialize)]
6407pub struct CustomerSegmentationSchemaConfig {
6408    /// Enable customer segmentation generation.
6409    #[serde(default)]
6410    pub enabled: bool,
6411
6412    /// Value segment distribution.
6413    #[serde(default)]
6414    pub value_segments: ValueSegmentsSchemaConfig,
6415
6416    /// Lifecycle stage configuration.
6417    #[serde(default)]
6418    pub lifecycle: LifecycleSchemaConfig,
6419
6420    /// Network (referrals, hierarchies) configuration.
6421    #[serde(default)]
6422    pub networks: CustomerNetworksSchemaConfig,
6423}
6424
6425/// Customer value segments distribution configuration.
6426#[derive(Debug, Clone, Serialize, Deserialize)]
6427pub struct ValueSegmentsSchemaConfig {
6428    /// Enterprise segment configuration.
6429    #[serde(default)]
6430    pub enterprise: SegmentDetailSchemaConfig,
6431
6432    /// Mid-market segment configuration.
6433    #[serde(default)]
6434    pub mid_market: SegmentDetailSchemaConfig,
6435
6436    /// SMB segment configuration.
6437    #[serde(default)]
6438    pub smb: SegmentDetailSchemaConfig,
6439
6440    /// Consumer segment configuration.
6441    #[serde(default)]
6442    pub consumer: SegmentDetailSchemaConfig,
6443}
6444
6445impl Default for ValueSegmentsSchemaConfig {
6446    fn default() -> Self {
6447        Self {
6448            enterprise: SegmentDetailSchemaConfig {
6449                revenue_share: 0.40,
6450                customer_share: 0.05,
6451                avg_order_value_range: "50000+".to_string(),
6452            },
6453            mid_market: SegmentDetailSchemaConfig {
6454                revenue_share: 0.35,
6455                customer_share: 0.20,
6456                avg_order_value_range: "5000-50000".to_string(),
6457            },
6458            smb: SegmentDetailSchemaConfig {
6459                revenue_share: 0.20,
6460                customer_share: 0.50,
6461                avg_order_value_range: "500-5000".to_string(),
6462            },
6463            consumer: SegmentDetailSchemaConfig {
6464                revenue_share: 0.05,
6465                customer_share: 0.25,
6466                avg_order_value_range: "50-500".to_string(),
6467            },
6468        }
6469    }
6470}
6471
6472/// Individual segment detail configuration.
6473#[derive(Debug, Clone, Serialize, Deserialize)]
6474pub struct SegmentDetailSchemaConfig {
6475    /// Revenue share for this segment.
6476    #[serde(default)]
6477    pub revenue_share: f64,
6478
6479    /// Customer share for this segment.
6480    #[serde(default)]
6481    pub customer_share: f64,
6482
6483    /// Average order value range (e.g., "5000-50000" or "50000+").
6484    #[serde(default)]
6485    pub avg_order_value_range: String,
6486}
6487
6488impl Default for SegmentDetailSchemaConfig {
6489    fn default() -> Self {
6490        Self {
6491            revenue_share: 0.25,
6492            customer_share: 0.25,
6493            avg_order_value_range: "1000-10000".to_string(),
6494        }
6495    }
6496}
6497
6498/// Customer lifecycle stage configuration.
6499#[derive(Debug, Clone, Serialize, Deserialize)]
6500pub struct LifecycleSchemaConfig {
6501    /// Prospect stage rate.
6502    #[serde(default)]
6503    pub prospect_rate: f64,
6504
6505    /// New customer stage rate.
6506    #[serde(default = "default_new_rate")]
6507    pub new_rate: f64,
6508
6509    /// Growth stage rate.
6510    #[serde(default = "default_growth_rate")]
6511    pub growth_rate: f64,
6512
6513    /// Mature stage rate.
6514    #[serde(default = "default_mature_rate")]
6515    pub mature_rate: f64,
6516
6517    /// At-risk stage rate.
6518    #[serde(default = "default_at_risk_rate")]
6519    pub at_risk_rate: f64,
6520
6521    /// Churned stage rate.
6522    #[serde(default = "default_churned_rate")]
6523    pub churned_rate: f64,
6524}
6525
6526fn default_new_rate() -> f64 {
6527    0.10
6528}
6529
6530fn default_growth_rate() -> f64 {
6531    0.15
6532}
6533
6534fn default_mature_rate() -> f64 {
6535    0.60
6536}
6537
6538fn default_at_risk_rate() -> f64 {
6539    0.10
6540}
6541
6542fn default_churned_rate() -> f64 {
6543    0.05
6544}
6545
6546impl Default for LifecycleSchemaConfig {
6547    fn default() -> Self {
6548        Self {
6549            prospect_rate: 0.0,
6550            new_rate: 0.10,
6551            growth_rate: 0.15,
6552            mature_rate: 0.60,
6553            at_risk_rate: 0.10,
6554            churned_rate: 0.05,
6555        }
6556    }
6557}
6558
6559/// Customer networks configuration (referrals, hierarchies).
6560#[derive(Debug, Clone, Default, Serialize, Deserialize)]
6561pub struct CustomerNetworksSchemaConfig {
6562    /// Referral network configuration.
6563    #[serde(default)]
6564    pub referrals: ReferralSchemaConfig,
6565
6566    /// Corporate hierarchy configuration.
6567    #[serde(default)]
6568    pub corporate_hierarchies: HierarchySchemaConfig,
6569}
6570
6571/// Referral network configuration.
6572#[derive(Debug, Clone, Serialize, Deserialize)]
6573pub struct ReferralSchemaConfig {
6574    /// Enable referral generation.
6575    #[serde(default = "default_true")]
6576    pub enabled: bool,
6577
6578    /// Rate of customers acquired via referral.
6579    #[serde(default = "default_referral_rate")]
6580    pub referral_rate: f64,
6581}
6582
6583fn default_referral_rate() -> f64 {
6584    0.15
6585}
6586
6587impl Default for ReferralSchemaConfig {
6588    fn default() -> Self {
6589        Self {
6590            enabled: true,
6591            referral_rate: 0.15,
6592        }
6593    }
6594}
6595
6596/// Corporate hierarchy configuration.
6597#[derive(Debug, Clone, Serialize, Deserialize)]
6598pub struct HierarchySchemaConfig {
6599    /// Enable corporate hierarchy generation.
6600    #[serde(default = "default_true")]
6601    pub enabled: bool,
6602
6603    /// Rate of customers in hierarchies.
6604    #[serde(default = "default_hierarchy_rate")]
6605    pub probability: f64,
6606}
6607
6608fn default_hierarchy_rate() -> f64 {
6609    0.30
6610}
6611
6612impl Default for HierarchySchemaConfig {
6613    fn default() -> Self {
6614        Self {
6615            enabled: true,
6616            probability: 0.30,
6617        }
6618    }
6619}
6620
6621// =============================================================================
6622// Relationship Strength Configuration
6623// =============================================================================
6624
6625/// Configuration for relationship strength calculation.
6626#[derive(Debug, Clone, Default, Serialize, Deserialize)]
6627pub struct RelationshipStrengthSchemaConfig {
6628    /// Enable relationship strength calculation.
6629    #[serde(default)]
6630    pub enabled: bool,
6631
6632    /// Calculation weights.
6633    #[serde(default)]
6634    pub calculation: StrengthCalculationSchemaConfig,
6635
6636    /// Strength thresholds for classification.
6637    #[serde(default)]
6638    pub thresholds: StrengthThresholdsSchemaConfig,
6639}
6640
6641/// Strength calculation weights configuration.
6642#[derive(Debug, Clone, Serialize, Deserialize)]
6643pub struct StrengthCalculationSchemaConfig {
6644    /// Weight for transaction volume (default: 0.30).
6645    #[serde(default = "default_volume_weight")]
6646    pub transaction_volume_weight: f64,
6647
6648    /// Weight for transaction count (default: 0.25).
6649    #[serde(default = "default_count_weight")]
6650    pub transaction_count_weight: f64,
6651
6652    /// Weight for relationship duration (default: 0.20).
6653    #[serde(default = "default_duration_weight")]
6654    pub relationship_duration_weight: f64,
6655
6656    /// Weight for recency (default: 0.15).
6657    #[serde(default = "default_recency_weight")]
6658    pub recency_weight: f64,
6659
6660    /// Weight for mutual connections (default: 0.10).
6661    #[serde(default = "default_mutual_weight")]
6662    pub mutual_connections_weight: f64,
6663
6664    /// Recency half-life in days (default: 90).
6665    #[serde(default = "default_recency_half_life")]
6666    pub recency_half_life_days: u32,
6667}
6668
6669fn default_volume_weight() -> f64 {
6670    0.30
6671}
6672
6673fn default_count_weight() -> f64 {
6674    0.25
6675}
6676
6677fn default_duration_weight() -> f64 {
6678    0.20
6679}
6680
6681fn default_recency_weight() -> f64 {
6682    0.15
6683}
6684
6685fn default_mutual_weight() -> f64 {
6686    0.10
6687}
6688
6689fn default_recency_half_life() -> u32 {
6690    90
6691}
6692
6693impl Default for StrengthCalculationSchemaConfig {
6694    fn default() -> Self {
6695        Self {
6696            transaction_volume_weight: 0.30,
6697            transaction_count_weight: 0.25,
6698            relationship_duration_weight: 0.20,
6699            recency_weight: 0.15,
6700            mutual_connections_weight: 0.10,
6701            recency_half_life_days: 90,
6702        }
6703    }
6704}
6705
6706/// Strength thresholds for relationship classification.
6707#[derive(Debug, Clone, Serialize, Deserialize)]
6708pub struct StrengthThresholdsSchemaConfig {
6709    /// Threshold for strong relationships (default: 0.7).
6710    #[serde(default = "default_strong_threshold")]
6711    pub strong: f64,
6712
6713    /// Threshold for moderate relationships (default: 0.4).
6714    #[serde(default = "default_moderate_threshold")]
6715    pub moderate: f64,
6716
6717    /// Threshold for weak relationships (default: 0.1).
6718    #[serde(default = "default_weak_threshold")]
6719    pub weak: f64,
6720}
6721
6722fn default_strong_threshold() -> f64 {
6723    0.7
6724}
6725
6726fn default_moderate_threshold() -> f64 {
6727    0.4
6728}
6729
6730fn default_weak_threshold() -> f64 {
6731    0.1
6732}
6733
6734impl Default for StrengthThresholdsSchemaConfig {
6735    fn default() -> Self {
6736        Self {
6737            strong: 0.7,
6738            moderate: 0.4,
6739            weak: 0.1,
6740        }
6741    }
6742}
6743
6744// =============================================================================
6745// Cross-Process Links Configuration
6746// =============================================================================
6747
6748/// Configuration for cross-process linkages.
6749#[derive(Debug, Clone, Serialize, Deserialize)]
6750pub struct CrossProcessLinksSchemaConfig {
6751    /// Enable cross-process link generation.
6752    #[serde(default)]
6753    pub enabled: bool,
6754
6755    /// Enable inventory links between P2P and O2C.
6756    #[serde(default = "default_true")]
6757    pub inventory_p2p_o2c: bool,
6758
6759    /// Enable payment to bank reconciliation links.
6760    #[serde(default = "default_true")]
6761    pub payment_bank_reconciliation: bool,
6762
6763    /// Enable intercompany bilateral matching.
6764    #[serde(default = "default_true")]
6765    pub intercompany_bilateral: bool,
6766
6767    /// Percentage of GR/Deliveries to link via inventory (0.0 - 1.0).
6768    #[serde(default = "default_inventory_link_rate")]
6769    pub inventory_link_rate: f64,
6770}
6771
6772fn default_inventory_link_rate() -> f64 {
6773    0.30
6774}
6775
6776impl Default for CrossProcessLinksSchemaConfig {
6777    fn default() -> Self {
6778        Self {
6779            enabled: false,
6780            inventory_p2p_o2c: true,
6781            payment_bank_reconciliation: true,
6782            intercompany_bilateral: true,
6783            inventory_link_rate: 0.30,
6784        }
6785    }
6786}
6787
6788// =============================================================================
6789// Organizational Events Configuration
6790// =============================================================================
6791
6792/// Configuration for organizational events (acquisitions, divestitures, etc.).
6793#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6794pub struct OrganizationalEventsSchemaConfig {
6795    /// Enable organizational events.
6796    #[serde(default)]
6797    pub enabled: bool,
6798
6799    /// Effect blending mode (multiplicative, additive, maximum, minimum).
6800    #[serde(default)]
6801    pub effect_blending: EffectBlendingModeConfig,
6802
6803    /// Organizational events (acquisitions, divestitures, reorganizations, etc.).
6804    #[serde(default)]
6805    pub events: Vec<OrganizationalEventSchemaConfig>,
6806
6807    /// Process evolution events.
6808    #[serde(default)]
6809    pub process_evolution: Vec<ProcessEvolutionSchemaConfig>,
6810
6811    /// Technology transition events.
6812    #[serde(default)]
6813    pub technology_transitions: Vec<TechnologyTransitionSchemaConfig>,
6814}
6815
6816/// Effect blending mode for combining multiple event effects.
6817#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
6818#[serde(rename_all = "snake_case")]
6819pub enum EffectBlendingModeConfig {
6820    /// Multiply effects together.
6821    #[default]
6822    Multiplicative,
6823    /// Add effects together.
6824    Additive,
6825    /// Take the maximum effect.
6826    Maximum,
6827    /// Take the minimum effect.
6828    Minimum,
6829}
6830
6831/// Configuration for a single organizational event.
6832#[derive(Debug, Clone, Serialize, Deserialize)]
6833pub struct OrganizationalEventSchemaConfig {
6834    /// Event ID.
6835    pub id: String,
6836
6837    /// Event type and configuration.
6838    pub event_type: OrganizationalEventTypeSchemaConfig,
6839
6840    /// Effective date.
6841    pub effective_date: String,
6842
6843    /// Transition duration in months.
6844    #[serde(default = "default_org_transition_months")]
6845    pub transition_months: u32,
6846
6847    /// Description.
6848    #[serde(default)]
6849    pub description: Option<String>,
6850}
6851
6852fn default_org_transition_months() -> u32 {
6853    6
6854}
6855
6856/// Organizational event type configuration.
6857#[derive(Debug, Clone, Serialize, Deserialize)]
6858#[serde(tag = "type", rename_all = "snake_case")]
6859pub enum OrganizationalEventTypeSchemaConfig {
6860    /// Acquisition event.
6861    Acquisition {
6862        /// Acquired entity code.
6863        acquired_entity: String,
6864        /// Volume increase multiplier.
6865        #[serde(default = "default_acquisition_volume")]
6866        volume_increase: f64,
6867        /// Integration error rate.
6868        #[serde(default = "default_acquisition_error")]
6869        integration_error_rate: f64,
6870        /// Parallel posting days.
6871        #[serde(default = "default_parallel_days")]
6872        parallel_posting_days: u32,
6873    },
6874    /// Divestiture event.
6875    Divestiture {
6876        /// Divested entity code.
6877        divested_entity: String,
6878        /// Volume reduction factor.
6879        #[serde(default = "default_divestiture_volume")]
6880        volume_reduction: f64,
6881        /// Remove entity from generation.
6882        #[serde(default = "default_true_val")]
6883        remove_entity: bool,
6884    },
6885    /// Reorganization event.
6886    Reorganization {
6887        /// Cost center remapping.
6888        #[serde(default)]
6889        cost_center_remapping: std::collections::HashMap<String, String>,
6890        /// Transition error rate.
6891        #[serde(default = "default_reorg_error")]
6892        transition_error_rate: f64,
6893    },
6894    /// Leadership change event.
6895    LeadershipChange {
6896        /// Role that changed.
6897        role: String,
6898        /// Policy changes.
6899        #[serde(default)]
6900        policy_changes: Vec<String>,
6901    },
6902    /// Workforce reduction event.
6903    WorkforceReduction {
6904        /// Reduction percentage.
6905        #[serde(default = "default_workforce_reduction")]
6906        reduction_percent: f64,
6907        /// Error rate increase.
6908        #[serde(default = "default_workforce_error")]
6909        error_rate_increase: f64,
6910    },
6911    /// Merger event.
6912    Merger {
6913        /// Merged entity code.
6914        merged_entity: String,
6915        /// Volume increase multiplier.
6916        #[serde(default = "default_merger_volume")]
6917        volume_increase: f64,
6918    },
6919}
6920
6921fn default_acquisition_volume() -> f64 {
6922    1.35
6923}
6924
6925fn default_acquisition_error() -> f64 {
6926    0.05
6927}
6928
6929fn default_parallel_days() -> u32 {
6930    30
6931}
6932
6933fn default_divestiture_volume() -> f64 {
6934    0.70
6935}
6936
6937fn default_true_val() -> bool {
6938    true
6939}
6940
6941fn default_reorg_error() -> f64 {
6942    0.04
6943}
6944
6945fn default_workforce_reduction() -> f64 {
6946    0.10
6947}
6948
6949fn default_workforce_error() -> f64 {
6950    0.05
6951}
6952
6953fn default_merger_volume() -> f64 {
6954    1.80
6955}
6956
6957/// Configuration for a process evolution event.
6958#[derive(Debug, Clone, Serialize, Deserialize)]
6959pub struct ProcessEvolutionSchemaConfig {
6960    /// Event ID.
6961    pub id: String,
6962
6963    /// Event type.
6964    pub event_type: ProcessEvolutionTypeSchemaConfig,
6965
6966    /// Effective date.
6967    pub effective_date: String,
6968
6969    /// Description.
6970    #[serde(default)]
6971    pub description: Option<String>,
6972}
6973
6974/// Process evolution type configuration.
6975#[derive(Debug, Clone, Serialize, Deserialize)]
6976#[serde(tag = "type", rename_all = "snake_case")]
6977pub enum ProcessEvolutionTypeSchemaConfig {
6978    /// Process automation.
6979    ProcessAutomation {
6980        /// Process name.
6981        process_name: String,
6982        /// Manual rate before.
6983        #[serde(default = "default_manual_before")]
6984        manual_rate_before: f64,
6985        /// Manual rate after.
6986        #[serde(default = "default_manual_after")]
6987        manual_rate_after: f64,
6988    },
6989    /// Approval workflow change.
6990    ApprovalWorkflowChange {
6991        /// Description.
6992        description: String,
6993    },
6994    /// Control enhancement.
6995    ControlEnhancement {
6996        /// Control ID.
6997        control_id: String,
6998        /// Error reduction.
6999        #[serde(default = "default_error_reduction")]
7000        error_reduction: f64,
7001    },
7002}
7003
7004fn default_manual_before() -> f64 {
7005    0.80
7006}
7007
7008fn default_manual_after() -> f64 {
7009    0.15
7010}
7011
7012fn default_error_reduction() -> f64 {
7013    0.02
7014}
7015
7016/// Configuration for a technology transition event.
7017#[derive(Debug, Clone, Serialize, Deserialize)]
7018pub struct TechnologyTransitionSchemaConfig {
7019    /// Event ID.
7020    pub id: String,
7021
7022    /// Event type.
7023    pub event_type: TechnologyTransitionTypeSchemaConfig,
7024
7025    /// Description.
7026    #[serde(default)]
7027    pub description: Option<String>,
7028}
7029
7030/// Technology transition type configuration.
7031#[derive(Debug, Clone, Serialize, Deserialize)]
7032#[serde(tag = "type", rename_all = "snake_case")]
7033pub enum TechnologyTransitionTypeSchemaConfig {
7034    /// ERP migration.
7035    ErpMigration {
7036        /// Source system.
7037        source_system: String,
7038        /// Target system.
7039        target_system: String,
7040        /// Cutover date.
7041        cutover_date: String,
7042        /// Stabilization end date.
7043        stabilization_end: String,
7044        /// Duplicate rate during migration.
7045        #[serde(default = "default_erp_duplicate_rate")]
7046        duplicate_rate: f64,
7047        /// Format mismatch rate.
7048        #[serde(default = "default_format_mismatch")]
7049        format_mismatch_rate: f64,
7050    },
7051    /// Module implementation.
7052    ModuleImplementation {
7053        /// Module name.
7054        module_name: String,
7055        /// Go-live date.
7056        go_live_date: String,
7057    },
7058}
7059
7060fn default_erp_duplicate_rate() -> f64 {
7061    0.02
7062}
7063
7064fn default_format_mismatch() -> f64 {
7065    0.03
7066}
7067
7068// =============================================================================
7069// Behavioral Drift Configuration
7070// =============================================================================
7071
7072/// Configuration for behavioral drift (vendor, customer, employee behavior).
7073#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7074pub struct BehavioralDriftSchemaConfig {
7075    /// Enable behavioral drift.
7076    #[serde(default)]
7077    pub enabled: bool,
7078
7079    /// Vendor behavior drift.
7080    #[serde(default)]
7081    pub vendor_behavior: VendorBehaviorSchemaConfig,
7082
7083    /// Customer behavior drift.
7084    #[serde(default)]
7085    pub customer_behavior: CustomerBehaviorSchemaConfig,
7086
7087    /// Employee behavior drift.
7088    #[serde(default)]
7089    pub employee_behavior: EmployeeBehaviorSchemaConfig,
7090
7091    /// Collective behavior drift.
7092    #[serde(default)]
7093    pub collective: CollectiveBehaviorSchemaConfig,
7094}
7095
7096/// Vendor behavior drift configuration.
7097#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7098pub struct VendorBehaviorSchemaConfig {
7099    /// Payment terms drift.
7100    #[serde(default)]
7101    pub payment_terms_drift: PaymentTermsDriftSchemaConfig,
7102
7103    /// Quality drift.
7104    #[serde(default)]
7105    pub quality_drift: QualityDriftSchemaConfig,
7106}
7107
7108/// Payment terms drift configuration.
7109#[derive(Debug, Clone, Serialize, Deserialize)]
7110pub struct PaymentTermsDriftSchemaConfig {
7111    /// Extension rate per year (days).
7112    #[serde(default = "default_extension_rate")]
7113    pub extension_rate_per_year: f64,
7114
7115    /// Economic sensitivity.
7116    #[serde(default = "default_economic_sensitivity")]
7117    pub economic_sensitivity: f64,
7118}
7119
7120fn default_extension_rate() -> f64 {
7121    2.5
7122}
7123
7124fn default_economic_sensitivity() -> f64 {
7125    1.0
7126}
7127
7128impl Default for PaymentTermsDriftSchemaConfig {
7129    fn default() -> Self {
7130        Self {
7131            extension_rate_per_year: 2.5,
7132            economic_sensitivity: 1.0,
7133        }
7134    }
7135}
7136
7137/// Quality drift configuration.
7138#[derive(Debug, Clone, Serialize, Deserialize)]
7139pub struct QualityDriftSchemaConfig {
7140    /// New vendor improvement rate (per year).
7141    #[serde(default = "default_improvement_rate")]
7142    pub new_vendor_improvement_rate: f64,
7143
7144    /// Complacency decline rate (per year after first year).
7145    #[serde(default = "default_decline_rate")]
7146    pub complacency_decline_rate: f64,
7147}
7148
7149fn default_improvement_rate() -> f64 {
7150    0.02
7151}
7152
7153fn default_decline_rate() -> f64 {
7154    0.01
7155}
7156
7157impl Default for QualityDriftSchemaConfig {
7158    fn default() -> Self {
7159        Self {
7160            new_vendor_improvement_rate: 0.02,
7161            complacency_decline_rate: 0.01,
7162        }
7163    }
7164}
7165
7166/// Customer behavior drift configuration.
7167#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7168pub struct CustomerBehaviorSchemaConfig {
7169    /// Payment drift.
7170    #[serde(default)]
7171    pub payment_drift: CustomerPaymentDriftSchemaConfig,
7172
7173    /// Order drift.
7174    #[serde(default)]
7175    pub order_drift: OrderDriftSchemaConfig,
7176}
7177
7178/// Customer payment drift configuration.
7179#[derive(Debug, Clone, Serialize, Deserialize)]
7180pub struct CustomerPaymentDriftSchemaConfig {
7181    /// Days extension during downturn (min, max).
7182    #[serde(default = "default_downturn_extension")]
7183    pub downturn_days_extension: (u32, u32),
7184
7185    /// Bad debt increase during downturn.
7186    #[serde(default = "default_bad_debt_increase")]
7187    pub downturn_bad_debt_increase: f64,
7188}
7189
7190fn default_downturn_extension() -> (u32, u32) {
7191    (5, 15)
7192}
7193
7194fn default_bad_debt_increase() -> f64 {
7195    0.02
7196}
7197
7198impl Default for CustomerPaymentDriftSchemaConfig {
7199    fn default() -> Self {
7200        Self {
7201            downturn_days_extension: (5, 15),
7202            downturn_bad_debt_increase: 0.02,
7203        }
7204    }
7205}
7206
7207/// Order drift configuration.
7208#[derive(Debug, Clone, Serialize, Deserialize)]
7209pub struct OrderDriftSchemaConfig {
7210    /// Digital shift rate (per year).
7211    #[serde(default = "default_digital_shift")]
7212    pub digital_shift_rate: f64,
7213}
7214
7215fn default_digital_shift() -> f64 {
7216    0.05
7217}
7218
7219impl Default for OrderDriftSchemaConfig {
7220    fn default() -> Self {
7221        Self {
7222            digital_shift_rate: 0.05,
7223        }
7224    }
7225}
7226
7227/// Employee behavior drift configuration.
7228#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7229pub struct EmployeeBehaviorSchemaConfig {
7230    /// Approval drift.
7231    #[serde(default)]
7232    pub approval_drift: ApprovalDriftSchemaConfig,
7233
7234    /// Error drift.
7235    #[serde(default)]
7236    pub error_drift: ErrorDriftSchemaConfig,
7237}
7238
7239/// Approval drift configuration.
7240#[derive(Debug, Clone, Serialize, Deserialize)]
7241pub struct ApprovalDriftSchemaConfig {
7242    /// EOM intensity increase per year.
7243    #[serde(default = "default_eom_intensity")]
7244    pub eom_intensity_increase_per_year: f64,
7245
7246    /// Rubber stamp volume threshold.
7247    #[serde(default = "default_rubber_stamp")]
7248    pub rubber_stamp_volume_threshold: u32,
7249}
7250
7251fn default_eom_intensity() -> f64 {
7252    0.05
7253}
7254
7255fn default_rubber_stamp() -> u32 {
7256    50
7257}
7258
7259impl Default for ApprovalDriftSchemaConfig {
7260    fn default() -> Self {
7261        Self {
7262            eom_intensity_increase_per_year: 0.05,
7263            rubber_stamp_volume_threshold: 50,
7264        }
7265    }
7266}
7267
7268/// Error drift configuration.
7269#[derive(Debug, Clone, Serialize, Deserialize)]
7270pub struct ErrorDriftSchemaConfig {
7271    /// New employee error rate.
7272    #[serde(default = "default_new_error")]
7273    pub new_employee_error_rate: f64,
7274
7275    /// Learning curve months.
7276    #[serde(default = "default_learning_months")]
7277    pub learning_curve_months: u32,
7278}
7279
7280fn default_new_error() -> f64 {
7281    0.08
7282}
7283
7284fn default_learning_months() -> u32 {
7285    6
7286}
7287
7288impl Default for ErrorDriftSchemaConfig {
7289    fn default() -> Self {
7290        Self {
7291            new_employee_error_rate: 0.08,
7292            learning_curve_months: 6,
7293        }
7294    }
7295}
7296
7297/// Collective behavior drift configuration.
7298#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7299pub struct CollectiveBehaviorSchemaConfig {
7300    /// Automation adoption configuration.
7301    #[serde(default)]
7302    pub automation_adoption: AutomationAdoptionSchemaConfig,
7303}
7304
7305/// Automation adoption configuration.
7306#[derive(Debug, Clone, Serialize, Deserialize)]
7307pub struct AutomationAdoptionSchemaConfig {
7308    /// Enable S-curve adoption model.
7309    #[serde(default)]
7310    pub s_curve_enabled: bool,
7311
7312    /// Adoption midpoint in months.
7313    #[serde(default = "default_midpoint")]
7314    pub adoption_midpoint_months: u32,
7315
7316    /// Steepness of adoption curve.
7317    #[serde(default = "default_steepness")]
7318    pub steepness: f64,
7319}
7320
7321fn default_midpoint() -> u32 {
7322    24
7323}
7324
7325fn default_steepness() -> f64 {
7326    0.15
7327}
7328
7329impl Default for AutomationAdoptionSchemaConfig {
7330    fn default() -> Self {
7331        Self {
7332            s_curve_enabled: false,
7333            adoption_midpoint_months: 24,
7334            steepness: 0.15,
7335        }
7336    }
7337}
7338
7339// =============================================================================
7340// Market Drift Configuration
7341// =============================================================================
7342
7343/// Configuration for market drift (economic cycles, commodities, price shocks).
7344#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7345pub struct MarketDriftSchemaConfig {
7346    /// Enable market drift.
7347    #[serde(default)]
7348    pub enabled: bool,
7349
7350    /// Economic cycle configuration.
7351    #[serde(default)]
7352    pub economic_cycle: MarketEconomicCycleSchemaConfig,
7353
7354    /// Industry-specific cycles.
7355    #[serde(default)]
7356    pub industry_cycles: std::collections::HashMap<String, IndustryCycleSchemaConfig>,
7357
7358    /// Commodity drift configuration.
7359    #[serde(default)]
7360    pub commodities: CommoditiesSchemaConfig,
7361}
7362
7363/// Market economic cycle configuration.
7364#[derive(Debug, Clone, Serialize, Deserialize)]
7365pub struct MarketEconomicCycleSchemaConfig {
7366    /// Enable economic cycle.
7367    #[serde(default)]
7368    pub enabled: bool,
7369
7370    /// Cycle type.
7371    #[serde(default)]
7372    pub cycle_type: CycleTypeSchemaConfig,
7373
7374    /// Cycle period in months.
7375    #[serde(default = "default_market_cycle_period")]
7376    pub period_months: u32,
7377
7378    /// Amplitude.
7379    #[serde(default = "default_market_amplitude")]
7380    pub amplitude: f64,
7381
7382    /// Recession configuration.
7383    #[serde(default)]
7384    pub recession: RecessionSchemaConfig,
7385}
7386
7387fn default_market_cycle_period() -> u32 {
7388    48
7389}
7390
7391fn default_market_amplitude() -> f64 {
7392    0.15
7393}
7394
7395impl Default for MarketEconomicCycleSchemaConfig {
7396    fn default() -> Self {
7397        Self {
7398            enabled: false,
7399            cycle_type: CycleTypeSchemaConfig::Sinusoidal,
7400            period_months: 48,
7401            amplitude: 0.15,
7402            recession: RecessionSchemaConfig::default(),
7403        }
7404    }
7405}
7406
7407/// Cycle type configuration.
7408#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
7409#[serde(rename_all = "snake_case")]
7410pub enum CycleTypeSchemaConfig {
7411    /// Sinusoidal cycle.
7412    #[default]
7413    Sinusoidal,
7414    /// Asymmetric cycle.
7415    Asymmetric,
7416    /// Mean-reverting cycle.
7417    MeanReverting,
7418}
7419
7420/// Recession configuration.
7421#[derive(Debug, Clone, Serialize, Deserialize)]
7422pub struct RecessionSchemaConfig {
7423    /// Enable recession simulation.
7424    #[serde(default)]
7425    pub enabled: bool,
7426
7427    /// Probability per year.
7428    #[serde(default = "default_recession_prob")]
7429    pub probability_per_year: f64,
7430
7431    /// Severity.
7432    #[serde(default)]
7433    pub severity: RecessionSeveritySchemaConfig,
7434
7435    /// Specific recession periods.
7436    #[serde(default)]
7437    pub recession_periods: Vec<RecessionPeriodSchemaConfig>,
7438}
7439
7440fn default_recession_prob() -> f64 {
7441    0.10
7442}
7443
7444impl Default for RecessionSchemaConfig {
7445    fn default() -> Self {
7446        Self {
7447            enabled: false,
7448            probability_per_year: 0.10,
7449            severity: RecessionSeveritySchemaConfig::Moderate,
7450            recession_periods: Vec::new(),
7451        }
7452    }
7453}
7454
7455/// Recession severity configuration.
7456#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
7457#[serde(rename_all = "snake_case")]
7458pub enum RecessionSeveritySchemaConfig {
7459    /// Mild recession.
7460    Mild,
7461    /// Moderate recession.
7462    #[default]
7463    Moderate,
7464    /// Severe recession.
7465    Severe,
7466}
7467
7468/// Recession period configuration.
7469#[derive(Debug, Clone, Serialize, Deserialize)]
7470pub struct RecessionPeriodSchemaConfig {
7471    /// Start month.
7472    pub start_month: u32,
7473    /// Duration in months.
7474    pub duration_months: u32,
7475}
7476
7477/// Industry cycle configuration.
7478#[derive(Debug, Clone, Serialize, Deserialize)]
7479pub struct IndustryCycleSchemaConfig {
7480    /// Period in months.
7481    #[serde(default = "default_industry_period")]
7482    pub period_months: u32,
7483
7484    /// Amplitude.
7485    #[serde(default = "default_industry_amp")]
7486    pub amplitude: f64,
7487}
7488
7489fn default_industry_period() -> u32 {
7490    36
7491}
7492
7493fn default_industry_amp() -> f64 {
7494    0.20
7495}
7496
7497/// Commodities drift configuration.
7498#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7499pub struct CommoditiesSchemaConfig {
7500    /// Enable commodity drift.
7501    #[serde(default)]
7502    pub enabled: bool,
7503
7504    /// Commodity items.
7505    #[serde(default)]
7506    pub items: Vec<CommodityItemSchemaConfig>,
7507}
7508
7509/// Commodity item configuration.
7510#[derive(Debug, Clone, Serialize, Deserialize)]
7511pub struct CommodityItemSchemaConfig {
7512    /// Commodity name.
7513    pub name: String,
7514
7515    /// Volatility.
7516    #[serde(default = "default_volatility")]
7517    pub volatility: f64,
7518
7519    /// COGS pass-through.
7520    #[serde(default)]
7521    pub cogs_pass_through: f64,
7522
7523    /// Overhead pass-through.
7524    #[serde(default)]
7525    pub overhead_pass_through: f64,
7526}
7527
7528fn default_volatility() -> f64 {
7529    0.20
7530}
7531
7532// =============================================================================
7533// Drift Labeling Configuration
7534// =============================================================================
7535
7536/// Configuration for drift ground truth labeling.
7537#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7538pub struct DriftLabelingSchemaConfig {
7539    /// Enable drift labeling.
7540    #[serde(default)]
7541    pub enabled: bool,
7542
7543    /// Statistical drift labeling.
7544    #[serde(default)]
7545    pub statistical: StatisticalDriftLabelingSchemaConfig,
7546
7547    /// Categorical drift labeling.
7548    #[serde(default)]
7549    pub categorical: CategoricalDriftLabelingSchemaConfig,
7550
7551    /// Temporal drift labeling.
7552    #[serde(default)]
7553    pub temporal: TemporalDriftLabelingSchemaConfig,
7554
7555    /// Regulatory calendar preset.
7556    #[serde(default)]
7557    pub regulatory_calendar_preset: Option<String>,
7558}
7559
7560/// Statistical drift labeling configuration.
7561#[derive(Debug, Clone, Serialize, Deserialize)]
7562pub struct StatisticalDriftLabelingSchemaConfig {
7563    /// Enable statistical drift labeling.
7564    #[serde(default = "default_true_val")]
7565    pub enabled: bool,
7566
7567    /// Minimum magnitude threshold.
7568    #[serde(default = "default_min_magnitude")]
7569    pub min_magnitude_threshold: f64,
7570}
7571
7572fn default_min_magnitude() -> f64 {
7573    0.05
7574}
7575
7576impl Default for StatisticalDriftLabelingSchemaConfig {
7577    fn default() -> Self {
7578        Self {
7579            enabled: true,
7580            min_magnitude_threshold: 0.05,
7581        }
7582    }
7583}
7584
7585/// Categorical drift labeling configuration.
7586#[derive(Debug, Clone, Serialize, Deserialize)]
7587pub struct CategoricalDriftLabelingSchemaConfig {
7588    /// Enable categorical drift labeling.
7589    #[serde(default = "default_true_val")]
7590    pub enabled: bool,
7591}
7592
7593impl Default for CategoricalDriftLabelingSchemaConfig {
7594    fn default() -> Self {
7595        Self { enabled: true }
7596    }
7597}
7598
7599/// Temporal drift labeling configuration.
7600#[derive(Debug, Clone, Serialize, Deserialize)]
7601pub struct TemporalDriftLabelingSchemaConfig {
7602    /// Enable temporal drift labeling.
7603    #[serde(default = "default_true_val")]
7604    pub enabled: bool,
7605}
7606
7607impl Default for TemporalDriftLabelingSchemaConfig {
7608    fn default() -> Self {
7609        Self { enabled: true }
7610    }
7611}
7612
7613// =============================================================================
7614// Enhanced Anomaly Injection Configuration
7615// =============================================================================
7616
7617/// Enhanced anomaly injection configuration.
7618///
7619/// Provides comprehensive anomaly injection capabilities including:
7620/// - Multi-stage fraud schemes (embezzlement, revenue manipulation, kickbacks)
7621/// - Correlated anomaly injection (co-occurrence patterns, error cascades)
7622/// - Near-miss generation for false positive reduction
7623/// - Detection difficulty classification
7624/// - Context-aware injection based on entity behavior
7625#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7626pub struct EnhancedAnomalyConfig {
7627    /// Enable enhanced anomaly injection.
7628    #[serde(default)]
7629    pub enabled: bool,
7630
7631    /// Base anomaly rates.
7632    #[serde(default)]
7633    pub rates: AnomalyRateConfig,
7634
7635    /// Multi-stage fraud scheme configuration.
7636    #[serde(default)]
7637    pub multi_stage_schemes: MultiStageSchemeConfig,
7638
7639    /// Correlated anomaly injection configuration.
7640    #[serde(default)]
7641    pub correlated_injection: CorrelatedInjectionConfig,
7642
7643    /// Near-miss generation configuration.
7644    #[serde(default)]
7645    pub near_miss: NearMissConfig,
7646
7647    /// Detection difficulty classification configuration.
7648    #[serde(default)]
7649    pub difficulty_classification: DifficultyClassificationConfig,
7650
7651    /// Context-aware injection configuration.
7652    #[serde(default)]
7653    pub context_aware: ContextAwareConfig,
7654
7655    /// Enhanced labeling configuration.
7656    #[serde(default)]
7657    pub labeling: EnhancedLabelingConfig,
7658}
7659
7660/// Base anomaly rate configuration.
7661#[derive(Debug, Clone, Serialize, Deserialize)]
7662pub struct AnomalyRateConfig {
7663    /// Total anomaly rate (0.0 to 1.0).
7664    #[serde(default = "default_total_anomaly_rate")]
7665    pub total_rate: f64,
7666
7667    /// Fraud anomaly rate.
7668    #[serde(default = "default_fraud_anomaly_rate")]
7669    pub fraud_rate: f64,
7670
7671    /// Error anomaly rate.
7672    #[serde(default = "default_error_anomaly_rate")]
7673    pub error_rate: f64,
7674
7675    /// Process issue rate.
7676    #[serde(default = "default_process_anomaly_rate")]
7677    pub process_rate: f64,
7678}
7679
7680fn default_total_anomaly_rate() -> f64 {
7681    0.03
7682}
7683fn default_fraud_anomaly_rate() -> f64 {
7684    0.01
7685}
7686fn default_error_anomaly_rate() -> f64 {
7687    0.015
7688}
7689fn default_process_anomaly_rate() -> f64 {
7690    0.005
7691}
7692
7693impl Default for AnomalyRateConfig {
7694    fn default() -> Self {
7695        Self {
7696            total_rate: default_total_anomaly_rate(),
7697            fraud_rate: default_fraud_anomaly_rate(),
7698            error_rate: default_error_anomaly_rate(),
7699            process_rate: default_process_anomaly_rate(),
7700        }
7701    }
7702}
7703
7704/// Multi-stage fraud scheme configuration.
7705#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7706pub struct MultiStageSchemeConfig {
7707    /// Enable multi-stage fraud schemes.
7708    #[serde(default)]
7709    pub enabled: bool,
7710
7711    /// Embezzlement scheme configuration.
7712    #[serde(default)]
7713    pub embezzlement: EmbezzlementSchemeConfig,
7714
7715    /// Revenue manipulation scheme configuration.
7716    #[serde(default)]
7717    pub revenue_manipulation: RevenueManipulationSchemeConfig,
7718
7719    /// Vendor kickback scheme configuration.
7720    #[serde(default)]
7721    pub kickback: KickbackSchemeConfig,
7722}
7723
7724/// Embezzlement scheme configuration.
7725#[derive(Debug, Clone, Serialize, Deserialize)]
7726pub struct EmbezzlementSchemeConfig {
7727    /// Probability of starting an embezzlement scheme per perpetrator per year.
7728    #[serde(default = "default_embezzlement_probability")]
7729    pub probability: f64,
7730
7731    /// Testing stage configuration.
7732    #[serde(default)]
7733    pub testing_stage: SchemeStageConfig,
7734
7735    /// Escalation stage configuration.
7736    #[serde(default)]
7737    pub escalation_stage: SchemeStageConfig,
7738
7739    /// Acceleration stage configuration.
7740    #[serde(default)]
7741    pub acceleration_stage: SchemeStageConfig,
7742
7743    /// Desperation stage configuration.
7744    #[serde(default)]
7745    pub desperation_stage: SchemeStageConfig,
7746}
7747
7748fn default_embezzlement_probability() -> f64 {
7749    0.02
7750}
7751
7752impl Default for EmbezzlementSchemeConfig {
7753    fn default() -> Self {
7754        Self {
7755            probability: default_embezzlement_probability(),
7756            testing_stage: SchemeStageConfig {
7757                duration_months: 2,
7758                amount_min: 100.0,
7759                amount_max: 500.0,
7760                transaction_count_min: 2,
7761                transaction_count_max: 5,
7762                difficulty: "hard".to_string(),
7763            },
7764            escalation_stage: SchemeStageConfig {
7765                duration_months: 6,
7766                amount_min: 500.0,
7767                amount_max: 2000.0,
7768                transaction_count_min: 3,
7769                transaction_count_max: 8,
7770                difficulty: "moderate".to_string(),
7771            },
7772            acceleration_stage: SchemeStageConfig {
7773                duration_months: 3,
7774                amount_min: 2000.0,
7775                amount_max: 10000.0,
7776                transaction_count_min: 5,
7777                transaction_count_max: 12,
7778                difficulty: "easy".to_string(),
7779            },
7780            desperation_stage: SchemeStageConfig {
7781                duration_months: 1,
7782                amount_min: 10000.0,
7783                amount_max: 50000.0,
7784                transaction_count_min: 3,
7785                transaction_count_max: 6,
7786                difficulty: "trivial".to_string(),
7787            },
7788        }
7789    }
7790}
7791
7792/// Revenue manipulation scheme configuration.
7793#[derive(Debug, Clone, Serialize, Deserialize)]
7794pub struct RevenueManipulationSchemeConfig {
7795    /// Probability of starting a revenue manipulation scheme per period.
7796    #[serde(default = "default_revenue_manipulation_probability")]
7797    pub probability: f64,
7798
7799    /// Early revenue recognition inflation target (Q4).
7800    #[serde(default = "default_early_recognition_target")]
7801    pub early_recognition_target: f64,
7802
7803    /// Expense deferral inflation target (Q1).
7804    #[serde(default = "default_expense_deferral_target")]
7805    pub expense_deferral_target: f64,
7806
7807    /// Reserve release inflation target (Q2).
7808    #[serde(default = "default_reserve_release_target")]
7809    pub reserve_release_target: f64,
7810
7811    /// Channel stuffing inflation target (Q4).
7812    #[serde(default = "default_channel_stuffing_target")]
7813    pub channel_stuffing_target: f64,
7814}
7815
7816fn default_revenue_manipulation_probability() -> f64 {
7817    0.01
7818}
7819fn default_early_recognition_target() -> f64 {
7820    0.02
7821}
7822fn default_expense_deferral_target() -> f64 {
7823    0.03
7824}
7825fn default_reserve_release_target() -> f64 {
7826    0.02
7827}
7828fn default_channel_stuffing_target() -> f64 {
7829    0.05
7830}
7831
7832impl Default for RevenueManipulationSchemeConfig {
7833    fn default() -> Self {
7834        Self {
7835            probability: default_revenue_manipulation_probability(),
7836            early_recognition_target: default_early_recognition_target(),
7837            expense_deferral_target: default_expense_deferral_target(),
7838            reserve_release_target: default_reserve_release_target(),
7839            channel_stuffing_target: default_channel_stuffing_target(),
7840        }
7841    }
7842}
7843
7844/// Vendor kickback scheme configuration.
7845#[derive(Debug, Clone, Serialize, Deserialize)]
7846pub struct KickbackSchemeConfig {
7847    /// Probability of starting a kickback scheme.
7848    #[serde(default = "default_kickback_probability")]
7849    pub probability: f64,
7850
7851    /// Minimum price inflation percentage.
7852    #[serde(default = "default_kickback_inflation_min")]
7853    pub inflation_min: f64,
7854
7855    /// Maximum price inflation percentage.
7856    #[serde(default = "default_kickback_inflation_max")]
7857    pub inflation_max: f64,
7858
7859    /// Kickback percentage (of inflation).
7860    #[serde(default = "default_kickback_percent")]
7861    pub kickback_percent: f64,
7862
7863    /// Setup duration in months.
7864    #[serde(default = "default_kickback_setup_months")]
7865    pub setup_months: u32,
7866
7867    /// Main operation duration in months.
7868    #[serde(default = "default_kickback_operation_months")]
7869    pub operation_months: u32,
7870}
7871
7872fn default_kickback_probability() -> f64 {
7873    0.01
7874}
7875fn default_kickback_inflation_min() -> f64 {
7876    0.10
7877}
7878fn default_kickback_inflation_max() -> f64 {
7879    0.25
7880}
7881fn default_kickback_percent() -> f64 {
7882    0.50
7883}
7884fn default_kickback_setup_months() -> u32 {
7885    3
7886}
7887fn default_kickback_operation_months() -> u32 {
7888    12
7889}
7890
7891impl Default for KickbackSchemeConfig {
7892    fn default() -> Self {
7893        Self {
7894            probability: default_kickback_probability(),
7895            inflation_min: default_kickback_inflation_min(),
7896            inflation_max: default_kickback_inflation_max(),
7897            kickback_percent: default_kickback_percent(),
7898            setup_months: default_kickback_setup_months(),
7899            operation_months: default_kickback_operation_months(),
7900        }
7901    }
7902}
7903
7904/// Individual scheme stage configuration.
7905#[derive(Debug, Clone, Serialize, Deserialize)]
7906pub struct SchemeStageConfig {
7907    /// Duration in months.
7908    pub duration_months: u32,
7909
7910    /// Minimum transaction amount.
7911    pub amount_min: f64,
7912
7913    /// Maximum transaction amount.
7914    pub amount_max: f64,
7915
7916    /// Minimum number of transactions.
7917    pub transaction_count_min: u32,
7918
7919    /// Maximum number of transactions.
7920    pub transaction_count_max: u32,
7921
7922    /// Detection difficulty level (trivial, easy, moderate, hard, expert).
7923    pub difficulty: String,
7924}
7925
7926impl Default for SchemeStageConfig {
7927    fn default() -> Self {
7928        Self {
7929            duration_months: 3,
7930            amount_min: 100.0,
7931            amount_max: 1000.0,
7932            transaction_count_min: 2,
7933            transaction_count_max: 10,
7934            difficulty: "moderate".to_string(),
7935        }
7936    }
7937}
7938
7939/// Correlated anomaly injection configuration.
7940#[derive(Debug, Clone, Serialize, Deserialize)]
7941pub struct CorrelatedInjectionConfig {
7942    /// Enable correlated anomaly injection.
7943    #[serde(default)]
7944    pub enabled: bool,
7945
7946    /// Enable fraud concealment co-occurrence patterns.
7947    #[serde(default = "default_true_val")]
7948    pub fraud_concealment: bool,
7949
7950    /// Enable error cascade patterns.
7951    #[serde(default = "default_true_val")]
7952    pub error_cascade: bool,
7953
7954    /// Enable temporal clustering (period-end spikes).
7955    #[serde(default = "default_true_val")]
7956    pub temporal_clustering: bool,
7957
7958    /// Temporal clustering configuration.
7959    #[serde(default)]
7960    pub temporal_clustering_config: TemporalClusteringConfig,
7961
7962    /// Co-occurrence patterns.
7963    #[serde(default)]
7964    pub co_occurrence_patterns: Vec<CoOccurrencePatternConfig>,
7965}
7966
7967impl Default for CorrelatedInjectionConfig {
7968    fn default() -> Self {
7969        Self {
7970            enabled: false,
7971            fraud_concealment: true,
7972            error_cascade: true,
7973            temporal_clustering: true,
7974            temporal_clustering_config: TemporalClusteringConfig::default(),
7975            co_occurrence_patterns: Vec::new(),
7976        }
7977    }
7978}
7979
7980/// Temporal clustering configuration.
7981#[derive(Debug, Clone, Serialize, Deserialize)]
7982pub struct TemporalClusteringConfig {
7983    /// Period-end error multiplier.
7984    #[serde(default = "default_period_end_multiplier")]
7985    pub period_end_multiplier: f64,
7986
7987    /// Number of business days before period end to apply multiplier.
7988    #[serde(default = "default_period_end_days")]
7989    pub period_end_days: u32,
7990
7991    /// Quarter-end additional multiplier.
7992    #[serde(default = "default_quarter_end_multiplier")]
7993    pub quarter_end_multiplier: f64,
7994
7995    /// Year-end additional multiplier.
7996    #[serde(default = "default_year_end_multiplier")]
7997    pub year_end_multiplier: f64,
7998}
7999
8000fn default_period_end_multiplier() -> f64 {
8001    2.5
8002}
8003fn default_period_end_days() -> u32 {
8004    5
8005}
8006fn default_quarter_end_multiplier() -> f64 {
8007    1.5
8008}
8009fn default_year_end_multiplier() -> f64 {
8010    2.0
8011}
8012
8013impl Default for TemporalClusteringConfig {
8014    fn default() -> Self {
8015        Self {
8016            period_end_multiplier: default_period_end_multiplier(),
8017            period_end_days: default_period_end_days(),
8018            quarter_end_multiplier: default_quarter_end_multiplier(),
8019            year_end_multiplier: default_year_end_multiplier(),
8020        }
8021    }
8022}
8023
8024/// Co-occurrence pattern configuration.
8025#[derive(Debug, Clone, Serialize, Deserialize)]
8026pub struct CoOccurrencePatternConfig {
8027    /// Pattern name.
8028    pub name: String,
8029
8030    /// Primary anomaly type that triggers the pattern.
8031    pub primary_type: String,
8032
8033    /// Correlated anomalies.
8034    pub correlated: Vec<CorrelatedAnomalyConfig>,
8035}
8036
8037/// Correlated anomaly configuration.
8038#[derive(Debug, Clone, Serialize, Deserialize)]
8039pub struct CorrelatedAnomalyConfig {
8040    /// Anomaly type.
8041    pub anomaly_type: String,
8042
8043    /// Probability of occurrence (0.0 to 1.0).
8044    pub probability: f64,
8045
8046    /// Minimum lag in days.
8047    pub lag_days_min: i32,
8048
8049    /// Maximum lag in days.
8050    pub lag_days_max: i32,
8051}
8052
8053/// Near-miss generation configuration.
8054#[derive(Debug, Clone, Serialize, Deserialize)]
8055pub struct NearMissConfig {
8056    /// Enable near-miss generation.
8057    #[serde(default)]
8058    pub enabled: bool,
8059
8060    /// Proportion of "anomalies" that are actually near-misses (0.0 to 1.0).
8061    #[serde(default = "default_near_miss_proportion")]
8062    pub proportion: f64,
8063
8064    /// Enable near-duplicate pattern.
8065    #[serde(default = "default_true_val")]
8066    pub near_duplicate: bool,
8067
8068    /// Near-duplicate date difference range in days.
8069    #[serde(default)]
8070    pub near_duplicate_days: NearDuplicateDaysConfig,
8071
8072    /// Enable threshold proximity pattern.
8073    #[serde(default = "default_true_val")]
8074    pub threshold_proximity: bool,
8075
8076    /// Threshold proximity range (e.g., 0.90-0.99 of threshold).
8077    #[serde(default)]
8078    pub threshold_proximity_range: ThresholdProximityRangeConfig,
8079
8080    /// Enable unusual but legitimate patterns.
8081    #[serde(default = "default_true_val")]
8082    pub unusual_legitimate: bool,
8083
8084    /// Types of unusual legitimate patterns to generate.
8085    #[serde(default = "default_unusual_legitimate_types")]
8086    pub unusual_legitimate_types: Vec<String>,
8087
8088    /// Enable corrected error patterns.
8089    #[serde(default = "default_true_val")]
8090    pub corrected_errors: bool,
8091
8092    /// Corrected error correction lag range in days.
8093    #[serde(default)]
8094    pub corrected_error_lag: CorrectedErrorLagConfig,
8095}
8096
8097fn default_near_miss_proportion() -> f64 {
8098    0.30
8099}
8100
8101fn default_unusual_legitimate_types() -> Vec<String> {
8102    vec![
8103        "year_end_bonus".to_string(),
8104        "contract_prepayment".to_string(),
8105        "insurance_claim".to_string(),
8106        "settlement_payment".to_string(),
8107    ]
8108}
8109
8110impl Default for NearMissConfig {
8111    fn default() -> Self {
8112        Self {
8113            enabled: false,
8114            proportion: default_near_miss_proportion(),
8115            near_duplicate: true,
8116            near_duplicate_days: NearDuplicateDaysConfig::default(),
8117            threshold_proximity: true,
8118            threshold_proximity_range: ThresholdProximityRangeConfig::default(),
8119            unusual_legitimate: true,
8120            unusual_legitimate_types: default_unusual_legitimate_types(),
8121            corrected_errors: true,
8122            corrected_error_lag: CorrectedErrorLagConfig::default(),
8123        }
8124    }
8125}
8126
8127/// Near-duplicate days configuration.
8128#[derive(Debug, Clone, Serialize, Deserialize)]
8129pub struct NearDuplicateDaysConfig {
8130    /// Minimum days apart.
8131    #[serde(default = "default_near_duplicate_min")]
8132    pub min: u32,
8133
8134    /// Maximum days apart.
8135    #[serde(default = "default_near_duplicate_max")]
8136    pub max: u32,
8137}
8138
8139fn default_near_duplicate_min() -> u32 {
8140    1
8141}
8142fn default_near_duplicate_max() -> u32 {
8143    3
8144}
8145
8146impl Default for NearDuplicateDaysConfig {
8147    fn default() -> Self {
8148        Self {
8149            min: default_near_duplicate_min(),
8150            max: default_near_duplicate_max(),
8151        }
8152    }
8153}
8154
8155/// Threshold proximity range configuration.
8156#[derive(Debug, Clone, Serialize, Deserialize)]
8157pub struct ThresholdProximityRangeConfig {
8158    /// Minimum proximity (e.g., 0.90 = 90% of threshold).
8159    #[serde(default = "default_threshold_proximity_min")]
8160    pub min: f64,
8161
8162    /// Maximum proximity (e.g., 0.99 = 99% of threshold).
8163    #[serde(default = "default_threshold_proximity_max")]
8164    pub max: f64,
8165}
8166
8167fn default_threshold_proximity_min() -> f64 {
8168    0.90
8169}
8170fn default_threshold_proximity_max() -> f64 {
8171    0.99
8172}
8173
8174impl Default for ThresholdProximityRangeConfig {
8175    fn default() -> Self {
8176        Self {
8177            min: default_threshold_proximity_min(),
8178            max: default_threshold_proximity_max(),
8179        }
8180    }
8181}
8182
8183/// Corrected error lag configuration.
8184#[derive(Debug, Clone, Serialize, Deserialize)]
8185pub struct CorrectedErrorLagConfig {
8186    /// Minimum correction lag in days.
8187    #[serde(default = "default_corrected_error_lag_min")]
8188    pub min: u32,
8189
8190    /// Maximum correction lag in days.
8191    #[serde(default = "default_corrected_error_lag_max")]
8192    pub max: u32,
8193}
8194
8195fn default_corrected_error_lag_min() -> u32 {
8196    1
8197}
8198fn default_corrected_error_lag_max() -> u32 {
8199    5
8200}
8201
8202impl Default for CorrectedErrorLagConfig {
8203    fn default() -> Self {
8204        Self {
8205            min: default_corrected_error_lag_min(),
8206            max: default_corrected_error_lag_max(),
8207        }
8208    }
8209}
8210
8211/// Detection difficulty classification configuration.
8212#[derive(Debug, Clone, Serialize, Deserialize)]
8213pub struct DifficultyClassificationConfig {
8214    /// Enable detection difficulty classification.
8215    #[serde(default)]
8216    pub enabled: bool,
8217
8218    /// Target distribution of difficulty levels.
8219    #[serde(default)]
8220    pub target_distribution: DifficultyDistributionConfig,
8221}
8222
8223impl Default for DifficultyClassificationConfig {
8224    fn default() -> Self {
8225        Self {
8226            enabled: true,
8227            target_distribution: DifficultyDistributionConfig::default(),
8228        }
8229    }
8230}
8231
8232/// Target distribution of detection difficulty levels.
8233#[derive(Debug, Clone, Serialize, Deserialize)]
8234pub struct DifficultyDistributionConfig {
8235    /// Proportion of trivial anomalies (expected 99% detection).
8236    #[serde(default = "default_difficulty_trivial")]
8237    pub trivial: f64,
8238
8239    /// Proportion of easy anomalies (expected 90% detection).
8240    #[serde(default = "default_difficulty_easy")]
8241    pub easy: f64,
8242
8243    /// Proportion of moderate anomalies (expected 70% detection).
8244    #[serde(default = "default_difficulty_moderate")]
8245    pub moderate: f64,
8246
8247    /// Proportion of hard anomalies (expected 40% detection).
8248    #[serde(default = "default_difficulty_hard")]
8249    pub hard: f64,
8250
8251    /// Proportion of expert anomalies (expected 15% detection).
8252    #[serde(default = "default_difficulty_expert")]
8253    pub expert: f64,
8254}
8255
8256fn default_difficulty_trivial() -> f64 {
8257    0.15
8258}
8259fn default_difficulty_easy() -> f64 {
8260    0.25
8261}
8262fn default_difficulty_moderate() -> f64 {
8263    0.30
8264}
8265fn default_difficulty_hard() -> f64 {
8266    0.20
8267}
8268fn default_difficulty_expert() -> f64 {
8269    0.10
8270}
8271
8272impl Default for DifficultyDistributionConfig {
8273    fn default() -> Self {
8274        Self {
8275            trivial: default_difficulty_trivial(),
8276            easy: default_difficulty_easy(),
8277            moderate: default_difficulty_moderate(),
8278            hard: default_difficulty_hard(),
8279            expert: default_difficulty_expert(),
8280        }
8281    }
8282}
8283
8284/// Context-aware injection configuration.
8285#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8286pub struct ContextAwareConfig {
8287    /// Enable context-aware injection.
8288    #[serde(default)]
8289    pub enabled: bool,
8290
8291    /// Vendor-specific anomaly rules.
8292    #[serde(default)]
8293    pub vendor_rules: VendorAnomalyRulesConfig,
8294
8295    /// Employee-specific anomaly rules.
8296    #[serde(default)]
8297    pub employee_rules: EmployeeAnomalyRulesConfig,
8298
8299    /// Account-specific anomaly rules.
8300    #[serde(default)]
8301    pub account_rules: AccountAnomalyRulesConfig,
8302
8303    /// Behavioral baseline configuration.
8304    #[serde(default)]
8305    pub behavioral_baseline: BehavioralBaselineConfig,
8306}
8307
8308/// Vendor-specific anomaly rules configuration.
8309#[derive(Debug, Clone, Serialize, Deserialize)]
8310pub struct VendorAnomalyRulesConfig {
8311    /// Error rate multiplier for new vendors (< threshold days).
8312    #[serde(default = "default_new_vendor_multiplier")]
8313    pub new_vendor_error_multiplier: f64,
8314
8315    /// Days threshold for "new" vendor classification.
8316    #[serde(default = "default_new_vendor_threshold")]
8317    pub new_vendor_threshold_days: u32,
8318
8319    /// Error rate multiplier for international vendors.
8320    #[serde(default = "default_international_multiplier")]
8321    pub international_error_multiplier: f64,
8322
8323    /// Strategic vendor anomaly types (may differ from general vendors).
8324    #[serde(default = "default_strategic_vendor_types")]
8325    pub strategic_vendor_anomaly_types: Vec<String>,
8326}
8327
8328fn default_new_vendor_multiplier() -> f64 {
8329    2.5
8330}
8331fn default_new_vendor_threshold() -> u32 {
8332    90
8333}
8334fn default_international_multiplier() -> f64 {
8335    1.5
8336}
8337fn default_strategic_vendor_types() -> Vec<String> {
8338    vec![
8339        "pricing_dispute".to_string(),
8340        "contract_violation".to_string(),
8341    ]
8342}
8343
8344impl Default for VendorAnomalyRulesConfig {
8345    fn default() -> Self {
8346        Self {
8347            new_vendor_error_multiplier: default_new_vendor_multiplier(),
8348            new_vendor_threshold_days: default_new_vendor_threshold(),
8349            international_error_multiplier: default_international_multiplier(),
8350            strategic_vendor_anomaly_types: default_strategic_vendor_types(),
8351        }
8352    }
8353}
8354
8355/// Employee-specific anomaly rules configuration.
8356#[derive(Debug, Clone, Serialize, Deserialize)]
8357pub struct EmployeeAnomalyRulesConfig {
8358    /// Error rate for new employees (< threshold days).
8359    #[serde(default = "default_new_employee_rate")]
8360    pub new_employee_error_rate: f64,
8361
8362    /// Days threshold for "new" employee classification.
8363    #[serde(default = "default_new_employee_threshold")]
8364    pub new_employee_threshold_days: u32,
8365
8366    /// Transaction volume threshold for fatigue errors.
8367    #[serde(default = "default_volume_fatigue_threshold")]
8368    pub volume_fatigue_threshold: u32,
8369
8370    /// Error rate multiplier when primary approver is absent.
8371    #[serde(default = "default_coverage_multiplier")]
8372    pub coverage_error_multiplier: f64,
8373}
8374
8375fn default_new_employee_rate() -> f64 {
8376    0.05
8377}
8378fn default_new_employee_threshold() -> u32 {
8379    180
8380}
8381fn default_volume_fatigue_threshold() -> u32 {
8382    50
8383}
8384fn default_coverage_multiplier() -> f64 {
8385    1.8
8386}
8387
8388impl Default for EmployeeAnomalyRulesConfig {
8389    fn default() -> Self {
8390        Self {
8391            new_employee_error_rate: default_new_employee_rate(),
8392            new_employee_threshold_days: default_new_employee_threshold(),
8393            volume_fatigue_threshold: default_volume_fatigue_threshold(),
8394            coverage_error_multiplier: default_coverage_multiplier(),
8395        }
8396    }
8397}
8398
8399/// Account-specific anomaly rules configuration.
8400#[derive(Debug, Clone, Serialize, Deserialize)]
8401pub struct AccountAnomalyRulesConfig {
8402    /// Error rate multiplier for high-risk accounts.
8403    #[serde(default = "default_high_risk_multiplier")]
8404    pub high_risk_account_multiplier: f64,
8405
8406    /// Account codes considered high-risk.
8407    #[serde(default = "default_high_risk_accounts")]
8408    pub high_risk_accounts: Vec<String>,
8409
8410    /// Error rate multiplier for suspense accounts.
8411    #[serde(default = "default_suspense_multiplier")]
8412    pub suspense_account_multiplier: f64,
8413
8414    /// Account codes considered suspense accounts.
8415    #[serde(default = "default_suspense_accounts")]
8416    pub suspense_accounts: Vec<String>,
8417
8418    /// Error rate multiplier for intercompany accounts.
8419    #[serde(default = "default_intercompany_multiplier")]
8420    pub intercompany_account_multiplier: f64,
8421}
8422
8423fn default_high_risk_multiplier() -> f64 {
8424    2.0
8425}
8426fn default_high_risk_accounts() -> Vec<String> {
8427    vec![
8428        "1100".to_string(), // AR Control
8429        "2000".to_string(), // AP Control
8430        "3000".to_string(), // Cash
8431    ]
8432}
8433fn default_suspense_multiplier() -> f64 {
8434    3.0
8435}
8436fn default_suspense_accounts() -> Vec<String> {
8437    vec!["9999".to_string(), "9998".to_string()]
8438}
8439fn default_intercompany_multiplier() -> f64 {
8440    1.5
8441}
8442
8443impl Default for AccountAnomalyRulesConfig {
8444    fn default() -> Self {
8445        Self {
8446            high_risk_account_multiplier: default_high_risk_multiplier(),
8447            high_risk_accounts: default_high_risk_accounts(),
8448            suspense_account_multiplier: default_suspense_multiplier(),
8449            suspense_accounts: default_suspense_accounts(),
8450            intercompany_account_multiplier: default_intercompany_multiplier(),
8451        }
8452    }
8453}
8454
8455/// Behavioral baseline configuration.
8456#[derive(Debug, Clone, Serialize, Deserialize)]
8457pub struct BehavioralBaselineConfig {
8458    /// Enable behavioral baseline tracking.
8459    #[serde(default)]
8460    pub enabled: bool,
8461
8462    /// Number of days to build baseline from.
8463    #[serde(default = "default_baseline_period")]
8464    pub baseline_period_days: u32,
8465
8466    /// Standard deviation threshold for amount anomalies.
8467    #[serde(default = "default_deviation_threshold")]
8468    pub deviation_threshold_std: f64,
8469
8470    /// Standard deviation threshold for frequency anomalies.
8471    #[serde(default = "default_frequency_deviation")]
8472    pub frequency_deviation_threshold: f64,
8473}
8474
8475fn default_baseline_period() -> u32 {
8476    90
8477}
8478fn default_deviation_threshold() -> f64 {
8479    3.0
8480}
8481fn default_frequency_deviation() -> f64 {
8482    2.0
8483}
8484
8485impl Default for BehavioralBaselineConfig {
8486    fn default() -> Self {
8487        Self {
8488            enabled: false,
8489            baseline_period_days: default_baseline_period(),
8490            deviation_threshold_std: default_deviation_threshold(),
8491            frequency_deviation_threshold: default_frequency_deviation(),
8492        }
8493    }
8494}
8495
8496/// Enhanced labeling configuration.
8497#[derive(Debug, Clone, Serialize, Deserialize)]
8498pub struct EnhancedLabelingConfig {
8499    /// Enable severity scoring.
8500    #[serde(default = "default_true_val")]
8501    pub severity_scoring: bool,
8502
8503    /// Enable difficulty classification.
8504    #[serde(default = "default_true_val")]
8505    pub difficulty_classification: bool,
8506
8507    /// Materiality thresholds for severity classification.
8508    #[serde(default)]
8509    pub materiality_thresholds: MaterialityThresholdsConfig,
8510}
8511
8512impl Default for EnhancedLabelingConfig {
8513    fn default() -> Self {
8514        Self {
8515            severity_scoring: true,
8516            difficulty_classification: true,
8517            materiality_thresholds: MaterialityThresholdsConfig::default(),
8518        }
8519    }
8520}
8521
8522/// Materiality thresholds configuration.
8523#[derive(Debug, Clone, Serialize, Deserialize)]
8524pub struct MaterialityThresholdsConfig {
8525    /// Threshold for trivial impact (as percentage of total).
8526    #[serde(default = "default_materiality_trivial")]
8527    pub trivial: f64,
8528
8529    /// Threshold for immaterial impact.
8530    #[serde(default = "default_materiality_immaterial")]
8531    pub immaterial: f64,
8532
8533    /// Threshold for material impact.
8534    #[serde(default = "default_materiality_material")]
8535    pub material: f64,
8536
8537    /// Threshold for highly material impact.
8538    #[serde(default = "default_materiality_highly_material")]
8539    pub highly_material: f64,
8540}
8541
8542fn default_materiality_trivial() -> f64 {
8543    0.001
8544}
8545fn default_materiality_immaterial() -> f64 {
8546    0.01
8547}
8548fn default_materiality_material() -> f64 {
8549    0.05
8550}
8551fn default_materiality_highly_material() -> f64 {
8552    0.10
8553}
8554
8555impl Default for MaterialityThresholdsConfig {
8556    fn default() -> Self {
8557        Self {
8558            trivial: default_materiality_trivial(),
8559            immaterial: default_materiality_immaterial(),
8560            material: default_materiality_material(),
8561            highly_material: default_materiality_highly_material(),
8562        }
8563    }
8564}
8565
8566// =============================================================================
8567// Industry-Specific Configuration
8568// =============================================================================
8569
8570/// Industry-specific transaction and anomaly generation configuration.
8571///
8572/// This configuration enables generation of industry-authentic:
8573/// - Transaction types with appropriate terminology
8574/// - Master data (BOM, routings, clinical codes, etc.)
8575/// - Industry-specific anomaly patterns
8576/// - Regulatory framework compliance
8577#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8578pub struct IndustrySpecificConfig {
8579    /// Enable industry-specific generation.
8580    #[serde(default)]
8581    pub enabled: bool,
8582
8583    /// Manufacturing industry settings.
8584    #[serde(default)]
8585    pub manufacturing: ManufacturingConfig,
8586
8587    /// Retail industry settings.
8588    #[serde(default)]
8589    pub retail: RetailConfig,
8590
8591    /// Healthcare industry settings.
8592    #[serde(default)]
8593    pub healthcare: HealthcareConfig,
8594
8595    /// Technology industry settings.
8596    #[serde(default)]
8597    pub technology: TechnologyConfig,
8598
8599    /// Financial services industry settings.
8600    #[serde(default)]
8601    pub financial_services: FinancialServicesConfig,
8602
8603    /// Professional services industry settings.
8604    #[serde(default)]
8605    pub professional_services: ProfessionalServicesConfig,
8606}
8607
8608/// Manufacturing industry configuration.
8609#[derive(Debug, Clone, Serialize, Deserialize)]
8610pub struct ManufacturingConfig {
8611    /// Enable manufacturing-specific generation.
8612    #[serde(default)]
8613    pub enabled: bool,
8614
8615    /// Bill of Materials depth (typical: 3-7).
8616    #[serde(default = "default_bom_depth")]
8617    pub bom_depth: u32,
8618
8619    /// Whether to use just-in-time inventory.
8620    #[serde(default)]
8621    pub just_in_time: bool,
8622
8623    /// Production order types to generate.
8624    #[serde(default = "default_production_order_types")]
8625    pub production_order_types: Vec<String>,
8626
8627    /// Quality framework (ISO_9001, Six_Sigma, etc.).
8628    #[serde(default)]
8629    pub quality_framework: Option<String>,
8630
8631    /// Number of supplier tiers to model (1-3).
8632    #[serde(default = "default_supplier_tiers")]
8633    pub supplier_tiers: u32,
8634
8635    /// Standard cost update frequency.
8636    #[serde(default = "default_cost_frequency")]
8637    pub standard_cost_frequency: String,
8638
8639    /// Target yield rate (0.95-0.99 typical).
8640    #[serde(default = "default_yield_rate")]
8641    pub target_yield_rate: f64,
8642
8643    /// Scrap percentage threshold for alerts.
8644    #[serde(default = "default_scrap_threshold")]
8645    pub scrap_alert_threshold: f64,
8646
8647    /// Manufacturing anomaly injection rates.
8648    #[serde(default)]
8649    pub anomaly_rates: ManufacturingAnomalyRates,
8650}
8651
8652fn default_bom_depth() -> u32 {
8653    4
8654}
8655
8656fn default_production_order_types() -> Vec<String> {
8657    vec![
8658        "standard".to_string(),
8659        "rework".to_string(),
8660        "prototype".to_string(),
8661    ]
8662}
8663
8664fn default_supplier_tiers() -> u32 {
8665    2
8666}
8667
8668fn default_cost_frequency() -> String {
8669    "quarterly".to_string()
8670}
8671
8672fn default_yield_rate() -> f64 {
8673    0.97
8674}
8675
8676fn default_scrap_threshold() -> f64 {
8677    0.03
8678}
8679
8680impl Default for ManufacturingConfig {
8681    fn default() -> Self {
8682        Self {
8683            enabled: false,
8684            bom_depth: default_bom_depth(),
8685            just_in_time: false,
8686            production_order_types: default_production_order_types(),
8687            quality_framework: Some("ISO_9001".to_string()),
8688            supplier_tiers: default_supplier_tiers(),
8689            standard_cost_frequency: default_cost_frequency(),
8690            target_yield_rate: default_yield_rate(),
8691            scrap_alert_threshold: default_scrap_threshold(),
8692            anomaly_rates: ManufacturingAnomalyRates::default(),
8693        }
8694    }
8695}
8696
8697/// Manufacturing anomaly injection rates.
8698#[derive(Debug, Clone, Serialize, Deserialize)]
8699pub struct ManufacturingAnomalyRates {
8700    /// Yield manipulation rate.
8701    #[serde(default = "default_mfg_yield_rate")]
8702    pub yield_manipulation: f64,
8703
8704    /// Labor misallocation rate.
8705    #[serde(default = "default_mfg_labor_rate")]
8706    pub labor_misallocation: f64,
8707
8708    /// Phantom production rate.
8709    #[serde(default = "default_mfg_phantom_rate")]
8710    pub phantom_production: f64,
8711
8712    /// Standard cost manipulation rate.
8713    #[serde(default = "default_mfg_cost_rate")]
8714    pub standard_cost_manipulation: f64,
8715
8716    /// Inventory fraud rate.
8717    #[serde(default = "default_mfg_inventory_rate")]
8718    pub inventory_fraud: f64,
8719}
8720
8721fn default_mfg_yield_rate() -> f64 {
8722    0.015
8723}
8724
8725fn default_mfg_labor_rate() -> f64 {
8726    0.02
8727}
8728
8729fn default_mfg_phantom_rate() -> f64 {
8730    0.005
8731}
8732
8733fn default_mfg_cost_rate() -> f64 {
8734    0.01
8735}
8736
8737fn default_mfg_inventory_rate() -> f64 {
8738    0.008
8739}
8740
8741impl Default for ManufacturingAnomalyRates {
8742    fn default() -> Self {
8743        Self {
8744            yield_manipulation: default_mfg_yield_rate(),
8745            labor_misallocation: default_mfg_labor_rate(),
8746            phantom_production: default_mfg_phantom_rate(),
8747            standard_cost_manipulation: default_mfg_cost_rate(),
8748            inventory_fraud: default_mfg_inventory_rate(),
8749        }
8750    }
8751}
8752
8753/// Retail industry configuration.
8754#[derive(Debug, Clone, Serialize, Deserialize)]
8755pub struct RetailConfig {
8756    /// Enable retail-specific generation.
8757    #[serde(default)]
8758    pub enabled: bool,
8759
8760    /// Store type distribution.
8761    #[serde(default)]
8762    pub store_types: RetailStoreTypeConfig,
8763
8764    /// Average daily transactions per store.
8765    #[serde(default = "default_retail_daily_txns")]
8766    pub avg_daily_transactions: u32,
8767
8768    /// Enable loss prevention tracking.
8769    #[serde(default = "default_true")]
8770    pub loss_prevention: bool,
8771
8772    /// Shrinkage rate (0.01-0.03 typical).
8773    #[serde(default = "default_shrinkage_rate")]
8774    pub shrinkage_rate: f64,
8775
8776    /// Retail anomaly injection rates.
8777    #[serde(default)]
8778    pub anomaly_rates: RetailAnomalyRates,
8779}
8780
8781fn default_retail_daily_txns() -> u32 {
8782    500
8783}
8784
8785fn default_shrinkage_rate() -> f64 {
8786    0.015
8787}
8788
8789impl Default for RetailConfig {
8790    fn default() -> Self {
8791        Self {
8792            enabled: false,
8793            store_types: RetailStoreTypeConfig::default(),
8794            avg_daily_transactions: default_retail_daily_txns(),
8795            loss_prevention: true,
8796            shrinkage_rate: default_shrinkage_rate(),
8797            anomaly_rates: RetailAnomalyRates::default(),
8798        }
8799    }
8800}
8801
8802/// Retail store type distribution.
8803#[derive(Debug, Clone, Serialize, Deserialize)]
8804pub struct RetailStoreTypeConfig {
8805    /// Percentage of flagship stores.
8806    #[serde(default = "default_flagship_pct")]
8807    pub flagship: f64,
8808
8809    /// Percentage of regional stores.
8810    #[serde(default = "default_regional_pct")]
8811    pub regional: f64,
8812
8813    /// Percentage of outlet stores.
8814    #[serde(default = "default_outlet_pct")]
8815    pub outlet: f64,
8816
8817    /// Percentage of e-commerce.
8818    #[serde(default = "default_ecommerce_pct")]
8819    pub ecommerce: f64,
8820}
8821
8822fn default_flagship_pct() -> f64 {
8823    0.10
8824}
8825
8826fn default_regional_pct() -> f64 {
8827    0.50
8828}
8829
8830fn default_outlet_pct() -> f64 {
8831    0.25
8832}
8833
8834fn default_ecommerce_pct() -> f64 {
8835    0.15
8836}
8837
8838impl Default for RetailStoreTypeConfig {
8839    fn default() -> Self {
8840        Self {
8841            flagship: default_flagship_pct(),
8842            regional: default_regional_pct(),
8843            outlet: default_outlet_pct(),
8844            ecommerce: default_ecommerce_pct(),
8845        }
8846    }
8847}
8848
8849/// Retail anomaly injection rates.
8850#[derive(Debug, Clone, Serialize, Deserialize)]
8851pub struct RetailAnomalyRates {
8852    /// Sweethearting rate.
8853    #[serde(default = "default_sweethearting_rate")]
8854    pub sweethearting: f64,
8855
8856    /// Skimming rate.
8857    #[serde(default = "default_skimming_rate")]
8858    pub skimming: f64,
8859
8860    /// Refund fraud rate.
8861    #[serde(default = "default_refund_fraud_rate")]
8862    pub refund_fraud: f64,
8863
8864    /// Void abuse rate.
8865    #[serde(default = "default_void_abuse_rate")]
8866    pub void_abuse: f64,
8867
8868    /// Gift card fraud rate.
8869    #[serde(default = "default_gift_card_rate")]
8870    pub gift_card_fraud: f64,
8871
8872    /// Vendor kickback rate.
8873    #[serde(default = "default_retail_kickback_rate")]
8874    pub vendor_kickback: f64,
8875}
8876
8877fn default_sweethearting_rate() -> f64 {
8878    0.02
8879}
8880
8881fn default_skimming_rate() -> f64 {
8882    0.005
8883}
8884
8885fn default_refund_fraud_rate() -> f64 {
8886    0.015
8887}
8888
8889fn default_void_abuse_rate() -> f64 {
8890    0.01
8891}
8892
8893fn default_gift_card_rate() -> f64 {
8894    0.008
8895}
8896
8897fn default_retail_kickback_rate() -> f64 {
8898    0.003
8899}
8900
8901impl Default for RetailAnomalyRates {
8902    fn default() -> Self {
8903        Self {
8904            sweethearting: default_sweethearting_rate(),
8905            skimming: default_skimming_rate(),
8906            refund_fraud: default_refund_fraud_rate(),
8907            void_abuse: default_void_abuse_rate(),
8908            gift_card_fraud: default_gift_card_rate(),
8909            vendor_kickback: default_retail_kickback_rate(),
8910        }
8911    }
8912}
8913
8914/// Healthcare industry configuration.
8915#[derive(Debug, Clone, Serialize, Deserialize)]
8916pub struct HealthcareConfig {
8917    /// Enable healthcare-specific generation.
8918    #[serde(default)]
8919    pub enabled: bool,
8920
8921    /// Healthcare facility type.
8922    #[serde(default = "default_facility_type")]
8923    pub facility_type: String,
8924
8925    /// Payer mix distribution.
8926    #[serde(default)]
8927    pub payer_mix: HealthcarePayerMix,
8928
8929    /// Coding systems enabled.
8930    #[serde(default)]
8931    pub coding_systems: HealthcareCodingSystems,
8932
8933    /// Healthcare compliance settings.
8934    #[serde(default)]
8935    pub compliance: HealthcareComplianceConfig,
8936
8937    /// Average daily encounters.
8938    #[serde(default = "default_daily_encounters")]
8939    pub avg_daily_encounters: u32,
8940
8941    /// Average charges per encounter.
8942    #[serde(default = "default_charges_per_encounter")]
8943    pub avg_charges_per_encounter: u32,
8944
8945    /// Denial rate (0.0-1.0).
8946    #[serde(default = "default_hc_denial_rate")]
8947    pub denial_rate: f64,
8948
8949    /// Bad debt rate (0.0-1.0).
8950    #[serde(default = "default_hc_bad_debt_rate")]
8951    pub bad_debt_rate: f64,
8952
8953    /// Charity care rate (0.0-1.0).
8954    #[serde(default = "default_hc_charity_care_rate")]
8955    pub charity_care_rate: f64,
8956
8957    /// Healthcare anomaly injection rates.
8958    #[serde(default)]
8959    pub anomaly_rates: HealthcareAnomalyRates,
8960}
8961
8962fn default_facility_type() -> String {
8963    "hospital".to_string()
8964}
8965
8966fn default_daily_encounters() -> u32 {
8967    150
8968}
8969
8970fn default_charges_per_encounter() -> u32 {
8971    8
8972}
8973
8974fn default_hc_denial_rate() -> f64 {
8975    0.05
8976}
8977
8978fn default_hc_bad_debt_rate() -> f64 {
8979    0.03
8980}
8981
8982fn default_hc_charity_care_rate() -> f64 {
8983    0.02
8984}
8985
8986impl Default for HealthcareConfig {
8987    fn default() -> Self {
8988        Self {
8989            enabled: false,
8990            facility_type: default_facility_type(),
8991            payer_mix: HealthcarePayerMix::default(),
8992            coding_systems: HealthcareCodingSystems::default(),
8993            compliance: HealthcareComplianceConfig::default(),
8994            avg_daily_encounters: default_daily_encounters(),
8995            avg_charges_per_encounter: default_charges_per_encounter(),
8996            denial_rate: default_hc_denial_rate(),
8997            bad_debt_rate: default_hc_bad_debt_rate(),
8998            charity_care_rate: default_hc_charity_care_rate(),
8999            anomaly_rates: HealthcareAnomalyRates::default(),
9000        }
9001    }
9002}
9003
9004/// Healthcare payer mix distribution.
9005#[derive(Debug, Clone, Serialize, Deserialize)]
9006pub struct HealthcarePayerMix {
9007    /// Medicare percentage.
9008    #[serde(default = "default_medicare_pct")]
9009    pub medicare: f64,
9010
9011    /// Medicaid percentage.
9012    #[serde(default = "default_medicaid_pct")]
9013    pub medicaid: f64,
9014
9015    /// Commercial insurance percentage.
9016    #[serde(default = "default_commercial_pct")]
9017    pub commercial: f64,
9018
9019    /// Self-pay percentage.
9020    #[serde(default = "default_self_pay_pct")]
9021    pub self_pay: f64,
9022}
9023
9024fn default_medicare_pct() -> f64 {
9025    0.40
9026}
9027
9028fn default_medicaid_pct() -> f64 {
9029    0.20
9030}
9031
9032fn default_commercial_pct() -> f64 {
9033    0.30
9034}
9035
9036fn default_self_pay_pct() -> f64 {
9037    0.10
9038}
9039
9040impl Default for HealthcarePayerMix {
9041    fn default() -> Self {
9042        Self {
9043            medicare: default_medicare_pct(),
9044            medicaid: default_medicaid_pct(),
9045            commercial: default_commercial_pct(),
9046            self_pay: default_self_pay_pct(),
9047        }
9048    }
9049}
9050
9051/// Healthcare coding systems configuration.
9052#[derive(Debug, Clone, Serialize, Deserialize)]
9053pub struct HealthcareCodingSystems {
9054    /// Enable ICD-10 diagnosis coding.
9055    #[serde(default = "default_true")]
9056    pub icd10: bool,
9057
9058    /// Enable CPT procedure coding.
9059    #[serde(default = "default_true")]
9060    pub cpt: bool,
9061
9062    /// Enable DRG grouping.
9063    #[serde(default = "default_true")]
9064    pub drg: bool,
9065
9066    /// Enable HCPCS Level II coding.
9067    #[serde(default = "default_true")]
9068    pub hcpcs: bool,
9069
9070    /// Enable revenue codes.
9071    #[serde(default = "default_true")]
9072    pub revenue_codes: bool,
9073}
9074
9075impl Default for HealthcareCodingSystems {
9076    fn default() -> Self {
9077        Self {
9078            icd10: true,
9079            cpt: true,
9080            drg: true,
9081            hcpcs: true,
9082            revenue_codes: true,
9083        }
9084    }
9085}
9086
9087/// Healthcare compliance configuration.
9088#[derive(Debug, Clone, Serialize, Deserialize)]
9089pub struct HealthcareComplianceConfig {
9090    /// Enable HIPAA compliance.
9091    #[serde(default = "default_true")]
9092    pub hipaa: bool,
9093
9094    /// Enable Stark Law compliance.
9095    #[serde(default = "default_true")]
9096    pub stark_law: bool,
9097
9098    /// Enable Anti-Kickback Statute compliance.
9099    #[serde(default = "default_true")]
9100    pub anti_kickback: bool,
9101
9102    /// Enable False Claims Act compliance.
9103    #[serde(default = "default_true")]
9104    pub false_claims_act: bool,
9105
9106    /// Enable EMTALA compliance (for hospitals).
9107    #[serde(default = "default_true")]
9108    pub emtala: bool,
9109}
9110
9111impl Default for HealthcareComplianceConfig {
9112    fn default() -> Self {
9113        Self {
9114            hipaa: true,
9115            stark_law: true,
9116            anti_kickback: true,
9117            false_claims_act: true,
9118            emtala: true,
9119        }
9120    }
9121}
9122
9123/// Healthcare anomaly injection rates.
9124#[derive(Debug, Clone, Serialize, Deserialize)]
9125pub struct HealthcareAnomalyRates {
9126    /// Upcoding rate.
9127    #[serde(default = "default_upcoding_rate")]
9128    pub upcoding: f64,
9129
9130    /// Unbundling rate.
9131    #[serde(default = "default_unbundling_rate")]
9132    pub unbundling: f64,
9133
9134    /// Phantom billing rate.
9135    #[serde(default = "default_phantom_billing_rate")]
9136    pub phantom_billing: f64,
9137
9138    /// Kickback rate.
9139    #[serde(default = "default_healthcare_kickback_rate")]
9140    pub kickbacks: f64,
9141
9142    /// Duplicate billing rate.
9143    #[serde(default = "default_duplicate_billing_rate")]
9144    pub duplicate_billing: f64,
9145
9146    /// Medical necessity abuse rate.
9147    #[serde(default = "default_med_necessity_rate")]
9148    pub medical_necessity_abuse: f64,
9149}
9150
9151fn default_upcoding_rate() -> f64 {
9152    0.02
9153}
9154
9155fn default_unbundling_rate() -> f64 {
9156    0.015
9157}
9158
9159fn default_phantom_billing_rate() -> f64 {
9160    0.005
9161}
9162
9163fn default_healthcare_kickback_rate() -> f64 {
9164    0.003
9165}
9166
9167fn default_duplicate_billing_rate() -> f64 {
9168    0.008
9169}
9170
9171fn default_med_necessity_rate() -> f64 {
9172    0.01
9173}
9174
9175impl Default for HealthcareAnomalyRates {
9176    fn default() -> Self {
9177        Self {
9178            upcoding: default_upcoding_rate(),
9179            unbundling: default_unbundling_rate(),
9180            phantom_billing: default_phantom_billing_rate(),
9181            kickbacks: default_healthcare_kickback_rate(),
9182            duplicate_billing: default_duplicate_billing_rate(),
9183            medical_necessity_abuse: default_med_necessity_rate(),
9184        }
9185    }
9186}
9187
9188/// Technology industry configuration.
9189#[derive(Debug, Clone, Serialize, Deserialize)]
9190pub struct TechnologyConfig {
9191    /// Enable technology-specific generation.
9192    #[serde(default)]
9193    pub enabled: bool,
9194
9195    /// Revenue model type.
9196    #[serde(default = "default_revenue_model")]
9197    pub revenue_model: String,
9198
9199    /// Subscription revenue percentage (for SaaS).
9200    #[serde(default = "default_subscription_pct")]
9201    pub subscription_revenue_pct: f64,
9202
9203    /// License revenue percentage.
9204    #[serde(default = "default_license_pct")]
9205    pub license_revenue_pct: f64,
9206
9207    /// Services revenue percentage.
9208    #[serde(default = "default_services_pct")]
9209    pub services_revenue_pct: f64,
9210
9211    /// R&D capitalization settings.
9212    #[serde(default)]
9213    pub rd_capitalization: RdCapitalizationConfig,
9214
9215    /// Technology anomaly injection rates.
9216    #[serde(default)]
9217    pub anomaly_rates: TechnologyAnomalyRates,
9218}
9219
9220fn default_revenue_model() -> String {
9221    "saas".to_string()
9222}
9223
9224fn default_subscription_pct() -> f64 {
9225    0.60
9226}
9227
9228fn default_license_pct() -> f64 {
9229    0.25
9230}
9231
9232fn default_services_pct() -> f64 {
9233    0.15
9234}
9235
9236impl Default for TechnologyConfig {
9237    fn default() -> Self {
9238        Self {
9239            enabled: false,
9240            revenue_model: default_revenue_model(),
9241            subscription_revenue_pct: default_subscription_pct(),
9242            license_revenue_pct: default_license_pct(),
9243            services_revenue_pct: default_services_pct(),
9244            rd_capitalization: RdCapitalizationConfig::default(),
9245            anomaly_rates: TechnologyAnomalyRates::default(),
9246        }
9247    }
9248}
9249
9250/// R&D capitalization configuration.
9251#[derive(Debug, Clone, Serialize, Deserialize)]
9252pub struct RdCapitalizationConfig {
9253    /// Enable R&D capitalization.
9254    #[serde(default = "default_true")]
9255    pub enabled: bool,
9256
9257    /// Capitalization rate (0.0-1.0).
9258    #[serde(default = "default_cap_rate")]
9259    pub capitalization_rate: f64,
9260
9261    /// Useful life in years.
9262    #[serde(default = "default_useful_life")]
9263    pub useful_life_years: u32,
9264}
9265
9266fn default_cap_rate() -> f64 {
9267    0.30
9268}
9269
9270fn default_useful_life() -> u32 {
9271    3
9272}
9273
9274impl Default for RdCapitalizationConfig {
9275    fn default() -> Self {
9276        Self {
9277            enabled: true,
9278            capitalization_rate: default_cap_rate(),
9279            useful_life_years: default_useful_life(),
9280        }
9281    }
9282}
9283
9284/// Technology anomaly injection rates.
9285#[derive(Debug, Clone, Serialize, Deserialize)]
9286pub struct TechnologyAnomalyRates {
9287    /// Premature revenue recognition rate.
9288    #[serde(default = "default_premature_rev_rate")]
9289    pub premature_revenue: f64,
9290
9291    /// Side letter abuse rate.
9292    #[serde(default = "default_side_letter_rate")]
9293    pub side_letter_abuse: f64,
9294
9295    /// Channel stuffing rate.
9296    #[serde(default = "default_channel_stuffing_rate")]
9297    pub channel_stuffing: f64,
9298
9299    /// Improper capitalization rate.
9300    #[serde(default = "default_improper_cap_rate")]
9301    pub improper_capitalization: f64,
9302}
9303
9304fn default_premature_rev_rate() -> f64 {
9305    0.015
9306}
9307
9308fn default_side_letter_rate() -> f64 {
9309    0.008
9310}
9311
9312fn default_channel_stuffing_rate() -> f64 {
9313    0.01
9314}
9315
9316fn default_improper_cap_rate() -> f64 {
9317    0.012
9318}
9319
9320impl Default for TechnologyAnomalyRates {
9321    fn default() -> Self {
9322        Self {
9323            premature_revenue: default_premature_rev_rate(),
9324            side_letter_abuse: default_side_letter_rate(),
9325            channel_stuffing: default_channel_stuffing_rate(),
9326            improper_capitalization: default_improper_cap_rate(),
9327        }
9328    }
9329}
9330
9331/// Financial services industry configuration.
9332#[derive(Debug, Clone, Serialize, Deserialize)]
9333pub struct FinancialServicesConfig {
9334    /// Enable financial services-specific generation.
9335    #[serde(default)]
9336    pub enabled: bool,
9337
9338    /// Financial institution type.
9339    #[serde(default = "default_fi_type")]
9340    pub institution_type: String,
9341
9342    /// Regulatory framework.
9343    #[serde(default = "default_fi_regulatory")]
9344    pub regulatory_framework: String,
9345
9346    /// Financial services anomaly injection rates.
9347    #[serde(default)]
9348    pub anomaly_rates: FinancialServicesAnomalyRates,
9349}
9350
9351fn default_fi_type() -> String {
9352    "commercial_bank".to_string()
9353}
9354
9355fn default_fi_regulatory() -> String {
9356    "us_banking".to_string()
9357}
9358
9359impl Default for FinancialServicesConfig {
9360    fn default() -> Self {
9361        Self {
9362            enabled: false,
9363            institution_type: default_fi_type(),
9364            regulatory_framework: default_fi_regulatory(),
9365            anomaly_rates: FinancialServicesAnomalyRates::default(),
9366        }
9367    }
9368}
9369
9370/// Financial services anomaly injection rates.
9371#[derive(Debug, Clone, Serialize, Deserialize)]
9372pub struct FinancialServicesAnomalyRates {
9373    /// Loan fraud rate.
9374    #[serde(default = "default_loan_fraud_rate")]
9375    pub loan_fraud: f64,
9376
9377    /// Trading fraud rate.
9378    #[serde(default = "default_trading_fraud_rate")]
9379    pub trading_fraud: f64,
9380
9381    /// Insurance fraud rate.
9382    #[serde(default = "default_insurance_fraud_rate")]
9383    pub insurance_fraud: f64,
9384
9385    /// Account manipulation rate.
9386    #[serde(default = "default_account_manip_rate")]
9387    pub account_manipulation: f64,
9388}
9389
9390fn default_loan_fraud_rate() -> f64 {
9391    0.01
9392}
9393
9394fn default_trading_fraud_rate() -> f64 {
9395    0.008
9396}
9397
9398fn default_insurance_fraud_rate() -> f64 {
9399    0.012
9400}
9401
9402fn default_account_manip_rate() -> f64 {
9403    0.005
9404}
9405
9406impl Default for FinancialServicesAnomalyRates {
9407    fn default() -> Self {
9408        Self {
9409            loan_fraud: default_loan_fraud_rate(),
9410            trading_fraud: default_trading_fraud_rate(),
9411            insurance_fraud: default_insurance_fraud_rate(),
9412            account_manipulation: default_account_manip_rate(),
9413        }
9414    }
9415}
9416
9417/// Professional services industry configuration.
9418#[derive(Debug, Clone, Serialize, Deserialize)]
9419pub struct ProfessionalServicesConfig {
9420    /// Enable professional services-specific generation.
9421    #[serde(default)]
9422    pub enabled: bool,
9423
9424    /// Firm type.
9425    #[serde(default = "default_firm_type")]
9426    pub firm_type: String,
9427
9428    /// Billing model.
9429    #[serde(default = "default_billing_model")]
9430    pub billing_model: String,
9431
9432    /// Average hourly rate.
9433    #[serde(default = "default_hourly_rate")]
9434    pub avg_hourly_rate: f64,
9435
9436    /// Trust account settings (for law firms).
9437    #[serde(default)]
9438    pub trust_accounting: TrustAccountingConfig,
9439
9440    /// Professional services anomaly injection rates.
9441    #[serde(default)]
9442    pub anomaly_rates: ProfessionalServicesAnomalyRates,
9443}
9444
9445fn default_firm_type() -> String {
9446    "consulting".to_string()
9447}
9448
9449fn default_billing_model() -> String {
9450    "time_and_materials".to_string()
9451}
9452
9453fn default_hourly_rate() -> f64 {
9454    250.0
9455}
9456
9457impl Default for ProfessionalServicesConfig {
9458    fn default() -> Self {
9459        Self {
9460            enabled: false,
9461            firm_type: default_firm_type(),
9462            billing_model: default_billing_model(),
9463            avg_hourly_rate: default_hourly_rate(),
9464            trust_accounting: TrustAccountingConfig::default(),
9465            anomaly_rates: ProfessionalServicesAnomalyRates::default(),
9466        }
9467    }
9468}
9469
9470/// Trust accounting configuration for law firms.
9471#[derive(Debug, Clone, Serialize, Deserialize)]
9472pub struct TrustAccountingConfig {
9473    /// Enable trust accounting.
9474    #[serde(default)]
9475    pub enabled: bool,
9476
9477    /// Require three-way reconciliation.
9478    #[serde(default = "default_true")]
9479    pub require_three_way_reconciliation: bool,
9480}
9481
9482impl Default for TrustAccountingConfig {
9483    fn default() -> Self {
9484        Self {
9485            enabled: false,
9486            require_three_way_reconciliation: true,
9487        }
9488    }
9489}
9490
9491/// Professional services anomaly injection rates.
9492#[derive(Debug, Clone, Serialize, Deserialize)]
9493pub struct ProfessionalServicesAnomalyRates {
9494    /// Time billing fraud rate.
9495    #[serde(default = "default_time_fraud_rate")]
9496    pub time_billing_fraud: f64,
9497
9498    /// Expense report fraud rate.
9499    #[serde(default = "default_expense_fraud_rate")]
9500    pub expense_fraud: f64,
9501
9502    /// Trust misappropriation rate.
9503    #[serde(default = "default_trust_misappropriation_rate")]
9504    pub trust_misappropriation: f64,
9505}
9506
9507fn default_time_fraud_rate() -> f64 {
9508    0.02
9509}
9510
9511fn default_expense_fraud_rate() -> f64 {
9512    0.015
9513}
9514
9515fn default_trust_misappropriation_rate() -> f64 {
9516    0.003
9517}
9518
9519impl Default for ProfessionalServicesAnomalyRates {
9520    fn default() -> Self {
9521        Self {
9522            time_billing_fraud: default_time_fraud_rate(),
9523            expense_fraud: default_expense_fraud_rate(),
9524            trust_misappropriation: default_trust_misappropriation_rate(),
9525        }
9526    }
9527}
9528
9529#[cfg(test)]
9530mod tests {
9531    use super::*;
9532    use crate::presets::demo_preset;
9533
9534    // ==========================================================================
9535    // Serialization/Deserialization Tests
9536    // ==========================================================================
9537
9538    #[test]
9539    fn test_config_yaml_roundtrip() {
9540        let config = demo_preset();
9541        let yaml = serde_yaml::to_string(&config).expect("Failed to serialize to YAML");
9542        let deserialized: GeneratorConfig =
9543            serde_yaml::from_str(&yaml).expect("Failed to deserialize from YAML");
9544
9545        assert_eq!(
9546            config.global.period_months,
9547            deserialized.global.period_months
9548        );
9549        assert_eq!(config.global.industry, deserialized.global.industry);
9550        assert_eq!(config.companies.len(), deserialized.companies.len());
9551        assert_eq!(config.companies[0].code, deserialized.companies[0].code);
9552    }
9553
9554    #[test]
9555    fn test_config_json_roundtrip() {
9556        // Create a config without infinity values (JSON can't serialize f64::INFINITY)
9557        let mut config = demo_preset();
9558        // Replace infinity with a large but finite value for JSON compatibility
9559        config.master_data.employees.approval_limits.executive = 1e12;
9560
9561        let json = serde_json::to_string(&config).expect("Failed to serialize to JSON");
9562        let deserialized: GeneratorConfig =
9563            serde_json::from_str(&json).expect("Failed to deserialize from JSON");
9564
9565        assert_eq!(
9566            config.global.period_months,
9567            deserialized.global.period_months
9568        );
9569        assert_eq!(config.global.industry, deserialized.global.industry);
9570        assert_eq!(config.companies.len(), deserialized.companies.len());
9571    }
9572
9573    #[test]
9574    fn test_transaction_volume_serialization() {
9575        // Test various transaction volumes serialize correctly
9576        let volumes = vec![
9577            (TransactionVolume::TenK, "ten_k"),
9578            (TransactionVolume::HundredK, "hundred_k"),
9579            (TransactionVolume::OneM, "one_m"),
9580            (TransactionVolume::TenM, "ten_m"),
9581            (TransactionVolume::HundredM, "hundred_m"),
9582        ];
9583
9584        for (volume, expected_key) in volumes {
9585            let json = serde_json::to_string(&volume).expect("Failed to serialize");
9586            assert!(
9587                json.contains(expected_key),
9588                "Expected {} in JSON: {}",
9589                expected_key,
9590                json
9591            );
9592        }
9593    }
9594
9595    #[test]
9596    fn test_transaction_volume_custom_serialization() {
9597        let volume = TransactionVolume::Custom(12345);
9598        let json = serde_json::to_string(&volume).expect("Failed to serialize");
9599        let deserialized: TransactionVolume =
9600            serde_json::from_str(&json).expect("Failed to deserialize");
9601        assert_eq!(deserialized.count(), 12345);
9602    }
9603
9604    #[test]
9605    fn test_output_mode_serialization() {
9606        let modes = vec![
9607            OutputMode::Streaming,
9608            OutputMode::FlatFile,
9609            OutputMode::Both,
9610        ];
9611
9612        for mode in modes {
9613            let json = serde_json::to_string(&mode).expect("Failed to serialize");
9614            let deserialized: OutputMode =
9615                serde_json::from_str(&json).expect("Failed to deserialize");
9616            assert!(format!("{:?}", mode) == format!("{:?}", deserialized));
9617        }
9618    }
9619
9620    #[test]
9621    fn test_file_format_serialization() {
9622        let formats = vec![
9623            FileFormat::Csv,
9624            FileFormat::Parquet,
9625            FileFormat::Json,
9626            FileFormat::JsonLines,
9627        ];
9628
9629        for format in formats {
9630            let json = serde_json::to_string(&format).expect("Failed to serialize");
9631            let deserialized: FileFormat =
9632                serde_json::from_str(&json).expect("Failed to deserialize");
9633            assert!(format!("{:?}", format) == format!("{:?}", deserialized));
9634        }
9635    }
9636
9637    #[test]
9638    fn test_compression_algorithm_serialization() {
9639        let algos = vec![
9640            CompressionAlgorithm::Gzip,
9641            CompressionAlgorithm::Zstd,
9642            CompressionAlgorithm::Lz4,
9643            CompressionAlgorithm::Snappy,
9644        ];
9645
9646        for algo in algos {
9647            let json = serde_json::to_string(&algo).expect("Failed to serialize");
9648            let deserialized: CompressionAlgorithm =
9649                serde_json::from_str(&json).expect("Failed to deserialize");
9650            assert!(format!("{:?}", algo) == format!("{:?}", deserialized));
9651        }
9652    }
9653
9654    #[test]
9655    fn test_transfer_pricing_method_serialization() {
9656        let methods = vec![
9657            TransferPricingMethod::CostPlus,
9658            TransferPricingMethod::ComparableUncontrolled,
9659            TransferPricingMethod::ResalePrice,
9660            TransferPricingMethod::TransactionalNetMargin,
9661            TransferPricingMethod::ProfitSplit,
9662        ];
9663
9664        for method in methods {
9665            let json = serde_json::to_string(&method).expect("Failed to serialize");
9666            let deserialized: TransferPricingMethod =
9667                serde_json::from_str(&json).expect("Failed to deserialize");
9668            assert!(format!("{:?}", method) == format!("{:?}", deserialized));
9669        }
9670    }
9671
9672    #[test]
9673    fn test_benford_exemption_serialization() {
9674        let exemptions = vec![
9675            BenfordExemption::Recurring,
9676            BenfordExemption::Payroll,
9677            BenfordExemption::FixedFees,
9678            BenfordExemption::RoundAmounts,
9679        ];
9680
9681        for exemption in exemptions {
9682            let json = serde_json::to_string(&exemption).expect("Failed to serialize");
9683            let deserialized: BenfordExemption =
9684                serde_json::from_str(&json).expect("Failed to deserialize");
9685            assert!(format!("{:?}", exemption) == format!("{:?}", deserialized));
9686        }
9687    }
9688
9689    // ==========================================================================
9690    // Default Value Tests
9691    // ==========================================================================
9692
9693    #[test]
9694    fn test_global_config_defaults() {
9695        let yaml = r#"
9696            industry: manufacturing
9697            start_date: "2024-01-01"
9698            period_months: 6
9699        "#;
9700        let config: GlobalConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
9701        assert_eq!(config.group_currency, "USD");
9702        assert!(config.parallel);
9703        assert_eq!(config.worker_threads, 0);
9704        assert_eq!(config.memory_limit_mb, 0);
9705    }
9706
9707    #[test]
9708    fn test_fraud_config_defaults() {
9709        let config = FraudConfig::default();
9710        assert!(!config.enabled);
9711        assert_eq!(config.fraud_rate, 0.005);
9712        assert!(!config.clustering_enabled);
9713    }
9714
9715    #[test]
9716    fn test_internal_controls_config_defaults() {
9717        let config = InternalControlsConfig::default();
9718        assert!(!config.enabled);
9719        assert_eq!(config.exception_rate, 0.02);
9720        assert_eq!(config.sod_violation_rate, 0.01);
9721        assert!(config.export_control_master_data);
9722        assert_eq!(config.sox_materiality_threshold, 10000.0);
9723        // COSO fields
9724        assert!(config.coso_enabled);
9725        assert!(!config.include_entity_level_controls);
9726        assert_eq!(config.target_maturity_level, "mixed");
9727    }
9728
9729    #[test]
9730    fn test_output_config_defaults() {
9731        let config = OutputConfig::default();
9732        assert!(matches!(config.mode, OutputMode::FlatFile));
9733        assert_eq!(config.formats, vec![FileFormat::Parquet]);
9734        assert!(config.compression.enabled);
9735        assert!(matches!(
9736            config.compression.algorithm,
9737            CompressionAlgorithm::Zstd
9738        ));
9739        assert!(config.include_acdoca);
9740        assert!(!config.include_bseg);
9741        assert!(config.partition_by_period);
9742        assert!(!config.partition_by_company);
9743    }
9744
9745    #[test]
9746    fn test_approval_config_defaults() {
9747        let config = ApprovalConfig::default();
9748        assert!(!config.enabled);
9749        assert_eq!(config.auto_approve_threshold, 1000.0);
9750        assert_eq!(config.rejection_rate, 0.02);
9751        assert_eq!(config.revision_rate, 0.05);
9752        assert_eq!(config.average_approval_delay_hours, 4.0);
9753        assert_eq!(config.thresholds.len(), 4);
9754    }
9755
9756    #[test]
9757    fn test_p2p_flow_config_defaults() {
9758        let config = P2PFlowConfig::default();
9759        assert!(config.enabled);
9760        assert_eq!(config.three_way_match_rate, 0.95);
9761        assert_eq!(config.partial_delivery_rate, 0.15);
9762        assert_eq!(config.average_po_to_gr_days, 14);
9763    }
9764
9765    #[test]
9766    fn test_o2c_flow_config_defaults() {
9767        let config = O2CFlowConfig::default();
9768        assert!(config.enabled);
9769        assert_eq!(config.credit_check_failure_rate, 0.02);
9770        assert_eq!(config.return_rate, 0.03);
9771        assert_eq!(config.bad_debt_rate, 0.01);
9772    }
9773
9774    #[test]
9775    fn test_balance_config_defaults() {
9776        let config = BalanceConfig::default();
9777        assert!(!config.generate_opening_balances);
9778        assert!(config.generate_trial_balances);
9779        assert_eq!(config.target_gross_margin, 0.35);
9780        assert!(config.validate_balance_equation);
9781        assert!(config.reconcile_subledgers);
9782    }
9783
9784    // ==========================================================================
9785    // Partial Config Deserialization Tests
9786    // ==========================================================================
9787
9788    #[test]
9789    fn test_partial_config_with_defaults() {
9790        // Minimal config that should use all defaults
9791        let yaml = r#"
9792            global:
9793              industry: manufacturing
9794              start_date: "2024-01-01"
9795              period_months: 3
9796            companies:
9797              - code: "TEST"
9798                name: "Test Company"
9799                currency: "USD"
9800                country: "US"
9801                annual_transaction_volume: ten_k
9802            chart_of_accounts:
9803              complexity: small
9804            output:
9805              output_directory: "./output"
9806        "#;
9807
9808        let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
9809        assert_eq!(config.global.period_months, 3);
9810        assert_eq!(config.companies.len(), 1);
9811        assert!(!config.fraud.enabled); // Default
9812        assert!(!config.internal_controls.enabled); // Default
9813    }
9814
9815    #[test]
9816    fn test_config_with_fraud_enabled() {
9817        let yaml = r#"
9818            global:
9819              industry: retail
9820              start_date: "2024-01-01"
9821              period_months: 12
9822            companies:
9823              - code: "RETAIL"
9824                name: "Retail Co"
9825                currency: "USD"
9826                country: "US"
9827                annual_transaction_volume: hundred_k
9828            chart_of_accounts:
9829              complexity: medium
9830            output:
9831              output_directory: "./output"
9832            fraud:
9833              enabled: true
9834              fraud_rate: 0.05
9835              clustering_enabled: true
9836        "#;
9837
9838        let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
9839        assert!(config.fraud.enabled);
9840        assert_eq!(config.fraud.fraud_rate, 0.05);
9841        assert!(config.fraud.clustering_enabled);
9842    }
9843
9844    #[test]
9845    fn test_config_with_multiple_companies() {
9846        let yaml = r#"
9847            global:
9848              industry: manufacturing
9849              start_date: "2024-01-01"
9850              period_months: 6
9851            companies:
9852              - code: "HQ"
9853                name: "Headquarters"
9854                currency: "USD"
9855                country: "US"
9856                annual_transaction_volume: hundred_k
9857                volume_weight: 1.0
9858              - code: "EU"
9859                name: "European Subsidiary"
9860                currency: "EUR"
9861                country: "DE"
9862                annual_transaction_volume: hundred_k
9863                volume_weight: 0.5
9864              - code: "APAC"
9865                name: "Asia Pacific"
9866                currency: "JPY"
9867                country: "JP"
9868                annual_transaction_volume: ten_k
9869                volume_weight: 0.3
9870            chart_of_accounts:
9871              complexity: large
9872            output:
9873              output_directory: "./output"
9874        "#;
9875
9876        let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
9877        assert_eq!(config.companies.len(), 3);
9878        assert_eq!(config.companies[0].code, "HQ");
9879        assert_eq!(config.companies[1].currency, "EUR");
9880        assert_eq!(config.companies[2].volume_weight, 0.3);
9881    }
9882
9883    #[test]
9884    fn test_intercompany_config() {
9885        let yaml = r#"
9886            enabled: true
9887            ic_transaction_rate: 0.20
9888            transfer_pricing_method: cost_plus
9889            markup_percent: 0.08
9890            generate_matched_pairs: true
9891            generate_eliminations: true
9892        "#;
9893
9894        let config: IntercompanyConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
9895        assert!(config.enabled);
9896        assert_eq!(config.ic_transaction_rate, 0.20);
9897        assert!(matches!(
9898            config.transfer_pricing_method,
9899            TransferPricingMethod::CostPlus
9900        ));
9901        assert_eq!(config.markup_percent, 0.08);
9902        assert!(config.generate_eliminations);
9903    }
9904
9905    // ==========================================================================
9906    // Company Config Tests
9907    // ==========================================================================
9908
9909    #[test]
9910    fn test_company_config_defaults() {
9911        let yaml = r#"
9912            code: "TEST"
9913            name: "Test Company"
9914            currency: "USD"
9915            country: "US"
9916            annual_transaction_volume: ten_k
9917        "#;
9918
9919        let config: CompanyConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
9920        assert_eq!(config.fiscal_year_variant, "K4"); // Default
9921        assert_eq!(config.volume_weight, 1.0); // Default
9922    }
9923
9924    // ==========================================================================
9925    // Chart of Accounts Config Tests
9926    // ==========================================================================
9927
9928    #[test]
9929    fn test_coa_config_defaults() {
9930        let yaml = r#"
9931            complexity: medium
9932        "#;
9933
9934        let config: ChartOfAccountsConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
9935        assert!(config.industry_specific); // Default true
9936        assert!(config.custom_accounts.is_none());
9937        assert_eq!(config.min_hierarchy_depth, 2); // Default
9938        assert_eq!(config.max_hierarchy_depth, 5); // Default
9939    }
9940
9941    // ==========================================================================
9942    // Accounting Standards Config Tests
9943    // ==========================================================================
9944
9945    #[test]
9946    fn test_accounting_standards_config_defaults() {
9947        let config = AccountingStandardsConfig::default();
9948        assert!(!config.enabled);
9949        assert!(matches!(
9950            config.framework,
9951            AccountingFrameworkConfig::UsGaap
9952        ));
9953        assert!(!config.revenue_recognition.enabled);
9954        assert!(!config.leases.enabled);
9955        assert!(!config.fair_value.enabled);
9956        assert!(!config.impairment.enabled);
9957        assert!(!config.generate_differences);
9958    }
9959
9960    #[test]
9961    fn test_accounting_standards_config_yaml() {
9962        let yaml = r#"
9963            enabled: true
9964            framework: ifrs
9965            revenue_recognition:
9966              enabled: true
9967              generate_contracts: true
9968              avg_obligations_per_contract: 2.5
9969              variable_consideration_rate: 0.20
9970              over_time_recognition_rate: 0.35
9971              contract_count: 150
9972            leases:
9973              enabled: true
9974              lease_count: 75
9975              finance_lease_percent: 0.25
9976              avg_lease_term_months: 48
9977            generate_differences: true
9978        "#;
9979
9980        let config: AccountingStandardsConfig =
9981            serde_yaml::from_str(yaml).expect("Failed to parse");
9982        assert!(config.enabled);
9983        assert!(matches!(config.framework, AccountingFrameworkConfig::Ifrs));
9984        assert!(config.revenue_recognition.enabled);
9985        assert_eq!(config.revenue_recognition.contract_count, 150);
9986        assert_eq!(config.revenue_recognition.avg_obligations_per_contract, 2.5);
9987        assert!(config.leases.enabled);
9988        assert_eq!(config.leases.lease_count, 75);
9989        assert_eq!(config.leases.finance_lease_percent, 0.25);
9990        assert!(config.generate_differences);
9991    }
9992
9993    #[test]
9994    fn test_accounting_framework_serialization() {
9995        let frameworks = [
9996            AccountingFrameworkConfig::UsGaap,
9997            AccountingFrameworkConfig::Ifrs,
9998            AccountingFrameworkConfig::DualReporting,
9999        ];
10000
10001        for framework in frameworks {
10002            let json = serde_json::to_string(&framework).expect("Failed to serialize");
10003            let deserialized: AccountingFrameworkConfig =
10004                serde_json::from_str(&json).expect("Failed to deserialize");
10005            assert!(format!("{:?}", framework) == format!("{:?}", deserialized));
10006        }
10007    }
10008
10009    #[test]
10010    fn test_revenue_recognition_config_defaults() {
10011        let config = RevenueRecognitionConfig::default();
10012        assert!(!config.enabled);
10013        assert!(config.generate_contracts);
10014        assert_eq!(config.avg_obligations_per_contract, 2.0);
10015        assert_eq!(config.variable_consideration_rate, 0.15);
10016        assert_eq!(config.over_time_recognition_rate, 0.30);
10017        assert_eq!(config.contract_count, 100);
10018    }
10019
10020    #[test]
10021    fn test_lease_accounting_config_defaults() {
10022        let config = LeaseAccountingConfig::default();
10023        assert!(!config.enabled);
10024        assert_eq!(config.lease_count, 50);
10025        assert_eq!(config.finance_lease_percent, 0.30);
10026        assert_eq!(config.avg_lease_term_months, 60);
10027        assert!(config.generate_amortization);
10028        assert_eq!(config.real_estate_percent, 0.40);
10029    }
10030
10031    #[test]
10032    fn test_fair_value_config_defaults() {
10033        let config = FairValueConfig::default();
10034        assert!(!config.enabled);
10035        assert_eq!(config.measurement_count, 25);
10036        assert_eq!(config.level1_percent, 0.40);
10037        assert_eq!(config.level2_percent, 0.35);
10038        assert_eq!(config.level3_percent, 0.25);
10039        assert!(!config.include_sensitivity_analysis);
10040    }
10041
10042    #[test]
10043    fn test_impairment_config_defaults() {
10044        let config = ImpairmentConfig::default();
10045        assert!(!config.enabled);
10046        assert_eq!(config.test_count, 15);
10047        assert_eq!(config.impairment_rate, 0.10);
10048        assert!(config.generate_projections);
10049        assert!(!config.include_goodwill);
10050    }
10051
10052    // ==========================================================================
10053    // Audit Standards Config Tests
10054    // ==========================================================================
10055
10056    #[test]
10057    fn test_audit_standards_config_defaults() {
10058        let config = AuditStandardsConfig::default();
10059        assert!(!config.enabled);
10060        assert!(!config.isa_compliance.enabled);
10061        assert!(!config.analytical_procedures.enabled);
10062        assert!(!config.confirmations.enabled);
10063        assert!(!config.opinion.enabled);
10064        assert!(!config.generate_audit_trail);
10065        assert!(!config.sox.enabled);
10066        assert!(!config.pcaob.enabled);
10067    }
10068
10069    #[test]
10070    fn test_audit_standards_config_yaml() {
10071        let yaml = r#"
10072            enabled: true
10073            isa_compliance:
10074              enabled: true
10075              compliance_level: comprehensive
10076              generate_isa_mappings: true
10077              include_pcaob: true
10078              framework: dual
10079            analytical_procedures:
10080              enabled: true
10081              procedures_per_account: 5
10082              variance_probability: 0.25
10083            confirmations:
10084              enabled: true
10085              confirmation_count: 75
10086              positive_response_rate: 0.90
10087              exception_rate: 0.08
10088            opinion:
10089              enabled: true
10090              generate_kam: true
10091              average_kam_count: 4
10092            sox:
10093              enabled: true
10094              generate_302_certifications: true
10095              generate_404_assessments: true
10096              material_weakness_rate: 0.03
10097            pcaob:
10098              enabled: true
10099              is_pcaob_audit: true
10100              include_icfr_opinion: true
10101            generate_audit_trail: true
10102        "#;
10103
10104        let config: AuditStandardsConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
10105        assert!(config.enabled);
10106        assert!(config.isa_compliance.enabled);
10107        assert_eq!(config.isa_compliance.compliance_level, "comprehensive");
10108        assert!(config.isa_compliance.include_pcaob);
10109        assert_eq!(config.isa_compliance.framework, "dual");
10110        assert!(config.analytical_procedures.enabled);
10111        assert_eq!(config.analytical_procedures.procedures_per_account, 5);
10112        assert!(config.confirmations.enabled);
10113        assert_eq!(config.confirmations.confirmation_count, 75);
10114        assert!(config.opinion.enabled);
10115        assert_eq!(config.opinion.average_kam_count, 4);
10116        assert!(config.sox.enabled);
10117        assert!(config.sox.generate_302_certifications);
10118        assert_eq!(config.sox.material_weakness_rate, 0.03);
10119        assert!(config.pcaob.enabled);
10120        assert!(config.pcaob.is_pcaob_audit);
10121        assert!(config.pcaob.include_icfr_opinion);
10122        assert!(config.generate_audit_trail);
10123    }
10124
10125    #[test]
10126    fn test_isa_compliance_config_defaults() {
10127        let config = IsaComplianceConfig::default();
10128        assert!(!config.enabled);
10129        assert_eq!(config.compliance_level, "standard");
10130        assert!(config.generate_isa_mappings);
10131        assert!(config.generate_coverage_summary);
10132        assert!(!config.include_pcaob);
10133        assert_eq!(config.framework, "isa");
10134    }
10135
10136    #[test]
10137    fn test_sox_compliance_config_defaults() {
10138        let config = SoxComplianceConfig::default();
10139        assert!(!config.enabled);
10140        assert!(config.generate_302_certifications);
10141        assert!(config.generate_404_assessments);
10142        assert_eq!(config.materiality_threshold, 10000.0);
10143        assert_eq!(config.material_weakness_rate, 0.02);
10144        assert_eq!(config.significant_deficiency_rate, 0.08);
10145    }
10146
10147    #[test]
10148    fn test_pcaob_config_defaults() {
10149        let config = PcaobConfig::default();
10150        assert!(!config.enabled);
10151        assert!(!config.is_pcaob_audit);
10152        assert!(config.generate_cam);
10153        assert!(!config.include_icfr_opinion);
10154        assert!(!config.generate_standard_mappings);
10155    }
10156
10157    #[test]
10158    fn test_config_with_standards_enabled() {
10159        let yaml = r#"
10160            global:
10161              industry: financial_services
10162              start_date: "2024-01-01"
10163              period_months: 12
10164            companies:
10165              - code: "BANK"
10166                name: "Test Bank"
10167                currency: "USD"
10168                country: "US"
10169                annual_transaction_volume: hundred_k
10170            chart_of_accounts:
10171              complexity: large
10172            output:
10173              output_directory: "./output"
10174            accounting_standards:
10175              enabled: true
10176              framework: us_gaap
10177              revenue_recognition:
10178                enabled: true
10179              leases:
10180                enabled: true
10181            audit_standards:
10182              enabled: true
10183              isa_compliance:
10184                enabled: true
10185              sox:
10186                enabled: true
10187        "#;
10188
10189        let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
10190        assert!(config.accounting_standards.enabled);
10191        assert!(matches!(
10192            config.accounting_standards.framework,
10193            AccountingFrameworkConfig::UsGaap
10194        ));
10195        assert!(config.accounting_standards.revenue_recognition.enabled);
10196        assert!(config.accounting_standards.leases.enabled);
10197        assert!(config.audit_standards.enabled);
10198        assert!(config.audit_standards.isa_compliance.enabled);
10199        assert!(config.audit_standards.sox.enabled);
10200    }
10201
10202    // ==========================================================================
10203    // Industry-Specific Config Tests
10204    // ==========================================================================
10205
10206    #[test]
10207    fn test_industry_specific_config_defaults() {
10208        let config = IndustrySpecificConfig::default();
10209        assert!(!config.enabled);
10210        assert!(!config.manufacturing.enabled);
10211        assert!(!config.retail.enabled);
10212        assert!(!config.healthcare.enabled);
10213        assert!(!config.technology.enabled);
10214        assert!(!config.financial_services.enabled);
10215        assert!(!config.professional_services.enabled);
10216    }
10217
10218    #[test]
10219    fn test_manufacturing_config_defaults() {
10220        let config = ManufacturingConfig::default();
10221        assert!(!config.enabled);
10222        assert_eq!(config.bom_depth, 4);
10223        assert!(!config.just_in_time);
10224        assert_eq!(config.supplier_tiers, 2);
10225        assert_eq!(config.target_yield_rate, 0.97);
10226        assert_eq!(config.scrap_alert_threshold, 0.03);
10227    }
10228
10229    #[test]
10230    fn test_retail_config_defaults() {
10231        let config = RetailConfig::default();
10232        assert!(!config.enabled);
10233        assert_eq!(config.avg_daily_transactions, 500);
10234        assert!(config.loss_prevention);
10235        assert_eq!(config.shrinkage_rate, 0.015);
10236    }
10237
10238    #[test]
10239    fn test_healthcare_config_defaults() {
10240        let config = HealthcareConfig::default();
10241        assert!(!config.enabled);
10242        assert_eq!(config.facility_type, "hospital");
10243        assert_eq!(config.avg_daily_encounters, 150);
10244        assert!(config.compliance.hipaa);
10245        assert!(config.compliance.stark_law);
10246        assert!(config.coding_systems.icd10);
10247        assert!(config.coding_systems.cpt);
10248    }
10249
10250    #[test]
10251    fn test_technology_config_defaults() {
10252        let config = TechnologyConfig::default();
10253        assert!(!config.enabled);
10254        assert_eq!(config.revenue_model, "saas");
10255        assert_eq!(config.subscription_revenue_pct, 0.60);
10256        assert!(config.rd_capitalization.enabled);
10257    }
10258
10259    #[test]
10260    fn test_config_with_industry_specific() {
10261        let yaml = r#"
10262            global:
10263              industry: healthcare
10264              start_date: "2024-01-01"
10265              period_months: 12
10266            companies:
10267              - code: "HOSP"
10268                name: "Test Hospital"
10269                currency: "USD"
10270                country: "US"
10271                annual_transaction_volume: hundred_k
10272            chart_of_accounts:
10273              complexity: medium
10274            output:
10275              output_directory: "./output"
10276            industry_specific:
10277              enabled: true
10278              healthcare:
10279                enabled: true
10280                facility_type: hospital
10281                payer_mix:
10282                  medicare: 0.45
10283                  medicaid: 0.15
10284                  commercial: 0.35
10285                  self_pay: 0.05
10286                coding_systems:
10287                  icd10: true
10288                  cpt: true
10289                  drg: true
10290                compliance:
10291                  hipaa: true
10292                  stark_law: true
10293                anomaly_rates:
10294                  upcoding: 0.03
10295                  unbundling: 0.02
10296        "#;
10297
10298        let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
10299        assert!(config.industry_specific.enabled);
10300        assert!(config.industry_specific.healthcare.enabled);
10301        assert_eq!(
10302            config.industry_specific.healthcare.facility_type,
10303            "hospital"
10304        );
10305        assert_eq!(config.industry_specific.healthcare.payer_mix.medicare, 0.45);
10306        assert_eq!(config.industry_specific.healthcare.payer_mix.self_pay, 0.05);
10307        assert!(config.industry_specific.healthcare.coding_systems.icd10);
10308        assert!(config.industry_specific.healthcare.compliance.hipaa);
10309        assert_eq!(
10310            config.industry_specific.healthcare.anomaly_rates.upcoding,
10311            0.03
10312        );
10313    }
10314
10315    #[test]
10316    fn test_config_with_manufacturing_specific() {
10317        let yaml = r#"
10318            global:
10319              industry: manufacturing
10320              start_date: "2024-01-01"
10321              period_months: 12
10322            companies:
10323              - code: "MFG"
10324                name: "Test Manufacturing"
10325                currency: "USD"
10326                country: "US"
10327                annual_transaction_volume: hundred_k
10328            chart_of_accounts:
10329              complexity: medium
10330            output:
10331              output_directory: "./output"
10332            industry_specific:
10333              enabled: true
10334              manufacturing:
10335                enabled: true
10336                bom_depth: 5
10337                just_in_time: true
10338                supplier_tiers: 3
10339                target_yield_rate: 0.98
10340                anomaly_rates:
10341                  yield_manipulation: 0.02
10342                  phantom_production: 0.01
10343        "#;
10344
10345        let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
10346        assert!(config.industry_specific.enabled);
10347        assert!(config.industry_specific.manufacturing.enabled);
10348        assert_eq!(config.industry_specific.manufacturing.bom_depth, 5);
10349        assert!(config.industry_specific.manufacturing.just_in_time);
10350        assert_eq!(config.industry_specific.manufacturing.supplier_tiers, 3);
10351        assert_eq!(
10352            config.industry_specific.manufacturing.target_yield_rate,
10353            0.98
10354        );
10355        assert_eq!(
10356            config
10357                .industry_specific
10358                .manufacturing
10359                .anomaly_rates
10360                .yield_manipulation,
10361            0.02
10362        );
10363    }
10364}