From 45a8f9456ce733c97ba66a6a1e5292f49a36632d Mon Sep 17 00:00:00 2001 From: Emmanuel MUGISHA Date: Tue, 19 Nov 2024 17:26:33 +0200 Subject: [PATCH] update applicant status to Admitted/Accepted and change role to trainee (#143) * update applicant status to Admitted/Accepted and change role to trainee * update trainee in all models --------- Co-authored-by: El-zizo Mugisha --- src/models/traineeApplicant.ts | 41 ++++--- src/resolvers/applicationStageResolver.ts | 105 +++++++++++++---- src/schema/traineeApplicantSchema.ts | 13 ++- src/seeders/users.ts | 135 ++++++++++++---------- 4 files changed, 198 insertions(+), 96 deletions(-) diff --git a/src/models/traineeApplicant.ts b/src/models/traineeApplicant.ts index fa9958d..324adb7 100644 --- a/src/models/traineeApplicant.ts +++ b/src/models/traineeApplicant.ts @@ -3,15 +3,16 @@ import mongoose, { Schema } from "mongoose"; const CycleAppliedSchema = new Schema({ cycle: { type: Schema.Types.ObjectId, - ref: 'ApplicationCycle', - required: true + ref: "ApplicationCycle", + required: true, }, -}) +}); -const TraineeApplicantSchema = new Schema({ +const TraineeApplicantSchema = new Schema( + { user: { type: Schema.Types.ObjectId, - ref: 'User' + ref: "User", }, email: { type: String, @@ -26,10 +27,10 @@ const TraineeApplicantSchema = new Schema({ type: String, required: true, }, - cycle_id:{ + cycle_id: { type: mongoose.Schema.Types.ObjectId, ref: "applicationCycle", - required: true + required: true, }, delete_at: { type: Boolean, @@ -38,21 +39,35 @@ const TraineeApplicantSchema = new Schema({ cycleApplied: [CycleAppliedSchema], applicationPhase: { type: String, - enum: ["Applied", 'Shortlisted', 'Technical Assessment', 'Interview Assessment', 'Admitted', 'Rejected', "Enrolled"], + enum: [ + "Applied", + "Shortlisted", + "Technical Assessment", + "Interview Assessment", + "Admitted", + "Rejected", + "Enrolled", + ], default: "Applied", }, status: { type: String, default: "No action", }, + role: { + type: Schema.Types.ObjectId, + ref: "Role", + }, cohort: { type: Schema.Types.ObjectId, ref: "cohortModel", - } - },{ + }, + }, + { timestamps: true, - }); + } +); -const TraineeApplicant = mongoose.model('Trainees', TraineeApplicantSchema); +const TraineeApplicant = mongoose.model("Trainees", TraineeApplicantSchema); - export default TraineeApplicant; +export default TraineeApplicant; diff --git a/src/resolvers/applicationStageResolver.ts b/src/resolvers/applicationStageResolver.ts index 34573a5..60a6d14 100644 --- a/src/resolvers/applicationStageResolver.ts +++ b/src/resolvers/applicationStageResolver.ts @@ -9,6 +9,7 @@ import InterviewAssessment from "../models/InterviewAssessmentStageSchema"; import TechnicalAssessment from "../models/technicalAssessmentStage"; import mongoose from "mongoose"; import { traineEAttributes } from "../models/traineeAttribute"; +import { LoggedUserModel } from "../models/AuthUser"; const validStages = [ "Shortlisted", @@ -93,28 +94,37 @@ export const applicationStageResolvers: any = { getTraineeCyclesApplications: async (_: any, __: any, context: any) => { try { if (!context.currentUser) { - throw new CustomGraphQLError("You must be logged in to view your applications"); + throw new CustomGraphQLError( + "You must be logged in to view your applications" + ); } - const applications = await TraineeApplicant.findOne({ email: context.currentUser.email }) + const applications = await TraineeApplicant.findOne({ + email: context.currentUser.email, + }) .populate("cycle_id") .lean(); - return applications - } - catch (error: any) { + return applications; + } catch (error: any) { console.error("Error retrieving applications with attributes:", error); throw new CustomGraphQLError(error); } }, - getApplicationsAttributes: async (_: any, { trainee_id }: any, context: any) => { + getApplicationsAttributes: async ( + _: any, + { trainee_id }: any, + context: any + ) => { try { if (!context.currentUser) { - throw new CustomGraphQLError("You must be logged in to view your applications"); + throw new CustomGraphQLError( + "You must be logged in to view your applications" + ); } const attributes = await traineEAttributes.findOne({ trainee_id }); - return attributes + return attributes; } catch (error) { console.error("Error getting attributes:", error); throw new CustomGraphQLError(error); @@ -123,12 +133,21 @@ export const applicationStageResolvers: any = { getApplicationStages: async (_: any, { trainee_id }: any, context: any) => { try { if (!context.currentUser) { - throw new CustomGraphQLError("You must be logged in to view your applications"); + throw new CustomGraphQLError( + "You must be logged in to view your applications" + ); } const trainee = new mongoose.Types.ObjectId(trainee_id); - const [shortlistStage, technicalStage, interviewStage, admittedStage, dismissedStage, AllStages] = await Promise.all([ + const [ + shortlistStage, + technicalStage, + interviewStage, + admittedStage, + dismissedStage, + AllStages, + ] = await Promise.all([ Shortlisted.findOne({ applicantId: trainee }), TechnicalAssessment.findOne({ applicantId: trainee }), InterviewAssessment.findOne({ applicantId: trainee }), @@ -143,15 +162,15 @@ export const applicationStageResolvers: any = { interview: interviewStage, admitted: admittedStage, dismissed: dismissedStage, - allStages: AllStages - } - - + allStages: AllStages, + }; } catch (error) { console.error("Error retrieving application stages:", error); - throw new CustomGraphQLError(error || "An error occurred while retrieving applications"); + throw new CustomGraphQLError( + error || "An error occurred while retrieving applications" + ); } - } + }, }, Mutation: { moveToNextStage: async ( @@ -241,6 +260,15 @@ export const applicationStageResolvers: any = { await stageTracking.save(); } + let traineeRole = await RoleModel.findOne({ roleName: "trainee" }); + if (!traineeRole) { + traineeRole = await RoleModel.create({ + roleName: "trainee", + description: "A user who has been accepted as a trainee", + permissions: [], + }); + } + let message = ""; switch (nextStage) { case "Technical Assessment": @@ -294,7 +322,11 @@ export const applicationStageResolvers: any = { ); } - await Promise.all(models.map(model => updateApplicantAfterAdmitted(model, applicantId))); + await Promise.all( + models.map((model) => + updateApplicantAfterAdmitted(model, applicantId) + ) + ); await Admitted.create({ applicantId, @@ -302,11 +334,40 @@ export const applicationStageResolvers: any = { status: "Passed", }); message = `Applicant passed the application stageāœ….`; + await TraineeApplicant.updateOne( { _id: applicantId }, - { $set: { applicationPhase: nextStage, status: "Admitted" } } + { + $set: { + applicationPhase: nextStage, + status: "Admitted", + role: traineeRole._id, + }, + } ); + const updatedApplicant = await TraineeApplicant.findOne({ + _id: applicantId, + }) + .populate("email") + .lean(); + + const email = updatedApplicant?.email; + + if (email) { + await LoggedUserModel.updateOne( + { email }, + { + $set: { + applicationPhase: nextStage, + status: "Admitted", + role: traineeRole._id, + }, + } + ); + } else { + throw new Error("Email not found for the provided applicant ID"); + } break; case "Rejected": @@ -316,7 +377,11 @@ export const applicationStageResolvers: any = { { $set: { status: "Rejected", exitedAt: new Date() } } ); } - await Promise.all(models.map(model => updateApplicantAfterDismissed(model, applicantId))); + await Promise.all( + models.map((model) => + updateApplicantAfterDismissed(model, applicantId) + ) + ); const stageDismissedFrom = await TraineeApplicant.findOne({ _id: applicantId, }); @@ -420,4 +485,4 @@ export const applicationStageResolvers: any = { } }, }, -}; \ No newline at end of file +}; diff --git a/src/schema/traineeApplicantSchema.ts b/src/schema/traineeApplicantSchema.ts index b587e1b..fac8087 100644 --- a/src/schema/traineeApplicantSchema.ts +++ b/src/schema/traineeApplicantSchema.ts @@ -37,6 +37,7 @@ export const typeDefsTrainee = gql` status: String! applicationPhase: ApplicationPhase! cohort: ID + role: Role createdAt: String! user: User } @@ -51,11 +52,11 @@ export const typeDefsTrainee = gql` } type applicationCycle { - _id: ID! - name: String! - startDate: String! - endDate: String! -} + _id: ID! + name: String! + startDate: String! + endDate: String! + } type AcceptTraineeResponse { success: Boolean! @@ -77,6 +78,7 @@ export const typeDefsTrainee = gql` firstName: String! email: String! cycle_id: ID! + role: ID attributes: traineeAttributeInput } @@ -88,6 +90,7 @@ export const typeDefsTrainee = gql` firstName: String lastName: String cycle_id: ID + role: ID status: String } diff --git a/src/seeders/users.ts b/src/seeders/users.ts index d27c7d7..040a353 100644 --- a/src/seeders/users.ts +++ b/src/seeders/users.ts @@ -5,65 +5,84 @@ import BcryptUtil from "../utils/bcrypt"; import { cohortModels } from "../models/cohortModel"; // Seed users with superAdmin role. -const seedUsers = async() => { - const superAdminRole = await RoleModel.findOne({ roleName: 'superAdmin' }); - const applicantRole = await RoleModel.findOne({ roleName: 'applicant' }); - const cohort = await cohortModels.findOne(); +const seedUsers = async () => { + const superAdminRole = await RoleModel.findOne({ roleName: "superAdmin" }); + const applicantRole = await RoleModel.findOne({ roleName: "applicant" }); + let traineeRole = await RoleModel.findOne({ roleName: "trainee" }); - if(!superAdminRole || !applicantRole || !cohort){ - return; - } + if (!traineeRole) { + traineeRole = await RoleModel.create({ + roleName: "trainee", + description: "A user who has been accepted as a trainee", + permissions: [], + }); + } + const cohort = await cohortModels.findOne(); - const users = [ - { - firstname: "Super", - lastname: "Admin", - email: "admin@example.com", - password: await BcryptUtil.hash("password123"), - role: superAdminRole._id, - country: "Rwanda", - code: "+250", - telephone: "0788888888", - isActive: true, - gender: "female", - isVerified:true, + if (!superAdminRole || !applicantRole || !traineeRole || !cohort) { + return; + } - }, - { - firstname: "Manzi", - lastname: "Jean", - email: "jean@example.com", - password: await BcryptUtil.hash("password123"), - role: applicantRole._id, - country: "Rwanda", - code: "+250", - telephone: "0788888889", - isActive: true, - gender: "male", - applicationPhase: "Enrolled", - cohort: cohort._id, - isVerified:true, + const users = [ + { + firstname: "John", + lastname: "Trainee", + email: "trainee@example.com", + password: await BcryptUtil.hash("password123"), + role: traineeRole._id, + country: "Rwanda", + code: "+250", + telephone: "0788888887", + isActive: true, + gender: "male", + cohort: cohort._id, + applicationPhase: "Accepted", + isVerified: true, + }, + { + firstname: "Super", + lastname: "Admin", + email: "admin@example.com", + password: await BcryptUtil.hash("password123"), + role: superAdminRole._id, + country: "Rwanda", + code: "+250", + telephone: "0788888888", + isActive: true, + gender: "female", + isVerified: true, + }, + { + firstname: "Manzi", + lastname: "Jean", + email: "jean@example.com", + password: await BcryptUtil.hash("password123"), + role: applicantRole._id, + country: "Rwanda", + code: "+250", + telephone: "0788888889", + isActive: true, + gender: "male", + applicationPhase: "Applied", + cohort: cohort._id, + isVerified: true, + }, + { + firstname: "Jane", + lastname: "Doe", + email: "jane@example.com", + password: await BcryptUtil.hash("password123"), + role: applicantRole._id, + country: "Rwanda", + code: "+250", + telephone: "0788888888", + isActive: true, + isVerified: true, + gender: "male", + }, + ]; + await LoggedUserModel.deleteMany({ users }); + await LoggedUserModel.insertMany(users); +}; - }, - { - firstname: "Jane", - lastname: "Doe", - email: "jane@example.com", - password: await BcryptUtil.hash("password123"), - role: applicantRole._id, - country: "Rwanda", - code: "+250", - telephone: "0788888888", - isActive: true, - isVerified:true, - gender: "male", - - - } - ] - await LoggedUserModel.deleteMany({users}); - await LoggedUserModel.insertMany(users); - -} - -export default seedUsers; \ No newline at end of file +export default seedUsers;