use crate::entities::*; use chrono::DateTime; use sqlite::{Connection, State}; pub fn setup(con: &Connection) { let _ = con.execute( " CREATE TABLE IF NOT EXISTS Accounts ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, type INTEGER NOT NULL ); CREATE TABLE IF NOT EXISTS TransactionTypes ( id INTEGER PRIMARY KEY AUTOINCREMENT, description TEXT NOT NULL ); CREATE TABLE IF NOT EXISTS Transactions ( id INTEGER PRIMARY KEY AUTOINCREMENT, account_id INTEGER NOT NULL, type_id INTEGER NOT NULL, amount FLOAT NOT NULL, date INTEGER NOT NULL, description TEXT, 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 get_account_total(id: i64, con: &Connection) -> f64 { let query = "SELECT SUM(amount) as total FROM Transactions WHERE account_id = ?"; let mut statement = con.prepare(query).unwrap(); statement.bind((1, id)).unwrap(); if let Ok(State::Row) = statement.next() { return statement.read::("total").unwrap(); } else { return 0.0; } } 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(), )); } 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; } pub fn upsert_transaction(con: &Connection, tr: Transaction) -> Transaction { let query; if tr.get_id() == 0 { query = "INSERT INTO Transactions (account_id, type_id, amount, date, description) VALUES (?, ?, ?, ?, ?) RETURNING id;"; } else { query = "UPDATE Transactions SET account_id = ?, type_id = ?, amount = ?, date = ?, description = ? WHERE id = ? RETURNING id;"; } let mut statement = con.prepare(query).unwrap(); statement.bind((1, tr.get_account().get_id())).unwrap(); statement.bind((2, tr.get_type().get_id())).unwrap(); statement.bind((3, tr.get_amount())).unwrap(); statement.bind((4, tr.get_date().timestamp())).unwrap(); statement.bind((5, &tr.get_desc() as &str)).unwrap(); if tr.get_id() != 0 { statement.bind((6, tr.get_id())).unwrap(); } let id; if let Ok(State::Row) = statement.next() { id = statement.read::("id").unwrap(); } else { id = 0; } return Transaction::new( id, tr.get_account().get_id(), tr.get_amount(), tr.get_date(), tr.get_desc(), tr.get_type().get_id(), con, ); } pub fn get_transaction(con: &Connection, id: i64) -> Transaction { let query = "SELECT * FROM Transactions WHERE id = ?"; let mut statement = con.prepare(query).unwrap(); statement.bind((1, id)).unwrap(); if let Ok(State::Row) = statement.next() { return Transaction::new( statement.read::("id").unwrap(), statement.read::("account_id").unwrap(), statement.read::("amount").unwrap(), DateTime::from_timestamp(statement.read::("date").unwrap(), 0).unwrap(), statement.read::("description").unwrap(), statement.read::("type_id").unwrap(), con, ); } else { return Transaction::new_empty(); } } pub fn get_account_transactions(con: &Connection, ac_id: i64) -> Vec { let query = "SELECT * FROM Transactions WHERE account_id = ?"; let mut statement = con.prepare(query).unwrap(); statement.bind((1, ac_id)).unwrap(); let mut vec = Vec::::new(); while let Ok(State::Row) = statement.next() { vec.push(Transaction::new( statement.read::("id").unwrap(), statement.read::("account_id").unwrap(), statement.read::("amount").unwrap(), DateTime::from_timestamp(statement.read::("date").unwrap(), 0).unwrap(), statement.read::("description").unwrap(), statement.read::("type_id").unwrap(), con, )); } return vec; } pub fn get_transactions(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(Transaction::new( statement.read::("id").unwrap(), statement.read::("account_id").unwrap(), statement.read::("amount").unwrap(), DateTime::from_timestamp(statement.read::("date").unwrap(), 0).unwrap(), statement.read::("description").unwrap(), statement.read::("type_id").unwrap(), con, )); } return vec; }