@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.
Files changed (198) hide show
  1. package/eslint.config.mjs +5 -0
  2. package/index.ts +81 -74
  3. package/jest.config.cjs +10 -0
  4. package/migrations.ts +16 -14
  5. package/package.json +11 -11
  6. package/src/crons/clear-excel-cache.test.ts +48 -50
  7. package/src/crons/clear-excel-cache.ts +18 -18
  8. package/src/crons/setup-steps.ts +2 -2
  9. package/src/crons.ts +325 -306
  10. package/src/decoders/StringArrayDecoder.ts +7 -7
  11. package/src/decoders/StringNullableDecoder.ts +1 -2
  12. package/src/email-recipient-loaders/members.ts +22 -22
  13. package/src/endpoints/admin/memberships/ChargeMembershipsEndpoint.ts +8 -9
  14. package/src/endpoints/admin/memberships/GetChargeMembershipsSummaryEndpoint.ts +39 -40
  15. package/src/endpoints/admin/organizations/GetOrganizationsCountEndpoint.ts +8 -8
  16. package/src/endpoints/admin/organizations/GetOrganizationsEndpoint.ts +44 -45
  17. package/src/endpoints/admin/organizations/PatchOrganizationsEndpoint.ts +58 -57
  18. package/src/endpoints/auth/CreateAdminEndpoint.ts +48 -45
  19. package/src/endpoints/auth/CreateTokenEndpoint.test.ts +31 -31
  20. package/src/endpoints/auth/CreateTokenEndpoint.ts +146 -147
  21. package/src/endpoints/auth/DeleteTokenEndpoint.ts +7 -7
  22. package/src/endpoints/auth/DeleteUserEndpoint.ts +15 -15
  23. package/src/endpoints/auth/ForgotPasswordEndpoint.ts +17 -18
  24. package/src/endpoints/auth/GetOtherUserEndpoint.ts +9 -10
  25. package/src/endpoints/auth/GetUserEndpoint.test.ts +32 -35
  26. package/src/endpoints/auth/GetUserEndpoint.ts +5 -6
  27. package/src/endpoints/auth/PatchApiUserEndpoint.ts +35 -33
  28. package/src/endpoints/auth/PatchUserEndpoint.ts +55 -52
  29. package/src/endpoints/auth/PollEmailVerificationEndpoint.ts +9 -9
  30. package/src/endpoints/auth/RetryEmailVerificationEndpoint.ts +8 -8
  31. package/src/endpoints/auth/SignupEndpoint.ts +37 -36
  32. package/src/endpoints/auth/VerifyEmailEndpoint.ts +29 -28
  33. package/src/endpoints/global/addresses/SearchRegionsEndpoint.ts +33 -33
  34. package/src/endpoints/global/addresses/ValidateAddressEndpoint.ts +7 -7
  35. package/src/endpoints/global/caddy/CheckDomainCertEndpoint.ts +37 -37
  36. package/src/endpoints/global/email/CreateEmailEndpoint.ts +30 -30
  37. package/src/endpoints/global/email/GetEmailAddressEndpoint.ts +13 -13
  38. package/src/endpoints/global/email/GetEmailEndpoint.ts +13 -13
  39. package/src/endpoints/global/email/ManageEmailAddressEndpoint.ts +16 -16
  40. package/src/endpoints/global/email/PatchEmailEndpoint.ts +25 -25
  41. package/src/endpoints/global/events/GetEventsEndpoint.ts +43 -44
  42. package/src/endpoints/global/events/PatchEventsEndpoint.ts +127 -172
  43. package/src/endpoints/global/files/ExportToExcelEndpoint.ts +49 -50
  44. package/src/endpoints/global/files/GetFileCache.ts +13 -13
  45. package/src/endpoints/global/files/UploadFile.ts +51 -54
  46. package/src/endpoints/global/files/UploadImage.ts +53 -53
  47. package/src/endpoints/global/groups/GetGroupsEndpoint.ts +25 -25
  48. package/src/endpoints/global/members/GetMemberFamilyEndpoint.ts +24 -23
  49. package/src/endpoints/global/members/GetMembersCountEndpoint.ts +8 -8
  50. package/src/endpoints/global/members/GetMembersEndpoint.ts +105 -102
  51. package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.ts +240 -239
  52. package/src/endpoints/global/organizations/CheckRegisterCodeEndpoint.ts +12 -14
  53. package/src/endpoints/global/organizations/CreateOrganizationEndpoint.test.ts +32 -33
  54. package/src/endpoints/global/organizations/CreateOrganizationEndpoint.ts +48 -57
  55. package/src/endpoints/global/organizations/GetOrganizationFromDomainEndpoint.test.ts +21 -22
  56. package/src/endpoints/global/organizations/GetOrganizationFromDomainEndpoint.ts +28 -28
  57. package/src/endpoints/global/organizations/GetOrganizationFromUriEndpoint.ts +18 -18
  58. package/src/endpoints/global/organizations/SearchOrganizationEndpoint.test.ts +20 -20
  59. package/src/endpoints/global/organizations/SearchOrganizationEndpoint.ts +17 -17
  60. package/src/endpoints/global/payments/StripeWebhookEndpoint.ts +81 -75
  61. package/src/endpoints/global/platform/GetPlatformAdminsEndpoint.ts +14 -14
  62. package/src/endpoints/global/platform/GetPlatformEnpoint.ts +11 -11
  63. package/src/endpoints/global/platform/PatchPlatformEnpoint.ts +71 -68
  64. package/src/endpoints/global/registration/GetPaymentRegistrations.ts +27 -27
  65. package/src/endpoints/global/registration/GetUserBillingStatusEndpoint.ts +30 -30
  66. package/src/endpoints/global/registration/GetUserDetailedBillingStatusEndpoint.ts +34 -34
  67. package/src/endpoints/global/registration/GetUserDocumentsEndpoint.ts +26 -26
  68. package/src/endpoints/global/registration/GetUserMembersEndpoint.ts +12 -12
  69. package/src/endpoints/global/registration/PatchUserMembersEndpoint.ts +90 -90
  70. package/src/endpoints/global/registration/RegisterMembersEndpoint.test.ts +118 -121
  71. package/src/endpoints/global/registration/RegisterMembersEndpoint.ts +362 -350
  72. package/src/endpoints/global/registration-periods/GetRegistrationPeriodsEndpoint.ts +8 -9
  73. package/src/endpoints/global/registration-periods/PatchRegistrationPeriodsEndpoint.ts +21 -21
  74. package/src/endpoints/global/webshops/GetWebshopFromDomainEndpoint.ts +65 -65
  75. package/src/endpoints/organization/dashboard/billing/GetOrganizationBillingStatusEndpoint.ts +9 -9
  76. package/src/endpoints/organization/dashboard/billing/GetOrganizationDetailedBillingStatusEndpoint.ts +14 -14
  77. package/src/endpoints/organization/dashboard/documents/GetDocumentTemplateXML.ts +17 -17
  78. package/src/endpoints/organization/dashboard/documents/GetDocumentTemplatesEndpoint.ts +21 -21
  79. package/src/endpoints/organization/dashboard/documents/GetDocumentsEndpoint.ts +15 -15
  80. package/src/endpoints/organization/dashboard/documents/PatchDocumentEndpoint.ts +52 -52
  81. package/src/endpoints/organization/dashboard/documents/PatchDocumentTemplateEndpoint.ts +37 -37
  82. package/src/endpoints/organization/dashboard/email/CheckEmailBouncesEndpoint.ts +14 -14
  83. package/src/endpoints/organization/dashboard/email/EmailEndpoint.ts +113 -112
  84. package/src/endpoints/organization/dashboard/email-templates/GetEmailTemplatesEndpoint.ts +29 -29
  85. package/src/endpoints/organization/dashboard/email-templates/PatchEmailTemplatesEndpoint.ts +48 -47
  86. package/src/endpoints/organization/dashboard/mollie/CheckMollieEndpoint.ts +22 -21
  87. package/src/endpoints/organization/dashboard/mollie/ConnectMollieEndpoint.ts +13 -14
  88. package/src/endpoints/organization/dashboard/mollie/DisconnectMollieEndpoint.ts +12 -13
  89. package/src/endpoints/organization/dashboard/mollie/GetMollieDashboardEndpoint.ts +24 -24
  90. package/src/endpoints/organization/dashboard/nolt/CreateNoltTokenEndpoint.ts +10 -12
  91. package/src/endpoints/organization/dashboard/organization/GetOrganizationArchivedGroups.ts +14 -14
  92. package/src/endpoints/organization/dashboard/organization/GetOrganizationDeletedGroups.ts +13 -13
  93. package/src/endpoints/organization/dashboard/organization/GetOrganizationSSOEndpoint.ts +12 -12
  94. package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.test.ts +120 -124
  95. package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.ts +172 -173
  96. package/src/endpoints/organization/dashboard/organization/SetOrganizationDomainEndpoint.ts +88 -89
  97. package/src/endpoints/organization/dashboard/organization/SetOrganizationSSOEndpoint.ts +12 -12
  98. package/src/endpoints/organization/dashboard/payments/GetMemberBalanceEndpoint.ts +17 -17
  99. package/src/endpoints/organization/dashboard/payments/GetPaymentsCountEndpoint.ts +8 -8
  100. package/src/endpoints/organization/dashboard/payments/GetPaymentsEndpoint.ts +66 -67
  101. package/src/endpoints/organization/dashboard/payments/PatchBalanceItemsEndpoint.ts +47 -47
  102. package/src/endpoints/organization/dashboard/payments/PatchPaymentsEndpoint.ts +93 -91
  103. package/src/endpoints/organization/dashboard/registration-periods/GetOrganizationRegistrationPeriodsEndpoint.ts +16 -17
  104. package/src/endpoints/organization/dashboard/registration-periods/PatchOrganizationRegistrationPeriodsEndpoint.ts +170 -167
  105. package/src/endpoints/organization/dashboard/registration-periods/SetupStepReviewEndpoint.ts +25 -24
  106. package/src/endpoints/organization/dashboard/stripe/ConnectStripeEndpoint.ts +22 -23
  107. package/src/endpoints/organization/dashboard/stripe/DeleteStripeAccountEndpoint.ts +22 -22
  108. package/src/endpoints/organization/dashboard/stripe/GetStripeAccountLinkEndpoint.ts +17 -18
  109. package/src/endpoints/organization/dashboard/stripe/GetStripeAccountsEndpoint.ts +8 -9
  110. package/src/endpoints/organization/dashboard/stripe/GetStripeLoginLinkEndpoint.ts +17 -18
  111. package/src/endpoints/organization/dashboard/stripe/UpdateStripeAccountEndpoint.ts +14 -15
  112. package/src/endpoints/organization/dashboard/users/CreateApiUserEndpoint.ts +19 -19
  113. package/src/endpoints/organization/dashboard/users/DeleteUserEndpoint.ts +19 -19
  114. package/src/endpoints/organization/dashboard/users/GetApiUsersEndpoint.ts +14 -14
  115. package/src/endpoints/organization/dashboard/users/GetOrganizationAdminsEndpoint.ts +12 -12
  116. package/src/endpoints/organization/dashboard/webshops/CreateWebshopEndpoint.ts +103 -100
  117. package/src/endpoints/organization/dashboard/webshops/DeleteWebshopEndpoint.ts +11 -12
  118. package/src/endpoints/organization/dashboard/webshops/GetDiscountCodesEndpoint.ts +15 -15
  119. package/src/endpoints/organization/dashboard/webshops/GetWebshopOrdersEndpoint.ts +14 -14
  120. package/src/endpoints/organization/dashboard/webshops/GetWebshopTicketsEndpoint.ts +14 -14
  121. package/src/endpoints/organization/dashboard/webshops/GetWebshopUriAvailabilityEndpoint.ts +23 -23
  122. package/src/endpoints/organization/dashboard/webshops/PatchDiscountCodesEndpoint.ts +54 -52
  123. package/src/endpoints/organization/dashboard/webshops/PatchWebshopEndpoint.ts +84 -81
  124. package/src/endpoints/organization/dashboard/webshops/PatchWebshopOrdersEndpoint.ts +120 -111
  125. package/src/endpoints/organization/dashboard/webshops/PatchWebshopTicketsEndpoint.ts +24 -24
  126. package/src/endpoints/organization/dashboard/webshops/VerifyWebshopDomainEndpoint.ts +18 -18
  127. package/src/endpoints/organization/shared/ExchangePaymentEndpoint.ts +141 -130
  128. package/src/endpoints/organization/shared/GetDocumentHtml.ts +25 -25
  129. package/src/endpoints/organization/shared/GetPaymentEndpoint.ts +18 -18
  130. package/src/endpoints/organization/shared/auth/GetOrganizationEndpoint.test.ts +36 -37
  131. package/src/endpoints/organization/shared/auth/GetOrganizationEndpoint.ts +9 -9
  132. package/src/endpoints/organization/shared/auth/OpenIDConnectCallbackEndpoint.ts +11 -11
  133. package/src/endpoints/organization/shared/auth/OpenIDConnectStartEndpoint.ts +28 -27
  134. package/src/endpoints/organization/webshops/CheckWebshopDiscountCodesEndpoint.ts +20 -20
  135. package/src/endpoints/organization/webshops/GetOrderByPaymentEndpoint.ts +22 -22
  136. package/src/endpoints/organization/webshops/GetOrderEndpoint.ts +14 -14
  137. package/src/endpoints/organization/webshops/GetTicketsEndpoint.ts +57 -56
  138. package/src/endpoints/organization/webshops/GetWebshopEndpoint.test.ts +65 -66
  139. package/src/endpoints/organization/webshops/GetWebshopEndpoint.ts +18 -17
  140. package/src/endpoints/organization/webshops/PlaceOrderEndpoint.test.ts +124 -128
  141. package/src/endpoints/organization/webshops/PlaceOrderEndpoint.ts +154 -145
  142. package/src/excel-loaders/members.ts +102 -103
  143. package/src/excel-loaders/payments.ts +155 -156
  144. package/src/helpers/AddressValidator.test.ts +32 -32
  145. package/src/helpers/AddressValidator.ts +128 -122
  146. package/src/helpers/AdminPermissionChecker.ts +339 -236
  147. package/src/helpers/AuthenticatedStructures.ts +233 -134
  148. package/src/helpers/BuckarooHelper.ts +134 -134
  149. package/src/helpers/CheckSettlements.ts +94 -88
  150. package/src/helpers/Context.ts +87 -86
  151. package/src/helpers/CookieHelper.ts +23 -22
  152. package/src/helpers/EmailResumer.ts +10 -10
  153. package/src/helpers/FileCache.ts +62 -62
  154. package/src/helpers/ForwardHandler.test.ts +122 -124
  155. package/src/helpers/ForwardHandler.ts +76 -70
  156. package/src/helpers/MemberUserSyncer.ts +101 -96
  157. package/src/helpers/MembershipCharger.ts +69 -69
  158. package/src/helpers/MembershipHelper.ts +11 -12
  159. package/src/helpers/OpenIDConnectHelper.ts +85 -82
  160. package/src/helpers/PeriodHelper.ts +65 -70
  161. package/src/helpers/StripeHelper.ts +146 -137
  162. package/src/helpers/StripePayoutChecker.ts +51 -52
  163. package/src/helpers/ViesHelper.ts +46 -44
  164. package/src/helpers/fetchToAsyncIterator.ts +14 -14
  165. package/src/helpers/xlsxAddressTransformerColumnFactory.ts +50 -52
  166. package/src/middleware/ContextMiddleware.ts +5 -5
  167. package/src/migrations/1646578856-validate-addresses.ts +6 -9
  168. package/src/seeds/0000000000-example.ts +3 -5
  169. package/src/seeds/1715028563-user-permissions.ts +16 -18
  170. package/src/seeds/1722256498-group-update-occupancy.ts +12 -12
  171. package/src/seeds/1722344162-sync-member-users.ts +14 -15
  172. package/src/seeds/1722344162-update-membership.ts +6 -6
  173. package/src/seeds/1726055544-balance-item-paid.ts +4 -4
  174. package/src/seeds/1726055545-balance-item-pending.ts +4 -4
  175. package/src/seeds/1726494419-update-cached-outstanding-balance.ts +16 -16
  176. package/src/seeds/1726494420-update-cached-outstanding-balance-from-items.ts +12 -12
  177. package/src/seeds/1726572303-schedule-stock-updates.ts +12 -12
  178. package/src/seeds/1726847064-setup-steps.ts +16 -0
  179. package/src/sql-filters/balance-item-payments.ts +7 -7
  180. package/src/sql-filters/events.ts +14 -14
  181. package/src/sql-filters/members.ts +96 -96
  182. package/src/sql-filters/organizations.ts +139 -75
  183. package/src/sql-filters/payments.ts +28 -28
  184. package/src/sql-filters/registrations.ts +14 -14
  185. package/src/sql-sorters/events.ts +25 -25
  186. package/src/sql-sorters/members.ts +26 -26
  187. package/src/sql-sorters/organizations.ts +36 -36
  188. package/src/sql-sorters/payments.ts +26 -26
  189. package/tests/e2e/stock.test.ts +616 -621
  190. package/tests/e2e/tickets.test.ts +255 -260
  191. package/tests/helpers/StripeMocker.ts +177 -179
  192. package/tests/helpers/TestServer.ts +9 -9
  193. package/tests/jest.global.setup.ts +14 -13
  194. package/tests/jest.setup.ts +33 -32
  195. package/.eslintrc.js +0 -61
  196. package/jest.config.js +0 -11
  197. package/src/helpers/SetupStepsUpdater.ts +0 -359
  198. package/src/seeds/1724076679-setup-steps.ts +0 -16
