@stamhoofd/backend 2.39.0 → 2.40.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/eslint.config.mjs +5 -0
- package/index.ts +81 -74
- package/jest.config.cjs +10 -0
- package/migrations.ts +16 -14
- package/package.json +11 -11
- package/src/crons/clear-excel-cache.test.ts +48 -50
- package/src/crons/clear-excel-cache.ts +18 -18
- package/src/crons/setup-steps.ts +2 -2
- package/src/crons.ts +325 -306
- package/src/decoders/StringArrayDecoder.ts +7 -7
- package/src/decoders/StringNullableDecoder.ts +1 -2
- package/src/email-recipient-loaders/members.ts +22 -22
- package/src/endpoints/admin/memberships/ChargeMembershipsEndpoint.ts +8 -9
- package/src/endpoints/admin/memberships/GetChargeMembershipsSummaryEndpoint.ts +39 -40
- package/src/endpoints/admin/organizations/GetOrganizationsCountEndpoint.ts +8 -8
- package/src/endpoints/admin/organizations/GetOrganizationsEndpoint.ts +44 -45
- package/src/endpoints/admin/organizations/PatchOrganizationsEndpoint.ts +58 -57
- package/src/endpoints/auth/CreateAdminEndpoint.ts +48 -45
- package/src/endpoints/auth/CreateTokenEndpoint.test.ts +31 -31
- package/src/endpoints/auth/CreateTokenEndpoint.ts +146 -147
- package/src/endpoints/auth/DeleteTokenEndpoint.ts +7 -7
- package/src/endpoints/auth/DeleteUserEndpoint.ts +15 -15
- package/src/endpoints/auth/ForgotPasswordEndpoint.ts +17 -18
- package/src/endpoints/auth/GetOtherUserEndpoint.ts +9 -10
- package/src/endpoints/auth/GetUserEndpoint.test.ts +32 -35
- package/src/endpoints/auth/GetUserEndpoint.ts +5 -6
- package/src/endpoints/auth/PatchApiUserEndpoint.ts +35 -33
- package/src/endpoints/auth/PatchUserEndpoint.ts +55 -52
- package/src/endpoints/auth/PollEmailVerificationEndpoint.ts +9 -9
- package/src/endpoints/auth/RetryEmailVerificationEndpoint.ts +8 -8
- package/src/endpoints/auth/SignupEndpoint.ts +37 -36
- package/src/endpoints/auth/VerifyEmailEndpoint.ts +29 -28
- package/src/endpoints/global/addresses/SearchRegionsEndpoint.ts +33 -33
- package/src/endpoints/global/addresses/ValidateAddressEndpoint.ts +7 -7
- package/src/endpoints/global/caddy/CheckDomainCertEndpoint.ts +37 -37
- package/src/endpoints/global/email/CreateEmailEndpoint.ts +30 -30
- package/src/endpoints/global/email/GetEmailAddressEndpoint.ts +13 -13
- package/src/endpoints/global/email/GetEmailEndpoint.ts +13 -13
- package/src/endpoints/global/email/ManageEmailAddressEndpoint.ts +16 -16
- package/src/endpoints/global/email/PatchEmailEndpoint.ts +25 -25
- package/src/endpoints/global/events/GetEventsEndpoint.ts +43 -44
- package/src/endpoints/global/events/PatchEventsEndpoint.ts +127 -172
- package/src/endpoints/global/files/ExportToExcelEndpoint.ts +49 -50
- package/src/endpoints/global/files/GetFileCache.ts +13 -13
- package/src/endpoints/global/files/UploadFile.ts +51 -54
- package/src/endpoints/global/files/UploadImage.ts +53 -53
- package/src/endpoints/global/groups/GetGroupsEndpoint.ts +25 -25
- package/src/endpoints/global/members/GetMemberFamilyEndpoint.ts +24 -23
- package/src/endpoints/global/members/GetMembersCountEndpoint.ts +8 -8
- package/src/endpoints/global/members/GetMembersEndpoint.ts +105 -102
- package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.ts +240 -239
- package/src/endpoints/global/organizations/CheckRegisterCodeEndpoint.ts +12 -14
- package/src/endpoints/global/organizations/CreateOrganizationEndpoint.test.ts +32 -33
- package/src/endpoints/global/organizations/CreateOrganizationEndpoint.ts +48 -57
- package/src/endpoints/global/organizations/GetOrganizationFromDomainEndpoint.test.ts +21 -22
- package/src/endpoints/global/organizations/GetOrganizationFromDomainEndpoint.ts +28 -28
- package/src/endpoints/global/organizations/GetOrganizationFromUriEndpoint.ts +18 -18
- package/src/endpoints/global/organizations/SearchOrganizationEndpoint.test.ts +20 -20
- package/src/endpoints/global/organizations/SearchOrganizationEndpoint.ts +17 -17
- package/src/endpoints/global/payments/StripeWebhookEndpoint.ts +81 -75
- package/src/endpoints/global/platform/GetPlatformAdminsEndpoint.ts +14 -14
- package/src/endpoints/global/platform/GetPlatformEnpoint.ts +11 -11
- package/src/endpoints/global/platform/PatchPlatformEnpoint.ts +71 -68
- package/src/endpoints/global/registration/GetPaymentRegistrations.ts +27 -27
- package/src/endpoints/global/registration/GetUserBillingStatusEndpoint.ts +30 -30
- package/src/endpoints/global/registration/GetUserDetailedBillingStatusEndpoint.ts +34 -34
- package/src/endpoints/global/registration/GetUserDocumentsEndpoint.ts +26 -26
- package/src/endpoints/global/registration/GetUserMembersEndpoint.ts +12 -12
- package/src/endpoints/global/registration/PatchUserMembersEndpoint.ts +90 -90
- package/src/endpoints/global/registration/RegisterMembersEndpoint.test.ts +118 -121
- package/src/endpoints/global/registration/RegisterMembersEndpoint.ts +362 -350
- package/src/endpoints/global/registration-periods/GetRegistrationPeriodsEndpoint.ts +8 -9
- package/src/endpoints/global/registration-periods/PatchRegistrationPeriodsEndpoint.ts +21 -21
- package/src/endpoints/global/webshops/GetWebshopFromDomainEndpoint.ts +65 -65
- package/src/endpoints/organization/dashboard/billing/GetOrganizationBillingStatusEndpoint.ts +9 -9
- package/src/endpoints/organization/dashboard/billing/GetOrganizationDetailedBillingStatusEndpoint.ts +14 -14
- package/src/endpoints/organization/dashboard/documents/GetDocumentTemplateXML.ts +17 -17
- package/src/endpoints/organization/dashboard/documents/GetDocumentTemplatesEndpoint.ts +21 -21
- package/src/endpoints/organization/dashboard/documents/GetDocumentsEndpoint.ts +15 -15
- package/src/endpoints/organization/dashboard/documents/PatchDocumentEndpoint.ts +52 -52
- package/src/endpoints/organization/dashboard/documents/PatchDocumentTemplateEndpoint.ts +37 -37
- package/src/endpoints/organization/dashboard/email/CheckEmailBouncesEndpoint.ts +14 -14
- package/src/endpoints/organization/dashboard/email/EmailEndpoint.ts +113 -112
- package/src/endpoints/organization/dashboard/email-templates/GetEmailTemplatesEndpoint.ts +29 -29
- package/src/endpoints/organization/dashboard/email-templates/PatchEmailTemplatesEndpoint.ts +48 -47
- package/src/endpoints/organization/dashboard/mollie/CheckMollieEndpoint.ts +22 -21
- package/src/endpoints/organization/dashboard/mollie/ConnectMollieEndpoint.ts +13 -14
- package/src/endpoints/organization/dashboard/mollie/DisconnectMollieEndpoint.ts +12 -13
- package/src/endpoints/organization/dashboard/mollie/GetMollieDashboardEndpoint.ts +24 -24
- package/src/endpoints/organization/dashboard/nolt/CreateNoltTokenEndpoint.ts +10 -12
- package/src/endpoints/organization/dashboard/organization/GetOrganizationArchivedGroups.ts +14 -14
- package/src/endpoints/organization/dashboard/organization/GetOrganizationDeletedGroups.ts +13 -13
- package/src/endpoints/organization/dashboard/organization/GetOrganizationSSOEndpoint.ts +12 -12
- package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.test.ts +120 -124
- package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.ts +172 -173
- package/src/endpoints/organization/dashboard/organization/SetOrganizationDomainEndpoint.ts +88 -89
- package/src/endpoints/organization/dashboard/organization/SetOrganizationSSOEndpoint.ts +12 -12
- package/src/endpoints/organization/dashboard/payments/GetMemberBalanceEndpoint.ts +17 -17
- package/src/endpoints/organization/dashboard/payments/GetPaymentsCountEndpoint.ts +8 -8
- package/src/endpoints/organization/dashboard/payments/GetPaymentsEndpoint.ts +66 -67
- package/src/endpoints/organization/dashboard/payments/PatchBalanceItemsEndpoint.ts +47 -47
- package/src/endpoints/organization/dashboard/payments/PatchPaymentsEndpoint.ts +93 -91
- package/src/endpoints/organization/dashboard/registration-periods/GetOrganizationRegistrationPeriodsEndpoint.ts +16 -17
- package/src/endpoints/organization/dashboard/registration-periods/PatchOrganizationRegistrationPeriodsEndpoint.ts +170 -167
- package/src/endpoints/organization/dashboard/registration-periods/SetupStepReviewEndpoint.ts +25 -24
- package/src/endpoints/organization/dashboard/stripe/ConnectStripeEndpoint.ts +22 -23
- package/src/endpoints/organization/dashboard/stripe/DeleteStripeAccountEndpoint.ts +22 -22
- package/src/endpoints/organization/dashboard/stripe/GetStripeAccountLinkEndpoint.ts +17 -18
- package/src/endpoints/organization/dashboard/stripe/GetStripeAccountsEndpoint.ts +8 -9
- package/src/endpoints/organization/dashboard/stripe/GetStripeLoginLinkEndpoint.ts +17 -18
- package/src/endpoints/organization/dashboard/stripe/UpdateStripeAccountEndpoint.ts +14 -15
- package/src/endpoints/organization/dashboard/users/CreateApiUserEndpoint.ts +19 -19
- package/src/endpoints/organization/dashboard/users/DeleteUserEndpoint.ts +19 -19
- package/src/endpoints/organization/dashboard/users/GetApiUsersEndpoint.ts +14 -14
- package/src/endpoints/organization/dashboard/users/GetOrganizationAdminsEndpoint.ts +12 -12
- package/src/endpoints/organization/dashboard/webshops/CreateWebshopEndpoint.ts +103 -100
- package/src/endpoints/organization/dashboard/webshops/DeleteWebshopEndpoint.ts +11 -12
- package/src/endpoints/organization/dashboard/webshops/GetDiscountCodesEndpoint.ts +15 -15
- package/src/endpoints/organization/dashboard/webshops/GetWebshopOrdersEndpoint.ts +14 -14
- package/src/endpoints/organization/dashboard/webshops/GetWebshopTicketsEndpoint.ts +14 -14
- package/src/endpoints/organization/dashboard/webshops/GetWebshopUriAvailabilityEndpoint.ts +23 -23
- package/src/endpoints/organization/dashboard/webshops/PatchDiscountCodesEndpoint.ts +54 -52
- package/src/endpoints/organization/dashboard/webshops/PatchWebshopEndpoint.ts +84 -81
- package/src/endpoints/organization/dashboard/webshops/PatchWebshopOrdersEndpoint.ts +120 -111
- package/src/endpoints/organization/dashboard/webshops/PatchWebshopTicketsEndpoint.ts +24 -24
- package/src/endpoints/organization/dashboard/webshops/VerifyWebshopDomainEndpoint.ts +18 -18
- package/src/endpoints/organization/shared/ExchangePaymentEndpoint.ts +141 -130
- package/src/endpoints/organization/shared/GetDocumentHtml.ts +25 -25
- package/src/endpoints/organization/shared/GetPaymentEndpoint.ts +18 -18
- package/src/endpoints/organization/shared/auth/GetOrganizationEndpoint.test.ts +36 -37
- package/src/endpoints/organization/shared/auth/GetOrganizationEndpoint.ts +9 -9
- package/src/endpoints/organization/shared/auth/OpenIDConnectCallbackEndpoint.ts +11 -11
- package/src/endpoints/organization/shared/auth/OpenIDConnectStartEndpoint.ts +28 -27
- package/src/endpoints/organization/webshops/CheckWebshopDiscountCodesEndpoint.ts +20 -20
- package/src/endpoints/organization/webshops/GetOrderByPaymentEndpoint.ts +22 -22
- package/src/endpoints/organization/webshops/GetOrderEndpoint.ts +14 -14
- package/src/endpoints/organization/webshops/GetTicketsEndpoint.ts +57 -56
- package/src/endpoints/organization/webshops/GetWebshopEndpoint.test.ts +65 -66
- package/src/endpoints/organization/webshops/GetWebshopEndpoint.ts +18 -17
- package/src/endpoints/organization/webshops/PlaceOrderEndpoint.test.ts +124 -128
- package/src/endpoints/organization/webshops/PlaceOrderEndpoint.ts +154 -145
- package/src/excel-loaders/members.ts +102 -103
- package/src/excel-loaders/payments.ts +155 -156
- package/src/helpers/AddressValidator.test.ts +32 -32
- package/src/helpers/AddressValidator.ts +128 -122
- package/src/helpers/AdminPermissionChecker.ts +339 -236
- package/src/helpers/AuthenticatedStructures.ts +233 -134
- package/src/helpers/BuckarooHelper.ts +134 -134
- package/src/helpers/CheckSettlements.ts +94 -88
- package/src/helpers/Context.ts +87 -86
- package/src/helpers/CookieHelper.ts +23 -22
- package/src/helpers/EmailResumer.ts +10 -10
- package/src/helpers/FileCache.ts +62 -62
- package/src/helpers/ForwardHandler.test.ts +122 -124
- package/src/helpers/ForwardHandler.ts +76 -70
- package/src/helpers/MemberUserSyncer.ts +101 -96
- package/src/helpers/MembershipCharger.ts +69 -69
- package/src/helpers/MembershipHelper.ts +11 -12
- package/src/helpers/OpenIDConnectHelper.ts +85 -82
- package/src/helpers/PeriodHelper.ts +65 -70
- package/src/helpers/StripeHelper.ts +146 -137
- package/src/helpers/StripePayoutChecker.ts +51 -52
- package/src/helpers/ViesHelper.ts +46 -44
- package/src/helpers/fetchToAsyncIterator.ts +14 -14
- package/src/helpers/xlsxAddressTransformerColumnFactory.ts +50 -52
- package/src/middleware/ContextMiddleware.ts +5 -5
- package/src/migrations/1646578856-validate-addresses.ts +6 -9
- package/src/seeds/0000000000-example.ts +3 -5
- package/src/seeds/1715028563-user-permissions.ts +16 -18
- package/src/seeds/1722256498-group-update-occupancy.ts +12 -12
- package/src/seeds/1722344162-sync-member-users.ts +14 -15
- package/src/seeds/1722344162-update-membership.ts +6 -6
- package/src/seeds/1726055544-balance-item-paid.ts +4 -4
- package/src/seeds/1726055545-balance-item-pending.ts +4 -4
- package/src/seeds/1726494419-update-cached-outstanding-balance.ts +16 -16
- package/src/seeds/1726494420-update-cached-outstanding-balance-from-items.ts +12 -12
- package/src/seeds/1726572303-schedule-stock-updates.ts +12 -12
- package/src/seeds/1726847064-setup-steps.ts +16 -0
- package/src/sql-filters/balance-item-payments.ts +7 -7
- package/src/sql-filters/events.ts +14 -14
- package/src/sql-filters/members.ts +96 -96
- package/src/sql-filters/organizations.ts +139 -75
- package/src/sql-filters/payments.ts +28 -28
- package/src/sql-filters/registrations.ts +14 -14
- package/src/sql-sorters/events.ts +25 -25
- package/src/sql-sorters/members.ts +26 -26
- package/src/sql-sorters/organizations.ts +36 -36
- package/src/sql-sorters/payments.ts +26 -26
- package/tests/e2e/stock.test.ts +616 -621
- package/tests/e2e/tickets.test.ts +255 -260
- package/tests/helpers/StripeMocker.ts +177 -179
- package/tests/helpers/TestServer.ts +9 -9
- package/tests/jest.global.setup.ts +14 -13
- package/tests/jest.setup.ts +33 -32
- package/.eslintrc.js +0 -61
- package/jest.config.js +0 -11
- package/src/helpers/SetupStepsUpdater.ts +0 -359
- package/src/seeds/1724076679-setup-steps.ts +0 -16
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AutoEncoderPatchType, Decoder, PatchableArrayAutoEncoder, PatchableArrayDecoder, patchObject, StringDecoder } from '@simonbackx/simple-encoding';
|
|
2
|
-
import { DecodedRequest, Endpoint, Request, Response } from
|
|
3
|
-
import { Event, Group,
|
|
4
|
-
import { Event as EventStruct, GroupType, NamedObject
|
|
2
|
+
import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
|
|
3
|
+
import { Event, Group, Platform, RegistrationPeriod } from '@stamhoofd/models';
|
|
4
|
+
import { Event as EventStruct, GroupType, NamedObject } from '@stamhoofd/structures';
|
|
5
5
|
|
|
6
6
|
import { SimpleError } from '@simonbackx/simple-errors';
|
|
7
7
|
import { SQL, SQLWhereSign } from '@stamhoofd/sql';
|
|
@@ -12,18 +12,18 @@ import { PatchOrganizationRegistrationPeriodsEndpoint } from '../../organization
|
|
|
12
12
|
|
|
13
13
|
type Params = { id: string };
|
|
14
14
|
type Query = undefined;
|
|
15
|
-
type Body = PatchableArrayAutoEncoder<EventStruct
|
|
16
|
-
type ResponseBody = EventStruct[]
|
|
15
|
+
type Body = PatchableArrayAutoEncoder<EventStruct>;
|
|
16
|
+
type ResponseBody = EventStruct[];
|
|
17
17
|
|
|
18
18
|
export class PatchEventsEndpoint extends Endpoint<Params, Query, Body, ResponseBody> {
|
|
19
|
-
bodyDecoder = new PatchableArrayDecoder(EventStruct as Decoder<EventStruct>, EventStruct.patchType() as Decoder<AutoEncoderPatchType<EventStruct>>, StringDecoder)
|
|
19
|
+
bodyDecoder = new PatchableArrayDecoder(EventStruct as Decoder<EventStruct>, EventStruct.patchType() as Decoder<AutoEncoderPatchType<EventStruct>>, StringDecoder);
|
|
20
20
|
|
|
21
21
|
protected doesMatch(request: Request): [true, Params] | [false] {
|
|
22
|
-
if (request.method
|
|
22
|
+
if (request.method !== 'PATCH') {
|
|
23
23
|
return [false];
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
const params = Endpoint.parseParameters(request.url,
|
|
26
|
+
const params = Endpoint.parseParameters(request.url, '/events', { id: String });
|
|
27
27
|
|
|
28
28
|
if (params) {
|
|
29
29
|
return [true, params as Params];
|
|
@@ -33,280 +33,230 @@ export class PatchEventsEndpoint extends Endpoint<Params, Query, Body, ResponseB
|
|
|
33
33
|
|
|
34
34
|
async handle(request: DecodedRequest<Params, Query, Body>) {
|
|
35
35
|
const organization = await Context.setOptionalOrganizationScope();
|
|
36
|
-
await Context.authenticate()
|
|
36
|
+
await Context.authenticate();
|
|
37
37
|
|
|
38
38
|
if (organization) {
|
|
39
39
|
if (!await Context.auth.hasSomeAccess(organization.id)) {
|
|
40
|
-
throw Context.auth.error()
|
|
40
|
+
throw Context.auth.error();
|
|
41
41
|
}
|
|
42
|
-
}
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
43
44
|
if (!Context.auth.hasSomePlatformAccess()) {
|
|
44
|
-
throw Context.auth.error()
|
|
45
|
+
throw Context.auth.error();
|
|
45
46
|
}
|
|
46
47
|
}
|
|
47
48
|
|
|
48
49
|
const events: Event[] = [];
|
|
49
50
|
|
|
50
|
-
for (const {put} of request.body.getPuts()) {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
code: 'invalid_data',
|
|
54
|
-
message: 'Invalid organizationId',
|
|
55
|
-
human: 'Je kan geen activiteiten aanmaken voor een andere organisatie',
|
|
56
|
-
})
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
if (!organization?.id && !Context.auth.hasPlatformFullAccess()) {
|
|
60
|
-
throw new SimpleError({
|
|
61
|
-
code: 'invalid_data',
|
|
62
|
-
message: 'Invalid organizationId',
|
|
63
|
-
human: 'Je kan activiteiten aanmaken via het administratieportaal als je geen platform hoofdbeheerder bent',
|
|
64
|
-
})
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
const eventOrganization = put.organizationId ? (await Organization.getByID(put.organizationId)) : null
|
|
68
|
-
if (!eventOrganization && put.organizationId) {
|
|
69
|
-
throw new SimpleError({
|
|
70
|
-
code: 'invalid_data',
|
|
71
|
-
message: 'Invalid organizationId',
|
|
72
|
-
human: 'De organisatie werd niet gevonden',
|
|
73
|
-
})
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const event = new Event()
|
|
77
|
-
event.id = put.id
|
|
78
|
-
event.organizationId = put.organizationId
|
|
79
|
-
event.name = put.name
|
|
80
|
-
event.startDate = put.startDate
|
|
81
|
-
event.endDate = put.endDate
|
|
51
|
+
for (const { put } of request.body.getPuts()) {
|
|
52
|
+
const event = new Event();
|
|
53
|
+
event.organizationId = put.organizationId;
|
|
82
54
|
event.meta = put.meta;
|
|
55
|
+
const eventOrganization = await this.checkEventAccess(event);
|
|
56
|
+
event.id = put.id;
|
|
57
|
+
event.name = put.name;
|
|
58
|
+
event.startDate = put.startDate;
|
|
59
|
+
event.endDate = put.endDate;
|
|
60
|
+
|
|
83
61
|
const type = await PatchEventsEndpoint.getEventType(put.typeId);
|
|
84
62
|
event.typeId = type.id;
|
|
85
|
-
event.meta.organizationCache = eventOrganization ? NamedObject.create({id: eventOrganization.id, name: eventOrganization.name}) : null
|
|
86
|
-
await PatchEventsEndpoint.checkEventLimits(event)
|
|
87
|
-
|
|
88
|
-
if (!(await Context.auth.canAccessEvent(event, PermissionLevel.Full))) {
|
|
89
|
-
throw Context.auth.error()
|
|
90
|
-
}
|
|
63
|
+
event.meta.organizationCache = eventOrganization ? NamedObject.create({ id: eventOrganization.id, name: eventOrganization.name }) : null;
|
|
64
|
+
await PatchEventsEndpoint.checkEventLimits(event);
|
|
91
65
|
|
|
92
66
|
if (put.group) {
|
|
93
|
-
const period = await RegistrationPeriod.getByDate(event.startDate)
|
|
67
|
+
const period = await RegistrationPeriod.getByDate(event.startDate);
|
|
94
68
|
|
|
95
69
|
if (!period) {
|
|
96
70
|
throw new SimpleError({
|
|
97
71
|
code: 'invalid_period',
|
|
98
72
|
message: 'No period found for this start date',
|
|
99
73
|
human: 'Oeps, je kan nog geen evenementen met inschrijvingen aanmaken in deze periode. Dit werkjaar is nog niet aangemaakt in het systeem.',
|
|
100
|
-
field: 'startDate'
|
|
101
|
-
})
|
|
74
|
+
field: 'startDate',
|
|
75
|
+
});
|
|
102
76
|
}
|
|
103
77
|
|
|
104
|
-
put.group.type = GroupType.EventRegistration
|
|
78
|
+
put.group.type = GroupType.EventRegistration;
|
|
105
79
|
const group = await PatchOrganizationRegistrationPeriodsEndpoint.createGroup(
|
|
106
80
|
put.group,
|
|
107
81
|
put.group.organizationId,
|
|
108
|
-
period
|
|
109
|
-
)
|
|
110
|
-
await event.syncGroupRequirements(group)
|
|
111
|
-
event.groupId = group.id
|
|
82
|
+
period,
|
|
83
|
+
);
|
|
84
|
+
await event.syncGroupRequirements(group);
|
|
85
|
+
event.groupId = group.id;
|
|
112
86
|
}
|
|
113
87
|
|
|
114
|
-
if(type.isLocationRequired === true) {
|
|
88
|
+
if (type.isLocationRequired === true) {
|
|
115
89
|
PatchEventsEndpoint.throwIfAddressIsMissing(event);
|
|
116
90
|
}
|
|
117
91
|
|
|
118
|
-
await event.save()
|
|
92
|
+
await event.save();
|
|
119
93
|
|
|
120
|
-
events.push(event)
|
|
94
|
+
events.push(event);
|
|
121
95
|
}
|
|
122
96
|
|
|
123
97
|
for (const patch of request.body.getPatches()) {
|
|
124
|
-
const event = await Event.getByID(patch.id)
|
|
98
|
+
const event = await Event.getByID(patch.id);
|
|
125
99
|
|
|
126
|
-
if (!event
|
|
100
|
+
if (!event) {
|
|
127
101
|
throw new SimpleError({
|
|
128
102
|
code: 'not_found',
|
|
129
103
|
message: 'Event not found',
|
|
130
104
|
human: 'De activiteit werd niet gevonden',
|
|
131
|
-
})
|
|
105
|
+
});
|
|
132
106
|
}
|
|
133
107
|
|
|
134
|
-
|
|
135
|
-
event.startDate = patch.startDate ?? event.startDate
|
|
136
|
-
event.endDate = patch.endDate ?? event.endDate
|
|
108
|
+
await this.checkEventAccess(event);
|
|
137
109
|
|
|
138
110
|
if (patch.meta?.organizationCache) {
|
|
139
111
|
throw new SimpleError({
|
|
140
112
|
code: 'invalid_field',
|
|
141
113
|
message: 'Cannot patch organizationCache',
|
|
142
114
|
human: 'Je kan de organizationCache niet aanpassen via een patch',
|
|
143
|
-
field: 'meta.organizationCache'
|
|
144
|
-
})
|
|
115
|
+
field: 'meta.organizationCache',
|
|
116
|
+
});
|
|
145
117
|
}
|
|
146
118
|
|
|
147
|
-
event.meta = patchObject(event.meta, patch.meta)
|
|
119
|
+
event.meta = patchObject(event.meta, patch.meta);
|
|
148
120
|
|
|
149
121
|
if (patch.organizationId !== undefined) {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
throw new SimpleError({
|
|
160
|
-
code: 'invalid_data',
|
|
161
|
-
message: 'Invalid organizationId',
|
|
162
|
-
human: 'Je kan geen activiteiten voor een specifieke organisatie aanmaken als je geen platform hoofdbeheerder bent',
|
|
163
|
-
})
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
const eventOrganization = patch.organizationId ? (await Organization.getByID(patch.organizationId)) : null
|
|
167
|
-
if (!eventOrganization && patch.organizationId) {
|
|
168
|
-
throw new SimpleError({
|
|
169
|
-
code: 'invalid_data',
|
|
170
|
-
message: 'Invalid organizationId',
|
|
171
|
-
human: 'De organisatie werd niet gevonden',
|
|
172
|
-
})
|
|
173
|
-
}
|
|
174
|
-
event.organizationId = patch.organizationId
|
|
175
|
-
event.meta.organizationCache = eventOrganization ? NamedObject.create({id: eventOrganization.id, name: eventOrganization.name}) : null
|
|
176
|
-
} else {
|
|
177
|
-
// Update cache
|
|
178
|
-
if (event.organizationId) {
|
|
179
|
-
const eventOrganization = await Organization.getByID(event.organizationId)
|
|
180
|
-
if (eventOrganization) {
|
|
181
|
-
event.meta.organizationCache = NamedObject.create({id: eventOrganization.id, name: eventOrganization.name})
|
|
182
|
-
}
|
|
183
|
-
}
|
|
122
|
+
event.organizationId = patch.organizationId;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const eventOrganization = await this.checkEventAccess(event);
|
|
126
|
+
if (eventOrganization) {
|
|
127
|
+
event.meta.organizationCache = NamedObject.create({ id: eventOrganization.id, name: eventOrganization.name });
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
event.meta.organizationCache = null;
|
|
184
131
|
}
|
|
185
132
|
|
|
133
|
+
event.name = patch.name ?? event.name;
|
|
134
|
+
event.startDate = patch.startDate ?? event.startDate;
|
|
135
|
+
event.endDate = patch.endDate ?? event.endDate;
|
|
136
|
+
|
|
186
137
|
const type = await PatchEventsEndpoint.getEventType(patch.typeId ?? event.typeId);
|
|
187
138
|
|
|
188
|
-
if(patch.typeId) {
|
|
139
|
+
if (patch.typeId) {
|
|
189
140
|
event.typeId = type.id;
|
|
190
141
|
}
|
|
191
142
|
|
|
192
|
-
await PatchEventsEndpoint.checkEventLimits(event)
|
|
143
|
+
await PatchEventsEndpoint.checkEventLimits(event);
|
|
193
144
|
|
|
194
145
|
if (patch.group !== undefined) {
|
|
195
146
|
if (patch.group === null) {
|
|
196
147
|
// delete
|
|
197
148
|
if (event.groupId) {
|
|
198
|
-
await PatchOrganizationRegistrationPeriodsEndpoint.deleteGroup(event.groupId)
|
|
149
|
+
await PatchOrganizationRegistrationPeriodsEndpoint.deleteGroup(event.groupId);
|
|
199
150
|
event.groupId = null;
|
|
200
151
|
}
|
|
201
|
-
|
|
202
|
-
|
|
152
|
+
}
|
|
153
|
+
else if (patch.group.isPatch()) {
|
|
203
154
|
if (!event.groupId) {
|
|
204
155
|
throw new SimpleError({
|
|
205
156
|
code: 'invalid_field',
|
|
206
157
|
field: 'group',
|
|
207
|
-
message: 'Cannot patch group before it is created'
|
|
208
|
-
})
|
|
158
|
+
message: 'Cannot patch group before it is created',
|
|
159
|
+
});
|
|
209
160
|
}
|
|
210
|
-
patch.group.id = event.groupId
|
|
211
|
-
patch.group.type = GroupType.EventRegistration
|
|
161
|
+
patch.group.id = event.groupId;
|
|
162
|
+
patch.group.type = GroupType.EventRegistration;
|
|
212
163
|
|
|
213
|
-
const period = await RegistrationPeriod.getByDate(event.startDate)
|
|
214
|
-
await PatchOrganizationRegistrationPeriodsEndpoint.patchGroup(patch.group, period)
|
|
215
|
-
}
|
|
164
|
+
const period = await RegistrationPeriod.getByDate(event.startDate);
|
|
165
|
+
await PatchOrganizationRegistrationPeriodsEndpoint.patchGroup(patch.group, period);
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
216
168
|
if (event.groupId) {
|
|
217
169
|
// need to delete old group first
|
|
218
|
-
await PatchOrganizationRegistrationPeriodsEndpoint.deleteGroup(event.groupId)
|
|
170
|
+
await PatchOrganizationRegistrationPeriodsEndpoint.deleteGroup(event.groupId);
|
|
219
171
|
event.groupId = null;
|
|
220
172
|
}
|
|
221
|
-
patch.group.type = GroupType.EventRegistration
|
|
173
|
+
patch.group.type = GroupType.EventRegistration;
|
|
222
174
|
|
|
223
|
-
const period = await RegistrationPeriod.getByDate(event.startDate)
|
|
175
|
+
const period = await RegistrationPeriod.getByDate(event.startDate);
|
|
224
176
|
|
|
225
177
|
if (!period) {
|
|
226
178
|
throw new SimpleError({
|
|
227
179
|
code: 'invalid_period',
|
|
228
180
|
message: 'No period found for this start date',
|
|
229
181
|
human: 'Oeps, je kan nog geen evenementen met inschrijvingen aanmaken in deze periode. Dit werkjaar is nog niet aangemaakt in het systeem.',
|
|
230
|
-
field: 'startDate'
|
|
231
|
-
})
|
|
182
|
+
field: 'startDate',
|
|
183
|
+
});
|
|
232
184
|
}
|
|
233
185
|
|
|
234
186
|
const group = await PatchOrganizationRegistrationPeriodsEndpoint.createGroup(
|
|
235
187
|
patch.group,
|
|
236
188
|
patch.group.organizationId,
|
|
237
|
-
period
|
|
238
|
-
)
|
|
239
|
-
event.groupId = group.id
|
|
189
|
+
period,
|
|
190
|
+
);
|
|
191
|
+
event.groupId = group.id;
|
|
240
192
|
}
|
|
241
193
|
}
|
|
242
194
|
|
|
243
|
-
if(type.isLocationRequired === true) {
|
|
195
|
+
if (type.isLocationRequired === true) {
|
|
244
196
|
PatchEventsEndpoint.throwIfAddressIsMissing(event);
|
|
245
197
|
}
|
|
246
198
|
|
|
247
|
-
await event.save()
|
|
199
|
+
await event.save();
|
|
248
200
|
|
|
249
201
|
if (event.groupId) {
|
|
250
|
-
const group = await Group.getByID(event.groupId)
|
|
202
|
+
const group = await Group.getByID(event.groupId);
|
|
251
203
|
if (group) {
|
|
252
|
-
await event.syncGroupRequirements(group)
|
|
204
|
+
await event.syncGroupRequirements(group);
|
|
253
205
|
}
|
|
254
206
|
}
|
|
255
|
-
|
|
256
|
-
events.push(event)
|
|
207
|
+
|
|
208
|
+
events.push(event);
|
|
257
209
|
}
|
|
258
210
|
|
|
259
211
|
for (const id of request.body.getDeletes()) {
|
|
260
212
|
const event = await Event.getByID(id);
|
|
261
213
|
if (!event) {
|
|
262
|
-
throw new SimpleError({ code:
|
|
214
|
+
throw new SimpleError({ code: 'not_found', message: 'Event not found', statusCode: 404 });
|
|
263
215
|
}
|
|
264
216
|
|
|
265
|
-
|
|
266
|
-
throw Context.auth.error()
|
|
267
|
-
}
|
|
217
|
+
await this.checkEventAccess(event);
|
|
268
218
|
|
|
269
|
-
if(event.groupId) {
|
|
270
|
-
await PatchOrganizationRegistrationPeriodsEndpoint.deleteGroup(event.groupId)
|
|
219
|
+
if (event.groupId) {
|
|
220
|
+
await PatchOrganizationRegistrationPeriodsEndpoint.deleteGroup(event.groupId);
|
|
271
221
|
event.groupId = null;
|
|
272
222
|
}
|
|
273
|
-
|
|
223
|
+
|
|
274
224
|
await event.delete();
|
|
275
225
|
}
|
|
276
226
|
|
|
277
227
|
return new Response(
|
|
278
|
-
await AuthenticatedStructures.events(events)
|
|
228
|
+
await AuthenticatedStructures.events(events),
|
|
279
229
|
);
|
|
280
230
|
}
|
|
281
231
|
|
|
282
232
|
static async validateEventType(typeId: string) {
|
|
283
|
-
return (await this.getEventType(typeId)).id
|
|
233
|
+
return (await this.getEventType(typeId)).id;
|
|
284
234
|
}
|
|
285
235
|
|
|
286
236
|
static async getEventType(typeId: string) {
|
|
287
237
|
const platform = await Platform.getSharedStruct();
|
|
288
|
-
const type = platform.config.eventTypes.find(t => t.id == typeId)
|
|
238
|
+
const type = platform.config.eventTypes.find(t => t.id == typeId);
|
|
289
239
|
if (!type) {
|
|
290
240
|
throw new SimpleError({
|
|
291
241
|
code: 'invalid_field',
|
|
292
242
|
message: 'Invalid typeId',
|
|
293
243
|
human: 'Dit type activiteit wordt niet ondersteund',
|
|
294
|
-
field: 'typeId'
|
|
295
|
-
})
|
|
244
|
+
field: 'typeId',
|
|
245
|
+
});
|
|
296
246
|
}
|
|
297
|
-
return type
|
|
247
|
+
return type;
|
|
298
248
|
}
|
|
299
249
|
|
|
300
250
|
static async checkEventLimits(event: Event) {
|
|
301
|
-
const type = await this.getEventType(event.typeId)
|
|
251
|
+
const type = await this.getEventType(event.typeId);
|
|
302
252
|
|
|
303
253
|
if (event.name.length < 2) {
|
|
304
254
|
throw new SimpleError({
|
|
305
255
|
code: 'invalid_field',
|
|
306
256
|
message: 'Name is too short',
|
|
307
257
|
human: 'Vul een naam voor je activiteit in',
|
|
308
|
-
field: 'name'
|
|
309
|
-
})
|
|
258
|
+
field: 'name',
|
|
259
|
+
});
|
|
310
260
|
}
|
|
311
261
|
|
|
312
262
|
if (event.endDate < event.startDate) {
|
|
@@ -314,25 +264,25 @@ export class PatchEventsEndpoint extends Endpoint<Params, Query, Body, ResponseB
|
|
|
314
264
|
code: 'invalid_dates',
|
|
315
265
|
message: 'End date is before start date',
|
|
316
266
|
human: 'De einddatum moet na de startdatum liggen',
|
|
317
|
-
field: 'endDate'
|
|
318
|
-
})
|
|
267
|
+
field: 'endDate',
|
|
268
|
+
});
|
|
319
269
|
}
|
|
320
270
|
|
|
321
271
|
if (type.maximumDays !== null || type.minimumDays !== null) {
|
|
322
|
-
const start = Formatter.luxon(event.startDate).startOf('day')
|
|
323
|
-
const end = Formatter.luxon(event.endDate).startOf('day')
|
|
272
|
+
const start = Formatter.luxon(event.startDate).startOf('day');
|
|
273
|
+
const end = Formatter.luxon(event.endDate).startOf('day');
|
|
324
274
|
|
|
325
275
|
const days = end.diff(start, 'days').days + 1;
|
|
326
276
|
|
|
327
|
-
console.log('Detected days:', days)
|
|
277
|
+
console.log('Detected days:', days);
|
|
328
278
|
|
|
329
279
|
if (type.minimumDays !== null && days < type.minimumDays) {
|
|
330
280
|
throw new SimpleError({
|
|
331
281
|
code: 'minimum_days',
|
|
332
282
|
message: 'An event with this type has a minimum of ' + type.minimumDays + ' days',
|
|
333
283
|
human: 'Een ' + type.name + ' moet minimum ' + Formatter.pluralText(type.minimumDays, 'dag', 'dagen') + ' duren',
|
|
334
|
-
field: 'startDate'
|
|
335
|
-
})
|
|
284
|
+
field: 'startDate',
|
|
285
|
+
});
|
|
336
286
|
}
|
|
337
287
|
|
|
338
288
|
if (type.maximumDays !== null && days > type.maximumDays) {
|
|
@@ -340,54 +290,59 @@ export class PatchEventsEndpoint extends Endpoint<Params, Query, Body, ResponseB
|
|
|
340
290
|
code: 'maximum_days',
|
|
341
291
|
message: 'An event with this type has a maximum of ' + type.maximumDays + ' days',
|
|
342
292
|
human: 'Een ' + type.name + ' mag maximaal ' + Formatter.pluralText(type.maximumDays, 'dag', 'dagen') + ' duren',
|
|
343
|
-
field: 'startDate'
|
|
344
|
-
})
|
|
293
|
+
field: 'startDate',
|
|
294
|
+
});
|
|
345
295
|
}
|
|
346
296
|
}
|
|
347
297
|
|
|
348
|
-
if (type.maximum && (!event.existsInDatabase || (
|
|
298
|
+
if (type.maximum && (!event.existsInDatabase || ('typeId' in (await event.getChangedDatabaseProperties()).fields))) {
|
|
349
299
|
const currentPeriod = await RegistrationPeriod.getByDate(event.startDate);
|
|
350
|
-
console.log('event.startDate', event.startDate)
|
|
300
|
+
console.log('event.startDate', event.startDate);
|
|
351
301
|
if (currentPeriod) {
|
|
352
302
|
const count = await SQL.select().from(
|
|
353
|
-
|
|
354
|
-
|
|
303
|
+
SQL.table(Event.table),
|
|
304
|
+
)
|
|
355
305
|
.where(SQL.column('organizationId'), event.organizationId)
|
|
356
306
|
.where(SQL.column('typeId'), event.typeId)
|
|
357
307
|
.where(SQL.column('id'), SQLWhereSign.NotEqual, event.id)
|
|
358
308
|
.where(SQL.column('startDate'), SQLWhereSign.GreaterEqual, currentPeriod.startDate)
|
|
359
309
|
.where(SQL.column('endDate'), SQLWhereSign.LessEqual, currentPeriod.endDate)
|
|
360
|
-
.count()
|
|
361
|
-
|
|
310
|
+
.count();
|
|
311
|
+
|
|
362
312
|
if (count >= type.maximum) {
|
|
363
313
|
throw new SimpleError({
|
|
364
314
|
code: 'type_maximum_reached',
|
|
365
315
|
message: 'Maximum number of events with this type reached',
|
|
366
316
|
human: 'Het maximum aantal voor ' + type.name + ' is bereikt (' + type.maximum + ')',
|
|
367
|
-
field: 'typeId'
|
|
368
|
-
})
|
|
317
|
+
field: 'typeId',
|
|
318
|
+
});
|
|
369
319
|
}
|
|
370
|
-
}
|
|
320
|
+
}
|
|
321
|
+
else {
|
|
371
322
|
throw new SimpleError({
|
|
372
323
|
code: 'invalid_period',
|
|
373
324
|
message: 'No period found for this start date',
|
|
374
325
|
human: 'Oeps, je kan nog geen evenementen van dit type aanmaken in deze periode',
|
|
375
|
-
field: 'startDate'
|
|
376
|
-
})
|
|
326
|
+
field: 'startDate',
|
|
327
|
+
});
|
|
377
328
|
}
|
|
378
329
|
}
|
|
379
330
|
}
|
|
380
331
|
|
|
332
|
+
private async checkEventAccess(event: Event) {
|
|
333
|
+
return await Context.auth.checkEventAccess(event);
|
|
334
|
+
}
|
|
335
|
+
|
|
381
336
|
private static throwIfAddressIsMissing(event: Event) {
|
|
382
337
|
const address = event.meta.location?.address;
|
|
383
338
|
|
|
384
|
-
if(!address) {
|
|
339
|
+
if (!address) {
|
|
385
340
|
throw new SimpleError({
|
|
386
|
-
code:
|
|
387
|
-
message:
|
|
388
|
-
human:
|
|
389
|
-
field:
|
|
390
|
-
})
|
|
341
|
+
code: 'invalid_field',
|
|
342
|
+
message: 'Empty number',
|
|
343
|
+
human: 'De locatie is verplicht voor deze soort activiteit.',
|
|
344
|
+
field: 'event_required',
|
|
345
|
+
});
|
|
391
346
|
}
|
|
392
347
|
|
|
393
348
|
address.throwIfIncomplete();
|