Skip to main content

datasynth_core/models/
deferred_tax.rs

1//! Deferred tax models (IAS 12 / ASC 740).
2//!
3//! This module provides data models for:
4//! - Temporary differences (book vs. tax basis) that give rise to DTA/DTL
5//! - ETR (effective tax rate) reconciliation from statutory to effective rate
6//! - Deferred tax rollforward schedules tracking opening/closing DTA and DTL
7
8use rust_decimal::Decimal;
9use serde::{Deserialize, Serialize};
10
11// ---------------------------------------------------------------------------
12// Enums
13// ---------------------------------------------------------------------------
14
15/// Whether a temporary difference gives rise to a deferred tax asset or liability.
16#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
17#[serde(rename_all = "snake_case")]
18pub enum DeferredTaxType {
19    /// Deferred Tax Asset – book basis exceeds tax basis (e.g. accruals, bad debt).
20    Asset,
21    /// Deferred Tax Liability – tax basis exceeds book basis (e.g. accelerated depreciation).
22    Liability,
23}
24
25// ---------------------------------------------------------------------------
26// Temporary Difference
27// ---------------------------------------------------------------------------
28
29/// A single temporary difference between book (GAAP/IFRS) and tax bases.
30///
31/// Under IAS 12 / ASC 740 a temporary difference arises when the carrying
32/// amount of an asset or liability differs from its tax base.  The deferred
33/// tax effect equals `difference × statutory_rate`.
34#[derive(Debug, Clone, Serialize, Deserialize)]
35pub struct TemporaryDifference {
36    /// Unique identifier for this temporary difference record.
37    pub id: String,
38    /// Company / entity code this difference relates to.
39    pub entity_code: String,
40    /// GL account code associated with the underlying asset or liability.
41    pub account: String,
42    /// Human-readable description (e.g. "Accelerated depreciation – MACRS").
43    pub description: String,
44    /// Book (GAAP/IFRS) carrying amount.
45    #[serde(with = "rust_decimal::serde::str")]
46    pub book_basis: Decimal,
47    /// Tax basis of the same asset or liability.
48    #[serde(with = "rust_decimal::serde::str")]
49    pub tax_basis: Decimal,
50    /// `book_basis − tax_basis`; positive = DTA, negative = DTL (before type override).
51    #[serde(with = "rust_decimal::serde::str")]
52    pub difference: Decimal,
53    /// Whether this difference yields a DTA or DTL.
54    pub deferred_type: DeferredTaxType,
55    /// Accounting standard that created this difference (e.g. "ASC 842", "IAS 16").
56    pub originating_standard: Option<String>,
57}
58
59// ---------------------------------------------------------------------------
60// ETR Reconciliation
61// ---------------------------------------------------------------------------
62
63/// A single permanent difference item in the ETR reconciliation.
64#[derive(Debug, Clone, Serialize, Deserialize)]
65pub struct PermanentDifference {
66    /// Description of the permanent difference (e.g. "Meals & entertainment (50% disallowed)").
67    pub description: String,
68    /// Pre-tax amount of the difference (positive = adds to taxable income).
69    #[serde(with = "rust_decimal::serde::str")]
70    pub amount: Decimal,
71    /// Tax effect = `amount × statutory_rate` (positive = increases tax expense).
72    #[serde(with = "rust_decimal::serde::str")]
73    pub tax_effect: Decimal,
74}
75
76/// Effective tax rate reconciliation for a reporting period.
77///
78/// Bridges from the statutory rate to the effective rate by listing all
79/// permanent differences that cause the two rates to diverge.
80#[derive(Debug, Clone, Serialize, Deserialize)]
81pub struct TaxRateReconciliation {
82    /// Company / entity code.
83    pub entity_code: String,
84    /// Period label (e.g. "FY2024", "2024-Q4").
85    pub period: String,
86    /// Pre-tax income (profit before income tax).
87    #[serde(with = "rust_decimal::serde::str")]
88    pub pre_tax_income: Decimal,
89    /// Statutory (nominal) corporate income tax rate.
90    #[serde(with = "rust_decimal::serde::str")]
91    pub statutory_rate: Decimal,
92    /// `pre_tax_income × statutory_rate` (expected tax at statutory rate).
93    #[serde(with = "rust_decimal::serde::str")]
94    pub expected_tax: Decimal,
95    /// Permanent differences that bridge expected → actual tax.
96    pub permanent_differences: Vec<PermanentDifference>,
97    /// `actual_tax / pre_tax_income`.
98    #[serde(with = "rust_decimal::serde::str")]
99    pub effective_rate: Decimal,
100    /// Actual income tax expense for the period.
101    #[serde(with = "rust_decimal::serde::str")]
102    pub actual_tax: Decimal,
103}
104
105// ---------------------------------------------------------------------------
106// Deferred Tax Rollforward
107// ---------------------------------------------------------------------------
108
109/// Period-over-period rollforward of deferred tax asset and liability balances.
110#[derive(Debug, Clone, Serialize, Deserialize)]
111pub struct DeferredTaxRollforward {
112    /// Company / entity code.
113    pub entity_code: String,
114    /// Period label.
115    pub period: String,
116    /// Opening Deferred Tax Asset balance.
117    #[serde(with = "rust_decimal::serde::str")]
118    pub opening_dta: Decimal,
119    /// Opening Deferred Tax Liability balance.
120    #[serde(with = "rust_decimal::serde::str")]
121    pub opening_dtl: Decimal,
122    /// Net movement during the period (DTA creation less reversal, net of DTL movement).
123    #[serde(with = "rust_decimal::serde::str")]
124    pub current_year_movement: Decimal,
125    /// Closing Deferred Tax Asset balance (`opening_dta + dta_movement`).
126    #[serde(with = "rust_decimal::serde::str")]
127    pub closing_dta: Decimal,
128    /// Closing Deferred Tax Liability balance (`opening_dtl + dtl_movement`).
129    #[serde(with = "rust_decimal::serde::str")]
130    pub closing_dtl: Decimal,
131}