@@ -1,22 +1,21 @@
1
1
  import { OneToManyRelation } from '@simonbackx/simple-database';
2
2
  import { ConvertArrayToPatchableArray, Decoder, PatchableArrayAutoEncoder, PatchableArrayDecoder, StringDecoder } from '@simonbackx/simple-encoding';
3
- import { DecodedRequest, Endpoint, Request, Response } from "@simonbackx/simple-endpoints";
4
- import { SimpleError } from "@simonbackx/simple-errors";
5
- import { BalanceItem, Document, Group, Member, MemberFactory, MemberPlatformMembership, MemberResponsibilityRecord, MemberWithRegistrations, Organization, Platform, Registration, User } from '@stamhoofd/models';
6
- import { GroupType, MemberWithRegistrationsBlob, MembersBlob, PermissionLevel } from "@stamhoofd/structures";
3
+ import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
4
+ import { SimpleError } from '@simonbackx/simple-errors';
5
+ import { BalanceItem, Document, Group, Member, MemberFactory, MemberPlatformMembership, MemberResponsibilityRecord, MemberWithRegistrations, Organization, Platform, Registration, SetupStepUpdater, User } from '@stamhoofd/models';
6
+ import { GroupType, MemberWithRegistrationsBlob, MembersBlob, PermissionLevel } from '@stamhoofd/structures';
7
7
  import { Formatter } from '@stamhoofd/utility';
