Skip to main content

datasynth_eval/coherence/
mod.rs

1//! Semantic coherence evaluation module.
2//!
3//! Validates that generated data maintains accounting coherence including
4//! balance sheet equations, subledger reconciliation, and document chain integrity.
5
6mod balance;
7mod document_chain;
8mod intercompany;
9mod multi_table;
10mod network;
11mod referential;
12mod standards;
13mod subledger;
14
15pub use balance::{BalanceSheetEvaluation, BalanceSheetEvaluator};
16pub use document_chain::{DocumentChainEvaluation, DocumentChainEvaluator};
17pub use intercompany::{ICMatchingEvaluation, ICMatchingEvaluator};
18pub use multi_table::{
19    get_o2c_flow_relationships, get_p2p_flow_relationships, AnomalyRecord, CascadeAnomalyAnalysis,
20    CascadePath, ConsistencyViolation, MultiTableConsistencyEvaluator, MultiTableData,
21    MultiTableEvaluation, TableConsistencyResult, TableRecord, TableRelationship,
22    TableRelationshipDef, ViolationType,
23};
24pub use network::{
25    ConcentrationMetrics, NetworkEdge, NetworkEvaluation, NetworkEvaluator, NetworkNode,
26    NetworkThresholds, StrengthStats,
27};
28pub use referential::{ReferentialIntegrityEvaluation, ReferentialIntegrityEvaluator};
29pub use standards::{
30    AuditTrailEvaluation, AuditTrailGap, FairValueEvaluation, FrameworkViolation,
31    ImpairmentEvaluation, IsaComplianceEvaluation, LeaseAccountingEvaluation,
32    LeaseAccountingEvaluator, LeaseEvaluation, PcaobComplianceEvaluation, PerformanceObligation,
33    RevenueContract, RevenueRecognitionEvaluation, RevenueRecognitionEvaluator,
34    SoxComplianceEvaluation, StandardsComplianceEvaluation, StandardsThresholds,
35    VariableConsideration, ViolationSeverity,
36};
37pub use subledger::{SubledgerEvaluator, SubledgerReconciliationEvaluation};
38
39use serde::{Deserialize, Serialize};
40
41/// Combined coherence evaluation results.
42#[derive(Debug, Clone, Serialize, Deserialize)]
43pub struct CoherenceEvaluation {
44    /// Balance sheet validation results.
45    pub balance: Option<BalanceSheetEvaluation>,
46    /// Subledger reconciliation results.
47    pub subledger: Option<SubledgerReconciliationEvaluation>,
48    /// Document chain completeness results.
49    pub document_chain: Option<DocumentChainEvaluation>,
50    /// Intercompany matching results.
51    pub intercompany: Option<ICMatchingEvaluation>,
52    /// Referential integrity results.
53    pub referential: Option<ReferentialIntegrityEvaluation>,
54    /// Multi-table consistency results.
55    pub multi_table: Option<MultiTableEvaluation>,
56    /// Accounting and audit standards compliance results.
57    pub standards: Option<StandardsComplianceEvaluation>,
58    /// Network/interconnectivity evaluation results.
59    pub network: Option<NetworkEvaluation>,
60    /// Overall pass/fail status.
61    pub passes: bool,
62    /// Summary of failed checks.
63    pub failures: Vec<String>,
64}
65
66impl CoherenceEvaluation {
67    /// Create a new empty evaluation.
68    pub fn new() -> Self {
69        Self {
70            balance: None,
71            subledger: None,
72            document_chain: None,
73            intercompany: None,
74            referential: None,
75            multi_table: None,
76            standards: None,
77            network: None,
78            passes: true,
79            failures: Vec::new(),
80        }
81    }
82
83    /// Check all results against thresholds and update pass status.
84    pub fn check_thresholds(&mut self, thresholds: &crate::config::EvaluationThresholds) {
85        self.failures.clear();
86
87        if let Some(ref balance) = self.balance {
88            if !balance.equation_balanced {
89                self.failures.push(format!(
90                    "Balance sheet equation not balanced (max imbalance: {})",
91                    balance.max_imbalance
92                ));
93            }
94        }
95
96        if let Some(ref subledger) = self.subledger {
97            if subledger.completeness_score < thresholds.subledger_reconciliation_rate_min {
98                self.failures.push(format!(
99                    "Subledger reconciliation {} < {} (threshold)",
100                    subledger.completeness_score, thresholds.subledger_reconciliation_rate_min
101                ));
102            }
103        }
104
105        if let Some(ref doc_chain) = self.document_chain {
106            let min_rate = thresholds.document_chain_completion_min;
107            if doc_chain.p2p_completion_rate < min_rate {
108                self.failures.push(format!(
109                    "P2P chain completion {} < {} (threshold)",
110                    doc_chain.p2p_completion_rate, min_rate
111                ));
112            }
113            if doc_chain.o2c_completion_rate < min_rate {
114                self.failures.push(format!(
115                    "O2C chain completion {} < {} (threshold)",
116                    doc_chain.o2c_completion_rate, min_rate
117                ));
118            }
119        }
120
121        if let Some(ref ic) = self.intercompany {
122            if ic.match_rate < thresholds.ic_match_rate_min {
123                self.failures.push(format!(
124                    "IC match rate {} < {} (threshold)",
125                    ic.match_rate, thresholds.ic_match_rate_min
126                ));
127            }
128        }
129
130        if let Some(ref referential) = self.referential {
131            if referential.overall_integrity_score < thresholds.referential_integrity_min {
132                self.failures.push(format!(
133                    "Referential integrity {} < {} (threshold)",
134                    referential.overall_integrity_score, thresholds.referential_integrity_min
135                ));
136            }
137        }
138
139        if let Some(ref multi_table) = self.multi_table {
140            // Check multi-table consistency (use referential_integrity_min as default threshold)
141            if multi_table.overall_consistency_score < thresholds.referential_integrity_min {
142                self.failures.push(format!(
143                    "Multi-table consistency {} < {} (threshold)",
144                    multi_table.overall_consistency_score, thresholds.referential_integrity_min
145                ));
146            }
147            // Add any issues from the multi-table evaluation
148            self.failures.extend(multi_table.issues.clone());
149        }
150
151        if let Some(ref mut standards_eval) = self.standards.clone() {
152            // Use default standards thresholds
153            let standards_thresholds = StandardsThresholds::default();
154            standards_eval.check_thresholds(&standards_thresholds);
155            self.failures.extend(standards_eval.failures.clone());
156        }
157
158        if let Some(ref network_eval) = self.network {
159            // Add any network evaluation issues
160            if !network_eval.passes {
161                self.failures.extend(network_eval.issues.clone());
162            }
163        }
164
165        self.passes = self.failures.is_empty();
166    }
167}
168
169impl Default for CoherenceEvaluation {
170    fn default() -> Self {
171        Self::new()
172    }
173}