diff --git a/Cargo.lock b/Cargo.lock index 44ef09c..9ca8572 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1343,6 +1343,7 @@ dependencies = [ "memo-map", "self_cell", "serde", + "serde_json", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 4f1722f..be67032 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,7 @@ tempfile = "3.3.0" fraction = "0.13.0" actix-web = "4.3.0" tokio = { version = "1.24.2", features = ["full"] } -minijinja = { version = "0.30.2", features = ["source"] } +minijinja = { version = "0.30.2", features = ["source", "builtins", "json"] } actix-utils = "3.0.1" actix-web-lab = "0.18.9" minijinja-autoreload = "0.30.2" diff --git a/resources/templates/account.html b/resources/templates/account.html index 27670f8..c88f976 100644 --- a/resources/templates/account.html +++ b/resources/templates/account.html @@ -4,7 +4,18 @@ {% block body %} -

Account!

+ + + + + + + + +
Summary
ID{{ account.id }}
Label{{ account.label }}
Amount{{ account.amount }}
Account Type{{ account.account_type | replace("_", " ") | lower}}
Last Update{{ account.last_update }}
Security{{ account.security.symbol }}
+ + +
 {{ "hello" | tojson }}
{% endblock %} \ No newline at end of file diff --git a/resources/templates/partials/actions/create_wire_transfer.html b/resources/templates/partials/actions/create_wire_transfer.html index b552c02..c72e532 100644 --- a/resources/templates/partials/actions/create_wire_transfer.html +++ b/resources/templates/partials/actions/create_wire_transfer.html @@ -1,4 +1,9 @@ + + + @@ -7,12 +12,12 @@
diff --git a/src/event_processor.rs b/src/event_processor.rs index d26b871..1a2542c 100644 --- a/src/event_processor.rs +++ b/src/event_processor.rs @@ -1,11 +1,11 @@ use rusqlite::{Connection, Transaction}; use crate::db::accounts; -use crate::db::accounts::{AccountType, create_checking_account, create_security_emitter_account}; +use crate::db::accounts::{AccountType, create_checking_account, create_security_emitter_account, get_account_by_id}; use crate::db::cheques::{Drawer, WireTransferRequest}; use crate::db::securities::create_security; use crate::db::users::create_user; -use crate::events::{CreateNewAccount, CreateNewSecurity, CreateNewUser, EmitSecurities, Event}; +use crate::events::{CreateNewAccount, CreateNewSecurity, CreateNewUser, CreateWireTransfer, EmitSecurities, Event}; use crate::services::cash_wire_transfer_request; use crate::util::{CustomResult, Error}; @@ -49,6 +49,17 @@ fn process_emit_securities_event(tx: &mut Transaction, event: EmitSecurities) -> Ok(()) } +fn process_create_wire_transfer(tx: &mut Transaction, event: CreateWireTransfer) -> CustomResult<()> { + let sec_id = get_account_by_id(tx, &event.payee_account_id)?.security().id(); + let wire_transfer = WireTransferRequest::new( + (event.drawer_user_id, event.drawer_account_id, sec_id), + &event.payee_account_id, + event.amount, + event.id + ); + cash_wire_transfer_request(tx, &wire_transfer) +} + pub fn process_event(conn: &mut Connection, event: Event) -> CustomResult<()> { let mut tx = conn.transaction().map_err(Error::SqlError)?; let ret = match event { @@ -56,6 +67,7 @@ pub fn process_event(conn: &mut Connection, event: Event) -> CustomResult<()> { Event::CreateNewUser(e) => process_create_new_user_event(&mut tx, e), Event::CreateNewAccount(e) => process_create_new_account_event(&mut tx, e), Event::EmitSecurities(e) => process_emit_securities_event(&mut tx, e), + Event::CreateWireTransfer(e) => process_create_wire_transfer(&mut tx, e), }; match ret { Err(_) => { diff --git a/src/events.rs b/src/events.rs index 66003d7..3f9d202 100644 --- a/src/events.rs +++ b/src/events.rs @@ -1,5 +1,5 @@ -use serde::{Deserialize, Serialize}; use crate::db::external_id::{AccountId, SecurityId, UserId}; +use serde::{Deserialize, Serialize}; use crate::db::securities::{NewSecurity, SecurityType}; @@ -54,12 +54,22 @@ pub struct EmitSecurities { pub payee_accounts: Vec, } +#[derive(Deserialize, Serialize, Debug)] +pub struct CreateWireTransfer { + pub id: i64, + pub amount: i64, + pub drawer_user_id: UserId, + pub drawer_account_id: AccountId, + pub payee_account_id: AccountId, +} + #[derive(Deserialize, Serialize, Debug)] pub enum Event { CreateNewSecurity(CreateNewSecurity), CreateNewUser(CreateNewUser), CreateNewAccount(CreateNewAccount), EmitSecurities(EmitSecurities), + CreateWireTransfer(CreateWireTransfer), } impl Event { diff --git a/src/services/_accounts.rs b/src/services/_accounts.rs index 75435df..867dc6d 100644 --- a/src/services/_accounts.rs +++ b/src/services/_accounts.rs @@ -1,9 +1,10 @@ use rusqlite::Connection; use crate::db::accounts::{Account, AccountType, get_checking_accounts_for_sec_id, list_user_accounts}; -use crate::db::external_id::{Id, SecurityId, UserId}; +use crate::db::external_id::{AccountId, Id, SecurityId, UserId}; use crate::util::{CustomResult, Error}; use serde::Deserialize; use serde::Serialize; +use crate::db::accounts; use crate::db::securities::Security; use crate::services::_securities::SecurityDTO; @@ -59,6 +60,10 @@ impl AccountService<'_> { pub fn get_checking_accounts_for_security(& self, sec_id: & SecurityId) -> CustomResult>{ let ret = get_checking_accounts_for_sec_id(self.conn, sec_id)?; Ok(ret.iter().map(AccountDTO::from_entity).collect()) + } + pub fn get_account_by_id(&self, account_id: &AccountId, user_id: &UserId) -> CustomResult { + let ret = &accounts::get_account_by_id(self.conn, account_id)?; + Ok(AccountDTO::from_entity(ret)) } } \ No newline at end of file diff --git a/src/webui/minininja_utils.rs b/src/webui/minininja_utils.rs new file mode 100644 index 0000000..9b65638 --- /dev/null +++ b/src/webui/minininja_utils.rs @@ -0,0 +1,30 @@ +use regex::Regex; +// +// fn is_number(value: String) -> bool{ +// true +// } +// +// fn pretty_number(value: String) -> String { +// let re = Regex::new(r"\d+").unwrap(); +// let cap = re.captures(&value); +// if cap.is_none() { +// return value; +// } +// let mut ret = "".to_string(); +// for (idx, letter) in value.as_bytes().iter().enumerate() { +// ret.push(letter); +// } +// "foo".to_string() +// +// } +// +// +// #[cfg(test)] +// pub mod test_minininja_utils { +// use super::*; +// +// #[test] +// fn test_pretty_number() { +// assert_eq!(pretty_number("foo".to_string()), "foo"); +// } +// } diff --git a/src/webui/mod.rs b/src/webui/mod.rs index 85924c7..90f9a22 100644 --- a/src/webui/mod.rs +++ b/src/webui/mod.rs @@ -27,6 +27,7 @@ mod services; mod templates; mod views; mod worker; +mod minininja_utils; struct ProductionEventProcessor; diff --git a/src/webui/views.rs b/src/webui/views.rs index 9347762..254bd51 100644 --- a/src/webui/views.rs +++ b/src/webui/views.rs @@ -8,7 +8,7 @@ use minijinja::context; use rusqlite::params; use serde::Deserialize; use uuid::Uuid; -use crate::db::external_id::{Id, SecurityId}; +use crate::db::external_id::{AccountId, Id, SecurityId}; use crate::events::Event; @@ -37,8 +37,17 @@ pub async fn accounts(tmpl_env: MiniJinjaRenderer, pub async fn account(tmpl_env: MiniJinjaRenderer, req: HttpRequest, service_factory: web::Data) -> actix_web::Result { + let path_event_type = req.match_info().get("account_id").unwrap(); + let account_id = AccountId::from_string(&path_event_type.to_string()).unwrap(); + let conn = service_factory.get_connection()?; + let auth_service = service_factory.get_authentication_service(&conn)?; + let account_service = service_factory.get_account_service(& conn)?; + let user_id = auth_service.get_login(&req).unwrap(); - tmpl_env.render("account.html", context!{}) + let ctx = context!{ + account => account_service.get_account_by_id(&account_id, &user_id).map_err(error::ErrorInternalServerError)? + }; + tmpl_env.render("account.html", ctx) }