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