UNPKG

@universis/candidates

Version:

Universis api server plugin for study program candidates, internship selection etc

168 lines (166 loc) 5.13 kB
import { DataError, DataNotFoundError } from '@themost/common'; import { DataObjectState } from '@themost/data'; import { Guid } from '@themost/common'; /** * @param {DataEventArgs} event */ async function beforeSaveAsync(event) { // operate only on insert if (event.state !== DataObjectState.Insert) { return; } if (!event.target.hasOwnProperty('candidate')) { return; } const context = event.model.context; const candidate = event.target.candidate; // if candidate is set on insert, exit if ( typeof candidate === 'number' || typeof candidate === 'string' || (typeof candidate === 'object' && candidate.hasOwnProperty('id')) ) { return; } // validate isAccessibleForFree property of event if (event.target.studyProgramEnrollmentEvent == null) { throw new DataError( 'E_ENROLLMENT_EVENT', 'The study program enrollment event cannot be empty at this context.' ); } const enrollmentEvent = await context .model('StudyProgramEnrollmentEvent') .where('id') .equal( event.target.studyProgramEnrollmentEvent.id || event.target.studyProgramEnrollmentEvent ) .select('id', 'isAccessibleForFree', 'studyProgram', 'inscriptionMode') .flatten() .silent() .getItem(); if (enrollmentEvent == null) { throw new DataNotFoundError( 'The specified enrollment event cannot be found' ); } if (!enrollmentEvent.isAccessibleForFree) { throw new DataError( 'E_ACCESS', 'The study program does not accept self-registration.' ); } if (enrollmentEvent.inscriptionMode == null) { throw new DataError( 'E_DEFAULT_INSCR_MODE', 'The default inscription mode is not set for the event.' ); } // find study program and always validate it if (!candidate.studyProgram) { throw new DataError( 'E_STUDY_PROGRAM', 'The candidate study program cannot be empty at this context' ); } const studyProgram = await context .model('StudyProgram') .where('id') .equal(candidate.studyProgram.id || candidate.studyProgram) .and('isActive') .equal(true) .expand('specialties') .getItem(); if (studyProgram == null) { throw new DataNotFoundError( 'The (active) study program cannot be found or is inaccessible.' ); } // validate that study program // indeed belongs to the event if (enrollmentEvent.studyProgram !== studyProgram.id) { throw new DataError( 'E_STUDY_PROGRAM', 'The provided study program is invalid.' ); } // if no specialization is set if (!candidate.specialtyId || !candidate.studyProgramSpecialty) { const specialtyId = candidate.specialtyId != null ? candidate.specialtyId : -1; // find study program specialty const studyProgramSpecialty = studyProgram.specialties.find( (specialization) => specialization.specialty === specialtyId ); if (studyProgramSpecialty == null) { throw new DataNotFoundError( 'The study program specialty cannot be found or is inaccessible.' ); } // assign data to candidate candidate.studyProgramSpecialty = studyProgramSpecialty; candidate.specialtyId = specialtyId; // also, append specialization to study program register action event.target.specialization = studyProgramSpecialty; } else { // if provided, always validate that study program and specialization match const trueSpecialty = studyProgram.specialties.find( (specialization) => specialization.specialty == candidate.specialtyId ); const studyProgramSpecialty = candidate.studyProgramSpecialty.id || candidate.studyProgramSpecialty; if (studyProgramSpecialty != trueSpecialty.id) { throw new DataError('E_SPECIALTY', 'The provided specialty is invalid.'); } } // check if candidate has already enrolled in this study program and specialty const alreadyEnrolled = await context .model('StudyProgramRegisterAction') .where('studyProgram') .equal(enrollmentEvent.studyProgram) .and('actionStatus/alternateName') .notEqual('CancelledActionStatus') .and('owner') .equal(event.target.owner) .and('specialization') .equal(candidate.studyProgramSpecialty.id || candidate.studyProgramSpecialty) .select('id') .silent() .count(); if (alreadyEnrolled) { throw new DataError( 'E_ALREADY_ENROLLED', 'The user has already enrolled (or has a pending enrollment request) in the specified study program and specialty.' ); } // assign extra attributes Object.assign(candidate, { // note: active studentStatus is forced when converting candidate to student studentStatus: { alternateName: 'candidate', }, // first semester and inscriptionSemester semester: 1, inscriptionSemester: 1, // a guid for inscriptionNumber inscriptionNumber: Guid.newGuid().toString(), // and the event's default inscriptionMode inscriptionMode: enrollmentEvent.inscriptionMode, }); // and emulate nested attribute by saving candidate await context.model('CandidateStudent').save(candidate); } /** * @param {DataEventArgs} event * @param {Function} callback */ export function beforeSave(event, callback) { return beforeSaveAsync(event) .then(() => { return callback(); }) .catch((err) => { return callback(err); }); }