@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,11 +1,11 @@
1
1
  import { createMollieClient, PaymentMethod as molliePaymentMethod } from '@mollie/api-client';
2
2
  import { ManyToOneRelation } from '@simonbackx/simple-database';
3
3
  import { Decoder } from '@simonbackx/simple-encoding';
4
- import { DecodedRequest, Endpoint, Request, Response } from "@simonbackx/simple-endpoints";
4
+ import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
5
5
  import { SimpleError } from '@simonbackx/simple-errors';
6
6
  import { Email } from '@stamhoofd/email';
7
7
  import { BalanceItem, BalanceItemPayment, Group, Member, MemberWithRegistrations, MolliePayment, MollieToken, Organization, PayconiqPayment, Payment, Platform, RateLimiter, Registration, User } from '@stamhoofd/models';
8
- import { BalanceItemRelation, BalanceItemRelationType, BalanceItemStatus, BalanceItemType, BalanceItemWithPayments, IDRegisterCheckout, PaymentCustomer, PaymentMethod, PaymentMethodHelper, PaymentProvider, PaymentStatus, Payment as PaymentStruct, PermissionLevel, PlatformFamily, PlatformMember, RegisterItem, RegisterResponse, Version } from "@stamhoofd/structures";
8
+ import { BalanceItemRelation, BalanceItemRelationType, BalanceItemStatus, BalanceItemType, BalanceItemWithPayments, IDRegisterCheckout, PaymentCustomer, PaymentMethod, PaymentMethodHelper, PaymentProvider, PaymentStatus, Payment as PaymentStruct, PermissionLevel, PlatformFamily, PlatformMember, RegisterItem, RegisterResponse, Version } from '@stamhoofd/structures';
9
9
  import { Formatter } from '@stamhoofd/utility';
10
10
 
11
11
  import { AuthenticatedStructures } from '../../../helpers/AuthenticatedStructures';
@@ -14,46 +14,46 @@ import { Context } from '../../../helpers/Context';
14
14
  import { StripeHelper } from '../../../helpers/StripeHelper';
15
15
  type Params = Record<string, never>;
16
16
  type Query = undefined;
17
- type Body = IDRegisterCheckout
18
- type ResponseBody = RegisterResponse
17
+ type Body = IDRegisterCheckout;
18
+ type ResponseBody = RegisterResponse;
19
19
 
20
20
  export const demoLimiter = new RateLimiter({
21
21
  limits: [
22
- {
22
+ {
23
23
  // Max 10 per hour
24
24
  limit: 10,
25
- duration: 60 * 1000 * 60
25
+ duration: 60 * 1000 * 60,
26
26
  },
27
- {
27
+ {
28
28
  // Max 20 a day
29
29
  limit: 20,
30
- duration: 24 * 60 * 1000 * 60
31
- }
32
- ]
30
+ duration: 24 * 60 * 1000 * 60,
31
+ },
32
+ ],
33
33
  });
34
34
 
35
- export type RegistrationWithMemberAndGroup = Registration & { member: Member } & { group: Group }
35
+ export type RegistrationWithMemberAndGroup = Registration & { member: Member } & { group: Group };
36
36
 
37
37
  /**
38
38
  * Allow to add, patch and delete multiple members simultaneously, which is needed in order to sync relational data that is saved encrypted in multiple members (e.g. parents)
39
39
  */
40
40
  export class RegisterMembersEndpoint extends Endpoint<Params, Query, Body, ResponseBody> {
41
- bodyDecoder = IDRegisterCheckout as Decoder<IDRegisterCheckout>
41
+ bodyDecoder = IDRegisterCheckout as Decoder<IDRegisterCheckout>;
42
42
 
43
43
  protected doesMatch(request: Request): [true, Params] | [false] {
44
- if (request.method != "POST") {
44
+ if (request.method !== 'POST') {
45
45
  return [false];
46
46
  }
47
47
 
48
- const params = Endpoint.parseParameters(request.url, "/members/register", {});
48
+ const params = Endpoint.parseParameters(request.url, '/members/register', {});
49
49
 
50
50
  if (params) {
51
51
  if (request.getVersion() < 257) {
52
52
  throw new SimpleError({
53
- code: "not_supported",
54
- message: "This version is no longer supported",
55
- human: "Oops! Je gebruikt een oude versie van de applicatie om in te schrijven. Herlaad de website en verwijder indien nodig de cache van jouw browser."
56
- })
53
+ code: 'not_supported',
54
+ message: 'This version is no longer supported',
55
+ human: 'Oops! Je gebruikt een oude versie van de applicatie om in te schrijven. Herlaad de website en verwijder indien nodig de cache van jouw browser.',
56
+ });
57
57
  }
58
58
  return [true, params as Params];
59
59
  }
@@ -62,171 +62,173 @@ export class RegisterMembersEndpoint extends Endpoint<Params, Query, Body, Respo
62
62
 
63
63
  async handle(request: DecodedRequest<Params, Query, Body>) {
64
64
  const organization = await Context.setOrganizationScope();
65
- const {user} = await Context.authenticate()
65
+ const { user } = await Context.authenticate();
66
66
 
67
67
  if (request.body.asOrganizationId && request.body.asOrganizationId !== organization.id) {
68
68
  if (!await Context.auth.hasFullAccess(request.body.asOrganizationId)) {
69
69
  throw new SimpleError({
70
- code: "forbidden",
71
- message: "No permission to register as this organization for a different organization",
70
+ code: 'forbidden',
71
+ message: 'No permission to register as this organization for a different organization',
72
72
  human: 'Je hebt niet de juiste toegangsrechten om leden in te schrijven bij een andere organisatie.',
73
- statusCode: 403
73
+ statusCode: 403,
74
74
  });
75
75
  }
76
76
  }
77
77
 
78
78
  // For non paid organizations, limit amount of tests
79
79
  if (!organization.meta.packages.isPaid) {
80
- const limiter = demoLimiter
80
+ const limiter = demoLimiter;
81
81
 
82
82
  try {
83
83
  limiter.track(organization.id, 1);
84
- } catch (e) {
84
+ }
85
+ catch (e) {
85
86
  Email.sendWebmaster({
86
- subject: "[Limiet] Limiet bereikt voor aantal inschrijvingen",
87
- text: "Beste, \nDe limiet werd bereikt voor het aantal inschrijvingen per dag. \nVereniging: "+organization.id+" ("+organization.name+")" + "\n\n" + e.message + "\n\nStamhoofd"
88
- })
87
+ subject: '[Limiet] Limiet bereikt voor aantal inschrijvingen',
88
+ text: 'Beste, \nDe limiet werd bereikt voor het aantal inschrijvingen per dag. \nVereniging: ' + organization.id + ' (' + organization.name + ')' + '\n\n' + e.message + '\n\nStamhoofd',
89
+ });
89
90
 
90
91
  throw new SimpleError({
91
- code: "too_many_emails_period",
92
- message: "Too many e-mails limited",
93
- human: "Oeps! Om spam te voorkomen limiteren we het aantal test inschrijvingen die je per uur of dag kan plaatsen. Probeer over een uur opnieuw of schakel over naar een betaald abonnement.",
94
- field: "recipients"
95
- })
92
+ code: 'too_many_emails_period',
93
+ message: 'Too many e-mails limited',
94
+ human: 'Oeps! Om spam te voorkomen limiteren we het aantal test inschrijvingen die je per uur of dag kan plaatsen. Probeer over een uur opnieuw of schakel over naar een betaald abonnement.',
95
+ field: 'recipients',
96
+ });
96
97
  }
97
98
  }
98
99
 
99
- const deleteRegistrationIds = request.body.cart.deleteRegistrationIds
100
- const deleteRegistrationModels = (deleteRegistrationIds.length ? (await Registration.getByIDs(...deleteRegistrationIds)) : []).filter(r => r.organizationId === organization.id)
100
+ const deleteRegistrationIds = request.body.cart.deleteRegistrationIds;
101
+ const deleteRegistrationModels = (deleteRegistrationIds.length ? (await Registration.getByIDs(...deleteRegistrationIds)) : []).filter(r => r.organizationId === organization.id);
101
102
 
