@stamhoofd/backend 2.57.1 → 2.59.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 (48) hide show
  1. package/index.ts +6 -1
  2. package/package.json +13 -13
  3. package/src/audit-logs/EventLogger.ts +30 -0
  4. package/src/audit-logs/GroupLogger.ts +95 -0
  5. package/src/audit-logs/MemberLogger.ts +24 -0
  6. package/src/audit-logs/MemberPlatformMembershipLogger.ts +57 -0
  7. package/src/audit-logs/MemberResponsibilityRecordLogger.ts +69 -0
  8. package/src/audit-logs/ModelLogger.ts +218 -0
  9. package/src/audit-logs/OrderLogger.ts +57 -0
  10. package/src/audit-logs/OrganizationLogger.ts +26 -0
  11. package/src/audit-logs/OrganizationRegistrationPeriodLogger.ts +77 -0
  12. package/src/audit-logs/PaymentLogger.ts +43 -0
  13. package/src/audit-logs/PlatformLogger.ts +13 -0
  14. package/src/audit-logs/RegistrationLogger.ts +53 -0
  15. package/src/audit-logs/RegistrationPeriodLogger.ts +21 -0
  16. package/src/audit-logs/StripeAccountLogger.ts +47 -0
  17. package/src/audit-logs/WebshopLogger.ts +35 -0
  18. package/src/crons.ts +2 -1
  19. package/src/endpoints/global/events/PatchEventsEndpoint.ts +12 -24
  20. package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.ts +4 -18
  21. package/src/endpoints/global/payments/StripeWebhookEndpoint.ts +6 -3
  22. package/src/endpoints/global/platform/PatchPlatformEnpoint.ts +3 -18
  23. package/src/endpoints/global/registration/PatchUserMembersEndpoint.ts +0 -15
  24. package/src/endpoints/global/registration/RegisterMembersEndpoint.ts +5 -2
  25. package/src/endpoints/global/registration-periods/PatchRegistrationPeriodsEndpoint.ts +2 -2
  26. package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.ts +5 -15
  27. package/src/endpoints/organization/dashboard/registration-periods/PatchOrganizationRegistrationPeriodsEndpoint.ts +18 -28
  28. package/src/endpoints/organization/dashboard/stripe/ConnectStripeEndpoint.ts +2 -1
  29. package/src/endpoints/organization/dashboard/stripe/DeleteStripeAccountEndpoint.ts +2 -1
  30. package/src/endpoints/organization/dashboard/stripe/UpdateStripeAccountEndpoint.ts +6 -3
  31. package/src/endpoints/organization/dashboard/webshops/PatchWebshopOrdersEndpoint.ts +7 -4
  32. package/src/endpoints/organization/webshops/PlaceOrderEndpoint.ts +8 -2
  33. package/src/helpers/AuthenticatedStructures.ts +16 -1
  34. package/src/helpers/Context.ts +8 -2
  35. package/src/helpers/MemberUserSyncer.ts +45 -40
  36. package/src/helpers/PeriodHelper.ts +31 -27
  37. package/src/helpers/TagHelper.ts +23 -20
  38. package/src/seeds/1722344162-update-membership.ts +2 -2
  39. package/src/seeds/1726572303-schedule-stock-updates.ts +2 -1
  40. package/src/services/AuditLogService.ts +89 -216
  41. package/src/services/BalanceItemPaymentService.ts +1 -1
  42. package/src/services/BalanceItemService.ts +14 -5
  43. package/src/services/MemberNumberService.ts +120 -0
  44. package/src/services/PaymentService.ts +199 -193
  45. package/src/services/PlatformMembershipService.ts +284 -0
  46. package/src/services/RegistrationService.ts +76 -27
  47. package/src/services/explainPatch.ts +528 -316
  48. package/src/helpers/MembershipHelper.ts +0 -54
