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