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    /// Fingerprint privacy configuration for extraction/synthesis
134    #[serde(default)]
135    pub fingerprint_privacy: FingerprintPrivacyConfig,
136    /// Quality gate configuration for pass/fail thresholds
137    #[serde(default)]
138    pub quality_gates: QualityGatesSchemaConfig,
139    /// Compliance configuration (EU AI Act, content marking)
140    #[serde(default)]
141    pub compliance: ComplianceSchemaConfig,
142    /// Webhook notification configuration
143    #[serde(default)]
144    pub webhooks: WebhookSchemaConfig,
145    /// LLM enrichment configuration (AI-augmented vendor names, descriptions, explanations)
146    #[serde(default)]
147    pub llm: LlmSchemaConfig,
148    /// Diffusion model configuration (statistical diffusion-based data enhancement)
149    #[serde(default)]
150    pub diffusion: DiffusionSchemaConfig,
151    /// Causal generation configuration (structural causal models, interventions)
152    #[serde(default)]
153    pub causal: CausalSchemaConfig,
154
155    // ===== Enterprise Process Chain Extensions =====
156    /// Source-to-Pay (S2C/S2P) configuration (sourcing, contracts, catalogs, scorecards)
157    #[serde(default)]
158    pub source_to_pay: SourceToPayConfig,
159    /// Financial reporting configuration (financial statements, KPIs, budgets)
160    #[serde(default)]
161    pub financial_reporting: FinancialReportingConfig,
162    /// HR process configuration (payroll, time & attendance, expenses)
163    #[serde(default)]
164    pub hr: HrConfig,
165    /// Manufacturing configuration (production orders, WIP, routing)
166    #[serde(default)]
167    pub manufacturing: ManufacturingProcessConfig,
168    /// Sales quote configuration (quote-to-order pipeline)
169    #[serde(default)]
170    pub sales_quotes: SalesQuoteConfig,
171    /// Tax accounting configuration (VAT/GST, sales tax, withholding, provisions, payroll tax)
172    #[serde(default)]
173    pub tax: TaxConfig,
174    /// Treasury and cash management configuration
175    #[serde(default)]
176    pub treasury: TreasuryConfig,
177    /// Project accounting configuration
178    #[serde(default)]
179    pub project_accounting: ProjectAccountingConfig,
180    /// ESG / Sustainability reporting configuration
181    #[serde(default)]
182    pub esg: EsgConfig,
183}
184
185/// LLM enrichment configuration.
186///
187/// Controls AI-augmented metadata enrichment using LLM providers.
188/// When enabled, vendor names, transaction descriptions, and anomaly explanations
189/// are enriched using the configured provider (mock by default).
190#[derive(Debug, Clone, Serialize, Deserialize)]
191pub struct LlmSchemaConfig {
192    /// Whether LLM enrichment is enabled.
193    #[serde(default)]
194    pub enabled: bool,
195    /// Provider type: "mock", "openai", "anthropic", "custom".
196    #[serde(default = "default_llm_provider")]
197    pub provider: String,
198    /// Model name/ID for the provider.
199    #[serde(default = "default_llm_model_name")]
200    pub model: String,
201    /// Maximum number of vendor names to enrich per run.
202    #[serde(default = "default_llm_batch_size")]
203    pub max_vendor_enrichments: usize,
204}
205
206fn default_llm_provider() -> String {
207    "mock".to_string()
208}
209
210fn default_llm_model_name() -> String {
211    "gpt-4o-mini".to_string()
212}
213
214fn default_llm_batch_size() -> usize {
215    50
216}
217
218impl Default for LlmSchemaConfig {
219    fn default() -> Self {
220        Self {
221            enabled: false,
222            provider: default_llm_provider(),
223            model: default_llm_model_name(),
224            max_vendor_enrichments: default_llm_batch_size(),
225        }
226    }
227}
228
229/// Diffusion model configuration.
230///
231/// Controls statistical diffusion-based data enhancement that generates samples
232/// matching target distribution properties (means, standard deviations, correlations).
233#[derive(Debug, Clone, Serialize, Deserialize)]
234pub struct DiffusionSchemaConfig {
235    /// Whether diffusion enhancement is enabled.
236    #[serde(default)]
237    pub enabled: bool,
238    /// Number of diffusion steps (higher = better quality, slower).
239    #[serde(default = "default_diffusion_steps")]
240    pub n_steps: usize,
241    /// Noise schedule type: "linear", "cosine", "sigmoid".
242    #[serde(default = "default_diffusion_schedule")]
243    pub schedule: String,
244    /// Number of sample rows to generate for demonstration.
245    #[serde(default = "default_diffusion_sample_size")]
246    pub sample_size: usize,
247}
248
249fn default_diffusion_steps() -> usize {
250    100
251}
252
253fn default_diffusion_schedule() -> String {
254    "linear".to_string()
255}
256
257fn default_diffusion_sample_size() -> usize {
258    100
259}
260
261impl Default for DiffusionSchemaConfig {
262    fn default() -> Self {
263        Self {
264            enabled: false,
265            n_steps: default_diffusion_steps(),
266            schedule: default_diffusion_schedule(),
267            sample_size: default_diffusion_sample_size(),
268        }
269    }
270}
271
272/// Causal generation configuration.
273///
274/// Controls structural causal model (SCM) based data generation that respects
275/// causal relationships between variables, supports do-calculus interventions,
276/// and enables counterfactual scenarios.
277#[derive(Debug, Clone, Serialize, Deserialize)]
278pub struct CausalSchemaConfig {
279    /// Whether causal generation is enabled.
280    #[serde(default)]
281    pub enabled: bool,
282    /// Built-in template to use: "fraud_detection", "revenue_cycle", or "custom".
283    #[serde(default = "default_causal_template")]
284    pub template: String,
285    /// Number of causal samples to generate.
286    #[serde(default = "default_causal_sample_size")]
287    pub sample_size: usize,
288    /// Whether to run causal validation on the output.
289    #[serde(default = "default_true")]
290    pub validate: bool,
291}
292
293fn default_causal_template() -> String {
294    "fraud_detection".to_string()
295}
296
297fn default_causal_sample_size() -> usize {
298    500
299}
300
301impl Default for CausalSchemaConfig {
302    fn default() -> Self {
303        Self {
304            enabled: false,
305            template: default_causal_template(),
306            sample_size: default_causal_sample_size(),
307            validate: true,
308        }
309    }
310}
311
312/// Graph export configuration for accounting network and ML training exports.
313///
314/// This section enables exporting generated data as graphs for:
315/// - Network reconstruction algorithms
316/// - Graph neural network training
317/// - Neo4j graph database import
318#[derive(Debug, Clone, Serialize, Deserialize)]
319pub struct GraphExportConfig {
320    /// Enable graph export.
321    #[serde(default)]
322    pub enabled: bool,
323
324    /// Graph types to generate.
325    #[serde(default = "default_graph_types")]
326    pub graph_types: Vec<GraphTypeConfig>,
327
328    /// Export formats to generate.
329    #[serde(default = "default_graph_formats")]
330    pub formats: Vec<GraphExportFormat>,
331
332    /// Train split ratio for ML datasets.
333    #[serde(default = "default_train_ratio")]
334    pub train_ratio: f64,
335
336    /// Validation split ratio for ML datasets.
337    #[serde(default = "default_val_ratio")]
338    pub validation_ratio: f64,
339
340    /// Random seed for train/val/test splits.
341    #[serde(default)]
342    pub split_seed: Option<u64>,
343
344    /// Output subdirectory for graph exports (relative to output directory).
345    #[serde(default = "default_graph_subdir")]
346    pub output_subdirectory: String,
347
348    /// Multi-layer hypergraph export settings for RustGraph integration.
349    #[serde(default)]
350    pub hypergraph: HypergraphExportSettings,
351}
352
353fn default_graph_types() -> Vec<GraphTypeConfig> {
354    vec![GraphTypeConfig::default()]
355}
356
357fn default_graph_formats() -> Vec<GraphExportFormat> {
358    vec![GraphExportFormat::PytorchGeometric]
359}
360
361fn default_train_ratio() -> f64 {
362    0.7
363}
364
365fn default_val_ratio() -> f64 {
366    0.15
367}
368
369fn default_graph_subdir() -> String {
370    "graphs".to_string()
371}
372
373impl Default for GraphExportConfig {
374    fn default() -> Self {
375        Self {
376            enabled: false,
377            graph_types: default_graph_types(),
378            formats: default_graph_formats(),
379            train_ratio: 0.7,
380            validation_ratio: 0.15,
381            split_seed: None,
382            output_subdirectory: "graphs".to_string(),
383            hypergraph: HypergraphExportSettings::default(),
384        }
385    }
386}
387
388/// Settings for the multi-layer hypergraph export (RustGraph integration).
389///
390/// Produces a 3-layer hypergraph:
391/// - Layer 1: Governance & Controls (COSO, SOX, internal controls, organizational)
392/// - Layer 2: Process Events (P2P/O2C document flows, OCPM events)
393/// - Layer 3: Accounting Network (GL accounts, journal entries as hyperedges)
394#[derive(Debug, Clone, Serialize, Deserialize)]
395pub struct HypergraphExportSettings {
396    /// Enable hypergraph export.
397    #[serde(default)]
398    pub enabled: bool,
399
400    /// Maximum total nodes across all layers (default 50000).
401    #[serde(default = "default_hypergraph_max_nodes")]
402    pub max_nodes: usize,
403
404    /// Aggregation strategy when node budget is exceeded.
405    #[serde(default = "default_aggregation_strategy")]
406    pub aggregation_strategy: String,
407
408    /// Layer 1 (Governance & Controls) settings.
409    #[serde(default)]
410    pub governance_layer: GovernanceLayerSettings,
411
412    /// Layer 2 (Process Events) settings.
413    #[serde(default)]
414    pub process_layer: ProcessLayerSettings,
415
416    /// Layer 3 (Accounting Network) settings.
417    #[serde(default)]
418    pub accounting_layer: AccountingLayerSettings,
419
420    /// Cross-layer edge generation settings.
421    #[serde(default)]
422    pub cross_layer: CrossLayerSettings,
423
424    /// Output subdirectory for hypergraph files (relative to graph output directory).
425    #[serde(default = "default_hypergraph_subdir")]
426    pub output_subdirectory: String,
427
428    /// Output format: "native" (default) for internal field names, "unified" for RustGraph format.
429    #[serde(default = "default_hypergraph_format")]
430    pub output_format: String,
431
432    /// Optional URL for streaming unified JSONL to a RustGraph ingest endpoint.
433    #[serde(default)]
434    pub stream_target: Option<String>,
435
436    /// Batch size for streaming (number of JSONL lines per HTTP POST). Default: 1000.
437    #[serde(default = "default_stream_batch_size")]
438    pub stream_batch_size: usize,
439}
440
441fn default_hypergraph_max_nodes() -> usize {
442    50_000
443}
444
445fn default_aggregation_strategy() -> String {
446    "pool_by_counterparty".to_string()
447}
448
449fn default_hypergraph_subdir() -> String {
450    "hypergraph".to_string()
451}
452
453fn default_hypergraph_format() -> String {
454    "native".to_string()
455}
456
457fn default_stream_batch_size() -> usize {
458    1000
459}
460
461impl Default for HypergraphExportSettings {
462    fn default() -> Self {
463        Self {
464            enabled: false,
465            max_nodes: 50_000,
466            aggregation_strategy: "pool_by_counterparty".to_string(),
467            governance_layer: GovernanceLayerSettings::default(),
468            process_layer: ProcessLayerSettings::default(),
469            accounting_layer: AccountingLayerSettings::default(),
470            cross_layer: CrossLayerSettings::default(),
471            output_subdirectory: "hypergraph".to_string(),
472            output_format: "native".to_string(),
473            stream_target: None,
474            stream_batch_size: 1000,
475        }
476    }
477}
478
479/// Layer 1: Governance & Controls layer settings.
480#[derive(Debug, Clone, Serialize, Deserialize)]
481pub struct GovernanceLayerSettings {
482    /// Include COSO framework nodes (5 components + 17 principles).
483    #[serde(default = "default_true")]
484    pub include_coso: bool,
485    /// Include internal control nodes.
486    #[serde(default = "default_true")]
487    pub include_controls: bool,
488    /// Include SOX assertion nodes.
489    #[serde(default = "default_true")]
490    pub include_sox: bool,
491    /// Include vendor master data nodes.
492    #[serde(default = "default_true")]
493    pub include_vendors: bool,
494    /// Include customer master data nodes.
495    #[serde(default = "default_true")]
496    pub include_customers: bool,
497    /// Include employee/organizational nodes.
498    #[serde(default = "default_true")]
499    pub include_employees: bool,
500}
501
502impl Default for GovernanceLayerSettings {
503    fn default() -> Self {
504        Self {
505            include_coso: true,
506            include_controls: true,
507            include_sox: true,
508            include_vendors: true,
509            include_customers: true,
510            include_employees: true,
511        }
512    }
513}
514
515/// Layer 2: Process Events layer settings.
516#[derive(Debug, Clone, Serialize, Deserialize)]
517pub struct ProcessLayerSettings {
518    /// Include P2P (Procure-to-Pay) document flow nodes.
519    #[serde(default = "default_true")]
520    pub include_p2p: bool,
521    /// Include O2C (Order-to-Cash) document flow nodes.
522    #[serde(default = "default_true")]
523    pub include_o2c: bool,
524    /// Include S2C (Source-to-Contract) document flow nodes.
525    #[serde(default = "default_true")]
526    pub include_s2c: bool,
527    /// Include H2R (Hire-to-Retire) document flow nodes.
528    #[serde(default = "default_true")]
529    pub include_h2r: bool,
530    /// Include MFG (Manufacturing) document flow nodes.
531    #[serde(default = "default_true")]
532    pub include_mfg: bool,
533    /// Include BANK (Banking) document flow nodes.
534    #[serde(default = "default_true")]
535    pub include_bank: bool,
536    /// Include AUDIT document flow nodes.
537    #[serde(default = "default_true")]
538    pub include_audit: bool,
539    /// Include R2R (Record-to-Report) document flow nodes (bank recon + period close).
540    #[serde(default = "default_true")]
541    pub include_r2r: bool,
542    /// Export OCPM events as hyperedges.
543    #[serde(default = "default_true")]
544    pub events_as_hyperedges: bool,
545    /// Threshold: if a counterparty has more documents than this, aggregate into pool nodes.
546    #[serde(default = "default_docs_per_counterparty_threshold")]
547    pub docs_per_counterparty_threshold: usize,
548}
549
550fn default_docs_per_counterparty_threshold() -> usize {
551    20
552}
553
554impl Default for ProcessLayerSettings {
555    fn default() -> Self {
556        Self {
557            include_p2p: true,
558            include_o2c: true,
559            include_s2c: true,
560            include_h2r: true,
561            include_mfg: true,
562            include_bank: true,
563            include_audit: true,
564            include_r2r: true,
565            events_as_hyperedges: true,
566            docs_per_counterparty_threshold: 20,
567        }
568    }
569}
570
571/// Layer 3: Accounting Network layer settings.
572#[derive(Debug, Clone, Serialize, Deserialize)]
573pub struct AccountingLayerSettings {
574    /// Include GL account nodes.
575    #[serde(default = "default_true")]
576    pub include_accounts: bool,
577    /// Export journal entries as hyperedges (debit+credit accounts as participants).
578    #[serde(default = "default_true")]
579    pub je_as_hyperedges: bool,
580}
581
582impl Default for AccountingLayerSettings {
583    fn default() -> Self {
584        Self {
585            include_accounts: true,
586            je_as_hyperedges: true,
587        }
588    }
589}
590
591/// Cross-layer edge generation settings.
592#[derive(Debug, Clone, Serialize, Deserialize)]
593pub struct CrossLayerSettings {
594    /// Generate cross-layer edges (Control→Account, Vendor→PO, etc.).
595    #[serde(default = "default_true")]
596    pub enabled: bool,
597}
598
599impl Default for CrossLayerSettings {
600    fn default() -> Self {
601        Self { enabled: true }
602    }
603}
604
605/// Configuration for a specific graph type to export.
606#[derive(Debug, Clone, Serialize, Deserialize)]
607pub struct GraphTypeConfig {
608    /// Name identifier for this graph configuration.
609    #[serde(default = "default_graph_name")]
610    pub name: String,
611
612    /// Whether to aggregate parallel edges between the same nodes.
613    #[serde(default)]
614    pub aggregate_edges: bool,
615
616    /// Minimum edge weight to include (filters out small transactions).
617    #[serde(default)]
618    pub min_edge_weight: f64,
619
620    /// Whether to include document nodes (creates hub-and-spoke structure).
621    #[serde(default)]
622    pub include_document_nodes: bool,
623}
624
625fn default_graph_name() -> String {
626    "accounting_network".to_string()
627}
628
629impl Default for GraphTypeConfig {
630    fn default() -> Self {
631        Self {
632            name: "accounting_network".to_string(),
633            aggregate_edges: false,
634            min_edge_weight: 0.0,
635            include_document_nodes: false,
636        }
637    }
638}
639
640/// Export format for graph data.
641#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
642#[serde(rename_all = "snake_case")]
643pub enum GraphExportFormat {
644    /// PyTorch Geometric format (.npy files + metadata.json).
645    PytorchGeometric,
646    /// Neo4j format (CSV files + Cypher import scripts).
647    Neo4j,
648    /// Deep Graph Library format.
649    Dgl,
650    /// RustGraph/RustAssureTwin JSON format.
651    RustGraph,
652    /// RustGraph multi-layer hypergraph format (nodes.jsonl + edges.jsonl + hyperedges.jsonl).
653    RustGraphHypergraph,
654}
655
656/// Scenario configuration for metadata, tagging, and ML training setup.
657///
658/// This section enables tracking the purpose and characteristics of a generation run.
659#[derive(Debug, Clone, Default, Serialize, Deserialize)]
660pub struct ScenarioConfig {
661    /// Tags for categorizing and filtering datasets.
662    /// Examples: "fraud_detection", "retail", "month_end_stress", "ml_training"
663    #[serde(default)]
664    pub tags: Vec<String>,
665
666    /// Data quality profile preset.
667    /// - "clean": Minimal data quality issues (0.1% missing, 0.05% typos)
668    /// - "noisy": Moderate issues (5% missing, 2% typos, 1% duplicates)
669    /// - "legacy": Heavy issues simulating legacy system data (10% missing, 5% typos)
670    #[serde(default)]
671    pub profile: Option<String>,
672
673    /// Human-readable description of the scenario purpose.
674    #[serde(default)]
675    pub description: Option<String>,
676
677    /// Whether this run is for ML training (enables balanced labeling).
678    #[serde(default)]
679    pub ml_training: bool,
680
681    /// Target anomaly class balance for ML training.
682    /// If set, anomalies will be injected to achieve this ratio.
683    #[serde(default)]
684    pub target_anomaly_ratio: Option<f64>,
685
686    /// Custom metadata key-value pairs.
687    #[serde(default)]
688    pub metadata: std::collections::HashMap<String, String>,
689}
690
691/// Temporal drift configuration for simulating distribution changes over time.
692///
693/// This enables generation of data that shows realistic temporal evolution,
694/// useful for training drift detection models and testing temporal robustness.
695#[derive(Debug, Clone, Serialize, Deserialize)]
696pub struct TemporalDriftConfig {
697    /// Enable temporal drift simulation.
698    #[serde(default)]
699    pub enabled: bool,
700
701    /// Amount mean drift per period (e.g., 0.02 = 2% mean shift per month).
702    /// Simulates gradual inflation or business growth.
703    #[serde(default = "default_amount_drift")]
704    pub amount_mean_drift: f64,
705
706    /// Amount variance drift per period (e.g., 0.01 = 1% variance increase per month).
707    /// Simulates increasing volatility over time.
708    #[serde(default)]
709    pub amount_variance_drift: f64,
710
711    /// Anomaly rate drift per period (e.g., 0.001 = 0.1% increase per month).
712    /// Simulates increasing fraud attempts or degrading controls.
713    #[serde(default)]
714    pub anomaly_rate_drift: f64,
715
716    /// Concept drift rate - how quickly feature distributions change (0.0-1.0).
717    /// Higher values cause more rapid distribution shifts.
718    #[serde(default = "default_concept_drift")]
719    pub concept_drift_rate: f64,
720
721    /// Sudden drift events - probability of a sudden distribution shift in any period.
722    #[serde(default)]
723    pub sudden_drift_probability: f64,
724
725    /// Magnitude of sudden drift events when they occur (multiplier).
726    #[serde(default = "default_sudden_drift_magnitude")]
727    pub sudden_drift_magnitude: f64,
728
729    /// Seasonal drift - enable cyclic patterns that repeat annually.
730    #[serde(default)]
731    pub seasonal_drift: bool,
732
733    /// Drift start period (0 = from beginning). Use to simulate stable baseline before drift.
734    #[serde(default)]
735    pub drift_start_period: u32,
736
737    /// Drift type: "gradual", "sudden", "recurring", "mixed"
738    #[serde(default = "default_drift_type")]
739    pub drift_type: DriftType,
740}
741
742fn default_amount_drift() -> f64 {
743    0.02
744}
745
746fn default_concept_drift() -> f64 {
747    0.01
748}
749
750fn default_sudden_drift_magnitude() -> f64 {
751    2.0
752}
753
754fn default_drift_type() -> DriftType {
755    DriftType::Gradual
756}
757
758impl Default for TemporalDriftConfig {
759    fn default() -> Self {
760        Self {
761            enabled: false,
762            amount_mean_drift: 0.02,
763            amount_variance_drift: 0.0,
764            anomaly_rate_drift: 0.0,
765            concept_drift_rate: 0.01,
766            sudden_drift_probability: 0.0,
767            sudden_drift_magnitude: 2.0,
768            seasonal_drift: false,
769            drift_start_period: 0,
770            drift_type: DriftType::Gradual,
771        }
772    }
773}
774
775impl TemporalDriftConfig {
776    /// Convert to core DriftConfig for use in generators.
777    pub fn to_core_config(&self) -> datasynth_core::distributions::DriftConfig {
778        datasynth_core::distributions::DriftConfig {
779            enabled: self.enabled,
780            amount_mean_drift: self.amount_mean_drift,
781            amount_variance_drift: self.amount_variance_drift,
782            anomaly_rate_drift: self.anomaly_rate_drift,
783            concept_drift_rate: self.concept_drift_rate,
784            sudden_drift_probability: self.sudden_drift_probability,
785            sudden_drift_magnitude: self.sudden_drift_magnitude,
786            seasonal_drift: self.seasonal_drift,
787            drift_start_period: self.drift_start_period,
788            drift_type: match self.drift_type {
789                DriftType::Gradual => datasynth_core::distributions::DriftType::Gradual,
790                DriftType::Sudden => datasynth_core::distributions::DriftType::Sudden,
791                DriftType::Recurring => datasynth_core::distributions::DriftType::Recurring,
792                DriftType::Mixed => datasynth_core::distributions::DriftType::Mixed,
793            },
794            regime_changes: Vec::new(),
795            economic_cycle: Default::default(),
796            parameter_drifts: Vec::new(),
797        }
798    }
799}
800
801/// Types of temporal drift patterns.
802#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
803#[serde(rename_all = "snake_case")]
804pub enum DriftType {
805    /// Gradual, continuous drift over time (like inflation).
806    #[default]
807    Gradual,
808    /// Sudden, point-in-time shifts (like policy changes).
809    Sudden,
810    /// Recurring patterns that cycle (like seasonal variations).
811    Recurring,
812    /// Combination of gradual background drift with occasional sudden shifts.
813    Mixed,
814}
815
816// ============================================================================
817// Streaming Output API Configuration (Phase 2)
818// ============================================================================
819
820/// Configuration for streaming output API.
821#[derive(Debug, Clone, Serialize, Deserialize)]
822pub struct StreamingSchemaConfig {
823    /// Enable streaming output.
824    #[serde(default)]
825    pub enabled: bool,
826    /// Buffer size for streaming (number of items).
827    #[serde(default = "default_buffer_size")]
828    pub buffer_size: usize,
829    /// Enable progress reporting.
830    #[serde(default = "default_true")]
831    pub enable_progress: bool,
832    /// Progress reporting interval (number of items).
833    #[serde(default = "default_progress_interval")]
834    pub progress_interval: u64,
835    /// Backpressure strategy.
836    #[serde(default)]
837    pub backpressure: BackpressureSchemaStrategy,
838}
839
840fn default_buffer_size() -> usize {
841    1000
842}
843
844fn default_progress_interval() -> u64 {
845    100
846}
847
848impl Default for StreamingSchemaConfig {
849    fn default() -> Self {
850        Self {
851            enabled: false,
852            buffer_size: 1000,
853            enable_progress: true,
854            progress_interval: 100,
855            backpressure: BackpressureSchemaStrategy::Block,
856        }
857    }
858}
859
860/// Backpressure strategy for streaming output.
861#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
862#[serde(rename_all = "snake_case")]
863pub enum BackpressureSchemaStrategy {
864    /// Block until space is available in the buffer.
865    #[default]
866    Block,
867    /// Drop oldest items when buffer is full.
868    DropOldest,
869    /// Drop newest items when buffer is full.
870    DropNewest,
871    /// Buffer overflow items up to a limit, then block.
872    Buffer,
873}
874
875// ============================================================================
876// Rate Limiting Configuration (Phase 5)
877// ============================================================================
878
879/// Configuration for rate limiting.
880#[derive(Debug, Clone, Serialize, Deserialize)]
881pub struct RateLimitSchemaConfig {
882    /// Enable rate limiting.
883    #[serde(default)]
884    pub enabled: bool,
885    /// Entities per second limit.
886    #[serde(default = "default_entities_per_second")]
887    pub entities_per_second: f64,
888    /// Burst size (number of tokens in bucket).
889    #[serde(default = "default_burst_size")]
890    pub burst_size: u32,
891    /// Backpressure strategy for rate limiting.
892    #[serde(default)]
893    pub backpressure: RateLimitBackpressureSchema,
894}
895
896fn default_entities_per_second() -> f64 {
897    1000.0
898}
899
900fn default_burst_size() -> u32 {
901    100
902}
903
904impl Default for RateLimitSchemaConfig {
905    fn default() -> Self {
906        Self {
907            enabled: false,
908            entities_per_second: 1000.0,
909            burst_size: 100,
910            backpressure: RateLimitBackpressureSchema::Block,
911        }
912    }
913}
914
915/// Backpressure strategy for rate limiting.
916#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
917#[serde(rename_all = "snake_case")]
918pub enum RateLimitBackpressureSchema {
919    /// Block until rate allows.
920    #[default]
921    Block,
922    /// Drop items that exceed rate.
923    Drop,
924    /// Buffer items and process when rate allows.
925    Buffer,
926}
927
928// ============================================================================
929// Temporal Attribute Generation Configuration (Phase 3)
930// ============================================================================
931
932/// Configuration for temporal attribute generation.
933#[derive(Debug, Clone, Serialize, Deserialize)]
934pub struct TemporalAttributeSchemaConfig {
935    /// Enable temporal attribute generation.
936    #[serde(default)]
937    pub enabled: bool,
938    /// Valid time configuration.
939    #[serde(default)]
940    pub valid_time: ValidTimeSchemaConfig,
941    /// Transaction time configuration.
942    #[serde(default)]
943    pub transaction_time: TransactionTimeSchemaConfig,
944    /// Generate version chains for entities.
945    #[serde(default)]
946    pub generate_version_chains: bool,
947    /// Average number of versions per entity.
948    #[serde(default = "default_avg_versions")]
949    pub avg_versions_per_entity: f64,
950}
951
952fn default_avg_versions() -> f64 {
953    1.5
954}
955
956impl Default for TemporalAttributeSchemaConfig {
957    fn default() -> Self {
958        Self {
959            enabled: false,
960            valid_time: ValidTimeSchemaConfig::default(),
961            transaction_time: TransactionTimeSchemaConfig::default(),
962            generate_version_chains: false,
963            avg_versions_per_entity: 1.5,
964        }
965    }
966}
967
968/// Configuration for valid time (business time) generation.
969#[derive(Debug, Clone, Serialize, Deserialize)]
970pub struct ValidTimeSchemaConfig {
971    /// Probability that valid_to is set (entity has ended validity).
972    #[serde(default = "default_closed_probability")]
973    pub closed_probability: f64,
974    /// Average validity duration in days.
975    #[serde(default = "default_avg_validity_days")]
976    pub avg_validity_days: u32,
977    /// Standard deviation of validity duration in days.
978    #[serde(default = "default_validity_stddev")]
979    pub validity_stddev_days: u32,
980}
981
982fn default_closed_probability() -> f64 {
983    0.1
984}
985
986fn default_avg_validity_days() -> u32 {
987    365
988}
989
990fn default_validity_stddev() -> u32 {
991    90
992}
993
994impl Default for ValidTimeSchemaConfig {
995    fn default() -> Self {
996        Self {
997            closed_probability: 0.1,
998            avg_validity_days: 365,
999            validity_stddev_days: 90,
1000        }
1001    }
1002}
1003
1004/// Configuration for transaction time (system time) generation.
1005#[derive(Debug, Clone, Serialize, Deserialize)]
1006pub struct TransactionTimeSchemaConfig {
1007    /// Average recording delay in seconds (0 = immediate).
1008    #[serde(default)]
1009    pub avg_recording_delay_seconds: u32,
1010    /// Allow backdating (recording time before valid time).
1011    #[serde(default)]
1012    pub allow_backdating: bool,
1013    /// Probability of backdating if allowed.
1014    #[serde(default = "default_backdating_probability")]
1015    pub backdating_probability: f64,
1016    /// Maximum backdate days.
1017    #[serde(default = "default_max_backdate_days")]
1018    pub max_backdate_days: u32,
1019}
1020
1021fn default_backdating_probability() -> f64 {
1022    0.01
1023}
1024
1025fn default_max_backdate_days() -> u32 {
1026    30
1027}
1028
1029impl Default for TransactionTimeSchemaConfig {
1030    fn default() -> Self {
1031        Self {
1032            avg_recording_delay_seconds: 0,
1033            allow_backdating: false,
1034            backdating_probability: 0.01,
1035            max_backdate_days: 30,
1036        }
1037    }
1038}
1039
1040// ============================================================================
1041// Relationship Generation Configuration (Phase 4)
1042// ============================================================================
1043
1044/// Configuration for relationship generation.
1045#[derive(Debug, Clone, Serialize, Deserialize)]
1046pub struct RelationshipSchemaConfig {
1047    /// Relationship type definitions.
1048    #[serde(default)]
1049    pub relationship_types: Vec<RelationshipTypeSchemaConfig>,
1050    /// Allow orphan entities (entities with no relationships).
1051    #[serde(default = "default_true")]
1052    pub allow_orphans: bool,
1053    /// Probability of creating an orphan entity.
1054    #[serde(default = "default_orphan_probability")]
1055    pub orphan_probability: f64,
1056    /// Allow circular relationships.
1057    #[serde(default)]
1058    pub allow_circular: bool,
1059    /// Maximum depth for circular relationship detection.
1060    #[serde(default = "default_max_circular_depth")]
1061    pub max_circular_depth: u32,
1062}
1063
1064fn default_orphan_probability() -> f64 {
1065    0.01
1066}
1067
1068fn default_max_circular_depth() -> u32 {
1069    3
1070}
1071
1072impl Default for RelationshipSchemaConfig {
1073    fn default() -> Self {
1074        Self {
1075            relationship_types: Vec::new(),
1076            allow_orphans: true,
1077            orphan_probability: 0.01,
1078            allow_circular: false,
1079            max_circular_depth: 3,
1080        }
1081    }
1082}
1083
1084/// Configuration for a specific relationship type.
1085#[derive(Debug, Clone, Serialize, Deserialize)]
1086pub struct RelationshipTypeSchemaConfig {
1087    /// Name of the relationship type (e.g., "debits", "credits", "created").
1088    pub name: String,
1089    /// Source entity type (e.g., "journal_entry").
1090    pub source_type: String,
1091    /// Target entity type (e.g., "account").
1092    pub target_type: String,
1093    /// Cardinality rule for this relationship.
1094    #[serde(default)]
1095    pub cardinality: CardinalitySchemaRule,
1096    /// Weight for this relationship in random selection.
1097    #[serde(default = "default_relationship_weight")]
1098    pub weight: f64,
1099    /// Whether this relationship is required.
1100    #[serde(default)]
1101    pub required: bool,
1102    /// Whether this relationship is directed.
1103    #[serde(default = "default_true")]
1104    pub directed: bool,
1105}
1106
1107fn default_relationship_weight() -> f64 {
1108    1.0
1109}
1110
1111impl Default for RelationshipTypeSchemaConfig {
1112    fn default() -> Self {
1113        Self {
1114            name: String::new(),
1115            source_type: String::new(),
1116            target_type: String::new(),
1117            cardinality: CardinalitySchemaRule::default(),
1118            weight: 1.0,
1119            required: false,
1120            directed: true,
1121        }
1122    }
1123}
1124
1125/// Cardinality rule for relationships in schema config.
1126#[derive(Debug, Clone, Serialize, Deserialize)]
1127#[serde(rename_all = "snake_case")]
1128pub enum CardinalitySchemaRule {
1129    /// One source to one target.
1130    OneToOne,
1131    /// One source to many targets.
1132    OneToMany {
1133        /// Minimum number of targets.
1134        min: u32,
1135        /// Maximum number of targets.
1136        max: u32,
1137    },
1138    /// Many sources to one target.
1139    ManyToOne {
1140        /// Minimum number of sources.
1141        min: u32,
1142        /// Maximum number of sources.
1143        max: u32,
1144    },
1145    /// Many sources to many targets.
1146    ManyToMany {
1147        /// Minimum targets per source.
1148        min_per_source: u32,
1149        /// Maximum targets per source.
1150        max_per_source: u32,
1151    },
1152}
1153
1154impl Default for CardinalitySchemaRule {
1155    fn default() -> Self {
1156        Self::OneToMany { min: 1, max: 5 }
1157    }
1158}
1159
1160/// Global configuration settings.
1161#[derive(Debug, Clone, Serialize, Deserialize)]
1162pub struct GlobalConfig {
1163    /// Random seed for reproducibility
1164    pub seed: Option<u64>,
1165    /// Industry sector
1166    pub industry: IndustrySector,
1167    /// Simulation start date (YYYY-MM-DD)
1168    pub start_date: String,
1169    /// Simulation period in months
1170    pub period_months: u32,
1171    /// Base currency for group reporting
1172    #[serde(default = "default_currency")]
1173    pub group_currency: String,
1174    /// Enable parallel generation
1175    #[serde(default = "default_true")]
1176    pub parallel: bool,
1177    /// Number of worker threads (0 = auto-detect)
1178    #[serde(default)]
1179    pub worker_threads: usize,
1180    /// Memory limit in MB (0 = unlimited)
1181    #[serde(default)]
1182    pub memory_limit_mb: usize,
1183}
1184
1185fn default_currency() -> String {
1186    "USD".to_string()
1187}
1188fn default_true() -> bool {
1189    true
1190}
1191
1192/// Company code configuration.
1193#[derive(Debug, Clone, Serialize, Deserialize)]
1194pub struct CompanyConfig {
1195    /// Company code identifier
1196    pub code: String,
1197    /// Company name
1198    pub name: String,
1199    /// Local currency (ISO 4217)
1200    pub currency: String,
1201    /// Country code (ISO 3166-1 alpha-2)
1202    pub country: String,
1203    /// Fiscal year variant
1204    #[serde(default = "default_fiscal_variant")]
1205    pub fiscal_year_variant: String,
1206    /// Transaction volume per year
1207    pub annual_transaction_volume: TransactionVolume,
1208    /// Company-specific transaction weight
1209    #[serde(default = "default_weight")]
1210    pub volume_weight: f64,
1211}
1212
1213fn default_fiscal_variant() -> String {
1214    "K4".to_string()
1215}
1216fn default_weight() -> f64 {
1217    1.0
1218}
1219
1220/// Transaction volume presets.
1221#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
1222#[serde(rename_all = "snake_case")]
1223pub enum TransactionVolume {
1224    /// 10,000 transactions per year
1225    TenK,
1226    /// 100,000 transactions per year
1227    HundredK,
1228    /// 1,000,000 transactions per year
1229    OneM,
1230    /// 10,000,000 transactions per year
1231    TenM,
1232    /// 100,000,000 transactions per year
1233    HundredM,
1234    /// Custom count
1235    Custom(u64),
1236}
1237
1238impl TransactionVolume {
1239    /// Get the transaction count.
1240    pub fn count(&self) -> u64 {
1241        match self {
1242            Self::TenK => 10_000,
1243            Self::HundredK => 100_000,
1244            Self::OneM => 1_000_000,
1245            Self::TenM => 10_000_000,
1246            Self::HundredM => 100_000_000,
1247            Self::Custom(n) => *n,
1248        }
1249    }
1250}
1251
1252/// Chart of Accounts configuration.
1253#[derive(Debug, Clone, Serialize, Deserialize)]
1254pub struct ChartOfAccountsConfig {
1255    /// CoA complexity level
1256    pub complexity: CoAComplexity,
1257    /// Use industry-specific accounts
1258    #[serde(default = "default_true")]
1259    pub industry_specific: bool,
1260    /// Custom account definitions file
1261    pub custom_accounts: Option<PathBuf>,
1262    /// Minimum hierarchy depth
1263    #[serde(default = "default_min_depth")]
1264    pub min_hierarchy_depth: u8,
1265    /// Maximum hierarchy depth
1266    #[serde(default = "default_max_depth")]
1267    pub max_hierarchy_depth: u8,
1268}
1269
1270fn default_min_depth() -> u8 {
1271    2
1272}
1273fn default_max_depth() -> u8 {
1274    5
1275}
1276
1277impl Default for ChartOfAccountsConfig {
1278    fn default() -> Self {
1279        Self {
1280            complexity: CoAComplexity::Small,
1281            industry_specific: true,
1282            custom_accounts: None,
1283            min_hierarchy_depth: default_min_depth(),
1284            max_hierarchy_depth: default_max_depth(),
1285        }
1286    }
1287}
1288
1289/// Transaction generation configuration.
1290#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1291pub struct TransactionConfig {
1292    /// Line item distribution
1293    #[serde(default)]
1294    pub line_item_distribution: LineItemDistributionConfig,
1295    /// Debit/credit balance distribution
1296    #[serde(default)]
1297    pub debit_credit_distribution: DebitCreditDistributionConfig,
1298    /// Even/odd line count distribution
1299    #[serde(default)]
1300    pub even_odd_distribution: EvenOddDistributionConfig,
1301    /// Transaction source distribution
1302    #[serde(default)]
1303    pub source_distribution: SourceDistribution,
1304    /// Seasonality configuration
1305    #[serde(default)]
1306    pub seasonality: SeasonalityConfig,
1307    /// Amount distribution
1308    #[serde(default)]
1309    pub amounts: AmountDistributionConfig,
1310    /// Benford's Law compliance configuration
1311    #[serde(default)]
1312    pub benford: BenfordConfig,
1313}
1314
1315/// Benford's Law compliance configuration.
1316#[derive(Debug, Clone, Serialize, Deserialize)]
1317pub struct BenfordConfig {
1318    /// Enable Benford's Law compliance for amount generation
1319    #[serde(default = "default_true")]
1320    pub enabled: bool,
1321    /// Tolerance for deviation from ideal Benford distribution (0.0-1.0)
1322    #[serde(default = "default_benford_tolerance")]
1323    pub tolerance: f64,
1324    /// Transaction sources exempt from Benford's Law (fixed amounts)
1325    #[serde(default)]
1326    pub exempt_sources: Vec<BenfordExemption>,
1327}
1328
1329fn default_benford_tolerance() -> f64 {
1330    0.05
1331}
1332
1333impl Default for BenfordConfig {
1334    fn default() -> Self {
1335        Self {
1336            enabled: true,
1337            tolerance: default_benford_tolerance(),
1338            exempt_sources: vec![BenfordExemption::Recurring, BenfordExemption::Payroll],
1339        }
1340    }
1341}
1342
1343/// Types of transactions exempt from Benford's Law.
1344#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1345#[serde(rename_all = "snake_case")]
1346pub enum BenfordExemption {
1347    /// Recurring fixed amounts (rent, subscriptions)
1348    Recurring,
1349    /// Payroll (standardized salaries)
1350    Payroll,
1351    /// Fixed fees and charges
1352    FixedFees,
1353    /// Round number purchases (often legitimate)
1354    RoundAmounts,
1355}
1356
1357/// Distribution of transaction sources.
1358#[derive(Debug, Clone, Serialize, Deserialize)]
1359pub struct SourceDistribution {
1360    /// Manual entries percentage
1361    pub manual: f64,
1362    /// Automated system entries
1363    pub automated: f64,
1364    /// Recurring entries
1365    pub recurring: f64,
1366    /// Adjustment entries
1367    pub adjustment: f64,
1368}
1369
1370impl Default for SourceDistribution {
1371    fn default() -> Self {
1372        Self {
1373            manual: 0.20,
1374            automated: 0.70,
1375            recurring: 0.07,
1376            adjustment: 0.03,
1377        }
1378    }
1379}
1380
1381/// Output configuration.
1382#[derive(Debug, Clone, Serialize, Deserialize)]
1383pub struct OutputConfig {
1384    /// Output mode
1385    #[serde(default)]
1386    pub mode: OutputMode,
1387    /// Output directory
1388    pub output_directory: PathBuf,
1389    /// File formats to generate
1390    #[serde(default = "default_formats")]
1391    pub formats: Vec<FileFormat>,
1392    /// Compression settings
1393    #[serde(default)]
1394    pub compression: CompressionConfig,
1395    /// Batch size for writes
1396    #[serde(default = "default_batch_size")]
1397    pub batch_size: usize,
1398    /// Include ACDOCA format
1399    #[serde(default = "default_true")]
1400    pub include_acdoca: bool,
1401    /// Include BSEG format
1402    #[serde(default)]
1403    pub include_bseg: bool,
1404    /// Partition by fiscal period
1405    #[serde(default = "default_true")]
1406    pub partition_by_period: bool,
1407    /// Partition by company code
1408    #[serde(default)]
1409    pub partition_by_company: bool,
1410}
1411
1412fn default_formats() -> Vec<FileFormat> {
1413    vec![FileFormat::Parquet]
1414}
1415fn default_batch_size() -> usize {
1416    100_000
1417}
1418
1419impl Default for OutputConfig {
1420    fn default() -> Self {
1421        Self {
1422            mode: OutputMode::FlatFile,
1423            output_directory: PathBuf::from("./output"),
1424            formats: default_formats(),
1425            compression: CompressionConfig::default(),
1426            batch_size: default_batch_size(),
1427            include_acdoca: true,
1428            include_bseg: false,
1429            partition_by_period: true,
1430            partition_by_company: false,
1431        }
1432    }
1433}
1434
1435/// Output mode.
1436#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
1437#[serde(rename_all = "snake_case")]
1438pub enum OutputMode {
1439    /// Stream records as generated
1440    Streaming,
1441    /// Write to flat files
1442    #[default]
1443    FlatFile,
1444    /// Both streaming and flat file
1445    Both,
1446}
1447
1448/// Supported file formats.
1449#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1450#[serde(rename_all = "snake_case")]
1451pub enum FileFormat {
1452    Csv,
1453    Parquet,
1454    Json,
1455    JsonLines,
1456}
1457
1458/// Compression configuration.
1459#[derive(Debug, Clone, Serialize, Deserialize)]
1460pub struct CompressionConfig {
1461    /// Enable compression
1462    #[serde(default = "default_true")]
1463    pub enabled: bool,
1464    /// Compression algorithm
1465    #[serde(default)]
1466    pub algorithm: CompressionAlgorithm,
1467    /// Compression level (1-9)
1468    #[serde(default = "default_compression_level")]
1469    pub level: u8,
1470}
1471
1472fn default_compression_level() -> u8 {
1473    3
1474}
1475
1476impl Default for CompressionConfig {
1477    fn default() -> Self {
1478        Self {
1479            enabled: true,
1480            algorithm: CompressionAlgorithm::default(),
1481            level: default_compression_level(),
1482        }
1483    }
1484}
1485
1486/// Compression algorithms.
1487#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
1488#[serde(rename_all = "snake_case")]
1489pub enum CompressionAlgorithm {
1490    Gzip,
1491    #[default]
1492    Zstd,
1493    Lz4,
1494    Snappy,
1495}
1496
1497/// Fraud simulation configuration.
1498#[derive(Debug, Clone, Serialize, Deserialize)]
1499pub struct FraudConfig {
1500    /// Enable fraud scenario generation
1501    #[serde(default)]
1502    pub enabled: bool,
1503    /// Overall fraud rate (0.0 to 1.0)
1504    #[serde(default = "default_fraud_rate")]
1505    pub fraud_rate: f64,
1506    /// Fraud type distribution
1507    #[serde(default)]
1508    pub fraud_type_distribution: FraudTypeDistribution,
1509    /// Enable fraud clustering
1510    #[serde(default)]
1511    pub clustering_enabled: bool,
1512    /// Clustering factor
1513    #[serde(default = "default_clustering_factor")]
1514    pub clustering_factor: f64,
1515    /// Approval thresholds for threshold-adjacent fraud pattern
1516    #[serde(default = "default_approval_thresholds")]
1517    pub approval_thresholds: Vec<f64>,
1518}
1519
1520fn default_approval_thresholds() -> Vec<f64> {
1521    vec![1000.0, 5000.0, 10000.0, 25000.0, 50000.0, 100000.0]
1522}
1523
1524fn default_fraud_rate() -> f64 {
1525    0.005
1526}
1527fn default_clustering_factor() -> f64 {
1528    3.0
1529}
1530
1531impl Default for FraudConfig {
1532    fn default() -> Self {
1533        Self {
1534            enabled: false,
1535            fraud_rate: default_fraud_rate(),
1536            fraud_type_distribution: FraudTypeDistribution::default(),
1537            clustering_enabled: false,
1538            clustering_factor: default_clustering_factor(),
1539            approval_thresholds: default_approval_thresholds(),
1540        }
1541    }
1542}
1543
1544/// Distribution of fraud types.
1545#[derive(Debug, Clone, Serialize, Deserialize)]
1546pub struct FraudTypeDistribution {
1547    pub suspense_account_abuse: f64,
1548    pub fictitious_transaction: f64,
1549    pub revenue_manipulation: f64,
1550    pub expense_capitalization: f64,
1551    pub split_transaction: f64,
1552    pub timing_anomaly: f64,
1553    pub unauthorized_access: f64,
1554    pub duplicate_payment: f64,
1555}
1556
1557impl Default for FraudTypeDistribution {
1558    fn default() -> Self {
1559        Self {
1560            suspense_account_abuse: 0.25,
1561            fictitious_transaction: 0.15,
1562            revenue_manipulation: 0.10,
1563            expense_capitalization: 0.10,
1564            split_transaction: 0.15,
1565            timing_anomaly: 0.10,
1566            unauthorized_access: 0.10,
1567            duplicate_payment: 0.05,
1568        }
1569    }
1570}
1571
1572/// Internal Controls System (ICS) configuration.
1573#[derive(Debug, Clone, Serialize, Deserialize)]
1574pub struct InternalControlsConfig {
1575    /// Enable internal controls system
1576    #[serde(default)]
1577    pub enabled: bool,
1578    /// Rate at which controls result in exceptions (0.0 - 1.0)
1579    #[serde(default = "default_exception_rate")]
1580    pub exception_rate: f64,
1581    /// Rate at which SoD violations occur (0.0 - 1.0)
1582    #[serde(default = "default_sod_violation_rate")]
1583    pub sod_violation_rate: f64,
1584    /// Export control master data to separate files
1585    #[serde(default = "default_true")]
1586    pub export_control_master_data: bool,
1587    /// SOX materiality threshold for marking transactions as SOX-relevant
1588    #[serde(default = "default_sox_materiality_threshold")]
1589    pub sox_materiality_threshold: f64,
1590    /// Enable COSO 2013 framework integration
1591    #[serde(default = "default_true")]
1592    pub coso_enabled: bool,
1593    /// Include entity-level controls in generation
1594    #[serde(default)]
1595    pub include_entity_level_controls: bool,
1596    /// Target maturity level for controls
1597    /// Valid values: "ad_hoc", "repeatable", "defined", "managed", "optimized", "mixed"
1598    #[serde(default = "default_target_maturity_level")]
1599    pub target_maturity_level: String,
1600}
1601
1602fn default_exception_rate() -> f64 {
1603    0.02
1604}
1605
1606fn default_sod_violation_rate() -> f64 {
1607    0.01
1608}
1609
1610fn default_sox_materiality_threshold() -> f64 {
1611    10000.0
1612}
1613
1614fn default_target_maturity_level() -> String {
1615    "mixed".to_string()
1616}
1617
1618impl Default for InternalControlsConfig {
1619    fn default() -> Self {
1620        Self {
1621            enabled: false,
1622            exception_rate: default_exception_rate(),
1623            sod_violation_rate: default_sod_violation_rate(),
1624            export_control_master_data: true,
1625            sox_materiality_threshold: default_sox_materiality_threshold(),
1626            coso_enabled: true,
1627            include_entity_level_controls: false,
1628            target_maturity_level: default_target_maturity_level(),
1629        }
1630    }
1631}
1632
1633/// Business process configuration.
1634#[derive(Debug, Clone, Serialize, Deserialize)]
1635pub struct BusinessProcessConfig {
1636    /// Order-to-Cash weight
1637    #[serde(default = "default_o2c")]
1638    pub o2c_weight: f64,
1639    /// Procure-to-Pay weight
1640    #[serde(default = "default_p2p")]
1641    pub p2p_weight: f64,
1642    /// Record-to-Report weight
1643    #[serde(default = "default_r2r")]
1644    pub r2r_weight: f64,
1645    /// Hire-to-Retire weight
1646    #[serde(default = "default_h2r")]
1647    pub h2r_weight: f64,
1648    /// Acquire-to-Retire weight
1649    #[serde(default = "default_a2r")]
1650    pub a2r_weight: f64,
1651}
1652
1653fn default_o2c() -> f64 {
1654    0.35
1655}
1656fn default_p2p() -> f64 {
1657    0.30
1658}
1659fn default_r2r() -> f64 {
1660    0.20
1661}
1662fn default_h2r() -> f64 {
1663    0.10
1664}
1665fn default_a2r() -> f64 {
1666    0.05
1667}
1668
1669impl Default for BusinessProcessConfig {
1670    fn default() -> Self {
1671        Self {
1672            o2c_weight: default_o2c(),
1673            p2p_weight: default_p2p(),
1674            r2r_weight: default_r2r(),
1675            h2r_weight: default_h2r(),
1676            a2r_weight: default_a2r(),
1677        }
1678    }
1679}
1680
1681/// User persona configuration.
1682#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1683pub struct UserPersonaConfig {
1684    /// Distribution of user personas
1685    #[serde(default)]
1686    pub persona_distribution: PersonaDistribution,
1687    /// Users per persona type
1688    #[serde(default)]
1689    pub users_per_persona: UsersPerPersona,
1690}
1691
1692/// Distribution of user personas for transaction generation.
1693#[derive(Debug, Clone, Serialize, Deserialize)]
1694pub struct PersonaDistribution {
1695    pub junior_accountant: f64,
1696    pub senior_accountant: f64,
1697    pub controller: f64,
1698    pub manager: f64,
1699    pub automated_system: f64,
1700}
1701
1702impl Default for PersonaDistribution {
1703    fn default() -> Self {
1704        Self {
1705            junior_accountant: 0.15,
1706            senior_accountant: 0.15,
1707            controller: 0.05,
1708            manager: 0.05,
1709            automated_system: 0.60,
1710        }
1711    }
1712}
1713
1714/// Number of users per persona type.
1715#[derive(Debug, Clone, Serialize, Deserialize)]
1716pub struct UsersPerPersona {
1717    pub junior_accountant: usize,
1718    pub senior_accountant: usize,
1719    pub controller: usize,
1720    pub manager: usize,
1721    pub automated_system: usize,
1722}
1723
1724impl Default for UsersPerPersona {
1725    fn default() -> Self {
1726        Self {
1727            junior_accountant: 10,
1728            senior_accountant: 5,
1729            controller: 2,
1730            manager: 3,
1731            automated_system: 20,
1732        }
1733    }
1734}
1735
1736/// Template configuration for realistic data generation.
1737#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1738pub struct TemplateConfig {
1739    /// Name generation settings
1740    #[serde(default)]
1741    pub names: NameTemplateConfig,
1742    /// Description generation settings
1743    #[serde(default)]
1744    pub descriptions: DescriptionTemplateConfig,
1745    /// Reference number settings
1746    #[serde(default)]
1747    pub references: ReferenceTemplateConfig,
1748}
1749
1750/// Name template configuration.
1751#[derive(Debug, Clone, Serialize, Deserialize)]
1752pub struct NameTemplateConfig {
1753    /// Distribution of name cultures
1754    #[serde(default)]
1755    pub culture_distribution: CultureDistribution,
1756    /// Email domain for generated users
1757    #[serde(default = "default_email_domain")]
1758    pub email_domain: String,
1759    /// Generate realistic display names
1760    #[serde(default = "default_true")]
1761    pub generate_realistic_names: bool,
1762}
1763
1764fn default_email_domain() -> String {
1765    "company.com".to_string()
1766}
1767
1768impl Default for NameTemplateConfig {
1769    fn default() -> Self {
1770        Self {
1771            culture_distribution: CultureDistribution::default(),
1772            email_domain: default_email_domain(),
1773            generate_realistic_names: true,
1774        }
1775    }
1776}
1777
1778/// Distribution of name cultures for generation.
1779#[derive(Debug, Clone, Serialize, Deserialize)]
1780pub struct CultureDistribution {
1781    pub western_us: f64,
1782    pub hispanic: f64,
1783    pub german: f64,
1784    pub french: f64,
1785    pub chinese: f64,
1786    pub japanese: f64,
1787    pub indian: f64,
1788}
1789
1790impl Default for CultureDistribution {
1791    fn default() -> Self {
1792        Self {
1793            western_us: 0.40,
1794            hispanic: 0.20,
1795            german: 0.10,
1796            french: 0.05,
1797            chinese: 0.10,
1798            japanese: 0.05,
1799            indian: 0.10,
1800        }
1801    }
1802}
1803
1804/// Description template configuration.
1805#[derive(Debug, Clone, Serialize, Deserialize)]
1806pub struct DescriptionTemplateConfig {
1807    /// Generate header text for journal entries
1808    #[serde(default = "default_true")]
1809    pub generate_header_text: bool,
1810    /// Generate line text for journal entry lines
1811    #[serde(default = "default_true")]
1812    pub generate_line_text: bool,
1813}
1814
1815impl Default for DescriptionTemplateConfig {
1816    fn default() -> Self {
1817        Self {
1818            generate_header_text: true,
1819            generate_line_text: true,
1820        }
1821    }
1822}
1823
1824/// Reference number template configuration.
1825#[derive(Debug, Clone, Serialize, Deserialize)]
1826pub struct ReferenceTemplateConfig {
1827    /// Generate reference numbers
1828    #[serde(default = "default_true")]
1829    pub generate_references: bool,
1830    /// Invoice prefix
1831    #[serde(default = "default_invoice_prefix")]
1832    pub invoice_prefix: String,
1833    /// Purchase order prefix
1834    #[serde(default = "default_po_prefix")]
1835    pub po_prefix: String,
1836    /// Sales order prefix
1837    #[serde(default = "default_so_prefix")]
1838    pub so_prefix: String,
1839}
1840
1841fn default_invoice_prefix() -> String {
1842    "INV".to_string()
1843}
1844fn default_po_prefix() -> String {
1845    "PO".to_string()
1846}
1847fn default_so_prefix() -> String {
1848    "SO".to_string()
1849}
1850
1851impl Default for ReferenceTemplateConfig {
1852    fn default() -> Self {
1853        Self {
1854            generate_references: true,
1855            invoice_prefix: default_invoice_prefix(),
1856            po_prefix: default_po_prefix(),
1857            so_prefix: default_so_prefix(),
1858        }
1859    }
1860}
1861
1862/// Approval workflow configuration.
1863#[derive(Debug, Clone, Serialize, Deserialize)]
1864pub struct ApprovalConfig {
1865    /// Enable approval workflow generation
1866    #[serde(default)]
1867    pub enabled: bool,
1868    /// Threshold below which transactions are auto-approved
1869    #[serde(default = "default_auto_approve_threshold")]
1870    pub auto_approve_threshold: f64,
1871    /// Rate at which approvals are rejected (0.0 to 1.0)
1872    #[serde(default = "default_rejection_rate")]
1873    pub rejection_rate: f64,
1874    /// Rate at which approvals require revision (0.0 to 1.0)
1875    #[serde(default = "default_revision_rate")]
1876    pub revision_rate: f64,
1877    /// Average delay in hours for approval processing
1878    #[serde(default = "default_approval_delay_hours")]
1879    pub average_approval_delay_hours: f64,
1880    /// Approval chain thresholds
1881    #[serde(default)]
1882    pub thresholds: Vec<ApprovalThresholdConfig>,
1883}
1884
1885fn default_auto_approve_threshold() -> f64 {
1886    1000.0
1887}
1888fn default_rejection_rate() -> f64 {
1889    0.02
1890}
1891fn default_revision_rate() -> f64 {
1892    0.05
1893}
1894fn default_approval_delay_hours() -> f64 {
1895    4.0
1896}
1897
1898impl Default for ApprovalConfig {
1899    fn default() -> Self {
1900        Self {
1901            enabled: false,
1902            auto_approve_threshold: default_auto_approve_threshold(),
1903            rejection_rate: default_rejection_rate(),
1904            revision_rate: default_revision_rate(),
1905            average_approval_delay_hours: default_approval_delay_hours(),
1906            thresholds: vec![
1907                ApprovalThresholdConfig {
1908                    amount: 1000.0,
1909                    level: 1,
1910                    roles: vec!["senior_accountant".to_string()],
1911                },
1912                ApprovalThresholdConfig {
1913                    amount: 10000.0,
1914                    level: 2,
1915                    roles: vec!["senior_accountant".to_string(), "controller".to_string()],
1916                },
1917                ApprovalThresholdConfig {
1918                    amount: 100000.0,
1919                    level: 3,
1920                    roles: vec![
1921                        "senior_accountant".to_string(),
1922                        "controller".to_string(),
1923                        "manager".to_string(),
1924                    ],
1925                },
1926                ApprovalThresholdConfig {
1927                    amount: 500000.0,
1928                    level: 4,
1929                    roles: vec![
1930                        "senior_accountant".to_string(),
1931                        "controller".to_string(),
1932                        "manager".to_string(),
1933                        "executive".to_string(),
1934                    ],
1935                },
1936            ],
1937        }
1938    }
1939}
1940
1941/// Configuration for a single approval threshold.
1942#[derive(Debug, Clone, Serialize, Deserialize)]
1943pub struct ApprovalThresholdConfig {
1944    /// Amount threshold
1945    pub amount: f64,
1946    /// Approval level required
1947    pub level: u8,
1948    /// Roles that can approve at this level
1949    pub roles: Vec<String>,
1950}
1951
1952/// Department configuration.
1953#[derive(Debug, Clone, Serialize, Deserialize)]
1954pub struct DepartmentConfig {
1955    /// Enable department assignment
1956    #[serde(default)]
1957    pub enabled: bool,
1958    /// Multiplier for department headcounts
1959    #[serde(default = "default_headcount_multiplier")]
1960    pub headcount_multiplier: f64,
1961    /// Custom department definitions (optional)
1962    #[serde(default)]
1963    pub custom_departments: Vec<CustomDepartmentConfig>,
1964}
1965
1966fn default_headcount_multiplier() -> f64 {
1967    1.0
1968}
1969
1970impl Default for DepartmentConfig {
1971    fn default() -> Self {
1972        Self {
1973            enabled: false,
1974            headcount_multiplier: default_headcount_multiplier(),
1975            custom_departments: Vec::new(),
1976        }
1977    }
1978}
1979
1980/// Custom department definition.
1981#[derive(Debug, Clone, Serialize, Deserialize)]
1982pub struct CustomDepartmentConfig {
1983    /// Department code
1984    pub code: String,
1985    /// Department name
1986    pub name: String,
1987    /// Associated cost center
1988    #[serde(default)]
1989    pub cost_center: Option<String>,
1990    /// Primary business processes
1991    #[serde(default)]
1992    pub primary_processes: Vec<String>,
1993    /// Parent department code
1994    #[serde(default)]
1995    pub parent_code: Option<String>,
1996}
1997
1998// ============================================================================
1999// Master Data Configuration
2000// ============================================================================
2001
2002/// Master data generation configuration.
2003#[derive(Debug, Clone, Default, Serialize, Deserialize)]
2004pub struct MasterDataConfig {
2005    /// Vendor master data settings
2006    #[serde(default)]
2007    pub vendors: VendorMasterConfig,
2008    /// Customer master data settings
2009    #[serde(default)]
2010    pub customers: CustomerMasterConfig,
2011    /// Material master data settings
2012    #[serde(default)]
2013    pub materials: MaterialMasterConfig,
2014    /// Fixed asset master data settings
2015    #[serde(default)]
2016    pub fixed_assets: FixedAssetMasterConfig,
2017    /// Employee master data settings
2018    #[serde(default)]
2019    pub employees: EmployeeMasterConfig,
2020    /// Cost center master data settings
2021    #[serde(default)]
2022    pub cost_centers: CostCenterMasterConfig,
2023}
2024
2025/// Vendor master data configuration.
2026#[derive(Debug, Clone, Serialize, Deserialize)]
2027pub struct VendorMasterConfig {
2028    /// Number of vendors to generate
2029    #[serde(default = "default_vendor_count")]
2030    pub count: usize,
2031    /// Percentage of vendors that are intercompany (0.0 to 1.0)
2032    #[serde(default = "default_intercompany_percent")]
2033    pub intercompany_percent: f64,
2034    /// Payment terms distribution
2035    #[serde(default)]
2036    pub payment_terms_distribution: PaymentTermsDistribution,
2037    /// Vendor behavior distribution
2038    #[serde(default)]
2039    pub behavior_distribution: VendorBehaviorDistribution,
2040    /// Generate bank account details
2041    #[serde(default = "default_true")]
2042    pub generate_bank_accounts: bool,
2043    /// Generate tax IDs
2044    #[serde(default = "default_true")]
2045    pub generate_tax_ids: bool,
2046}
2047
2048fn default_vendor_count() -> usize {
2049    500
2050}
2051
2052fn default_intercompany_percent() -> f64 {
2053    0.05
2054}
2055
2056impl Default for VendorMasterConfig {
2057    fn default() -> Self {
2058        Self {
2059            count: default_vendor_count(),
2060            intercompany_percent: default_intercompany_percent(),
2061            payment_terms_distribution: PaymentTermsDistribution::default(),
2062            behavior_distribution: VendorBehaviorDistribution::default(),
2063            generate_bank_accounts: true,
2064            generate_tax_ids: true,
2065        }
2066    }
2067}
2068
2069/// Payment terms distribution for vendors.
2070#[derive(Debug, Clone, Serialize, Deserialize)]
2071pub struct PaymentTermsDistribution {
2072    /// Net 30 days
2073    pub net_30: f64,
2074    /// Net 60 days
2075    pub net_60: f64,
2076    /// Net 90 days
2077    pub net_90: f64,
2078    /// 2% 10 Net 30 (early payment discount)
2079    pub two_ten_net_30: f64,
2080    /// Due on receipt
2081    pub due_on_receipt: f64,
2082    /// End of month
2083    pub end_of_month: f64,
2084}
2085
2086impl Default for PaymentTermsDistribution {
2087    fn default() -> Self {
2088        Self {
2089            net_30: 0.40,
2090            net_60: 0.20,
2091            net_90: 0.10,
2092            two_ten_net_30: 0.15,
2093            due_on_receipt: 0.05,
2094            end_of_month: 0.10,
2095        }
2096    }
2097}
2098
2099/// Vendor behavior distribution.
2100#[derive(Debug, Clone, Serialize, Deserialize)]
2101pub struct VendorBehaviorDistribution {
2102    /// Reliable vendors (consistent delivery, quality)
2103    pub reliable: f64,
2104    /// Sometimes late vendors
2105    pub sometimes_late: f64,
2106    /// Inconsistent quality vendors
2107    pub inconsistent_quality: f64,
2108    /// Premium vendors (high quality, premium pricing)
2109    pub premium: f64,
2110    /// Budget vendors (lower quality, lower pricing)
2111    pub budget: f64,
2112}
2113
2114impl Default for VendorBehaviorDistribution {
2115    fn default() -> Self {
2116        Self {
2117            reliable: 0.50,
2118            sometimes_late: 0.20,
2119            inconsistent_quality: 0.10,
2120            premium: 0.10,
2121            budget: 0.10,
2122        }
2123    }
2124}
2125
2126/// Customer master data configuration.
2127#[derive(Debug, Clone, Serialize, Deserialize)]
2128pub struct CustomerMasterConfig {
2129    /// Number of customers to generate
2130    #[serde(default = "default_customer_count")]
2131    pub count: usize,
2132    /// Percentage of customers that are intercompany (0.0 to 1.0)
2133    #[serde(default = "default_intercompany_percent")]
2134    pub intercompany_percent: f64,
2135    /// Credit rating distribution
2136    #[serde(default)]
2137    pub credit_rating_distribution: CreditRatingDistribution,
2138    /// Payment behavior distribution
2139    #[serde(default)]
2140    pub payment_behavior_distribution: PaymentBehaviorDistribution,
2141    /// Generate credit limits based on rating
2142    #[serde(default = "default_true")]
2143    pub generate_credit_limits: bool,
2144}
2145
2146fn default_customer_count() -> usize {
2147    2000
2148}
2149
2150impl Default for CustomerMasterConfig {
2151    fn default() -> Self {
2152        Self {
2153            count: default_customer_count(),
2154            intercompany_percent: default_intercompany_percent(),
2155            credit_rating_distribution: CreditRatingDistribution::default(),
2156            payment_behavior_distribution: PaymentBehaviorDistribution::default(),
2157            generate_credit_limits: true,
2158        }
2159    }
2160}
2161
2162/// Credit rating distribution for customers.
2163#[derive(Debug, Clone, Serialize, Deserialize)]
2164pub struct CreditRatingDistribution {
2165    /// AAA rating
2166    pub aaa: f64,
2167    /// AA rating
2168    pub aa: f64,
2169    /// A rating
2170    pub a: f64,
2171    /// BBB rating
2172    pub bbb: f64,
2173    /// BB rating
2174    pub bb: f64,
2175    /// B rating
2176    pub b: f64,
2177    /// Below B rating
2178    pub below_b: f64,
2179}
2180
2181impl Default for CreditRatingDistribution {
2182    fn default() -> Self {
2183        Self {
2184            aaa: 0.05,
2185            aa: 0.10,
2186            a: 0.20,
2187            bbb: 0.30,
2188            bb: 0.20,
2189            b: 0.10,
2190            below_b: 0.05,
2191        }
2192    }
2193}
2194
2195/// Payment behavior distribution for customers.
2196#[derive(Debug, Clone, Serialize, Deserialize)]
2197pub struct PaymentBehaviorDistribution {
2198    /// Always pays early
2199    pub early_payer: f64,
2200    /// Pays on time
2201    pub on_time: f64,
2202    /// Occasionally late
2203    pub occasional_late: f64,
2204    /// Frequently late
2205    pub frequent_late: f64,
2206    /// Takes early payment discounts
2207    pub discount_taker: f64,
2208}
2209
2210impl Default for PaymentBehaviorDistribution {
2211    fn default() -> Self {
2212        Self {
2213            early_payer: 0.10,
2214            on_time: 0.50,
2215            occasional_late: 0.25,
2216            frequent_late: 0.10,
2217            discount_taker: 0.05,
2218        }
2219    }
2220}
2221
2222/// Material master data configuration.
2223#[derive(Debug, Clone, Serialize, Deserialize)]
2224pub struct MaterialMasterConfig {
2225    /// Number of materials to generate
2226    #[serde(default = "default_material_count")]
2227    pub count: usize,
2228    /// Material type distribution
2229    #[serde(default)]
2230    pub type_distribution: MaterialTypeDistribution,
2231    /// Valuation method distribution
2232    #[serde(default)]
2233    pub valuation_distribution: ValuationMethodDistribution,
2234    /// Percentage of materials with BOM (bill of materials)
2235    #[serde(default = "default_bom_percent")]
2236    pub bom_percent: f64,
2237    /// Maximum BOM depth
2238    #[serde(default = "default_max_bom_depth")]
2239    pub max_bom_depth: u8,
2240}
2241
2242fn default_material_count() -> usize {
2243    5000
2244}
2245
2246fn default_bom_percent() -> f64 {
2247    0.20
2248}
2249
2250fn default_max_bom_depth() -> u8 {
2251    3
2252}
2253
2254impl Default for MaterialMasterConfig {
2255    fn default() -> Self {
2256        Self {
2257            count: default_material_count(),
2258            type_distribution: MaterialTypeDistribution::default(),
2259            valuation_distribution: ValuationMethodDistribution::default(),
2260            bom_percent: default_bom_percent(),
2261            max_bom_depth: default_max_bom_depth(),
2262        }
2263    }
2264}
2265
2266/// Material type distribution.
2267#[derive(Debug, Clone, Serialize, Deserialize)]
2268pub struct MaterialTypeDistribution {
2269    /// Raw materials
2270    pub raw_material: f64,
2271    /// Semi-finished goods
2272    pub semi_finished: f64,
2273    /// Finished goods
2274    pub finished_good: f64,
2275    /// Trading goods (purchased for resale)
2276    pub trading_good: f64,
2277    /// Operating supplies
2278    pub operating_supply: f64,
2279    /// Services
2280    pub service: f64,
2281}
2282
2283impl Default for MaterialTypeDistribution {
2284    fn default() -> Self {
2285        Self {
2286            raw_material: 0.30,
2287            semi_finished: 0.15,
2288            finished_good: 0.25,
2289            trading_good: 0.15,
2290            operating_supply: 0.10,
2291            service: 0.05,
2292        }
2293    }
2294}
2295
2296/// Valuation method distribution for materials.
2297#[derive(Debug, Clone, Serialize, Deserialize)]
2298pub struct ValuationMethodDistribution {
2299    /// Standard cost
2300    pub standard_cost: f64,
2301    /// Moving average
2302    pub moving_average: f64,
2303    /// FIFO (First In, First Out)
2304    pub fifo: f64,
2305    /// LIFO (Last In, First Out)
2306    pub lifo: f64,
2307}
2308
2309impl Default for ValuationMethodDistribution {
2310    fn default() -> Self {
2311        Self {
2312            standard_cost: 0.50,
2313            moving_average: 0.30,
2314            fifo: 0.15,
2315            lifo: 0.05,
2316        }
2317    }
2318}
2319
2320/// Fixed asset master data configuration.
2321#[derive(Debug, Clone, Serialize, Deserialize)]
2322pub struct FixedAssetMasterConfig {
2323    /// Number of fixed assets to generate
2324    #[serde(default = "default_asset_count")]
2325    pub count: usize,
2326    /// Asset class distribution
2327    #[serde(default)]
2328    pub class_distribution: AssetClassDistribution,
2329    /// Depreciation method distribution
2330    #[serde(default)]
2331    pub depreciation_distribution: DepreciationMethodDistribution,
2332    /// Percentage of assets that are fully depreciated
2333    #[serde(default = "default_fully_depreciated_percent")]
2334    pub fully_depreciated_percent: f64,
2335    /// Generate acquisition history
2336    #[serde(default = "default_true")]
2337    pub generate_acquisition_history: bool,
2338}
2339
2340fn default_asset_count() -> usize {
2341    800
2342}
2343
2344fn default_fully_depreciated_percent() -> f64 {
2345    0.15
2346}
2347
2348impl Default for FixedAssetMasterConfig {
2349    fn default() -> Self {
2350        Self {
2351            count: default_asset_count(),
2352            class_distribution: AssetClassDistribution::default(),
2353            depreciation_distribution: DepreciationMethodDistribution::default(),
2354            fully_depreciated_percent: default_fully_depreciated_percent(),
2355            generate_acquisition_history: true,
2356        }
2357    }
2358}
2359
2360/// Asset class distribution.
2361#[derive(Debug, Clone, Serialize, Deserialize)]
2362pub struct AssetClassDistribution {
2363    /// Buildings and structures
2364    pub buildings: f64,
2365    /// Machinery and equipment
2366    pub machinery: f64,
2367    /// Vehicles
2368    pub vehicles: f64,
2369    /// IT equipment
2370    pub it_equipment: f64,
2371    /// Furniture and fixtures
2372    pub furniture: f64,
2373    /// Land (non-depreciable)
2374    pub land: f64,
2375    /// Leasehold improvements
2376    pub leasehold: f64,
2377}
2378
2379impl Default for AssetClassDistribution {
2380    fn default() -> Self {
2381        Self {
2382            buildings: 0.15,
2383            machinery: 0.30,
2384            vehicles: 0.15,
2385            it_equipment: 0.20,
2386            furniture: 0.10,
2387            land: 0.05,
2388            leasehold: 0.05,
2389        }
2390    }
2391}
2392
2393/// Depreciation method distribution.
2394#[derive(Debug, Clone, Serialize, Deserialize)]
2395pub struct DepreciationMethodDistribution {
2396    /// Straight line
2397    pub straight_line: f64,
2398    /// Declining balance
2399    pub declining_balance: f64,
2400    /// Double declining balance
2401    pub double_declining: f64,
2402    /// Sum of years' digits
2403    pub sum_of_years: f64,
2404    /// Units of production
2405    pub units_of_production: f64,
2406}
2407
2408impl Default for DepreciationMethodDistribution {
2409    fn default() -> Self {
2410        Self {
2411            straight_line: 0.60,
2412            declining_balance: 0.20,
2413            double_declining: 0.10,
2414            sum_of_years: 0.05,
2415            units_of_production: 0.05,
2416        }
2417    }
2418}
2419
2420/// Employee master data configuration.
2421#[derive(Debug, Clone, Serialize, Deserialize)]
2422pub struct EmployeeMasterConfig {
2423    /// Number of employees to generate
2424    #[serde(default = "default_employee_count")]
2425    pub count: usize,
2426    /// Generate organizational hierarchy
2427    #[serde(default = "default_true")]
2428    pub generate_hierarchy: bool,
2429    /// Maximum hierarchy depth
2430    #[serde(default = "default_hierarchy_depth")]
2431    pub max_hierarchy_depth: u8,
2432    /// Average span of control (direct reports per manager)
2433    #[serde(default = "default_span_of_control")]
2434    pub average_span_of_control: f64,
2435    /// Approval limit distribution by job level
2436    #[serde(default)]
2437    pub approval_limits: ApprovalLimitDistribution,
2438    /// Department distribution
2439    #[serde(default)]
2440    pub department_distribution: EmployeeDepartmentDistribution,
2441}
2442
2443fn default_employee_count() -> usize {
2444    1500
2445}
2446
2447fn default_hierarchy_depth() -> u8 {
2448    6
2449}
2450
2451fn default_span_of_control() -> f64 {
2452    5.0
2453}
2454
2455impl Default for EmployeeMasterConfig {
2456    fn default() -> Self {
2457        Self {
2458            count: default_employee_count(),
2459            generate_hierarchy: true,
2460            max_hierarchy_depth: default_hierarchy_depth(),
2461            average_span_of_control: default_span_of_control(),
2462            approval_limits: ApprovalLimitDistribution::default(),
2463            department_distribution: EmployeeDepartmentDistribution::default(),
2464        }
2465    }
2466}
2467
2468/// Approval limit distribution by job level.
2469#[derive(Debug, Clone, Serialize, Deserialize)]
2470pub struct ApprovalLimitDistribution {
2471    /// Staff level approval limit
2472    #[serde(default = "default_staff_limit")]
2473    pub staff: f64,
2474    /// Senior staff approval limit
2475    #[serde(default = "default_senior_limit")]
2476    pub senior: f64,
2477    /// Manager approval limit
2478    #[serde(default = "default_manager_limit")]
2479    pub manager: f64,
2480    /// Director approval limit
2481    #[serde(default = "default_director_limit")]
2482    pub director: f64,
2483    /// VP approval limit
2484    #[serde(default = "default_vp_limit")]
2485    pub vp: f64,
2486    /// Executive approval limit
2487    #[serde(default = "default_executive_limit")]
2488    pub executive: f64,
2489}
2490
2491fn default_staff_limit() -> f64 {
2492    1000.0
2493}
2494fn default_senior_limit() -> f64 {
2495    5000.0
2496}
2497fn default_manager_limit() -> f64 {
2498    25000.0
2499}
2500fn default_director_limit() -> f64 {
2501    100000.0
2502}
2503fn default_vp_limit() -> f64 {
2504    500000.0
2505}
2506fn default_executive_limit() -> f64 {
2507    f64::INFINITY
2508}
2509
2510impl Default for ApprovalLimitDistribution {
2511    fn default() -> Self {
2512        Self {
2513            staff: default_staff_limit(),
2514            senior: default_senior_limit(),
2515            manager: default_manager_limit(),
2516            director: default_director_limit(),
2517            vp: default_vp_limit(),
2518            executive: default_executive_limit(),
2519        }
2520    }
2521}
2522
2523/// Employee distribution across departments.
2524#[derive(Debug, Clone, Serialize, Deserialize)]
2525pub struct EmployeeDepartmentDistribution {
2526    /// Finance and Accounting
2527    pub finance: f64,
2528    /// Procurement
2529    pub procurement: f64,
2530    /// Sales
2531    pub sales: f64,
2532    /// Warehouse and Logistics
2533    pub warehouse: f64,
2534    /// IT
2535    pub it: f64,
2536    /// Human Resources
2537    pub hr: f64,
2538    /// Operations
2539    pub operations: f64,
2540    /// Executive
2541    pub executive: f64,
2542}
2543
2544impl Default for EmployeeDepartmentDistribution {
2545    fn default() -> Self {
2546        Self {
2547            finance: 0.12,
2548            procurement: 0.10,
2549            sales: 0.25,
2550            warehouse: 0.15,
2551            it: 0.10,
2552            hr: 0.05,
2553            operations: 0.20,
2554            executive: 0.03,
2555        }
2556    }
2557}
2558
2559/// Cost center master data configuration.
2560#[derive(Debug, Clone, Serialize, Deserialize)]
2561pub struct CostCenterMasterConfig {
2562    /// Number of cost centers to generate
2563    #[serde(default = "default_cost_center_count")]
2564    pub count: usize,
2565    /// Generate cost center hierarchy
2566    #[serde(default = "default_true")]
2567    pub generate_hierarchy: bool,
2568    /// Maximum hierarchy depth
2569    #[serde(default = "default_cc_hierarchy_depth")]
2570    pub max_hierarchy_depth: u8,
2571}
2572
2573fn default_cost_center_count() -> usize {
2574    50
2575}
2576
2577fn default_cc_hierarchy_depth() -> u8 {
2578    3
2579}
2580
2581impl Default for CostCenterMasterConfig {
2582    fn default() -> Self {
2583        Self {
2584            count: default_cost_center_count(),
2585            generate_hierarchy: true,
2586            max_hierarchy_depth: default_cc_hierarchy_depth(),
2587        }
2588    }
2589}
2590
2591// ============================================================================
2592// Document Flow Configuration
2593// ============================================================================
2594
2595/// Document flow generation configuration.
2596#[derive(Debug, Clone, Serialize, Deserialize)]
2597pub struct DocumentFlowConfig {
2598    /// P2P (Procure-to-Pay) flow configuration
2599    #[serde(default)]
2600    pub p2p: P2PFlowConfig,
2601    /// O2C (Order-to-Cash) flow configuration
2602    #[serde(default)]
2603    pub o2c: O2CFlowConfig,
2604    /// Generate document reference chains
2605    #[serde(default = "default_true")]
2606    pub generate_document_references: bool,
2607    /// Export document flow graph
2608    #[serde(default)]
2609    pub export_flow_graph: bool,
2610}
2611
2612impl Default for DocumentFlowConfig {
2613    fn default() -> Self {
2614        Self {
2615            p2p: P2PFlowConfig::default(),
2616            o2c: O2CFlowConfig::default(),
2617            generate_document_references: true,
2618            export_flow_graph: false,
2619        }
2620    }
2621}
2622
2623/// P2P (Procure-to-Pay) flow configuration.
2624#[derive(Debug, Clone, Serialize, Deserialize)]
2625pub struct P2PFlowConfig {
2626    /// Enable P2P document flow generation
2627    #[serde(default = "default_true")]
2628    pub enabled: bool,
2629    /// Three-way match success rate (PO-GR-Invoice)
2630    #[serde(default = "default_three_way_match_rate")]
2631    pub three_way_match_rate: f64,
2632    /// Rate of partial deliveries
2633    #[serde(default = "default_partial_delivery_rate")]
2634    pub partial_delivery_rate: f64,
2635    /// Rate of price variances between PO and Invoice
2636    #[serde(default = "default_price_variance_rate")]
2637    pub price_variance_rate: f64,
2638    /// Maximum price variance percentage
2639    #[serde(default = "default_max_price_variance")]
2640    pub max_price_variance_percent: f64,
2641    /// Rate of quantity variances between PO/GR and Invoice
2642    #[serde(default = "default_quantity_variance_rate")]
2643    pub quantity_variance_rate: f64,
2644    /// Average days from PO to goods receipt
2645    #[serde(default = "default_po_to_gr_days")]
2646    pub average_po_to_gr_days: u32,
2647    /// Average days from GR to invoice
2648    #[serde(default = "default_gr_to_invoice_days")]
2649    pub average_gr_to_invoice_days: u32,
2650    /// Average days from invoice to payment
2651    #[serde(default = "default_invoice_to_payment_days")]
2652    pub average_invoice_to_payment_days: u32,
2653    /// PO line count distribution
2654    #[serde(default)]
2655    pub line_count_distribution: DocumentLineCountDistribution,
2656    /// Payment behavior configuration
2657    #[serde(default)]
2658    pub payment_behavior: P2PPaymentBehaviorConfig,
2659}
2660
2661fn default_three_way_match_rate() -> f64 {
2662    0.95
2663}
2664
2665fn default_partial_delivery_rate() -> f64 {
2666    0.15
2667}
2668
2669fn default_price_variance_rate() -> f64 {
2670    0.08
2671}
2672
2673fn default_max_price_variance() -> f64 {
2674    0.05
2675}
2676
2677fn default_quantity_variance_rate() -> f64 {
2678    0.05
2679}
2680
2681fn default_po_to_gr_days() -> u32 {
2682    14
2683}
2684
2685fn default_gr_to_invoice_days() -> u32 {
2686    5
2687}
2688
2689fn default_invoice_to_payment_days() -> u32 {
2690    30
2691}
2692
2693impl Default for P2PFlowConfig {
2694    fn default() -> Self {
2695        Self {
2696            enabled: true,
2697            three_way_match_rate: default_three_way_match_rate(),
2698            partial_delivery_rate: default_partial_delivery_rate(),
2699            price_variance_rate: default_price_variance_rate(),
2700            max_price_variance_percent: default_max_price_variance(),
2701            quantity_variance_rate: default_quantity_variance_rate(),
2702            average_po_to_gr_days: default_po_to_gr_days(),
2703            average_gr_to_invoice_days: default_gr_to_invoice_days(),
2704            average_invoice_to_payment_days: default_invoice_to_payment_days(),
2705            line_count_distribution: DocumentLineCountDistribution::default(),
2706            payment_behavior: P2PPaymentBehaviorConfig::default(),
2707        }
2708    }
2709}
2710
2711// ============================================================================
2712// P2P Payment Behavior Configuration
2713// ============================================================================
2714
2715/// P2P payment behavior configuration.
2716#[derive(Debug, Clone, Serialize, Deserialize)]
2717pub struct P2PPaymentBehaviorConfig {
2718    /// Rate of late payments (beyond due date)
2719    #[serde(default = "default_p2p_late_payment_rate")]
2720    pub late_payment_rate: f64,
2721    /// Distribution of late payment days
2722    #[serde(default)]
2723    pub late_payment_days_distribution: LatePaymentDaysDistribution,
2724    /// Rate of partial payments
2725    #[serde(default = "default_p2p_partial_payment_rate")]
2726    pub partial_payment_rate: f64,
2727    /// Rate of payment corrections (NSF, chargebacks, reversals)
2728    #[serde(default = "default_p2p_payment_correction_rate")]
2729    pub payment_correction_rate: f64,
2730}
2731
2732fn default_p2p_late_payment_rate() -> f64 {
2733    0.15
2734}
2735
2736fn default_p2p_partial_payment_rate() -> f64 {
2737    0.05
2738}
2739
2740fn default_p2p_payment_correction_rate() -> f64 {
2741    0.02
2742}
2743
2744impl Default for P2PPaymentBehaviorConfig {
2745    fn default() -> Self {
2746        Self {
2747            late_payment_rate: default_p2p_late_payment_rate(),
2748            late_payment_days_distribution: LatePaymentDaysDistribution::default(),
2749            partial_payment_rate: default_p2p_partial_payment_rate(),
2750            payment_correction_rate: default_p2p_payment_correction_rate(),
2751        }
2752    }
2753}
2754
2755/// Distribution of late payment days for P2P.
2756#[derive(Debug, Clone, Serialize, Deserialize)]
2757pub struct LatePaymentDaysDistribution {
2758    /// 1-7 days late (slightly late)
2759    #[serde(default = "default_slightly_late")]
2760    pub slightly_late_1_to_7: f64,
2761    /// 8-14 days late
2762    #[serde(default = "default_late_8_14")]
2763    pub late_8_to_14: f64,
2764    /// 15-30 days late (very late)
2765    #[serde(default = "default_very_late")]
2766    pub very_late_15_to_30: f64,
2767    /// 31-60 days late (severely late)
2768    #[serde(default = "default_severely_late")]
2769    pub severely_late_31_to_60: f64,
2770    /// Over 60 days late (extremely late)
2771    #[serde(default = "default_extremely_late")]
2772    pub extremely_late_over_60: f64,
2773}
2774
2775fn default_slightly_late() -> f64 {
2776    0.50
2777}
2778
2779fn default_late_8_14() -> f64 {
2780    0.25
2781}
2782
2783fn default_very_late() -> f64 {
2784    0.15
2785}
2786
2787fn default_severely_late() -> f64 {
2788    0.07
2789}
2790
2791fn default_extremely_late() -> f64 {
2792    0.03
2793}
2794
2795impl Default for LatePaymentDaysDistribution {
2796    fn default() -> Self {
2797        Self {
2798            slightly_late_1_to_7: default_slightly_late(),
2799            late_8_to_14: default_late_8_14(),
2800            very_late_15_to_30: default_very_late(),
2801            severely_late_31_to_60: default_severely_late(),
2802            extremely_late_over_60: default_extremely_late(),
2803        }
2804    }
2805}
2806
2807/// O2C (Order-to-Cash) flow configuration.
2808#[derive(Debug, Clone, Serialize, Deserialize)]
2809pub struct O2CFlowConfig {
2810    /// Enable O2C document flow generation
2811    #[serde(default = "default_true")]
2812    pub enabled: bool,
2813    /// Credit check failure rate
2814    #[serde(default = "default_credit_check_failure_rate")]
2815    pub credit_check_failure_rate: f64,
2816    /// Rate of partial shipments
2817    #[serde(default = "default_partial_shipment_rate")]
2818    pub partial_shipment_rate: f64,
2819    /// Rate of returns
2820    #[serde(default = "default_return_rate")]
2821    pub return_rate: f64,
2822    /// Bad debt write-off rate
2823    #[serde(default = "default_bad_debt_rate")]
2824    pub bad_debt_rate: f64,
2825    /// Average days from SO to delivery
2826    #[serde(default = "default_so_to_delivery_days")]
2827    pub average_so_to_delivery_days: u32,
2828    /// Average days from delivery to invoice
2829    #[serde(default = "default_delivery_to_invoice_days")]
2830    pub average_delivery_to_invoice_days: u32,
2831    /// Average days from invoice to receipt
2832    #[serde(default = "default_invoice_to_receipt_days")]
2833    pub average_invoice_to_receipt_days: u32,
2834    /// SO line count distribution
2835    #[serde(default)]
2836    pub line_count_distribution: DocumentLineCountDistribution,
2837    /// Cash discount configuration
2838    #[serde(default)]
2839    pub cash_discount: CashDiscountConfig,
2840    /// Payment behavior configuration
2841    #[serde(default)]
2842    pub payment_behavior: O2CPaymentBehaviorConfig,
2843}
2844
2845fn default_credit_check_failure_rate() -> f64 {
2846    0.02
2847}
2848
2849fn default_partial_shipment_rate() -> f64 {
2850    0.10
2851}
2852
2853fn default_return_rate() -> f64 {
2854    0.03
2855}
2856
2857fn default_bad_debt_rate() -> f64 {
2858    0.01
2859}
2860
2861fn default_so_to_delivery_days() -> u32 {
2862    7
2863}
2864
2865fn default_delivery_to_invoice_days() -> u32 {
2866    1
2867}
2868
2869fn default_invoice_to_receipt_days() -> u32 {
2870    45
2871}
2872
2873impl Default for O2CFlowConfig {
2874    fn default() -> Self {
2875        Self {
2876            enabled: true,
2877            credit_check_failure_rate: default_credit_check_failure_rate(),
2878            partial_shipment_rate: default_partial_shipment_rate(),
2879            return_rate: default_return_rate(),
2880            bad_debt_rate: default_bad_debt_rate(),
2881            average_so_to_delivery_days: default_so_to_delivery_days(),
2882            average_delivery_to_invoice_days: default_delivery_to_invoice_days(),
2883            average_invoice_to_receipt_days: default_invoice_to_receipt_days(),
2884            line_count_distribution: DocumentLineCountDistribution::default(),
2885            cash_discount: CashDiscountConfig::default(),
2886            payment_behavior: O2CPaymentBehaviorConfig::default(),
2887        }
2888    }
2889}
2890
2891// ============================================================================
2892// O2C Payment Behavior Configuration
2893// ============================================================================
2894
2895/// O2C payment behavior configuration.
2896#[derive(Debug, Clone, Serialize, Deserialize, Default)]
2897pub struct O2CPaymentBehaviorConfig {
2898    /// Dunning (Mahnung) configuration
2899    #[serde(default)]
2900    pub dunning: DunningConfig,
2901    /// Partial payment configuration
2902    #[serde(default)]
2903    pub partial_payments: PartialPaymentConfig,
2904    /// Short payment configuration (unauthorized deductions)
2905    #[serde(default)]
2906    pub short_payments: ShortPaymentConfig,
2907    /// On-account payment configuration (unapplied payments)
2908    #[serde(default)]
2909    pub on_account_payments: OnAccountPaymentConfig,
2910    /// Payment correction configuration (NSF, chargebacks)
2911    #[serde(default)]
2912    pub payment_corrections: PaymentCorrectionConfig,
2913}
2914
2915/// Dunning (Mahnungen) configuration for AR collections.
2916#[derive(Debug, Clone, Serialize, Deserialize)]
2917pub struct DunningConfig {
2918    /// Enable dunning process
2919    #[serde(default)]
2920    pub enabled: bool,
2921    /// Days overdue for level 1 dunning (1st reminder)
2922    #[serde(default = "default_dunning_level_1_days")]
2923    pub level_1_days_overdue: u32,
2924    /// Days overdue for level 2 dunning (2nd reminder)
2925    #[serde(default = "default_dunning_level_2_days")]
2926    pub level_2_days_overdue: u32,
2927    /// Days overdue for level 3 dunning (final notice)
2928    #[serde(default = "default_dunning_level_3_days")]
2929    pub level_3_days_overdue: u32,
2930    /// Days overdue for collection handover
2931    #[serde(default = "default_collection_days")]
2932    pub collection_days_overdue: u32,
2933    /// Payment rates after each dunning level
2934    #[serde(default)]
2935    pub payment_after_dunning_rates: DunningPaymentRates,
2936    /// Rate of invoices blocked from dunning (disputes)
2937    #[serde(default = "default_dunning_block_rate")]
2938    pub dunning_block_rate: f64,
2939    /// Interest rate per year for overdue amounts
2940    #[serde(default = "default_dunning_interest_rate")]
2941    pub interest_rate_per_year: f64,
2942    /// Fixed dunning charge per letter
2943    #[serde(default = "default_dunning_charge")]
2944    pub dunning_charge: f64,
2945}
2946
2947fn default_dunning_level_1_days() -> u32 {
2948    14
2949}
2950
2951fn default_dunning_level_2_days() -> u32 {
2952    28
2953}
2954
2955fn default_dunning_level_3_days() -> u32 {
2956    42
2957}
2958
2959fn default_collection_days() -> u32 {
2960    60
2961}
2962
2963fn default_dunning_block_rate() -> f64 {
2964    0.05
2965}
2966
2967fn default_dunning_interest_rate() -> f64 {
2968    0.09
2969}
2970
2971fn default_dunning_charge() -> f64 {
2972    25.0
2973}
2974
2975impl Default for DunningConfig {
2976    fn default() -> Self {
2977        Self {
2978            enabled: false,
2979            level_1_days_overdue: default_dunning_level_1_days(),
2980            level_2_days_overdue: default_dunning_level_2_days(),
2981            level_3_days_overdue: default_dunning_level_3_days(),
2982            collection_days_overdue: default_collection_days(),
2983            payment_after_dunning_rates: DunningPaymentRates::default(),
2984            dunning_block_rate: default_dunning_block_rate(),
2985            interest_rate_per_year: default_dunning_interest_rate(),
2986            dunning_charge: default_dunning_charge(),
2987        }
2988    }
2989}
2990
2991/// Payment rates after each dunning level.
2992#[derive(Debug, Clone, Serialize, Deserialize)]
2993pub struct DunningPaymentRates {
2994    /// Rate that pays after level 1 reminder
2995    #[serde(default = "default_after_level_1")]
2996    pub after_level_1: f64,
2997    /// Rate that pays after level 2 reminder
2998    #[serde(default = "default_after_level_2")]
2999    pub after_level_2: f64,
3000    /// Rate that pays after level 3 final notice
3001    #[serde(default = "default_after_level_3")]
3002    pub after_level_3: f64,
3003    /// Rate that pays during collection
3004    #[serde(default = "default_during_collection")]
3005    pub during_collection: f64,
3006    /// Rate that never pays (becomes bad debt)
3007    #[serde(default = "default_never_pay")]
3008    pub never_pay: f64,
3009}
3010
3011fn default_after_level_1() -> f64 {
3012    0.40
3013}
3014
3015fn default_after_level_2() -> f64 {
3016    0.30
3017}
3018
3019fn default_after_level_3() -> f64 {
3020    0.15
3021}
3022
3023fn default_during_collection() -> f64 {
3024    0.05
3025}
3026
3027fn default_never_pay() -> f64 {
3028    0.10
3029}
3030
3031impl Default for DunningPaymentRates {
3032    fn default() -> Self {
3033        Self {
3034            after_level_1: default_after_level_1(),
3035            after_level_2: default_after_level_2(),
3036            after_level_3: default_after_level_3(),
3037            during_collection: default_during_collection(),
3038            never_pay: default_never_pay(),
3039        }
3040    }
3041}
3042
3043/// Partial payment configuration.
3044#[derive(Debug, Clone, Serialize, Deserialize)]
3045pub struct PartialPaymentConfig {
3046    /// Rate of invoices paid partially
3047    #[serde(default = "default_partial_payment_rate")]
3048    pub rate: f64,
3049    /// Distribution of partial payment percentages
3050    #[serde(default)]
3051    pub percentage_distribution: PartialPaymentPercentageDistribution,
3052    /// Average days until remainder is paid
3053    #[serde(default = "default_avg_days_until_remainder")]
3054    pub avg_days_until_remainder: u32,
3055}
3056
3057fn default_partial_payment_rate() -> f64 {
3058    0.08
3059}
3060
3061fn default_avg_days_until_remainder() -> u32 {
3062    30
3063}
3064
3065impl Default for PartialPaymentConfig {
3066    fn default() -> Self {
3067        Self {
3068            rate: default_partial_payment_rate(),
3069            percentage_distribution: PartialPaymentPercentageDistribution::default(),
3070            avg_days_until_remainder: default_avg_days_until_remainder(),
3071        }
3072    }
3073}
3074
3075/// Distribution of partial payment percentages.
3076#[derive(Debug, Clone, Serialize, Deserialize)]
3077pub struct PartialPaymentPercentageDistribution {
3078    /// Pay 25% of invoice
3079    #[serde(default = "default_partial_25")]
3080    pub pay_25_percent: f64,
3081    /// Pay 50% of invoice
3082    #[serde(default = "default_partial_50")]
3083    pub pay_50_percent: f64,
3084    /// Pay 75% of invoice
3085    #[serde(default = "default_partial_75")]
3086    pub pay_75_percent: f64,
3087    /// Pay random percentage
3088    #[serde(default = "default_partial_random")]
3089    pub pay_random_percent: f64,
3090}
3091
3092fn default_partial_25() -> f64 {
3093    0.15
3094}
3095
3096fn default_partial_50() -> f64 {
3097    0.50
3098}
3099
3100fn default_partial_75() -> f64 {
3101    0.25
3102}
3103
3104fn default_partial_random() -> f64 {
3105    0.10
3106}
3107
3108impl Default for PartialPaymentPercentageDistribution {
3109    fn default() -> Self {
3110        Self {
3111            pay_25_percent: default_partial_25(),
3112            pay_50_percent: default_partial_50(),
3113            pay_75_percent: default_partial_75(),
3114            pay_random_percent: default_partial_random(),
3115        }
3116    }
3117}
3118
3119/// Short payment configuration (unauthorized deductions).
3120#[derive(Debug, Clone, Serialize, Deserialize)]
3121pub struct ShortPaymentConfig {
3122    /// Rate of payments that are short
3123    #[serde(default = "default_short_payment_rate")]
3124    pub rate: f64,
3125    /// Distribution of short payment reasons
3126    #[serde(default)]
3127    pub reason_distribution: ShortPaymentReasonDistribution,
3128    /// Maximum percentage that can be short
3129    #[serde(default = "default_max_short_percent")]
3130    pub max_short_percent: f64,
3131}
3132
3133fn default_short_payment_rate() -> f64 {
3134    0.03
3135}
3136
3137fn default_max_short_percent() -> f64 {
3138    0.10
3139}
3140
3141impl Default for ShortPaymentConfig {
3142    fn default() -> Self {
3143        Self {
3144            rate: default_short_payment_rate(),
3145            reason_distribution: ShortPaymentReasonDistribution::default(),
3146            max_short_percent: default_max_short_percent(),
3147        }
3148    }
3149}
3150
3151/// Distribution of short payment reasons.
3152#[derive(Debug, Clone, Serialize, Deserialize)]
3153pub struct ShortPaymentReasonDistribution {
3154    /// Pricing dispute
3155    #[serde(default = "default_pricing_dispute")]
3156    pub pricing_dispute: f64,
3157    /// Quality issue
3158    #[serde(default = "default_quality_issue")]
3159    pub quality_issue: f64,
3160    /// Quantity discrepancy
3161    #[serde(default = "default_quantity_discrepancy")]
3162    pub quantity_discrepancy: f64,
3163    /// Unauthorized deduction
3164    #[serde(default = "default_unauthorized_deduction")]
3165    pub unauthorized_deduction: f64,
3166    /// Early payment discount taken incorrectly
3167    #[serde(default = "default_incorrect_discount")]
3168    pub incorrect_discount: f64,
3169}
3170
3171fn default_pricing_dispute() -> f64 {
3172    0.30
3173}
3174
3175fn default_quality_issue() -> f64 {
3176    0.20
3177}
3178
3179fn default_quantity_discrepancy() -> f64 {
3180    0.20
3181}
3182
3183fn default_unauthorized_deduction() -> f64 {
3184    0.15
3185}
3186
3187fn default_incorrect_discount() -> f64 {
3188    0.15
3189}
3190
3191impl Default for ShortPaymentReasonDistribution {
3192    fn default() -> Self {
3193        Self {
3194            pricing_dispute: default_pricing_dispute(),
3195            quality_issue: default_quality_issue(),
3196            quantity_discrepancy: default_quantity_discrepancy(),
3197            unauthorized_deduction: default_unauthorized_deduction(),
3198            incorrect_discount: default_incorrect_discount(),
3199        }
3200    }
3201}
3202
3203/// On-account payment configuration (unapplied payments).
3204#[derive(Debug, Clone, Serialize, Deserialize)]
3205pub struct OnAccountPaymentConfig {
3206    /// Rate of payments that are on-account (unapplied)
3207    #[serde(default = "default_on_account_rate")]
3208    pub rate: f64,
3209    /// Average days until on-account payments are applied
3210    #[serde(default = "default_avg_days_until_applied")]
3211    pub avg_days_until_applied: u32,
3212}
3213
3214fn default_on_account_rate() -> f64 {
3215    0.02
3216}
3217
3218fn default_avg_days_until_applied() -> u32 {
3219    14
3220}
3221
3222impl Default for OnAccountPaymentConfig {
3223    fn default() -> Self {
3224        Self {
3225            rate: default_on_account_rate(),
3226            avg_days_until_applied: default_avg_days_until_applied(),
3227        }
3228    }
3229}
3230
3231/// Payment correction configuration.
3232#[derive(Debug, Clone, Serialize, Deserialize)]
3233pub struct PaymentCorrectionConfig {
3234    /// Rate of payments requiring correction
3235    #[serde(default = "default_payment_correction_rate")]
3236    pub rate: f64,
3237    /// Distribution of correction types
3238    #[serde(default)]
3239    pub type_distribution: PaymentCorrectionTypeDistribution,
3240}
3241
3242fn default_payment_correction_rate() -> f64 {
3243    0.02
3244}
3245
3246impl Default for PaymentCorrectionConfig {
3247    fn default() -> Self {
3248        Self {
3249            rate: default_payment_correction_rate(),
3250            type_distribution: PaymentCorrectionTypeDistribution::default(),
3251        }
3252    }
3253}
3254
3255/// Distribution of payment correction types.
3256#[derive(Debug, Clone, Serialize, Deserialize)]
3257pub struct PaymentCorrectionTypeDistribution {
3258    /// NSF (Non-sufficient funds) / bounced check
3259    #[serde(default = "default_nsf_rate")]
3260    pub nsf: f64,
3261    /// Chargeback
3262    #[serde(default = "default_chargeback_rate")]
3263    pub chargeback: f64,
3264    /// Wrong amount applied
3265    #[serde(default = "default_wrong_amount_rate")]
3266    pub wrong_amount: f64,
3267    /// Wrong customer applied
3268    #[serde(default = "default_wrong_customer_rate")]
3269    pub wrong_customer: f64,
3270    /// Duplicate payment
3271    #[serde(default = "default_duplicate_payment_rate")]
3272    pub duplicate_payment: f64,
3273}
3274
3275fn default_nsf_rate() -> f64 {
3276    0.30
3277}
3278
3279fn default_chargeback_rate() -> f64 {
3280    0.20
3281}
3282
3283fn default_wrong_amount_rate() -> f64 {
3284    0.20
3285}
3286
3287fn default_wrong_customer_rate() -> f64 {
3288    0.15
3289}
3290
3291fn default_duplicate_payment_rate() -> f64 {
3292    0.15
3293}
3294
3295impl Default for PaymentCorrectionTypeDistribution {
3296    fn default() -> Self {
3297        Self {
3298            nsf: default_nsf_rate(),
3299            chargeback: default_chargeback_rate(),
3300            wrong_amount: default_wrong_amount_rate(),
3301            wrong_customer: default_wrong_customer_rate(),
3302            duplicate_payment: default_duplicate_payment_rate(),
3303        }
3304    }
3305}
3306
3307/// Document line count distribution.
3308#[derive(Debug, Clone, Serialize, Deserialize)]
3309pub struct DocumentLineCountDistribution {
3310    /// Minimum number of lines
3311    #[serde(default = "default_min_lines")]
3312    pub min_lines: u32,
3313    /// Maximum number of lines
3314    #[serde(default = "default_max_lines")]
3315    pub max_lines: u32,
3316    /// Most common line count (mode)
3317    #[serde(default = "default_mode_lines")]
3318    pub mode_lines: u32,
3319}
3320
3321fn default_min_lines() -> u32 {
3322    1
3323}
3324
3325fn default_max_lines() -> u32 {
3326    20
3327}
3328
3329fn default_mode_lines() -> u32 {
3330    3
3331}
3332
3333impl Default for DocumentLineCountDistribution {
3334    fn default() -> Self {
3335        Self {
3336            min_lines: default_min_lines(),
3337            max_lines: default_max_lines(),
3338            mode_lines: default_mode_lines(),
3339        }
3340    }
3341}
3342
3343/// Cash discount configuration.
3344#[derive(Debug, Clone, Serialize, Deserialize)]
3345pub struct CashDiscountConfig {
3346    /// Percentage of invoices eligible for cash discount
3347    #[serde(default = "default_discount_eligible_rate")]
3348    pub eligible_rate: f64,
3349    /// Rate at which customers take the discount
3350    #[serde(default = "default_discount_taken_rate")]
3351    pub taken_rate: f64,
3352    /// Standard discount percentage
3353    #[serde(default = "default_discount_percent")]
3354    pub discount_percent: f64,
3355    /// Days within which discount must be taken
3356    #[serde(default = "default_discount_days")]
3357    pub discount_days: u32,
3358}
3359
3360fn default_discount_eligible_rate() -> f64 {
3361    0.30
3362}
3363
3364fn default_discount_taken_rate() -> f64 {
3365    0.60
3366}
3367
3368fn default_discount_percent() -> f64 {
3369    0.02
3370}
3371
3372fn default_discount_days() -> u32 {
3373    10
3374}
3375
3376impl Default for CashDiscountConfig {
3377    fn default() -> Self {
3378        Self {
3379            eligible_rate: default_discount_eligible_rate(),
3380            taken_rate: default_discount_taken_rate(),
3381            discount_percent: default_discount_percent(),
3382            discount_days: default_discount_days(),
3383        }
3384    }
3385}
3386
3387// ============================================================================
3388// Intercompany Configuration
3389// ============================================================================
3390
3391/// Intercompany transaction configuration.
3392#[derive(Debug, Clone, Serialize, Deserialize)]
3393pub struct IntercompanyConfig {
3394    /// Enable intercompany transaction generation
3395    #[serde(default)]
3396    pub enabled: bool,
3397    /// Rate of transactions that are intercompany
3398    #[serde(default = "default_ic_transaction_rate")]
3399    pub ic_transaction_rate: f64,
3400    /// Transfer pricing method
3401    #[serde(default)]
3402    pub transfer_pricing_method: TransferPricingMethod,
3403    /// Transfer pricing markup percentage (for cost-plus)
3404    #[serde(default = "default_markup_percent")]
3405    pub markup_percent: f64,
3406    /// Generate matched IC pairs (offsetting entries)
3407    #[serde(default = "default_true")]
3408    pub generate_matched_pairs: bool,
3409    /// IC transaction type distribution
3410    #[serde(default)]
3411    pub transaction_type_distribution: ICTransactionTypeDistribution,
3412    /// Generate elimination entries for consolidation
3413    #[serde(default)]
3414    pub generate_eliminations: bool,
3415}
3416
3417fn default_ic_transaction_rate() -> f64 {
3418    0.15
3419}
3420
3421fn default_markup_percent() -> f64 {
3422    0.05
3423}
3424
3425impl Default for IntercompanyConfig {
3426    fn default() -> Self {
3427        Self {
3428            enabled: false,
3429            ic_transaction_rate: default_ic_transaction_rate(),
3430            transfer_pricing_method: TransferPricingMethod::default(),
3431            markup_percent: default_markup_percent(),
3432            generate_matched_pairs: true,
3433            transaction_type_distribution: ICTransactionTypeDistribution::default(),
3434            generate_eliminations: false,
3435        }
3436    }
3437}
3438
3439/// Transfer pricing method.
3440#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
3441#[serde(rename_all = "snake_case")]
3442pub enum TransferPricingMethod {
3443    /// Cost plus a markup
3444    #[default]
3445    CostPlus,
3446    /// Comparable uncontrolled price
3447    ComparableUncontrolled,
3448    /// Resale price method
3449    ResalePrice,
3450    /// Transactional net margin method
3451    TransactionalNetMargin,
3452    /// Profit split method
3453    ProfitSplit,
3454}
3455
3456/// IC transaction type distribution.
3457#[derive(Debug, Clone, Serialize, Deserialize)]
3458pub struct ICTransactionTypeDistribution {
3459    /// Goods sales between entities
3460    pub goods_sale: f64,
3461    /// Services provided
3462    pub service_provided: f64,
3463    /// Intercompany loans
3464    pub loan: f64,
3465    /// Dividends
3466    pub dividend: f64,
3467    /// Management fees
3468    pub management_fee: f64,
3469    /// Royalties
3470    pub royalty: f64,
3471    /// Cost sharing
3472    pub cost_sharing: f64,
3473}
3474
3475impl Default for ICTransactionTypeDistribution {
3476    fn default() -> Self {
3477        Self {
3478            goods_sale: 0.35,
3479            service_provided: 0.20,
3480            loan: 0.10,
3481            dividend: 0.05,
3482            management_fee: 0.15,
3483            royalty: 0.10,
3484            cost_sharing: 0.05,
3485        }
3486    }
3487}
3488
3489// ============================================================================
3490// Balance Configuration
3491// ============================================================================
3492
3493/// Balance and trial balance configuration.
3494#[derive(Debug, Clone, Serialize, Deserialize)]
3495pub struct BalanceConfig {
3496    /// Generate opening balances
3497    #[serde(default)]
3498    pub generate_opening_balances: bool,
3499    /// Generate trial balances
3500    #[serde(default = "default_true")]
3501    pub generate_trial_balances: bool,
3502    /// Target gross margin (for revenue/COGS coherence)
3503    #[serde(default = "default_gross_margin")]
3504    pub target_gross_margin: f64,
3505    /// Target DSO (Days Sales Outstanding)
3506    #[serde(default = "default_dso")]
3507    pub target_dso_days: u32,
3508    /// Target DPO (Days Payable Outstanding)
3509    #[serde(default = "default_dpo")]
3510    pub target_dpo_days: u32,
3511    /// Target current ratio
3512    #[serde(default = "default_current_ratio")]
3513    pub target_current_ratio: f64,
3514    /// Target debt-to-equity ratio
3515    #[serde(default = "default_debt_equity")]
3516    pub target_debt_to_equity: f64,
3517    /// Validate balance sheet equation (A = L + E)
3518    #[serde(default = "default_true")]
3519    pub validate_balance_equation: bool,
3520    /// Reconcile subledgers to GL control accounts
3521    #[serde(default = "default_true")]
3522    pub reconcile_subledgers: bool,
3523}
3524
3525fn default_gross_margin() -> f64 {
3526    0.35
3527}
3528
3529fn default_dso() -> u32 {
3530    45
3531}
3532
3533fn default_dpo() -> u32 {
3534    30
3535}
3536
3537fn default_current_ratio() -> f64 {
3538    1.5
3539}
3540
3541fn default_debt_equity() -> f64 {
3542    0.5
3543}
3544
3545impl Default for BalanceConfig {
3546    fn default() -> Self {
3547        Self {
3548            generate_opening_balances: false,
3549            generate_trial_balances: true,
3550            target_gross_margin: default_gross_margin(),
3551            target_dso_days: default_dso(),
3552            target_dpo_days: default_dpo(),
3553            target_current_ratio: default_current_ratio(),
3554            target_debt_to_equity: default_debt_equity(),
3555            validate_balance_equation: true,
3556            reconcile_subledgers: true,
3557        }
3558    }
3559}
3560
3561// ==========================================================================
3562// OCPM (Object-Centric Process Mining) Configuration
3563// ==========================================================================
3564
3565/// OCPM (Object-Centric Process Mining) configuration.
3566///
3567/// Controls generation of OCEL 2.0 compatible event logs with
3568/// many-to-many event-to-object relationships.
3569#[derive(Debug, Clone, Serialize, Deserialize)]
3570pub struct OcpmConfig {
3571    /// Enable OCPM event log generation
3572    #[serde(default)]
3573    pub enabled: bool,
3574
3575    /// Generate lifecycle events (Start/Complete pairs vs atomic events)
3576    #[serde(default = "default_true")]
3577    pub generate_lifecycle_events: bool,
3578
3579    /// Include object-to-object relationships in output
3580    #[serde(default = "default_true")]
3581    pub include_object_relationships: bool,
3582
3583    /// Compute and export process variants
3584    #[serde(default = "default_true")]
3585    pub compute_variants: bool,
3586
3587    /// Maximum variants to track (0 = unlimited)
3588    #[serde(default)]
3589    pub max_variants: usize,
3590
3591    /// P2P process configuration
3592    #[serde(default)]
3593    pub p2p_process: OcpmProcessConfig,
3594
3595    /// O2C process configuration
3596    #[serde(default)]
3597    pub o2c_process: OcpmProcessConfig,
3598
3599    /// Output format configuration
3600    #[serde(default)]
3601    pub output: OcpmOutputConfig,
3602}
3603
3604impl Default for OcpmConfig {
3605    fn default() -> Self {
3606        Self {
3607            enabled: false,
3608            generate_lifecycle_events: true,
3609            include_object_relationships: true,
3610            compute_variants: true,
3611            max_variants: 0,
3612            p2p_process: OcpmProcessConfig::default(),
3613            o2c_process: OcpmProcessConfig::default(),
3614            output: OcpmOutputConfig::default(),
3615        }
3616    }
3617}
3618
3619/// Process-specific OCPM configuration.
3620#[derive(Debug, Clone, Serialize, Deserialize)]
3621pub struct OcpmProcessConfig {
3622    /// Rework probability (0.0-1.0)
3623    #[serde(default = "default_rework_probability")]
3624    pub rework_probability: f64,
3625
3626    /// Skip step probability (0.0-1.0)
3627    #[serde(default = "default_skip_probability")]
3628    pub skip_step_probability: f64,
3629
3630    /// Out-of-order step probability (0.0-1.0)
3631    #[serde(default = "default_out_of_order_probability")]
3632    pub out_of_order_probability: f64,
3633}
3634
3635fn default_rework_probability() -> f64 {
3636    0.05
3637}
3638
3639fn default_skip_probability() -> f64 {
3640    0.02
3641}
3642
3643fn default_out_of_order_probability() -> f64 {
3644    0.03
3645}
3646
3647impl Default for OcpmProcessConfig {
3648    fn default() -> Self {
3649        Self {
3650            rework_probability: default_rework_probability(),
3651            skip_step_probability: default_skip_probability(),
3652            out_of_order_probability: default_out_of_order_probability(),
3653        }
3654    }
3655}
3656
3657/// OCPM output format configuration.
3658#[derive(Debug, Clone, Serialize, Deserialize)]
3659pub struct OcpmOutputConfig {
3660    /// Export OCEL 2.0 JSON format
3661    #[serde(default = "default_true")]
3662    pub ocel_json: bool,
3663
3664    /// Export OCEL 2.0 XML format
3665    #[serde(default)]
3666    pub ocel_xml: bool,
3667
3668    /// Export XES 2.0 XML format (IEEE standard for process mining tools)
3669    #[serde(default)]
3670    pub xes: bool,
3671
3672    /// Include lifecycle transitions in XES output (start/complete pairs)
3673    #[serde(default = "default_true")]
3674    pub xes_include_lifecycle: bool,
3675
3676    /// Include resource attributes in XES output
3677    #[serde(default = "default_true")]
3678    pub xes_include_resources: bool,
3679
3680    /// Export flattened CSV for each object type
3681    #[serde(default = "default_true")]
3682    pub flattened_csv: bool,
3683
3684    /// Export event-object relationship table
3685    #[serde(default = "default_true")]
3686    pub event_object_csv: bool,
3687
3688    /// Export object-object relationship table
3689    #[serde(default = "default_true")]
3690    pub object_relationship_csv: bool,
3691
3692    /// Export process variants summary
3693    #[serde(default = "default_true")]
3694    pub variants_csv: bool,
3695
3696    /// Export reference process models (canonical P2P, O2C, R2R)
3697    #[serde(default)]
3698    pub export_reference_models: bool,
3699}
3700
3701impl Default for OcpmOutputConfig {
3702    fn default() -> Self {
3703        Self {
3704            ocel_json: true,
3705            ocel_xml: false,
3706            xes: false,
3707            xes_include_lifecycle: true,
3708            xes_include_resources: true,
3709            flattened_csv: true,
3710            event_object_csv: true,
3711            object_relationship_csv: true,
3712            variants_csv: true,
3713            export_reference_models: false,
3714        }
3715    }
3716}
3717
3718/// Audit engagement and workpaper generation configuration.
3719#[derive(Debug, Clone, Serialize, Deserialize)]
3720pub struct AuditGenerationConfig {
3721    /// Enable audit engagement generation
3722    #[serde(default)]
3723    pub enabled: bool,
3724
3725    /// Generate engagement documents and workpapers
3726    #[serde(default = "default_true")]
3727    pub generate_workpapers: bool,
3728
3729    /// Default engagement type distribution
3730    #[serde(default)]
3731    pub engagement_types: AuditEngagementTypesConfig,
3732
3733    /// Workpaper configuration
3734    #[serde(default)]
3735    pub workpapers: WorkpaperConfig,
3736
3737    /// Team configuration
3738    #[serde(default)]
3739    pub team: AuditTeamConfig,
3740
3741    /// Review workflow configuration
3742    #[serde(default)]
3743    pub review: ReviewWorkflowConfig,
3744}
3745
3746impl Default for AuditGenerationConfig {
3747    fn default() -> Self {
3748        Self {
3749            enabled: false,
3750            generate_workpapers: true,
3751            engagement_types: AuditEngagementTypesConfig::default(),
3752            workpapers: WorkpaperConfig::default(),
3753            team: AuditTeamConfig::default(),
3754            review: ReviewWorkflowConfig::default(),
3755        }
3756    }
3757}
3758
3759/// Engagement type distribution configuration.
3760#[derive(Debug, Clone, Serialize, Deserialize)]
3761pub struct AuditEngagementTypesConfig {
3762    /// Financial statement audit probability
3763    #[serde(default = "default_financial_audit_prob")]
3764    pub financial_statement: f64,
3765    /// SOX/ICFR audit probability
3766    #[serde(default = "default_sox_audit_prob")]
3767    pub sox_icfr: f64,
3768    /// Integrated audit probability
3769    #[serde(default = "default_integrated_audit_prob")]
3770    pub integrated: f64,
3771    /// Review engagement probability
3772    #[serde(default = "default_review_prob")]
3773    pub review: f64,
3774    /// Agreed-upon procedures probability
3775    #[serde(default = "default_aup_prob")]
3776    pub agreed_upon_procedures: f64,
3777}
3778
3779fn default_financial_audit_prob() -> f64 {
3780    0.40
3781}
3782fn default_sox_audit_prob() -> f64 {
3783    0.20
3784}
3785fn default_integrated_audit_prob() -> f64 {
3786    0.25
3787}
3788fn default_review_prob() -> f64 {
3789    0.10
3790}
3791fn default_aup_prob() -> f64 {
3792    0.05
3793}
3794
3795impl Default for AuditEngagementTypesConfig {
3796    fn default() -> Self {
3797        Self {
3798            financial_statement: default_financial_audit_prob(),
3799            sox_icfr: default_sox_audit_prob(),
3800            integrated: default_integrated_audit_prob(),
3801            review: default_review_prob(),
3802            agreed_upon_procedures: default_aup_prob(),
3803        }
3804    }
3805}
3806
3807/// Workpaper generation configuration.
3808#[derive(Debug, Clone, Serialize, Deserialize)]
3809pub struct WorkpaperConfig {
3810    /// Average workpapers per engagement phase
3811    #[serde(default = "default_workpapers_per_phase")]
3812    pub average_per_phase: usize,
3813
3814    /// Include ISA compliance references
3815    #[serde(default = "default_true")]
3816    pub include_isa_references: bool,
3817
3818    /// Generate sample details
3819    #[serde(default = "default_true")]
3820    pub include_sample_details: bool,
3821
3822    /// Include cross-references between workpapers
3823    #[serde(default = "default_true")]
3824    pub include_cross_references: bool,
3825
3826    /// Sampling configuration
3827    #[serde(default)]
3828    pub sampling: SamplingConfig,
3829}
3830
3831fn default_workpapers_per_phase() -> usize {
3832    5
3833}
3834
3835impl Default for WorkpaperConfig {
3836    fn default() -> Self {
3837        Self {
3838            average_per_phase: default_workpapers_per_phase(),
3839            include_isa_references: true,
3840            include_sample_details: true,
3841            include_cross_references: true,
3842            sampling: SamplingConfig::default(),
3843        }
3844    }
3845}
3846
3847/// Sampling method configuration.
3848#[derive(Debug, Clone, Serialize, Deserialize)]
3849pub struct SamplingConfig {
3850    /// Statistical sampling rate (0.0-1.0)
3851    #[serde(default = "default_statistical_rate")]
3852    pub statistical_rate: f64,
3853    /// Judgmental sampling rate (0.0-1.0)
3854    #[serde(default = "default_judgmental_rate")]
3855    pub judgmental_rate: f64,
3856    /// Haphazard sampling rate (0.0-1.0)
3857    #[serde(default = "default_haphazard_rate")]
3858    pub haphazard_rate: f64,
3859    /// 100% examination rate (0.0-1.0)
3860    #[serde(default = "default_complete_examination_rate")]
3861    pub complete_examination_rate: f64,
3862}
3863
3864fn default_statistical_rate() -> f64 {
3865    0.40
3866}
3867fn default_judgmental_rate() -> f64 {
3868    0.30
3869}
3870fn default_haphazard_rate() -> f64 {
3871    0.20
3872}
3873fn default_complete_examination_rate() -> f64 {
3874    0.10
3875}
3876
3877impl Default for SamplingConfig {
3878    fn default() -> Self {
3879        Self {
3880            statistical_rate: default_statistical_rate(),
3881            judgmental_rate: default_judgmental_rate(),
3882            haphazard_rate: default_haphazard_rate(),
3883            complete_examination_rate: default_complete_examination_rate(),
3884        }
3885    }
3886}
3887
3888/// Audit team configuration.
3889#[derive(Debug, Clone, Serialize, Deserialize)]
3890pub struct AuditTeamConfig {
3891    /// Minimum team size
3892    #[serde(default = "default_min_team_size")]
3893    pub min_team_size: usize,
3894    /// Maximum team size
3895    #[serde(default = "default_max_team_size")]
3896    pub max_team_size: usize,
3897    /// Probability of having a specialist on the team
3898    #[serde(default = "default_specialist_probability")]
3899    pub specialist_probability: f64,
3900}
3901
3902fn default_min_team_size() -> usize {
3903    3
3904}
3905fn default_max_team_size() -> usize {
3906    8
3907}
3908fn default_specialist_probability() -> f64 {
3909    0.30
3910}
3911
3912impl Default for AuditTeamConfig {
3913    fn default() -> Self {
3914        Self {
3915            min_team_size: default_min_team_size(),
3916            max_team_size: default_max_team_size(),
3917            specialist_probability: default_specialist_probability(),
3918        }
3919    }
3920}
3921
3922/// Review workflow configuration.
3923#[derive(Debug, Clone, Serialize, Deserialize)]
3924pub struct ReviewWorkflowConfig {
3925    /// Average days between preparer completion and first review
3926    #[serde(default = "default_review_delay_days")]
3927    pub average_review_delay_days: u32,
3928    /// Probability of review notes requiring rework
3929    #[serde(default = "default_rework_probability_review")]
3930    pub rework_probability: f64,
3931    /// Require partner sign-off for all workpapers
3932    #[serde(default = "default_true")]
3933    pub require_partner_signoff: bool,
3934}
3935
3936fn default_review_delay_days() -> u32 {
3937    2
3938}
3939fn default_rework_probability_review() -> f64 {
3940    0.15
3941}
3942
3943impl Default for ReviewWorkflowConfig {
3944    fn default() -> Self {
3945        Self {
3946            average_review_delay_days: default_review_delay_days(),
3947            rework_probability: default_rework_probability_review(),
3948            require_partner_signoff: true,
3949        }
3950    }
3951}
3952
3953// =============================================================================
3954// Data Quality Configuration
3955// =============================================================================
3956
3957/// Data quality variation settings for realistic flakiness injection.
3958#[derive(Debug, Clone, Serialize, Deserialize)]
3959pub struct DataQualitySchemaConfig {
3960    /// Enable data quality variations
3961    #[serde(default)]
3962    pub enabled: bool,
3963    /// Preset to use (overrides individual settings if set)
3964    #[serde(default)]
3965    pub preset: DataQualityPreset,
3966    /// Missing value injection settings
3967    #[serde(default)]
3968    pub missing_values: MissingValuesSchemaConfig,
3969    /// Typo injection settings
3970    #[serde(default)]
3971    pub typos: TypoSchemaConfig,
3972    /// Format variation settings
3973    #[serde(default)]
3974    pub format_variations: FormatVariationSchemaConfig,
3975    /// Duplicate injection settings
3976    #[serde(default)]
3977    pub duplicates: DuplicateSchemaConfig,
3978    /// Encoding issue settings
3979    #[serde(default)]
3980    pub encoding_issues: EncodingIssueSchemaConfig,
3981    /// Generate quality issue labels for ML training
3982    #[serde(default)]
3983    pub generate_labels: bool,
3984    /// Per-sink quality profiles (different settings for CSV vs JSON etc.)
3985    #[serde(default)]
3986    pub sink_profiles: SinkQualityProfiles,
3987}
3988
3989impl Default for DataQualitySchemaConfig {
3990    fn default() -> Self {
3991        Self {
3992            enabled: false,
3993            preset: DataQualityPreset::None,
3994            missing_values: MissingValuesSchemaConfig::default(),
3995            typos: TypoSchemaConfig::default(),
3996            format_variations: FormatVariationSchemaConfig::default(),
3997            duplicates: DuplicateSchemaConfig::default(),
3998            encoding_issues: EncodingIssueSchemaConfig::default(),
3999            generate_labels: true,
4000            sink_profiles: SinkQualityProfiles::default(),
4001        }
4002    }
4003}
4004
4005impl DataQualitySchemaConfig {
4006    /// Creates a config for a specific preset profile.
4007    pub fn with_preset(preset: DataQualityPreset) -> Self {
4008        let mut config = Self {
4009            preset,
4010            ..Default::default()
4011        };
4012        config.apply_preset();
4013        config
4014    }
4015
4016    /// Applies the preset settings to the individual configuration fields.
4017    /// Call this after deserializing if preset is not Custom or None.
4018    pub fn apply_preset(&mut self) {
4019        if !self.preset.overrides_settings() {
4020            return;
4021        }
4022
4023        self.enabled = true;
4024
4025        // Missing values
4026        self.missing_values.enabled = self.preset.missing_rate() > 0.0;
4027        self.missing_values.rate = self.preset.missing_rate();
4028
4029        // Typos
4030        self.typos.enabled = self.preset.typo_rate() > 0.0;
4031        self.typos.char_error_rate = self.preset.typo_rate();
4032
4033        // Duplicates
4034        self.duplicates.enabled = self.preset.duplicate_rate() > 0.0;
4035        self.duplicates.exact_duplicate_ratio = self.preset.duplicate_rate() * 0.4;
4036        self.duplicates.near_duplicate_ratio = self.preset.duplicate_rate() * 0.4;
4037        self.duplicates.fuzzy_duplicate_ratio = self.preset.duplicate_rate() * 0.2;
4038
4039        // Format variations
4040        self.format_variations.enabled = self.preset.format_variations_enabled();
4041
4042        // Encoding issues
4043        self.encoding_issues.enabled = self.preset.encoding_issues_enabled();
4044        self.encoding_issues.rate = self.preset.encoding_issue_rate();
4045
4046        // OCR errors for typos in legacy preset
4047        if self.preset.ocr_errors_enabled() {
4048            self.typos.type_weights.ocr_errors = 0.3;
4049        }
4050    }
4051
4052    /// Returns the effective missing value rate (considering preset).
4053    pub fn effective_missing_rate(&self) -> f64 {
4054        if self.preset.overrides_settings() {
4055            self.preset.missing_rate()
4056        } else {
4057            self.missing_values.rate
4058        }
4059    }
4060
4061    /// Returns the effective typo rate (considering preset).
4062    pub fn effective_typo_rate(&self) -> f64 {
4063        if self.preset.overrides_settings() {
4064            self.preset.typo_rate()
4065        } else {
4066            self.typos.char_error_rate
4067        }
4068    }
4069
4070    /// Returns the effective duplicate rate (considering preset).
4071    pub fn effective_duplicate_rate(&self) -> f64 {
4072        if self.preset.overrides_settings() {
4073            self.preset.duplicate_rate()
4074        } else {
4075            self.duplicates.exact_duplicate_ratio
4076                + self.duplicates.near_duplicate_ratio
4077                + self.duplicates.fuzzy_duplicate_ratio
4078        }
4079    }
4080
4081    /// Creates a clean profile config.
4082    pub fn clean() -> Self {
4083        Self::with_preset(DataQualityPreset::Clean)
4084    }
4085
4086    /// Creates a noisy profile config.
4087    pub fn noisy() -> Self {
4088        Self::with_preset(DataQualityPreset::Noisy)
4089    }
4090
4091    /// Creates a legacy profile config.
4092    pub fn legacy() -> Self {
4093        Self::with_preset(DataQualityPreset::Legacy)
4094    }
4095}
4096
4097/// Preset configurations for common data quality scenarios.
4098#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
4099#[serde(rename_all = "snake_case")]
4100pub enum DataQualityPreset {
4101    /// No data quality variations (clean data)
4102    #[default]
4103    None,
4104    /// Minimal variations (very clean data with rare issues)
4105    Minimal,
4106    /// Normal variations (realistic enterprise data quality)
4107    Normal,
4108    /// High variations (messy data for stress testing)
4109    High,
4110    /// Custom (use individual settings)
4111    Custom,
4112
4113    // ========================================
4114    // ML-Oriented Profiles (Phase 2.1)
4115    // ========================================
4116    /// Clean profile for ML training - minimal data quality issues
4117    /// Missing: 0.1%, Typos: 0.05%, Duplicates: 0%, Format: None
4118    Clean,
4119    /// Noisy profile simulating typical production data issues
4120    /// Missing: 5%, Typos: 2%, Duplicates: 1%, Format: Medium
4121    Noisy,
4122    /// Legacy profile simulating migrated/OCR'd historical data
4123    /// Missing: 10%, Typos: 5%, Duplicates: 3%, Format: Heavy + OCR
4124    Legacy,
4125}
4126
4127impl DataQualityPreset {
4128    /// Returns the missing value rate for this preset.
4129    pub fn missing_rate(&self) -> f64 {
4130        match self {
4131            DataQualityPreset::None => 0.0,
4132            DataQualityPreset::Minimal => 0.005,
4133            DataQualityPreset::Normal => 0.02,
4134            DataQualityPreset::High => 0.08,
4135            DataQualityPreset::Custom => 0.01, // Use config value
4136            DataQualityPreset::Clean => 0.001,
4137            DataQualityPreset::Noisy => 0.05,
4138            DataQualityPreset::Legacy => 0.10,
4139        }
4140    }
4141
4142    /// Returns the typo rate for this preset.
4143    pub fn typo_rate(&self) -> f64 {
4144        match self {
4145            DataQualityPreset::None => 0.0,
4146            DataQualityPreset::Minimal => 0.0005,
4147            DataQualityPreset::Normal => 0.002,
4148            DataQualityPreset::High => 0.01,
4149            DataQualityPreset::Custom => 0.001, // Use config value
4150            DataQualityPreset::Clean => 0.0005,
4151            DataQualityPreset::Noisy => 0.02,
4152            DataQualityPreset::Legacy => 0.05,
4153        }
4154    }
4155
4156    /// Returns the duplicate rate for this preset.
4157    pub fn duplicate_rate(&self) -> f64 {
4158        match self {
4159            DataQualityPreset::None => 0.0,
4160            DataQualityPreset::Minimal => 0.001,
4161            DataQualityPreset::Normal => 0.005,
4162            DataQualityPreset::High => 0.02,
4163            DataQualityPreset::Custom => 0.0, // Use config value
4164            DataQualityPreset::Clean => 0.0,
4165            DataQualityPreset::Noisy => 0.01,
4166            DataQualityPreset::Legacy => 0.03,
4167        }
4168    }
4169
4170    /// Returns whether format variations are enabled for this preset.
4171    pub fn format_variations_enabled(&self) -> bool {
4172        match self {
4173            DataQualityPreset::None | DataQualityPreset::Clean => false,
4174            DataQualityPreset::Minimal => true,
4175            DataQualityPreset::Normal => true,
4176            DataQualityPreset::High => true,
4177            DataQualityPreset::Custom => true,
4178            DataQualityPreset::Noisy => true,
4179            DataQualityPreset::Legacy => true,
4180        }
4181    }
4182
4183    /// Returns whether OCR-style errors are enabled for this preset.
4184    pub fn ocr_errors_enabled(&self) -> bool {
4185        matches!(self, DataQualityPreset::Legacy | DataQualityPreset::High)
4186    }
4187
4188    /// Returns whether encoding issues are enabled for this preset.
4189    pub fn encoding_issues_enabled(&self) -> bool {
4190        matches!(
4191            self,
4192            DataQualityPreset::Legacy | DataQualityPreset::High | DataQualityPreset::Noisy
4193        )
4194    }
4195
4196    /// Returns the encoding issue rate for this preset.
4197    pub fn encoding_issue_rate(&self) -> f64 {
4198        match self {
4199            DataQualityPreset::None | DataQualityPreset::Clean | DataQualityPreset::Minimal => 0.0,
4200            DataQualityPreset::Normal => 0.002,
4201            DataQualityPreset::High => 0.01,
4202            DataQualityPreset::Custom => 0.0,
4203            DataQualityPreset::Noisy => 0.005,
4204            DataQualityPreset::Legacy => 0.02,
4205        }
4206    }
4207
4208    /// Returns true if this preset overrides individual settings.
4209    pub fn overrides_settings(&self) -> bool {
4210        !matches!(self, DataQualityPreset::Custom | DataQualityPreset::None)
4211    }
4212
4213    /// Returns a human-readable description of this preset.
4214    pub fn description(&self) -> &'static str {
4215        match self {
4216            DataQualityPreset::None => "No data quality issues (pristine data)",
4217            DataQualityPreset::Minimal => "Very rare data quality issues",
4218            DataQualityPreset::Normal => "Realistic enterprise data quality",
4219            DataQualityPreset::High => "Messy data for stress testing",
4220            DataQualityPreset::Custom => "Custom settings from configuration",
4221            DataQualityPreset::Clean => "ML-ready clean data with minimal issues",
4222            DataQualityPreset::Noisy => "Typical production data with moderate issues",
4223            DataQualityPreset::Legacy => "Legacy/migrated data with heavy issues and OCR errors",
4224        }
4225    }
4226}
4227
4228/// Missing value injection configuration.
4229#[derive(Debug, Clone, Serialize, Deserialize)]
4230pub struct MissingValuesSchemaConfig {
4231    /// Enable missing value injection
4232    #[serde(default)]
4233    pub enabled: bool,
4234    /// Global missing rate (0.0 to 1.0)
4235    #[serde(default = "default_missing_rate")]
4236    pub rate: f64,
4237    /// Missing value strategy
4238    #[serde(default)]
4239    pub strategy: MissingValueStrategy,
4240    /// Field-specific rates (field name -> rate)
4241    #[serde(default)]
4242    pub field_rates: std::collections::HashMap<String, f64>,
4243    /// Fields that should never have missing values
4244    #[serde(default)]
4245    pub protected_fields: Vec<String>,
4246}
4247
4248fn default_missing_rate() -> f64 {
4249    0.01
4250}
4251
4252impl Default for MissingValuesSchemaConfig {
4253    fn default() -> Self {
4254        Self {
4255            enabled: false,
4256            rate: default_missing_rate(),
4257            strategy: MissingValueStrategy::Mcar,
4258            field_rates: std::collections::HashMap::new(),
4259            protected_fields: vec![
4260                "document_id".to_string(),
4261                "company_code".to_string(),
4262                "posting_date".to_string(),
4263            ],
4264        }
4265    }
4266}
4267
4268/// Missing value strategy types.
4269#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
4270#[serde(rename_all = "snake_case")]
4271pub enum MissingValueStrategy {
4272    /// Missing Completely At Random - equal probability for all values
4273    #[default]
4274    Mcar,
4275    /// Missing At Random - depends on other observed values
4276    Mar,
4277    /// Missing Not At Random - depends on the value itself
4278    Mnar,
4279    /// Systematic - entire field groups missing together
4280    Systematic,
4281}
4282
4283/// Typo injection configuration.
4284#[derive(Debug, Clone, Serialize, Deserialize)]
4285pub struct TypoSchemaConfig {
4286    /// Enable typo injection
4287    #[serde(default)]
4288    pub enabled: bool,
4289    /// Character error rate (per character, not per field)
4290    #[serde(default = "default_typo_rate")]
4291    pub char_error_rate: f64,
4292    /// Typo type weights
4293    #[serde(default)]
4294    pub type_weights: TypoTypeWeights,
4295    /// Fields that should never have typos
4296    #[serde(default)]
4297    pub protected_fields: Vec<String>,
4298}
4299
4300fn default_typo_rate() -> f64 {
4301    0.001
4302}
4303
4304impl Default for TypoSchemaConfig {
4305    fn default() -> Self {
4306        Self {
4307            enabled: false,
4308            char_error_rate: default_typo_rate(),
4309            type_weights: TypoTypeWeights::default(),
4310            protected_fields: vec![
4311                "document_id".to_string(),
4312                "gl_account".to_string(),
4313                "company_code".to_string(),
4314            ],
4315        }
4316    }
4317}
4318
4319/// Weights for different typo types.
4320#[derive(Debug, Clone, Serialize, Deserialize)]
4321pub struct TypoTypeWeights {
4322    /// Keyboard-adjacent substitution (e.g., 'a' -> 's')
4323    #[serde(default = "default_substitution_weight")]
4324    pub substitution: f64,
4325    /// Adjacent character transposition (e.g., 'ab' -> 'ba')
4326    #[serde(default = "default_transposition_weight")]
4327    pub transposition: f64,
4328    /// Character insertion
4329    #[serde(default = "default_insertion_weight")]
4330    pub insertion: f64,
4331    /// Character deletion
4332    #[serde(default = "default_deletion_weight")]
4333    pub deletion: f64,
4334    /// OCR-style errors (e.g., '0' -> 'O')
4335    #[serde(default = "default_ocr_weight")]
4336    pub ocr_errors: f64,
4337    /// Homophone substitution (e.g., 'their' -> 'there')
4338    #[serde(default = "default_homophone_weight")]
4339    pub homophones: f64,
4340}
4341
4342fn default_substitution_weight() -> f64 {
4343    0.35
4344}
4345fn default_transposition_weight() -> f64 {
4346    0.25
4347}
4348fn default_insertion_weight() -> f64 {
4349    0.10
4350}
4351fn default_deletion_weight() -> f64 {
4352    0.15
4353}
4354fn default_ocr_weight() -> f64 {
4355    0.10
4356}
4357fn default_homophone_weight() -> f64 {
4358    0.05
4359}
4360
4361impl Default for TypoTypeWeights {
4362    fn default() -> Self {
4363        Self {
4364            substitution: default_substitution_weight(),
4365            transposition: default_transposition_weight(),
4366            insertion: default_insertion_weight(),
4367            deletion: default_deletion_weight(),
4368            ocr_errors: default_ocr_weight(),
4369            homophones: default_homophone_weight(),
4370        }
4371    }
4372}
4373
4374/// Format variation configuration.
4375#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4376pub struct FormatVariationSchemaConfig {
4377    /// Enable format variations
4378    #[serde(default)]
4379    pub enabled: bool,
4380    /// Date format variation settings
4381    #[serde(default)]
4382    pub dates: DateFormatVariationConfig,
4383    /// Amount format variation settings
4384    #[serde(default)]
4385    pub amounts: AmountFormatVariationConfig,
4386    /// Identifier format variation settings
4387    #[serde(default)]
4388    pub identifiers: IdentifierFormatVariationConfig,
4389}
4390
4391/// Date format variation configuration.
4392#[derive(Debug, Clone, Serialize, Deserialize)]
4393pub struct DateFormatVariationConfig {
4394    /// Enable date format variations
4395    #[serde(default)]
4396    pub enabled: bool,
4397    /// Overall variation rate
4398    #[serde(default = "default_date_variation_rate")]
4399    pub rate: f64,
4400    /// Include ISO format (2024-01-15)
4401    #[serde(default = "default_true")]
4402    pub iso_format: bool,
4403    /// Include US format (01/15/2024)
4404    #[serde(default)]
4405    pub us_format: bool,
4406    /// Include EU format (15.01.2024)
4407    #[serde(default)]
4408    pub eu_format: bool,
4409    /// Include long format (January 15, 2024)
4410    #[serde(default)]
4411    pub long_format: bool,
4412}
4413
4414fn default_date_variation_rate() -> f64 {
4415    0.05
4416}
4417
4418impl Default for DateFormatVariationConfig {
4419    fn default() -> Self {
4420        Self {
4421            enabled: false,
4422            rate: default_date_variation_rate(),
4423            iso_format: true,
4424            us_format: false,
4425            eu_format: false,
4426            long_format: false,
4427        }
4428    }
4429}
4430
4431/// Amount format variation configuration.
4432#[derive(Debug, Clone, Serialize, Deserialize)]
4433pub struct AmountFormatVariationConfig {
4434    /// Enable amount format variations
4435    #[serde(default)]
4436    pub enabled: bool,
4437    /// Overall variation rate
4438    #[serde(default = "default_amount_variation_rate")]
4439    pub rate: f64,
4440    /// Include US comma format (1,234.56)
4441    #[serde(default)]
4442    pub us_comma_format: bool,
4443    /// Include EU format (1.234,56)
4444    #[serde(default)]
4445    pub eu_format: bool,
4446    /// Include currency prefix ($1,234.56)
4447    #[serde(default)]
4448    pub currency_prefix: bool,
4449    /// Include accounting format with parentheses for negatives
4450    #[serde(default)]
4451    pub accounting_format: bool,
4452}
4453
4454fn default_amount_variation_rate() -> f64 {
4455    0.02
4456}
4457
4458impl Default for AmountFormatVariationConfig {
4459    fn default() -> Self {
4460        Self {
4461            enabled: false,
4462            rate: default_amount_variation_rate(),
4463            us_comma_format: false,
4464            eu_format: false,
4465            currency_prefix: false,
4466            accounting_format: false,
4467        }
4468    }
4469}
4470
4471/// Identifier format variation configuration.
4472#[derive(Debug, Clone, Serialize, Deserialize)]
4473pub struct IdentifierFormatVariationConfig {
4474    /// Enable identifier format variations
4475    #[serde(default)]
4476    pub enabled: bool,
4477    /// Overall variation rate
4478    #[serde(default = "default_identifier_variation_rate")]
4479    pub rate: f64,
4480    /// Case variations (uppercase, lowercase, mixed)
4481    #[serde(default)]
4482    pub case_variations: bool,
4483    /// Padding variations (leading zeros)
4484    #[serde(default)]
4485    pub padding_variations: bool,
4486    /// Separator variations (dash vs underscore)
4487    #[serde(default)]
4488    pub separator_variations: bool,
4489}
4490
4491fn default_identifier_variation_rate() -> f64 {
4492    0.02
4493}
4494
4495impl Default for IdentifierFormatVariationConfig {
4496    fn default() -> Self {
4497        Self {
4498            enabled: false,
4499            rate: default_identifier_variation_rate(),
4500            case_variations: false,
4501            padding_variations: false,
4502            separator_variations: false,
4503        }
4504    }
4505}
4506
4507/// Duplicate injection configuration.
4508#[derive(Debug, Clone, Serialize, Deserialize)]
4509pub struct DuplicateSchemaConfig {
4510    /// Enable duplicate injection
4511    #[serde(default)]
4512    pub enabled: bool,
4513    /// Overall duplicate rate
4514    #[serde(default = "default_duplicate_rate")]
4515    pub rate: f64,
4516    /// Exact duplicate proportion (out of duplicates)
4517    #[serde(default = "default_exact_duplicate_ratio")]
4518    pub exact_duplicate_ratio: f64,
4519    /// Near duplicate proportion (slight variations)
4520    #[serde(default = "default_near_duplicate_ratio")]
4521    pub near_duplicate_ratio: f64,
4522    /// Fuzzy duplicate proportion (typos in key fields)
4523    #[serde(default = "default_fuzzy_duplicate_ratio")]
4524    pub fuzzy_duplicate_ratio: f64,
4525    /// Maximum date offset for near/fuzzy duplicates (days)
4526    #[serde(default = "default_max_date_offset")]
4527    pub max_date_offset_days: u32,
4528    /// Maximum amount variance for near duplicates (fraction)
4529    #[serde(default = "default_max_amount_variance")]
4530    pub max_amount_variance: f64,
4531}
4532
4533fn default_duplicate_rate() -> f64 {
4534    0.005
4535}
4536fn default_exact_duplicate_ratio() -> f64 {
4537    0.4
4538}
4539fn default_near_duplicate_ratio() -> f64 {
4540    0.35
4541}
4542fn default_fuzzy_duplicate_ratio() -> f64 {
4543    0.25
4544}
4545fn default_max_date_offset() -> u32 {
4546    3
4547}
4548fn default_max_amount_variance() -> f64 {
4549    0.01
4550}
4551
4552impl Default for DuplicateSchemaConfig {
4553    fn default() -> Self {
4554        Self {
4555            enabled: false,
4556            rate: default_duplicate_rate(),
4557            exact_duplicate_ratio: default_exact_duplicate_ratio(),
4558            near_duplicate_ratio: default_near_duplicate_ratio(),
4559            fuzzy_duplicate_ratio: default_fuzzy_duplicate_ratio(),
4560            max_date_offset_days: default_max_date_offset(),
4561            max_amount_variance: default_max_amount_variance(),
4562        }
4563    }
4564}
4565
4566/// Encoding issue configuration.
4567#[derive(Debug, Clone, Serialize, Deserialize)]
4568pub struct EncodingIssueSchemaConfig {
4569    /// Enable encoding issue injection
4570    #[serde(default)]
4571    pub enabled: bool,
4572    /// Overall encoding issue rate
4573    #[serde(default = "default_encoding_rate")]
4574    pub rate: f64,
4575    /// Include mojibake (UTF-8/Latin-1 confusion)
4576    #[serde(default)]
4577    pub mojibake: bool,
4578    /// Include HTML entity corruption
4579    #[serde(default)]
4580    pub html_entities: bool,
4581    /// Include BOM issues
4582    #[serde(default)]
4583    pub bom_issues: bool,
4584}
4585
4586fn default_encoding_rate() -> f64 {
4587    0.001
4588}
4589
4590impl Default for EncodingIssueSchemaConfig {
4591    fn default() -> Self {
4592        Self {
4593            enabled: false,
4594            rate: default_encoding_rate(),
4595            mojibake: false,
4596            html_entities: false,
4597            bom_issues: false,
4598        }
4599    }
4600}
4601
4602/// Per-sink quality profiles for different output formats.
4603#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4604pub struct SinkQualityProfiles {
4605    /// CSV-specific quality settings
4606    #[serde(default)]
4607    pub csv: Option<SinkQualityOverride>,
4608    /// JSON-specific quality settings
4609    #[serde(default)]
4610    pub json: Option<SinkQualityOverride>,
4611    /// Parquet-specific quality settings
4612    #[serde(default)]
4613    pub parquet: Option<SinkQualityOverride>,
4614}
4615
4616/// Quality setting overrides for a specific sink type.
4617#[derive(Debug, Clone, Serialize, Deserialize)]
4618pub struct SinkQualityOverride {
4619    /// Override enabled state
4620    pub enabled: Option<bool>,
4621    /// Override missing value rate
4622    pub missing_rate: Option<f64>,
4623    /// Override typo rate
4624    pub typo_rate: Option<f64>,
4625    /// Override format variation rate
4626    pub format_variation_rate: Option<f64>,
4627    /// Override duplicate rate
4628    pub duplicate_rate: Option<f64>,
4629}
4630
4631// =============================================================================
4632// Accounting Standards Configuration
4633// =============================================================================
4634
4635/// Accounting standards framework configuration for generating standards-compliant data.
4636///
4637/// Supports US GAAP and IFRS frameworks with specific standards:
4638/// - ASC 606/IFRS 15: Revenue Recognition
4639/// - ASC 842/IFRS 16: Leases
4640/// - ASC 820/IFRS 13: Fair Value Measurement
4641/// - ASC 360/IAS 36: Impairment
4642#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4643pub struct AccountingStandardsConfig {
4644    /// Enable accounting standards generation
4645    #[serde(default)]
4646    pub enabled: bool,
4647
4648    /// Accounting framework to use
4649    #[serde(default)]
4650    pub framework: AccountingFrameworkConfig,
4651
4652    /// Revenue recognition configuration (ASC 606/IFRS 15)
4653    #[serde(default)]
4654    pub revenue_recognition: RevenueRecognitionConfig,
4655
4656    /// Lease accounting configuration (ASC 842/IFRS 16)
4657    #[serde(default)]
4658    pub leases: LeaseAccountingConfig,
4659
4660    /// Fair value measurement configuration (ASC 820/IFRS 13)
4661    #[serde(default)]
4662    pub fair_value: FairValueConfig,
4663
4664    /// Impairment testing configuration (ASC 360/IAS 36)
4665    #[serde(default)]
4666    pub impairment: ImpairmentConfig,
4667
4668    /// Generate framework differences for dual reporting
4669    #[serde(default)]
4670    pub generate_differences: bool,
4671}
4672
4673/// Accounting framework selection.
4674#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
4675#[serde(rename_all = "snake_case")]
4676pub enum AccountingFrameworkConfig {
4677    /// US Generally Accepted Accounting Principles
4678    #[default]
4679    UsGaap,
4680    /// International Financial Reporting Standards
4681    Ifrs,
4682    /// Generate data for both frameworks with reconciliation
4683    DualReporting,
4684}
4685
4686/// Revenue recognition configuration (ASC 606/IFRS 15).
4687#[derive(Debug, Clone, Serialize, Deserialize)]
4688pub struct RevenueRecognitionConfig {
4689    /// Enable revenue recognition generation
4690    #[serde(default)]
4691    pub enabled: bool,
4692
4693    /// Generate customer contracts
4694    #[serde(default = "default_true")]
4695    pub generate_contracts: bool,
4696
4697    /// Average number of performance obligations per contract
4698    #[serde(default = "default_avg_obligations")]
4699    pub avg_obligations_per_contract: f64,
4700
4701    /// Rate of contracts with variable consideration
4702    #[serde(default = "default_variable_consideration_rate")]
4703    pub variable_consideration_rate: f64,
4704
4705    /// Rate of over-time revenue recognition (vs point-in-time)
4706    #[serde(default = "default_over_time_rate")]
4707    pub over_time_recognition_rate: f64,
4708
4709    /// Number of contracts to generate
4710    #[serde(default = "default_contract_count")]
4711    pub contract_count: usize,
4712}
4713
4714fn default_avg_obligations() -> f64 {
4715    2.0
4716}
4717
4718fn default_variable_consideration_rate() -> f64 {
4719    0.15
4720}
4721
4722fn default_over_time_rate() -> f64 {
4723    0.30
4724}
4725
4726fn default_contract_count() -> usize {
4727    100
4728}
4729
4730impl Default for RevenueRecognitionConfig {
4731    fn default() -> Self {
4732        Self {
4733            enabled: false,
4734            generate_contracts: true,
4735            avg_obligations_per_contract: default_avg_obligations(),
4736            variable_consideration_rate: default_variable_consideration_rate(),
4737            over_time_recognition_rate: default_over_time_rate(),
4738            contract_count: default_contract_count(),
4739        }
4740    }
4741}
4742
4743/// Lease accounting configuration (ASC 842/IFRS 16).
4744#[derive(Debug, Clone, Serialize, Deserialize)]
4745pub struct LeaseAccountingConfig {
4746    /// Enable lease accounting generation
4747    #[serde(default)]
4748    pub enabled: bool,
4749
4750    /// Number of leases to generate
4751    #[serde(default = "default_lease_count")]
4752    pub lease_count: usize,
4753
4754    /// Percentage of finance leases (vs operating)
4755    #[serde(default = "default_finance_lease_pct")]
4756    pub finance_lease_percent: f64,
4757
4758    /// Average lease term in months
4759    #[serde(default = "default_avg_lease_term")]
4760    pub avg_lease_term_months: u32,
4761
4762    /// Generate amortization schedules
4763    #[serde(default = "default_true")]
4764    pub generate_amortization: bool,
4765
4766    /// Real estate lease percentage
4767    #[serde(default = "default_real_estate_pct")]
4768    pub real_estate_percent: f64,
4769}
4770
4771fn default_lease_count() -> usize {
4772    50
4773}
4774
4775fn default_finance_lease_pct() -> f64 {
4776    0.30
4777}
4778
4779fn default_avg_lease_term() -> u32 {
4780    60
4781}
4782
4783fn default_real_estate_pct() -> f64 {
4784    0.40
4785}
4786
4787impl Default for LeaseAccountingConfig {
4788    fn default() -> Self {
4789        Self {
4790            enabled: false,
4791            lease_count: default_lease_count(),
4792            finance_lease_percent: default_finance_lease_pct(),
4793            avg_lease_term_months: default_avg_lease_term(),
4794            generate_amortization: true,
4795            real_estate_percent: default_real_estate_pct(),
4796        }
4797    }
4798}
4799
4800/// Fair value measurement configuration (ASC 820/IFRS 13).
4801#[derive(Debug, Clone, Serialize, Deserialize)]
4802pub struct FairValueConfig {
4803    /// Enable fair value measurement generation
4804    #[serde(default)]
4805    pub enabled: bool,
4806
4807    /// Number of fair value measurements to generate
4808    #[serde(default = "default_fv_count")]
4809    pub measurement_count: usize,
4810
4811    /// Level 1 (quoted prices) percentage
4812    #[serde(default = "default_level1_pct")]
4813    pub level1_percent: f64,
4814
4815    /// Level 2 (observable inputs) percentage
4816    #[serde(default = "default_level2_pct")]
4817    pub level2_percent: f64,
4818
4819    /// Level 3 (unobservable inputs) percentage
4820    #[serde(default = "default_level3_pct")]
4821    pub level3_percent: f64,
4822
4823    /// Include sensitivity analysis for Level 3
4824    #[serde(default)]
4825    pub include_sensitivity_analysis: bool,
4826}
4827
4828fn default_fv_count() -> usize {
4829    25
4830}
4831
4832fn default_level1_pct() -> f64 {
4833    0.40
4834}
4835
4836fn default_level2_pct() -> f64 {
4837    0.35
4838}
4839
4840fn default_level3_pct() -> f64 {
4841    0.25
4842}
4843
4844impl Default for FairValueConfig {
4845    fn default() -> Self {
4846        Self {
4847            enabled: false,
4848            measurement_count: default_fv_count(),
4849            level1_percent: default_level1_pct(),
4850            level2_percent: default_level2_pct(),
4851            level3_percent: default_level3_pct(),
4852            include_sensitivity_analysis: false,
4853        }
4854    }
4855}
4856
4857/// Impairment testing configuration (ASC 360/IAS 36).
4858#[derive(Debug, Clone, Serialize, Deserialize)]
4859pub struct ImpairmentConfig {
4860    /// Enable impairment testing generation
4861    #[serde(default)]
4862    pub enabled: bool,
4863
4864    /// Number of impairment tests to generate
4865    #[serde(default = "default_impairment_count")]
4866    pub test_count: usize,
4867
4868    /// Rate of tests resulting in impairment
4869    #[serde(default = "default_impairment_rate")]
4870    pub impairment_rate: f64,
4871
4872    /// Generate cash flow projections
4873    #[serde(default = "default_true")]
4874    pub generate_projections: bool,
4875
4876    /// Include goodwill impairment tests
4877    #[serde(default)]
4878    pub include_goodwill: bool,
4879}
4880
4881fn default_impairment_count() -> usize {
4882    15
4883}
4884
4885fn default_impairment_rate() -> f64 {
4886    0.10
4887}
4888
4889impl Default for ImpairmentConfig {
4890    fn default() -> Self {
4891        Self {
4892            enabled: false,
4893            test_count: default_impairment_count(),
4894            impairment_rate: default_impairment_rate(),
4895            generate_projections: true,
4896            include_goodwill: false,
4897        }
4898    }
4899}
4900
4901// =============================================================================
4902// Audit Standards Configuration
4903// =============================================================================
4904
4905/// Audit standards framework configuration for generating standards-compliant audit data.
4906///
4907/// Supports ISA (International Standards on Auditing) and PCAOB standards:
4908/// - ISA 200-720: Complete coverage of audit standards
4909/// - ISA 520: Analytical Procedures
4910/// - ISA 505: External Confirmations
4911/// - ISA 700/705/706/701: Audit Reports
4912/// - PCAOB AS 2201: ICFR Auditing
4913#[derive(Debug, Clone, Serialize, Deserialize, Default)]
4914pub struct AuditStandardsConfig {
4915    /// Enable audit standards generation
4916    #[serde(default)]
4917    pub enabled: bool,
4918
4919    /// ISA compliance configuration
4920    #[serde(default)]
4921    pub isa_compliance: IsaComplianceConfig,
4922
4923    /// Analytical procedures configuration (ISA 520)
4924    #[serde(default)]
4925    pub analytical_procedures: AnalyticalProceduresConfig,
4926
4927    /// External confirmations configuration (ISA 505)
4928    #[serde(default)]
4929    pub confirmations: ConfirmationsConfig,
4930
4931    /// Audit opinion configuration (ISA 700/705/706/701)
4932    #[serde(default)]
4933    pub opinion: AuditOpinionConfig,
4934
4935    /// Generate complete audit trail with traceability
4936    #[serde(default)]
4937    pub generate_audit_trail: bool,
4938
4939    /// SOX 302/404 compliance configuration
4940    #[serde(default)]
4941    pub sox: SoxComplianceConfig,
4942
4943    /// PCAOB-specific configuration
4944    #[serde(default)]
4945    pub pcaob: PcaobConfig,
4946}
4947
4948/// ISA compliance level configuration.
4949#[derive(Debug, Clone, Serialize, Deserialize)]
4950pub struct IsaComplianceConfig {
4951    /// Enable ISA compliance tracking
4952    #[serde(default)]
4953    pub enabled: bool,
4954
4955    /// Compliance level: "basic", "standard", "comprehensive"
4956    #[serde(default = "default_compliance_level")]
4957    pub compliance_level: String,
4958
4959    /// Generate ISA requirement mappings
4960    #[serde(default = "default_true")]
4961    pub generate_isa_mappings: bool,
4962
4963    /// Generate ISA coverage summary
4964    #[serde(default = "default_true")]
4965    pub generate_coverage_summary: bool,
4966
4967    /// Include PCAOB standard mappings (for dual framework)
4968    #[serde(default)]
4969    pub include_pcaob: bool,
4970
4971    /// Framework to use: "isa", "pcaob", "dual"
4972    #[serde(default = "default_audit_framework")]
4973    pub framework: String,
4974}
4975
4976fn default_compliance_level() -> String {
4977    "standard".to_string()
4978}
4979
4980fn default_audit_framework() -> String {
4981    "isa".to_string()
4982}
4983
4984impl Default for IsaComplianceConfig {
4985    fn default() -> Self {
4986        Self {
4987            enabled: false,
4988            compliance_level: default_compliance_level(),
4989            generate_isa_mappings: true,
4990            generate_coverage_summary: true,
4991            include_pcaob: false,
4992            framework: default_audit_framework(),
4993        }
4994    }
4995}
4996
4997/// Analytical procedures configuration (ISA 520).
4998#[derive(Debug, Clone, Serialize, Deserialize)]
4999pub struct AnalyticalProceduresConfig {
5000    /// Enable analytical procedures generation
5001    #[serde(default)]
5002    pub enabled: bool,
5003
5004    /// Number of procedures per account/area
5005    #[serde(default = "default_procedures_per_account")]
5006    pub procedures_per_account: usize,
5007
5008    /// Probability of variance exceeding threshold
5009    #[serde(default = "default_variance_probability")]
5010    pub variance_probability: f64,
5011
5012    /// Include variance investigations
5013    #[serde(default = "default_true")]
5014    pub generate_investigations: bool,
5015
5016    /// Include financial ratio analysis
5017    #[serde(default = "default_true")]
5018    pub include_ratio_analysis: bool,
5019}
5020
5021fn default_procedures_per_account() -> usize {
5022    3
5023}
5024
5025fn default_variance_probability() -> f64 {
5026    0.20
5027}
5028
5029impl Default for AnalyticalProceduresConfig {
5030    fn default() -> Self {
5031        Self {
5032            enabled: false,
5033            procedures_per_account: default_procedures_per_account(),
5034            variance_probability: default_variance_probability(),
5035            generate_investigations: true,
5036            include_ratio_analysis: true,
5037        }
5038    }
5039}
5040
5041/// External confirmations configuration (ISA 505).
5042#[derive(Debug, Clone, Serialize, Deserialize)]
5043pub struct ConfirmationsConfig {
5044    /// Enable confirmation generation
5045    #[serde(default)]
5046    pub enabled: bool,
5047
5048    /// Number of confirmations to generate
5049    #[serde(default = "default_confirmation_count")]
5050    pub confirmation_count: usize,
5051
5052    /// Positive response rate
5053    #[serde(default = "default_positive_response_rate")]
5054    pub positive_response_rate: f64,
5055
5056    /// Exception rate (responses with differences)
5057    #[serde(default = "default_exception_rate_confirm")]
5058    pub exception_rate: f64,
5059
5060    /// Non-response rate
5061    #[serde(default = "default_non_response_rate")]
5062    pub non_response_rate: f64,
5063
5064    /// Generate alternative procedures for non-responses
5065    #[serde(default = "default_true")]
5066    pub generate_alternative_procedures: bool,
5067}
5068
5069fn default_confirmation_count() -> usize {
5070    50
5071}
5072
5073fn default_positive_response_rate() -> f64 {
5074    0.85
5075}
5076
5077fn default_exception_rate_confirm() -> f64 {
5078    0.10
5079}
5080
5081fn default_non_response_rate() -> f64 {
5082    0.05
5083}
5084
5085impl Default for ConfirmationsConfig {
5086    fn default() -> Self {
5087        Self {
5088            enabled: false,
5089            confirmation_count: default_confirmation_count(),
5090            positive_response_rate: default_positive_response_rate(),
5091            exception_rate: default_exception_rate_confirm(),
5092            non_response_rate: default_non_response_rate(),
5093            generate_alternative_procedures: true,
5094        }
5095    }
5096}
5097
5098/// Audit opinion configuration (ISA 700/705/706/701).
5099#[derive(Debug, Clone, Serialize, Deserialize)]
5100pub struct AuditOpinionConfig {
5101    /// Enable audit opinion generation
5102    #[serde(default)]
5103    pub enabled: bool,
5104
5105    /// Generate Key Audit Matters (KAM) / Critical Audit Matters (CAM)
5106    #[serde(default = "default_true")]
5107    pub generate_kam: bool,
5108
5109    /// Average number of KAMs/CAMs per opinion
5110    #[serde(default = "default_kam_count")]
5111    pub average_kam_count: usize,
5112
5113    /// Rate of modified opinions
5114    #[serde(default = "default_modified_opinion_rate")]
5115    pub modified_opinion_rate: f64,
5116
5117    /// Include emphasis of matter paragraphs
5118    #[serde(default)]
5119    pub include_emphasis_of_matter: bool,
5120
5121    /// Include going concern conclusions
5122    #[serde(default = "default_true")]
5123    pub include_going_concern: bool,
5124}
5125
5126fn default_kam_count() -> usize {
5127    3
5128}
5129
5130fn default_modified_opinion_rate() -> f64 {
5131    0.05
5132}
5133
5134impl Default for AuditOpinionConfig {
5135    fn default() -> Self {
5136        Self {
5137            enabled: false,
5138            generate_kam: true,
5139            average_kam_count: default_kam_count(),
5140            modified_opinion_rate: default_modified_opinion_rate(),
5141            include_emphasis_of_matter: false,
5142            include_going_concern: true,
5143        }
5144    }
5145}
5146
5147/// SOX compliance configuration (Sections 302/404).
5148#[derive(Debug, Clone, Serialize, Deserialize)]
5149pub struct SoxComplianceConfig {
5150    /// Enable SOX compliance generation
5151    #[serde(default)]
5152    pub enabled: bool,
5153
5154    /// Generate Section 302 CEO/CFO certifications
5155    #[serde(default = "default_true")]
5156    pub generate_302_certifications: bool,
5157
5158    /// Generate Section 404 ICFR assessments
5159    #[serde(default = "default_true")]
5160    pub generate_404_assessments: bool,
5161
5162    /// Materiality threshold for SOX testing
5163    #[serde(default = "default_sox_materiality_threshold")]
5164    pub materiality_threshold: f64,
5165
5166    /// Rate of material weaknesses
5167    #[serde(default = "default_material_weakness_rate")]
5168    pub material_weakness_rate: f64,
5169
5170    /// Rate of significant deficiencies
5171    #[serde(default = "default_significant_deficiency_rate")]
5172    pub significant_deficiency_rate: f64,
5173}
5174
5175fn default_material_weakness_rate() -> f64 {
5176    0.02
5177}
5178
5179fn default_significant_deficiency_rate() -> f64 {
5180    0.08
5181}
5182
5183impl Default for SoxComplianceConfig {
5184    fn default() -> Self {
5185        Self {
5186            enabled: false,
5187            generate_302_certifications: true,
5188            generate_404_assessments: true,
5189            materiality_threshold: default_sox_materiality_threshold(),
5190            material_weakness_rate: default_material_weakness_rate(),
5191            significant_deficiency_rate: default_significant_deficiency_rate(),
5192        }
5193    }
5194}
5195
5196/// PCAOB-specific configuration.
5197#[derive(Debug, Clone, Serialize, Deserialize)]
5198pub struct PcaobConfig {
5199    /// Enable PCAOB-specific elements
5200    #[serde(default)]
5201    pub enabled: bool,
5202
5203    /// Treat as PCAOB audit (vs ISA-only)
5204    #[serde(default)]
5205    pub is_pcaob_audit: bool,
5206
5207    /// Generate Critical Audit Matters (CAM)
5208    #[serde(default = "default_true")]
5209    pub generate_cam: bool,
5210
5211    /// Include ICFR opinion (for integrated audits)
5212    #[serde(default)]
5213    pub include_icfr_opinion: bool,
5214
5215    /// Generate PCAOB-ISA standard mappings
5216    #[serde(default)]
5217    pub generate_standard_mappings: bool,
5218}
5219
5220impl Default for PcaobConfig {
5221    fn default() -> Self {
5222        Self {
5223            enabled: false,
5224            is_pcaob_audit: false,
5225            generate_cam: true,
5226            include_icfr_opinion: false,
5227            generate_standard_mappings: false,
5228        }
5229    }
5230}
5231
5232// =============================================================================
5233// Advanced Distribution Configuration
5234// =============================================================================
5235
5236/// Advanced distribution configuration for realistic data generation.
5237///
5238/// This section enables sophisticated distribution models including:
5239/// - Mixture models (multi-modal distributions)
5240/// - Cross-field correlations
5241/// - Conditional distributions
5242/// - Regime changes and economic cycles
5243/// - Statistical validation
5244#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5245pub struct AdvancedDistributionConfig {
5246    /// Enable advanced distribution features.
5247    #[serde(default)]
5248    pub enabled: bool,
5249
5250    /// Mixture model configuration for amounts.
5251    #[serde(default)]
5252    pub amounts: MixtureDistributionSchemaConfig,
5253
5254    /// Cross-field correlation configuration.
5255    #[serde(default)]
5256    pub correlations: CorrelationSchemaConfig,
5257
5258    /// Conditional distribution configurations.
5259    #[serde(default)]
5260    pub conditional: Vec<ConditionalDistributionSchemaConfig>,
5261
5262    /// Regime change configuration.
5263    #[serde(default)]
5264    pub regime_changes: RegimeChangeSchemaConfig,
5265
5266    /// Industry-specific distribution profile.
5267    #[serde(default)]
5268    pub industry_profile: Option<IndustryProfileType>,
5269
5270    /// Statistical validation configuration.
5271    #[serde(default)]
5272    pub validation: StatisticalValidationSchemaConfig,
5273}
5274
5275/// Industry profile types for pre-configured distribution settings.
5276#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
5277#[serde(rename_all = "snake_case")]
5278pub enum IndustryProfileType {
5279    /// Retail industry profile (POS sales, inventory, seasonal)
5280    Retail,
5281    /// Manufacturing industry profile (raw materials, maintenance, capital)
5282    Manufacturing,
5283    /// Financial services profile (wire transfers, ACH, fee income)
5284    FinancialServices,
5285    /// Healthcare profile (claims, procedures, supplies)
5286    Healthcare,
5287    /// Technology profile (subscriptions, services, R&D)
5288    Technology,
5289}
5290
5291/// Mixture model distribution configuration.
5292#[derive(Debug, Clone, Serialize, Deserialize)]
5293pub struct MixtureDistributionSchemaConfig {
5294    /// Enable mixture model for amount generation.
5295    #[serde(default)]
5296    pub enabled: bool,
5297
5298    /// Distribution type: "gaussian" or "lognormal".
5299    #[serde(default = "default_mixture_type")]
5300    pub distribution_type: MixtureDistributionType,
5301
5302    /// Mixture components with weights.
5303    #[serde(default)]
5304    pub components: Vec<MixtureComponentConfig>,
5305
5306    /// Minimum value constraint.
5307    #[serde(default = "default_min_amount")]
5308    pub min_value: f64,
5309
5310    /// Maximum value constraint (optional).
5311    #[serde(default)]
5312    pub max_value: Option<f64>,
5313
5314    /// Decimal places for rounding.
5315    #[serde(default = "default_decimal_places")]
5316    pub decimal_places: u8,
5317}
5318
5319fn default_mixture_type() -> MixtureDistributionType {
5320    MixtureDistributionType::LogNormal
5321}
5322
5323fn default_min_amount() -> f64 {
5324    0.01
5325}
5326
5327fn default_decimal_places() -> u8 {
5328    2
5329}
5330
5331impl Default for MixtureDistributionSchemaConfig {
5332    fn default() -> Self {
5333        Self {
5334            enabled: false,
5335            distribution_type: MixtureDistributionType::LogNormal,
5336            components: Vec::new(),
5337            min_value: 0.01,
5338            max_value: None,
5339            decimal_places: 2,
5340        }
5341    }
5342}
5343
5344/// Mixture distribution type.
5345#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5346#[serde(rename_all = "snake_case")]
5347pub enum MixtureDistributionType {
5348    /// Gaussian (normal) mixture
5349    Gaussian,
5350    /// Log-normal mixture (for positive amounts)
5351    #[default]
5352    LogNormal,
5353}
5354
5355/// Configuration for a single mixture component.
5356#[derive(Debug, Clone, Serialize, Deserialize)]
5357pub struct MixtureComponentConfig {
5358    /// Weight of this component (must sum to 1.0 across all components).
5359    pub weight: f64,
5360
5361    /// Location parameter (mean for Gaussian, mu for log-normal).
5362    pub mu: f64,
5363
5364    /// Scale parameter (std dev for Gaussian, sigma for log-normal).
5365    pub sigma: f64,
5366
5367    /// Optional label for this component (e.g., "routine", "significant", "major").
5368    #[serde(default)]
5369    pub label: Option<String>,
5370}
5371
5372/// Cross-field correlation configuration.
5373#[derive(Debug, Clone, Serialize, Deserialize)]
5374pub struct CorrelationSchemaConfig {
5375    /// Enable correlation modeling.
5376    #[serde(default)]
5377    pub enabled: bool,
5378
5379    /// Copula type for dependency modeling.
5380    #[serde(default)]
5381    pub copula_type: CopulaSchemaType,
5382
5383    /// Field definitions for correlation.
5384    #[serde(default)]
5385    pub fields: Vec<CorrelatedFieldConfig>,
5386
5387    /// Correlation matrix (upper triangular, row-major).
5388    /// For n fields, this should have n*(n-1)/2 values.
5389    #[serde(default)]
5390    pub matrix: Vec<f64>,
5391
5392    /// Expected correlations for validation.
5393    #[serde(default)]
5394    pub expected_correlations: Vec<ExpectedCorrelationConfig>,
5395}
5396
5397impl Default for CorrelationSchemaConfig {
5398    fn default() -> Self {
5399        Self {
5400            enabled: false,
5401            copula_type: CopulaSchemaType::Gaussian,
5402            fields: Vec::new(),
5403            matrix: Vec::new(),
5404            expected_correlations: Vec::new(),
5405        }
5406    }
5407}
5408
5409/// Copula type for dependency modeling.
5410#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5411#[serde(rename_all = "snake_case")]
5412pub enum CopulaSchemaType {
5413    /// Gaussian copula (symmetric, no tail dependence)
5414    #[default]
5415    Gaussian,
5416    /// Clayton copula (lower tail dependence)
5417    Clayton,
5418    /// Gumbel copula (upper tail dependence)
5419    Gumbel,
5420    /// Frank copula (symmetric, no tail dependence)
5421    Frank,
5422    /// Student-t copula (both tail dependencies)
5423    StudentT,
5424}
5425
5426/// Configuration for a correlated field.
5427#[derive(Debug, Clone, Serialize, Deserialize)]
5428pub struct CorrelatedFieldConfig {
5429    /// Field name.
5430    pub name: String,
5431
5432    /// Marginal distribution type.
5433    #[serde(default)]
5434    pub distribution: MarginalDistributionConfig,
5435}
5436
5437/// Marginal distribution configuration.
5438#[derive(Debug, Clone, Serialize, Deserialize)]
5439#[serde(tag = "type", rename_all = "snake_case")]
5440pub enum MarginalDistributionConfig {
5441    /// Normal distribution.
5442    Normal {
5443        /// Mean
5444        mu: f64,
5445        /// Standard deviation
5446        sigma: f64,
5447    },
5448    /// Log-normal distribution.
5449    LogNormal {
5450        /// Location parameter
5451        mu: f64,
5452        /// Scale parameter
5453        sigma: f64,
5454    },
5455    /// Uniform distribution.
5456    Uniform {
5457        /// Minimum value
5458        min: f64,
5459        /// Maximum value
5460        max: f64,
5461    },
5462    /// Discrete uniform distribution.
5463    DiscreteUniform {
5464        /// Minimum integer value
5465        min: i32,
5466        /// Maximum integer value
5467        max: i32,
5468    },
5469}
5470
5471impl Default for MarginalDistributionConfig {
5472    fn default() -> Self {
5473        Self::Normal {
5474            mu: 0.0,
5475            sigma: 1.0,
5476        }
5477    }
5478}
5479
5480/// Expected correlation for validation.
5481#[derive(Debug, Clone, Serialize, Deserialize)]
5482pub struct ExpectedCorrelationConfig {
5483    /// First field name.
5484    pub field1: String,
5485    /// Second field name.
5486    pub field2: String,
5487    /// Expected correlation coefficient.
5488    pub expected_r: f64,
5489    /// Acceptable tolerance.
5490    #[serde(default = "default_correlation_tolerance")]
5491    pub tolerance: f64,
5492}
5493
5494fn default_correlation_tolerance() -> f64 {
5495    0.10
5496}
5497
5498/// Conditional distribution configuration.
5499#[derive(Debug, Clone, Serialize, Deserialize)]
5500pub struct ConditionalDistributionSchemaConfig {
5501    /// Output field name to generate.
5502    pub output_field: String,
5503
5504    /// Input field name that conditions the distribution.
5505    pub input_field: String,
5506
5507    /// Breakpoints defining distribution changes.
5508    #[serde(default)]
5509    pub breakpoints: Vec<ConditionalBreakpointConfig>,
5510
5511    /// Default distribution when below all breakpoints.
5512    #[serde(default)]
5513    pub default_distribution: ConditionalDistributionParamsConfig,
5514
5515    /// Minimum output value constraint.
5516    #[serde(default)]
5517    pub min_value: Option<f64>,
5518
5519    /// Maximum output value constraint.
5520    #[serde(default)]
5521    pub max_value: Option<f64>,
5522
5523    /// Decimal places for output rounding.
5524    #[serde(default = "default_decimal_places")]
5525    pub decimal_places: u8,
5526}
5527
5528/// Breakpoint for conditional distribution.
5529#[derive(Debug, Clone, Serialize, Deserialize)]
5530pub struct ConditionalBreakpointConfig {
5531    /// Input value threshold.
5532    pub threshold: f64,
5533
5534    /// Distribution to use when input >= threshold.
5535    pub distribution: ConditionalDistributionParamsConfig,
5536}
5537
5538/// Distribution parameters for conditional distributions.
5539#[derive(Debug, Clone, Serialize, Deserialize)]
5540#[serde(tag = "type", rename_all = "snake_case")]
5541pub enum ConditionalDistributionParamsConfig {
5542    /// Fixed value.
5543    Fixed {
5544        /// The fixed value
5545        value: f64,
5546    },
5547    /// Normal distribution.
5548    Normal {
5549        /// Mean
5550        mu: f64,
5551        /// Standard deviation
5552        sigma: f64,
5553    },
5554    /// Log-normal distribution.
5555    LogNormal {
5556        /// Location parameter
5557        mu: f64,
5558        /// Scale parameter
5559        sigma: f64,
5560    },
5561    /// Uniform distribution.
5562    Uniform {
5563        /// Minimum
5564        min: f64,
5565        /// Maximum
5566        max: f64,
5567    },
5568    /// Beta distribution (scaled).
5569    Beta {
5570        /// Alpha parameter
5571        alpha: f64,
5572        /// Beta parameter
5573        beta: f64,
5574        /// Minimum output value
5575        min: f64,
5576        /// Maximum output value
5577        max: f64,
5578    },
5579    /// Discrete values with weights.
5580    Discrete {
5581        /// Possible values
5582        values: Vec<f64>,
5583        /// Weights (should sum to 1.0)
5584        weights: Vec<f64>,
5585    },
5586}
5587
5588impl Default for ConditionalDistributionParamsConfig {
5589    fn default() -> Self {
5590        Self::Normal {
5591            mu: 0.0,
5592            sigma: 1.0,
5593        }
5594    }
5595}
5596
5597/// Regime change configuration.
5598#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5599pub struct RegimeChangeSchemaConfig {
5600    /// Enable regime change modeling.
5601    #[serde(default)]
5602    pub enabled: bool,
5603
5604    /// List of regime changes.
5605    #[serde(default)]
5606    pub changes: Vec<RegimeChangeEventConfig>,
5607
5608    /// Economic cycle configuration.
5609    #[serde(default)]
5610    pub economic_cycle: Option<EconomicCycleSchemaConfig>,
5611
5612    /// Parameter drift configurations.
5613    #[serde(default)]
5614    pub parameter_drifts: Vec<ParameterDriftSchemaConfig>,
5615}
5616
5617/// A single regime change event.
5618#[derive(Debug, Clone, Serialize, Deserialize)]
5619pub struct RegimeChangeEventConfig {
5620    /// Date when the change occurs (ISO 8601 format).
5621    pub date: String,
5622
5623    /// Type of regime change.
5624    pub change_type: RegimeChangeTypeConfig,
5625
5626    /// Description of the change.
5627    #[serde(default)]
5628    pub description: Option<String>,
5629
5630    /// Effects of this regime change.
5631    #[serde(default)]
5632    pub effects: Vec<RegimeEffectConfig>,
5633}
5634
5635/// Type of regime change.
5636#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
5637#[serde(rename_all = "snake_case")]
5638pub enum RegimeChangeTypeConfig {
5639    /// Acquisition - sudden volume and amount increase
5640    Acquisition,
5641    /// Divestiture - sudden volume and amount decrease
5642    Divestiture,
5643    /// Price increase - amounts increase
5644    PriceIncrease,
5645    /// Price decrease - amounts decrease
5646    PriceDecrease,
5647    /// New product launch - volume ramp-up
5648    ProductLaunch,
5649    /// Product discontinuation - volume ramp-down
5650    ProductDiscontinuation,
5651    /// Policy change - affects patterns
5652    PolicyChange,
5653    /// Competitor entry - market disruption
5654    CompetitorEntry,
5655    /// Custom effect
5656    Custom,
5657}
5658
5659/// Effect of a regime change on a specific field.
5660#[derive(Debug, Clone, Serialize, Deserialize)]
5661pub struct RegimeEffectConfig {
5662    /// Field being affected.
5663    pub field: String,
5664
5665    /// Multiplier to apply (1.0 = no change, 1.5 = 50% increase).
5666    pub multiplier: f64,
5667}
5668
5669/// Economic cycle configuration.
5670#[derive(Debug, Clone, Serialize, Deserialize)]
5671pub struct EconomicCycleSchemaConfig {
5672    /// Enable economic cycle modeling.
5673    #[serde(default)]
5674    pub enabled: bool,
5675
5676    /// Cycle period in months (e.g., 48 for 4-year business cycle).
5677    #[serde(default = "default_cycle_period")]
5678    pub period_months: u32,
5679
5680    /// Amplitude of cycle effect (0.0-1.0).
5681    #[serde(default = "default_cycle_amplitude")]
5682    pub amplitude: f64,
5683
5684    /// Phase offset in months.
5685    #[serde(default)]
5686    pub phase_offset: u32,
5687
5688    /// Recession periods (start_month, duration_months).
5689    #[serde(default)]
5690    pub recessions: Vec<RecessionPeriodConfig>,
5691}
5692
5693fn default_cycle_period() -> u32 {
5694    48
5695}
5696
5697fn default_cycle_amplitude() -> f64 {
5698    0.15
5699}
5700
5701impl Default for EconomicCycleSchemaConfig {
5702    fn default() -> Self {
5703        Self {
5704            enabled: false,
5705            period_months: 48,
5706            amplitude: 0.15,
5707            phase_offset: 0,
5708            recessions: Vec::new(),
5709        }
5710    }
5711}
5712
5713/// Recession period configuration.
5714#[derive(Debug, Clone, Serialize, Deserialize)]
5715pub struct RecessionPeriodConfig {
5716    /// Start month (0-indexed from generation start).
5717    pub start_month: u32,
5718
5719    /// Duration in months.
5720    pub duration_months: u32,
5721
5722    /// Severity (0.0-1.0, affects volume reduction).
5723    #[serde(default = "default_recession_severity")]
5724    pub severity: f64,
5725}
5726
5727fn default_recession_severity() -> f64 {
5728    0.20
5729}
5730
5731/// Parameter drift configuration.
5732#[derive(Debug, Clone, Serialize, Deserialize)]
5733pub struct ParameterDriftSchemaConfig {
5734    /// Parameter being drifted.
5735    pub parameter: String,
5736
5737    /// Drift type.
5738    pub drift_type: ParameterDriftTypeConfig,
5739
5740    /// Start value.
5741    pub start_value: f64,
5742
5743    /// End value.
5744    pub end_value: f64,
5745
5746    /// Start period (month, 0-indexed).
5747    #[serde(default)]
5748    pub start_period: u32,
5749
5750    /// End period (month, optional - defaults to end of generation).
5751    #[serde(default)]
5752    pub end_period: Option<u32>,
5753}
5754
5755/// Parameter drift type.
5756#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5757#[serde(rename_all = "snake_case")]
5758pub enum ParameterDriftTypeConfig {
5759    /// Linear interpolation
5760    #[default]
5761    Linear,
5762    /// Exponential growth/decay
5763    Exponential,
5764    /// S-curve (logistic)
5765    Logistic,
5766    /// Step function
5767    Step,
5768}
5769
5770/// Statistical validation configuration.
5771#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5772pub struct StatisticalValidationSchemaConfig {
5773    /// Enable statistical validation.
5774    #[serde(default)]
5775    pub enabled: bool,
5776
5777    /// Statistical tests to run.
5778    #[serde(default)]
5779    pub tests: Vec<StatisticalTestConfig>,
5780
5781    /// Validation reporting configuration.
5782    #[serde(default)]
5783    pub reporting: ValidationReportingConfig,
5784}
5785
5786/// Statistical test configuration.
5787#[derive(Debug, Clone, Serialize, Deserialize)]
5788#[serde(tag = "type", rename_all = "snake_case")]
5789pub enum StatisticalTestConfig {
5790    /// Benford's Law first digit test.
5791    BenfordFirstDigit {
5792        /// Threshold MAD for failure.
5793        #[serde(default = "default_benford_threshold")]
5794        threshold_mad: f64,
5795        /// Warning MAD threshold.
5796        #[serde(default = "default_benford_warning")]
5797        warning_mad: f64,
5798    },
5799    /// Distribution fit test.
5800    DistributionFit {
5801        /// Target distribution to test.
5802        target: TargetDistributionConfig,
5803        /// K-S test significance level.
5804        #[serde(default = "default_ks_significance")]
5805        ks_significance: f64,
5806        /// Test method (ks, anderson_darling, chi_squared).
5807        #[serde(default)]
5808        method: DistributionFitMethod,
5809    },
5810    /// Correlation check.
5811    CorrelationCheck {
5812        /// Expected correlations to validate.
5813        expected_correlations: Vec<ExpectedCorrelationConfig>,
5814    },
5815    /// Chi-squared test.
5816    ChiSquared {
5817        /// Number of bins.
5818        #[serde(default = "default_chi_squared_bins")]
5819        bins: usize,
5820        /// Significance level.
5821        #[serde(default = "default_chi_squared_significance")]
5822        significance: f64,
5823    },
5824    /// Anderson-Darling test.
5825    AndersonDarling {
5826        /// Target distribution.
5827        target: TargetDistributionConfig,
5828        /// Significance level.
5829        #[serde(default = "default_ad_significance")]
5830        significance: f64,
5831    },
5832}
5833
5834fn default_benford_threshold() -> f64 {
5835    0.015
5836}
5837
5838fn default_benford_warning() -> f64 {
5839    0.010
5840}
5841
5842fn default_ks_significance() -> f64 {
5843    0.05
5844}
5845
5846fn default_chi_squared_bins() -> usize {
5847    10
5848}
5849
5850fn default_chi_squared_significance() -> f64 {
5851    0.05
5852}
5853
5854fn default_ad_significance() -> f64 {
5855    0.05
5856}
5857
5858/// Target distribution for fit tests.
5859#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5860#[serde(rename_all = "snake_case")]
5861pub enum TargetDistributionConfig {
5862    /// Normal distribution
5863    Normal,
5864    /// Log-normal distribution
5865    #[default]
5866    LogNormal,
5867    /// Exponential distribution
5868    Exponential,
5869    /// Uniform distribution
5870    Uniform,
5871}
5872
5873/// Distribution fit test method.
5874#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5875#[serde(rename_all = "snake_case")]
5876pub enum DistributionFitMethod {
5877    /// Kolmogorov-Smirnov test
5878    #[default]
5879    KolmogorovSmirnov,
5880    /// Anderson-Darling test
5881    AndersonDarling,
5882    /// Chi-squared test
5883    ChiSquared,
5884}
5885
5886/// Validation reporting configuration.
5887#[derive(Debug, Clone, Serialize, Deserialize)]
5888pub struct ValidationReportingConfig {
5889    /// Output validation report to file.
5890    #[serde(default)]
5891    pub output_report: bool,
5892
5893    /// Report format.
5894    #[serde(default)]
5895    pub format: ValidationReportFormat,
5896
5897    /// Fail generation if validation fails.
5898    #[serde(default)]
5899    pub fail_on_error: bool,
5900
5901    /// Include detailed statistics in report.
5902    #[serde(default = "default_true")]
5903    pub include_details: bool,
5904}
5905
5906impl Default for ValidationReportingConfig {
5907    fn default() -> Self {
5908        Self {
5909            output_report: false,
5910            format: ValidationReportFormat::Json,
5911            fail_on_error: false,
5912            include_details: true,
5913        }
5914    }
5915}
5916
5917/// Validation report format.
5918#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
5919#[serde(rename_all = "snake_case")]
5920pub enum ValidationReportFormat {
5921    /// JSON format
5922    #[default]
5923    Json,
5924    /// YAML format
5925    Yaml,
5926    /// HTML report
5927    Html,
5928}
5929
5930// =============================================================================
5931// Temporal Patterns Configuration
5932// =============================================================================
5933
5934/// Temporal patterns configuration for business days, period-end dynamics, and processing lags.
5935///
5936/// This section enables sophisticated temporal modeling including:
5937/// - Business day calculations and settlement dates
5938/// - Regional holiday calendars
5939/// - Period-end decay curves (non-flat volume spikes)
5940/// - Processing lag modeling (event-to-posting delays)
5941#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5942pub struct TemporalPatternsConfig {
5943    /// Enable temporal patterns features.
5944    #[serde(default)]
5945    pub enabled: bool,
5946
5947    /// Business day calculation configuration.
5948    #[serde(default)]
5949    pub business_days: BusinessDaySchemaConfig,
5950
5951    /// Regional calendar configuration.
5952    #[serde(default)]
5953    pub calendars: CalendarSchemaConfig,
5954
5955    /// Period-end dynamics configuration.
5956    #[serde(default)]
5957    pub period_end: PeriodEndSchemaConfig,
5958
5959    /// Processing lag configuration.
5960    #[serde(default)]
5961    pub processing_lags: ProcessingLagSchemaConfig,
5962
5963    /// Fiscal calendar configuration (custom year start, 4-4-5, 13-period).
5964    #[serde(default)]
5965    pub fiscal_calendar: FiscalCalendarSchemaConfig,
5966
5967    /// Intra-day patterns configuration (morning spike, lunch dip, EOD rush).
5968    #[serde(default)]
5969    pub intraday: IntraDaySchemaConfig,
5970
5971    /// Timezone handling configuration.
5972    #[serde(default)]
5973    pub timezones: TimezoneSchemaConfig,
5974}
5975
5976/// Business day calculation configuration.
5977#[derive(Debug, Clone, Serialize, Deserialize)]
5978pub struct BusinessDaySchemaConfig {
5979    /// Enable business day calculations.
5980    #[serde(default = "default_true")]
5981    pub enabled: bool,
5982
5983    /// Half-day policy: "full_day", "half_day", "non_business_day".
5984    #[serde(default = "default_half_day_policy")]
5985    pub half_day_policy: String,
5986
5987    /// Settlement rules configuration.
5988    #[serde(default)]
5989    pub settlement_rules: SettlementRulesSchemaConfig,
5990
5991    /// Month-end convention: "modified_following", "preceding", "following", "end_of_month".
5992    #[serde(default = "default_month_end_convention")]
5993    pub month_end_convention: String,
5994
5995    /// Weekend days (e.g., ["saturday", "sunday"] or ["friday", "saturday"] for Middle East).
5996    #[serde(default)]
5997    pub weekend_days: Option<Vec<String>>,
5998}
5999
6000fn default_half_day_policy() -> String {
6001    "half_day".to_string()
6002}
6003
6004fn default_month_end_convention() -> String {
6005    "modified_following".to_string()
6006}
6007
6008impl Default for BusinessDaySchemaConfig {
6009    fn default() -> Self {
6010        Self {
6011            enabled: true,
6012            half_day_policy: "half_day".to_string(),
6013            settlement_rules: SettlementRulesSchemaConfig::default(),
6014            month_end_convention: "modified_following".to_string(),
6015            weekend_days: None,
6016        }
6017    }
6018}
6019
6020/// Settlement rules configuration.
6021#[derive(Debug, Clone, Serialize, Deserialize)]
6022pub struct SettlementRulesSchemaConfig {
6023    /// Equity settlement days (T+N).
6024    #[serde(default = "default_settlement_2")]
6025    pub equity_days: i32,
6026
6027    /// Government bonds settlement days.
6028    #[serde(default = "default_settlement_1")]
6029    pub government_bonds_days: i32,
6030
6031    /// FX spot settlement days.
6032    #[serde(default = "default_settlement_2")]
6033    pub fx_spot_days: i32,
6034
6035    /// Corporate bonds settlement days.
6036    #[serde(default = "default_settlement_2")]
6037    pub corporate_bonds_days: i32,
6038
6039    /// Wire transfer cutoff time (HH:MM format).
6040    #[serde(default = "default_wire_cutoff")]
6041    pub wire_cutoff_time: String,
6042
6043    /// International wire settlement days.
6044    #[serde(default = "default_settlement_1")]
6045    pub wire_international_days: i32,
6046
6047    /// ACH settlement days.
6048    #[serde(default = "default_settlement_1")]
6049    pub ach_days: i32,
6050}
6051
6052fn default_settlement_1() -> i32 {
6053    1
6054}
6055
6056fn default_settlement_2() -> i32 {
6057    2
6058}
6059
6060fn default_wire_cutoff() -> String {
6061    "14:00".to_string()
6062}
6063
6064impl Default for SettlementRulesSchemaConfig {
6065    fn default() -> Self {
6066        Self {
6067            equity_days: 2,
6068            government_bonds_days: 1,
6069            fx_spot_days: 2,
6070            corporate_bonds_days: 2,
6071            wire_cutoff_time: "14:00".to_string(),
6072            wire_international_days: 1,
6073            ach_days: 1,
6074        }
6075    }
6076}
6077
6078/// Regional calendar configuration.
6079#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6080pub struct CalendarSchemaConfig {
6081    /// List of regions to include (e.g., ["US", "DE", "BR", "SG", "KR"]).
6082    #[serde(default)]
6083    pub regions: Vec<String>,
6084
6085    /// Custom holidays (in addition to regional calendars).
6086    #[serde(default)]
6087    pub custom_holidays: Vec<CustomHolidaySchemaConfig>,
6088}
6089
6090/// Custom holiday configuration.
6091#[derive(Debug, Clone, Serialize, Deserialize)]
6092pub struct CustomHolidaySchemaConfig {
6093    /// Holiday name.
6094    pub name: String,
6095    /// Month (1-12).
6096    pub month: u8,
6097    /// Day of month.
6098    pub day: u8,
6099    /// Activity multiplier (0.0-1.0, default 0.05).
6100    #[serde(default = "default_holiday_multiplier")]
6101    pub activity_multiplier: f64,
6102}
6103
6104fn default_holiday_multiplier() -> f64 {
6105    0.05
6106}
6107
6108/// Period-end dynamics configuration.
6109#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6110pub struct PeriodEndSchemaConfig {
6111    /// Model type: "flat", "exponential", "extended_crunch", "daily_profile".
6112    #[serde(default)]
6113    pub model: Option<String>,
6114
6115    /// Month-end configuration.
6116    #[serde(default)]
6117    pub month_end: Option<PeriodEndModelSchemaConfig>,
6118
6119    /// Quarter-end configuration.
6120    #[serde(default)]
6121    pub quarter_end: Option<PeriodEndModelSchemaConfig>,
6122
6123    /// Year-end configuration.
6124    #[serde(default)]
6125    pub year_end: Option<PeriodEndModelSchemaConfig>,
6126}
6127
6128/// Period-end model configuration.
6129#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6130pub struct PeriodEndModelSchemaConfig {
6131    /// Inherit configuration from another period (e.g., "month_end").
6132    #[serde(default)]
6133    pub inherit_from: Option<String>,
6134
6135    /// Additional multiplier on top of inherited/base model.
6136    #[serde(default)]
6137    pub additional_multiplier: Option<f64>,
6138
6139    /// Days before period end to start acceleration (negative, e.g., -10).
6140    #[serde(default)]
6141    pub start_day: Option<i32>,
6142
6143    /// Base multiplier at start of acceleration.
6144    #[serde(default)]
6145    pub base_multiplier: Option<f64>,
6146
6147    /// Peak multiplier on last day.
6148    #[serde(default)]
6149    pub peak_multiplier: Option<f64>,
6150
6151    /// Decay rate for exponential model (0.1-0.5 typical).
6152    #[serde(default)]
6153    pub decay_rate: Option<f64>,
6154
6155    /// Sustained high days for crunch model.
6156    #[serde(default)]
6157    pub sustained_high_days: Option<i32>,
6158}
6159
6160/// Processing lag configuration.
6161#[derive(Debug, Clone, Serialize, Deserialize)]
6162pub struct ProcessingLagSchemaConfig {
6163    /// Enable processing lag calculations.
6164    #[serde(default = "default_true")]
6165    pub enabled: bool,
6166
6167    /// Sales order lag configuration (log-normal mu, sigma).
6168    #[serde(default)]
6169    pub sales_order_lag: Option<LagDistributionSchemaConfig>,
6170
6171    /// Purchase order lag configuration.
6172    #[serde(default)]
6173    pub purchase_order_lag: Option<LagDistributionSchemaConfig>,
6174
6175    /// Goods receipt lag configuration.
6176    #[serde(default)]
6177    pub goods_receipt_lag: Option<LagDistributionSchemaConfig>,
6178
6179    /// Invoice receipt lag configuration.
6180    #[serde(default)]
6181    pub invoice_receipt_lag: Option<LagDistributionSchemaConfig>,
6182
6183    /// Invoice issue lag configuration.
6184    #[serde(default)]
6185    pub invoice_issue_lag: Option<LagDistributionSchemaConfig>,
6186
6187    /// Payment lag configuration.
6188    #[serde(default)]
6189    pub payment_lag: Option<LagDistributionSchemaConfig>,
6190
6191    /// Journal entry lag configuration.
6192    #[serde(default)]
6193    pub journal_entry_lag: Option<LagDistributionSchemaConfig>,
6194
6195    /// Cross-day posting configuration.
6196    #[serde(default)]
6197    pub cross_day_posting: Option<CrossDayPostingSchemaConfig>,
6198}
6199
6200impl Default for ProcessingLagSchemaConfig {
6201    fn default() -> Self {
6202        Self {
6203            enabled: true,
6204            sales_order_lag: None,
6205            purchase_order_lag: None,
6206            goods_receipt_lag: None,
6207            invoice_receipt_lag: None,
6208            invoice_issue_lag: None,
6209            payment_lag: None,
6210            journal_entry_lag: None,
6211            cross_day_posting: None,
6212        }
6213    }
6214}
6215
6216/// Lag distribution configuration (log-normal parameters).
6217#[derive(Debug, Clone, Serialize, Deserialize)]
6218pub struct LagDistributionSchemaConfig {
6219    /// Log-scale mean (mu for log-normal).
6220    pub mu: f64,
6221    /// Log-scale standard deviation (sigma for log-normal).
6222    pub sigma: f64,
6223    /// Minimum lag in hours.
6224    #[serde(default)]
6225    pub min_hours: Option<f64>,
6226    /// Maximum lag in hours.
6227    #[serde(default)]
6228    pub max_hours: Option<f64>,
6229}
6230
6231/// Cross-day posting configuration.
6232#[derive(Debug, Clone, Serialize, Deserialize)]
6233pub struct CrossDayPostingSchemaConfig {
6234    /// Enable cross-day posting logic.
6235    #[serde(default = "default_true")]
6236    pub enabled: bool,
6237
6238    /// Probability of next-day posting by hour (map of hour -> probability).
6239    /// E.g., { 17: 0.7, 19: 0.9, 21: 0.99 }
6240    #[serde(default)]
6241    pub probability_by_hour: std::collections::HashMap<u8, f64>,
6242}
6243
6244impl Default for CrossDayPostingSchemaConfig {
6245    fn default() -> Self {
6246        let mut probability_by_hour = std::collections::HashMap::new();
6247        probability_by_hour.insert(17, 0.3);
6248        probability_by_hour.insert(18, 0.6);
6249        probability_by_hour.insert(19, 0.8);
6250        probability_by_hour.insert(20, 0.9);
6251        probability_by_hour.insert(21, 0.95);
6252        probability_by_hour.insert(22, 0.99);
6253
6254        Self {
6255            enabled: true,
6256            probability_by_hour,
6257        }
6258    }
6259}
6260
6261// =============================================================================
6262// Fiscal Calendar Configuration (P2)
6263// =============================================================================
6264
6265/// Fiscal calendar configuration.
6266///
6267/// Supports calendar year, custom year start, 4-4-5 retail calendar,
6268/// and 13-period calendars.
6269#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6270pub struct FiscalCalendarSchemaConfig {
6271    /// Enable non-standard fiscal calendar.
6272    #[serde(default)]
6273    pub enabled: bool,
6274
6275    /// Fiscal calendar type: "calendar_year", "custom", "four_four_five", "thirteen_period".
6276    #[serde(default = "default_fiscal_calendar_type")]
6277    pub calendar_type: String,
6278
6279    /// Month the fiscal year starts (1-12). Used for custom year start.
6280    #[serde(default)]
6281    pub year_start_month: Option<u8>,
6282
6283    /// Day the fiscal year starts (1-31). Used for custom year start.
6284    #[serde(default)]
6285    pub year_start_day: Option<u8>,
6286
6287    /// 4-4-5 calendar configuration (if calendar_type is "four_four_five").
6288    #[serde(default)]
6289    pub four_four_five: Option<FourFourFiveSchemaConfig>,
6290}
6291
6292fn default_fiscal_calendar_type() -> String {
6293    "calendar_year".to_string()
6294}
6295
6296/// 4-4-5 retail calendar configuration.
6297#[derive(Debug, Clone, Serialize, Deserialize)]
6298pub struct FourFourFiveSchemaConfig {
6299    /// Week pattern: "four_four_five", "four_five_four", "five_four_four".
6300    #[serde(default = "default_week_pattern")]
6301    pub pattern: String,
6302
6303    /// Anchor type: "first_sunday", "last_saturday", "nearest_saturday".
6304    #[serde(default = "default_anchor_type")]
6305    pub anchor_type: String,
6306
6307    /// Anchor month (1-12).
6308    #[serde(default = "default_anchor_month")]
6309    pub anchor_month: u8,
6310
6311    /// Where to place leap week: "q4_period3" or "q1_period1".
6312    #[serde(default = "default_leap_week_placement")]
6313    pub leap_week_placement: String,
6314}
6315
6316fn default_week_pattern() -> String {
6317    "four_four_five".to_string()
6318}
6319
6320fn default_anchor_type() -> String {
6321    "last_saturday".to_string()
6322}
6323
6324fn default_anchor_month() -> u8 {
6325    1 // January
6326}
6327
6328fn default_leap_week_placement() -> String {
6329    "q4_period3".to_string()
6330}
6331
6332impl Default for FourFourFiveSchemaConfig {
6333    fn default() -> Self {
6334        Self {
6335            pattern: "four_four_five".to_string(),
6336            anchor_type: "last_saturday".to_string(),
6337            anchor_month: 1,
6338            leap_week_placement: "q4_period3".to_string(),
6339        }
6340    }
6341}
6342
6343// =============================================================================
6344// Intra-Day Patterns Configuration (P2)
6345// =============================================================================
6346
6347/// Intra-day patterns configuration.
6348///
6349/// Defines time-of-day segments with different activity multipliers
6350/// for realistic modeling of morning spikes, lunch dips, and end-of-day rushes.
6351#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6352pub struct IntraDaySchemaConfig {
6353    /// Enable intra-day patterns.
6354    #[serde(default)]
6355    pub enabled: bool,
6356
6357    /// Custom intra-day segments.
6358    #[serde(default)]
6359    pub segments: Vec<IntraDaySegmentSchemaConfig>,
6360}
6361
6362/// Intra-day segment configuration.
6363#[derive(Debug, Clone, Serialize, Deserialize)]
6364pub struct IntraDaySegmentSchemaConfig {
6365    /// Name of the segment (e.g., "morning_spike", "lunch_dip").
6366    pub name: String,
6367
6368    /// Start time (HH:MM format).
6369    pub start: String,
6370
6371    /// End time (HH:MM format).
6372    pub end: String,
6373
6374    /// Activity multiplier (1.0 = normal).
6375    #[serde(default = "default_multiplier")]
6376    pub multiplier: f64,
6377
6378    /// Posting type: "human", "system", "both".
6379    #[serde(default = "default_posting_type")]
6380    pub posting_type: String,
6381}
6382
6383fn default_multiplier() -> f64 {
6384    1.0
6385}
6386
6387fn default_posting_type() -> String {
6388    "both".to_string()
6389}
6390
6391// =============================================================================
6392// Timezone Configuration
6393// =============================================================================
6394
6395/// Timezone handling configuration for multi-region entities.
6396#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6397pub struct TimezoneSchemaConfig {
6398    /// Enable timezone handling.
6399    #[serde(default)]
6400    pub enabled: bool,
6401
6402    /// Default timezone (IANA format, e.g., "America/New_York").
6403    #[serde(default = "default_timezone")]
6404    pub default_timezone: String,
6405
6406    /// Consolidation timezone for group reporting (IANA format).
6407    #[serde(default = "default_consolidation_timezone")]
6408    pub consolidation_timezone: String,
6409
6410    /// Entity-to-timezone mappings.
6411    /// Supports patterns like "EU_*" -> "Europe/London".
6412    #[serde(default)]
6413    pub entity_mappings: Vec<EntityTimezoneMapping>,
6414}
6415
6416fn default_timezone() -> String {
6417    "America/New_York".to_string()
6418}
6419
6420fn default_consolidation_timezone() -> String {
6421    "UTC".to_string()
6422}
6423
6424/// Mapping from entity pattern to timezone.
6425#[derive(Debug, Clone, Serialize, Deserialize)]
6426pub struct EntityTimezoneMapping {
6427    /// Entity code pattern (e.g., "EU_*", "*_APAC", "1000").
6428    pub pattern: String,
6429
6430    /// Timezone (IANA format, e.g., "Europe/London").
6431    pub timezone: String,
6432}
6433
6434// =============================================================================
6435// Vendor Network Configuration
6436// =============================================================================
6437
6438/// Configuration for multi-tier vendor network generation.
6439#[derive(Debug, Clone, Serialize, Deserialize)]
6440pub struct VendorNetworkSchemaConfig {
6441    /// Enable vendor network generation.
6442    #[serde(default)]
6443    pub enabled: bool,
6444
6445    /// Maximum depth of supply chain tiers (1-3).
6446    #[serde(default = "default_vendor_tier_depth")]
6447    pub depth: u8,
6448
6449    /// Tier 1 vendor count configuration.
6450    #[serde(default)]
6451    pub tier1: TierCountSchemaConfig,
6452
6453    /// Tier 2 vendors per Tier 1 parent.
6454    #[serde(default)]
6455    pub tier2_per_parent: TierCountSchemaConfig,
6456
6457    /// Tier 3 vendors per Tier 2 parent.
6458    #[serde(default)]
6459    pub tier3_per_parent: TierCountSchemaConfig,
6460
6461    /// Vendor cluster distribution.
6462    #[serde(default)]
6463    pub clusters: VendorClusterSchemaConfig,
6464
6465    /// Concentration limits.
6466    #[serde(default)]
6467    pub dependencies: DependencySchemaConfig,
6468}
6469
6470fn default_vendor_tier_depth() -> u8 {
6471    3
6472}
6473
6474impl Default for VendorNetworkSchemaConfig {
6475    fn default() -> Self {
6476        Self {
6477            enabled: false,
6478            depth: 3,
6479            tier1: TierCountSchemaConfig { min: 50, max: 100 },
6480            tier2_per_parent: TierCountSchemaConfig { min: 4, max: 10 },
6481            tier3_per_parent: TierCountSchemaConfig { min: 2, max: 5 },
6482            clusters: VendorClusterSchemaConfig::default(),
6483            dependencies: DependencySchemaConfig::default(),
6484        }
6485    }
6486}
6487
6488/// Tier count configuration.
6489#[derive(Debug, Clone, Serialize, Deserialize)]
6490pub struct TierCountSchemaConfig {
6491    /// Minimum count.
6492    #[serde(default = "default_tier_min")]
6493    pub min: usize,
6494
6495    /// Maximum count.
6496    #[serde(default = "default_tier_max")]
6497    pub max: usize,
6498}
6499
6500fn default_tier_min() -> usize {
6501    5
6502}
6503
6504fn default_tier_max() -> usize {
6505    20
6506}
6507
6508impl Default for TierCountSchemaConfig {
6509    fn default() -> Self {
6510        Self {
6511            min: default_tier_min(),
6512            max: default_tier_max(),
6513        }
6514    }
6515}
6516
6517/// Vendor cluster distribution configuration.
6518#[derive(Debug, Clone, Serialize, Deserialize)]
6519pub struct VendorClusterSchemaConfig {
6520    /// Reliable strategic vendors percentage (default: 0.20).
6521    #[serde(default = "default_reliable_strategic")]
6522    pub reliable_strategic: f64,
6523
6524    /// Standard operational vendors percentage (default: 0.50).
6525    #[serde(default = "default_standard_operational")]
6526    pub standard_operational: f64,
6527
6528    /// Transactional vendors percentage (default: 0.25).
6529    #[serde(default = "default_transactional")]
6530    pub transactional: f64,
6531
6532    /// Problematic vendors percentage (default: 0.05).
6533    #[serde(default = "default_problematic")]
6534    pub problematic: f64,
6535}
6536
6537fn default_reliable_strategic() -> f64 {
6538    0.20
6539}
6540
6541fn default_standard_operational() -> f64 {
6542    0.50
6543}
6544
6545fn default_transactional() -> f64 {
6546    0.25
6547}
6548
6549fn default_problematic() -> f64 {
6550    0.05
6551}
6552
6553impl Default for VendorClusterSchemaConfig {
6554    fn default() -> Self {
6555        Self {
6556            reliable_strategic: 0.20,
6557            standard_operational: 0.50,
6558            transactional: 0.25,
6559            problematic: 0.05,
6560        }
6561    }
6562}
6563
6564/// Dependency and concentration limits configuration.
6565#[derive(Debug, Clone, Serialize, Deserialize)]
6566pub struct DependencySchemaConfig {
6567    /// Maximum concentration for a single vendor (default: 0.15).
6568    #[serde(default = "default_max_single_vendor")]
6569    pub max_single_vendor_concentration: f64,
6570
6571    /// Maximum concentration for top 5 vendors (default: 0.45).
6572    #[serde(default = "default_max_top5")]
6573    pub top_5_concentration: f64,
6574
6575    /// Percentage of single-source vendors (default: 0.05).
6576    #[serde(default = "default_single_source_percent")]
6577    pub single_source_percent: f64,
6578}
6579
6580fn default_max_single_vendor() -> f64 {
6581    0.15
6582}
6583
6584fn default_max_top5() -> f64 {
6585    0.45
6586}
6587
6588fn default_single_source_percent() -> f64 {
6589    0.05
6590}
6591
6592impl Default for DependencySchemaConfig {
6593    fn default() -> Self {
6594        Self {
6595            max_single_vendor_concentration: 0.15,
6596            top_5_concentration: 0.45,
6597            single_source_percent: 0.05,
6598        }
6599    }
6600}
6601
6602// =============================================================================
6603// Customer Segmentation Configuration
6604// =============================================================================
6605
6606/// Configuration for customer segmentation generation.
6607#[derive(Debug, Clone, Default, Serialize, Deserialize)]
6608pub struct CustomerSegmentationSchemaConfig {
6609    /// Enable customer segmentation generation.
6610    #[serde(default)]
6611    pub enabled: bool,
6612
6613    /// Value segment distribution.
6614    #[serde(default)]
6615    pub value_segments: ValueSegmentsSchemaConfig,
6616
6617    /// Lifecycle stage configuration.
6618    #[serde(default)]
6619    pub lifecycle: LifecycleSchemaConfig,
6620
6621    /// Network (referrals, hierarchies) configuration.
6622    #[serde(default)]
6623    pub networks: CustomerNetworksSchemaConfig,
6624}
6625
6626/// Customer value segments distribution configuration.
6627#[derive(Debug, Clone, Serialize, Deserialize)]
6628pub struct ValueSegmentsSchemaConfig {
6629    /// Enterprise segment configuration.
6630    #[serde(default)]
6631    pub enterprise: SegmentDetailSchemaConfig,
6632
6633    /// Mid-market segment configuration.
6634    #[serde(default)]
6635    pub mid_market: SegmentDetailSchemaConfig,
6636
6637    /// SMB segment configuration.
6638    #[serde(default)]
6639    pub smb: SegmentDetailSchemaConfig,
6640
6641    /// Consumer segment configuration.
6642    #[serde(default)]
6643    pub consumer: SegmentDetailSchemaConfig,
6644}
6645
6646impl Default for ValueSegmentsSchemaConfig {
6647    fn default() -> Self {
6648        Self {
6649            enterprise: SegmentDetailSchemaConfig {
6650                revenue_share: 0.40,
6651                customer_share: 0.05,
6652                avg_order_value_range: "50000+".to_string(),
6653            },
6654            mid_market: SegmentDetailSchemaConfig {
6655                revenue_share: 0.35,
6656                customer_share: 0.20,
6657                avg_order_value_range: "5000-50000".to_string(),
6658            },
6659            smb: SegmentDetailSchemaConfig {
6660                revenue_share: 0.20,
6661                customer_share: 0.50,
6662                avg_order_value_range: "500-5000".to_string(),
6663            },
6664            consumer: SegmentDetailSchemaConfig {
6665                revenue_share: 0.05,
6666                customer_share: 0.25,
6667                avg_order_value_range: "50-500".to_string(),
6668            },
6669        }
6670    }
6671}
6672
6673/// Individual segment detail configuration.
6674#[derive(Debug, Clone, Serialize, Deserialize)]
6675pub struct SegmentDetailSchemaConfig {
6676    /// Revenue share for this segment.
6677    #[serde(default)]
6678    pub revenue_share: f64,
6679
6680    /// Customer share for this segment.
6681    #[serde(default)]
6682    pub customer_share: f64,
6683
6684    /// Average order value range (e.g., "5000-50000" or "50000+").
6685    #[serde(default)]
6686    pub avg_order_value_range: String,
6687}
6688
6689impl Default for SegmentDetailSchemaConfig {
6690    fn default() -> Self {
6691        Self {
6692            revenue_share: 0.25,
6693            customer_share: 0.25,
6694            avg_order_value_range: "1000-10000".to_string(),
6695        }
6696    }
6697}
6698
6699/// Customer lifecycle stage configuration.
6700#[derive(Debug, Clone, Serialize, Deserialize)]
6701pub struct LifecycleSchemaConfig {
6702    /// Prospect stage rate.
6703    #[serde(default)]
6704    pub prospect_rate: f64,
6705
6706    /// New customer stage rate.
6707    #[serde(default = "default_new_rate")]
6708    pub new_rate: f64,
6709
6710    /// Growth stage rate.
6711    #[serde(default = "default_growth_rate")]
6712    pub growth_rate: f64,
6713
6714    /// Mature stage rate.
6715    #[serde(default = "default_mature_rate")]
6716    pub mature_rate: f64,
6717
6718    /// At-risk stage rate.
6719    #[serde(default = "default_at_risk_rate")]
6720    pub at_risk_rate: f64,
6721
6722    /// Churned stage rate.
6723    #[serde(default = "default_churned_rate")]
6724    pub churned_rate: f64,
6725}
6726
6727fn default_new_rate() -> f64 {
6728    0.10
6729}
6730
6731fn default_growth_rate() -> f64 {
6732    0.15
6733}
6734
6735fn default_mature_rate() -> f64 {
6736    0.60
6737}
6738
6739fn default_at_risk_rate() -> f64 {
6740    0.10
6741}
6742
6743fn default_churned_rate() -> f64 {
6744    0.05
6745}
6746
6747impl Default for LifecycleSchemaConfig {
6748    fn default() -> Self {
6749        Self {
6750            prospect_rate: 0.0,
6751            new_rate: 0.10,
6752            growth_rate: 0.15,
6753            mature_rate: 0.60,
6754            at_risk_rate: 0.10,
6755            churned_rate: 0.05,
6756        }
6757    }
6758}
6759
6760/// Customer networks configuration (referrals, hierarchies).
6761#[derive(Debug, Clone, Default, Serialize, Deserialize)]
6762pub struct CustomerNetworksSchemaConfig {
6763    /// Referral network configuration.
6764    #[serde(default)]
6765    pub referrals: ReferralSchemaConfig,
6766
6767    /// Corporate hierarchy configuration.
6768    #[serde(default)]
6769    pub corporate_hierarchies: HierarchySchemaConfig,
6770}
6771
6772/// Referral network configuration.
6773#[derive(Debug, Clone, Serialize, Deserialize)]
6774pub struct ReferralSchemaConfig {
6775    /// Enable referral generation.
6776    #[serde(default = "default_true")]
6777    pub enabled: bool,
6778
6779    /// Rate of customers acquired via referral.
6780    #[serde(default = "default_referral_rate")]
6781    pub referral_rate: f64,
6782}
6783
6784fn default_referral_rate() -> f64 {
6785    0.15
6786}
6787
6788impl Default for ReferralSchemaConfig {
6789    fn default() -> Self {
6790        Self {
6791            enabled: true,
6792            referral_rate: 0.15,
6793        }
6794    }
6795}
6796
6797/// Corporate hierarchy configuration.
6798#[derive(Debug, Clone, Serialize, Deserialize)]
6799pub struct HierarchySchemaConfig {
6800    /// Enable corporate hierarchy generation.
6801    #[serde(default = "default_true")]
6802    pub enabled: bool,
6803
6804    /// Rate of customers in hierarchies.
6805    #[serde(default = "default_hierarchy_rate")]
6806    pub probability: f64,
6807}
6808
6809fn default_hierarchy_rate() -> f64 {
6810    0.30
6811}
6812
6813impl Default for HierarchySchemaConfig {
6814    fn default() -> Self {
6815        Self {
6816            enabled: true,
6817            probability: 0.30,
6818        }
6819    }
6820}
6821
6822// =============================================================================
6823// Relationship Strength Configuration
6824// =============================================================================
6825
6826/// Configuration for relationship strength calculation.
6827#[derive(Debug, Clone, Default, Serialize, Deserialize)]
6828pub struct RelationshipStrengthSchemaConfig {
6829    /// Enable relationship strength calculation.
6830    #[serde(default)]
6831    pub enabled: bool,
6832
6833    /// Calculation weights.
6834    #[serde(default)]
6835    pub calculation: StrengthCalculationSchemaConfig,
6836
6837    /// Strength thresholds for classification.
6838    #[serde(default)]
6839    pub thresholds: StrengthThresholdsSchemaConfig,
6840}
6841
6842/// Strength calculation weights configuration.
6843#[derive(Debug, Clone, Serialize, Deserialize)]
6844pub struct StrengthCalculationSchemaConfig {
6845    /// Weight for transaction volume (default: 0.30).
6846    #[serde(default = "default_volume_weight")]
6847    pub transaction_volume_weight: f64,
6848
6849    /// Weight for transaction count (default: 0.25).
6850    #[serde(default = "default_count_weight")]
6851    pub transaction_count_weight: f64,
6852
6853    /// Weight for relationship duration (default: 0.20).
6854    #[serde(default = "default_duration_weight")]
6855    pub relationship_duration_weight: f64,
6856
6857    /// Weight for recency (default: 0.15).
6858    #[serde(default = "default_recency_weight")]
6859    pub recency_weight: f64,
6860
6861    /// Weight for mutual connections (default: 0.10).
6862    #[serde(default = "default_mutual_weight")]
6863    pub mutual_connections_weight: f64,
6864
6865    /// Recency half-life in days (default: 90).
6866    #[serde(default = "default_recency_half_life")]
6867    pub recency_half_life_days: u32,
6868}
6869
6870fn default_volume_weight() -> f64 {
6871    0.30
6872}
6873
6874fn default_count_weight() -> f64 {
6875    0.25
6876}
6877
6878fn default_duration_weight() -> f64 {
6879    0.20
6880}
6881
6882fn default_recency_weight() -> f64 {
6883    0.15
6884}
6885
6886fn default_mutual_weight() -> f64 {
6887    0.10
6888}
6889
6890fn default_recency_half_life() -> u32 {
6891    90
6892}
6893
6894impl Default for StrengthCalculationSchemaConfig {
6895    fn default() -> Self {
6896        Self {
6897            transaction_volume_weight: 0.30,
6898            transaction_count_weight: 0.25,
6899            relationship_duration_weight: 0.20,
6900            recency_weight: 0.15,
6901            mutual_connections_weight: 0.10,
6902            recency_half_life_days: 90,
6903        }
6904    }
6905}
6906
6907/// Strength thresholds for relationship classification.
6908#[derive(Debug, Clone, Serialize, Deserialize)]
6909pub struct StrengthThresholdsSchemaConfig {
6910    /// Threshold for strong relationships (default: 0.7).
6911    #[serde(default = "default_strong_threshold")]
6912    pub strong: f64,
6913
6914    /// Threshold for moderate relationships (default: 0.4).
6915    #[serde(default = "default_moderate_threshold")]
6916    pub moderate: f64,
6917
6918    /// Threshold for weak relationships (default: 0.1).
6919    #[serde(default = "default_weak_threshold")]
6920    pub weak: f64,
6921}
6922
6923fn default_strong_threshold() -> f64 {
6924    0.7
6925}
6926
6927fn default_moderate_threshold() -> f64 {
6928    0.4
6929}
6930
6931fn default_weak_threshold() -> f64 {
6932    0.1
6933}
6934
6935impl Default for StrengthThresholdsSchemaConfig {
6936    fn default() -> Self {
6937        Self {
6938            strong: 0.7,
6939            moderate: 0.4,
6940            weak: 0.1,
6941        }
6942    }
6943}
6944
6945// =============================================================================
6946// Cross-Process Links Configuration
6947// =============================================================================
6948
6949/// Configuration for cross-process linkages.
6950#[derive(Debug, Clone, Serialize, Deserialize)]
6951pub struct CrossProcessLinksSchemaConfig {
6952    /// Enable cross-process link generation.
6953    #[serde(default)]
6954    pub enabled: bool,
6955
6956    /// Enable inventory links between P2P and O2C.
6957    #[serde(default = "default_true")]
6958    pub inventory_p2p_o2c: bool,
6959
6960    /// Enable payment to bank reconciliation links.
6961    #[serde(default = "default_true")]
6962    pub payment_bank_reconciliation: bool,
6963
6964    /// Enable intercompany bilateral matching.
6965    #[serde(default = "default_true")]
6966    pub intercompany_bilateral: bool,
6967
6968    /// Percentage of GR/Deliveries to link via inventory (0.0 - 1.0).
6969    #[serde(default = "default_inventory_link_rate")]
6970    pub inventory_link_rate: f64,
6971}
6972
6973fn default_inventory_link_rate() -> f64 {
6974    0.30
6975}
6976
6977impl Default for CrossProcessLinksSchemaConfig {
6978    fn default() -> Self {
6979        Self {
6980            enabled: false,
6981            inventory_p2p_o2c: true,
6982            payment_bank_reconciliation: true,
6983            intercompany_bilateral: true,
6984            inventory_link_rate: 0.30,
6985        }
6986    }
6987}
6988
6989// =============================================================================
6990// Organizational Events Configuration
6991// =============================================================================
6992
6993/// Configuration for organizational events (acquisitions, divestitures, etc.).
6994#[derive(Debug, Clone, Serialize, Deserialize, Default)]
6995pub struct OrganizationalEventsSchemaConfig {
6996    /// Enable organizational events.
6997    #[serde(default)]
6998    pub enabled: bool,
6999
7000    /// Effect blending mode (multiplicative, additive, maximum, minimum).
7001    #[serde(default)]
7002    pub effect_blending: EffectBlendingModeConfig,
7003
7004    /// Organizational events (acquisitions, divestitures, reorganizations, etc.).
7005    #[serde(default)]
7006    pub events: Vec<OrganizationalEventSchemaConfig>,
7007
7008    /// Process evolution events.
7009    #[serde(default)]
7010    pub process_evolution: Vec<ProcessEvolutionSchemaConfig>,
7011
7012    /// Technology transition events.
7013    #[serde(default)]
7014    pub technology_transitions: Vec<TechnologyTransitionSchemaConfig>,
7015}
7016
7017/// Effect blending mode for combining multiple event effects.
7018#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
7019#[serde(rename_all = "snake_case")]
7020pub enum EffectBlendingModeConfig {
7021    /// Multiply effects together.
7022    #[default]
7023    Multiplicative,
7024    /// Add effects together.
7025    Additive,
7026    /// Take the maximum effect.
7027    Maximum,
7028    /// Take the minimum effect.
7029    Minimum,
7030}
7031
7032/// Configuration for a single organizational event.
7033#[derive(Debug, Clone, Serialize, Deserialize)]
7034pub struct OrganizationalEventSchemaConfig {
7035    /// Event ID.
7036    pub id: String,
7037
7038    /// Event type and configuration.
7039    pub event_type: OrganizationalEventTypeSchemaConfig,
7040
7041    /// Effective date.
7042    pub effective_date: String,
7043
7044    /// Transition duration in months.
7045    #[serde(default = "default_org_transition_months")]
7046    pub transition_months: u32,
7047
7048    /// Description.
7049    #[serde(default)]
7050    pub description: Option<String>,
7051}
7052
7053fn default_org_transition_months() -> u32 {
7054    6
7055}
7056
7057/// Organizational event type configuration.
7058#[derive(Debug, Clone, Serialize, Deserialize)]
7059#[serde(tag = "type", rename_all = "snake_case")]
7060pub enum OrganizationalEventTypeSchemaConfig {
7061    /// Acquisition event.
7062    Acquisition {
7063        /// Acquired entity code.
7064        acquired_entity: String,
7065        /// Volume increase multiplier.
7066        #[serde(default = "default_acquisition_volume")]
7067        volume_increase: f64,
7068        /// Integration error rate.
7069        #[serde(default = "default_acquisition_error")]
7070        integration_error_rate: f64,
7071        /// Parallel posting days.
7072        #[serde(default = "default_parallel_days")]
7073        parallel_posting_days: u32,
7074    },
7075    /// Divestiture event.
7076    Divestiture {
7077        /// Divested entity code.
7078        divested_entity: String,
7079        /// Volume reduction factor.
7080        #[serde(default = "default_divestiture_volume")]
7081        volume_reduction: f64,
7082        /// Remove entity from generation.
7083        #[serde(default = "default_true_val")]
7084        remove_entity: bool,
7085    },
7086    /// Reorganization event.
7087    Reorganization {
7088        /// Cost center remapping.
7089        #[serde(default)]
7090        cost_center_remapping: std::collections::HashMap<String, String>,
7091        /// Transition error rate.
7092        #[serde(default = "default_reorg_error")]
7093        transition_error_rate: f64,
7094    },
7095    /// Leadership change event.
7096    LeadershipChange {
7097        /// Role that changed.
7098        role: String,
7099        /// Policy changes.
7100        #[serde(default)]
7101        policy_changes: Vec<String>,
7102    },
7103    /// Workforce reduction event.
7104    WorkforceReduction {
7105        /// Reduction percentage.
7106        #[serde(default = "default_workforce_reduction")]
7107        reduction_percent: f64,
7108        /// Error rate increase.
7109        #[serde(default = "default_workforce_error")]
7110        error_rate_increase: f64,
7111    },
7112    /// Merger event.
7113    Merger {
7114        /// Merged entity code.
7115        merged_entity: String,
7116        /// Volume increase multiplier.
7117        #[serde(default = "default_merger_volume")]
7118        volume_increase: f64,
7119    },
7120}
7121
7122fn default_acquisition_volume() -> f64 {
7123    1.35
7124}
7125
7126fn default_acquisition_error() -> f64 {
7127    0.05
7128}
7129
7130fn default_parallel_days() -> u32 {
7131    30
7132}
7133
7134fn default_divestiture_volume() -> f64 {
7135    0.70
7136}
7137
7138fn default_true_val() -> bool {
7139    true
7140}
7141
7142fn default_reorg_error() -> f64 {
7143    0.04
7144}
7145
7146fn default_workforce_reduction() -> f64 {
7147    0.10
7148}
7149
7150fn default_workforce_error() -> f64 {
7151    0.05
7152}
7153
7154fn default_merger_volume() -> f64 {
7155    1.80
7156}
7157
7158/// Configuration for a process evolution event.
7159#[derive(Debug, Clone, Serialize, Deserialize)]
7160pub struct ProcessEvolutionSchemaConfig {
7161    /// Event ID.
7162    pub id: String,
7163
7164    /// Event type.
7165    pub event_type: ProcessEvolutionTypeSchemaConfig,
7166
7167    /// Effective date.
7168    pub effective_date: String,
7169
7170    /// Description.
7171    #[serde(default)]
7172    pub description: Option<String>,
7173}
7174
7175/// Process evolution type configuration.
7176#[derive(Debug, Clone, Serialize, Deserialize)]
7177#[serde(tag = "type", rename_all = "snake_case")]
7178pub enum ProcessEvolutionTypeSchemaConfig {
7179    /// Process automation.
7180    ProcessAutomation {
7181        /// Process name.
7182        process_name: String,
7183        /// Manual rate before.
7184        #[serde(default = "default_manual_before")]
7185        manual_rate_before: f64,
7186        /// Manual rate after.
7187        #[serde(default = "default_manual_after")]
7188        manual_rate_after: f64,
7189    },
7190    /// Approval workflow change.
7191    ApprovalWorkflowChange {
7192        /// Description.
7193        description: String,
7194    },
7195    /// Control enhancement.
7196    ControlEnhancement {
7197        /// Control ID.
7198        control_id: String,
7199        /// Error reduction.
7200        #[serde(default = "default_error_reduction")]
7201        error_reduction: f64,
7202    },
7203}
7204
7205fn default_manual_before() -> f64 {
7206    0.80
7207}
7208
7209fn default_manual_after() -> f64 {
7210    0.15
7211}
7212
7213fn default_error_reduction() -> f64 {
7214    0.02
7215}
7216
7217/// Configuration for a technology transition event.
7218#[derive(Debug, Clone, Serialize, Deserialize)]
7219pub struct TechnologyTransitionSchemaConfig {
7220    /// Event ID.
7221    pub id: String,
7222
7223    /// Event type.
7224    pub event_type: TechnologyTransitionTypeSchemaConfig,
7225
7226    /// Description.
7227    #[serde(default)]
7228    pub description: Option<String>,
7229}
7230
7231/// Technology transition type configuration.
7232#[derive(Debug, Clone, Serialize, Deserialize)]
7233#[serde(tag = "type", rename_all = "snake_case")]
7234pub enum TechnologyTransitionTypeSchemaConfig {
7235    /// ERP migration.
7236    ErpMigration {
7237        /// Source system.
7238        source_system: String,
7239        /// Target system.
7240        target_system: String,
7241        /// Cutover date.
7242        cutover_date: String,
7243        /// Stabilization end date.
7244        stabilization_end: String,
7245        /// Duplicate rate during migration.
7246        #[serde(default = "default_erp_duplicate_rate")]
7247        duplicate_rate: f64,
7248        /// Format mismatch rate.
7249        #[serde(default = "default_format_mismatch")]
7250        format_mismatch_rate: f64,
7251    },
7252    /// Module implementation.
7253    ModuleImplementation {
7254        /// Module name.
7255        module_name: String,
7256        /// Go-live date.
7257        go_live_date: String,
7258    },
7259}
7260
7261fn default_erp_duplicate_rate() -> f64 {
7262    0.02
7263}
7264
7265fn default_format_mismatch() -> f64 {
7266    0.03
7267}
7268
7269// =============================================================================
7270// Behavioral Drift Configuration
7271// =============================================================================
7272
7273/// Configuration for behavioral drift (vendor, customer, employee behavior).
7274#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7275pub struct BehavioralDriftSchemaConfig {
7276    /// Enable behavioral drift.
7277    #[serde(default)]
7278    pub enabled: bool,
7279
7280    /// Vendor behavior drift.
7281    #[serde(default)]
7282    pub vendor_behavior: VendorBehaviorSchemaConfig,
7283
7284    /// Customer behavior drift.
7285    #[serde(default)]
7286    pub customer_behavior: CustomerBehaviorSchemaConfig,
7287
7288    /// Employee behavior drift.
7289    #[serde(default)]
7290    pub employee_behavior: EmployeeBehaviorSchemaConfig,
7291
7292    /// Collective behavior drift.
7293    #[serde(default)]
7294    pub collective: CollectiveBehaviorSchemaConfig,
7295}
7296
7297/// Vendor behavior drift configuration.
7298#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7299pub struct VendorBehaviorSchemaConfig {
7300    /// Payment terms drift.
7301    #[serde(default)]
7302    pub payment_terms_drift: PaymentTermsDriftSchemaConfig,
7303
7304    /// Quality drift.
7305    #[serde(default)]
7306    pub quality_drift: QualityDriftSchemaConfig,
7307}
7308
7309/// Payment terms drift configuration.
7310#[derive(Debug, Clone, Serialize, Deserialize)]
7311pub struct PaymentTermsDriftSchemaConfig {
7312    /// Extension rate per year (days).
7313    #[serde(default = "default_extension_rate")]
7314    pub extension_rate_per_year: f64,
7315
7316    /// Economic sensitivity.
7317    #[serde(default = "default_economic_sensitivity")]
7318    pub economic_sensitivity: f64,
7319}
7320
7321fn default_extension_rate() -> f64 {
7322    2.5
7323}
7324
7325fn default_economic_sensitivity() -> f64 {
7326    1.0
7327}
7328
7329impl Default for PaymentTermsDriftSchemaConfig {
7330    fn default() -> Self {
7331        Self {
7332            extension_rate_per_year: 2.5,
7333            economic_sensitivity: 1.0,
7334        }
7335    }
7336}
7337
7338/// Quality drift configuration.
7339#[derive(Debug, Clone, Serialize, Deserialize)]
7340pub struct QualityDriftSchemaConfig {
7341    /// New vendor improvement rate (per year).
7342    #[serde(default = "default_improvement_rate")]
7343    pub new_vendor_improvement_rate: f64,
7344
7345    /// Complacency decline rate (per year after first year).
7346    #[serde(default = "default_decline_rate")]
7347    pub complacency_decline_rate: f64,
7348}
7349
7350fn default_improvement_rate() -> f64 {
7351    0.02
7352}
7353
7354fn default_decline_rate() -> f64 {
7355    0.01
7356}
7357
7358impl Default for QualityDriftSchemaConfig {
7359    fn default() -> Self {
7360        Self {
7361            new_vendor_improvement_rate: 0.02,
7362            complacency_decline_rate: 0.01,
7363        }
7364    }
7365}
7366
7367/// Customer behavior drift configuration.
7368#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7369pub struct CustomerBehaviorSchemaConfig {
7370    /// Payment drift.
7371    #[serde(default)]
7372    pub payment_drift: CustomerPaymentDriftSchemaConfig,
7373
7374    /// Order drift.
7375    #[serde(default)]
7376    pub order_drift: OrderDriftSchemaConfig,
7377}
7378
7379/// Customer payment drift configuration.
7380#[derive(Debug, Clone, Serialize, Deserialize)]
7381pub struct CustomerPaymentDriftSchemaConfig {
7382    /// Days extension during downturn (min, max).
7383    #[serde(default = "default_downturn_extension")]
7384    pub downturn_days_extension: (u32, u32),
7385
7386    /// Bad debt increase during downturn.
7387    #[serde(default = "default_bad_debt_increase")]
7388    pub downturn_bad_debt_increase: f64,
7389}
7390
7391fn default_downturn_extension() -> (u32, u32) {
7392    (5, 15)
7393}
7394
7395fn default_bad_debt_increase() -> f64 {
7396    0.02
7397}
7398
7399impl Default for CustomerPaymentDriftSchemaConfig {
7400    fn default() -> Self {
7401        Self {
7402            downturn_days_extension: (5, 15),
7403            downturn_bad_debt_increase: 0.02,
7404        }
7405    }
7406}
7407
7408/// Order drift configuration.
7409#[derive(Debug, Clone, Serialize, Deserialize)]
7410pub struct OrderDriftSchemaConfig {
7411    /// Digital shift rate (per year).
7412    #[serde(default = "default_digital_shift")]
7413    pub digital_shift_rate: f64,
7414}
7415
7416fn default_digital_shift() -> f64 {
7417    0.05
7418}
7419
7420impl Default for OrderDriftSchemaConfig {
7421    fn default() -> Self {
7422        Self {
7423            digital_shift_rate: 0.05,
7424        }
7425    }
7426}
7427
7428/// Employee behavior drift configuration.
7429#[derive(Debug, Clone, Default, Serialize, Deserialize)]
7430pub struct EmployeeBehaviorSchemaConfig {
7431    /// Approval drift.
7432    #[serde(default)]
7433    pub approval_drift: ApprovalDriftSchemaConfig,
7434
7435    /// Error drift.
7436    #[serde(default)]
7437    pub error_drift: ErrorDriftSchemaConfig,
7438}
7439
7440/// Approval drift configuration.
7441#[derive(Debug, Clone, Serialize, Deserialize)]
7442pub struct ApprovalDriftSchemaConfig {
7443    /// EOM intensity increase per year.
7444    #[serde(default = "default_eom_intensity")]
7445    pub eom_intensity_increase_per_year: f64,
7446
7447    /// Rubber stamp volume threshold.
7448    #[serde(default = "default_rubber_stamp")]
7449    pub rubber_stamp_volume_threshold: u32,
7450}
7451
7452fn default_eom_intensity() -> f64 {
7453    0.05
7454}
7455
7456fn default_rubber_stamp() -> u32 {
7457    50
7458}
7459
7460impl Default for ApprovalDriftSchemaConfig {
7461    fn default() -> Self {
7462        Self {
7463            eom_intensity_increase_per_year: 0.05,
7464            rubber_stamp_volume_threshold: 50,
7465        }
7466    }
7467}
7468
7469/// Error drift configuration.
7470#[derive(Debug, Clone, Serialize, Deserialize)]
7471pub struct ErrorDriftSchemaConfig {
7472    /// New employee error rate.
7473    #[serde(default = "default_new_error")]
7474    pub new_employee_error_rate: f64,
7475
7476    /// Learning curve months.
7477    #[serde(default = "default_learning_months")]
7478    pub learning_curve_months: u32,
7479}
7480
7481fn default_new_error() -> f64 {
7482    0.08
7483}
7484
7485fn default_learning_months() -> u32 {
7486    6
7487}
7488
7489impl Default for ErrorDriftSchemaConfig {
7490    fn default() -> Self {
7491        Self {
7492            new_employee_error_rate: 0.08,
7493            learning_curve_months: 6,
7494        }
7495    }
7496}
7497
7498/// Collective behavior drift configuration.
7499#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7500pub struct CollectiveBehaviorSchemaConfig {
7501    /// Automation adoption configuration.
7502    #[serde(default)]
7503    pub automation_adoption: AutomationAdoptionSchemaConfig,
7504}
7505
7506/// Automation adoption configuration.
7507#[derive(Debug, Clone, Serialize, Deserialize)]
7508pub struct AutomationAdoptionSchemaConfig {
7509    /// Enable S-curve adoption model.
7510    #[serde(default)]
7511    pub s_curve_enabled: bool,
7512
7513    /// Adoption midpoint in months.
7514    #[serde(default = "default_midpoint")]
7515    pub adoption_midpoint_months: u32,
7516
7517    /// Steepness of adoption curve.
7518    #[serde(default = "default_steepness")]
7519    pub steepness: f64,
7520}
7521
7522fn default_midpoint() -> u32 {
7523    24
7524}
7525
7526fn default_steepness() -> f64 {
7527    0.15
7528}
7529
7530impl Default for AutomationAdoptionSchemaConfig {
7531    fn default() -> Self {
7532        Self {
7533            s_curve_enabled: false,
7534            adoption_midpoint_months: 24,
7535            steepness: 0.15,
7536        }
7537    }
7538}
7539
7540// =============================================================================
7541// Market Drift Configuration
7542// =============================================================================
7543
7544/// Configuration for market drift (economic cycles, commodities, price shocks).
7545#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7546pub struct MarketDriftSchemaConfig {
7547    /// Enable market drift.
7548    #[serde(default)]
7549    pub enabled: bool,
7550
7551    /// Economic cycle configuration.
7552    #[serde(default)]
7553    pub economic_cycle: MarketEconomicCycleSchemaConfig,
7554
7555    /// Industry-specific cycles.
7556    #[serde(default)]
7557    pub industry_cycles: std::collections::HashMap<String, IndustryCycleSchemaConfig>,
7558
7559    /// Commodity drift configuration.
7560    #[serde(default)]
7561    pub commodities: CommoditiesSchemaConfig,
7562}
7563
7564/// Market economic cycle configuration.
7565#[derive(Debug, Clone, Serialize, Deserialize)]
7566pub struct MarketEconomicCycleSchemaConfig {
7567    /// Enable economic cycle.
7568    #[serde(default)]
7569    pub enabled: bool,
7570
7571    /// Cycle type.
7572    #[serde(default)]
7573    pub cycle_type: CycleTypeSchemaConfig,
7574
7575    /// Cycle period in months.
7576    #[serde(default = "default_market_cycle_period")]
7577    pub period_months: u32,
7578
7579    /// Amplitude.
7580    #[serde(default = "default_market_amplitude")]
7581    pub amplitude: f64,
7582
7583    /// Recession configuration.
7584    #[serde(default)]
7585    pub recession: RecessionSchemaConfig,
7586}
7587
7588fn default_market_cycle_period() -> u32 {
7589    48
7590}
7591
7592fn default_market_amplitude() -> f64 {
7593    0.15
7594}
7595
7596impl Default for MarketEconomicCycleSchemaConfig {
7597    fn default() -> Self {
7598        Self {
7599            enabled: false,
7600            cycle_type: CycleTypeSchemaConfig::Sinusoidal,
7601            period_months: 48,
7602            amplitude: 0.15,
7603            recession: RecessionSchemaConfig::default(),
7604        }
7605    }
7606}
7607
7608/// Cycle type configuration.
7609#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
7610#[serde(rename_all = "snake_case")]
7611pub enum CycleTypeSchemaConfig {
7612    /// Sinusoidal cycle.
7613    #[default]
7614    Sinusoidal,
7615    /// Asymmetric cycle.
7616    Asymmetric,
7617    /// Mean-reverting cycle.
7618    MeanReverting,
7619}
7620
7621/// Recession configuration.
7622#[derive(Debug, Clone, Serialize, Deserialize)]
7623pub struct RecessionSchemaConfig {
7624    /// Enable recession simulation.
7625    #[serde(default)]
7626    pub enabled: bool,
7627
7628    /// Probability per year.
7629    #[serde(default = "default_recession_prob")]
7630    pub probability_per_year: f64,
7631
7632    /// Severity.
7633    #[serde(default)]
7634    pub severity: RecessionSeveritySchemaConfig,
7635
7636    /// Specific recession periods.
7637    #[serde(default)]
7638    pub recession_periods: Vec<RecessionPeriodSchemaConfig>,
7639}
7640
7641fn default_recession_prob() -> f64 {
7642    0.10
7643}
7644
7645impl Default for RecessionSchemaConfig {
7646    fn default() -> Self {
7647        Self {
7648            enabled: false,
7649            probability_per_year: 0.10,
7650            severity: RecessionSeveritySchemaConfig::Moderate,
7651            recession_periods: Vec::new(),
7652        }
7653    }
7654}
7655
7656/// Recession severity configuration.
7657#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
7658#[serde(rename_all = "snake_case")]
7659pub enum RecessionSeveritySchemaConfig {
7660    /// Mild recession.
7661    Mild,
7662    /// Moderate recession.
7663    #[default]
7664    Moderate,
7665    /// Severe recession.
7666    Severe,
7667}
7668
7669/// Recession period configuration.
7670#[derive(Debug, Clone, Serialize, Deserialize)]
7671pub struct RecessionPeriodSchemaConfig {
7672    /// Start month.
7673    pub start_month: u32,
7674    /// Duration in months.
7675    pub duration_months: u32,
7676}
7677
7678/// Industry cycle configuration.
7679#[derive(Debug, Clone, Serialize, Deserialize)]
7680pub struct IndustryCycleSchemaConfig {
7681    /// Period in months.
7682    #[serde(default = "default_industry_period")]
7683    pub period_months: u32,
7684
7685    /// Amplitude.
7686    #[serde(default = "default_industry_amp")]
7687    pub amplitude: f64,
7688}
7689
7690fn default_industry_period() -> u32 {
7691    36
7692}
7693
7694fn default_industry_amp() -> f64 {
7695    0.20
7696}
7697
7698/// Commodities drift configuration.
7699#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7700pub struct CommoditiesSchemaConfig {
7701    /// Enable commodity drift.
7702    #[serde(default)]
7703    pub enabled: bool,
7704
7705    /// Commodity items.
7706    #[serde(default)]
7707    pub items: Vec<CommodityItemSchemaConfig>,
7708}
7709
7710/// Commodity item configuration.
7711#[derive(Debug, Clone, Serialize, Deserialize)]
7712pub struct CommodityItemSchemaConfig {
7713    /// Commodity name.
7714    pub name: String,
7715
7716    /// Volatility.
7717    #[serde(default = "default_volatility")]
7718    pub volatility: f64,
7719
7720    /// COGS pass-through.
7721    #[serde(default)]
7722    pub cogs_pass_through: f64,
7723
7724    /// Overhead pass-through.
7725    #[serde(default)]
7726    pub overhead_pass_through: f64,
7727}
7728
7729fn default_volatility() -> f64 {
7730    0.20
7731}
7732
7733// =============================================================================
7734// Drift Labeling Configuration
7735// =============================================================================
7736
7737/// Configuration for drift ground truth labeling.
7738#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7739pub struct DriftLabelingSchemaConfig {
7740    /// Enable drift labeling.
7741    #[serde(default)]
7742    pub enabled: bool,
7743
7744    /// Statistical drift labeling.
7745    #[serde(default)]
7746    pub statistical: StatisticalDriftLabelingSchemaConfig,
7747
7748    /// Categorical drift labeling.
7749    #[serde(default)]
7750    pub categorical: CategoricalDriftLabelingSchemaConfig,
7751
7752    /// Temporal drift labeling.
7753    #[serde(default)]
7754    pub temporal: TemporalDriftLabelingSchemaConfig,
7755
7756    /// Regulatory calendar preset.
7757    #[serde(default)]
7758    pub regulatory_calendar_preset: Option<String>,
7759}
7760
7761/// Statistical drift labeling configuration.
7762#[derive(Debug, Clone, Serialize, Deserialize)]
7763pub struct StatisticalDriftLabelingSchemaConfig {
7764    /// Enable statistical drift labeling.
7765    #[serde(default = "default_true_val")]
7766    pub enabled: bool,
7767
7768    /// Minimum magnitude threshold.
7769    #[serde(default = "default_min_magnitude")]
7770    pub min_magnitude_threshold: f64,
7771}
7772
7773fn default_min_magnitude() -> f64 {
7774    0.05
7775}
7776
7777impl Default for StatisticalDriftLabelingSchemaConfig {
7778    fn default() -> Self {
7779        Self {
7780            enabled: true,
7781            min_magnitude_threshold: 0.05,
7782        }
7783    }
7784}
7785
7786/// Categorical drift labeling configuration.
7787#[derive(Debug, Clone, Serialize, Deserialize)]
7788pub struct CategoricalDriftLabelingSchemaConfig {
7789    /// Enable categorical drift labeling.
7790    #[serde(default = "default_true_val")]
7791    pub enabled: bool,
7792}
7793
7794impl Default for CategoricalDriftLabelingSchemaConfig {
7795    fn default() -> Self {
7796        Self { enabled: true }
7797    }
7798}
7799
7800/// Temporal drift labeling configuration.
7801#[derive(Debug, Clone, Serialize, Deserialize)]
7802pub struct TemporalDriftLabelingSchemaConfig {
7803    /// Enable temporal drift labeling.
7804    #[serde(default = "default_true_val")]
7805    pub enabled: bool,
7806}
7807
7808impl Default for TemporalDriftLabelingSchemaConfig {
7809    fn default() -> Self {
7810        Self { enabled: true }
7811    }
7812}
7813
7814// =============================================================================
7815// Enhanced Anomaly Injection Configuration
7816// =============================================================================
7817
7818/// Enhanced anomaly injection configuration.
7819///
7820/// Provides comprehensive anomaly injection capabilities including:
7821/// - Multi-stage fraud schemes (embezzlement, revenue manipulation, kickbacks)
7822/// - Correlated anomaly injection (co-occurrence patterns, error cascades)
7823/// - Near-miss generation for false positive reduction
7824/// - Detection difficulty classification
7825/// - Context-aware injection based on entity behavior
7826#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7827pub struct EnhancedAnomalyConfig {
7828    /// Enable enhanced anomaly injection.
7829    #[serde(default)]
7830    pub enabled: bool,
7831
7832    /// Base anomaly rates.
7833    #[serde(default)]
7834    pub rates: AnomalyRateConfig,
7835
7836    /// Multi-stage fraud scheme configuration.
7837    #[serde(default)]
7838    pub multi_stage_schemes: MultiStageSchemeConfig,
7839
7840    /// Correlated anomaly injection configuration.
7841    #[serde(default)]
7842    pub correlated_injection: CorrelatedInjectionConfig,
7843
7844    /// Near-miss generation configuration.
7845    #[serde(default)]
7846    pub near_miss: NearMissConfig,
7847
7848    /// Detection difficulty classification configuration.
7849    #[serde(default)]
7850    pub difficulty_classification: DifficultyClassificationConfig,
7851
7852    /// Context-aware injection configuration.
7853    #[serde(default)]
7854    pub context_aware: ContextAwareConfig,
7855
7856    /// Enhanced labeling configuration.
7857    #[serde(default)]
7858    pub labeling: EnhancedLabelingConfig,
7859}
7860
7861/// Base anomaly rate configuration.
7862#[derive(Debug, Clone, Serialize, Deserialize)]
7863pub struct AnomalyRateConfig {
7864    /// Total anomaly rate (0.0 to 1.0).
7865    #[serde(default = "default_total_anomaly_rate")]
7866    pub total_rate: f64,
7867
7868    /// Fraud anomaly rate.
7869    #[serde(default = "default_fraud_anomaly_rate")]
7870    pub fraud_rate: f64,
7871
7872    /// Error anomaly rate.
7873    #[serde(default = "default_error_anomaly_rate")]
7874    pub error_rate: f64,
7875
7876    /// Process issue rate.
7877    #[serde(default = "default_process_anomaly_rate")]
7878    pub process_rate: f64,
7879}
7880
7881fn default_total_anomaly_rate() -> f64 {
7882    0.03
7883}
7884fn default_fraud_anomaly_rate() -> f64 {
7885    0.01
7886}
7887fn default_error_anomaly_rate() -> f64 {
7888    0.015
7889}
7890fn default_process_anomaly_rate() -> f64 {
7891    0.005
7892}
7893
7894impl Default for AnomalyRateConfig {
7895    fn default() -> Self {
7896        Self {
7897            total_rate: default_total_anomaly_rate(),
7898            fraud_rate: default_fraud_anomaly_rate(),
7899            error_rate: default_error_anomaly_rate(),
7900            process_rate: default_process_anomaly_rate(),
7901        }
7902    }
7903}
7904
7905/// Multi-stage fraud scheme configuration.
7906#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7907pub struct MultiStageSchemeConfig {
7908    /// Enable multi-stage fraud schemes.
7909    #[serde(default)]
7910    pub enabled: bool,
7911
7912    /// Embezzlement scheme configuration.
7913    #[serde(default)]
7914    pub embezzlement: EmbezzlementSchemeConfig,
7915
7916    /// Revenue manipulation scheme configuration.
7917    #[serde(default)]
7918    pub revenue_manipulation: RevenueManipulationSchemeConfig,
7919
7920    /// Vendor kickback scheme configuration.
7921    #[serde(default)]
7922    pub kickback: KickbackSchemeConfig,
7923}
7924
7925/// Embezzlement scheme configuration.
7926#[derive(Debug, Clone, Serialize, Deserialize)]
7927pub struct EmbezzlementSchemeConfig {
7928    /// Probability of starting an embezzlement scheme per perpetrator per year.
7929    #[serde(default = "default_embezzlement_probability")]
7930    pub probability: f64,
7931
7932    /// Testing stage configuration.
7933    #[serde(default)]
7934    pub testing_stage: SchemeStageConfig,
7935
7936    /// Escalation stage configuration.
7937    #[serde(default)]
7938    pub escalation_stage: SchemeStageConfig,
7939
7940    /// Acceleration stage configuration.
7941    #[serde(default)]
7942    pub acceleration_stage: SchemeStageConfig,
7943
7944    /// Desperation stage configuration.
7945    #[serde(default)]
7946    pub desperation_stage: SchemeStageConfig,
7947}
7948
7949fn default_embezzlement_probability() -> f64 {
7950    0.02
7951}
7952
7953impl Default for EmbezzlementSchemeConfig {
7954    fn default() -> Self {
7955        Self {
7956            probability: default_embezzlement_probability(),
7957            testing_stage: SchemeStageConfig {
7958                duration_months: 2,
7959                amount_min: 100.0,
7960                amount_max: 500.0,
7961                transaction_count_min: 2,
7962                transaction_count_max: 5,
7963                difficulty: "hard".to_string(),
7964            },
7965            escalation_stage: SchemeStageConfig {
7966                duration_months: 6,
7967                amount_min: 500.0,
7968                amount_max: 2000.0,
7969                transaction_count_min: 3,
7970                transaction_count_max: 8,
7971                difficulty: "moderate".to_string(),
7972            },
7973            acceleration_stage: SchemeStageConfig {
7974                duration_months: 3,
7975                amount_min: 2000.0,
7976                amount_max: 10000.0,
7977                transaction_count_min: 5,
7978                transaction_count_max: 12,
7979                difficulty: "easy".to_string(),
7980            },
7981            desperation_stage: SchemeStageConfig {
7982                duration_months: 1,
7983                amount_min: 10000.0,
7984                amount_max: 50000.0,
7985                transaction_count_min: 3,
7986                transaction_count_max: 6,
7987                difficulty: "trivial".to_string(),
7988            },
7989        }
7990    }
7991}
7992
7993/// Revenue manipulation scheme configuration.
7994#[derive(Debug, Clone, Serialize, Deserialize)]
7995pub struct RevenueManipulationSchemeConfig {
7996    /// Probability of starting a revenue manipulation scheme per period.
7997    #[serde(default = "default_revenue_manipulation_probability")]
7998    pub probability: f64,
7999
8000    /// Early revenue recognition inflation target (Q4).
8001    #[serde(default = "default_early_recognition_target")]
8002    pub early_recognition_target: f64,
8003
8004    /// Expense deferral inflation target (Q1).
8005    #[serde(default = "default_expense_deferral_target")]
8006    pub expense_deferral_target: f64,
8007
8008    /// Reserve release inflation target (Q2).
8009    #[serde(default = "default_reserve_release_target")]
8010    pub reserve_release_target: f64,
8011
8012    /// Channel stuffing inflation target (Q4).
8013    #[serde(default = "default_channel_stuffing_target")]
8014    pub channel_stuffing_target: f64,
8015}
8016
8017fn default_revenue_manipulation_probability() -> f64 {
8018    0.01
8019}
8020fn default_early_recognition_target() -> f64 {
8021    0.02
8022}
8023fn default_expense_deferral_target() -> f64 {
8024    0.03
8025}
8026fn default_reserve_release_target() -> f64 {
8027    0.02
8028}
8029fn default_channel_stuffing_target() -> f64 {
8030    0.05
8031}
8032
8033impl Default for RevenueManipulationSchemeConfig {
8034    fn default() -> Self {
8035        Self {
8036            probability: default_revenue_manipulation_probability(),
8037            early_recognition_target: default_early_recognition_target(),
8038            expense_deferral_target: default_expense_deferral_target(),
8039            reserve_release_target: default_reserve_release_target(),
8040            channel_stuffing_target: default_channel_stuffing_target(),
8041        }
8042    }
8043}
8044
8045/// Vendor kickback scheme configuration.
8046#[derive(Debug, Clone, Serialize, Deserialize)]
8047pub struct KickbackSchemeConfig {
8048    /// Probability of starting a kickback scheme.
8049    #[serde(default = "default_kickback_probability")]
8050    pub probability: f64,
8051
8052    /// Minimum price inflation percentage.
8053    #[serde(default = "default_kickback_inflation_min")]
8054    pub inflation_min: f64,
8055
8056    /// Maximum price inflation percentage.
8057    #[serde(default = "default_kickback_inflation_max")]
8058    pub inflation_max: f64,
8059
8060    /// Kickback percentage (of inflation).
8061    #[serde(default = "default_kickback_percent")]
8062    pub kickback_percent: f64,
8063
8064    /// Setup duration in months.
8065    #[serde(default = "default_kickback_setup_months")]
8066    pub setup_months: u32,
8067
8068    /// Main operation duration in months.
8069    #[serde(default = "default_kickback_operation_months")]
8070    pub operation_months: u32,
8071}
8072
8073fn default_kickback_probability() -> f64 {
8074    0.01
8075}
8076fn default_kickback_inflation_min() -> f64 {
8077    0.10
8078}
8079fn default_kickback_inflation_max() -> f64 {
8080    0.25
8081}
8082fn default_kickback_percent() -> f64 {
8083    0.50
8084}
8085fn default_kickback_setup_months() -> u32 {
8086    3
8087}
8088fn default_kickback_operation_months() -> u32 {
8089    12
8090}
8091
8092impl Default for KickbackSchemeConfig {
8093    fn default() -> Self {
8094        Self {
8095            probability: default_kickback_probability(),
8096            inflation_min: default_kickback_inflation_min(),
8097            inflation_max: default_kickback_inflation_max(),
8098            kickback_percent: default_kickback_percent(),
8099            setup_months: default_kickback_setup_months(),
8100            operation_months: default_kickback_operation_months(),
8101        }
8102    }
8103}
8104
8105/// Individual scheme stage configuration.
8106#[derive(Debug, Clone, Serialize, Deserialize)]
8107pub struct SchemeStageConfig {
8108    /// Duration in months.
8109    pub duration_months: u32,
8110
8111    /// Minimum transaction amount.
8112    pub amount_min: f64,
8113
8114    /// Maximum transaction amount.
8115    pub amount_max: f64,
8116
8117    /// Minimum number of transactions.
8118    pub transaction_count_min: u32,
8119
8120    /// Maximum number of transactions.
8121    pub transaction_count_max: u32,
8122
8123    /// Detection difficulty level (trivial, easy, moderate, hard, expert).
8124    pub difficulty: String,
8125}
8126
8127impl Default for SchemeStageConfig {
8128    fn default() -> Self {
8129        Self {
8130            duration_months: 3,
8131            amount_min: 100.0,
8132            amount_max: 1000.0,
8133            transaction_count_min: 2,
8134            transaction_count_max: 10,
8135            difficulty: "moderate".to_string(),
8136        }
8137    }
8138}
8139
8140/// Correlated anomaly injection configuration.
8141#[derive(Debug, Clone, Serialize, Deserialize)]
8142pub struct CorrelatedInjectionConfig {
8143    /// Enable correlated anomaly injection.
8144    #[serde(default)]
8145    pub enabled: bool,
8146
8147    /// Enable fraud concealment co-occurrence patterns.
8148    #[serde(default = "default_true_val")]
8149    pub fraud_concealment: bool,
8150
8151    /// Enable error cascade patterns.
8152    #[serde(default = "default_true_val")]
8153    pub error_cascade: bool,
8154
8155    /// Enable temporal clustering (period-end spikes).
8156    #[serde(default = "default_true_val")]
8157    pub temporal_clustering: bool,
8158
8159    /// Temporal clustering configuration.
8160    #[serde(default)]
8161    pub temporal_clustering_config: TemporalClusteringConfig,
8162
8163    /// Co-occurrence patterns.
8164    #[serde(default)]
8165    pub co_occurrence_patterns: Vec<CoOccurrencePatternConfig>,
8166}
8167
8168impl Default for CorrelatedInjectionConfig {
8169    fn default() -> Self {
8170        Self {
8171            enabled: false,
8172            fraud_concealment: true,
8173            error_cascade: true,
8174            temporal_clustering: true,
8175            temporal_clustering_config: TemporalClusteringConfig::default(),
8176            co_occurrence_patterns: Vec::new(),
8177        }
8178    }
8179}
8180
8181/// Temporal clustering configuration.
8182#[derive(Debug, Clone, Serialize, Deserialize)]
8183pub struct TemporalClusteringConfig {
8184    /// Period-end error multiplier.
8185    #[serde(default = "default_period_end_multiplier")]
8186    pub period_end_multiplier: f64,
8187
8188    /// Number of business days before period end to apply multiplier.
8189    #[serde(default = "default_period_end_days")]
8190    pub period_end_days: u32,
8191
8192    /// Quarter-end additional multiplier.
8193    #[serde(default = "default_quarter_end_multiplier")]
8194    pub quarter_end_multiplier: f64,
8195
8196    /// Year-end additional multiplier.
8197    #[serde(default = "default_year_end_multiplier")]
8198    pub year_end_multiplier: f64,
8199}
8200
8201fn default_period_end_multiplier() -> f64 {
8202    2.5
8203}
8204fn default_period_end_days() -> u32 {
8205    5
8206}
8207fn default_quarter_end_multiplier() -> f64 {
8208    1.5
8209}
8210fn default_year_end_multiplier() -> f64 {
8211    2.0
8212}
8213
8214impl Default for TemporalClusteringConfig {
8215    fn default() -> Self {
8216        Self {
8217            period_end_multiplier: default_period_end_multiplier(),
8218            period_end_days: default_period_end_days(),
8219            quarter_end_multiplier: default_quarter_end_multiplier(),
8220            year_end_multiplier: default_year_end_multiplier(),
8221        }
8222    }
8223}
8224
8225/// Co-occurrence pattern configuration.
8226#[derive(Debug, Clone, Serialize, Deserialize)]
8227pub struct CoOccurrencePatternConfig {
8228    /// Pattern name.
8229    pub name: String,
8230
8231    /// Primary anomaly type that triggers the pattern.
8232    pub primary_type: String,
8233
8234    /// Correlated anomalies.
8235    pub correlated: Vec<CorrelatedAnomalyConfig>,
8236}
8237
8238/// Correlated anomaly configuration.
8239#[derive(Debug, Clone, Serialize, Deserialize)]
8240pub struct CorrelatedAnomalyConfig {
8241    /// Anomaly type.
8242    pub anomaly_type: String,
8243
8244    /// Probability of occurrence (0.0 to 1.0).
8245    pub probability: f64,
8246
8247    /// Minimum lag in days.
8248    pub lag_days_min: i32,
8249
8250    /// Maximum lag in days.
8251    pub lag_days_max: i32,
8252}
8253
8254/// Near-miss generation configuration.
8255#[derive(Debug, Clone, Serialize, Deserialize)]
8256pub struct NearMissConfig {
8257    /// Enable near-miss generation.
8258    #[serde(default)]
8259    pub enabled: bool,
8260
8261    /// Proportion of "anomalies" that are actually near-misses (0.0 to 1.0).
8262    #[serde(default = "default_near_miss_proportion")]
8263    pub proportion: f64,
8264
8265    /// Enable near-duplicate pattern.
8266    #[serde(default = "default_true_val")]
8267    pub near_duplicate: bool,
8268
8269    /// Near-duplicate date difference range in days.
8270    #[serde(default)]
8271    pub near_duplicate_days: NearDuplicateDaysConfig,
8272
8273    /// Enable threshold proximity pattern.
8274    #[serde(default = "default_true_val")]
8275    pub threshold_proximity: bool,
8276
8277    /// Threshold proximity range (e.g., 0.90-0.99 of threshold).
8278    #[serde(default)]
8279    pub threshold_proximity_range: ThresholdProximityRangeConfig,
8280
8281    /// Enable unusual but legitimate patterns.
8282    #[serde(default = "default_true_val")]
8283    pub unusual_legitimate: bool,
8284
8285    /// Types of unusual legitimate patterns to generate.
8286    #[serde(default = "default_unusual_legitimate_types")]
8287    pub unusual_legitimate_types: Vec<String>,
8288
8289    /// Enable corrected error patterns.
8290    #[serde(default = "default_true_val")]
8291    pub corrected_errors: bool,
8292
8293    /// Corrected error correction lag range in days.
8294    #[serde(default)]
8295    pub corrected_error_lag: CorrectedErrorLagConfig,
8296}
8297
8298fn default_near_miss_proportion() -> f64 {
8299    0.30
8300}
8301
8302fn default_unusual_legitimate_types() -> Vec<String> {
8303    vec![
8304        "year_end_bonus".to_string(),
8305        "contract_prepayment".to_string(),
8306        "insurance_claim".to_string(),
8307        "settlement_payment".to_string(),
8308    ]
8309}
8310
8311impl Default for NearMissConfig {
8312    fn default() -> Self {
8313        Self {
8314            enabled: false,
8315            proportion: default_near_miss_proportion(),
8316            near_duplicate: true,
8317            near_duplicate_days: NearDuplicateDaysConfig::default(),
8318            threshold_proximity: true,
8319            threshold_proximity_range: ThresholdProximityRangeConfig::default(),
8320            unusual_legitimate: true,
8321            unusual_legitimate_types: default_unusual_legitimate_types(),
8322            corrected_errors: true,
8323            corrected_error_lag: CorrectedErrorLagConfig::default(),
8324        }
8325    }
8326}
8327
8328/// Near-duplicate days configuration.
8329#[derive(Debug, Clone, Serialize, Deserialize)]
8330pub struct NearDuplicateDaysConfig {
8331    /// Minimum days apart.
8332    #[serde(default = "default_near_duplicate_min")]
8333    pub min: u32,
8334
8335    /// Maximum days apart.
8336    #[serde(default = "default_near_duplicate_max")]
8337    pub max: u32,
8338}
8339
8340fn default_near_duplicate_min() -> u32 {
8341    1
8342}
8343fn default_near_duplicate_max() -> u32 {
8344    3
8345}
8346
8347impl Default for NearDuplicateDaysConfig {
8348    fn default() -> Self {
8349        Self {
8350            min: default_near_duplicate_min(),
8351            max: default_near_duplicate_max(),
8352        }
8353    }
8354}
8355
8356/// Threshold proximity range configuration.
8357#[derive(Debug, Clone, Serialize, Deserialize)]
8358pub struct ThresholdProximityRangeConfig {
8359    /// Minimum proximity (e.g., 0.90 = 90% of threshold).
8360    #[serde(default = "default_threshold_proximity_min")]
8361    pub min: f64,
8362
8363    /// Maximum proximity (e.g., 0.99 = 99% of threshold).
8364    #[serde(default = "default_threshold_proximity_max")]
8365    pub max: f64,
8366}
8367
8368fn default_threshold_proximity_min() -> f64 {
8369    0.90
8370}
8371fn default_threshold_proximity_max() -> f64 {
8372    0.99
8373}
8374
8375impl Default for ThresholdProximityRangeConfig {
8376    fn default() -> Self {
8377        Self {
8378            min: default_threshold_proximity_min(),
8379            max: default_threshold_proximity_max(),
8380        }
8381    }
8382}
8383
8384/// Corrected error lag configuration.
8385#[derive(Debug, Clone, Serialize, Deserialize)]
8386pub struct CorrectedErrorLagConfig {
8387    /// Minimum correction lag in days.
8388    #[serde(default = "default_corrected_error_lag_min")]
8389    pub min: u32,
8390
8391    /// Maximum correction lag in days.
8392    #[serde(default = "default_corrected_error_lag_max")]
8393    pub max: u32,
8394}
8395
8396fn default_corrected_error_lag_min() -> u32 {
8397    1
8398}
8399fn default_corrected_error_lag_max() -> u32 {
8400    5
8401}
8402
8403impl Default for CorrectedErrorLagConfig {
8404    fn default() -> Self {
8405        Self {
8406            min: default_corrected_error_lag_min(),
8407            max: default_corrected_error_lag_max(),
8408        }
8409    }
8410}
8411
8412/// Detection difficulty classification configuration.
8413#[derive(Debug, Clone, Serialize, Deserialize)]
8414pub struct DifficultyClassificationConfig {
8415    /// Enable detection difficulty classification.
8416    #[serde(default)]
8417    pub enabled: bool,
8418
8419    /// Target distribution of difficulty levels.
8420    #[serde(default)]
8421    pub target_distribution: DifficultyDistributionConfig,
8422}
8423
8424impl Default for DifficultyClassificationConfig {
8425    fn default() -> Self {
8426        Self {
8427            enabled: true,
8428            target_distribution: DifficultyDistributionConfig::default(),
8429        }
8430    }
8431}
8432
8433/// Target distribution of detection difficulty levels.
8434#[derive(Debug, Clone, Serialize, Deserialize)]
8435pub struct DifficultyDistributionConfig {
8436    /// Proportion of trivial anomalies (expected 99% detection).
8437    #[serde(default = "default_difficulty_trivial")]
8438    pub trivial: f64,
8439
8440    /// Proportion of easy anomalies (expected 90% detection).
8441    #[serde(default = "default_difficulty_easy")]
8442    pub easy: f64,
8443
8444    /// Proportion of moderate anomalies (expected 70% detection).
8445    #[serde(default = "default_difficulty_moderate")]
8446    pub moderate: f64,
8447
8448    /// Proportion of hard anomalies (expected 40% detection).
8449    #[serde(default = "default_difficulty_hard")]
8450    pub hard: f64,
8451
8452    /// Proportion of expert anomalies (expected 15% detection).
8453    #[serde(default = "default_difficulty_expert")]
8454    pub expert: f64,
8455}
8456
8457fn default_difficulty_trivial() -> f64 {
8458    0.15
8459}
8460fn default_difficulty_easy() -> f64 {
8461    0.25
8462}
8463fn default_difficulty_moderate() -> f64 {
8464    0.30
8465}
8466fn default_difficulty_hard() -> f64 {
8467    0.20
8468}
8469fn default_difficulty_expert() -> f64 {
8470    0.10
8471}
8472
8473impl Default for DifficultyDistributionConfig {
8474    fn default() -> Self {
8475        Self {
8476            trivial: default_difficulty_trivial(),
8477            easy: default_difficulty_easy(),
8478            moderate: default_difficulty_moderate(),
8479            hard: default_difficulty_hard(),
8480            expert: default_difficulty_expert(),
8481        }
8482    }
8483}
8484
8485/// Context-aware injection configuration.
8486#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8487pub struct ContextAwareConfig {
8488    /// Enable context-aware injection.
8489    #[serde(default)]
8490    pub enabled: bool,
8491
8492    /// Vendor-specific anomaly rules.
8493    #[serde(default)]
8494    pub vendor_rules: VendorAnomalyRulesConfig,
8495
8496    /// Employee-specific anomaly rules.
8497    #[serde(default)]
8498    pub employee_rules: EmployeeAnomalyRulesConfig,
8499
8500    /// Account-specific anomaly rules.
8501    #[serde(default)]
8502    pub account_rules: AccountAnomalyRulesConfig,
8503
8504    /// Behavioral baseline configuration.
8505    #[serde(default)]
8506    pub behavioral_baseline: BehavioralBaselineConfig,
8507}
8508
8509/// Vendor-specific anomaly rules configuration.
8510#[derive(Debug, Clone, Serialize, Deserialize)]
8511pub struct VendorAnomalyRulesConfig {
8512    /// Error rate multiplier for new vendors (< threshold days).
8513    #[serde(default = "default_new_vendor_multiplier")]
8514    pub new_vendor_error_multiplier: f64,
8515
8516    /// Days threshold for "new" vendor classification.
8517    #[serde(default = "default_new_vendor_threshold")]
8518    pub new_vendor_threshold_days: u32,
8519
8520    /// Error rate multiplier for international vendors.
8521    #[serde(default = "default_international_multiplier")]
8522    pub international_error_multiplier: f64,
8523
8524    /// Strategic vendor anomaly types (may differ from general vendors).
8525    #[serde(default = "default_strategic_vendor_types")]
8526    pub strategic_vendor_anomaly_types: Vec<String>,
8527}
8528
8529fn default_new_vendor_multiplier() -> f64 {
8530    2.5
8531}
8532fn default_new_vendor_threshold() -> u32 {
8533    90
8534}
8535fn default_international_multiplier() -> f64 {
8536    1.5
8537}
8538fn default_strategic_vendor_types() -> Vec<String> {
8539    vec![
8540        "pricing_dispute".to_string(),
8541        "contract_violation".to_string(),
8542    ]
8543}
8544
8545impl Default for VendorAnomalyRulesConfig {
8546    fn default() -> Self {
8547        Self {
8548            new_vendor_error_multiplier: default_new_vendor_multiplier(),
8549            new_vendor_threshold_days: default_new_vendor_threshold(),
8550            international_error_multiplier: default_international_multiplier(),
8551            strategic_vendor_anomaly_types: default_strategic_vendor_types(),
8552        }
8553    }
8554}
8555
8556/// Employee-specific anomaly rules configuration.
8557#[derive(Debug, Clone, Serialize, Deserialize)]
8558pub struct EmployeeAnomalyRulesConfig {
8559    /// Error rate for new employees (< threshold days).
8560    #[serde(default = "default_new_employee_rate")]
8561    pub new_employee_error_rate: f64,
8562
8563    /// Days threshold for "new" employee classification.
8564    #[serde(default = "default_new_employee_threshold")]
8565    pub new_employee_threshold_days: u32,
8566
8567    /// Transaction volume threshold for fatigue errors.
8568    #[serde(default = "default_volume_fatigue_threshold")]
8569    pub volume_fatigue_threshold: u32,
8570
8571    /// Error rate multiplier when primary approver is absent.
8572    #[serde(default = "default_coverage_multiplier")]
8573    pub coverage_error_multiplier: f64,
8574}
8575
8576fn default_new_employee_rate() -> f64 {
8577    0.05
8578}
8579fn default_new_employee_threshold() -> u32 {
8580    180
8581}
8582fn default_volume_fatigue_threshold() -> u32 {
8583    50
8584}
8585fn default_coverage_multiplier() -> f64 {
8586    1.8
8587}
8588
8589impl Default for EmployeeAnomalyRulesConfig {
8590    fn default() -> Self {
8591        Self {
8592            new_employee_error_rate: default_new_employee_rate(),
8593            new_employee_threshold_days: default_new_employee_threshold(),
8594            volume_fatigue_threshold: default_volume_fatigue_threshold(),
8595            coverage_error_multiplier: default_coverage_multiplier(),
8596        }
8597    }
8598}
8599
8600/// Account-specific anomaly rules configuration.
8601#[derive(Debug, Clone, Serialize, Deserialize)]
8602pub struct AccountAnomalyRulesConfig {
8603    /// Error rate multiplier for high-risk accounts.
8604    #[serde(default = "default_high_risk_multiplier")]
8605    pub high_risk_account_multiplier: f64,
8606
8607    /// Account codes considered high-risk.
8608    #[serde(default = "default_high_risk_accounts")]
8609    pub high_risk_accounts: Vec<String>,
8610
8611    /// Error rate multiplier for suspense accounts.
8612    #[serde(default = "default_suspense_multiplier")]
8613    pub suspense_account_multiplier: f64,
8614
8615    /// Account codes considered suspense accounts.
8616    #[serde(default = "default_suspense_accounts")]
8617    pub suspense_accounts: Vec<String>,
8618
8619    /// Error rate multiplier for intercompany accounts.
8620    #[serde(default = "default_intercompany_multiplier")]
8621    pub intercompany_account_multiplier: f64,
8622}
8623
8624fn default_high_risk_multiplier() -> f64 {
8625    2.0
8626}
8627fn default_high_risk_accounts() -> Vec<String> {
8628    vec![
8629        "1100".to_string(), // AR Control
8630        "2000".to_string(), // AP Control
8631        "3000".to_string(), // Cash
8632    ]
8633}
8634fn default_suspense_multiplier() -> f64 {
8635    3.0
8636}
8637fn default_suspense_accounts() -> Vec<String> {
8638    vec!["9999".to_string(), "9998".to_string()]
8639}
8640fn default_intercompany_multiplier() -> f64 {
8641    1.5
8642}
8643
8644impl Default for AccountAnomalyRulesConfig {
8645    fn default() -> Self {
8646        Self {
8647            high_risk_account_multiplier: default_high_risk_multiplier(),
8648            high_risk_accounts: default_high_risk_accounts(),
8649            suspense_account_multiplier: default_suspense_multiplier(),
8650            suspense_accounts: default_suspense_accounts(),
8651            intercompany_account_multiplier: default_intercompany_multiplier(),
8652        }
8653    }
8654}
8655
8656/// Behavioral baseline configuration.
8657#[derive(Debug, Clone, Serialize, Deserialize)]
8658pub struct BehavioralBaselineConfig {
8659    /// Enable behavioral baseline tracking.
8660    #[serde(default)]
8661    pub enabled: bool,
8662
8663    /// Number of days to build baseline from.
8664    #[serde(default = "default_baseline_period")]
8665    pub baseline_period_days: u32,
8666
8667    /// Standard deviation threshold for amount anomalies.
8668    #[serde(default = "default_deviation_threshold")]
8669    pub deviation_threshold_std: f64,
8670
8671    /// Standard deviation threshold for frequency anomalies.
8672    #[serde(default = "default_frequency_deviation")]
8673    pub frequency_deviation_threshold: f64,
8674}
8675
8676fn default_baseline_period() -> u32 {
8677    90
8678}
8679fn default_deviation_threshold() -> f64 {
8680    3.0
8681}
8682fn default_frequency_deviation() -> f64 {
8683    2.0
8684}
8685
8686impl Default for BehavioralBaselineConfig {
8687    fn default() -> Self {
8688        Self {
8689            enabled: false,
8690            baseline_period_days: default_baseline_period(),
8691            deviation_threshold_std: default_deviation_threshold(),
8692            frequency_deviation_threshold: default_frequency_deviation(),
8693        }
8694    }
8695}
8696
8697/// Enhanced labeling configuration.
8698#[derive(Debug, Clone, Serialize, Deserialize)]
8699pub struct EnhancedLabelingConfig {
8700    /// Enable severity scoring.
8701    #[serde(default = "default_true_val")]
8702    pub severity_scoring: bool,
8703
8704    /// Enable difficulty classification.
8705    #[serde(default = "default_true_val")]
8706    pub difficulty_classification: bool,
8707
8708    /// Materiality thresholds for severity classification.
8709    #[serde(default)]
8710    pub materiality_thresholds: MaterialityThresholdsConfig,
8711}
8712
8713impl Default for EnhancedLabelingConfig {
8714    fn default() -> Self {
8715        Self {
8716            severity_scoring: true,
8717            difficulty_classification: true,
8718            materiality_thresholds: MaterialityThresholdsConfig::default(),
8719        }
8720    }
8721}
8722
8723/// Materiality thresholds configuration.
8724#[derive(Debug, Clone, Serialize, Deserialize)]
8725pub struct MaterialityThresholdsConfig {
8726    /// Threshold for trivial impact (as percentage of total).
8727    #[serde(default = "default_materiality_trivial")]
8728    pub trivial: f64,
8729
8730    /// Threshold for immaterial impact.
8731    #[serde(default = "default_materiality_immaterial")]
8732    pub immaterial: f64,
8733
8734    /// Threshold for material impact.
8735    #[serde(default = "default_materiality_material")]
8736    pub material: f64,
8737
8738    /// Threshold for highly material impact.
8739    #[serde(default = "default_materiality_highly_material")]
8740    pub highly_material: f64,
8741}
8742
8743fn default_materiality_trivial() -> f64 {
8744    0.001
8745}
8746fn default_materiality_immaterial() -> f64 {
8747    0.01
8748}
8749fn default_materiality_material() -> f64 {
8750    0.05
8751}
8752fn default_materiality_highly_material() -> f64 {
8753    0.10
8754}
8755
8756impl Default for MaterialityThresholdsConfig {
8757    fn default() -> Self {
8758        Self {
8759            trivial: default_materiality_trivial(),
8760            immaterial: default_materiality_immaterial(),
8761            material: default_materiality_material(),
8762            highly_material: default_materiality_highly_material(),
8763        }
8764    }
8765}
8766
8767// =============================================================================
8768// Industry-Specific Configuration
8769// =============================================================================
8770
8771/// Industry-specific transaction and anomaly generation configuration.
8772///
8773/// This configuration enables generation of industry-authentic:
8774/// - Transaction types with appropriate terminology
8775/// - Master data (BOM, routings, clinical codes, etc.)
8776/// - Industry-specific anomaly patterns
8777/// - Regulatory framework compliance
8778#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8779pub struct IndustrySpecificConfig {
8780    /// Enable industry-specific generation.
8781    #[serde(default)]
8782    pub enabled: bool,
8783
8784    /// Manufacturing industry settings.
8785    #[serde(default)]
8786    pub manufacturing: ManufacturingConfig,
8787
8788    /// Retail industry settings.
8789    #[serde(default)]
8790    pub retail: RetailConfig,
8791
8792    /// Healthcare industry settings.
8793    #[serde(default)]
8794    pub healthcare: HealthcareConfig,
8795
8796    /// Technology industry settings.
8797    #[serde(default)]
8798    pub technology: TechnologyConfig,
8799
8800    /// Financial services industry settings.
8801    #[serde(default)]
8802    pub financial_services: FinancialServicesConfig,
8803
8804    /// Professional services industry settings.
8805    #[serde(default)]
8806    pub professional_services: ProfessionalServicesConfig,
8807}
8808
8809/// Manufacturing industry configuration.
8810#[derive(Debug, Clone, Serialize, Deserialize)]
8811pub struct ManufacturingConfig {
8812    /// Enable manufacturing-specific generation.
8813    #[serde(default)]
8814    pub enabled: bool,
8815
8816    /// Bill of Materials depth (typical: 3-7).
8817    #[serde(default = "default_bom_depth")]
8818    pub bom_depth: u32,
8819
8820    /// Whether to use just-in-time inventory.
8821    #[serde(default)]
8822    pub just_in_time: bool,
8823
8824    /// Production order types to generate.
8825    #[serde(default = "default_production_order_types")]
8826    pub production_order_types: Vec<String>,
8827
8828    /// Quality framework (ISO_9001, Six_Sigma, etc.).
8829    #[serde(default)]
8830    pub quality_framework: Option<String>,
8831
8832    /// Number of supplier tiers to model (1-3).
8833    #[serde(default = "default_supplier_tiers")]
8834    pub supplier_tiers: u32,
8835
8836    /// Standard cost update frequency.
8837    #[serde(default = "default_cost_frequency")]
8838    pub standard_cost_frequency: String,
8839
8840    /// Target yield rate (0.95-0.99 typical).
8841    #[serde(default = "default_yield_rate")]
8842    pub target_yield_rate: f64,
8843
8844    /// Scrap percentage threshold for alerts.
8845    #[serde(default = "default_scrap_threshold")]
8846    pub scrap_alert_threshold: f64,
8847
8848    /// Manufacturing anomaly injection rates.
8849    #[serde(default)]
8850    pub anomaly_rates: ManufacturingAnomalyRates,
8851}
8852
8853fn default_bom_depth() -> u32 {
8854    4
8855}
8856
8857fn default_production_order_types() -> Vec<String> {
8858    vec![
8859        "standard".to_string(),
8860        "rework".to_string(),
8861        "prototype".to_string(),
8862    ]
8863}
8864
8865fn default_supplier_tiers() -> u32 {
8866    2
8867}
8868
8869fn default_cost_frequency() -> String {
8870    "quarterly".to_string()
8871}
8872
8873fn default_yield_rate() -> f64 {
8874    0.97
8875}
8876
8877fn default_scrap_threshold() -> f64 {
8878    0.03
8879}
8880
8881impl Default for ManufacturingConfig {
8882    fn default() -> Self {
8883        Self {
8884            enabled: false,
8885            bom_depth: default_bom_depth(),
8886            just_in_time: false,
8887            production_order_types: default_production_order_types(),
8888            quality_framework: Some("ISO_9001".to_string()),
8889            supplier_tiers: default_supplier_tiers(),
8890            standard_cost_frequency: default_cost_frequency(),
8891            target_yield_rate: default_yield_rate(),
8892            scrap_alert_threshold: default_scrap_threshold(),
8893            anomaly_rates: ManufacturingAnomalyRates::default(),
8894        }
8895    }
8896}
8897
8898/// Manufacturing anomaly injection rates.
8899#[derive(Debug, Clone, Serialize, Deserialize)]
8900pub struct ManufacturingAnomalyRates {
8901    /// Yield manipulation rate.
8902    #[serde(default = "default_mfg_yield_rate")]
8903    pub yield_manipulation: f64,
8904
8905    /// Labor misallocation rate.
8906    #[serde(default = "default_mfg_labor_rate")]
8907    pub labor_misallocation: f64,
8908
8909    /// Phantom production rate.
8910    #[serde(default = "default_mfg_phantom_rate")]
8911    pub phantom_production: f64,
8912
8913    /// Standard cost manipulation rate.
8914    #[serde(default = "default_mfg_cost_rate")]
8915    pub standard_cost_manipulation: f64,
8916
8917    /// Inventory fraud rate.
8918    #[serde(default = "default_mfg_inventory_rate")]
8919    pub inventory_fraud: f64,
8920}
8921
8922fn default_mfg_yield_rate() -> f64 {
8923    0.015
8924}
8925
8926fn default_mfg_labor_rate() -> f64 {
8927    0.02
8928}
8929
8930fn default_mfg_phantom_rate() -> f64 {
8931    0.005
8932}
8933
8934fn default_mfg_cost_rate() -> f64 {
8935    0.01
8936}
8937
8938fn default_mfg_inventory_rate() -> f64 {
8939    0.008
8940}
8941
8942impl Default for ManufacturingAnomalyRates {
8943    fn default() -> Self {
8944        Self {
8945            yield_manipulation: default_mfg_yield_rate(),
8946            labor_misallocation: default_mfg_labor_rate(),
8947            phantom_production: default_mfg_phantom_rate(),
8948            standard_cost_manipulation: default_mfg_cost_rate(),
8949            inventory_fraud: default_mfg_inventory_rate(),
8950        }
8951    }
8952}
8953
8954/// Retail industry configuration.
8955#[derive(Debug, Clone, Serialize, Deserialize)]
8956pub struct RetailConfig {
8957    /// Enable retail-specific generation.
8958    #[serde(default)]
8959    pub enabled: bool,
8960
8961    /// Store type distribution.
8962    #[serde(default)]
8963    pub store_types: RetailStoreTypeConfig,
8964
8965    /// Average daily transactions per store.
8966    #[serde(default = "default_retail_daily_txns")]
8967    pub avg_daily_transactions: u32,
8968
8969    /// Enable loss prevention tracking.
8970    #[serde(default = "default_true")]
8971    pub loss_prevention: bool,
8972
8973    /// Shrinkage rate (0.01-0.03 typical).
8974    #[serde(default = "default_shrinkage_rate")]
8975    pub shrinkage_rate: f64,
8976
8977    /// Retail anomaly injection rates.
8978    #[serde(default)]
8979    pub anomaly_rates: RetailAnomalyRates,
8980}
8981
8982fn default_retail_daily_txns() -> u32 {
8983    500
8984}
8985
8986fn default_shrinkage_rate() -> f64 {
8987    0.015
8988}
8989
8990impl Default for RetailConfig {
8991    fn default() -> Self {
8992        Self {
8993            enabled: false,
8994            store_types: RetailStoreTypeConfig::default(),
8995            avg_daily_transactions: default_retail_daily_txns(),
8996            loss_prevention: true,
8997            shrinkage_rate: default_shrinkage_rate(),
8998            anomaly_rates: RetailAnomalyRates::default(),
8999        }
9000    }
9001}
9002
9003/// Retail store type distribution.
9004#[derive(Debug, Clone, Serialize, Deserialize)]
9005pub struct RetailStoreTypeConfig {
9006    /// Percentage of flagship stores.
9007    #[serde(default = "default_flagship_pct")]
9008    pub flagship: f64,
9009
9010    /// Percentage of regional stores.
9011    #[serde(default = "default_regional_pct")]
9012    pub regional: f64,
9013
9014    /// Percentage of outlet stores.
9015    #[serde(default = "default_outlet_pct")]
9016    pub outlet: f64,
9017
9018    /// Percentage of e-commerce.
9019    #[serde(default = "default_ecommerce_pct")]
9020    pub ecommerce: f64,
9021}
9022
9023fn default_flagship_pct() -> f64 {
9024    0.10
9025}
9026
9027fn default_regional_pct() -> f64 {
9028    0.50
9029}
9030
9031fn default_outlet_pct() -> f64 {
9032    0.25
9033}
9034
9035fn default_ecommerce_pct() -> f64 {
9036    0.15
9037}
9038
9039impl Default for RetailStoreTypeConfig {
9040    fn default() -> Self {
9041        Self {
9042            flagship: default_flagship_pct(),
9043            regional: default_regional_pct(),
9044            outlet: default_outlet_pct(),
9045            ecommerce: default_ecommerce_pct(),
9046        }
9047    }
9048}
9049
9050/// Retail anomaly injection rates.
9051#[derive(Debug, Clone, Serialize, Deserialize)]
9052pub struct RetailAnomalyRates {
9053    /// Sweethearting rate.
9054    #[serde(default = "default_sweethearting_rate")]
9055    pub sweethearting: f64,
9056
9057    /// Skimming rate.
9058    #[serde(default = "default_skimming_rate")]
9059    pub skimming: f64,
9060
9061    /// Refund fraud rate.
9062    #[serde(default = "default_refund_fraud_rate")]
9063    pub refund_fraud: f64,
9064
9065    /// Void abuse rate.
9066    #[serde(default = "default_void_abuse_rate")]
9067    pub void_abuse: f64,
9068
9069    /// Gift card fraud rate.
9070    #[serde(default = "default_gift_card_rate")]
9071    pub gift_card_fraud: f64,
9072
9073    /// Vendor kickback rate.
9074    #[serde(default = "default_retail_kickback_rate")]
9075    pub vendor_kickback: f64,
9076}
9077
9078fn default_sweethearting_rate() -> f64 {
9079    0.02
9080}
9081
9082fn default_skimming_rate() -> f64 {
9083    0.005
9084}
9085
9086fn default_refund_fraud_rate() -> f64 {
9087    0.015
9088}
9089
9090fn default_void_abuse_rate() -> f64 {
9091    0.01
9092}
9093
9094fn default_gift_card_rate() -> f64 {
9095    0.008
9096}
9097
9098fn default_retail_kickback_rate() -> f64 {
9099    0.003
9100}
9101
9102impl Default for RetailAnomalyRates {
9103    fn default() -> Self {
9104        Self {
9105            sweethearting: default_sweethearting_rate(),
9106            skimming: default_skimming_rate(),
9107            refund_fraud: default_refund_fraud_rate(),
9108            void_abuse: default_void_abuse_rate(),
9109            gift_card_fraud: default_gift_card_rate(),
9110            vendor_kickback: default_retail_kickback_rate(),
9111        }
9112    }
9113}
9114
9115/// Healthcare industry configuration.
9116#[derive(Debug, Clone, Serialize, Deserialize)]
9117pub struct HealthcareConfig {
9118    /// Enable healthcare-specific generation.
9119    #[serde(default)]
9120    pub enabled: bool,
9121
9122    /// Healthcare facility type.
9123    #[serde(default = "default_facility_type")]
9124    pub facility_type: String,
9125
9126    /// Payer mix distribution.
9127    #[serde(default)]
9128    pub payer_mix: HealthcarePayerMix,
9129
9130    /// Coding systems enabled.
9131    #[serde(default)]
9132    pub coding_systems: HealthcareCodingSystems,
9133
9134    /// Healthcare compliance settings.
9135    #[serde(default)]
9136    pub compliance: HealthcareComplianceConfig,
9137
9138    /// Average daily encounters.
9139    #[serde(default = "default_daily_encounters")]
9140    pub avg_daily_encounters: u32,
9141
9142    /// Average charges per encounter.
9143    #[serde(default = "default_charges_per_encounter")]
9144    pub avg_charges_per_encounter: u32,
9145
9146    /// Denial rate (0.0-1.0).
9147    #[serde(default = "default_hc_denial_rate")]
9148    pub denial_rate: f64,
9149
9150    /// Bad debt rate (0.0-1.0).
9151    #[serde(default = "default_hc_bad_debt_rate")]
9152    pub bad_debt_rate: f64,
9153
9154    /// Charity care rate (0.0-1.0).
9155    #[serde(default = "default_hc_charity_care_rate")]
9156    pub charity_care_rate: f64,
9157
9158    /// Healthcare anomaly injection rates.
9159    #[serde(default)]
9160    pub anomaly_rates: HealthcareAnomalyRates,
9161}
9162
9163fn default_facility_type() -> String {
9164    "hospital".to_string()
9165}
9166
9167fn default_daily_encounters() -> u32 {
9168    150
9169}
9170
9171fn default_charges_per_encounter() -> u32 {
9172    8
9173}
9174
9175fn default_hc_denial_rate() -> f64 {
9176    0.05
9177}
9178
9179fn default_hc_bad_debt_rate() -> f64 {
9180    0.03
9181}
9182
9183fn default_hc_charity_care_rate() -> f64 {
9184    0.02
9185}
9186
9187impl Default for HealthcareConfig {
9188    fn default() -> Self {
9189        Self {
9190            enabled: false,
9191            facility_type: default_facility_type(),
9192            payer_mix: HealthcarePayerMix::default(),
9193            coding_systems: HealthcareCodingSystems::default(),
9194            compliance: HealthcareComplianceConfig::default(),
9195            avg_daily_encounters: default_daily_encounters(),
9196            avg_charges_per_encounter: default_charges_per_encounter(),
9197            denial_rate: default_hc_denial_rate(),
9198            bad_debt_rate: default_hc_bad_debt_rate(),
9199            charity_care_rate: default_hc_charity_care_rate(),
9200            anomaly_rates: HealthcareAnomalyRates::default(),
9201        }
9202    }
9203}
9204
9205/// Healthcare payer mix distribution.
9206#[derive(Debug, Clone, Serialize, Deserialize)]
9207pub struct HealthcarePayerMix {
9208    /// Medicare percentage.
9209    #[serde(default = "default_medicare_pct")]
9210    pub medicare: f64,
9211
9212    /// Medicaid percentage.
9213    #[serde(default = "default_medicaid_pct")]
9214    pub medicaid: f64,
9215
9216    /// Commercial insurance percentage.
9217    #[serde(default = "default_commercial_pct")]
9218    pub commercial: f64,
9219
9220    /// Self-pay percentage.
9221    #[serde(default = "default_self_pay_pct")]
9222    pub self_pay: f64,
9223}
9224
9225fn default_medicare_pct() -> f64 {
9226    0.40
9227}
9228
9229fn default_medicaid_pct() -> f64 {
9230    0.20
9231}
9232
9233fn default_commercial_pct() -> f64 {
9234    0.30
9235}
9236
9237fn default_self_pay_pct() -> f64 {
9238    0.10
9239}
9240
9241impl Default for HealthcarePayerMix {
9242    fn default() -> Self {
9243        Self {
9244            medicare: default_medicare_pct(),
9245            medicaid: default_medicaid_pct(),
9246            commercial: default_commercial_pct(),
9247            self_pay: default_self_pay_pct(),
9248        }
9249    }
9250}
9251
9252/// Healthcare coding systems configuration.
9253#[derive(Debug, Clone, Serialize, Deserialize)]
9254pub struct HealthcareCodingSystems {
9255    /// Enable ICD-10 diagnosis coding.
9256    #[serde(default = "default_true")]
9257    pub icd10: bool,
9258
9259    /// Enable CPT procedure coding.
9260    #[serde(default = "default_true")]
9261    pub cpt: bool,
9262
9263    /// Enable DRG grouping.
9264    #[serde(default = "default_true")]
9265    pub drg: bool,
9266
9267    /// Enable HCPCS Level II coding.
9268    #[serde(default = "default_true")]
9269    pub hcpcs: bool,
9270
9271    /// Enable revenue codes.
9272    #[serde(default = "default_true")]
9273    pub revenue_codes: bool,
9274}
9275
9276impl Default for HealthcareCodingSystems {
9277    fn default() -> Self {
9278        Self {
9279            icd10: true,
9280            cpt: true,
9281            drg: true,
9282            hcpcs: true,
9283            revenue_codes: true,
9284        }
9285    }
9286}
9287
9288/// Healthcare compliance configuration.
9289#[derive(Debug, Clone, Serialize, Deserialize)]
9290pub struct HealthcareComplianceConfig {
9291    /// Enable HIPAA compliance.
9292    #[serde(default = "default_true")]
9293    pub hipaa: bool,
9294
9295    /// Enable Stark Law compliance.
9296    #[serde(default = "default_true")]
9297    pub stark_law: bool,
9298
9299    /// Enable Anti-Kickback Statute compliance.
9300    #[serde(default = "default_true")]
9301    pub anti_kickback: bool,
9302
9303    /// Enable False Claims Act compliance.
9304    #[serde(default = "default_true")]
9305    pub false_claims_act: bool,
9306
9307    /// Enable EMTALA compliance (for hospitals).
9308    #[serde(default = "default_true")]
9309    pub emtala: bool,
9310}
9311
9312impl Default for HealthcareComplianceConfig {
9313    fn default() -> Self {
9314        Self {
9315            hipaa: true,
9316            stark_law: true,
9317            anti_kickback: true,
9318            false_claims_act: true,
9319            emtala: true,
9320        }
9321    }
9322}
9323
9324/// Healthcare anomaly injection rates.
9325#[derive(Debug, Clone, Serialize, Deserialize)]
9326pub struct HealthcareAnomalyRates {
9327    /// Upcoding rate.
9328    #[serde(default = "default_upcoding_rate")]
9329    pub upcoding: f64,
9330
9331    /// Unbundling rate.
9332    #[serde(default = "default_unbundling_rate")]
9333    pub unbundling: f64,
9334
9335    /// Phantom billing rate.
9336    #[serde(default = "default_phantom_billing_rate")]
9337    pub phantom_billing: f64,
9338
9339    /// Kickback rate.
9340    #[serde(default = "default_healthcare_kickback_rate")]
9341    pub kickbacks: f64,
9342
9343    /// Duplicate billing rate.
9344    #[serde(default = "default_duplicate_billing_rate")]
9345    pub duplicate_billing: f64,
9346
9347    /// Medical necessity abuse rate.
9348    #[serde(default = "default_med_necessity_rate")]
9349    pub medical_necessity_abuse: f64,
9350}
9351
9352fn default_upcoding_rate() -> f64 {
9353    0.02
9354}
9355
9356fn default_unbundling_rate() -> f64 {
9357    0.015
9358}
9359
9360fn default_phantom_billing_rate() -> f64 {
9361    0.005
9362}
9363
9364fn default_healthcare_kickback_rate() -> f64 {
9365    0.003
9366}
9367
9368fn default_duplicate_billing_rate() -> f64 {
9369    0.008
9370}
9371
9372fn default_med_necessity_rate() -> f64 {
9373    0.01
9374}
9375
9376impl Default for HealthcareAnomalyRates {
9377    fn default() -> Self {
9378        Self {
9379            upcoding: default_upcoding_rate(),
9380            unbundling: default_unbundling_rate(),
9381            phantom_billing: default_phantom_billing_rate(),
9382            kickbacks: default_healthcare_kickback_rate(),
9383            duplicate_billing: default_duplicate_billing_rate(),
9384            medical_necessity_abuse: default_med_necessity_rate(),
9385        }
9386    }
9387}
9388
9389/// Technology industry configuration.
9390#[derive(Debug, Clone, Serialize, Deserialize)]
9391pub struct TechnologyConfig {
9392    /// Enable technology-specific generation.
9393    #[serde(default)]
9394    pub enabled: bool,
9395
9396    /// Revenue model type.
9397    #[serde(default = "default_revenue_model")]
9398    pub revenue_model: String,
9399
9400    /// Subscription revenue percentage (for SaaS).
9401    #[serde(default = "default_subscription_pct")]
9402    pub subscription_revenue_pct: f64,
9403
9404    /// License revenue percentage.
9405    #[serde(default = "default_license_pct")]
9406    pub license_revenue_pct: f64,
9407
9408    /// Services revenue percentage.
9409    #[serde(default = "default_services_pct")]
9410    pub services_revenue_pct: f64,
9411
9412    /// R&D capitalization settings.
9413    #[serde(default)]
9414    pub rd_capitalization: RdCapitalizationConfig,
9415
9416    /// Technology anomaly injection rates.
9417    #[serde(default)]
9418    pub anomaly_rates: TechnologyAnomalyRates,
9419}
9420
9421fn default_revenue_model() -> String {
9422    "saas".to_string()
9423}
9424
9425fn default_subscription_pct() -> f64 {
9426    0.60
9427}
9428
9429fn default_license_pct() -> f64 {
9430    0.25
9431}
9432
9433fn default_services_pct() -> f64 {
9434    0.15
9435}
9436
9437impl Default for TechnologyConfig {
9438    fn default() -> Self {
9439        Self {
9440            enabled: false,
9441            revenue_model: default_revenue_model(),
9442            subscription_revenue_pct: default_subscription_pct(),
9443            license_revenue_pct: default_license_pct(),
9444            services_revenue_pct: default_services_pct(),
9445            rd_capitalization: RdCapitalizationConfig::default(),
9446            anomaly_rates: TechnologyAnomalyRates::default(),
9447        }
9448    }
9449}
9450
9451/// R&D capitalization configuration.
9452#[derive(Debug, Clone, Serialize, Deserialize)]
9453pub struct RdCapitalizationConfig {
9454    /// Enable R&D capitalization.
9455    #[serde(default = "default_true")]
9456    pub enabled: bool,
9457
9458    /// Capitalization rate (0.0-1.0).
9459    #[serde(default = "default_cap_rate")]
9460    pub capitalization_rate: f64,
9461
9462    /// Useful life in years.
9463    #[serde(default = "default_useful_life")]
9464    pub useful_life_years: u32,
9465}
9466
9467fn default_cap_rate() -> f64 {
9468    0.30
9469}
9470
9471fn default_useful_life() -> u32 {
9472    3
9473}
9474
9475impl Default for RdCapitalizationConfig {
9476    fn default() -> Self {
9477        Self {
9478            enabled: true,
9479            capitalization_rate: default_cap_rate(),
9480            useful_life_years: default_useful_life(),
9481        }
9482    }
9483}
9484
9485/// Technology anomaly injection rates.
9486#[derive(Debug, Clone, Serialize, Deserialize)]
9487pub struct TechnologyAnomalyRates {
9488    /// Premature revenue recognition rate.
9489    #[serde(default = "default_premature_rev_rate")]
9490    pub premature_revenue: f64,
9491
9492    /// Side letter abuse rate.
9493    #[serde(default = "default_side_letter_rate")]
9494    pub side_letter_abuse: f64,
9495
9496    /// Channel stuffing rate.
9497    #[serde(default = "default_channel_stuffing_rate")]
9498    pub channel_stuffing: f64,
9499
9500    /// Improper capitalization rate.
9501    #[serde(default = "default_improper_cap_rate")]
9502    pub improper_capitalization: f64,
9503}
9504
9505fn default_premature_rev_rate() -> f64 {
9506    0.015
9507}
9508
9509fn default_side_letter_rate() -> f64 {
9510    0.008
9511}
9512
9513fn default_channel_stuffing_rate() -> f64 {
9514    0.01
9515}
9516
9517fn default_improper_cap_rate() -> f64 {
9518    0.012
9519}
9520
9521impl Default for TechnologyAnomalyRates {
9522    fn default() -> Self {
9523        Self {
9524            premature_revenue: default_premature_rev_rate(),
9525            side_letter_abuse: default_side_letter_rate(),
9526            channel_stuffing: default_channel_stuffing_rate(),
9527            improper_capitalization: default_improper_cap_rate(),
9528        }
9529    }
9530}
9531
9532/// Financial services industry configuration.
9533#[derive(Debug, Clone, Serialize, Deserialize)]
9534pub struct FinancialServicesConfig {
9535    /// Enable financial services-specific generation.
9536    #[serde(default)]
9537    pub enabled: bool,
9538
9539    /// Financial institution type.
9540    #[serde(default = "default_fi_type")]
9541    pub institution_type: String,
9542
9543    /// Regulatory framework.
9544    #[serde(default = "default_fi_regulatory")]
9545    pub regulatory_framework: String,
9546
9547    /// Financial services anomaly injection rates.
9548    #[serde(default)]
9549    pub anomaly_rates: FinancialServicesAnomalyRates,
9550}
9551
9552fn default_fi_type() -> String {
9553    "commercial_bank".to_string()
9554}
9555
9556fn default_fi_regulatory() -> String {
9557    "us_banking".to_string()
9558}
9559
9560impl Default for FinancialServicesConfig {
9561    fn default() -> Self {
9562        Self {
9563            enabled: false,
9564            institution_type: default_fi_type(),
9565            regulatory_framework: default_fi_regulatory(),
9566            anomaly_rates: FinancialServicesAnomalyRates::default(),
9567        }
9568    }
9569}
9570
9571/// Financial services anomaly injection rates.
9572#[derive(Debug, Clone, Serialize, Deserialize)]
9573pub struct FinancialServicesAnomalyRates {
9574    /// Loan fraud rate.
9575    #[serde(default = "default_loan_fraud_rate")]
9576    pub loan_fraud: f64,
9577
9578    /// Trading fraud rate.
9579    #[serde(default = "default_trading_fraud_rate")]
9580    pub trading_fraud: f64,
9581
9582    /// Insurance fraud rate.
9583    #[serde(default = "default_insurance_fraud_rate")]
9584    pub insurance_fraud: f64,
9585
9586    /// Account manipulation rate.
9587    #[serde(default = "default_account_manip_rate")]
9588    pub account_manipulation: f64,
9589}
9590
9591fn default_loan_fraud_rate() -> f64 {
9592    0.01
9593}
9594
9595fn default_trading_fraud_rate() -> f64 {
9596    0.008
9597}
9598
9599fn default_insurance_fraud_rate() -> f64 {
9600    0.012
9601}
9602
9603fn default_account_manip_rate() -> f64 {
9604    0.005
9605}
9606
9607impl Default for FinancialServicesAnomalyRates {
9608    fn default() -> Self {
9609        Self {
9610            loan_fraud: default_loan_fraud_rate(),
9611            trading_fraud: default_trading_fraud_rate(),
9612            insurance_fraud: default_insurance_fraud_rate(),
9613            account_manipulation: default_account_manip_rate(),
9614        }
9615    }
9616}
9617
9618/// Professional services industry configuration.
9619#[derive(Debug, Clone, Serialize, Deserialize)]
9620pub struct ProfessionalServicesConfig {
9621    /// Enable professional services-specific generation.
9622    #[serde(default)]
9623    pub enabled: bool,
9624
9625    /// Firm type.
9626    #[serde(default = "default_firm_type")]
9627    pub firm_type: String,
9628
9629    /// Billing model.
9630    #[serde(default = "default_billing_model")]
9631    pub billing_model: String,
9632
9633    /// Average hourly rate.
9634    #[serde(default = "default_hourly_rate")]
9635    pub avg_hourly_rate: f64,
9636
9637    /// Trust account settings (for law firms).
9638    #[serde(default)]
9639    pub trust_accounting: TrustAccountingConfig,
9640
9641    /// Professional services anomaly injection rates.
9642    #[serde(default)]
9643    pub anomaly_rates: ProfessionalServicesAnomalyRates,
9644}
9645
9646fn default_firm_type() -> String {
9647    "consulting".to_string()
9648}
9649
9650fn default_billing_model() -> String {
9651    "time_and_materials".to_string()
9652}
9653
9654fn default_hourly_rate() -> f64 {
9655    250.0
9656}
9657
9658impl Default for ProfessionalServicesConfig {
9659    fn default() -> Self {
9660        Self {
9661            enabled: false,
9662            firm_type: default_firm_type(),
9663            billing_model: default_billing_model(),
9664            avg_hourly_rate: default_hourly_rate(),
9665            trust_accounting: TrustAccountingConfig::default(),
9666            anomaly_rates: ProfessionalServicesAnomalyRates::default(),
9667        }
9668    }
9669}
9670
9671/// Trust accounting configuration for law firms.
9672#[derive(Debug, Clone, Serialize, Deserialize)]
9673pub struct TrustAccountingConfig {
9674    /// Enable trust accounting.
9675    #[serde(default)]
9676    pub enabled: bool,
9677
9678    /// Require three-way reconciliation.
9679    #[serde(default = "default_true")]
9680    pub require_three_way_reconciliation: bool,
9681}
9682
9683impl Default for TrustAccountingConfig {
9684    fn default() -> Self {
9685        Self {
9686            enabled: false,
9687            require_three_way_reconciliation: true,
9688        }
9689    }
9690}
9691
9692/// Professional services anomaly injection rates.
9693#[derive(Debug, Clone, Serialize, Deserialize)]
9694pub struct ProfessionalServicesAnomalyRates {
9695    /// Time billing fraud rate.
9696    #[serde(default = "default_time_fraud_rate")]
9697    pub time_billing_fraud: f64,
9698
9699    /// Expense report fraud rate.
9700    #[serde(default = "default_expense_fraud_rate")]
9701    pub expense_fraud: f64,
9702
9703    /// Trust misappropriation rate.
9704    #[serde(default = "default_trust_misappropriation_rate")]
9705    pub trust_misappropriation: f64,
9706}
9707
9708fn default_time_fraud_rate() -> f64 {
9709    0.02
9710}
9711
9712fn default_expense_fraud_rate() -> f64 {
9713    0.015
9714}
9715
9716fn default_trust_misappropriation_rate() -> f64 {
9717    0.003
9718}
9719
9720impl Default for ProfessionalServicesAnomalyRates {
9721    fn default() -> Self {
9722        Self {
9723            time_billing_fraud: default_time_fraud_rate(),
9724            expense_fraud: default_expense_fraud_rate(),
9725            trust_misappropriation: default_trust_misappropriation_rate(),
9726        }
9727    }
9728}
9729
9730/// Fingerprint privacy configuration for extraction and synthesis.
9731///
9732/// Controls the privacy parameters used when extracting fingerprints
9733/// from sensitive data. Supports predefined levels or custom (epsilon, delta) tuples.
9734///
9735/// ```yaml
9736/// fingerprint_privacy:
9737///   level: custom
9738///   epsilon: 0.5
9739///   delta: 1.0e-5
9740///   k_anonymity: 10
9741///   composition_method: renyi_dp
9742/// ```
9743#[derive(Debug, Clone, Serialize, Deserialize)]
9744pub struct FingerprintPrivacyConfig {
9745    /// Privacy level preset. Use "custom" for user-specified epsilon/delta.
9746    #[serde(default)]
9747    pub level: String,
9748    /// Custom epsilon value (only used when level = "custom").
9749    #[serde(default = "default_epsilon")]
9750    pub epsilon: f64,
9751    /// Custom delta value for (epsilon, delta)-DP (only used with RDP/zCDP).
9752    #[serde(default = "default_delta")]
9753    pub delta: f64,
9754    /// K-anonymity threshold.
9755    #[serde(default = "default_k_anonymity")]
9756    pub k_anonymity: u32,
9757    /// Composition method: "naive", "advanced", "renyi_dp", "zcdp".
9758    #[serde(default)]
9759    pub composition_method: String,
9760}
9761
9762fn default_epsilon() -> f64 {
9763    1.0
9764}
9765
9766fn default_delta() -> f64 {
9767    1e-5
9768}
9769
9770fn default_k_anonymity() -> u32 {
9771    5
9772}
9773
9774impl Default for FingerprintPrivacyConfig {
9775    fn default() -> Self {
9776        Self {
9777            level: "standard".to_string(),
9778            epsilon: default_epsilon(),
9779            delta: default_delta(),
9780            k_anonymity: default_k_anonymity(),
9781            composition_method: "naive".to_string(),
9782        }
9783    }
9784}
9785
9786/// Quality gates configuration for pass/fail thresholds on generation runs.
9787///
9788/// ```yaml
9789/// quality_gates:
9790///   enabled: true
9791///   profile: strict  # strict, default, lenient, custom
9792///   fail_on_violation: true
9793///   custom_gates:
9794///     - name: benford_compliance
9795///       metric: benford_mad
9796///       threshold: 0.015
9797///       comparison: lte
9798/// ```
9799#[derive(Debug, Clone, Serialize, Deserialize)]
9800pub struct QualityGatesSchemaConfig {
9801    /// Enable quality gate evaluation.
9802    #[serde(default)]
9803    pub enabled: bool,
9804    /// Gate profile: "strict", "default", "lenient", or "custom".
9805    #[serde(default = "default_gate_profile_name")]
9806    pub profile: String,
9807    /// Whether to fail the generation on gate violations.
9808    #[serde(default)]
9809    pub fail_on_violation: bool,
9810    /// Custom gate definitions (used when profile = "custom").
9811    #[serde(default)]
9812    pub custom_gates: Vec<QualityGateEntry>,
9813}
9814
9815fn default_gate_profile_name() -> String {
9816    "default".to_string()
9817}
9818
9819impl Default for QualityGatesSchemaConfig {
9820    fn default() -> Self {
9821        Self {
9822            enabled: false,
9823            profile: default_gate_profile_name(),
9824            fail_on_violation: false,
9825            custom_gates: Vec::new(),
9826        }
9827    }
9828}
9829
9830/// A single quality gate entry in configuration.
9831#[derive(Debug, Clone, Serialize, Deserialize)]
9832pub struct QualityGateEntry {
9833    /// Gate name.
9834    pub name: String,
9835    /// Metric to check: benford_mad, balance_coherence, document_chain_integrity,
9836    /// correlation_preservation, temporal_consistency, privacy_mia_auc,
9837    /// completion_rate, duplicate_rate, referential_integrity, ic_match_rate.
9838    pub metric: String,
9839    /// Threshold value.
9840    pub threshold: f64,
9841    /// Upper threshold for "between" comparison.
9842    #[serde(default)]
9843    pub upper_threshold: Option<f64>,
9844    /// Comparison operator: "gte", "lte", "eq", "between".
9845    #[serde(default = "default_gate_comparison")]
9846    pub comparison: String,
9847}
9848
9849fn default_gate_comparison() -> String {
9850    "gte".to_string()
9851}
9852
9853/// Compliance configuration for regulatory requirements.
9854///
9855/// ```yaml
9856/// compliance:
9857///   content_marking:
9858///     enabled: true
9859///     format: embedded  # embedded, sidecar, both
9860///   article10_report: true
9861/// ```
9862#[derive(Debug, Clone, Default, Serialize, Deserialize)]
9863pub struct ComplianceSchemaConfig {
9864    /// Synthetic content marking configuration (EU AI Act Article 50).
9865    #[serde(default)]
9866    pub content_marking: ContentMarkingSchemaConfig,
9867    /// Generate Article 10 data governance report.
9868    #[serde(default)]
9869    pub article10_report: bool,
9870    /// Certificate configuration for proving DP guarantees.
9871    #[serde(default)]
9872    pub certificates: CertificateSchemaConfig,
9873}
9874
9875/// Configuration for synthetic data certificates.
9876#[derive(Debug, Clone, Default, Serialize, Deserialize)]
9877pub struct CertificateSchemaConfig {
9878    /// Whether certificate generation is enabled.
9879    #[serde(default)]
9880    pub enabled: bool,
9881    /// Environment variable name for the signing key.
9882    #[serde(default)]
9883    pub signing_key_env: Option<String>,
9884    /// Whether to include quality metrics in the certificate.
9885    #[serde(default)]
9886    pub include_quality_metrics: bool,
9887}
9888
9889/// Content marking configuration for synthetic data output.
9890#[derive(Debug, Clone, Serialize, Deserialize)]
9891pub struct ContentMarkingSchemaConfig {
9892    /// Whether content marking is enabled.
9893    #[serde(default = "default_true")]
9894    pub enabled: bool,
9895    /// Marking format: "embedded", "sidecar", or "both".
9896    #[serde(default = "default_marking_format")]
9897    pub format: String,
9898}
9899
9900fn default_marking_format() -> String {
9901    "embedded".to_string()
9902}
9903
9904impl Default for ContentMarkingSchemaConfig {
9905    fn default() -> Self {
9906        Self {
9907            enabled: true,
9908            format: default_marking_format(),
9909        }
9910    }
9911}
9912
9913/// Webhook notification configuration.
9914#[derive(Debug, Clone, Default, Serialize, Deserialize)]
9915pub struct WebhookSchemaConfig {
9916    /// Whether webhooks are enabled.
9917    #[serde(default)]
9918    pub enabled: bool,
9919    /// Webhook endpoint configurations.
9920    #[serde(default)]
9921    pub endpoints: Vec<WebhookEndpointConfig>,
9922}
9923
9924/// Configuration for a single webhook endpoint.
9925#[derive(Debug, Clone, Serialize, Deserialize)]
9926pub struct WebhookEndpointConfig {
9927    /// Target URL for the webhook.
9928    pub url: String,
9929    /// Event types this endpoint subscribes to.
9930    #[serde(default)]
9931    pub events: Vec<String>,
9932    /// Optional secret for HMAC-SHA256 signature.
9933    #[serde(default)]
9934    pub secret: Option<String>,
9935    /// Maximum retry attempts (default: 3).
9936    #[serde(default = "default_webhook_retries")]
9937    pub max_retries: u32,
9938    /// Timeout in seconds (default: 10).
9939    #[serde(default = "default_webhook_timeout")]
9940    pub timeout_secs: u64,
9941}
9942
9943fn default_webhook_retries() -> u32 {
9944    3
9945}
9946fn default_webhook_timeout() -> u64 {
9947    10
9948}
9949
9950// ===== Enterprise Process Chain Config Structs =====
9951
9952// ----- Source-to-Pay (S2C/S2P) -----
9953
9954/// Source-to-Pay configuration covering the entire sourcing lifecycle.
9955#[derive(Debug, Clone, Default, Serialize, Deserialize)]
9956pub struct SourceToPayConfig {
9957    /// Enable source-to-pay generation
9958    #[serde(default)]
9959    pub enabled: bool,
9960    /// Spend analysis configuration
9961    #[serde(default)]
9962    pub spend_analysis: SpendAnalysisConfig,
9963    /// Sourcing project configuration
9964    #[serde(default)]
9965    pub sourcing: SourcingConfig,
9966    /// Supplier qualification configuration
9967    #[serde(default)]
9968    pub qualification: QualificationConfig,
9969    /// RFx event configuration
9970    #[serde(default)]
9971    pub rfx: RfxConfig,
9972    /// Contract configuration
9973    #[serde(default)]
9974    pub contracts: ContractConfig,
9975    /// Catalog configuration
9976    #[serde(default)]
9977    pub catalog: CatalogConfig,
9978    /// Scorecard configuration
9979    #[serde(default)]
9980    pub scorecards: ScorecardConfig,
9981    /// P2P integration settings
9982    #[serde(default)]
9983    pub p2p_integration: P2PIntegrationConfig,
9984}
9985
9986/// Spend analysis configuration.
9987#[derive(Debug, Clone, Serialize, Deserialize)]
9988pub struct SpendAnalysisConfig {
9989    /// HHI threshold for triggering sourcing project
9990    #[serde(default = "default_hhi_threshold")]
9991    pub hhi_threshold: f64,
9992    /// Target spend coverage under contracts
9993    #[serde(default = "default_contract_coverage_target")]
9994    pub contract_coverage_target: f64,
9995}
9996
9997impl Default for SpendAnalysisConfig {
9998    fn default() -> Self {
9999        Self {
10000            hhi_threshold: default_hhi_threshold(),
10001            contract_coverage_target: default_contract_coverage_target(),
10002        }
10003    }
10004}
10005
10006fn default_hhi_threshold() -> f64 {
10007    2500.0
10008}
10009fn default_contract_coverage_target() -> f64 {
10010    0.80
10011}
10012
10013/// Sourcing project configuration.
10014#[derive(Debug, Clone, Serialize, Deserialize)]
10015pub struct SourcingConfig {
10016    /// Number of sourcing projects per year
10017    #[serde(default = "default_sourcing_projects_per_year")]
10018    pub projects_per_year: u32,
10019    /// Months before expiry to trigger renewal project
10020    #[serde(default = "default_renewal_horizon_months")]
10021    pub renewal_horizon_months: u32,
10022    /// Average project duration in months
10023    #[serde(default = "default_project_duration_months")]
10024    pub project_duration_months: u32,
10025}
10026
10027impl Default for SourcingConfig {
10028    fn default() -> Self {
10029        Self {
10030            projects_per_year: default_sourcing_projects_per_year(),
10031            renewal_horizon_months: default_renewal_horizon_months(),
10032            project_duration_months: default_project_duration_months(),
10033        }
10034    }
10035}
10036
10037fn default_sourcing_projects_per_year() -> u32 {
10038    10
10039}
10040fn default_renewal_horizon_months() -> u32 {
10041    3
10042}
10043fn default_project_duration_months() -> u32 {
10044    4
10045}
10046
10047/// Supplier qualification configuration.
10048#[derive(Debug, Clone, Serialize, Deserialize)]
10049pub struct QualificationConfig {
10050    /// Pass rate for qualification
10051    #[serde(default = "default_qualification_pass_rate")]
10052    pub pass_rate: f64,
10053    /// Qualification validity in days
10054    #[serde(default = "default_qualification_validity_days")]
10055    pub validity_days: u32,
10056    /// Financial stability weight
10057    #[serde(default = "default_financial_weight")]
10058    pub financial_weight: f64,
10059    /// Quality management weight
10060    #[serde(default = "default_quality_weight")]
10061    pub quality_weight: f64,
10062    /// Delivery performance weight
10063    #[serde(default = "default_delivery_weight")]
10064    pub delivery_weight: f64,
10065    /// Compliance weight
10066    #[serde(default = "default_compliance_weight")]
10067    pub compliance_weight: f64,
10068}
10069
10070impl Default for QualificationConfig {
10071    fn default() -> Self {
10072        Self {
10073            pass_rate: default_qualification_pass_rate(),
10074            validity_days: default_qualification_validity_days(),
10075            financial_weight: default_financial_weight(),
10076            quality_weight: default_quality_weight(),
10077            delivery_weight: default_delivery_weight(),
10078            compliance_weight: default_compliance_weight(),
10079        }
10080    }
10081}
10082
10083fn default_qualification_pass_rate() -> f64 {
10084    0.75
10085}
10086fn default_qualification_validity_days() -> u32 {
10087    365
10088}
10089fn default_financial_weight() -> f64 {
10090    0.25
10091}
10092fn default_quality_weight() -> f64 {
10093    0.30
10094}
10095fn default_delivery_weight() -> f64 {
10096    0.25
10097}
10098fn default_compliance_weight() -> f64 {
10099    0.20
10100}
10101
10102/// RFx event configuration.
10103#[derive(Debug, Clone, Serialize, Deserialize)]
10104pub struct RfxConfig {
10105    /// Spend threshold above which RFI is required before RFP
10106    #[serde(default = "default_rfi_threshold")]
10107    pub rfi_threshold: f64,
10108    /// Minimum vendors invited per RFx
10109    #[serde(default = "default_min_invited_vendors")]
10110    pub min_invited_vendors: u32,
10111    /// Maximum vendors invited per RFx
10112    #[serde(default = "default_max_invited_vendors")]
10113    pub max_invited_vendors: u32,
10114    /// Response rate (% of invited vendors that submit bids)
10115    #[serde(default = "default_response_rate")]
10116    pub response_rate: f64,
10117    /// Default price weight in evaluation
10118    #[serde(default = "default_price_weight")]
10119    pub default_price_weight: f64,
10120    /// Default quality weight in evaluation
10121    #[serde(default = "default_rfx_quality_weight")]
10122    pub default_quality_weight: f64,
10123    /// Default delivery weight in evaluation
10124    #[serde(default = "default_rfx_delivery_weight")]
10125    pub default_delivery_weight: f64,
10126}
10127
10128impl Default for RfxConfig {
10129    fn default() -> Self {
10130        Self {
10131            rfi_threshold: default_rfi_threshold(),
10132            min_invited_vendors: default_min_invited_vendors(),
10133            max_invited_vendors: default_max_invited_vendors(),
10134            response_rate: default_response_rate(),
10135            default_price_weight: default_price_weight(),
10136            default_quality_weight: default_rfx_quality_weight(),
10137            default_delivery_weight: default_rfx_delivery_weight(),
10138        }
10139    }
10140}
10141
10142fn default_rfi_threshold() -> f64 {
10143    100_000.0
10144}
10145fn default_min_invited_vendors() -> u32 {
10146    3
10147}
10148fn default_max_invited_vendors() -> u32 {
10149    8
10150}
10151fn default_response_rate() -> f64 {
10152    0.70
10153}
10154fn default_price_weight() -> f64 {
10155    0.40
10156}
10157fn default_rfx_quality_weight() -> f64 {
10158    0.35
10159}
10160fn default_rfx_delivery_weight() -> f64 {
10161    0.25
10162}
10163
10164/// Contract configuration.
10165#[derive(Debug, Clone, Serialize, Deserialize)]
10166pub struct ContractConfig {
10167    /// Minimum contract duration in months
10168    #[serde(default = "default_min_contract_months")]
10169    pub min_duration_months: u32,
10170    /// Maximum contract duration in months
10171    #[serde(default = "default_max_contract_months")]
10172    pub max_duration_months: u32,
10173    /// Auto-renewal rate
10174    #[serde(default = "default_auto_renewal_rate")]
10175    pub auto_renewal_rate: f64,
10176    /// Amendment rate (% of contracts with at least one amendment)
10177    #[serde(default = "default_amendment_rate")]
10178    pub amendment_rate: f64,
10179    /// Distribution of contract types
10180    #[serde(default)]
10181    pub type_distribution: ContractTypeDistribution,
10182}
10183
10184impl Default for ContractConfig {
10185    fn default() -> Self {
10186        Self {
10187            min_duration_months: default_min_contract_months(),
10188            max_duration_months: default_max_contract_months(),
10189            auto_renewal_rate: default_auto_renewal_rate(),
10190            amendment_rate: default_amendment_rate(),
10191            type_distribution: ContractTypeDistribution::default(),
10192        }
10193    }
10194}
10195
10196fn default_min_contract_months() -> u32 {
10197    12
10198}
10199fn default_max_contract_months() -> u32 {
10200    36
10201}
10202fn default_auto_renewal_rate() -> f64 {
10203    0.40
10204}
10205fn default_amendment_rate() -> f64 {
10206    0.20
10207}
10208
10209/// Distribution of contract types.
10210#[derive(Debug, Clone, Serialize, Deserialize)]
10211pub struct ContractTypeDistribution {
10212    /// Fixed price percentage
10213    #[serde(default = "default_fixed_price_pct")]
10214    pub fixed_price: f64,
10215    /// Blanket/framework percentage
10216    #[serde(default = "default_blanket_pct")]
10217    pub blanket: f64,
10218    /// Time and materials percentage
10219    #[serde(default = "default_time_materials_pct")]
10220    pub time_and_materials: f64,
10221    /// Service agreement percentage
10222    #[serde(default = "default_service_agreement_pct")]
10223    pub service_agreement: f64,
10224}
10225
10226impl Default for ContractTypeDistribution {
10227    fn default() -> Self {
10228        Self {
10229            fixed_price: default_fixed_price_pct(),
10230            blanket: default_blanket_pct(),
10231            time_and_materials: default_time_materials_pct(),
10232            service_agreement: default_service_agreement_pct(),
10233        }
10234    }
10235}
10236
10237fn default_fixed_price_pct() -> f64 {
10238    0.40
10239}
10240fn default_blanket_pct() -> f64 {
10241    0.30
10242}
10243fn default_time_materials_pct() -> f64 {
10244    0.15
10245}
10246fn default_service_agreement_pct() -> f64 {
10247    0.15
10248}
10249
10250/// Catalog configuration.
10251#[derive(Debug, Clone, Serialize, Deserialize)]
10252pub struct CatalogConfig {
10253    /// Percentage of catalog items marked as preferred
10254    #[serde(default = "default_preferred_vendor_flag_rate")]
10255    pub preferred_vendor_flag_rate: f64,
10256    /// Rate of materials with multiple sources in catalog
10257    #[serde(default = "default_multi_source_rate")]
10258    pub multi_source_rate: f64,
10259}
10260
10261impl Default for CatalogConfig {
10262    fn default() -> Self {
10263        Self {
10264            preferred_vendor_flag_rate: default_preferred_vendor_flag_rate(),
10265            multi_source_rate: default_multi_source_rate(),
10266        }
10267    }
10268}
10269
10270fn default_preferred_vendor_flag_rate() -> f64 {
10271    0.70
10272}
10273fn default_multi_source_rate() -> f64 {
10274    0.25
10275}
10276
10277/// Scorecard configuration.
10278#[derive(Debug, Clone, Serialize, Deserialize)]
10279pub struct ScorecardConfig {
10280    /// Scorecard review frequency (quarterly, monthly)
10281    #[serde(default = "default_scorecard_frequency")]
10282    pub frequency: String,
10283    /// On-time delivery weight in overall score
10284    #[serde(default = "default_otd_weight")]
10285    pub on_time_delivery_weight: f64,
10286    /// Quality weight in overall score
10287    #[serde(default = "default_quality_score_weight")]
10288    pub quality_weight: f64,
10289    /// Price competitiveness weight
10290    #[serde(default = "default_price_score_weight")]
10291    pub price_weight: f64,
10292    /// Responsiveness weight
10293    #[serde(default = "default_responsiveness_weight")]
10294    pub responsiveness_weight: f64,
10295    /// Grade A threshold (score >= this)
10296    #[serde(default = "default_grade_a_threshold")]
10297    pub grade_a_threshold: f64,
10298    /// Grade B threshold
10299    #[serde(default = "default_grade_b_threshold")]
10300    pub grade_b_threshold: f64,
10301    /// Grade C threshold
10302    #[serde(default = "default_grade_c_threshold")]
10303    pub grade_c_threshold: f64,
10304}
10305
10306impl Default for ScorecardConfig {
10307    fn default() -> Self {
10308        Self {
10309            frequency: default_scorecard_frequency(),
10310            on_time_delivery_weight: default_otd_weight(),
10311            quality_weight: default_quality_score_weight(),
10312            price_weight: default_price_score_weight(),
10313            responsiveness_weight: default_responsiveness_weight(),
10314            grade_a_threshold: default_grade_a_threshold(),
10315            grade_b_threshold: default_grade_b_threshold(),
10316            grade_c_threshold: default_grade_c_threshold(),
10317        }
10318    }
10319}
10320
10321fn default_scorecard_frequency() -> String {
10322    "quarterly".to_string()
10323}
10324fn default_otd_weight() -> f64 {
10325    0.30
10326}
10327fn default_quality_score_weight() -> f64 {
10328    0.30
10329}
10330fn default_price_score_weight() -> f64 {
10331    0.25
10332}
10333fn default_responsiveness_weight() -> f64 {
10334    0.15
10335}
10336fn default_grade_a_threshold() -> f64 {
10337    90.0
10338}
10339fn default_grade_b_threshold() -> f64 {
10340    75.0
10341}
10342fn default_grade_c_threshold() -> f64 {
10343    60.0
10344}
10345
10346/// P2P integration settings for contract enforcement.
10347#[derive(Debug, Clone, Serialize, Deserialize)]
10348pub struct P2PIntegrationConfig {
10349    /// Rate of off-contract (maverick) purchases
10350    #[serde(default = "default_off_contract_rate")]
10351    pub off_contract_rate: f64,
10352    /// Price tolerance for contract price validation
10353    #[serde(default = "default_price_tolerance")]
10354    pub price_tolerance: f64,
10355    /// Whether to enforce catalog ordering
10356    #[serde(default)]
10357    pub catalog_enforcement: bool,
10358}
10359
10360impl Default for P2PIntegrationConfig {
10361    fn default() -> Self {
10362        Self {
10363            off_contract_rate: default_off_contract_rate(),
10364            price_tolerance: default_price_tolerance(),
10365            catalog_enforcement: false,
10366        }
10367    }
10368}
10369
10370fn default_off_contract_rate() -> f64 {
10371    0.15
10372}
10373fn default_price_tolerance() -> f64 {
10374    0.02
10375}
10376
10377// ----- Financial Reporting -----
10378
10379/// Financial reporting configuration.
10380#[derive(Debug, Clone, Serialize, Deserialize)]
10381pub struct FinancialReportingConfig {
10382    /// Enable financial reporting generation
10383    #[serde(default)]
10384    pub enabled: bool,
10385    /// Generate balance sheet
10386    #[serde(default = "default_true")]
10387    pub generate_balance_sheet: bool,
10388    /// Generate income statement
10389    #[serde(default = "default_true")]
10390    pub generate_income_statement: bool,
10391    /// Generate cash flow statement
10392    #[serde(default = "default_true")]
10393    pub generate_cash_flow: bool,
10394    /// Generate changes in equity statement
10395    #[serde(default = "default_true")]
10396    pub generate_changes_in_equity: bool,
10397    /// Number of comparative periods
10398    #[serde(default = "default_comparative_periods")]
10399    pub comparative_periods: u32,
10400    /// Management KPIs configuration
10401    #[serde(default)]
10402    pub management_kpis: ManagementKpisConfig,
10403    /// Budget configuration
10404    #[serde(default)]
10405    pub budgets: BudgetConfig,
10406}
10407
10408impl Default for FinancialReportingConfig {
10409    fn default() -> Self {
10410        Self {
10411            enabled: false,
10412            generate_balance_sheet: true,
10413            generate_income_statement: true,
10414            generate_cash_flow: true,
10415            generate_changes_in_equity: true,
10416            comparative_periods: default_comparative_periods(),
10417            management_kpis: ManagementKpisConfig::default(),
10418            budgets: BudgetConfig::default(),
10419        }
10420    }
10421}
10422
10423fn default_comparative_periods() -> u32 {
10424    1
10425}
10426
10427/// Management KPIs configuration.
10428#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10429pub struct ManagementKpisConfig {
10430    /// Enable KPI generation
10431    #[serde(default)]
10432    pub enabled: bool,
10433    /// KPI calculation frequency (monthly, quarterly)
10434    #[serde(default = "default_kpi_frequency")]
10435    pub frequency: String,
10436}
10437
10438fn default_kpi_frequency() -> String {
10439    "monthly".to_string()
10440}
10441
10442/// Budget configuration.
10443#[derive(Debug, Clone, Serialize, Deserialize)]
10444pub struct BudgetConfig {
10445    /// Enable budget generation
10446    #[serde(default)]
10447    pub enabled: bool,
10448    /// Expected revenue growth rate for budgeting
10449    #[serde(default = "default_revenue_growth_rate")]
10450    pub revenue_growth_rate: f64,
10451    /// Expected expense inflation rate
10452    #[serde(default = "default_expense_inflation_rate")]
10453    pub expense_inflation_rate: f64,
10454    /// Random noise to add to budget vs actual
10455    #[serde(default = "default_variance_noise")]
10456    pub variance_noise: f64,
10457}
10458
10459impl Default for BudgetConfig {
10460    fn default() -> Self {
10461        Self {
10462            enabled: false,
10463            revenue_growth_rate: default_revenue_growth_rate(),
10464            expense_inflation_rate: default_expense_inflation_rate(),
10465            variance_noise: default_variance_noise(),
10466        }
10467    }
10468}
10469
10470fn default_revenue_growth_rate() -> f64 {
10471    0.05
10472}
10473fn default_expense_inflation_rate() -> f64 {
10474    0.03
10475}
10476fn default_variance_noise() -> f64 {
10477    0.10
10478}
10479
10480// ----- HR Configuration -----
10481
10482/// HR (Hire-to-Retire) process configuration.
10483#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10484pub struct HrConfig {
10485    /// Enable HR generation
10486    #[serde(default)]
10487    pub enabled: bool,
10488    /// Payroll configuration
10489    #[serde(default)]
10490    pub payroll: PayrollConfig,
10491    /// Time and attendance configuration
10492    #[serde(default)]
10493    pub time_attendance: TimeAttendanceConfig,
10494    /// Expense management configuration
10495    #[serde(default)]
10496    pub expenses: ExpenseConfig,
10497}
10498
10499/// Payroll configuration.
10500#[derive(Debug, Clone, Serialize, Deserialize)]
10501pub struct PayrollConfig {
10502    /// Enable payroll generation
10503    #[serde(default = "default_true")]
10504    pub enabled: bool,
10505    /// Pay frequency (monthly, biweekly, weekly)
10506    #[serde(default = "default_pay_frequency")]
10507    pub pay_frequency: String,
10508    /// Salary ranges by job level
10509    #[serde(default)]
10510    pub salary_ranges: PayrollSalaryRanges,
10511    /// Effective tax rates
10512    #[serde(default)]
10513    pub tax_rates: PayrollTaxRates,
10514    /// Benefits enrollment rate
10515    #[serde(default = "default_benefits_enrollment_rate")]
10516    pub benefits_enrollment_rate: f64,
10517    /// Retirement plan participation rate
10518    #[serde(default = "default_retirement_participation_rate")]
10519    pub retirement_participation_rate: f64,
10520}
10521
10522impl Default for PayrollConfig {
10523    fn default() -> Self {
10524        Self {
10525            enabled: true,
10526            pay_frequency: default_pay_frequency(),
10527            salary_ranges: PayrollSalaryRanges::default(),
10528            tax_rates: PayrollTaxRates::default(),
10529            benefits_enrollment_rate: default_benefits_enrollment_rate(),
10530            retirement_participation_rate: default_retirement_participation_rate(),
10531        }
10532    }
10533}
10534
10535fn default_pay_frequency() -> String {
10536    "monthly".to_string()
10537}
10538fn default_benefits_enrollment_rate() -> f64 {
10539    0.60
10540}
10541fn default_retirement_participation_rate() -> f64 {
10542    0.45
10543}
10544
10545/// Salary ranges by job level.
10546#[derive(Debug, Clone, Serialize, Deserialize)]
10547pub struct PayrollSalaryRanges {
10548    /// Staff level min/max
10549    #[serde(default = "default_staff_min")]
10550    pub staff_min: f64,
10551    #[serde(default = "default_staff_max")]
10552    pub staff_max: f64,
10553    /// Manager level min/max
10554    #[serde(default = "default_manager_min")]
10555    pub manager_min: f64,
10556    #[serde(default = "default_manager_max")]
10557    pub manager_max: f64,
10558    /// Director level min/max
10559    #[serde(default = "default_director_min")]
10560    pub director_min: f64,
10561    #[serde(default = "default_director_max")]
10562    pub director_max: f64,
10563    /// Executive level min/max
10564    #[serde(default = "default_executive_min")]
10565    pub executive_min: f64,
10566    #[serde(default = "default_executive_max")]
10567    pub executive_max: f64,
10568}
10569
10570impl Default for PayrollSalaryRanges {
10571    fn default() -> Self {
10572        Self {
10573            staff_min: default_staff_min(),
10574            staff_max: default_staff_max(),
10575            manager_min: default_manager_min(),
10576            manager_max: default_manager_max(),
10577            director_min: default_director_min(),
10578            director_max: default_director_max(),
10579            executive_min: default_executive_min(),
10580            executive_max: default_executive_max(),
10581        }
10582    }
10583}
10584
10585fn default_staff_min() -> f64 {
10586    50_000.0
10587}
10588fn default_staff_max() -> f64 {
10589    70_000.0
10590}
10591fn default_manager_min() -> f64 {
10592    80_000.0
10593}
10594fn default_manager_max() -> f64 {
10595    120_000.0
10596}
10597fn default_director_min() -> f64 {
10598    120_000.0
10599}
10600fn default_director_max() -> f64 {
10601    180_000.0
10602}
10603fn default_executive_min() -> f64 {
10604    180_000.0
10605}
10606fn default_executive_max() -> f64 {
10607    350_000.0
10608}
10609
10610/// Effective tax rates for payroll.
10611#[derive(Debug, Clone, Serialize, Deserialize)]
10612pub struct PayrollTaxRates {
10613    /// Federal effective tax rate
10614    #[serde(default = "default_federal_rate")]
10615    pub federal_effective: f64,
10616    /// State effective tax rate
10617    #[serde(default = "default_state_rate")]
10618    pub state_effective: f64,
10619    /// FICA/social security rate
10620    #[serde(default = "default_fica_rate")]
10621    pub fica: f64,
10622}
10623
10624impl Default for PayrollTaxRates {
10625    fn default() -> Self {
10626        Self {
10627            federal_effective: default_federal_rate(),
10628            state_effective: default_state_rate(),
10629            fica: default_fica_rate(),
10630        }
10631    }
10632}
10633
10634fn default_federal_rate() -> f64 {
10635    0.22
10636}
10637fn default_state_rate() -> f64 {
10638    0.05
10639}
10640fn default_fica_rate() -> f64 {
10641    0.0765
10642}
10643
10644/// Time and attendance configuration.
10645#[derive(Debug, Clone, Serialize, Deserialize)]
10646pub struct TimeAttendanceConfig {
10647    /// Enable time tracking
10648    #[serde(default = "default_true")]
10649    pub enabled: bool,
10650    /// Overtime rate (% of employees with overtime in a period)
10651    #[serde(default = "default_overtime_rate")]
10652    pub overtime_rate: f64,
10653}
10654
10655impl Default for TimeAttendanceConfig {
10656    fn default() -> Self {
10657        Self {
10658            enabled: true,
10659            overtime_rate: default_overtime_rate(),
10660        }
10661    }
10662}
10663
10664fn default_overtime_rate() -> f64 {
10665    0.10
10666}
10667
10668/// Expense management configuration.
10669#[derive(Debug, Clone, Serialize, Deserialize)]
10670pub struct ExpenseConfig {
10671    /// Enable expense report generation
10672    #[serde(default = "default_true")]
10673    pub enabled: bool,
10674    /// Rate of employees submitting expenses per month
10675    #[serde(default = "default_expense_submission_rate")]
10676    pub submission_rate: f64,
10677    /// Rate of policy violations
10678    #[serde(default = "default_policy_violation_rate")]
10679    pub policy_violation_rate: f64,
10680}
10681
10682impl Default for ExpenseConfig {
10683    fn default() -> Self {
10684        Self {
10685            enabled: true,
10686            submission_rate: default_expense_submission_rate(),
10687            policy_violation_rate: default_policy_violation_rate(),
10688        }
10689    }
10690}
10691
10692fn default_expense_submission_rate() -> f64 {
10693    0.30
10694}
10695fn default_policy_violation_rate() -> f64 {
10696    0.08
10697}
10698
10699// ----- Manufacturing Configuration -----
10700
10701/// Manufacturing process configuration (production orders, WIP, routing).
10702#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10703pub struct ManufacturingProcessConfig {
10704    /// Enable manufacturing generation
10705    #[serde(default)]
10706    pub enabled: bool,
10707    /// Production order configuration
10708    #[serde(default)]
10709    pub production_orders: ProductionOrderConfig,
10710    /// Costing configuration
10711    #[serde(default)]
10712    pub costing: ManufacturingCostingConfig,
10713    /// Routing configuration
10714    #[serde(default)]
10715    pub routing: RoutingConfig,
10716}
10717
10718/// Production order configuration.
10719#[derive(Debug, Clone, Serialize, Deserialize)]
10720pub struct ProductionOrderConfig {
10721    /// Orders per month
10722    #[serde(default = "default_prod_orders_per_month")]
10723    pub orders_per_month: u32,
10724    /// Average batch size
10725    #[serde(default = "default_prod_avg_batch_size")]
10726    pub avg_batch_size: u32,
10727    /// Yield rate
10728    #[serde(default = "default_prod_yield_rate")]
10729    pub yield_rate: f64,
10730    /// Make-to-order rate (vs make-to-stock)
10731    #[serde(default = "default_prod_make_to_order_rate")]
10732    pub make_to_order_rate: f64,
10733    /// Rework rate
10734    #[serde(default = "default_prod_rework_rate")]
10735    pub rework_rate: f64,
10736}
10737
10738impl Default for ProductionOrderConfig {
10739    fn default() -> Self {
10740        Self {
10741            orders_per_month: default_prod_orders_per_month(),
10742            avg_batch_size: default_prod_avg_batch_size(),
10743            yield_rate: default_prod_yield_rate(),
10744            make_to_order_rate: default_prod_make_to_order_rate(),
10745            rework_rate: default_prod_rework_rate(),
10746        }
10747    }
10748}
10749
10750fn default_prod_orders_per_month() -> u32 {
10751    50
10752}
10753fn default_prod_avg_batch_size() -> u32 {
10754    100
10755}
10756fn default_prod_yield_rate() -> f64 {
10757    0.97
10758}
10759fn default_prod_make_to_order_rate() -> f64 {
10760    0.20
10761}
10762fn default_prod_rework_rate() -> f64 {
10763    0.03
10764}
10765
10766/// Manufacturing costing configuration.
10767#[derive(Debug, Clone, Serialize, Deserialize)]
10768pub struct ManufacturingCostingConfig {
10769    /// Labor rate per hour
10770    #[serde(default = "default_labor_rate")]
10771    pub labor_rate_per_hour: f64,
10772    /// Overhead application rate (multiplier on direct labor)
10773    #[serde(default = "default_overhead_rate")]
10774    pub overhead_rate: f64,
10775    /// Standard cost update frequency
10776    #[serde(default = "default_cost_update_frequency")]
10777    pub standard_cost_update_frequency: String,
10778}
10779
10780impl Default for ManufacturingCostingConfig {
10781    fn default() -> Self {
10782        Self {
10783            labor_rate_per_hour: default_labor_rate(),
10784            overhead_rate: default_overhead_rate(),
10785            standard_cost_update_frequency: default_cost_update_frequency(),
10786        }
10787    }
10788}
10789
10790fn default_labor_rate() -> f64 {
10791    35.0
10792}
10793fn default_overhead_rate() -> f64 {
10794    1.50
10795}
10796fn default_cost_update_frequency() -> String {
10797    "quarterly".to_string()
10798}
10799
10800/// Routing configuration for production operations.
10801#[derive(Debug, Clone, Serialize, Deserialize)]
10802pub struct RoutingConfig {
10803    /// Average number of operations per routing
10804    #[serde(default = "default_avg_operations")]
10805    pub avg_operations: u32,
10806    /// Average setup time in hours
10807    #[serde(default = "default_setup_time")]
10808    pub setup_time_hours: f64,
10809    /// Run time variation coefficient
10810    #[serde(default = "default_run_time_variation")]
10811    pub run_time_variation: f64,
10812}
10813
10814impl Default for RoutingConfig {
10815    fn default() -> Self {
10816        Self {
10817            avg_operations: default_avg_operations(),
10818            setup_time_hours: default_setup_time(),
10819            run_time_variation: default_run_time_variation(),
10820        }
10821    }
10822}
10823
10824fn default_avg_operations() -> u32 {
10825    4
10826}
10827fn default_setup_time() -> f64 {
10828    1.5
10829}
10830fn default_run_time_variation() -> f64 {
10831    0.15
10832}
10833
10834// ----- Sales Quote Configuration -----
10835
10836/// Sales quote (quote-to-order) pipeline configuration.
10837#[derive(Debug, Clone, Serialize, Deserialize)]
10838pub struct SalesQuoteConfig {
10839    /// Enable sales quote generation
10840    #[serde(default)]
10841    pub enabled: bool,
10842    /// Quotes per month
10843    #[serde(default = "default_quotes_per_month")]
10844    pub quotes_per_month: u32,
10845    /// Win rate (fraction of quotes that convert to orders)
10846    #[serde(default = "default_quote_win_rate")]
10847    pub win_rate: f64,
10848    /// Average quote validity in days
10849    #[serde(default = "default_quote_validity_days")]
10850    pub validity_days: u32,
10851}
10852
10853impl Default for SalesQuoteConfig {
10854    fn default() -> Self {
10855        Self {
10856            enabled: false,
10857            quotes_per_month: default_quotes_per_month(),
10858            win_rate: default_quote_win_rate(),
10859            validity_days: default_quote_validity_days(),
10860        }
10861    }
10862}
10863
10864fn default_quotes_per_month() -> u32 {
10865    30
10866}
10867fn default_quote_win_rate() -> f64 {
10868    0.35
10869}
10870fn default_quote_validity_days() -> u32 {
10871    30
10872}
10873
10874// =============================================================================
10875// Tax Accounting Configuration
10876// =============================================================================
10877
10878/// Tax accounting configuration.
10879///
10880/// Controls generation of tax-related data including VAT/GST, sales tax,
10881/// withholding tax, tax provisions, and payroll tax across multiple jurisdictions.
10882#[derive(Debug, Clone, Serialize, Deserialize)]
10883pub struct TaxConfig {
10884    /// Whether tax generation is enabled.
10885    #[serde(default)]
10886    pub enabled: bool,
10887    /// Tax jurisdiction configuration.
10888    #[serde(default)]
10889    pub jurisdictions: TaxJurisdictionConfig,
10890    /// VAT/GST configuration.
10891    #[serde(default)]
10892    pub vat_gst: VatGstConfig,
10893    /// Sales tax configuration.
10894    #[serde(default)]
10895    pub sales_tax: SalesTaxConfig,
10896    /// Withholding tax configuration.
10897    #[serde(default)]
10898    pub withholding: WithholdingTaxSchemaConfig,
10899    /// Tax provision configuration.
10900    #[serde(default)]
10901    pub provisions: TaxProvisionSchemaConfig,
10902    /// Payroll tax configuration.
10903    #[serde(default)]
10904    pub payroll_tax: PayrollTaxSchemaConfig,
10905    /// Anomaly injection rate for tax data (0.0 to 1.0).
10906    #[serde(default = "default_tax_anomaly_rate")]
10907    pub anomaly_rate: f64,
10908}
10909
10910fn default_tax_anomaly_rate() -> f64 {
10911    0.03
10912}
10913
10914impl Default for TaxConfig {
10915    fn default() -> Self {
10916        Self {
10917            enabled: false,
10918            jurisdictions: TaxJurisdictionConfig::default(),
10919            vat_gst: VatGstConfig::default(),
10920            sales_tax: SalesTaxConfig::default(),
10921            withholding: WithholdingTaxSchemaConfig::default(),
10922            provisions: TaxProvisionSchemaConfig::default(),
10923            payroll_tax: PayrollTaxSchemaConfig::default(),
10924            anomaly_rate: default_tax_anomaly_rate(),
10925        }
10926    }
10927}
10928
10929/// Tax jurisdiction configuration.
10930///
10931/// Specifies which countries and subnational jurisdictions to include
10932/// when generating tax data.
10933#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10934pub struct TaxJurisdictionConfig {
10935    /// List of country codes to include (e.g., ["US", "DE", "GB"]).
10936    #[serde(default)]
10937    pub countries: Vec<String>,
10938    /// Whether to include subnational jurisdictions (e.g., US states, Canadian provinces).
10939    #[serde(default)]
10940    pub include_subnational: bool,
10941}
10942
10943/// VAT/GST configuration.
10944///
10945/// Controls generation of Value Added Tax / Goods and Services Tax data,
10946/// including standard and reduced rates, exempt categories, and reverse charge.
10947#[derive(Debug, Clone, Serialize, Deserialize)]
10948pub struct VatGstConfig {
10949    /// Whether VAT/GST generation is enabled.
10950    #[serde(default)]
10951    pub enabled: bool,
10952    /// Standard VAT/GST rates by country code (e.g., {"DE": 0.19, "GB": 0.20}).
10953    #[serde(default)]
10954    pub standard_rates: std::collections::HashMap<String, f64>,
10955    /// Reduced VAT/GST rates by country code (e.g., {"DE": 0.07, "GB": 0.05}).
10956    #[serde(default)]
10957    pub reduced_rates: std::collections::HashMap<String, f64>,
10958    /// Categories exempt from VAT/GST (e.g., ["financial_services", "healthcare"]).
10959    #[serde(default)]
10960    pub exempt_categories: Vec<String>,
10961    /// Whether to apply reverse charge mechanism for cross-border B2B transactions.
10962    #[serde(default = "default_true")]
10963    pub reverse_charge: bool,
10964}
10965
10966impl Default for VatGstConfig {
10967    fn default() -> Self {
10968        Self {
10969            enabled: false,
10970            standard_rates: std::collections::HashMap::new(),
10971            reduced_rates: std::collections::HashMap::new(),
10972            exempt_categories: Vec::new(),
10973            reverse_charge: true,
10974        }
10975    }
10976}
10977
10978/// Sales tax configuration.
10979///
10980/// Controls generation of US-style sales tax data including nexus determination.
10981#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10982pub struct SalesTaxConfig {
10983    /// Whether sales tax generation is enabled.
10984    #[serde(default)]
10985    pub enabled: bool,
10986    /// US states where the company has nexus (e.g., ["CA", "NY", "TX"]).
10987    #[serde(default)]
10988    pub nexus_states: Vec<String>,
10989}
10990
10991/// Withholding tax configuration.
10992///
10993/// Controls generation of withholding tax data for cross-border payments,
10994/// including treaty network and rate overrides.
10995#[derive(Debug, Clone, Serialize, Deserialize)]
10996pub struct WithholdingTaxSchemaConfig {
10997    /// Whether withholding tax generation is enabled.
10998    #[serde(default)]
10999    pub enabled: bool,
11000    /// Whether to simulate a treaty network with reduced rates.
11001    #[serde(default = "default_true")]
11002    pub treaty_network: bool,
11003    /// Default withholding tax rate for non-treaty countries (0.0 to 1.0).
11004    #[serde(default = "default_withholding_rate")]
11005    pub default_rate: f64,
11006    /// Reduced withholding tax rate for treaty countries (0.0 to 1.0).
11007    #[serde(default = "default_treaty_reduced_rate")]
11008    pub treaty_reduced_rate: f64,
11009}
11010
11011fn default_withholding_rate() -> f64 {
11012    0.30
11013}
11014
11015fn default_treaty_reduced_rate() -> f64 {
11016    0.15
11017}
11018
11019impl Default for WithholdingTaxSchemaConfig {
11020    fn default() -> Self {
11021        Self {
11022            enabled: false,
11023            treaty_network: true,
11024            default_rate: default_withholding_rate(),
11025            treaty_reduced_rate: default_treaty_reduced_rate(),
11026        }
11027    }
11028}
11029
11030/// Tax provision configuration.
11031///
11032/// Controls generation of tax provision data including statutory rates
11033/// and uncertain tax positions (ASC 740 / IAS 12).
11034#[derive(Debug, Clone, Serialize, Deserialize)]
11035pub struct TaxProvisionSchemaConfig {
11036    /// Whether tax provision generation is enabled.
11037    /// Defaults to true when tax is enabled, as provisions are typically required.
11038    #[serde(default = "default_true")]
11039    pub enabled: bool,
11040    /// Statutory corporate tax rate (0.0 to 1.0).
11041    #[serde(default = "default_statutory_rate")]
11042    pub statutory_rate: f64,
11043    /// Whether to generate uncertain tax positions (FIN 48 / IFRIC 23).
11044    #[serde(default = "default_true")]
11045    pub uncertain_positions: bool,
11046}
11047
11048fn default_statutory_rate() -> f64 {
11049    0.21
11050}
11051
11052impl Default for TaxProvisionSchemaConfig {
11053    fn default() -> Self {
11054        Self {
11055            enabled: true,
11056            statutory_rate: default_statutory_rate(),
11057            uncertain_positions: true,
11058        }
11059    }
11060}
11061
11062/// Payroll tax configuration.
11063///
11064/// Controls generation of payroll tax data (employer/employee contributions,
11065/// social security, Medicare, etc.).
11066#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11067pub struct PayrollTaxSchemaConfig {
11068    /// Whether payroll tax generation is enabled.
11069    #[serde(default)]
11070    pub enabled: bool,
11071}
11072
11073// ---------------------------------------------------------------------------
11074// Treasury & Cash Management Configuration
11075// ---------------------------------------------------------------------------
11076
11077/// Treasury and cash management configuration.
11078///
11079/// Controls generation of cash positions, forecasts, pooling, hedging
11080/// instruments (ASC 815 / IFRS 9), debt instruments with covenants,
11081/// bank guarantees, and intercompany netting runs.
11082#[derive(Debug, Clone, Serialize, Deserialize)]
11083pub struct TreasuryConfig {
11084    /// Whether treasury generation is enabled.
11085    #[serde(default)]
11086    pub enabled: bool,
11087    /// Cash positioning configuration.
11088    #[serde(default)]
11089    pub cash_positioning: CashPositioningConfig,
11090    /// Cash forecasting configuration.
11091    #[serde(default)]
11092    pub cash_forecasting: CashForecastingConfig,
11093    /// Cash pooling configuration.
11094    #[serde(default)]
11095    pub cash_pooling: CashPoolingConfig,
11096    /// Hedging configuration (FX forwards, IR swaps, etc.).
11097    #[serde(default)]
11098    pub hedging: HedgingSchemaConfig,
11099    /// Debt instrument and covenant configuration.
11100    #[serde(default)]
11101    pub debt: DebtSchemaConfig,
11102    /// Intercompany netting configuration.
11103    #[serde(default)]
11104    pub netting: NettingSchemaConfig,
11105    /// Bank guarantee / letter of credit configuration.
11106    #[serde(default)]
11107    pub bank_guarantees: BankGuaranteeSchemaConfig,
11108    /// Anomaly injection rate for treasury data (0.0 to 1.0).
11109    #[serde(default = "default_treasury_anomaly_rate")]
11110    pub anomaly_rate: f64,
11111}
11112
11113fn default_treasury_anomaly_rate() -> f64 {
11114    0.02
11115}
11116
11117impl Default for TreasuryConfig {
11118    fn default() -> Self {
11119        Self {
11120            enabled: false,
11121            cash_positioning: CashPositioningConfig::default(),
11122            cash_forecasting: CashForecastingConfig::default(),
11123            cash_pooling: CashPoolingConfig::default(),
11124            hedging: HedgingSchemaConfig::default(),
11125            debt: DebtSchemaConfig::default(),
11126            netting: NettingSchemaConfig::default(),
11127            bank_guarantees: BankGuaranteeSchemaConfig::default(),
11128            anomaly_rate: default_treasury_anomaly_rate(),
11129        }
11130    }
11131}
11132
11133/// Cash positioning configuration.
11134///
11135/// Controls daily cash position generation per entity/bank account.
11136#[derive(Debug, Clone, Serialize, Deserialize)]
11137pub struct CashPositioningConfig {
11138    /// Whether cash positioning is enabled.
11139    #[serde(default = "default_true")]
11140    pub enabled: bool,
11141    /// Position generation frequency.
11142    #[serde(default = "default_cash_frequency")]
11143    pub frequency: String,
11144    /// Minimum cash balance policy threshold.
11145    #[serde(default = "default_minimum_balance_policy")]
11146    pub minimum_balance_policy: f64,
11147}
11148
11149fn default_cash_frequency() -> String {
11150    "daily".to_string()
11151}
11152
11153fn default_minimum_balance_policy() -> f64 {
11154    100_000.0
11155}
11156
11157impl Default for CashPositioningConfig {
11158    fn default() -> Self {
11159        Self {
11160            enabled: true,
11161            frequency: default_cash_frequency(),
11162            minimum_balance_policy: default_minimum_balance_policy(),
11163        }
11164    }
11165}
11166
11167/// Cash forecasting configuration.
11168///
11169/// Controls forward-looking cash forecast generation with probability-weighted items.
11170#[derive(Debug, Clone, Serialize, Deserialize)]
11171pub struct CashForecastingConfig {
11172    /// Whether cash forecasting is enabled.
11173    #[serde(default = "default_true")]
11174    pub enabled: bool,
11175    /// Number of days to forecast into the future.
11176    #[serde(default = "default_horizon_days")]
11177    pub horizon_days: u32,
11178    /// AR collection probability curve type ("aging" or "flat").
11179    #[serde(default = "default_ar_probability_curve")]
11180    pub ar_collection_probability_curve: String,
11181    /// Confidence interval for the forecast (0.0 to 1.0).
11182    #[serde(default = "default_confidence_interval")]
11183    pub confidence_interval: f64,
11184}
11185
11186fn default_horizon_days() -> u32 {
11187    90
11188}
11189
11190fn default_ar_probability_curve() -> String {
11191    "aging".to_string()
11192}
11193
11194fn default_confidence_interval() -> f64 {
11195    0.90
11196}
11197
11198impl Default for CashForecastingConfig {
11199    fn default() -> Self {
11200        Self {
11201            enabled: true,
11202            horizon_days: default_horizon_days(),
11203            ar_collection_probability_curve: default_ar_probability_curve(),
11204            confidence_interval: default_confidence_interval(),
11205        }
11206    }
11207}
11208
11209/// Cash pooling configuration.
11210///
11211/// Controls cash pool structure generation (physical, notional, zero-balancing).
11212#[derive(Debug, Clone, Serialize, Deserialize)]
11213pub struct CashPoolingConfig {
11214    /// Whether cash pooling is enabled.
11215    #[serde(default)]
11216    pub enabled: bool,
11217    /// Pool type: "physical_pooling", "notional_pooling", or "zero_balancing".
11218    #[serde(default = "default_pool_type")]
11219    pub pool_type: String,
11220    /// Time of day when sweeps occur (HH:MM format).
11221    #[serde(default = "default_sweep_time")]
11222    pub sweep_time: String,
11223}
11224
11225fn default_pool_type() -> String {
11226    "zero_balancing".to_string()
11227}
11228
11229fn default_sweep_time() -> String {
11230    "16:00".to_string()
11231}
11232
11233impl Default for CashPoolingConfig {
11234    fn default() -> Self {
11235        Self {
11236            enabled: false,
11237            pool_type: default_pool_type(),
11238            sweep_time: default_sweep_time(),
11239        }
11240    }
11241}
11242
11243/// Hedging configuration.
11244///
11245/// Controls generation of hedging instruments and hedge relationship designations
11246/// under ASC 815 / IFRS 9.
11247#[derive(Debug, Clone, Serialize, Deserialize)]
11248pub struct HedgingSchemaConfig {
11249    /// Whether hedging generation is enabled.
11250    #[serde(default)]
11251    pub enabled: bool,
11252    /// Target hedge ratio (0.0 to 1.0). Proportion of FX exposure to hedge.
11253    #[serde(default = "default_hedge_ratio")]
11254    pub hedge_ratio: f64,
11255    /// Types of instruments to generate (e.g., ["fx_forward", "interest_rate_swap"]).
11256    #[serde(default = "default_hedge_instruments")]
11257    pub instruments: Vec<String>,
11258    /// Whether to designate formal hedge accounting relationships.
11259    #[serde(default = "default_true")]
11260    pub hedge_accounting: bool,
11261    /// Effectiveness testing method: "dollar_offset", "regression", or "critical_terms".
11262    #[serde(default = "default_effectiveness_method")]
11263    pub effectiveness_method: String,
11264}
11265
11266fn default_hedge_ratio() -> f64 {
11267    0.75
11268}
11269
11270fn default_hedge_instruments() -> Vec<String> {
11271    vec!["fx_forward".to_string(), "interest_rate_swap".to_string()]
11272}
11273
11274fn default_effectiveness_method() -> String {
11275    "regression".to_string()
11276}
11277
11278impl Default for HedgingSchemaConfig {
11279    fn default() -> Self {
11280        Self {
11281            enabled: false,
11282            hedge_ratio: default_hedge_ratio(),
11283            instruments: default_hedge_instruments(),
11284            hedge_accounting: true,
11285            effectiveness_method: default_effectiveness_method(),
11286        }
11287    }
11288}
11289
11290/// Debt instrument configuration.
11291///
11292/// Controls generation of debt instruments (term loans, revolving credit, bonds)
11293/// with amortization schedules and financial covenants.
11294#[derive(Debug, Clone, Default, Serialize, Deserialize)]
11295pub struct DebtSchemaConfig {
11296    /// Whether debt instrument generation is enabled.
11297    #[serde(default)]
11298    pub enabled: bool,
11299    /// Debt instrument definitions.
11300    #[serde(default)]
11301    pub instruments: Vec<DebtInstrumentDef>,
11302    /// Covenant definitions.
11303    #[serde(default)]
11304    pub covenants: Vec<CovenantDef>,
11305}
11306
11307/// Definition of a debt instrument in configuration.
11308#[derive(Debug, Clone, Serialize, Deserialize)]
11309pub struct DebtInstrumentDef {
11310    /// Instrument type: "term_loan", "revolving_credit", "bond", "commercial_paper", "bridge_loan".
11311    #[serde(rename = "type")]
11312    pub instrument_type: String,
11313    /// Principal amount (for term loans, bonds).
11314    #[serde(default)]
11315    pub principal: Option<f64>,
11316    /// Interest rate (annual, as decimal fraction).
11317    #[serde(default)]
11318    pub rate: Option<f64>,
11319    /// Maturity in months.
11320    #[serde(default)]
11321    pub maturity_months: Option<u32>,
11322    /// Facility limit (for revolving credit).
11323    #[serde(default)]
11324    pub facility: Option<f64>,
11325}
11326
11327/// Definition of a debt covenant in configuration.
11328#[derive(Debug, Clone, Serialize, Deserialize)]
11329pub struct CovenantDef {
11330    /// Covenant type: "debt_to_equity", "interest_coverage", "current_ratio",
11331    /// "net_worth", "debt_to_ebitda", "fixed_charge_coverage".
11332    #[serde(rename = "type")]
11333    pub covenant_type: String,
11334    /// Covenant threshold value.
11335    pub threshold: f64,
11336}
11337
11338/// Intercompany netting configuration.
11339///
11340/// Controls generation of multilateral netting runs.
11341#[derive(Debug, Clone, Serialize, Deserialize)]
11342pub struct NettingSchemaConfig {
11343    /// Whether netting generation is enabled.
11344    #[serde(default)]
11345    pub enabled: bool,
11346    /// Netting cycle: "daily", "weekly", or "monthly".
11347    #[serde(default = "default_netting_cycle")]
11348    pub cycle: String,
11349}
11350
11351fn default_netting_cycle() -> String {
11352    "monthly".to_string()
11353}
11354
11355impl Default for NettingSchemaConfig {
11356    fn default() -> Self {
11357        Self {
11358            enabled: false,
11359            cycle: default_netting_cycle(),
11360        }
11361    }
11362}
11363
11364/// Bank guarantee and letter of credit configuration.
11365///
11366/// Controls generation of bank guarantees, standby LCs, and performance bonds.
11367#[derive(Debug, Clone, Serialize, Deserialize)]
11368pub struct BankGuaranteeSchemaConfig {
11369    /// Whether bank guarantee generation is enabled.
11370    #[serde(default)]
11371    pub enabled: bool,
11372    /// Number of guarantees to generate.
11373    #[serde(default = "default_guarantee_count")]
11374    pub count: u32,
11375}
11376
11377fn default_guarantee_count() -> u32 {
11378    5
11379}
11380
11381impl Default for BankGuaranteeSchemaConfig {
11382    fn default() -> Self {
11383        Self {
11384            enabled: false,
11385            count: default_guarantee_count(),
11386        }
11387    }
11388}
11389
11390// ===========================================================================
11391// Project Accounting Configuration
11392// ===========================================================================
11393
11394/// Project accounting configuration.
11395///
11396/// Controls generation of project cost lines, revenue recognition,
11397/// milestones, change orders, retainage, and earned value metrics.
11398#[derive(Debug, Clone, Serialize, Deserialize)]
11399pub struct ProjectAccountingConfig {
11400    /// Whether project accounting is enabled.
11401    #[serde(default)]
11402    pub enabled: bool,
11403    /// Number of projects to generate.
11404    #[serde(default = "default_project_count")]
11405    pub project_count: u32,
11406    /// Distribution of project types (capital, internal, customer, r_and_d, maintenance, technology).
11407    #[serde(default)]
11408    pub project_types: ProjectTypeDistribution,
11409    /// WBS structure configuration.
11410    #[serde(default)]
11411    pub wbs: WbsSchemaConfig,
11412    /// Cost allocation rates (what % of source documents get project-tagged).
11413    #[serde(default)]
11414    pub cost_allocation: CostAllocationConfig,
11415    /// Revenue recognition configuration for project accounting.
11416    #[serde(default)]
11417    pub revenue_recognition: ProjectRevenueRecognitionConfig,
11418    /// Milestone configuration.
11419    #[serde(default)]
11420    pub milestones: MilestoneSchemaConfig,
11421    /// Change order configuration.
11422    #[serde(default)]
11423    pub change_orders: ChangeOrderSchemaConfig,
11424    /// Retainage configuration.
11425    #[serde(default)]
11426    pub retainage: RetainageSchemaConfig,
11427    /// Earned value management configuration.
11428    #[serde(default)]
11429    pub earned_value: EarnedValueSchemaConfig,
11430    /// Anomaly injection rate for project accounting data (0.0 to 1.0).
11431    #[serde(default = "default_project_anomaly_rate")]
11432    pub anomaly_rate: f64,
11433}
11434
11435fn default_project_count() -> u32 {
11436    10
11437}
11438
11439fn default_project_anomaly_rate() -> f64 {
11440    0.03
11441}
11442
11443impl Default for ProjectAccountingConfig {
11444    fn default() -> Self {
11445        Self {
11446            enabled: false,
11447            project_count: default_project_count(),
11448            project_types: ProjectTypeDistribution::default(),
11449            wbs: WbsSchemaConfig::default(),
11450            cost_allocation: CostAllocationConfig::default(),
11451            revenue_recognition: ProjectRevenueRecognitionConfig::default(),
11452            milestones: MilestoneSchemaConfig::default(),
11453            change_orders: ChangeOrderSchemaConfig::default(),
11454            retainage: RetainageSchemaConfig::default(),
11455            earned_value: EarnedValueSchemaConfig::default(),
11456            anomaly_rate: default_project_anomaly_rate(),
11457        }
11458    }
11459}
11460
11461/// Distribution of project types by weight.
11462#[derive(Debug, Clone, Serialize, Deserialize)]
11463pub struct ProjectTypeDistribution {
11464    /// Weight for capital projects (default 0.25).
11465    #[serde(default = "default_capital_weight")]
11466    pub capital: f64,
11467    /// Weight for internal projects (default 0.20).
11468    #[serde(default = "default_internal_weight")]
11469    pub internal: f64,
11470    /// Weight for customer projects (default 0.30).
11471    #[serde(default = "default_customer_weight")]
11472    pub customer: f64,
11473    /// Weight for R&D projects (default 0.10).
11474    #[serde(default = "default_rnd_weight")]
11475    pub r_and_d: f64,
11476    /// Weight for maintenance projects (default 0.10).
11477    #[serde(default = "default_maintenance_weight")]
11478    pub maintenance: f64,
11479    /// Weight for technology projects (default 0.05).
11480    #[serde(default = "default_technology_weight")]
11481    pub technology: f64,
11482}
11483
11484fn default_capital_weight() -> f64 {
11485    0.25
11486}
11487fn default_internal_weight() -> f64 {
11488    0.20
11489}
11490fn default_customer_weight() -> f64 {
11491    0.30
11492}
11493fn default_rnd_weight() -> f64 {
11494    0.10
11495}
11496fn default_maintenance_weight() -> f64 {
11497    0.10
11498}
11499fn default_technology_weight() -> f64 {
11500    0.05
11501}
11502
11503impl Default for ProjectTypeDistribution {
11504    fn default() -> Self {
11505        Self {
11506            capital: default_capital_weight(),
11507            internal: default_internal_weight(),
11508            customer: default_customer_weight(),
11509            r_and_d: default_rnd_weight(),
11510            maintenance: default_maintenance_weight(),
11511            technology: default_technology_weight(),
11512        }
11513    }
11514}
11515
11516/// WBS structure configuration.
11517#[derive(Debug, Clone, Serialize, Deserialize)]
11518pub struct WbsSchemaConfig {
11519    /// Maximum depth of WBS hierarchy (default 3).
11520    #[serde(default = "default_wbs_max_depth")]
11521    pub max_depth: u32,
11522    /// Minimum elements per level-1 WBS (default 2).
11523    #[serde(default = "default_wbs_min_elements")]
11524    pub min_elements_per_level: u32,
11525    /// Maximum elements per level-1 WBS (default 6).
11526    #[serde(default = "default_wbs_max_elements")]
11527    pub max_elements_per_level: u32,
11528}
11529
11530fn default_wbs_max_depth() -> u32 {
11531    3
11532}
11533fn default_wbs_min_elements() -> u32 {
11534    2
11535}
11536fn default_wbs_max_elements() -> u32 {
11537    6
11538}
11539
11540impl Default for WbsSchemaConfig {
11541    fn default() -> Self {
11542        Self {
11543            max_depth: default_wbs_max_depth(),
11544            min_elements_per_level: default_wbs_min_elements(),
11545            max_elements_per_level: default_wbs_max_elements(),
11546        }
11547    }
11548}
11549
11550/// Cost allocation rates — what fraction of each document type gets linked to a project.
11551#[derive(Debug, Clone, Serialize, Deserialize)]
11552pub struct CostAllocationConfig {
11553    /// Fraction of time entries assigned to projects (0.0 to 1.0).
11554    #[serde(default = "default_time_entry_rate")]
11555    pub time_entry_project_rate: f64,
11556    /// Fraction of expense reports assigned to projects (0.0 to 1.0).
11557    #[serde(default = "default_expense_rate")]
11558    pub expense_project_rate: f64,
11559    /// Fraction of purchase orders assigned to projects (0.0 to 1.0).
11560    #[serde(default = "default_po_rate")]
11561    pub purchase_order_project_rate: f64,
11562    /// Fraction of vendor invoices assigned to projects (0.0 to 1.0).
11563    #[serde(default = "default_vi_rate")]
11564    pub vendor_invoice_project_rate: f64,
11565}
11566
11567fn default_time_entry_rate() -> f64 {
11568    0.60
11569}
11570fn default_expense_rate() -> f64 {
11571    0.30
11572}
11573fn default_po_rate() -> f64 {
11574    0.40
11575}
11576fn default_vi_rate() -> f64 {
11577    0.35
11578}
11579
11580impl Default for CostAllocationConfig {
11581    fn default() -> Self {
11582        Self {
11583            time_entry_project_rate: default_time_entry_rate(),
11584            expense_project_rate: default_expense_rate(),
11585            purchase_order_project_rate: default_po_rate(),
11586            vendor_invoice_project_rate: default_vi_rate(),
11587        }
11588    }
11589}
11590
11591/// Revenue recognition configuration for project accounting.
11592#[derive(Debug, Clone, Serialize, Deserialize)]
11593pub struct ProjectRevenueRecognitionConfig {
11594    /// Whether revenue recognition is enabled for customer projects.
11595    #[serde(default = "default_true")]
11596    pub enabled: bool,
11597    /// Default method: "percentage_of_completion", "completed_contract", "milestone_based".
11598    #[serde(default = "default_revenue_method")]
11599    pub method: String,
11600    /// Default completion measure: "cost_to_cost", "labor_hours", "physical_completion".
11601    #[serde(default = "default_completion_measure")]
11602    pub completion_measure: String,
11603    /// Average contract value for customer projects.
11604    #[serde(default = "default_avg_contract_value")]
11605    pub avg_contract_value: f64,
11606}
11607
11608fn default_revenue_method() -> String {
11609    "percentage_of_completion".to_string()
11610}
11611fn default_completion_measure() -> String {
11612    "cost_to_cost".to_string()
11613}
11614fn default_avg_contract_value() -> f64 {
11615    500_000.0
11616}
11617
11618impl Default for ProjectRevenueRecognitionConfig {
11619    fn default() -> Self {
11620        Self {
11621            enabled: true,
11622            method: default_revenue_method(),
11623            completion_measure: default_completion_measure(),
11624            avg_contract_value: default_avg_contract_value(),
11625        }
11626    }
11627}
11628
11629/// Milestone configuration.
11630#[derive(Debug, Clone, Serialize, Deserialize)]
11631pub struct MilestoneSchemaConfig {
11632    /// Whether milestone generation is enabled.
11633    #[serde(default = "default_true")]
11634    pub enabled: bool,
11635    /// Average number of milestones per project.
11636    #[serde(default = "default_milestones_per_project")]
11637    pub avg_per_project: u32,
11638    /// Fraction of milestones that are payment milestones (0.0 to 1.0).
11639    #[serde(default = "default_payment_milestone_rate")]
11640    pub payment_milestone_rate: f64,
11641}
11642
11643fn default_milestones_per_project() -> u32 {
11644    4
11645}
11646fn default_payment_milestone_rate() -> f64 {
11647    0.50
11648}
11649
11650impl Default for MilestoneSchemaConfig {
11651    fn default() -> Self {
11652        Self {
11653            enabled: true,
11654            avg_per_project: default_milestones_per_project(),
11655            payment_milestone_rate: default_payment_milestone_rate(),
11656        }
11657    }
11658}
11659
11660/// Change order configuration.
11661#[derive(Debug, Clone, Serialize, Deserialize)]
11662pub struct ChangeOrderSchemaConfig {
11663    /// Whether change order generation is enabled.
11664    #[serde(default = "default_true")]
11665    pub enabled: bool,
11666    /// Probability that a project will have at least one change order (0.0 to 1.0).
11667    #[serde(default = "default_change_order_probability")]
11668    pub probability: f64,
11669    /// Maximum change orders per project.
11670    #[serde(default = "default_max_change_orders")]
11671    pub max_per_project: u32,
11672    /// Approval rate for change orders (0.0 to 1.0).
11673    #[serde(default = "default_change_order_approval_rate")]
11674    pub approval_rate: f64,
11675}
11676
11677fn default_change_order_probability() -> f64 {
11678    0.40
11679}
11680fn default_max_change_orders() -> u32 {
11681    3
11682}
11683fn default_change_order_approval_rate() -> f64 {
11684    0.75
11685}
11686
11687impl Default for ChangeOrderSchemaConfig {
11688    fn default() -> Self {
11689        Self {
11690            enabled: true,
11691            probability: default_change_order_probability(),
11692            max_per_project: default_max_change_orders(),
11693            approval_rate: default_change_order_approval_rate(),
11694        }
11695    }
11696}
11697
11698/// Retainage configuration.
11699#[derive(Debug, Clone, Serialize, Deserialize)]
11700pub struct RetainageSchemaConfig {
11701    /// Whether retainage is enabled.
11702    #[serde(default)]
11703    pub enabled: bool,
11704    /// Default retainage percentage (0.0 to 1.0, e.g., 0.10 for 10%).
11705    #[serde(default = "default_retainage_pct")]
11706    pub default_percentage: f64,
11707}
11708
11709fn default_retainage_pct() -> f64 {
11710    0.10
11711}
11712
11713impl Default for RetainageSchemaConfig {
11714    fn default() -> Self {
11715        Self {
11716            enabled: false,
11717            default_percentage: default_retainage_pct(),
11718        }
11719    }
11720}
11721
11722/// Earned value management (EVM) configuration.
11723#[derive(Debug, Clone, Serialize, Deserialize)]
11724pub struct EarnedValueSchemaConfig {
11725    /// Whether EVM metrics are generated.
11726    #[serde(default = "default_true")]
11727    pub enabled: bool,
11728    /// Measurement frequency: "weekly", "biweekly", "monthly".
11729    #[serde(default = "default_evm_frequency")]
11730    pub frequency: String,
11731}
11732
11733fn default_evm_frequency() -> String {
11734    "monthly".to_string()
11735}
11736
11737impl Default for EarnedValueSchemaConfig {
11738    fn default() -> Self {
11739        Self {
11740            enabled: true,
11741            frequency: default_evm_frequency(),
11742        }
11743    }
11744}
11745
11746// =============================================================================
11747// ESG / Sustainability Configuration
11748// =============================================================================
11749
11750/// Top-level ESG / sustainability reporting configuration.
11751#[derive(Debug, Clone, Serialize, Deserialize)]
11752pub struct EsgConfig {
11753    /// Whether ESG generation is enabled.
11754    #[serde(default)]
11755    pub enabled: bool,
11756    /// Environmental metrics (emissions, energy, water, waste).
11757    #[serde(default)]
11758    pub environmental: EnvironmentalConfig,
11759    /// Social metrics (diversity, pay equity, safety).
11760    #[serde(default)]
11761    pub social: SocialConfig,
11762    /// Governance metrics (board composition, ethics, compliance).
11763    #[serde(default)]
11764    pub governance: GovernanceSchemaConfig,
11765    /// Supply-chain ESG assessment settings.
11766    #[serde(default)]
11767    pub supply_chain_esg: SupplyChainEsgConfig,
11768    /// ESG reporting / disclosure framework settings.
11769    #[serde(default)]
11770    pub reporting: EsgReportingConfig,
11771    /// Climate scenario analysis settings.
11772    #[serde(default)]
11773    pub climate_scenarios: ClimateScenarioConfig,
11774    /// Anomaly injection rate for ESG data (0.0 to 1.0).
11775    #[serde(default = "default_esg_anomaly_rate")]
11776    pub anomaly_rate: f64,
11777}
11778
11779fn default_esg_anomaly_rate() -> f64 {
11780    0.02
11781}
11782
11783impl Default for EsgConfig {
11784    fn default() -> Self {
11785        Self {
11786            enabled: false,
11787            environmental: EnvironmentalConfig::default(),
11788            social: SocialConfig::default(),
11789            governance: GovernanceSchemaConfig::default(),
11790            supply_chain_esg: SupplyChainEsgConfig::default(),
11791            reporting: EsgReportingConfig::default(),
11792            climate_scenarios: ClimateScenarioConfig::default(),
11793            anomaly_rate: default_esg_anomaly_rate(),
11794        }
11795    }
11796}
11797
11798/// Environmental metrics configuration.
11799#[derive(Debug, Clone, Serialize, Deserialize)]
11800pub struct EnvironmentalConfig {
11801    /// Whether environmental metrics are generated.
11802    #[serde(default = "default_true")]
11803    pub enabled: bool,
11804    /// Scope 1 (direct) emission generation settings.
11805    #[serde(default)]
11806    pub scope1: EmissionScopeConfig,
11807    /// Scope 2 (purchased energy) emission generation settings.
11808    #[serde(default)]
11809    pub scope2: EmissionScopeConfig,
11810    /// Scope 3 (value chain) emission generation settings.
11811    #[serde(default)]
11812    pub scope3: Scope3Config,
11813    /// Energy consumption tracking settings.
11814    #[serde(default)]
11815    pub energy: EnergySchemaConfig,
11816    /// Water usage tracking settings.
11817    #[serde(default)]
11818    pub water: WaterSchemaConfig,
11819    /// Waste management tracking settings.
11820    #[serde(default)]
11821    pub waste: WasteSchemaConfig,
11822}
11823
11824impl Default for EnvironmentalConfig {
11825    fn default() -> Self {
11826        Self {
11827            enabled: true,
11828            scope1: EmissionScopeConfig::default(),
11829            scope2: EmissionScopeConfig::default(),
11830            scope3: Scope3Config::default(),
11831            energy: EnergySchemaConfig::default(),
11832            water: WaterSchemaConfig::default(),
11833            waste: WasteSchemaConfig::default(),
11834        }
11835    }
11836}
11837
11838/// Configuration for a single emission scope (Scope 1 or 2).
11839#[derive(Debug, Clone, Serialize, Deserialize)]
11840pub struct EmissionScopeConfig {
11841    /// Whether this scope is enabled.
11842    #[serde(default = "default_true")]
11843    pub enabled: bool,
11844    /// Emission factor region (e.g., "US", "EU", "global").
11845    #[serde(default = "default_emission_region")]
11846    pub factor_region: String,
11847}
11848
11849fn default_emission_region() -> String {
11850    "US".to_string()
11851}
11852
11853impl Default for EmissionScopeConfig {
11854    fn default() -> Self {
11855        Self {
11856            enabled: true,
11857            factor_region: default_emission_region(),
11858        }
11859    }
11860}
11861
11862/// Scope 3 (value chain) emission configuration.
11863#[derive(Debug, Clone, Serialize, Deserialize)]
11864pub struct Scope3Config {
11865    /// Whether Scope 3 emissions are generated.
11866    #[serde(default = "default_true")]
11867    pub enabled: bool,
11868    /// Categories to include (e.g., "purchased_goods", "business_travel", "commuting").
11869    #[serde(default = "default_scope3_categories")]
11870    pub categories: Vec<String>,
11871    /// Spend-based emission intensity (kg CO2e per USD).
11872    #[serde(default = "default_spend_intensity")]
11873    pub default_spend_intensity_kg_per_usd: f64,
11874}
11875
11876fn default_scope3_categories() -> Vec<String> {
11877    vec![
11878        "purchased_goods".to_string(),
11879        "business_travel".to_string(),
11880        "employee_commuting".to_string(),
11881    ]
11882}
11883
11884fn default_spend_intensity() -> f64 {
11885    0.5
11886}
11887
11888impl Default for Scope3Config {
11889    fn default() -> Self {
11890        Self {
11891            enabled: true,
11892            categories: default_scope3_categories(),
11893            default_spend_intensity_kg_per_usd: default_spend_intensity(),
11894        }
11895    }
11896}
11897
11898/// Energy consumption configuration.
11899#[derive(Debug, Clone, Serialize, Deserialize)]
11900pub struct EnergySchemaConfig {
11901    /// Whether energy consumption tracking is enabled.
11902    #[serde(default = "default_true")]
11903    pub enabled: bool,
11904    /// Number of facilities to generate.
11905    #[serde(default = "default_facility_count")]
11906    pub facility_count: u32,
11907    /// Target percentage of energy from renewable sources (0.0 to 1.0).
11908    #[serde(default = "default_renewable_target")]
11909    pub renewable_target: f64,
11910}
11911
11912fn default_facility_count() -> u32 {
11913    5
11914}
11915
11916fn default_renewable_target() -> f64 {
11917    0.30
11918}
11919
11920impl Default for EnergySchemaConfig {
11921    fn default() -> Self {
11922        Self {
11923            enabled: true,
11924            facility_count: default_facility_count(),
11925            renewable_target: default_renewable_target(),
11926        }
11927    }
11928}
11929
11930/// Water usage configuration.
11931#[derive(Debug, Clone, Serialize, Deserialize)]
11932pub struct WaterSchemaConfig {
11933    /// Whether water usage tracking is enabled.
11934    #[serde(default = "default_true")]
11935    pub enabled: bool,
11936    /// Number of facilities with water tracking.
11937    #[serde(default = "default_water_facility_count")]
11938    pub facility_count: u32,
11939}
11940
11941fn default_water_facility_count() -> u32 {
11942    3
11943}
11944
11945impl Default for WaterSchemaConfig {
11946    fn default() -> Self {
11947        Self {
11948            enabled: true,
11949            facility_count: default_water_facility_count(),
11950        }
11951    }
11952}
11953
11954/// Waste management configuration.
11955#[derive(Debug, Clone, Serialize, Deserialize)]
11956pub struct WasteSchemaConfig {
11957    /// Whether waste tracking is enabled.
11958    #[serde(default = "default_true")]
11959    pub enabled: bool,
11960    /// Target diversion rate (0.0 to 1.0).
11961    #[serde(default = "default_diversion_target")]
11962    pub diversion_target: f64,
11963}
11964
11965fn default_diversion_target() -> f64 {
11966    0.50
11967}
11968
11969impl Default for WasteSchemaConfig {
11970    fn default() -> Self {
11971        Self {
11972            enabled: true,
11973            diversion_target: default_diversion_target(),
11974        }
11975    }
11976}
11977
11978/// Social metrics configuration.
11979#[derive(Debug, Clone, Serialize, Deserialize)]
11980pub struct SocialConfig {
11981    /// Whether social metrics are generated.
11982    #[serde(default = "default_true")]
11983    pub enabled: bool,
11984    /// Workforce diversity tracking settings.
11985    #[serde(default)]
11986    pub diversity: DiversitySchemaConfig,
11987    /// Pay equity analysis settings.
11988    #[serde(default)]
11989    pub pay_equity: PayEquitySchemaConfig,
11990    /// Safety incident and metrics settings.
11991    #[serde(default)]
11992    pub safety: SafetySchemaConfig,
11993}
11994
11995impl Default for SocialConfig {
11996    fn default() -> Self {
11997        Self {
11998            enabled: true,
11999            diversity: DiversitySchemaConfig::default(),
12000            pay_equity: PayEquitySchemaConfig::default(),
12001            safety: SafetySchemaConfig::default(),
12002        }
12003    }
12004}
12005
12006/// Workforce diversity configuration.
12007#[derive(Debug, Clone, Serialize, Deserialize)]
12008pub struct DiversitySchemaConfig {
12009    /// Whether diversity metrics are generated.
12010    #[serde(default = "default_true")]
12011    pub enabled: bool,
12012    /// Dimensions to track (e.g., "gender", "ethnicity", "age_group").
12013    #[serde(default = "default_diversity_dimensions")]
12014    pub dimensions: Vec<String>,
12015}
12016
12017fn default_diversity_dimensions() -> Vec<String> {
12018    vec![
12019        "gender".to_string(),
12020        "ethnicity".to_string(),
12021        "age_group".to_string(),
12022    ]
12023}
12024
12025impl Default for DiversitySchemaConfig {
12026    fn default() -> Self {
12027        Self {
12028            enabled: true,
12029            dimensions: default_diversity_dimensions(),
12030        }
12031    }
12032}
12033
12034/// Pay equity analysis configuration.
12035#[derive(Debug, Clone, Serialize, Deserialize)]
12036pub struct PayEquitySchemaConfig {
12037    /// Whether pay equity analysis is generated.
12038    #[serde(default = "default_true")]
12039    pub enabled: bool,
12040    /// Target pay gap threshold for flagging (e.g., 0.05 = 5% gap).
12041    #[serde(default = "default_pay_gap_threshold")]
12042    pub gap_threshold: f64,
12043}
12044
12045fn default_pay_gap_threshold() -> f64 {
12046    0.05
12047}
12048
12049impl Default for PayEquitySchemaConfig {
12050    fn default() -> Self {
12051        Self {
12052            enabled: true,
12053            gap_threshold: default_pay_gap_threshold(),
12054        }
12055    }
12056}
12057
12058/// Safety metrics configuration.
12059#[derive(Debug, Clone, Serialize, Deserialize)]
12060pub struct SafetySchemaConfig {
12061    /// Whether safety metrics are generated.
12062    #[serde(default = "default_true")]
12063    pub enabled: bool,
12064    /// Average annual recordable incidents per 200,000 hours.
12065    #[serde(default = "default_trir_target")]
12066    pub target_trir: f64,
12067    /// Number of safety incidents to generate.
12068    #[serde(default = "default_incident_count")]
12069    pub incident_count: u32,
12070}
12071
12072fn default_trir_target() -> f64 {
12073    2.5
12074}
12075
12076fn default_incident_count() -> u32 {
12077    20
12078}
12079
12080impl Default for SafetySchemaConfig {
12081    fn default() -> Self {
12082        Self {
12083            enabled: true,
12084            target_trir: default_trir_target(),
12085            incident_count: default_incident_count(),
12086        }
12087    }
12088}
12089
12090/// Governance metrics configuration.
12091#[derive(Debug, Clone, Serialize, Deserialize)]
12092pub struct GovernanceSchemaConfig {
12093    /// Whether governance metrics are generated.
12094    #[serde(default = "default_true")]
12095    pub enabled: bool,
12096    /// Number of board members.
12097    #[serde(default = "default_board_size")]
12098    pub board_size: u32,
12099    /// Target independent director ratio (0.0 to 1.0).
12100    #[serde(default = "default_independence_target")]
12101    pub independence_target: f64,
12102}
12103
12104fn default_board_size() -> u32 {
12105    11
12106}
12107
12108fn default_independence_target() -> f64 {
12109    0.67
12110}
12111
12112impl Default for GovernanceSchemaConfig {
12113    fn default() -> Self {
12114        Self {
12115            enabled: true,
12116            board_size: default_board_size(),
12117            independence_target: default_independence_target(),
12118        }
12119    }
12120}
12121
12122/// Supply-chain ESG assessment configuration.
12123#[derive(Debug, Clone, Serialize, Deserialize)]
12124pub struct SupplyChainEsgConfig {
12125    /// Whether supply chain ESG assessments are generated.
12126    #[serde(default = "default_true")]
12127    pub enabled: bool,
12128    /// Proportion of vendors to assess (0.0 to 1.0).
12129    #[serde(default = "default_assessment_coverage")]
12130    pub assessment_coverage: f64,
12131    /// High-risk country codes for automatic flagging.
12132    #[serde(default = "default_high_risk_countries")]
12133    pub high_risk_countries: Vec<String>,
12134}
12135
12136fn default_assessment_coverage() -> f64 {
12137    0.80
12138}
12139
12140fn default_high_risk_countries() -> Vec<String> {
12141    vec!["CN".to_string(), "BD".to_string(), "MM".to_string()]
12142}
12143
12144impl Default for SupplyChainEsgConfig {
12145    fn default() -> Self {
12146        Self {
12147            enabled: true,
12148            assessment_coverage: default_assessment_coverage(),
12149            high_risk_countries: default_high_risk_countries(),
12150        }
12151    }
12152}
12153
12154/// ESG reporting / disclosure framework configuration.
12155#[derive(Debug, Clone, Serialize, Deserialize)]
12156pub struct EsgReportingConfig {
12157    /// Whether ESG disclosures are generated.
12158    #[serde(default = "default_true")]
12159    pub enabled: bool,
12160    /// Frameworks to generate disclosures for.
12161    #[serde(default = "default_esg_frameworks")]
12162    pub frameworks: Vec<String>,
12163    /// Whether materiality assessment is performed.
12164    #[serde(default = "default_true")]
12165    pub materiality_assessment: bool,
12166    /// Materiality threshold for impact dimension (0.0 to 1.0).
12167    #[serde(default = "default_materiality_threshold")]
12168    pub impact_threshold: f64,
12169    /// Materiality threshold for financial dimension (0.0 to 1.0).
12170    #[serde(default = "default_materiality_threshold")]
12171    pub financial_threshold: f64,
12172}
12173
12174fn default_esg_frameworks() -> Vec<String> {
12175    vec!["GRI".to_string(), "ESRS".to_string()]
12176}
12177
12178fn default_materiality_threshold() -> f64 {
12179    0.6
12180}
12181
12182impl Default for EsgReportingConfig {
12183    fn default() -> Self {
12184        Self {
12185            enabled: true,
12186            frameworks: default_esg_frameworks(),
12187            materiality_assessment: true,
12188            impact_threshold: default_materiality_threshold(),
12189            financial_threshold: default_materiality_threshold(),
12190        }
12191    }
12192}
12193
12194/// Climate scenario analysis configuration.
12195#[derive(Debug, Clone, Serialize, Deserialize)]
12196pub struct ClimateScenarioConfig {
12197    /// Whether climate scenario analysis is generated.
12198    #[serde(default)]
12199    pub enabled: bool,
12200    /// Scenarios to model (e.g., "net_zero_2050", "stated_policies", "current_trajectory").
12201    #[serde(default = "default_climate_scenarios")]
12202    pub scenarios: Vec<String>,
12203    /// Time horizons in years to project.
12204    #[serde(default = "default_time_horizons")]
12205    pub time_horizons: Vec<u32>,
12206}
12207
12208fn default_climate_scenarios() -> Vec<String> {
12209    vec![
12210        "net_zero_2050".to_string(),
12211        "stated_policies".to_string(),
12212        "current_trajectory".to_string(),
12213    ]
12214}
12215
12216fn default_time_horizons() -> Vec<u32> {
12217    vec![5, 10, 30]
12218}
12219
12220impl Default for ClimateScenarioConfig {
12221    fn default() -> Self {
12222        Self {
12223            enabled: false,
12224            scenarios: default_climate_scenarios(),
12225            time_horizons: default_time_horizons(),
12226        }
12227    }
12228}
12229
12230#[cfg(test)]
12231#[allow(clippy::unwrap_used)]
12232mod tests {
12233    use super::*;
12234    use crate::presets::demo_preset;
12235
12236    // ==========================================================================
12237    // Serialization/Deserialization Tests
12238    // ==========================================================================
12239
12240    #[test]
12241    fn test_config_yaml_roundtrip() {
12242        let config = demo_preset();
12243        let yaml = serde_yaml::to_string(&config).expect("Failed to serialize to YAML");
12244        let deserialized: GeneratorConfig =
12245            serde_yaml::from_str(&yaml).expect("Failed to deserialize from YAML");
12246
12247        assert_eq!(
12248            config.global.period_months,
12249            deserialized.global.period_months
12250        );
12251        assert_eq!(config.global.industry, deserialized.global.industry);
12252        assert_eq!(config.companies.len(), deserialized.companies.len());
12253        assert_eq!(config.companies[0].code, deserialized.companies[0].code);
12254    }
12255
12256    #[test]
12257    fn test_config_json_roundtrip() {
12258        // Create a config without infinity values (JSON can't serialize f64::INFINITY)
12259        let mut config = demo_preset();
12260        // Replace infinity with a large but finite value for JSON compatibility
12261        config.master_data.employees.approval_limits.executive = 1e12;
12262
12263        let json = serde_json::to_string(&config).expect("Failed to serialize to JSON");
12264        let deserialized: GeneratorConfig =
12265            serde_json::from_str(&json).expect("Failed to deserialize from JSON");
12266
12267        assert_eq!(
12268            config.global.period_months,
12269            deserialized.global.period_months
12270        );
12271        assert_eq!(config.global.industry, deserialized.global.industry);
12272        assert_eq!(config.companies.len(), deserialized.companies.len());
12273    }
12274
12275    #[test]
12276    fn test_transaction_volume_serialization() {
12277        // Test various transaction volumes serialize correctly
12278        let volumes = vec![
12279            (TransactionVolume::TenK, "ten_k"),
12280            (TransactionVolume::HundredK, "hundred_k"),
12281            (TransactionVolume::OneM, "one_m"),
12282            (TransactionVolume::TenM, "ten_m"),
12283            (TransactionVolume::HundredM, "hundred_m"),
12284        ];
12285
12286        for (volume, expected_key) in volumes {
12287            let json = serde_json::to_string(&volume).expect("Failed to serialize");
12288            assert!(
12289                json.contains(expected_key),
12290                "Expected {} in JSON: {}",
12291                expected_key,
12292                json
12293            );
12294        }
12295    }
12296
12297    #[test]
12298    fn test_transaction_volume_custom_serialization() {
12299        let volume = TransactionVolume::Custom(12345);
12300        let json = serde_json::to_string(&volume).expect("Failed to serialize");
12301        let deserialized: TransactionVolume =
12302            serde_json::from_str(&json).expect("Failed to deserialize");
12303        assert_eq!(deserialized.count(), 12345);
12304    }
12305
12306    #[test]
12307    fn test_output_mode_serialization() {
12308        let modes = vec![
12309            OutputMode::Streaming,
12310            OutputMode::FlatFile,
12311            OutputMode::Both,
12312        ];
12313
12314        for mode in modes {
12315            let json = serde_json::to_string(&mode).expect("Failed to serialize");
12316            let deserialized: OutputMode =
12317                serde_json::from_str(&json).expect("Failed to deserialize");
12318            assert!(format!("{:?}", mode) == format!("{:?}", deserialized));
12319        }
12320    }
12321
12322    #[test]
12323    fn test_file_format_serialization() {
12324        let formats = vec![
12325            FileFormat::Csv,
12326            FileFormat::Parquet,
12327            FileFormat::Json,
12328            FileFormat::JsonLines,
12329        ];
12330
12331        for format in formats {
12332            let json = serde_json::to_string(&format).expect("Failed to serialize");
12333            let deserialized: FileFormat =
12334                serde_json::from_str(&json).expect("Failed to deserialize");
12335            assert!(format!("{:?}", format) == format!("{:?}", deserialized));
12336        }
12337    }
12338
12339    #[test]
12340    fn test_compression_algorithm_serialization() {
12341        let algos = vec![
12342            CompressionAlgorithm::Gzip,
12343            CompressionAlgorithm::Zstd,
12344            CompressionAlgorithm::Lz4,
12345            CompressionAlgorithm::Snappy,
12346        ];
12347
12348        for algo in algos {
12349            let json = serde_json::to_string(&algo).expect("Failed to serialize");
12350            let deserialized: CompressionAlgorithm =
12351                serde_json::from_str(&json).expect("Failed to deserialize");
12352            assert!(format!("{:?}", algo) == format!("{:?}", deserialized));
12353        }
12354    }
12355
12356    #[test]
12357    fn test_transfer_pricing_method_serialization() {
12358        let methods = vec![
12359            TransferPricingMethod::CostPlus,
12360            TransferPricingMethod::ComparableUncontrolled,
12361            TransferPricingMethod::ResalePrice,
12362            TransferPricingMethod::TransactionalNetMargin,
12363            TransferPricingMethod::ProfitSplit,
12364        ];
12365
12366        for method in methods {
12367            let json = serde_json::to_string(&method).expect("Failed to serialize");
12368            let deserialized: TransferPricingMethod =
12369                serde_json::from_str(&json).expect("Failed to deserialize");
12370            assert!(format!("{:?}", method) == format!("{:?}", deserialized));
12371        }
12372    }
12373
12374    #[test]
12375    fn test_benford_exemption_serialization() {
12376        let exemptions = vec![
12377            BenfordExemption::Recurring,
12378            BenfordExemption::Payroll,
12379            BenfordExemption::FixedFees,
12380            BenfordExemption::RoundAmounts,
12381        ];
12382
12383        for exemption in exemptions {
12384            let json = serde_json::to_string(&exemption).expect("Failed to serialize");
12385            let deserialized: BenfordExemption =
12386                serde_json::from_str(&json).expect("Failed to deserialize");
12387            assert!(format!("{:?}", exemption) == format!("{:?}", deserialized));
12388        }
12389    }
12390
12391    // ==========================================================================
12392    // Default Value Tests
12393    // ==========================================================================
12394
12395    #[test]
12396    fn test_global_config_defaults() {
12397        let yaml = r#"
12398            industry: manufacturing
12399            start_date: "2024-01-01"
12400            period_months: 6
12401        "#;
12402        let config: GlobalConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12403        assert_eq!(config.group_currency, "USD");
12404        assert!(config.parallel);
12405        assert_eq!(config.worker_threads, 0);
12406        assert_eq!(config.memory_limit_mb, 0);
12407    }
12408
12409    #[test]
12410    fn test_fraud_config_defaults() {
12411        let config = FraudConfig::default();
12412        assert!(!config.enabled);
12413        assert_eq!(config.fraud_rate, 0.005);
12414        assert!(!config.clustering_enabled);
12415    }
12416
12417    #[test]
12418    fn test_internal_controls_config_defaults() {
12419        let config = InternalControlsConfig::default();
12420        assert!(!config.enabled);
12421        assert_eq!(config.exception_rate, 0.02);
12422        assert_eq!(config.sod_violation_rate, 0.01);
12423        assert!(config.export_control_master_data);
12424        assert_eq!(config.sox_materiality_threshold, 10000.0);
12425        // COSO fields
12426        assert!(config.coso_enabled);
12427        assert!(!config.include_entity_level_controls);
12428        assert_eq!(config.target_maturity_level, "mixed");
12429    }
12430
12431    #[test]
12432    fn test_output_config_defaults() {
12433        let config = OutputConfig::default();
12434        assert!(matches!(config.mode, OutputMode::FlatFile));
12435        assert_eq!(config.formats, vec![FileFormat::Parquet]);
12436        assert!(config.compression.enabled);
12437        assert!(matches!(
12438            config.compression.algorithm,
12439            CompressionAlgorithm::Zstd
12440        ));
12441        assert!(config.include_acdoca);
12442        assert!(!config.include_bseg);
12443        assert!(config.partition_by_period);
12444        assert!(!config.partition_by_company);
12445    }
12446
12447    #[test]
12448    fn test_approval_config_defaults() {
12449        let config = ApprovalConfig::default();
12450        assert!(!config.enabled);
12451        assert_eq!(config.auto_approve_threshold, 1000.0);
12452        assert_eq!(config.rejection_rate, 0.02);
12453        assert_eq!(config.revision_rate, 0.05);
12454        assert_eq!(config.average_approval_delay_hours, 4.0);
12455        assert_eq!(config.thresholds.len(), 4);
12456    }
12457
12458    #[test]
12459    fn test_p2p_flow_config_defaults() {
12460        let config = P2PFlowConfig::default();
12461        assert!(config.enabled);
12462        assert_eq!(config.three_way_match_rate, 0.95);
12463        assert_eq!(config.partial_delivery_rate, 0.15);
12464        assert_eq!(config.average_po_to_gr_days, 14);
12465    }
12466
12467    #[test]
12468    fn test_o2c_flow_config_defaults() {
12469        let config = O2CFlowConfig::default();
12470        assert!(config.enabled);
12471        assert_eq!(config.credit_check_failure_rate, 0.02);
12472        assert_eq!(config.return_rate, 0.03);
12473        assert_eq!(config.bad_debt_rate, 0.01);
12474    }
12475
12476    #[test]
12477    fn test_balance_config_defaults() {
12478        let config = BalanceConfig::default();
12479        assert!(!config.generate_opening_balances);
12480        assert!(config.generate_trial_balances);
12481        assert_eq!(config.target_gross_margin, 0.35);
12482        assert!(config.validate_balance_equation);
12483        assert!(config.reconcile_subledgers);
12484    }
12485
12486    // ==========================================================================
12487    // Partial Config Deserialization Tests
12488    // ==========================================================================
12489
12490    #[test]
12491    fn test_partial_config_with_defaults() {
12492        // Minimal config that should use all defaults
12493        let yaml = r#"
12494            global:
12495              industry: manufacturing
12496              start_date: "2024-01-01"
12497              period_months: 3
12498            companies:
12499              - code: "TEST"
12500                name: "Test Company"
12501                currency: "USD"
12502                country: "US"
12503                annual_transaction_volume: ten_k
12504            chart_of_accounts:
12505              complexity: small
12506            output:
12507              output_directory: "./output"
12508        "#;
12509
12510        let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12511        assert_eq!(config.global.period_months, 3);
12512        assert_eq!(config.companies.len(), 1);
12513        assert!(!config.fraud.enabled); // Default
12514        assert!(!config.internal_controls.enabled); // Default
12515    }
12516
12517    #[test]
12518    fn test_config_with_fraud_enabled() {
12519        let yaml = r#"
12520            global:
12521              industry: retail
12522              start_date: "2024-01-01"
12523              period_months: 12
12524            companies:
12525              - code: "RETAIL"
12526                name: "Retail Co"
12527                currency: "USD"
12528                country: "US"
12529                annual_transaction_volume: hundred_k
12530            chart_of_accounts:
12531              complexity: medium
12532            output:
12533              output_directory: "./output"
12534            fraud:
12535              enabled: true
12536              fraud_rate: 0.05
12537              clustering_enabled: true
12538        "#;
12539
12540        let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12541        assert!(config.fraud.enabled);
12542        assert_eq!(config.fraud.fraud_rate, 0.05);
12543        assert!(config.fraud.clustering_enabled);
12544    }
12545
12546    #[test]
12547    fn test_config_with_multiple_companies() {
12548        let yaml = r#"
12549            global:
12550              industry: manufacturing
12551              start_date: "2024-01-01"
12552              period_months: 6
12553            companies:
12554              - code: "HQ"
12555                name: "Headquarters"
12556                currency: "USD"
12557                country: "US"
12558                annual_transaction_volume: hundred_k
12559                volume_weight: 1.0
12560              - code: "EU"
12561                name: "European Subsidiary"
12562                currency: "EUR"
12563                country: "DE"
12564                annual_transaction_volume: hundred_k
12565                volume_weight: 0.5
12566              - code: "APAC"
12567                name: "Asia Pacific"
12568                currency: "JPY"
12569                country: "JP"
12570                annual_transaction_volume: ten_k
12571                volume_weight: 0.3
12572            chart_of_accounts:
12573              complexity: large
12574            output:
12575              output_directory: "./output"
12576        "#;
12577
12578        let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12579        assert_eq!(config.companies.len(), 3);
12580        assert_eq!(config.companies[0].code, "HQ");
12581        assert_eq!(config.companies[1].currency, "EUR");
12582        assert_eq!(config.companies[2].volume_weight, 0.3);
12583    }
12584
12585    #[test]
12586    fn test_intercompany_config() {
12587        let yaml = r#"
12588            enabled: true
12589            ic_transaction_rate: 0.20
12590            transfer_pricing_method: cost_plus
12591            markup_percent: 0.08
12592            generate_matched_pairs: true
12593            generate_eliminations: true
12594        "#;
12595
12596        let config: IntercompanyConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12597        assert!(config.enabled);
12598        assert_eq!(config.ic_transaction_rate, 0.20);
12599        assert!(matches!(
12600            config.transfer_pricing_method,
12601            TransferPricingMethod::CostPlus
12602        ));
12603        assert_eq!(config.markup_percent, 0.08);
12604        assert!(config.generate_eliminations);
12605    }
12606
12607    // ==========================================================================
12608    // Company Config Tests
12609    // ==========================================================================
12610
12611    #[test]
12612    fn test_company_config_defaults() {
12613        let yaml = r#"
12614            code: "TEST"
12615            name: "Test Company"
12616            currency: "USD"
12617            country: "US"
12618            annual_transaction_volume: ten_k
12619        "#;
12620
12621        let config: CompanyConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12622        assert_eq!(config.fiscal_year_variant, "K4"); // Default
12623        assert_eq!(config.volume_weight, 1.0); // Default
12624    }
12625
12626    // ==========================================================================
12627    // Chart of Accounts Config Tests
12628    // ==========================================================================
12629
12630    #[test]
12631    fn test_coa_config_defaults() {
12632        let yaml = r#"
12633            complexity: medium
12634        "#;
12635
12636        let config: ChartOfAccountsConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12637        assert!(config.industry_specific); // Default true
12638        assert!(config.custom_accounts.is_none());
12639        assert_eq!(config.min_hierarchy_depth, 2); // Default
12640        assert_eq!(config.max_hierarchy_depth, 5); // Default
12641    }
12642
12643    // ==========================================================================
12644    // Accounting Standards Config Tests
12645    // ==========================================================================
12646
12647    #[test]
12648    fn test_accounting_standards_config_defaults() {
12649        let config = AccountingStandardsConfig::default();
12650        assert!(!config.enabled);
12651        assert!(matches!(
12652            config.framework,
12653            AccountingFrameworkConfig::UsGaap
12654        ));
12655        assert!(!config.revenue_recognition.enabled);
12656        assert!(!config.leases.enabled);
12657        assert!(!config.fair_value.enabled);
12658        assert!(!config.impairment.enabled);
12659        assert!(!config.generate_differences);
12660    }
12661
12662    #[test]
12663    fn test_accounting_standards_config_yaml() {
12664        let yaml = r#"
12665            enabled: true
12666            framework: ifrs
12667            revenue_recognition:
12668              enabled: true
12669              generate_contracts: true
12670              avg_obligations_per_contract: 2.5
12671              variable_consideration_rate: 0.20
12672              over_time_recognition_rate: 0.35
12673              contract_count: 150
12674            leases:
12675              enabled: true
12676              lease_count: 75
12677              finance_lease_percent: 0.25
12678              avg_lease_term_months: 48
12679            generate_differences: true
12680        "#;
12681
12682        let config: AccountingStandardsConfig =
12683            serde_yaml::from_str(yaml).expect("Failed to parse");
12684        assert!(config.enabled);
12685        assert!(matches!(config.framework, AccountingFrameworkConfig::Ifrs));
12686        assert!(config.revenue_recognition.enabled);
12687        assert_eq!(config.revenue_recognition.contract_count, 150);
12688        assert_eq!(config.revenue_recognition.avg_obligations_per_contract, 2.5);
12689        assert!(config.leases.enabled);
12690        assert_eq!(config.leases.lease_count, 75);
12691        assert_eq!(config.leases.finance_lease_percent, 0.25);
12692        assert!(config.generate_differences);
12693    }
12694
12695    #[test]
12696    fn test_accounting_framework_serialization() {
12697        let frameworks = [
12698            AccountingFrameworkConfig::UsGaap,
12699            AccountingFrameworkConfig::Ifrs,
12700            AccountingFrameworkConfig::DualReporting,
12701        ];
12702
12703        for framework in frameworks {
12704            let json = serde_json::to_string(&framework).expect("Failed to serialize");
12705            let deserialized: AccountingFrameworkConfig =
12706                serde_json::from_str(&json).expect("Failed to deserialize");
12707            assert!(format!("{:?}", framework) == format!("{:?}", deserialized));
12708        }
12709    }
12710
12711    #[test]
12712    fn test_revenue_recognition_config_defaults() {
12713        let config = RevenueRecognitionConfig::default();
12714        assert!(!config.enabled);
12715        assert!(config.generate_contracts);
12716        assert_eq!(config.avg_obligations_per_contract, 2.0);
12717        assert_eq!(config.variable_consideration_rate, 0.15);
12718        assert_eq!(config.over_time_recognition_rate, 0.30);
12719        assert_eq!(config.contract_count, 100);
12720    }
12721
12722    #[test]
12723    fn test_lease_accounting_config_defaults() {
12724        let config = LeaseAccountingConfig::default();
12725        assert!(!config.enabled);
12726        assert_eq!(config.lease_count, 50);
12727        assert_eq!(config.finance_lease_percent, 0.30);
12728        assert_eq!(config.avg_lease_term_months, 60);
12729        assert!(config.generate_amortization);
12730        assert_eq!(config.real_estate_percent, 0.40);
12731    }
12732
12733    #[test]
12734    fn test_fair_value_config_defaults() {
12735        let config = FairValueConfig::default();
12736        assert!(!config.enabled);
12737        assert_eq!(config.measurement_count, 25);
12738        assert_eq!(config.level1_percent, 0.40);
12739        assert_eq!(config.level2_percent, 0.35);
12740        assert_eq!(config.level3_percent, 0.25);
12741        assert!(!config.include_sensitivity_analysis);
12742    }
12743
12744    #[test]
12745    fn test_impairment_config_defaults() {
12746        let config = ImpairmentConfig::default();
12747        assert!(!config.enabled);
12748        assert_eq!(config.test_count, 15);
12749        assert_eq!(config.impairment_rate, 0.10);
12750        assert!(config.generate_projections);
12751        assert!(!config.include_goodwill);
12752    }
12753
12754    // ==========================================================================
12755    // Audit Standards Config Tests
12756    // ==========================================================================
12757
12758    #[test]
12759    fn test_audit_standards_config_defaults() {
12760        let config = AuditStandardsConfig::default();
12761        assert!(!config.enabled);
12762        assert!(!config.isa_compliance.enabled);
12763        assert!(!config.analytical_procedures.enabled);
12764        assert!(!config.confirmations.enabled);
12765        assert!(!config.opinion.enabled);
12766        assert!(!config.generate_audit_trail);
12767        assert!(!config.sox.enabled);
12768        assert!(!config.pcaob.enabled);
12769    }
12770
12771    #[test]
12772    fn test_audit_standards_config_yaml() {
12773        let yaml = r#"
12774            enabled: true
12775            isa_compliance:
12776              enabled: true
12777              compliance_level: comprehensive
12778              generate_isa_mappings: true
12779              include_pcaob: true
12780              framework: dual
12781            analytical_procedures:
12782              enabled: true
12783              procedures_per_account: 5
12784              variance_probability: 0.25
12785            confirmations:
12786              enabled: true
12787              confirmation_count: 75
12788              positive_response_rate: 0.90
12789              exception_rate: 0.08
12790            opinion:
12791              enabled: true
12792              generate_kam: true
12793              average_kam_count: 4
12794            sox:
12795              enabled: true
12796              generate_302_certifications: true
12797              generate_404_assessments: true
12798              material_weakness_rate: 0.03
12799            pcaob:
12800              enabled: true
12801              is_pcaob_audit: true
12802              include_icfr_opinion: true
12803            generate_audit_trail: true
12804        "#;
12805
12806        let config: AuditStandardsConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12807        assert!(config.enabled);
12808        assert!(config.isa_compliance.enabled);
12809        assert_eq!(config.isa_compliance.compliance_level, "comprehensive");
12810        assert!(config.isa_compliance.include_pcaob);
12811        assert_eq!(config.isa_compliance.framework, "dual");
12812        assert!(config.analytical_procedures.enabled);
12813        assert_eq!(config.analytical_procedures.procedures_per_account, 5);
12814        assert!(config.confirmations.enabled);
12815        assert_eq!(config.confirmations.confirmation_count, 75);
12816        assert!(config.opinion.enabled);
12817        assert_eq!(config.opinion.average_kam_count, 4);
12818        assert!(config.sox.enabled);
12819        assert!(config.sox.generate_302_certifications);
12820        assert_eq!(config.sox.material_weakness_rate, 0.03);
12821        assert!(config.pcaob.enabled);
12822        assert!(config.pcaob.is_pcaob_audit);
12823        assert!(config.pcaob.include_icfr_opinion);
12824        assert!(config.generate_audit_trail);
12825    }
12826
12827    #[test]
12828    fn test_isa_compliance_config_defaults() {
12829        let config = IsaComplianceConfig::default();
12830        assert!(!config.enabled);
12831        assert_eq!(config.compliance_level, "standard");
12832        assert!(config.generate_isa_mappings);
12833        assert!(config.generate_coverage_summary);
12834        assert!(!config.include_pcaob);
12835        assert_eq!(config.framework, "isa");
12836    }
12837
12838    #[test]
12839    fn test_sox_compliance_config_defaults() {
12840        let config = SoxComplianceConfig::default();
12841        assert!(!config.enabled);
12842        assert!(config.generate_302_certifications);
12843        assert!(config.generate_404_assessments);
12844        assert_eq!(config.materiality_threshold, 10000.0);
12845        assert_eq!(config.material_weakness_rate, 0.02);
12846        assert_eq!(config.significant_deficiency_rate, 0.08);
12847    }
12848
12849    #[test]
12850    fn test_pcaob_config_defaults() {
12851        let config = PcaobConfig::default();
12852        assert!(!config.enabled);
12853        assert!(!config.is_pcaob_audit);
12854        assert!(config.generate_cam);
12855        assert!(!config.include_icfr_opinion);
12856        assert!(!config.generate_standard_mappings);
12857    }
12858
12859    #[test]
12860    fn test_config_with_standards_enabled() {
12861        let yaml = r#"
12862            global:
12863              industry: financial_services
12864              start_date: "2024-01-01"
12865              period_months: 12
12866            companies:
12867              - code: "BANK"
12868                name: "Test Bank"
12869                currency: "USD"
12870                country: "US"
12871                annual_transaction_volume: hundred_k
12872            chart_of_accounts:
12873              complexity: large
12874            output:
12875              output_directory: "./output"
12876            accounting_standards:
12877              enabled: true
12878              framework: us_gaap
12879              revenue_recognition:
12880                enabled: true
12881              leases:
12882                enabled: true
12883            audit_standards:
12884              enabled: true
12885              isa_compliance:
12886                enabled: true
12887              sox:
12888                enabled: true
12889        "#;
12890
12891        let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
12892        assert!(config.accounting_standards.enabled);
12893        assert!(matches!(
12894            config.accounting_standards.framework,
12895            AccountingFrameworkConfig::UsGaap
12896        ));
12897        assert!(config.accounting_standards.revenue_recognition.enabled);
12898        assert!(config.accounting_standards.leases.enabled);
12899        assert!(config.audit_standards.enabled);
12900        assert!(config.audit_standards.isa_compliance.enabled);
12901        assert!(config.audit_standards.sox.enabled);
12902    }
12903
12904    // ==========================================================================
12905    // Industry-Specific Config Tests
12906    // ==========================================================================
12907
12908    #[test]
12909    fn test_industry_specific_config_defaults() {
12910        let config = IndustrySpecificConfig::default();
12911        assert!(!config.enabled);
12912        assert!(!config.manufacturing.enabled);
12913        assert!(!config.retail.enabled);
12914        assert!(!config.healthcare.enabled);
12915        assert!(!config.technology.enabled);
12916        assert!(!config.financial_services.enabled);
12917        assert!(!config.professional_services.enabled);
12918    }
12919
12920    #[test]
12921    fn test_manufacturing_config_defaults() {
12922        let config = ManufacturingConfig::default();
12923        assert!(!config.enabled);
12924        assert_eq!(config.bom_depth, 4);
12925        assert!(!config.just_in_time);
12926        assert_eq!(config.supplier_tiers, 2);
12927        assert_eq!(config.target_yield_rate, 0.97);
12928        assert_eq!(config.scrap_alert_threshold, 0.03);
12929    }
12930
12931    #[test]
12932    fn test_retail_config_defaults() {
12933        let config = RetailConfig::default();
12934        assert!(!config.enabled);
12935        assert_eq!(config.avg_daily_transactions, 500);
12936        assert!(config.loss_prevention);
12937        assert_eq!(config.shrinkage_rate, 0.015);
12938    }
12939
12940    #[test]
12941    fn test_healthcare_config_defaults() {
12942        let config = HealthcareConfig::default();
12943        assert!(!config.enabled);
12944        assert_eq!(config.facility_type, "hospital");
12945        assert_eq!(config.avg_daily_encounters, 150);
12946        assert!(config.compliance.hipaa);
12947        assert!(config.compliance.stark_law);
12948        assert!(config.coding_systems.icd10);
12949        assert!(config.coding_systems.cpt);
12950    }
12951
12952    #[test]
12953    fn test_technology_config_defaults() {
12954        let config = TechnologyConfig::default();
12955        assert!(!config.enabled);
12956        assert_eq!(config.revenue_model, "saas");
12957        assert_eq!(config.subscription_revenue_pct, 0.60);
12958        assert!(config.rd_capitalization.enabled);
12959    }
12960
12961    #[test]
12962    fn test_config_with_industry_specific() {
12963        let yaml = r#"
12964            global:
12965              industry: healthcare
12966              start_date: "2024-01-01"
12967              period_months: 12
12968            companies:
12969              - code: "HOSP"
12970                name: "Test Hospital"
12971                currency: "USD"
12972                country: "US"
12973                annual_transaction_volume: hundred_k
12974            chart_of_accounts:
12975              complexity: medium
12976            output:
12977              output_directory: "./output"
12978            industry_specific:
12979              enabled: true
12980              healthcare:
12981                enabled: true
12982                facility_type: hospital
12983                payer_mix:
12984                  medicare: 0.45
12985                  medicaid: 0.15
12986                  commercial: 0.35
12987                  self_pay: 0.05
12988                coding_systems:
12989                  icd10: true
12990                  cpt: true
12991                  drg: true
12992                compliance:
12993                  hipaa: true
12994                  stark_law: true
12995                anomaly_rates:
12996                  upcoding: 0.03
12997                  unbundling: 0.02
12998        "#;
12999
13000        let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13001        assert!(config.industry_specific.enabled);
13002        assert!(config.industry_specific.healthcare.enabled);
13003        assert_eq!(
13004            config.industry_specific.healthcare.facility_type,
13005            "hospital"
13006        );
13007        assert_eq!(config.industry_specific.healthcare.payer_mix.medicare, 0.45);
13008        assert_eq!(config.industry_specific.healthcare.payer_mix.self_pay, 0.05);
13009        assert!(config.industry_specific.healthcare.coding_systems.icd10);
13010        assert!(config.industry_specific.healthcare.compliance.hipaa);
13011        assert_eq!(
13012            config.industry_specific.healthcare.anomaly_rates.upcoding,
13013            0.03
13014        );
13015    }
13016
13017    #[test]
13018    fn test_config_with_manufacturing_specific() {
13019        let yaml = r#"
13020            global:
13021              industry: manufacturing
13022              start_date: "2024-01-01"
13023              period_months: 12
13024            companies:
13025              - code: "MFG"
13026                name: "Test Manufacturing"
13027                currency: "USD"
13028                country: "US"
13029                annual_transaction_volume: hundred_k
13030            chart_of_accounts:
13031              complexity: medium
13032            output:
13033              output_directory: "./output"
13034            industry_specific:
13035              enabled: true
13036              manufacturing:
13037                enabled: true
13038                bom_depth: 5
13039                just_in_time: true
13040                supplier_tiers: 3
13041                target_yield_rate: 0.98
13042                anomaly_rates:
13043                  yield_manipulation: 0.02
13044                  phantom_production: 0.01
13045        "#;
13046
13047        let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13048        assert!(config.industry_specific.enabled);
13049        assert!(config.industry_specific.manufacturing.enabled);
13050        assert_eq!(config.industry_specific.manufacturing.bom_depth, 5);
13051        assert!(config.industry_specific.manufacturing.just_in_time);
13052        assert_eq!(config.industry_specific.manufacturing.supplier_tiers, 3);
13053        assert_eq!(
13054            config.industry_specific.manufacturing.target_yield_rate,
13055            0.98
13056        );
13057        assert_eq!(
13058            config
13059                .industry_specific
13060                .manufacturing
13061                .anomaly_rates
13062                .yield_manipulation,
13063            0.02
13064        );
13065    }
13066
13067    // ==========================================================================
13068    // Tax Configuration Tests
13069    // ==========================================================================
13070
13071    #[test]
13072    fn test_tax_config_defaults() {
13073        let tax = TaxConfig::default();
13074        assert!(!tax.enabled);
13075        assert!(tax.jurisdictions.countries.is_empty());
13076        assert!(!tax.jurisdictions.include_subnational);
13077        assert!(!tax.vat_gst.enabled);
13078        assert!(tax.vat_gst.standard_rates.is_empty());
13079        assert!(tax.vat_gst.reduced_rates.is_empty());
13080        assert!(tax.vat_gst.exempt_categories.is_empty());
13081        assert!(tax.vat_gst.reverse_charge);
13082        assert!(!tax.sales_tax.enabled);
13083        assert!(tax.sales_tax.nexus_states.is_empty());
13084        assert!(!tax.withholding.enabled);
13085        assert!(tax.withholding.treaty_network);
13086        assert_eq!(tax.withholding.default_rate, 0.30);
13087        assert_eq!(tax.withholding.treaty_reduced_rate, 0.15);
13088        assert!(tax.provisions.enabled);
13089        assert_eq!(tax.provisions.statutory_rate, 0.21);
13090        assert!(tax.provisions.uncertain_positions);
13091        assert!(!tax.payroll_tax.enabled);
13092        assert_eq!(tax.anomaly_rate, 0.03);
13093    }
13094
13095    #[test]
13096    fn test_tax_config_from_yaml() {
13097        let yaml = r#"
13098            global:
13099              seed: 42
13100              start_date: "2024-01-01"
13101              period_months: 12
13102              industry: retail
13103            companies:
13104              - code: C001
13105                name: Test Corp
13106                currency: USD
13107                country: US
13108                annual_transaction_volume: ten_k
13109            chart_of_accounts:
13110              complexity: small
13111            output:
13112              output_directory: ./output
13113            tax:
13114              enabled: true
13115              anomaly_rate: 0.05
13116              jurisdictions:
13117                countries: ["US", "DE", "GB"]
13118                include_subnational: true
13119              vat_gst:
13120                enabled: true
13121                standard_rates:
13122                  DE: 0.19
13123                  GB: 0.20
13124                reduced_rates:
13125                  DE: 0.07
13126                  GB: 0.05
13127                exempt_categories:
13128                  - financial_services
13129                  - healthcare
13130                reverse_charge: false
13131              sales_tax:
13132                enabled: true
13133                nexus_states: ["CA", "NY", "TX"]
13134              withholding:
13135                enabled: true
13136                treaty_network: false
13137                default_rate: 0.25
13138                treaty_reduced_rate: 0.10
13139              provisions:
13140                enabled: false
13141                statutory_rate: 0.28
13142                uncertain_positions: false
13143              payroll_tax:
13144                enabled: true
13145        "#;
13146
13147        let config: GeneratorConfig = serde_yaml::from_str(yaml).expect("Failed to parse");
13148        assert!(config.tax.enabled);
13149        assert_eq!(config.tax.anomaly_rate, 0.05);
13150
13151        // Jurisdictions
13152        assert_eq!(config.tax.jurisdictions.countries.len(), 3);
13153        assert!(config
13154            .tax
13155            .jurisdictions
13156            .countries
13157            .contains(&"DE".to_string()));
13158        assert!(config.tax.jurisdictions.include_subnational);
13159
13160        // VAT/GST
13161        assert!(config.tax.vat_gst.enabled);
13162        assert_eq!(config.tax.vat_gst.standard_rates.get("DE"), Some(&0.19));
13163        assert_eq!(config.tax.vat_gst.standard_rates.get("GB"), Some(&0.20));
13164        assert_eq!(config.tax.vat_gst.reduced_rates.get("DE"), Some(&0.07));
13165        assert_eq!(config.tax.vat_gst.exempt_categories.len(), 2);
13166        assert!(!config.tax.vat_gst.reverse_charge);
13167
13168        // Sales tax
13169        assert!(config.tax.sales_tax.enabled);
13170        assert_eq!(config.tax.sales_tax.nexus_states.len(), 3);
13171        assert!(config
13172            .tax
13173            .sales_tax
13174            .nexus_states
13175            .contains(&"CA".to_string()));
13176
13177        // Withholding
13178        assert!(config.tax.withholding.enabled);
13179        assert!(!config.tax.withholding.treaty_network);
13180        assert_eq!(config.tax.withholding.default_rate, 0.25);
13181        assert_eq!(config.tax.withholding.treaty_reduced_rate, 0.10);
13182
13183        // Provisions
13184        assert!(!config.tax.provisions.enabled);
13185        assert_eq!(config.tax.provisions.statutory_rate, 0.28);
13186        assert!(!config.tax.provisions.uncertain_positions);
13187
13188        // Payroll tax
13189        assert!(config.tax.payroll_tax.enabled);
13190    }
13191
13192    #[test]
13193    fn test_generator_config_with_tax_default() {
13194        let yaml = r#"
13195            global:
13196              seed: 42
13197              start_date: "2024-01-01"
13198              period_months: 12
13199              industry: retail
13200            companies:
13201              - code: C001
13202                name: Test Corp
13203                currency: USD
13204                country: US
13205                annual_transaction_volume: ten_k
13206            chart_of_accounts:
13207              complexity: small
13208            output:
13209              output_directory: ./output
13210        "#;
13211
13212        let config: GeneratorConfig =
13213            serde_yaml::from_str(yaml).expect("Failed to parse config without tax section");
13214        // Tax should be present with defaults when not specified in YAML
13215        assert!(!config.tax.enabled);
13216        assert!(config.tax.jurisdictions.countries.is_empty());
13217        assert_eq!(config.tax.anomaly_rate, 0.03);
13218        assert!(config.tax.provisions.enabled); // provisions default to enabled=true
13219        assert_eq!(config.tax.provisions.statutory_rate, 0.21);
13220    }
13221}