@@ -0,0 +1,77 @@
1
+ import { Organization, OrganizationRegistrationPeriod, RegistrationPeriod } from '@stamhoofd/models';
2
+ import { getDefaultGenerator, ModelLogger } from './ModelLogger';
3
+ import { AuditLogPatchItem, AuditLogPatchItemType, AuditLogReplacement, AuditLogReplacementType, AuditLogType } from '@stamhoofd/structures';
4
+
5
+ const defaultGenerator = getDefaultGenerator({
6
+ created: AuditLogType.OrganizationEdited,
7
+ updated: AuditLogType.OrganizationEdited,
8
+ deleted: AuditLogType.OrganizationEdited,
9
+ });
10
+
11
+ export const OrganizationRegistrationPeriodLogger = new ModelLogger(OrganizationRegistrationPeriod, {
12
+ async optionsGenerator(event) {
13
+ const result = await defaultGenerator(event);
14
+
15
+ if (!result) {
16
+ return;
17
+ }
18
+
19
+ // Load data
20
+ const organization = await Organization.getByID(event.model.organizationId);
21
+ if (!organization) {
22
+ return;
23
+ }
24
+
25
+ const period = await RegistrationPeriod.getByID(event.model.periodId);
26
+ if (!period) {
27
+ return;
28
+ }
29
+
30
+ return {
31
+ ...result,
32
+ data: {
33
+ organization,
34
+ period,
35
+ },
36
+ };
37
+ },
38
+
39
+ createReplacements(_, { data }) {
40
+ return new Map([
41
+ ['o', AuditLogReplacement.create({
42
+ id: data.organization.id,
43
+ value: data.organization.name,
44
+ type: AuditLogReplacementType.Organization,
45
+ })],
46
+ ]);
47
+ },
48
+
49
+ postProcess(event, options, log) {
50
+ const prependKey = AuditLogReplacement.create({
51
+ id: event.model.periodId,
52
+ value: options.data.period.getStructure().name,
53
+ type: AuditLogReplacementType.RegistrationPeriod,
54
+ });
55
+
56
+ // Prefix changes
57
+ for (const item of log.patchList) {
58
+ item.key = item.key.prepend(prependKey);
59
+ }
60
+
61
+ if (event.type === 'created') {
62
+ // Add create patch
63
+ log.patchList.push(AuditLogPatchItem.create({
64
+ key: prependKey,
65
+ type: AuditLogPatchItemType.Added,
66
+ }));
67
+ }
68
+
69
+ if (event.type === 'deleted') {
70
+ // Add delete patch
71
+ log.patchList.push(AuditLogPatchItem.create({
72
+ key: prependKey,
73
+ type: AuditLogPatchItemType.Removed,
74
+ }));
75
+ }
76
+ },
77
+ });
@@ -0,0 +1,43 @@
1
+ import { Payment } from '@stamhoofd/models';
2
+ import { AuditLogReplacement, AuditLogReplacementType, AuditLogType, PaymentMethod, PaymentMethodHelper, PaymentStatusHelper } from '@stamhoofd/structures';
3
+ import { Formatter } from '@stamhoofd/utility';
4
+ import { getDefaultGenerator, ModelLogger } from './ModelLogger';
5
+
6
+ export const PaymentLogger = new ModelLogger(Payment, {
7
+ skipKeys: ['transferFee'],
8
+
9
+ optionsGenerator: getDefaultGenerator({
10
+ created: AuditLogType.PaymentAdded,
11
+ updated: AuditLogType.PaymentEdited,
12
+ deleted: AuditLogType.PaymentDeleted,
13
+ }),
14
+
15
+ generateDescription(event, options) {
16
+ if (event.type === 'created') {
17
+ let description = `Status: ${PaymentStatusHelper.getNameCapitalized(event.model.status)}\n`
18
+ + `Bedrag: ${Formatter.price(event.model.price)}`;
19
+
20
+ if (event.model.method === PaymentMethod.Transfer && event.model.transferDescription) {
21
+ description += `\nMededeling: ${event.model.transferDescription}`;
22
+ }
23
+
24
+ return description;
25
+ }
26
+ },
27
+
28
+ createReplacements(model, options) {
29
+ let name = `${PaymentMethodHelper.getPaymentName(model.method)}`;
30
+
31
+ if (model.customer?.dynamicName) {
32
+ name += ` van ${model.customer.dynamicName}`;
33
+ }
34
+
35
+ return new Map([
36
+ ['p', AuditLogReplacement.create({
37
+ id: model.id,
38
+ value: name,
39
+ type: AuditLogReplacementType.Payment,
40
+ })],
41
+ ]);
42
+ },
43
+ });
@@ -0,0 +1,13 @@
1
+ import { Platform } from '@stamhoofd/models';
2
+ import { getDefaultGenerator, ModelLogger } from './ModelLogger';
3
+ import { AuditLogType } from '@stamhoofd/structures';
4
+
5
+ export const PlatformLogger = new ModelLogger(Platform, {
6
+ optionsGenerator: getDefaultGenerator({
7
+ updated: AuditLogType.PlatformSettingsChanged,
8
+ }),
9
+
10
+ postProcess(event, options, log) {
11
+ log.organizationId = null;
12
+ },
13
+ });
@@ -0,0 +1,53 @@
1
+ import { Group, Member, Registration } from '@stamhoofd/models';
2
+ import { ModelLogger } from './ModelLogger';
3
+ import { AuditLogReplacement, AuditLogReplacementType, AuditLogType } from '@stamhoofd/structures';
4
+
5
+ export const RegistrationLogger = new ModelLogger(Registration, {
6
+ async optionsGenerator(event) {
7
+ if (event.type === 'created' && event.model.registeredAt === null) {
8
+ // Ignored for now
9
+ return;
10
+ }
11
+ const wasActive = event.type === 'updated' ? (!event.originalFields.deactivatedAt && !!event.originalFields.registeredAt) : true;
12
+ const isActive = event.type === 'deleted' ? false : (!event.model.deactivatedAt && !!event.model.registeredAt);
13
+
14
+ if (wasActive === isActive) {
15
+ return;
16
+ }
17
+
18
+ const member = await Member.getByID(event.model.memberId);
19
+ const group = await Group.getByID(event.model.groupId);
20
+
21
+ if (!member || !group) {
22
+ return;
23
+ }
24
+
25
+ return {
26
+ type: wasActive ? AuditLogType.MemberUnregistered : AuditLogType.MemberRegistered,
27
+ generatePatchList: false,
28
+ data: { member, group },
29
+ objectId: member.id,
30
+ };
31
+ },
32
+
33
+ createReplacements(_, { data }) {
34
+ return new Map([
35
+ ['m', AuditLogReplacement.create({
36
+ id: data.member.id,
37
+ value: data.member.details.name,
38
+ type: AuditLogReplacementType.Member,
39
+ })],
40
+ ['g', AuditLogReplacement.create({
41
+ id: data.group.id,
42
+ value: data.group.settings.name,
43
+ type: AuditLogReplacementType.Group,
44
+ })],
45
+ ]);
46
+ },
47
+
48
+ generateDescription(event, options) {
49
+ const d = event.model.setRelation(Registration.group, options.data.group).getStructure();
50
+ return d.description;
51
+ },
52
+
53
+ });
@@ -0,0 +1,21 @@
1
+ import { RegistrationPeriod } from '@stamhoofd/models';
2
+ import { getDefaultGenerator, ModelLogger } from './ModelLogger';
3
+ import { AuditLogReplacement, AuditLogReplacementType, AuditLogType } from '@stamhoofd/structures';
4
+
5
+ export const RegistrationPeriodLogger = new ModelLogger(RegistrationPeriod, {
6
+ optionsGenerator: getDefaultGenerator({
7
+ created: AuditLogType.RegistrationPeriodAdded,
8
+ updated: AuditLogType.RegistrationPeriodEdited,
9
+ deleted: AuditLogType.RegistrationPeriodDeleted,
10
+ }),
11
+
12
+ createReplacements(model) {
13
+ return new Map([
14
+ ['p', AuditLogReplacement.create({
15
+ id: model.id,
16
+ value: model.getStructure().nameShort,
17
+ type: AuditLogReplacementType.RegistrationPeriod,
18
+ })],
19
+ ]);
20
+ },
21
+ });
@@ -0,0 +1,47 @@
1
+ import { StripeAccount } from '@stamhoofd/models';
2
+ import { AuditLogReplacement, AuditLogReplacementType, AuditLogSource, AuditLogType } from '@stamhoofd/structures';
3
+ import { getDefaultGenerator, ModelLogger } from './ModelLogger';
4
+
5
+ const defaultGenerator = getDefaultGenerator({
6
+ created: AuditLogType.StripeAccountAdded,
7
+ updated: AuditLogType.StripeAccountEdited,
8
+ deleted: AuditLogType.StripeAccountDeleted,
9
+ });
10
+
11
+ export const StripeAccountLogger = new ModelLogger(StripeAccount, {
12
+ async optionsGenerator(event) {
13
+ const result = await defaultGenerator(event);
14
+
15
+ if (!result) {
16
+ return;
17
+ }
18
+
19
+ if (event.type === 'updated' && 'status' in event.changedFields && event.changedFields.status === 'deleted') {
20
+ result.type = AuditLogType.StripeAccountDeleted;
21
+ result.generatePatchList = false;
22
+ }
23
+
24
+ return result;
25
+ },
26
+
27
+ createReplacements(model) {
28
+ return new Map([
29
+ ['a', AuditLogReplacement.create({
30
+ id: model.id,
31
+ value: model.accountId,
32
+ type: AuditLogReplacementType.StripeAccount,
33
+ })],
34
+ ]);
35
+ },
36
+
37
+ postProcess: (event, _options, log) => {
38
+ if (log.type === AuditLogType.StripeAccountEdited) {
39
+ // Never caused by a user
40
+ log.userId = null;
41
+
42
+ if (log.source === AuditLogSource.User) {
43
+ log.source = AuditLogSource.System;
44
+ }
45
+ }
46
+ },
47
+ });
@@ -0,0 +1,35 @@
1
+ import { Webshop } from '@stamhoofd/models';
2
+ import { getDefaultGenerator, ModelLogger } from './ModelLogger';
3
+ import { AuditLogReplacement, AuditLogReplacementType, AuditLogType } from '@stamhoofd/structures';
4
+
5
+ const defaultGenerator = getDefaultGenerator({
6
+ created: AuditLogType.WebshopAdded,
7
+ updated: AuditLogType.WebshopEdited,
8
+ deleted: AuditLogType.WebshopDeleted,
9
+ });
10
+
11
+ export const WebshopLogger = new ModelLogger(Webshop, {
12
+ skipKeys: [],
13
+ async optionsGenerator(event) {
14
+ const result = await defaultGenerator(event);
15
+
16
+ if (!result) {
17
+ return;
18
+ }
19
+
20
+ // todo: when placing an order / marking an order as paid
21
+ // we should not log any stock changes
22
+
23
+ return result;
24
+ },
25
+
26
+ createReplacements: (model) => {
27
+ return new Map([
28
+ ['w', AuditLogReplacement.create({
29
+ id: model.id,
30
+ value: model.meta.name,
31
+ type: AuditLogReplacementType.Webshop,
32
+ })],
33
+ ]);
34
+ },
35
+ });
package/src/crons.ts CHANGED
@@ -14,6 +14,7 @@ import { ExchangePaymentEndpoint } from './endpoints/organization/shared/Exchang
14
14
  import { checkSettlements } from './helpers/CheckSettlements';
