@universis/candidates
Version:
Universis api server plugin for study program candidates, internship selection etc
834 lines (130 loc) • 31.2 kB
JavaScript
;var _data = require("@themost/data");
var _middlewares = require("../middlewares");
var _lodash = _interopRequireDefault(require("lodash"));
var _common = require("@themost/common");
var _util = _interopRequireWildcard(require("util"));
var _RandomCandidateUserActivationCode = require("../RandomCandidateUserActivationCode");
var _sendSmsAfterCreateCandidateUserAction = require("../listeners/send-sms-after-create-candidate-user-action");
var _fs = _interopRequireDefault(require("fs"));
var _mailer = require("@themost/mailer");var _dec, _dec2, _dec3, _dec4, _dec5, _dec6, _dec7, _dec8, _dec9, _dec10, _dec11, _dec12, _dec13, _class;function _getRequireWildcardCache() {if (typeof WeakMap !== "function") return null;var cache = new WeakMap();_getRequireWildcardCache = function () {return cache;};return cache;}function _interopRequireWildcard(obj) {if (obj && obj.__esModule) {return obj;}if (obj === null || typeof obj !== "object" && typeof obj !== "function") {return { default: obj };}var cache = _getRequireWildcardCache();if (cache && cache.has(obj)) {return cache.get(obj);}var newObj = {};var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;for (var key in obj) {if (Object.prototype.hasOwnProperty.call(obj, key)) {var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;if (desc && (desc.get || desc.set)) {Object.defineProperty(newObj, key, desc);} else {newObj[key] = obj[key];}}}newObj.default = obj;if (cache) {cache.set(obj, newObj);}return newObj;}function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };}function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {try {var info = gen[key](arg);var value = info.value;} catch (error) {reject(error);return;}if (info.done) {resolve(value);} else {Promise.resolve(value).then(_next, _throw);}}function _asyncToGenerator(fn) {return function () {var self = this,args = arguments;return new Promise(function (resolve, reject) {var gen = fn.apply(self, args);function _next(value) {asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);}function _throw(err) {asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);}_next(undefined);});};}function _applyDecoratedDescriptor(target, property, decorators, descriptor, context) {var desc = {};Object.keys(descriptor).forEach(function (key) {desc[key] = descriptor[key];});desc.enumerable = !!desc.enumerable;desc.configurable = !!desc.configurable;if ('value' in desc || desc.initializer) {desc.writable = true;}desc = decorators.slice().reverse().reduce(function (desc, decorator) {return decorator(target, property, desc) || desc;}, desc);if (context && desc.initializer !== void 0) {desc.value = desc.initializer ? desc.initializer.call(context) : void 0;desc.initializer = undefined;}if (desc.initializer === void 0) {Object.defineProperty(target, property, desc);desc = null;}return desc;}const path = require('path');let
CandidateStudent = (_dec =
_data.EdmMapping.param('schema', _data.EdmType.EdmStream, false), _dec2 =
_data.EdmMapping.param('file', _data.EdmType.EdmStream, false), _dec3 =
_data.EdmMapping.action('import', 'CandidateStudentUploadAction'), _dec4 =
_data.EdmMapping.action('createUser', 'CandidateStudent'), _dec5 =
_data.EdmMapping.action('enroll', 'StudyProgramRegisterAction'), _dec6 =
_data.EdmMapping.action('sendActivationMessage', 'CandidateStudent'), _dec7 =
_data.EdmMapping.action('createStudent', 'Student'), _dec8 =
_data.EdmMapping.param('data', 'Object', false, true), _dec9 =
_data.EdmMapping.param('file', _data.EdmType.EdmStream, false), _dec10 =
_data.EdmMapping.action('importFromSource', 'CandidateStudentUploadAction'), _dec11 =
_data.EdmMapping.param('data', 'Object', false, true), _dec12 =
_data.EdmMapping.action('sendMessage'), _dec13 =
_data.EdmMapping.func("Me", "CandidateStudent"), (_class = class CandidateStudent extends _data.DataObject {static importFile(context, file, schema, forceUpdate) {return _asyncToGenerator(function* () {const req = { files: { file: [Object.assign(file, { mimetype: file.contentType, destination: path.dirname(file.path), filename: path.basename(file.path), originalfilename: file.contentFileName, originalname: file.contentFileName })], schema: [Object.assign(schema, { mimetype: schema.contentType, destination: path.dirname(schema.path), filename: path.basename(schema.path), originalfilename: schema.contentFileName, originalname: schema.contentFileName })] } };const res = {};yield new Promise((resolve, reject) => {(0, _middlewares.xlsPostParserWithConfig)({ name: "file", schema: "schema" })(req, res, err => {if (err) {return reject(err);} // get body
return resolve();});});if (req.body.length > 0) {const testDepartmentAltCode = req.body[0].department.hasOwnProperty('alternativeCode');const groupByExp = testDepartmentAltCode ? 'department.alternativeCode' : 'department';const searchPropertyDP = testDepartmentAltCode ? 'alternativeCode' : 'id';const searchPropertySP = testDepartmentAltCode ? 'department/alternativeCode' : 'department';const inscriptionModes = new Map();const studyPrograms = new Map();const lastActiveStudyPrograms = new Map(); // group candidates by department
const candidates = _lodash.default.groupBy(req.body, groupByExp); // iterate through each one of the unique departments
for (const [department, candidateList] of Object.entries(candidates)) {if (department === 'undefined' /* groupBy shows undefined like a string */) {throw new _common.DataError('Invalid candidates file data. Department column cannot be empty at this context.');} // validate department
const departmentObject = yield context.model('Department').where(searchPropertyDP).equal(department.toString()).getItem();if (departmentObject == null) {throw new _common.DataNotFoundError(`The department with id or alternativeCode ${department} cannot be found or is inaccessible.`);} // validate data for each candidate
for (const candidate of candidateList) {// get inscription mode id
const inscriptionModeId = candidate.inscriptionMode;if (inscriptionModeId) {// check map to prevent uneccessary calls
if (!inscriptionModes.has(inscriptionModeId)) {// validate inscription mode
const inscriptionMode = yield context.model('InscriptionMode').where('id').equal(inscriptionModeId).getItem();if (inscriptionMode == null) {throw new _common.DataNotFoundError(`The inscription mode with id ${inscriptionModeId} cannot be found or is inaccessible.`);} // cache inscription mode
inscriptionModes.set(inscriptionModeId, inscriptionMode);}} else {throw new _common.DataError('Invalid cadidate student data. Inscription mode column cannot be empty at this context.');} // get studyProgramId
const studyProgramId = candidate.studyProgram;if (studyProgramId) {// check map to prevent uneccessary calls
if (!studyPrograms.has(studyProgramId)) {// validate study program
const studyProgram = yield context.model('StudyProgram').where('id').equal(studyProgramId).and('isActive').equal(1).getItem();if (studyProgram == null) {throw new _common.DataNotFoundError(`The study program with id ${studyProgramId} cannot be found, is inaccessible or is inactive.`);} // cache study program
studyPrograms.set(studyProgramId, studyProgram);}} else /*if study program is null, assign last active for that department*/{let lastActiveSP;if (!lastActiveStudyPrograms.has(department)) {// get the department's last active study program
lastActiveSP = yield context.model('StudyProgram').where(searchPropertySP).equal(department.toString()).and('isActive').equal(1).expand('specialties').orderByDescending('id').getItem();if (lastActiveSP == null) {throw new _common.DataNotFoundError('The candidate study program cannot be found or is inaccessible.');}lastActiveStudyPrograms.set(department, lastActiveSP);} else {lastActiveSP = lastActiveStudyPrograms.get(department);} // get the core specialty of the study program
const studyProgramSpecialty = lastActiveSP.specialties.find(sPSpecialty => sPSpecialty.specialty === -1);if (studyProgramSpecialty == null) {throw new _common.DataNotFoundError('The candidate study program specialty cannot be found or is inaccessible.');} // define extra required fields
const extraRequiredFields = { studyProgram: lastActiveSP.id, studyProgramSpecialty: studyProgramSpecialty.id, specialtyId: -1 }; // assign fields to candidate student
Object.assign(candidate, extraRequiredFields);} // ensure that department alternative code is a string
if (candidate.department.alternativeCode) {candidate.department.alternativeCode = candidate.department.alternativeCode.toString();}}}const uploadActionObject = { totalCandidates: req.body.length, updateForced: forceUpdate == null ? false : forceUpdate }; // get the inscriptionYear of the first candidate
const inscriptionYear = req.body[0].inscriptionYear != null ? req.body[0].inscriptionYear.id || req.body[0].inscriptionYear : null;if (inscriptionYear) {// only if all the candidates have the same inscription year
const yearIsShared = req.body.every(candidate => {const candidateYear = candidate.inscriptionYear && (candidate.inscriptionYear.id || candidate.inscriptionYear);return candidateYear === inscriptionYear;});if (yearIsShared) {// append inscriptionYear to upload action
uploadActionObject.inscriptionYear = inscriptionYear;}}const emptyData = req.body.find(candidate => {return !(candidate.inscriptionNumber && candidate.inscriptionYear && candidate.inscriptionMode);});if (emptyData) {throw new _common.DataError('E_ATTRIBUTES', 'The inscription year, inscription mode and inscription number cannot be empty for any candidate.');}const action = yield context.model('CandidateStudentUploadAction').silent().save(uploadActionObject);yield CandidateStudent.saveCandidates(context, req.body, action, forceUpdate);return action;} else {throw new _common.DataError('No candidate students found in provided file.');}})();}static saveCandidates(appContext, candidates, action, forceUpdate) {const app = appContext.getApplication();const context = app.createContext();context.user = appContext.user;const errors = [];const success = [];const skipped = [];_asyncToGenerator(function* () {for (const candidate of candidates) {// ensure inscriptionNumber as string
candidate.inscriptionNumber = candidate.inscriptionNumber.toString();try {// try to find if the candidate is already registered
// note: use the unique constraint attributes of the model
const candidateAlreadySaved = yield context.model('CandidateStudent').where('inscriptionNumber').equal(candidate.inscriptionNumber.toString()).and('inscriptionMode').equal(candidate.inscriptionMode).and('inscriptionYear').equal(candidate.inscriptionYear).select('id', 'user').silent().getItem(); // if force update is falsy and candidate exists, continue
if (!forceUpdate && candidateAlreadySaved) {skipped.push(candidateAlreadySaved);continue;}const candidateUpdated = !!candidateAlreadySaved;if (candidateUpdated) {candidate.user = candidateAlreadySaved.user;}yield new Promise((resolve, reject) => {return context.model('CandidateStudent').save(candidate).then(() => {success.push(candidate); // save also result
return context.model('CandidateStudentUploadActionResult').silent().save({ action: action.id, candidate: candidate, forcelyUpdated: candidateUpdated, result: true, inscriptionNumber: candidate.inscriptionNumber.toString() }).then(() => {return resolve();}).catch(err => {return reject(err);});}).catch(err => {// extend error
err.candidate = `${candidate.person.familyName} ${candidate.person.givenName} (${candidate.inscriptionNumber})`; // push error
errors.push(JSON.stringify(err));return context.model('CandidateStudentUploadActionResult').silent().save({ action: action.id, forcelyUpdated: false, result: false, inscriptionNumber: candidate.inscriptionNumber.toString(), additionalMessage: JSON.stringify(err) }).then(() => {return resolve();}).catch(err => {return reject(err);});});});} catch (err) {_common.TraceUtils.error(err);}}})().then(() => {// finalize context
context.finalize(() => {// add error messages to action message
action.message = errors.length > 0 ? errors.join(' --- ') : null; // set action as completed
action.actionStatus = { alternateName: 'CompletedActionStatus' }; // set totalFailed, totalInserted and totalSkipped
action.totalFailed = errors.length;action.totalInserted = success.length;action.totalSkipped = skipped.length;action.endTime = new Date(); // and update
return context.model('CandidateStudentUploadAction').silent().save(action).then(() => {//
}).catch(err => {_common.TraceUtils.error(`An error occured while trying to complete CandidateStudentUploadAction ${action.id}`);_common.TraceUtils.error(err);});});}).catch(err => {context.finalize(() => {action.actionStatus = { alternateName: 'FailedActionStatus' };action.endTime = new Date();action.message = err.message;action.totalFailed = action.totalCandidates;action.totalInserted = 0;action.totalSkipped = skipped.length; // is 0
return context.model('CandidateStudentUploadAction').silent().save(action).then(() => {//
}).catch(err => {_common.TraceUtils.error(`An error occured while trying to set failed status to CandidateStudentUploadAction ${action.id}`);_common.TraceUtils.error(err);});});});} /**
* Create candidate user
*/createUser() {var _this = this;return _asyncToGenerator(function* () {const model = _this.context.model('CandidateStudent'); // infer object state
const candidate = yield model.where('id').equal(_this.getId()).expand('person', 'user').getItem();if (candidate == null) {return;} // check if user already set
if (candidate.user) {return candidate;}const username = candidate.inscriptionNumber.toString() || candidate.person.email; // check if user already exists
const existingUser = yield _this.context.model('User').where('name').equal(username).select('id').silent().getItem();if (existingUser) {const student = yield _this.context.model('Student').where('user').equal(existingUser.id).select('id').silent().count();if (student) {throw new Error(`User ${username} already exists`);}candidate.user = existingUser;yield _this.context.model('CandidateStudent').silent().save(candidate);return candidate;} // create user
const user = { "name": username, "email": candidate.person.email, "description": `${candidate.person.familyName} ${candidate.person.givenName}` };const service = _this.context.getApplication().getService(_RandomCandidateUserActivationCode.RandomCandidateUserActivationCode);if (service != null) {const activationCode = yield service.generate(_this.context, _this);Object.assign(user, { activationCode });}const result = yield new Promise((resolve, reject) => {_this.context.db.executeInTransaction(cb => {return _this.context.model('CandidateUser').silent().save(user).then(updated => {candidate.user = updated;return model.save(candidate).then(() => {return cb();});}).catch(err => {return cb(err);});}, err => {if (err) {return reject(err);}return resolve(candidate);});});return result;})();}createStudyProgramRegisterAction() {var _this2 = this;return _asyncToGenerator(function* () {const model = _this2.context.model('CandidateStudent'); // get candidate
const candidate = yield model.where('id').equal(_this2.getId()).getItem();if (candidate == null) {throw new _common.DataNotFoundError(`The candidate student cannot be found or is inaccessible.`);} // check if candidate has been linked to a student
// (either directly or by an enrollment application approval)
if (candidate.student) {throw new _common.DataError('E_STUDENT', 'The candidate student has already been linked to a student.');} // check if an action already exists for the candidate
// for this, or later years
const existingAction = yield _this2.context.model('StudyProgramRegisterAction').where('candidate').equal(candidate.id).and('studyProgramEnrollmentEvent/inscriptionYear').greaterOrEqual(candidate.inscriptionYear.id || candidate.inscriptionYear).select('id').silent().count();if (existingAction) {return existingAction;} // create studyProgramRegisterAction
const studyProgramRegisterAction = { studyProgram: candidate.studyProgram, specialization: candidate.studyProgramSpecialty, inscriptionYear: candidate.inscriptionYear, inscriptionPeriod: candidate.inscriptionPeriod, inscriptionMode: candidate.inscriptionMode, candidate: candidate.id, owner: candidate.user // if owner is null, the studyProgramRegisterAction validation listener will throw an error
}; // save studyProgramRegisterAction
const action = yield _this2.context.model('StudyProgramRegisterAction').save(studyProgramRegisterAction); // check if candidate has potential register actions in previous years
const previousRegisterActions = yield _this2.context.model('StudyProgramRegisterAction').where('candidate').equal(candidate.id).and('studyProgramEnrollmentEvent/inscriptionYear').lowerThan(candidate.inscriptionYear.id || candidate.inscriptionYear).and('actionStatus/alternateName').equal('PotentialActionStatus').and('studyProgram').equal(candidate.studyProgram.id || candidate.studyProgram).select('id').silent().getAllItems(); // if any exist
if (previousRegisterActions && previousRegisterActions.length) {// auto-cancel them
yield _this2.context.model('StudyProgramRegisterAction').save(previousRegisterActions.map(item => {return { id: item.id, actionStatus: { alternateName: 'CancelledActionStatus' } };}));}return action;})();}sendActivationMessage() {var _this3 = this;return _asyncToGenerator(function* () {// get validator listener
const validator = new _data.DataPermissionEventListener(); // noinspection JSUnresolvedFunction
const validateAsync = (0, _util.promisify)(validator.validate).bind(validator); // validate CandidateStudent/SendActivationMessage execute permission
const event = { model: _this3.getModel(), privilege: 'CandidateStudent/SendActivationMessage', mask: _data.PermissionMask.Execute, target: _this3, throwError: false };yield validateAsync(event);if (event.result === false) {throw new _common.HttpForbiddenError();} /**
* @type {ApplicationBase}
*/const app = _this3.context.getApplication();let service = app.getService(_sendSmsAfterCreateCandidateUserAction.SendSmsAfterCreateCandidateUser);if (service != null) {return yield service.send(_this3.context, _this3);} // otherwise check if application has sms service enabled
const parentService = app.getService(function SmsService() {});if (parentService == null) {throw new Error('The operation cannot be completed due to invalid application configuration. A required service is missing');}return yield _sendSmsAfterCreateCandidateUserAction.SendSmsAfterCreateCandidateUser.prototype.send(_this3.context, _this3);})();}createStudent() {var _this4 = this;return _asyncToGenerator(function* () {const model = _this4.context.model('CandidateStudent'); // get candidate
/**
* @type {CandidateStudent}
*/const candidate = yield model.where('id').equal(_this4.getId()).expand('student', { name: 'person', options: { $expand: 'gender' } }).getTypedItem();if (candidate == null) {throw new _common.DataNotFoundError(`The candidate student cannot be found or is inaccessible.`);} // check if candidate student exists
if (candidate.student) {throw new _common.DataError('E_STATE', `Candidate student ${candidate.id} is already related to student ${candidate.student.id}.`);} // check if candidate has pending action for same academic year
const exists = yield _this4.context.model('StudyProgramRegisterAction').where('candidate').equal(candidate.id).and('inscriptionYear').equal(candidate.inscriptionYear).and('actionStatus/alternateName').in(['PotentialActionStatus', 'ActiveActionStatus']).silent().count();if (exists) {throw new _common.DataError('E_STATE', `The candidate student has pending StudyProgramRegisterAction for inscription year ${candidate.inscriptionYear && candidate.inscriptionYear.name}.`);}return yield candidate.convertCandidateToStudent(_this4.context);})();}convertCandidateToStudent(context) {var _this5 = this;return _asyncToGenerator(function* () {const candidate = _this5;let student = candidate.student;const result = yield new Promise((resolve, reject) => {_this5.context.db.executeInTransaction(cb => {_asyncToGenerator(function* () {if (student == null) {// get study program data
const studyProgramSpecialty = yield context.model('StudyProgramSpecialty').where('id').equal(candidate.studyProgramSpecialty.id || candidate.studyProgramSpecialty).getItem(); // create person
const person = Object.assign({}, candidate.person); // set gender
person.gender = candidate.person.gender.identifier; // remove person id in order to insert a person based on its data
delete person.id; // create student
// important note: each student has a unique for each study program
const newStudent = Object.assign({}, candidate);if (candidate.user) {// try to find if a student exists with the candidate user
const studentWithCandidateUser = yield context.model('Student').where('user').equal(candidate.user.id || candidate.user).select('id').silent().count();if (studentWithCandidateUser) {const institute = yield context.model('Department').where('id').equal(candidate.department).silent().select('organization').value();const allowStudentUserSharing = yield context.model('InstituteConfiguration').where('institute').equal(institute).select('allowStudentUserSharing').silent().value();if (allowStudentUserSharing === false) {// and if it exists, ensure that the new student is not linked with it
newStudent.user = null;}}const user = candidate.user; // when allowStudentUserSharing === true
if (user != null && candidate.user === newStudent.user) {const convertedUser = context.model('User').convert(user); // add user to students group
const userGroups = convertedUser.property('groups'); // add to students group
yield userGroups.silent().insert({ name: 'Students' }); // find user's groups
const groupOfuser = yield context.model('User').where('id').equal(user).expand('groups').silent().select('groups').getItem();const exists = groupOfuser.groups.filter(el => el.name === 'Candidates').length;if (exists) {// and remove it from candidates
yield userGroups.silent().remove({ name: 'Candidates' });}if (candidate.department) {// handle user departments
const userDepartments = convertedUser.property('departments'); // insert current candidate department
yield userDepartments.silent().insert({ id: candidate.department.id || candidate.department });} // save also applicationUser
// get student group // TODO: Change this when user model becomes updatable
const studentGroup = yield context.model('Group').where('name').equal('Students').silent().getItem();const applicationUser = yield context.model('ApplicationUser').where('userId').equal(user).silent().getItem();if (applicationUser) {applicationUser.roleId = studentGroup.id;applicationUser.applicationId = 'GRUNI'; // save applicationUser
yield context.model('ApplicationUser').silent().save(applicationUser);}}delete newStudent.id; /*
delete newStudent.studentIdentifier;
delete newStudent.studentInstituteIdentifier;
*/newStudent.person = person;newStudent.studyProgramSpecialty = studyProgramSpecialty;newStudent.semester = 1;newStudent.inscriptionDate = new Date();newStudent.inscriptionSemester = 1;newStudent.studentStatus = { alternateName: 'active' };newStudent.specialtyId = studyProgramSpecialty.specialty;const Students = context.model('Student');student = yield Students.save(newStudent); // create user for newStudent when allowStudentUserSharing = false
if (student.user === null) {const studentModel = context.model('Student').convert(student);const action = yield studentModel.createUser(context);student.user = action && action.student && action.student.user;} // update candidateStudent with new student id
candidate.student = student.id; // save candidateStudent
yield context.model('CandidateStudent').save(candidate);}}})().then(() => {return cb();}).catch(err => {return cb(err);});}, err => {if (err) {return reject(err);}return resolve(student);});});return result || student;})();}static importFromSource(context, file, data) {return _asyncToGenerator(function* () {// parse form data
data = JSON.parse(data && data.data); // validate candidate source on passed data
if (!(data && data.candidateSource)) {throw new _common.DataError('E_CANDIDATE_SOURCE', 'No candidate source provided.');} // validate candidate source access/existance
// NOTE: Consider using silent
const candidateSource = yield context.model('CandidateSource').where('id').equal(data.candidateSource.id || data.candidateSource).expand('attachments').getItem();if (candidateSource == null) {throw new _common.DataNotFoundError('The specified candidate source is not found or is inaccessible.');} // validate candidate source attachments (e.g. schema configuration)
if (!(Array.isArray(candidateSource.attachments) && candidateSource.attachments.length)) {throw new _common.DataNotFoundError('The specified candidate source is not linked to a schema (configuration) file or it is inaccessible.');} // fetch the schema configuration attachment
// based on the schemaURL of the source
if (!candidateSource.schemaURL) {throw new _common.DataError('E_SCHEMA_URL', 'The schemaURL is not set for the specified candidate source.');}const schemaAttachment = candidateSource.attachments.find(attachment => attachment.url === candidateSource.schemaURL);if (schemaAttachment == null) {throw new _common.DataError('E_SCHEMA_ATTACHMENT', 'The schema (configuration) attachment based on the schemaURL of the source cannot be found or is inaccessible.');} /**
* get private content service
* @type {PrivateContentService}
*/let privateContentService = context.getApplication().getService(function PrivateContentService() {});if (privateContentService == null) {throw new _common.DataError('E_PCService', 'Private content service is not registered.');} // get physical path
const resolvePhysicalPath = _util.default.promisify(privateContentService.resolvePhysicalPath).bind(privateContentService);const physicalPath = yield resolvePhysicalPath(context, schemaAttachment); // and create a read stream
const configuration = _fs.default.createReadStream(physicalPath);configuration.contentType = schemaAttachment.contentType; // and import the candidate students
return yield CandidateStudent.importFile(context, file, configuration, data.forceUpdate);})();}sendEmail(data) {var _this6 = this;return _asyncToGenerator(function* () {if (!(data && data.candidateStudent && data.body && data.subject)) {throw new _common.DataError('E_ARG', 'Provide a valid candidateStudent, body and subject.');}const context = _this6.context; // validate student
const candidate = yield context.model('CandidateStudent').where('id').equal(data.candidateStudent.id || data.candidateStudent).expand('person').getItem();if (candidate == null) {throw new _common.DataNotFoundError('The specified candidate student cannot be found or is inaccessible.');} // validate email
const email = candidate.person.email; // https://github.com/formio/formio.js/blob/master/src/validator/rules/Email.js#L13
const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;if (!re.test(email)) {throw new _common.DataError('E_INVALID_EMAIL', `The candidate student's email is invalid or empty.`);} // get mail template
const mailTemplate = (yield context.model('MailConfiguration').where('target').equal('DirectEmailToCandidate').select('template').silent().value()) || 'direct-email-to-candidate';const mailer = (0, _mailer.getMailer)(context);const body = data.body; // and try to send
return yield new Promise((resolve, reject) => {mailer.template(mailTemplate).subject(data.subject).to(email).send({ model: { candidate, body } }, err => {if (err) {_common.TraceUtils.error(err);return reject(err);}return resolve();});});})();}static getMe(context) {return context.model('CandidateStudent').where('user/name').notEqual(null).and('user/name').equal(context.user && context.user.name).orderByDescending('id').prepare();}}, (_applyDecoratedDescriptor(_class, "importFile", [_dec, _dec2, _dec3], Object.getOwnPropertyDescriptor(_class, "importFile"), _class), _applyDecoratedDescriptor(_class.prototype, "createUser", [_dec4], Object.getOwnPropertyDescriptor(_class.prototype, "createUser"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "createStudyProgramRegisterAction", [_dec5], Object.getOwnPropertyDescriptor(_class.prototype, "createStudyProgramRegisterAction"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "sendActivationMessage", [_dec6], Object.getOwnPropertyDescriptor(_class.prototype, "sendActivationMessage"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "createStudent", [_dec7], Object.getOwnPropertyDescriptor(_class.prototype, "createStudent"), _class.prototype), _applyDecoratedDescriptor(_class, "importFromSource", [_dec8, _dec9, _dec10], Object.getOwnPropertyDescriptor(_class, "importFromSource"), _class), _applyDecoratedDescriptor(_class.prototype, "sendEmail", [_dec11, _dec12], Object.getOwnPropertyDescriptor(_class.prototype, "sendEmail"), _class.prototype), _applyDecoratedDescriptor(_class, "getMe", [_dec13], Object.getOwnPropertyDescriptor(_class, "getMe"), _class)), _class));module.exports = CandidateStudent;
//# sourceMappingURL=CandidateStudent.js.map