Files
escarmouche/src/db/account.rs
T

110 lines
3.4 KiB
Rust

use rusqlite::{Connection, params, Result, Row, Transaction};
use crate::db::securities::Security;
use crate::db::users::User;
pub struct Account {
id: i64,
amount: i64,
timestamp: i64,
}
fn _account_from_row(row: &Row) -> Result<Account> {
return Ok(Account{
id: row.get(0)?,
amount: row.get(1)?,
timestamp: row.get(2)?,
});
}
pub fn list_accounts<'a>(conn: &Connection) -> Result<Vec<Account>> {
let q = "SELECT id, amount, UNIXEPOCH(timestamp)
FROM accounts
ORDER BY id ASC";
let mut stmt = conn.prepare(q)?;
let ret: Vec<Account> = stmt
.query_map([], &_account_from_row)?
.filter(Result::is_ok)
.map(Result::unwrap)
.collect();
return Ok(ret);
}
pub fn get_account_by_id(tx: &Transaction, id: u32) -> Result<Account>{
let q = "SELECT id, amount, UNIXEPOCH(timestamp) FROM accounts WHERE id = ?1";
return tx.query_row(q, params![id], _account_from_row);
}
pub fn create_account(tx: &Transaction, sec: &Security, user: &User) -> Result<Account>{
let q = "INSERT INTO accounts(security, owner, amount, timestamp)
VALUES (?1, ?2, 0, CURRENT_TIMESTAMP)";
tx.execute(q, (sec.id, user.id))?;
return get_account_by_id(tx, tx.last_insert_rowid() as u32);
}
#[cfg(test)]
mod test {
use rusqlite::{Connection};
use crate::db::users;
use crate::db::securities;
use crate::migration;
use super::*;
fn setup_users(tx: &Transaction) -> Result<Vec<User>> {
let user_1 = users::create_user(tx, &"bernard".to_string(), &"123".to_string())?;
let user_2 = users::create_user(tx, &"sam".to_string(), &"abc".to_string())?;
return Ok(vec![user_1, user_2]);
}
fn setup_securities(tx: &Transaction) -> Result<Vec<Security>> {
let sec_1 = securities::create_security(tx, &securities::test_util::mock_currency_1())?;
let sec_2 = securities::create_security(tx, &securities::test_util::mock_currency_2())?;
return Ok(vec![sec_1, sec_2]);
}
fn setup() -> (Connection, Vec<User>, Vec<Security>) {
let mut conn = Connection::open_in_memory().unwrap();
migration::apply_migrations(&mut conn).unwrap();
let tx = conn.transaction().unwrap();
let users = setup_users(&tx).unwrap();
let securities = setup_securities(&tx).unwrap();
tx.commit().unwrap();
return (conn, users, securities);
}
fn create_all_accounts(tx: & Transaction, users: & Vec<User>, secs: & Vec<Security>) -> Result<()>{
for sec in secs.iter() {
for user in users.iter() {
create_account(&tx, sec, user)?;
}
}
return Ok(());
}
#[test]
fn test_happy_path() -> Result<()>{
let (mut conn, users, secs) = setup();
let tx = conn.transaction()?;
create_all_accounts(& tx, &users, &secs)?;
tx.commit()?;
let accs = list_accounts(& conn)?;
assert_eq!(4, accs.len());
assert_eq!(1, accs.get(0).unwrap().id);
assert_eq!(4, accs.get(3).unwrap().id);
return Ok(());
}
#[test]
fn test_happy_path_no_commit() -> Result<()>{
let (mut conn, users, secs) = setup();
create_all_accounts(& conn.transaction()?, &users, &secs)?;
let accs = list_accounts(& conn)?;
assert_eq!(0, accs.len());
return Ok(());
}
}