mirror of
https://github.com/danbulant/Portfolio
synced 2026-06-19 14:31:05 +00:00
feat!: candidate list field of study filtering, pagination
This commit is contained in:
parent
51d86ff507
commit
7a9910c9d7
10 changed files with 67 additions and 17 deletions
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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?;
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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")]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
0
core/src/utils/field_of_study.rs
Normal file
0
core/src/utils/field_of_study.rs
Normal 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;
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Reference in a new issue