use chrono::NaiveDate;
use rust_decimal::Decimal;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct StatementOfChangesInEquity {
pub group_id: String,
pub period_start: NaiveDate,
pub period_end: NaiveDate,
pub currency: String,
pub owners_equity: EquityRollforward,
pub nci: EquityRollforward,
pub total_equity: EquityRollforward,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct EquityRollforward {
pub opening: Decimal,
pub net_income: Decimal,
pub oci: Decimal,
pub dividends: Decimal,
pub other: Decimal,
pub closing: Decimal,
}
pub struct EquityChangesInputs {
pub opening_owners_equity: Decimal,
pub opening_nci: Decimal,
pub net_income_to_owners: Decimal,
pub net_income_to_nci: Decimal,
pub oci_to_owners: Decimal,
pub oci_to_nci: Decimal,
pub dividends_to_owners: Decimal,
pub dividends_to_nci: Decimal,
pub other_owners: Decimal,
pub other_nci: Decimal,
}
pub fn build_statement_of_changes_in_equity(
inputs: &EquityChangesInputs,
group_id: &str,
period_start: NaiveDate,
period_end: NaiveDate,
currency: &str,
) -> StatementOfChangesInEquity {
let owners = rollforward(
inputs.opening_owners_equity,
inputs.net_income_to_owners,
inputs.oci_to_owners,
inputs.dividends_to_owners,
inputs.other_owners,
);
let nci = rollforward(
inputs.opening_nci,
inputs.net_income_to_nci,
inputs.oci_to_nci,
inputs.dividends_to_nci,
inputs.other_nci,
);
let total = EquityRollforward {
opening: owners.opening + nci.opening,
net_income: owners.net_income + nci.net_income,
oci: owners.oci + nci.oci,
dividends: owners.dividends + nci.dividends,
other: owners.other + nci.other,
closing: owners.closing + nci.closing,
};
StatementOfChangesInEquity {
group_id: group_id.to_string(),
period_start,
period_end,
currency: currency.to_string(),
owners_equity: owners,
nci,
total_equity: total,
}
}
fn rollforward(
opening: Decimal,
net_income: Decimal,
oci: Decimal,
dividends: Decimal,
other: Decimal,
) -> EquityRollforward {
let closing = opening + net_income + oci - dividends + other;
EquityRollforward {
opening,
net_income,
oci,
dividends,
other,
closing,
}
}
#[cfg(test)]
mod tests {
use super::*;
use rust_decimal_macros::dec;
#[test]
fn rollforward_identity() {
let r = rollforward(dec!(100), dec!(50), dec!(10), dec!(5), dec!(2));
assert_eq!(r.closing, dec!(157));
}
}