8
8
 
9
+ import { QueueHandler } from '@stamhoofd/queues';
9
10
  import { AuthenticatedStructures } from '../../../helpers/AuthenticatedStructures';
10
11
  import { Context } from '../../../helpers/Context';
11
- import { MemberUserSyncer } from '../../../helpers/MemberUserSyncer';
12
- import { SetupStepUpdater } from '../../../helpers/SetupStepsUpdater';
13
12
  import { MembershipCharger } from '../../../helpers/MembershipCharger';
14
- import { QueueHandler } from '@stamhoofd/queues';
13
+ import { MemberUserSyncer } from '../../../helpers/MemberUserSyncer';
15
14
 
16
15
  type Params = Record<string, never>;
17
16
  type Query = undefined;
18
- type Body = PatchableArrayAutoEncoder<MemberWithRegistrationsBlob>
19
- type ResponseBody = MembersBlob
17
+ type Body = PatchableArrayAutoEncoder<MemberWithRegistrationsBlob>;
18
+ type ResponseBody = MembersBlob;
20
19
 
21
20
  /**
22
21
  * One endpoint to create, patch and delete members and their registrations and payments
@@ -24,14 +23,14 @@ type ResponseBody = MembersBlob
24
23
 
25
24
  export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Body, ResponseBody> {
26
25
  // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
27
- bodyDecoder = new PatchableArrayDecoder(MemberWithRegistrationsBlob as any, MemberWithRegistrationsBlob.patchType(), StringDecoder) as any as Decoder<ConvertArrayToPatchableArray<MemberWithRegistrationsBlob[]>>
26
+ bodyDecoder = new PatchableArrayDecoder(MemberWithRegistrationsBlob as any, MemberWithRegistrationsBlob.patchType(), StringDecoder) as any as Decoder<ConvertArrayToPatchableArray<MemberWithRegistrationsBlob[]>>;
28
27
 
29
28
  protected doesMatch(request: Request): [true, Params] | [false] {
30
- if (request.method != "PATCH") {
29
+ if (request.method !== 'PATCH') {
31
30
  return [false];
32
31
  }
33
32
 
34
- const params = Endpoint.parseParameters(request.url, "/organization/members", {});
33
+ const params = Endpoint.parseParameters(request.url, '/organization/members', {});
35
34
 
36
35
  if (params) {
37
36
  return [true, params as Params];
@@ -41,240 +40,241 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
41
40
 
42
41
  async handle(request: DecodedRequest<Params, Query, Body>) {
43
42
  const organization = await Context.setOptionalOrganizationScope();
44
- await Context.authenticate()
43
+ await Context.authenticate();
45
44
 
46
45
  // Fast throw first (more in depth checking for patches later)
47
46
  if (organization) {
48
47
  if (!await Context.auth.hasSomeAccess(organization.id)) {
49
- throw Context.auth.error()
50
- }
51
- } else {
48
+ throw Context.auth.error();
49
+ }
50
+ }
51
+ else {
52
52
  if (!Context.auth.hasSomePlatformAccess()) {
53
- throw Context.auth.error()
54
- }
53
+ throw Context.auth.error();
54
+ }
55
55
  }
56
56
 
57
- const members: MemberWithRegistrations[] = []
57
+ const members: MemberWithRegistrations[] = [];
58
58
 
59
- const platform = await Platform.getShared()
59
+ const platform = await Platform.getShared();
60
60
 
61
61
  // Cache
62
- const groups: Group[] = []
63
-
62
+ const groups: Group[] = [];
63
+
64
64
  async function getGroup(id: string) {
65
- const f = groups.find(g => g.id === id)
65
+ const f = groups.find(g => g.id === id);
66
66
  if (f) {
67
- return f
67
+ return f;
68
68
  }
69
- const group = await Group.getByID(id)
69
+ const group = await Group.getByID(id);
70
70
  if (group) {
71
- groups.push(group)
72
- return group
71
+ groups.push(group);
72
+ return group;
73
73
  }
74
- return null
74
+ return null;
75
75
  }
76
76
 
77
- const updateMembershipMemberIds = new Set<string>()
78
- const updateMembershipsForOrganizations = new Set<string>()
77
+ const updateMembershipMemberIds = new Set<string>();
78
+ const updateMembershipsForOrganizations = new Set<string>();
79
79
 
80
80
  // Loop all members one by one
81
81
  for (const put of request.body.getPuts()) {
82
- const struct = put.put
82
+ const struct = put.put;
83
83
  let member = new Member()
84
- .setManyRelation(Member.registrations as any as OneToManyRelation<"registrations", Member, Registration & {group: Group}>, [])
85
- .setManyRelation(Member.users, [])
86
- member.id = struct.id
84
+ .setManyRelation(Member.registrations as any as OneToManyRelation<'registrations', Member, Registration & { group: Group }>, [])
85
+ .setManyRelation(Member.users, []);
86
+ member.id = struct.id;
87
87
 
88
88
  if (organization && STAMHOOFD.userMode !== 'platform') {
89
- member.organizationId = organization.id
89
+ member.organizationId = organization.id;
90
90
  }
91
91
 
92
- struct.details.cleanData()
93
- member.details = struct.details
92
+ struct.details.cleanData();
93
+ member.details = struct.details;
94
94
 
95
95
  const duplicate = await PatchOrganizationMembersEndpoint.checkDuplicate(member);
96
96
  if (duplicate) {
97
97
  // Merge data
98
- duplicate.details.merge(member.details)
99
- member = duplicate
98
+ duplicate.details.merge(member.details);
99
+ member = duplicate;
100
100
 
101
101
  // You need write permissions, because a user can potentially earn write permissions on a member
102
102
  // by registering it
103
103
  if (!await Context.auth.canAccessMember(duplicate, PermissionLevel.Write)) {
104
104
  throw new SimpleError({
105
- code: "known_member_missing_rights",
106
- message: "Creating known member without sufficient access rights",
107
- human: "Dit lid is al bekend in het systeem, maar je hebt er geen toegang tot. Vraag iemand met de juiste toegangsrechten om dit lid voor jou toe te voegen, of vraag het lid om zelf in te schrijven via het ledenportaal.",
108
- statusCode: 400
109
- })
105
+ code: 'known_member_missing_rights',
106
+ message: 'Creating known member without sufficient access rights',
107
+ human: 'Dit lid is al bekend in het systeem, maar je hebt er geen toegang tot. Vraag iemand met de juiste toegangsrechten om dit lid voor jou toe te voegen, of vraag het lid om zelf in te schrijven via het ledenportaal.',
108
+ statusCode: 400,
109
+ });
110
110
  }
111
111
  }
112
112
 
113
113
  // We risk creating a new member without being able to access it manually afterwards
114
114
  if ((organization && !await Context.auth.hasFullAccess(organization.id)) || (!organization && !Context.auth.hasPlatformFullAccess())) {
115
115
  throw new SimpleError({
116
- code: "missing_group",
117
- message: "Missing group",
118
- human: "Je moet hoofdbeheerder zijn om een lid toe te voegen in het systeem",
119
- statusCode: 400
120
- })
116
+ code: 'missing_group',
117
+ message: 'Missing group',
118
+ human: 'Je moet hoofdbeheerder zijn om een lid toe te voegen in het systeem',
119
+ statusCode: 400,
120
+ });
121
121
  }
122
122
 
123
123
  if (STAMHOOFD.userMode !== 'platform' && !member.organizationId) {
124
124
  throw new SimpleError({
125
- code: "missing_organization",
126
- message: "Missing organization",
127
- human: "Je moet een organisatie selecteren voor dit lid",
128
- statusCode: 400
129
- })
125
+ code: 'missing_organization',
126
+ message: 'Missing organization',
127
+ human: 'Je moet een organisatie selecteren voor dit lid',
128
+ statusCode: 400,
129
+ });
130
130
  }
131
131
 
132
132
  /**
133
133
  * In development mode, we allow some secret usernames to create fake data
134
134
  */
