diff --git a/api/src/routes/candidate.rs b/api/src/routes/candidate.rs index b8a3550..def5068 100644 --- a/api/src/routes/candidate.rs +++ b/api/src/routes/candidate.rs @@ -317,7 +317,8 @@ mod tests { \"sex\": \"MALE\", \"personalIdNumber\": \"0101010000\", \"schoolName\": \"29988383\", - \"healthInsurance\": \"000\" + \"healthInsurance\": \"000\", + \"grades\": [] }, \"parents\": [ { @@ -376,8 +377,7 @@ mod tests { assert_eq!(response.status(), Status::Ok); - let details_resp: ApplicationDetails = - serde_json::from_str(&response.into_string().unwrap()).unwrap(); + let details_resp: ApplicationDetails = serde_json::from_str(&response.into_string().unwrap()).unwrap(); assert_eq!(details_orig, details_resp); } diff --git a/core/src/database/mutation/candidate.rs b/core/src/database/mutation/candidate.rs index 5f53073..c0dc4f6 100644 --- a/core/src/database/mutation/candidate.rs +++ b/core/src/database/mutation/candidate.rs @@ -33,7 +33,7 @@ impl Mutation { Ok(delete) } - pub async fn update_candidate_details( + pub async fn update_candidate_opt_details( db: &DbConn, candidate: candidate::Model, enc_candidate: EncryptedCandidateDetails, @@ -51,9 +51,9 @@ impl Mutation { candidate.citizenship = Set(enc_candidate.citizenship.map(|e| e.into())); candidate.email = Set(enc_candidate.email.map(|e| e.into())); candidate.sex = Set(enc_candidate.sex.map(|e| e.into())); - // candidate.personal_identification_number = Set(enc_candidate.personal_id_number.map(|e| e.into()).unwrap_or_default()); // TODO: do not set this here, it is already set in the create_candidate mutation??? candidate.school_name = Set(enc_candidate.school_name.map(|e| e.into())); candidate.health_insurance = Set(enc_candidate.health_insurance.map(|e| e.into())); + candidate.grades_json = Set(enc_candidate.grades_json.map(|e| e.into())); candidate.encrypted_by_id = Set(Some(encrypted_by_id)); candidate.updated_at = Set(chrono::offset::Local::now().naive_local()); @@ -120,7 +120,7 @@ mod tests { vec!["age1u889gp407hsz309wn09kxx9anl6uns30m27lfwnctfyq9tq4qpus8tzmq5".to_string()], ).await.unwrap(); - let candidate = Mutation::update_candidate_details(&db, candidate, encrypted_details.candidate, 1).await.unwrap(); + let candidate = Mutation::update_candidate_opt_details(&db, candidate, encrypted_details.candidate, 1).await.unwrap(); let candidate = Query::find_candidate_by_id(&db, candidate.id) .await diff --git a/core/src/models/candidate.rs b/core/src/models/candidate.rs index 37cd3e9..3938639 100644 --- a/core/src/models/candidate.rs +++ b/core/src/models/candidate.rs @@ -6,7 +6,7 @@ use crate::{ error::ServiceError, }; -use super::candidate_details::{EncryptedString, EncryptedCandidateDetails}; +use super::{candidate_details::{EncryptedString, EncryptedCandidateDetails}, grade::GradeList}; pub enum FieldOfStudy { G, @@ -57,7 +57,7 @@ pub struct CreateCandidateResponse { pub password: String, } -#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)] +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] #[serde(rename_all = "camelCase")] pub struct CandidateDetails { pub name: String, @@ -72,8 +72,9 @@ pub struct CandidateDetails { pub personal_id_number: String, pub school_name: String, pub health_insurance: String, + pub grades: GradeList, } -#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)] +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] #[serde(rename_all = "camelCase")] pub struct ParentDetails { pub name: String, @@ -83,7 +84,7 @@ pub struct ParentDetails { } /// Candidate details (admin and candidate endpoints) -#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)] +#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] #[serde(rename_all = "camelCase")] pub struct ApplicationDetails { // Candidate diff --git a/core/src/models/candidate_details.rs b/core/src/models/candidate_details.rs index 65fd311..55453d8 100644 --- a/core/src/models/candidate_details.rs +++ b/core/src/models/candidate_details.rs @@ -5,7 +5,7 @@ use futures::future; use crate::{crypto, models::candidate::{ApplicationDetails}, error::ServiceError, utils::date::parse_naive_date_from_opt_str}; -use super::{candidate::{CandidateDetails, ParentDetails}, application::ApplicationRow}; +use super::{candidate::{CandidateDetails, ParentDetails}, application::ApplicationRow, grade::GradeList}; pub const NAIVE_DATE_FMT: &str = "%Y-%m-%d"; @@ -26,6 +26,7 @@ pub struct EncryptedCandidateDetails { pub personal_id_number: Option, pub school_name: Option, pub health_insurance: Option, + pub grades_json: Option, } #[derive(Debug, Clone)] @@ -118,6 +119,7 @@ impl EncryptedCandidateDetails { recipients: &Vec, ) -> Result { let birthdate_str = form.birthdate.format(NAIVE_DATE_FMT).to_string(); + let grades_str = form.grades.to_string(); let d = tokio::try_join!( EncryptedString::new_option(&form.name, recipients), EncryptedString::new_option(&form.surname, recipients), @@ -131,6 +133,7 @@ impl EncryptedCandidateDetails { EncryptedString::new_option(&form.personal_id_number, recipients), EncryptedString::new_option(&form.school_name, recipients), EncryptedString::new_option(&form.health_insurance, recipients), + EncryptedString::new_option(&grades_str, recipients), )?; Ok( @@ -147,6 +150,7 @@ impl EncryptedCandidateDetails { personal_id_number: d.9, school_name: d.10, health_insurance: d.11, + grades_json: d.12, } ) } @@ -165,6 +169,7 @@ impl EncryptedCandidateDetails { EncryptedString::decrypt_option(&self.personal_id_number, priv_key),// 9 EncryptedString::decrypt_option(&self.school_name, priv_key), // 10 EncryptedString::decrypt_option(&self.health_insurance, priv_key), // 11 + EncryptedString::decrypt_option(&self.grades_json, priv_key), // 12 )?; Ok(CandidateDetails { @@ -180,6 +185,7 @@ impl EncryptedCandidateDetails { personal_id_number: d.9.unwrap_or_default(), school_name: d.10.unwrap_or_default(), health_insurance: d.11.unwrap_or_default(), + grades: GradeList::from_opt_str(d.12).unwrap_or_default(), } ) } @@ -214,6 +220,7 @@ impl From<&candidate::Model> for EncryptedCandidateDetails { personal_id_number: Some(EncryptedString::from(candidate.personal_identification_number.to_owned())), school_name: EncryptedString::try_from(&candidate.school_name).ok(), health_insurance: EncryptedString::try_from(&candidate.health_insurance).ok(), + grades_json: EncryptedString::try_from(&candidate.grades_json).ok(), } } } @@ -351,6 +358,7 @@ impl TryFrom for EncryptedApplicationDetails { personal_id_number: EncryptedString::try_from(&cp.personal_identification_number).ok(), school_name: EncryptedString::try_from(&cp.school_name).ok(), health_insurance: EncryptedString::try_from(&cp.health_insurance).ok(), + grades_json: None, // TODO }, parents: vec![EncryptedParentDetails { name: EncryptedString::try_from(&cp.parent_name).ok(), @@ -382,7 +390,7 @@ pub mod tests { use once_cell::sync::Lazy; use sea_orm::{DbConn, Set, ActiveModelTrait}; - use crate::{crypto, models::candidate::{CandidateDetails, ParentDetails}, utils::db::get_memory_sqlite_connection, services::candidate_service::tests::put_user_data}; + use crate::{crypto, models::{candidate::{CandidateDetails, ParentDetails}, grade::GradeList}, utils::db::get_memory_sqlite_connection, services::candidate_service::tests::put_user_data}; use super::{ApplicationDetails, EncryptedApplicationDetails, EncryptedString}; @@ -404,6 +412,7 @@ pub mod tests { personal_id_number: "personal_id_number".to_string(), school_name: "school_name".to_string(), health_insurance: "health_insurance".to_string(), + grades: GradeList::from(vec![]), }, parents: vec![ParentDetails { name: "parent_name".to_string(), diff --git a/core/src/models/grade.rs b/core/src/models/grade.rs new file mode 100644 index 0000000..42aea09 --- /dev/null +++ b/core/src/models/grade.rs @@ -0,0 +1,37 @@ +use serde::{Serialize, Deserialize}; + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct Grade { + subject: String, + value: i32, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct GradeList(Vec); + +impl GradeList { + pub fn from_opt_str(grades: Option) -> Option { + println!("grades: {:?}", grades); + grades.map( + |grades| serde_json::from_str(&grades).unwrap() // TODO: handle error + ) + } +} + +impl Default for GradeList { + fn default() -> Self { + Self(vec![]) + } +} + +impl From> for GradeList { + fn from(grades: Vec) -> Self { + Self(grades) + } +} + +impl ToString for GradeList { + fn to_string(&self) -> String { + serde_json::to_string(&self.0).unwrap() + } +} \ No newline at end of file diff --git a/core/src/models/mod.rs b/core/src/models/mod.rs index 1251244..08cc4f2 100644 --- a/core/src/models/mod.rs +++ b/core/src/models/mod.rs @@ -1,4 +1,5 @@ pub mod candidate_details; pub mod candidate; pub mod auth; -pub mod application; \ No newline at end of file +pub mod application; +pub mod grade; \ No newline at end of file diff --git a/core/src/services/application_service.rs b/core/src/services/application_service.rs index b791425..3fd93dc 100644 --- a/core/src/services/application_service.rs +++ b/core/src/services/application_service.rs @@ -324,7 +324,7 @@ impl ApplicationService { .ok_or(ServiceError::CandidateDetailsNotSet)?.to_string() ).await?; - Mutation::update_candidate_details(db, + Mutation::update_candidate_opt_details(db, candidate, enc_details.candidate, application.id diff --git a/core/src/services/candidate_service.rs b/core/src/services/candidate_service.rs index 661d614..46a4976 100644 --- a/core/src/services/candidate_service.rs +++ b/core/src/services/candidate_service.rs @@ -48,7 +48,7 @@ impl CandidateService { encrypted_by: i32, ) -> Result { let enc_details = EncryptedCandidateDetails::new(&details, recipients).await?; - let model = Mutation::update_candidate_details( + let model = Mutation::update_candidate_opt_details( db, candidate, enc_details, diff --git a/core/src/services/parent_service.rs b/core/src/services/parent_service.rs index f07ba2f..21fd62f 100644 --- a/core/src/services/parent_service.rs +++ b/core/src/services/parent_service.rs @@ -54,7 +54,7 @@ mod tests { use once_cell::sync::Lazy; - use crate::{utils::db::get_memory_sqlite_connection, models::{candidate::{ParentDetails, ApplicationDetails, CandidateDetails}, candidate_details::EncryptedApplicationDetails}, services::{candidate_service::{CandidateService, tests::put_user_data}, application_service::ApplicationService, parent_service::ParentService}, crypto}; + use crate::{utils::db::get_memory_sqlite_connection, models::{candidate::{ParentDetails, ApplicationDetails, CandidateDetails}, candidate_details::EncryptedApplicationDetails, grade::GradeList}, services::{candidate_service::{CandidateService, tests::put_user_data}, application_service::ApplicationService, parent_service::ParentService}, crypto}; pub static APPLICATION_DETAILS_TWO_PARENTS: Lazy> = Lazy::new(|| Mutex::new(ApplicationDetails { @@ -71,6 +71,7 @@ mod tests { personal_id_number: "personal_id_number".to_string(), school_name: "school_name".to_string(), health_insurance: "health_insurance".to_string(), + grades: GradeList::from(vec![]), }, parents: vec![ParentDetails { name: "parent_name".to_string(), diff --git a/entity/src/candidate.rs b/entity/src/candidate.rs index 9f88ce3..eee1efa 100644 --- a/entity/src/candidate.rs +++ b/entity/src/candidate.rs @@ -20,6 +20,7 @@ pub struct Model { pub personal_identification_number: String, pub school_name: Option, pub health_insurance: Option, + pub grades_json: Option, pub encrypted_by_id: Option, pub created_at: DateTime, pub updated_at: DateTime, diff --git a/migration/src/m20221024_121621_create_candidate.rs b/migration/src/m20221024_121621_create_candidate.rs index 77f242d..1b6edad 100644 --- a/migration/src/m20221024_121621_create_candidate.rs +++ b/migration/src/m20221024_121621_create_candidate.rs @@ -31,6 +31,7 @@ impl MigrationTrait for Migration { .col(ColumnDef::new(Candidate::PersonalIdentificationNumber).string().not_null()) .col(ColumnDef::new(Candidate::SchoolName).string()) .col(ColumnDef::new(Candidate::HealthInsurance).string()) + .col(ColumnDef::new(Candidate::GradesJson).string()) .col(ColumnDef::new(Candidate::EncryptedById).integer()) .col(ColumnDef::new(Candidate::CreatedAt).date_time().not_null()) .col(ColumnDef::new(Candidate::UpdatedAt).date_time().not_null()) @@ -63,6 +64,7 @@ pub enum Candidate { PersonalIdentificationNumber, SchoolName, HealthInsurance, + GradesJson, EncryptedById, CreatedAt, UpdatedAt,