1use chrono::NaiveDate;
4use rust_decimal::Decimal;
5use serde::{Deserialize, Serialize};
6use std::collections::BTreeMap;
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct GroupConfig {
11 pub id: String,
12 #[serde(default)]
13 pub name: Option<String>,
14 pub presentation_currency: String,
15 pub period: PeriodConfig,
16 pub seed: u64,
17
18 #[serde(default)]
19 pub defaults: serde_yaml::Value, #[serde(default)]
22 pub scoping_profiles: BTreeMap<String, serde_yaml::Value>,
23
24 pub ownership: OwnershipConfig,
25
26 #[serde(default)]
27 pub intercompany: IntercompanyConfig,
28
29 pub fx: FxConfig,
30
31 #[serde(default)]
32 pub audit: AuditEngagementConfig,
33
34 #[serde(default)]
35 pub tax: TaxGroupConfig,
36
37 #[serde(default)]
44 pub cgu: CguConfig,
45
46 #[serde(default)]
47 pub output: OutputLayoutConfig,
48
49 #[serde(default)]
50 pub fleet: Option<FleetConfig>,
51}
52
53#[derive(Debug, Clone, Serialize, Deserialize)]
54pub struct PeriodConfig {
55 pub start_date: NaiveDate,
56 pub length: PeriodLength,
57 #[serde(default)]
58 pub fiscal_year_end: Option<NaiveDate>,
59}
60
61#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
62#[serde(rename_all = "lowercase")]
63pub enum PeriodLength {
64 Monthly,
65 Quarterly,
66 SemiAnnual,
67 Annual,
68}
69
70#[derive(Debug, Clone, Serialize, Deserialize)]
71pub struct OwnershipConfig {
72 pub parent_entity_code: String,
73 #[serde(default)]
74 pub entities: Vec<EntityConfig>,
75 #[serde(default)]
76 pub generated: Vec<GeneratedEntityBlock>,
77 #[serde(default)]
78 pub entities_from: Option<std::path::PathBuf>,
79}
80
81#[derive(Debug, Clone, Serialize, Deserialize)]
82pub struct EntityConfig {
83 pub code: String,
84 #[serde(default)]
85 pub name: Option<String>,
86 pub country: String,
87 pub functional_currency: String,
88 pub scoping_profile: String,
89 pub consolidation_method: ConsolidationMethod,
90 #[serde(default)]
91 pub ownership_percent: Option<Decimal>,
92 #[serde(default)]
93 pub parent_code: Option<String>,
94 #[serde(default)]
95 pub acquisition_date: Option<NaiveDate>,
96 #[serde(default)]
97 pub accounting_framework: Option<String>,
98 #[serde(default)]
99 pub industry: Option<String>,
100 #[serde(default)]
101 pub rows: Option<u64>,
102 #[serde(default)]
115 pub ownership_changes: Vec<OwnershipChangeEntry>,
116 #[serde(default)]
123 pub hyperinflation_status: datasynth_core::models::HyperinflationStatus,
124 #[serde(default, flatten)]
125 pub overrides: BTreeMap<String, serde_yaml::Value>, }
127
128#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
129#[serde(rename_all = "snake_case")]
130pub enum ConsolidationMethod {
131 Parent,
132 Full,
133 EquityMethod,
134 Proportional,
135 FairValue,
136}
137
138#[derive(Debug, Clone, Serialize, Deserialize)]
139pub struct GeneratedEntityBlock {
140 pub count: u32,
141 pub code_prefix: String,
142 #[serde(default)]
143 pub country: Vec<String>,
144 #[serde(default)]
145 pub functional_currency: Option<String>,
146 pub scoping_profile: String,
147 pub consolidation_method: ConsolidationMethod,
148 #[serde(default)]
149 pub ownership_percent_range: Option<[Decimal; 2]>,
150 #[serde(default)]
151 pub parent_code: Option<String>,
152 #[serde(default)]
153 pub accounting_framework: Option<String>,
154 #[serde(default)]
155 pub industry: Option<String>,
156}
157
158#[derive(Debug, Clone, Default, Serialize, Deserialize)]
159pub struct IntercompanyConfig {
160 #[serde(default)]
161 pub relationships: Vec<IcRelationshipConfig>,
162 #[serde(default)]
163 pub matching: IcMatchingConfig,
164}
165
166#[derive(Debug, Clone, Serialize, Deserialize)]
167#[serde(untagged)]
168pub enum IcRelationshipConfig {
169 Explicit(IcRelationshipExplicit),
170 Pattern(IcRelationshipPattern),
171}
172
173#[derive(Debug, Clone, Serialize, Deserialize)]
174#[serde(deny_unknown_fields)]
175pub struct IcRelationshipExplicit {
176 pub seller: String,
177 pub buyer: String,
178 pub types: Vec<IcTransactionType>,
179 pub annual_volume: Decimal,
180 #[serde(default)]
181 pub transfer_pricing: Option<TransferPricingMethod>,
182 #[serde(default)]
183 pub markup_percent: Option<Decimal>,
184}
185
186#[derive(Debug, Clone, Serialize, Deserialize)]
187#[serde(deny_unknown_fields)]
188pub struct IcRelationshipPattern {
189 pub pattern: IcPattern,
190 pub types: Vec<IcTransactionType>,
191 pub per_pair_volume: Decimal,
192 #[serde(default)]
193 pub transfer_pricing: Option<TransferPricingMethod>,
194}
195
196#[derive(Debug, Clone, Serialize, Deserialize)]
197pub struct IcPattern {
198 #[serde(default)]
199 pub seller_scoping_profile: Option<String>,
200 #[serde(default)]
201 pub buyer_scoping_profile: Option<String>,
202 #[serde(default)]
203 pub seller: Option<String>,
204 #[serde(default)]
205 pub buyer: Option<String>,
206}
207
208#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
209#[serde(rename_all = "snake_case")]
210pub enum IcTransactionType {
211 GoodsSale,
212 ServiceProvided,
213 ManagementFee,
214 Royalty,
215 CostSharing,
216 LoanInterest,
217 Dividend,
218 ExpenseRecharge,
219}
220
221#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
222#[serde(rename_all = "snake_case")]
223pub enum TransferPricingMethod {
224 CostPlus,
225 ComparableUncontrolled,
226 ResalePrice,
227 TransactionalNetMargin,
228 ProfitSplit,
229}
230
231#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
232pub struct IcMatchingConfig {
233 #[serde(default = "default_strategy")]
234 pub strategy: IcMatchingStrategy,
235 #[serde(default = "default_coverage_target")]
236 pub coverage_target: f64,
237 #[serde(default = "default_tolerance_percent")]
249 pub tolerance_percent: rust_decimal::Decimal,
250}
251
252fn default_strategy() -> IcMatchingStrategy {
253 IcMatchingStrategy::ManifestDriven
254}
255fn default_coverage_target() -> f64 {
256 0.98
257}
258fn default_tolerance_percent() -> rust_decimal::Decimal {
259 rust_decimal::Decimal::ZERO
260}
261
262impl Default for IcMatchingConfig {
263 fn default() -> Self {
264 Self {
265 strategy: default_strategy(),
266 coverage_target: default_coverage_target(),
267 tolerance_percent: default_tolerance_percent(),
268 }
269 }
270}
271
272#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
273#[serde(rename_all = "snake_case")]
274pub enum IcMatchingStrategy {
275 ManifestDriven,
276 EmergentFuzzy,
277}
278
279#[derive(Debug, Clone, Serialize, Deserialize)]
280pub struct FxConfig {
281 pub base_currency: String,
282 #[serde(default)]
283 pub rate_source: FxRateSource,
284 #[serde(default)]
285 pub rates: BTreeMap<String, BTreeMap<NaiveDate, Decimal>>,
286 pub policy: FxPolicyConfig,
287}
288
289#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Default)]
290#[serde(rename_all = "snake_case")]
291pub enum FxRateSource {
292 #[default]
293 Inline,
294 UserSupplied,
295 HistoricalSeries,
296}
297
298#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
299pub struct FxPolicyConfig {
300 pub balance_sheet: FxRateBasis,
301 pub income_statement: FxRateBasis,
302 pub equity: FxRateBasis,
303}
304
305#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Default)]
306#[serde(rename_all = "snake_case")]
307pub enum FxRateBasis {
308 #[default]
309 Closing,
310 Average,
311 Historical,
312}
313
314#[derive(Debug, Clone, Default, Serialize, Deserialize)]
315pub struct AuditEngagementConfig {
316 #[serde(default)]
317 pub engagement_id: Option<String>,
318 #[serde(default)]
319 pub lead_auditor: Option<String>,
320 #[serde(default)]
321 pub framework: Option<String>, #[serde(default)]
323 pub fsm_blueprint: Option<String>,
324 #[serde(default)]
325 pub group_materiality: Option<GroupMaterialityConfig>,
326 #[serde(default)]
327 pub component_scope_thresholds: Option<ComponentScopeThresholds>,
328 #[serde(default)]
329 pub generate_kams: bool,
330 #[serde(default)]
331 pub generate_group_opinion: bool,
332}
333
334#[derive(Debug, Clone, Serialize, Deserialize)]
335pub struct GroupMaterialityConfig {
336 pub basis: MaterialityBasis,
337 pub percent: Decimal,
338}
339
340#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
341#[serde(rename_all = "snake_case")]
342pub enum MaterialityBasis {
343 Revenue,
344 Assets,
345 PretaxIncome,
346 Equity,
347}
348
349#[derive(Debug, Clone, Serialize, Deserialize)]
350pub struct ComponentScopeThresholds {
351 pub full_scope: Decimal,
352 pub specific_scope: Decimal,
353}
354
355#[derive(Debug, Clone, Default, Serialize, Deserialize)]
356pub struct TaxGroupConfig {
357 #[serde(default)]
358 pub pillar_two: Option<PillarTwoConfig>,
359 #[serde(default)]
360 pub cbc_report: Option<CbcReportConfig>,
361 #[serde(default)]
362 pub transfer_pricing: Option<TpConfig>,
363}
364
365#[derive(Debug, Clone, Serialize, Deserialize)]
366pub struct PillarTwoConfig {
367 pub enabled: bool,
368 #[serde(default)]
369 pub jurisdictions: Vec<String>,
370}
371
372#[derive(Debug, Clone, Serialize, Deserialize)]
373pub struct CbcReportConfig {
374 pub enabled: bool,
375 #[serde(default)]
376 pub reporting_jurisdiction: Option<String>,
377}
378
379#[derive(Debug, Clone, Serialize, Deserialize)]
380pub struct TpConfig {
381 #[serde(default)]
382 pub master_file: bool,
383 #[serde(default)]
384 pub local_files_for: Vec<String>,
385}
386
387#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
388pub struct OutputLayoutConfig {
389 #[serde(default = "default_layout")]
390 pub layout: OutputLayout,
391 #[serde(default = "default_true")]
392 pub shared_masters_at_root: bool,
393 #[serde(default)]
394 pub compression: Option<OutputCompression>,
395}
396
397fn default_layout() -> OutputLayout {
398 OutputLayout::PerEntitySubtree
399}
400fn default_true() -> bool {
401 true
402}
403
404#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Default)]
405#[serde(rename_all = "snake_case")]
406pub enum OutputLayout {
407 #[default]
408 PerEntitySubtree,
409 Flat,
410}
411
412#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
413#[serde(rename_all = "lowercase")]
414pub enum OutputCompression {
415 Json,
416 Csv,
417 Parquet,
418}
419
420#[derive(Debug, Clone, Default, Serialize, Deserialize)]
421pub struct FleetConfig {
422 #[serde(default)]
423 pub dispatcher: Option<String>, #[serde(default)]
425 pub max_concurrent_shards: Option<u32>,
426 #[serde(default)]
427 pub per_shard_timeout_seconds: Option<u64>,
428}
429
430#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
443pub struct CguConfig {
444 #[serde(default)]
449 pub cgus: Vec<CguDefinitionEntry>,
450
451 #[serde(default)]
459 pub goodwill_allocations: Vec<CguGoodwillAllocationEntry>,
460}
461
462#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
466pub struct CguDefinitionEntry {
467 pub cgu_id: String,
471 pub name: String,
473 #[serde(default)]
479 pub member_entity_codes: Vec<String>,
480 #[serde(default, skip_serializing_if = "Option::is_none")]
483 pub segment_code: Option<String>,
484}
485
486#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
489pub struct CguGoodwillAllocationEntry {
490 pub cgu_id: String,
493 pub business_combination_id: String,
498 pub goodwill_amount: Decimal,
501 pub allocation_date: NaiveDate,
503}
504
505#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
514pub struct OwnershipChangeEntry {
515 pub event_type: datasynth_core::models::intercompany::OwnershipChangeType,
518 pub effective_date: NaiveDate,
521 pub ownership_percent_before: Decimal,
524 pub ownership_percent_after: Decimal,
527 #[serde(default)]
532 pub previously_held_interest_carrying: Option<Decimal>,
533 #[serde(default)]
536 pub previously_held_interest_fair_value: Option<Decimal>,
537 pub consideration_paid_or_received: Decimal,
542 #[serde(default)]
546 pub acquisition_date_nci_fair_value: Option<Decimal>,
547 #[serde(default)]
550 pub nci_measurement_method: datasynth_core::models::intercompany::NciMeasurementMethod,
551 pub currency: String,
553}