aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjvech <jmvalenciae@unal.edu.co>2024-06-19 09:15:10 -0500
committerjvech <jmvalenciae@unal.edu.co>2024-06-19 09:15:10 -0500
commit4b14f87cc80e7cfb78480644281022296973bc66 (patch)
tree74a2cf5fba8557730837f1d681ea1d203b8775f7
parent821eeb0263725d33cbb5d1a044ca593d5959031f (diff)
feat: agent deletion and name update done
-rw-r--r--Cargo.lock7
-rw-r--r--Cargo.toml3
-rw-r--r--README.md16
-rw-r--r--src/cli.rs16
-rw-r--r--src/database.rs70
-rw-r--r--src/main.rs12
6 files changed, 115 insertions, 9 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 288083b..0ccb97d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -200,6 +200,7 @@ dependencies = [
"confy",
"rusqlite",
"serde",
+ "text_io",
"xdg",
]
@@ -481,6 +482,12 @@ dependencies = [
]
[[package]]
+name = "text_io"
+version = "0.1.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d5f0c8eb2ad70c12a6a69508f499b3051c924f4b1cfeae85bfad96e6bc5bba46"
+
+[[package]]
name = "thiserror"
version = "1.0.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index 12f5ca9..6781e61 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "debt"
-version = "0.2.2"
+version = "1.0.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -11,4 +11,5 @@ clap = { version = "4.5.4", features = ["derive", "env", "default"] }
confy = "0.6.1"
rusqlite = "0.31.0"
serde = { version = "1.0.197", features = ["serde_derive"] }
+text_io = "0.1.12"
xdg = "2.5.2"
diff --git a/README.md b/README.md
index 2f3b57f..159733d 100644
--- a/README.md
+++ b/README.md
@@ -11,7 +11,7 @@ Commands:
init Initialize Database
register Register a transaction
view View Registered data
- add Add a new agent to lend or pay
+ agent Add, update or remove an agent
help Print this message or the help of the given subcommand(s)
Options:
@@ -36,7 +36,7 @@ CREATE TABLE Registers (
register_date INTEGER NOT NULL,
amount INTEGER NOT NULL,
note TEXT,
- FOREIGN KEY(agent_id) REFERENCES Agents(id)
+ FOREIGN KEY(agent_id) REFERENCES Agents(id) ON DELETE CASCADE
)
```
@@ -48,7 +48,17 @@ debt init
Add a new debtor:
```
-debt add 'Jane Doe'
+debt agent -a 'Jane Doe'
+```
+
+Delete a created agent
+```
+debt agent -d 'Jane Doe'
+```
+
+Update a created agent:
+```
+debt agent 'Jane Doe' -u 'Joe Doe'
```
Borrow 1000 (dollars, euros or whatever) to Jane Doe:
diff --git a/src/cli.rs b/src/cli.rs
index 38ac648..61b3d39 100644
--- a/src/cli.rs
+++ b/src/cli.rs
@@ -46,9 +46,21 @@ pub enum Commands {
total: bool
},
- /// Add a new agent to lend or pay
- Add {
+ /// Add, update or remove an agent
+ Agent {
name: String,
+
+ /// Add a new agent (default)
+ #[arg(short,long)]
+ add: bool,
+
+ /// Delete a registered agent
+ #[arg(short,long, conflicts_with_all = ["add", "update"])]
+ delete: bool,
+
+ /// Update a registered agent
+ #[arg(short,long, conflicts_with_all = ["add", "delete"], value_name = "NEW_NAME")]
+ update: Option<String>
},
}
diff --git a/src/database.rs b/src/database.rs
index 8752255..da514ef 100644
--- a/src/database.rs
+++ b/src/database.rs
@@ -2,6 +2,8 @@ use rusqlite::{Connection, Result, Rows, Statement};
use rusqlite::config::DbConfig::{*};
use chrono::Utc;
use std::path::PathBuf;
+use text_io::scan;
+use std::io::{stdout, Write};
pub struct Database {
date: i64,
@@ -23,6 +25,12 @@ impl Database {
pub fn add_register(&self, filepath: &PathBuf) -> Result<()> {
let conn = Connection::open(filepath)?;
conn.set_db_config(SQLITE_DBCONFIG_ENABLE_FKEY, true)?;
+
+ if !&self.check_agent_exists(&conn)? {
+ println!("The Agent '{}' is not registered in the database", &self.person);
+ return Ok(());
+ }
+
conn.execute("
INSERT INTO Registers (agent_id, register_date, amount, note)
VALUES (
@@ -45,6 +53,38 @@ impl Database {
Ok(())
}
+ pub fn update_agent(&self, filepath: &PathBuf, new_name: String) -> Result <()> {
+ let conn = Connection::open(filepath)?;
+
+ if !&self.check_agent_exists(&conn)? {
+ println!("The Agent '{}' is not registered in the database", &self.person);
+ return Ok(());
+ }
+
+ conn.execute("UPDATE Agents SET name=?1 WHERE name=?2", (&new_name, &self.person))?;
+
+ println!("Agent '{}' was updated to '{}'", &self.person, &new_name);
+ Ok(())
+ }
+
+ pub fn delete_agent(&self, filepath: &PathBuf) -> Result<()>{
+ let conn = Connection::open(filepath)?;
+ let prompt = format!("The Agent '{}' will be removed are you sure?", &self.person);
+
+ if !&self.check_agent_exists(&conn)? {
+ println!("The Agent '{}' is not registered in the database", &self.person);
+ return Ok(());
+ }
+ if !Database::ask_user_confirmaton(prompt.as_str()) {
+ println!("Operation aborted");
+ return Ok(());
+ }
+ conn.set_db_config(SQLITE_DBCONFIG_ENABLE_FKEY, true)?;
+ conn.execute("DELETE FROM Agents WHERE name=?1", (&self.person,))?;
+ println!("agent '{}' deleted successfully", &self.person);
+ Ok(())
+ }
+
pub fn view_history(filepath: &PathBuf, filter: Option<String>) -> Result<()> {
let conn = Connection::open(filepath)?;
let mut hist_query: String = "
@@ -123,9 +163,37 @@ impl Database {
register_date INTEGER NOT NULL,
amount INTEGER NOT NULL,
note TEXT,
- FOREIGN KEY(agent_id) REFERENCES Agents(id))", ())
+ FOREIGN KEY(agent_id) REFERENCES Agents(id)
+ ON DELETE CASCADE)", ())
.expect("SQL initialization error");
println!("'{}' database created", &filepath.display());
Ok(())
}
+
+ fn check_agent_exists(&self, conn: &Connection) -> Result<bool> {
+ let mut stmt = conn.prepare("SELECT name FROM Agents WHERE name=?1")?;
+ let mut reg = stmt.query([&self.person])?;
+
+ if let Some(_) = reg.next()? {
+ Ok(true)
+ } else {
+ Ok(false)
+ }
+ }
+
+ fn ask_user_confirmaton(prompt: &str) -> bool {
+ let mut input: String;
+ let complete_prompt = format!("{} (Y/n)", prompt);
+ loop {
+ print!("{}: ", complete_prompt);
+ stdout().flush().unwrap();
+ scan!("{}\n", input);
+
+ match input.to_lowercase().as_str() {
+ "y"|"" => return true,
+ "n" => return false,
+ _ => println!("Invalid input")
+ }
+ }
+ }
}
diff --git a/src/main.rs b/src/main.rs
index be23ac3..8a4f338 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -26,6 +26,7 @@ fn main() -> Result<()> {
let datapath = cli.database_path.unwrap();
register.add_register(&datapath)?;
},
+
Commands::View {history, filter, total} => {
let datapath = cli.database_path.expect("database path not found");
@@ -37,10 +38,17 @@ fn main() -> Result<()> {
}
},
- Commands::Add {name} => {
+ Commands::Agent {name, add, delete, update} => {
let register = Database::new(name, 0, None, false);
let datapath = cli.database_path.unwrap();
- register.add_agent(&datapath)?;
+
+ match (add, delete, update) {
+ (true, false, None) => register.add_agent(&datapath)?,
+ (false, true, None) => register.delete_agent(&datapath)?,
+ (false, false, None) => register.add_agent(&datapath)?,
+ (false, false, Some(new_name)) => register.update_agent(&datapath, new_name)?,
+ (_, _, _) => unreachable!()
+ }
}
};
Ok(())
Feel free to download, copy and edit any repo