102
103
  // Validate balance items (can only happen serverside)
103
- const balanceItemIds = request.body.cart.balanceItems.map(i => i.item.id)
104
- let memberBalanceItemsStructs: BalanceItemWithPayments[] = []
105
- let balanceItemsModels: BalanceItem[] = []
104
+ const balanceItemIds = request.body.cart.balanceItems.map(i => i.item.id);
105
+ let memberBalanceItemsStructs: BalanceItemWithPayments[] = [];
106
+ let balanceItemsModels: BalanceItem[] = [];
106
107
  if (balanceItemIds.length > 0) {
107
- balanceItemsModels = await BalanceItem.where({ id: { sign:'IN', value: balanceItemIds }, organizationId: organization.id })
108
- if (balanceItemsModels.length != balanceItemIds.length) {
108
+ balanceItemsModels = await BalanceItem.where({ id: { sign: 'IN', value: balanceItemIds }, organizationId: organization.id });
109
+ if (balanceItemsModels.length !== balanceItemIds.length) {
109
110
  throw new SimpleError({
110
- code: "invalid_data",
111
- message: "Oeps, één of meerdere openstaande bedragen in jouw winkelmandje zijn aangepast. Herlaad de pagina en probeer opnieuw."
112
- })
111
+ code: 'invalid_data',
112
+ message: 'Oeps, één of meerdere openstaande bedragen in jouw winkelmandje zijn aangepast. Herlaad de pagina en probeer opnieuw.',
113
+ });
113
114
  }
114
- memberBalanceItemsStructs = await BalanceItem.getStructureWithPayments(balanceItemsModels)
115
+ memberBalanceItemsStructs = await BalanceItem.getStructureWithPayments(balanceItemsModels);
115
116
  }
116
117
 
117
118
  const memberIds = Formatter.uniqueArray(
118
- [...request.body.memberIds, ...deleteRegistrationModels.map(i => i.memberId), ...balanceItemsModels.map(i => i.memberId).filter(m => m !== null)]
119
- )
120
- const members = await Member.getBlobByIds(...memberIds)
121
- const groupIds = request.body.groupIds
122
- const groups = await Group.getByIDs(...groupIds)
119
+ [...request.body.memberIds, ...deleteRegistrationModels.map(i => i.memberId), ...balanceItemsModels.map(i => i.memberId).filter(m => m !== null)],
120
+ );
121
+ const members = await Member.getBlobByIds(...memberIds);
122
+ const groupIds = request.body.groupIds;
123
+ const groups = await Group.getByIDs(...groupIds);
123
124
 
124
125
  for (const group of groups) {
125
126
  if (group.organizationId !== organization.id) {
126
127
  throw new SimpleError({
127
- code: "invalid_data",
128
- message: "Oeps, één of meerdere groepen waarin je probeert in te schrijven lijken niet meer te bestaan. Herlaad de pagina en probeer opnieuw."
129
- })
128
+ code: 'invalid_data',
129
+ message: 'Oeps, één of meerdere groepen waarin je probeert in te schrijven lijken niet meer te bestaan. Herlaad de pagina en probeer opnieuw.',
130
+ });
130
131
  }
131
132
  }
132
133
 
133
134
  for (const member of members) {
134
135
  if (!await Context.auth.canAccessMember(member, PermissionLevel.Write)) {
135
136
  throw new SimpleError({
136
- code: "forbidden",
137
- message: "No permission to register this member",
137
+ code: 'forbidden',
138
+ message: 'No permission to register this member',
138
139
  human: 'Je hebt niet de juiste toegangsrechten om dit lid in te schrijven. Je kan enkel leden inschrijven als je minstens bewerkrechten hebt voor dat lid.',
139
- statusCode: 403
140
+ statusCode: 403,
140
141
  });
141
142
  }
142
143
  }
143
144
 
144
- const blob = await AuthenticatedStructures.membersBlob(members, true)
145
- const platformMembers: PlatformMember[] = []
145
+ const blob = await AuthenticatedStructures.membersBlob(members, true);
146
+ const platformMembers: PlatformMember[] = [];
146
147
 
147
148
  if (request.body.asOrganizationId) {
148
149
  const _m = PlatformFamily.createSingles(blob, {
149
150
  platform: await Platform.getSharedStruct(),
150
- contextOrganization: await AuthenticatedStructures.organization(organization)
151
- })
152
- platformMembers.push(..._m)
153
- } else {
151
+ contextOrganization: await AuthenticatedStructures.organization(organization),
152
+ });
153
+ platformMembers.push(..._m);
154
+ }
155
+ else {
154
156
  const family = PlatformFamily.create(blob, {
155
157
  platform: await Platform.getSharedStruct(),
156
- contextOrganization: await AuthenticatedStructures.organization(organization)
157
- })
158
- platformMembers.push(...family.members)
158
+ contextOrganization: await AuthenticatedStructures.organization(organization),
159
+ });
160
+ platformMembers.push(...family.members);
159
161
  }
160
162
 
161
- const organizationStruct = await AuthenticatedStructures.organization(organization)
163
+ const organizationStruct = await AuthenticatedStructures.organization(organization);
162
164
  const checkout = request.body.hydrate({
163
165
  members: platformMembers,
164
166
  groups: await AuthenticatedStructures.groups(groups),
165
- organizations: [organizationStruct]
166
- })
167
+ organizations: [organizationStruct],
168
+ });
167
169
 
168
170
  // Set circular references
169
171
  for (const member of platformMembers) {
170
- member.family.checkout = checkout
172
+ member.family.checkout = checkout;
171
173
  }
172
174
 
173
- checkout.setDefaultOrganization(organizationStruct)
174
-
175
- const registrations: RegistrationWithMemberAndGroup[] = []
176
- const payRegistrations: {registration: RegistrationWithMemberAndGroup, item: RegisterItem}[] = []
175
+ checkout.setDefaultOrganization(organizationStruct);
176
+
177
+ const registrations: RegistrationWithMemberAndGroup[] = [];
178
+ const payRegistrations: { registration: RegistrationWithMemberAndGroup; item: RegisterItem }[] = [];
177
179
  const deactivatedRegistrationGroupIds: string[] = [];
178
180
 
179
181
  if (checkout.cart.isEmpty) {
180
182
  throw new SimpleError({
181
- code: "empty_data",
182
- message: "Oeps, jouw mandje is leeg. Voeg eerst inschrijvingen toe voor je verder gaat."
183
- })
183
+ code: 'empty_data',
184
+ message: 'Oeps, jouw mandje is leeg. Voeg eerst inschrijvingen toe voor je verder gaat.',
185
+ });
184
186
  }
185
187
 
186
188
  // Validate the cart
187
- checkout.validate({memberBalanceItems: memberBalanceItemsStructs})
189
+ checkout.validate({ memberBalanceItems: memberBalanceItemsStructs });
188
190
 
189
191
  // Recalculate the price
190
- checkout.updatePrices()
192
+ checkout.updatePrices();
191
193
 
192
- const totalPrice = checkout.totalPrice
194
+ const totalPrice = checkout.totalPrice;
193
195
 
194
196
  if (totalPrice !== request.body.totalPrice) {
195
197
  throw new SimpleError({
196
- code: "changed_price",
197
- message: "Oeps! De prijs is gewijzigd terwijl je aan het afrekenen was (naar "+Formatter.price(totalPrice)+"). Herlaad de pagina even om ervoor te zorgen dat je alle aangepaste prijzen ziet. Contacteer de webmaster als je dit probleem blijft ondervinden na het te herladen."
198
- })
198
+ code: 'changed_price',
199
+ message: 'Oeps! De prijs is gewijzigd terwijl je aan het afrekenen was (naar ' + Formatter.price(totalPrice) + '). Herlaad de pagina even om ervoor te zorgen dat je alle aangepaste prijzen ziet. Contacteer de webmaster als je dit probleem blijft ondervinden na het te herladen.',
200
+ });
199
201
  }