15
15
  import { ForwardHandler } from './helpers/ForwardHandler';
16
16
  import { PaymentService } from './services/PaymentService';
17
+ import { RegistrationService } from './services/RegistrationService';
17
18
 
18
19
  // Importing postmark returns undefined (this is a bug, so we need to use require)
19
20
  // eslint-disable-next-line @typescript-eslint/no-require-imports
@@ -595,7 +596,7 @@ async function checkReservedUntil() {
595
596
  });
596
597
 
597
598
  for (const registration of registrations) {
598
- registration.scheduleStockUpdate();
599
+ RegistrationService.scheduleStockUpdate(registration.id);
599
600
  }
600
601
 
601
602
  // Update occupancy
@@ -1,7 +1,7 @@
1
1
  import { AutoEncoderPatchType, Decoder, PatchableArrayAutoEncoder, PatchableArrayDecoder, patchObject, StringDecoder } from '@simonbackx/simple-encoding';
2
2
  import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
3
3
  import { Event, Group, Platform, RegistrationPeriod } from '@stamhoofd/models';
4
- import { Event as EventStruct, GroupType, NamedObject, Group as GroupStruct, AuditLogType } from '@stamhoofd/structures';
4
+ import { Event as EventStruct, GroupType, NamedObject, Group as GroupStruct, AuditLogType, AuditLogSource } from '@stamhoofd/structures';
5
5
 
