/* * advotracker - Hotline tackingtool for Advocats * * Copyright 2020 Ralf Zerres * SPDX-License-Identifier: (0BSD or MIT) */ use chrono::{Local, DateTime}; use locales::t; use serde::Deserialize; use std::env; use std::{error::Error, process}; use tracing::{debug, trace, Level}; //use crate::db::data::CsvImportRecord; // include modules mod parse_args; /// respect environment variables set in .env files /// located in the current call directory /// this is primarily used in testing scenarios (eg. debugging) #[derive(Debug, Deserialize)] struct Environment { test_lang: String, log: String, } #[derive(Debug, Deserialize)] pub struct CsvImportRecord { // dion => Allianz Dion: 1-9 // policy_code => Policy Typ: "AS" // policy_number => Versicherungsscheinnummer: "1515735810" pub dion: String, pub policy_code: String, pub policy_number: String, } #[derive(Default, Debug, Deserialize)] pub struct RecordList { records: Vec } /// export as csv format /// https://docs.rs/csv/1.1.3/csv/cookbook/index.html /// https://blog.burntsushi.net/csv/ fn export(p: &mut String, lang: &String) -> Result<(), Box> { use std::fs::File; use std::path::Path; //use std::ffi::OsStr; let mut res = t!("csv_import.started", lang); let mut state = t!("state.started", lang); trace!(target: "csv-test", process = ?res, state = ?state); // Note: slash syntax also works on Windows! let path = Path::new(p); // only create files with a '.txt' extensions //let extension = path.extension(); // match extension { // //Some(String) => println!("file extension ok!"), // //_ => extension = OsStr::new("txt") // _ => println!("got file extension {:?}", extension) // }; // open the file let file = File::open(path)?; trace!(target: "csv-export", extension = ?path.extension(), file = ?file); state = t!("state.finished", lang); res = t!("csv_import.finished", lang); trace!(target: "csv-test", process = ?res, state = ?state); Ok(()) } /// import from csv format /// https://docs.rs/csv/1.1.3/csv/cookbook/index.html /// https://blog.burntsushi.net/csv/ fn import(p: &mut String, lang: &String) -> Result> { use std::fs::File; use std::path::Path; use std::ffi::OsStr; let mut res = t!("csv_import.started", lang); let mut state = t!("state.started", lang); let dt_start: DateTime = Local::now(); trace!(target: "csv-test", process = ?res, state = ?state, date_start = ?dt_start.to_string()); // Note: slash syntax also workd on Windows! let path = Path::new(p); // must be a readable file trace!(target: "csv-test", path = ?path); assert_eq!(path.is_file(), true); // only accept files with '.txt' extensions let extension = path.extension(); assert_eq!(extension, Some(OsStr::new("txt"))); // open the file let file = File::open(path)?; trace!(target: "csv-test", extension = ?extension, file = ?file); // Build the CSV reader and iterate over each record. let mut csv_reader = csv::ReaderBuilder::new() .has_headers(false) .delimiter(b' ') .comment(Some(b'#')) //.has_headers(true) //.from_reader(io::stdin()); //.from_path(path); .from_reader(file); { // We nest this call in its own scope because of lifetimes. let headers = csv_reader.headers()?; trace!(target: "csv-test", header = ?headers); } //for result in csv_reader.records() { let mut count = 0; for result in csv_reader.deserialize() { // The iterator yields Result, so we check the // error here. //let record = result?; let _record: CsvImportRecord = result?; //println!("{:?}", record); count +=1; } let dt_end: DateTime = Local::now(); let duration = dt_end.signed_duration_since(dt_start); println!("Duration: {:#?}", duration); //let seconds = duration.secs; //println!("Seconds: {:#?}", seconds); trace!(target: "csv-test", record_count = ?count, duration = ?duration); state = t!("state.finished", lang); res = t!("csv_import.finished", lang); trace!(target: "csv-test", process = ?res, state = ?state, date_stop = ?dt_end.to_string()); //Ok(count, duration.seconds()) Ok(count) } fn main() -> Result<(), Box> { use dotenv::dotenv; use parse_args::parse_args; //use std::process; //use std::sync::Arc; use tracing_subscriber::fmt; use viperus::Viperus; //static DEFAULT_FILTER: &str = concat!(module_path!(), "=", "trace"); // initialize the tracing subsystem // a drop in replacement for classical logging // reference: https://tokio.rs/blog/2019-08-tracing/ let span = tracing::span!(Level::TRACE, "csv-test"); let _enter = span.enter(); let subscriber = fmt::Subscriber::builder() .with_env_filter("trace") //.with_max_level(tracing::Level::DEBUG) .finish(); // initialize logger //env_logger::init(); //info!("Commencing the import Test-Run!"); tracing::subscriber::with_default(subscriber, || { // get system environment let mut lang = env::var("LANG").unwrap_or("en".to_string()); let mut res = t!("parse.environment", lang); let mut state = t!("state.started", lang); trace!(target: "csv-test", message = ?res, state = ?state); //debug!(message = ?res, state = ?state); trace!(target: "csv-test", environment = "system", lang = ?lang); // testing environment: read from .env file dotenv().ok(); match envy::from_env::() { Ok(environment) => { if environment.test_lang != lang { lang = environment.test_lang; } }, Err(e) => { debug!(target: "csv-test", "{}", e); } } // how to handle unumplemented lang resources?? res = t!("parse.environment", lang); trace!(target: "csv-test", environment = "envy", lang = ?lang); state = t!("state.finished", lang); trace!(target: "csv-test", message = ?res, state = ?state); // initialize viperus structure let mut v = Viperus::new(); // parse commandline arguments res = t!("parse.arguments", lang); state = t!("state.started", lang); trace!(target: "csv-test", process = ?res, state = ?state); let _ = parse_args(&mut v); state = t!("state.finished", lang); trace!(target: "csv-test", process = ?res, state = ?state); //trace!(target: "Viperus", "Config results: {:?}", v); // main tasks res = t!("main.started", lang); state = t!("state.started", lang); trace!(target: "csv-test", process = ?res, state = ?state); // importing policy code elements from csv-file let mut csv_import_path = v.get::("import_file").unwrap(); match import(&mut csv_import_path, &lang) { Ok(count) => { println!("Imported {:?} records", count); } Err(err) => { println!("error running Csv-Test: {}", err); process::exit(1); } } // export policy code elements to csv-file let mut csv_export_path = v.get::("export_file").unwrap(); match export(&mut csv_export_path, &lang) { Ok(count) => { println!("Exported {:?} records", count); } Err(err) => { println!("error running CSV-Export: {}", err); process::exit(1); } } state = t!("state.finished", lang); res = t!("main.finished", lang); trace!(target: "csv-test", process = ?res, state = ?state); }); Ok(()) }