Skip to content

Commit

Permalink
perf(api-finance): optimize retrieve and list methods more simple
Browse files Browse the repository at this point in the history
  • Loading branch information
spicyzboss committed Jan 19, 2024
1 parent 205642d commit d858f8d
Show file tree
Hide file tree
Showing 18 changed files with 269 additions and 133 deletions.
8 changes: 4 additions & 4 deletions libs/core_finance/src/domain/entities/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
mod tags;
mod tags_on_transaction;
mod tag;
mod tag_on_transaction;
mod transaction;
mod transaction_type;

pub use tags::Tags;
pub use tags_on_transaction::TagsOnTransaction;
pub use tag::{Tag, TagCreateParams};
pub use tag_on_transaction::TagOnTransaction;
pub use transaction::{Transaction, TransactionCreateParams};
pub use transaction_type::TransactionType;
14 changes: 14 additions & 0 deletions libs/core_finance/src/domain/entities/tag.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Clone)]
pub struct Tag {
pub id: i32,
pub name: String,
pub created_at: String,
pub updated_at: String,
}

#[derive(Serialize, Deserialize, Clone)]
pub struct TagCreateParams {
pub name: String,
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Clone)]
pub struct TagsOnTransaction {
pub struct TagOnTransaction {
pub transaction_id: String,
pub tag_id: i32,
pub created_at: String,
Expand Down
2 changes: 1 addition & 1 deletion libs/core_finance/src/domain/entities/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Transaction {
pub id: String,
pub r#type: Option<String>,
pub r#type: String,
pub amount: i32,
pub tags: Option<Vec<String>>,
pub created_at: String,
Expand Down
7 changes: 2 additions & 5 deletions libs/core_finance/src/domain/entities/transaction_type.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
use crate::domain::entities::{Tags, Transaction};
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Clone)]
pub struct TransactionType {
pub transaction_id: String,
pub tag_id: i32,
pub id: i32,
pub name: String,
pub created_at: String,
pub updated_at: String,
pub transaction: Option<Box<Transaction>>,
pub tags: Option<Box<Tags>>,
}
2 changes: 2 additions & 0 deletions libs/core_finance/src/domain/repositories/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
mod repository;
mod tag;
mod transaction;

pub use repository::{
PaginationResult, QueryParams, QueryParamsImpl, RepositoryResult, DEFAULT_LIMIT, DEFAULT_OFFSET,
};
pub use tag::{TagQueryParams, TagRepository};
pub use transaction::{TransactionQueryParams, TransactionRepository};
5 changes: 4 additions & 1 deletion libs/core_finance/src/domain/repositories/repository.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ pub type RepositoryResult<T> = Result<T, RepositoryError>;

#[derive(Debug, Serialize, Deserialize)]
pub struct PaginationResult<T> {
pub total: i64,
pub items: Vec<T>,
// pub page: i64,
// pub per_page: i64,
pub total: i64,
// pub page_count: i64,
}

pub const DEFAULT_OFFSET: Option<i64> = Some(0);
Expand Down
31 changes: 31 additions & 0 deletions libs/core_finance/src/domain/repositories/tag.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use crate::domain::{
entities::{Tag, TagCreateParams},
repositories::repository::{
PaginationResult, QueryParams, RepositoryResult, DEFAULT_LIMIT, DEFAULT_OFFSET,
},
};
use async_trait::async_trait;
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize)]
pub struct TagQueryParams {
pub limit: Option<i64>,
pub offset: Option<i64>,
}

impl QueryParams for TagQueryParams {
fn limit(&self) -> i64 {
self.limit.or(DEFAULT_LIMIT).unwrap_or_default()
}

fn offset(&self) -> i64 {
self.offset.or(DEFAULT_OFFSET).unwrap_or_default()
}
}

#[async_trait(?Send)]
pub trait TagRepository {
async fn create(&self, new_tag: TagCreateParams) -> RepositoryResult<Tag>;
async fn retrieve(&self, transaction_id: String) -> RepositoryResult<Tag>;
async fn list(&self, params: TagQueryParams) -> RepositoryResult<PaginationResult<Tag>>;
}
4 changes: 4 additions & 0 deletions libs/core_finance/src/infrastructure/entities/d1/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
mod tag;
mod transaction;
mod transaction_type;

pub use tag::D1Tag;
pub use transaction::D1Transaction;
pub use transaction_type::D1TransactionType;
22 changes: 22 additions & 0 deletions libs/core_finance/src/infrastructure/entities/d1/tag.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use serde::{Deserialize, Serialize};

use crate::domain::entities::Tag;

#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct D1Tag {
pub id: i32,
pub name: String,
pub created_at: String,
pub updated_at: String,
}

impl From<D1Tag> for Tag {
fn from(tag: D1Tag) -> Tag {
Tag {
id: tag.id,
name: tag.name,
created_at: tag.created_at,
updated_at: tag.updated_at,
}
}
}
90 changes: 21 additions & 69 deletions libs/core_finance/src/infrastructure/entities/d1/transaction.rs
Original file line number Diff line number Diff line change
@@ -1,84 +1,36 @@
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;

use crate::domain::{entities::Transaction, repositories::PaginationResult};
use crate::domain::entities::Transaction;

#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct D1Transaction {
pub id: String,
pub transaction_type_id: i32,
pub r#type: String,
pub amount: i32,
pub tags: Option<String>,
pub created_at: String,
pub updated_at: String,
pub tag: Option<String>,
pub r#type: Option<String>,
}