6
6
  import { SimpleError } from '@simonbackx/simple-errors';
7
7
  import { SQL, SQLWhereSign } from '@stamhoofd/sql';
@@ -96,7 +96,9 @@ export class PatchEventsEndpoint extends Endpoint<Params, Query, Body, ResponseB
96
96
  put.group.organizationId,
97
97
  period,
98
98
  );
99
- await event.syncGroupRequirements(group);
99
+ await AuditLogService.setContext({ source: AuditLogSource.System }, async () => {
100
+ await event.syncGroupRequirements(group);
101
+ });
100
102
  event.groupId = group.id;
101
103
  }
102
104
 
@@ -107,15 +109,9 @@ export class PatchEventsEndpoint extends Endpoint<Params, Query, Body, ResponseB
107
109
  await event.save();
108
110
 
109
111
  events.push(event);
110
-
111
- await AuditLogService.log({
112
- type: AuditLogType.EventAdded,
113
- event,
114
- });
115
112
  }
116
113
 
117
114
  const patchingEvents = await Event.getByIDs(...request.body.getPatches().map(p => p.id));
118
- const initialStructs = (await AuthenticatedStructures.events(patchingEvents)).map(e => e.clone()); // Clone is required for audit log (otherwise references might change)
119
115
 
120
116
  for (const patch of request.body.getPatches()) {
121
117
  const event = patchingEvents.find(e => e.id === patch.id);
@@ -232,7 +228,11 @@ export class PatchEventsEndpoint extends Endpoint<Params, Query, Body, ResponseB
232
228
  // Correct period id if needed
233
229
  const period = await RegistrationPeriod.getByDate(event.startDate);
234
230
  if (event.groupId) {
235
- await PatchOrganizationRegistrationPeriodsEndpoint.patchGroup(GroupStruct.patch({ id: event.groupId }), period);
231
+ await AuditLogService.setContext({ source: AuditLogSource.System }, async () => {
232
+ if (event.groupId) {
233
+ await PatchOrganizationRegistrationPeriodsEndpoint.patchGroup(GroupStruct.patch({ id: event.groupId }), period);
234
+ }
235
+ });
236
236
  }
237
237
  }
