|
@@ -0,0 +1,76 @@
|
|
|
+use crate::data::Root;
|
|
|
+use crate::show::show_transaction;
|
|
|
+
|
|
|
+pub fn do_inference(data: &mut Root) -> anyhow::Result<bool> {
|
|
|
+ let placeholder = data.spec_root().placeholder_account;
|
|
|
+
|
|
|
+ let num_txns = data.ledger_data_for(placeholder).unwrap().len();
|
|
|
+
|
|
|
+ let mut any_changed = false;
|
|
|
+
|
|
|
+ for idx in 0..num_txns {
|
|
|
+ let txns = data.ledger_data_for(placeholder).unwrap();
|
|
|
+ let txn = &txns[idx];
|
|
|
+ let txn_title = txn.title.clone();
|
|
|
+
|
|
|
+ log::trace!("Considering transaction");
|
|
|
+ let (_, mut chg) = txn.split_changes(placeholder).unwrap();
|
|
|
+
|
|
|
+ let complementary_change = chg.next().unwrap().clone();
|
|
|
+
|
|
|
+ if chg.next().is_some() {
|
|
|
+ log::debug!("Skipping transaction with more than two changes");
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ let other_account = *complementary_change.account;
|
|
|
+ let Some(other_txns) = data.ledger_data_for(other_account) else {
|
|
|
+ // this should never happen
|
|
|
+ panic!("Account {other_account} has no transaction data!");
|
|
|
+ };
|
|
|
+
|
|
|
+ drop(chg);
|
|
|
+
|
|
|
+ for other_txn in other_txns {
|
|
|
+ if other_txn.title.is_none() || other_txn.title != txn_title || other_txn == txn {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ // get other_txn's other
|
|
|
+ let (_, mut chg) = other_txn.split_changes(other_account).unwrap();
|
|
|
+ let candidate = chg.next().unwrap();
|
|
|
+ if chg.next().is_some() || *candidate.account == placeholder {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ log::debug!("possible candidate {}, titles are {:?} and {:?}", candidate.account, other_txn.title, txn.title);
|
|
|
+
|
|
|
+ show_transaction(None, txn.as_ref());
|
|
|
+
|
|
|
+ println!("Candidate account: {} (Y/n)", console::style(candidate.account).red());
|
|
|
+ let answer = console::Term::stdout().read_char().unwrap();
|
|
|
+ match answer.to_lowercase().next() {
|
|
|
+ Some('y') | Some('\n') | Some('\r') => {
|
|
|
+ let new_account = candidate.account.0.clone();
|
|
|
+ println!(" Changing to account {} ...", console::style(new_account).green());
|
|
|
+
|
|
|
+ drop(chg);
|
|
|
+
|
|
|
+ data.ledger_data_for_mut(placeholder).unwrap()[idx].changes.iter_mut().for_each(|c| {
|
|
|
+ log::info!("change account is {}, placeholder is {}", c.account, placeholder);
|
|
|
+ if *c.account == placeholder {
|
|
|
+ c.account = new_account.into();
|
|
|
+ log::info!(" changed account to {new_account}");
|
|
|
+ }
|
|
|
+ });
|
|
|
+ any_changed = true;
|
|
|
+
|
|
|
+ break
|
|
|
+ }
|
|
|
+ | Some('n') => (),
|
|
|
+ c => println!("unknown {c:?}"),
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ Ok(any_changed)
|
|
|
+}
|