Ho fuck you car.
This commit is contained in:
1 parent
511b2a88f6
commit
20cc644bfb
4 files changed
+124
-29
No files matched your search
@@ -16,10 +16,11 @@ VALUES ('currency'), ('bond');
|
|||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS securities
|
CREATE TABLE IF NOT EXISTS securities
|
||||||
(
|
(
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
security_type TEXT NOT NULL,
|
security_type TEXT NOT NULL,
|
||||||
name TEXT NOT NULL UNIQUE,
|
name TEXT NOT NULL UNIQUE,
|
||||||
symbol TEXT NOT NULL UNIQUE,
|
symbol TEXT NOT NULL UNIQUE,
|
||||||
|
creation_time DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
FOREIGN KEY (security_type) REFERENCES security_types (name)
|
FOREIGN KEY (security_type) REFERENCES security_types (name)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
use rusqlite::Connection;
|
||||||
|
use crate::securities::Security;
|
||||||
|
use crate::users::User;
|
||||||
|
|
||||||
|
struct Account<'a> {
|
||||||
|
security: &'a Security,
|
||||||
|
user: &'a User,
|
||||||
|
amount: i64,
|
||||||
|
time_stamp: i64
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn list_accounts(conn: & Connection){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
+16
-9
@@ -1,17 +1,18 @@
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use clap::{Arg, ArgAction, ArgMatches, Command, value_parser};
|
use clap::{Arg, ArgAction, ArgMatches, Command, value_parser};
|
||||||
use serde::{Serialize};
|
|
||||||
|
|
||||||
use log::{debug, info};
|
use log::{debug, info};
|
||||||
use rusqlite::Connection;
|
use rusqlite::Connection;
|
||||||
|
use serde::Serialize;
|
||||||
use simple_logger::SimpleLogger;
|
use simple_logger::SimpleLogger;
|
||||||
|
|
||||||
use crate::migration::apply_migrations;
|
use crate::migration::apply_migrations;
|
||||||
|
use crate::securities::list_securities;
|
||||||
|
|
||||||
mod migration;
|
mod migration;
|
||||||
mod users;
|
mod users;
|
||||||
mod securities;
|
mod securities;
|
||||||
|
mod account;
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
struct Output<T> {
|
struct Output<T> {
|
||||||
@@ -21,9 +22,8 @@ struct Output<T> {
|
|||||||
|
|
||||||
impl<T> Output<T> {
|
impl<T> Output<T> {
|
||||||
fn success(shit: T) -> Output<T> {
|
fn success(shit: T) -> Output<T> {
|
||||||
return Output{status: "success".to_string(), result: shit};
|
return Output { status: "success".to_string(), result: shit };
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
trait CommandLineUserLogic {
|
trait CommandLineUserLogic {
|
||||||
@@ -128,13 +128,11 @@ fn process_user_command_line(conn: &Connection, m: &ArgMatches, logic: &mut dyn
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn process_list_securities_command_line(conn: &Connection, m: &ArgMatches, logic: &mut dyn CommandLineUserLogic) {
|
fn process_list_securities_command_line(conn: &Connection, m: &ArgMatches, logic: &mut dyn CommandLineUserLogic) {
|
||||||
debug!("Processing list securities command line {:?}.", m);
|
debug!("Processing list securities command line {:?}.", m);
|
||||||
logic.list_securities(conn);
|
logic.list_securities(conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn process_securities_command_line(conn: &Connection, m: &ArgMatches, logic: &mut dyn CommandLineUserLogic) {
|
fn process_securities_command_line(conn: &Connection, m: &ArgMatches, logic: &mut dyn CommandLineUserLogic) {
|
||||||
debug!("Processing securities command line {:?}.", m);
|
debug!("Processing securities command line {:?}.", m);
|
||||||
match m.subcommand() {
|
match m.subcommand() {
|
||||||
@@ -284,7 +282,7 @@ impl CommandLineUserLogic for ProCommandLineLogic {
|
|||||||
|
|
||||||
let out = Output::success(r);
|
let out = Output::success(r);
|
||||||
|
|
||||||
println!("{}", serde_json::to_string(& out).unwrap());
|
println!("{}", serde_json::to_string(&out).unwrap());
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("{:?}", e);
|
println!("{:?}", e);
|
||||||
@@ -292,8 +290,17 @@ impl CommandLineUserLogic for ProCommandLineLogic {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn list_securities(&mut self, _conn: &Connection) {
|
fn list_securities(&mut self, conn: & Connection) {
|
||||||
todo!()
|
let securities = list_securities(conn);
|
||||||
|
match securities {
|
||||||
|
Ok(s) => {
|
||||||
|
let out = Output::success(s);
|
||||||
|
println!("{}", serde_json::to_string(&out).unwrap());
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
println!("{:?}", e);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+87
-16
@@ -1,17 +1,29 @@
|
|||||||
use rusqlite::{Connection, ToSql};
|
use rusqlite::{Connection, Result, ToSql};
|
||||||
use serde::{Serialize};
|
use serde::Serialize;
|
||||||
|
|
||||||
use crate::migration;
|
use crate::migration;
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, PartialEq)]
|
||||||
#[derive(Debug, Serialize)]
|
|
||||||
pub enum SecurityType {
|
pub enum SecurityType {
|
||||||
Currency,
|
Currency,
|
||||||
Bond,
|
Bond,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SecurityType {
|
||||||
|
fn from_string(s: String) -> SecurityType {
|
||||||
|
if s == "currency".to_string() {
|
||||||
|
return SecurityType::Currency;
|
||||||
|
}
|
||||||
|
if s == "bond".to_string() {
|
||||||
|
return SecurityType::Bond;
|
||||||
|
}
|
||||||
|
panic!("Impossible to convert string {} to SecurityType.", s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ToSql for SecurityType {
|
impl ToSql for SecurityType {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_sql(&self) -> rusqlite::Result<rusqlite::types::ToSqlOutput<'_>> {
|
fn to_sql(&self) -> Result<rusqlite::types::ToSqlOutput<'_>> {
|
||||||
Ok(rusqlite::types::ToSqlOutput::from(match self {
|
Ok(rusqlite::types::ToSqlOutput::from(match self {
|
||||||
SecurityType::Currency => "currency",
|
SecurityType::Currency => "currency",
|
||||||
SecurityType::Bond => "bond",
|
SecurityType::Bond => "bond",
|
||||||
@@ -19,11 +31,10 @@ impl ToSql for SecurityType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize, PartialEq)]
|
||||||
pub struct Security {
|
pub struct Security {
|
||||||
id: i32,
|
id: i32,
|
||||||
security_type: SecurityType,
|
security_type: SecurityType,
|
||||||
public_key: String,
|
|
||||||
symbol: String,
|
symbol: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,22 +45,38 @@ pub struct NewSecurity {
|
|||||||
name: String,
|
name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_security(conn: &mut Connection, sec: &NewSecurity) -> Result<(), rusqlite::Error> {
|
pub fn create_security(conn: &mut Connection, sec: &NewSecurity) -> Result<()> {
|
||||||
let tx = conn.transaction()?;
|
let tx = conn.transaction()?;
|
||||||
let q = "INSERT INTO
|
let q = "INSERT INTO
|
||||||
securities(name, symbol, security_type)
|
securities(name, symbol, security_type)
|
||||||
VALUES(?1, ?2, ?3)";
|
VALUES(?1, ?2, ?3)";
|
||||||
let params = (&sec.name, &sec.symbol, &sec.security_type);
|
let params = (&sec.name, &sec.symbol, &sec.security_type);
|
||||||
tx.execute(q, params)?;
|
tx.execute(q, params)?;
|
||||||
return Ok(());
|
return tx.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn list_securities(conn: & Connection) -> Result<Vec<Security>> {
|
||||||
|
let q = "SELECT id, security_type, symbol
|
||||||
|
FROM securities
|
||||||
|
ORDER BY creation_time DESC";
|
||||||
|
let mut stmt = conn.prepare(q)?;
|
||||||
|
|
||||||
|
let ret: Vec<Security> = stmt.query_map([], |row| {
|
||||||
|
Ok(Security {
|
||||||
|
id: row.get(0)?,
|
||||||
|
security_type: SecurityType::from_string(row.get(1)?),
|
||||||
|
symbol: row.get(2)?,
|
||||||
|
})
|
||||||
|
}).unwrap().filter(|x| x.is_ok()).map(|x| x.unwrap()).collect();
|
||||||
|
return Ok(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
|
||||||
use rusqlite::{Connection, params};
|
use rusqlite::{Connection, params};
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
fn setup() -> Connection {
|
fn setup() -> Connection {
|
||||||
let mut conn = Connection::open_in_memory().unwrap();
|
let mut conn = Connection::open_in_memory().unwrap();
|
||||||
@@ -57,6 +84,24 @@ mod test {
|
|||||||
return conn;
|
return conn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn mock_currency_1() -> NewSecurity {
|
||||||
|
return NewSecurity {
|
||||||
|
security_type: SecurityType::Currency,
|
||||||
|
public_key: "123".to_string(),
|
||||||
|
symbol: "P".to_string(),
|
||||||
|
name: "pisatre".to_string(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mock_currency_2() -> NewSecurity {
|
||||||
|
return NewSecurity {
|
||||||
|
security_type: SecurityType::Bond,
|
||||||
|
public_key: "123".to_string(),
|
||||||
|
symbol: "B".to_string(),
|
||||||
|
name: "bong".to_string(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_security_types() -> Result<(), rusqlite::Error> {
|
fn test_security_types() -> Result<(), rusqlite::Error> {
|
||||||
let conn = setup();
|
let conn = setup();
|
||||||
@@ -76,13 +121,39 @@ mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_create_security() -> Result<(), rusqlite::Error> {
|
fn test_create_security() -> Result<(), rusqlite::Error> {
|
||||||
let mut conn = setup();
|
let mut conn = setup();
|
||||||
let sec = NewSecurity {
|
let sec = mock_currency_1();
|
||||||
security_type: SecurityType::Currency,
|
|
||||||
public_key: "123".to_string(),
|
|
||||||
symbol: "P".to_string(),
|
|
||||||
name: "pisatre".to_string(),
|
|
||||||
};
|
|
||||||
create_security(&mut conn, &sec)?;
|
create_security(&mut conn, &sec)?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_list_security() -> Result<(), rusqlite::Error> {
|
||||||
|
let mut conn = setup();
|
||||||
|
assert_eq!(0, list_securities(& conn)?.len());
|
||||||
|
|
||||||
|
let sec = mock_currency_1();
|
||||||
|
create_security(&mut conn, &sec)?;
|
||||||
|
let ret = list_securities(& conn)?;
|
||||||
|
let expt = Security {
|
||||||
|
id: 1,
|
||||||
|
security_type: SecurityType::Currency,
|
||||||
|
symbol: "P".to_string(),
|
||||||
|
};
|
||||||
|
assert_eq!(1, ret.len());
|
||||||
|
assert_eq!(&expt, ret.get(0).unwrap());
|
||||||
|
|
||||||
|
|
||||||
|
let sec = mock_currency_2();
|
||||||
|
let expt = Security {
|
||||||
|
id: 2,
|
||||||
|
security_type: SecurityType::Bond,
|
||||||
|
symbol: "B".to_string(),
|
||||||
|
};
|
||||||
|
create_security(&mut conn, &sec)?;
|
||||||
|
let ret = list_securities(& conn)?;
|
||||||
|
assert_eq!(2, ret.len());
|
||||||
|
assert_eq!(&expt, ret.get(1).unwrap());
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user