Skip to content

Commit 0cc0ce5

Browse files
committed
feat: cleanup, API for statement works correctly now
Signed-off-by: Martin <martin@hotmail.com.br>
1 parent a5caddf commit 0cc0ce5

File tree

3 files changed

+88
-70
lines changed

3 files changed

+88
-70
lines changed

src/api/mod.rs

Lines changed: 54 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,16 @@
11
use crate::application::adapters::{StatementDTO, TransactionDTO};
2+
use crate::application::cache::AccountCache;
3+
use crate::application::repositories::TransactionRepository;
24
use crate::application::ServerData;
5+
use crate::domain::account::Account;
36
use crate::domain::transaction::Transaction;
4-
use crate::infrastructure::redis_lock::RedisLock;
57
use crate::infrastructure::server_impl::request::Request;
68
use crate::infrastructure::server_impl::response::{JsonResponse, Response, StatusCode};
79
use crate::infrastructure::server_impl::server::Method;
8-
use crate::{AnyResult, Statement};
9-
use compact_str::CompactString;
10+
use crate::AnyResult;
1011
use eyre::bail;
11-
use redis::streams::StreamRangeReply;
12-
use redis::{AsyncCommands, Client, Value};
13-
use serde::{Deserialize, Serialize};
14-
use std::mem;
15-
use std::sync::Arc;
16-
use time::OffsetDateTime;
12+
use fnv::FnvHashMap;
13+
use std::sync::{Arc, Mutex};
1714

1815
pub mod input_types;
1916

@@ -28,13 +25,16 @@ pub async fn statement_route(
2825
bail!("Only GET available.")
2926
}
3027

31-
let my = Statement {
32-
balance: 0,
33-
time_of_statement: OffsetDateTime::now_utc(),
34-
credit_limit: 0,
28+
let service = BankAccountService {
29+
re_conn: server_data.re_conn.clone(),
30+
pg_conn: server_data.pg_pool.clone(),
3531
};
3632

37-
let a = JsonResponse::from::<StatementDTO>(my.into());
33+
let res = service
34+
.query(AccountQueries::Statement { account: client_id })
35+
.await;
36+
37+
let a = JsonResponse::from::<StatementDTO>(StatementDTO::from_other(res));
3838
Ok(a.0)
3939
}
4040