135
- if ((STAMHOOFD.environment == "development" || STAMHOOFD.environment == "staging") && organization) {
136
- if (member.details.firstName.toLocaleLowerCase() == "create" && parseInt(member.details.lastName) > 0) {
135
+ if ((STAMHOOFD.environment == 'development' || STAMHOOFD.environment == 'staging') && organization) {
136
+ if (member.details.firstName.toLocaleLowerCase() == 'create' && parseInt(member.details.lastName) > 0) {
137
137
  const count = parseInt(member.details.lastName);
138
- await this.createDummyMembers(organization, count)
138
+ await this.createDummyMembers(organization, count);
139
139
 
140
140
  // Skip creating this member
141
141
  continue;
142
142
  }
143
143
  }
144
144
 
145
- await member.save()
146
- members.push(member)
147
- updateMembershipMemberIds.add(member.id)
145
+ await member.save();
146
+ members.push(member);
147
+ updateMembershipMemberIds.add(member.id);
148
148
 
149
149
  // Auto link users based on data
150
- await MemberUserSyncer.onChangeMember(member)
150
+ await MemberUserSyncer.onChangeMember(member);
151
151
  }
152
152
 
153
153
  let shouldUpdateSetupSteps = false;
154
154
 
155
155
  // Loop all members one by one
156
156
  for (let patch of request.body.getPatches()) {
157
- const member = members.find(m => m.id === patch.id) ?? await Member.getWithRegistrations(patch.id)
157
+ const member = members.find(m => m.id === patch.id) ?? await Member.getWithRegistrations(patch.id);
158
158
  if (!member || !await Context.auth.canAccessMember(member, PermissionLevel.Write)) {
159
- throw Context.auth.notFoundOrNoAccess("Je hebt geen toegang tot dit lid of het bestaat niet")
159
+ throw Context.auth.notFoundOrNoAccess('Je hebt geen toegang tot dit lid of het bestaat niet');
160
160
  }
161
- patch = await Context.auth.filterMemberPatch(member, patch)
161
+ patch = await Context.auth.filterMemberPatch(member, patch);
162
162
 
163
163
  if (patch.details) {
164
164
  if (patch.details.isPut()) {
165
165
  throw new SimpleError({
166
- code: "not_allowed",
167
- message: "Cannot override details",
168
- human: "Er ging iets mis bij het aanpassen van de gegevens van dit lid. Probeer het later opnieuw en neem contact op als het probleem zich blijft voordoen.",
169
- field: "details"
170
- })
166
+ code: 'not_allowed',
167
+ message: 'Cannot override details',
168
+ human: 'Er ging iets mis bij het aanpassen van de gegevens van dit lid. Probeer het later opnieuw en neem contact op als het probleem zich blijft voordoen.',
169
+ field: 'details',
170
+ });
171
171
  }
172
-
173
- const wasReduced = member.details.shouldApplyReducedPrice
174
- member.details.patchOrPut(patch.details)
175
- member.details.cleanData()
172
+
173
+ const wasReduced = member.details.shouldApplyReducedPrice;
174
+ member.details.patchOrPut(patch.details);
175
+ member.details.cleanData();
176
176
 
177
177
  if (wasReduced !== member.details.shouldApplyReducedPrice) {
178
- updateMembershipMemberIds.add(member.id)
178
+ updateMembershipMemberIds.add(member.id);
179
179
  }
180
180
  }
