@universis/candidates
Version:
Universis api server plugin for study program candidates, internship selection etc
157 lines (150 loc) • 7.02 kB
JavaScript
import {DataObjectState, DataCacheStrategy, DataConfigurationStrategy, ModelClassLoaderStrategy, SchemaLoaderStrategy} from "@themost/data";
import {DataError, AccessDeniedError, DataNotFoundError, TraceUtils, ApplicationService, Args} from "@themost/common";
import path from "path";
/**
* @param {DataEventArgs} event
*/
async function afterSaveAsync(event) {
const context = event.model.context;
// get current status
const actionStatus = await context.model('StudyProgramRegisterAction')
.where('id').equal(event.target.id).select('actionStatus/alternateName').value();
if (actionStatus !== 'CompletedActionStatus') {
return;
}
if (event.state === DataObjectState.Insert) {
throw new AccessDeniedError('A study program registration cannot be completed automatically.', null);
}
if (event.state === DataObjectState.Update) {
// get previous status
let previousStatus = 'UnknownActionStatus';
if (event.previous) {
previousStatus = event.previous.actionStatus.alternateName;
} else {
throw new DataError('E_STATE', 'The previous state of an object cannot be determined', null, 'StudyProgramRegisterAction');
}
if (previousStatus === 'ActiveActionStatus') {
// get register action
const item = await context.model('StudyProgramRegisterAction')
.where('id').equal(event.target.id)
.expand('studyProgram', {
name: 'candidate',
options: {
$expand: 'person($expand=gender)'
}
}, 'attachments', 'studyProgramEnrollmentEvent')
.silent().getItem();
if (item == null) {
throw new DataNotFoundError('Current item cannot be found or is inaccessible', null, 'StudyProgramRegisterAction');
}
/**
* @type {Student}
*/
let student = item.candidate.student ? context.model('Student').convert(item.candidate.student) : null;
if (student==null) {
/**
* @type {CandidateStudent}
*/
const candidate = context.model('CandidateStudent').convert(item.candidate);
student = await candidate.convertCandidateToStudent(context);
// if the event requires automated obligatory courses registration
if (item.studyProgramEnrollmentEvent && item.studyProgramEnrollmentEvent.autoRegisterCourses) {
// autoRegisterClasses method is static, so load base class through ModelClassLoaderStrategy
// to prevent direct import from the parent api
const applicationConfiguration = context.getApplication().getConfiguration();
// get schema loader
const schemaLoader = applicationConfiguration
.getStrategy(SchemaLoaderStrategy);
Args.notNull(schemaLoader, 'Schema loader');
// get student model definition
const model = schemaLoader.getModelDefinition('Student');
Args.notNull(model, 'Student model');
// get model class loader
const loader = applicationConfiguration
.getStrategy(ModelClassLoaderStrategy);
Args.notNull(loader, 'Model class loader');
// get student class
const studentBaseClass = loader.resolve(model);
if (studentBaseClass && typeof studentBaseClass.autoRegisterClasses === 'function') {
// create an AutoRegisterClassesAction through autoRegisterClasses student method
const autoRegistrationPayload = {
students: [student.id],
data: {
// only obligatory courses of the student's semester
onlyObligatory: true,
department: student.department
}
}
// start the async auto courses registration process
await studentBaseClass.autoRegisterClasses(context, autoRegistrationPayload);
}
}
}
// add also student attachments
if (item.attachments) {
const attachments = [];
// add to student attachments
for (let i = 0; i < item.attachments.length; i++) {
attachments.push(item.attachments[i].id);
}
student.attachments = attachments;
if (attachments && attachments.length) {
await context.model('Student').silent().save(student);
}
}
const cache = context.getApplication().getConfiguration().getStrategy(DataCacheStrategy);
if (cache != null) {
cache.clear();
}
}
}
}
/**
* @param {DataEventArgs} event
* @param {Function} callback
*/
function afterSave(event, callback) {
return afterSaveAsync(event).then(() => {
return callback();
}).catch((err) => {
return callback(err);
});
}
class CreateStudentAfterAcceptCandidate extends ApplicationService {
constructor(app) {
super(app);
this.install('StudyProgramRegisterAction', __filename);
}
install() {
/**
* get data configuration
* @type {DataConfigurationStrategy}
*/
const configuration = this.getApplication().getConfiguration().getStrategy(DataConfigurationStrategy);
// get StudentRequestAction model definition
const model = configuration.getModelDefinition('StudyProgramRegisterAction');
// get this file path relative to application execution path
const listenerType = './' + path.relative(this.getApplication().getConfiguration().getExecutionPath(), __filename);
// ensure model event listeners
model.eventListeners = model.eventListeners || [];
// try to find event listener
const findIndex = model.eventListeners.findIndex(listener => {
return listener.type === listenerType ||
listener.type === listenerType.replace(/\.js$/, '');
});
if (findIndex < 0) {
// add event listener
model.eventListeners.push({
type: listenerType
});
// update StudentRequestAction model definition
configuration.setModelDefinition(model);
// write to log
TraceUtils.info(`Services: ${this.constructor.name} service has been successfully installed`);
}
}
}
export {
afterSave,
CreateStudentAfterAcceptCandidate
}