impl From<Vec<D1Transaction>> for Transaction {
fn from(transactions: Vec<D1Transaction>) -> Transaction {
transactions
.into_iter()
.fold(BTreeMap::new(), |mut acc, transaction| {
acc
.entry(transaction.id.clone())
.or_insert_with(|| Transaction {
id: transaction.id,
r#type: transaction.r#type,
amount: transaction.amount,
tags: Some(Vec::new()),
created_at: transaction.created_at,
updated_at: transaction.updated_at,
})
.tags
.as_mut()
.map(|tags| {
if let Some(tag) = transaction.tag {
tags.push(tag)
}
});
impl From<D1Transaction> for Transaction {
fn from(transaction: D1Transaction) -> Transaction {
let tags = match transaction.tags {
Some(tags) => Some(
tags
.split(',')
.map(|tag| tag.to_string())
.collect::<Vec<String>>(),
),
None => None,
};

acc
})
.into_iter()
.map(|(_, v)| v)
.collect::<Vec<Transaction>>()
.get(0)
.unwrap()
.clone()
}
}

impl From<Vec<D1Transaction>> for PaginationResult<Transaction> {
fn from(transactions: Vec<D1Transaction>) -> PaginationResult<Transaction> {
PaginationResult {
total: transactions.len() as i64,
items: transactions
.into_iter()
.fold(BTreeMap::new(), |mut acc, transaction| {
acc
.entry(transaction.id.clone())
.or_insert_with(|| Transaction {
id: transaction.id,
r#type: transaction.r#type,
amount: transaction.amount,
tags: Some(Vec::new()),
created_at: transaction.created_at,
updated_at: transaction.updated_at,
})
.tags
.as_mut()
.map(|tags| {
if let Some(tag) = transaction.tag {
tags.push(tag)
}
});

acc
})
.into_iter()
.map(|(_, v)| v)
.collect::<Vec<Transaction>>()
.clone(),
Transaction {
id: transaction.id,
r#type: transaction.r#type,
amount: transaction.amount,
created_at: transaction.created_at,
updated_at: transaction.updated_at,
tags,
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Clone)]
pub struct Tags {
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct D1TransactionType {
pub id: i32,
pub name: String,
pub created_at: String,
Expand Down
2 changes: 1 addition & 1 deletion libs/core_finance/src/infrastructure/entities/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
mod d1;

pub use d1::D1Transaction;
pub use d1::{D1Tag, D1Transaction, D1TransactionType};
4 changes: 2 additions & 2 deletions libs/core_finance/src/infrastructure/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ mod entities;
mod errors;
mod repositories;

pub use entities::D1Transaction;
pub use entities::{D1Tag, D1Transaction, D1TransactionType};
pub use errors::D1RepositoryError;
pub use repositories::TransactionD1Repository;
pub use repositories::{TagD1Repository, TransactionD1Repository};
2 changes: 2 additions & 0 deletions libs/core_finance/src/infrastructure/repositories/d1/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
mod tag;
mod transaction;

pub use tag::TagD1Repository;
pub use transaction::TransactionD1Repository;
108 changes: 108 additions & 0 deletions libs/core_finance/src/infrastructure/repositories/d1/tag.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
use std::sync::Arc;

use crate::{
domain::{
entities::{Tag, TagCreateParams},
repositories::{PaginationResult, RepositoryResult, TagQueryParams, TagRepository},
},
infrastructure::{errors::D1RepositoryError, D1Tag},
};

use async_trait::async_trait;
use uuid::Uuid;
use worker::D1Database;

pub struct TagD1Repository {
pub db: Arc<D1Database>,
}

impl TagD1Repository {
pub fn new(db: Arc<D1Database>) -> Self {
TagD1Repository { db }
}
}

#[async_trait(?Send)]
impl TagRepository for TagD1Repository {
async fn create(&self, new_tag: TagCreateParams) -> RepositoryResult<Tag> {
let id = Uuid::new_v4().to_string();

let statement = self.db.prepare(
"
INSERT INTO tags (name)
VALUES (?1);
",
);

let query = statement
.bind(&[new_tag.name.into()])
.map_err(|v| D1RepositoryError::from(v).into_inner())?;

let query_result = query
.run()
.await;

match query_result {
Ok(_) => {}
Err(e) => return Err(D1RepositoryError::from(e).into_inner()),
}

let result = self
.retrieve(id)
.await
.map_err(|v| D1RepositoryError::from(v).into_inner())?;

Ok(result)
}

async fn retrieve(&self, tag_id: String) -> RepositoryResult<Tag> {
let statement = self.db.prepare(
"
SELECT id, name, created_at, updated_at
FROM tags
WHERE id = ?1;
",
);

let query = statement
.bind(&[tag_id.into()])
.map_err(|v| D1RepositoryError::from(v).into_inner())?;

let result = query
.first::<D1Tag>(None)
.await
.map_err(|v| D1RepositoryError::from(v).into_inner())?
.ok_or(String::from("Tag not found"))
.map_err(|v| D1RepositoryError::from(v).into_inner())?;

Ok(result.into())
}

async fn list(&self, _params: TagQueryParams) -> RepositoryResult<PaginationResult<Tag>> {
let statement = self.db.prepare(
"
SELECT id, name
FROM tags
ORDER BY id ASC
",
);

let query = statement
.bind(&[])
.map_err(|v| D1RepositoryError::from(v).into_inner())?;

let d1_result = query
.all()
.await
.map_err(|v| D1RepositoryError::from(v).into_inner())?;

let result = d1_result
.results::<D1Tag>()
.map_err(|v| D1RepositoryError::from(v).into_inner())?;

Ok(PaginationResult {
total: result.len() as i64,
items: result.into_iter().map(|v| v.into()).collect(),
})
}
}
Loading

0 comments on commit d858f8d

Please sign in to comment.