diff --git a/.gitignore b/.gitignore index ab951f8..91567fc 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,4 @@ Cargo.lock # and can be added to the global gitignore or merged into this file. For a more nuclear # option (not recommended) you can uncomment the following to ignore the entire idea folder. #.idea/ +*.db diff --git a/src/data_layer.rs b/src/data_layer.rs index 750c0a3..4c89efe 100644 --- a/src/data_layer.rs +++ b/src/data_layer.rs @@ -1,5 +1,5 @@ -use sqlite::{Connection, State}; use crate::entities::*; +use sqlite::{Connection, State}; pub fn setup(con: &Connection) { let _ = con.execute( @@ -25,19 +25,127 @@ pub fn setup(con: &Connection) { FOREIGN KEY(account_id) REFERENCES Accounts(id), FOREIGN KEY(type_id) REFERENCES TransactionTypes(id) ); - "); - + ", + ); +} + +pub fn upsert_account(con: &Connection, ac: Account) -> Account { + let query; + let ac_type = ac.get_ac_type() as i64; + if ac.get_id() == 0 { + query = "INSERT INTO Accounts (name, type) VALUES (?, ?) RETURNING id;"; + } else { + query = "UPDATE Accounts SET name = ?, type = ? WHERE id = ? RETURNING id;"; + } + + let mut statement = con.prepare(query).unwrap(); + statement.bind((1, &ac.get_name() as &str)).unwrap(); + statement.bind((2, ac_type)).unwrap(); + + if ac.get_id() != 0 { + statement.bind((3, ac.get_id())).unwrap(); + } + + let id; + if let Ok(State::Row) = statement.next() { + id = statement.read::("id").unwrap(); + } else { + id = 0; + } + + return Account::new(id, ac.get_name(), ac_type.try_into().unwrap()); +} + +pub fn get_account(con: &Connection, id: i64) -> Account { + let query = "SELECT * FROM Accounts WHERE id = ?"; + let mut statement = con.prepare(query).unwrap(); + statement.bind((1, id)).unwrap(); + + if let Ok(State::Row) = statement.next() { + return Account::new( + statement.read::("id").unwrap(), + statement.read::("name").unwrap(), + statement + .read::("type") + .unwrap() + .try_into() + .unwrap(), + ); + } else { + return Account::new(0, "".to_string(), AccountType::Cash); + } } -//pub fn - pub fn get_accounts(con: &Connection) -> Vec { let query = "SELECT * FROM Accounts"; let mut statement = con.prepare(query).unwrap(); let mut vec = Vec::::new(); while let Ok(State::Row) = statement.next() { - vec.push(Account::new(statement.read::("id").unwrap(), statement.read::("name").unwrap(), statement.read::("type").unwrap().try_into().unwrap())); + vec.push(Account::new( + statement.read::("id").unwrap(), + statement.read::("name").unwrap(), + statement + .read::("type") + .unwrap() + .try_into() + .unwrap(), + )); + } + + return vec; +} + +pub fn upsert_transaction_type(con: &Connection, tt: TransactionType) -> TransactionType { + let query; + if tt.get_id() == 0 { + query = "INSERT INTO TransactionTypes (description) VALUES (?) RETURNING id;"; + } else { + query = "UPDATE TransactionTypes SET description = ? WHERE id = ? RETURNING id;"; + } + + let mut statement = con.prepare(query).unwrap(); + statement.bind((1, &tt.get_description() as &str)).unwrap(); + + if tt.get_id() != 0 { + statement.bind((2, tt.get_id())).unwrap(); + } + + let id; + if let Ok(State::Row) = statement.next() { + id = statement.read::("id").unwrap(); + } else { + id = 0; + } + + return TransactionType::new(id, tt.get_description()); +} + +pub fn get_transaction_type(con: &Connection, id: i64) -> TransactionType { + let query = "SELECT * FROM TransactionTypes WHERE id = ?"; + let mut statement = con.prepare(query).unwrap(); + statement.bind((1, id)).unwrap(); + + if let Ok(State::Row) = statement.next() { + return TransactionType::new( + statement.read::("id").unwrap(), + statement.read::("description").unwrap(), + ); + } else { + return TransactionType::new(0, "".to_string()); + } +} + +pub fn get_transaction_types(con: &Connection) -> Vec { + let query = "SELECT * FROM TransactionTypes"; + let mut statement = con.prepare(query).unwrap(); + let mut vec = Vec::::new(); + + while let Ok(State::Row) = statement.next() { + vec.push(TransactionType::new( + statement.read::("id").unwrap(), + statement.read::("description").unwrap(), + )); } return vec; diff --git a/src/entities/account.rs b/src/entities/account.rs index d81e0e1..065305f 100644 --- a/src/entities/account.rs +++ b/src/entities/account.rs @@ -1,26 +1,35 @@ use std::convert::TryFrom; pub struct Account { id: i64, - pub name: String, + name: String, ac_type: AccountType, } -impl Account{ +impl Account { pub fn new(id: i64, name: String, ac_type: AccountType) -> Self { Account { id: id, name: name, ac_type: ac_type, - } + } + } + pub fn get_id(&self) -> i64 { + return self.id; + } + pub fn get_name(&self) -> String { + return self.name.clone(); + } + pub fn get_ac_type(&self) -> AccountType { + return AccountType::try_from(self.ac_type as i64).unwrap(); } } -pub enum AccountType{ - Cash, +#[derive(Copy, Clone)] +pub enum AccountType { + Cash = 1, Assets, } - impl TryFrom for AccountType { type Error = (); diff --git a/src/entities/transaction.rs b/src/entities/transaction.rs index 9b45ab8..a3925ba 100644 --- a/src/entities/transaction.rs +++ b/src/entities/transaction.rs @@ -1,5 +1,5 @@ -use chrono::{DateTime, Utc}; use crate::entities::Account; +use chrono::{DateTime, Utc}; pub struct Transaction { id: i32, @@ -13,7 +13,22 @@ pub struct Transaction { tr_type: TransactionType, } -pub struct TransactionType{ - id: i32, +pub struct TransactionType { + id: i64, description: String, } + +impl TransactionType { + pub fn new(id: i64, desc: String) -> Self { + TransactionType { + id: id, + description: desc, + } + } + pub fn get_id(&self) -> i64 { + return self.id; + } + pub fn get_description(&self) -> String { + return self.description.clone(); + } +} diff --git a/src/main.rs b/src/main.rs index 7b55bdd..151daad 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,8 @@ mod data_layer; mod entities; use sqlite::Connection; +use crate::entities::Account; + fn main() { println!("Hello, world!"); @@ -14,8 +16,10 @@ fn main() { }; data_layer::setup(&connection); + let mut account = Account::new(0, "test".to_string(), entities::AccountType::Cash); + account = data_layer::upsert_account(&connection, account); let accounts = data_layer::get_accounts(&connection); for ac in accounts.iter() { - println!("name: {}", ac.name) + println!("name: {}", ac.get_name()) } }