269 lines
8.5 KiB
Rust
269 lines
8.5 KiB
Rust
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::<i64, _>("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::<i64, _>("id").unwrap(),
|
|
statement.read::<String, _>("name").unwrap(),
|
|
statement
|
|
.read::<i64, _>("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::<f64, _>("total").unwrap();
|
|
} else {
|
|
return 0.0;
|
|
}
|
|
}
|
|
|
|
pub fn get_accounts(con: &Connection) -> Vec<Account> {
|
|
let query = "SELECT * FROM Accounts";
|
|
let mut statement = con.prepare(query).unwrap();
|
|
let mut vec = Vec::<Account>::new();
|
|
|
|
while let Ok(State::Row) = statement.next() {
|
|
vec.push(Account::new(
|
|
statement.read::<i64, _>("id").unwrap(),
|
|
statement.read::<String, _>("name").unwrap(),
|
|
statement
|
|
.read::<i64, _>("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::<i64, _>("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::<i64, _>("id").unwrap(),
|
|
statement.read::<String, _>("description").unwrap(),
|
|
);
|
|
} else {
|
|
return TransactionType::new(0, "".to_string());
|
|
}
|
|
}
|
|
|
|
pub fn get_transaction_types(con: &Connection) -> Vec<TransactionType> {
|
|
let query = "SELECT * FROM TransactionTypes";
|
|
let mut statement = con.prepare(query).unwrap();
|
|
let mut vec = Vec::<TransactionType>::new();
|
|
|
|
while let Ok(State::Row) = statement.next() {
|
|
vec.push(TransactionType::new(
|
|
statement.read::<i64, _>("id").unwrap(),
|
|
statement.read::<String, _>("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::<i64, _>("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::<i64, _>("id").unwrap(),
|
|
statement.read::<i64, _>("account_id").unwrap(),
|
|
statement.read::<f64, _>("amount").unwrap(),
|
|
DateTime::from_timestamp(statement.read::<i64, _>("date").unwrap(), 0).unwrap(),
|
|
statement.read::<String, _>("description").unwrap(),
|
|
statement.read::<i64, _>("type_id").unwrap(),
|
|
con,
|
|
);
|
|
} else {
|
|
return Transaction::new_empty();
|
|
}
|
|
}
|
|
|
|
pub fn get_account_transactions(con: &Connection, ac_id: i64) -> Vec<Transaction> {
|
|
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::<Transaction>::new();
|
|
|
|
while let Ok(State::Row) = statement.next() {
|
|
vec.push(Transaction::new(
|
|
statement.read::<i64, _>("id").unwrap(),
|
|
statement.read::<i64, _>("account_id").unwrap(),
|
|
statement.read::<f64, _>("amount").unwrap(),
|
|
DateTime::from_timestamp(statement.read::<i64, _>("date").unwrap(), 0).unwrap(),
|
|
statement.read::<String, _>("description").unwrap(),
|
|
statement.read::<i64, _>("type_id").unwrap(),
|
|
con,
|
|
));
|
|
}
|
|
|
|
return vec;
|
|
}
|
|
|
|
pub fn get_transactions(con: &Connection) -> Vec<Transaction> {
|
|
let query = "SELECT * FROM TransactionTypes";
|
|
let mut statement = con.prepare(query).unwrap();
|
|
let mut vec = Vec::<Transaction>::new();
|
|
|
|
while let Ok(State::Row) = statement.next() {
|
|
vec.push(Transaction::new(
|
|
statement.read::<i64, _>("id").unwrap(),
|
|
statement.read::<i64, _>("account_id").unwrap(),
|
|
statement.read::<f64, _>("amount").unwrap(),
|
|
DateTime::from_timestamp(statement.read::<i64, _>("date").unwrap(), 0).unwrap(),
|
|
statement.read::<String, _>("description").unwrap(),
|
|
statement.read::<i64, _>("type_id").unwrap(),
|
|
con,
|
|
));
|
|
}
|
|
|
|
return vec;
|
|
}
|