Fix most of clippy's warnings #14

Merged
alban merged 1 commits from clippy into master 3 years ago

@ -11,7 +11,7 @@ pub async fn get_transactions(
let res = reqwasm::http::Request::get(&format!( let res = reqwasm::http::Request::get(&format!(
"{}transaction{}?page={}&size={}", "{}transaction{}?page={}&size={}",
Config::new().api_url, Config::new().api_url,
company_slug.unwrap_or("".to_string()), company_slug.unwrap_or_default(),
page, page,
size, size,
)) ))

@ -11,6 +11,6 @@ pub struct Company {
impl IntoAsyncSelectListItem for Company { impl IntoAsyncSelectListItem for Company {
fn to_select_list_item(&self) -> String { fn to_select_list_item(&self) -> String {
format!("{}", self.name) self.name.to_string()
} }
} }

@ -60,7 +60,7 @@ where
let t1 = t.clone(); let t1 = t.clone();
res.push(view! { (t1.nature.to_owned()) }); res.push(view! { (t1.nature.to_owned()) });
let t1 = t.clone(); let t1 = t.clone();
res.push(view! { (t1.isin.to_owned().unwrap_or("-".to_string())) }); res.push(view! { (t1.isin.to_owned().unwrap_or_else(|| "-".to_string())) });
let t1 = t.clone(); let t1 = t.clone();
res.push(view! { (t1.instrument.to_owned()) }); res.push(view! { (t1.instrument.to_owned()) });
let t1 = t.clone(); let t1 = t.clone();
@ -69,8 +69,7 @@ where
res.push(view! { (t1.volume.to_owned()) }); res.push(view! { (t1.volume.to_owned()) });
let t1 = t.clone(); let t1 = t.clone();
res.push(view! { (t1.unit_price.to_owned()) }); res.push(view! { (t1.unit_price.to_owned()) });
let t1 = t.clone(); res.push(view! { ((t.volume as f32 * t.unit_price).to_string()) });
res.push(view! { ((t1.volume as f32 * t1.unit_price).to_string()) });
res res
}) })

@ -108,7 +108,7 @@ where
"<<" "<<"
} }
div (class="m-1 align-middle text-center") { div (class="m-1 align-middle text-center") {
(format!("{}/{}",(*page.get() + 1).to_string(), *n_page.get()) ) (format!("{}/{}",*page.get() + 1, *n_page.get()) )
} }
button (on:click=page_up, class="m-1 hover:font-bold") { button (on:click=page_up, class="m-1 hover:font-bold") {
">>" ">>"

@ -13,3 +13,9 @@ impl Config {
Config { api_url } Config { api_url }
} }
} }
impl Default for Config {
fn default() -> Self {
Config::new()
}
}

@ -7,5 +7,5 @@ pub mod types;
pub trait TransactionDataTrait { pub trait TransactionDataTrait {
type Err; type Err;
async fn get_transaction_data(self: &Self) -> Result<TransactionData, Self::Err>; async fn get_transaction_data(&self) -> Result<TransactionData, Self::Err>;
} }

