/// simple typed helper enums mod simple_enums; mod transaction; fn main() { use chrono::Datelike; use encoding::types::Encoding; use prettytable::{cell, format, row, Cell, Row, Table}; use std::collections::BTreeMap; for i in std::env::args().skip(1) { println!("F = {}", i); let fh = readfilez::read_from_file(std::fs::File::open(i)).expect("unable to open file"); let dat = encoding::all::ISO_8859_1 .decode(&*fh, encoding::types::DecoderTrap::Replace) .expect("got invalid latin-1 data"); std::mem::drop(fh); let mut rdr = csv::ReaderBuilder::new() .delimiter(b';') .flexible(true) .has_headers(false) .from_reader(dat.as_bytes()); let mut recsit = rdr.records().skip(8); assert_eq!( recsit.next().unwrap().unwrap(), vec![ "Buchungstag", "Valuta", "Auftraggeber/Zahlungsempfänger", "Empfänger/Zahlungspflichtiger", "Konto-Nr.", "IBAN", "BLZ", "BIC", "Vorgang/Verwendungszweck", "Kundenreferenz", "Währung", "Umsatz", " " ] ); let mut tmp = transaction::TransactionColl::new(); for result in recsit { let record = result.expect("got invalid line"); let record_bak = record.clone(); let pres: Result = std::convert::TryInto::try_into(record); match pres { Ok(tl) => tmp.push(tl), Err(transaction::ParseError::Finalizer) => break, Err(x) => panic!("got error '{}' @ {:?}", x, record_bak), } } let dat = tmp.finish(); let mut accu = BTreeMap::< (i32, bool, string_cache::DefaultAtom), (usize, transaction::TransactionValue), >::new(); let mut i_skipped = 0usize; for i in dat { if i.direction != simple_enums::TransactionDirection::Haben || i.waehrung != simple_enums::Waehrung::EUR || i.p_other.is_empty() || i.p_other.find(" ZINS BIS ").is_some() { i_skipped += 1; continue; } let mut ent = accu .entry(( i.d_buchungs.year(), i.d_buchungs.month() > 6, i.p_other.clone(), )) .or_default(); ent.0 += 1; ent.1 += i.umsatz; } println!("skipped {} entries", i_skipped); if accu.is_empty() { continue; } let mut table = Table::new(); table.set_format( format::FormatBuilder::new() .column_separator('│') .borders('│') .separator( format::LinePosition::Top, format::LineSeparator::new('─', '┬', '┌', '┐'), ) .separator( format::LinePosition::Bottom, format::LineSeparator::new('─', '┴', '└', '┘'), ) .padding(1, 1) .build(), ); table.add_row(row!["Jahr", "Einzahler", "Zahlungen", "Summe"]); for (k, v) in accu { table.add_row(Row::new(vec![ Cell::new(&format!("{} {}.", k.0, if k.1 { 2 } else { 1 })), Cell::new(&k.2), Cell::new(&v.0.to_string()), Cell::new(&v.1.to_string()), ])); } table.printstd(); } }