@universis/accommodation 1.1.2 → 1.1.3

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.
@@ -8,7 +8,7 @@
8
8
  "sealed": false,
9
9
  "implements": "Place",
10
10
  "classPath": "./models/AccommodationPlace",
11
- "version": "1.0",
11
+ "version": "1.1",
12
12
  "fields": [
13
13
  {
14
14
  "@id": "http://schema.org/identifier",
@@ -25,13 +25,6 @@
25
25
  "type": "Boolean",
26
26
  "default": true
27
27
  },
28
- {
29
- "name": "numberOfRooms",
30
- "description": "The number of rooms (excluding bathrooms and closets) of the accommodation.",
31
- "type": "Number",
32
- "nullable": false,
33
- "editable": true
34
- },
35
28
  {
36
29
  "@id": "http://schema.org/events",
37
30
  "name": "events",
@@ -56,6 +49,8 @@
56
49
  "name": "address",
57
50
  "title": "address",
58
51
  "description": "Physical address of the item.",
52
+ "nested": true,
53
+ "many": true,
59
54
  "type": "PostalAddress",
60
55
  "mapping": {
61
56
  "parentModel": "AccommodationPlace",
@@ -73,20 +68,20 @@
73
68
  "description": "The geo coordinates of the accommodation.",
74
69
  "type": "Json",
75
70
  "additionalType": "GeoCoordinates"
76
- },
77
- {
71
+ },
72
+ {
78
73
  "name": "locales",
79
74
  "type": "AccommodationPlaceLocale",
80
75
  "mapping": {
81
- "associationType": "association",
82
- "cascade": "delete",
83
- "parentModel": "AccommodationPlace",
84
- "parentField": "id",
85
- "childModel": "AccommodationPlaceLocale",
86
- "childField": "object"
76
+ "associationType": "association",
77
+ "cascade": "delete",
78
+ "parentModel": "AccommodationPlace",
79
+ "parentField": "id",
80
+ "childModel": "AccommodationPlaceLocale",
81
+ "childField": "object"
87
82
  }
88
- },
89
- {
83
+ },
84
+ {
90
85
  "name": "locale",
91
86
  "type": "AccommodationPlaceLocale",
92
87
  "readonly": true,
@@ -95,35 +90,47 @@
95
90
  "expandable": true,
96
91
  "multiplicity": "ZeroOrOne",
97
92
  "mapping": {
98
- "associationType": "association",
99
- "cascade": "delete",
100
- "parentModel": "AccommodationPlace",
101
- "parentField": "id",
102
- "childModel": "AccommodationPlaceLocale",
103
- "childField": "object",
104
- "options": {
105
- "$filter": "inLanguage eq lang()",
106
- "$first": true
107
- }
93
+ "associationType": "association",
94
+ "cascade": "delete",
95
+ "parentModel": "AccommodationPlace",
96
+ "parentField": "id",
97
+ "childModel": "AccommodationPlaceLocale",
98
+ "childField": "object",
99
+ "options": {
100
+ "$filter": "inLanguage eq lang()",
101
+ "$first": true
102
+ }
103
+ }
104
+ },
105
+ {
106
+ "name": "rooms",
107
+ "type": "AccommodationRoom",
108
+ "mapping": {
109
+ "associationType": "association",
110
+ "cascade": "delete",
111
+ "parentModel": "AccommodationPlace",
112
+ "parentField": "id",
113
+ "childModel": "AccommodationRoom",
114
+ "childField": "containedInPlace"
108
115
  }
109
- }
116
+ }
110
117
  ],
111
118
  "eventListeners": [
112
119
  {
113
- "type": "@themost/data/previous-state-listener"
120
+ "type": "@themost/data/previous-state-listener"
114
121
  },
115
122
  {
116
- "type": "./listeners/data-localization"
123
+ "type": "./listeners/data-localization"
117
124
  }
118
125
  ],
119
126
  "constraints": [
120
- {
121
- "type": "unique",
122
- "fields": [
123
- "identifier"
124
- ]
125
- }
126
- ],
127
+ {
128
+ "type": "unique",
129
+ "fields": [
130
+ "identifier"
131
+ ]
132
+ }
133
+ ],
127
134
  "privileges": [
128
135
  {
129
136
  "mask": 1,
@@ -24,7 +24,7 @@
24
24
  "type": "Text",
25
25
  "size": 500
26
26
  },
27
- {
27
+ {
28
28
  "name": "roomType",
29
29
  "description": "Tύπος δωματίου",
30
30
  "type": "RoomType",
@@ -161,7 +161,19 @@
161
161
  "$first": true
162
162
  }
163
163
  }
164
+ },
165
+ {
166
+ "name": "cards",
167
+ "type": "StudentAccommodationCard",
168
+ "mapping": {
169
+ "associationType": "association",
170
+ "cascade": "delete",
171
+ "parentModel": "AccommodationRoom",
172
+ "parentField": "id",
173
+ "childModel": "StudentAccommodationCard",
174
+ "childField": "accommodationRoom"
164
175
  }
176
+ }
165
177
  ],