200
-
202
+
201
203
  if (totalPrice < 0) {
202
204
  throw new SimpleError({
203
- code: "empty_data",
204
- message: "Oeps! De totaalprijs is negatief."
205
- })
205
+ code: 'empty_data',
206
+ message: 'Oeps! De totaalprijs is negatief.',
207
+ });
206
208
  }
207
209
 
208
- const registrationMemberRelation = new ManyToOneRelation(Member, "member")
209
- registrationMemberRelation.foreignKey = "memberId"
210
+ const registrationMemberRelation = new ManyToOneRelation(Member, 'member');
211
+ registrationMemberRelation.foreignKey = 'memberId';
210
212
 
211
213
  for (const item of checkout.cart.items) {
212
- const member = members.find(m => m.id == item.memberId)
214
+ const member = members.find(m => m.id == item.memberId);
213
215
  if (!member) {
214
216
  throw new SimpleError({
215
- code: "invalid_member",
216
- message: "Het lid dat je probeert in te schrijven konden we niet meer terugvinden. Je herlaadt best even de pagina om opnieuw te proberen."
217
- })
217
+ code: 'invalid_member',
218
+ message: 'Het lid dat je probeert in te schrijven konden we niet meer terugvinden. Je herlaadt best even de pagina om opnieuw te proberen.',
219
+ });
218
220
  }
219
221
 
220
222
  const group = groups.find(g => g.id == item.groupId);
221
223
  if (!group) {
222
224
  throw new SimpleError({
223
- code: "invalid_member",
224
- message: "De groep waarin je een lid probeert in te schrijven lijkt niet meer te bestaan. Je herlaadt best even de pagina om opnieuw te proberen."
225
- })
225
+ code: 'invalid_member',
226
+ message: 'De groep waarin je een lid probeert in te schrijven lijkt niet meer te bestaan. Je herlaadt best even de pagina om opnieuw te proberen.',
227
+ });
226
228
  }
227
229
 
228
230
  // Check if this member is already registered in this group?
229
- const existingRegistrations = await Registration.where({ memberId: member.id, groupId: item.groupId, cycle: group.cycle })
231
+ const existingRegistrations = await Registration.where({ memberId: member.id, groupId: item.groupId, cycle: group.cycle });
230
232
 
231
233
  for (const existingRegistration of existingRegistrations) {
232
234
  if (item.replaceRegistrations.some(r => r.id === existingRegistration.id)) {
@@ -241,157 +243,159 @@ export class RegisterMembersEndpoint extends Endpoint<Params, Query, Body, Respo
241
243
 
242
244
  if (existingRegistration.registeredAt !== null && existingRegistration.deactivatedAt === null) {
243
245
  throw new SimpleError({
244
- code: "already_registered",
245
- message: `${member.firstName} is al ingeschreven voor ${group.settings.name}. Mogelijks heb je meerdere keren proberen in te schrijven en is het intussen wel gelukt. Herlaad de pagina best even om zeker te zijn.`
246
- })
246
+ code: 'already_registered',
247
+ message: `${member.firstName} is al ingeschreven voor ${group.settings.name}. Mogelijks heb je meerdere keren proberen in te schrijven en is het intussen wel gelukt. Herlaad de pagina best even om zeker te zijn.`,
248
+ });
247
249
  }
248
250
  }
249
251
 
250
252
  const registration = new Registration()
251
253
  .setRelation(registrationMemberRelation, member as Member)
252
- .setRelation(Registration.group, group)
253
- registration.organizationId = organization.id
254
- registration.periodId = group.periodId
254
+ .setRelation(Registration.group, group);
255
+ registration.organizationId = organization.id;
256
+ registration.periodId = group.periodId;
255
257
 
256
- registration.memberId = member.id
257
- registration.groupId = group.id
258
- registration.price = 0 // will get filled by balance items themselves
258
+ registration.memberId = member.id;
259
+ registration.groupId = group.id;
260
+ registration.price = 0; // will get filled by balance items themselves
259
261
  registration.groupPrice = item.groupPrice;
260
- registration.options = item.options
262
+ registration.options = item.options;
261
263
 
262
264
  payRegistrations.push({
263
265
  registration,
264
- item
266
+ item,
265
267
  });
266
268
 
267
- registrations.push(registration)
269
+ registrations.push(registration);
268
270
  }
269
271
 
270
272
  // Who is going to pay?
271
- let whoWillPayNow: 'member'|'organization'|'nobody' = 'member' // if this is set to 'organization', there will also be created separate balance items so the member can pay back the paying organization
273
+ let whoWillPayNow: 'member' | 'organization' | 'nobody' = 'member'; // if this is set to 'organization', there will also be created separate balance items so the member can pay back the paying organization
272
274
 
273
275
  if (request.body.asOrganizationId && request.body.asOrganizationId === organization.id) {
274
276
  // Will get added to the outstanding amount of the member
275
- whoWillPayNow = 'nobody'
276
- } else if (request.body.asOrganizationId && request.body.asOrganizationId !== organization.id) {
277
+ whoWillPayNow = 'nobody';
278
+ }
279
+ else if (request.body.asOrganizationId && request.body.asOrganizationId !== organization.id) {
277
280
  // The organization will pay to the organizing organization, and it will get added to the outstanding amount of the member towards the paying organization
278
- whoWillPayNow = 'organization'
281
+ whoWillPayNow = 'organization';
279
282
  }
280
283
 
281
284
  // Validate payment method
282
285
  if (totalPrice > 0 && whoWillPayNow !== 'nobody') {
283
- const allowedPaymentMethods = organization.meta.registrationPaymentConfiguration.paymentMethods
286
+ const allowedPaymentMethods = organization.meta.registrationPaymentConfiguration.paymentMethods;
284
287
 
285
288
  if (!checkout.paymentMethod || !allowedPaymentMethods.includes(checkout.paymentMethod)) {
286
289
  throw new SimpleError({
287
- code: "invalid_payment_method",
288
- message: "Oeps, je hebt geen geldige betaalmethode geselecteerd. Selecteer een betaalmethode en probeer opnieuw. Herlaad de pagina indien nodig."
289
- })
290
+ code: 'invalid_payment_method',
291
+ message: 'Oeps, je hebt geen geldige betaalmethode geselecteerd. Selecteer een betaalmethode en probeer opnieuw. Herlaad de pagina indien nodig.',
292
+ });
290
293
  }
291
294
 
292
295
  if ((checkout.paymentMethod !== PaymentMethod.Transfer && checkout.paymentMethod !== PaymentMethod.PointOfSale) && (!request.body.redirectUrl || !request.body.cancelUrl)) {
293
296
  throw new SimpleError({
294
297
  code: 'missing_fields',
295
298
  message: 'redirectUrl or cancelUrl is missing and is required for non-zero online payments',
296
- human: 'Er is iets mis. Contacteer de webmaster.'
297
- })
299
+ human: 'Er is iets mis. Contacteer de webmaster.',
300
+ });
298
301
  }
299
- } else {
300
- checkout.paymentMethod = PaymentMethod.Unknown
302
+ }
303
+ else {
304
+ checkout.paymentMethod = PaymentMethod.Unknown;
301
305
  }
302
306
 
303
- console.log('Registering members using whoWillPayNow', whoWillPayNow, checkout.paymentMethod, totalPrice)
307
+ console.log('Registering members using whoWillPayNow', whoWillPayNow, checkout.paymentMethod, totalPrice);
308
+
309
+ const createdBalanceItems: BalanceItem[] = [];
310
+ const unrelatedCreatedBalanceItems: BalanceItem[] = [];
311
+ const shouldMarkValid = whoWillPayNow === 'nobody' || checkout.paymentMethod === PaymentMethod.Transfer || checkout.paymentMethod === PaymentMethod.PointOfSale || checkout.paymentMethod === PaymentMethod.Unknown;
304
312
 
305
- const createdBalanceItems: BalanceItem[] = []
306
- const unrelatedCreatedBalanceItems: BalanceItem[] = []
307
- const shouldMarkValid = whoWillPayNow === 'nobody' || checkout.paymentMethod === PaymentMethod.Transfer || checkout.paymentMethod === PaymentMethod.PointOfSale || checkout.paymentMethod === PaymentMethod.Unknown
308
-
309
313
  // Create negative balance items
