use chrono::NaiveDate;
use datasynth_core::accounts::{cash_accounts, dividend_accounts, equity_accounts};
use datasynth_core::models::{DividendDeclaration, JournalEntry, JournalEntryLine};
use datasynth_core::utils::seeded_rng;
use datasynth_core::uuid_factory::{DeterministicUuidFactory, GeneratorType};
use rand_chacha::ChaCha8Rng;
use rust_decimal::Decimal;
pub struct DividendResult {
pub declarations: Vec<DividendDeclaration>,
pub journal_entries: Vec<JournalEntry>,
}
pub struct DividendGenerator {
#[allow(dead_code)]
rng: ChaCha8Rng,
uuid_factory: DeterministicUuidFactory,
}
impl DividendGenerator {
pub fn new(seed: u64) -> Self {
Self {
rng: seeded_rng(seed, 0),
uuid_factory: DeterministicUuidFactory::new(seed, GeneratorType::PeriodClose),
}
}
pub fn generate(
&mut self,
entity_code: &str,
declaration_date: NaiveDate,
per_share_amount: Decimal,
total_amount: Decimal,
currency: &str,
) -> DividendResult {
let id = self.uuid_factory.next().to_string();
let record_date = declaration_date + chrono::Duration::days(14);
let payment_date = record_date + chrono::Duration::days(30);
let declaration = DividendDeclaration {
id: id.clone(),
entity_code: entity_code.to_string(),
declaration_date,
record_date,
payment_date,
per_share_amount,
total_amount,
currency: currency.to_string(),
};
let decl_doc_id = format!("JE-DIV-DECL-{id}");
let mut decl_je = JournalEntry::new_simple(
decl_doc_id,
entity_code.to_string(),
declaration_date,
format!("Dividend declaration – {entity_code}"),
);
decl_je.add_line(JournalEntryLine {
line_number: 1,
gl_account: equity_accounts::RETAINED_EARNINGS.to_string(),
debit_amount: total_amount,
credit_amount: Decimal::ZERO,
reference: Some(id.clone()),
..Default::default()
});
decl_je.add_line(JournalEntryLine {
line_number: 2,
gl_account: dividend_accounts::DIVIDENDS_PAYABLE.to_string(),
debit_amount: Decimal::ZERO,
credit_amount: total_amount,
reference: Some(id.clone()),
..Default::default()
});
let pay_doc_id = format!("JE-DIV-PAY-{id}");
let mut pay_je = JournalEntry::new_simple(
pay_doc_id,
entity_code.to_string(),
payment_date,
format!("Dividend payment – {entity_code}"),
);
pay_je.add_line(JournalEntryLine {
line_number: 1,
gl_account: dividend_accounts::DIVIDENDS_PAYABLE.to_string(),
debit_amount: total_amount,
credit_amount: Decimal::ZERO,
reference: Some(id.clone()),
..Default::default()
});
pay_je.add_line(JournalEntryLine {
line_number: 2,
gl_account: cash_accounts::OPERATING_CASH.to_string(),
debit_amount: Decimal::ZERO,
credit_amount: total_amount,
reference: Some(id.clone()),
..Default::default()
});
DividendResult {
declarations: vec![declaration],
journal_entries: vec![decl_je, pay_je],
}
}
}