166
178
  "eventListeners": [
167
179
  {
@@ -5,7 +5,7 @@
5
5
  "title": "StudentAccommodationCard",
6
6
  "hidden": false,
7
7
  "sealed": false,
8
- "version": "1.5",
8
+ "version": "1.8",
9
9
  "source": "StudentAccommodationCardBase",
10
10
  "view": "StudentAccommodationCardData",
11
11
  "classPath": "./models/StudentAccommodationCard",
@@ -16,14 +16,14 @@
16
16
  "description": "Ο κωδικός της εγγραφής",
17
17
  "type": "Counter",
18
18
  "primary": true
19
- },
19
+ },
20
20
  {
21
21
  "name": "action",
22
22
  "title": "Action",
23
23
  "description": "The action associated with this card.",
24
24
  "type": "AccommodationRequestAction",
25
25
  "nullable": false
26
- },
26
+ },
27
27
  {
28
28
  "name": "student",
29
29
  "title": "Φοιτητής",
@@ -47,80 +47,75 @@
47
47
  "type": "AcademicYear",
48
48
  "expandable": true,
49
49
  "nullable": false
50
- },
51
-
52
- {
53
- "name": "serialNumber",
54
- "title": "Number",
55
- "type": "Integer",
56
- "nullable": false,
57
- "value": "javascript:return this.newid();"
58
- },
59
- {
60
- "name": "dateCreated",
61
- "title": "Date Created",
62
- "description": "The date on which this item was created.",
63
- "type": "DateTime",
64
- "value": "javascript:return (new Date());",
65
- "readonly": true
66
- },
67
- {
68
- "@id": "http://schema.org/validFrom",
69
- "name": "validFrom",
70
- "title": "validFrom",
71
- "description": "The date when the item becomes valid.",
72
- "type": "DateTime",
73
- "nullable": false
74
- },
75
- {
76
- "@id": "http://schema.org/validThrough",
77
- "name": "validThrough",
78
- "title": "validThrough",
79
- "description": "The date after when the item is not valid.",
80
- "type": "DateTime",
81
- "nullable": false
82
- },
83
- {
84
- "@id": "http://schema.org/cardStatus",
85
- "name": "cardStatus",
86
- "title": "cardStatus",
87
- "description": "Indicates the current disposition of the Card.",
88
- "type": "ActionStatusType",
89
- "value": "javascript:return { alternateName:'PotentialActionStatus' };"
90
- },
91
- {
92
- "name": "dateCancelled",
93
- "title": "Date Cancelled",
94
- "description": "The date on which this item was cancelled.",
95
- "type": "DateTime",
96
- "nullable": true
97
- },
98
- {
99
- "name": "cancelReason",
100
- "title": "Λόγοι ακύρωσης",
101
- "description": "Λόγοι ακύρωσης",
102
- "type": "Text",
103
- "size": 255,
104
- "many": false,
105
- "nullable": true
106
- },
107
- {
108
- "name": "dateModified",
109
- "title": "Ημερομηνία τροποποίησης",
110
- "description": "Ημερομηνία τροποποίησης",
111
- "type": "DateTime",
112
- "nullable": false,
113
- "value": "javascript:return new Date();",
114
- "calculation": "javascript:return this.now();"
115
- }
116
- ],
117
- "constraints": [
50
+ },
51
+ {
52
+ "name": "serialNumber",
53
+ "title": "Number",
54
+ "type": "Integer",
55
+ "nullable": false,
56
+ "value": "javascript:return this.newid();"
57
+ },
118
58
  {
119
- "type": "unique",
120
- "fields": [
121
- "student",
122
- "academicYear"
123
- ]
59
+ "name": "dateCreated",
60
+ "title": "Date Created",
61
+ "description": "The date on which this item was created.",
62
+ "type": "DateTime",
63
+ "value": "javascript:return (new Date());",
64
+ "readonly": true
65
+ },
66
+ {
67
+ "@id": "http://schema.org/validFrom",
68
+ "name": "validFrom",
69
+ "title": "validFrom",
70
+ "description": "The date when the item becomes valid.",
71
+ "type": "DateTime",
72
+ "nullable": false
73
+ },
74
+ {
75
+ "@id": "http://schema.org/validThrough",
76
+ "name": "validThrough",
77
+ "title": "validThrough",
78
+ "description": "The date after when the item is not valid.",
79
+ "type": "DateTime",
80
+ "nullable": false
81
+ },
82
+ {
83
+ "@id": "http://schema.org/cardStatus",
84
+ "name": "cardStatus",
85
+ "title": "cardStatus",
86
+ "description": "Indicates the current disposition of the Card.",
87
+ "type": "ActionStatusType",
88
+ "value": "javascript:return { alternateName:'PotentialActionStatus' };"
89
+ },
90
+ {
91
+ "name": "dateCancelled",
92
+ "title": "Date Cancelled",
93
+ "description": "The date on which this item was cancelled.",
94
+ "type": "DateTime",
95
+ "nullable": true
96
+ },
97
+ {
98
+ "name": "cancelReason",
99
+ "title": "Λόγοι ακύρωσης",
100
+ "description": "Λόγοι ακύρωσης",
101
+ "type": "Text",
102
+ "size": 255,
103
+ "many": false,
104
+ "nullable": true
105
+ },
106
+ {
107
+ "name": "dateModified",
108
+ "title": "Ημερομηνία τροποποίησης",
109
+ "description": "Ημερομηνία τροποποίησης",
110
+ "type": "DateTime",
111
+ "nullable": false,
112
+ "value": "javascript:return new Date();",
113
+ "calculation": "javascript:return this.now();"
114
+ },
115
+ {
116
+ "name": "isActive",
117
+ "readonly": true,
118
+ "virtual": true
124
119
  }
