1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
//! IAS 21 currency translation result models.
//!
//! These models capture the output of translating an entity's financial
//! statements from its functional currency into the group presentation currency.
//!
//! Under the **current-rate method** (most common for foreign operations):
//! - Balance sheet monetary items → closing rate
//! - Balance sheet non-monetary items (PP&E, equity) → historical rate
//! - P&L items → average rate for the period
//! - The balancing difference is the **Currency Translation Adjustment (CTA)**,
//! recognised as Other Comprehensive Income (OCI).
use rust_decimal::Decimal;
use serde::{Deserialize, Serialize};
/// The overall IAS 21 translation method applied.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Ias21TranslationMethod {
/// Current-rate method — all balance-sheet items at closing rate except
/// equity which uses historical rates; P&L at average rate.
CurrentRate,
/// Temporal method — monetary items at closing rate, non-monetary at
/// historical rate; P&L at average rate.
Temporal,
}
impl std::fmt::Display for Ias21TranslationMethod {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::CurrentRate => write!(f, "current_rate"),
Self::Temporal => write!(f, "temporal"),
}
}
}
/// Which exchange rate was used to translate a particular line item.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum TranslationRateType {
/// Period-end (closing) rate — used for balance-sheet monetary items.
ClosingRate,
/// Rate prevailing at the original transaction date — used for equity and
/// non-monetary balance-sheet items.
HistoricalRate,
/// Weighted average rate for the period — used for P&L items.
AverageRate,
/// One-to-one (no translation required; functional == presentation).
NoTranslation,
}
impl std::fmt::Display for TranslationRateType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::ClosingRate => write!(f, "closing_rate"),
Self::HistoricalRate => write!(f, "historical_rate"),
Self::AverageRate => write!(f, "average_rate"),
Self::NoTranslation => write!(f, "no_translation"),
}
}
}
/// A single translated line item (one GL account / account group).
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TranslatedLineItem {
/// GL account code.
pub account: String,
/// Account type label (e.g. "Asset", "Liability", "Revenue").
pub account_type: String,
/// Amount in the entity's functional currency.
pub functional_amount: Decimal,
/// Exchange rate applied.
pub rate_used: Decimal,
/// Category of rate used.
pub rate_type: TranslationRateType,
/// Translated amount in the presentation currency.
pub presentation_amount: Decimal,
}
/// Full IAS 21 translation result for one entity and one reporting period.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CurrencyTranslationResult {
/// Entity (company) code.
pub entity_code: String,
/// Functional currency of the entity (ISO 4217).
pub functional_currency: String,
/// Presentation (group reporting) currency (ISO 4217).
pub presentation_currency: String,
/// Period label (e.g. "2024-12").
pub period: String,
/// Translation method applied.
pub translation_method: Ias21TranslationMethod,
/// All translated line items.
pub translated_items: Vec<TranslatedLineItem>,
/// Currency Translation Adjustment recognised in OCI.
///
/// Positive = OCI gain (foreign currency strengthened relative to
/// presentation currency); negative = OCI loss.
pub cta_amount: Decimal,
/// Closing rate used for balance-sheet monetary items.
pub closing_rate: Decimal,
/// Average rate used for P&L items.
pub average_rate: Decimal,
/// Total balance-sheet amount translated (functional currency).
pub total_balance_sheet_functional: Decimal,
/// Total balance-sheet amount translated (presentation currency).
pub total_balance_sheet_presentation: Decimal,
/// Total P&L amount translated (functional currency).
pub total_pnl_functional: Decimal,
/// Total P&L amount translated (presentation currency).
pub total_pnl_presentation: Decimal,
}