238
238
  }
@@ -246,20 +246,13 @@ export class PatchEventsEndpoint extends Endpoint<Params, Query, Body, ResponseB
246
246
  if (event.groupId) {
247
247
  const group = await Group.getByID(event.groupId);
248
248
  if (group) {
249
- await event.syncGroupRequirements(group);
249
+ await AuditLogService.setContext({ source: AuditLogSource.System }, async () => {
250
+ await event.syncGroupRequirements(group);
251
+ });
250
252
  }
251
253
  }
252
254
 
253
255
  events.push(event);
254
-
255
- const struct = initialStructs.find(e => e.id === patch.id);
256
-
257
- await AuditLogService.log({
258
- type: AuditLogType.EventEdited,
259
- event,
260
- oldData: struct,
261
- patch,
262
- });
263
256
  }
264
257
 
265
258
  for (const id of request.body.getDeletes()) {
@@ -276,11 +269,6 @@ export class PatchEventsEndpoint extends Endpoint<Params, Query, Body, ResponseB
276
269
  }
277
270
 
278
271
  await event.delete();
279
-
280
- await AuditLogService.log({
281
- type: AuditLogType.EventDeleted,
282
- event,
283
- });
284
272
  }
285
273
 
286
274
  const structures = await AuthenticatedStructures.events(events);
@@ -14,6 +14,8 @@ import { Context } from '../../../helpers/Context';
14
14
  import { MembershipCharger } from '../../../helpers/MembershipCharger';
15
15
  import { MemberUserSyncer } from '../../../helpers/MemberUserSyncer';
16
16
  import { AuditLogService } from '../../../services/AuditLogService';
17
+ import { PlatformMembershipService } from '../../../services/PlatformMembershipService';
18
+ import { RegistrationService } from '../../../services/RegistrationService';
17
19
 
18
20
  type Params = Record<string, never>;
19
21
  type Query = undefined;
@@ -143,13 +145,6 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
143
145
 
144
146
  // Auto link users based on data
145
147
  await MemberUserSyncer.onChangeMember(member);
146
-
147
- if (!duplicate) {
148
- await AuditLogService.log({
149
- type: AuditLogType.MemberAdded,
150
- member: member,
151
- });
152
- }
153
148
  }
154
149
 
155
150
  let shouldUpdateSetupSteps = false;
@@ -205,15 +200,6 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
205
200
 
206
201
  await member.save();
207
202
 
208
- if (patch.details) {
209
- await AuditLogService.log({
210
- type: AuditLogType.MemberEdited,
211
- member: member,
212
- oldMemberDetails: originalDetails,
213
- memberDetailsPatch: patch.details,
214
- });
215
- }
216
-
217
203
  // Update documents
218
204
  await Document.updateForMember(member.id);
219
205
 
@@ -553,7 +539,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
553
539
 