125
120
  ],
126
121
  "privileges": [
@@ -143,7 +138,7 @@
143
138
  "type": "self",
144
139
  "account": "Students",
145
140
  "filter": "student/user eq me()"
146
- }
141
+ }
147
142
  ],
148
143
  "eventListeners": [
149
144
  {
@@ -155,9 +150,11 @@
155
150
  {
156
151
  "type": "./listeners/OnCancelAccommodationCardListener"
157
152
  },
153
+ {
154
+ "type": "./listeners/OnUpdateAccommodationRoomListener"
155
+ },
158
156
  {
159
157
  "type": "./listeners/SendEmailAfterCardStatusChangeListener"
160
158
  }
161
159
  ]
162
- }
163
-
160
+ }
@@ -258,6 +258,33 @@
258
258
  'read',
259
259
  'write']
260
260
 
261
+ },
262
+ {
263
+ 'scope': [
264
+ 'accommodation'],
265
+
266
+ 'resource': '/api/RoomTypes',
267
+ 'access': [
268
+ 'read']
269
+
270
+ },
271
+ {
272
+ 'scope': [
273
+ 'accommodation'],
274
+
275
+ 'resource': '/api/Regions',
276
+ 'access': [
277
+ 'read']
278
+
279
+ },
280
+ {
281
+ 'scope': [
282
+ 'accommodation'],
283
+
284
+ 'resource': '/api/Countries',
285
+ 'access': [
286
+ 'read']
287
+
261
288
  },
