diff options
Diffstat (limited to 'src/web_frontend')
| -rw-r--r-- | src/web_frontend/balance.rs | 118 | ||||
| -rw-r--r-- | src/web_frontend/chart.rs | 61 | ||||
| -rw-r--r-- | src/web_frontend/mod.rs | 29 | ||||
| -rw-r--r-- | src/web_frontend/transactions.rs | 101 |
4 files changed, 309 insertions, 0 deletions
diff --git a/src/web_frontend/balance.rs b/src/web_frontend/balance.rs new file mode 100644 index 0000000..2cbebec --- /dev/null +++ b/src/web_frontend/balance.rs @@ -0,0 +1,118 @@ +use parsers::csv::CsvFile; +use banking::Account; +//use parsers::ini::IniFile; +use std::collections::HashMap; +use rocket_contrib::templates::Template; +use rocket::response::NamedFile; +use std::path::{PathBuf, Path}; +use rocket::request::Form; +use rocket::http::RawStr; +use regex::Regex; +use chrono::{NaiveDate, Utc}; +use chrono::Datelike; + +#[derive(Serialize)] +struct MonthEarnSpend { + name : String, + earned : f32, + spent : f32, +} + + +#[derive(Serialize)] +struct BalanceContext { + account_name : String, + months : Vec<MonthEarnSpend>, + date_start : String, + date_end : String +} + +#[derive(Debug)] +struct DateRange { + start_year : i32, + start_month : u32, + end_year : i32, + end_month : u32, +} + +impl DateRange { + fn new(start : chrono::NaiveDate, end : chrono::NaiveDate) -> DateRange { + DateRange { + start_year : start.year(), + start_month : start.month(), + end_year : end.year(), + end_month : end.month(), + } + } +} + +impl Iterator for DateRange { + type Item = chrono::NaiveDate; + + fn next(&mut self) -> Option<Self::Item> { + println!("next called"); + if (self.start_year <= self.end_year) { + if(self.start_month <= self.end_month) { + let mut tmp = self.start_year.to_string(); + if self.start_month < 10 { + tmp.push_str("-0"); + } else { + tmp.push_str("-"); + } + tmp.push_str(&self.start_month.to_string()); + tmp.push_str("-01"); + if self.start_month < 13 { + self.start_month = self.start_month + 1; + } else { + self.start_month = 1; + self.start_year = self.start_year + 1; + } + println!("{}", tmp); + return Some(chrono::NaiveDate::parse_from_str(&tmp, "%Y-%m-%d").unwrap()) + } + } + None + } +} + +#[get("/balance?<start>&<end>")] +pub fn balance_handler(start : Option<&RawStr>, end : Option<&RawStr>) -> rocket_contrib::templates::Template { + let date_start = match start { + Some(s) => { let mut tmp = s.to_string(); + tmp.push_str("-01"); + chrono::NaiveDate::parse_from_str(&tmp, "%Y-%m-%d").unwrap() }, + None => Utc::today().naive_utc() + }; + let date_end = match end { + Some(s) => { let mut tmp = s.to_string(); + tmp.push_str("-01"); + chrono::NaiveDate::parse_from_str(&tmp, "%Y-%m-%d").unwrap() }, + None => Utc::today().naive_utc() + }; + let date_range = DateRange::new(date_start, date_end); + + let mut earn_spend_v = Vec::new(); + for date in date_range { + let transactions = CsvFile::from_file("data/t.csv", ";", true); + let t : Vec<crate::banking::Transaction> ; + match transactions { + Ok(trans) => t = crate::banking::Transaction::from_sparkasse_csv_file(trans), + Err(e) => panic!("could not read file {:?}", e) + } + let result : Vec<_> = t.iter().filter(|x| x.date.month() == date.month()).collect(); + let mut earn = 0.0; + let mut spend = 0.0; + for r in &result { + if r.amount > 0.0 { + earn = earn + r.amount; + } else { + spend = spend + r.amount.abs(); + } + } + earn_spend_v.push(MonthEarnSpend { name : date.to_string(), earned : earn, spent : spend}); + } + let context = BalanceContext { account_name : String::from("Girokonto"), + months : earn_spend_v , date_start : date_start.to_string()[0..7].to_string(), + date_end : date_end.to_string()[0..7].to_string()}; + Template::render("balance", context) +} diff --git a/src/web_frontend/chart.rs b/src/web_frontend/chart.rs new file mode 100644 index 0000000..c5948fe --- /dev/null +++ b/src/web_frontend/chart.rs @@ -0,0 +1,61 @@ +use parsers::csv::CsvFile; +use banking::Account; +//use parsers::ini::IniFile; +use std::collections::HashMap; +use rocket_contrib::templates::Template; +use rocket::response::NamedFile; +use std::path::{PathBuf, Path}; +use rocket::request::Form; +use rocket::http::RawStr; +use regex::Regex; +use chrono::{NaiveDate, Utc}; +use chrono::Datelike; + +#[derive(Serialize)] +struct ChartContext { + account_name : String, + groups : HashMap<String, f32> +} + + +#[get("/chart")] +fn chart_handler() -> rocket_contrib::templates::Template { + // read group config + let chart_file = "data/giro"; + let chart_config = IniFile::from_file(chart_file); + let ini_file; + match chart_config { + Ok(file) => ini_file = file, + Err(e) => panic!("could not read group file {:?}", e) + } + let mut groups = HashMap::new(); + for (section_name, entries) in ini_file.sections { + let mut complete = 0.0; + println!("section name: {}", section_name); + for entrie in entries { + for val in entrie.values { + if entrie.name.is_empty() || val.is_empty() { + continue + } + println!("entrie is : {}", entrie.name); + let transactions = CsvFile::from_file("data/t.csv", ";", true); + let t : Vec<banking::Transaction> ; + match transactions { + Ok(trans) => t = banking::Transaction::from_sparkasse_csv_file(trans), + Err(e) => panic!("could not read file {:?}", e) + } + let re = Regex::new(&val).unwrap(); + let tmp = t.into_iter().filter(|transaction| + re.is_match(&transaction.sender_name) ) + .fold(0.0, |acc, x| acc + x.amount); + complete = complete + tmp.abs(); + } + } + groups.insert(section_name, complete); + // ALSO INSERT OTHER, AKA THE REST + } + let context = ChartContext { account_name : String::from("Girokonto"), + groups : groups }; + Template::render("chart", context) +} + diff --git a/src/web_frontend/mod.rs b/src/web_frontend/mod.rs new file mode 100644 index 0000000..8577065 --- /dev/null +++ b/src/web_frontend/mod.rs @@ -0,0 +1,29 @@ +pub mod transactions; +pub mod balance; +use parsers::csv::CsvFile; +use crate::banking::Account; +//use parsers::ini::IniFile; +use std::collections::HashMap; +use rocket_contrib::templates::Template; +use rocket::response::NamedFile; +use std::path::{PathBuf, Path}; +use rocket::request::Form; +use rocket::http::RawStr; +use regex::Regex; +use chrono::{NaiveDate, Utc}; +use chrono::Datelike; +/* + * Overview over all accounts, complete asset overview? + */ +#[get("/")] +pub fn account_handler() -> rocket_contrib::templates::Template { + let context : HashMap<u32, u32> = HashMap::new(); + Template::render("account", context) +} + +// allow always access +#[get("/static/<file..>")] +pub fn static_handler(file: PathBuf) -> Option<NamedFile> { + NamedFile::open(Path::new("static/").join(file)).ok() +} + diff --git a/src/web_frontend/transactions.rs b/src/web_frontend/transactions.rs new file mode 100644 index 0000000..417ca96 --- /dev/null +++ b/src/web_frontend/transactions.rs @@ -0,0 +1,101 @@ +use parsers::csv::CsvFile; +use crate::banking::Account; +//use parsers::ini::IniFile; +use std::collections::HashMap; +use rocket_contrib::templates::Template; +use rocket::response::NamedFile; +use std::path::{PathBuf, Path}; +use rocket::request::Form; +use rocket::http::RawStr; +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! + */ +#[derive(Serialize)] +struct TransactionContext { + transactions : Vec<crate::banking::Transaction>, + account_name : String, + filter : String, + date_start : String, + date_end : String +} + +#[derive(FromForm)] +pub struct TransactionFilter { + filter : String +} + +impl TransactionFilter { + pub fn apply_filter(&self, transactions : Vec<crate::banking::Transaction>) -> Vec<crate::banking::Transaction> { + let transactions = CsvFile::from_file("data/t.csv", ";", true); + let t : Vec<crate::banking::Transaction> ; + match transactions { + Ok(trans) => t = crate::banking::Transaction::from_sparkasse_csv_file(trans), + Err(e) => panic!("could not read file {:?}", e) + } + //self.filter.split("=").collect::<Vec<&str>>(); + let re = Regex::new(&self.filter).unwrap(); + let tmp = t.into_iter().filter(|transaction| re.is_match(&transaction.sender_name) || re.is_match(&transaction.reference) ).collect(); + tmp + + } +} + +#[post("/transactions?<start>&<end>", data= "<transaction_filter>")] +pub fn transaction_handler_post(start : Option<&RawStr>, end : Option<&RawStr>, + transaction_filter : Form<TransactionFilter>) -> rocket_contrib::templates::Template { + let date_start = match start { + Some(s) => { let mut tmp = s.to_string(); + tmp.push_str("-01"); + chrono::NaiveDate::parse_from_str(&tmp, "%Y-%m-%d").unwrap() }, + None => Utc::today().naive_utc() + }; + let date_end = match end { + Some(s) => { let mut tmp = s.to_string(); + tmp.push_str("-01"); + chrono::NaiveDate::parse_from_str(&tmp, "%Y-%m-%d").unwrap() }, + None => Utc::today().naive_utc() + }; + let input : TransactionFilter = transaction_filter.into_inner(); + let tmp = Vec::new(); + let ft = input.apply_filter(tmp); + let context = TransactionContext { transactions : ft, account_name : String::from("TEST"), + filter : input.filter, date_start : date_start.to_string(), + date_end : date_end.to_string()}; + Template::render("transaction", context) +} + +#[get("/transactions?<start>&<end>")] +pub fn transaction_handler(start : Option<&RawStr>, end : Option<&RawStr>) -> rocket_contrib::templates::Template { + let date_start = match start { + Some(s) => { let mut tmp = s.to_string(); + tmp.push_str("-01"); + chrono::NaiveDate::parse_from_str(&tmp, "%Y-%m-%d").unwrap() }, + None => Utc::today().naive_utc() + }; + let date_end = match end { + Some(s) => { let mut tmp = s.to_string(); + tmp.push_str("-01"); + chrono::NaiveDate::parse_from_str(&tmp, "%Y-%m-%d").unwrap() }, + None => Utc::today().naive_utc() + }; + let transactions = CsvFile::from_file("data/t.csv", ";", true); + let t : Vec<crate::banking::Transaction> ; + match transactions { + Ok(trans) => t = crate::banking::Transaction::from_sparkasse_csv_file(trans), + Err(e) => panic!("could not read file {:?}", e) + } + let context = TransactionContext { transactions: t, account_name : String::from("Girokonto"), + filter : String::from(""), date_start : date_start.to_string()[0..7].to_string(), + date_end : date_end.to_string()[0..7].to_string()}; + Template::render("transaction", context) +} |