554
540
  for (const member of members) {
555
541
  if (updateMembershipMemberIds.has(member.id)) {
556
- await member.updateMemberships();
542
+ await PlatformMembershipService.updateMembershipsForId(member.id);
557
543
  }
558
544
  }
559
545
 
@@ -600,7 +586,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
600
586
  }
601
587
 
602
588
  for (const registration of updateRegistrations.values()) {
603
- registration.scheduleStockUpdate();
589
+ RegistrationService.scheduleStockUpdate(registration.id);
604
590
  }
605
591
 
606
592
  const groups = await Group.getByIDs(...Array.from(updateGroups));
@@ -5,8 +5,9 @@ import { Organization, StripeAccount, StripeCheckoutSession, StripePaymentIntent
5
5
  import { isDebouncedError, QueueHandler } from '@stamhoofd/queues';
6
6
 
7
7
  import { StripeHelper } from '../../../helpers/StripeHelper';
8
- import { ExchangePaymentEndpoint } from '../../organization/shared/ExchangePaymentEndpoint';
9
8
  import { PaymentService } from '../../../services/PaymentService';
9
+ import { AuditLog, AuditLogSource } from '@stamhoofd/structures';
10
+ import { AuditLogService } from '../../../services/AuditLogService';
10
11
 
11
12
  type Params = Record<string, never>;
12
13
  class Body extends AutoEncoder {
@@ -85,8 +86,10 @@ export class StripeWebookEndpoint extends Endpoint<Params, Query, Body, Response
85
86
  const id = account.id as string;
86
87
  const [model] = await StripeAccount.where({ accountId: id }, { limit: 1 });
87
88
  if (model) {
88
- model.setMetaFromStripeAccount(account);
89
- await model.save();
89
+ await AuditLogService.setContext({ userId: null, source: AuditLogSource.System }, async () => {
90
+ model.setMetaFromStripeAccount(account);
91
+ await model.save();
92
+ });
90
93
  }
91
94
  else {
92
95
  console.warn('Could not find stripe account with id', id);
@@ -1,16 +1,15 @@
1
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, SetupStepUpdater } from '@stamhoofd/models';
4
- import { AuditLogType, MemberResponsibility, PlatformConfig, PlatformPremiseType, Platform as PlatformStruct } from '@stamhoofd/structures';
4
+ import { MemberResponsibility, PlatformConfig, PlatformPremiseType, Platform as PlatformStruct } from '@stamhoofd/structures';
5
5
 
6
6
  import { SimpleError } from '@simonbackx/simple-errors';
7
7
  import { QueueHandler } from '@stamhoofd/queues';
8
8
  import { Context } from '../../../helpers/Context';
9
9
  import { MembershipCharger } from '../../../helpers/MembershipCharger';
10
- import { MembershipHelper } from '../../../helpers/MembershipHelper';
11
10
  import { PeriodHelper } from '../../../helpers/PeriodHelper';
12
11
  import { TagHelper } from '../../../helpers/TagHelper';
13
- import { AuditLogService } from '../../../services/AuditLogService';
12
+ import { PlatformMembershipService } from '../../../services/PlatformMembershipService';
14
13
 
15
14
  type Params = Record<string, never>;
16
15
  type Query = undefined;
@@ -51,8 +50,6 @@ export class PatchPlatformEndpoint extends Endpoint<
51
50
  const platform = await Platform.getShared();
52
51
 
53
52
  if (request.body.privateConfig) {
54
- const oldConfig = platform.privateConfig.clone();
55
-
56
53
  // Did we patch roles?
57
54
  if (request.body.privateConfig.roles) {
58
55
  if (!Context.auth.canManagePlatformAdmins()) {
@@ -77,12 +74,6 @@ export class PatchPlatformEndpoint extends Endpoint<
77
74
  request.body.privateConfig.emails,
78
75
  );
79
76
  }
80
-
81
- await AuditLogService.log({
82
- type: AuditLogType.PlatformSettingsChanged,
83
- oldConfig,
84
- patch: request.body.privateConfig,
85
- });
86
77
  }
87
78
 
88
79
  let shouldUpdateSetupSteps = false;
@@ -116,12 +107,6 @@ export class PatchPlatformEndpoint extends Endpoint<
116
107
  else {
117
108
  platform.config = patchObject(platform.config, newConfig);
118
109
  }
119
-
120
- await AuditLogService.log({
121
- type: AuditLogType.PlatformSettingsChanged,
122
- oldConfig,
123
- patch: newConfig,
124
- });
125
110
  }
126
111
 
127
112
  if (newConfig.tags && isPatchableArray(newConfig.tags) && newConfig.tags.changes.length > 0) {
@@ -219,7 +204,7 @@ export class PatchPlatformEndpoint extends Endpoint<
219
204
  if (!QueueHandler.isRunning('update-membership-prices')) {
220
205
  QueueHandler.schedule('update-membership-prices', async () => {
221
206
  await MembershipCharger.updatePrices();
222
- await MembershipHelper.updateAll();
207
+ await PlatformMembershipService.updateAll();
223
208
  }).catch(console.error);
224
209
  }
225
210
  }
@@ -69,11 +69,6 @@ export class PatchUserMembersEndpoint extends Endpoint<Params, Query, Body, Resp
69
69
 
70
70
  await member.save();
71
71
  addedMembers.push(member);
72
-
73
- await AuditLogService.log({
74
- type: AuditLogType.MemberAdded,
75
- member: member,
76
- });
77
72
  }