310
314
  for (const registrationStruct of [...checkout.cart.deleteRegistrations, ...checkout.cart.items.flatMap(i => i.replaceRegistrations)]) {
311
315
  if (whoWillPayNow !== 'nobody') {
312
- // this also fixes the issue that we cannot delete the registration right away if we would need to wait for a payment
316
+ // this also fixes the issue that we cannot delete the registration right away if we would need to wait for a payment
313
317
  throw new SimpleError({
314
- code: "forbidden",
315
- message: "Permission denied: you are not allowed to delete registrations",
316
- human: "Oeps, je hebt geen toestemming om inschrijvingen te verwijderen.",
317
- statusCode: 403
318
- })
318
+ code: 'forbidden',
319
+ message: 'Permission denied: you are not allowed to delete registrations',
320
+ human: 'Oeps, je hebt geen toestemming om inschrijvingen te verwijderen.',
321
+ statusCode: 403,
322
+ });
319
323
  }
320
324
 
321
- const existingRegistration = await Registration.getByID(registrationStruct.id)
325
+ const existingRegistration = await Registration.getByID(registrationStruct.id);
322
326
  if (!existingRegistration || existingRegistration.organizationId !== organization.id) {
323
327
  throw new SimpleError({
324
- code: "invalid_data",
325
- message: "Oeps, één of meerdere inschrijvingen die je probeert te verwijderen lijken niet meer te bestaan. Herlaad de pagina en probeer opnieuw."
326
- })
328
+ code: 'invalid_data',
329
+ message: 'Oeps, één of meerdere inschrijvingen die je probeert te verwijderen lijken niet meer te bestaan. Herlaad de pagina en probeer opnieuw.',
330
+ });
327
331
  }
328
332
 
329
333
  if (!await Context.auth.canAccessRegistration(existingRegistration, PermissionLevel.Write)) {
330
334
  throw new SimpleError({
331
- code: "forbidden",
332
- message: "Je hebt geen toegaansrechten om deze inschrijving te verwijderen.",
333
- statusCode: 403
334
- })
335
+ code: 'forbidden',
336
+ message: 'Je hebt geen toegaansrechten om deze inschrijving te verwijderen.',
337
+ statusCode: 403,
338
+ });
335
339
  }
336
340
 
337
341
  if (existingRegistration.deactivatedAt || !existingRegistration.registeredAt) {
338
342
  throw new SimpleError({
339
- code: "invalid_data",
340
- message: "Oeps, één of meerdere inschrijvingen die je probeert te verwijderen was al verwijderd. Herlaad de pagina en probeer opnieuw."
341
- })
343
+ code: 'invalid_data',
344
+ message: 'Oeps, één of meerdere inschrijvingen die je probeert te verwijderen was al verwijderd. Herlaad de pagina en probeer opnieuw.',
345
+ });
342
346
  }
343
347
 
344
348
  // We can alter right away since whoWillPayNow is nobody, and shouldMarkValid will always be true
345
349
  // Find all balance items of this registration and set them to zero
346
- await BalanceItem.deleteForDeletedRegistration(existingRegistration.id)
347
-
350
+ await BalanceItem.deleteForDeletedRegistration(existingRegistration.id);
351
+
348
352
  // Clear the registration
349
- await existingRegistration.deactivate()
353
+ await existingRegistration.deactivate();
350
354
  deactivatedRegistrationGroupIds.push(existingRegistration.groupId);
351
355
 
352
- const group = groups.find(g => g.id === existingRegistration.groupId)
356
+ const group = groups.find(g => g.id === existingRegistration.groupId);
353
357
  if (!group) {
354
- const g = await Group.getByID(existingRegistration.groupId)
358
+ const g = await Group.getByID(existingRegistration.groupId);
355
359
  if (g) {
356
- groups.push(g)
360
+ groups.push(g);
357
361
  }
358
362
  }
359
363
  }
360
364
 
361
- async function createBalanceItem({registration, amount, unitPrice, description, type, relations}: {amount?: number, registration: RegistrationWithMemberAndGroup, unitPrice: number, description: string, relations: Map<BalanceItemRelationType, BalanceItemRelation>, type: BalanceItemType}) {
365
+ async function createBalanceItem({ registration, amount, unitPrice, description, type, relations }: { amount?: number; registration: RegistrationWithMemberAndGroup; unitPrice: number; description: string; relations: Map<BalanceItemRelationType, BalanceItemRelation>; type: BalanceItemType }) {
362
366
  // NOTE: We also need to save zero-price balance items because for online payments, we need to know which registrations to activate after payment
363
367
 
364
368
  // Create balance item
365
369
  const balanceItem = new BalanceItem();
366
370
  balanceItem.registrationId = registration.id;
367
- balanceItem.unitPrice = unitPrice
368
- balanceItem.amount = amount ?? 1
369
- balanceItem.description = description
370
- balanceItem.relations = relations
371
- balanceItem.type = type
371
+ balanceItem.unitPrice = unitPrice;
372
+ balanceItem.amount = amount ?? 1;
373
+ balanceItem.description = description;
374
+ balanceItem.relations = relations;
375
+ balanceItem.type = type;
372
376
 
373
377
  // Who needs to receive this money?
374
378
  balanceItem.organizationId = organization.id;
375
379
 
376
380
  // Who is responsible for payment?
377
- let balanceItem2: BalanceItem | null = null
381
+ let balanceItem2: BalanceItem | null = null;
378
382
  if (whoWillPayNow === 'organization' && request.body.asOrganizationId) {
379
383
  // Create a separate balance item for this meber to pay back the paying organization
380
384
  // this is not yet associated with a payment but will be added to the outstanding balance of the member
381
385
 
382
- balanceItem.payingOrganizationId = request.body.asOrganizationId
386
+ balanceItem.payingOrganizationId = request.body.asOrganizationId;
383
387
 
384
388
  balanceItem2 = new BalanceItem();
385
389
 
386
390
  // NOTE: we don't connect the registrationId here
387
391
  // because otherwise the total price and pricePaid for the registration would be incorrect
388
- //balanceItem2.registrationId = registration.id;
392
+ // balanceItem2.registrationId = registration.id;
389
393
 
390
- balanceItem2.unitPrice = unitPrice
391
- balanceItem2.amount = amount ?? 1
392
- balanceItem2.description = description
393
- balanceItem2.relations = relations
394
- balanceItem2.type = type
394
+ balanceItem2.unitPrice = unitPrice;
395
+ balanceItem2.amount = amount ?? 1;
396
+ balanceItem2.description = description;
397
+ balanceItem2.relations = relations;
398
+ balanceItem2.type = type;
395
399
 
396
400
  // Who needs to receive this money?
397
401
  balanceItem2.organizationId = request.body.asOrganizationId;
@@ -400,46 +404,48 @@ export class RegisterMembersEndpoint extends Endpoint<Params, Query, Body, Respo
400
404
  balanceItem2.memberId = registration.memberId;
401
405
 
402
406
  // If the paying organization hasn't paid yet, this should be hidden and move to pending as soon as the paying organization has paid
403
- balanceItem2.status = shouldMarkValid ? BalanceItemStatus.Pending : BalanceItemStatus.Hidden
407
+ balanceItem2.status = shouldMarkValid ? BalanceItemStatus.Pending : BalanceItemStatus.Hidden;
404
408
  await balanceItem2.save();
405
409
 
406
410
  // do not add to createdBalanceItems array because we don't want to add this to the payment if we create a payment
407
- unrelatedCreatedBalanceItems.push(balanceItem2)
408
- } else {
411
+ unrelatedCreatedBalanceItems.push(balanceItem2);
412
+ }
413
+ else {
409
414
  balanceItem.memberId = registration.memberId;
410
- balanceItem.userId = user.id
415
+ balanceItem.userId = user.id;
411
416
  }
412
417
 
413
- balanceItem.status = shouldMarkValid ? BalanceItemStatus.Pending : BalanceItemStatus.Hidden
414
- balanceItem.pricePaid = 0
415
-
418
+ balanceItem.status = shouldMarkValid ? BalanceItemStatus.Pending : BalanceItemStatus.Hidden;
419
+ balanceItem.pricePaid = 0;
420
+
416
421
  // Connect the 'pay back' balance item to this balance item. As soon as this balance item is paid, we'll mark the other one as pending so the outstanding balance for the member increases
417
- balanceItem.dependingBalanceItemId = balanceItem2?.id ?? null
418
-
422
+ balanceItem.dependingBalanceItemId = balanceItem2?.id ?? null;
423
+
419
424
  await balanceItem.save();
420
- createdBalanceItems.push(balanceItem)
425
+ createdBalanceItems.push(balanceItem);
421
426
  }
422
427
 
423
428
  // Save registrations and add extra data if needed
424
429
  for (const bundle of payRegistrations) {
425
- const {item, registration} = bundle;
426
- registration.reservedUntil = null
430
+ const { item, registration } = bundle;
431
+ registration.reservedUntil = null;
427
432
 
428
433
  if (shouldMarkValid) {
429
- await registration.markValid({skipEmail: bundle.item.replaceRegistrations.length > 0})
430
- } else {
434
+ await registration.markValid({ skipEmail: bundle.item.replaceRegistrations.length > 0 });
435
+ }
436
+ else {
431
437
  // Reserve registration for 30 minutes (if needed)
432
- const group = groups.find(g => g.id === registration.groupId)
438
+ const group = groups.find(g => g.id === registration.groupId);
433
439
 
434
440
  if (group && group.settings.maxMembers !== null) {
435
- registration.reservedUntil = new Date(new Date().getTime() + 1000*60*30)
441
+ registration.reservedUntil = new Date(new Date().getTime() + 1000 * 60 * 30);
436
442
  }
437
- await registration.save()
443
+ await registration.save();
438
444
  }
439
445
 
440
446
  // Note: we should always create the balance items: even when the price is zero
441
447
  // Otherwise we don't know which registrations to activate after payment
442
-
448
+
443
449
  if (shouldMarkValid && item.calculatedPrice === 0) {
444
450
  continue;
445
451
  }
@@ -447,46 +453,46 @@ export class RegisterMembersEndpoint extends Endpoint<Params, Query, Body, Respo
447
453
  // Create balance items
448
454
  const sharedRelations: [BalanceItemRelationType, BalanceItemRelation][] = [
449
455
  [
450
- BalanceItemRelationType.Member,
456
+ BalanceItemRelationType.Member,
451
457
  BalanceItemRelation.create({
452
458
  id: item.member.id,
453
- name: item.member.patchedMember.name
454
- })
459
+ name: item.member.patchedMember.name,
460
+ }),
455
461
  ],
456
462
  [
457
- BalanceItemRelationType.Group,
463
+ BalanceItemRelationType.Group,
458
464
  BalanceItemRelation.create({
459
465
  id: item.group.id,
460
- name: item.group.settings.name
461
- })
462
- ]
463
- ]
466
+ name: item.group.settings.name,
467
+ }),
468
+ ],
469
+ ];
464
470
 
