@universis/accommodation 1.1.3 → 1.1.5
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/dist/config/models/AccommodationRoom.json +0 -5
- package/dist/config/models/RoomType.json +246 -240
- package/dist/config/models/StudentAccommodationCard.json +1 -4
- package/dist/config/scope.access.js +9 -0
- package/dist/config/scope.access.js.map +1 -1
- package/dist/listeners/StudentAccommodationCardSaveListener.js +13 -2
- package/dist/listeners/StudentAccommodationCardSaveListener.js.map +1 -1
- package/dist/models/StudentAccommodationCard.js +170 -47
- package/dist/models/StudentAccommodationCard.js.map +1 -1
- package/package.json +1 -1
- package/src/config/models/AccommodationRoom.json +0 -5
- package/src/config/models/RoomType.json +246 -240
- package/src/config/models/StudentAccommodationCard.json +1 -4
- package/src/config/scope.access.js +9 -0
- package/src/listeners/StudentAccommodationCardSaveListener.js +14 -3
- package/src/models/StudentAccommodationCard.js +157 -34
- package/dist/listeners/OnUpdateAccommodationRoomListener.js +0 -151
- package/dist/listeners/OnUpdateAccommodationRoomListener.js.map +0 -1
- package/src/listeners/OnUpdateAccommodationRoomListener.js +0 -150
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
|
|
2
|
-
import {
|
|
3
|
-
import { DataError, DataNotFoundError } from "@themost/common"
|
|
2
|
+
import { EdmMapping } from '@themost/data';
|
|
3
|
+
import { DataError, DataNotFoundError, Args, TraceUtils, LangUtils } from "@themost/common"
|
|
4
|
+
import EnableAttachmentModel from './EnableAttachmentModel';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* @class
|
|
@@ -20,7 +21,7 @@ import { DataError, DataNotFoundError } from "@themost/common"
|
|
|
20
21
|
* @property {User|any} student
|
|
21
22
|
*/
|
|
22
23
|
@EdmMapping.entityType('StudentAccommodationCard')
|
|
23
|
-
class StudentAccommodationCard extends
|
|
24
|
+
class StudentAccommodationCard extends EnableAttachmentModel {
|
|
24
25
|
/**
|
|
25
26
|
* @constructor
|
|
26
27
|
*/
|
|
@@ -35,58 +36,180 @@ class StudentAccommodationCard extends DataObject {
|
|
|
35
36
|
|
|
36
37
|
async cancel(data) {
|
|
37
38
|
|
|
38
|
-
|
|
39
|
-
throw new DataError('E_CANCEL_REASON', 'Cancel Reason should be provided');
|
|
40
|
-
}
|
|
39
|
+
Args.notEmpty(data.cancelReason, 'Cancel Reason');
|
|
41
40
|
|
|
41
|
+
if ( !LangUtils.isDate(data.dateCancelled) ) {
|
|
42
|
+
throw new DataError('E_STATE', 'Cancel date can not be empty or invalid date');
|
|
43
|
+
}
|
|
42
44
|
await this.context.executeInTransactionAsync(async () => {
|
|
43
45
|
// find StudentAccommodationCard from id
|
|
44
|
-
const
|
|
46
|
+
const currentStudentAccommodationCard = await this.context.model('StudentAccommodationCard')
|
|
45
47
|
.where('id')
|
|
46
48
|
.equal(this.getId())
|
|
47
|
-
.select('id', '
|
|
48
|
-
.
|
|
49
|
+
.select('id', 'serialNumber', 'action', 'student', 'cardStatus', 'academicYear', 'isActive', 'validThrough', 'accommodationRoom')
|
|
50
|
+
.expand('cardStatus')
|
|
49
51
|
.getItem();
|
|
50
52
|
|
|
51
|
-
|
|
52
|
-
if (StudentAccommodationCard == null) {
|
|
53
|
-
throw new DataNotFoundError('The specified Student Accommodation Card cannot be found or is inaccessible');
|
|
54
|
-
}
|
|
53
|
+
Args.notNull(currentStudentAccommodationCard, 'The specified Student Accommodation Card' )
|
|
55
54
|
// StudentAccommodationCard already cancelled throw error
|
|
56
|
-
if (
|
|
57
|
-
throw new DataError('E_ACTIVE', 'The specified Student Accommodation Card
|
|
55
|
+
if ( currentStudentAccommodationCard?.cardStatus?.alternateName === 'CompletedActionStatus') {
|
|
56
|
+
throw new DataError('E_ACTIVE', 'The specified Student Accommodation Card in not active')
|
|
58
57
|
}
|
|
58
|
+
// cancel StudentAccommodationCard
|
|
59
|
+
currentStudentAccommodationCard.cardStatus = { alternateName: 'CompletedActionStatus' };
|
|
60
|
+
currentStudentAccommodationCard.cancelReason = data.cancelReason;
|
|
61
|
+
currentStudentAccommodationCard.dateCancelled = data.dateCancelled;
|
|
62
|
+
await this.context.model('StudentAccommodationCard').save(currentStudentAccommodationCard);
|
|
63
|
+
const room = currentStudentAccommodationCard.accommodationRoom?.id || currentStudentAccommodationCard?.accommodationRoom;
|
|
64
|
+
Args.notNull(room, 'Accommodation room can not be empty');
|
|
65
|
+
Args.notNumber(room, 'Accommodation room should be a number');
|
|
66
|
+
await calculateOccupancy(this.context, room);
|
|
67
|
+
},(err)=>{
|
|
68
|
+
TraceUtils.log(err);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
59
71
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
throw new DataError('E_ACTION', 'The Student Accommodation Card is not linked to a Accommodation Request Action')
|
|
63
|
-
}
|
|
72
|
+
@EdmMapping.param('data', 'Object', false, true)
|
|
73
|
+
@EdmMapping.action('changeRoom', 'StudentAccommodationCard')
|
|
64
74
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
75
|
+
async changeRoom(data) {
|
|
76
|
+
|
|
77
|
+
const room = data.accommodationRoom?.id || data?.accommodationRoom;
|
|
78
|
+
Args.notNull(room, 'Accommodation room can not be empty');
|
|
79
|
+
Args.notNumber(room, 'Accommodation room should be a number');
|
|
80
|
+
|
|
81
|
+
if ( !LangUtils.isDate(data.validThrough) ) {
|
|
82
|
+
throw new DataError('E_STATE', 'Valid through date can not be empty or it is not a valid date');
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
Args.notEmpty(data.cancelReason, 'Cancel Reason cannot be empty');
|
|
86
|
+
|
|
87
|
+
if ( !LangUtils.isDate(data.dateCancelled) ) {
|
|
88
|
+
throw new DataError('E_STATE', 'Cancel date can not be empty or invalid date');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
await this.context.executeInTransactionAsync(async () => {
|
|
92
|
+
const currentStudentAccommodationCard = await this.context.model('StudentAccommodationCard')
|
|
93
|
+
.where('id')
|
|
94
|
+
.equal(this.getId())
|
|
95
|
+
.select('id', 'serialNumber', 'action', 'student', 'cardStatus', 'academicYear', 'isActive', 'validThrough', 'accommodationRoom')
|
|
96
|
+
.expand('cardStatus')
|
|
97
|
+
.getItem();
|
|
98
|
+
|
|
99
|
+
Args.notNull(currentStudentAccommodationCard, 'The specified Student Accommodation Card cannot be found or is inaccessible');
|
|
100
|
+
|
|
101
|
+
if (currentStudentAccommodationCard?.cardStatus?.alternateName !== 'ActiveActionStatus') {
|
|
102
|
+
throw new DataError('E_STATE', 'The accommodation room cannot be changed for inactive accommodation card');
|
|
74
103
|
}
|
|
104
|
+
const newCard = {
|
|
105
|
+
action: currentStudentAccommodationCard.action,
|
|
106
|
+
student: currentStudentAccommodationCard.student,
|
|
107
|
+
accommodationRoom: room,
|
|
108
|
+
academicYear: currentStudentAccommodationCard.academicYear,
|
|
109
|
+
validFrom: data.validThrough,
|
|
110
|
+
validThrough: currentStudentAccommodationCard.validThrough,
|
|
111
|
+
cardStatus: {
|
|
112
|
+
alternateName: 'ActiveActionStatus'
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
currentStudentAccommodationCard.cancelReason = data.cancelReason;
|
|
117
|
+
currentStudentAccommodationCard.dateCancelled = data.dateCancelled;
|
|
118
|
+
currentStudentAccommodationCard.validThrough = data.dateCancelled;
|
|
119
|
+
delete currentStudentAccommodationCard.cardStatus ;
|
|
120
|
+
currentStudentAccommodationCard.cardStatus= { alternateName : 'CompletedActionStatus'};
|
|
75
121
|
|
|
76
|
-
|
|
77
|
-
|
|
122
|
+
await this.context.model('StudentAccommodationCard').save(currentStudentAccommodationCard);
|
|
123
|
+
const currentAccommodationRoom = currentStudentAccommodationCard.accommodationRoom?.id || currentStudentAccommodationCard?.accommodationRoom;
|
|
124
|
+
Args.notNull(currentAccommodationRoom, 'The specified Student Accommodation Card does not contain any room');
|
|
125
|
+
await calculateOccupancy(this.context, currentAccommodationRoom);
|
|
126
|
+
await this.context.model('StudentAccommodationCards').save(newCard);
|
|
127
|
+
await calculateOccupancy(this.context, room);
|
|
128
|
+
},(err)=>{
|
|
129
|
+
TraceUtils.log(err);
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
@EdmMapping.param('data', 'Object', false, true)
|
|
134
|
+
@EdmMapping.action('addToRoom', 'StudentAccommodationCard')
|
|
135
|
+
|
|
136
|
+
async addToRoom(data) {
|
|
137
|
+
const room = data.accommodationRoom?.id || data?.accommodationRoom;
|
|
138
|
+
Args.notNull(room, 'Accommodation room can not be empty');
|
|
139
|
+
Args.notNumber(room, 'Accommodation room should be a number');
|
|
140
|
+
if (!LangUtils.isDate(data.validFrom)) {
|
|
141
|
+
throw new DataError('E_STATE', 'Valid through date can not be empty or it is not a valid date');
|
|
142
|
+
}
|
|
143
|
+
await this.context.executeInTransactionAsync(async () => {
|
|
144
|
+
const currentStudentAccommodationCard = await this.context.model('StudentAccommodationCard')
|
|
145
|
+
.where('id')
|
|
146
|
+
.equal(this.getId())
|
|
147
|
+
.select('id', 'serialNumber', 'action', 'student', 'cardStatus', 'academicYear', 'isActive', 'validThrough')
|
|
148
|
+
.expand('cardStatus')
|
|
149
|
+
.getItem();
|
|
150
|
+
Args.notNull(currentStudentAccommodationCard, 'The specified Student Accommodation Card cannot be found or is inaccessible');
|
|
151
|
+
if (currentStudentAccommodationCard?.cardStatus?.alternateName !== 'ActiveActionStatus') {
|
|
152
|
+
throw new DataError('E_STATE', 'Add to room action can only be applied when student accommodation card status is Active');
|
|
78
153
|
}
|
|
154
|
+
currentStudentAccommodationCard.accommodationRoom = room;
|
|
155
|
+
currentStudentAccommodationCard.validFrom = data.validFrom;
|
|
156
|
+
await this.context.model('StudentAccommodationCard').save(currentStudentAccommodationCard);
|
|
157
|
+
await calculateOccupancy(this.context, room); // calculate occupancy after new room updated
|
|
158
|
+
}, (err) => {
|
|
159
|
+
TraceUtils.log(err);
|
|
160
|
+
});
|
|
161
|
+
}
|
|
79
162
|
|
|
80
|
-
|
|
81
|
-
|
|
163
|
+
@EdmMapping.param('data', 'Object', false, true)
|
|
164
|
+
@EdmMapping.action('revertToPending', 'StudentAccommodationCard')
|
|
165
|
+
|
|
166
|
+
async revertToPending(data) {
|
|
167
|
+
await this.context.executeInTransactionAsync(async () => {
|
|
168
|
+
const currentStudentAccommodationCard = await this.context.model('StudentAccommodationCard')
|
|
169
|
+
.where('id')
|
|
170
|
+
.equal(this.getId())
|
|
171
|
+
.select('id', 'serialNumber', 'action', 'student', 'cardStatus', 'academicYear', 'isActive', 'validThrough', 'accommodationRoom')
|
|
172
|
+
.expand('cardStatus')
|
|
173
|
+
.getItem();
|
|
174
|
+
|
|
175
|
+
Args.notNull(currentStudentAccommodationCard, 'The specified Student Accommodation Card cannot be found or is inaccessible');
|
|
176
|
+
if (currentStudentAccommodationCard?.cardStatus?.alternateName !== 'ActiveActionStatus') {
|
|
177
|
+
throw new DataError('E_STATE', 'Inactive accommodation card');
|
|
82
178
|
}
|
|
83
179
|
|
|
84
|
-
|
|
85
|
-
|
|
180
|
+
const accommodationRoom = currentStudentAccommodationCard.accommodationRoom?.id || currentStudentAccommodationCard?.accommodationRoom;
|
|
181
|
+
currentStudentAccommodationCard.cardStatus = { alternateName: 'ActiveActionStatus' };
|
|
182
|
+
currentStudentAccommodationCard.accommodationRoom = null;
|
|
183
|
+
await this.context.model('StudentAccommodationCard').save(currentStudentAccommodationCard);
|
|
184
|
+
await calculateOccupancy(this.context, accommodationRoom);
|
|
86
185
|
});
|
|
87
186
|
}
|
|
88
187
|
|
|
89
188
|
|
|
90
189
|
}
|
|
190
|
+
async function calculateOccupancy(context, accommodationRoom) {
|
|
191
|
+
if (accommodationRoom == null) {
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
const currentOccupancy = await context.model('StudentAccommodationCard')
|
|
195
|
+
.where('accommodationRoom').equal(accommodationRoom)
|
|
196
|
+
.and('cardStatus/alternateName').equal('ActiveActionStatus')
|
|
197
|
+
.and('accommodationRoom/outOfService').equal(0)
|
|
198
|
+
.and('accommodationRoom/roomType/accessibleType').equal(1)
|
|
199
|
+
.select('count(id) as total', 'accommodationRoom/occupancy as maxOccupancy')
|
|
200
|
+
.groupBy('accommodationRoom/occupancy')
|
|
201
|
+
.silent()
|
|
202
|
+
.getItem();
|
|
203
|
+
|
|
204
|
+
const totalOccupancy = (currentOccupancy && currentOccupancy.total) || 0;
|
|
205
|
+
if (totalOccupancy && totalOccupancy > currentOccupancy.maxOccupancy) {
|
|
206
|
+
throw new DataError('E_STATE', 'No room space for new resident');
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
await context.model('AccommodationRoom').save({
|
|
210
|
+
id: accommodationRoom,
|
|
211
|
+
currentOccupancy: totalOccupancy
|
|
212
|
+
});
|
|
213
|
+
}
|
|
91
214
|
|
|
92
215
|
module.exports = StudentAccommodationCard;
|
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", { value: true });exports.afterSave = afterSave;exports.beforeSave = beforeSave;
|
|
2
|
-
var _common = require("@themost/common");
|
|
3
|
-
|
|
4
|
-
async function beforeSaveAsync(event) {
|
|
5
|
-
//
|
|
6
|
-
if (event.state !== 2) {
|
|
7
|
-
return;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
const context = event.model.context;
|
|
11
|
-
const target = event.target;
|
|
12
|
-
const previous = event.previous;
|
|
13
|
-
|
|
14
|
-
if (previous == null) {
|
|
15
|
-
throw new _common.DataError('E_PREVIOUS', 'The previous state of the object cannot be determined');
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const previousActionStatus = await context.model('ActionStatusType').find(previous.cardStatus).select('alternateName').value();
|
|
19
|
-
const targetActionStatus = await context.model('ActionStatusType').find(event.target.cardStatus).select('alternateName').value();
|
|
20
|
-
|
|
21
|
-
if (previousActionStatus === 'CompletedActionStatus' && targetActionStatus === 'ActiveActionStatus') {
|
|
22
|
-
target.accommodationRoom = null;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
if (Object.prototype.hasOwnProperty.call(target, 'accommodationRoom') === true) {var _target$accommodation;
|
|
26
|
-
const targetAccommodationRoom = ((_target$accommodation = target.accommodationRoom) === null || _target$accommodation === void 0 ? void 0 : _target$accommodation.id) || target.accommodationRoom;
|
|
27
|
-
|
|
28
|
-
if (previous.accommodationRoom !== targetAccommodationRoom && targetAccommodationRoom != null && previous.accommodationRoom != null) {
|
|
29
|
-
|
|
30
|
-
if (targetActionStatus !== 'CompletedActionStatus') {
|
|
31
|
-
throw new _common.DataError('E_STATE', 'The accommodation room cannot be changed for inactive accommodation card');
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
target.cancelReason = target.cancelReason || context.translate('Change Room');
|
|
35
|
-
target.dateCancelled = target.dateCancelled || new Date();
|
|
36
|
-
target.validThrough = target.dateCancelled;
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
async function afterSaveAsync(event) {var _target$accommodation2;
|
|
43
|
-
|
|
44
|
-
if (event.state !== 2) {
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const previous = event.previous;
|
|
49
|
-
if (previous == null) {
|
|
50
|
-
throw new _common.DataError('E_PREVIOUS', 'The previous state of the object cannot be determined');
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const target = event.target;
|
|
54
|
-
|
|
55
|
-
if (Object.prototype.hasOwnProperty.call(target, 'accommodationRoom') === false) {
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const context = event.model.context;
|
|
61
|
-
const previousActionStatus = await context.model('ActionStatusType').find(previous.cardStatus).select('alternateName').value();
|
|
62
|
-
const targetActionStatus = await context.model('ActionStatusType').find(event.target.cardStatus).select('alternateName').value();
|
|
63
|
-
const targetAccommodationRoom = ((_target$accommodation2 = target.accommodationRoom) === null || _target$accommodation2 === void 0 ? void 0 : _target$accommodation2.id) || target.accommodationRoom;
|
|
64
|
-
|
|
65
|
-
if (previousActionStatus === 'CompletedActionStatus' && targetActionStatus === 'ActiveActionStatus' && previous.accommodationRoom != null) {
|
|
66
|
-
// update previous room occupancy
|
|
67
|
-
await calculateOccupancy(context, previous.accommodationRoom);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
if (['CompletedActionStatus', 'ActiveActionStatus'].includes(previousActionStatus) && targetActionStatus === 'CancelledActionStatus') {
|
|
71
|
-
// on cancel student accommodation card status
|
|
72
|
-
await calculateOccupancy(context, targetAccommodationRoom);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
if (['CompletedActionStatus', 'ActiveActionStatus'].includes(previousActionStatus) && targetActionStatus === 'CompletedActionStatus') {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
if (previous.accommodationRoom === targetAccommodationRoom) {
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
if (previousActionStatus === 'CompletedActionStatus') {
|
|
83
|
-
const newCard = {
|
|
84
|
-
action: previous.action,
|
|
85
|
-
student: previous.student,
|
|
86
|
-
accommodationRoom: targetAccommodationRoom,
|
|
87
|
-
academicYear: previous.academicYear,
|
|
88
|
-
validFrom: target.validThrough,
|
|
89
|
-
validThrough: previous.validThrough,
|
|
90
|
-
cardStatus: {
|
|
91
|
-
alternateName: 'CompletedActionStatus'
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
await context.model('StudentAccommodationCards').save(newCard);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
await calculateOccupancy(context, targetAccommodationRoom);
|
|
100
|
-
|
|
101
|
-
if (previous.accommodationRoom != null) {
|
|
102
|
-
await calculateOccupancy(context, previous.accommodationRoom);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
async function calculateOccupancy(context, accommodationRoom) {
|
|
108
|
-
|
|
109
|
-
const currentOccupancy = await context.model('StudentAccommodationCard').
|
|
110
|
-
where('accommodationRoom').equal(accommodationRoom).
|
|
111
|
-
and('isActive').equal(1).
|
|
112
|
-
select('count(id) as total', 'accommodationRoom/occupancy as maxOccupancy').
|
|
113
|
-
groupBy('accommodationRoom/occupancy').
|
|
114
|
-
silent().
|
|
115
|
-
getItem();
|
|
116
|
-
|
|
117
|
-
const totalOccupancy = currentOccupancy && currentOccupancy.total || 0;
|
|
118
|
-
if (totalOccupancy && totalOccupancy > currentOccupancy.maxOccupancy) {
|
|
119
|
-
throw new _common.DataError('E_STATE', 'No room space for new resident');
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
await context.model('AccommodationRoom').save({
|
|
123
|
-
id: accommodationRoom,
|
|
124
|
-
currentOccupancy: totalOccupancy
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* @param {DataEventArgs} event
|
|
130
|
-
* @param {Function} callback
|
|
131
|
-
*/
|
|
132
|
-
function beforeSave(event, callback) {
|
|
133
|
-
return beforeSaveAsync(event).then(() => {
|
|
134
|
-
return callback();
|
|
135
|
-
}).catch((err) => {
|
|
136
|
-
return callback(err);
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* @param {DataEventArgs} event
|
|
142
|
-
* @param {Function} callback
|
|
143
|
-
*/
|
|
144
|
-
function afterSave(event, callback) {
|
|
145
|
-
return afterSaveAsync(event).then(() => {
|
|
146
|
-
return callback();
|
|
147
|
-
}).catch((err) => {
|
|
148
|
-
return callback(err);
|
|
149
|
-
});
|
|
150
|
-
}
|
|
151
|
-
//# sourceMappingURL=OnUpdateAccommodationRoomListener.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"OnUpdateAccommodationRoomListener.js","names":["_common","require","beforeSaveAsync","event","state","context","model","target","previous","DataError","previousActionStatus","find","cardStatus","select","value","targetActionStatus","accommodationRoom","Object","prototype","hasOwnProperty","call","_target$accommodation","targetAccommodationRoom","id","cancelReason","translate","dateCancelled","Date","validThrough","afterSaveAsync","_target$accommodation2","calculateOccupancy","includes","newCard","action","student","academicYear","validFrom","alternateName","save","currentOccupancy","where","equal","and","groupBy","silent","getItem","totalOccupancy","total","maxOccupancy","beforeSave","callback","then","catch","err","afterSave"],"sources":["../../src/listeners/OnUpdateAccommodationRoomListener.js"],"sourcesContent":["\nimport { DataError } from '@themost/common';\n\nasync function beforeSaveAsync(event) {\n //\n if (event.state !== 2) {\n return;\n }\n\n const context = event.model.context;\n const target = event.target;\n const previous = event.previous;\n\n if (previous == null) {\n throw new DataError('E_PREVIOUS', 'The previous state of the object cannot be determined');\n }\n\n const previousActionStatus = await context.model('ActionStatusType').find(previous.cardStatus).select('alternateName').value();\n const targetActionStatus = await context.model('ActionStatusType').find(event.target.cardStatus).select('alternateName').value();\n\n if (previousActionStatus === 'CompletedActionStatus' && targetActionStatus === 'ActiveActionStatus') {\n target.accommodationRoom = null\n }\n\n if (Object.prototype.hasOwnProperty.call(target, 'accommodationRoom') === true) {\n const targetAccommodationRoom = target.accommodationRoom?.id || target.accommodationRoom;\n\n if (previous.accommodationRoom !== targetAccommodationRoom && targetAccommodationRoom != null && previous.accommodationRoom != null) {\n\n if (targetActionStatus !== 'CompletedActionStatus') {\n throw new DataError('E_STATE', 'The accommodation room cannot be changed for inactive accommodation card');\n }\n\n target.cancelReason = target.cancelReason || context.translate('Change Room');\n target.dateCancelled = target.dateCancelled || new Date();\n target.validThrough = target.dateCancelled;\n\n }\n }\n}\n\nasync function afterSaveAsync(event) {\n\n if (event.state !== 2) {\n return;\n }\n\n const previous = event.previous;\n if (previous == null) {\n throw new DataError('E_PREVIOUS', 'The previous state of the object cannot be determined');\n }\n\n const target = event.target;\n\n if (Object.prototype.hasOwnProperty.call(target, 'accommodationRoom') === false) {\n return;\n }\n\n\n const context = event.model.context;\n const previousActionStatus = await context.model('ActionStatusType').find(previous.cardStatus).select('alternateName').value();\n const targetActionStatus = await context.model('ActionStatusType').find(event.target.cardStatus).select('alternateName').value();\n const targetAccommodationRoom = target.accommodationRoom?.id || target.accommodationRoom;\n\n if (previousActionStatus === 'CompletedActionStatus' && targetActionStatus === 'ActiveActionStatus' && previous.accommodationRoom != null) {\n // update previous room occupancy\n await calculateOccupancy(context, previous.accommodationRoom);\n }\n\n if (['CompletedActionStatus', 'ActiveActionStatus'].includes(previousActionStatus) && targetActionStatus === 'CancelledActionStatus') {\n // on cancel student accommodation card status\n await calculateOccupancy(context, targetAccommodationRoom);\n }\n\n if (['CompletedActionStatus', 'ActiveActionStatus'].includes(previousActionStatus) && targetActionStatus === 'CompletedActionStatus') {\n \n\n if (previous.accommodationRoom === targetAccommodationRoom) {\n return;\n }\n\n if (previousActionStatus === 'CompletedActionStatus') {\n const newCard = {\n action: previous.action,\n student: previous.student,\n accommodationRoom: targetAccommodationRoom,\n academicYear: previous.academicYear,\n validFrom: target.validThrough,\n validThrough: previous.validThrough,\n cardStatus: {\n alternateName: 'CompletedActionStatus'\n }\n\n }\n\n await context.model('StudentAccommodationCards').save(newCard);\n }\n\n await calculateOccupancy(context, targetAccommodationRoom);\n\n if (previous.accommodationRoom != null) {\n await calculateOccupancy(context, previous.accommodationRoom);\n }\n }\n}\n\nasync function calculateOccupancy(context, accommodationRoom) {\n \n const currentOccupancy = await context.model('StudentAccommodationCard')\n .where('accommodationRoom').equal(accommodationRoom)\n .and('isActive').equal(1)\n .select('count(id) as total', 'accommodationRoom/occupancy as maxOccupancy')\n .groupBy('accommodationRoom/occupancy')\n .silent()\n .getItem();\n\n const totalOccupancy= (currentOccupancy && currentOccupancy.total ) || 0;\n if (totalOccupancy && totalOccupancy > currentOccupancy.maxOccupancy) {\n throw new DataError('E_STATE', 'No room space for new resident');\n }\n\n await context.model('AccommodationRoom').save({\n id: accommodationRoom,\n currentOccupancy: totalOccupancy\n });\n}\n\n/**\n * @param {DataEventArgs} event\n * @param {Function} callback\n */\nexport function beforeSave(event, callback) {\n return beforeSaveAsync(event).then(() => {\n return callback();\n }).catch((err) => {\n return callback(err);\n });\n}\n\n/**\n * @param {DataEventArgs} event\n * @param {Function} callback\n */\nexport function afterSave(event, callback) {\n return afterSaveAsync(event).then(() => {\n return callback();\n }).catch((err) => {\n return callback(err);\n });\n}"],"mappings":"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"}
|
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import { DataError } from '@themost/common';
|
|
3
|
-
|
|
4
|
-
async function beforeSaveAsync(event) {
|
|
5
|
-
//
|
|
6
|
-
if (event.state !== 2) {
|
|
7
|
-
return;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
const context = event.model.context;
|
|
11
|
-
const target = event.target;
|
|
12
|
-
const previous = event.previous;
|
|
13
|
-
|
|
14
|
-
if (previous == null) {
|
|
15
|
-
throw new DataError('E_PREVIOUS', 'The previous state of the object cannot be determined');
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const previousActionStatus = await context.model('ActionStatusType').find(previous.cardStatus).select('alternateName').value();
|
|
19
|
-
const targetActionStatus = await context.model('ActionStatusType').find(event.target.cardStatus).select('alternateName').value();
|
|
20
|
-
|
|
21
|
-
if (previousActionStatus === 'CompletedActionStatus' && targetActionStatus === 'ActiveActionStatus') {
|
|
22
|
-
target.accommodationRoom = null
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
if (Object.prototype.hasOwnProperty.call(target, 'accommodationRoom') === true) {
|
|
26
|
-
const targetAccommodationRoom = target.accommodationRoom?.id || target.accommodationRoom;
|
|
27
|
-
|
|
28
|
-
if (previous.accommodationRoom !== targetAccommodationRoom && targetAccommodationRoom != null && previous.accommodationRoom != null) {
|
|
29
|
-
|
|
30
|
-
if (targetActionStatus !== 'CompletedActionStatus') {
|
|
31
|
-
throw new DataError('E_STATE', 'The accommodation room cannot be changed for inactive accommodation card');
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
target.cancelReason = target.cancelReason || context.translate('Change Room');
|
|
35
|
-
target.dateCancelled = target.dateCancelled || new Date();
|
|
36
|
-
target.validThrough = target.dateCancelled;
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
async function afterSaveAsync(event) {
|
|
43
|
-
|
|
44
|
-
if (event.state !== 2) {
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const previous = event.previous;
|
|
49
|
-
if (previous == null) {
|
|
50
|
-
throw new DataError('E_PREVIOUS', 'The previous state of the object cannot be determined');
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const target = event.target;
|
|
54
|
-
|
|
55
|
-
if (Object.prototype.hasOwnProperty.call(target, 'accommodationRoom') === false) {
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const context = event.model.context;
|
|
61
|
-
const previousActionStatus = await context.model('ActionStatusType').find(previous.cardStatus).select('alternateName').value();
|
|
62
|
-
const targetActionStatus = await context.model('ActionStatusType').find(event.target.cardStatus).select('alternateName').value();
|
|
63
|
-
const targetAccommodationRoom = target.accommodationRoom?.id || target.accommodationRoom;
|
|
64
|
-
|
|
65
|
-
if (previousActionStatus === 'CompletedActionStatus' && targetActionStatus === 'ActiveActionStatus' && previous.accommodationRoom != null) {
|
|
66
|
-
// update previous room occupancy
|
|
67
|
-
await calculateOccupancy(context, previous.accommodationRoom);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
if (['CompletedActionStatus', 'ActiveActionStatus'].includes(previousActionStatus) && targetActionStatus === 'CancelledActionStatus') {
|
|
71
|
-
// on cancel student accommodation card status
|
|
72
|
-
await calculateOccupancy(context, targetAccommodationRoom);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
if (['CompletedActionStatus', 'ActiveActionStatus'].includes(previousActionStatus) && targetActionStatus === 'CompletedActionStatus') {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
if (previous.accommodationRoom === targetAccommodationRoom) {
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
if (previousActionStatus === 'CompletedActionStatus') {
|
|
83
|
-
const newCard = {
|
|
84
|
-
action: previous.action,
|
|
85
|
-
student: previous.student,
|
|
86
|
-
accommodationRoom: targetAccommodationRoom,
|
|
87
|
-
academicYear: previous.academicYear,
|
|
88
|
-
validFrom: target.validThrough,
|
|
89
|
-
validThrough: previous.validThrough,
|
|
90
|
-
cardStatus: {
|
|
91
|
-
alternateName: 'CompletedActionStatus'
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
await context.model('StudentAccommodationCards').save(newCard);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
await calculateOccupancy(context, targetAccommodationRoom);
|
|
100
|
-
|
|
101
|
-
if (previous.accommodationRoom != null) {
|
|
102
|
-
await calculateOccupancy(context, previous.accommodationRoom);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
async function calculateOccupancy(context, accommodationRoom) {
|
|
108
|
-
|
|
109
|
-
const currentOccupancy = await context.model('StudentAccommodationCard')
|
|
110
|
-
.where('accommodationRoom').equal(accommodationRoom)
|
|
111
|
-
.and('isActive').equal(1)
|
|
112
|
-
.select('count(id) as total', 'accommodationRoom/occupancy as maxOccupancy')
|
|
113
|
-
.groupBy('accommodationRoom/occupancy')
|
|
114
|
-
.silent()
|
|
115
|
-
.getItem();
|
|
116
|
-
|
|
117
|
-
const totalOccupancy= (currentOccupancy && currentOccupancy.total ) || 0;
|
|
118
|
-
if (totalOccupancy && totalOccupancy > currentOccupancy.maxOccupancy) {
|
|
119
|
-
throw new DataError('E_STATE', 'No room space for new resident');
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
await context.model('AccommodationRoom').save({
|
|
123
|
-
id: accommodationRoom,
|
|
124
|
-
currentOccupancy: totalOccupancy
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* @param {DataEventArgs} event
|
|
130
|
-
* @param {Function} callback
|
|
131
|
-
*/
|
|
132
|
-
export function beforeSave(event, callback) {
|
|
133
|
-
return beforeSaveAsync(event).then(() => {
|
|
134
|
-
return callback();
|
|
135
|
-
}).catch((err) => {
|
|
136
|
-
return callback(err);
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* @param {DataEventArgs} event
|
|
142
|
-
* @param {Function} callback
|
|
143
|
-
*/
|
|
144
|
-
export function afterSave(event, callback) {
|
|
145
|
-
return afterSaveAsync(event).then(() => {
|
|
146
|
-
return callback();
|
|
147
|
-
}).catch((err) => {
|
|
148
|
-
return callback(err);
|
|
149
|
-
});
|
|
150
|
-
}
|