181
-
181
+
182
182
  await member.save();
183
183
 
184
184
  // Update documents
185
- await Document.updateForMember(member.id)
185
+ await Document.updateForMember(member.id);
186
186
 
187
187
  // Update responsibilities
188
188
  for (const patchResponsibility of patch.responsibilities.getPatches()) {
189
189
  if (!Context.auth.hasPlatformFullAccess() && !(organization && await Context.auth.hasFullAccess(organization.id))) {
190
- throw Context.auth.error("Je hebt niet voldoende rechten om functies van leden aan te passen")
190
+ throw Context.auth.error('Je hebt niet voldoende rechten om functies van leden aan te passen');
191
191
  }
192
192
 
193
- const responsibilityRecord = await MemberResponsibilityRecord.getByID(patchResponsibility.id)
194
- if (!responsibilityRecord || responsibilityRecord.memberId != member.id || (organization && responsibilityRecord.organizationId !== organization.id)) {
193
+ const responsibilityRecord = await MemberResponsibilityRecord.getByID(patchResponsibility.id);
194
+ if (!responsibilityRecord || responsibilityRecord.memberId !== member.id || (organization && responsibilityRecord.organizationId !== organization.id)) {
195
195
  throw new SimpleError({
196
- code: "permission_denied",
196
+ code: 'permission_denied',
197
197
  message: "You don't have permissions to access this endpoint",
198
- human: "Je hebt geen toegang om deze functie te wijzigen"
199
- })
198
+ human: 'Je hebt geen toegang om deze functie te wijzigen',
199
+ });
200
200
  }
201
201
 
202
- const platform = await Platform.getShared()
203
- const responsibility = platform.config.responsibilities.find(r => r.id === patchResponsibility.responsibilityId)
202
+ const platform = await Platform.getShared();
203
+ const responsibility = platform.config.responsibilities.find(r => r.id === patchResponsibility.responsibilityId);
204
204
 
205
205
  if (responsibility && !responsibility.organizationBased && !Context.auth.hasPlatformFullAccess()) {
206
- throw Context.auth.error("Je hebt niet voldoende rechten om deze functie aan te passen")
206
+ throw Context.auth.error('Je hebt niet voldoende rechten om deze functie aan te passen');
207
207
  }
208
-
208
+
209
209
  // Allow patching begin and end date
210
210
  if (patchResponsibility.endDate !== undefined) {
211
211
  if (responsibilityRecord.endDate) {
212
212
  if (!Context.auth.hasPlatformFullAccess()) {
213
- throw Context.auth.error("Je hebt niet voldoende rechten om reeds beëindigde functies aan te passen")
213
+ throw Context.auth.error('Je hebt niet voldoende rechten om reeds beëindigde functies aan te passen');
214
214
  }
215
215
  }
216
- responsibilityRecord.endDate = patchResponsibility.endDate
216
+ responsibilityRecord.endDate = patchResponsibility.endDate;
217
217
  }
218
218
 
219
219
  if (patchResponsibility.startDate !== undefined) {
220
220
  if (patchResponsibility.startDate.getTime() > Date.now() + 5 * 60 * 1000) {
221
- throw Context.auth.error("Je kan de startdatum van een functie niet in de toekomst zetten")
221
+ throw Context.auth.error('Je kan de startdatum van een functie niet in de toekomst zetten');
222
222
  }
223
223
  if (patchResponsibility.startDate.getTime() > Date.now()) {
224
- patchResponsibility.startDate = new Date() // force now
224
+ patchResponsibility.startDate = new Date(); // force now
225
225
  }
226
226
 
227
- const daysDiff = Math.abs((new Date().getTime() - patchResponsibility.startDate.getTime()) / (1000 * 60 * 60 * 24))
227
+ const daysDiff = Math.abs((new Date().getTime() - patchResponsibility.startDate.getTime()) / (1000 * 60 * 60 * 24));
228
228
 
229
229
  if (daysDiff > 60 && !Context.auth.hasPlatformFullAccess()) {
230
- throw Context.auth.error("Je kan de startdatum van een functie niet zoveel verplaatsen")
230
+ throw Context.auth.error('Je kan de startdatum van een functie niet zoveel verplaatsen');
231
231
  }
232
- responsibilityRecord.startDate = patchResponsibility.startDate
232
+ responsibilityRecord.startDate = patchResponsibility.startDate;
233
233
  }
234
234
 
235
- await responsibilityRecord.save()
235
+ await responsibilityRecord.save();
236
236
  shouldUpdateSetupSteps = true;
237
237
  }
238
238
 
239
239
  // Create responsibilities
