summaryrefslogtreecommitdiff
path: root/src/web_frontend/transactions.rs
blob: f6d65afe6b8af5df50d5d195a2e063451f37ca60 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
use parsers::csv::CsvFile;
use crate::banking::account::Account;
use crate::banking::asset::Asset;
//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::account::Transaction>,
	account_name : String,
	filter : String,
	date_start : String,
	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>,
			   filter : Option<&RawStr>) -> rocket_contrib::templates::Template {
	let account_name = account.to_string();
	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 transaction_filter = match filter {
		Some(s) => s.to_string(),
		None => String::from("")
	};
	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);
    let acc;
    match transactions {
	    Some(trans) => acc = trans,
	    None => panic!("could not read file")
    }
    let t = acc.transactions;
    // apply parameters
    // apply date filters
	let date_range = crate::web_frontend::util::DateRange::new(date_start, date_end);	
	let mut t_filtered = Vec::new();
	for date in date_range {
		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);
	}

   // apply filter
    let ft = 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(),
    			date_end : date_end.to_string()[0..7].to_string()};
    Template::render("transaction", context)
}