diff --git a/core/src/database/query/application.rs b/core/src/database/query/application.rs index 4b2baef..a7b904e 100644 --- a/core/src/database/query/application.rs +++ b/core/src/database/query/application.rs @@ -51,6 +51,15 @@ impl Query { .await } + pub async fn list_applications_compact( + db: &DbConn, + ) -> Result, DbErr> { + application::Entity::find() + .join(JoinType::InnerJoin, application::Relation::Candidate.def()) + .all(db) + .await + } + pub async fn find_applications_by_candidate_id( db: &DbConn, candidate_id: i32, diff --git a/core/src/models/application.rs b/core/src/models/application.rs index 19f9fd6..aac9c2f 100644 --- a/core/src/models/application.rs +++ b/core/src/models/application.rs @@ -37,4 +37,33 @@ impl ApplicationResponse { } ) } +} + +/// CSV export (admin endpoint) +#[derive(Serialize, Default)] +#[serde(rename_all = "camelCase")] +pub struct ApplicationRow { + pub application: i32, + pub name: Option, + pub surname: Option, + pub birthplace: Option, + pub birthdate: Option, + pub address: Option, + pub telephone: Option, + pub citizenship: Option, + pub email: Option, + pub sex: Option, + pub personal_identification_number: Option, + pub school_name: Option, + pub health_insurance: Option, + + pub parent_name: Option, + pub parent_surname: Option, + pub parent_telephone: Option, + pub parent_email: Option, + + pub second_parent_name: Option, + pub second_parent_surname: Option, + pub second_parent_telephone: Option, + pub second_parent_email: Option, } \ No newline at end of file diff --git a/core/src/models/candidate.rs b/core/src/models/candidate.rs index 9b36218..c03cb78 100644 --- a/core/src/models/candidate.rs +++ b/core/src/models/candidate.rs @@ -65,36 +65,6 @@ pub struct ApplicationDetails { pub parents: Vec, } -/// CSV export (admin endpoint) -#[derive(FromQueryResult, Serialize, Default)] -#[serde(rename_all = "camelCase")] -pub struct Row { - pub application: i32, - pub name: Option, - pub surname: Option, - pub birthplace: Option, - pub birthdate: Option, - pub address: Option, - pub telephone: Option, - pub citizenship: Option, - pub email: Option, - pub sex: Option, - pub study: Option, - pub personal_identification_number: Option, - pub school_name: Option, - pub health_insurance: Option, - - pub parent_name: Option, - pub parent_surname: Option, - pub parent_telephone: Option, - pub parent_email: Option, - - pub second_parent_name: Option, - pub second_parent_surname: Option, - pub second_parent_telephone: Option, - pub second_parent_email: Option, -} - impl NewCandidateResponse { pub async fn from_encrypted( current_application: i32, diff --git a/core/src/models/candidate_details.rs b/core/src/models/candidate_details.rs index 194608d..5a470bf 100644 --- a/core/src/models/candidate_details.rs +++ b/core/src/models/candidate_details.rs @@ -3,9 +3,9 @@ use chrono::NaiveDate; use entity::{candidate, parent}; use futures::future; -use crate::{crypto, models::candidate::{Row, ApplicationDetails}, error::ServiceError}; +use crate::{crypto, models::candidate::{ApplicationDetails}, error::ServiceError}; -use super::candidate::{CandidateDetails, ParentDetails}; +use super::{candidate::{CandidateDetails, ParentDetails}, application::ApplicationRow}; pub const NAIVE_DATE_FMT: &str = "%Y-%m-%d"; @@ -331,11 +331,11 @@ impl From<(&candidate::Model, Vec)> for EncryptedApplicationDetai } } -impl TryFrom for EncryptedApplicationDetails { +impl TryFrom for EncryptedApplicationDetails { type Error = ServiceError; fn try_from( - cp: Row, + cp: ApplicationRow, ) -> Result { Ok(EncryptedApplicationDetails { candidate: EncryptedCandidateDetails { diff --git a/core/src/utils/csv.rs b/core/src/utils/csv.rs index 4a48a82..ce6827f 100644 --- a/core/src/utils/csv.rs +++ b/core/src/utils/csv.rs @@ -1,7 +1,12 @@ -use sea_orm::{DbConn}; -use crate::{error::ServiceError, models::candidate_details::{EncryptedApplicationDetails}, Query, models::candidate::{Row, ApplicationDetails}}; +use crate::{ + error::ServiceError, + models::candidate_details::EncryptedApplicationDetails, + models::{application::ApplicationRow, candidate::ApplicationDetails}, + Query, services::application_service::ApplicationService, +}; +use sea_orm::DbConn; -impl From<(i32, ApplicationDetails)> for Row { +impl From<(i32, ApplicationDetails)> for ApplicationRow { fn from((application, d): (i32, ApplicationDetails)) -> Self { let c = d.candidate; Self { @@ -15,7 +20,6 @@ impl From<(i32, ApplicationDetails)> for Row { citizenship: Some(c.citizenship), email: Some(c.email), sex: Some(c.sex), - study: Some("TODO".to_string()), health_insurance: Some(c.health_insurance), school_name: Some(c.school_name), personal_identification_number: Some(c.personal_id_number), @@ -33,33 +37,29 @@ impl From<(i32, ApplicationDetails)> for Row { } } -pub async fn export( - db: &DbConn, - private_key: String, -) -> Result, ServiceError> { +pub async fn export(db: &DbConn, private_key: String) -> Result, ServiceError> { let mut wtr = csv::Writer::from_writer(vec![]); - let candidates_with_parents = Query::list_candidates_full(&db).await?; - for candidate in candidates_with_parents { - let application = candidate.id; + let applications = Query::list_applications_compact(&db).await?; + for application in applications { + let candidate = ApplicationService::find_related_candidate(db, &application).await?; let parents = Query::find_candidate_parents(db, &candidate).await?; - let row: Row = match EncryptedApplicationDetails::try_from((&candidate, parents)) { - Ok(d) => Row::from( - d - .decrypt(private_key.to_string()) + let row: ApplicationRow = match EncryptedApplicationDetails::try_from((&candidate, parents)) + { + Ok(d) => ApplicationRow::from( + d.decrypt(private_key.to_string()) .await - .map(|d| (application, d))? + .map(|d| (application.id, d))?, ), - Err(_) => Row { - application, + Err(_) => ApplicationRow { + application: application.id, ..Default::default() - } + }, }; wtr.serialize(row)?; } - wtr - .into_inner() + wtr.into_inner() .map_err(|_| ServiceError::CsvIntoInnerError) -} \ No newline at end of file +}