Skip to main content

datasynth_standards/regulatory/
sox.rs

1//! Sarbanes-Oxley Act (SOX) Compliance Models.
2//!
3//! Implements SOX compliance structures:
4//! - Section 302: CEO/CFO Certifications
5//! - Section 404: Management's Assessment of Internal Control
6//! - Control deficiency classification
7//! - Material weakness documentation
8
9use chrono::NaiveDate;
10use rust_decimal::Decimal;
11use serde::{Deserialize, Serialize};
12use uuid::Uuid;
13
14/// SOX Section 302 CEO/CFO Certification.
15#[derive(Debug, Clone, Serialize, Deserialize)]
16pub struct Sox302Certification {
17    /// Unique certification identifier.
18    pub certification_id: Uuid,
19
20    /// Company code.
21    pub company_code: String,
22
23    /// Fiscal year.
24    pub fiscal_year: u16,
25
26    /// Period end date.
27    pub period_end_date: NaiveDate,
28
29    /// Certifier role.
30    pub certifier_role: CertifierRole,
31
32    /// Certifier name.
33    pub certifier_name: String,
34
35    /// Certification date.
36    pub certification_date: NaiveDate,
37
38    /// Report type being certified.
39    pub report_type: ReportType,
40
41    // Certification statements (302(a))
42    /// Statement (a)(1): Reviewed the report.
43    pub reviewed_report: bool,
44
45    /// Statement (a)(2): Report does not contain material misstatement.
46    pub no_material_misstatement: bool,
47
48    /// Statement (a)(3): Financial statements fairly present.
49    pub fairly_presented: bool,
50
51    // Disclosure controls (302(a)(4))
52    /// Disclosure controls and procedures are effective.
53    pub disclosure_controls_effective: bool,
54
55    /// Disclosure controls evaluation date.
56    pub disclosure_controls_evaluation_date: Option<NaiveDate>,
57
58    // Internal control (302(a)(4)(B))
59    /// Internal control designed effectively.
60    pub internal_control_designed_effectively: bool,
61
62    // Changes disclosed (302(a)(5))
63    /// Significant changes in internal control disclosed.
64    pub significant_changes_disclosed: bool,
65
66    /// Description of significant changes.
67    pub significant_changes_description: Option<String>,
68
69    // Fraud notifications (302(a)(5))
70    /// Any fraud involving management disclosed.
71    pub fraud_disclosed: bool,
72
73    /// Description of fraud if any.
74    pub fraud_description: Option<String>,
75
76    /// Material weaknesses disclosed.
77    pub material_weaknesses: Vec<Uuid>, // References to Finding IDs
78
79    /// Significant deficiencies disclosed.
80    pub significant_deficiencies: Vec<Uuid>,
81
82    /// Certification statement text.
83    pub certification_text: String,
84}
85
86impl Sox302Certification {
87    /// Create a new SOX 302 certification.
88    pub fn new(
89        company_code: impl Into<String>,
90        fiscal_year: u16,
91        period_end_date: NaiveDate,
92        certifier_role: CertifierRole,
93        certifier_name: impl Into<String>,
94    ) -> Self {
95        Self {
96            certification_id: Uuid::now_v7(),
97            company_code: company_code.into(),
98            fiscal_year,
99            period_end_date,
100            certifier_role,
101            certifier_name: certifier_name.into(),
102            certification_date: chrono::Utc::now().date_naive(),
103            report_type: ReportType::AnnualReport10K,
104            reviewed_report: true,
105            no_material_misstatement: true,
106            fairly_presented: true,
107            disclosure_controls_effective: true,
108            disclosure_controls_evaluation_date: Some(period_end_date),
109            internal_control_designed_effectively: true,
110            significant_changes_disclosed: true,
111            significant_changes_description: None,
112            fraud_disclosed: false,
113            fraud_description: None,
114            material_weaknesses: Vec::new(),
115            significant_deficiencies: Vec::new(),
116            certification_text: String::new(),
117        }
118    }
119
120    /// Generate standard certification text.
121    pub fn generate_certification_text(&mut self) {
122        let report_name = match self.report_type {
123            ReportType::AnnualReport10K => "annual report on Form 10-K",
124            ReportType::QuarterlyReport10Q => "quarterly report on Form 10-Q",
125        };
126
127        self.certification_text = format!(
128            "I, {}, certify that:\n\n\
129             1. I have reviewed this {} of {};\n\n\
130             2. Based on my knowledge, this report does not contain any untrue statement of a \
131                material fact or omit to state a material fact necessary to make the statements \
132                made, in light of the circumstances under which such statements were made, not \
133                misleading with respect to the period covered by this report;\n\n\
134             3. Based on my knowledge, the financial statements, and other financial information \
135                included in this report, fairly present in all material respects the financial \
136                condition, results of operations and cash flows of the registrant as of, and for, \
137                the periods presented in this report;\n\n\
138             4. The registrant's other certifying officer and I are responsible for establishing \
139                and maintaining disclosure controls and procedures (as defined in Exchange Act \
140                Rules 13a-15(e) and 15d-15(e)) and internal control over financial reporting \
141                (as defined in Exchange Act Rules 13a-15(f) and 15d-15(f)) for the registrant \
142                and have:\n\n\
143                (a) Designed such disclosure controls and procedures, or caused such disclosure \
144                    controls and procedures to be designed under our supervision, to ensure that \
145                    material information relating to the registrant is made known to us;\n\n\
146                (b) Designed such internal control over financial reporting, or caused such \
147                    internal control over financial reporting to be designed under our supervision, \
148                    to provide reasonable assurance regarding the reliability of financial reporting;\n\n\
149                (c) Evaluated the effectiveness of the registrant's disclosure controls and \
150                    procedures and presented in this report our conclusions about the effectiveness \
151                    of the disclosure controls and procedures;\n\n\
152                (d) Disclosed in this report any change in the registrant's internal control over \
153                    financial reporting that occurred during the registrant's most recent fiscal \
154                    quarter that has materially affected, or is reasonably likely to materially \
155                    affect, the registrant's internal control over financial reporting;\n\n\
156             5. The registrant's other certifying officer and I have disclosed, based on our most \
157                recent evaluation of internal control over financial reporting, to the registrant's \
158                auditors and the audit committee of the registrant's board of directors:\n\n\
159                (a) All significant deficiencies and material weaknesses in the design or operation \
160                    of internal control over financial reporting which are reasonably likely to \
161                    adversely affect the registrant's ability to record, process, summarize and \
162                    report financial information; and\n\n\
163                (b) Any fraud, whether or not material, that involves management or other employees \
164                    who have a significant role in the registrant's internal control over financial \
165                    reporting.",
166            self.certifier_name,
167            report_name,
168            self.company_code
169        );
170    }
171}
172
173/// Certifier role for SOX certifications.
174#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
175#[serde(rename_all = "snake_case")]
176pub enum CertifierRole {
177    /// Chief Executive Officer.
178    Ceo,
179    /// Chief Financial Officer.
180    Cfo,
181    /// Principal Executive Officer (if not CEO).
182    PrincipalExecutiveOfficer,
183    /// Principal Financial Officer (if not CFO).
184    PrincipalFinancialOfficer,
185}
186
187impl std::fmt::Display for CertifierRole {
188    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
189        match self {
190            Self::Ceo => write!(f, "Chief Executive Officer"),
191            Self::Cfo => write!(f, "Chief Financial Officer"),
192            Self::PrincipalExecutiveOfficer => write!(f, "Principal Executive Officer"),
193            Self::PrincipalFinancialOfficer => write!(f, "Principal Financial Officer"),
194        }
195    }
196}
197
198/// Type of report being certified.
199#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
200#[serde(rename_all = "snake_case")]
201pub enum ReportType {
202    /// Form 10-K Annual Report.
203    #[default]
204    AnnualReport10K,
205    /// Form 10-Q Quarterly Report.
206    QuarterlyReport10Q,
207}
208
209/// SOX Section 404 Management's Assessment of ICFR.
210#[derive(Debug, Clone, Serialize, Deserialize)]
211pub struct Sox404Assessment {
212    /// Unique assessment identifier.
213    pub assessment_id: Uuid,
214
215    /// Company code.
216    pub company_code: String,
217
218    /// Fiscal year being assessed.
219    pub fiscal_year: u16,
220
221    /// Assessment date.
222    pub assessment_date: NaiveDate,
223
224    /// Framework used for assessment.
225    pub framework: IcfrFramework,
226
227    /// Overall ICFR effectiveness conclusion.
228    pub icfr_effective: bool,
229
230    /// Scope of the assessment.
231    pub scope: Vec<ScopedEntity>,
232
233    /// Materiality threshold used.
234    #[serde(with = "rust_decimal::serde::str")]
235    pub materiality_threshold: Decimal,
236
237    /// Number of key controls tested.
238    pub key_controls_tested: usize,
239
240    /// Number of key controls found effective.
241    pub key_controls_effective: usize,
242
243    /// Deficiency classification results.
244    pub deficiency_classification: DeficiencyClassificationSummary,
245
246    /// Material weaknesses identified.
247    pub material_weaknesses: Vec<MaterialWeakness>,
248
249    /// Significant deficiencies identified.
250    pub significant_deficiencies: Vec<SignificantDeficiency>,
251
252    /// Control deficiencies identified.
253    pub control_deficiencies: Vec<ControlDeficiency>,
254
255    /// Remediation actions planned/completed.
256    pub remediation_actions: Vec<RemediationAction>,
257
258    /// Management's conclusion statement.
259    pub management_conclusion: String,
260
261    /// Date of management's report.
262    pub management_report_date: NaiveDate,
263}
264
265impl Sox404Assessment {
266    /// Create a new SOX 404 assessment.
267    pub fn new(
268        company_code: impl Into<String>,
269        fiscal_year: u16,
270        assessment_date: NaiveDate,
271    ) -> Self {
272        Self {
273            assessment_id: Uuid::now_v7(),
274            company_code: company_code.into(),
275            fiscal_year,
276            assessment_date,
277            framework: IcfrFramework::Coso2013,
278            icfr_effective: true,
279            scope: Vec::new(),
280            materiality_threshold: Decimal::ZERO,
281            key_controls_tested: 0,
282            key_controls_effective: 0,
283            deficiency_classification: DeficiencyClassificationSummary::default(),
284            material_weaknesses: Vec::new(),
285            significant_deficiencies: Vec::new(),
286            control_deficiencies: Vec::new(),
287            remediation_actions: Vec::new(),
288            management_conclusion: String::new(),
289            management_report_date: assessment_date,
290        }
291    }
292
293    /// Determine if ICFR is effective based on material weaknesses.
294    pub fn evaluate_effectiveness(&mut self) {
295        // ICFR cannot be effective if any material weaknesses exist
296        self.icfr_effective = self.material_weaknesses.is_empty();
297    }
298
299    /// Calculate control testing effectiveness rate.
300    pub fn effectiveness_rate(&self) -> f64 {
301        if self.key_controls_tested == 0 {
302            return 0.0;
303        }
304        (self.key_controls_effective as f64 / self.key_controls_tested as f64) * 100.0
305    }
306}
307
308/// Framework used for ICFR assessment.
309#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
310#[serde(rename_all = "snake_case")]
311pub enum IcfrFramework {
312    /// COSO 2013 Internal Control-Integrated Framework.
313    #[default]
314    Coso2013,
315    /// COSO 1992 (legacy).
316    Coso1992,
317    /// Other recognized framework.
318    Other,
319}
320
321impl std::fmt::Display for IcfrFramework {
322    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
323        match self {
324            Self::Coso2013 => write!(f, "COSO 2013"),
325            Self::Coso1992 => write!(f, "COSO 1992"),
326            Self::Other => write!(f, "Other Framework"),
327        }
328    }
329}
330
331/// Entity in scope for SOX 404 assessment.
332#[derive(Debug, Clone, Serialize, Deserialize)]
333pub struct ScopedEntity {
334    /// Entity code.
335    pub entity_code: String,
336
337    /// Entity name.
338    pub entity_name: String,
339
340    /// Percentage of consolidated revenue.
341    #[serde(with = "rust_decimal::serde::str")]
342    pub revenue_percent: Decimal,
343
344    /// Percentage of consolidated assets.
345    #[serde(with = "rust_decimal::serde::str")]
346    pub assets_percent: Decimal,
347
348    /// Scoping conclusion.
349    pub scope_conclusion: ScopeConclusion,
350
351    /// Significant accounts at this entity.
352    pub significant_accounts: Vec<String>,
353}
354
355/// Scoping conclusion for an entity.
356#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
357#[serde(rename_all = "snake_case")]
358pub enum ScopeConclusion {
359    /// Entity is in scope - full testing required.
360    #[default]
361    InScope,
362    /// Entity is out of scope - immaterial.
363    OutOfScope,
364    /// Specific accounts only in scope.
365    SpecificAccountsOnly,
366    /// Under common control - reliance on group.
367    CommonControl,
368}
369
370/// Deficiency classification summary.
371#[derive(Debug, Clone, Default, Serialize, Deserialize)]
372pub struct DeficiencyClassificationSummary {
373    /// Number of deficiencies initially identified.
374    pub deficiencies_identified: u32,
375
376    /// Number classified as control deficiency.
377    pub control_deficiencies: u32,
378
379    /// Number classified as significant deficiency.
380    pub significant_deficiencies: u32,
381
382    /// Number classified as material weakness.
383    pub material_weaknesses: u32,
384
385    /// Number remediated before year-end.
386    pub remediated: u32,
387}
388
389/// Deficiency classification matrix.
390#[derive(Debug, Clone, Serialize, Deserialize)]
391pub struct DeficiencyMatrix {
392    /// Likelihood of misstatement occurring.
393    pub likelihood: DeficiencyLikelihood,
394
395    /// Magnitude of potential misstatement.
396    pub magnitude: DeficiencyMagnitude,
397
398    /// Resulting classification.
399    pub classification: DeficiencyClassification,
400}
401
402impl DeficiencyMatrix {
403    /// Determine classification based on likelihood and magnitude.
404    pub fn classify(
405        likelihood: DeficiencyLikelihood,
406        magnitude: DeficiencyMagnitude,
407    ) -> DeficiencyClassification {
408        match (likelihood, magnitude) {
409            // Material weakness: reasonably possible + material OR probable + more than inconsequential
410            (DeficiencyLikelihood::Probable, DeficiencyMagnitude::Material) => {
411                DeficiencyClassification::MaterialWeakness
412            }
413            (DeficiencyLikelihood::ReasonablyPossible, DeficiencyMagnitude::Material) => {
414                DeficiencyClassification::MaterialWeakness
415            }
416            (DeficiencyLikelihood::Probable, DeficiencyMagnitude::MoreThanInconsequential) => {
417                DeficiencyClassification::MaterialWeakness
418            }
419
420            // Significant deficiency: reasonably possible + more than inconsequential
421            (
422                DeficiencyLikelihood::ReasonablyPossible,
423                DeficiencyMagnitude::MoreThanInconsequential,
424            ) => DeficiencyClassification::SignificantDeficiency,
425            (DeficiencyLikelihood::Probable, DeficiencyMagnitude::Inconsequential) => {
426                DeficiencyClassification::SignificantDeficiency
427            }
428
429            // Control deficiency: remote likelihood or inconsequential magnitude
430            _ => DeficiencyClassification::ControlDeficiency,
431        }
432    }
433}
434
435/// Likelihood of misstatement for deficiency classification.
436#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
437#[serde(rename_all = "snake_case")]
438pub enum DeficiencyLikelihood {
439    /// Remote - chance is slight.
440    Remote,
441    /// Reasonably possible - more than remote but less than likely.
442    #[default]
443    ReasonablyPossible,
444    /// Probable - likely to occur.
445    Probable,
446}
447
448impl std::fmt::Display for DeficiencyLikelihood {
449    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
450        match self {
451            Self::Remote => write!(f, "Remote"),
452            Self::ReasonablyPossible => write!(f, "Reasonably Possible"),
453            Self::Probable => write!(f, "Probable"),
454        }
455    }
456}
457
458/// Magnitude of potential misstatement for deficiency classification.
459#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
460#[serde(rename_all = "snake_case")]
461pub enum DeficiencyMagnitude {
462    /// Inconsequential - clearly trivial.
463    Inconsequential,
464    /// More than inconsequential but less than material.
465    #[default]
466    MoreThanInconsequential,
467    /// Material - would influence decisions of users.
468    Material,
469}
470
471impl std::fmt::Display for DeficiencyMagnitude {
472    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
473        match self {
474            Self::Inconsequential => write!(f, "Inconsequential"),
475            Self::MoreThanInconsequential => write!(f, "More Than Inconsequential"),
476            Self::Material => write!(f, "Material"),
477        }
478    }
479}
480
481/// Deficiency classification result.
482#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
483#[serde(rename_all = "snake_case")]
484pub enum DeficiencyClassification {
485    /// Control deficiency - does not rise to significant or material.
486    #[default]
487    ControlDeficiency,
488    /// Significant deficiency - less severe than material weakness.
489    SignificantDeficiency,
490    /// Material weakness - reasonable possibility of material misstatement.
491    MaterialWeakness,
492}
493
494impl std::fmt::Display for DeficiencyClassification {
495    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
496        match self {
497            Self::ControlDeficiency => write!(f, "Control Deficiency"),
498            Self::SignificantDeficiency => write!(f, "Significant Deficiency"),
499            Self::MaterialWeakness => write!(f, "Material Weakness"),
500        }
501    }
502}
503
504/// Material weakness record.
505#[derive(Debug, Clone, Serialize, Deserialize)]
506pub struct MaterialWeakness {
507    /// Unique identifier.
508    pub weakness_id: Uuid,
509
510    /// Description of the material weakness.
511    pub description: String,
512
513    /// Affected controls.
514    pub affected_controls: Vec<String>,
515
516    /// Affected significant accounts.
517    pub affected_accounts: Vec<String>,
518
519    /// Related assertions impacted.
520    pub related_assertions: Vec<String>,
521
522    /// Root cause.
523    pub root_cause: String,
524
525    /// Potential misstatement amount.
526    #[serde(default, with = "rust_decimal::serde::str_option")]
527    pub potential_misstatement: Option<Decimal>,
528
529    /// Likelihood assessment.
530    pub likelihood: DeficiencyLikelihood,
531
532    /// Magnitude assessment.
533    pub magnitude: DeficiencyMagnitude,
534
535    /// Identification date.
536    pub identification_date: NaiveDate,
537
538    /// Whether remediated by year-end.
539    pub remediated_by_year_end: bool,
540
541    /// Remediation date if remediated.
542    pub remediation_date: Option<NaiveDate>,
543
544    /// Reference to related findings.
545    pub related_finding_ids: Vec<Uuid>,
546}
547
548impl MaterialWeakness {
549    /// Create a new material weakness.
550    pub fn new(description: impl Into<String>, identification_date: NaiveDate) -> Self {
551        Self {
552            weakness_id: Uuid::now_v7(),
553            description: description.into(),
554            affected_controls: Vec::new(),
555            affected_accounts: Vec::new(),
556            related_assertions: Vec::new(),
557            root_cause: String::new(),
558            potential_misstatement: None,
559            likelihood: DeficiencyLikelihood::Probable,
560            magnitude: DeficiencyMagnitude::Material,
561            identification_date,
562            remediated_by_year_end: false,
563            remediation_date: None,
564            related_finding_ids: Vec::new(),
565        }
566    }
567}
568
569/// Significant deficiency record.
570#[derive(Debug, Clone, Serialize, Deserialize)]
571pub struct SignificantDeficiency {
572    /// Unique identifier.
573    pub deficiency_id: Uuid,
574
575    /// Description.
576    pub description: String,
577
578    /// Affected controls.
579    pub affected_controls: Vec<String>,
580
581    /// Affected accounts.
582    pub affected_accounts: Vec<String>,
583
584    /// Likelihood assessment.
585    pub likelihood: DeficiencyLikelihood,
586
587    /// Magnitude assessment.
588    pub magnitude: DeficiencyMagnitude,
589
590    /// Identification date.
591    pub identification_date: NaiveDate,
592
593    /// Remediation status.
594    pub remediated: bool,
595}
596
597impl SignificantDeficiency {
598    /// Create a new significant deficiency.
599    pub fn new(description: impl Into<String>, identification_date: NaiveDate) -> Self {
600        Self {
601            deficiency_id: Uuid::now_v7(),
602            description: description.into(),
603            affected_controls: Vec::new(),
604            affected_accounts: Vec::new(),
605            likelihood: DeficiencyLikelihood::ReasonablyPossible,
606            magnitude: DeficiencyMagnitude::MoreThanInconsequential,
607            identification_date,
608            remediated: false,
609        }
610    }
611}
612
613/// Control deficiency record.
614#[derive(Debug, Clone, Serialize, Deserialize)]
615pub struct ControlDeficiency {
616    /// Unique identifier.
617    pub deficiency_id: Uuid,
618
619    /// Description.
620    pub description: String,
621
622    /// Affected control.
623    pub affected_control: String,
624
625    /// Identification date.
626    pub identification_date: NaiveDate,
627
628    /// Remediation status.
629    pub remediated: bool,
630}
631
632/// Remediation action record.
633#[derive(Debug, Clone, Serialize, Deserialize)]
634pub struct RemediationAction {
635    /// Action identifier.
636    pub action_id: Uuid,
637
638    /// Related deficiency ID.
639    pub deficiency_id: Uuid,
640
641    /// Action description.
642    pub description: String,
643
644    /// Responsible party.
645    pub responsible_party: String,
646
647    /// Target completion date.
648    pub target_date: NaiveDate,
649
650    /// Actual completion date.
651    pub completion_date: Option<NaiveDate>,
652
653    /// Status.
654    pub status: RemediationStatus,
655
656    /// Testing of remediation performed.
657    pub remediation_tested: bool,
658
659    /// Remediation effective.
660    pub remediation_effective: bool,
661}
662
663/// Remediation status.
664#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
665#[serde(rename_all = "snake_case")]
666pub enum RemediationStatus {
667    /// Not started.
668    #[default]
669    NotStarted,
670    /// In progress.
671    InProgress,
672    /// Completed.
673    Completed,
674    /// Deferred to next period.
675    Deferred,
676}
677
678#[cfg(test)]
679mod tests {
680    use super::*;
681    use rust_decimal_macros::dec;
682
683    #[test]
684    fn test_sox_302_certification() {
685        let mut cert = Sox302Certification::new(
686            "ABC Corp",
687            2024,
688            NaiveDate::from_ymd_opt(2024, 12, 31).unwrap(),
689            CertifierRole::Ceo,
690            "John Smith",
691        );
692
693        cert.generate_certification_text();
694
695        assert!(!cert.certification_text.is_empty());
696        assert!(cert.certification_text.contains("John Smith"));
697        assert!(cert.disclosure_controls_effective);
698    }
699
700    #[test]
701    fn test_sox_404_assessment() {
702        let mut assessment = Sox404Assessment::new(
703            "ABC Corp",
704            2024,
705            NaiveDate::from_ymd_opt(2025, 2, 28).unwrap(),
706        );
707
708        assessment.key_controls_tested = 100;
709        assessment.key_controls_effective = 95;
710        assessment.materiality_threshold = dec!(100000);
711
712        assert_eq!(assessment.effectiveness_rate(), 95.0);
713        assert!(assessment.icfr_effective);
714    }
715
716    #[test]
717    fn test_sox_404_with_material_weakness() {
718        let mut assessment = Sox404Assessment::new(
719            "ABC Corp",
720            2024,
721            NaiveDate::from_ymd_opt(2025, 2, 28).unwrap(),
722        );
723
724        assessment.material_weaknesses.push(MaterialWeakness::new(
725            "Inadequate segregation of duties in accounts payable",
726            NaiveDate::from_ymd_opt(2024, 9, 30).unwrap(),
727        ));
728
729        assessment.evaluate_effectiveness();
730
731        assert!(!assessment.icfr_effective);
732    }
733
734    #[test]
735    fn test_deficiency_matrix_classification() {
736        // Material weakness cases
737        assert_eq!(
738            DeficiencyMatrix::classify(
739                DeficiencyLikelihood::Probable,
740                DeficiencyMagnitude::Material
741            ),
742            DeficiencyClassification::MaterialWeakness
743        );
744        assert_eq!(
745            DeficiencyMatrix::classify(
746                DeficiencyLikelihood::ReasonablyPossible,
747                DeficiencyMagnitude::Material
748            ),
749            DeficiencyClassification::MaterialWeakness
750        );
751
752        // Significant deficiency
753        assert_eq!(
754            DeficiencyMatrix::classify(
755                DeficiencyLikelihood::ReasonablyPossible,
756                DeficiencyMagnitude::MoreThanInconsequential
757            ),
758            DeficiencyClassification::SignificantDeficiency
759        );
760
761        // Control deficiency
762        assert_eq!(
763            DeficiencyMatrix::classify(
764                DeficiencyLikelihood::Remote,
765                DeficiencyMagnitude::Inconsequential
766            ),
767            DeficiencyClassification::ControlDeficiency
768        );
769    }
770}