262
289
  {
263
290
  'scope': [
@@ -282,7 +309,7 @@
282
309
  'scope': [
283
310
  'students'],
284
311
 
285
- 'resource': '/api/Accommodations/?$',
312
+ 'resource': '/api/AccommodationPlaces/?$',
286
313
  'access': [
287
314
  'read']
288
315
 
@@ -1 +1 @@
1
- {"version":3,"file":"scope.access.js","names":["exports","default","_default"],"sources":["../../src/config/scope.access.js"],"sourcesContent":["export default [\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/users/me',\n 'access': [\n 'read'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/content/private',\n 'access': [\n 'read'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/ActionStatusTypes',\n 'access': [\n 'read'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/StudentStatuses',\n 'access': [\n 'read'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/StudentCategories',\n 'access': [\n 'read'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/FamilyStatuses',\n 'access': [\n 'read'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/LocalDepartments',\n 'access': [\n 'read'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/EventStatusTypes',\n 'access': [\n 'read'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/JsonAttachments',\n 'access': [\n 'read'\n ]\n },\n {\n 'scope': [\n 'registrar',\n 'accommodation'\n ],\n 'resource': '/api/AccommodationInscriptionModeTags',\n 'access': [\n 'read',\n 'write'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/AccommodationRequestActions',\n 'access': [\n 'read',\n 'write'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/SpecialAccommodationRequestActions',\n 'access': [\n 'read',\n 'write'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/AccommodationRequestActionMessages',\n 'access': [\n 'read',\n 'write'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/AccommodationRequestActionReviews',\n 'access': [\n 'read',\n 'write'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/AccommodationRequestAttachmentConfigurations',\n 'access': [\n 'read',\n 'write'\n ]\n },\n {\n 'scope': [\n 'registrar',\n 'accommodation'\n ],\n 'resource': '/api/AccommodationRequestEffectiveStatusTypes',\n 'access': [\n 'read',\n 'write'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/AccommodationRequestEvents',\n 'access': [\n 'read',\n 'write'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/AcademicYears',\n 'access': [\n 'read'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/AcademicPeriods',\n 'access': [\n 'read'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/StudentAccommodationCards',\n 'access': [\n 'read',\n 'write'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/AccommodationPlaces',\n 'access': [\n 'read',\n 'write'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/AccommodationRooms',\n 'access': [\n 'read',\n 'write'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/AccommodationConfigurations',\n 'access': [\n 'read',\n 'write'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/ReportTemplates',\n 'access': [\n 'read',\n 'write'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/AccommodationRequestCategories',\n 'access': [\n 'read',\n 'write'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/AccommodationRequestPreferences',\n 'access': [\n 'read'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/UpdateAccommodationRequestEventActions',\n 'access': [\n 'read',\n 'write'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/Institutes',\n 'access': [\n 'read'\n ]\n },\n {\n 'scope': [\n 'students'\n ],\n 'resource': '/api/TestActions/?$',\n 'access': [\n 'read',\n 'write'\n ]\n },\n {\n 'scope': [\n 'students'\n ],\n 'resource': '/api/Accommodations/?$',\n 'access': [\n 'read'\n ]\n },\n {\n 'scope': [\n 'students'\n ],\n 'resource': '/api/AccommodationRequestActions',\n 'access': [\n 'read',\n 'write'\n ]\n },\n {\n 'scope': [\n 'students'\n ],\n 'resource': '/api/AccommodationRequestEvents',\n 'access': [\n 'read'\n ]\n },\n {\n 'scope': [\n 'students'\n ],\n 'resource': '/api/AccommodationRequestCategories',\n 'access': [\n 'read'\n ]\n },\n {\n 'scope': [\n 'students'\n ],\n 'resource': '/api/StudentAccommodationCards',\n 'access': [\n 'read'\n ]\n }\n]\n"],"mappings":"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"}
1
+ {"version":3,"file":"scope.access.js","names":["exports","default","_default"],"sources":["../../src/config/scope.access.js"],"sourcesContent":["export default [\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/users/me',\n 'access': [\n 'read'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/content/private',\n 'access': [\n 'read'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/ActionStatusTypes',\n 'access': [\n 'read'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/StudentStatuses',\n 'access': [\n 'read'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/StudentCategories',\n 'access': [\n 'read'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/FamilyStatuses',\n 'access': [\n 'read'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/LocalDepartments',\n 'access': [\n 'read'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/EventStatusTypes',\n 'access': [\n 'read'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/JsonAttachments',\n 'access': [\n 'read'\n ]\n },\n {\n 'scope': [\n 'registrar',\n 'accommodation'\n ],\n 'resource': '/api/AccommodationInscriptionModeTags',\n 'access': [\n 'read',\n 'write'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/AccommodationRequestActions',\n 'access': [\n 'read',\n 'write'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/SpecialAccommodationRequestActions',\n 'access': [\n 'read',\n 'write'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/AccommodationRequestActionMessages',\n 'access': [\n 'read',\n 'write'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/AccommodationRequestActionReviews',\n 'access': [\n 'read',\n 'write'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/AccommodationRequestAttachmentConfigurations',\n 'access': [\n 'read',\n 'write'\n ]\n },\n {\n 'scope': [\n 'registrar',\n 'accommodation'\n ],\n 'resource': '/api/AccommodationRequestEffectiveStatusTypes',\n 'access': [\n 'read',\n 'write'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/AccommodationRequestEvents',\n 'access': [\n 'read',\n 'write'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/AcademicYears',\n 'access': [\n 'read'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/AcademicPeriods',\n 'access': [\n 'read'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/StudentAccommodationCards',\n 'access': [\n 'read',\n 'write'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/AccommodationPlaces',\n 'access': [\n 'read',\n 'write'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/AccommodationRooms',\n 'access': [\n 'read',\n 'write'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/AccommodationConfigurations',\n 'access': [\n 'read',\n 'write'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/ReportTemplates',\n 'access': [\n 'read',\n 'write'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/AccommodationRequestCategories',\n 'access': [\n 'read',\n 'write'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/AccommodationRequestPreferences',\n 'access': [\n 'read'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/UpdateAccommodationRequestEventActions',\n 'access': [\n 'read',\n 'write'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/RoomTypes',\n 'access': [\n 'read'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/Regions',\n 'access': [\n 'read'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/Countries',\n 'access': [\n 'read'\n ]\n },\n {\n 'scope': [\n 'accommodation'\n ],\n 'resource': '/api/Institutes',\n 'access': [\n 'read'\n ]\n },\n {\n 'scope': [\n 'students'\n ],\n 'resource': '/api/TestActions/?$',\n 'access': [\n 'read',\n 'write'\n ]\n },\n {\n 'scope': [\n 'students'\n ],\n 'resource': '/api/AccommodationPlaces/?$',\n 'access': [\n 'read'\n ]\n },\n {\n 'scope': [\n 'students'\n ],\n 'resource': '/api/AccommodationRequestActions',\n 'access': [\n 'read',\n 'write'\n ]\n },\n {\n 'scope': [\n 'students'\n ],\n 'resource': '/api/AccommodationRequestEvents',\n 'access': [\n 'read'\n ]\n },\n {\n 'scope': [\n 'students'\n ],\n 'resource': '/api/AccommodationRequestCategories',\n 'access': [\n 'read'\n ]\n },\n {\n 'scope': [\n 'students'\n ],\n 'resource': '/api/StudentAccommodationCards',\n 'access': [\n 'read'\n ]\n }\n]\n"],"mappings":"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"}
@@ -0,0 +1,151 @@
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
@@ -0,0 +1 @@
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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"}
@@ -13,7 +13,15 @@ var _common = require("@themost/common"); /**
13
13
  /**
14
14
  * @type {Student|DataObject|*}
15
15
  */
16
- const student = context.model('Student').convert(event.target.student);
16
+ const previous = event.previous;
17
+ let student = context.model('Student').convert(event.target.student);
18
+ if (!student) {
19
+ if (previous) {
20
+ student = context.model('Student').convert(previous.student);
21
+ } else {
22
+ throw new _common.DataError('ERR_STATUS', 'Student cannot be found');
23
+ }
24
+ }
17
25
  // const isActive = await student.silent().isActive();
18
26
  const isActive = await student.is(':active');
19
27
  if (!isActive) {
@@ -23,8 +31,6 @@ var _common = require("@themost/common"); /**
23
31
  'Student', 'studentStatus');
24
32
  }
25
33
 
26
- const studentObject = await context.model('Student').where('id').equal(student.id).silent().flatten().getItem();
27
-
28
34
  const academicYear = context.model('AcademicYear').convert(event.target.academicYear).getId();
29
35
  if (Number.isInteger(academicYear) === false) {
30
36
  throw new _common.DataError('E_VALUE', 'Invalid academic year. Expected number.', null, 'AcademicYear', 'id');
@@ -1 +1 @@
1
- {"version":3,"file":"StudentAccommodationCardSaveListener.js","names":["_common","require","beforeSave","event","callback","state","context","model","student","convert","target","isActive","is","DataError","studentObject","where","equal","id","silent","flatten","getItem","academicYear","getId","Number","isInteger","academicYearObject","undefined","academicPeriod","academicPeriodObject","then","catch","err","afterSave","accommodationRoom","Object","keys","length","room","newRoom","currentOccupancy","save"],"sources":["../../src/listeners/StudentAccommodationCardSaveListener.js"],"sourcesContent":["/**\n * @param {DataEventArgs} event\n * @param {Function} callback\n */\nimport {DataError} from \"@themost/common\";\n\nexport function beforeSave(event, callback) {\n (async () => {\n\n // validate student state (on insert or update)\n if (event.state === 1 || event.state === 2) {\n let context = event.model.context;\n /**\n * @type {Student|DataObject|*}\n */\n const student = context.model('Student').convert(event.target.student);\n // const isActive = await student.silent().isActive();\n const isActive = await student.is(':active');\n if (!isActive) {\n throw new DataError('ERR_STATUS',\n 'Invalid student status. Student Accommodation Card may be published upon an active student only.'+student\n , null,\n 'Student', 'studentStatus');\n }\n \n const studentObject = await context.model('Student').where('id').equal(student.id).silent().flatten().getItem();\n \n const academicYear = context.model('AcademicYear').convert(event.target.academicYear).getId();\n if (Number.isInteger(academicYear) === false) {\n throw new DataError('E_VALUE', 'Invalid academic year. Expected number.', null, 'AcademicYear', 'id');\n }\n\n const academicYearObject = await context.model('AcademicYear').where('id').equal(academicYear).getItem();\n if (academicYearObject === undefined){\n throw new DataError('E_VALUE', 'Invalid academic year.', null, 'AcademicYear', 'id');\n }\n\n if (event.target.academicPeriod != null){\n\n const academicPeriod = context.model('AcademicPeriod').convert(event.target.academicPeriod).getId();\n if (Number.isInteger(academicPeriod) === false) {\n throw new DataError('E_VALUE', 'Invalid academic period. Expected number.', null, 'AcademicPeriod', 'id');\n }\n \n const academicPeriodObject = await context.model('AcademicPeriod').where('id').equal(academicPeriod).getItem();\n if (academicPeriodObject === undefined){\n throw new DataError('E_VALUE', 'Invalid academic period.', null, 'AcademicPeriod', 'id');\n }\n \n }\n }\n })().then( () => {\n return callback();\n }).catch( err => {\n return callback(err);\n });\n}\n\n\n/**\n * @param {DataEventArgs} event\n * @param {Function} callback\n */\nexport function afterSave(event, callback) {\n (async () => {\n //\n let context = event.model.context;\n if (event.state === 1) {\n if (event.target.accommodationRoom && Object.keys(event.target.accommodationRoom).length != 0) {\n // get accommodation valid through date\n\n const room = await context.model('AccommodationRoom').where('id').equal(event.target.accommodationRoom.id).getItem();\n if (room === undefined) {\n throw new DataError('E_VALUE', 'Invalid accommodation room.', null, 'AccommodationRoom', 'id');\n }\n let newRoom = room;\n newRoom.currentOccupancy = room.currentOccupancy+1;\n //todo if i can increase occupancy\n await context.model('AccommodationRoom').silent().save(newRoom);\n }\n }\n\n\n })().then(() => {\n return callback();\n }).catch(err => {\n return callback(err);\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"StudentAccommodationCardSaveListener.js","names":["_common","require","beforeSave","event","callback","state","context","model","previous","student","convert","target","DataError","isActive","is","academicYear","getId","Number","isInteger","academicYearObject","where","equal","getItem","undefined","academicPeriod","academicPeriodObject","then","catch","err","afterSave","accommodationRoom","Object","keys","length","room","id","newRoom","currentOccupancy","silent","save"],"sources":["../../src/listeners/StudentAccommodationCardSaveListener.js"],"sourcesContent":["/**\n * @param {DataEventArgs} event\n * @param {Function} callback\n */\nimport {DataError} from \"@themost/common\";\n\nexport function beforeSave(event, callback) {\n (async () => {\n\n // validate student state (on insert or update)\n if (event.state === 1 || event.state === 2) {\n let context = event.model.context;\n /**\n * @type {Student|DataObject|*}\n */\n const previous = event.previous;\n let student = context.model('Student').convert(event.target.student);\n if (!student){\n if (previous){\n student = context.model('Student').convert(previous.student);\n }else{\n throw new DataError('ERR_STATUS','Student cannot be found');\n }\n }\n // const isActive = await student.silent().isActive();\n const isActive = await student.is(':active');\n if (!isActive) {\n throw new DataError('ERR_STATUS',\n 'Invalid student status. Student Accommodation Card may be published upon an active student only.'+student\n , null,\n 'Student', 'studentStatus');\n }\n \n const academicYear = context.model('AcademicYear').convert(event.target.academicYear).getId();\n if (Number.isInteger(academicYear) === false) {\n throw new DataError('E_VALUE', 'Invalid academic year. Expected number.', null, 'AcademicYear', 'id');\n }\n\n const academicYearObject = await context.model('AcademicYear').where('id').equal(academicYear).getItem();\n if (academicYearObject === undefined){\n throw new DataError('E_VALUE', 'Invalid academic year.', null, 'AcademicYear', 'id');\n }\n\n if (event.target.academicPeriod != null){\n\n const academicPeriod = context.model('AcademicPeriod').convert(event.target.academicPeriod).getId();\n if (Number.isInteger(academicPeriod) === false) {\n throw new DataError('E_VALUE', 'Invalid academic period. Expected number.', null, 'AcademicPeriod', 'id');\n }\n \n const academicPeriodObject = await context.model('AcademicPeriod').where('id').equal(academicPeriod).getItem();\n if (academicPeriodObject === undefined){\n throw new DataError('E_VALUE', 'Invalid academic period.', null, 'AcademicPeriod', 'id');\n }\n \n }\n }\n })().then( () => {\n return callback();\n }).catch( err => {\n return callback(err);\n });\n}\n\n\n/**\n * @param {DataEventArgs} event\n * @param {Function} callback\n */\nexport function afterSave(event, callback) {\n (async () => {\n //\n let context = event.model.context;\n if (event.state === 1) {\n if (event.target.accommodationRoom && Object.keys(event.target.accommodationRoom).length != 0) {\n // get accommodation valid through date\n\n const room = await context.model('AccommodationRoom').where('id').equal(event.target.accommodationRoom.id).getItem();\n if (room === undefined) {\n throw new DataError('E_VALUE', 'Invalid accommodation room.', null, 'AccommodationRoom', 'id');\n }\n let newRoom = room;\n newRoom.currentOccupancy = room.currentOccupancy+1;\n //todo if i can increase occupancy\n await context.model('AccommodationRoom').silent().save(newRoom);\n }\n }\n\n\n })().then(() => {\n return callback();\n }).catch(err => {\n return callback(err);\n });\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@universis/accommodation",
3
- "version": "1.1.2",
3
+ "version": "1.1.3",
4
4
  "description": "Universis api library template",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -8,7 +8,7 @@
8
8
  "sealed": false,
9
9
  "implements": "Place",
10
10
  "classPath": "./models/AccommodationPlace",
11
- "version": "1.0",
11
+ "version": "1.1",
12
12
  "fields": [
13
13
  {
14
14
  "@id": "http://schema.org/identifier",
@@ -25,13 +25,6 @@
25
25
  "type": "Boolean",
26
26
  "default": true
27
27
  },
28
- {
29
- "name": "numberOfRooms",
30
- "description": "The number of rooms (excluding bathrooms and closets) of the accommodation.",
31
- "type": "Number",
32
- "nullable": false,
33
- "editable": true
34
- },
35
28
  {
36
29
  "@id": "http://schema.org/events",
37
30
  "name": "events",
@@ -56,6 +49,8 @@
56
49
  "name": "address",
57
50
  "title": "address",
58
51
  "description": "Physical address of the item.",
52
+ "nested": true,
53
+ "many": true,
59
54
  "type": "PostalAddress",
60
55
  "mapping": {
61
56
  "parentModel": "AccommodationPlace",
@@ -73,20 +68,20 @@
73
68
  "description": "The geo coordinates of the accommodation.",
74
69
  "type": "Json",
75
70
  "additionalType": "GeoCoordinates"
76
- },
77
- {
71
+ },
72
+ {
78
73
  "name": "locales",
79
74
  "type": "AccommodationPlaceLocale",
80
75
  "mapping": {
81
- "associationType": "association",
82
- "cascade": "delete",
83
- "parentModel": "AccommodationPlace",
84
- "parentField": "id",
85
- "childModel": "AccommodationPlaceLocale",
86
- "childField": "object"
76
+ "associationType": "association",
77
+ "cascade": "delete",
78
+ "parentModel": "AccommodationPlace",
79
+ "parentField": "id",
80
+ "childModel": "AccommodationPlaceLocale",
81
+ "childField": "object"
87
82
  }
88
- },
89
- {
83
+ },
84
+ {
90
85
  "name": "locale",
91
86
  "type": "AccommodationPlaceLocale",
92
87
  "readonly": true,
@@ -95,35 +90,47 @@
95
90
  "expandable": true,
96
91
  "multiplicity": "ZeroOrOne",
97
92
  "mapping": {
98
- "associationType": "association",
99
- "cascade": "delete",
100
- "parentModel": "AccommodationPlace",
101
- "parentField": "id",
102
- "childModel": "AccommodationPlaceLocale",
103
- "childField": "object",
104
- "options": {
105
- "$filter": "inLanguage eq lang()",
106
- "$first": true
107
- }
93
+ "associationType": "association",
94
+ "cascade": "delete",
95
+ "parentModel": "AccommodationPlace",
96
+ "parentField": "id",
97
+ "childModel": "AccommodationPlaceLocale",
98
+ "childField": "object",
99
+ "options": {
100
+ "$filter": "inLanguage eq lang()",
101
+ "$first": true
102
+ }
103
+ }
104
+ },
105
+ {
106
+ "name": "rooms",
107
+ "type": "AccommodationRoom",
108
+ "mapping": {
109
+ "associationType": "association",
110
+ "cascade": "delete",
111
+ "parentModel": "AccommodationPlace",
112
+ "parentField": "id",
113
+ "childModel": "AccommodationRoom",
114
+ "childField": "containedInPlace"
108
115
  }
109
- }
116
+ }
110
117
  ],
111
118
  "eventListeners": [
112
119
  {
113
- "type": "@themost/data/previous-state-listener"
120
+ "type": "@themost/data/previous-state-listener"
114
121
  },
115
122
  {
116
- "type": "./listeners/data-localization"
123
+ "type": "./listeners/data-localization"
117
124
  }
118
125
  ],
119
126
  "constraints": [
120
- {
121
- "type": "unique",
122
- "fields": [
123
- "identifier"
124
- ]
125
- }
126
- ],
127
+ {
128
+ "type": "unique",
129
+ "fields": [
130
+ "identifier"
131
+ ]
132
+ }
133
+ ],
127
134
  "privileges": [
128
135
  {
129
136
  "mask": 1,
@@ -24,7 +24,7 @@
24
24
  "type": "Text",
25
25
  "size": 500
26
26
  },
27
- {
27
+ {
28
28
  "name": "roomType",
29
29
  "description": "Tύπος δωματίου",
30
30
  "type": "RoomType",
@@ -161,7 +161,19 @@
161
161
  "$first": true
162
162
  }
163
163
  }
164
+ },
165
+ {
166
+ "name": "cards",
167
+ "type": "StudentAccommodationCard",
168
+ "mapping": {
169
+ "associationType": "association",
170
+ "cascade": "delete",
171
+ "parentModel": "AccommodationRoom",
172
+ "parentField": "id",
173
+ "childModel": "StudentAccommodationCard",
174
+ "childField": "accommodationRoom"
164
175
  }
176
+ }
165
177
  ],
166
178
  "eventListeners": [
167
179
  {
@@ -5,7 +5,7 @@
5
5
  "title": "StudentAccommodationCard",
6
6
  "hidden": false,
7
7
  "sealed": false,
8
- "version": "1.5",
8
+ "version": "1.8",
9
9
  "source": "StudentAccommodationCardBase",
10
10
  "view": "StudentAccommodationCardData",
11
11
  "classPath": "./models/StudentAccommodationCard",
@@ -16,14 +16,14 @@
16
16
  "description": "Ο κωδικός της εγγραφής",
17
17
  "type": "Counter",
18
18
  "primary": true
19
- },
19
+ },
20
20
  {
21
21
  "name": "action",
22
22
  "title": "Action",
23
23
  "description": "The action associated with this card.",
24
24
  "type": "AccommodationRequestAction",
25
25
  "nullable": false
26
- },
26
+ },
27
27
  {
28
28
  "name": "student",
29
29
  "title": "Φοιτητής",
@@ -47,80 +47,75 @@
47
47
  "type": "AcademicYear",
48
48
  "expandable": true,
49
49
  "nullable": false
50
- },
51
-
52
- {
53
- "name": "serialNumber",
54
- "title": "Number",
55
- "type": "Integer",
56
- "nullable": false,
57
- "value": "javascript:return this.newid();"
58
- },
59
- {
60
- "name": "dateCreated",
61
- "title": "Date Created",
62
- "description": "The date on which this item was created.",
63
- "type": "DateTime",
64
- "value": "javascript:return (new Date());",
65
- "readonly": true
66
- },
67
- {
68
- "@id": "http://schema.org/validFrom",
69
- "name": "validFrom",
70
- "title": "validFrom",
71
- "description": "The date when the item becomes valid.",
72
- "type": "DateTime",
73
- "nullable": false
74
- },
75
- {
76
- "@id": "http://schema.org/validThrough",
77
- "name": "validThrough",
78
- "title": "validThrough",
79
- "description": "The date after when the item is not valid.",
80
- "type": "DateTime",
81
- "nullable": false
82
- },
83
- {
84
- "@id": "http://schema.org/cardStatus",
85
- "name": "cardStatus",
86
- "title": "cardStatus",
87
- "description": "Indicates the current disposition of the Card.",
88
- "type": "ActionStatusType",
89
- "value": "javascript:return { alternateName:'PotentialActionStatus' };"
90
- },
91
- {
92
- "name": "dateCancelled",
93
- "title": "Date Cancelled",
94
- "description": "The date on which this item was cancelled.",
95
- "type": "DateTime",
96
- "nullable": true
97
- },
98
- {
99
- "name": "cancelReason",
100
- "title": "Λόγοι ακύρωσης",
101
- "description": "Λόγοι ακύρωσης",
102
- "type": "Text",
103
- "size": 255,
104
- "many": false,
105
- "nullable": true
106
- },
107
- {
108
- "name": "dateModified",
109
- "title": "Ημερομηνία τροποποίησης",
110
- "description": "Ημερομηνία τροποποίησης",
111
- "type": "DateTime",
112
- "nullable": false,
113
- "value": "javascript:return new Date();",
114
- "calculation": "javascript:return this.now();"
115
- }
116
- ],
117
- "constraints": [
50
+ },
51
+ {
52
+ "name": "serialNumber",
53
+ "title": "Number",
54
+ "type": "Integer",
55
+ "nullable": false,
56
+ "value": "javascript:return this.newid();"
57
+ },
118
58
  {
119
- "type": "unique",
120
- "fields": [
121
- "student",
122
- "academicYear"
123
- ]
59
+ "name": "dateCreated",
60
+ "title": "Date Created",
61
+ "description": "The date on which this item was created.",
62
+ "type": "DateTime",
63
+ "value": "javascript:return (new Date());",
64
+ "readonly": true
65
+ },
66
+ {
67
+ "@id": "http://schema.org/validFrom",
68
+ "name": "validFrom",
69
+ "title": "validFrom",
70
+ "description": "The date when the item becomes valid.",
71
+ "type": "DateTime",
72
+ "nullable": false
73
+ },
74
+ {
75
+ "@id": "http://schema.org/validThrough",
76
+ "name": "validThrough",
77
+ "title": "validThrough",
78
+ "description": "The date after when the item is not valid.",
79
+ "type": "DateTime",
80
+ "nullable": false
81
+ },
82
+ {
83
+ "@id": "http://schema.org/cardStatus",
84
+ "name": "cardStatus",
85
+ "title": "cardStatus",
86
+ "description": "Indicates the current disposition of the Card.",
87
+ "type": "ActionStatusType",
88
+ "value": "javascript:return { alternateName:'PotentialActionStatus' };"
89
+ },
90
+ {
91
+ "name": "dateCancelled",
92
+ "title": "Date Cancelled",
93
+ "description": "The date on which this item was cancelled.",
94
+ "type": "DateTime",
95
+ "nullable": true
96
+ },
97
+ {
98
+ "name": "cancelReason",
99
+ "title": "Λόγοι ακύρωσης",
100
+ "description": "Λόγοι ακύρωσης",
101
+ "type": "Text",
102
+ "size": 255,
103
+ "many": false,
104
+ "nullable": true
105
+ },
106
+ {
107
+ "name": "dateModified",
108
+ "title": "Ημερομηνία τροποποίησης",
109
+ "description": "Ημερομηνία τροποποίησης",
110
+ "type": "DateTime",
111
+ "nullable": false,
112
+ "value": "javascript:return new Date();",
113
+ "calculation": "javascript:return this.now();"
114
+ },
115
+ {
116
+ "name": "isActive",
117
+ "readonly": true,
118
+ "virtual": true
124
119
  }
