@stamhoofd/backend 2.89.1 → 2.90.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.
Files changed (66) hide show
  1. package/package.json +12 -11
  2. package/src/boot.ts +2 -0
  3. package/src/crons/balance-emails.ts +1 -6
  4. package/src/endpoints/admin/organizations/GetOrganizationsEndpoint.ts +1 -1
  5. package/src/endpoints/admin/organizations/SearchUitpasOrganizersEndpoint.ts +42 -0
  6. package/src/endpoints/global/audit-logs/GetAuditLogsEndpoint.ts +4 -4
  7. package/src/endpoints/global/events/GetEventNotificationsEndpoint.ts +3 -3
  8. package/src/endpoints/global/events/GetEventsEndpoint.ts +2 -2
  9. package/src/endpoints/global/events/PatchEventsEndpoint.ts +23 -2
  10. package/src/endpoints/global/groups/GetGroupsEndpoint.ts +6 -6
  11. package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.test.ts +8 -6
  12. package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.ts +2 -2
  13. package/src/endpoints/global/platform/GetPlatformEndpoint.ts +1 -0
  14. package/src/endpoints/global/registration/PatchUserMembersEndpoint.test.ts +10 -8
  15. package/src/endpoints/global/registration/RegisterMembersEndpoint.ts +11 -0
  16. package/src/endpoints/global/registration-periods/GetRegistrationPeriodsEndpoint.ts +2 -2
  17. package/src/endpoints/organization/dashboard/documents/GetDocumentsEndpoint.ts +3 -6
  18. package/src/endpoints/organization/dashboard/organization/GetUitpasClientIdEndpoint.ts +38 -0
  19. package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.ts +31 -1
  20. package/src/endpoints/organization/dashboard/organization/SetUitpasClientCredentialsEndpoint.ts +108 -0
  21. package/src/endpoints/organization/dashboard/payments/GetPaymentsEndpoint.ts +1 -1
  22. package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalancesEndpoint.ts +1 -2
  23. package/src/endpoints/organization/dashboard/registration-periods/GetOrganizationRegistrationPeriodsEndpoint.ts +1 -1
  24. package/src/endpoints/organization/dashboard/registration-periods/PatchOrganizationRegistrationPeriodsEndpoint.ts +9 -1
  25. package/src/endpoints/organization/dashboard/webshops/GetWebshopOrdersEndpoint.ts +3 -2
  26. package/src/endpoints/organization/dashboard/webshops/GetWebshopTicketsEndpoint.ts +1 -1
  27. package/src/endpoints/organization/webshops/GetWebshopEndpoint.test.ts +2 -9
  28. package/src/endpoints/organization/webshops/GetWebshopEndpoint.ts +1 -7
  29. package/src/endpoints/organization/webshops/PlaceOrderEndpoint.ts +68 -1
  30. package/src/endpoints/organization/webshops/RetrieveUitpasSocialTariffPriceEndpoint.ts +27 -20
  31. package/src/helpers/AdminPermissionChecker.ts +129 -22
  32. package/src/helpers/AuthenticatedStructures.ts +13 -10
  33. package/src/helpers/Context.ts +1 -1
  34. package/src/helpers/UitpasTokenRepository.ts +125 -35
  35. package/src/helpers/ViesHelper.ts +2 -1
  36. package/src/seeds/0000000002-clear-stamhoofd-email-templates.ts +13 -0
  37. package/src/seeds/0000000003-default-email-templates.ts +20 -0
  38. package/src/seeds/data/default-email-templates.sql +55 -0
  39. package/src/services/RegistrationService.ts +6 -4
  40. package/src/services/uitpas/UitpasService.test.ts +23 -0
  41. package/src/services/uitpas/UitpasService.ts +222 -0
  42. package/src/services/uitpas/checkPermissionsFor.ts +111 -0
  43. package/src/services/uitpas/checkUitpasNumbers.ts +180 -0
  44. package/src/services/uitpas/getSocialTariffForEvent.ts +90 -0
  45. package/src/services/uitpas/getSocialTariffForUitpasNumbers.ts +181 -0
  46. package/src/services/uitpas/searchUitpasOrganizers.ts +93 -0
  47. package/src/sql-filters/audit-logs.ts +26 -6
  48. package/src/sql-filters/balance-item-payments.ts +23 -8
  49. package/src/sql-filters/base-registration-filter-compilers.ts +74 -23
  50. package/src/sql-filters/documents.ts +46 -13
  51. package/src/sql-filters/event-notifications.ts +48 -12
  52. package/src/sql-filters/events.ts +62 -26
  53. package/src/sql-filters/groups.ts +12 -12
  54. package/src/sql-filters/members.ts +325 -137
  55. package/src/sql-filters/orders.ts +96 -48
  56. package/src/sql-filters/organization-registration-periods.ts +16 -4
  57. package/src/sql-filters/organizations.ts +105 -99
  58. package/src/sql-filters/payments.ts +97 -47
  59. package/src/sql-filters/receivable-balances.ts +56 -19
  60. package/src/sql-filters/registration-periods.ts +16 -4
  61. package/src/sql-filters/registrations.ts +2 -2
  62. package/src/sql-filters/shared/EmailRelationFilterCompilers.ts +14 -8
  63. package/src/sql-filters/tickets.ts +26 -6
  64. package/tests/e2e/charge-members.test.ts +1 -0
  65. package/src/helpers/UitpasNumberValidator.test.ts +0 -23
  66. package/src/helpers/UitpasNumberValidator.ts +0 -185
