From a361eb833f516befe79b45a8b6ed3162a21bc06a Mon Sep 17 00:00:00 2001 From: jvech Date: Sun, 28 Apr 2024 22:53:50 -0500 Subject: add: view subcommand implemented --- src/cli.rs | 12 ++++++----- src/database.rs | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- src/main.rs | 27 ++++++++++++------------ 3 files changed, 83 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/cli.rs b/src/cli.rs index 0bd0a78..38ac648 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -3,7 +3,7 @@ use clap::{Subcommand, Parser, ValueHint}; use std::env; #[derive(Debug, Parser)] -#[command(version, about, long_about = None)] +#[command(version, about = "A simple debt manager", long_about = None)] pub struct Cli { /// file path where data is stored [default: /// $XDG_DATA_HOME/debt/debt.db @@ -24,7 +24,7 @@ pub enum Commands { person: String, /// amount of money - amount: i32, + amount: u32, /// additional notes note: Option, @@ -34,13 +34,15 @@ pub enum Commands { payment: bool }, + /// View Registered data View { + /// Filter history data (only works with -H) filter: Option, /// View register history - #[arg(short='H', long)] + #[arg(short='H', long, conflicts_with = "total")] history: bool, /// Transaction accumulation by person - #[arg(short, long)] + #[arg(short, long, conflicts_with = "history")] total: bool }, @@ -70,7 +72,7 @@ fn load_datapath(cli: &mut Cli) { }) }).or_else(|| { if let Ok(home) = env::var("HOME") { - let fallback = PathBuf::from(&home).join(".debt.db"); + let fallback = PathBuf::from(&home).join(".cache.db"); if fallback.exists() { return Some(fallback) } diff --git a/src/database.rs b/src/database.rs index 8321723..14f04d9 100644 --- a/src/database.rs +++ b/src/database.rs @@ -1,5 +1,4 @@ -use rusqlite::Connection; -use rusqlite::Result; +use rusqlite::{Connection, Result, Rows, Statement}; use rusqlite::config::DbConfig::{*}; use chrono::Utc; use std::path::PathBuf; @@ -46,6 +45,68 @@ impl Database { Ok(()) } + pub fn view_history(filepath: &PathBuf, filter: Option) -> Result<()> { + let conn = Connection::open(filepath)?; + let mut hist_query: String = " + SELECT date(r.register_date, 'auto'), a.name, r.amount + FROM Registers r + INNER JOIN Agents a + ON a.id = r.agent_id + ".to_owned(); + + let mut stmt: Statement; + let mut regs: Rows; + + match filter { + Some(name) => { + hist_query.push_str("WHERE name = ?1"); + stmt = conn.prepare(hist_query.as_str())?; + regs = stmt.query([name])?; + }, + None => { + stmt = conn.prepare(hist_query.as_str())?; + regs = stmt.query([])?; + } + }; + let mut total = 0; + println!("+{:-<10}+{:-<20}+{:-<10}+", "", "", ""); + println!("|{:^10}|{:^20}|{:^10}|", "date", "name", "amount"); + println!("+{:-<10}+{:-<20}+{:-<10}+", "", "", ""); + while let Some(row) = regs.next()? { + let date: String = row.get(0)?; + let name: String = row.get(1)?; + let amount: i32 = row.get(2)?; + + println!("|{}|{:>20}|{:>10}|", date, name, amount); + total += amount; + } + println!("+{:-<10}+{:-<20}+{:-<10}+", "", "", ""); + println!("|{:^10}{:>32}|", "total", total); + println!("+{:-<10}+{:-<20}+{:-<10}+", "", "", ""); + Ok(()) + } + + pub fn view_total(filepath: &PathBuf) -> Result<()> { + let conn = Connection::open(filepath)?; + let mut stmt = conn.prepare(" + SELECT a.name, sum(r.amount) + FROM Registers r + INNER JOIN Agents a + ON a.id = r.agent_id + GROUP BY a.name")?; + let mut agents = stmt.query([])?; + println!("+{:->20}+{:->11}+", "", ""); + println!("|{:^20}| {:^10}|", "name", "amount"); + println!("+{:->20}+{:->11}+", "", ""); + while let Some(row) = agents.next()? { + let name: String = row.get(0)?; + let amount: i32 = row.get(1)?; + println!("|{:>20}| {:>10}|", name, amount); + } + println!("+{:->20}+{:->11}+", "", ""); + Ok(()) + } + pub fn init_database(filepath: &PathBuf) -> Result<()> { let conn = Connection::open(filepath).expect("Database file creation Error"); conn.execute(" diff --git a/src/main.rs b/src/main.rs index 8ef62b3..be23ac3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -22,26 +22,25 @@ fn main() -> Result<()> { } }, Commands::Register {person, amount, note, payment} => { - let register = Database::new(person, amount, note, !payment); - if let Some(datapath) = cli.database_path { - register.add_register(&datapath)?; - } else { - panic!("database file not found"); - } + let register = Database::new(person, amount as i32, note, !payment); + let datapath = cli.database_path.unwrap(); + register.add_register(&datapath)?; }, Commands::View {history, filter, total} => { - println!("{}", filter.unwrap_or(String::from("None"))); - println!("{}", history); - println!("{}", total); + let datapath = cli.database_path.expect("database path not found"); + + match (history, total) { + (true, false) => Database::view_history(&datapath, filter)?, + (false, true) => Database::view_total(&datapath)?, + (false, false) => Database::view_total(&datapath)?, + (true, true) => unreachable!() + } }, Commands::Add {name} => { let register = Database::new(name, 0, None, false); - if let Some(datapath) = cli.database_path { - register.add_agent(&datapath)?; - } else { - panic!("database file not found"); - } + let datapath = cli.database_path.unwrap(); + register.add_agent(&datapath)?; } }; Ok(()) -- cgit v1.2.3-70-g09d2