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}