@stamhoofd/backend 2.95.2 → 2.96.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stamhoofd/backend",
3
- "version": "2.95.2",
3
+ "version": "2.96.0",
4
4
  "main": "./dist/index.js",
5
5
  "exports": {
6
6
  ".": {
@@ -45,14 +45,14 @@
45
45
  "@simonbackx/simple-encoding": "2.22.0",
46
46
  "@simonbackx/simple-endpoints": "1.20.1",
47
47
  "@simonbackx/simple-logging": "^1.0.1",
48
- "@stamhoofd/backend-i18n": "2.95.2",
49
- "@stamhoofd/backend-middleware": "2.95.2",
50
- "@stamhoofd/email": "2.95.2",
51
- "@stamhoofd/models": "2.95.2",
52
- "@stamhoofd/queues": "2.95.2",
53
- "@stamhoofd/sql": "2.95.2",
54
- "@stamhoofd/structures": "2.95.2",
55
- "@stamhoofd/utility": "2.95.2",
48
+ "@stamhoofd/backend-i18n": "2.96.0",
49
+ "@stamhoofd/backend-middleware": "2.96.0",
50
+ "@stamhoofd/email": "2.96.0",
51
+ "@stamhoofd/models": "2.96.0",
52
+ "@stamhoofd/queues": "2.96.0",
53
+ "@stamhoofd/sql": "2.96.0",
54
+ "@stamhoofd/structures": "2.96.0",
55
+ "@stamhoofd/utility": "2.96.0",
56
56
  "archiver": "^7.0.1",
57
57
  "axios": "^1.8.2",
58
58
  "cookie": "^0.7.0",
@@ -70,5 +70,5 @@
70
70
  "publishConfig": {
71
71
  "access": "public"
72
72
  },
73
- "gitHead": "395db4d4c0866e0908e80f4c8cf8980f0862ef53"
73
+ "gitHead": "370bebc6a70f9771fe22c33a9d2bc49a6ca83fe4"
74
74
  }
@@ -123,7 +123,8 @@ export class GetRegistrationsEndpoint extends Endpoint<Params, Query, Body, Resp
123
123
  .setMaxExecutionTime(15 * 1000)
124
124
  .from(
125
125
  SQL.table('registrations'),
126
- );
126
+ )
127
+ .where('registeredAt', '!=', null);
127
128
 