240
- for (const {put} of patch.responsibilities.getPuts()) {
240
+ for (const { put } of patch.responsibilities.getPuts()) {
241
241
  if (!Context.auth.hasPlatformFullAccess() && !(organization && await Context.auth.hasFullAccess(organization.id))) {
242
- throw Context.auth.error("Je hebt niet voldoende rechten om functies van leden aan te passen")
242
+ throw Context.auth.error('Je hebt niet voldoende rechten om functies van leden aan te passen');
243
243
  }
244
244
 
245
- const platform = await Platform.getShared()
246
- const platformResponsibility = platform.config.responsibilities.find(r => r.id === put.responsibilityId)
247
- const org = organization ?? (put.organizationId ? await Organization.getByID(put.organizationId) : null)
245
+ const platform = await Platform.getShared();
246
+ const platformResponsibility = platform.config.responsibilities.find(r => r.id === put.responsibilityId);
247
+ const org = organization ?? (put.organizationId ? await Organization.getByID(put.organizationId) : null);
248
248
 
249
249
  if (!org && put.organizationId) {
250
250
  throw new SimpleError({
251
- code: "invalid_field",
252
- message: "Invalid organization",
253
- human: "Deze vereniging bestaat niet",
254
- field: "organizationId"
255
- })
251
+ code: 'invalid_field',
252
+ message: 'Invalid organization',
253
+ human: 'Deze vereniging bestaat niet',
254
+ field: 'organizationId',
255
+ });
256
256
  }
257
- const responsibility = platformResponsibility ?? org?.privateMeta.responsibilities.find(r => r.id === put.responsibilityId)
257
+ const responsibility = platformResponsibility ?? org?.privateMeta.responsibilities.find(r => r.id === put.responsibilityId);
258
258
 
259
259
  if (!responsibility) {
260
260
  throw new SimpleError({
261
- code: "invalid_field",
262
- message: "Invalid responsibility",
263
- human: "Deze functie bestaat niet",
264
- field: "responsibilityId"
265
- })
261
+ code: 'invalid_field',
262
+ message: 'Invalid responsibility',
263
+ human: 'Deze functie bestaat niet',
264
+ field: 'responsibilityId',
265
+ });
266
266
  }
267
267
 
268
268
  if (!org && responsibility.organizationBased) {
269
269
  throw new SimpleError({
270
- code: "invalid_field",
271
- message: "Invalid organization",
272
- human: "Deze functie kan niet worden toegewezen aan deze vereniging",
273
- field: "organizationId"
274
- })
270
+ code: 'invalid_field',
271
+ message: 'Invalid organization',
272
+ human: 'Deze functie kan niet worden toegewezen aan deze vereniging',
273
+ field: 'organizationId',
274
+ });
275
275
  }
276
276
 
277
- const hasRegistration = member.registrations.some(registration => {
277
+ const hasRegistration = member.registrations.some((registration) => {
278
278
  if (platformResponsibility) {
279
279
  if (registration.group.defaultAgeGroupId === null) {
280
280
  return false;
@@ -285,95 +285,96 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
285
285
  if (registration.periodId !== org.periodId) {
286
286
  return false;
287
287
  }
288
- } else {
288
+ }
289
+ else {
289
290
  if (registration.periodId !== platform.periodId) {
290
291
  return false;
291
292
  }
292
293
  }
293
- return registration.deactivatedAt === null && registration.registeredAt !== null && registration.group.type === GroupType.Membership
294
- })
294
+ return registration.deactivatedAt === null && registration.registeredAt !== null && registration.group.type === GroupType.Membership;
295
+ });
295
296
 
296
297
  if (!hasRegistration) {
297
298
  throw new SimpleError({
298
- code: "invalid_field",
299
- message: "Invalid organization",
300
- human: "Je kan een functie enkel toekennen aan leden die zijn ingeschreven in het huidige werkjaar",
301
- })
299
+ code: 'invalid_field',
300
+ message: 'Invalid organization',
301
+ human: 'Je kan een functie enkel toekennen aan leden die zijn ingeschreven in het huidige werkjaar',
302
+ });
302
303
  }
303
304
 
304
- const model = new MemberResponsibilityRecord()
305
- model.memberId = member.id
306
- model.responsibilityId = responsibility.id
307
- model.organizationId = org?.id ?? null
305
+ const model = new MemberResponsibilityRecord();
306
+ model.memberId = member.id;
307
+ model.responsibilityId = responsibility.id;
308
+ model.organizationId = org?.id ?? null;
308
309
 
309
310
  if (responsibility.organizationTagIds !== null && (!org || !org.meta.matchTags(responsibility.organizationTagIds))) {
310
311
  throw new SimpleError({
311
- code: "invalid_field",
312
- message: "Invalid organization",
313
- human: "Deze functie is niet beschikbaar voor deze vereniging",
314
- field: "organizationId"
315
- })
312
+ code: 'invalid_field',
313
+ message: 'Invalid organization',
314
+ human: 'Deze functie is niet beschikbaar voor deze vereniging',
315
+ field: 'organizationId',
316
+ });
316
317
  }
317
318
 
318
319
  if (responsibility.defaultAgeGroupIds !== null) {
319
320
  if (!put.groupId) {
320
321
  throw new SimpleError({
321
- code: "invalid_field",
322
- message: "Missing groupId",
323
- human: "Kies een leeftijdsgroep waarvoor je deze functie wilt toekennen",
324
- field: "groupId"
325
- })
322
+ code: 'invalid_field',
323
+ message: 'Missing groupId',
324
+ human: 'Kies een leeftijdsgroep waarvoor je deze functie wilt toekennen',
325
+ field: 'groupId',
326
+ });
326
327
  }
327
328
 
328
- const group = await Group.getByID(put.groupId)
329
+ const group = await Group.getByID(put.groupId);
329
330
  if (!group || group.organizationId !== model.organizationId) {
330
331
  throw new SimpleError({
331
- code: "invalid_field",
332
- message: "Invalid groupId",
333
- human: "Deze leeftijdsgroep bestaat niet",
334
- field: "groupId"
335
- })
332
+ code: 'invalid_field',
333
+ message: 'Invalid groupId',
334
+ human: 'Deze leeftijdsgroep bestaat niet',
335
+ field: 'groupId',
336
+ });
336
337
  }
337
338
 
338
339
  if (group.defaultAgeGroupId === null || !responsibility.defaultAgeGroupIds.includes(group.defaultAgeGroupId)) {
339
340
  throw new SimpleError({
340
- code: "invalid_field",
341
- message: "Invalid groupId",
342
- human: "Deze leeftijdsgroep komt niet in aanmerking voor deze functie",
343
- field: "groupId"
344
- })
341
+ code: 'invalid_field',
342
+ message: 'Invalid groupId',
343
+ human: 'Deze leeftijdsgroep komt niet in aanmerking voor deze functie',
344
+ field: 'groupId',
345
+ });
345
346
  }
346
347
 
347
- model.groupId = group.id
348
+ model.groupId = group.id;
348
349
  }
349
-
350
+
350
351
  // Allow patching begin and end date
