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