@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,347 @@
|
|
|
1
|
+
import {DataError} from "@themost/common";
|
|
2
|
+
import { HttpForbiddenError } from '@themost/common/errors';
|
|
3
|
+
import { DataObjectState, DataModel } from "@themost/data";
|
|
4
|
+
// eslint-disable-next-line no-unused-vars
|
|
5
|
+
async function beforeSaveAsync(event) {
|
|
6
|
+
|
|
7
|
+
let runAllRules = false;
|
|
8
|
+
const user = event.model.context.user;
|
|
9
|
+
const target = event.model.convert(event.target);
|
|
10
|
+
const context = event.model.context;
|
|
11
|
+
|
|
12
|
+
let studentId = target.student;
|
|
13
|
+
let action;
|
|
14
|
+
let eventHasConsent;
|
|
15
|
+
|
|
16
|
+
if (!Object.prototype.hasOwnProperty.call(target,'student')) {
|
|
17
|
+
const actionID = event.target || event.target.id;
|
|
18
|
+
action = await context.model('AccommodationRequestAction')
|
|
19
|
+
.where('id')
|
|
20
|
+
.equal(actionID)
|
|
21
|
+
.select('student','accommodationRequestEvent/hasConsent as hasConsent','studentConsent')
|
|
22
|
+
.getItem();
|
|
23
|
+
studentId = action.student;
|
|
24
|
+
}
|
|
25
|
+
if (!studentId) {
|
|
26
|
+
throw new DataError('E_STUDENT', 'The student cannot be empty at this context.');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const student = event.model.context.model('Student').convert(studentId);
|
|
30
|
+
|
|
31
|
+
const isMe = await student.is(':me');
|
|
32
|
+
if (isMe) {
|
|
33
|
+
const isActive = await student.is(':active');
|
|
34
|
+
if (!isActive) {
|
|
35
|
+
throw new HttpForbiddenError();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const accommodationRequestEvent = target.accommodationRequestEvent || target.accommodationRequestEvent.id;
|
|
39
|
+
eventHasConsent = await context.model('AccommodationRequestEvent')
|
|
40
|
+
.where('id')
|
|
41
|
+
.equal(accommodationRequestEvent)
|
|
42
|
+
.select('hasConsent')
|
|
43
|
+
.silent()
|
|
44
|
+
.value();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (event.state === 2) {
|
|
48
|
+
if (isMe === true) {
|
|
49
|
+
//check studentConsent
|
|
50
|
+
if (event.target && eventHasConsent === true && Object.prototype.hasOwnProperty.call(target, 'studentConsent') === false) {
|
|
51
|
+
const translateService = context.application.getStrategy(function TranslateService() { });
|
|
52
|
+
throw new DataError('E_STUDENT_CONSENT', translateService.translate('The application cannot be saved without consent about personal data.'), null, 'AccommodationRequestAction', 'studentConsent');
|
|
53
|
+
} else if (event.target && eventHasConsent === true && Object.prototype.hasOwnProperty.call(target, 'studentConsent') === true && target.studentConsent === false) {
|
|
54
|
+
const translateService = context.application.getStrategy(function TranslateService() { });
|
|
55
|
+
throw new DataError('E_STUDENT_CONSENT', translateService.translate('The application cannot be saved without consent about personal data.'), null, 'AccommodationRequestAction', 'studentConsent');
|
|
56
|
+
}
|
|
57
|
+
//check category
|
|
58
|
+
if (target && (Object.prototype.hasOwnProperty.call(target, 'category') && (target.category == null))) {
|
|
59
|
+
throw new HttpForbiddenError(
|
|
60
|
+
context.__(
|
|
61
|
+
'The accommodation request creation failed because no request category has been set.'
|
|
62
|
+
)
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
//UPDATE
|
|
69
|
+
//Load current status
|
|
70
|
+
const actionStatus = await event.model.where('id').equal(event.target.id).select('actionStatus/alternateName').value();
|
|
71
|
+
|
|
72
|
+
//Action is not submitted yet. Run again all rules
|
|
73
|
+
if (actionStatus === 'PotentialActionStatus') {
|
|
74
|
+
runAllRules = true;
|
|
75
|
+
}
|
|
76
|
+
else if (actionStatus === 'ActiveActionStatus' || actionStatus === 'CompletedActionStatus'){
|
|
77
|
+
//accommodation request already submitted. Do not allow to update any property
|
|
78
|
+
removeAllInformationExceptStatus(event.target);
|
|
79
|
+
}
|
|
80
|
+
else if (actionStatus === 'CancelledActionStatus' && event.target.actionStatus && event.target.actionStatus.alternateName !== actionStatus && event.target.actionStatus.alternateName != 'ActiveActionStatus') {
|
|
81
|
+
//accommodation request already cancelled.
|
|
82
|
+
throw new DataError('E_VALUE', 'Cannot update cancelled action.', null, 'AccommodationRequestAction', 'actionStatus');
|
|
83
|
+
}
|
|
84
|
+
// allow agent to change request's status when target request status = 'ActiveActionStatus' example: to reconsider a cancelled request
|
|
85
|
+
else if (actionStatus === 'CancelledActionStatus' && event.target.actionStatus && event.target.actionStatus.alternateName !== actionStatus && event.target.actionStatus.alternateName === 'ActiveActionStatus') {
|
|
86
|
+
let model = event.target;
|
|
87
|
+
// set loggedIn user as request's agent
|
|
88
|
+
if (event.previous.agent != user.id) {
|
|
89
|
+
model.agent = user.id;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
else if (event.state === 1) {
|
|
95
|
+
// check studentConsent
|
|
96
|
+
if (isMe === true && eventHasConsent === true) {
|
|
97
|
+
if (Object.prototype.hasOwnProperty.call(target, 'studentConsent') === false) {
|
|
98
|
+
const translateService = context.application.getStrategy(function TranslateService() { });
|
|
99
|
+
throw new DataError('E_STUDENT_CONSENT', translateService.translate('The application cannot be saved without consent about personal data.'), null, 'AccommodationRequestAction', 'studentConsent');
|
|
100
|
+
} else if (eventHasConsent === true && target.studentConsent === false) {
|
|
101
|
+
const translateService = context.application.getStrategy(function TranslateService() { });
|
|
102
|
+
throw new DataError('E_STUDENT_CONSENT', translateService.translate('The application cannot be saved without consent about personal data.'), null, 'AccommodationRequestAction', 'studentConsent');
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (target && (Object.prototype.hasOwnProperty.call(target, 'category') === false || (target.category == null))) {
|
|
107
|
+
throw new HttpForbiddenError(
|
|
108
|
+
context.__(
|
|
109
|
+
'The accommodation request creation failed because no request category has been set.'
|
|
110
|
+
)
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
runAllRules = true;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
if (runAllRules){
|
|
120
|
+
// set nullable fields to null when they don't need to have a value
|
|
121
|
+
let model = event.target;
|
|
122
|
+
|
|
123
|
+
if (Object.prototype.hasOwnProperty.call(model, 'militaryActive')) {
|
|
124
|
+
if (model.militaryActive == true) {
|
|
125
|
+
applyRulesForPrerequisites(model);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (Object.prototype.hasOwnProperty.call(model, 'militarySchool')) {
|
|
131
|
+
if (model.militarySchool == true) {
|
|
132
|
+
applyRulesForPrerequisites(model);
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (Object.prototype.hasOwnProperty.call(model, 'studentHouseResident')) {
|
|
138
|
+
if (model.studentHouseResident == true) {
|
|
139
|
+
applyRulesForPrerequisites(model);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (Object.prototype.hasOwnProperty.call(model, 'sameDegreeHolder')) {
|
|
145
|
+
if (model.sameDegreeHolder == true) {
|
|
146
|
+
applyRulesForPrerequisites(model);
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (Object.prototype.hasOwnProperty.call(model, 'foreignScholarStudent')) {
|
|
152
|
+
if (model.foreignScholarStudent == true) {
|
|
153
|
+
applyRulesForPrerequisites(model);
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
if (Object.prototype.hasOwnProperty.call(model, 'foreignStudentOrChildOfGreekExpatriate')) {
|
|
160
|
+
if (model.foreignStudentOrChildOfGreekExpatriate == true) {
|
|
161
|
+
applyRulesForCyprusStudentOrForeignStudentOrChildOfGreekExpatriate(model);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (Object.prototype.hasOwnProperty.call(model, 'studentReceivesUnemploymentBenefit')) {
|
|
167
|
+
if (model.studentReceivesUnemploymentBenefit == true){
|
|
168
|
+
model.institutionOrClubLocationSameAsStudentPermanentResidence = null;
|
|
169
|
+
model.studentSubmitsTaxReportInGreece = null;
|
|
170
|
+
nullifyFamilyInformation(model);
|
|
171
|
+
nullifyGuardianFinancialInformation(model);
|
|
172
|
+
nullifySpouseFinancialInformation(model);
|
|
173
|
+
nullifyStudentFinancialInformation(model);
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (Object.prototype.hasOwnProperty.call(model, 'maritalStatus')) {
|
|
179
|
+
if (model.maritalStatus && model.maritalStatus.alternateName == 'single') {
|
|
180
|
+
model.noOfChildren = null;
|
|
181
|
+
nullifySpouseFinancialInformation(model);
|
|
182
|
+
if (model.guardianType.alternateName == 'nobody') {
|
|
183
|
+
model.institutionOrClubLocationSameAsGuardianPermanentResidence = null;
|
|
184
|
+
model.guardianNoOfChildren = null;
|
|
185
|
+
model.numberOfStudyingSiblings = null;
|
|
186
|
+
nullifyGuardianFinancialInformation(model);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
model.guardianType = null;
|
|
191
|
+
model.institutionOrClubLocationSameAsGuardianPermanentResidence = null;
|
|
192
|
+
model.guardianNoOfChildren = null;
|
|
193
|
+
model.numberOfStudyingSiblings = null;
|
|
194
|
+
nullifyGuardianFinancialInformation(model);
|
|
195
|
+
if (model.maritalStatus && model.maritalStatus.alternateName != 'married') {
|
|
196
|
+
nullifySpouseFinancialInformation(model);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function applyRulesForPrerequisites(model) {
|
|
206
|
+
//nullify all other properties except foreignScholarStudent, inscriptionModeTag, lessThan25yrs and allInformationSubmittedIsTrueConfirmation
|
|
207
|
+
nullifyPersonalInformation(model);
|
|
208
|
+
nullifyFamilyInformation(model);
|
|
209
|
+
nullifyGuardianFinancialInformation(model);
|
|
210
|
+
nullifySpouseFinancialInformation(model);
|
|
211
|
+
nullifyStudentFinancialInformation(model);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function applyRulesForCyprusStudentOrForeignStudentOrChildOfGreekExpatriate(model) {
|
|
215
|
+
model.studentAfm = null;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function nullifyPersonalInformation(model){
|
|
219
|
+
model.foreignStudentOrChildOfGreekExpatriate = null;
|
|
220
|
+
model.studentDisabledPerson = null;
|
|
221
|
+
model.studentOrphan = null;
|
|
222
|
+
model.studentReceivesUnemploymentBenefit = null;
|
|
223
|
+
model.studentSubmitsTaxReportInGreece = null;
|
|
224
|
+
model.institutionOrClubLocationSameAsStudentPermanentResidence = null;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function nullifyFamilyInformation(model){
|
|
228
|
+
model.noOfChildren = null;
|
|
229
|
+
model.maritalStatus = null;
|
|
230
|
+
model.numberOfStudyingSiblings = null;
|
|
231
|
+
model.guardianNoOfChildren = null;
|
|
232
|
+
model.guardianType = null;
|
|
233
|
+
model.institutionOrClubLocationSameAsGuadianPermanentResidence = null;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function nullifyGuardianFinancialInformation(model){
|
|
237
|
+
model.studentGuardianTotalIncome = null;
|
|
238
|
+
model.studentGuardianAfm = null;
|
|
239
|
+
model.studentGuardianReceivesUnemploymentBenefit = null;
|
|
240
|
+
model.studentGuardianSubmitsTaxReportInGreece = null;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function nullifySpouseFinancialInformation(model){
|
|
244
|
+
model.studentSpouseTotalIncome = null;
|
|
245
|
+
model.studentSpouseAfm = null;
|
|
246
|
+
model.studentSpouseReceivesUnemploymentBenefit = null;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function nullifyStudentFinancialInformation(model){
|
|
250
|
+
model.studentTotalIncome = null;
|
|
251
|
+
model.studentAfm = null;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function removeAllInformationExceptStatus(model){
|
|
255
|
+
delete model.militaryActive;
|
|
256
|
+
delete model.militarySchool;
|
|
257
|
+
delete model.studentHouseResident;
|
|
258
|
+
delete model.sameDegreeHolder;
|
|
259
|
+
delete model.foreignScholarStudent;
|
|
260
|
+
delete model.lessThan25yrs;
|
|
261
|
+
delete model.institutionOrClubLocationSameAsStudentPermanentResidence;
|
|
262
|
+
delete model.studentDisabledPerson;
|
|
263
|
+
delete model.studentOrphan;
|
|
264
|
+
delete model.numberOfStudyingSiblings ;
|
|
265
|
+
delete model.maritalStatus;
|
|
266
|
+
delete model.noOfChildren;
|
|
267
|
+
delete model.guardianType;
|
|
268
|
+
delete model.institutionOrClubLocationSameAsGuadianPermanentResidence;
|
|
269
|
+
delete model.guardianNoOfChildren;
|
|
270
|
+
delete model.studentReceivesUnemploymentBenefit;
|
|
271
|
+
delete model.studentSubmitsTaxReportInGreece;
|
|
272
|
+
delete model.studentGuardianSubmitsTaxReportInGreece;
|
|
273
|
+
delete model.studentAfm;
|
|
274
|
+
delete model.studentTotalIncome;
|
|
275
|
+
delete model.studentSpouseReceivesUnemploymentBenefit;
|
|
276
|
+
delete model.studentSpouseAfm;
|
|
277
|
+
delete model.studentSpouseTotalIncome;
|
|
278
|
+
delete model.studentGuardianReceivesUnemploymentBenefit ;
|
|
279
|
+
delete model.foreignStudentOrChildOfGreekExpatriate;
|
|
280
|
+
delete model.studentGuardianAfm;
|
|
281
|
+
delete model.studentGuardianTotalIncome;
|
|
282
|
+
delete model.allInformationSubmittedIsTrueConfirmation;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
async function afterSaveAsync(event) {
|
|
286
|
+
// on insert
|
|
287
|
+
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
async function beforeRemoveAsync(event) {
|
|
291
|
+
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
async function afterRemoveAsync(event) {
|
|
295
|
+
const context = event.model.context;
|
|
296
|
+
// try to find if a preference exists for that event
|
|
297
|
+
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* @param {DataEventArgs} event
|
|
302
|
+
* @param {Function} callback
|
|
303
|
+
*/
|
|
304
|
+
export function beforeSave(event, callback) {
|
|
305
|
+
return beforeSaveAsync(event).then(() => {
|
|
306
|
+
return callback();
|
|
307
|
+
}).catch((err) => {
|
|
308
|
+
return callback(err);
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* @param {DataEventArgs} event
|
|
314
|
+
* @param {Function} callback
|
|
315
|
+
*/
|
|
316
|
+
export function afterSave(event, callback) {
|
|
317
|
+
return afterSaveAsync(event).then(() => {
|
|
318
|
+
return callback();
|
|
319
|
+
}).catch((err) => {
|
|
320
|
+
return callback(err);
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* @param {DataEventArgs} event
|
|
326
|
+
* @param {Function} callback
|
|
327
|
+
*/
|
|
328
|
+
export function afterRemove(event, callback) {
|
|
329
|
+
return afterRemoveAsync(event).then(() => {
|
|
330
|
+
return callback();
|
|
331
|
+
}).catch((err) => {
|
|
332
|
+
return callback(err);
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* @param {DataEventArgs} event
|
|
339
|
+
* @param {Function} callback
|
|
340
|
+
*/
|
|
341
|
+
export function beforeRemove(event, callback) {
|
|
342
|
+
return beforeRemoveAsync(event).then(() => {
|
|
343
|
+
return callback();
|
|
344
|
+
}).catch((err) => {
|
|
345
|
+
return callback(err);
|
|
346
|
+
});
|
|
347
|
+
}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import {Args} from '@themost/common';
|
|
2
|
+
import {ElotConverter} from '@universis/elot-converter';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @name DataContext#locale
|
|
6
|
+
* @description Gets or sets the current context locale
|
|
7
|
+
* @type {string}
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Returns true if a data model has a localization enabled
|
|
11
|
+
* @param {DataModel} model
|
|
12
|
+
* @returns {DataField}
|
|
13
|
+
*/
|
|
14
|
+
function hasLocales(model) {
|
|
15
|
+
Args.notNull(model, 'model');
|
|
16
|
+
const attribute = model.getAttribute('locales');
|
|
17
|
+
// if target model does not have a `locales` attribute
|
|
18
|
+
if (attribute == null) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
// if attribute belongs to another model (and it's being inherited by this model)
|
|
22
|
+
if (attribute.model !== model.name) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
return attribute;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function getElotAttributes(context) {
|
|
29
|
+
// do not require elotAttributes configuration
|
|
30
|
+
// make it completely optional
|
|
31
|
+
return context.getConfiguration().getSourceAt('settings/i18n/elotAttributes') || ['familyName', 'givenName', 'motherName', 'fatherName'];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function getElotLocale() {
|
|
35
|
+
return {
|
|
36
|
+
requiresDefault: 'el',
|
|
37
|
+
isInLocale: 'en'
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* @param {DataEventArgs} event
|
|
42
|
+
* @returns {Promise<void>}
|
|
43
|
+
*/
|
|
44
|
+
async function afterSaveAsync(event) {
|
|
45
|
+
const context = event.model.context;
|
|
46
|
+
const attribute = hasLocales(event.model);
|
|
47
|
+
if (attribute == null) {
|
|
48
|
+
// do nothing
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if (Object.prototype.hasOwnProperty.call(event.target, 'locales') === false) {
|
|
52
|
+
// do nothing and exit because locales property is missing
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
// get localized model
|
|
56
|
+
const childModel = context.model(attribute.type);
|
|
57
|
+
// throw error for invalid model
|
|
58
|
+
if (childModel == null) {
|
|
59
|
+
throw new Error('Invalid configuration. Localization model cannot be found or is not inaccessible yet');
|
|
60
|
+
}
|
|
61
|
+
if (Array.isArray(event.target.locales) === false) {
|
|
62
|
+
throw new Error('Invalid property type. Property locales must be an array');
|
|
63
|
+
}
|
|
64
|
+
for (let i = 0; i < event.target.locales.length; i++) {
|
|
65
|
+
const itemLocale = event.target.locales[i];
|
|
66
|
+
if (childModel.sealed === false) {
|
|
67
|
+
// delete primary key if any
|
|
68
|
+
delete itemLocale[childModel.primaryKey];
|
|
69
|
+
}
|
|
70
|
+
if (itemLocale.object == null) {
|
|
71
|
+
// set object key
|
|
72
|
+
Object.defineProperty(itemLocale, 'object', {
|
|
73
|
+
configurable: true,
|
|
74
|
+
enumerable: true,
|
|
75
|
+
writable: true,
|
|
76
|
+
value: event.target[event.model.primaryKey]
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (childModel.sealed === true) {
|
|
81
|
+
// if child model (locale model) is sealed add only other language (not default)
|
|
82
|
+
// get default application locale
|
|
83
|
+
let defaultLocale = context.getConfiguration().getSourceAt('settings/i18n/defaultLocale');
|
|
84
|
+
// throw error if default locale is not defined
|
|
85
|
+
if (defaultLocale == null) {
|
|
86
|
+
throw new Error('Invalid application configuration. The default locale is missing.');
|
|
87
|
+
}
|
|
88
|
+
event.target.locales = event.target.locales.filter((item) => {
|
|
89
|
+
return item.inLanguage !== defaultLocale;
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
// important note: get silent mode of parent model
|
|
93
|
+
const silentMode = event.model.isSilent();
|
|
94
|
+
// apply silent mode and save items
|
|
95
|
+
if (event.target.locales.length > 0) {
|
|
96
|
+
await childModel.silent(silentMode).save(event.target.locales);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* @param {DataEventArgs} event
|
|
101
|
+
* @returns {Promise<void>}
|
|
102
|
+
*/
|
|
103
|
+
async function beforeSaveAsync(event) {
|
|
104
|
+
const context = event.model.context;
|
|
105
|
+
const attribute = hasLocales(event.model);
|
|
106
|
+
if (attribute == null) {
|
|
107
|
+
// do nothing
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
// get localized model
|
|
111
|
+
const childModel = context.model(attribute.type);
|
|
112
|
+
// ensure locales property
|
|
113
|
+
event.target.locales = event.target.locales || [];
|
|
114
|
+
// get default application locale
|
|
115
|
+
let defaultLocale = context.getConfiguration().getSourceAt('settings/i18n/defaultLocale');
|
|
116
|
+
// throw error if default locale is not defined
|
|
117
|
+
if (defaultLocale == null) {
|
|
118
|
+
throw new Error('Invalid application configuration. The default locale is missing.');
|
|
119
|
+
}
|
|
120
|
+
let findLocale = event.target.locales.find((item) => {
|
|
121
|
+
return item.inLanguage === defaultLocale;
|
|
122
|
+
});
|
|
123
|
+
let add = false;
|
|
124
|
+
if (findLocale == null) {
|
|
125
|
+
add = true;
|
|
126
|
+
findLocale = {};
|
|
127
|
+
}
|
|
128
|
+
// enumerate properties and update object
|
|
129
|
+
childModel.attributes.forEach((attribute) => {
|
|
130
|
+
if (!attribute.primary && attribute.type !== event.model.name) {
|
|
131
|
+
if (Object.prototype.hasOwnProperty.call(event.target, attribute.name)) {
|
|
132
|
+
Object.defineProperty(findLocale, attribute.name, {
|
|
133
|
+
configurable: true,
|
|
134
|
+
enumerable: true,
|
|
135
|
+
writable: true,
|
|
136
|
+
value: event.target[attribute.name]
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
// set language
|
|
142
|
+
findLocale.inLanguage = defaultLocale;
|
|
143
|
+
if (add) {
|
|
144
|
+
event.target.locales.push(findLocale);
|
|
145
|
+
}
|
|
146
|
+
if (defaultLocale === getElotLocale().requiresDefault) {
|
|
147
|
+
// try to find locale that is in language of elot locale
|
|
148
|
+
let elotLocale = event.target.locales.find(locale => locale.inLanguage === getElotLocale().isInLocale);
|
|
149
|
+
let addElotLocale = false;
|
|
150
|
+
if (!elotLocale) {
|
|
151
|
+
elotLocale = {};
|
|
152
|
+
addElotLocale = true;
|
|
153
|
+
}
|
|
154
|
+
// get elot attributes
|
|
155
|
+
const elotAttributes = getElotAttributes(context);
|
|
156
|
+
// if they are configured, validate them
|
|
157
|
+
if (!(Array.isArray(elotAttributes) && elotAttributes.length)) {
|
|
158
|
+
throw new Error('Invalid configuration. Elot attributes must be a (not-empty) array, e.g. ["familyName", "givenName"]');
|
|
159
|
+
}
|
|
160
|
+
// get previous state
|
|
161
|
+
// it can be undefined for various reasons (e.g. insert state, missing or misplaced previous-state-listener)
|
|
162
|
+
const previous = event.previous;
|
|
163
|
+
// enumerate elot attributes
|
|
164
|
+
for (const attribute of elotAttributes) {
|
|
165
|
+
// if target has the property
|
|
166
|
+
if (Object.prototype.hasOwnProperty.call(event.target, attribute)) {
|
|
167
|
+
// it's not null and has been changed
|
|
168
|
+
if (event.target[attribute] != null && event.target[attribute] != (previous && previous[attribute])) {
|
|
169
|
+
// convert and assign to elot locale
|
|
170
|
+
elotLocale[attribute] = ElotConverter.convert(event.target[attribute]);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
if (addElotLocale) {
|
|
175
|
+
elotLocale.inLanguage = getElotLocale().isInLocale;
|
|
176
|
+
// and finally push the contructed locale
|
|
177
|
+
event.target.locales.push(elotLocale);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
// noinspection JSUnusedGlobalSymbols
|
|
182
|
+
/**
|
|
183
|
+
*
|
|
184
|
+
* @param {DataEventArgs} event
|
|
185
|
+
* @param {*} callback
|
|
186
|
+
* @returns {any}
|
|
187
|
+
*/
|
|
188
|
+
function beforeSave(event, callback) {
|
|
189
|
+
return beforeSaveAsync(event).then(() => {
|
|
190
|
+
return callback();
|
|
191
|
+
}).catch((err) => {
|
|
192
|
+
return callback(err);
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
// noinspection JSUnusedGlobalSymbols
|
|
196
|
+
/**
|
|
197
|
+
*
|
|
198
|
+
* @param {DataEventArgs} event
|
|
199
|
+
* @param {*} callback
|
|
200
|
+
* @returns {any}
|
|
201
|
+
*/
|
|
202
|
+
function afterSave(event, callback) {
|
|
203
|
+
return afterSaveAsync(event).then(() => {
|
|
204
|
+
return callback();
|
|
205
|
+
}).catch((err) => {
|
|
206
|
+
return callback(err);
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export {
|
|
211
|
+
hasLocales,
|
|
212
|
+
beforeSave,
|
|
213
|
+
afterSave
|
|
214
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import {TextUtils, TraceUtils} from '@themost/common';
|
|
2
|
+
import {DataCacheStrategy} from "@themost/data";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @param {DataEventArgs} event
|
|
6
|
+
* @param {Function} callback
|
|
7
|
+
*/
|
|
8
|
+
export function beforeExecute(event, callback) {
|
|
9
|
+
try {
|
|
10
|
+
const context = event.model.context;
|
|
11
|
+
if (event.query) {
|
|
12
|
+
if (event.query.$select) {
|
|
13
|
+
//create hash
|
|
14
|
+
const hash = event.emitter? event.emitter.toMD5() : TextUtils.toMD5(event.query);
|
|
15
|
+
const key = '/' + event.model.name + '/?query=' + hash + '&lang=' + event.model.context.locale;
|
|
16
|
+
TraceUtils.debug('Getting data from cache [' + key + ']');
|
|
17
|
+
return context.getConfiguration().getStrategy(DataCacheStrategy).get(key).then((result) => {
|
|
18
|
+
if (typeof result !== 'undefined') {
|
|
19
|
+
//delete expandables
|
|
20
|
+
if (event.emitter) {
|
|
21
|
+
delete event.emitter.$expand;
|
|
22
|
+
}
|
|
23
|
+
event.cached = true;
|
|
24
|
+
event.result = result;
|
|
25
|
+
return callback();
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
return callback();
|
|
29
|
+
}
|
|
30
|
+
}).catch((err)=> {
|
|
31
|
+
return callback(err);
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
callback();
|
|
36
|
+
}
|
|
37
|
+
catch (e) {
|
|
38
|
+
callback(e)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function afterExecute(event, callback) {
|
|
43
|
+
try {
|
|
44
|
+
const context = event.model.context;
|
|
45
|
+
if (event.query) {
|
|
46
|
+
if (event.query.$select) {
|
|
47
|
+
if (typeof event.result !== 'undefined' && !event.cached) {
|
|
48
|
+
//create hash
|
|
49
|
+
const hash = event.emitter? event.emitter.toMD5() : TextUtils.toMD5(event.query);
|
|
50
|
+
const key = '/' + event.model.name + '/?query=' + hash + '&lang=' + event.model.context.locale;
|
|
51
|
+
TraceUtils.debug('Setting data to cache [' + key + ']');
|
|
52
|
+
context.getConfiguration().getStrategy(DataCacheStrategy).add(key, event.result);
|
|
53
|
+
return callback();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
callback();
|
|
58
|
+
}
|
|
59
|
+
catch (e) {
|
|
60
|
+
callback(e)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function cleanupCache(event, callback) {
|
|
65
|
+
const { name, caching, context } = event.model;
|
|
66
|
+
if (caching === 'none') {
|
|
67
|
+
return callback();
|
|
68
|
+
}
|
|
69
|
+
const service = context.getConfiguration().getStrategy(DataCacheStrategy);
|
|
70
|
+
if (service) {
|
|
71
|
+
return service.remove(`/${name}/*`).then(() => {
|
|
72
|
+
return callback();
|
|
73
|
+
}).catch((err) => {
|
|
74
|
+
TraceUtils.warn('An error occurred while cleaning up cache items');
|
|
75
|
+
TraceUtils.warn(err);
|
|
76
|
+
return callback();
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
return callback();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
export function afterSave(event, callback) {
|
|
84
|
+
return cleanupCache(event, callback);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export function afterRemove(event, callback) {
|
|
88
|
+
return cleanupCache(event, callback);
|
|
89
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/* eslint-disable no-unused-vars */
|
|
2
|
+
import { DataError } from "@themost/common";
|
|
3
|
+
import { DataObject, EdmMapping } from "@themost/data";
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@EdmMapping.entityType('Accommodation')
|
|
7
|
+
class AccommodationRequestEvent extends DataObject {
|
|
8
|
+
/**
|
|
9
|
+
* @constructor
|
|
10
|
+
*/
|
|
11
|
+
constructor() {
|
|
12
|
+
super();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* POST AccommodationRequestEvents/:id/Remove
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
//remove accommodation request event
|
|
20
|
+
@EdmMapping.param('data', 'Object', false, true)
|
|
21
|
+
@EdmMapping.action('remove', 'Accommodation')
|
|
22
|
+
async remove(data) {
|
|
23
|
+
/**
|
|
24
|
+
* @type {import('@themost/data').DataModel}
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
const model = this.getModel();
|
|
28
|
+
|
|
29
|
+
const item = await model.where('id')
|
|
30
|
+
.equal(this.getId())
|
|
31
|
+
.getItem();
|
|
32
|
+
const translateService = this.context.application.getStrategy(function TranslateService() { });
|
|
33
|
+
|
|
34
|
+
if (item == null) {
|
|
35
|
+
throw new DataError('E_ACCOMMODATION', translateService.translate('The specified Accommodation cannot be found or is inaccessible.'));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const hasRooms = await this.context.model('AccommodationRooms')
|
|
39
|
+
.where('containedInPlace').equal(item.id).count();
|
|
40
|
+
|
|
41
|
+
if (hasRooms) {
|
|
42
|
+
throw new DataError('E_ACCOMMODATION_ROOM', translateService.translate('Cannot remove accommodation. Accommodation is related to rooms.'), null, 'Accommodation');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return model.silent().remove(item);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
module.exports = AccommodationRequestEvent;
|