@@ -1,8 +1,7 @@
1
1
  import { SimpleError } from '@simonbackx/simple-errors';
2
2
  import { Member } from '@stamhoofd/models';
3
- import { SQL, SQLAge, SQLConcat, SQLFilterDefinitions, SQLScalar, SQLValueType, baseSQLFilterCompilers, createSQLColumnFilterCompiler, createSQLExpressionFilterCompiler, createSQLFilterNamespace, createSQLRelationFilterCompiler } from '@stamhoofd/sql';
3
+ import { baseSQLFilterCompilers, createColumnFilter, createExistsFilter, SQL, SQLAge, SQLCast, SQLConcat, SQLFilterDefinitions, SQLValueType, SQLScalar, createWildcardColumnFilter, SQLJsonExtract } from '@stamhoofd/sql';
4
4
  import { AccessRight } from '@stamhoofd/structures';
5
- import { Formatter } from '@stamhoofd/utility';
6
5
  import { Context } from '../helpers/Context';
7
6
  import { baseRegistrationFilterCompilers } from './base-registration-filter-compilers';
8
7
  import { organizationFilterCompilers } from './organizations';
@@ -14,42 +13,71 @@ const membersTable = SQL.table(Member.table);
14
13
  */
15
14
  export const memberFilterCompilers: SQLFilterDefinitions = {
16
15
  ...baseSQLFilterCompilers,
17
- 'id': createSQLColumnFilterCompiler(SQL.column(membersTable, 'id')),
18
- 'memberNumber': createSQLColumnFilterCompiler(SQL.column(membersTable, 'memberNumber')),
19
- 'firstName': createSQLColumnFilterCompiler(SQL.column(membersTable, 'firstName')),
20
- 'lastName': createSQLColumnFilterCompiler(SQL.column(membersTable, 'lastName')),
21
- 'name': createSQLExpressionFilterCompiler(
22
- new SQLConcat(
16
+ 'id': createColumnFilter({
17
+ expression: SQL.column(membersTable, 'id'),
18
+ type: SQLValueType.String,
19
+ nullable: false,
20
+ }),
21
+ 'memberNumber': createColumnFilter({
22
+ expression: SQL.column(membersTable, 'memberNumber'),
23
+ type: SQLValueType.Number,
24
+ nullable: true,
25
+ }),
26
+ 'firstName': createColumnFilter({
27
+ expression: SQL.column(membersTable, 'firstName'),
28
+ type: SQLValueType.String,
29
+ nullable: false,
30
+ }),
31
+ 'lastName': createColumnFilter({
32
+ expression: SQL.column(membersTable, 'lastName'),
33
+ type: SQLValueType.String,
34
+ nullable: false,
35
+ }),
36
+ 'name': createColumnFilter({
37
+ expression: new SQLConcat(
23
38
  SQL.column(membersTable, 'firstName'),
24
39
  new SQLScalar(' '),
25
40
  SQL.column(membersTable, 'lastName'),
26
41
  ),
27
- ),
28
- 'age': createSQLExpressionFilterCompiler(
29
- new SQLAge(SQL.column(membersTable, 'birthDay')),
30
- { nullable: true },
31
- ),
32
- 'gender': createSQLExpressionFilterCompiler(
33
- SQL.jsonValue(SQL.column(membersTable, 'details'), '$.value.gender'),
34
- { isJSONValue: true, type: SQLValueType.JSONString },
35
- ),
36
- 'birthDay': createSQLColumnFilterCompiler(SQL.column(membersTable, 'birthDay'), {
37
- normalizeValue: (d) => {
38
- if (typeof d === 'number') {
39
- const date = new Date(d);
40
- return Formatter.dateIso(date);
41
- }
42
- return d;
43
- },
42
+ type: SQLValueType.String,
43
+ nullable: false,
44
44
  }),
45
- 'organizationName': createSQLExpressionFilterCompiler(
46
- SQL.column('organizations', 'name'),
47
- ),
48
- 'details.requiresFinancialSupport': createSQLExpressionFilterCompiler(
49
- SQL.jsonValue(SQL.column(membersTable, 'details'), '$.value.requiresFinancialSupport.value'),
50
- { isJSONValue: true, type: SQLValueType.JSONBoolean, checkPermission: async () => {
45
+ 'age': createColumnFilter({
46
+ expression: new SQLAge(SQL.column(membersTable, 'birthDay')),
47
+ type: SQLValueType.Number,
48
+ nullable: true,
49
+ }),
50
+ 'gender': createColumnFilter({
51
+ expression: SQL.jsonValue(SQL.column(membersTable, 'details'), '$.value.gender'),
52
+ type: SQLValueType.JSONString,
53
+ nullable: false,
54
+ }),
55
+ 'birthDay': createColumnFilter({
56
+ // todo: check normalization of date
57
+ expression: SQL.column(membersTable, 'birthDay'),
58
+ type: SQLValueType.Datetime,
59
+ nullable: true,
60
+ }),
61
+ 'organizationName': createColumnFilter({
62
+ expression: SQL.column('organizations', 'name'),
63
+ type: SQLValueType.String,
64
+ nullable: false,
65
+ }),
66
+ 'details.requiresFinancialSupport': createColumnFilter({
67
+ expression: SQL.jsonValue(SQL.column(membersTable, 'details'), '$.value.requiresFinancialSupport.value'),
68
+ type: SQLValueType.JSONBoolean,
69
+ nullable: true,
70
+ checkPermission: async () => {
51
71
  const organization = Context.organization;
52
72
  if (!organization) {
73
+ if (!Context.auth.hasPlatformFullAccess()) {
74
+ throw new SimpleError({
75
+ code: 'permission_denied',
76
+ message: 'No permissions for financial support filter.',
77
+ human: $t(`64d658fa-0727-4924-9448-b243fe8e10a1`),
78
+ statusCode: 400,
79
+ });
80
+ }
53
81
  return;
54
82
  }
55
83
 
@@ -63,89 +91,113 @@ export const memberFilterCompilers: SQLFilterDefinitions = {
63
91
  statusCode: 400,
64
92
  });
65
93
  }
66
- } },
67
- ),
68
- 'email': createSQLExpressionFilterCompiler(
69
- SQL.jsonValue(SQL.column(membersTable, 'details'), '$.value.email'),
70
- { isJSONValue: true, type: SQLValueType.JSONString },
71
- ),
72
- 'parentEmail': createSQLExpressionFilterCompiler(
73
- SQL.jsonValue(SQL.column(membersTable, 'details'), '$.value.parents[*].email'),
74
- { isJSONValue: true, isJSONObject: true, type: SQLValueType.JSONString },
75
- ),
76
- 'details.parents[0]': createSQLFilterNamespace({
77
- name: createSQLExpressionFilterCompiler(
78
- new SQLConcat(
79
- SQL.jsonUnquotedValue(SQL.column(membersTable, 'details'), '$.value.parents[0].firstName'),
80
- new SQLScalar(' '),
81
- SQL.jsonUnquotedValue(SQL.column(membersTable, 'details'), '$.value.parents[0].lastName'),
82
- ),
83
- { isJSONValue: true, isJSONObject: false, type: SQLValueType.JSONString },
84
- ),
94
+ },
85
95
  }),
86
- 'details.parents[1]': createSQLFilterNamespace({
87
- name: createSQLExpressionFilterCompiler(
88
- new SQLConcat(
89
- SQL.jsonUnquotedValue(SQL.column(membersTable, 'details'), '$.value.parents[1].firstName'),
90
- new SQLScalar(' '),
91
- SQL.jsonUnquotedValue(SQL.column(membersTable, 'details'), '$.value.parents[1].lastName'),
92
- ),
93
- { isJSONValue: true, isJSONObject: false, type: SQLValueType.JSONString },
94
- ),
96
+ 'email': createColumnFilter({
97
+ expression: SQL.jsonValue(SQL.column(membersTable, 'details'), '$.value.email'),
98
+ type: SQLValueType.JSONString,
99
+ nullable: true,
95
100
  }),
96
- 'unverifiedEmail': createSQLExpressionFilterCompiler(
97
- SQL.jsonValue(SQL.column(membersTable, 'details'), '$.value.unverifiedEmails'),
98
- { isJSONValue: true, isJSONObject: true, type: SQLValueType.JSONString },
99
- ),
100
- 'phone': createSQLExpressionFilterCompiler(
101
- SQL.jsonValue(SQL.column(membersTable, 'details'), '$.value.phone'),
102
- { isJSONValue: true },
103
- ),
104
- 'details.address': createSQLFilterNamespace({
105
- city: createSQLExpressionFilterCompiler(
106
- SQL.jsonValue(SQL.column(membersTable, 'details'), '$.value.address.city'),
107
- { isJSONValue: true, type: SQLValueType.JSONString },
108
- ),
109
- postalCode: createSQLExpressionFilterCompiler(
110
- SQL.jsonValue(SQL.column(membersTable, 'details'), '$.value.address.postalCode'),
111
- { isJSONValue: true, type: SQLValueType.JSONString },
112
- ),
113
- street: createSQLExpressionFilterCompiler(
114
- SQL.jsonValue(SQL.column(membersTable, 'details'), '$.value.address.street'),
115
- { isJSONValue: true, type: SQLValueType.JSONString },
116
- ),
117
- number: createSQLExpressionFilterCompiler(
118
- SQL.jsonValue(SQL.column(membersTable, 'details'), '$.value.address.number'),
119
- { isJSONValue: true, type: SQLValueType.JSONString },
120
- ),
101
+ 'parentEmail': createColumnFilter({
102
+ expression: SQL.jsonValue(SQL.column(membersTable, 'details'), '$.value.parents[*].email'),
103
+ type: SQLValueType.JSONArray,
104
+ nullable: true,
121
105
  }),
122
- 'details.parents[*].address': createSQLFilterNamespace({
123
- city: createSQLExpressionFilterCompiler(
124
- SQL.jsonValue(SQL.column(membersTable, 'details'), '$.value.parents[*].address.city'),
125
- { isJSONValue: true, isJSONObject: true },
126
- ),
127
- postalCode: createSQLExpressionFilterCompiler(
128
- SQL.jsonValue(SQL.column(membersTable, 'details'), '$.value.parents[*].address.postalCode'),
129
- { isJSONValue: true, isJSONObject: true },
130
- ),
131
- street: createSQLExpressionFilterCompiler(
132
- SQL.jsonValue(SQL.column(membersTable, 'details'), '$.value.parents[*].address.street'),
133
- { isJSONValue: true, isJSONObject: true },
134
- ),
135
- number: createSQLExpressionFilterCompiler(
136
- SQL.jsonValue(SQL.column(membersTable, 'details'), '$.value.parents[*].address.number'),
137
- { isJSONValue: true, isJSONObject: true },
138
- ),
106
+ 'details.parents[0]': {
107
+ ...baseSQLFilterCompilers,
108
+ name: createColumnFilter({
109
+ expression: new SQLCast(
110
+ new SQLConcat(
111
+ SQL.jsonUnquotedValue(SQL.column(membersTable, 'details'), '$.value.parents[0].firstName'),
112
+ new SQLScalar(' '),
113
+ SQL.jsonUnquotedValue(SQL.column(membersTable, 'details'), '$.value.parents[0].lastName'),
114
+ ),
115
+ 'CHAR'),
116
+ type: SQLValueType.String,
117
+ nullable: true,
118
+ }),
119
+ },
120
+ 'details.parents[1]': {
121
+ ...baseSQLFilterCompilers,
122
+ name: createColumnFilter({
123
+ expression: new SQLCast(
124
+ new SQLConcat(
125
+ SQL.jsonUnquotedValue(SQL.column(membersTable, 'details'), '$.value.parents[1].firstName'),
126
+ new SQLScalar(' '),
127
+ SQL.jsonUnquotedValue(SQL.column(membersTable, 'details'), '$.value.parents[1].lastName'),
128
+ ),
129
+ 'CHAR'),
130
+ type: SQLValueType.String,
131
+ nullable: true,
132
+ }),
133
+ },
134
+ 'unverifiedEmail': createColumnFilter({
135
+ expression: SQL.jsonValue(SQL.column(membersTable, 'details'), '$.value.unverifiedEmails'),
136
+ type: SQLValueType.JSONArray,
137
+ nullable: true,
139
138
  }),
140
- 'parentPhone': createSQLExpressionFilterCompiler(
141
- SQL.jsonValue(SQL.column(membersTable, 'details'), '$.value.parents[*].phone'),
142
- { isJSONValue: true, isJSONObject: true },
143
- ),
144
- 'unverifiedPhone': createSQLExpressionFilterCompiler(
145
- SQL.jsonValue(SQL.column(membersTable, 'details'), '$.value.unverifiedPhones'),
146
- { isJSONValue: true, isJSONObject: true },
147
- ),
148
- 'registrations': createSQLRelationFilterCompiler(
139
+ 'phone': createColumnFilter({
140
+ expression: SQL.jsonValue(SQL.column(membersTable, 'details'), '$.value.phone'),
141
+ type: SQLValueType.JSONString,
142
+ nullable: true,
143
+ }),
144
+ 'details.address': {
145
+ ...baseSQLFilterCompilers,
146
+ city: createColumnFilter({
147
+ expression: SQL.jsonValue(SQL.column(membersTable, 'details'), '$.value.address.city'),
148
+ type: SQLValueType.JSONString,
149
+ nullable: true,
150
+ }),
151
+ postalCode: createColumnFilter({
152
+ expression: SQL.jsonValue(SQL.column(membersTable, 'details'), '$.value.address.postalCode'),
153
+ type: SQLValueType.JSONString,
154
+ nullable: true,
155
+ }),
156
+ street: createColumnFilter({
157
+ expression: SQL.jsonValue(SQL.column(membersTable, 'details'), '$.value.address.street'),
158
+ type: SQLValueType.JSONString,
159
+ nullable: true,
160
+ }),
161
+ number: createColumnFilter({
162
+ expression: SQL.jsonValue(SQL.column(membersTable, 'details'), '$.value.address.number'),
163
+ type: SQLValueType.JSONString,
164
+ nullable: true,
165
+ }),
166
+ },
167
+ 'details.parents[*].address': {
168
+ ...baseSQLFilterCompilers,
169
+ city: createColumnFilter({
170
+ expression: SQL.jsonValue(SQL.column(membersTable, 'details'), '$.value.parents[*].address.city'),
171
+ type: SQLValueType.JSONArray,
172
+ nullable: true,
173
+ }),
174
+ postalCode: createColumnFilter({
175
+ expression: SQL.jsonValue(SQL.column(membersTable, 'details'), '$.value.parents[*].address.postalCode'),
176
+ type: SQLValueType.JSONArray,
177
+ nullable: true,
178
+ }),
179
+ street: createColumnFilter({
180
+ expression: SQL.jsonValue(SQL.column(membersTable, 'details'), '$.value.parents[*].address.street'),
181
+ type: SQLValueType.JSONArray,
182
+ nullable: true,
183
+ }),
184
+ number: createColumnFilter({
185
+ expression: SQL.jsonValue(SQL.column(membersTable, 'details'), '$.value.parents[*].address.number'),
186
+ type: SQLValueType.JSONArray,
187
+ nullable: true,
188
+ }),
189
+ },
190
+ 'parentPhone': createColumnFilter({
191
+ expression: SQL.jsonValue(SQL.column(membersTable, 'details'), '$.value.parents[*].phone'),
192
+ type: SQLValueType.JSONArray,
193
+ nullable: true,
194
+ }),
195
+ 'unverifiedPhone': createColumnFilter({
196
+ expression: SQL.jsonValue(SQL.column(membersTable, 'details'), '$.value.unverifiedPhones'),
197
+ type: SQLValueType.JSONArray,
198
+ nullable: true,
199
+ }),
200
+ 'registrations': createExistsFilter(
149
201
  SQL.select()
150
202
  .from(
151
203
  SQL.table('registrations'),
@@ -173,10 +225,14 @@ export const memberFilterCompilers: SQLFilterDefinitions = {
173
225
  {
174
226
  ...baseRegistrationFilterCompilers,
175
227
  // Override the registration periodId - can be outdated - and always use the group periodId
176
- periodId: createSQLColumnFilterCompiler(SQL.column('groups', 'periodId')),
228
+ periodId: createColumnFilter({
229
+ expression: SQL.column('groups', 'periodId'),
230
+ type: SQLValueType.String,
231
+ nullable: false,
232
+ }),
177
233
  },
178
234
  ),
179
- 'responsibilities': createSQLRelationFilterCompiler(
235
+ 'responsibilities': createExistsFilter(
180
236
  SQL.select()
181
237
  .from(
182
238
  SQL.table('member_responsibility_records'),
@@ -204,20 +260,48 @@ export const memberFilterCompilers: SQLFilterDefinitions = {
204
260
  {
205
261
  ...baseSQLFilterCompilers,
206
262
  // Alias for responsibilityId
207
- id: createSQLColumnFilterCompiler(SQL.column('member_responsibility_records', 'responsibilityId')),
208
- responsibilityId: createSQLColumnFilterCompiler(SQL.column('member_responsibility_records', 'responsibilityId')),
209
- organizationId: createSQLColumnFilterCompiler(SQL.column('member_responsibility_records', 'organizationId')),
210
- startDate: createSQLColumnFilterCompiler(SQL.column('member_responsibility_records', 'startDate')),
211
- endDate: createSQLColumnFilterCompiler(SQL.column('member_responsibility_records', 'endDate')),
212
- group: createSQLFilterNamespace({
213
- ...baseSQLFilterCompilers,
214
- id: createSQLColumnFilterCompiler(SQL.column('groups', 'id')),
215
- defaultAgeGroupId: createSQLColumnFilterCompiler(SQL.column('groups', 'defaultAgeGroupId')),
263
+ id: createColumnFilter({
264
+ expression: SQL.column('member_responsibility_records', 'responsibilityId'),
265
+ type: SQLValueType.String,
266
+ nullable: false,
267
+ }),
268
+ responsibilityId: createColumnFilter({
269
+ expression: SQL.column('member_responsibility_records', 'responsibilityId'),
270
+ type: SQLValueType.String,
271
+ nullable: false,
272
+ }),
273
+ organizationId: createColumnFilter({
274
+ expression: SQL.column('member_responsibility_records', 'organizationId'),
275
+ type: SQLValueType.String,
276
+ nullable: false,
277
+ }),
278
+ startDate: createColumnFilter({
279
+ expression: SQL.column('member_responsibility_records', 'startDate'),
280
+ type: SQLValueType.Datetime,
281
+ nullable: false,
216
282
  }),
217
- organization: createSQLFilterNamespace(organizationFilterCompilers),
283
+ endDate: createColumnFilter({
284
+ expression: SQL.column('member_responsibility_records', 'endDate'),
285
+ type: SQLValueType.Datetime,
286
+ nullable: true,
287
+ }),
288
+ group: {
289
+ ...baseSQLFilterCompilers,
290
+ id: createColumnFilter({
291
+ expression: SQL.column('groups', 'id'),
292
+ type: SQLValueType.String,
293
+ nullable: false,
294
+ }),
295
+ defaultAgeGroupId: createColumnFilter({
296
+ expression: SQL.column('groups', 'defaultAgeGroupId'),
297
+ type: SQLValueType.String,
298
+ nullable: true,
299
+ }),
300
+ },
301
+ organization: organizationFilterCompilers,
218
302
  },
219
303
  ),
220
- 'platformMemberships': createSQLRelationFilterCompiler(
304
+ 'platformMemberships': createExistsFilter(
221
305
  SQL.select()
222
306
  .from(
223
307
  SQL.table('member_platform_memberships'),
@@ -232,22 +316,74 @@ export const memberFilterCompilers: SQLFilterDefinitions = {
232
316
  ),
233
317
  {
234
318
  ...baseSQLFilterCompilers,
235
- id: createSQLColumnFilterCompiler(SQL.column('member_platform_memberships', 'id')),
236
- membershipTypeId: createSQLColumnFilterCompiler(SQL.column('member_platform_memberships', 'membershipTypeId')),
237
- organizationId: createSQLColumnFilterCompiler(SQL.column('member_platform_memberships', 'organizationId')),
238
- periodId: createSQLColumnFilterCompiler(SQL.column('member_platform_memberships', 'periodId')),
239
- price: createSQLColumnFilterCompiler(SQL.column('member_platform_memberships', 'price')),
240
- priceWithoutDiscount: createSQLColumnFilterCompiler(SQL.column('member_platform_memberships', 'priceWithoutDiscount')),
241
- startDate: createSQLColumnFilterCompiler(SQL.column('member_platform_memberships', 'startDate')),
242
- endDate: createSQLColumnFilterCompiler(SQL.column('member_platform_memberships', 'endDate')),
243
- expireDate: createSQLColumnFilterCompiler(SQL.column('member_platform_memberships', 'expireDate')),
244
- trialUntil: createSQLColumnFilterCompiler(SQL.column('member_platform_memberships', 'trialUntil')),
245
- locked: createSQLColumnFilterCompiler(SQL.column('member_platform_memberships', 'locked')),
246
- balanceItemId: createSQLColumnFilterCompiler(SQL.column('member_platform_memberships', 'balanceItemId')),
247
- generated: createSQLColumnFilterCompiler(SQL.column('member_platform_memberships', 'generated')),
319
+ id: createColumnFilter({
320
+ expression: SQL.column('member_platform_memberships', 'id'),
321
+ type: SQLValueType.String,
322
+ nullable: false,
323
+ }),
324
+ membershipTypeId: createColumnFilter({
325
+ expression: SQL.column('member_platform_memberships', 'membershipTypeId'),
326
+ type: SQLValueType.String,
327
+ nullable: false,
328
+ }),
329
+ organizationId: createColumnFilter({
330
+ expression: SQL.column('member_platform_memberships', 'organizationId'),
331
+ type: SQLValueType.String,
332
+ nullable: false,
333
+ }),
334
+ periodId: createColumnFilter({
335
+ expression: SQL.column('member_platform_memberships', 'periodId'),
336
+ type: SQLValueType.String,
337
+ nullable: false,
338
+ }),
339
+ price: createColumnFilter({
340
+ expression: SQL.column('member_platform_memberships', 'price'),
341
+ type: SQLValueType.Number,
342
+ nullable: false,
343
+ }),
344
+ priceWithoutDiscount: createColumnFilter({
345
+ expression: SQL.column('member_platform_memberships', 'priceWithoutDiscount'),
346
+ type: SQLValueType.Number,
347
+ nullable: false,
348
+ }),
349
+ startDate: createColumnFilter({
350
+ expression: SQL.column('member_platform_memberships', 'startDate'),
351
+ type: SQLValueType.Datetime,
352
+ nullable: false,
353
+ }),
354
+ endDate: createColumnFilter({
355
+ expression: SQL.column('member_platform_memberships', 'endDate'),
356
+ type: SQLValueType.Datetime,
357
+ nullable: false,
358
+ }),
359
+ expireDate: createColumnFilter({
360
+ expression: SQL.column('member_platform_memberships', 'expireDate'),
361
+ type: SQLValueType.Datetime,
362
+ nullable: true,
363
+ }),
364
+ trialUntil: createColumnFilter({
365
+ expression: SQL.column('member_platform_memberships', 'trialUntil'),
366
+ type: SQLValueType.Datetime,
367
+ nullable: true,
368
+ }),
369
+ locked: createColumnFilter({
370
+ expression: SQL.column('member_platform_memberships', 'locked'),
371
+ type: SQLValueType.Boolean,
372
+ nullable: false,
373
+ }),
374
+ balanceItemId: createColumnFilter({
375
+ expression: SQL.column('member_platform_memberships', 'balanceItemId'),
376
+ type: SQLValueType.String,
377
+ nullable: true,
378
+ }),
379
+ generated: createColumnFilter({
380
+ expression: SQL.column('member_platform_memberships', 'generated'),
381
+ type: SQLValueType.Boolean,
382
+ nullable: false,
383
+ }),
248
384
  },
249
385
  ),
250
- 'organizations': createSQLRelationFilterCompiler(
386
+ 'organizations': createExistsFilter(
251
387
  SQL.select()
252
388
  .from(
253
389
  SQL.table('registrations'),
@@ -277,4 +413,56 @@ export const memberFilterCompilers: SQLFilterDefinitions = {
277
413
  ),
278
414
  organizationFilterCompilers,
279
415
  ),
416
+ 'details': {
417
+ ...baseSQLFilterCompilers,
418
+ recordAnswers: createWildcardColumnFilter(
419
+ (key: string) => ({
420
+ expression: SQL.jsonValue(SQL.column('details'), `$.value.recordAnswers.${SQLJsonExtract.escapePathComponent(key)}`, true),
421
+ type: SQLValueType.JSONObject,
422
+ nullable: true,
423
+ }),
424
+ (key: string) => ({
425
+ ...baseSQLFilterCompilers,
426
+ selected: createColumnFilter({
427
+ expression: SQL.jsonValue(SQL.column('details'), `$.value.recordAnswers.${SQLJsonExtract.escapePathComponent(key)}.selected`, true),
428
+ type: SQLValueType.JSONBoolean,
429
+ nullable: true,
430
+ }),
431
+ selectedChoice: {
432
+ ...baseSQLFilterCompilers,
433
+ id: createColumnFilter({
434
+ expression: SQL.jsonValue(SQL.column('details'), `$.value.recordAnswers.${SQLJsonExtract.escapePathComponent(key)}.selectedChoice.id`, true),
435
+ type: SQLValueType.JSONString,
436
+ nullable: true,
437
+ }),
438
+ },
439
+ selectedChoices: {
440
+ ...baseSQLFilterCompilers,
441
+ id: createColumnFilter({
442
+ expression: SQL.jsonValue(SQL.column('details'), `$.value.recordAnswers.${SQLJsonExtract.escapePathComponent(key)}.selectedChoices[*].id`, true),
443
+ type: SQLValueType.JSONArray,
444
+ nullable: true,
445
+ }),
446
+ },
447
+ value: createColumnFilter({
448
+ expression: SQL.jsonValue(SQL.column('details'), `$.value.recordAnswers.${SQLJsonExtract.escapePathComponent(key)}.value`, true),
449
+ type: SQLValueType.JSONString,
450
+ nullable: true,
451
+ }),
452
+ }),
453
+ {
454
+ checkPermission: async (key: string) => {
455
+ const result = await Context.auth.canFilterMembersOnRecordId(key);
456
+ if (!result.canAccess) {
457
+ throw new SimpleError({
458
+ code: 'permission_denied',
459
+ message: 'No permissions for financial support filter (organization scope).',
460
+ human: result.record ? $t(`Je hebt niet voldoende toegangsrechten om te filteren op {recordName}`, { recordName: result.record.name }) : $t(`Je hebt niet voldoende toegangsrechten om te filteren op dit gegevensveld`),
461
+ statusCode: 400,
462
+ });
463
+ }
464
+ },
465
+ },
466
+ ),
467
+ },
280
468
  };