Skip to content

Commit

Permalink
Merge pull request #14 from sebinsua/feat/totals-all-outgoing-incoming
Browse files Browse the repository at this point in the history
Ability to see outgoing and incoming totals of each month
  • Loading branch information
sebinsua committed Dec 21, 2015
2 parents 6a6a8de + d8c9f3d commit 25a16a2
Show file tree
Hide file tree
Showing 6 changed files with 189 additions and 45 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
All notable changes to this project will be [documented](http://keepachangelog.com/) in this file.
This project adheres to [Semantic Versioning](http://semver.org/).

## [v0.0.2](https://github.com/sebinsua/teller-cli/releases/tag/v0.0.2) - 2015-12-22

`list balances` became `list totals` and now supports `--amount-type=incoming|outgoing|all`.

## [v0.0.1](https://github.com/sebinsua/teller-cli/releases/tag/v0.0.1) - 2015-12-21

Preliminary release.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "teller_cli"
version = "0.0.1"
version = "0.0.2"
authors = ["Seb Insua <[email protected]>"]

[[bin]]
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ It uses [Teller](http://teller.io) behind-the-scenes to interact with your UK ba

*e.g.*

![Instructions](http://i.imgur.com/XJ5Vsfa.png)
![Instructions](http://i.imgur.com/aILWh5r.png)

## Why?

Expand Down Expand Up @@ -60,7 +60,7 @@ Hopefully Teller will add support for querying transactions soon.
#### Am I saving money with a chart :chart_with_upwards_trend: with [`spark`](https://github.com/holman/spark)

```
> teller list balances business --interval=monthly --timeframe=year --output=spark | spark
> teller list totals business --amount-type=all --interval=monthly --timeframe=year --output=spark | spark
▁▁▁▂▃▂▃▄▄▅▆█
```

Expand All @@ -69,7 +69,7 @@ Hopefully Teller will add support for querying transactions soon.
### From release

```
> curl -L https://github.com/sebinsua/teller-cli/releases/download/v0.0.1/teller > /usr/local/bin/teller && chmod +x /usr/local/bin/teller
> curl -L https://github.com/sebinsua/teller-cli/releases/download/v0.0.2/teller > /usr/local/bin/teller && chmod +x /usr/local/bin/teller
```

### From source
Expand Down
88 changes: 77 additions & 11 deletions src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ pub enum Timeframe {

pub type ApiServiceResult<T> = Result<T, TellerClientError>;
pub type IntervalAmount = (String, String);
pub type Balances = HistoricalAmountsWithCurrency;
pub type Outgoings = HistoricalAmountsWithCurrency;
pub type Incomings = HistoricalAmountsWithCurrency;

#[derive(Debug)]
pub struct Money {
Expand Down Expand Up @@ -89,7 +92,7 @@ pub struct Transaction {
}

#[derive(Debug)]
pub struct Balances {
pub struct HistoricalAmountsWithCurrency {
pub historical_amounts: Vec<IntervalAmount>,
pub currency: String,
}
Expand Down Expand Up @@ -252,26 +255,35 @@ pub fn get_transactions(config: &Config, account_id: &str, timeframe: &Timeframe
}
}

pub fn get_balances(config: &Config, account_id: &str, interval: &Interval, timeframe: &Timeframe) -> ApiServiceResult<Balances> {
fn get_grouped_transaction_aggregates(config: &Config, account_id: &str, interval: &Interval, timeframe: &Timeframe, aggregate_txs: &Fn((String, Vec<Transaction>)) -> (String, i64)) -> ApiServiceResult<Vec<(String, i64)>> {
let transactions: Vec<Transaction> = get_transactions(&config, &account_id, &timeframe).unwrap_or(vec![]);

let mut month_year_total_transactions: Vec<(String, i64)> = transactions.into_iter().group_by(|t| {
let mut month_year_grouped_transactions: Vec<(String, i64)> = transactions.into_iter().group_by(|t| {
let transaction_date = parse_utc_date_from_transaction(&t);
match *interval {
Interval::Monthly => {
let group_name = transaction_date.format("%m-%Y").to_string();
group_name
}
}
}).map(|myt| {
}).map(aggregate_txs).collect();
month_year_grouped_transactions.reverse();

Ok(month_year_grouped_transactions)
}

pub fn get_balances(config: &Config, account_id: &str, interval: &Interval, timeframe: &Timeframe) -> ApiServiceResult<Balances> {
let sum_all = |myt: (String, Vec<Transaction>)| {
let to_cent_integer = |t: &Transaction| {
(f64::from_str(&t.amount).unwrap() * 100f64).round() as i64
};

let group_name = myt.0;
let amount = myt.1.into_iter().map(|t| {
let v = (f64::from_str(&t.amount).unwrap() * 100f64).round() as i64;
v
}).fold(0i64, |sum, v| sum + v);
let amount = myt.1.iter().map(to_cent_integer).fold(0i64, |sum, v| sum + v);
(group_name, amount)
}).collect();
month_year_total_transactions.reverse();
};

let month_year_total_transactions = try!(get_grouped_transaction_aggregates(&config, &account_id, &interval, &timeframe, &sum_all));

let account = try!(get_account(&config, &account_id));
let current_balance = (f64::from_str(&account.balance).unwrap() * 100f64).round() as i64;
Expand All @@ -287,5 +299,59 @@ pub fn get_balances(config: &Config, account_id: &str, interval: &Interval, time
}
historical_amounts.reverse();

Ok(Balances::new(historical_amounts, currency))
Ok(HistoricalAmountsWithCurrency::new(historical_amounts, currency))
}

pub fn get_outgoings(config: &Config, account_id: &str, interval: &Interval, timeframe: &Timeframe) -> ApiServiceResult<Outgoings> {
let sum_outgoings = |myt: (String, Vec<Transaction>)| {
let to_cent_integer = |t: &Transaction| {
(f64::from_str(&t.amount).unwrap() * 100f64).round() as i64
};

let group_name = myt.0;
let amount = myt.1.iter().map(to_cent_integer).filter(|ci| {
*ci < 0
}).fold(0i64, |sum, v| sum + v);
(group_name, amount)
};

let month_year_total_outgoing = try!(get_grouped_transaction_aggregates(&config, &account_id, &interval, &timeframe, &sum_outgoings));

let account = try!(get_account(&config, &account_id));
let currency = account.currency;

let mut historical_amounts: Vec<IntervalAmount> = vec![];
for mytt in month_year_total_outgoing {
historical_amounts.push((mytt.0.to_string(), format!("{:.2}", mytt.1 as f64 / 100f64)));
}
historical_amounts.reverse();

Ok(HistoricalAmountsWithCurrency::new(historical_amounts, currency))
}

pub fn get_incomings(config: &Config, account_id: &str, interval: &Interval, timeframe: &Timeframe) -> ApiServiceResult<Incomings> {
let sum_incomings = |myt: (String, Vec<Transaction>)| {
let to_cent_integer = |t: &Transaction| {
(f64::from_str(&t.amount).unwrap() * 100f64).round() as i64
};

let group_name = myt.0;
let amount = myt.1.iter().map(to_cent_integer).filter(|ci| {
*ci > 0
}).fold(0i64, |sum, v| sum + v);
(group_name, amount)
};

let month_year_total_incoming = try!(get_grouped_transaction_aggregates(&config, &account_id, &interval, &timeframe, &sum_incomings));

let account = try!(get_account(&config, &account_id));
let currency = account.currency;

let mut historical_amounts: Vec<IntervalAmount> = vec![];
for mytt in month_year_total_incoming {
historical_amounts.push((mytt.0.to_string(), format!("{:.2}", mytt.1 as f64 / 100f64)));
}
historical_amounts.reverse();

Ok(HistoricalAmountsWithCurrency::new(historical_amounts, currency))
}
Loading

0 comments on commit 25a16a2

Please sign in to comment.