128
129
  if (scopeFilter) {
129
130
  query.where(await compileToSQLFilter(scopeFilter, filterCompilers));
@@ -27,7 +27,7 @@ export class GetOrganizationAdminsEndpoint extends Endpoint<Params, Query, Body,
27
27
  await Context.authenticate();
28
28
 
29
29
  // Fast throw first (more in depth checking for patches later)
30
- if (!await Context.auth.canManageAdmins(organization.id)) {
30
+ if (!await Context.auth.hasFullAccess(organization.id)) {
31
31
  throw Context.auth.error();
32
32
  }
33
33
 
@@ -9,6 +9,14 @@ import { Context } from '../helpers/Context';
9
9
  import { XlsxTransformerColumnHelper } from '../helpers/XlsxTransformerColumnHelper';
10
10
 
11
11
  export const baseMemberColumns: XlsxTransformerColumn<PlatformMember>[] = [
12
+ {
13
+ id: 'id',
14
+ name: $t(`29360811-3663-496c-8d8f-c9fdf9467a74`),
15
+ width: 40,
16
+ getValue: ({ patchedMember: object }: PlatformMember) => ({
17
+ value: object.id,
18
+ }),
19
+ },
12
20
  {
13
21
  id: 'memberNumber',
14
22
  name: $t(`cc1cf4a7-0bd2-4fa7-8ff2-0a12470a738d`),
@@ -134,60 +142,6 @@ export const baseMemberColumns: XlsxTransformerColumn<PlatformMember>[] = [
134
142
  value: object.details.notes,
135
143
  }),
136
144
  },
137
- {
138
- id: 'organization',
139
- name: $t(`afd7843d-f355-445b-a158-ddacf469a5b1`),
140
- width: 40,
141
- getValue: (member: PlatformMember) => {
142
- const organizations = member.filterOrganizations({ currentPeriod: true, types: [GroupType.Membership] });
143
- const str = Formatter.joinLast(organizations.map(o => o.name).sort(), ', ', ' ' + $t(`c1843768-2bf4-42f2-baa4-42f49028463d`) + ' ') || Context.i18n.$t('1a16a32a-7ee4-455d-af3d-6073821efa8f');
144
-
145
- return {
146
- value: str,
147
- };
148
- },
149
- },
150
- {
151
- id: 'uri',
152
- name: $t(`27cfaf26-6b88-4ebc-a50a-627a9f0f9e64`),
153
- width: 30,
154
- getValue: (member: PlatformMember) => {
155
- const organizations = member.filterOrganizations({ currentPeriod: true, types: [GroupType.Membership] });
156
- const str = Formatter.joinLast(organizations.map(o => o.uri).sort(), ', ', ' ' + $t(`c1843768-2bf4-42f2-baa4-42f49028463d`) + ' ') || Context.i18n.$t('1a16a32a-7ee4-455d-af3d-6073821efa8f');
157
-
158
- return {
159
- value: str,
160
- };
161
- },
162
- },
163
- {
164
- id: 'group',
165
- name: $t(`0c230001-c3be-4a8e-8eab-23dc3fd96e52`),
166
- width: 40,
167
- getValue: (member: PlatformMember) => {
168
- const groups = member.filterRegistrations({ currentPeriod: true, types: [GroupType.Membership], organizationId: Context.organization?.id });
169
- const str = Formatter.joinLast(Formatter.uniqueArray(groups.map(o => o.group.settings.name.toString())).sort(), ', ', ' ' + $t(`c1843768-2bf4-42f2-baa4-42f49028463d`) + ' ') || Context.i18n.$t('1a16a32a-7ee4-455d-af3d-6073821efa8f');
170
-
171
- return {
172
- value: str,
173
- };
174
- },
175
- },
176
- {
177
- id: 'defaultAgeGroup',
178
- name: $t(`0ef2bbb3-0b3c-411a-8901-a454cff1f839`),
179
- width: 40,
180
- getValue: (member: PlatformMember) => {
181
- const groups = member.filterRegistrations({ currentPeriod: true, types: [GroupType.Membership], organizationId: Context.organization?.id });
182
- const defaultAgeGroupIds = Formatter.uniqueArray(groups.filter(o => o.group.defaultAgeGroupId));
183
- const defaultAgeGroups = defaultAgeGroupIds.map(o => PlatformStruct.shared.config.defaultAgeGroups.find(g => g.id === o.group.defaultAgeGroupId)?.name ?? $t(`6aeee253-beb2-4548-b60e-30836afcf2f0`));
184
- const str = Formatter.joinLast(Formatter.uniqueArray(defaultAgeGroups).sort(), ', ', ' ' + $t(`c1843768-2bf4-42f2-baa4-42f49028463d`) + ' ') || Context.i18n.$t('1a16a32a-7ee4-455d-af3d-6073821efa8f');
185
-
186
- return {
187
- value: str,
188
- };
189
- },
190
- },
191
145
  {
192
146
  id: 'nationalRegisterNumber',
193
147
  name: $t(`00881b27-7501-4c56-98de-55618be2bf11`),
@@ -251,16 +205,61 @@ const sheet: XlsxTransformerSheet<PlatformMember, PlatformMember> = {
251
205
  id: 'members',
252
206
  name: $t(`fb35c140-e936-4e91-aa92-ef4dfc59fb51`),
253
207
  columns: [
208
+ ...baseMemberColumns,
254
209
  {
255
- id: 'id',
256
- name: $t(`29360811-3663-496c-8d8f-c9fdf9467a74`),
210
+ id: 'organization',
211
+ name: $t(`afd7843d-f355-445b-a158-ddacf469a5b1`),
257
212
  width: 40,
258
- getValue: ({ patchedMember: object }: PlatformMember) => ({
259
- value: object.id,
260
- }),
213
+ getValue: (member: PlatformMember) => {
214
+ const organizations = member.filterOrganizations({ currentPeriod: true, types: [GroupType.Membership] });
215
+ const str = Formatter.joinLast(organizations.map(o => o.name).sort(), ', ', ' ' + $t(`c1843768-2bf4-42f2-baa4-42f49028463d`) + ' ') || Context.i18n.$t('1a16a32a-7ee4-455d-af3d-6073821efa8f');
216
+
217
+ return {
218
+ value: str,
219
+ };
220
+ },
221
+ },
222
+ {
223
+ id: 'uri',
224
+ name: $t(`27cfaf26-6b88-4ebc-a50a-627a9f0f9e64`),
225
+ width: 30,
226
+ getValue: (member: PlatformMember) => {
227
+ const organizations = member.filterOrganizations({ currentPeriod: true, types: [GroupType.Membership] });
228
+ const str = Formatter.joinLast(organizations.map(o => o.uri).sort(), ', ', ' ' + $t(`c1843768-2bf4-42f2-baa4-42f49028463d`) + ' ') || Context.i18n.$t('1a16a32a-7ee4-455d-af3d-6073821efa8f');
229
+
230
+ return {
231
+ value: str,
232
+ };
233
+ },
261
234
  },
235
+ {
236
+ id: 'group',
237
+ name: $t(`0c230001-c3be-4a8e-8eab-23dc3fd96e52`),
238
+ width: 40,
239
+ getValue: (member: PlatformMember) => {
240
+ const groups = member.filterRegistrations({ currentPeriod: true, types: [GroupType.Membership], organizationId: Context.organization?.id });
241
+ const str = Formatter.joinLast(Formatter.uniqueArray(groups.map(o => o.group.settings.name.toString())).sort(), ', ', ' ' + $t(`c1843768-2bf4-42f2-baa4-42f49028463d`) + ' ') || Context.i18n.$t('1a16a32a-7ee4-455d-af3d-6073821efa8f');
262
242
 
263
- ...baseMemberColumns,
243
+ return {
244
+ value: str,
245
+ };
246
+ },
247
+ },
248
+ {
249
+ id: 'defaultAgeGroup',
250
+ name: $t(`0ef2bbb3-0b3c-411a-8901-a454cff1f839`),
251
+ width: 40,
252
+ getValue: (member: PlatformMember) => {
253
+ const groups = member.filterRegistrations({ currentPeriod: true, types: [GroupType.Membership], organizationId: Context.organization?.id });
254
+ const defaultAgeGroupIds = Formatter.uniqueArray(groups.filter(o => o.group.defaultAgeGroupId));
255
+ const defaultAgeGroups = defaultAgeGroupIds.map(o => PlatformStruct.shared.config.defaultAgeGroups.find(g => g.id === o.group.defaultAgeGroupId)?.name ?? $t(`6aeee253-beb2-4548-b60e-30836afcf2f0`));
256
+ const str = Formatter.joinLast(Formatter.uniqueArray(defaultAgeGroups).sort(), ', ', ' ' + $t(`c1843768-2bf4-42f2-baa4-42f49028463d`) + ' ') || Context.i18n.$t('1a16a32a-7ee4-455d-af3d-6073821efa8f');
257
+
258
+ return {
259
+ value: str,
260
+ };
261
+ },
262
+ },
264
263
 
265
264
  // Registration records
266
265
  {
@@ -1,6 +1,6 @@
1
1
  import { XlsxBuiltInNumberFormat, XlsxTransformerSheet } from '@stamhoofd/excel-writer';
2
2
  import { Platform } from '@stamhoofd/models';
3
- import { ExcelExportType, LimitedFilteredRequest, PlatformMember, PlatformRegistration, UnencodeablePaginatedResponse } from '@stamhoofd/structures';
3
+ import { ExcelExportType, LimitedFilteredRequest, PlatformMember, PlatformRegistration, Platform as PlatformStruct, UnencodeablePaginatedResponse } from '@stamhoofd/structures';
4
4
  import { ExportToExcelEndpoint } from '../endpoints/global/files/ExportToExcelEndpoint';
5
5
  import { GetRegistrationsEndpoint } from '../endpoints/global/registration/GetRegistrationsEndpoint';
6
6
  import { AuthenticatedStructures } from '../helpers/AuthenticatedStructures';
@@ -132,6 +132,52 @@ const sheet: XlsxTransformerSheet<PlatformMember, PlatformRegistration> = {
132
132
  key: 'member',
133
133
  getPropertyValue: (registration: PlatformRegistration) => registration.member,
134
134
  })),
135
+ {
136
+ id: 'organization',
137
+ name: $t(`afd7843d-f355-445b-a158-ddacf469a5b1`),
138
+ width: 40,
139
+ getValue: (registration: PlatformRegistration) => {
140
+ return {
141
+ value: registration.member.organizations.find(o => o.id === registration.organizationId)?.name ?? '',
142
+ };
143
+ },
144
+ },
145
+ {
146
+ id: 'uri',
147
+ name: $t(`27cfaf26-6b88-4ebc-a50a-627a9f0f9e64`),
148
+ width: 30,
149
+ getValue: (registration: PlatformRegistration) => {
150
+ return {
151
+ value: registration.member.organizations.find(o => o.id === registration.organizationId)?.uri ?? '',
152
+ };
153
+ },
154
+ },
155
+ {
156
+ id: 'group',
157
+ name: $t(`0c230001-c3be-4a8e-8eab-23dc3fd96e52`),
158
+ width: 40,
159
+ getValue: (registration: PlatformRegistration) => {
160
+ return {
161
+ value: registration.group.settings.name.toString(),
162
+ };
163
+ },
164
+ },
165
+ {
166
+ id: 'defaultAgeGroup',
167
+ name: $t(`0ef2bbb3-0b3c-411a-8901-a454cff1f839`),
168
+ width: 40,
169
+ getValue: (registration: PlatformRegistration) => {
170
+ const defaultAgeGroupId = registration.group.defaultAgeGroupId;
171
+ if (!defaultAgeGroupId) {
172
+ return {
173
+ value: '',
174
+ };
175
+ }
176
+ return {
177
+ value: PlatformStruct.shared.config.defaultAgeGroups.find(g => g.id === defaultAgeGroupId)?.name ?? $t(`6aeee253-beb2-4548-b60e-30836afcf2f0`),
178
+ };
179
+ },
180
+ },
135
181
  ],
136
182
  };
137
183
 
@@ -54,12 +54,12 @@ export const eventFilterCompilers: SQLFilterDefinitions = {
54
54
  }),
55
55
  'minAge': createColumnFilter({
56
56
  expression: SQL.jsonValue(SQL.column('meta'), '$.value.minAge'),
57
- type: SQLValueType.Number,
57
+ type: SQLValueType.JSONNumber,
58
58
  nullable: true,
59
59
  }),
60
60
  'maxAge': createColumnFilter({
61
61
  expression: SQL.jsonValue(SQL.column('meta'), '$.value.maxAge'),
62
- type: SQLValueType.Number,
62
+ type: SQLValueType.JSONNumber,
63
63
  nullable: true,
64
64
  }),
65
65
  'meta.visible': createColumnFilter({
@@ -1,10 +1,12 @@
1
- import { Member, Registration } from '@stamhoofd/models';
2
- import { baseSQLFilterCompilers, createJoinedRelationFilter, SQL, SQLFilterDefinitions } from '@stamhoofd/sql';
1
+ import { Group, Member, Registration } from '@stamhoofd/models';
2
+ import { baseSQLFilterCompilers, createColumnFilter, createJoinedRelationFilter, SQL, SQLFilterDefinitions, SQLValueType } from '@stamhoofd/sql';
3
3
  import { baseRegistrationFilterCompilers } from './base-registration-filter-compilers';
4
4
  import { memberFilterCompilers } from './members';
5
5
 
6
6
  export const memberJoin = SQL.join(Member.table).where(SQL.column(Member.table, 'id'), SQL.column(Registration.table, 'memberId'));
7
7
 
8
+ const groupJoin = SQL.join(Group.table).where(SQL.column(Group.table, 'id'), SQL.column(Registration.table, 'groupId'));
9
+
8
10
  export const registrationFilterCompilers: SQLFilterDefinitions = {
9
11
  ...baseSQLFilterCompilers,
10
12
  ...baseRegistrationFilterCompilers,
@@ -12,4 +14,40 @@ export const registrationFilterCompilers: SQLFilterDefinitions = {
12
14
  memberJoin,
13
15
  memberFilterCompilers,
14
16
  ),
17
+ group: createJoinedRelationFilter(
18
+ groupJoin,
19
+ {
20
+ ...baseSQLFilterCompilers,
21
+ id: createColumnFilter({
22
+ expression: SQL.column('groupId'),
23
+ type: SQLValueType.String,
24
+ nullable: false,
25
+ }),
26
+ type: createColumnFilter({
27
+ expression: SQL.column('groups', 'type'),
28
+ type: SQLValueType.String,
29
+ nullable: false,
30
+ }),
31
+ name: createColumnFilter({
32
+ expression: SQL.jsonValue(SQL.column('groups', 'settings'), '$.value.name'),
33
+ type: SQLValueType.JSONString,
34
+ nullable: false,
35
+ }),
36
+ status: createColumnFilter({
37
+ expression: SQL.column('groups', 'status'),
38
+ type: SQLValueType.String,
39
+ nullable: false,
40
+ }),
41
+ defaultAgeGroupId: createColumnFilter({
42
+ expression: SQL.column('groups', 'defaultAgeGroupId'),
43
+ type: SQLValueType.String,
44
+ nullable: true,
45
+ }),
46
+ deletedAt: createColumnFilter({
47
+ expression: SQL.column('groups', 'deletedAt'),
48
+ type: SQLValueType.Datetime,
49
+ nullable: true,
50
+ }),
51
+ },
52
+ ),
15
53
  };