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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
//! Cash flow enhancer — supplementary CashFlowItem entries from v2.3 data.
//!
//! The existing [`FinancialStatementGenerator`] produces a basic indirect-method
//! cash flow statement. This module generates **additional** items (from
//! manufacturing, treasury, tax, and dividend modules) that Task 10 merges into
//! the financial statement's `cash_flow_items` vector.
use datasynth_core::models::{CashFlowCategory, CashFlowItem};
use rust_decimal::Decimal;
/// Source data collected from upstream v2.3 generators.
#[derive(Debug, Clone)]
pub struct CashFlowSourceData {
/// Total depreciation / amortisation for the period (from depreciation runs).
pub depreciation_total: Decimal,
/// Net movement in provisions for the period (from provision generator).
pub provision_movements_net: Decimal,
/// Change in accounts-receivable balance (positive = AR increased).
pub delta_ar: Decimal,
/// Change in accounts-payable balance (positive = AP increased).
pub delta_ap: Decimal,
/// Change in inventory balance (positive = inventory increased).
pub delta_inventory: Decimal,
/// Capital expenditure paid in the period (non-negative).
pub capex: Decimal,
/// Proceeds from new debt issued in the period.
pub debt_issuance: Decimal,
/// Principal repaid on debt in the period (non-negative).
pub debt_repayment: Decimal,
/// Interest paid in cash during the period (non-negative).
pub interest_paid: Decimal,
/// Income tax paid in cash during the period (non-negative).
pub tax_paid: Decimal,
/// Dividends paid to shareholders in the period (non-negative).
pub dividends_paid: Decimal,
/// Accounting framework: `"US_GAAP"` or `"IFRS"`.
///
/// Under US GAAP, interest paid is an Operating cash flow.
/// Under IFRS, interest paid is a Financing cash flow.
pub framework: String,
}
/// Generates supplementary cash flow items from v2.3 source data.
pub struct CashFlowEnhancer;
impl CashFlowEnhancer {
/// Build the supplementary [`CashFlowItem`] list.
///
/// Items whose computed amount is zero are silently omitted so that the
/// merged statement is not cluttered with empty lines.
pub fn generate(data: &CashFlowSourceData) -> Vec<CashFlowItem> {
let is_ifrs = data.framework.eq_ignore_ascii_case("IFRS");
let mut items: Vec<CashFlowItem> = Vec::new();
let mut sort = 100u32; // start above the values the FS generator uses
// ------------------------------------------------------------------
// Operating activities — adjustments to net income
// ------------------------------------------------------------------
// Depreciation add-back (non-cash charge reversed back)
if !data.depreciation_total.is_zero() {
items.push(CashFlowItem {
item_code: "CF-DEP".to_string(),
label: "Depreciation and Amortisation".to_string(),
category: CashFlowCategory::Operating,
amount: data.depreciation_total,
amount_prior: None,
sort_order: sort,
is_total: false,
});
sort += 10;
}
// Provision movements (e.g., warranties, bad-debt allowances)
if !data.provision_movements_net.is_zero() {
items.push(CashFlowItem {
item_code: "CF-PROV".to_string(),
label: "Movement in Provisions".to_string(),
category: CashFlowCategory::Operating,
amount: data.provision_movements_net,
amount_prior: None,
sort_order: sort,
is_total: false,
});
sort += 10;
}
// ΔAR: increase in AR → cash has been tied up → outflow (negative)
let dar = -data.delta_ar;
if !dar.is_zero() {
items.push(CashFlowItem {
item_code: "CF-DAR".to_string(),
label: "Change in Trade Receivables".to_string(),
category: CashFlowCategory::Operating,
amount: dar,
amount_prior: None,
sort_order: sort,
is_total: false,
});
sort += 10;
}
// ΔAP: increase in AP → supplier financing received → inflow (positive)
if !data.delta_ap.is_zero() {
items.push(CashFlowItem {
item_code: "CF-DAP".to_string(),
label: "Change in Trade Payables".to_string(),
category: CashFlowCategory::Operating,
amount: data.delta_ap,
amount_prior: None,
sort_order: sort,
is_total: false,
});
sort += 10;
}
// ΔInventory: increase in inventory → cash consumed → outflow (negative)
let dinv = -data.delta_inventory;
if !dinv.is_zero() {
items.push(CashFlowItem {
item_code: "CF-DINV".to_string(),
label: "Change in Inventories".to_string(),
category: CashFlowCategory::Operating,
amount: dinv,
amount_prior: None,
sort_order: sort,
is_total: false,
});
sort += 10;
}
// Interest paid — Operating under US GAAP only
if !is_ifrs && !data.interest_paid.is_zero() {
items.push(CashFlowItem {
item_code: "CF-INT".to_string(),
label: "Interest Paid".to_string(),
category: CashFlowCategory::Operating,
amount: -data.interest_paid.abs(),
amount_prior: None,
sort_order: sort,
is_total: false,
});
sort += 10;
}
// Tax paid (always Operating under both frameworks)
if !data.tax_paid.is_zero() {
items.push(CashFlowItem {
item_code: "CF-TAX".to_string(),
label: "Income Tax Paid".to_string(),
category: CashFlowCategory::Operating,
amount: -data.tax_paid.abs(),
amount_prior: None,
sort_order: sort,
is_total: false,
});
sort += 10;
}
// ------------------------------------------------------------------
// Investing activities
// ------------------------------------------------------------------
if !data.capex.is_zero() {
items.push(CashFlowItem {
item_code: "CF-CAPEX".to_string(),
label: "Purchase of Property, Plant and Equipment".to_string(),
category: CashFlowCategory::Investing,
amount: -data.capex.abs(),
amount_prior: None,
sort_order: sort,
is_total: false,
});
sort += 10;
}
// ------------------------------------------------------------------
// Financing activities
// ------------------------------------------------------------------
if !data.debt_issuance.is_zero() {
items.push(CashFlowItem {
item_code: "CF-DEBT-IN".to_string(),
label: "Proceeds from Borrowings".to_string(),
category: CashFlowCategory::Financing,
amount: data.debt_issuance,
amount_prior: None,
sort_order: sort,
is_total: false,
});
sort += 10;
}
if !data.debt_repayment.is_zero() {
items.push(CashFlowItem {
item_code: "CF-DEBT-OUT".to_string(),
label: "Repayment of Borrowings".to_string(),
category: CashFlowCategory::Financing,
amount: -data.debt_repayment.abs(),
amount_prior: None,
sort_order: sort,
is_total: false,
});
sort += 10;
}
// Interest paid — Financing under IFRS only
if is_ifrs && !data.interest_paid.is_zero() {
items.push(CashFlowItem {
item_code: "CF-INT-FIN".to_string(),
label: "Interest Paid".to_string(),
category: CashFlowCategory::Financing,
amount: -data.interest_paid.abs(),
amount_prior: None,
sort_order: sort,
is_total: false,
});
sort += 10;
}
if !data.dividends_paid.is_zero() {
items.push(CashFlowItem {
item_code: "CF-DIV".to_string(),
label: "Dividends Paid".to_string(),
category: CashFlowCategory::Financing,
amount: -data.dividends_paid.abs(),
amount_prior: None,
sort_order: sort,
is_total: false,
});
}
items
}
}