datasynth_core/models/compliance/
cross_reference.rs1use serde::{Deserialize, Serialize};
4
5use super::standard_id::StandardId;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
9#[serde(rename_all = "snake_case")]
10pub enum CrossReferenceType {
11 Converged,
13 Related,
15 Complementary,
17 DerivedFrom,
19 IncorporatedInto,
21 Parallel,
23 AuditMapping,
25 ControlFrameworkMapping,
27}
28
29impl std::fmt::Display for CrossReferenceType {
30 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
31 match self {
32 Self::Converged => write!(f, "Converged"),
33 Self::Related => write!(f, "Related"),
34 Self::Complementary => write!(f, "Complementary"),
35 Self::DerivedFrom => write!(f, "Derived From"),
36 Self::IncorporatedInto => write!(f, "Incorporated Into"),
37 Self::Parallel => write!(f, "Parallel"),
38 Self::AuditMapping => write!(f, "Audit Mapping"),
39 Self::ControlFrameworkMapping => write!(f, "Control Framework Mapping"),
40 }
41 }
42}
43
44#[derive(Debug, Clone, Serialize, Deserialize)]
46pub struct CrossReference {
47 pub from_standard: StandardId,
49 pub to_standard: StandardId,
51 pub relationship: CrossReferenceType,
53 pub convergence_level: f64,
55 pub description: Option<String>,
57}
58
59impl CrossReference {
60 pub fn new(from: StandardId, to: StandardId, relationship: CrossReferenceType) -> Self {
62 let convergence = match relationship {
63 CrossReferenceType::Converged => 0.9,
64 CrossReferenceType::IncorporatedInto => 0.85,
65 CrossReferenceType::Related => 0.6,
66 CrossReferenceType::Complementary => 0.5,
67 CrossReferenceType::DerivedFrom => 0.7,
68 CrossReferenceType::Parallel => 0.4,
69 CrossReferenceType::AuditMapping => 0.7,
70 CrossReferenceType::ControlFrameworkMapping => 0.6,
71 };
72
73 Self {
74 from_standard: from,
75 to_standard: to,
76 relationship,
77 convergence_level: convergence,
78 description: None,
79 }
80 }
81
82 pub fn with_convergence(mut self, level: f64) -> Self {
84 self.convergence_level = level.clamp(0.0, 1.0);
85 self
86 }
87
88 pub fn with_description(mut self, desc: impl Into<String>) -> Self {
90 self.description = Some(desc.into());
91 self
92 }
93}
94
95#[cfg(test)]
96mod tests {
97 use super::*;
98
99 #[test]
100 fn test_cross_reference() {
101 let xref = CrossReference::new(
102 StandardId::new("IFRS", "15"),
103 StandardId::new("ASC", "606"),
104 CrossReferenceType::Converged,
105 )
106 .with_description("Joint standard — substantially converged");
107
108 assert_eq!(xref.from_standard.as_str(), "IFRS-15");
109 assert_eq!(xref.to_standard.as_str(), "ASC-606");
110 assert!(xref.convergence_level > 0.8);
111 }
112}