use core::fmt::Display;
use core::hash::Hash;
use time::Date;
use time::OffsetDateTime;
use time_tz::PrimitiveDateTimeExt;
use crate::Account;
use crate::Amount;
use crate::MetadataKey;
use crate::MetadataMap;
use crate::MetadataValue;
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct Balance {
pub date: Date,
pub account: Account,
pub amount: Amount,
pub meta: MetadataMap,
}
impl Balance {
pub fn new(date: Date, account: impl Into<Account>, amount: Amount) -> Self {
let (account, meta) = (account.into(), MetadataMap::default());
Self {
date,
account,
amount,
meta,
}
}
}
impl Balance {
#[inline]
pub fn add_meta(
&mut self,
key: impl Into<MetadataKey>,
value: impl Into<MetadataValue>,
) -> &mut Self {
self.meta.insert(key.into(), value.into());
self
}
#[inline]
pub fn clear_meta(&mut self) -> &mut Self {
self.meta.clear();
self
}
#[inline]
pub fn set_account(&mut self, account: impl Into<Account>) -> &mut Self {
self.account = account.into();
self
}
#[inline]
pub fn set_amount(&mut self, amount: Amount) -> &mut Self {
self.amount = amount;
self
}
#[inline]
pub fn set_date(&mut self, date: Date) -> &mut Self {
self.date = date;
self
}
#[inline]
pub fn set_meta(&mut self, meta: impl Into<MetadataMap>) -> &mut Self {
self.meta = meta.into();
self
}
}
impl Balance {
#[inline]
#[must_use]
pub fn timestamp(&self) -> Option<OffsetDateTime> {
let local_timestamp = self.date.midnight();
let timezone = time_tz::system::get_timezone().ok()?;
local_timestamp.assume_timezone(timezone).take_first()
}
}
impl Display for Balance {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let Self {
date,
account,
amount,
meta,
} = self;
write!(f, "{date} balance {account} {amount}")?;
for (key, value) in meta {
write!(f, "\n {key}: {value}")?;
}
Ok(())
}
}