Skip to main content

datasynth_core/models/audit/
subsequent_events.rs

1//! Subsequent events models per ISA 560 and IAS 10.
2//!
3//! Subsequent events are events that occur between the balance sheet date and
4//! the date when the financial statements are authorised for issue.  IAS 10
5//! distinguishes between adjusting events (that provide evidence of conditions
6//! at the balance sheet date) and non-adjusting events (that arise after the
7//! balance sheet date).
8
9use chrono::NaiveDate;
10use rust_decimal::Decimal;
11use serde::{Deserialize, Serialize};
12
13/// A subsequent event identified during the completion phase of an audit.
14#[derive(Debug, Clone, Serialize, Deserialize)]
15pub struct SubsequentEvent {
16    /// Unique identifier for this event
17    pub id: String,
18    /// Entity code of the reporting entity
19    pub entity_code: String,
20    /// Date the event occurred
21    pub event_date: NaiveDate,
22    /// Date the event was discovered by the auditor
23    pub discovery_date: NaiveDate,
24    /// Type of subsequent event
25    pub event_type: SubsequentEventType,
26    /// Classification per IAS 10 (adjusting or non-adjusting)
27    pub classification: EventClassification,
28    /// Narrative description of the event
29    pub description: String,
30    /// Financial impact, if quantifiable (adjusting events or disclosed amounts)
31    #[serde(
32        with = "crate::serde_decimal::option",
33        skip_serializing_if = "Option::is_none",
34        default
35    )]
36    pub financial_impact: Option<Decimal>,
37    /// Whether a disclosure in the notes is required
38    pub disclosure_required: bool,
39    /// IDs of adjustment journal entries raised for this event (future enhancement)
40    pub adjustment_entry_ids: Vec<String>,
41}
42
43/// Type of subsequent event.
44#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
45#[serde(rename_all = "snake_case")]
46pub enum SubsequentEventType {
47    /// Settlement of litigation after period-end
48    #[default]
49    LitigationSettlement,
50    /// Customer bankruptcy or insolvency after period-end
51    CustomerBankruptcy,
52    /// Material impairment of an asset after period-end
53    AssetImpairment,
54    /// Announcement of a restructuring programme
55    RestructuringAnnouncement,
56    /// Natural disaster affecting operations or assets
57    NaturalDisaster,
58    /// Significant regulatory change affecting the entity
59    RegulatoryChange,
60    /// Announcement of a merger or acquisition
61    MergerAnnouncement,
62    /// Declaration of dividends after period-end
63    DividendDeclaration,
64}
65
66/// Classification of a subsequent event per IAS 10.
67#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
68#[serde(rename_all = "snake_case")]
69pub enum EventClassification {
70    /// Adjusting event — provides evidence of conditions existing at the balance sheet date
71    /// (IAS 10.8).  The financial statements are adjusted to reflect the event.
72    #[default]
73    Adjusting,
74    /// Non-adjusting event — arises after the balance sheet date.
75    /// Disclosure in the notes is required if material (IAS 10.21).
76    NonAdjusting,
77}
78
79impl SubsequentEvent {
80    /// Create a new subsequent event.
81    pub fn new(
82        entity_code: impl Into<String>,
83        event_date: NaiveDate,
84        discovery_date: NaiveDate,
85        event_type: SubsequentEventType,
86        classification: EventClassification,
87        description: impl Into<String>,
88    ) -> Self {
89        let disclosure_required = matches!(classification, EventClassification::NonAdjusting);
90        Self {
91            id: crate::clock::next_document_id().to_string(),
92            entity_code: entity_code.into(),
93            event_date,
94            discovery_date,
95            event_type,
96            classification,
97            description: description.into(),
98            financial_impact: None,
99            disclosure_required,
100            adjustment_entry_ids: Vec::new(),
101        }
102    }
103
104    /// Attach a financial impact amount.
105    pub fn with_financial_impact(mut self, impact: Decimal) -> Self {
106        self.financial_impact = Some(impact);
107        self
108    }
109
110    /// Mark adjustment entry IDs for this event.
111    pub fn with_adjustment_entries(mut self, ids: Vec<String>) -> Self {
112        self.adjustment_entry_ids = ids;
113        self
114    }
115}