@stamhoofd/backend 2.107.3 → 2.109.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/index.ts +2 -2
- package/package.json +20 -20
- package/src/crons/disable-auto-update-documents.test.ts +164 -0
- package/src/crons/disable-auto-update-documents.ts +82 -0
- package/src/endpoints/admin/members/ChargeMembersEndpoint.ts +5 -5
- package/src/endpoints/admin/registrations/ChargeRegistrationsEndpoint.ts +87 -0
- package/src/endpoints/global/members/GetMembersCountEndpoint.ts +2 -2
- package/src/endpoints/global/members/GetMembersEndpoint.ts +5 -5
- package/src/endpoints/global/registration/GetRegistrationsCountEndpoint.ts +2 -2
- package/src/endpoints/global/registration/GetRegistrationsEndpoint.ts +14 -11
- package/src/endpoints/global/registration/RegisterMembersEndpoint.ts +9 -8
- package/src/endpoints/organization/dashboard/documents/GetDocumentTemplatesCountEndpoint.ts +48 -0
- package/src/endpoints/organization/dashboard/documents/GetDocumentTemplatesEndpoint.ts +95 -19
- package/src/endpoints/organization/dashboard/documents/PatchDocumentTemplatesEndpoint.test.ts +282 -0
- package/src/endpoints/organization/dashboard/documents/{PatchDocumentTemplateEndpoint.ts → PatchDocumentTemplatesEndpoint.ts} +56 -3
- package/src/excel-loaders/members.ts +62 -8
- package/src/excel-loaders/registrations.ts +180 -9
- package/src/helpers/LimitedFilteredRequestHelper.ts +24 -0
- package/src/helpers/MemberCharger.ts +16 -4
- package/src/helpers/SQLTranslatedString.ts +14 -0
- package/src/helpers/TagHelper.test.ts +9 -9
- package/src/helpers/fetchToAsyncIterator.ts +1 -1
- package/src/helpers/outstandingBalanceJoin.ts +49 -0
- package/src/seeds/1765896674-document-update-year.test.ts +179 -0
- package/src/seeds/1765896674-document-update-year.ts +75 -0
- package/src/seeds/1766150402-document-published-at.test.ts +46 -0
- package/src/seeds/1766150402-document-published-at.ts +20 -0
- package/src/services/PaymentService.ts +14 -32
- package/src/sql-filters/base-registration-filter-compilers.ts +51 -4
- package/src/sql-filters/document-templates.ts +45 -0
- package/src/sql-filters/documents.ts +1 -1
- package/src/sql-filters/events.ts +6 -6
- package/src/sql-filters/groups.ts +7 -6
- package/src/sql-filters/members.ts +31 -26
- package/src/sql-filters/orders.ts +16 -16
- package/src/sql-filters/organizations.ts +11 -11
- package/src/sql-filters/payments.ts +10 -10
- package/src/sql-filters/registrations.ts +14 -6
- package/src/sql-sorters/document-templates.ts +79 -0
- package/src/sql-sorters/documents.ts +1 -1
- package/src/sql-sorters/members.ts +22 -0
- package/src/sql-sorters/orders.ts +5 -5
- package/src/sql-sorters/organizations.ts +3 -3
- package/src/sql-sorters/registrations.ts +186 -15
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { DocumentTemplate, DocumentTemplateFactory } from '@stamhoofd/models';
|
|
2
|
+
import { SQL } from '@stamhoofd/sql';
|
|
3
|
+
import { DocumentStatus } from '@stamhoofd/structures';
|
|
4
|
+
import { initPublishedAtForPublishedDocuments } from './1766150402-document-published-at.js';
|
|
5
|
+
|
|
6
|
+
describe('migration.document-published-at', () => {
|
|
7
|
+
it('should init published at for published documents', async () => {
|
|
8
|
+
// arrange
|
|
9
|
+
// published documents
|
|
10
|
+
const document1 = await createDocument(DocumentStatus.Published, new Date(2022, 0, 1));
|
|
11
|
+
const document2 = await createDocument(DocumentStatus.Published, new Date(2023, 5, 17));
|
|
12
|
+
const document3 = await createDocument(DocumentStatus.Published, new Date(2025, 3, 9));
|
|
13
|
+
|
|
14
|
+
// draft documents
|
|
15
|
+
const document4 = await createDocument(DocumentStatus.Draft, new Date(2022, 0, 1));
|
|
16
|
+
const document5 = await createDocument(DocumentStatus.Draft, new Date(2023, 5, 17));
|
|
17
|
+
const document6 = await createDocument(DocumentStatus.Draft, new Date(2025, 3, 9));
|
|
18
|
+
|
|
19
|
+
// reset published at (save does not update published at automatically)
|
|
20
|
+
await SQL.update(DocumentTemplate.table).set('publishedAt', null).where('id', [document1.id, document2.id, document3.id, document4.id, document5.id, document6.id]).update();
|
|
21
|
+
|
|
22
|
+
// act
|
|
23
|
+
await initPublishedAtForPublishedDocuments();
|
|
24
|
+
|
|
25
|
+
// assert
|
|
26
|
+
const updatedDocument1 = await DocumentTemplate.getByID(document1.id);
|
|
27
|
+
const updatedDocument2 = await DocumentTemplate.getByID(document2.id);
|
|
28
|
+
const updatedDocument3 = await DocumentTemplate.getByID(document3.id);
|
|
29
|
+
|
|
30
|
+
const updatedDocument4 = await DocumentTemplate.getByID(document4.id);
|
|
31
|
+
const updatedDocument5 = await DocumentTemplate.getByID(document5.id);
|
|
32
|
+
const updatedDocument6 = await DocumentTemplate.getByID(document6.id);
|
|
33
|
+
|
|
34
|
+
expect(updatedDocument1?.publishedAt?.getTime()).toEqual(document1.createdAt.getTime());
|
|
35
|
+
expect(updatedDocument2?.publishedAt?.getTime()).toEqual(document2.createdAt.getTime());
|
|
36
|
+
expect(updatedDocument3?.publishedAt?.getTime()).toEqual(document3.createdAt.getTime());
|
|
37
|
+
|
|
38
|
+
expect(updatedDocument4?.publishedAt).toBeNull();
|
|
39
|
+
expect(updatedDocument5?.publishedAt).toBeNull();
|
|
40
|
+
expect(updatedDocument6?.publishedAt).toBeNull();
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
async function createDocument(status: DocumentStatus, createdAt: Date) {
|
|
45
|
+
return await new DocumentTemplateFactory({ groups: [], status, createdAt }).create();
|
|
46
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Migration } from '@simonbackx/simple-database';
|
|
2
|
+
import { DocumentTemplate } from '@stamhoofd/models';
|
|
3
|
+
import { SQL } from '@stamhoofd/sql';
|
|
4
|
+
import { DocumentStatus } from '@stamhoofd/structures';
|
|
5
|
+
|
|
6
|
+
export async function initPublishedAtForPublishedDocuments() {
|
|
7
|
+
await SQL.update(DocumentTemplate.table)
|
|
8
|
+
.set('publishedAt', SQL.column('createdAt'))
|
|
9
|
+
.where('publishedAt', null)
|
|
10
|
+
.where('status', DocumentStatus.Published)
|
|
11
|
+
.update();
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default new Migration(async () => {
|
|
15
|
+
process.stdout.write('\n');
|
|
16
|
+
console.log('Start init published at for published documents.');
|
|
17
|
+
await initPublishedAtForPublishedDocuments();
|
|
18
|
+
|
|
19
|
+
return Promise.resolve();
|
|
20
|
+
});
|
|
@@ -2,11 +2,11 @@ import createMollieClient, { PaymentStatus as MolliePaymentStatus } from '@molli
|
|
|
2
2
|
import { BalanceItem, BalanceItemPayment, MolliePayment, MollieToken, Organization, PayconiqPayment, Payment } from '@stamhoofd/models';
|
|
3
3
|
import { QueueHandler } from '@stamhoofd/queues';
|
|
4
4
|
import { AuditLogSource, BalanceItemRelation, BalanceItemStatus, BalanceItemType, PaymentMethod, PaymentProvider, PaymentStatus } from '@stamhoofd/structures';
|
|
5
|
-
import { BuckarooHelper } from '../helpers/BuckarooHelper';
|
|
6
|
-
import { StripeHelper } from '../helpers/StripeHelper';
|
|
7
|
-
import { AuditLogService } from './AuditLogService';
|
|
8
|
-
import { BalanceItemPaymentService } from './BalanceItemPaymentService';
|
|
9
|
-
import { BalanceItemService } from './BalanceItemService';
|
|
5
|
+
import { BuckarooHelper } from '../helpers/BuckarooHelper.js';
|
|
6
|
+
import { StripeHelper } from '../helpers/StripeHelper.js';
|
|
7
|
+
import { AuditLogService } from './AuditLogService.js';
|
|
8
|
+
import { BalanceItemPaymentService } from './BalanceItemPaymentService.js';
|
|
9
|
+
import { BalanceItemService } from './BalanceItemService.js';
|
|
10
10
|
|
|
11
11
|
export const PaymentService = {
|
|
12
12
|
async handlePaymentStatusUpdate(payment: Payment, organization: Organization, status: PaymentStatus) {
|
|
@@ -336,46 +336,28 @@ export const PaymentService = {
|
|
|
336
336
|
* Say the total amount to pay is 15,238 because (e.g. because of VAT). In that case,
|
|
337
337
|
* we'll need to round the payment to 1 cent. That can cause issues in the financial statements because
|
|
338
338
|
* the total amount of balances does not match the total amount received/paid.
|
|
339
|
-
*
|
|
339
|
+
*
|
|
340
340
|
* To fix that, we create an extra balance item with the difference. So the rounding always matches.
|
|
341
|
+
*
|
|
342
|
+
* TODO: update this method to generate a virtual invoice and use the price of the invoice instead of the rounded payment price, so we don't get differences in calculation
|
|
341
343
|
*/
|
|
342
344
|
async round(payment: Payment) {
|
|
343
|
-
if (!payment.organizationId) {
|
|
344
|
-
throw new Error('Cannot round payments without organizationId')
|
|
345
|
-
}
|
|
346
|
-
|
|
347
345
|
const amount = payment.price;
|
|
348
|
-
const rounded = Payment.roundPrice(payment.price)
|
|
346
|
+
const rounded = Payment.roundPrice(payment.price);
|
|
349
347
|
const difference = rounded - amount;
|
|
350
348
|
|
|
351
349
|
if (difference === 0) {
|
|
352
350
|
return;
|
|
353
351
|
}
|
|
354
352
|
|
|
355
|
-
if (difference > 100) {
|
|
356
|
-
throw new Error('Unexpected rounding difference.
|
|
353
|
+
if (difference > 100 || difference < -100) {
|
|
354
|
+
throw new Error('Unexpected rounding difference of ' + difference + ' for payment ' + payment.id);
|
|
357
355
|
}
|
|
358
356
|
|
|
359
|
-
|
|
360
|
-
balanceItem.type = BalanceItemType.Rounding;
|
|
361
|
-
balanceItem.userId = payment.payingUserId;
|
|
362
|
-
balanceItem.payingOrganizationId = payment.payingOrganizationId
|
|
363
|
-
balanceItem.unitPrice = difference;
|
|
364
|
-
balanceItem.pricePaid = 0;
|
|
365
|
-
balanceItem.organizationId = payment.organizationId;
|
|
366
|
-
balanceItem.status = BalanceItemStatus.Hidden;
|
|
367
|
-
await balanceItem.save();
|
|
368
|
-
|
|
369
|
-
// Create balance item payment
|
|
370
|
-
const balanceItemPayment = new BalanceItemPayment();
|
|
371
|
-
balanceItemPayment.organizationId = payment.organizationId;
|
|
372
|
-
balanceItemPayment.balanceItemId = balanceItem.id;
|
|
373
|
-
balanceItemPayment.price = difference;
|
|
374
|
-
balanceItemPayment.paymentId = payment.id;
|
|
375
|
-
await balanceItemPayment.save();
|
|
357
|
+
// payment.roundingAmount = difference;
|
|
376
358
|
|
|
377
359
|
// Change payment total price
|
|
378
|
-
payment.price += difference
|
|
360
|
+
payment.price += difference;
|
|
379
361
|
await payment.save();
|
|
380
|
-
}
|
|
362
|
+
},
|
|
381
363
|
};
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { SimpleError } from '@simonbackx/simple-errors';
|
|
2
|
-
import { baseSQLFilterCompilers, createColumnFilter, createExistsFilter, SQL, SQLFilterDefinitions, SQLValueType } from '@stamhoofd/sql';
|
|
2
|
+
import { baseSQLFilterCompilers, createColumnFilter, createExistsFilter, createJoinedRelationFilter, SQL, SQLFilterDefinitions, SQLIfNull, SQLValueType } from '@stamhoofd/sql';
|
|
3
3
|
import { FilterWrapperMarker, PermissionLevel, StamhoofdFilter, unwrapFilter } from '@stamhoofd/structures';
|
|
4
|
-
import { Context } from '../helpers/Context';
|
|
5
|
-
import {
|
|
4
|
+
import { Context } from '../helpers/Context.js';
|
|
5
|
+
import { memberCachedBalanceForOrganizationJoin, registrationCachedBalanceJoin } from '../helpers/outstandingBalanceJoin.js';
|
|
6
|
+
import { SQLTranslatedString } from '../helpers/SQLTranslatedString.js';
|
|
7
|
+
import { organizationFilterCompilers } from './organizations.js';
|
|
6
8
|
|
|
7
9
|
async function checkGroupIdFilterAccess(filter: StamhoofdFilter, permissionLevel: PermissionLevel) {
|
|
8
10
|
const groupIds = typeof filter === 'string'
|
|
@@ -77,6 +79,11 @@ export const baseRegistrationFilterCompilers: SQLFilterDefinitions = {
|
|
|
77
79
|
type: SQLValueType.Number,
|
|
78
80
|
nullable: false,
|
|
79
81
|
}),
|
|
82
|
+
groupPrice: createColumnFilter({
|
|
83
|
+
expression: new SQLTranslatedString(SQL.column('groupPrice'), '$.value.name'),
|
|
84
|
+
type: SQLValueType.String,
|
|
85
|
+
nullable: true,
|
|
86
|
+
}),
|
|
80
87
|
canRegister: createColumnFilter({
|
|
81
88
|
expression: SQL.column('canRegister'),
|
|
82
89
|
type: SQLValueType.Boolean,
|
|
@@ -110,6 +117,21 @@ export const baseRegistrationFilterCompilers: SQLFilterDefinitions = {
|
|
|
110
117
|
type: SQLValueType.Datetime,
|
|
111
118
|
nullable: true,
|
|
112
119
|
}),
|
|
120
|
+
trialUntil: createColumnFilter({
|
|
121
|
+
expression: SQL.column('registrations', 'trialUntil'),
|
|
122
|
+
type: SQLValueType.Datetime,
|
|
123
|
+
nullable: true,
|
|
124
|
+
}),
|
|
125
|
+
startDate: createColumnFilter({
|
|
126
|
+
expression: SQL.column('registrations', 'startDate'),
|
|
127
|
+
type: SQLValueType.Datetime,
|
|
128
|
+
nullable: true,
|
|
129
|
+
}),
|
|
130
|
+
endDate: createColumnFilter({
|
|
131
|
+
expression: SQL.column('registrations', 'endDate'),
|
|
132
|
+
type: SQLValueType.Datetime,
|
|
133
|
+
nullable: true,
|
|
134
|
+
}),
|
|
113
135
|
group: {
|
|
114
136
|
...baseSQLFilterCompilers,
|
|
115
137
|
id: createColumnFilter({
|
|
@@ -126,7 +148,7 @@ export const baseRegistrationFilterCompilers: SQLFilterDefinitions = {
|
|
|
126
148
|
nullable: false,
|
|
127
149
|
}),
|
|
128
150
|
name: createColumnFilter({
|
|
129
|
-
expression: SQL.
|
|
151
|
+
expression: SQL.jsonExtract(SQL.column('groups', 'settings'), '$.value.name'),
|
|
130
152
|
type: SQLValueType.JSONString,
|
|
131
153
|
nullable: false,
|
|
132
154
|
}),
|
|
@@ -150,4 +172,29 @@ export const baseRegistrationFilterCompilers: SQLFilterDefinitions = {
|
|
|
150
172
|
),
|
|
151
173
|
organizationFilterCompilers,
|
|
152
174
|
),
|
|
175
|
+
memberCachedBalance: createJoinedRelationFilter(
|
|
176
|
+
memberCachedBalanceForOrganizationJoin,
|
|
177
|
+
{
|
|
178
|
+
amountOpen: createColumnFilter({
|
|
179
|
+
expression: new SQLIfNull(SQL.column('memberCachedBalance', 'amountOpen'), 0),
|
|
180
|
+
type: SQLValueType.Number,
|
|
181
|
+
nullable: false,
|
|
182
|
+
}),
|
|
183
|
+
},
|
|
184
|
+
),
|
|
185
|
+
registrationCachedBalance: createJoinedRelationFilter(
|
|
186
|
+
registrationCachedBalanceJoin,
|
|
187
|
+
{
|
|
188
|
+
toPay: createColumnFilter({
|
|
189
|
+
expression: new SQLIfNull(SQL.column('registrationCachedBalance', 'toPay'), 0),
|
|
190
|
+
type: SQLValueType.Number,
|
|
191
|
+
nullable: false,
|
|
192
|
+
}),
|
|
193
|
+
price: createColumnFilter({
|
|
194
|
+
expression: new SQLIfNull(SQL.column('registrationCachedBalance', 'price'), 0),
|
|
195
|
+
type: SQLValueType.Number,
|
|
196
|
+
nullable: false,
|
|
197
|
+
}),
|
|
198
|
+
},
|
|
199
|
+
),
|
|
153
200
|
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { baseSQLFilterCompilers, createColumnFilter, SQL, SQLFilterDefinitions, SQLValueType } from '@stamhoofd/sql';
|
|
2
|
+
|
|
3
|
+
export const documentTemplateFilterCompilers: SQLFilterDefinitions = {
|
|
4
|
+
...baseSQLFilterCompilers,
|
|
5
|
+
id: createColumnFilter({
|
|
6
|
+
expression: SQL.column('id'),
|
|
7
|
+
type: SQLValueType.String,
|
|
8
|
+
nullable: false,
|
|
9
|
+
}),
|
|
10
|
+
name: createColumnFilter({
|
|
11
|
+
expression: SQL.jsonExtract(SQL.column('settings'), '$.value.name'),
|
|
12
|
+
type: SQLValueType.JSONString,
|
|
13
|
+
nullable: false,
|
|
14
|
+
}),
|
|
15
|
+
year: createColumnFilter({
|
|
16
|
+
expression: SQL.column('year'),
|
|
17
|
+
type: SQLValueType.Number,
|
|
18
|
+
nullable: false,
|
|
19
|
+
}),
|
|
20
|
+
organizationId: createColumnFilter({
|
|
21
|
+
expression: SQL.column('organizationId'),
|
|
22
|
+
type: SQLValueType.String,
|
|
23
|
+
nullable: false,
|
|
24
|
+
}),
|
|
25
|
+
updatedAt: createColumnFilter({
|
|
26
|
+
expression: SQL.column('updatedAt'),
|
|
27
|
+
type: SQLValueType.Datetime,
|
|
28
|
+
nullable: false,
|
|
29
|
+
}),
|
|
30
|
+
createdAt: createColumnFilter({
|
|
31
|
+
expression: SQL.column('createdAt'),
|
|
32
|
+
type: SQLValueType.Datetime,
|
|
33
|
+
nullable: false,
|
|
34
|
+
}),
|
|
35
|
+
status: createColumnFilter({
|
|
36
|
+
expression: SQL.column('status'),
|
|
37
|
+
type: SQLValueType.String,
|
|
38
|
+
nullable: false,
|
|
39
|
+
}),
|
|
40
|
+
type: createColumnFilter({
|
|
41
|
+
expression: SQL.jsonExtract(SQL.column('privateSettings'), '$.value.templateDefinition.type'),
|
|
42
|
+
type: SQLValueType.JSONString,
|
|
43
|
+
nullable: false,
|
|
44
|
+
}),
|
|
45
|
+
};
|
|
@@ -8,7 +8,7 @@ export const documentFilterCompilers: SQLFilterDefinitions = {
|
|
|
8
8
|
nullable: false,
|
|
9
9
|
}),
|
|
10
10
|
description: createColumnFilter({
|
|
11
|
-
expression: SQL.
|
|
11
|
+
expression: SQL.jsonExtract(SQL.column('data'), '$.value.description'),
|
|
12
12
|
type: SQLValueType.JSONString,
|
|
13
13
|
nullable: false,
|
|
14
14
|
}),
|
|
@@ -28,7 +28,7 @@ export const eventFilterCompilers: SQLFilterDefinitions = {
|
|
|
28
28
|
nullable: false,
|
|
29
29
|
}),
|
|
30
30
|
'groupIds': createColumnFilter({
|
|
31
|
-
expression: SQL.
|
|
31
|
+
expression: SQL.jsonExtract(SQL.column('meta'), '$.value.groups[*].id'),
|
|
32
32
|
type: SQLValueType.JSONArray,
|
|
33
33
|
nullable: true,
|
|
34
34
|
}),
|
|
@@ -43,27 +43,27 @@ export const eventFilterCompilers: SQLFilterDefinitions = {
|
|
|
43
43
|
nullable: false,
|
|
44
44
|
}),
|
|
45
45
|
'defaultAgeGroupIds': createColumnFilter({
|
|
46
|
-
expression: SQL.
|
|
46
|
+
expression: SQL.jsonExtract(SQL.column('meta'), '$.value.defaultAgeGroupIds'),
|
|
47
47
|
type: SQLValueType.JSONArray,
|
|
48
48
|
nullable: true,
|
|
49
49
|
}),
|
|
50
50
|
'organizationTagIds': createColumnFilter({
|
|
51
|
-
expression: SQL.
|
|
51
|
+
expression: SQL.jsonExtract(SQL.column('meta'), '$.value.organizationTagIds'),
|
|
52
52
|
type: SQLValueType.JSONArray,
|
|
53
53
|
nullable: true,
|
|
54
54
|
}),
|
|
55
55
|
'minAge': createColumnFilter({
|
|
56
|
-
expression: SQL.
|
|
56
|
+
expression: SQL.jsonExtract(SQL.column('meta'), '$.value.minAge'),
|
|
57
57
|
type: SQLValueType.JSONNumber,
|
|
58
58
|
nullable: true,
|
|
59
59
|
}),
|
|
60
60
|
'maxAge': createColumnFilter({
|
|
61
|
-
expression: SQL.
|
|
61
|
+
expression: SQL.jsonExtract(SQL.column('meta'), '$.value.maxAge'),
|
|
62
62
|
type: SQLValueType.JSONNumber,
|
|
63
63
|
nullable: true,
|
|
64
64
|
}),
|
|
65
65
|
'meta.visible': createColumnFilter({
|
|
66
|
-
expression: SQL.
|
|
66
|
+
expression: SQL.jsonExtract(SQL.column('meta'), '$.value.visible'),
|
|
67
67
|
type: SQLValueType.JSONBoolean,
|
|
68
68
|
nullable: false,
|
|
69
69
|
}),
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { baseSQLFilterCompilers, createColumnFilter, createWildcardColumnFilter, SQL,
|
|
1
|
+
import { baseSQLFilterCompilers, createColumnFilter, createWildcardColumnFilter, SQL, SQLFilterDefinitions, SQLJsonExtract, SQLValueType } from '@stamhoofd/sql';
|
|
2
|
+
import { SQLTranslatedString } from '../helpers/SQLTranslatedString.js';
|
|
2
3
|
|
|
3
4
|
export const groupFilterCompilers: SQLFilterDefinitions = {
|
|
4
5
|
...baseSQLFilterCompilers,
|
|
@@ -18,9 +19,9 @@ export const groupFilterCompilers: SQLFilterDefinitions = {
|
|
|
18
19
|
nullable: false,
|
|
19
20
|
}),
|
|
20
21
|
name: createColumnFilter({
|
|
21
|
-
expression:
|
|
22
|
-
type: SQLValueType.
|
|
23
|
-
nullable:
|
|
22
|
+
expression: new SQLTranslatedString(SQL.column('settings'), '$.value.name'),
|
|
23
|
+
type: SQLValueType.String,
|
|
24
|
+
nullable: true,
|
|
24
25
|
}),
|
|
25
26
|
status: createColumnFilter({
|
|
26
27
|
expression: SQL.column('status'),
|
|
@@ -34,14 +35,14 @@ export const groupFilterCompilers: SQLFilterDefinitions = {
|
|
|
34
35
|
}),
|
|
35
36
|
bundleDiscounts: createWildcardColumnFilter(
|
|
36
37
|
(key: string) => ({
|
|
37
|
-
expression: SQL.
|
|
38
|
+
expression: SQL.jsonExtract(SQL.column('settings'), `$.value.prices[*].bundleDiscounts.${SQLJsonExtract.escapePathComponent(key)}`, true),
|
|
38
39
|
type: SQLValueType.JSONArray,
|
|
39
40
|
nullable: true,
|
|
40
41
|
}),
|
|
41
42
|
(key: string) => ({
|
|
42
43
|
...baseSQLFilterCompilers,
|
|
43
44
|
name: createColumnFilter({
|
|
44
|
-
expression: SQL.
|
|
45
|
+
expression: SQL.jsonExtract(SQL.column('settings'), `$.value.prices[*].bundleDiscounts.${SQLJsonExtract.escapePathComponent(key)}.name`, true),
|
|
45
46
|
type: SQLValueType.JSONArray,
|
|
46
47
|
nullable: true,
|
|
47
48
|
}),
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { SimpleError } from '@simonbackx/simple-errors';
|
|
2
2
|
import { Email, Member } from '@stamhoofd/models';
|
|
3
|
-
import { baseSQLFilterCompilers, createColumnFilter, createExistsFilter, SQL, SQLAge, SQLCast, SQLConcat, SQLFilterDefinitions,
|
|
3
|
+
import { baseSQLFilterCompilers, createColumnFilter, createExistsFilter, createWildcardColumnFilter, SQL, SQLAge, SQLCast, SQLConcat, SQLFilterDefinitions, SQLJsonExtract, SQLScalar, SQLValueType } from '@stamhoofd/sql';
|
|
4
4
|
import { AccessRight } from '@stamhoofd/structures';
|
|
5
|
-
import { Context } from '../helpers/Context';
|
|
6
|
-
import { baseRegistrationFilterCompilers } from './base-registration-filter-compilers';
|
|
7
|
-
import { organizationFilterCompilers } from './organizations';
|
|
5
|
+
import { Context } from '../helpers/Context.js';
|
|
6
|
+
import { baseRegistrationFilterCompilers } from './base-registration-filter-compilers.js';
|
|
7
|
+
import { organizationFilterCompilers } from './organizations.js';
|
|
8
8
|
|
|
9
9
|
const membersTable = SQL.table(Member.table);
|
|
10
10
|
|
|
@@ -20,7 +20,7 @@ export const memberFilterCompilers: SQLFilterDefinitions = {
|
|
|
20
20
|
}),
|
|
21
21
|
'memberNumber': createColumnFilter({
|
|
22
22
|
expression: SQL.column(membersTable, 'memberNumber'),
|
|
23
|
-
type: SQLValueType.
|
|
23
|
+
type: SQLValueType.String,
|
|
24
24
|
nullable: true,
|
|
25
25
|
}),
|
|
26
26
|
'firstName': createColumnFilter({
|
|
@@ -48,7 +48,7 @@ export const memberFilterCompilers: SQLFilterDefinitions = {
|
|
|
48
48
|
nullable: true,
|
|
49
49
|
}),
|
|
50
50
|
'gender': createColumnFilter({
|
|
51
|
-
expression: SQL.
|
|
51
|
+
expression: SQL.jsonExtract(SQL.column(membersTable, 'details'), '$.value.gender'),
|
|
52
52
|
type: SQLValueType.JSONString,
|
|
53
53
|
nullable: false,
|
|
54
54
|
}),
|
|
@@ -58,13 +58,18 @@ export const memberFilterCompilers: SQLFilterDefinitions = {
|
|
|
58
58
|
type: SQLValueType.Datetime,
|
|
59
59
|
nullable: true,
|
|
60
60
|
}),
|
|
61
|
+
'createdAt': createColumnFilter({
|
|
62
|
+
expression: SQL.column(membersTable, 'createdAt'),
|
|
63
|
+
type: SQLValueType.Datetime,
|
|
64
|
+
nullable: false,
|
|
65
|
+
}),
|
|
61
66
|
'organizationName': createColumnFilter({
|
|
62
67
|
expression: SQL.column('organizations', 'name'),
|
|
63
68
|
type: SQLValueType.String,
|
|
64
69
|
nullable: false,
|
|
65
70
|
}),
|
|
66
71
|
'details.requiresFinancialSupport': createColumnFilter({
|
|
67
|
-
expression: SQL.
|
|
72
|
+
expression: SQL.jsonExtract(SQL.column(membersTable, 'details'), '$.value.requiresFinancialSupport.value'),
|
|
68
73
|
type: SQLValueType.JSONBoolean,
|
|
69
74
|
nullable: true,
|
|
70
75
|
checkPermission: async () => {
|
|
@@ -94,12 +99,12 @@ export const memberFilterCompilers: SQLFilterDefinitions = {
|
|
|
94
99
|
},
|
|
95
100
|
}),
|
|
96
101
|
'email': createColumnFilter({
|
|
97
|
-
expression: SQL.
|
|
102
|
+
expression: SQL.jsonExtract(SQL.column(membersTable, 'details'), '$.value.email'),
|
|
98
103
|
type: SQLValueType.JSONString,
|
|
99
104
|
nullable: true,
|
|
100
105
|
}),
|
|
101
106
|
'parentEmail': createColumnFilter({
|
|
102
|
-
expression: SQL.
|
|
107
|
+
expression: SQL.jsonExtract(SQL.column(membersTable, 'details'), '$.value.parents[*].email'),
|
|
103
108
|
type: SQLValueType.JSONArray,
|
|
104
109
|
nullable: true,
|
|
105
110
|
}),
|
|
@@ -132,34 +137,34 @@ export const memberFilterCompilers: SQLFilterDefinitions = {
|
|
|
132
137
|
}),
|
|
133
138
|
},
|
|
134
139
|
'unverifiedEmail': createColumnFilter({
|
|
135
|
-
expression: SQL.
|
|
140
|
+
expression: SQL.jsonExtract(SQL.column(membersTable, 'details'), '$.value.unverifiedEmails'),
|
|
136
141
|
type: SQLValueType.JSONArray,
|
|
137
142
|
nullable: true,
|
|
138
143
|
}),
|
|
139
144
|
'phone': createColumnFilter({
|
|
140
|
-
expression: SQL.
|
|
145
|
+
expression: SQL.jsonExtract(SQL.column(membersTable, 'details'), '$.value.phone'),
|
|
141
146
|
type: SQLValueType.JSONString,
|
|
142
147
|
nullable: true,
|
|
143
148
|
}),
|
|
144
149
|
'details.address': {
|
|
145
150
|
...baseSQLFilterCompilers,
|
|
146
151
|
city: createColumnFilter({
|
|
147
|
-
expression: SQL.
|
|
152
|
+
expression: SQL.jsonExtract(SQL.column(membersTable, 'details'), '$.value.address.city'),
|
|
148
153
|
type: SQLValueType.JSONString,
|
|
149
154
|
nullable: true,
|
|
150
155
|
}),
|
|
151
156
|
postalCode: createColumnFilter({
|
|
152
|
-
expression: SQL.
|
|
157
|
+
expression: SQL.jsonExtract(SQL.column(membersTable, 'details'), '$.value.address.postalCode'),
|
|
153
158
|
type: SQLValueType.JSONString,
|
|
154
159
|
nullable: true,
|
|
155
160
|
}),
|
|
156
161
|
street: createColumnFilter({
|
|
157
|
-
expression: SQL.
|
|
162
|
+
expression: SQL.jsonExtract(SQL.column(membersTable, 'details'), '$.value.address.street'),
|
|
158
163
|
type: SQLValueType.JSONString,
|
|
159
164
|
nullable: true,
|
|
160
165
|
}),
|
|
161
166
|
number: createColumnFilter({
|
|
162
|
-
expression: SQL.
|
|
167
|
+
expression: SQL.jsonExtract(SQL.column(membersTable, 'details'), '$.value.address.number'),
|
|
163
168
|
type: SQLValueType.JSONString,
|
|
164
169
|
nullable: true,
|
|
165
170
|
}),
|
|
@@ -167,33 +172,33 @@ export const memberFilterCompilers: SQLFilterDefinitions = {
|
|
|
167
172
|
'details.parents[*].address': {
|
|
168
173
|
...baseSQLFilterCompilers,
|
|
169
174
|
city: createColumnFilter({
|
|
170
|
-
expression: SQL.
|
|
175
|
+
expression: SQL.jsonExtract(SQL.column(membersTable, 'details'), '$.value.parents[*].address.city'),
|
|
171
176
|
type: SQLValueType.JSONArray,
|
|
172
177
|
nullable: true,
|
|
173
178
|
}),
|
|
174
179
|
postalCode: createColumnFilter({
|
|
175
|
-
expression: SQL.
|
|
180
|
+
expression: SQL.jsonExtract(SQL.column(membersTable, 'details'), '$.value.parents[*].address.postalCode'),
|
|
176
181
|
type: SQLValueType.JSONArray,
|
|
177
182
|
nullable: true,
|
|
178
183
|
}),
|
|
179
184
|
street: createColumnFilter({
|
|
180
|
-
expression: SQL.
|
|
185
|
+
expression: SQL.jsonExtract(SQL.column(membersTable, 'details'), '$.value.parents[*].address.street'),
|
|
181
186
|
type: SQLValueType.JSONArray,
|
|
182
187
|
nullable: true,
|
|
183
188
|
}),
|
|
184
189
|
number: createColumnFilter({
|
|
185
|
-
expression: SQL.
|
|
190
|
+
expression: SQL.jsonExtract(SQL.column(membersTable, 'details'), '$.value.parents[*].address.number'),
|
|
186
191
|
type: SQLValueType.JSONArray,
|
|
187
192
|
nullable: true,
|
|
188
193
|
}),
|
|
189
194
|
},
|
|
190
195
|
'parentPhone': createColumnFilter({
|
|
191
|
-
expression: SQL.
|
|
196
|
+
expression: SQL.jsonExtract(SQL.column(membersTable, 'details'), '$.value.parents[*].phone'),
|
|
192
197
|
type: SQLValueType.JSONArray,
|
|
193
198
|
nullable: true,
|
|
194
199
|
}),
|
|
195
200
|
'unverifiedPhone': createColumnFilter({
|
|
196
|
-
expression: SQL.
|
|
201
|
+
expression: SQL.jsonExtract(SQL.column(membersTable, 'details'), '$.value.unverifiedPhones'),
|
|
197
202
|
type: SQLValueType.JSONArray,
|
|
198
203
|
nullable: true,
|
|
199
204
|
}),
|
|
@@ -458,21 +463,21 @@ export const memberFilterCompilers: SQLFilterDefinitions = {
|
|
|
458
463
|
...baseSQLFilterCompilers,
|
|
459
464
|
recordAnswers: createWildcardColumnFilter(
|
|
460
465
|
(key: string) => ({
|
|
461
|
-
expression: SQL.
|
|
466
|
+
expression: SQL.jsonExtract(SQL.column('details'), `$.value.recordAnswers.${SQLJsonExtract.escapePathComponent(key)}`, true),
|
|
462
467
|
type: SQLValueType.JSONObject,
|
|
463
468
|
nullable: true,
|
|
464
469
|
}),
|
|
465
470
|
(key: string) => ({
|
|
466
471
|
...baseSQLFilterCompilers,
|
|
467
472
|
selected: createColumnFilter({
|
|
468
|
-
expression: SQL.
|
|
473
|
+
expression: SQL.jsonExtract(SQL.column('details'), `$.value.recordAnswers.${SQLJsonExtract.escapePathComponent(key)}.selected`, true),
|
|
469
474
|
type: SQLValueType.JSONBoolean,
|
|
470
475
|
nullable: true,
|
|
471
476
|
}),
|
|
472
477
|
selectedChoice: {
|
|
473
478
|
...baseSQLFilterCompilers,
|
|
474
479
|
id: createColumnFilter({
|
|
475
|
-
expression: SQL.
|
|
480
|
+
expression: SQL.jsonExtract(SQL.column('details'), `$.value.recordAnswers.${SQLJsonExtract.escapePathComponent(key)}.selectedChoice.id`, true),
|
|
476
481
|
type: SQLValueType.JSONString,
|
|
477
482
|
nullable: true,
|
|
478
483
|
}),
|
|
@@ -480,13 +485,13 @@ export const memberFilterCompilers: SQLFilterDefinitions = {
|
|
|
480
485
|
selectedChoices: {
|
|
481
486
|
...baseSQLFilterCompilers,
|
|
482
487
|
id: createColumnFilter({
|
|
483
|
-
expression: SQL.
|
|
488
|
+
expression: SQL.jsonExtract(SQL.column('details'), `$.value.recordAnswers.${SQLJsonExtract.escapePathComponent(key)}.selectedChoices[*].id`, true),
|
|
484
489
|
type: SQLValueType.JSONArray,
|
|
485
490
|
nullable: true,
|
|
486
491
|
}),
|
|
487
492
|
},
|
|
488
493
|
value: createColumnFilter({
|
|
489
|
-
expression: SQL.
|
|
494
|
+
expression: SQL.jsonExtract(SQL.column('details'), `$.value.recordAnswers.${SQLJsonExtract.escapePathComponent(key)}.value`, true),
|
|
490
495
|
type: SQLValueType.JSONString,
|
|
491
496
|
nullable: true,
|
|
492
497
|
}),
|