@universis/accommodation 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitlab-ci.yml +23 -0
- package/LICENSE +163 -0
- package/README.md +3 -0
- package/dist/AccommodationSchemaLoader.js +35 -0
- package/dist/AccommodationSchemaLoader.js.map +1 -0
- package/dist/AccommodationService.js +68 -0
- package/dist/AccommodationService.js.map +1 -0
- package/dist/DepartmentReplacer.js +54 -0
- package/dist/DepartmentReplacer.js.map +1 -0
- package/dist/StudentReplacer.js +75 -0
- package/dist/StudentReplacer.js.map +1 -0
- package/dist/config/models/Accommodation.json +96 -0
- package/dist/config/models/AccommodationCardEffectiveStatusType.json +107 -0
- package/dist/config/models/AccommodationCardEffectiveStatusTypeLocale.json +85 -0
- package/dist/config/models/AccommodationChildFinancialAttribute.json +46 -0
- package/dist/config/models/AccommodationGuardianFinancialAttribute.json +46 -0
- package/dist/config/models/AccommodationInscriptionModeTag.json +100 -0
- package/dist/config/models/AccommodationRequestAction.json +500 -0
- package/dist/config/models/AccommodationRequestActionMessage.json +46 -0
- package/dist/config/models/AccommodationRequestActionReview.json +31 -0
- package/dist/config/models/AccommodationRequestAttachmentConfiguration.json +72 -0
- package/dist/config/models/AccommodationRequestCategory.json +50 -0
- package/dist/config/models/AccommodationRequestEffectiveStatusType.json +212 -0
- package/dist/config/models/AccommodationRequestEffectiveStatusTypeLocale.json +85 -0
- package/dist/config/models/AccommodationRequestEvent.json +117 -0
- package/dist/config/models/AccommodationRequestFinancialAttribute.json +53 -0
- package/dist/config/models/AccommodationRoom.json +151 -0
- package/dist/config/models/AccommodationSiblingFinancialAttribute.json +57 -0
- package/dist/config/models/CancelAccommodationCardAction.json +32 -0
- package/dist/config/models/GuardianType.json +78 -0
- package/dist/config/models/Review.json +50 -0
- package/dist/config/models/RoomType.json +320 -0
- package/dist/config/models/RoomTypeLocale.json +86 -0
- package/dist/config/models/StudentAccommodationCard.json +158 -0
- package/dist/config/models/TestAction.json +50 -0
- package/dist/config/scope.access.js +148 -0
- package/dist/config/scope.access.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/listeners/AddDefaultAttachmentConfiguration.js +44 -0
- package/dist/listeners/AddDefaultAttachmentConfiguration.js.map +1 -0
- package/dist/listeners/DefaultAttachmentConfigurations.json +277 -0
- package/dist/listeners/DefaultAttachmentTypes.json +523 -0
- package/dist/listeners/GenerateRequestNumberListener.js +87 -0
- package/dist/listeners/GenerateRequestNumberListener.js.map +1 -0
- package/dist/listeners/OnActionCompleteListener.js +96 -0
- package/dist/listeners/OnActionCompleteListener.js.map +1 -0
- package/dist/listeners/OnCancelAccommodationCardListener.js +87 -0
- package/dist/listeners/OnCancelAccommodationCardListener.js.map +1 -0
- package/dist/listeners/OnReactivateAccommodationCardListener.js +87 -0
- package/dist/listeners/OnReactivateAccommodationCardListener.js.map +1 -0
- package/dist/listeners/SendEmailAfterActionStatusChangeListener.js +98 -0
- package/dist/listeners/SendEmailAfterActionStatusChangeListener.js.map +1 -0
- package/dist/listeners/SendEmailAfterCardStatusChangeListener.js +139 -0
- package/dist/listeners/SendEmailAfterCardStatusChangeListener.js.map +1 -0
- package/dist/listeners/StudentAccommodationCardSaveListener.js +90 -0
- package/dist/listeners/StudentAccommodationCardSaveListener.js.map +1 -0
- package/dist/listeners/UpdateStudentAccommodationCardListener.js +70 -0
- package/dist/listeners/UpdateStudentAccommodationCardListener.js.map +1 -0
- package/dist/listeners/ValidateActionListener.js +348 -0
- package/dist/listeners/ValidateActionListener.js.map +1 -0
- package/dist/listeners/data-localization.js +209 -0
- package/dist/listeners/data-localization.js.map +1 -0
- package/dist/listeners/lookup-cache-listener.js +90 -0
- package/dist/listeners/lookup-cache-listener.js.map +1 -0
- package/dist/models/Accommodation.js +53 -0
- package/dist/models/Accommodation.js.map +1 -0
- package/dist/models/AccommodationRequestAction.js +214 -0
- package/dist/models/AccommodationRequestAction.js.map +1 -0
- package/dist/models/AccommodationRequestEvent.js +277 -0
- package/dist/models/AccommodationRequestEvent.js.map +1 -0
- package/dist/models/EnableAttachmentModel.js +210 -0
- package/dist/models/EnableAttachmentModel.js.map +1 -0
- package/dist/models/StudentAccommodationCard.js +93 -0
- package/dist/models/StudentAccommodationCard.js.map +1 -0
- package/dist/models/TestAction.d.ts +5 -0
- package/dist/models/TestAction.js +5 -0
- package/dist/models/TestAction.js.map +1 -0
- package/dist/templates/mail-after-dining-request-status-change/html.ejs +27 -0
- package/package.json +57 -0
- package/src/AccommodationSchemaLoader.js +35 -0
- package/src/AccommodationService.js +67 -0
- package/src/DepartmentReplacer.js +53 -0
- package/src/StudentReplacer.js +74 -0
- package/src/config/models/Accommodation.json +96 -0
- package/src/config/models/AccommodationCardEffectiveStatusType.json +107 -0
- package/src/config/models/AccommodationCardEffectiveStatusTypeLocale.json +85 -0
- package/src/config/models/AccommodationChildFinancialAttribute.json +46 -0
- package/src/config/models/AccommodationGuardianFinancialAttribute.json +46 -0
- package/src/config/models/AccommodationInscriptionModeTag.json +100 -0
- package/src/config/models/AccommodationRequestAction.json +500 -0
- package/src/config/models/AccommodationRequestActionMessage.json +46 -0
- package/src/config/models/AccommodationRequestActionReview.json +31 -0
- package/src/config/models/AccommodationRequestAttachmentConfiguration.json +72 -0
- package/src/config/models/AccommodationRequestCategory.json +50 -0
- package/src/config/models/AccommodationRequestEffectiveStatusType.json +212 -0
- package/src/config/models/AccommodationRequestEffectiveStatusTypeLocale.json +85 -0
- package/src/config/models/AccommodationRequestEvent.json +117 -0
- package/src/config/models/AccommodationRequestFinancialAttribute.json +53 -0
- package/src/config/models/AccommodationRoom.json +151 -0
- package/src/config/models/AccommodationSiblingFinancialAttribute.json +57 -0
- package/src/config/models/CancelAccommodationCardAction.json +32 -0
- package/src/config/models/GuardianType.json +78 -0
- package/src/config/models/Review.json +50 -0
- package/src/config/models/RoomType.json +320 -0
- package/src/config/models/RoomTypeLocale.json +86 -0
- package/src/config/models/StudentAccommodationCard.json +158 -0
- package/src/config/models/TestAction.json +50 -0
- package/src/config/scope.access.js +148 -0
- package/src/index.d.ts +2 -0
- package/src/index.js +2 -0
- package/src/listeners/AddDefaultAttachmentConfiguration.js +43 -0
- package/src/listeners/DefaultAttachmentConfigurations.json +277 -0
- package/src/listeners/DefaultAttachmentTypes.json +523 -0
- package/src/listeners/GenerateRequestNumberListener.js +86 -0
- package/src/listeners/OnActionCompleteListener.js +95 -0
- package/src/listeners/OnCancelAccommodationCardListener.js +86 -0
- package/src/listeners/OnReactivateAccommodationCardListener.js +86 -0
- package/src/listeners/SendEmailAfterActionStatusChangeListener.js +97 -0
- package/src/listeners/SendEmailAfterCardStatusChangeListener.js +138 -0
- package/src/listeners/StudentAccommodationCardSaveListener.js +89 -0
- package/src/listeners/UpdateStudentAccommodationCardListener.js +69 -0
- package/src/listeners/ValidateActionListener.js +347 -0
- package/src/listeners/data-localization.js +214 -0
- package/src/listeners/lookup-cache-listener.js +89 -0
- package/src/models/Accommodation.js +52 -0
- package/src/models/AccommodationRequestAction.js +195 -0
- package/src/models/AccommodationRequestEvent.js +276 -0
- package/src/models/EnableAttachmentModel.js +209 -0
- package/src/models/StudentAccommodationCard.js +92 -0
- package/src/models/TestAction.d.ts +5 -0
- package/src/models/TestAction.js +10 -0
- package/src/templates/mail-after-dining-request-status-change/html.ejs +27 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// eslint-disable-next-line no-unused-vars
|
|
2
|
+
async function beforeSaveAsync(event) {
|
|
3
|
+
const context = event.model.context;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
async function afterSaveAsync(event) {
|
|
7
|
+
// get context
|
|
8
|
+
// eslint-disable-next-line no-unused-vars
|
|
9
|
+
const context = event.model.context;
|
|
10
|
+
// get current status
|
|
11
|
+
const request = await event.model.where('id').equal(event.target.id)
|
|
12
|
+
.expand({
|
|
13
|
+
name: 'accommodationRequestEvent',
|
|
14
|
+
options: {
|
|
15
|
+
$expand: 'academicYear,academicPeriod',
|
|
16
|
+
}
|
|
17
|
+
}).getItem();
|
|
18
|
+
const actionStatus = request && request.actionStatus && request.actionStatus.alternateName ? request.actionStatus.alternateName : null;
|
|
19
|
+
if ((actionStatus || actionStatus.alternateName) === 'CompletedActionStatus') {
|
|
20
|
+
// set student accommodation card
|
|
21
|
+
const now = new Date();
|
|
22
|
+
|
|
23
|
+
// const now = new Date();
|
|
24
|
+
let academicYear = request && request.accommodationRequestEvent && request.accommodationRequestEvent.academicYear ? request.accommodationRequestEvent.academicYear : null;
|
|
25
|
+
let academicPeriod = request && request.accommodationRequestEvent && request.accommodationRequestEvent.academicPeriod ? request.accommodationRequestEvent.academicPeriod : null;
|
|
26
|
+
let validThrough = request && request.accommodationRequestEvent && request.accommodationRequestEvent.validThrough ? request.accommodationRequestEvent.validThrough : null;
|
|
27
|
+
// get original student
|
|
28
|
+
const student = await context.model('Student').where('id').equal(request.student.id || request.student)
|
|
29
|
+
.expand({
|
|
30
|
+
name: 'department',
|
|
31
|
+
options: {
|
|
32
|
+
$expand: 'currentYear,currentPeriod',
|
|
33
|
+
}
|
|
34
|
+
}).getItem();
|
|
35
|
+
if (student == null) {
|
|
36
|
+
throw new Error(`Student with id ${request.student.id || request.student} not found.`);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (academicYear == null) {
|
|
40
|
+
// get student current academic year
|
|
41
|
+
|
|
42
|
+
academicYear = student && student.department && student.department.currentYear ? student.department.currentYear : null;
|
|
43
|
+
// await event.model.where('id').equal(event.target.id).select('student/department/currentYear').value();
|
|
44
|
+
}
|
|
45
|
+
if (academicPeriod == null) {
|
|
46
|
+
// get student current academic period
|
|
47
|
+
academicPeriod = student && student.department && student.department.currentPeriod ? student.department.currentPeriod : null;
|
|
48
|
+
}
|
|
49
|
+
let cardActionStatus = {};
|
|
50
|
+
if (event.target.accommodation && (Object.keys(event.target.accommodation).length === 0 || event.target.accommodation === '')) {
|
|
51
|
+
// get accommodation valid through date
|
|
52
|
+
cardActionStatus = { alternateName: 'PotentialActionStatus' }
|
|
53
|
+
|
|
54
|
+
} else {
|
|
55
|
+
cardActionStatus = { alternateName: 'CompletedActionStatus' }
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const StudentAccommodationCard = {
|
|
59
|
+
action: event.target.id,
|
|
60
|
+
student: student,
|
|
61
|
+
academicYear: academicYear,
|
|
62
|
+
academicPeriod: academicPeriod,
|
|
63
|
+
validFrom: now,
|
|
64
|
+
validThrough: validThrough,
|
|
65
|
+
cardStatus: cardActionStatus,
|
|
66
|
+
accommodationRoom: event.target.room || null
|
|
67
|
+
};
|
|
68
|
+
// save student accommodation card
|
|
69
|
+
await context.model('StudentAccommodationCard').silent().save(StudentAccommodationCard);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* @param {DataEventArgs} event
|
|
75
|
+
* @param {Function} callback
|
|
76
|
+
*/
|
|
77
|
+
export function beforeSave(event, callback) {
|
|
78
|
+
return beforeSaveAsync(event).then(() => {
|
|
79
|
+
return callback();
|
|
80
|
+
}).catch((err) => {
|
|
81
|
+
return callback(err);
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* @param {DataEventArgs} event
|
|
87
|
+
* @param {Function} callback
|
|
88
|
+
*/
|
|
89
|
+
export function afterSave(event, callback) {
|
|
90
|
+
return afterSaveAsync(event).then(() => {
|
|
91
|
+
return callback();
|
|
92
|
+
}).catch((err) => {
|
|
93
|
+
return callback(err);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { DataPermissionEventListener, PermissionMask } from "@themost/data";
|
|
2
|
+
import { DataError } from '@themost/common';
|
|
3
|
+
import { promisify } from "util";
|
|
4
|
+
|
|
5
|
+
async function beforeSaveAsync(event) {
|
|
6
|
+
//
|
|
7
|
+
if (event.state !== 2) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const context = event.model.context;
|
|
12
|
+
|
|
13
|
+
const previous = event.previous;
|
|
14
|
+
if (previous == null) {
|
|
15
|
+
throw new DataError('E_PREVIOUS', 'The previous state of the object cannot be determined');
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const target = event.target;
|
|
19
|
+
|
|
20
|
+
if (target.active === false && previous.active === true) {
|
|
21
|
+
// get validator listener
|
|
22
|
+
const validator = new DataPermissionEventListener();
|
|
23
|
+
// noinspection JSUnresolvedFunction
|
|
24
|
+
const validateAsync = promisify(validator.validate)
|
|
25
|
+
.bind(validator);
|
|
26
|
+
// validate StudentAccommodationCard/Cancel execute permission
|
|
27
|
+
const validateEvent = {
|
|
28
|
+
model: context.model('StudentAccommodationCard'),
|
|
29
|
+
privilege: 'StudentAccommodationCard/Cancel',
|
|
30
|
+
mask: PermissionMask.Execute,
|
|
31
|
+
target: event.target && event.target.id,
|
|
32
|
+
throwError: true
|
|
33
|
+
}
|
|
34
|
+
await validateAsync(validateEvent);
|
|
35
|
+
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function afterSaveAsync(event) {
|
|
40
|
+
if (event.state !== 2) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const context = event.model.context;
|
|
45
|
+
|
|
46
|
+
const previous = event.previous;
|
|
47
|
+
if (previous == null) {
|
|
48
|
+
throw new DataError('E_PREVIOUS', 'The previous state of the object cannot be determined');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const target = event.target;
|
|
52
|
+
|
|
53
|
+
if (target.active === false && previous.active === true) {
|
|
54
|
+
//save
|
|
55
|
+
await context.model('CancelAccommodationCardAction').save({
|
|
56
|
+
accommodationCard: target.id,
|
|
57
|
+
actionStatus: {
|
|
58
|
+
alternateName: 'CompletedActionStatus'
|
|
59
|
+
}
|
|
60
|
+
})
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* @param {DataEventArgs} event
|
|
66
|
+
* @param {Function} callback
|
|
67
|
+
*/
|
|
68
|
+
export function beforeSave(event, callback) {
|
|
69
|
+
return beforeSaveAsync(event).then(() => {
|
|
70
|
+
return callback();
|
|
71
|
+
}).catch((err) => {
|
|
72
|
+
return callback(err);
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* @param {DataEventArgs} event
|
|
78
|
+
* @param {Function} callback
|
|
79
|
+
*/
|
|
80
|
+
export function afterSave(event, callback) {
|
|
81
|
+
return afterSaveAsync(event).then(() => {
|
|
82
|
+
return callback();
|
|
83
|
+
}).catch((err) => {
|
|
84
|
+
return callback(err);
|
|
85
|
+
});
|
|
86
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { DataPermissionEventListener, PermissionMask } from "@themost/data";
|
|
2
|
+
import { DataError } from '@themost/common';
|
|
3
|
+
import { promisify } from "util";
|
|
4
|
+
|
|
5
|
+
async function beforeSaveAsync(event) {
|
|
6
|
+
//
|
|
7
|
+
if (event.state !== 2) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const context = event.model.context;
|
|
12
|
+
|
|
13
|
+
const previous = event.previous;
|
|
14
|
+
if (previous == null) {
|
|
15
|
+
throw new DataError('E_PREVIOUS', 'The previous state of the object cannot be determined');
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const target = event.target;
|
|
19
|
+
|
|
20
|
+
if (target.active === false && previous.active === true) {
|
|
21
|
+
// get validator listener
|
|
22
|
+
const validator = new DataPermissionEventListener();
|
|
23
|
+
// noinspection JSUnresolvedFunction
|
|
24
|
+
const validateAsync = promisify(validator.validate)
|
|
25
|
+
.bind(validator);
|
|
26
|
+
// validate StudentAccommodationCard/Cancel execute permission
|
|
27
|
+
const validateEvent = {
|
|
28
|
+
model: context.model('StudentAccommodationCard'),
|
|
29
|
+
privilege: 'StudentAccommodationCard/Cancel',
|
|
30
|
+
mask: PermissionMask.Execute,
|
|
31
|
+
target: event.target && event.target.id,
|
|
32
|
+
throwError: true
|
|
33
|
+
}
|
|
34
|
+
await validateAsync(validateEvent);
|
|
35
|
+
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function afterSaveAsync(event) {
|
|
40
|
+
if (event.state !== 2) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const context = event.model.context;
|
|
45
|
+
|
|
46
|
+
const previous = event.previous;
|
|
47
|
+
if (previous == null) {
|
|
48
|
+
throw new DataError('E_PREVIOUS', 'The previous state of the object cannot be determined');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const target = event.target;
|
|
52
|
+
|
|
53
|
+
if (target.active === false && previous.active === true) {
|
|
54
|
+
//save
|
|
55
|
+
await context.model('CancelAccommodationCardAction').save({
|
|
56
|
+
accommodationCard: target.id,
|
|
57
|
+
actionStatus: {
|
|
58
|
+
alternateName: 'CompletedActionStatus'
|
|
59
|
+
}
|
|
60
|
+
})
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* @param {DataEventArgs} event
|
|
66
|
+
* @param {Function} callback
|
|
67
|
+
*/
|
|
68
|
+
export function beforeSave(event, callback) {
|
|
69
|
+
return beforeSaveAsync(event).then(() => {
|
|
70
|
+
return callback();
|
|
71
|
+
}).catch((err) => {
|
|
72
|
+
return callback(err);
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* @param {DataEventArgs} event
|
|
78
|
+
* @param {Function} callback
|
|
79
|
+
*/
|
|
80
|
+
export function afterSave(event, callback) {
|
|
81
|
+
return afterSaveAsync(event).then(() => {
|
|
82
|
+
return callback();
|
|
83
|
+
}).catch((err) => {
|
|
84
|
+
return callback(err);
|
|
85
|
+
});
|
|
86
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { getMailer } from '@themost/mailer';
|
|
2
|
+
import { DataError } from '@themost/data';
|
|
3
|
+
import { TraceUtils } from "@themost/common";
|
|
4
|
+
/**
|
|
5
|
+
* @param {DataEventArgs} event
|
|
6
|
+
*/
|
|
7
|
+
async function afterSaveAsync(event) {
|
|
8
|
+
if (event.state === 2) {
|
|
9
|
+
const context = event.model.context;
|
|
10
|
+
/**
|
|
11
|
+
* @type {import('@themost/mailer').MailerHelper}
|
|
12
|
+
*/
|
|
13
|
+
const mailer = getMailer(context);
|
|
14
|
+
|
|
15
|
+
const actionStatus = await context.model('AccommodationRequestAction')
|
|
16
|
+
.where('id').equal(event.target.id).select('actionStatus/alternateName').value();
|
|
17
|
+
let previousStatus = 'UnknownActionStatus';
|
|
18
|
+
if (event.previous) {
|
|
19
|
+
previousStatus = event.previous.actionStatus.alternateName;
|
|
20
|
+
} else {
|
|
21
|
+
throw new DataError('E_STATE', 'The previous state of an object cannot be determined', null, 'AccommodationRequestAction');
|
|
22
|
+
}
|
|
23
|
+
if (actionStatus === previousStatus) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
// get mail template
|
|
27
|
+
const mailTemplate = await context.model('MailConfiguration').where('target').equal('AccommodationRequestActionStatusChange').silent().getItem();
|
|
28
|
+
if (mailTemplate == null) {
|
|
29
|
+
//
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
// get parent action data
|
|
33
|
+
const item = await context.model('AccommodationRequestAction')
|
|
34
|
+
.where('id').equal(event.target.id)
|
|
35
|
+
.expand({
|
|
36
|
+
name: 'student',
|
|
37
|
+
options: {
|
|
38
|
+
$expand: 'person'
|
|
39
|
+
}
|
|
40
|
+
}, 'owner')
|
|
41
|
+
.silent().getItem();
|
|
42
|
+
|
|
43
|
+
const application = await context.model('WebApplication')
|
|
44
|
+
.where('alternateName').equal('students')
|
|
45
|
+
.and('applicationSuite').equal('universis')
|
|
46
|
+
.silent().getItem();
|
|
47
|
+
const config = await context.model('StudentRequestConfiguration')
|
|
48
|
+
.where('additionalType').equal(event.model.name)
|
|
49
|
+
.and('inLanguage').equal(event.target.inLanguage || context.locale)
|
|
50
|
+
.silent().getItem();
|
|
51
|
+
|
|
52
|
+
if (item && application && config) {
|
|
53
|
+
|
|
54
|
+
const email = item.student.person.email;
|
|
55
|
+
|
|
56
|
+
if (email == null || typeof email !== 'string') {
|
|
57
|
+
TraceUtils.warn(`Cannot send email for ${item.student.person.familyName} ${item.student.person.givenName}. Student [${item.student.id}] email does not exist.`);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
await new Promise((resolve) => {
|
|
61
|
+
mailer.template(mailTemplate.template)
|
|
62
|
+
.subject(mailTemplate.subject)
|
|
63
|
+
.bcc(mailTemplate.bcc || '')
|
|
64
|
+
.to(email)
|
|
65
|
+
.send({
|
|
66
|
+
model: item,
|
|
67
|
+
application: application,
|
|
68
|
+
configuration: config
|
|
69
|
+
}, (err) => {
|
|
70
|
+
if (err) {
|
|
71
|
+
try {
|
|
72
|
+
TraceUtils.error('An error occurred while trying to send an email notification after status change.');
|
|
73
|
+
TraceUtils.error(`Student=${item.student.id}, template=${mailTemplate.template}`);
|
|
74
|
+
TraceUtils.error(err);
|
|
75
|
+
} catch (err1) {
|
|
76
|
+
// do nothing
|
|
77
|
+
}
|
|
78
|
+
return resolve();
|
|
79
|
+
}
|
|
80
|
+
return resolve();
|
|
81
|
+
})
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* @param {DataEventArgs} event
|
|
89
|
+
* @param {Function} callback
|
|
90
|
+
*/
|
|
91
|
+
export function afterSave(event, callback) {
|
|
92
|
+
return afterSaveAsync(event).then(() => {
|
|
93
|
+
return callback();
|
|
94
|
+
}).catch((err) => {
|
|
95
|
+
return callback(err);
|
|
96
|
+
});
|
|
97
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { getMailer } from '@themost/mailer';
|
|
2
|
+
import { DataError } from '@themost/data';
|
|
3
|
+
import { TraceUtils } from "@themost/common";
|
|
4
|
+
/**
|
|
5
|
+
* @param {DataEventArgs} event
|
|
6
|
+
*/
|
|
7
|
+
async function afterSaveAsync(event) {
|
|
8
|
+
if (event.state === 2) {
|
|
9
|
+
const context = event.model.context;
|
|
10
|
+
/**
|
|
11
|
+
* @type {import('@themost/mailer').MailerHelper}
|
|
12
|
+
*/
|
|
13
|
+
const mailer = getMailer(context);
|
|
14
|
+
|
|
15
|
+
const currentCardStatus = await context
|
|
16
|
+
.model('StudentDiningCard')
|
|
17
|
+
.where('id')
|
|
18
|
+
.equal(event.target.id)
|
|
19
|
+
.select('active')
|
|
20
|
+
.value();
|
|
21
|
+
let previousCardStatus = 'UnknownStatus';
|
|
22
|
+
if (event.previous) {
|
|
23
|
+
previousCardStatus = event.previous.active;
|
|
24
|
+
} else {
|
|
25
|
+
throw new DataError('E_STATE', 'The previous state of an object cannot be determined', null, 'StudentDiningCard');
|
|
26
|
+
}
|
|
27
|
+
if (currentCardStatus === previousCardStatus) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// get mail template
|
|
32
|
+
const mailTemplate = await context
|
|
33
|
+
.model('MailConfigurations')
|
|
34
|
+
.where('target')
|
|
35
|
+
.equal('DiningCardActiveStatusChange')
|
|
36
|
+
.silent()
|
|
37
|
+
.getItem();
|
|
38
|
+
if (mailTemplate == null) {
|
|
39
|
+
//
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
//get parent action data
|
|
44
|
+
let item;
|
|
45
|
+
if (typeof event.target.action === 'object' && typeof event.target.action.id === 'number' && Number.isInteger(event.target.action.id) && event.target.action.id > 0) {
|
|
46
|
+
item = await context
|
|
47
|
+
.model('DiningRequestAction')
|
|
48
|
+
.where('id')
|
|
49
|
+
.equal(event.target.action.id)
|
|
50
|
+
.expand({
|
|
51
|
+
name: 'student',
|
|
52
|
+
options: {
|
|
53
|
+
$expand: 'person'
|
|
54
|
+
}
|
|
55
|
+
})
|
|
56
|
+
.silent()
|
|
57
|
+
.getItem();
|
|
58
|
+
|
|
59
|
+
} else if (typeof event.target.action === 'number' && Number.isInteger(event.target.action) && event.target.action > 0) {
|
|
60
|
+
item = await context
|
|
61
|
+
.model('DiningRequestAction')
|
|
62
|
+
.where('id')
|
|
63
|
+
.equal(event.target.action)
|
|
64
|
+
.expand({
|
|
65
|
+
name: 'student',
|
|
66
|
+
options: {
|
|
67
|
+
$expand: 'person'
|
|
68
|
+
}
|
|
69
|
+
})
|
|
70
|
+
.silent()
|
|
71
|
+
.getItem();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const application = await context
|
|
75
|
+
.model('WebApplication')
|
|
76
|
+
.where('alternateName')
|
|
77
|
+
.equal('students')
|
|
78
|
+
.and('applicationSuite')
|
|
79
|
+
.equal('universis')
|
|
80
|
+
.silent()
|
|
81
|
+
.getItem();
|
|
82
|
+
|
|
83
|
+
const config = await context
|
|
84
|
+
.model('StudentRequestConfiguration')
|
|
85
|
+
.where('additionalType')
|
|
86
|
+
.equal('DiningRequestAction')
|
|
87
|
+
.and('inLanguage')
|
|
88
|
+
.equal(event.target.inLanguage || context.locale)
|
|
89
|
+
.silent()
|
|
90
|
+
.getItem();
|
|
91
|
+
|
|
92
|
+
if (item && application && config) {
|
|
93
|
+
|
|
94
|
+
const email = item.student.person.email;
|
|
95
|
+
|
|
96
|
+
if (email == null || typeof email !== 'string') {
|
|
97
|
+
TraceUtils.warn(`Cannot send email for ${item.student.person.familyName} ${item.student.person.givenName}. Student [${item.student.id}] email does not exist.`);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
await new Promise((resolve) => {
|
|
101
|
+
mailer.template(mailTemplate.template)
|
|
102
|
+
.subject(mailTemplate.subject)
|
|
103
|
+
.bcc(mailTemplate.bcc || '')
|
|
104
|
+
.to(email)
|
|
105
|
+
.send({
|
|
106
|
+
model: item,
|
|
107
|
+
application: application,
|
|
108
|
+
configuration: config
|
|
109
|
+
}, (err) => {
|
|
110
|
+
if (err) {
|
|
111
|
+
try {
|
|
112
|
+
TraceUtils.error('An error occurred while trying to send an email notification after status change.');
|
|
113
|
+
TraceUtils.error(`Student=${item.student.id}, template=${mailTemplate.template}`);
|
|
114
|
+
TraceUtils.error(err);
|
|
115
|
+
} catch (err1) {
|
|
116
|
+
// do nothing
|
|
117
|
+
}
|
|
118
|
+
return resolve();
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return resolve();
|
|
122
|
+
})
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* @param {DataEventArgs} event
|
|
130
|
+
* @param {Function} callback
|
|
131
|
+
*/
|
|
132
|
+
export function afterSave(event, callback) {
|
|
133
|
+
return afterSaveAsync(event).then(() => {
|
|
134
|
+
return callback();
|
|
135
|
+
}).catch((err) => {
|
|
136
|
+
return callback(err);
|
|
137
|
+
});
|
|
138
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {DataEventArgs} event
|
|
3
|
+
* @param {Function} callback
|
|
4
|
+
*/
|
|
5
|
+
import {DataError} from "@themost/common";
|
|
6
|
+
|
|
7
|
+
export function beforeSave(event, callback) {
|
|
8
|
+
(async () => {
|
|
9
|
+
|
|
10
|
+
// validate student state (on insert or update)
|
|
11
|
+
if (event.state === 1 || event.state === 2) {
|
|
12
|
+
let context = event.model.context;
|
|
13
|
+
/**
|
|
14
|
+
* @type {Student|DataObject|*}
|
|
15
|
+
*/
|
|
16
|
+
const student = context.model('Student').convert(event.target.student);
|
|
17
|
+
// const isActive = await student.silent().isActive();
|
|
18
|
+
const isActive = await student.is(':active');
|
|
19
|
+
if (!isActive) {
|
|
20
|
+
throw new DataError('ERR_STATUS',
|
|
21
|
+
'Invalid student status. Student Accommodation Card may be published upon an active student only.'+student
|
|
22
|
+
, null,
|
|
23
|
+
'Student', 'studentStatus');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const studentObject = await context.model('Student').where('id').equal(student.id).silent().flatten().getItem();
|
|
27
|
+
|
|
28
|
+
const academicYear = context.model('AcademicYear').convert(event.target.academicYear).getId();
|
|
29
|
+
if (Number.isInteger(academicYear) === false) {
|
|
30
|
+
throw new DataError('E_VALUE', 'Invalid academic year. Expected number.', null, 'AcademicYear', 'id');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const academicYearObject = await context.model('AcademicYear').where('id').equal(academicYear).getItem();
|
|
34
|
+
if (academicYearObject === undefined){
|
|
35
|
+
throw new DataError('E_VALUE', 'Invalid academic year.', null, 'AcademicYear', 'id');
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (event.target.academicPeriod != null){
|
|
39
|
+
|
|
40
|
+
const academicPeriod = context.model('AcademicPeriod').convert(event.target.academicPeriod).getId();
|
|
41
|
+
if (Number.isInteger(academicPeriod) === false) {
|
|
42
|
+
throw new DataError('E_VALUE', 'Invalid academic period. Expected number.', null, 'AcademicPeriod', 'id');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const academicPeriodObject = await context.model('AcademicPeriod').where('id').equal(academicPeriod).getItem();
|
|
46
|
+
if (academicPeriodObject === undefined){
|
|
47
|
+
throw new DataError('E_VALUE', 'Invalid academic period.', null, 'AcademicPeriod', 'id');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
})().then( () => {
|
|
53
|
+
return callback();
|
|
54
|
+
}).catch( err => {
|
|
55
|
+
return callback(err);
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* @param {DataEventArgs} event
|
|
62
|
+
* @param {Function} callback
|
|
63
|
+
*/
|
|
64
|
+
export function afterSave(event, callback) {
|
|
65
|
+
(async () => {
|
|
66
|
+
//
|
|
67
|
+
let context = event.model.context;
|
|
68
|
+
if (event.state === 1) {
|
|
69
|
+
if (event.target.accommodationRoom && Object.keys(event.target.accommodationRoom).length != 0) {
|
|
70
|
+
// get accommodation valid through date
|
|
71
|
+
|
|
72
|
+
const room = await context.model('AccommodationRoom').where('id').equal(event.target.accommodationRoom.id).getItem();
|
|
73
|
+
if (room === undefined) {
|
|
74
|
+
throw new DataError('E_VALUE', 'Invalid accommodation room.', null, 'AccommodationRoom', 'id');
|
|
75
|
+
}
|
|
76
|
+
let newRoom = room;
|
|
77
|
+
newRoom.currentOccupancy = room.currentOccupancy+1;
|
|
78
|
+
//todo if i can increase occupancy
|
|
79
|
+
await context.model('AccommodationRoom').silent().save(newRoom);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
})().then(() => {
|
|
85
|
+
return callback();
|
|
86
|
+
}).catch(err => {
|
|
87
|
+
return callback(err);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { DataError } from '@themost/common';
|
|
2
|
+
|
|
3
|
+
async function afterSaveAsync(event) {
|
|
4
|
+
//
|
|
5
|
+
if (event.state !== 2) {
|
|
6
|
+
return;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const context = event.model.context;
|
|
10
|
+
|
|
11
|
+
const previous = event.previous;
|
|
12
|
+
if (previous == null) {
|
|
13
|
+
throw new DataError('E_PREVIOUS', 'The previous state of the object cannot be determined');
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
const previousStudentStatus = event.previous.studentStatus;
|
|
18
|
+
if (previousStudentStatus.alternateName === 'active' && event.target.studentStatus && event.target.studentStatus.alternateName != 'active') {
|
|
19
|
+
|
|
20
|
+
// find StudentAccommodationCard
|
|
21
|
+
const StudentAccommodationCard = await context.model('StudentAccommodationCards').where('student/id').equal(event.target.id).select('id', 'active', 'action', 'student', 'academicPeriod', 'academicYear')
|
|
22
|
+
.flatten().silent().getItem();
|
|
23
|
+
|
|
24
|
+
if (StudentAccommodationCard == null) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (StudentAccommodationCard.active === false) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (StudentAccommodationCard.active === true) {
|
|
33
|
+
|
|
34
|
+
StudentAccommodationCard.active = false
|
|
35
|
+
//save StudentAccommodationCard
|
|
36
|
+
await context.model('StudentAccommodationCard').save(StudentAccommodationCard);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// eslint-disable-next-line no-unused-vars
|
|
43
|
+
async function beforeSaveAsync(event) {
|
|
44
|
+
//
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @param {DataEventArgs} event
|
|
49
|
+
* @param {Function} callback
|
|
50
|
+
*/
|
|
51
|
+
export function beforeSave(event, callback) {
|
|
52
|
+
return beforeSaveAsync(event).then(() => {
|
|
53
|
+
return callback();
|
|
54
|
+
}).catch((err) => {
|
|
55
|
+
return callback(err);
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* @param {DataEventArgs} event
|
|
61
|
+
* @param {Function} callback
|
|
62
|
+
*/
|
|
63
|
+
export function afterSave(event, callback) {
|
|
64
|
+
return afterSaveAsync(event).then(() => {
|
|
65
|
+
return callback();
|
|
66
|
+
}).catch((err) => {
|
|
67
|
+
return callback(err);
|
|
68
|
+
});
|
|
69
|
+
}
|