465
471
  if (item.group.settings.prices.length > 1) {
466
472
  sharedRelations.push([
467
- BalanceItemRelationType.GroupPrice,
473
+ BalanceItemRelationType.GroupPrice,
468
474
  BalanceItemRelation.create({
469
475
  id: item.groupPrice.id,
470
- name: item.groupPrice.name
471
- })
472
- ])
476
+ name: item.groupPrice.name,
477
+ }),
478
+ ]);
473
479
  }
474
480
 
475
481
  // Base price
476
482
  await createBalanceItem({
477
- registration,
483
+ registration,
478
484
  unitPrice: item.groupPrice.price.forMember(item.member),
479
485
  type: BalanceItemType.Registration,
480
486
  description: `${item.member.patchedMember.name} bij ${item.group.settings.name}`,
481
487
  relations: new Map([
482
- ...sharedRelations
483
- ])
484
- })
488
+ ...sharedRelations,
489
+ ]),
490
+ });
485
491
 
486
492
  // Options
487
493
  for (const option of item.options) {
488
494
  await createBalanceItem({
489
- registration,
495
+ registration,
490
496
  amount: option.amount,
491
497
  unitPrice: option.option.price.forMember(item.member),
492
498
  type: BalanceItemType.Registration,
@@ -494,66 +500,66 @@ export class RegisterMembersEndpoint extends Endpoint<Params, Query, Body, Respo
494
500
  relations: new Map([
495
501
  ...sharedRelations,
496
502
  [
497
- BalanceItemRelationType.GroupOptionMenu,
503
+ BalanceItemRelationType.GroupOptionMenu,
498
504
  BalanceItemRelation.create({
499
505
  id: option.optionMenu.id,
500
506
  name: option.optionMenu.name,
501
- })
507
+ }),
502
508
  ],
503
509
  [
504
- BalanceItemRelationType.GroupOption,
510
+ BalanceItemRelationType.GroupOption,
505
511
  BalanceItemRelation.create({
506
512
  id: option.option.id,
507
513
  name: option.option.name,
508
- })
509
- ]
510
- ])
511
- })
514
+ }),
515
+ ],
516
+ ]),
517
+ });
512
518
  }
513
-
514
519
  }
515
-
516
- const oldestMember = members.slice().sort((a, b) => b.details.defaultAge - a.details.defaultAge)[0]
520
+
521
+ const oldestMember = members.slice().sort((a, b) => b.details.defaultAge - a.details.defaultAge)[0];
517
522
  if (checkout.freeContribution && !request.body.asOrganizationId) {
518
523
  // Create balance item
519
524
  const balanceItem = new BalanceItem();
520
- balanceItem.type = BalanceItemType.FreeContribution
521
- balanceItem.unitPrice = checkout.freeContribution
522
- balanceItem.description = `Vrije bijdrage`
525
+ balanceItem.type = BalanceItemType.FreeContribution;
526
+ balanceItem.unitPrice = checkout.freeContribution;
527
+ balanceItem.description = `Vrije bijdrage`;
523
528
  balanceItem.pricePaid = 0;
524
- balanceItem.userId = user.id
529
+ balanceItem.userId = user.id;
525
530
  balanceItem.organizationId = organization.id;
526
531
 
527
532
  // Connect this to the oldest member
528
-
533
+
529
534
  if (oldestMember) {
530
535
  balanceItem.memberId = oldestMember.id;
531
536
  }
532
- balanceItem.status = shouldMarkValid ? BalanceItemStatus.Pending : BalanceItemStatus.Hidden
537
+ balanceItem.status = shouldMarkValid ? BalanceItemStatus.Pending : BalanceItemStatus.Hidden;
533
538
  await balanceItem.save();
534
- createdBalanceItems.push(balanceItem)
539
+ createdBalanceItems.push(balanceItem);
535
540
  }
536
541
 
537
542
  if (checkout.administrationFee && whoWillPayNow !== 'nobody') {
538
543
  // Create balance item
539
544
  const balanceItem = new BalanceItem();
540
- balanceItem.type = BalanceItemType.AdministrationFee
541
- balanceItem.unitPrice = checkout.administrationFee
542
- balanceItem.description = `Administratiekosten`
545
+ balanceItem.type = BalanceItemType.AdministrationFee;
546
+ balanceItem.unitPrice = checkout.administrationFee;
547
+ balanceItem.description = `Administratiekosten`;
543
548
  balanceItem.pricePaid = 0;
544
549
  balanceItem.organizationId = organization.id;
545
550
 
546
551
  if (request.body.asOrganizationId) {
547
- balanceItem.payingOrganizationId = request.body.asOrganizationId
548
- } else {
549
- balanceItem.userId = user.id
552
+ balanceItem.payingOrganizationId = request.body.asOrganizationId;
553
+ }
554
+ else {
555
+ balanceItem.userId = user.id;
550
556
  // Connect this to the oldest member
551
557
  if (oldestMember) {
552
558
  balanceItem.memberId = oldestMember.id;
553
559
  }
554
560
  }
555
561
 
556
- balanceItem.status = shouldMarkValid ? BalanceItemStatus.Pending : BalanceItemStatus.Hidden
562
+ balanceItem.status = shouldMarkValid ? BalanceItemStatus.Pending : BalanceItemStatus.Hidden;
557
563
  await balanceItem.save();
558
564
 
559
565
  createdBalanceItems.push(balanceItem);
@@ -563,105 +569,107 @@ export class RegisterMembersEndpoint extends Endpoint<Params, Query, Body, Respo
563
569
  throw new SimpleError({
564
570
  code: 'invalid_data',
565
571
  message: 'Not possible to pay balance items as the organization',
566
- statusCode: 400
567
- })
572
+ statusCode: 400,
573
+ });
568
574
  }
