diff options
| author | Benedict Börger <benedict@0xb8000.de> | 2019-06-24 21:49:51 +0200 |
|---|---|---|
| committer | Benedict Börger <benedict@0xb8000.de> | 2019-06-24 21:49:51 +0200 |
| commit | 18dd51842832ac21d81b398cc512e9c6ef245039 (patch) | |
| tree | 9447e175112569d10aab1b4431bf32a5316d483c /src | |
| parent | b7a7d1d9512357bb2309fff50afaebd4082f9dd8 (diff) | |
[web_frontend] move transaction_filter to util
Since the sites transactions and chart both filter the transactions, move
the function to util, whre both can access it.
Diffstat (limited to 'src')
| -rw-r--r-- | src/web_frontend/chart.rs | 33 | ||||
| -rw-r--r-- | src/web_frontend/transactions.rs | 69 | ||||
| -rw-r--r-- | src/web_frontend/util.rs | 67 |
3 files changed, 88 insertions, 81 deletions
diff --git a/src/web_frontend/chart.rs b/src/web_frontend/chart.rs index 0992e99..a6b387a 100644 --- a/src/web_frontend/chart.rs +++ b/src/web_frontend/chart.rs @@ -64,16 +64,17 @@ pub fn chart_handler(account : &RawStr, start : Option<&RawStr>, end : Option<&R let t = acc.transactions; // filter transaction to match only the specified timeframe - println!("unfiltered number: {}", t.len()); let mut t_filtered = Vec::new(); for date in date_range { - let mut tmp : Vec<_> = t.iter().filter(|x| x.date.month() == date.month() && x.date.year() == date.year()).collect(); - t_filtered.append(& mut tmp); + let tc = t.clone(); + let mut tmp : Vec<_> = tc.into_iter().filter(|x| x.date.month() == date.month() && x.date.year() == date.year()).collect(); + t_filtered.append(&mut tmp); } - println!("filtered number: {}", t_filtered.len()); - let total_sum = t_filtered.iter().filter(|t| t.amount < 0.0 ) - .fold(0.0, |acc, x| acc + x.amount).abs(); + // spending chart, so do not consider income + let t_final : Vec<_> = t_filtered.clone().into_iter().filter(|t| t.amount < 0.0 ).collect(); + + let total_sum = t_final.clone().into_iter().fold(0.0, |acc, x| acc + x.amount).abs(); println!("total sum: {}", total_sum); let mut total_chart = 0.0; for (section_name, entries) in ini_file.sections { @@ -81,24 +82,22 @@ pub fn chart_handler(account : &RawStr, start : Option<&RawStr>, end : Option<&R let mut complete = 0.0; for (key, values) in entries { for val in values { - filter_string.push_str(&key); - filter_string.push_str("-"); - filter_string.push_str(&val); - filter_string.push_str("."); - let mut t_filtered_cloned = t_filtered.clone(); if val.is_empty() || val.is_empty() { continue } - let re = Regex::new(&val).unwrap(); - let tmp = t_filtered_cloned.into_iter().filter(|transaction| - re.is_match(&transaction.sender_name) ) - .fold(0.0, |acc, x| acc + x.amount); - complete = complete + tmp.abs(); + filter_string.push_str(&key); + filter_string.push_str("-"); + filter_string.push_str(&val); + filter_string.push_str(";"); } } + let t_filtered_cloned = crate::web_frontend::util::apply_transaction_filter(filter_string.clone(), t_final.clone()); + println!("for filter: {}: transactions: {}", filter_string, t_filtered_cloned.len()); + let tmp = t_filtered_cloned.into_iter() + .fold(0.0, |acc, x| acc + x.amount); + complete = complete + tmp.abs(); groups.insert(section_name, GroupValues{ amount: complete, filter : filter_string } ); total_chart = total_chart + complete; - // ALSO INSERT OTHER, AKA THE REST } let context = ChartContext { account_name : account_name, groups : groups, total_sum : total_sum, total_chart : total_chart, diff --git a/src/web_frontend/transactions.rs b/src/web_frontend/transactions.rs index f6d65af..6e5ae8c 100644 --- a/src/web_frontend/transactions.rs +++ b/src/web_frontend/transactions.rs @@ -8,15 +8,12 @@ use rocket::response::NamedFile; use std::path::{PathBuf, Path}; use rocket::request::Form; use rocket::http::RawStr; +use rocket::http::uri::Uri; use regex::Regex; use chrono::{NaiveDate, Utc}; use chrono::Datelike; /* - This files contains the code to handle the /transactions requests -*/ - -/* * This context is passed to the template rendering engine * If you modify this structure, adapt also the template to include the * changes! @@ -30,65 +27,6 @@ struct TransactionContext { date_end : String } -struct TransactionFilter { - sender_name_filter : Vec<String>, - reference_filter : Vec<String> -} - -/* - * files syntax: . seperates different search critereas - * a search crietera is a key value pair, with key as fiter type, e.g. - * sender name of transation. The value is what is should be and can be a regex - * key value pair is split by - - */ -fn apply_transaction_filter(filter : String, transactions : Vec<crate::banking::account::Transaction>) -> Vec<crate::banking::account::Transaction> { - let mut tmp = transactions.clone(); - // special case if for general search - if !filter.to_string().contains(".") { - println!("in special case"); - let re = Regex::new(&filter).unwrap(); - tmp = transactions.into_iter().filter(|transaction| re.is_match(&transaction.sender_name) || re.is_match(&transaction.reference) ).collect(); - return tmp; - } - - // parse filter string and construct TransactionFilter struct - let mut sender_name_vec = Vec::new(); - let mut reference_vec = Vec::new(); - for entry in filter.to_string().split(".") { - let v : Vec<_> = entry.split("-").collect(); - println!("{:?}", v); - if v.len() > 1 { - if v[0] == "sender" { - println!("Filter for sender_name"); - sender_name_vec.push(v[1].to_string()); - } - else if v[0] == "reference" { - println!("filter for reference"); - reference_vec.push(v[1].to_string()); - } - } - - } - tmp = transactions.clone().into_iter().filter(|transaction| { - let mut sender_match = false; - let mut reference_match = false; - for sender in &sender_name_vec { - let re_sender = Regex::new(&sender).unwrap(); - if re_sender.is_match(&transaction.sender_name) { - sender_match = true; - } - } - for reference in &reference_vec { - let re = Regex::new(&reference).unwrap(); - if re.is_match(&transaction.reference) { - reference_match = true; - } - } - sender_match || reference_match - }).collect(); - tmp - -} #[get("/transactions/<account>?<start>&<end>&<filter>")] pub fn transaction_handler(account : &RawStr, start : Option<&RawStr>, end : Option<&RawStr>, @@ -110,6 +48,9 @@ pub fn transaction_handler(account : &RawStr, start : Option<&RawStr>, end : Opt Some(s) => s.to_string(), None => String::from("") }; + let tf_c = transaction_filter.clone(); + let test = Uri::percent_decode_lossy(tf_c.as_bytes()); + let transaction_filter = test.to_string(); let asset_ini = "data/asset.ini"; let asset : Asset = crate::banking::asset::Asset::from_ini_file(asset_ini); let transactions = asset.get_account_by_name(&account_name); @@ -130,7 +71,7 @@ pub fn transaction_handler(account : &RawStr, start : Option<&RawStr>, end : Opt } // apply filter - let ft = apply_transaction_filter(transaction_filter.clone(), t_filtered); + let ft = crate::web_frontend::util::apply_transaction_filter(transaction_filter.clone(), t_filtered); let context = TransactionContext { transactions: ft, account_name : account_name, filter : transaction_filter, date_start : date_start.to_string()[0..7].to_string(), diff --git a/src/web_frontend/util.rs b/src/web_frontend/util.rs index 208b5b9..8c24465 100644 --- a/src/web_frontend/util.rs +++ b/src/web_frontend/util.rs @@ -1,5 +1,6 @@ use chrono::{NaiveDate, Utc}; use chrono::Datelike; +use regex::Regex; #[derive(Debug)] pub struct DateRange { @@ -49,3 +50,69 @@ impl Iterator for DateRange { return Some(chrono::NaiveDate::parse_from_str(&tmp, "%Y-%m-%d").unwrap()) } } + + + +/* + This files contains the code to handle the /transactions requests +*/ + +struct TransactionFilter { + sender_name_filter : Vec<String>, + reference_filter : Vec<String> +} + +/* + * files syntax: . seperates different search critereas + * a search crietera is a key value pair, with key as fiter type, e.g. + * sender name of transation. The value is what is should be and can be a regex + * key value pair is split by - + */ +pub fn apply_transaction_filter(filter : String, transactions : Vec<crate::banking::account::Transaction>) -> Vec<crate::banking::account::Transaction> { + let mut tmp = transactions.clone(); + // special case if for general search + if !filter.to_string().contains(";") { + println!("in special case"); + let re = Regex::new(&filter).unwrap(); + tmp = transactions.into_iter().filter(|transaction| re.is_match(&transaction.sender_name) || re.is_match(&transaction.reference) ).collect(); + return tmp; + } + + // parse filter string and construct TransactionFilter struct + let mut sender_name_vec = Vec::new(); + let mut reference_vec = Vec::new(); + for entry in filter.to_string().split(";") { + let v : Vec<_> = entry.split("-").collect(); + println!("{:?}", v); + if v.len() > 1 { + if v[0] == "sender" { + println!("Filter for sender_name"); + sender_name_vec.push(v[1].to_string()); + } + else if v[0] == "reference" { + println!("filter for reference"); + reference_vec.push(v[1].to_string()); + } + } + + } + tmp = transactions.clone().into_iter().filter(|transaction| { + let mut sender_match = false; + let mut reference_match = false; + for sender in &sender_name_vec { + let re_sender = Regex::new(&sender).unwrap(); + if re_sender.is_match(&transaction.sender_name) { + sender_match = true; + } + } + for reference in &reference_vec { + let re = Regex::new(&reference).unwrap(); + if re.is_match(&transaction.reference) { + reference_match = true; + } + } + sender_match || reference_match + }).collect(); + tmp + +} |