@ -20,7 +20,7 @@ impl AMFResponse {
#[async_trait::async_trait] #[async_trait::async_trait]
impl TransactionDataTrait for Hit { impl TransactionDataTrait for Hit {
type Err = GetAMFTransactionsError; type Err = GetAMFTransactionsError;
async fn get_transaction_data(self: &Self) -> Result<TransactionData, Self::Err> { async fn get_transaction_data(&self) -> Result<TransactionData, Self::Err> {
let foreign_id = self.source.numero.to_owned(); let foreign_id = self.source.numero.to_owned();
let docs = self.get_documents(); let docs = self.get_documents();
if docs.len() > 1 { if docs.len() > 1 {
@ -29,15 +29,14 @@ impl TransactionDataTrait for Hit {
let doc_path = &docs let doc_path = &docs
.first() .first()
.ok_or(GetAMFTransactionsError::NoDocumentError( .ok_or_else(|| GetAMFTransactionsError::NoDocument(foreign_id.to_owned()))?
foreign_id.to_owned(),
))?
.path; .path;
let amf_pdf = AMFPdf::new(&doc_path); let amf_pdf = AMFPdf::new(doc_path);
let info = amf_pdf.extract_info().await.map_err(|e| { let info = amf_pdf
GetAMFTransactionsError::InformationExtractionError(doc_path.to_string(), e) .extract_info()
})?; .await
.map_err(|e| GetAMFTransactionsError::InformationExtraction(doc_path.to_string(), e))?;
Ok(TransactionData { Ok(TransactionData {
foreign_id, foreign_id,

@ -7,11 +7,11 @@ use crate::CONFIG;
#[derive(Debug, Error)] #[derive(Debug, Error)]
pub enum AMFRequestError { pub enum AMFRequestError {
#[error("Request error: {0}")] #[error("Request error: {0}")]
RequestError(reqwest::Error), Request(reqwest::Error),
#[error("Json conversion error: {0}")] #[error("Json conversion error: {0}")]
JsonConversionError(reqwest::Error), JsonConversion(reqwest::Error),
#[error("Status code error: {0}")] #[error("Status code error: {0}")]
StatusCodeError(reqwest::Error), StatusCode(reqwest::Error),
} }
pub struct AMFRequest { pub struct AMFRequest {
@ -30,14 +30,14 @@ impl AMFRequest {
} }
pub async fn get_list(&self) -> Result<AMFResponse, AMFRequestError> { pub async fn get_list(&self) -> Result<AMFResponse, AMFRequestError> {
Ok(reqwest::get(&self.url) reqwest::get(&self.url)
.await .await
.map_err(|e| AMFRequestError::RequestError(e))? .map_err(AMFRequestError::Request)?
.error_for_status() .error_for_status()
.map_err(|e| AMFRequestError::StatusCodeError(e))? .map_err(AMFRequestError::StatusCode)?
.json::<AMFResponse>() .json::<AMFResponse>()
.await .await
.map_err(|e| AMFRequestError::JsonConversionError(e))?) .map_err(AMFRequestError::JsonConversion)
} }
} }

@ -13,47 +13,47 @@ pub struct AMFPdf {
} }
#[derive(Debug, Error)] #[derive(Debug, Error)]
pub enum PatternExtractionError { pub enum PatternExtractionNotFoundError {
#[error("Person not found")] #[error("Person not found")]
PersonNotFoundError, Person,
#[error("Date executed not found")] #[error("Date executed not found")]
DateExecutedNotFoundError, DateExecuted,
#[error("Date published not found")] #[error("Date published not found")]
DatePublishedNotFoundError, DatePublished,
#[error("Exchange not found")] #[error("Exchange not found")]
ExchangeNotFoundError, Exchange,
#[error("Nature not found")] #[error("Nature not found")]
NatureNotFoundError, Nature,
#[error("Instrument not found")] #[error("Instrument not found")]
InstrumentNotFoundError, Instrument,
#[error("Coordonnees section not found")] #[error("Coordonnees section not found")]
CoordonneesNotFound, Coordonnees,
#[error("Company name not found")] #[error("Company name not found")]
CompanyNameNotFound, CompanyName,
#[error("Aggregated informations not found")] #[error("Aggregated informations not found")]
AggregatedInformationNotFoundError, AggregatedInformation,
#[error("Volume not found")] #[error("Volume not found")]
VolumeNotFoundError, Volume,
#[error("Price not found")] #[error("Price not found")]
PriceNotFoundError, PriceNotFound,
} }
#[derive(Debug, Error)] #[derive(Debug, Error)]
pub enum AMFPdfError { pub enum AMFPdfError {
#[error("Download error: {0}")] #[error("Download error: {0}")]
DownloadError(reqwest::Error), Download(reqwest::Error),
#[error("Bytes conversion error: {0}")] #[error("Bytes conversion error: {0}")]
BytesConversionError(reqwest::Error), BytesConversion(reqwest::Error),
#[error("Error loading pdf document: {0}")] #[error("Error loading pdf document: {0}")]
DocumentLoadError(lopdf::Error), DocumentLoad(lopdf::Error),
#[error("Error during lopdf text extraction: {0}")] #[error("Error during lopdf text extraction: {0}")]
PdfTextExtractionError(lopdf::Error), PdfTextExtraction(lopdf::Error),
#[error("Error during extraction of information: {0}")] #[error("Error during extraction of information: {0}")]
PatternExtractionError(PatternExtractionError), PatternExtraction(PatternExtractionNotFoundError),
#[error("Error parsing date: {0}")] #[error("Error parsing date: {0}")]
DateParseError(DateParseError), DateParse(DateParseError),
#[error("Error parsing unit price: {0}")] #[error("Error parsing unit price: {0}")]
PriceParseError(ParseFloatError), PriceParse(ParseFloatError),
#[error("Error parsing volume: {0}")] #[error("Error parsing volume: {0}")]
VolumeParseError(ParseFloatError), VolumeParseError(ParseFloatError),
} }
@ -72,30 +72,29 @@ pub struct AMFPdfData {
} }
impl AMFPdf { impl AMFPdf {
pub fn new(path: &String) -> AMFPdf { pub fn new(path: &str) -> AMFPdf {
let mut url = (&CONFIG.amf_documents_path).to_string(); let mut url = CONFIG.amf_documents_path.to_string();
url.push_str(&path); url.push_str(path);
AMFPdf { url } AMFPdf { url }
} }
async fn download(&self) -> Result<Bytes, AMFPdfError> { async fn download(&self) -> Result<Bytes, AMFPdfError> {
Ok(reqwest::get(&self.url) reqwest::get(&self.url)
.await .await
.map_err(|e| AMFPdfError::DownloadError(e))? .map_err(AMFPdfError::Download)?
.bytes() .bytes()
.await .await
.map_err(|e| AMFPdfError::BytesConversionError(e))?) .map_err(AMFPdfError::BytesConversion)
} }
async fn extract_text(&self) -> Result<String, AMFPdfError> { async fn extract_text(&self) -> Result<String, AMFPdfError> {
let bfile = self.download().await?; let bfile = self.download().await?;
let pdf = let pdf = lopdf::Document::load_mem(&bfile).map_err(AMFPdfError::DocumentLoad)?;
lopdf::Document::load_mem(&bfile).map_err(|e| AMFPdfError::DocumentLoadError(e))?;
let mut text = "".to_string(); let mut text = "".to_string();
for (idx, _) in pdf.page_iter().enumerate() { for (idx, _) in pdf.page_iter().enumerate() {
text.push_str( text.push_str(
&pdf.extract_text(&[idx as u32 + 1]) &pdf.extract_text(&[idx as u32 + 1])
.map_err(|e| AMFPdfError::PdfTextExtractionError(e))?, .map_err(AMFPdfError::PdfTextExtraction)?,
); );
} }
Ok(text) Ok(text)
@ -117,7 +116,7 @@ impl AMFPdf {
.skip_while(|l| l.is_empty()) .skip_while(|l| l.is_empty())
.nth(1) .nth(1)
.unwrap() .unwrap()
.split(" ") .split(' ')
.next() .next()
.unwrap() .unwrap()
.get(0..12) .get(0..12)
@ -130,82 +129,77 @@ impl AMFPdf {
let person = extract_pattern( let person = extract_pattern(
&text, &text,
&"NOM /FONCTION DE LA PERSONNE EXERCANT DES RESPONSABILITES DIRIGEANTES OU DE LAPERSONNE ETROITEMENT LIEE :\n", "NOM /FONCTION DE LA PERSONNE EXERCANT DES RESPONSABILITES DIRIGEANTES OU DE LAPERSONNE ETROITEMENT LIEE :\n",
"\n", "\n",
) )
.ok_or(AMFPdfError::PatternExtractionError( .ok_or_else(|| AMFPdfError::PatternExtraction(
PatternExtractionError::PersonNotFoundError, PatternExtractionNotFoundError::Person,
))?; ))?;
let date_published_raw = let date_published_raw =
extract_pattern(&text, &"DATE DE RECEPTION DE LA NOTIFICATION : ", &"\n").ok_or( extract_pattern(&text, "DATE DE RECEPTION DE LA NOTIFICATION : ", "\n").ok_or_else(
AMFPdfError::PatternExtractionError( || AMFPdfError::PatternExtraction(PatternExtractionNotFoundError::DatePublished),
PatternExtractionError::DatePublishedNotFoundError,
),
)?; )?;
let date_published = let date_published =
naive_date_from_str(&date_published_raw).map_err(|e| AMFPdfError::DateParseError(e))?; naive_date_from_str(&date_published_raw).map_err(AMFPdfError::DateParse)?;
let date_executed_raw = extract_pattern(&text, &"DATE DE LA TRANSACTION : ", &"\n").ok_or( let date_executed_raw = extract_pattern(&text, "DATE DE LA TRANSACTION : ", "\n")
AMFPdfError::PatternExtractionError(PatternExtractionError::DateExecutedNotFoundError), .ok_or_else(|| {
)?; AMFPdfError::PatternExtraction(PatternExtractionNotFoundError::DateExecuted)
})?;
let date_executed = let date_executed =
naive_date_from_str(&date_executed_raw).map_err(|e| AMFPdfError::DateParseError(e))?; naive_date_from_str(&date_executed_raw).map_err(AMFPdfError::DateParse)?;
let exchange = extract_pattern(&text, &"LIEU DE LA TRANSACTION : ", &"\n").ok_or( let exchange =
AMFPdfError::PatternExtractionError(PatternExtractionError::ExchangeNotFoundError), extract_pattern(&text, "LIEU DE LA TRANSACTION : ", "\n").ok_or_else(|| {
)?; AMFPdfError::PatternExtraction(PatternExtractionNotFoundError::Exchange)
})?;
let nature = extract_pattern(&text, &"NATURE DE LA TRANSACTION : ", &"\n").ok_or( let nature =
AMFPdfError::PatternExtractionError(PatternExtractionError::NatureNotFoundError), extract_pattern(&text, "NATURE DE LA TRANSACTION : ", "\n").ok_or_else(|| {
)?; AMFPdfError::PatternExtraction(PatternExtractionNotFoundError::Nature)
})?;
let instrument = extract_pattern(&text, &"DESCRIPTION DE LINSTRUMENT FINANCIER : ", &"\n") let instrument = extract_pattern(&text, "DESCRIPTION DE LINSTRUMENT FINANCIER : ", "\n")
.ok_or(AMFPdfError::PatternExtractionError( .ok_or_else(|| {
PatternExtractionError::InstrumentNotFoundError, AMFPdfError::PatternExtraction(PatternExtractionNotFoundError::Instrument)
))?; })?;
let inf_coordonnees = let inf_coordonnees = text.find("COORDONNEES DE LEMETTEUR").ok_or_else(|| {
text.find("COORDONNEES DE LEMETTEUR") AMFPdfError::PatternExtraction(PatternExtractionNotFoundError::Coordonnees)
.ok_or(AMFPdfError::PatternExtractionError( })?;
PatternExtractionError::CoordonneesNotFound,
))?;
let mut text_cp = text.clone(); let mut text_cp = text.clone();
text_cp.drain(0..inf_coordonnees); text_cp.drain(0..inf_coordonnees);
let company_name = extract_pattern(&text_cp, &"NOM : ", &"\n").ok_or( let company_name = extract_pattern(&text_cp, "NOM : ", "\n").ok_or_else(|| {
AMFPdfError::PatternExtractionError(PatternExtractionError::CompanyNameNotFound), AMFPdfError::PatternExtraction(PatternExtractionNotFoundError::CompanyName)
)?; })?;
let inf_aggregees_idx = let inf_aggregees_idx = text.find("INFORMATIONS AGREGEES").ok_or_else(|| {
text.find("INFORMATIONS AGREGEES") AMFPdfError::PatternExtraction(PatternExtractionNotFoundError::AggregatedInformation)
.ok_or(AMFPdfError::PatternExtractionError( })?;
PatternExtractionError::AggregatedInformationNotFoundError,
))?;
text.drain(0..inf_aggregees_idx); text.drain(0..inf_aggregees_idx);
let volume = extract_pattern(&text, &"VOLUME : ", &"\n") let volume = extract_pattern(&text, "VOLUME : ", "\n")
.ok_or(AMFPdfError::PatternExtractionError( .ok_or_else(|| AMFPdfError::PatternExtraction(PatternExtractionNotFoundError::Volume))?
PatternExtractionError::VolumeNotFoundError, .replace(' ', "")
))?
.replace(" ", "")
.parse::<f32>() .parse::<f32>()
.map_err(|e| AMFPdfError::VolumeParseError(e))?; .map_err(AMFPdfError::VolumeParseError)?;
let unit_price = extract_pattern(&text, &"PRIX : ".to_string(), &"\n".to_string()) let unit_price = extract_pattern(&text, "PRIX : ", "\n")
.ok_or(AMFPdfError::PatternExtractionError( .ok_or_else(|| {
PatternExtractionError::PriceNotFoundError, AMFPdfError::PatternExtraction(PatternExtractionNotFoundError::PriceNotFound)
))? })?
.replace(" ", "") .replace(' ', "")
.chars() .chars()
.take_while(|c| c.is_digit(10) || c == &'.') .take_while(|c| c.is_ascii_digit() || c == &'.')
.collect::<String>() .collect::<String>()
.parse::<f32>() .parse::<f32>()
.map_err(|e| AMFPdfError::PriceParseError(e))?; .map_err(AMFPdfError::PriceParse)?;
Ok(AMFPdfData { Ok(AMFPdfData {
company_name, company_name,

@ -63,31 +63,33 @@ impl std::error::Error for DateParseError {}
/// Day month and year are separated by 1 space and are written exactly in that order. /// Day month and year are separated by 1 space and are written exactly in that order.
/// The day and years are represented by numbers while the month is represented by its french name. /// The day and years are represented by numbers while the month is represented by its french name.
pub fn naive_date_from_str(s: &str) -> Result<NaiveDate, DateParseError> { pub fn naive_date_from_str(s: &str) -> Result<NaiveDate, DateParseError> {
let mut data = s.split(" "); let mut data = s.split(' ');
let day = data.next().ok_or(DateParseError::NotEnoughData( let day = data
"Given date string is empty".to_string(), .next()
))?; .ok_or_else(|| DateParseError::NotEnoughData("Given date string is empty".to_string()))?;
let month = data.next().ok_or(DateParseError::NotEnoughData(format!( let month = data.next().ok_or_else(|| {
DateParseError::NotEnoughData(format!(
"Given date string: \"{s}\" does not contain a complete date" "Given date string: \"{s}\" does not contain a complete date"
)))?; ))
let year = data.next().ok_or(DateParseError::NotEnoughData(format!( })?;
let year = data.next().ok_or_else(|| {
DateParseError::NotEnoughData(format!(
"Given date string: \"{s}\" does not contain a complete date" "Given date string: \"{s}\" does not contain a complete date"
)))?; ))
})?;
let date = NaiveDate::from_ymd_opt( let date = NaiveDate::from_ymd_opt(
year.parse() year.parse().map_err(DateParseError::YearParseError)?,
.map_err(|e| DateParseError::YearParseError(e))?,
month month
.parse::<FrenchMonth>() .parse::<FrenchMonth>()
.map_err(|e| DateParseError::MonthParseError(e))? .map_err(DateParseError::MonthParseError)?
.0 as u32 .0 as u32
+ 1, + 1,
day.parse().map_err(|e| DateParseError::DayParseError(e))?, day.parse().map_err(DateParseError::DayParseError)?,
) )
.ok_or(DateParseError::InvalidDateError(format!( .ok_or_else(|| {
"Invalid date resulted from string {}", DateParseError::InvalidDateError(format!("Invalid date resulted from string {}", s))
s })?;
)))?;
Ok(date) Ok(date)
} }

@ -2,10 +2,10 @@ use rocket::fairing::{Fairing, Info, Kind};
use rocket::http::Header; use rocket::http::Header;
use rocket::{Request, Response}; use rocket::{Request, Response};
pub struct CORS; pub struct Cors;
#[rocket::async_trait] #[rocket::async_trait]
impl Fairing for CORS { impl Fairing for Cors {
fn info(&self) -> Info { fn info(&self) -> Info {
Info { Info {
name: "Add CORS headers to responses", name: "Add CORS headers to responses",

@ -86,9 +86,7 @@ impl Env {
dotenvy::dotenv().expect("Failed to load .env file"); dotenvy::dotenv().expect("Failed to load .env file");
} }
let env = envy::from_env::<Env>().expect("Failed to load env"); envy::from_env::<Env>().expect("Failed to load env")
env
} }
} }
@ -133,8 +131,6 @@ impl Config {
config.amf_documents_path.push('/'); config.amf_documents_path.push('/');
} }
info!("Config: {:?}", config);
config config
} }
} }

@ -15,7 +15,6 @@ use sea_orm_rocket::rocket::fairing::{self, AdHoc};
use sea_orm_rocket::Database; use sea_orm_rocket::Database;
// Local crates // Local crates
use migration;
use migration::MigratorTrait; use migration::MigratorTrait;
mod amf; mod amf;
@ -48,7 +47,7 @@ async fn start_rocket() -> Result<(), sea_orm_rocket::rocket::Error> {
rocket::build() rocket::build()
.attach(Db::init()) .attach(Db::init())
.attach(AdHoc::try_on_ignite("Migrations", run_migrations)) .attach(AdHoc::try_on_ignite("Migrations", run_migrations))
.attach(crate::cors::CORS) .attach(crate::cors::Cors)
.mount( .mount(
"/v1", "/v1",
routes![ routes![

@ -28,7 +28,7 @@ impl NewCompany {
db, db,
) )
.await .await
.map_err(|e| CompanyRepoError::CompanyCreationErr(e))? .map_err(CompanyRepoError::CompanyCreationErr)?
.into(); .into();
let mut comp = self.clone().into_active_model(); let mut comp = self.clone().into_active_model();
@ -37,7 +37,7 @@ impl NewCompany {
let res = comp let res = comp
.insert(db) .insert(db)
.await .await
.map_err(|e| CompanyRepoError::CompanyCreationErr(e))?; .map_err(CompanyRepoError::CompanyCreationErr)?;
Ok(res) Ok(res)
} }
} }

@ -4,11 +4,11 @@ use crate::amf::TransactionDataTrait;
use crate::model; use crate::model;
use chrono::NaiveDateTime; use chrono::NaiveDateTime;
use sea_orm::error::DbErr; use sea_orm::error::DbErr;
use sea_orm::DatabaseConnection;
use sea_orm::{ use sea_orm::{
AccessMode, ActiveModelTrait, ConnectionTrait, DeriveIntoActiveModel, IntoActiveModel, AccessMode, ActiveModelTrait, ConnectionTrait, DeriveIntoActiveModel, IntoActiveModel,
IsolationLevel, TransactionTrait, IsolationLevel, TransactionTrait,
}; };
use sea_orm::DatabaseConnection;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use thiserror::Error; use thiserror::Error;
@ -52,7 +52,7 @@ impl NewInProcessTransaction {
.into_active_model() .into_active_model()
.insert(db) .insert(db)
.await .await
.map_err(|e| InProcessTransactionError::InProcessTransactionCreationError(e))?; .map_err(InProcessTransactionError::InProcessTransactionCreation)?;
Ok(res) Ok(res)
} }
@ -61,17 +61,17 @@ impl NewInProcessTransaction {
#[derive(Debug, Error)] #[derive(Debug, Error)]
pub enum InProcessTransactionError { pub enum InProcessTransactionError {
#[error("Error creating in process transaction record: {0}")] #[error("Error creating in process transaction record: {0}")]
InProcessTransactionCreationError(DbErr), InProcessTransactionCreation(DbErr),
#[error("Error creating transaction: {0}")] #[error("Error creating transaction: {0}")]
TransactionCreateError(TransactionRepoError), TransactionCreate(TransactionRepoError),
#[error("Database error: {0}")] #[error("Database error: {0}")]
DatabaseError(DbErr), Database(DbErr),
#[error("Error during data extraction")] #[error("Error during data extraction")]
DataExtractionError(AMFPdfError), DataExtraction(AMFPdfError),
#[error("Error deleting in process transaction record")] #[error("Error deleting in process transaction record")]
InProcessTransactionDeleteError(DbErr), InProcessTransactionDelete(DbErr),
#[error("No document error for id {0}")] #[error("No document error for id {0}")]
NoDocumentError(String), NoDocument(String),
#[error("Error while extracting information from doc {0}: {1}")] #[error("Error while extracting information from doc {0}: {1}")]
InformationExtractionError(String, AMFPdfError), InformationExtractionError(String, AMFPdfError),
} }
@ -80,7 +80,7 @@ pub enum InProcessTransactionError {
impl TransactionDataTrait for model::in_process_transaction::Model { impl TransactionDataTrait for model::in_process_transaction::Model {
type Err = InProcessTransactionError; type Err = InProcessTransactionError;
async fn get_transaction_data(self: &Self) -> Result<TransactionData, Self::Err> { async fn get_transaction_data(&self) -> Result<TransactionData, Self::Err> {
let amf_pdf = AMFPdf::new(&self.doc_path); let amf_pdf = AMFPdf::new(&self.doc_path);
let info = amf_pdf.extract_info().await.map_err(|e| { let info = amf_pdf.extract_info().await.map_err(|e| {
InProcessTransactionError::InformationExtractionError(self.doc_path.to_string(), e) InProcessTransactionError::InformationExtractionError(self.doc_path.to_string(), e)
@ -115,22 +115,22 @@ impl model::in_process_transaction::Model {
Some(AccessMode::ReadWrite), Some(AccessMode::ReadWrite),
) )
.await .await
.map_err(|e| InProcessTransactionError::DatabaseError(e))?; .map_err(InProcessTransactionError::Database)?;
NewTransactionFromTransactionData::new_from_transaction_data(val) NewTransactionFromTransactionData::new_from_transaction_data(val)
.create(&txn) .create(&txn)
.await .await
.map_err(|e| InProcessTransactionError::TransactionCreateError(e))?; .map_err(InProcessTransactionError::TransactionCreate)?;
self.clone() self.clone()
.into_active_model() .into_active_model()
.delete(&txn) .delete(&txn)
.await .await
.map_err(|e| InProcessTransactionError::DatabaseError(e))?; .map_err(InProcessTransactionError::Database)?;
txn.commit() txn.commit()
.await .await
.map_err(|e| InProcessTransactionError::DatabaseError(e))?; .map_err(InProcessTransactionError::Database)?;
} }
Err(e) => { Err(e) => {
self.error_string = Some(e.to_string()); self.error_string = Some(e.to_string());
@ -139,7 +139,7 @@ impl model::in_process_transaction::Model {
.into_active_model() .into_active_model()
.update(db) .update(db)
.await .await
.map_err(|e| InProcessTransactionError::DatabaseError(e))?; .map_err(InProcessTransactionError::Database)?;
} }
}; };

@ -71,7 +71,7 @@ impl NewTransactionFromTransactionData {
.filter(model::company::Column::Name.eq(self.company_name.to_owned())) .filter(model::company::Column::Name.eq(self.company_name.to_owned()))
.one(db) .one(db)
.await .await
.map_err(|e| TransactionRepoError::DatabaseError(e))? .map_err(TransactionRepoError::DatabaseError)?
{ {
comp = c; comp = c;
} else { } else {
@ -81,7 +81,7 @@ impl NewTransactionFromTransactionData {
comp = new_comp comp = new_comp
.create(db) .create(db)
.await .await
.map_err(|e| TransactionRepoError::CompanyCreationError(e))?; .map_err(TransactionRepoError::CompanyCreationError)?;
} }
let new_tr = NewTransaction { let new_tr = NewTransaction {
@ -94,7 +94,7 @@ impl NewTransactionFromTransactionData {
nature: self.nature.to_owned(), nature: self.nature.to_owned(),
isin: self.isin.to_owned(), isin: self.isin.to_owned(),
instrument: self.instrument.to_owned(), instrument: self.instrument.to_owned(),
volume: self.volume as i32, volume: self.volume,
unit_price: self.unit_price, unit_price: self.unit_price,
}; };
let res = new_tr.create(db).await?; let res = new_tr.create(db).await?;
@ -102,7 +102,7 @@ impl NewTransactionFromTransactionData {
.find_also_related(model::company::Entity) .find_also_related(model::company::Entity)
.one(db) .one(db)
.await .await
.map_err(|e| TransactionRepoError::DatabaseError(e))? .map_err(TransactionRepoError::DatabaseError)?
.ok_or(TransactionRepoError::CreatedTransactionNotFound)?; .ok_or(TransactionRepoError::CreatedTransactionNotFound)?;
Ok(ret) Ok(ret)
@ -119,7 +119,7 @@ impl NewTransaction {
.into_active_model() .into_active_model()
.insert(db) .insert(db)
.await .await
.map_err(|e| TransactionRepoError::TransactionCreationError(e))?; .map_err(TransactionRepoError::TransactionCreationError)?;
Ok(res) Ok(res)
} }

@ -61,10 +61,12 @@ pub async fn retry_failed_transaction(
format!("Database error: {}", e), format!("Database error: {}", e),
) )
})? })?
.ok_or(Custom( .ok_or_else(|| {
Custom(
Status::NotFound, Status::NotFound,
format!("Failed transaction {} doesn't exist", foreign_id), format!("Failed transaction {} doesn't exist", foreign_id),
))?; )
})?;
tr.process(&txn).await.map_err(|e| { tr.process(&txn).await.map_err(|e| {
Custom( Custom(
@ -84,10 +86,12 @@ pub async fn retry_failed_transaction(
format!("Database error: {}", e), format!("Database error: {}", e),
) )
})? })?
.ok_or(Custom( .ok_or_else(|| {
Custom(
Status::NotFound, Status::NotFound,
format!("Failed to fetch just created transaction"), "Failed to fetch just created transaction".to_string(),
))?; )
})?;
txn.commit().await.map_err(|e| { txn.commit().await.map_err(|e| {
Custom( Custom(
@ -115,9 +119,8 @@ pub async fn retry_all(conn: Connection<'_, Db>) -> Result<(), Custom<String>> {
let mut res_list = vec![]; let mut res_list = vec![];
for mut tr in list { for mut tr in list {
let res = tr.process(db).await; let res = tr.process(db).await;
match res { if let Ok(val) = res {
Ok(val) => res_list.push(val), res_list.push(val);
Err(_) => (),
} }
} }

@ -21,11 +21,11 @@ pub struct GetAMFTransactions {
#[derive(Debug, Error)] #[derive(Debug, Error)]
pub enum GetAMFTransactionsError { pub enum GetAMFTransactionsError {
#[error("The transaction {0} contains no pdf document")] #[error("The transaction {0} contains no pdf document")]
NoDocumentError(String), NoDocument(String),
#[error("Database error: {0}")] #[error("Database error: {0}")]
DatabaseError(DbErr), Database(DbErr),
#[error("Error extracting information from pdf at {0} : {1}")] #[error("Error extracting information from pdf at {0} : {1}")]
InformationExtractionError(String, AMFPdfError), InformationExtraction(String, AMFPdfError),
} }
impl Default for GetAMFTransactions { impl Default for GetAMFTransactions {
@ -54,7 +54,7 @@ impl GetAMFTransactions {
let mut req = AMFRequest::new(AMFRequestType::DD, from, self.max_req_size); let mut req = AMFRequest::new(AMFRequestType::DD, from, self.max_req_size);
let mut tr_to_process = Vec::new(); let mut tr_to_process = Vec::new();
'outer: while let Some(resp) = req.get_list().await.ok() { 'outer: while let Ok(resp) = req.get_list().await {
info!( info!(
"Downloading hit list from {} to {}", "Downloading hit list from {} to {}",
from, from,
@ -70,7 +70,7 @@ impl GetAMFTransactions {
.filter(transaction::Column::ForeignId.eq(number.to_owned())) .filter(transaction::Column::ForeignId.eq(number.to_owned()))
.one(db) .one(db)
.await .await
.map_err(|e| GetAMFTransactionsError::DatabaseError(e))? .map_err(GetAMFTransactionsError::Database)?
.is_some() .is_some()
{ {
// We've saved this transaction before, so we stop here. // We've saved this transaction before, so we stop here.
@ -81,7 +81,7 @@ impl GetAMFTransactions {
.filter(in_process_transaction::Column::ForeignId.eq(number.to_owned())) .filter(in_process_transaction::Column::ForeignId.eq(number.to_owned()))
.one(db) .one(db)
.await .await
.map_err(|e| GetAMFTransactionsError::DatabaseError(e))? .map_err(GetAMFTransactionsError::Database)?
.is_some() .is_some()
{ {
// We've registered this transaction before, so we stop here. // We've registered this transaction before, so we stop here.
@ -106,7 +106,7 @@ impl GetAMFTransactions {
in_process_transaction::Entity::insert_many(tr_to_process) in_process_transaction::Entity::insert_many(tr_to_process)
.exec(db) .exec(db)
.await .await
.map_err(|e| GetAMFTransactionsError::DatabaseError(e))?; .map_err(GetAMFTransactionsError::Database)?;
} }
let mut to_run = in_process_transaction::Entity::find() let mut to_run = in_process_transaction::Entity::find()
@ -116,7 +116,7 @@ impl GetAMFTransactions {
let n_not_failed = to_run let n_not_failed = to_run
.num_items() .num_items()
.await .await
.map_err(|e| GetAMFTransactionsError::DatabaseError(e))?; .map_err(GetAMFTransactionsError::Database)?;
if n_not_failed == 0 { if n_not_failed == 0 {
info!("No new transactions to process since last run"); info!("No new transactions to process since last run");
@ -128,7 +128,7 @@ impl GetAMFTransactions {
while let Some(page) = to_run while let Some(page) = to_run
.fetch_and_next() .fetch_and_next()
.await .await
.map_err(|e| GetAMFTransactionsError::DatabaseError(e))? .map_err(GetAMFTransactionsError::Database)?
{ {
let mut futures = Vec::new(); let mut futures = Vec::new();
for tr in page.iter() { for tr in page.iter() {

@ -1,5 +1,3 @@
use server;
fn main() -> Result<(), Box<dyn std::error::Error>> { fn main() -> Result<(), Box<dyn std::error::Error>> {
server::main()?; server::main()?;
Ok(()) Ok(())

@ -1,2 +1,2 @@
fn main() -> () {
}

Loading…
Cancel
Save