You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
fast-insiders/server/src/repo/transaction.rs

139 lines
4.2 KiB

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<String>,
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<String>,
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<C>(
&self,
db: &C,
) -> Result<(model::transaction::Model, Option<model::company::Model>), 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<C>(&self, db: &C) -> Result<model::transaction::Model, TransactionRepoError>
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,
}