diff --git a/src/db/_accounts.rs b/src/db/_accounts.rs index 7a5fc09..0a6a095 100644 --- a/src/db/_accounts.rs +++ b/src/db/_accounts.rs @@ -303,6 +303,7 @@ pub fn is_owner(tx: &Connection, account_id: &AccountId, user_id: &UserId) -> Cu pub struct AccountChangeReceipt { pub account_id: AccountId, pub security_id: SecurityId, + pub account_type: AccountType, pub version: i64, pub timestamp: i64, pub amount: i64, @@ -316,6 +317,7 @@ impl AccountChangeReceipt { amount: row.get("amount")?, timestamp: row.get("timestamp")?, security_id: SecurityId::from_id(row.get("security_id")?), + account_type: AccountType::from_row(row)? }) } } @@ -341,18 +343,16 @@ pub fn add_to_account( amount: i64, ) -> CustomResult { let q = " - UPDATE accounts SET amount = CASE account_type - WHEN 'security_emitter' - THEN amount - ELSE amount + ?1 END, + UPDATE accounts SET amount = amount + ?1, version = version + 1, timestamp = CURRENT_TIMESTAMP WHERE id = ?2 RETURNING id, version, amount, - UNIXEPOCH(CURRENT_TIMESTAMP) as timestamp, - security as security_id + UNIXEPOCH(CURRENT_TIMESTAMP) AS timestamp, + account_type AS acc_account_type, + security AS security_id "; let params = params![amount, account_id]; let ret = tx @@ -516,16 +516,16 @@ mod test_accounts { let user = users.get(0).unwrap().id(); let acc = create_security_emitter_account(&tx, &sec, &user)?; - let receipt = add_to_account(&tx, &acc.id(), 33)?; + let receipt = add_to_account(&tx, &acc.id(), -33)?; assert_eq!(receipt.account_id, acc.id()); - assert_eq!(receipt.amount, 0); + assert_eq!(receipt.amount, -33); assert_eq!(receipt.version, 1); tx.commit().unwrap(); let tx2 = conn.transaction().unwrap(); let acc = get_account_by_id(&tx2, &acc.id()).unwrap(); assert_eq!(acc.timestamp, receipt.timestamp); - assert_eq!(acc.amount, 0); + assert_eq!(acc.amount, -33); assert_eq!(get_account_history(&tx2, &acc.id())?.len(), 2); Ok(()) diff --git a/src/services/_transactions.rs b/src/services/_transactions.rs index 500d64a..5772ba7 100644 --- a/src/services/_transactions.rs +++ b/src/services/_transactions.rs @@ -1,6 +1,7 @@ use rusqlite::{ffi, params, Connection, Savepoint, Transaction}; use crate::db::accounts; +use crate::db::accounts::AccountType; use crate::db::cheques::{Cheque, WireTransferRequest}; use crate::db::external_id::AccountId; @@ -17,9 +18,9 @@ fn _transfer_securities_from_one_account_to_another( )> { let drawer_receipt = accounts::add_to_account(tx, drawer_account_id, -amount)?; let payee_receipt = accounts::add_to_account(tx, payee_account_id, amount)?; - if drawer_receipt.amount < 0 { + if drawer_receipt.amount < 0 && drawer_receipt.account_type != AccountType::SecurityEmitter { let m = format!( - "Drawer of {:?} does not have sufficient amount in account.", + "Drawer of {:} does not have sufficient amount in account.", drawer_account_id ); return Err(Error::InvalidAmount(m)); @@ -177,7 +178,7 @@ fn cash_cheque_unsafe( if !accounts::is_owner(&savepoint, payee_account_id, &cheque.payee_user_id)? { return Err(Error::InvalidPayee(format!( "Trying to cash the cheque {:?} in \ - an account {:?} that is not owned by the payee.", + an account {:} that is not owned by the payee.", cheque, payee_account_id ))); } @@ -207,12 +208,12 @@ fn cash_wire_transfer_request_unsafe( savepoint: &Savepoint, wire_transfer: &WireTransferRequest, ) -> CustomResult<()> { - if wire_transfer.amount < 0 { - return Err(Error::InvalidAmount(format!( - "The cheque {:?} has a negative amount.", - wire_transfer - ))); - } + // if wire_transfer.amount < 0 { + // return Err(Error::InvalidAmount(format!( + // "The cheque {:?} has a negative amount.", + // wire_transfer + // ))); + // } let (drawer_receipt, payee_receipt) = _transfer_wire_transfer_securities(&savepoint, wire_transfer)?; _add_wire_transfer_request_to_wire_transfers_log(&savepoint, wire_transfer, &drawer_receipt, &payee_receipt)?; Ok(()) @@ -407,6 +408,22 @@ mod test_caching_cheques { } } + #[test] + fn test_unfounded_cheque() -> CustomResult<()> { + let (mut conn, drawer, payee, payee_account) = setup_basic(); + let mut tx = conn.transaction().unwrap(); + + let cheque = Cheque::new(drawer, payee, 1_000_000, 99); + + let ret = cash_cheque(&mut tx, &cheque, &payee_account); + match ret { + Err(Error::InvalidAmount(_)) => Ok(()), + _ => Err(Error::Testing( + "Expected invalid amount error here.".to_string(), + )), + } + } + #[test] fn test_negative_security_emitter_cheque() -> CustomResult<()> { let (mut conn, security_emitter, payee, payee_account) = setup_security_emitter();