ledger.rs 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. use itertools::Itertools;
  2. use super::{AccountName, Decimal, Spanned, UnitName};
  3. mod parse;
  4. pub use parse::parse_ledger;
  5. mod print;
  6. pub use print::print_ledger;
  7. #[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq)]
  8. pub struct Balance {
  9. pub account: Spanned<AccountName>,
  10. pub amount: Spanned<Decimal>,
  11. pub unit: Spanned<UnitName>,
  12. }
  13. #[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord)]
  14. pub struct LedgerEntry {
  15. pub datestamp: (u16, u8, u8),
  16. pub title: Option<String>,
  17. pub annotations: Vec<String>,
  18. pub balances: Vec<Spanned<Balance>>,
  19. }
  20. impl LedgerEntry {
  21. pub fn modifies(&self, account: AccountName) -> bool {
  22. self.balances.iter().any(|b| b.account.as_ref() == &account)
  23. }
  24. pub fn balance_for(&self, account: AccountName) -> Option<&Spanned<Balance>> {
  25. self.balances
  26. .iter()
  27. .find(|b| b.account.as_ref() == &account)
  28. }
  29. pub fn split_balances(
  30. &self,
  31. account: AccountName,
  32. ) -> Option<(&Spanned<Balance>, impl Iterator<Item = &Spanned<Balance>>)> {
  33. let index = self
  34. .balances
  35. .iter()
  36. .position(|b| b.account.as_ref() == &account)?;
  37. Some((
  38. &self.balances[index],
  39. self.balances[0..index]
  40. .iter()
  41. .chain(self.balances[index + 1..].iter()),
  42. ))
  43. }
  44. pub fn is_mono_unit(&self) -> bool {
  45. self.balances.iter().unique_by(|b| *b.unit).count() == 1
  46. }
  47. pub fn mono_unit(&self) -> Option<UnitName> {
  48. let mut it = self.balances.iter().unique_by(|b| *b.unit);
  49. let uniq = it.next()?;
  50. it.next().is_none().then_some(*uniq.unit)
  51. }
  52. }