78
73
 
79
74
  // Modify members
@@ -90,7 +85,6 @@ export class PatchUserMembersEndpoint extends Endpoint<Params, Query, Body, Resp
90
85
  }
91
86
  const securityCode = struct.details?.securityCode; // will get cleared after the filter
92
87
  struct = await Context.auth.filterMemberPatch(member, struct);
93
- const originalDetails = member.details.clone();
94
88
 
95
89
  if (struct.details) {
96
90
  if (struct.details.isPut()) {
@@ -129,15 +123,6 @@ export class PatchUserMembersEndpoint extends Endpoint<Params, Query, Body, Resp
129
123
  await member.save();
130
124
  await MemberUserSyncer.onChangeMember(member);
131
125
 
132
- if (struct.details) {
133
- await AuditLogService.log({
134
- type: AuditLogType.MemberEdited,
135
- member: member,
136
- oldMemberDetails: originalDetails,
137
- memberDetailsPatch: struct.details,
138
- });
139
- }
140
-
141
126
  // Update documents
142
127
  await Document.updateForMember(member.id);
143
128
  }
@@ -583,10 +583,13 @@ export class RegisterMembersEndpoint extends Endpoint<Params, Query, Body, Respo
583
583
  let paymentUrl: string | null = null;
584
584
  let payment: Payment | null = null;
585
585
 
586
- // Delaying markign as valid as late as possible so any errors will prevent creating valid balance items
586
+ // Delay marking as valid as late as possible so any errors will prevent creating valid balance items
587
+ // Keep a copy because createdBalanceItems will be altered - and we don't want to mark added items as valid
588
+ const markValidList = [...createdBalanceItems, ...unrelatedCreatedBalanceItems];
589
+
587
590
  async function markValidIfNeeded() {
588
591
  if (shouldMarkValid) {
589
- for (const balanceItem of [...createdBalanceItems, ...unrelatedCreatedBalanceItems]) {
592
+ for (const balanceItem of markValidList) {
590
593
  // Mark valid
591
594
  await BalanceItemService.markPaid(balanceItem, payment, organization);
592
595
  }
@@ -1,11 +1,12 @@
1
1
  import { ConvertArrayToPatchableArray, Decoder, PatchableArrayAutoEncoder, PatchableArrayDecoder, StringDecoder, patchObject } from '@simonbackx/simple-encoding';
2
2
  import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
3
- import { RegistrationPeriod as RegistrationPeriodStruct } from '@stamhoofd/structures';
3
+ import { AuditLogType, RegistrationPeriod as RegistrationPeriodStruct } from '@stamhoofd/structures';
4
4
 
5
5
  import { SimpleError } from '@simonbackx/simple-errors';
6
6
  import { Platform, RegistrationPeriod } from '@stamhoofd/models';
7
7
  import { Context } from '../../../helpers/Context';
8
8
  import { PeriodHelper } from '../../../helpers/PeriodHelper';
9
+ import { AuditLogService } from '../../../services/AuditLogService';
9
10
 
10
11
  type Params = Record<string, never>;
11
12
  type Query = undefined;
@@ -74,7 +75,6 @@ export class PatchRegistrationPeriodsEndpoint extends Endpoint<Params, Query, Bo
74
75
  message: 'Registration period not found',
75
76
  });
76
77
  }
77
-
78
78
  if (patch.startDate !== undefined) {
79
79
  model.startDate = patch.startDate;
80
80
  }