|
@@ -30,49 +30,7 @@ pub type AccountName = stringstore::StoredString<AccountTag>;
|
|
|
|
|
|
pub type Datestamp = chrono::NaiveDate;
|
|
|
|
|
|
-/*
|
|
|
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
|
|
-pub struct Datestamp {
|
|
|
- pub year: u16,
|
|
|
- pub month: u8,
|
|
|
- pub day: u8,
|
|
|
-}
|
|
|
-
|
|
|
-impl Datestamp {
|
|
|
- pub fn distance_from(&self, other: &Self) -> usize {
|
|
|
- if self > other {
|
|
|
- return other.distance_from(self)
|
|
|
- }
|
|
|
-
|
|
|
- // at target?
|
|
|
- if self.year == other.year && self.month == other.month && self.day == other.day {
|
|
|
- 0
|
|
|
- }
|
|
|
- // advance days?
|
|
|
- else if self.year == other.year && self.month == other.month {
|
|
|
- (other.day - self.day) as usize
|
|
|
- } else if self.year == other.year {
|
|
|
- todo!()
|
|
|
- } else {
|
|
|
- todo!()
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-*/
|
|
|
-
|
|
|
-/*impl std::fmt::Display for Datestamp {
|
|
|
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
- write!(f, "{:04}-{:02}-{:02}", self.0.year, self.month, self.day)
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-impl std::fmt::Debug for Datestamp {
|
|
|
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
- write!(f, "Datestamp ({self})")
|
|
|
- }
|
|
|
-}*/
|
|
|
-
|
|
|
-#[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq)]
|
|
|
+#[derive(Clone, Debug)]
|
|
|
pub struct Change {
|
|
|
pub source: Option<io::Span>,
|
|
|
|
|
@@ -82,7 +40,7 @@ pub struct Change {
|
|
|
pub unit: Spanned<UnitName>,
|
|
|
}
|
|
|
|
|
|
-#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord)]
|
|
|
+#[derive(Clone, Debug)]
|
|
|
pub struct Transaction {
|
|
|
pub source: Option<io::Span>,
|
|
|
|
|
@@ -101,6 +59,10 @@ impl Transaction {
|
|
|
self.changes.iter().find(|b| b.account.as_ref() == &account)
|
|
|
}
|
|
|
|
|
|
+ pub fn change_for_mut(&mut self, account: AccountName) -> Option<&mut Change> {
|
|
|
+ self.changes.iter_mut().find(|b| b.account.as_ref() == &account)
|
|
|
+ }
|
|
|
+
|
|
|
pub fn split_changes(
|
|
|
&self,
|
|
|
account: AccountName,
|
|
@@ -117,6 +79,31 @@ impl Transaction {
|
|
|
))
|
|
|
}
|
|
|
|
|
|
+ pub fn split_changes_mut(
|
|
|
+ &mut self,
|
|
|
+ account: AccountName,
|
|
|
+ ) -> Option<(&mut Change, impl Iterator<Item = &mut Change>)> {
|
|
|
+ let index = self
|
|
|
+ .changes
|
|
|
+ .iter()
|
|
|
+ .position(|b| b.account.as_ref() == &account)?;
|
|
|
+
|
|
|
+ match index {
|
|
|
+ 0 => {
|
|
|
+ let (l, r) = self.changes.split_at_mut(1);
|
|
|
+ // chain with the empty list here to make the return types equal
|
|
|
+ Some((&mut l[0], r.into_iter().chain((&mut []).into_iter())))
|
|
|
+ }
|
|
|
+ _ => {
|
|
|
+ let (l, r1) = self.changes.split_at_mut(index);
|
|
|
+
|
|
|
+ let (at, r) = r1.split_at_mut(1);
|
|
|
+
|
|
|
+ Some((&mut at[0], l.into_iter().chain(r.into_iter())))
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
pub fn is_mono_unit(&self) -> bool {
|
|
|
self.changes.iter().unique_by(|b| *b.unit).count() == 1
|
|
|
}
|
|
@@ -137,9 +124,43 @@ impl Transaction {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-pub type TransactionRef = std::rc::Rc<std::cell::RefCell<Transaction>>;
|
|
|
+#[derive(Clone)]
|
|
|
+pub struct TransactionRef(std::rc::Rc<std::cell::RefCell<Transaction>>);
|
|
|
+
|
|
|
+impl std::ops::Deref for TransactionRef {
|
|
|
+ type Target = std::cell::RefCell<Transaction>;
|
|
|
+ fn deref(&self) -> &Self::Target {
|
|
|
+ &self.0
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+impl std::fmt::Debug for TransactionRef {
|
|
|
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
+ self.0.borrow().fmt(f)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+impl PartialEq for TransactionRef {
|
|
|
+ fn eq(&self, other: &Self) -> bool {
|
|
|
+ std::rc::Rc::as_ptr(&self.0) == std::rc::Rc::as_ptr(&other.0)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+impl Eq for TransactionRef { }
|
|
|
+
|
|
|
+impl PartialOrd for TransactionRef {
|
|
|
+ fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
|
|
+ Some(<Self as Ord>::cmp(self, other))
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+impl Ord for TransactionRef {
|
|
|
+ fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
|
|
+ std::rc::Rc::as_ptr(&self.0).cmp(&std::rc::Rc::as_ptr(&other.0))
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
-#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
|
|
|
+#[derive(Debug)]
|
|
|
pub enum RawLedgerEntry {
|
|
|
Transaction(Transaction),
|
|
|
Comment(Spanned<String>),
|
|
@@ -168,7 +189,7 @@ impl RawLedgerEntry {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
|
|
|
+#[derive(Debug)]
|
|
|
pub enum LedgerEntry {
|
|
|
Transaction(TransactionRef),
|
|
|
Comment(Spanned<String>),
|
|
@@ -321,7 +342,7 @@ impl Hoard {
|
|
|
}
|
|
|
};
|
|
|
|
|
|
- let txn_ref = std::rc::Rc::new(std::cell::RefCell::new(tx.clone()));
|
|
|
+ let txn_ref = TransactionRef(std::rc::Rc::new(std::cell::RefCell::new(tx.clone())));
|
|
|
for bal in &tx.changes {
|
|
|
self.account_ledger_data
|
|
|
.entry(*bal.account)
|
|
@@ -382,4 +403,18 @@ impl Hoard {
|
|
|
|
|
|
Some(running)
|
|
|
}
|
|
|
+
|
|
|
+ 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 };
|
|
|
+ account_data.remove(pos);
|
|
|
+ }
|
|
|
+ // transaction txn_ref should now be dangling
|
|
|
+ }
|
|
|
+
|
|
|
+ pub fn kill_transactions(&mut self, txns: impl Iterator<Item = TransactionRef>) {
|
|
|
+ txns.for_each(|t| self.kill_transaction(t));
|
|
|
+ }
|
|
|
}
|