569
575
 
570
- let paymentUrl: string | null = null
571
- let payment: Payment | null = null
576
+ let paymentUrl: string | null = null;
577
+ let payment: Payment | null = null;
572
578
 
573
579
  if (whoWillPayNow !== 'nobody') {
574
- const mappedBalanceItems = new Map<BalanceItem, number>()
580
+ const mappedBalanceItems = new Map<BalanceItem, number>();
575
581
 
576
582
  for (const item of createdBalanceItems) {
577
- mappedBalanceItems.set(item, item.price)
583
+ mappedBalanceItems.set(item, item.price);
578
584
  }
579
585
 
580
586
  for (const item of checkout.cart.balanceItems) {
581
- const balanceItem = balanceItemsModels.find(i => i.id === item.item.id)
587
+ const balanceItem = balanceItemsModels.find(i => i.id === item.item.id);
582
588
  if (!balanceItem) {
583
- throw new Error('Balance item not found')
589
+ throw new Error('Balance item not found');
584
590
  }
585
- mappedBalanceItems.set(balanceItem, item.price)
586
- createdBalanceItems.push(balanceItem)
591
+ mappedBalanceItems.set(balanceItem, item.price);
592
+ createdBalanceItems.push(balanceItem);
587
593
  }
588
594
 
589
595
  // Make sure every price is accurate before creating a payment
590
- await BalanceItem.updateOutstanding([...createdBalanceItems, ...unrelatedCreatedBalanceItems])
596
+ await BalanceItem.updateOutstanding([...createdBalanceItems, ...unrelatedCreatedBalanceItems]);
591
597
  try {
592
598
  const response = await this.createPayment({
593
599
  balanceItems: mappedBalanceItems,
594
600
  organization,
595
601
  user,
596
602
  checkout: request.body,
597
- members
598
- })
603
+ members,
604
+ });
599
605
 
600
606
  if (response) {
601
- paymentUrl = response.paymentUrl
602
- payment = response.payment
607
+ paymentUrl = response.paymentUrl;
608
+ payment = response.payment;
603
609
  }
604
- } finally {
610
+ }
611
+ finally {
605
612
  // Update cached balance items pending amount (only created balance items, because those are involved in the payment)
606
- await BalanceItem.updateOutstanding(createdBalanceItems)
613
+ await BalanceItem.updateOutstanding(createdBalanceItems);
607
614
  }
608
- } else {
609
- await BalanceItem.updateOutstanding([...createdBalanceItems, ...unrelatedCreatedBalanceItems])
615
+ }
616
+ else {
617
+ await BalanceItem.updateOutstanding([...createdBalanceItems, ...unrelatedCreatedBalanceItems]);
610
618
  }
611
619
 
612
620
  // Update occupancy
613
621
  for (const group of groups) {
614
622
  if (registrations.some(r => r.groupId === group.id) || deactivatedRegistrationGroupIds.some(id => id === group.id)) {
615
- await group.updateOccupancy()
616
- await group.save()
623
+ await group.updateOccupancy();
624
+ await group.save();
617
625
  }
618
626
  }
619
627
 
620
- const updatedMembers = await Member.getBlobByIds(...memberIds)
628
+ const updatedMembers = await Member.getBlobByIds(...memberIds);
621
629
 
622
630
  return new Response(RegisterResponse.create({
623
631
  payment: payment ? PaymentStruct.create(payment) : null,
624
632
  members: await AuthenticatedStructures.membersBlob(updatedMembers),
625
633
  registrations: registrations.map(r => Member.getRegistrationWithMemberStructure(r)),
626
- paymentUrl
634
+ paymentUrl,
627
635
  }));
628
636
  }
629
637
 
630
- async createPayment({balanceItems, organization, user, checkout, members}: {balanceItems: Map<BalanceItem, number>, organization: Organization, user: User, checkout: IDRegisterCheckout, members: MemberWithRegistrations[]}) {
638
+ async createPayment({ balanceItems, organization, user, checkout, members }: { balanceItems: Map<BalanceItem, number>; organization: Organization; user: User; checkout: IDRegisterCheckout; members: MemberWithRegistrations[] }) {
631
639
  // Calculate total price to pay
632
- let totalPrice = 0
633
- const payMembers: MemberWithRegistrations[] = []
640
+ let totalPrice = 0;
641
+ const payMembers: MemberWithRegistrations[] = [];
634
642
 
635
643
  for (const [balanceItem, price] of balanceItems) {
636
644
  if (organization.id !== balanceItem.organizationId) {
637
- throw new Error('Unexpected balance item from other organization')
645
+ throw new Error('Unexpected balance item from other organization');
638
646
  }
639
647
 
640
648
  if (price > 0 && price > Math.max(balanceItem.priceOpen, balanceItem.price - balanceItem.pricePaid)) {
641
649
  throw new SimpleError({
642
- code: "invalid_data",
643
- message: "Oeps, het bedrag dat je probeert te betalen is ongeldig (het bedrag is hoger dan het bedrag dat je moet betalen). Herlaad de pagina en probeer opnieuw."
644
- })
650
+ code: 'invalid_data',
651
+ message: 'Oeps, het bedrag dat je probeert te betalen is ongeldig (het bedrag is hoger dan het bedrag dat je moet betalen). Herlaad de pagina en probeer opnieuw.',
652
+ });
645
653
  }
646
654
 
647
655
  if (price < 0 && price < Math.min(balanceItem.priceOpen, balanceItem.price - balanceItem.pricePaid)) {
648
656
  throw new SimpleError({
649
- code: "invalid_data",
650
- message: "Oeps, het bedrag dat je probeert te betalen is ongeldig (het terug te krijgen bedrag is hoger dan het bedrag dat je kan terug krijgen). Herlaad de pagina en probeer opnieuw."
651
- })
657
+ code: 'invalid_data',
658
+ message: 'Oeps, het bedrag dat je probeert te betalen is ongeldig (het terug te krijgen bedrag is hoger dan het bedrag dat je kan terug krijgen). Herlaad de pagina en probeer opnieuw.',
659
+ });
652
660
  }
653
661
 
654
- totalPrice += price
662
+ totalPrice += price;
655
663
 
656
664
  if (price > 0 && balanceItem.memberId) {
657
- const member = members.find(m => m.id === balanceItem.memberId)
665
+ const member = members.find(m => m.id === balanceItem.memberId);
658
666
  if (!member) {
659
667
  throw new SimpleError({
660
- code: "invalid_data",
661
- message: "Oeps, het lid dat je probeert in te schrijven konden we niet meer terugvinden. Je herlaadt best even de pagina om opnieuw te proberen."
662
- })
668
+ code: 'invalid_data',
669
+ message: 'Oeps, het lid dat je probeert in te schrijven konden we niet meer terugvinden. Je herlaadt best even de pagina om opnieuw te proberen.',
670
+ });
663
671
  }
664
- payMembers.push(member)
672
+ payMembers.push(member);
665
673
  }
666
674
  }
667
675
 
@@ -680,150 +688,152 @@ export class RegisterMembersEndpoint extends Endpoint<Params, Query, Body, Respo
680
688
 
681
689
  if (!checkout.paymentMethod || checkout.paymentMethod === PaymentMethod.Unknown) {
682
690
  throw new SimpleError({
683
- code: "invalid_data",
684
- message: "Oeps, je hebt geen betaalmethode geselecteerd. Selecteer een betaalmethode en probeer opnieuw."
685
- })
691
+ code: 'invalid_data',
692
+ message: 'Oeps, je hebt geen betaalmethode geselecteerd. Selecteer een betaalmethode en probeer opnieuw.',
693
+ });
686
694
  }