351
- model.endDate = put.endDate
352
+ model.endDate = put.endDate;
352
353
 
353
354
  if (put.startDate.getTime() > Date.now() + 5 * 60 * 1000) {
354
- throw Context.auth.error("Je kan de startdatum van een functie niet in de toekomst zetten")
355
+ throw Context.auth.error('Je kan de startdatum van een functie niet in de toekomst zetten');
355
356
  }
356
357
 
357
358
  if (put.startDate.getTime() > Date.now()) {
358
- put.startDate = new Date() // force now
359
+ put.startDate = new Date(); // force now
359
360
  }
360
361
 
361
- if (put.endDate && put.endDate > new Date(Date.now() + 60*1000)) {
362
- throw Context.auth.error("Je kan de einddatum van een functie niet in de toekomst zetten - kijk indien nodig je systeemtijd na")
362
+ if (put.endDate && put.endDate > new Date(Date.now() + 60 * 1000)) {
363
+ throw Context.auth.error('Je kan de einddatum van een functie niet in de toekomst zetten - kijk indien nodig je systeemtijd na');
363
364
  }
364
365
 
365
- model.startDate = put.startDate
366
+ model.startDate = put.startDate;
366
367
 
367
- await model.save()
368
+ await model.save();
368
369
  shouldUpdateSetupSteps = true;
369
370
  }
370
371
 
371
372
  // Auto link users based on data
372
- await MemberUserSyncer.onChangeMember(member)
373
+ await MemberUserSyncer.onChangeMember(member);
373
374
 
374
375
  // Allow to remove access for certain users
375
376
  for (const id of patch.users.getDeletes()) {
376
- const user = member.users.find(u => u.id === id)
377
+ const user = member.users.find(u => u.id === id);
377
378
  if (!user) {
378
379
  // Ignore silently
379
380
  continue;
@@ -381,138 +382,138 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
381
382
 
382
383
  if (MemberUserSyncer.doesEmailHaveAccess(member.details, user.email)) {
383
384
  throw new SimpleError({
384
- code: "invalid_field",
385
- message: "Invalid email",
386
- human: "Je kan een account niet de toegang ontzeggen tot een lid als het e-mailadres nog steeds is opgeslagen als onderdeel van de gegevens van dat lid. Verwijder eerst het e-mailadres uit de gegevens van het lid en ontkoppel daarna het account."
385
+ code: 'invalid_field',
386
+ message: 'Invalid email',
387
+ human: 'Je kan een account niet de toegang ontzeggen tot een lid als het e-mailadres nog steeds is opgeslagen als onderdeel van de gegevens van dat lid. Verwijder eerst het e-mailadres uit de gegevens van het lid en ontkoppel daarna het account.',
387
388
  });
388
389
  }
389
390
 
390
391
  // Remove access
391
- await MemberUserSyncer.unlinkUser(user, member)
392
+ await MemberUserSyncer.unlinkUser(user, member);
392
393
  }
393
394
 
394
395
  // Add platform memberships
395
- for (const {put} of patch.platformMemberships.getPuts()) {
396
+ for (const { put } of patch.platformMemberships.getPuts()) {
396
397
  if (put.periodId !== platform.periodId) {
397
398
  throw new SimpleError({
398
- code: "invalid_field",
399
- message: "Invalid period",
400
- human: "Je kan geen aansluitingen maken voor een andere werkjaar dan het actieve werkjaar",
401
- field: "periodId"
402
- })
399
+ code: 'invalid_field',
400
+ message: 'Invalid period',
401
+ human: 'Je kan geen aansluitingen maken voor een andere werkjaar dan het actieve werkjaar',
402
+ field: 'periodId',
403
+ });
403
404
  }
404
405
 
405
406
  if (organization && put.organizationId !== organization.id) {
406
407
  throw new SimpleError({
407
- code: "invalid_field",
408
- message: "Invalid organization",
409
- human: "Je kan geen aansluitingen maken voor een andere vereniging",
410
- field: "organizationId"
411
- })
408
+ code: 'invalid_field',
409
+ message: 'Invalid organization',
410
+ human: 'Je kan geen aansluitingen maken voor een andere vereniging',
411
+ field: 'organizationId',
412
+ });
412
413
  }
413
414
 
414
415
  if (!await Context.auth.hasFullAccess(put.organizationId)) {
415
- throw Context.auth.error("Je hebt niet voldoende rechten om deze aansluiting toe te voegen")
416
+ throw Context.auth.error('Je hebt niet voldoende rechten om deze aansluiting toe te voegen');
416
417
  }
417
418
 
418
419
  if (!platform.config.membershipTypes.find(t => t.id === put.membershipTypeId)) {
419
420
  throw new SimpleError({
420
- code: "invalid_field",
421
- field: "membershipTypeId",
422
- message: "Invalid membership type",
423
- human: "Dit aansluitingstype bestaat niet"
424
- })
421
+ code: 'invalid_field',
422
+ field: 'membershipTypeId',
423
+ message: 'Invalid membership type',
424
+ human: 'Dit aansluitingstype bestaat niet',
425
+ });
425
426
  }
426
-
427
+
427
428
  // Check duplicate memberships
428
429
 
429
430
  // Check dates
430
431
 
431
432
  // Calculate prices
432
433
 
433
- const membership = new MemberPlatformMembership()
434
- membership.id = put.id
435
- membership.memberId = member.id
436
- membership.membershipTypeId = put.membershipTypeId
437
- membership.organizationId = put.organizationId
438
- membership.periodId = put.periodId
434
+ const membership = new MemberPlatformMembership();
435
+ membership.id = put.id;
436
+ membership.memberId = member.id;
437
+ membership.membershipTypeId = put.membershipTypeId;
438
+ membership.organizationId = put.organizationId;
439
+ membership.periodId = put.periodId;
439
440
 
440
- membership.startDate = put.startDate
441
- membership.endDate = put.endDate
442
- membership.expireDate = put.expireDate
441
+ membership.startDate = put.startDate;
442
+ membership.endDate = put.endDate;
443
+ membership.expireDate = put.expireDate;
443
444
 
444
- await membership.calculatePrice(member)
445
- await membership.save()
445
+ await membership.calculatePrice(member);
446
+ await membership.save();
446
447
 
447
- updateMembershipMemberIds.add(member.id)
448
+ updateMembershipMemberIds.add(member.id);
448
449
  }
449
450
 
450
451
  // Delete platform memberships
451
452
  for (const id of patch.platformMemberships.getDeletes()) {
452
- const membership = await MemberPlatformMembership.getByID(id)
453
+ const membership = await MemberPlatformMembership.getByID(id);
453
454
 
454
455
  if (!membership || membership.memberId !== member.id) {
455
456
  throw new SimpleError({
456
- code: "invalid_field",
457
- field: "id",
458
- message: "Invalid id",
459
- human: "Deze aansluiting bestaat niet"
460
- })
457
+ code: 'invalid_field',
458
+ field: 'id',
459
+ message: 'Invalid id',
460
+ human: 'Deze aansluiting bestaat niet',
461
+ });
461
462
  }
462
463
 