@@ -54,7 +54,7 @@ pub async fn transaction_route(
5454
.unwrap();
5555

5656
let mapping = serde_json::from_slice::<TransactionDTO>(body)
57-
.map_err(|e| ())
57+
.map_err(|_| ())
5858
.and_then(|c| c.try_into());
5959

6060
let transaction: Transaction = match mapping {
@@ -83,69 +83,78 @@ pub async fn transaction_route(
8383
// -> insert transaction and balance on redis
8484
// -> remove lock
8585

86-
let command = AccountCommands::WithdrawMoney {
86+
let command = AccountCommands::HandleMoney {
8787
account: client_id,
88-
transaction: &transaction,
88+
transaction,
8989
};
9090

91-
let res = BankAccountService {
91+
let bank_service = BankAccountService {
9292
re_conn: server_data.re_conn.clone(),
9393
pg_conn: server_data.pg_pool.clone(),
94-
}
95-
.handler(command)
96-
.await;
94+
};
95+
let res = bank_service.handler(command).await;
96+
97+
// if res.is_err() {
98+
// return Ok(Response::from_status_code(
99+
// StatusCode::UnprocessableEntity,
100+
// None,
101+
// ));
102+
// }
97103

98-
let a = JsonResponse::from::<TransactionDTO>(transaction.into());
104+
let a =
105+
JsonResponse::from::<TransactionDTO>(TransactionDTO::from(Transaction::generate(1, None)));
99106
Ok(a.0)
100107
}
101108

109+
pub type AccountMapStorage = Arc<FnvHashMap<i32, (u32, Mutex<Account>)>>;
110+
102111
struct BankAccountService {
103112
re_conn: redis::aio::ConnectionManager,
104113
pg_conn: deadpool_postgres::Pool,
114+
// storage: AccountMapStorage,
105115
}
106116

107-
enum AccountCommands<'a> {
108-
DepositMoney {
109-
user: i32,
110-
amount: &'a Transaction,
111-
},
112-
WithdrawMoney {
117+
#[derive(Debug)]
118+
enum AccountCommands {
119+
HandleMoney {
113120
account: i32,
114-
transaction: &'a Transaction,
121+
transaction: Transaction,
115122
},
116123
}
117124

125+
#[derive(Debug)]
118126
enum AccountQueries {
119-
Statement,
127+
Statement { account: i32 },
120128
}
121129

122130
impl BankAccountService {
123-
async fn handler(&self, command: AccountCommands<'_>) {
131+
async fn query(&self, command: AccountQueries) -> (Account, impl Iterator<Item = Transaction>) {
124132
match command {
125-
AccountCommands::DepositMoney { .. } => unimplemented!(),
126-
AccountCommands::WithdrawMoney {
133+
AccountQueries::Statement { account: user } => {
134+
let trans_cache = AccountCache {
135+
re_conn: self.re_conn.clone(),
136+
};
137+
138+
let res = trans_cache.get_account(user, true).await;
139+
(res.0, res.1.unwrap())
140+
}
141+
}
142+
}
143+
async fn handler(&self, command: AccountCommands) -> AnyResult<()> {
144+
match command {
145+
AccountCommands::HandleMoney {
127146
account: user,
128147
transaction,
129148
} => {
130149
let trans_repo = TransactionRepository {
131150
conn: self.pg_conn.clone(),
132151
};
133152

134-
let trans_cache = TransactionCache {
153+
let trans_cache = AccountCache {
135154
re_conn: self.re_conn.clone(),
136155
};
137156

138-
let redis_lock = RedisLock::new(self.re_conn.clone(), user, 100);
139-
{
140-
let guard = redis_lock.acquire().await.unwrap();
141-
trans_repo.save_transaction(user, transaction).await;
142-
trans_cache.append(user, transaction).await;
143-
guard.release().await;
144-
}
145-
}
146-
}
147-
}
148-
}
157+
// let redis_lock = RedisLock::new(self.re_conn.clone(), user, 100);
149158

150159
let (acc, _) = trans_cache.get_account(user, false).await;
151160
let acc = acc

src/application/adapters/mod.rs

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1+
use crate::domain::account::Account;
12
use crate::domain::transaction::{Transaction, TransactionDescription, TransactionKind};
2-
use crate::Statement;
33
use compact_str::{CompactString, ToCompactString};
44
use serde::{Deserialize, Serialize};
55
use std::borrow::Cow;
@@ -10,26 +10,41 @@ use time::OffsetDateTime;
1010
#[allow(non_camel_case_types)]
1111
#[derive(Debug, Serialize)]
1212
pub struct StatementDTO {
13+
#[serde(rename = "saldo")]
14+
saldo: SaldoDTO,
15+
#[serde(rename = "ultimas_transacoes")]
16+
transactions: Vec<TransactionDTO<'static>>,
17+
}
18+
19+
#[allow(non_camel_case_types)]
20+
#[derive(Debug, Serialize)]
21+
pub struct SaldoDTO {
1322
#[serde(rename = "total")]
1423
total_balance: i32,
1524
#[serde(rename = "data_extrato")]
1625
data_extrato: CompactString,
1726
#[serde(rename = "limite")]
1827
credit_limit: u32,
1928
}
20-
21-
impl From<Statement> for StatementDTO {
22-
fn from(value: Statement) -> Self {
23-
let formatted = value
24-
.time_of_statement
29+
impl StatementDTO {
30+
pub fn from_other(value: (Account, impl Iterator<Item = Transaction>)) -> Self {
31+
let formatted = OffsetDateTime::now_utc()
2532
.format(&Iso8601::DEFAULT)
2633
.unwrap()
2734
.to_compact_string();
2835

36+
let acc = value.0;
37+
let transactions = value.1;
2938
Self {
30-
total_balance: value.balance,
31-
data_extrato: formatted,
32-
credit_limit: value.credit_limit,
39+
saldo: SaldoDTO {
40+
total_balance: acc.balance,
41+
data_extrato: formatted,
42+
credit_limit: acc.credit_limit,
43+
},
44+
transactions: transactions
45+
.into_iter()
46+
.map(TransactionDTO::from)
47+
.collect::<Vec<_>>(),
3348
}
3449
}
3550
}
@@ -59,11 +74,15 @@ impl TryFrom<TransactionDTO<'_>> for Transaction {
5974
_ => return Err(()),
6075
};
6176

62-
let description = TransactionDescription::new(&value.description).map_err(|e| {
77+
let description = TransactionDescription::new(&value.description).map_err(|_| {
6378
eprintln!("desc error");
64-
()
6579
})?;
66-
let amount = NonZeroI32::new(value.amount).ok_or(())?;
80+
81+
let amount = if matches!(kind, TransactionKind::Debit) {
82+
NonZeroI32::new(-value.amount).ok_or(())?
83+
} else {
84+
NonZeroI32::new(value.amount).ok_or(())?
85+
};
6786

6887
Ok(Self {
6988
valor: amount,
@@ -82,7 +101,7 @@ impl From<Transaction> for TransactionDTO<'_> {
82101
};
83102

84103
let description = value.descricao.0.into();
85-
let amount = i32::from(value.valor);
104+
let amount = i32::from(value.valor.abs());
86105
let created_on = Some(value.realizada_em.format(&Iso8601::DEFAULT).unwrap().into());
87106

88107
Self {

src/application/mod.rs

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,8 @@
11
pub mod adapters;
2+
pub mod cache;
3+
pub mod repositories;
24

35
use deadpool_postgres::Pool;
4-
use std::sync::Arc;
5-
6-
#[derive(Copy, Clone, Debug)]
7-
pub struct AccountService {}
8-
9-
impl AccountService {
10-
fn get_balance() {
11-
12-
// get user from database
13-
// and store transactions on redis so we can get to the balance faster
14-
}
15-
}
166

177
#[derive(Clone)]
188
pub struct ServerData {

0 commit comments

Comments
 (0)