use crate::amf::types::TransactionData; use crate::model; use chrono::NaiveDate; use sea_orm::error::DbErr; use sea_orm::ConnectionTrait; use sea_orm::{ ActiveModelTrait, ColumnTrait, DeriveIntoActiveModel, EntityTrait, IntoActiveModel, QueryFilter, }; use serde::{Deserialize, Serialize}; use thiserror::Error; use super::company::{CompanyRepoError, NewCompany}; type ActiveModel = model::transaction::ActiveModel; #[derive(Debug, PartialEq, Clone, DeriveIntoActiveModel, Serialize, Deserialize)] struct NewTransaction { pub company_id: i32, pub foreign_id: String, pub date_published: NaiveDate, pub date_executed: NaiveDate, pub person: String, pub exchange: String, pub nature: String, pub isin: Option, pub instrument: String, pub volume: i32, pub unit_price: f32, } pub struct NewTransactionFromTransactionData { pub company_name: String, pub date_published: NaiveDate, pub date_executed: NaiveDate, pub person: String, pub exchange: String, pub nature: String, pub isin: Option, pub instrument: String, pub volume: i32, pub unit_price: f32, pub foreign_id: String, } impl NewTransactionFromTransactionData { pub fn new_from_transaction_data(data: TransactionData) -> Self { NewTransactionFromTransactionData { foreign_id: data.foreign_id, company_name: data.company_name, date_published: data.date_published, date_executed: data.date_executed, person: data.person, exchange: data.exchange, nature: data.nature, isin: data.isin, instrument: data.instrument, volume: data.volume as i32, unit_price: data.unit_price, } } pub async fn create( &self, db: &C, ) -> Result<(model::transaction::Model, Option), TransactionRepoError> where C: ConnectionTrait, { let comp; if let Some(c) = model::company::Entity::find() .filter(model::company::Column::Name.eq(self.company_name.to_owned())) .one(db) .await .map_err(TransactionRepoError::DatabaseError)? { comp = c; } else { let name = self.company_name.to_owned(); info!("Company {} will be created", name); let new_comp = NewCompany::new(name); comp = new_comp .create(db) .await .map_err(TransactionRepoError::CompanyCreationError)?; } let new_tr = NewTransaction { company_id: comp.id, foreign_id: self.foreign_id.to_owned(), date_published: self.date_published, date_executed: self.date_executed, person: self.person.to_owned(), exchange: self.exchange.to_owned(), nature: self.nature.to_owned(), isin: self.isin.to_owned(), instrument: self.instrument.to_owned(), volume: self.volume, unit_price: self.unit_price, }; let res = new_tr.create(db).await?; let ret = model::transaction::Entity::find_by_id(res.id) .find_also_related(model::company::Entity) .one(db) .await .map_err(TransactionRepoError::DatabaseError)? .ok_or(TransactionRepoError::CreatedTransactionNotFound)?; Ok(ret) } } impl NewTransaction { async fn create(&self, db: &C) -> Result where C: ConnectionTrait, { let res = self .clone() .into_active_model() .insert(db) .await .map_err(TransactionRepoError::TransactionCreationError)?; Ok(res) } } #[derive(Debug, Error)] pub enum TransactionRepoError { #[error("Error creating transaction record: {0}")] TransactionCreationError(DbErr), #[error("Error creating company record: {0}")] CompanyCreationError(CompanyRepoError), #[error("Error finding company record: {0}")] DatabaseError(DbErr), #[error("The created transaction has not been found")] CreatedTransactionNotFound, }