feat!: candidate list field of study filtering, pagination

This commit is contained in:
Sebastian Pravda 2023-01-15 20:42:32 +01:00
parent 51d86ff507
commit 7a9910c9d7
No known key found for this signature in database
GPG key ID: F3BC84F08EFA3F57
10 changed files with 67 additions and 17 deletions

View file

@ -123,10 +123,9 @@ pub async fn list_candidates(
if !(field == "KB".to_string() || field == "IT".to_string() || field == "G") {
return Err(Custom(Status::BadRequest, "Invalid field of study".to_string()));
}
}
let candidates = ApplicationService::list_applications(&private_key, db)
let candidates = ApplicationService::list_applications(&private_key, db, field, page)
.await.map_err(to_custom_error)?;
Ok(

View file

@ -2,7 +2,7 @@ use ::entity::application;
use log::{info, warn};
use sea_orm::{DbConn, DbErr, Set, ActiveModelTrait, IntoActiveModel, DeleteResult, ModelTrait};
use crate::Mutation;
use crate::{Mutation, models::candidate::FieldOfStudy};
impl Mutation {
pub async fn create_application(
@ -14,8 +14,10 @@ impl Mutation {
pubkey: String,
encrypted_priv_key: String,
) -> Result<application::Model, DbErr> {
let field_of_study = FieldOfStudy::from(application_id);
let insert = application::ActiveModel {
id: Set(application_id),
field_of_study: Set(field_of_study.into()),
personal_id_number: Set(enc_personal_id_number),
password: Set(hashed_password),
candidate_id: Set(candidate_id),
@ -23,7 +25,6 @@ impl Mutation {
private_key: Set(encrypted_priv_key),
created_at: Set(chrono::offset::Local::now().naive_local()),
updated_at: Set(chrono::offset::Local::now().naive_local()),
..Default::default()
}
.insert(db)
.await?;

View file

@ -1,5 +1,7 @@
use entity::{application, candidate};
use sea_orm::{EntityTrait, DbErr, DbConn, ModelTrait, FromQueryResult, QuerySelect, JoinType, RelationTrait, QueryFilter, ColumnTrait};
use sea_orm::{EntityTrait, DbErr, DbConn, ModelTrait, FromQueryResult, QuerySelect, JoinType, RelationTrait, QueryFilter, ColumnTrait, QueryOrder, PaginatorTrait};
const PAGE_SIZE: u64 = 20;
#[derive(FromQueryResult, Clone)]
pub struct ApplicationCandidateJoin {
@ -12,7 +14,7 @@ pub struct ApplicationCandidateJoin {
pub telephone: Option<String>,
}
use crate::Query;
use crate::{Query};
impl Query {
pub async fn find_application_by_id(
@ -36,9 +38,16 @@ impl Query {
pub async fn list_applications(
db: &DbConn,
field_of_study: Option<String>,
page: Option<u64>,
) -> Result<Vec<ApplicationCandidateJoin>, DbErr> {
application::Entity::find()
// .column_as(application::Column::Id, "application_id")
let select = application::Entity::find();
let query = if let Some(field) = field_of_study {
select.filter(application::Column::FieldOfStudy.eq(field))
} else {
select
}
.order_by(application::Column::Id, sea_orm::Order::Asc)
.join(JoinType::InnerJoin, application::Relation::Candidate.def())
.column_as(application::Column::Id, "application_id")
.column_as(candidate::Column::Id, "candidate_id")
@ -46,9 +55,16 @@ impl Query {
.column_as(candidate::Column::Surname, "surname")
.column_as(candidate::Column::Email, "email")
.column_as(candidate::Column::Telephone, "telephone")
.into_model::<ApplicationCandidateJoin>()
.all(db)
.await
.into_model::<ApplicationCandidateJoin>();
if let Some(page) = page {
query
.paginate(db, PAGE_SIZE)
.fetch_page(page).await
} else {
query
.all(db).await
}
}
pub async fn list_applications_compact(

View file

@ -8,6 +8,33 @@ use crate::{
use super::candidate_details::{EncryptedString, EncryptedCandidateDetails};
pub enum FieldOfStudy {
G,
IT,
KB,
}
impl Into<String> for FieldOfStudy {
fn into(self) -> String {
match self {
FieldOfStudy::G => "G".to_string(),
FieldOfStudy::IT => "IT".to_string(),
FieldOfStudy::KB => "KB".to_string(),
}
}
}
impl From<i32> for FieldOfStudy {
fn from(id: i32) -> Self {
match &id.to_string().as_str()[0..3] {
"101" => FieldOfStudy::G,
"102" => FieldOfStudy::IT,
"103" => FieldOfStudy::KB,
_ => panic!("Invalid field of study id"), // TODO: handle using TryFrom
}
}
}
/// Minimal candidate response containing database only not null fields
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]

View file

@ -100,11 +100,11 @@ impl ApplicationService {
.filter(|(_, id)| id == &personal_id_number)
.collect();
if found_ids.iter().any(|(_, personal_id)| personal_id == &personal_id_number) {
if let Some((candidate_id, _)) = found_ids.first() {
Ok(
Self::find_linkable_candidate(db,
application_id,
found_ids[0].0,
*candidate_id,
personal_id_number
).await?
)
@ -230,8 +230,11 @@ impl ApplicationService {
pub async fn list_applications(
private_key: &String,
db: &DbConn,
field_of_study: Option<String>,
page: Option<u64>,
) -> Result<Vec<ApplicationResponse>, ServiceError> {
let applications = Query::list_applications(db).await?;
let applications = Query::list_applications(db, field_of_study, page).await?;
futures::future::try_join_all(
applications

View file

@ -79,12 +79,12 @@ pub mod tests {
let db = get_memory_sqlite_connection().await;
let admin = create_admin(&db).await;
let private_key = crypto::decrypt_password(admin.private_key, "admin".to_string()).await.unwrap();
let candidates = ApplicationService::list_applications(&private_key, &db).await.unwrap();
let candidates = ApplicationService::list_applications(&private_key, &db, None, None).await.unwrap();
assert_eq!(candidates.len(), 0);
put_user_data(&db).await;
let candidates = ApplicationService::list_applications(&private_key, &db).await.unwrap();
let candidates = ApplicationService::list_applications(&private_key, &db, None, None).await.unwrap();
assert_eq!(candidates.len(), 1);
}

View file

View file

@ -1,4 +1,5 @@
pub mod csv;
pub mod filetype;
pub mod db;
pub mod date;
pub mod date;
pub mod field_of_study;

View file

@ -8,6 +8,7 @@ pub struct Model {
#[sea_orm(primary_key, auto_increment = false)]
pub id: i32,
pub candidate_id: i32,
pub field_of_study: String,
pub password: String,
pub public_key: String,
pub private_key: String,

View file

@ -17,6 +17,7 @@ impl MigrationTrait for Migration {
.not_null()
.primary_key(),
)
.col(ColumnDef::new(Application::FieldOfStudy).string().not_null())
.col(ColumnDef::new(Application::CandidateId).integer().not_null())
.col(ColumnDef::new(Application::Password).string().not_null())
.col(ColumnDef::new(Application::PublicKey).string().not_null())
@ -51,6 +52,7 @@ impl MigrationTrait for Migration {
pub enum Application {
Table,
Id,
FieldOfStudy,
Password,
PersonalIdNumber,
PublicKey,