687
695
 
688
- const payment = new Payment()
696
+ const payment = new Payment();
689
697
 
690
698
  // Who will receive this money?
691
- payment.organizationId = organization.id
699
+ payment.organizationId = organization.id;
692
700
 
693
701
  // Who paid
694
- payment.payingUserId = user.id
695
- payment.payingOrganizationId = checkout.asOrganizationId ?? null
702
+ payment.payingUserId = user.id;
703
+ payment.payingOrganizationId = checkout.asOrganizationId ?? null;
696
704
 
697
705
  // Fill in customer:
698
706
  payment.customer = PaymentCustomer.create({
699
707
  firstName: user.firstName,
700
708
  lastName: user.lastName,
701
709
  email: user.email,
702
- })
710
+ });
703
711
 
704
712
  if (checkout.asOrganizationId) {
705
713
  if (!checkout.customer) {
706
714
  throw new SimpleError({
707
- code: "missing_fields",
708
- message: "customer is required when paying as an organization",
709
- human: "Vul je facturatiegegevens in om verder te gaan."
710
- })
715
+ code: 'missing_fields',
716
+ message: 'customer is required when paying as an organization',
717
+ human: 'Vul je facturatiegegevens in om verder te gaan.',
718
+ });
711
719
  }
712
720
 
713
721
  if (!checkout.customer.company) {
714
722
  throw new SimpleError({
715
- code: "missing_fields",
716
- message: "customer.company is required when paying as an organization",
717
- human: "Als je een betaling uitvoert in naam van je vereniging, is het noodzakelijk om facturatiegegevens met bedrijfsgegevens in te vullen."
718
- })
723
+ code: 'missing_fields',
724
+ message: 'customer.company is required when paying as an organization',
725
+ human: 'Als je een betaling uitvoert in naam van je vereniging, is het noodzakelijk om facturatiegegevens met bedrijfsgegevens in te vullen.',
726
+ });
719
727
  }
720
728
 
721
729
  const payingOrganization = await Organization.getByID(checkout.asOrganizationId);
722
730
  if (!payingOrganization) {
723
731
  throw new SimpleError({
724
- code: "invalid_data",
725
- message: "Oeps, de organisatie waarvoor je probeert te betalen lijkt niet meer te bestaan. Herlaad de pagina en probeer opnieuw."
726
- })
732
+ code: 'invalid_data',
733
+ message: 'Oeps, de organisatie waarvoor je probeert te betalen lijkt niet meer te bestaan. Herlaad de pagina en probeer opnieuw.',
734
+ });
727
735
  }
728
736
 
729
737
  // Search company id
730
738
  // this avoids needing to check the VAT number every time
731
- const id = checkout.customer.company.id
732
- const foundCompany = payingOrganization.meta.companies.find(c => c.id === id)
739
+ const id = checkout.customer.company.id;
740
+ const foundCompany = payingOrganization.meta.companies.find(c => c.id === id);
733
741
 
734
742
  if (!foundCompany) {
735
743
  throw new SimpleError({
736
- code: "invalid_data",
737
- message: "Oeps, de facturatiegegevens die je probeerde te selecteren lijken niet meer te bestaan. Herlaad de pagina en probeer opnieuw."
738
- })
744
+ code: 'invalid_data',
745
+ message: 'Oeps, de facturatiegegevens die je probeerde te selecteren lijken niet meer te bestaan. Herlaad de pagina en probeer opnieuw.',
746
+ });
739
747
  }
740
748
 
741
- payment.customer.company = foundCompany
749
+ payment.customer.company = foundCompany;
742
750
  }
743
751
 
744
- payment.method = checkout.paymentMethod
745
- payment.status = PaymentStatus.Created
746
- payment.price = totalPrice
752
+ payment.method = checkout.paymentMethod;
753
+ payment.status = PaymentStatus.Created;
754
+ payment.price = totalPrice;
747
755
 
748
756
  if (payment.method == PaymentMethod.Transfer) {
749
757
  // remark: we cannot add the lastnames, these will get added in the frontend when it is decrypted
750
- payment.transferSettings = organization.mappedTransferSettings
758
+ payment.transferSettings = organization.mappedTransferSettings;
751
759
 
752
760
  if (!payment.transferSettings.iban) {
753
761
  throw new SimpleError({
754
- code: "no_iban",
755
- message: "No IBAN",
756
- human: "Er is geen rekeningnummer ingesteld voor overschrijvingen. Contacteer de beheerder."
757
- })
762
+ code: 'no_iban',
763
+ message: 'No IBAN',
764
+ human: 'Er is geen rekeningnummer ingesteld voor overschrijvingen. Contacteer de beheerder.',
765
+ });
758
766
  }
759
767
 
760
- const m = payMembers.map(r => r.details)
768
+ const m = payMembers.map(r => r.details);
761
769
  payment.generateDescription(
762
- organization,
770
+ organization,
763
771
  Formatter.groupNamesByFamily(m),
764
772
  {
765
773
  name: Formatter.groupNamesByFamily(m),
766
- naam: Formatter.groupNamesByFamily(m),
767
- email: user.email
768
- }
769
- )
774
+ naam: Formatter.groupNamesByFamily(m),
775
+ email: user.email,
776
+ },
777
+ );
770
778
  }
771
- payment.paidAt = null
779
+ payment.paidAt = null;
772
780
 
773
781
  // Determine the payment provider
774
782
  // Throws if invalid
775
- const {provider, stripeAccount} = await organization.getPaymentProviderFor(payment.method, organization.privateMeta.registrationPaymentConfiguration)
776
- payment.provider = provider
777
- payment.stripeAccountId = stripeAccount?.id ?? null
783
+ const { provider, stripeAccount } = await organization.getPaymentProviderFor(payment.method, organization.privateMeta.registrationPaymentConfiguration);
784
+ payment.provider = provider;
785
+ payment.stripeAccountId = stripeAccount?.id ?? null;
778
786
 
779
- await payment.save()
787
+ await payment.save();
780
788
 
781
789
  // Create balance item payments
782
- const balanceItemPayments: (BalanceItemPayment & { balanceItem: BalanceItem })[] = []
790
+ const balanceItemPayments: (BalanceItemPayment & { balanceItem: BalanceItem })[] = [];
783
791
 
784
792
  for (const [balanceItem, price] of balanceItems) {
785
793
  // Create one balance item payment to pay it in one payment
786
- const balanceItemPayment = new BalanceItemPayment()
794
+ const balanceItemPayment = new BalanceItemPayment();
787
795
  balanceItemPayment.balanceItemId = balanceItem.id;
788
796
  balanceItemPayment.paymentId = payment.id;
789
797
  balanceItemPayment.organizationId = organization.id;
790
798
  balanceItemPayment.price = price;
791
799
  await balanceItemPayment.save();
792
800
 
793
- balanceItemPayments.push(balanceItemPayment.setRelation(BalanceItemPayment.balanceItem, balanceItem))
801
+ balanceItemPayments.push(balanceItemPayment.setRelation(BalanceItemPayment.balanceItem, balanceItem));
794
802
  }
795
803
 
796
- const description = 'Inschrijving '+organization.name
804
+ const description = 'Inschrijving ' + organization.name;
797
805
 
798
- let paymentUrl: string | null = null
806
+ let paymentUrl: string | null = null;
799
807
 
800
808
  // Update balance items
