@stamhoofd/backend 2.36.2 → 2.38.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +10 -10
- package/src/endpoints/admin/memberships/ChargeMembershipsEndpoint.ts +1 -2
- package/src/endpoints/admin/organizations/PatchOrganizationsEndpoint.ts +8 -0
- package/src/endpoints/auth/CreateAdminEndpoint.ts +4 -3
- package/src/endpoints/auth/PatchUserEndpoint.ts +2 -2
- package/src/endpoints/global/addresses/SearchRegionsEndpoint.ts +12 -0
- package/src/endpoints/global/email/CreateEmailEndpoint.ts +2 -0
- package/src/endpoints/global/email/PatchEmailEndpoint.ts +6 -0
- package/src/endpoints/global/events/PatchEventsEndpoint.ts +1 -1
- package/src/endpoints/global/files/ExportToExcelEndpoint.ts +9 -10
- package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.ts +46 -24
- package/src/endpoints/global/platform/PatchPlatformEnpoint.ts +11 -4
- package/src/endpoints/global/registration/PatchUserMembersEndpoint.ts +2 -0
- package/src/endpoints/global/registration/RegisterMembersEndpoint.test.ts +453 -0
- package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.ts +19 -2
- package/src/endpoints/organization/shared/ExchangePaymentEndpoint.ts +13 -2
- package/src/endpoints/organization/shared/GetPaymentEndpoint.ts +1 -1
- package/src/excel-loaders/members.ts +87 -24
- package/src/helpers/AddressValidator.ts +11 -0
- package/src/helpers/AdminPermissionChecker.ts +14 -1
- package/src/helpers/Context.ts +2 -2
- package/src/helpers/MembershipCharger.ts +84 -2
- package/src/helpers/fetchToAsyncIterator.ts +3 -4
- package/src/seeds/1726494420-update-cached-outstanding-balance-from-items.ts +40 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stamhoofd/backend",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.38.0",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -36,14 +36,14 @@
|
|
|
36
36
|
"@simonbackx/simple-encoding": "2.15.1",
|
|
37
37
|
"@simonbackx/simple-endpoints": "1.14.0",
|
|
38
38
|
"@simonbackx/simple-logging": "^1.0.1",
|
|
39
|
-
"@stamhoofd/backend-i18n": "2.
|
|
40
|
-
"@stamhoofd/backend-middleware": "2.
|
|
41
|
-
"@stamhoofd/email": "2.
|
|
42
|
-
"@stamhoofd/models": "2.
|
|
43
|
-
"@stamhoofd/queues": "2.
|
|
44
|
-
"@stamhoofd/sql": "2.
|
|
45
|
-
"@stamhoofd/structures": "2.
|
|
46
|
-
"@stamhoofd/utility": "2.
|
|
39
|
+
"@stamhoofd/backend-i18n": "2.38.0",
|
|
40
|
+
"@stamhoofd/backend-middleware": "2.38.0",
|
|
41
|
+
"@stamhoofd/email": "2.38.0",
|
|
42
|
+
"@stamhoofd/models": "2.38.0",
|
|
43
|
+
"@stamhoofd/queues": "2.38.0",
|
|
44
|
+
"@stamhoofd/sql": "2.38.0",
|
|
45
|
+
"@stamhoofd/structures": "2.38.0",
|
|
46
|
+
"@stamhoofd/utility": "2.38.0",
|
|
47
47
|
"archiver": "^7.0.1",
|
|
48
48
|
"aws-sdk": "^2.885.0",
|
|
49
49
|
"axios": "1.6.8",
|
|
@@ -60,5 +60,5 @@
|
|
|
60
60
|
"postmark": "^4.0.5",
|
|
61
61
|
"stripe": "^16.6.0"
|
|
62
62
|
},
|
|
63
|
-
"gitHead": "
|
|
63
|
+
"gitHead": "4af6773c9729d690145d60993542452989d6219d"
|
|
64
64
|
}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
|
|
2
|
+
import { SimpleError } from '@simonbackx/simple-errors';
|
|
2
3
|
import { QueueHandler } from '@stamhoofd/queues';
|
|
3
|
-
import { sleep } from '@stamhoofd/utility';
|
|
4
4
|
import { Context } from '../../../helpers/Context';
|
|
5
5
|
import { MembershipCharger } from '../../../helpers/MembershipCharger';
|
|
6
|
-
import { SimpleError } from '@simonbackx/simple-errors';
|
|
7
6
|
|
|
8
7
|
|
|
9
8
|
type Params = Record<string, never>;
|
|
@@ -43,6 +43,10 @@ export class PatchOrganizationsEndpoint extends Endpoint<Params, Query, Body, Re
|
|
|
43
43
|
const platform = await Platform.getShared()
|
|
44
44
|
|
|
45
45
|
for (const id of request.body.getDeletes()) {
|
|
46
|
+
if (!Context.auth.hasPlatformFullAccess()) {
|
|
47
|
+
throw Context.auth.error('Enkel een platform hoofdbeheerder kan groepen verwijderen')
|
|
48
|
+
}
|
|
49
|
+
|
|
46
50
|
const organization = await Organization.getByID(id);
|
|
47
51
|
if (!organization) {
|
|
48
52
|
throw new SimpleError({ code: "not_found", message: "Organization not found", statusCode: 404 });
|
|
@@ -85,6 +89,10 @@ export class PatchOrganizationsEndpoint extends Endpoint<Params, Query, Body, Re
|
|
|
85
89
|
|
|
86
90
|
// Organization creation
|
|
87
91
|
for (const {put} of request.body.getPuts()) {
|
|
92
|
+
if (!Context.auth.hasPlatformFullAccess()) {
|
|
93
|
+
throw Context.auth.error('Enkel een platform hoofdbeheerder kan nieuwe groepen aanmaken')
|
|
94
|
+
}
|
|
95
|
+
|
|
88
96
|
if (put.name.length < 4) {
|
|
89
97
|
if (put.name.length == 0) {
|
|
90
98
|
throw new SimpleError({
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Decoder } from '@simonbackx/simple-encoding';
|
|
2
2
|
import { DecodedRequest, Endpoint, Request, Response } from "@simonbackx/simple-endpoints";
|
|
3
3
|
import { SimpleError } from "@simonbackx/simple-errors";
|
|
4
|
-
import { PasswordToken, sendEmailTemplate, User } from '@stamhoofd/models';
|
|
4
|
+
import { PasswordToken, Platform, sendEmailTemplate, User } from '@stamhoofd/models';
|
|
5
5
|
import { EmailTemplateType, Recipient, Replacement, UserPermissions, User as UserStruct, UserWithMembers } from "@stamhoofd/structures";
|
|
6
6
|
import { Formatter } from '@stamhoofd/utility';
|
|
7
7
|
|
|
@@ -100,9 +100,10 @@ export class CreateAdminEndpoint extends Endpoint<Params, Query, Body, ResponseB
|
|
|
100
100
|
|
|
101
101
|
const dateTime = Formatter.dateTime(validUntil)
|
|
102
102
|
const recoveryUrl = await PasswordToken.getPasswordRecoveryUrl(admin, organization, request.i18n, validUntil)
|
|
103
|
+
const platformName = ((await Platform.getSharedStruct()).config.name)
|
|
103
104
|
|
|
104
|
-
const name = organization?.name ??
|
|
105
|
-
const what = organization ? `de vereniging ${name} op ${
|
|
105
|
+
const name = organization?.name ?? platformName
|
|
106
|
+
const what = organization ? `de vereniging ${name} op ${platformName}` : platformName
|
|
106
107
|
|
|
107
108
|
const emailTo = admin.getEmailTo();
|
|
108
109
|
const email: string = typeof emailTo === 'string' ? emailTo : emailTo[0]?.email;
|
|
@@ -79,7 +79,7 @@ export class PatchUserEndpoint extends Endpoint<Params, Query, Body, ResponseBod
|
|
|
79
79
|
if (organization) {
|
|
80
80
|
editUser.permissions = UserPermissions.limitedPatch(editUser.permissions, request.body.permissions, organization.id)
|
|
81
81
|
|
|
82
|
-
if (editUser.id === user.id && (!editUser.permissions || !editUser.permissions.forOrganization(organization)?.hasFullAccess())) {
|
|
82
|
+
if (editUser.id === user.id && (!editUser.permissions || !editUser.permissions.forOrganization(organization)?.hasFullAccess()) && STAMHOOFD.environment !== 'development') {
|
|
83
83
|
throw new SimpleError({
|
|
84
84
|
code: "permission_denied",
|
|
85
85
|
message: "Je kan jezelf niet verwijderen als hoofdbeheerder"
|
|
@@ -96,7 +96,7 @@ export class PatchUserEndpoint extends Endpoint<Params, Query, Body, ResponseBod
|
|
|
96
96
|
editUser.permissions = null
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
if (editUser.id === user.id && !editUser.permissions?.platform?.hasFullAccess()) {
|
|
99
|
+
if (editUser.id === user.id && !editUser.permissions?.platform?.hasFullAccess() && STAMHOOFD.environment !== 'development') {
|
|
100
100
|
throw new SimpleError({
|
|
101
101
|
code: "permission_denied",
|
|
102
102
|
message: "Je kan jezelf niet verwijderen als hoofdbeheerder"
|
|
@@ -85,6 +85,18 @@ export class SearchRegionsEndpoint extends Endpoint<Params, Query, Body, Respons
|
|
|
85
85
|
if (StringCompare.typoCount(request.query.query, "Nederland") < 3) {
|
|
86
86
|
countries.push(Country.Netherlands)
|
|
87
87
|
}
|
|
88
|
+
|
|
89
|
+
if (StringCompare.typoCount(request.query.query, "Luxemburg") < 3) {
|
|
90
|
+
countries.push(Country.Luxembourg)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (StringCompare.typoCount(request.query.query, "Duitsland") < 3) {
|
|
94
|
+
countries.push(Country.Germany)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (StringCompare.typoCount(request.query.query, "Frankrijk") < 3) {
|
|
98
|
+
countries.push(Country.France)
|
|
99
|
+
}
|
|
88
100
|
|
|
89
101
|
return new Response(SearchRegions.create({
|
|
90
102
|
cities: loadedCities.map(c => CityStruct.create(Object.assign({...c}, { province: ProvinceStruct.create(c.province) }))),
|
|
@@ -83,6 +83,8 @@ export class CreateEmailEndpoint extends Endpoint<Params, Query, Body, ResponseB
|
|
|
83
83
|
model.fromAddress = request.body.fromAddress;
|
|
84
84
|
model.fromName = request.body.fromName;
|
|
85
85
|
|
|
86
|
+
model.validateAttachments()
|
|
87
|
+
|
|
86
88
|
// Check default
|
|
87
89
|
if (JSON.stringify(model.json).length < 3 && model.recipientFilter.filters[0].type && EmailTemplateStruct.getDefaultForRecipient(model.recipientFilter.filters[0].type)) {
|
|
88
90
|
const type = EmailTemplateStruct.getDefaultForRecipient(model.recipientFilter.filters[0].type)
|
|
@@ -89,6 +89,12 @@ export class PatchEmailEndpoint extends Endpoint<Params, Query, Body, ResponseBo
|
|
|
89
89
|
rebuild = true;
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
+
// Attachments
|
|
93
|
+
if (request.body.attachments !== undefined) {
|
|
94
|
+
model.attachments = patchObject(model.attachments, request.body.attachments);
|
|
95
|
+
model.validateAttachments()
|
|
96
|
+
}
|
|
97
|
+
|
|
92
98
|
await model.save();
|
|
93
99
|
|
|
94
100
|
if (rebuild) {
|
|
@@ -60,7 +60,7 @@ export class PatchEventsEndpoint extends Endpoint<Params, Query, Body, ResponseB
|
|
|
60
60
|
throw new SimpleError({
|
|
61
61
|
code: 'invalid_data',
|
|
62
62
|
message: 'Invalid organizationId',
|
|
63
|
-
human: 'Je kan
|
|
63
|
+
human: 'Je kan activiteiten aanmaken via het administratieportaal als je geen platform hoofdbeheerder bent',
|
|
64
64
|
})
|
|
65
65
|
}
|
|
66
66
|
|
|
@@ -1,24 +1,23 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
|
2
|
-
import { Decoder
|
|
2
|
+
import { Decoder } from '@simonbackx/simple-encoding';
|
|
3
3
|
import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
|
|
4
4
|
import { SimpleError } from '@simonbackx/simple-errors';
|
|
5
|
-
import { Email } from '@stamhoofd/email';
|
|
6
5
|
import { ArchiverWriterAdapter, exportToExcel, XlsxTransformerSheet, XlsxWriter } from '@stamhoofd/excel-writer';
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
6
|
+
import { Platform, RateLimiter, sendEmailTemplate } from '@stamhoofd/models';
|
|
7
|
+
import { QueueHandler } from '@stamhoofd/queues';
|
|
8
|
+
import { EmailTemplateType, ExcelExportRequest, ExcelExportResponse, ExcelExportType, IPaginatedResponse, LimitedFilteredRequest, Replacement, Version } from '@stamhoofd/structures';
|
|
9
9
|
import { sleep } from "@stamhoofd/utility";
|
|
10
10
|
import { Context } from '../../../helpers/Context';
|
|
11
11
|
import { fetchToAsyncIterator } from '../../../helpers/fetchToAsyncIterator';
|
|
12
12
|
import { FileCache } from '../../../helpers/FileCache';
|
|
13
|
-
import { QueueHandler } from '@stamhoofd/queues';
|
|
14
13
|
|
|
15
14
|
type Params = { type: string };
|
|
16
15
|
type Query = undefined;
|
|
17
16
|
type Body = ExcelExportRequest;
|
|
18
17
|
type ResponseBody = ExcelExportResponse;
|
|
19
18
|
|
|
20
|
-
type ExcelExporter<T
|
|
21
|
-
fetch(request: LimitedFilteredRequest): Promise<
|
|
19
|
+
type ExcelExporter<T> = {
|
|
20
|
+
fetch(request: LimitedFilteredRequest): Promise<IPaginatedResponse<T[], LimitedFilteredRequest>>
|
|
22
21
|
sheets: XlsxTransformerSheet<T, unknown>[]
|
|
23
22
|
}
|
|
24
23
|
|
|
@@ -36,7 +35,7 @@ export class ExportToExcelEndpoint extends Endpoint<Params, Query, Body, Respons
|
|
|
36
35
|
bodyDecoder = ExcelExportRequest as Decoder<ExcelExportRequest>
|
|
37
36
|
|
|
38
37
|
// Other endpoints can register exports here
|
|
39
|
-
static loaders: Map<ExcelExportType, ExcelExporter<
|
|
38
|
+
static loaders: Map<ExcelExportType, ExcelExporter<unknown>> = new Map()
|
|
40
39
|
|
|
41
40
|
protected doesMatch(request: Request): [true, Params] | [false] {
|
|
42
41
|
if (request.method != "POST") {
|
|
@@ -52,7 +51,7 @@ export class ExportToExcelEndpoint extends Endpoint<Params, Query, Body, Respons
|
|
|
52
51
|
}
|
|
53
52
|
|
|
54
53
|
async handle(request: DecodedRequest<Params, Query, Body>) {
|
|
55
|
-
|
|
54
|
+
await Context.setOptionalOrganizationScope();
|
|
56
55
|
const {user} = await Context.authenticate()
|
|
57
56
|
|
|
58
57
|
if (user.isApiUser) {
|
|
@@ -138,7 +137,7 @@ export class ExportToExcelEndpoint extends Endpoint<Params, Query, Body, Respons
|
|
|
138
137
|
}))
|
|
139
138
|
}
|
|
140
139
|
|
|
141
|
-
async job(loader: ExcelExporter<
|
|
140
|
+
async job(loader: ExcelExporter<unknown>, request: ExcelExportRequest, type: string): Promise<string> {
|
|
142
141
|
// Only run 1 export per user at the same time
|
|
143
142
|
return await QueueHandler.schedule('user-export-to-excel-' + Context.user!.id, async () => {
|
|
144
143
|
// Allow maximum 2 running Excel jobs at the same time for all users
|
|
@@ -10,6 +10,8 @@ import { AuthenticatedStructures } from '../../../helpers/AuthenticatedStructure
|
|
|
10
10
|
import { Context } from '../../../helpers/Context';
|
|
11
11
|
import { MemberUserSyncer } from '../../../helpers/MemberUserSyncer';
|
|
12
12
|
import { SetupStepUpdater } from '../../../helpers/SetupStepsUpdater';
|
|
13
|
+
import { MembershipCharger } from '../../../helpers/MembershipCharger';
|
|
14
|
+
import { QueueHandler } from '@stamhoofd/queues';
|
|
13
15
|
|
|
14
16
|
type Params = Record<string, never>;
|
|
15
17
|
type Query = undefined;
|
|
@@ -71,9 +73,9 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
71
73
|
}
|
|
72
74
|
return null
|
|
73
75
|
}
|
|
74
|
-
|
|
75
|
-
const updateRegistrations = new Map<string, Registration>();
|
|
76
|
+
|
|
76
77
|
const updateMembershipMemberIds = new Set<string>()
|
|
78
|
+
const updateMembershipsForOrganizations = new Set<string>()
|
|
77
79
|
|
|
78
80
|
// Loop all members one by one
|
|
79
81
|
for (const put of request.body.getPuts()) {
|
|
@@ -471,7 +473,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
471
473
|
})
|
|
472
474
|
}
|
|
473
475
|
|
|
474
|
-
if (!membership.canDelete()) {
|
|
476
|
+
if (!membership.canDelete() && !Context.auth.hasPlatformFullAccess()) {
|
|
475
477
|
throw new SimpleError({
|
|
476
478
|
code: "invalid_field",
|
|
477
479
|
message: "Invalid invoice",
|
|
@@ -479,8 +481,8 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
479
481
|
})
|
|
480
482
|
}
|
|
481
483
|
|
|
482
|
-
membership.
|
|
483
|
-
|
|
484
|
+
await membership.doDelete();
|
|
485
|
+
updateMembershipsForOrganizations.add(membership.organizationId) // can influence free memberships in other members of same organization
|
|
484
486
|
updateMembershipMemberIds.add(member.id)
|
|
485
487
|
}
|
|
486
488
|
|
|
@@ -489,8 +491,38 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
489
491
|
}
|
|
490
492
|
}
|
|
491
493
|
|
|
494
|
+
await PatchOrganizationMembersEndpoint.deleteMembers(request.body.getDeletes())
|
|
495
|
+
|
|
496
|
+
for (const member of members) {
|
|
497
|
+
if (updateMembershipMemberIds.has(member.id)) {
|
|
498
|
+
await member.updateMemberships()
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
if (updateMembershipsForOrganizations.size) {
|
|
503
|
+
QueueHandler.schedule('update-membership-prices', async () => {
|
|
504
|
+
for (const id of updateMembershipsForOrganizations) {
|
|
505
|
+
await MembershipCharger.updatePrices(id)
|
|
506
|
+
}
|
|
507
|
+
}).catch(console.error);
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
if(shouldUpdateSetupSteps && organization) {
|
|
511
|
+
SetupStepUpdater.updateForOrganization(organization).catch(console.error);
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
return new Response(
|
|
515
|
+
await AuthenticatedStructures.membersBlob(members)
|
|
516
|
+
);
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
static async deleteMembers(ids: string[]) {
|
|
520
|
+
const updateGroups = new Set<string>();
|
|
521
|
+
const updateRegistrations = new Map<string, Registration>();
|
|
522
|
+
const updateSteps = new Set<string>();
|
|
523
|
+
|
|
492
524
|
// Loop all members one by one
|
|
493
|
-
for (const id of
|
|
525
|
+
for (const id of ids) {
|
|
494
526
|
const member = await Member.getWithRegistrations(id)
|
|
495
527
|
if (!member || !await Context.auth.canDeleteMember(member)) {
|
|
496
528
|
throw Context.auth.error("Je hebt niet voldoende rechten om dit lid te verwijderen")
|
|
@@ -500,16 +532,12 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
500
532
|
await User.deleteForDeletedMember(member.id)
|
|
501
533
|
await BalanceItem.deleteForDeletedMember(member.id)
|
|
502
534
|
await member.delete()
|
|
503
|
-
shouldUpdateSetupSteps = true
|
|
504
535
|
|
|
505
536
|
for(const registration of member.registrations) {
|
|
506
537
|
const groupId = registration.groupId;
|
|
507
|
-
const group = await getGroup(groupId);
|
|
508
538
|
updateRegistrations.set(registration.id, registration);
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
updateGroups.set(group.id, group)
|
|
512
|
-
}
|
|
539
|
+
updateGroups.add(groupId);
|
|
540
|
+
updateSteps.add(registration.organizationId);
|
|
513
541
|
}
|
|
514
542
|
}
|
|
515
543
|
|
|
@@ -517,25 +545,19 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
517
545
|
registration.scheduleStockUpdate();
|
|
518
546
|
}
|
|
519
547
|
|
|
548
|
+
const groups = await Group.getByIDs(...Array.from(updateGroups));
|
|
549
|
+
|
|
520
550
|
// Loop all groups and update occupancy if needed
|
|
521
|
-
for (const group of
|
|
551
|
+
for (const group of groups) {
|
|
522
552
|
await group.updateOccupancy()
|
|
523
553
|
await group.save()
|
|
524
554
|
}
|
|
525
|
-
|
|
526
|
-
for (const member of members) {
|
|
527
|
-
if (updateMembershipMemberIds.has(member.id)) {
|
|
528
|
-
await member.updateMemberships()
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
555
|
|
|
532
|
-
|
|
556
|
+
const organizations = await Organization.getByIDs(...Array.from(updateSteps));
|
|
557
|
+
|
|
558
|
+
for (const organization of organizations) {
|
|
533
559
|
SetupStepUpdater.updateForOrganization(organization).catch(console.error);
|
|
534
560
|
}
|
|
535
|
-
|
|
536
|
-
return new Response(
|
|
537
|
-
await AuthenticatedStructures.membersBlob(members)
|
|
538
|
-
);
|
|
539
561
|
}
|
|
540
562
|
|
|
541
563
|
static async checkDuplicate(member: Member) {
|
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
import { AutoEncoderPatchType, Decoder,
|
|
1
|
+
import { AutoEncoderPatchType, Decoder, isPatchableArray, patchObject } from "@simonbackx/simple-encoding";
|
|
2
2
|
import { DecodedRequest, Endpoint, Request, Response } from "@simonbackx/simple-endpoints";
|
|
3
3
|
import { Organization, Platform, RegistrationPeriod } from "@stamhoofd/models";
|
|
4
4
|
import { MemberResponsibility, PlatformConfig, PlatformPremiseType, Platform as PlatformStruct } from "@stamhoofd/structures";
|
|
5
5
|
|
|
6
6
|
import { SimpleError } from "@simonbackx/simple-errors";
|
|
7
|
+
import { QueueHandler } from "@stamhoofd/queues";
|
|
7
8
|
import { Context } from "../../../helpers/Context";
|
|
8
|
-
import {
|
|
9
|
-
import { PeriodHelper } from "../../../helpers/PeriodHelper";
|
|
9
|
+
import { MembershipCharger } from "../../../helpers/MembershipCharger";
|
|
10
10
|
import { MembershipHelper } from "../../../helpers/MembershipHelper";
|
|
11
|
+
import { PeriodHelper } from "../../../helpers/PeriodHelper";
|
|
12
|
+
import { SetupStepUpdater } from "../../../helpers/SetupStepsUpdater";
|
|
11
13
|
|
|
12
14
|
type Params = Record<string, never>;
|
|
13
15
|
type Query = undefined;
|
|
@@ -174,7 +176,12 @@ export class PatchPlatformEndpoint extends Endpoint<
|
|
|
174
176
|
await platform.save();
|
|
175
177
|
|
|
176
178
|
if (shouldUpdateMemberships) {
|
|
177
|
-
|
|
179
|
+
if (!QueueHandler.isRunning('update-membership-prices')) {
|
|
180
|
+
QueueHandler.schedule('update-membership-prices', async () => {
|
|
181
|
+
await MembershipCharger.updatePrices()
|
|
182
|
+
await MembershipHelper.updateAll()
|
|
183
|
+
}).catch(console.error);
|
|
184
|
+
}
|
|
178
185
|
}
|
|
179
186
|
|
|
180
187
|
if (shouldMoveToPeriod) {
|
|
@@ -134,6 +134,8 @@ export class PatchUserMembersEndpoint extends Endpoint<Params, Query, Body, Resp
|
|
|
134
134
|
// Give access to created members
|
|
135
135
|
await Member.users.reverse("members").link(user, addedMembers)
|
|
136
136
|
}
|
|
137
|
+
|
|
138
|
+
await PatchOrganizationMembersEndpoint.deleteMembers(request.body.getDeletes())
|
|
137
139
|
|
|
138
140
|
members = await Member.getMembersWithRegistrationForUser(user)
|
|
139
141
|
|