463
464
  if (!await Context.auth.hasFullAccess(membership.organizationId)) {
464
- throw Context.auth.error("Je hebt niet voldoende rechten om deze aansluiting te verwijderen")
465
+ throw Context.auth.error('Je hebt niet voldoende rechten om deze aansluiting te verwijderen');
465
466
  }
466
467
 
467
468
  if (membership.periodId !== platform.periodId) {
468
469
  throw new SimpleError({
469
- code: "invalid_field",
470
- message: "Invalid period",
471
- human: "Je kan geen aansluitingen meer verwijderen voor een ander werkjaar dan het actieve werkjaar",
472
- field: "periodId"
473
- })
470
+ code: 'invalid_field',
471
+ message: 'Invalid period',
472
+ human: 'Je kan geen aansluitingen meer verwijderen voor een ander werkjaar dan het actieve werkjaar',
473
+ field: 'periodId',
474
+ });
474
475
  }
475
476
 
476
477
  if (!membership.canDelete() && !Context.auth.hasPlatformFullAccess()) {
477
478
  throw new SimpleError({
478
- code: "invalid_field",
479
- message: "Invalid invoice",
480
- human: "Je kan geen aansluiting verwijderen die al werd gefactureerd",
481
- })
479
+ code: 'invalid_field',
480
+ message: 'Invalid invoice',
481
+ human: 'Je kan geen aansluiting verwijderen die al werd gefactureerd',
482
+ });
482
483
  }
483
484
 
484
485
  await membership.doDelete();
485
- updateMembershipsForOrganizations.add(membership.organizationId) // can influence free memberships in other members of same organization
486
- updateMembershipMemberIds.add(member.id)
486
+ updateMembershipsForOrganizations.add(membership.organizationId); // can influence free memberships in other members of same organization
487
+ updateMembershipMemberIds.add(member.id);
487
488
  }
488
489
 
489
490
  if (!members.find(m => m.id === member.id)) {
490
- members.push(member)
491
+ members.push(member);
491
492
  }
492
493
  }
493
494
 
494
- await PatchOrganizationMembersEndpoint.deleteMembers(request.body.getDeletes())
495
-
495
+ await PatchOrganizationMembersEndpoint.deleteMembers(request.body.getDeletes());
496
+
496
497
  for (const member of members) {
497
498
  if (updateMembershipMemberIds.has(member.id)) {
498
- await member.updateMemberships()
499
+ await member.updateMemberships();
499
500
  }
500
501
  }
501
502
 
502
503
  if (updateMembershipsForOrganizations.size) {
503
504
  QueueHandler.schedule('update-membership-prices', async () => {
504
505
  for (const id of updateMembershipsForOrganizations) {
505
- await MembershipCharger.updatePrices(id)
506
+ await MembershipCharger.updatePrices(id);
506
507
  }
507
508
  }).catch(console.error);
508
509
  }
509
510
 
510
- if(shouldUpdateSetupSteps && organization) {
511
+ if (shouldUpdateSetupSteps && organization) {
511
512
  SetupStepUpdater.updateForOrganization(organization).catch(console.error);
512
513
  }
513
514
 
514
515
  return new Response(
515
- await AuthenticatedStructures.membersBlob(members)
516
+ await AuthenticatedStructures.membersBlob(members),
516
517
  );
517
518
  }
518
519
 
@@ -520,20 +521,20 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
520
521
  const updateGroups = new Set<string>();
521
522
  const updateRegistrations = new Map<string, Registration>();
522
523
  const updateSteps = new Set<string>();
523
-
524
+
524
525
  // Loop all members one by one
525
526
  for (const id of ids) {
526
- const member = await Member.getWithRegistrations(id)
527
+ const member = await Member.getWithRegistrations(id);
527
528
  if (!member || !await Context.auth.canDeleteMember(member)) {
528
- throw Context.auth.error("Je hebt niet voldoende rechten om dit lid te verwijderen")
529
+ throw Context.auth.error('Je hebt niet voldoende rechten om dit lid te verwijderen');
529
530
  }
530
531
 
531
- await MemberUserSyncer.onDeleteMember(member)
532
- await User.deleteForDeletedMember(member.id)
533
- await BalanceItem.deleteForDeletedMember(member.id)
534
- await member.delete()
532
+ await MemberUserSyncer.onDeleteMember(member);
533
+ await User.deleteForDeletedMember(member.id);
534
+ await BalanceItem.deleteForDeletedMember(member.id);
535
+ await member.delete();
535
536
 
536
- for(const registration of member.registrations) {
537
+ for (const registration of member.registrations) {
537
538
  const groupId = registration.groupId;
538
539
  updateRegistrations.set(registration.id, registration);
539
540
  updateGroups.add(groupId);
@@ -541,7 +542,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
541
542
  }
542
543
  }
543
544
 
544
- for(const registration of updateRegistrations.values()) {
545
+ for (const registration of updateRegistrations.values()) {
545
546
  registration.scheduleStockUpdate();
546
547
  }
547
548
 
@@ -549,12 +550,12 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
549
550
 
550
551
  // Loop all groups and update occupancy if needed
551
552
  for (const group of groups) {
552
- await group.updateOccupancy()
553
- await group.save()
553
+ await group.updateOccupancy();
554
+ await group.save();
554
555
  }
555
556
 
556
557
  const organizations = await Organization.getByIDs(...Array.from(updateSteps));
557
-
558
+
558
559
  for (const organization of organizations) {
559
560
  SetupStepUpdater.updateForOrganization(organization).catch(console.error);
560
561
  }
@@ -562,31 +563,31 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
562
563
 
563
564
  static async checkDuplicate(member: Member) {
564
565
  if (!member.details.birthDay) {
565
- return
566
+ return;
566
567
  }
567
568
  let existingMembers = await Member.where({ organizationId: member.organizationId, firstName: member.details.firstName, lastName: member.details.lastName, birthDay: Formatter.dateIso(member.details.birthDay) });
568
569
 
569
570
  if (member.existsInDatabase) {
570
- existingMembers = existingMembers.filter(e => e.id !== member.id)
571
+ existingMembers = existingMembers.filter(e => e.id !== member.id);
571
572
  }
572
-
573
+
573
574
  if (existingMembers.length > 0) {
574
- const withRegistrations = await Member.getBlobByIds(...existingMembers.map(m => m.id))
575
+ const withRegistrations = await Member.getBlobByIds(...existingMembers.map(m => m.id));
575
576
  for (const m of withRegistrations) {
576
577
  if (m.registrations.length > 0) {
577
- return m
578
+ return m;
578
579
  }
579
580
  }
580
581
 
581
582
  if (withRegistrations.length > 0) {
582
- return withRegistrations[0]
583
+ return withRegistrations[0];
583
584
  }
584
585
  }
585
586
  }
586
587
 
587
588
  async createDummyMembers(organization: Organization, count: number) {
588
- await new MemberFactory({
589
- organization
590
- }).createMultiple(count)
589
+ await new MemberFactory({
590
+ organization,
591
+ }).createMultiple(count);
591
592
  }
592
593
  }