Skip to content

Commit

Permalink
Tweak the way transfers are calculated
Browse files Browse the repository at this point in the history
Prefer transfers whose dates are closer together
  • Loading branch information
zmbush committed Oct 20, 2017
1 parent 9cd1cc4 commit d26f582
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 35 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "budgetron"
version = "2.0.0-0.0.2"
version = "2.0.0-0.0.3"
authors = ["Zachary Bush <[email protected]>"]

[[bin]]
Expand Down
4 changes: 1 addition & 3 deletions budgetronrc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,6 @@ budgets:
Household: 150
yearly:
Home Improvement: 5000
rolling:
barry: {}

owners:
joint:
Expand Down Expand Up @@ -202,7 +200,7 @@ owners:
- "Card 4.*"

rolling_budget:
start_date: '08/01/2017'
start_date: '10/01/2017'
split: 'joint'
skip_tags:
- essential
Expand Down
14 changes: 14 additions & 0 deletions src/loading/generic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,20 @@ impl Default for TransactionType {
}
}

impl TransactionType {
pub fn is_credit(&self) -> bool {
TransactionType::Credit == *self
}

pub fn is_debit(&self) -> bool {
TransactionType::Debit == *self
}

pub fn is_transfer(&self) -> bool {
TransactionType::Transfer == *self
}
}

#[derive(Debug, Serialize, Deserialize, Clone, Default)]
pub struct Transaction {
pub date: Date,
Expand Down
72 changes: 51 additions & 21 deletions src/processing/transfers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use loading::{Transaction, TransactionType};
use processing::Collate;
use std::cmp::min;
use std::collections::{HashMap, HashSet};
use std::i64;

pub struct TransferCollator {
pub horizon: usize,
Expand All @@ -19,28 +20,57 @@ impl Collate for TransferCollator {
let mut to_delete = HashSet::new();
let mut to_update = HashMap::new();
for (i, t) in transactions.iter().enumerate() {
for j in i..min(transactions.len(), i + self.horizon) {
let ref tn = transactions[j];
if tn.amount == t.amount && tn.transaction_type != t.transaction_type &&
!to_delete.contains(&i) && !to_delete.contains(&j) &&
!to_update.contains_key(&i) && !to_update.contains_key(&j)
{
if t.account_name == tn.account_name {
to_delete.insert(i);
to_delete.insert(j);
} else {
match t.transaction_type {
TransactionType::Debit => {
to_delete.insert(j);
to_update.insert(i, tn.account_name.clone());
},
TransactionType::Credit => {
to_delete.insert(i);
to_update.insert(j, t.account_name.clone());
},
TransactionType::Transfer => unreachable!(),
};
loop {
let candidates: Vec<_> = (i..min(transactions.len(), i + self.horizon))
.filter_map(|j| {
let ref tn = transactions[j];
if tn.amount == t.amount && !to_delete.contains(&i) &&
!to_delete.contains(&j) &&
!to_update.contains_key(&i) &&
!to_update.contains_key(&j)
{
Some(j)
} else {
None
}
})
.collect();

if candidates.len() <= 1 {
break;
}

let mut mindelta = i64::MAX;
let mut found_transfer = (0, 0);
let debits = candidates.iter().filter(|&i| {
transactions[*i].transaction_type.is_debit()
});

for debit_ix in debits {
let ref debit = transactions[*debit_ix];
let credits = candidates.iter().filter(|&i| {
transactions[*i].transaction_type.is_credit()
});
for credit_ix in credits {
let ref credit = transactions[*credit_ix];
if (debit.date - credit.date).abs() < mindelta {
found_transfer = (*debit_ix, *credit_ix);
mindelta = (debit.date - credit.date).abs();
}
}
}

if found_transfer != (0, 0) {
let ref tn = transactions[found_transfer.1];

to_delete.insert(found_transfer.1);
to_update.insert(found_transfer.0, tn.account_name.clone());

if found_transfer.0 == i || found_transfer.1 == i {
break;
}
} else {
break;
}
}
}
Expand Down
10 changes: 0 additions & 10 deletions src/reporting/rolling_budget.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,16 +86,6 @@ impl Reporter for RollingBudget {
_ => {},
}
}
println!(
"Processing transaction: {:?} {} (${:.02}) [{}/{}/{}]",
transaction.transaction_type,
transaction.description,
transaction.amount,
transaction.person,
transaction.category,
transaction.original_category,
);
println!(" -- {:?}", report.budgets["Zach"]);
}
}
serde_json::to_value(&report).expect("Couldn't serialize")
Expand Down

0 comments on commit d26f582

Please sign in to comment.