Added nice chart for account history.
This commit is contained in:
1 parent
80153dd6ad
commit
e76a521356
14 files changed
+125
-187
No files matched your search
@@ -10,7 +10,7 @@ nix build
|
|||||||
|
|
||||||
### Building dev environment
|
### Building dev environment
|
||||||
|
|
||||||
#### For ide
|
#### For IDE
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
nix build .#development-environment
|
nix build .#development-environment
|
||||||
@@ -18,14 +18,20 @@ nix build .#development-environment
|
|||||||
|
|
||||||
Then, in IntelliJ use `result/bin`
|
Then, in IntelliJ use `result/bin`
|
||||||
|
|
||||||
The rust source must be `/nix/store/pmih7jv9r5xfaif92bza8w05876qvnvc-rust-src/`
|
The rust source must be `/nix/store/pmih7jv9r5xfaif92bza8w05876qvnvc-rust-src/` or similar.
|
||||||
|
|
||||||
#### For shell
|
#### For development shell
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
nix develop
|
nix develop
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Init Postgres
|
||||||
|
|
||||||
|
```shell
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
## Technologies
|
## Technologies
|
||||||
|
|
||||||
### Front-end
|
### Front-end
|
||||||
|
|||||||
@@ -80,12 +80,13 @@ CREATE TABLE IF NOT EXISTS accounts
|
|||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS accounts_history
|
CREATE TABLE IF NOT EXISTS accounts_history
|
||||||
(
|
(
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
account_id INTEGER NOT NULL,
|
account_id INTEGER NOT NULL,
|
||||||
account_version INTEGER NOT NULL,
|
account_version INTEGER NOT NULL,
|
||||||
amount INTEGER NOT NULL,
|
amount INTEGER NOT NULL,
|
||||||
timestamp DATETIME NOT NULL,
|
timestamp DATETIME NOT NULL,
|
||||||
FOREIGN KEY (account_id) REFERENCES accounts (id),
|
FOREIGN KEY (account_id) REFERENCES accounts (id),
|
||||||
PRIMARY KEY (account_id, account_version)
|
UNIQUE (account_id, account_version)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS account_user_permissions
|
CREATE TABLE IF NOT EXISTS account_user_permissions
|
||||||
|
|||||||
@@ -15,60 +15,34 @@
|
|||||||
<tr><th>Account Type</th><td>{{ account.account_type | replace("_", " ") | lower}}</td></tr>
|
<tr><th>Account Type</th><td>{{ account.account_type | replace("_", " ") | lower}}</td></tr>
|
||||||
<tr><th>Last Update</th><td>{{ account.last_update | utc_date }}</td></tr>
|
<tr><th>Last Update</th><td>{{ account.last_update | utc_date }}</td></tr>
|
||||||
<tr><th>Security</th><td>{{ account.security.symbol }}</td></tr>
|
<tr><th>Security</th><td>{{ account.security.symbol }}</td></tr>
|
||||||
|
<tr><th>Data</th><td>
|
||||||
|
<a href="/data/accounts/{{ account.id }}/amount-history.json">data</a>
|
||||||
|
</td></tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<canvas id="account-history-chart"></canvas>
|
<div id="account-history-chart-2" style="width: 100%"></div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
const ctx = document.getElementById('account-history-chart');
|
var vlSpec = {
|
||||||
const labels = {{account_history.timestamps | tojson }};
|
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
|
||||||
const datapoints = {{ account_history.amounts | tojson }};
|
title: "History of {{ account.id }}",
|
||||||
const data = {
|
"width": "container",
|
||||||
labels: labels.map(x => new Date(1000 * x)),
|
"height": 250,
|
||||||
datasets: [
|
"data": {url: "/data/accounts/{{ account.id }}/amount-history.json",
|
||||||
{
|
format:{
|
||||||
label: {{ account.id | micro_id | tojson }},
|
type: "json",
|
||||||
data: datapoints,
|
property: "snapshots"
|
||||||
fill: false,
|
}
|
||||||
tension: 0.4
|
},
|
||||||
|
"mark": "line",
|
||||||
|
"encoding": {
|
||||||
|
"x": {"field": "timestamp", "type": "temporal", title: 'Time'},
|
||||||
|
"y": {"field": "amount", "type": "quantitative", title: 'Quantity'}
|
||||||
}
|
}
|
||||||
]
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const config = {
|
// Embed the visualization in the container with id `vis`
|
||||||
type: 'line',
|
vegaEmbed('#account-history-chart-2', vlSpec);
|
||||||
data: data,
|
|
||||||
options: {
|
|
||||||
responsive: true,
|
|
||||||
plugins: {
|
|
||||||
title: {
|
|
||||||
display: true,
|
|
||||||
text: 'Account Amount History'
|
|
||||||
},
|
|
||||||
},
|
|
||||||
interaction: {
|
|
||||||
intersect: false,
|
|
||||||
},
|
|
||||||
scales: {
|
|
||||||
x: {
|
|
||||||
display: true,
|
|
||||||
type: 'time',
|
|
||||||
title: {
|
|
||||||
display: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
y: {
|
|
||||||
display: true,
|
|
||||||
title: {
|
|
||||||
display: true,
|
|
||||||
text: 'Value'
|
|
||||||
},
|
|
||||||
suggestedMin: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
new Chart(ctx, config);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -18,9 +18,10 @@
|
|||||||
<script src="/static/vendor/htmx.org@1.8.5"></script>
|
<script src="/static/vendor/htmx.org@1.8.5"></script>
|
||||||
<script src="/static/embedded-json-enc.js"></script>
|
<script src="/static/embedded-json-enc.js"></script>
|
||||||
{% if script_chart_js %}
|
{% if script_chart_js %}
|
||||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/vega@5.22.1"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/luxon@3.3.0/build/global/luxon.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/vega-lite@5.6.1"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-luxon"></script>
|
<script src="https://cdn.jsdelivr.net/npm/vega-embed@6.21.2"></script>
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
@@ -29,7 +29,6 @@
|
|||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<input type="hidden" name="event.CreateNewSecurity.user_id" value="{{ user.id }}">
|
<input type="hidden" name="event.CreateNewSecurity.user_id" value="{{ user.id }}">
|
||||||
|
|
||||||
{%include "partials/actions/submit_button.html"%}
|
{%include "partials/actions/submit_button.html"%}
|
||||||
@@ -1,99 +0,0 @@
|
|||||||
use rusqlite::{Connection, OptionalExtension, params};
|
|
||||||
use crate::db::accounts;
|
|
||||||
use crate::db::accounts::Account;
|
|
||||||
use crate::db::external_id::AccountId;
|
|
||||||
use crate::util::{CustomResult, Error};
|
|
||||||
|
|
||||||
pub struct AccountHistory {
|
|
||||||
account: Account,
|
|
||||||
timestamps: Vec<i64>,
|
|
||||||
amounts: Vec<i64>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AccountHistory {
|
|
||||||
pub fn account(&self) -> &Account {
|
|
||||||
&self.account
|
|
||||||
}
|
|
||||||
pub fn timestamps(&self) -> &Vec<i64> {
|
|
||||||
&self.timestamps
|
|
||||||
}
|
|
||||||
pub fn amount(&self) -> &Vec<i64> {
|
|
||||||
&self.amounts
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_account_history(tx: &Connection, account_id: &AccountId) -> CustomResult<AccountHistory> {
|
|
||||||
let q = "
|
|
||||||
SELECT amount, UNIXEPOCH(timestamp) AS timestamp
|
|
||||||
FROM accounts_history
|
|
||||||
WHERE account_id = ?1
|
|
||||||
ORDER BY account_version ASC
|
|
||||||
";
|
|
||||||
|
|
||||||
let mut stmt = tx.prepare(q).map_err(Error::SqlError)?;
|
|
||||||
let rows = stmt
|
|
||||||
.query_map(params![account_id], |row| Ok((row.get("amount")?, row.get("timestamp")?)))
|
|
||||||
.optional()
|
|
||||||
.map_err(Error::SqlError)?;
|
|
||||||
|
|
||||||
let ret: Vec<(i64, i64)> = rows.map(|x|
|
|
||||||
x.map(Result::unwrap)
|
|
||||||
.collect()).unwrap_or(vec![]);
|
|
||||||
|
|
||||||
let account = accounts::get_account_by_id(tx, account_id)?;
|
|
||||||
let mut amounts: Vec<i64> = ret.iter().map(|r| r.0).collect();
|
|
||||||
let mut timestamps: Vec<i64> = ret.iter().map(|r| r.1).collect();
|
|
||||||
amounts.push(account.amount());
|
|
||||||
timestamps.push(account.timestamp());
|
|
||||||
|
|
||||||
Ok(AccountHistory{account, timestamps, amounts })
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test_account_history {
|
|
||||||
use crate::db::test_utils::setup_basic_environment;
|
|
||||||
use crate::migration;
|
|
||||||
use crate::util::CustomResult;
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
fn setup() -> CustomResult<(Connection, Account)> {
|
|
||||||
let mut conn = Connection::open_in_memory().unwrap();
|
|
||||||
|
|
||||||
migration::apply_migrations(&mut conn).unwrap();
|
|
||||||
let ret = {
|
|
||||||
let mut tx = conn.transaction().unwrap();
|
|
||||||
let (_, _, accounts) = setup_basic_environment(&mut tx)?;
|
|
||||||
tx.commit().unwrap();
|
|
||||||
accounts.get(0).unwrap().clone()
|
|
||||||
};
|
|
||||||
Ok((conn, ret))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_get_account_history_trivial() -> CustomResult<()>{
|
|
||||||
let (mut conn, acc) = setup()?;
|
|
||||||
let acc_hist = get_account_history(&conn, &acc.id())?;
|
|
||||||
assert_eq!(acc_hist.amounts, vec![0, 0]);
|
|
||||||
assert_eq!(acc_hist.timestamps.len(), 2);
|
|
||||||
assert_eq!(acc_hist.account.label(), "acc1");
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_get_account_history_with_transactions() -> CustomResult<()>{
|
|
||||||
let (mut conn, acc) = setup()?;
|
|
||||||
{
|
|
||||||
let tx = conn.transaction().unwrap();
|
|
||||||
accounts::add_to_account(&tx, &acc.id(), 1)?;
|
|
||||||
tx.commit().unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
let tx = conn.transaction().unwrap();
|
|
||||||
let acc_hist = get_account_history(&tx, &acc.id())?;
|
|
||||||
assert_eq!(acc_hist.amounts, vec![0, 1, 1]);
|
|
||||||
assert_eq!(acc_hist.timestamps.len(), 3);
|
|
||||||
assert_eq!(acc_hist.account.label(), "acc1");
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
+22
-5
@@ -120,7 +120,7 @@ impl Clone for Account {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct AccountSnapshot {
|
pub struct AccountSnapshot {
|
||||||
amount: i64,
|
amount: i64,
|
||||||
version: i64,
|
version: i64,
|
||||||
timestamp: i64,
|
timestamp: i64,
|
||||||
@@ -134,9 +134,18 @@ impl AccountSnapshot {
|
|||||||
timestamp: row.get("timestamp")?,
|
timestamp: row.get("timestamp")?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
pub fn amount(&self) -> i64 {
|
||||||
|
self.amount
|
||||||
|
}
|
||||||
|
pub fn version(&self) -> i64 {
|
||||||
|
self.version
|
||||||
|
}
|
||||||
|
pub fn timestamp(&self) -> i64 {
|
||||||
|
self.timestamp
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AccountHistory {
|
pub struct AccountHistory {
|
||||||
id: i64,
|
id: i64,
|
||||||
security: Security,
|
security: Security,
|
||||||
account_type: AccountType,
|
account_type: AccountType,
|
||||||
@@ -165,6 +174,15 @@ impl AccountHistory {
|
|||||||
snapshots,
|
snapshots,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
pub fn security(&self) -> &Security {
|
||||||
|
&self.security
|
||||||
|
}
|
||||||
|
pub fn account_type(&self) -> &AccountType {
|
||||||
|
&self.account_type
|
||||||
|
}
|
||||||
|
pub fn snapshots(&self) -> &Vec<AccountSnapshot> {
|
||||||
|
&self.snapshots
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn list_accounts<'a>(conn: &Connection) -> CustomResult<Vec<Account>> {
|
pub fn list_accounts<'a>(conn: &Connection) -> CustomResult<Vec<Account>> {
|
||||||
@@ -289,7 +307,7 @@ fn create_account(
|
|||||||
return get_account_by_id(tx, &id);
|
return get_account_by_id(tx, &id);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_account_history(tx: &Connection, id: &AccountId) -> CustomResult<AccountHistory> {
|
pub fn get_account_history(tx: &Connection, id: &AccountId) -> CustomResult<AccountHistory> {
|
||||||
let q = "
|
let q = "
|
||||||
SELECT account_version,
|
SELECT account_version,
|
||||||
amount,
|
amount,
|
||||||
@@ -361,7 +379,7 @@ impl AccountChangeReceipt {
|
|||||||
|
|
||||||
fn update_account_history(tx: &Connection, account_id: &AccountId) -> CustomResult<()> {
|
fn update_account_history(tx: &Connection, account_id: &AccountId) -> CustomResult<()> {
|
||||||
let q = "
|
let q = "
|
||||||
INSERT INTO accounts_history
|
INSERT INTO accounts_history(account_id, account_version, amount, timestamp)
|
||||||
SELECT id AS account_id,
|
SELECT id AS account_id,
|
||||||
version AS account_version,
|
version AS account_version,
|
||||||
amount,
|
amount,
|
||||||
@@ -630,7 +648,6 @@ mod test_accounts {
|
|||||||
let (mut conn, users, secs) = setup();
|
let (mut conn, users, secs) = setup();
|
||||||
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 sec_emitter_acc = create_security_emitter_account(&conn, &sec, &user, & "sec emitter acc".to_string())?;
|
|
||||||
let checking_account =
|
let checking_account =
|
||||||
create_checking_account(&conn, &sec, &user, &"checking acc".to_string())?;
|
create_checking_account(&conn, &sec, &user, &"checking acc".to_string())?;
|
||||||
match add_to_account(&conn, &checking_account.id(), -33) {
|
match add_to_account(&conn, &checking_account.id(), -33) {
|
||||||
|
|||||||
+1
-11
@@ -6,7 +6,6 @@ mod _ledger_internal;
|
|||||||
mod _securities;
|
mod _securities;
|
||||||
mod _test_utils;
|
mod _test_utils;
|
||||||
mod _users;
|
mod _users;
|
||||||
mod _account_history;
|
|
||||||
|
|
||||||
pub mod ledger_internal {
|
pub mod ledger_internal {
|
||||||
pub use super::_ledger_internal::*;
|
pub use super::_ledger_internal::*;
|
||||||
@@ -27,16 +26,7 @@ pub mod users {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub mod accounts {
|
pub mod accounts {
|
||||||
pub use super::_accounts::{
|
pub use super::_accounts::*;
|
||||||
add_to_account, create_checking_account, create_security_emitter_account,
|
|
||||||
get_account_by_id, is_owner, list_accounts, Account, AccountChangeReceipt,
|
|
||||||
list_user_accounts, AccountType, get_checking_accounts_for_sec_id, get_number_of_accounts,
|
|
||||||
get_security_market_cap
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod account_history{
|
|
||||||
pub use super::_account_history::get_account_history;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod cheques {
|
pub mod cheques {
|
||||||
|
|||||||
+31
-13
@@ -1,10 +1,10 @@
|
|||||||
use rusqlite::Connection;
|
use rusqlite::Connection;
|
||||||
use crate::db::accounts::{Account, AccountType, get_checking_accounts_for_sec_id, list_user_accounts};
|
use crate::db::accounts::{Account, AccountHistory, AccountType, get_checking_accounts_for_sec_id, list_user_accounts};
|
||||||
use crate::db::external_id::{AccountId, Id, SecurityId, UserId};
|
use crate::db::external_id::{AccountId, Id, SecurityId, UserId};
|
||||||
use crate::util::{CustomResult, Error};
|
use crate::util::{CustomResult, Error};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use crate::db::{account_history, accounts};
|
use crate::db::{accounts};
|
||||||
use crate::db::securities::Security;
|
use crate::db::securities::Security;
|
||||||
use crate::services::_securities::SecurityDTO;
|
use crate::services::_securities::SecurityDTO;
|
||||||
|
|
||||||
@@ -28,9 +28,32 @@ pub struct AccountDTO {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Debug)]
|
#[derive(Serialize, Debug)]
|
||||||
pub struct AccountHistoryDTO {
|
pub struct AccountSnapshotDTO{
|
||||||
amounts: Vec<i64>,
|
amount: i64,
|
||||||
timestamps: Vec<i64>,
|
timestamp: i64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Debug)]
|
||||||
|
pub struct AccountHistoryDTO2{
|
||||||
|
id: String,
|
||||||
|
security: SecurityDTO,
|
||||||
|
account_type: String,
|
||||||
|
snapshots: Vec<AccountSnapshotDTO>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AccountHistoryDTO2 {
|
||||||
|
fn from_entity(entity: &AccountHistory) -> AccountHistoryDTO2{
|
||||||
|
let snapshots = entity.snapshots()
|
||||||
|
.iter()
|
||||||
|
.map(|x| AccountSnapshotDTO{amount: x.amount(), timestamp: x.timestamp() * 1000})
|
||||||
|
.collect();
|
||||||
|
AccountHistoryDTO2{
|
||||||
|
id: entity.id().to_string(),
|
||||||
|
security: SecurityDTO::from_entity(entity.security()),
|
||||||
|
account_type: entity.account_type().to_string(),
|
||||||
|
snapshots
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AccountDTO {
|
impl AccountDTO {
|
||||||
@@ -76,14 +99,9 @@ impl AccountService<'_> {
|
|||||||
Ok(AccountDTO::from_entity(ret))
|
Ok(AccountDTO::from_entity(ret))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_account_history_by_id(&self, account_id: &AccountId, user_id: &UserId) -> CustomResult<AccountHistoryDTO> {
|
pub fn get_account_history_by_id_2(&self, account_id: &AccountId, user_id: &UserId) -> CustomResult<AccountHistoryDTO2> {
|
||||||
let ac = account_history::get_account_history(self.conn, account_id)?;
|
let ac = accounts::get_account_history(self.conn, account_id)?;
|
||||||
// ret.account()
|
Ok(AccountHistoryDTO2::from_entity(&ac))
|
||||||
let ret = AccountHistoryDTO{
|
|
||||||
amounts: ac.amount().clone(),
|
|
||||||
timestamps: ac.timestamps().clone(),
|
|
||||||
};
|
|
||||||
Ok(ret)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_number_of_accounts(&self, sec_id: &SecurityId) -> CustomResult<AccountNumbers>{
|
pub fn get_number_of_accounts(&self, sec_id: &SecurityId) -> CustomResult<AccountNumbers>{
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
pub use crate::services::_authentication::SessionService;
|
pub use crate::services::_authentication::SessionService;
|
||||||
pub use crate::services::_securities::SecurityService;
|
pub use crate::services::_securities::SecurityService;
|
||||||
pub use crate::services::_users::UserService;
|
pub use crate::services::_users::UserService;
|
||||||
pub use crate::services::_accounts::AccountService;
|
pub use crate::services::_accounts::{AccountService};
|
||||||
pub use crate::services::_transactions::cash_wire_transfer_request;
|
pub use crate::services::_transactions::cash_wire_transfer_request;
|
||||||
|
|
||||||
mod _authentication;
|
mod _authentication;
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
use crate::db::external_id::{AccountId, Id};
|
||||||
|
use crate::webui::services::ServicesFactory;
|
||||||
|
use crate::webui::templates::MiniJinjaRenderer;
|
||||||
|
use actix_web::{error, web, HttpRequest, Responder, Result};
|
||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
|
|
||||||
|
struct ResponseData{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#[actix_web::get("/data/accounts/{account_id}/amount-history.json")]
|
||||||
|
pub async fn get_account_amount_history(
|
||||||
|
account_id: web::Path<String>,
|
||||||
|
req: HttpRequest,
|
||||||
|
service_factory: web::Data<ServicesFactory>,
|
||||||
|
) -> Result<impl Responder> {
|
||||||
|
let account_id = AccountId::from_string(&account_id.to_string()).unwrap();
|
||||||
|
|
||||||
|
let conn = service_factory.get_connection()?;
|
||||||
|
let auth_service = service_factory.get_authentication_service(&conn)?;
|
||||||
|
let conn = service_factory.get_connection()?;
|
||||||
|
let account_service = service_factory.get_account_service(&conn)?;
|
||||||
|
let user_id = auth_service.get_login(&req).unwrap();
|
||||||
|
let ac = account_service
|
||||||
|
.get_account_history_by_id_2(&account_id, &user_id)
|
||||||
|
.map_err(error::ErrorInternalServerError)?;
|
||||||
|
|
||||||
|
Ok(web::Json(ac))
|
||||||
|
}
|
||||||
@@ -28,6 +28,7 @@ mod templates;
|
|||||||
mod views;
|
mod views;
|
||||||
mod worker;
|
mod worker;
|
||||||
mod minininja_utils;
|
mod minininja_utils;
|
||||||
|
mod data_views;
|
||||||
|
|
||||||
struct ProductionEventProcessor;
|
struct ProductionEventProcessor;
|
||||||
|
|
||||||
@@ -78,6 +79,7 @@ fn create_views_scope() -> Scope {
|
|||||||
.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)
|
||||||
|
.service(data_views::get_account_amount_history)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
|
|||||||
@@ -46,13 +46,10 @@ pub async fn get_account(tmpl_env: MiniJinjaRenderer,
|
|||||||
|
|
||||||
let ctx = context!{
|
let ctx = context!{
|
||||||
account => account_service.get_account_by_id(&account_id, &user_id).map_err(error::ErrorInternalServerError)?,
|
account => account_service.get_account_by_id(&account_id, &user_id).map_err(error::ErrorInternalServerError)?,
|
||||||
account_history => account_service.get_account_history_by_id(&account_id, &user_id).map_err(error::ErrorInternalServerError)?
|
|
||||||
};
|
};
|
||||||
tmpl_env.render("account.html", ctx)
|
tmpl_env.render("account.html", ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[actix_web::get("/securities")]
|
#[actix_web::get("/securities")]
|
||||||
pub async fn securities(tmpl_env: MiniJinjaRenderer,
|
pub async fn securities(tmpl_env: MiniJinjaRenderer,
|
||||||
service_factory: web::Data<ServicesFactory>) -> actix_web::Result<impl Responder> {
|
service_factory: web::Data<ServicesFactory>) -> actix_web::Result<impl Responder> {
|
||||||
|
|||||||
Executable
+2
@@ -0,0 +1,2 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
cargo run users new --name didier.amyot@gmail.com --public-key fooof
|
||||||
Reference in new issue
Block a user