|
@@ -1,4 +1,4 @@
|
|
|
-use std::collections::HashMap;
|
|
|
+use std::collections::BTreeMap;
|
|
|
|
|
|
use itertools::Itertools;
|
|
|
|
|
@@ -13,7 +13,7 @@ mod format;
|
|
|
mod parse;
|
|
|
pub mod spec;
|
|
|
|
|
|
-pub use format::{format_ledger,format_entire_ledger};
|
|
|
+pub use format::{format_entire_ledger, format_ledger};
|
|
|
pub use parse::parse_ledger;
|
|
|
|
|
|
pub struct UnitTag;
|
|
@@ -46,7 +46,7 @@ pub struct Transaction {
|
|
|
|
|
|
pub datestamp: Datestamp,
|
|
|
pub title: Option<String>,
|
|
|
- pub annotations: Vec<String>,
|
|
|
+ pub annotations: BTreeMap<String, String>,
|
|
|
pub changes: Vec<Change>,
|
|
|
}
|
|
|
|
|
@@ -60,7 +60,9 @@ impl Transaction {
|
|
|
}
|
|
|
|
|
|
pub fn change_for_mut(&mut self, account: AccountName) -> Option<&mut Change> {
|
|
|
- self.changes.iter_mut().find(|b| b.account.as_ref() == &account)
|
|
|
+ self.changes
|
|
|
+ .iter_mut()
|
|
|
+ .find(|b| b.account.as_ref() == &account)
|
|
|
}
|
|
|
|
|
|
pub fn split_changes(
|
|
@@ -115,12 +117,15 @@ impl Transaction {
|
|
|
}
|
|
|
|
|
|
pub fn get_annotation(&self, label: &str) -> Option<&str> {
|
|
|
- for anno in self.annotations.iter() {
|
|
|
- if let Some(body) = anno.strip_prefix(label) {
|
|
|
- return Some(body);
|
|
|
- }
|
|
|
- }
|
|
|
- None
|
|
|
+ self.annotations.get(label).map(String::as_str)
|
|
|
+ }
|
|
|
+
|
|
|
+ pub fn id(&self) -> Option<&str> {
|
|
|
+ self.get_annotation("id")
|
|
|
+ }
|
|
|
+
|
|
|
+ pub fn ghost(&self) -> Option<&str> {
|
|
|
+ self.get_annotation("ghost")
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -146,7 +151,7 @@ impl PartialEq for TransactionRef {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-impl Eq for TransactionRef { }
|
|
|
+impl Eq for TransactionRef {}
|
|
|
|
|
|
impl PartialOrd for TransactionRef {
|
|
|
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
|
@@ -224,10 +229,11 @@ pub struct Hoard {
|
|
|
spec_root: spec::SpecRoot,
|
|
|
|
|
|
comments: Vec<Spanned<String>>,
|
|
|
+ ghosts: Vec<Transaction>,
|
|
|
|
|
|
raw_ledger_data: Vec<RawLedgerEntry>,
|
|
|
|
|
|
- account_ledger_data: HashMap<AccountName, Vec<TransactionRef>>,
|
|
|
+ account_ledger_data: BTreeMap<AccountName, Vec<TransactionRef>>,
|
|
|
}
|
|
|
|
|
|
impl Hoard {
|
|
@@ -246,6 +252,7 @@ impl Hoard {
|
|
|
spec_root,
|
|
|
raw_ledger_data: vec![],
|
|
|
comments: vec![],
|
|
|
+ ghosts: vec![],
|
|
|
account_ledger_data: Default::default(),
|
|
|
};
|
|
|
|
|
@@ -338,10 +345,15 @@ impl Hoard {
|
|
|
RawLedgerEntry::Transaction(tx) => tx,
|
|
|
RawLedgerEntry::Comment(c) => {
|
|
|
self.comments.push(c.clone());
|
|
|
- continue
|
|
|
+ continue;
|
|
|
}
|
|
|
};
|
|
|
|
|
|
+ if tx.ghost().is_some() {
|
|
|
+ self.ghosts.push(tx.clone());
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
let txn_ref = TransactionRef(std::rc::Rc::new(std::cell::RefCell::new(tx.clone())));
|
|
|
for bal in &tx.changes {
|
|
|
self.account_ledger_data
|
|
@@ -351,7 +363,9 @@ impl Hoard {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- self.account_ledger_data.values_mut().for_each(|v| v.sort_by_key(|t| t.borrow().datestamp));
|
|
|
+ self.account_ledger_data
|
|
|
+ .values_mut()
|
|
|
+ .for_each(|v| v.sort_by_key(|t| t.borrow().datestamp));
|
|
|
}
|
|
|
|
|
|
pub fn all_raw_ledger_data(&self) -> &[RawLedgerEntry] {
|
|
@@ -366,7 +380,10 @@ impl Hoard {
|
|
|
self.account_ledger_data.get(&aname).map(Vec::as_slice)
|
|
|
}
|
|
|
|
|
|
- pub fn raw_ledger_data_from(&self, source: io::SourceFile) -> impl Iterator<Item = &RawLedgerEntry> {
|
|
|
+ pub fn raw_ledger_data_from(
|
|
|
+ &self,
|
|
|
+ source: io::SourceFile,
|
|
|
+ ) -> impl Iterator<Item = &RawLedgerEntry> {
|
|
|
self.all_raw_ledger_data()
|
|
|
.iter()
|
|
|
.filter(move |le| le.span().context == Some(source))
|
|
@@ -388,8 +405,8 @@ impl Hoard {
|
|
|
&self.spec_root
|
|
|
}
|
|
|
|
|
|
- pub fn balance(&self, aname: AccountName) -> Option<HashMap<UnitName, Decimal>> {
|
|
|
- let mut running = HashMap::<UnitName, Decimal>::new();
|
|
|
+ pub fn balance(&self, aname: AccountName) -> Option<BTreeMap<UnitName, Decimal>> {
|
|
|
+ let mut running = BTreeMap::<UnitName, Decimal>::new();
|
|
|
|
|
|
for le in self.ledger_data_for(aname)? {
|
|
|
for b in &le.borrow().changes {
|
|
@@ -407,8 +424,12 @@ impl Hoard {
|
|
|
pub fn kill_transaction(&mut self, txn_ref: TransactionRef) {
|
|
|
let txn = txn_ref.borrow();
|
|
|
for account in txn.changes.iter().map(|v| *v.account).collect::<Vec<_>>() {
|
|
|
- let Some(account_data) = self.account_ledger_data.get_mut(&account) else { continue };
|
|
|
- let Some(pos) = account_data.iter().position(|v| *v == txn_ref) else { continue };
|
|
|
+ let Some(account_data) = self.account_ledger_data.get_mut(&account) else {
|
|
|
+ continue;
|
|
|
+ };
|
|
|
+ let Some(pos) = account_data.iter().position(|v| *v == txn_ref) else {
|
|
|
+ continue;
|
|
|
+ };
|
|
|
account_data.remove(pos);
|
|
|
}
|
|
|
// transaction txn_ref should now be dangling
|