801
809
  if (payment.method === PaymentMethod.Transfer) {
802
810
  // Send a small reminder email
803
811
  try {
804
- await Registration.sendTransferEmail(user, organization, payment)
805
- } catch (e) {
806
- console.error("Failed to send transfer email")
807
- console.error(e)
812
+ await Registration.sendTransferEmail(user, organization, payment);
813
+ }
814
+ catch (e) {
815
+ console.error('Failed to send transfer email');
816
+ console.error(e);
808
817
  }
809
- } else if (payment.method !== PaymentMethod.PointOfSale) {
818
+ }
819
+ else if (payment.method !== PaymentMethod.PointOfSale) {
810
820
  if (!checkout.redirectUrl || !checkout.cancelUrl) {
811
- throw new Error('Should have been caught earlier')
821
+ throw new Error('Should have been caught earlier');
812
822
  }
813
823
 
814
- const _redirectUrl = new URL(checkout.redirectUrl)
824
+ const _redirectUrl = new URL(checkout.redirectUrl);
815
825
  _redirectUrl.searchParams.set('paymentId', payment.id);
816
826
  _redirectUrl.searchParams.set('organizationId', organization.id); // makes sure the client uses the token associated with this organization when fetching payment polling status
817
827
 
818
- const _cancelUrl = new URL(checkout.cancelUrl)
828
+ const _cancelUrl = new URL(checkout.cancelUrl);
819
829
  _cancelUrl.searchParams.set('paymentId', payment.id);
820
830
  _cancelUrl.searchParams.set('cancel', 'true');
821
831
  _cancelUrl.searchParams.set('organizationId', organization.id); // makes sure the client uses the token associated with this organization when fetching payment polling status
822
832
 
823
- const redirectUrl = _redirectUrl.href
824
- const cancelUrl = _cancelUrl.href
833
+ const redirectUrl = _redirectUrl.href;
834
+ const cancelUrl = _cancelUrl.href;
825
835
 
826
- const webhookUrl = 'https://'+organization.getApiHost()+"/v"+Version+"/payments/"+encodeURIComponent(payment.id)+"?exchange=true"
836
+ const webhookUrl = 'https://' + organization.getApiHost() + '/v' + Version + '/payments/' + encodeURIComponent(payment.id) + '?exchange=true';
827
837
 
828
838
  if (payment.provider === PaymentProvider.Stripe) {
829
839
  const stripeResult = await StripeHelper.createPayment({
@@ -835,7 +845,7 @@ export class RegisterMembersEndpoint extends Endpoint<Params, Query, Body, Respo
835
845
  metadata: {
836
846
  organization: organization.id,
837
847
  user: user.id,
838
- payment: payment.id
848
+ payment: payment.id,
839
849
  },
840
850
  i18n: Context.i18n,
841
851
  lineItems: balanceItemPayments,
@@ -843,34 +853,34 @@ export class RegisterMembersEndpoint extends Endpoint<Params, Query, Body, Respo
843
853
  customer: {
844
854
  name: user.name ?? payMembers[0]?.details.name ?? 'Onbekend',
845
855
  email: user.email,
846
- }
856
+ },
847
857
  });
848
- paymentUrl = stripeResult.paymentUrl
849
- } else if (payment.provider === PaymentProvider.Mollie) {
850
-
858
+ paymentUrl = stripeResult.paymentUrl;
859
+ }
860
+ else if (payment.provider === PaymentProvider.Mollie) {
851
861
  // Mollie payment
852
- const token = await MollieToken.getTokenFor(organization.id)
862
+ const token = await MollieToken.getTokenFor(organization.id);
853
863
  if (!token) {
854
864
  throw new SimpleError({
855
- code: "",
856
- message: "Betaling via " + PaymentMethodHelper.getName(payment.method) + " is onbeschikbaar"
857
- })
865
+ code: '',
866
+ message: 'Betaling via ' + PaymentMethodHelper.getName(payment.method) + ' is onbeschikbaar',
867
+ });
858
868
  }
859
- const profileId = organization.privateMeta.mollieProfile?.id ?? await token.getProfileId(organization.getHost())
869
+ const profileId = organization.privateMeta.mollieProfile?.id ?? await token.getProfileId(organization.getHost());
860
870
  if (!profileId) {
861
871
  throw new SimpleError({
862
- code: "",
863
- message: "Betaling via " + PaymentMethodHelper.getName(payment.method) + " is tijdelijk onbeschikbaar"
864
- })
872
+ code: '',
873
+ message: 'Betaling via ' + PaymentMethodHelper.getName(payment.method) + ' is tijdelijk onbeschikbaar',
874
+ });
865
875
  }
866
876
  const mollieClient = createMollieClient({ accessToken: await token.getAccessToken() });
867
877
  const molliePayment = await mollieClient.payments.create({
868
878
  amount: {
869
879
  currency: 'EUR',
870
- value: (totalPrice / 100).toFixed(2)
880
+ value: (totalPrice / 100).toFixed(2),
871
881
  },
872
882
  method: payment.method == PaymentMethod.Bancontact ? molliePaymentMethod.bancontact : (payment.method == PaymentMethod.iDEAL ? molliePaymentMethod.ideal : molliePaymentMethod.creditcard),
873
- testmode: organization.privateMeta.useTestPayments ?? STAMHOOFD.environment != 'production',
883
+ testmode: organization.privateMeta.useTestPayments ?? STAMHOOFD.environment !== 'production',
874
884
  profileId,
875
885
  description,
876
886
  redirectUrl,
@@ -879,29 +889,31 @@ export class RegisterMembersEndpoint extends Endpoint<Params, Query, Body, Respo
879
889
  paymentId: payment.id,
880
890
  },
881
891
  });
882
- paymentUrl = molliePayment.getCheckoutUrl()
892
+ paymentUrl = molliePayment.getCheckoutUrl();
883
893
 
884
894
  // Save payment
885
- const dbPayment = new MolliePayment()
886
- dbPayment.paymentId = payment.id
887
- dbPayment.mollieId = molliePayment.id
895
+ const dbPayment = new MolliePayment();
896
+ dbPayment.paymentId = payment.id;
897
+ dbPayment.mollieId = molliePayment.id;
888
898
  await dbPayment.save();
889
- } else if (payment.provider === PaymentProvider.Payconiq) {
890
- paymentUrl = await PayconiqPayment.createPayment(payment, organization, description, redirectUrl, webhookUrl)
891
- } else if (payment.provider == PaymentProvider.Buckaroo) {
899
+ }
900
+ else if (payment.provider === PaymentProvider.Payconiq) {
901
+ paymentUrl = await PayconiqPayment.createPayment(payment, organization, description, redirectUrl, webhookUrl);
902
+ }
903
+ else if (payment.provider == PaymentProvider.Buckaroo) {
892
904
  // Increase request timeout because buckaroo is super slow (in development)
893
- Context.request.request?.setTimeout(60 * 1000)
894
- const buckaroo = new BuckarooHelper(organization.privateMeta?.buckarooSettings?.key ?? "", organization.privateMeta?.buckarooSettings?.secret ?? "", organization.privateMeta.useTestPayments ?? STAMHOOFD.environment != 'production')
895
- const ip = Context.request.getIP()
896
- paymentUrl = await buckaroo.createPayment(payment, ip, description, redirectUrl, webhookUrl)
897
- await payment.save()
905
+ Context.request.request?.setTimeout(60 * 1000);
906
+ const buckaroo = new BuckarooHelper(organization.privateMeta?.buckarooSettings?.key ?? '', organization.privateMeta?.buckarooSettings?.secret ?? '', organization.privateMeta.useTestPayments ?? STAMHOOFD.environment !== 'production');
907
+ const ip = Context.request.getIP();
908
+ paymentUrl = await buckaroo.createPayment(payment, ip, description, redirectUrl, webhookUrl);
909
+ await payment.save();
898
910
 
899
911
  // TypeScript doesn't understand that the status can change and isn't a const....
900
912
  if ((payment.status as any) === PaymentStatus.Failed) {
901
913
  throw new SimpleError({
902
- code: "payment_failed",
903
- message: "Betaling via " + PaymentMethodHelper.getName(payment.method) + " is onbeschikbaar"
904
- })
914
+ code: 'payment_failed',
915
+ message: 'Betaling via ' + PaymentMethodHelper.getName(payment.method) + ' is onbeschikbaar',
916
+ });
905
917
  }
906
918
  }
907
919
  }
@@ -911,7 +923,7 @@ export class RegisterMembersEndpoint extends Endpoint<Params, Query, Body, Respo
911
923
  balanceItemPayments,
912
924
  provider,
913
925
  stripeAccount,
914
- paymentUrl
915
- }
926
+ paymentUrl,
927
+ };
916
928
  }
917
929
  }