125
120
  ],
126
121
  "privileges": [
@@ -143,7 +138,7 @@
143
138
  "type": "self",
144
139
  "account": "Students",
145
140
  "filter": "student/user eq me()"
146
- }
141
+ }
147
142
  ],
148
143
  "eventListeners": [
149
144
  {
@@ -155,9 +150,11 @@
155
150
  {
156
151
  "type": "./listeners/OnCancelAccommodationCardListener"
157
152
  },
153
+ {
154
+ "type": "./listeners/OnUpdateAccommodationRoomListener"
155
+ },
158
156
  {
159
157
  "type": "./listeners/SendEmailAfterCardStatusChangeListener"
160
158
  }
161
159
  ]
162
- }
163
-
160
+ }
@@ -259,6 +259,33 @@ export default [
259
259
  'write'
260
260
  ]
261
261
  },
262
+ {
263
+ 'scope': [
264
+ 'accommodation'
265
+ ],
266
+ 'resource': '/api/RoomTypes',
267
+ 'access': [
268
+ 'read'
269
+ ]
270
+ },
271
+ {
272
+ 'scope': [
273
+ 'accommodation'
274
+ ],
275
+ 'resource': '/api/Regions',
276
+ 'access': [
277
+ 'read'
278
+ ]
279
+ },
280
+ {
281
+ 'scope': [
282
+ 'accommodation'
283
+ ],
284
+ 'resource': '/api/Countries',
285
+ 'access': [
286
+ 'read'
287
+ ]
288
+ },
262
289
  {
263
290
  'scope': [
264
291
  'accommodation'
@@ -282,7 +309,7 @@ export default [
282
309
  'scope': [
283
310
  'students'
284
311
  ],
285
- 'resource': '/api/Accommodations/?$',
312
+ 'resource': '/api/AccommodationPlaces/?$',
286
313
  'access': [
287
314
  'read'
288
315
  ]
@@ -0,0 +1,150 @@
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
+ }
@@ -13,7 +13,15 @@ export function beforeSave(event, callback) {
13
13
  /**
14
14
  * @type {Student|DataObject|*}
15
15
  */
16
- const student = context.model('Student').convert(event.target.student);
16
+ const previous = event.previous;
17
+ let student = context.model('Student').convert(event.target.student);
18
+ if (!student){
19
+ if (previous){
20
+ student = context.model('Student').convert(previous.student);
21
+ }else{
22
+ throw new DataError('ERR_STATUS','Student cannot be found');
23
+ }
24
+ }
17
25
  // const isActive = await student.silent().isActive();
18
26
  const isActive = await student.is(':active');
19
27
  if (!isActive) {
@@ -23,8 +31,6 @@ export function beforeSave(event, callback) {
23
31
  'Student', 'studentStatus');
24
32
  }
25
33
 
26
- const studentObject = await context.model('Student').where('id').equal(student.id).silent().flatten().getItem();
27
-
28
34
  const academicYear = context.model('AcademicYear').convert(event.target.academicYear).getId();
29
35
  if (Number.isInteger(academicYear) === false) {
30
36
  throw new DataError('E_VALUE', 'Invalid academic year. Expected number.', null, 'AcademicYear', 'id');