More things before going to fix my backyard.
This commit is contained in:
1 parent
a980b1a9b1
commit
fe32c526eb
15 files changed
+199
-71
No files matched your search
@@ -53,6 +53,7 @@ CREATE TABLE IF NOT EXISTS accounts
|
|||||||
version INTEGER NOT NULL CHECK ( version >= 0 ),
|
version INTEGER NOT NULL CHECK ( version >= 0 ),
|
||||||
security INTEGER NOT NULL,
|
security INTEGER NOT NULL,
|
||||||
account_type TEXT NOT NULL,
|
account_type TEXT NOT NULL,
|
||||||
|
label TEXT NOT NULL,
|
||||||
|
|
||||||
amount INTEGER NOT NULL,
|
amount INTEGER NOT NULL,
|
||||||
timestamp DATETIME NOT NULL,
|
timestamp DATETIME NOT NULL,
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th></th>
|
<th></th>
|
||||||
<th>id</th>
|
<th>id</th>
|
||||||
|
<th>Label</th>
|
||||||
<th>Amount</th>
|
<th>Amount</th>
|
||||||
<th>Account Type</th>
|
<th>Account Type</th>
|
||||||
<th>Last Update</th>
|
<th>Last Update</th>
|
||||||
@@ -21,6 +22,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td><a href="/accounts/{{ account.id }}"><span uk-icon="info"></span></a></td>
|
<td><a href="/accounts/{{ account.id }}"><span uk-icon="info"></span></a></td>
|
||||||
<td>{{ account.id }}</td>
|
<td>{{ account.id }}</td>
|
||||||
|
<td>{{ account.label }}</td>
|
||||||
<td>{{ account.amount }}</td>
|
<td>{{ account.amount }}</td>
|
||||||
<td style="font-variant: small-caps;">{{ account.account_type | replace("_", " ") | lower}}</td>
|
<td style="font-variant: small-caps;">{{ account.account_type | replace("_", " ") | lower}}</td>
|
||||||
<td>{{ account.last_update }}</td>
|
<td>{{ account.last_update }}</td>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<form>
|
<form>
|
||||||
<fieldset class="uk-fieldset">
|
<fieldset class="uk-fieldset">
|
||||||
|
|
||||||
<legend class="uk-legend">Create new item</legend>
|
<br>
|
||||||
<div class="uk-margin">
|
<div class="uk-margin">
|
||||||
<select name="event_type"
|
<select name="event_type"
|
||||||
class="uk-select"
|
class="uk-select"
|
||||||
@@ -21,6 +21,7 @@
|
|||||||
<option value="create_security">Create Security</option>
|
<option value="create_security">Create Security</option>
|
||||||
<option value="create_account">Create Account</option>
|
<option value="create_account">Create Account</option>
|
||||||
<option value="emit_securities">Emit Securities</option>
|
<option value="emit_securities">Emit Securities</option>
|
||||||
|
<option value="create_wire_transfer">Create Wire Transfer</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<input type="hidden" name="initiator" value="bob le chef">
|
<input type="hidden" name="initiator" value="bob le chef">
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
Ledger
|
Ledger
|
||||||
</a>
|
</a>
|
||||||
<ul class="uk-navbar-nav">
|
<ul class="uk-navbar-nav">
|
||||||
{% set nav_bar_items = [{'id': 'overview', 'label': 'Overview'},
|
{% set nav_bar_items = [{'id': 'users', 'label': 'Users'},
|
||||||
{'id': 'accounts', 'label': 'Accounts'},
|
{'id': 'accounts', 'label': 'Accounts'},
|
||||||
{'id': 'securities', 'label': 'Securities'},
|
{'id': 'securities', 'label': 'Securities'},
|
||||||
{'id': 'actions', 'label': 'Actions'}]%}
|
{'id': 'actions', 'label': 'Actions'}]%}
|
||||||
|
|||||||
@@ -6,7 +6,17 @@
|
|||||||
<option value="{{ sec.id }}">{{ sec.name }} ({{ sec.symbol }}) </option>
|
<option value="{{ sec.id }}">{{ sec.name }} ({{ sec.symbol }}) </option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="uk-margin">
|
||||||
|
<label class="uk-form-label"> Label
|
||||||
|
<input class="uk-input"
|
||||||
|
type="text"
|
||||||
|
placeholder="For Bribes"
|
||||||
|
aria-label="Default"
|
||||||
|
name="event.CreateNewAccount.label"
|
||||||
|
required>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
|
||||||
|
<input type="hidden"
|
||||||
|
name="event.CreateWireTransfer.drawer_user_id"
|
||||||
|
value="{{ user.id }}">
|
||||||
|
|
||||||
|
|
||||||
|
<div class="uk-margin">
|
||||||
|
<label class="uk-form-label"> Drawer Account
|
||||||
|
<select class="uk-select"
|
||||||
|
name="event.CreateWireTransfer.emitter_account"
|
||||||
|
id="event.CreateWireTransfer.emitter_account"
|
||||||
|
hx-get="/partials/actions/accounts-by-security-selectors"
|
||||||
|
hx-trigger="change,load"
|
||||||
|
hx-target="#onetwothree"
|
||||||
|
hx-vals="js:{'sec-id': document.getElementById('event.CreateWireTransfer.emitter_account').options[document.getElementById('event.CreateWireTransfer.emitter_account').selectedIndex].getAttribute('data-sec-id')}"
|
||||||
|
hx-swap="innerHtml">
|
||||||
|
{% for account in emitter_accounts %}
|
||||||
|
<option value="{{ account.id }}" data-sec-id="{{ account.security.id }}">
|
||||||
|
{{ account.security.name }} ({{ account.security.symbol }})
|
||||||
|
</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="uk-margin">
|
||||||
|
<label class="uk-form-label"> Payee Accounts
|
||||||
|
<select class="uk-select"
|
||||||
|
name="event.CreateWireTransfer.payee_account"
|
||||||
|
id="onetwothree">
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="uk-margin">
|
||||||
|
<label class="uk-form-label"> Amount
|
||||||
|
<input class="uk-input"
|
||||||
|
type="number"
|
||||||
|
step="1"
|
||||||
|
placeholder="100 000"
|
||||||
|
aria-label="Default"
|
||||||
|
name="event.CreateWireTransfer.amount"
|
||||||
|
required>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{%include "partials/actions/submit_button.html"%}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
{% set active_navbar_item = 'overview' %}
|
{% set active_navbar_item = 'users' %}
|
||||||
|
|
||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
|
|
||||||
+28
-11
@@ -56,6 +56,7 @@ pub struct Account {
|
|||||||
timestamp: i64,
|
timestamp: i64,
|
||||||
security: Security,
|
security: Security,
|
||||||
account_type: AccountType,
|
account_type: AccountType,
|
||||||
|
label: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Account {
|
impl Account {
|
||||||
@@ -70,6 +71,7 @@ impl Account {
|
|||||||
timestamp: row.get("acc_timestamp")?,
|
timestamp: row.get("acc_timestamp")?,
|
||||||
security: Security::from_row(row)?,
|
security: Security::from_row(row)?,
|
||||||
account_type: AccountType::from_row(row)?,
|
account_type: AccountType::from_row(row)?,
|
||||||
|
label: row.get("acc_label")?,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,6 +91,10 @@ impl Account {
|
|||||||
pub fn account_type(&self) -> &AccountType {
|
pub fn account_type(&self) -> &AccountType {
|
||||||
&self.account_type
|
&self.account_type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn label(&self) -> &str {
|
||||||
|
&self.label
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -144,6 +150,7 @@ pub fn list_accounts<'a>(conn: &Connection) -> CustomResult<Vec<Account>> {
|
|||||||
acc.amount AS acc_amount,
|
acc.amount AS acc_amount,
|
||||||
UNIXEPOCH(acc.timestamp) AS acc_timestamp,
|
UNIXEPOCH(acc.timestamp) AS acc_timestamp,
|
||||||
account_type AS acc_account_type,
|
account_type AS acc_account_type,
|
||||||
|
label AS acc_label,
|
||||||
|
|
||||||
sec.id AS sec_id,
|
sec.id AS sec_id,
|
||||||
sec.symbol AS sec_symbol,
|
sec.symbol AS sec_symbol,
|
||||||
@@ -167,6 +174,7 @@ pub fn list_user_accounts(conn: &Connection, user_id: & UserId) -> CustomResult<
|
|||||||
acc.amount AS acc_amount,
|
acc.amount AS acc_amount,
|
||||||
UNIXEPOCH(acc.timestamp) AS acc_timestamp,
|
UNIXEPOCH(acc.timestamp) AS acc_timestamp,
|
||||||
account_type AS acc_account_type,
|
account_type AS acc_account_type,
|
||||||
|
label AS acc_label,
|
||||||
|
|
||||||
sec.id AS sec_id,
|
sec.id AS sec_id,
|
||||||
sec.symbol AS sec_symbol,
|
sec.symbol AS sec_symbol,
|
||||||
@@ -192,6 +200,7 @@ pub fn get_account_by_id(tx: &Connection, id: &AccountId) -> CustomResult<Accoun
|
|||||||
acc.amount AS acc_amount,
|
acc.amount AS acc_amount,
|
||||||
UNIXEPOCH(acc.timestamp) AS acc_timestamp,
|
UNIXEPOCH(acc.timestamp) AS acc_timestamp,
|
||||||
account_type AS acc_account_type,
|
account_type AS acc_account_type,
|
||||||
|
label AS acc_label,
|
||||||
|
|
||||||
sec.id AS sec_id,
|
sec.id AS sec_id,
|
||||||
sec.symbol AS sec_symbol,
|
sec.symbol AS sec_symbol,
|
||||||
@@ -211,6 +220,7 @@ pub fn get_checking_accounts_for_sec_id(tx: &Connection, sec_id: &SecurityId) ->
|
|||||||
acc.amount AS acc_amount,
|
acc.amount AS acc_amount,
|
||||||
UNIXEPOCH(acc.timestamp) AS acc_timestamp,
|
UNIXEPOCH(acc.timestamp) AS acc_timestamp,
|
||||||
account_type AS acc_account_type,
|
account_type AS acc_account_type,
|
||||||
|
label AS acc_label,
|
||||||
|
|
||||||
sec.id AS sec_id,
|
sec.id AS sec_id,
|
||||||
sec.symbol AS sec_symbol,
|
sec.symbol AS sec_symbol,
|
||||||
@@ -235,14 +245,15 @@ fn create_account(
|
|||||||
sec: &SecurityId,
|
sec: &SecurityId,
|
||||||
user: &UserId,
|
user: &UserId,
|
||||||
account_type: AccountType,
|
account_type: AccountType,
|
||||||
|
label: &String,
|
||||||
) -> CustomResult<Account> {
|
) -> CustomResult<Account> {
|
||||||
let q = "INSERT INTO accounts(security, version, amount, timestamp, account_type)
|
let q = "INSERT INTO accounts(security, version, amount, timestamp, account_type, label)
|
||||||
VALUES (?1, 0, 0, CURRENT_TIMESTAMP, ?2)";
|
VALUES (?1, 0, 0, CURRENT_TIMESTAMP, ?2, ?3)";
|
||||||
let account_type = match account_type {
|
let account_type = match account_type {
|
||||||
AccountType::Checking => "checking",
|
AccountType::Checking => "checking",
|
||||||
AccountType::SecurityEmitter => "security_emitter",
|
AccountType::SecurityEmitter => "security_emitter",
|
||||||
};
|
};
|
||||||
tx.execute(q, (sec, account_type))
|
tx.execute(q, (sec, account_type, label))
|
||||||
.map_err(Error::SqlError)?;
|
.map_err(Error::SqlError)?;
|
||||||
let id = AccountId::from_id(tx.last_insert_rowid() as i64);
|
let id = AccountId::from_id(tx.last_insert_rowid() as i64);
|
||||||
|
|
||||||
@@ -277,16 +288,18 @@ pub fn create_checking_account(
|
|||||||
tx: &Connection,
|
tx: &Connection,
|
||||||
sec: &SecurityId,
|
sec: &SecurityId,
|
||||||
user: &UserId,
|
user: &UserId,
|
||||||
|
label: &String,
|
||||||
) -> CustomResult<Account> {
|
) -> CustomResult<Account> {
|
||||||
create_account(tx, sec, user, AccountType::Checking)
|
create_account(tx, sec, user, AccountType::Checking, label)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_security_emitter_account(
|
pub fn create_security_emitter_account(
|
||||||
tx: &Connection,
|
tx: &Connection,
|
||||||
sec: &SecurityId,
|
sec: &SecurityId,
|
||||||
user: &UserId,
|
user: &UserId,
|
||||||
|
label: &String,
|
||||||
) -> CustomResult<Account> {
|
) -> CustomResult<Account> {
|
||||||
create_account(tx, sec, user, AccountType::SecurityEmitter)
|
create_account(tx, sec, user, AccountType::SecurityEmitter, label)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_owner(tx: &Connection, account_id: &AccountId, user_id: &UserId) -> CustomResult<bool> {
|
pub fn is_owner(tx: &Connection, account_id: &AccountId, user_id: &UserId) -> CustomResult<bool> {
|
||||||
@@ -392,7 +405,8 @@ mod test_accounts {
|
|||||||
let mut ret: Vec<Account> = Vec::new();
|
let mut ret: Vec<Account> = Vec::new();
|
||||||
for sec in secs.iter() {
|
for sec in secs.iter() {
|
||||||
for user in users.iter() {
|
for user in users.iter() {
|
||||||
ret.push(create_checking_account(&tx, &sec.id(), &user.id())?);
|
let label = &format!("Account for {:} in {:}", user.id(), sec.id());
|
||||||
|
ret.push(create_checking_account(&tx, &sec.id(), &user.id(), label)?);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Ok(ret);
|
return Ok(ret);
|
||||||
@@ -418,7 +432,10 @@ mod test_accounts {
|
|||||||
let sec = secs.get(0).unwrap();
|
let sec = secs.get(0).unwrap();
|
||||||
let tx = conn.transaction().unwrap();
|
let tx = conn.transaction().unwrap();
|
||||||
|
|
||||||
let acc = create_checking_account(&tx, &sec.id(), &user.id())?;
|
let acc = create_checking_account(&tx,
|
||||||
|
&sec.id(),
|
||||||
|
&user.id(),
|
||||||
|
&format!("Account for {:} in {:}", sec.id(), user.id()))?;
|
||||||
assert_eq!(acc.account_type, AccountType::Checking);
|
assert_eq!(acc.account_type, AccountType::Checking);
|
||||||
assert_eq!(0, acc.raw_amount());
|
assert_eq!(0, acc.raw_amount());
|
||||||
|
|
||||||
@@ -437,7 +454,7 @@ mod test_accounts {
|
|||||||
let sec = secs.get(0).unwrap();
|
let sec = secs.get(0).unwrap();
|
||||||
let tx = conn.transaction().unwrap();
|
let tx = conn.transaction().unwrap();
|
||||||
|
|
||||||
let acc = create_security_emitter_account(&tx, &sec.id(), &user.id())?;
|
let acc = create_security_emitter_account(&tx, &sec.id(), &user.id(), &"acc".to_string())?;
|
||||||
assert_eq!(acc.account_type, AccountType::SecurityEmitter);
|
assert_eq!(acc.account_type, AccountType::SecurityEmitter);
|
||||||
assert_eq!(0, acc.raw_amount());
|
assert_eq!(0, acc.raw_amount());
|
||||||
|
|
||||||
@@ -476,7 +493,7 @@ mod test_accounts {
|
|||||||
let user_2 = users.get(1).unwrap();
|
let user_2 = users.get(1).unwrap();
|
||||||
let sec = secs.get(0).unwrap();
|
let sec = secs.get(0).unwrap();
|
||||||
|
|
||||||
let acc = create_checking_account(&tx, &sec.id(), &user_1.id())?;
|
let acc = create_checking_account(&tx, &sec.id(), &user_1.id(), &"acc".to_string())?;
|
||||||
|
|
||||||
assert!(is_owner(tx, &acc.id(), &user_1.id())?);
|
assert!(is_owner(tx, &acc.id(), &user_1.id())?);
|
||||||
assert!(!is_owner(tx, &acc.id(), &user_2.id())?);
|
assert!(!is_owner(tx, &acc.id(), &user_2.id())?);
|
||||||
@@ -490,7 +507,7 @@ mod test_accounts {
|
|||||||
let tx = conn.transaction().unwrap();
|
let tx = conn.transaction().unwrap();
|
||||||
let sec = secs.get(0).unwrap().id();
|
let sec = secs.get(0).unwrap().id();
|
||||||
let user = users.get(0).unwrap().id();
|
let user = users.get(0).unwrap().id();
|
||||||
let acc = create_checking_account(&tx, &sec, &user).unwrap();
|
let acc = create_checking_account(&tx, &sec, &user, & "acc".to_string()).unwrap();
|
||||||
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.account_id, acc.id());
|
||||||
assert_eq!(receipt.amount, 33);
|
assert_eq!(receipt.amount, 33);
|
||||||
@@ -514,7 +531,7 @@ mod test_accounts {
|
|||||||
let tx = conn.transaction().unwrap();
|
let tx = conn.transaction().unwrap();
|
||||||
let sec = secs.get(0).unwrap().id();
|
let sec = secs.get(0).unwrap().id();
|
||||||
let user = users.get(0).unwrap().id();
|
let user = users.get(0).unwrap().id();
|
||||||
let acc = create_security_emitter_account(&tx, &sec, &user)?;
|
let acc = create_security_emitter_account(&tx, &sec, &user, & "acc".to_string())?;
|
||||||
|
|
||||||
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.account_id, acc.id());
|
||||||
|
|||||||
@@ -51,11 +51,13 @@ pub fn setup_basic_environment(
|
|||||||
tx,
|
tx,
|
||||||
&securities.get(0).unwrap().id(),
|
&securities.get(0).unwrap().id(),
|
||||||
&users.get(0).unwrap().id(),
|
&users.get(0).unwrap().id(),
|
||||||
|
&"acc1".to_string()
|
||||||
)?;
|
)?;
|
||||||
let acc2 = create_checking_account(
|
let acc2 = create_checking_account(
|
||||||
tx,
|
tx,
|
||||||
&securities.get(1).unwrap().id(),
|
&securities.get(1).unwrap().id(),
|
||||||
&users.get(1).unwrap().id(),
|
&users.get(1).unwrap().id(),
|
||||||
|
&"acc2".to_string()
|
||||||
)?;
|
)?;
|
||||||
Ok((users, securities, vec![acc1, acc2]))
|
Ok((users, securities, vec![acc1, acc2]))
|
||||||
}
|
}
|
||||||
@@ -15,7 +15,7 @@ fn process_create_new_security_event(
|
|||||||
) -> CustomResult<()> {
|
) -> CustomResult<()> {
|
||||||
let r = event.to_create_new_security().unwrap();
|
let r = event.to_create_new_security().unwrap();
|
||||||
let sec = create_security(tx, &r)?;
|
let sec = create_security(tx, &r)?;
|
||||||
create_security_emitter_account(&tx, &sec.id(), &event.user_id)?;
|
create_security_emitter_account(&tx, &sec.id(), &event.user_id, & "acc".to_string())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ fn process_create_new_user_event(tx: &mut Transaction, event: CreateNewUser) ->
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn process_create_new_account_event(tx: &mut Transaction, event: CreateNewAccount) -> CustomResult<()> {
|
fn process_create_new_account_event(tx: &mut Transaction, event: CreateNewAccount) -> CustomResult<()> {
|
||||||
create_checking_account(&tx, &event.securityId, &event.userId)?;
|
create_checking_account(&tx, &event.securityId, &event.userId, &event.label)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ pub struct CreateNewUser {
|
|||||||
pub struct CreateNewAccount {
|
pub struct CreateNewAccount {
|
||||||
pub securityId: SecurityId,
|
pub securityId: SecurityId,
|
||||||
pub userId: UserId,
|
pub userId: UserId,
|
||||||
|
pub label: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug)]
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ pub struct AccountDTO {
|
|||||||
pub account_type: String,
|
pub account_type: String,
|
||||||
pub last_update: i64,
|
pub last_update: i64,
|
||||||
pub security: SecurityDTO,
|
pub security: SecurityDTO,
|
||||||
|
pub label: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AccountDTO {
|
impl AccountDTO {
|
||||||
@@ -27,7 +28,8 @@ impl AccountDTO {
|
|||||||
amount: account.amount(),
|
amount: account.amount(),
|
||||||
account_type: account.account_type().to_string(),
|
account_type: account.account_type().to_string(),
|
||||||
last_update: account.timestamp(),
|
last_update: account.timestamp(),
|
||||||
security: SecurityDTO::from_entity(account.security())
|
security: SecurityDTO::from_entity(account.security()),
|
||||||
|
label: account.label().to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,11 +28,9 @@ fn _transfer_securities_from_one_account_to_another(
|
|||||||
if drawer_receipt.security_id != drawer_receipt.security_id {
|
if drawer_receipt.security_id != drawer_receipt.security_id {
|
||||||
let m = format!(
|
let m = format!(
|
||||||
"Incompatible security type between accounts {:} (drawer) and {:} (payee).",
|
"Incompatible security type between accounts {:} (drawer) and {:} (payee).",
|
||||||
drawer_account_id,
|
drawer_account_id, payee_account_id
|
||||||
payee_account_id
|
|
||||||
);
|
);
|
||||||
return Err(Error::InvalidAmount(m));
|
return Err(Error::InvalidAmount(m));
|
||||||
|
|
||||||
}
|
}
|
||||||
Ok((drawer_receipt, payee_receipt))
|
Ok((drawer_receipt, payee_receipt))
|
||||||
}
|
}
|
||||||
@@ -45,11 +43,14 @@ fn _transfer_cheque_securities(
|
|||||||
accounts::AccountChangeReceipt,
|
accounts::AccountChangeReceipt,
|
||||||
accounts::AccountChangeReceipt,
|
accounts::AccountChangeReceipt,
|
||||||
)> {
|
)> {
|
||||||
_transfer_securities_from_one_account_to_another(tx, &cheque.drawer_account_id, account_id, cheque.amount)
|
_transfer_securities_from_one_account_to_another(
|
||||||
|
tx,
|
||||||
|
&cheque.drawer_account_id,
|
||||||
|
account_id,
|
||||||
|
cheque.amount,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fn _transfer_wire_transfer_securities(
|
fn _transfer_wire_transfer_securities(
|
||||||
tx: &Savepoint,
|
tx: &Savepoint,
|
||||||
wire_transfer_request: &WireTransferRequest,
|
wire_transfer_request: &WireTransferRequest,
|
||||||
@@ -57,16 +58,20 @@ fn _transfer_wire_transfer_securities(
|
|||||||
accounts::AccountChangeReceipt,
|
accounts::AccountChangeReceipt,
|
||||||
accounts::AccountChangeReceipt,
|
accounts::AccountChangeReceipt,
|
||||||
)> {
|
)> {
|
||||||
_transfer_securities_from_one_account_to_another(tx,
|
_transfer_securities_from_one_account_to_another(
|
||||||
&wire_transfer_request.drawer_account_id,
|
tx,
|
||||||
&wire_transfer_request.payee_account_id,
|
&wire_transfer_request.drawer_account_id,
|
||||||
wire_transfer_request.amount)
|
&wire_transfer_request.payee_account_id,
|
||||||
|
wire_transfer_request.amount,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _add_wire_transfer_request_to_wire_transfers_log(tx: &Connection,
|
fn _add_wire_transfer_request_to_wire_transfers_log(
|
||||||
cheque: &WireTransferRequest,
|
tx: &Connection,
|
||||||
drawer_receipt: &accounts::AccountChangeReceipt,
|
cheque: &WireTransferRequest,
|
||||||
payee_receipt: &accounts::AccountChangeReceipt) -> Result<(), Error> {
|
drawer_receipt: &accounts::AccountChangeReceipt,
|
||||||
|
payee_receipt: &accounts::AccountChangeReceipt,
|
||||||
|
) -> Result<(), Error> {
|
||||||
let q = "
|
let q = "
|
||||||
INSERT INTO cached_wire_transfers(
|
INSERT INTO cached_wire_transfers(
|
||||||
drawer_account_id,
|
drawer_account_id,
|
||||||
@@ -92,12 +97,12 @@ fn _add_wire_transfer_request_to_wire_transfers_log(tx: &Connection,
|
|||||||
match ret {
|
match ret {
|
||||||
Ok(_) => Ok(()),
|
Ok(_) => Ok(()),
|
||||||
Err(Error::SqlError(rusqlite::Error::SqliteFailure(
|
Err(Error::SqlError(rusqlite::Error::SqliteFailure(
|
||||||
ffi::Error {
|
ffi::Error {
|
||||||
code: _,
|
code: _,
|
||||||
extended_code: 2067,
|
extended_code: 2067,
|
||||||
},
|
},
|
||||||
_,
|
_,
|
||||||
))) => Err(Error::DoubleSpendingError(format!(
|
))) => Err(Error::DoubleSpendingError(format!(
|
||||||
"Wire transfer number {} has already been cached.",
|
"Wire transfer number {} has already been cached.",
|
||||||
cheque.amount
|
cheque.amount
|
||||||
))),
|
))),
|
||||||
@@ -183,23 +188,28 @@ fn cash_cheque_unsafe(
|
|||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
let drawer_account_sec = accounts::get_account_by_id(&savepoint, &cheque.drawer_account_id)?.security().id();
|
let drawer_account_sec = accounts::get_account_by_id(&savepoint, &cheque.drawer_account_id)?
|
||||||
if drawer_account_sec != cheque.security_id{
|
.security()
|
||||||
|
.id();
|
||||||
|
if drawer_account_sec != cheque.security_id {
|
||||||
return Err(Error::InvalidDrawer(format!(
|
return Err(Error::InvalidDrawer(format!(
|
||||||
"Impossible to use an account containing {:} to emit a cheque in {:}",
|
"Impossible to use an account containing {:} to emit a cheque in {:}",
|
||||||
drawer_account_sec, cheque.security_id
|
drawer_account_sec, cheque.security_id
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
let payee_account_sec = accounts::get_account_by_id(&savepoint, &payee_account_id)?.security().id();
|
let payee_account_sec = accounts::get_account_by_id(&savepoint, &payee_account_id)?
|
||||||
if payee_account_sec != cheque.security_id{
|
.security()
|
||||||
|
.id();
|
||||||
|
if payee_account_sec != cheque.security_id {
|
||||||
return Err(Error::InvalidPayee(format!(
|
return Err(Error::InvalidPayee(format!(
|
||||||
"Impossible to cache a {:} cheque in {:} account .",
|
"Impossible to cache a {:} cheque in {:} account .",
|
||||||
cheque.security_id, payee_account_sec
|
cheque.security_id, payee_account_sec
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
let (drawer_receipt, payee_receipt) = _transfer_cheque_securities(&savepoint, cheque, payee_account_id)?;
|
let (drawer_receipt, payee_receipt) =
|
||||||
|
_transfer_cheque_securities(&savepoint, cheque, payee_account_id)?;
|
||||||
_add_cheque_to_cashed_cheques_log(&savepoint, cheque, &drawer_receipt, &payee_receipt)?;
|
_add_cheque_to_cashed_cheques_log(&savepoint, cheque, &drawer_receipt, &payee_receipt)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -214,8 +224,14 @@ fn cash_wire_transfer_request_unsafe(
|
|||||||
// wire_transfer
|
// wire_transfer
|
||||||
// )));
|
// )));
|
||||||
// }
|
// }
|
||||||
let (drawer_receipt, payee_receipt) = _transfer_wire_transfer_securities(&savepoint, wire_transfer)?;
|
let (drawer_receipt, payee_receipt) =
|
||||||
_add_wire_transfer_request_to_wire_transfers_log(&savepoint, wire_transfer, &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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -240,7 +256,7 @@ pub fn cash_wire_transfer_request(
|
|||||||
wire_transfer: &WireTransferRequest,
|
wire_transfer: &WireTransferRequest,
|
||||||
) -> CustomResult<()> {
|
) -> CustomResult<()> {
|
||||||
let mut savepoint = tx.savepoint().map_err(Error::SqlError)?;
|
let mut savepoint = tx.savepoint().map_err(Error::SqlError)?;
|
||||||
let ret = cash_wire_transfer_request_unsafe(& savepoint, wire_transfer);
|
let ret = cash_wire_transfer_request_unsafe(&savepoint, wire_transfer);
|
||||||
match ret {
|
match ret {
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
savepoint.rollback().map_err(Error::SqlError)?;
|
savepoint.rollback().map_err(Error::SqlError)?;
|
||||||
@@ -277,9 +293,16 @@ mod test_utils {
|
|||||||
let sec = securities.get(0).unwrap();
|
let sec = securities.get(0).unwrap();
|
||||||
let drawer = users.get(0).unwrap();
|
let drawer = users.get(0).unwrap();
|
||||||
let payee = users.get(1).unwrap();
|
let payee = users.get(1).unwrap();
|
||||||
let security_emitter_account =
|
let security_emitter_account = create_security_emitter_account(
|
||||||
create_security_emitter_account(&tx, &sec.id(), &drawer.id()).unwrap();
|
&tx,
|
||||||
let payee_account = create_checking_account(&tx, &sec.id(), &payee.id()).unwrap();
|
&sec.id(),
|
||||||
|
&drawer.id(),
|
||||||
|
&"sec emitter".to_string(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
let payee_account =
|
||||||
|
create_checking_account(&tx, &sec.id(), &payee.id(), &"checking account".to_string())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
tx.commit().unwrap();
|
tx.commit().unwrap();
|
||||||
let security_emitter: Drawer = (drawer.id(), security_emitter_account.id(), sec.id());
|
let security_emitter: Drawer = (drawer.id(), security_emitter_account.id(), sec.id());
|
||||||
@@ -295,15 +318,21 @@ mod test_utils {
|
|||||||
let sec_2 = securities.get(1).unwrap();
|
let sec_2 = securities.get(1).unwrap();
|
||||||
let drawer = users.get(0).unwrap();
|
let drawer = users.get(0).unwrap();
|
||||||
let payee = users.get(1).unwrap();
|
let payee = users.get(1).unwrap();
|
||||||
let security_emitter_account =
|
let security_emitter_account = create_security_emitter_account(
|
||||||
create_security_emitter_account(&tx, &sec_1.id(), &drawer.id()).unwrap();
|
&tx,
|
||||||
let payee_account = create_checking_account(&tx, &sec_2.id(), &payee.id()).unwrap();
|
&sec_1.id(),
|
||||||
|
&drawer.id(),
|
||||||
|
&"sec emitter account".to_string(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
let payee_account =
|
||||||
|
create_checking_account(&tx, &sec_2.id(), &payee.id(), &"payee account".to_string())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
tx.commit().unwrap();
|
tx.commit().unwrap();
|
||||||
let security_emitter: Drawer = (drawer.id(), security_emitter_account.id(), sec_1.id());
|
let security_emitter: Drawer = (drawer.id(), security_emitter_account.id(), sec_1.id());
|
||||||
let payee: Payee = (payee.id(), sec_1.id());
|
let payee: Payee = (payee.id(), sec_1.id());
|
||||||
(conn, security_emitter, payee, payee_account.id())
|
(conn, security_emitter, payee, payee_account.id())
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_100_security_units_in_payee_account(
|
pub fn create_100_security_units_in_payee_account(
|
||||||
@@ -326,9 +355,19 @@ mod test_utils {
|
|||||||
|
|
||||||
let mut tx = conn.transaction().unwrap();
|
let mut tx = conn.transaction().unwrap();
|
||||||
|
|
||||||
create_100_security_units_in_payee_account(&mut tx, &security_emitter, &payee, &payee_account);
|
create_100_security_units_in_payee_account(
|
||||||
let reg_account =
|
&mut tx,
|
||||||
create_checking_account(&tx, &security_emitter.2, &security_emitter.0).unwrap();
|
&security_emitter,
|
||||||
|
&payee,
|
||||||
|
&payee_account,
|
||||||
|
);
|
||||||
|
let reg_account = create_checking_account(
|
||||||
|
&tx,
|
||||||
|
&security_emitter.2,
|
||||||
|
&security_emitter.0,
|
||||||
|
&"reg account".to_string(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
tx.commit().unwrap();
|
tx.commit().unwrap();
|
||||||
|
|
||||||
@@ -351,11 +390,12 @@ mod test_caching_cheques {
|
|||||||
use crate::db::test_utils;
|
use crate::db::test_utils;
|
||||||
use crate::migration;
|
use crate::migration;
|
||||||
|
|
||||||
use super::*;
|
|
||||||
use super::test_utils::*;
|
use super::test_utils::*;
|
||||||
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_happy_path_currency_emitter() -> CustomResult<()> { // done
|
fn test_happy_path_currency_emitter() -> CustomResult<()> {
|
||||||
|
// done
|
||||||
let (mut conn, security_emitter, payee, payee_account) = setup_security_emitter();
|
let (mut conn, security_emitter, payee, payee_account) = setup_security_emitter();
|
||||||
let mut tx = conn.transaction().unwrap();
|
let mut tx = conn.transaction().unwrap();
|
||||||
|
|
||||||
@@ -372,7 +412,8 @@ mod test_caching_cheques {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_happy_path_regular_cheque() -> CustomResult<()> { // done
|
fn test_happy_path_regular_cheque() -> CustomResult<()> {
|
||||||
|
// done
|
||||||
let (mut conn, drawer, payee, payee_account) = setup_basic();
|
let (mut conn, drawer, payee, payee_account) = setup_basic();
|
||||||
let mut tx = conn.transaction().unwrap();
|
let mut tx = conn.transaction().unwrap();
|
||||||
|
|
||||||
@@ -531,24 +572,23 @@ mod test_caching_cheques {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_mismatch_securities() -> CustomResult<()>{
|
fn test_mismatch_securities() -> CustomResult<()> {
|
||||||
let (mut conn, drawer, payee, payee_account) = setup_security_emitter_mismatched_accounts();
|
let (mut conn, drawer, payee, payee_account) = setup_security_emitter_mismatched_accounts();
|
||||||
let cheque = Cheque::new(drawer.clone(), payee.clone(), 1000, 99);
|
let cheque = Cheque::new(drawer.clone(), payee.clone(), 1000, 99);
|
||||||
let mut tx = conn.transaction().unwrap();
|
let mut tx = conn.transaction().unwrap();
|
||||||
|
|
||||||
match cash_cheque(&mut tx, &cheque, & payee_account) {
|
match cash_cheque(&mut tx, &cheque, &payee_account) {
|
||||||
Err(Error::InvalidPayee(_)) => Ok(()),
|
Err(Error::InvalidPayee(_)) => Ok(()),
|
||||||
_ => Err(Error::Testing("Expected invalid payee here.".to_string()))
|
_ => Err(Error::Testing("Expected invalid payee here.".to_string())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test_wire_transfers {
|
mod test_wire_transfers {
|
||||||
use crate::db::accounts::get_account_by_id;
|
|
||||||
use super::*;
|
|
||||||
use super::test_utils::*;
|
use super::test_utils::*;
|
||||||
|
use super::*;
|
||||||
|
use crate::db::accounts::get_account_by_id;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_happy_path_currency_emitter() -> CustomResult<()> {
|
fn test_happy_path_currency_emitter() -> CustomResult<()> {
|
||||||
@@ -556,7 +596,7 @@ mod test_wire_transfers {
|
|||||||
let mut tx = conn.transaction().unwrap();
|
let mut tx = conn.transaction().unwrap();
|
||||||
|
|
||||||
// let cheque = Cheque::new(security_emitter, payee, 1000, 99);
|
// let cheque = Cheque::new(security_emitter, payee, 1000, 99);
|
||||||
let wire_transfer = WireTransferRequest::new(security_emitter, &payee_account, 1000, 777);;
|
let wire_transfer = WireTransferRequest::new(security_emitter, &payee_account, 1000, 777);
|
||||||
|
|
||||||
cash_wire_transfer_request(&mut tx, &wire_transfer)?;
|
cash_wire_transfer_request(&mut tx, &wire_transfer)?;
|
||||||
tx.commit().unwrap();
|
tx.commit().unwrap();
|
||||||
@@ -599,7 +639,9 @@ mod test_wire_transfers {
|
|||||||
let ret = cash_wire_transfer_request(&mut tx, &wire_transfer);
|
let ret = cash_wire_transfer_request(&mut tx, &wire_transfer);
|
||||||
match ret {
|
match ret {
|
||||||
Err(Error::DoubleSpendingError(_)) => Ok(()),
|
Err(Error::DoubleSpendingError(_)) => Ok(()),
|
||||||
_ => Err(Error::Testing("Expected DoubleSpendingError error".to_string()))
|
_ => Err(Error::Testing(
|
||||||
|
"Expected DoubleSpendingError error".to_string(),
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -70,7 +70,7 @@ fn create_views_scope() -> Scope {
|
|||||||
.service(views::account)
|
.service(views::account)
|
||||||
.service(views::securities)
|
.service(views::securities)
|
||||||
.service(views::security)
|
.service(views::security)
|
||||||
.service(views::overview)
|
.service(views::users)
|
||||||
.service(views::overview_submit_button)
|
.service(views::overview_submit_button)
|
||||||
.service(views::actions_partials)
|
.service(views::actions_partials)
|
||||||
.service(views::get_accounts_by_security_selectors)
|
.service(views::get_accounts_by_security_selectors)
|
||||||
|
|||||||
+3
-3
@@ -62,8 +62,8 @@ pub async fn security(tmpl_env: MiniJinjaRenderer,
|
|||||||
tmpl_env.render("security.html", ctx)
|
tmpl_env.render("security.html", ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_web::get("/overview")]
|
#[actix_web::get("/users")]
|
||||||
pub async fn overview(
|
pub async fn users(
|
||||||
tmpl_env: MiniJinjaRenderer,
|
tmpl_env: MiniJinjaRenderer,
|
||||||
service_factory: web::Data<ServicesFactory>,
|
service_factory: web::Data<ServicesFactory>,
|
||||||
) -> actix_web::Result<impl Responder> {
|
) -> actix_web::Result<impl Responder> {
|
||||||
@@ -74,7 +74,7 @@ pub async fn overview(
|
|||||||
let ctx = context! {
|
let ctx = context! {
|
||||||
users => users,
|
users => users,
|
||||||
};
|
};
|
||||||
tmpl_env.render("overview.html", ctx)
|
tmpl_env.render("users.html", ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_web::get("/partials/overview/submit_button")]
|
#[actix_web::get("/partials/overview/submit_button")]
|
||||||
|
|||||||
Reference in new issue
Block a user