@stamhoofd/backend 2.115.1 → 2.117.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 (284) hide show
  1. package/migrations.ts +1 -1
  2. package/package.json +10 -10
  3. package/src/audit-logs/DocumentTemplateLogger.ts +1 -1
  4. package/src/audit-logs/EmailAddressLogger.ts +1 -1
  5. package/src/audit-logs/EmailLogger.ts +1 -1
  6. package/src/audit-logs/EmailTemplateLogger.ts +1 -1
  7. package/src/audit-logs/EventLogger.ts +1 -1
  8. package/src/audit-logs/GroupLogger.ts +1 -1
  9. package/src/audit-logs/MemberLogger.ts +1 -1
  10. package/src/audit-logs/MemberPlatformMembershipLogger.ts +1 -1
  11. package/src/audit-logs/MemberResponsibilityRecordLogger.ts +1 -1
  12. package/src/audit-logs/ModelLogger.ts +27 -19
  13. package/src/audit-logs/OrderLogger.ts +1 -1
  14. package/src/audit-logs/OrganizationLogger.ts +23 -3
  15. package/src/audit-logs/OrganizationRegistrationPeriodLogger.ts +1 -1
  16. package/src/audit-logs/PaymentLogger.ts +1 -1
  17. package/src/audit-logs/PlatformLogger.ts +1 -1
  18. package/src/audit-logs/RegistrationLogger.ts +1 -1
  19. package/src/audit-logs/RegistrationPeriodLogger.ts +1 -1
  20. package/src/audit-logs/StripeAccountLogger.ts +1 -1
  21. package/src/audit-logs/UserLogger.ts +1 -1
  22. package/src/audit-logs/WebshopLogger.ts +1 -1
  23. package/src/audit-logs/init.ts +40 -0
  24. package/src/boot.ts +6 -4
  25. package/src/crons/amazon-ses.ts +1 -1
  26. package/src/crons/balance-emails.ts +1 -1
  27. package/src/crons/clearExcelCache.test.ts +1 -1
  28. package/src/crons/delete-archived-data.ts +47 -0
  29. package/src/crons/endFunctionsOfUsersWithoutRegistration.ts +1 -1
  30. package/src/crons/index.ts +1 -0
  31. package/src/crons.ts +3 -3
  32. package/src/debug.ts +230 -0
  33. package/src/email-recipient-loaders/documents.ts +1 -1
  34. package/src/email-recipient-loaders/members.ts +1 -1
  35. package/src/email-recipient-loaders/orders.ts +3 -3
  36. package/src/email-recipient-loaders/payments.ts +118 -353
  37. package/src/email-replacements/getEmailReplacementsForPayment.ts +321 -0
  38. package/src/endpoints/admin/members/ChargeMembersEndpoint.ts +9 -7
  39. package/src/endpoints/admin/memberships/ChargeMembershipsEndpoint.ts +2 -2
  40. package/src/endpoints/admin/memberships/GetChargeMembershipsSummaryEndpoint.ts +1 -1
  41. package/src/endpoints/admin/organizations/ChargeOrganizationsEndpoint.ts +16 -50
  42. package/src/endpoints/admin/organizations/GetOrganizationsCountEndpoint.ts +2 -2
  43. package/src/endpoints/admin/organizations/GetOrganizationsEndpoint.ts +4 -4
  44. package/src/endpoints/admin/organizations/PatchOrganizationsEndpoint.ts +21 -6
  45. package/src/endpoints/admin/registrations/ChargeRegistrationsEndpoint.ts +9 -7
  46. package/src/endpoints/auth/CreateAdminEndpoint.ts +2 -2
  47. package/src/endpoints/auth/CreateTokenEndpoint.test.ts +2 -2
  48. package/src/endpoints/auth/CreateTokenEndpoint.ts +1 -1
  49. package/src/endpoints/auth/DeleteTokenEndpoint.ts +1 -1
  50. package/src/endpoints/auth/DeleteUserEndpoint.ts +1 -1
  51. package/src/endpoints/auth/ForgotPasswordEndpoint.ts +1 -1
  52. package/src/endpoints/auth/GetOtherUserEndpoint.ts +2 -2
  53. package/src/endpoints/auth/GetUserEndpoint.test.ts +2 -2
  54. package/src/endpoints/auth/GetUserEndpoint.ts +2 -2
  55. package/src/endpoints/auth/OpenIDConnectAuthTokenEndpoint.ts +2 -2
  56. package/src/endpoints/auth/OpenIDConnectCallbackEndpoint.ts +2 -2
  57. package/src/endpoints/auth/OpenIDConnectStartEndpoint.ts +2 -2
  58. package/src/endpoints/auth/PatchUserEndpoint.ts +4 -4
  59. package/src/endpoints/auth/PollEmailVerificationEndpoint.ts +1 -1
  60. package/src/endpoints/auth/RetryEmailVerificationEndpoint.ts +1 -1
  61. package/src/endpoints/auth/SignupEndpoint.ts +1 -1
  62. package/src/endpoints/auth/VerifyEmailEndpoint.ts +1 -1
  63. package/src/endpoints/global/addresses/ValidateAddressEndpoint.ts +1 -1
  64. package/src/endpoints/global/audit-logs/GetAuditLogsEndpoint.ts +4 -4
  65. package/src/endpoints/global/billing/ActivatePackagesEndpoint.ts +191 -7
  66. package/src/endpoints/global/billing/DeactivatePackageEndpoint.ts +64 -0
  67. package/src/endpoints/global/email/GetAdminEmailsEndpoint.test.ts +2 -2
  68. package/src/endpoints/global/email/GetAdminEmailsEndpoint.ts +3 -3
  69. package/src/endpoints/global/email/GetEmailAddressEndpoint.ts +1 -1
  70. package/src/endpoints/global/email/GetEmailEndpoint.ts +1 -1
  71. package/src/endpoints/global/email/GetUserEmailsEndpoint.test.ts +2 -2
  72. package/src/endpoints/global/email/GetUserEmailsEndpoint.ts +3 -3
  73. package/src/endpoints/global/email/ManageEmailAddressEndpoint.ts +62 -16
  74. package/src/endpoints/global/email/PatchEmailEndpoint.test.ts +6 -6
  75. package/src/endpoints/global/email-recipients/GetEmailRecipientsCountEndpoint.ts +2 -2
  76. package/src/endpoints/global/email-recipients/GetEmailRecipientsEndpoint.test.ts +2 -2
  77. package/src/endpoints/global/email-recipients/GetEmailRecipientsEndpoint.ts +4 -4
  78. package/src/endpoints/global/email-recipients/RetryEmailRecipientEndpoint.ts +1 -1
  79. package/src/endpoints/global/email-recipients/helpers/validateEmailRecipientFilter.ts +1 -1
  80. package/src/endpoints/global/events/GetEventNotificationsCountEndpoint.ts +2 -2
  81. package/src/endpoints/global/events/GetEventNotificationsEndpoint.ts +4 -4
  82. package/src/endpoints/global/events/GetEventsEndpoint.ts +4 -4
  83. package/src/endpoints/global/events/PatchEventNotificationsEndpoint.test.ts +2 -2
  84. package/src/endpoints/global/events/PatchEventNotificationsEndpoint.ts +3 -3
  85. package/src/endpoints/global/events/PatchEventsEndpoint.test.ts +2 -2
  86. package/src/endpoints/global/events/PatchEventsEndpoint.ts +5 -5
  87. package/src/endpoints/global/files/ExportToExcelEndpoint.ts +4 -4
  88. package/src/endpoints/global/files/GetFileCache.ts +2 -2
  89. package/src/endpoints/global/files/UploadFile.ts +2 -2
  90. package/src/endpoints/global/files/UploadImage.ts +1 -1
  91. package/src/endpoints/global/groups/GetGroupsEndpoint.test.ts +3 -3
  92. package/src/endpoints/global/groups/GetGroupsEndpoint.ts +4 -4
  93. package/src/endpoints/global/members/GetMemberFamilyEndpoint.ts +4 -4
  94. package/src/endpoints/global/members/GetMembersEndpoint.test.ts +3 -3
  95. package/src/endpoints/global/members/GetMembersEndpoint.ts +4 -16
  96. package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.ts +8 -7
  97. package/src/endpoints/global/members/helpers/validateGroupFilter.ts +1 -1
  98. package/src/endpoints/global/organizations/CreateOrganizationEndpoint.test.ts +2 -2
  99. package/src/endpoints/global/organizations/CreateOrganizationEndpoint.ts +23 -12
  100. package/src/endpoints/global/organizations/GetOrganizationFromDomainEndpoint.test.ts +2 -2
  101. package/src/endpoints/global/organizations/GetOrganizationFromDomainEndpoint.ts +1 -1
  102. package/src/endpoints/global/organizations/GetOrganizationFromUriEndpoint.ts +1 -1
  103. package/src/endpoints/global/organizations/SearchOrganizationEndpoint.test.ts +2 -2
  104. package/src/endpoints/global/organizations/SearchOrganizationEndpoint.ts +1 -1
  105. package/src/endpoints/global/payments/StripeWebhookEndpoint.ts +3 -3
  106. package/src/endpoints/global/platform/GetPlatformAdminsEndpoint.ts +1 -1
  107. package/src/endpoints/global/platform/GetPlatformEndpoint.test.ts +2 -2
  108. package/src/endpoints/global/platform/GetPlatformEndpoint.ts +1 -1
  109. package/src/endpoints/global/platform/PatchPlatformEnpoint.test.ts +2 -2
  110. package/src/endpoints/global/platform/PatchPlatformEnpoint.ts +7 -7
  111. package/src/endpoints/global/registration/GetRegistrationsEndpoint.test.ts +2 -2
  112. package/src/endpoints/global/registration/GetRegistrationsEndpoint.ts +1 -2
  113. package/src/endpoints/global/registration/GetUserDetailedPayableBalanceEndpoint.ts +2 -2
  114. package/src/endpoints/global/registration/GetUserDocumentsEndpoint.ts +2 -2
  115. package/src/endpoints/global/registration/GetUserMembersEndpoint.ts +2 -2
  116. package/src/endpoints/global/registration/GetUserPayableBalanceEndpoint.ts +2 -2
  117. package/src/endpoints/global/registration/RegisterMembersEndpoint.test.ts +2 -2
  118. package/src/endpoints/global/registration/RegisterMembersEndpoint.ts +24 -389
  119. package/src/endpoints/global/registration-periods/GetRegistrationPeriodsEndpoint.ts +3 -3
  120. package/src/endpoints/global/registration-periods/PatchRegistrationPeriodsEndpoint.ts +2 -2
  121. package/src/endpoints/global/sso/GetSSOEndpoint.ts +2 -2
  122. package/src/endpoints/global/sso/SetSSOEndpoint.ts +3 -3
  123. package/src/endpoints/organization/dashboard/balance-items/GetBalanceItemEndpoint.ts +55 -0
  124. package/src/endpoints/organization/dashboard/balance-items/GetBalanceItemsCountEndpoint.ts +43 -0
  125. package/src/endpoints/organization/dashboard/balance-items/GetBalanceItemsEndpoint.ts +160 -0
  126. package/src/endpoints/organization/dashboard/{payments → balance-items}/PatchBalanceItemsEndpoint.ts +1 -1
  127. package/src/endpoints/organization/dashboard/billing/GetOrganizationDetailedPayableBalanceEndpoint.ts +2 -2
  128. package/src/endpoints/organization/dashboard/billing/GetOrganizationPayableBalanceEndpoint.ts +2 -2
  129. package/src/endpoints/organization/dashboard/billing/GetPackagesEndpoint.test.ts +3 -3
  130. package/src/endpoints/organization/dashboard/billing/GetPackagesEndpoint.ts +3 -3
  131. package/src/endpoints/organization/dashboard/documents/GetDocumentTemplateXML.ts +1 -1
  132. package/src/endpoints/organization/dashboard/documents/GetDocumentsCountEndpoint.ts +2 -2
  133. package/src/endpoints/organization/dashboard/documents/PatchDocumentEndpoint.ts +2 -2
  134. package/src/endpoints/organization/dashboard/email/CheckEmailBouncesEndpoint.ts +37 -6
  135. package/src/endpoints/organization/dashboard/email-templates/GetEmailTemplatesEndpoint.test.ts +2 -2
  136. package/src/endpoints/organization/dashboard/email-templates/GetEmailTemplatesEndpoint.ts +3 -3
  137. package/src/endpoints/organization/dashboard/email-templates/PatchEmailTemplatesEndpoint.test.ts +2 -2
  138. package/src/endpoints/organization/dashboard/email-templates/PatchEmailTemplatesEndpoint.ts +1 -1
  139. package/src/endpoints/organization/dashboard/invoices/PatchInvoicesEndpoint.ts +53 -0
  140. package/src/endpoints/organization/dashboard/mollie/CheckMollieEndpoint.ts +2 -2
  141. package/src/endpoints/organization/dashboard/mollie/ConnectMollieEndpoint.ts +3 -3
  142. package/src/endpoints/organization/dashboard/mollie/DisconnectMollieEndpoint.ts +2 -2
  143. package/src/endpoints/organization/dashboard/mollie/GetMollieDashboardEndpoint.ts +1 -1
  144. package/src/endpoints/organization/dashboard/nolt/CreateNoltTokenEndpoint.ts +1 -1
  145. package/src/endpoints/organization/dashboard/organization/GetOrganizationArchivedGroups.ts +2 -2
  146. package/src/endpoints/organization/dashboard/organization/GetOrganizationDeletedGroups.ts +2 -2
  147. package/src/endpoints/organization/dashboard/organization/GetUitpasClientIdEndpoint.ts +2 -2
  148. package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.test.ts +2 -2
  149. package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.ts +12 -1
  150. package/src/endpoints/organization/dashboard/organization/SearchUitpasOrganizersEndpoint.ts +2 -2
  151. package/src/endpoints/organization/dashboard/organization/SetOrganizationDomainEndpoint.ts +2 -2
  152. package/src/endpoints/organization/dashboard/organization/SetUitpasClientCredentialsEndpoint.ts +2 -2
  153. package/src/endpoints/organization/dashboard/payments/GetPaymentsCountEndpoint.ts +2 -2
  154. package/src/endpoints/organization/dashboard/payments/GetPaymentsEndpoint.ts +4 -4
  155. package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalanceEndpoint.ts +12 -12
  156. package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalancesCountEndpoint.ts +2 -2
  157. package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalancesEndpoint.ts +4 -4
  158. package/src/endpoints/organization/dashboard/registration-periods/GetOrganizationRegistrationPeriodsEndpoint.test.ts +2 -2
  159. package/src/endpoints/organization/dashboard/registration-periods/GetOrganizationRegistrationPeriodsEndpoint.ts +4 -4
  160. package/src/endpoints/organization/dashboard/registration-periods/MoveRegistrationPeriods.test.ts +2 -2
  161. package/src/endpoints/organization/dashboard/registration-periods/PatchOrganizationRegistrationPeriodsEndpoint.test.ts +2 -2
  162. package/src/endpoints/organization/dashboard/registration-periods/PatchOrganizationRegistrationPeriodsEndpoint.ts +3 -3
  163. package/src/endpoints/organization/dashboard/registration-periods/SetupStepReviewEndpoint.ts +2 -2
  164. package/src/endpoints/organization/dashboard/stripe/ConnectStripeEndpoint.ts +3 -3
  165. package/src/endpoints/organization/dashboard/stripe/DeleteStripeAccountEndpoint.ts +3 -3
  166. package/src/endpoints/organization/dashboard/stripe/GetStripeAccountLinkEndpoint.ts +2 -2
  167. package/src/endpoints/organization/dashboard/stripe/GetStripeAccountsEndpoint.ts +1 -1
  168. package/src/endpoints/organization/dashboard/stripe/GetStripeLoginLinkEndpoint.ts +2 -2
  169. package/src/endpoints/organization/dashboard/stripe/UpdateStripeAccountEndpoint.ts +3 -3
  170. package/src/endpoints/organization/dashboard/users/CreateApiUserEndpoint.test.ts +3 -3
  171. package/src/endpoints/organization/dashboard/users/CreateApiUserEndpoint.ts +1 -1
  172. package/src/endpoints/organization/dashboard/users/DeleteUserEndpoint.ts +1 -1
  173. package/src/endpoints/organization/dashboard/users/GetApiUsersEndpoint.ts +1 -1
  174. package/src/endpoints/organization/dashboard/users/GetOrganizationAdminsEndpoint.ts +1 -1
  175. package/src/endpoints/organization/dashboard/users/PatchApiUserEndpoint.test.ts +3 -3
  176. package/src/endpoints/organization/dashboard/users/PatchApiUserEndpoint.ts +1 -1
  177. package/src/endpoints/organization/dashboard/webshops/CreateWebshopEndpoint.ts +1 -1
  178. package/src/endpoints/organization/dashboard/webshops/DeleteWebshopEndpoint.ts +2 -2
  179. package/src/endpoints/organization/dashboard/webshops/GetDiscountCodesEndpoint.ts +1 -1
  180. package/src/endpoints/organization/dashboard/webshops/GetWebshopOrdersCountEndpoint.ts +2 -2
  181. package/src/endpoints/organization/dashboard/webshops/GetWebshopOrdersEndpoint.ts +5 -5
  182. package/src/endpoints/organization/dashboard/webshops/GetWebshopTicketsEndpoint.ts +5 -5
  183. package/src/endpoints/organization/dashboard/webshops/GetWebshopUriAvailabilityEndpoint.ts +1 -1
  184. package/src/endpoints/organization/dashboard/webshops/PatchDiscountCodesEndpoint.ts +1 -1
  185. package/src/endpoints/organization/dashboard/webshops/PatchWebshopEndpoint.ts +1 -1
  186. package/src/endpoints/organization/dashboard/webshops/PatchWebshopOrdersEndpoint.ts +1 -1
  187. package/src/endpoints/organization/dashboard/webshops/PatchWebshopTicketsEndpoint.ts +1 -1
  188. package/src/endpoints/organization/dashboard/webshops/SearchUitpasEventsEndpoint.ts +2 -2
  189. package/src/endpoints/organization/dashboard/webshops/VerifyWebshopDomainEndpoint.ts +1 -1
  190. package/src/endpoints/organization/shared/ExchangePaymentEndpoint.ts +3 -3
  191. package/src/endpoints/organization/shared/GetDocumentHtml.ts +1 -1
  192. package/src/endpoints/organization/shared/GetPaymentEndpoint.ts +2 -2
  193. package/src/endpoints/organization/shared/auth/GetOrganizationEndpoint.test.ts +2 -2
  194. package/src/endpoints/organization/shared/auth/GetOrganizationEndpoint.ts +2 -2
  195. package/src/endpoints/organization/webshops/CheckWebshopDiscountCodesEndpoint.ts +1 -1
  196. package/src/endpoints/organization/webshops/GetOrderByPaymentEndpoint.ts +1 -1
  197. package/src/endpoints/organization/webshops/GetOrderEndpoint.ts +1 -1
  198. package/src/endpoints/organization/webshops/GetTicketsEndpoint.ts +1 -1
  199. package/src/endpoints/organization/webshops/GetWebshopEndpoint.test.ts +2 -2
  200. package/src/endpoints/organization/webshops/GetWebshopEndpoint.ts +2 -2
  201. package/src/endpoints/organization/webshops/PlaceOrderEndpoint.test.ts +4 -4
  202. package/src/excel-loaders/balance-items.ts +268 -0
  203. package/src/excel-loaders/event-notifications.ts +3 -3
  204. package/src/excel-loaders/index.ts +6 -5
  205. package/src/excel-loaders/organizations.ts +4 -4
  206. package/src/excel-loaders/payments.ts +11 -3
  207. package/src/excel-loaders/receivable-balances.ts +2 -2
  208. package/src/helpers/AddressValidator.test.ts +1 -1
  209. package/src/helpers/AddressValidator.ts +1 -1
  210. package/src/helpers/AdminPermissionChecker.ts +20 -17
  211. package/src/helpers/AuthenticatedStructures.ts +194 -109
  212. package/src/helpers/Context.ts +2 -0
  213. package/src/helpers/EmailResumer.ts +1 -1
  214. package/src/helpers/FlagMomentCleanup.ts +1 -1
  215. package/src/helpers/ForwardHandler.test.ts +1 -1
  216. package/src/helpers/ForwardHandler.ts +1 -1
  217. package/src/helpers/GlobalHelper.ts +4 -4
  218. package/src/helpers/GroupBuilder.ts +417 -0
  219. package/src/helpers/GroupedThrottledQueue.test.ts +1 -1
  220. package/src/helpers/GroupedThrottledQueue.ts +1 -1
  221. package/src/helpers/MemberUserSyncer.test.ts +1 -1
  222. package/src/helpers/MemberUserSyncer.ts +1 -1
  223. package/src/helpers/PeriodHelper.ts +5 -45
  224. package/src/helpers/ServiceFeeHelper.ts +5 -1
  225. package/src/helpers/SetupStepUpdater.ts +5 -4
  226. package/src/helpers/TagHelper.ts +1 -1
  227. package/src/helpers/ThrottledQueue.test.ts +1 -1
  228. package/src/helpers/ViesHelper.ts +9 -0
  229. package/src/helpers/email-html-helpers.ts +0 -41
  230. package/src/helpers/outstandingBalanceJoin.ts +3 -1
  231. package/src/middleware/ContextMiddleware.ts +1 -1
  232. package/src/seeds/1726572303-schedule-stock-updates.ts +1 -1
  233. package/src/seeds/1726847064-setup-steps.ts +1 -1
  234. package/src/seeds/1728928974-update-cached-outstanding-balance-from-items.ts +1 -1
  235. package/src/seeds/1740046783-update-membership.ts +1 -1
  236. package/src/seeds/1754560914-groups-prices.test.ts +1 -1
  237. package/src/seeds/1755876819-remove-duplicate-members.ts +1 -1
  238. package/src/seeds/1760702454-update-cached-outstanding-balance-from-items.ts +1 -1
  239. package/src/seeds/1761665607-sync-member-users.ts +1 -1
  240. package/src/seeds/data/default-email-templates.sql +1 -1
  241. package/src/seeds-temporary/1732117645-move-rrn.ts +1 -1
  242. package/src/services/AuditLogService.ts +1 -41
  243. package/src/services/BalanceItemPaymentService.ts +1 -1
  244. package/src/services/BalanceItemService.ts +12 -5
  245. package/src/services/EventNotificationService.ts +3 -3
  246. package/src/services/InvoiceService.ts +131 -17
  247. package/src/services/MemberRecordStore.ts +1 -1
  248. package/src/services/PaymentReallocationService.test.ts +9 -10
  249. package/src/services/PaymentReallocationService.ts +1 -1
  250. package/src/services/PaymentService.ts +560 -18
  251. package/src/services/PlatformMembershipService.ts +3 -3
  252. package/src/services/RegistrationService.ts +3 -3
  253. package/src/services/SSOService.ts +2 -2
  254. package/src/services/STPackageService.ts +241 -0
  255. package/src/services/uitpas/UitpasService.test.ts +1 -1
  256. package/src/sql-filters/balance-items.ts +56 -0
  257. package/src/sql-filters/emails.ts +1 -1
  258. package/src/sql-filters/event-notifications.ts +2 -2
  259. package/src/sql-filters/events.ts +51 -0
  260. package/src/sql-filters/members.ts +38 -2
  261. package/src/sql-filters/receivable-balances.ts +3 -3
  262. package/src/sql-filters/users.ts +10 -0
  263. package/src/sql-sorters/balance-items.ts +36 -0
  264. package/src/sql-sorters/document-templates.ts +2 -2
  265. package/src/sql-sorters/documents.ts +2 -2
  266. package/src/sql-sorters/event-notifications.ts +1 -1
  267. package/src/sql-sorters/members.ts +2 -2
  268. package/src/sql-sorters/orders.ts +2 -2
  269. package/src/sql-sorters/tickets.ts +2 -2
  270. package/tests/actions/patchOrganizationMember.ts +3 -3
  271. package/tests/actions/patchPaymentStatus.ts +3 -3
  272. package/tests/actions/patchUserMember.ts +2 -2
  273. package/tests/assertions/assertBalances.ts +1 -1
  274. package/tests/e2e/api-rate-limits.test.ts +3 -3
  275. package/tests/e2e/charge-members.test.ts +14 -14
  276. package/tests/e2e/documents.test.ts +8 -8
  277. package/tests/e2e/private-files.test.ts +4 -4
  278. package/tests/e2e/register.test.ts +10 -10
  279. package/tests/e2e/stock.test.ts +4 -4
  280. package/tests/e2e/tickets.test.ts +4 -4
  281. package/tests/helpers/TestServer.ts +2 -2
  282. package/tests/init/index.ts +7 -7
  283. package/tests/init/initAdmin.ts +1 -1
  284. package/src/endpoints/global/registration/GetPaymentRegistrations.ts +0 -67
@@ -4,8 +4,8 @@ import { PermissionLevel, Permissions, PlatformConfig, Platform as PlatformStruc
4
4
 
5
5
  import { AutoEncoderPatchType } from '@simonbackx/simple-encoding';
6
6
  import { TestUtils } from '@stamhoofd/test-utils';
7
- import { testServer } from '../../../../tests/helpers/TestServer';
8
- import { PatchPlatformEndpoint } from './PatchPlatformEnpoint';
7
+ import { testServer } from '../../../../tests/helpers/TestServer.js';
8
+ import { PatchPlatformEndpoint } from './PatchPlatformEnpoint.js';
9
9
 
10
10
  describe('Endpoint.PatchPlatform', () => {
11
11
  // Test endpoint
@@ -5,13 +5,13 @@ import { MemberResponsibility, PlatformConfig, PlatformPremiseType, Platform as
5
5
 
6
6
  import { SimpleError } from '@simonbackx/simple-errors';
7
7
  import { QueueHandler } from '@stamhoofd/queues';
8
- import { Context } from '../../../helpers/Context';
9
- import { MembershipCharger } from '../../../helpers/MembershipCharger';
10
- import { MemberUserSyncer } from '../../../helpers/MemberUserSyncer';
11
- import { PeriodHelper } from '../../../helpers/PeriodHelper';
12
- import { SetupStepUpdater } from '../../../helpers/SetupStepUpdater';
13
- import { TagHelper } from '../../../helpers/TagHelper';
14
- import { PlatformMembershipService } from '../../../services/PlatformMembershipService';
8
+ import { Context } from '../../../helpers/Context.js';
9
+ import { MembershipCharger } from '../../../helpers/MembershipCharger.js';
10
+ import { MemberUserSyncer } from '../../../helpers/MemberUserSyncer.js';
11
+ import { PeriodHelper } from '../../../helpers/PeriodHelper.js';
12
+ import { SetupStepUpdater } from '../../../helpers/SetupStepUpdater.js';
13
+ import { TagHelper } from '../../../helpers/TagHelper.js';
14
+ import { PlatformMembershipService } from '../../../services/PlatformMembershipService.js';
15
15
 
16
16
  type Params = Record<string, never>;
17
17
  type Query = undefined;
@@ -2,8 +2,8 @@ import { Request } from '@simonbackx/simple-endpoints';
2
2
  import { EventFactory, GroupFactory, MemberFactory, OrganizationFactory, RegistrationFactory, RegistrationPeriod, RegistrationPeriodFactory, Token, UserFactory } from '@stamhoofd/models';
3
3
  import { AccessRight, EventMeta, GroupType, LimitedFilteredRequest, NamedObject, PermissionLevel, PermissionRoleDetailed, Permissions, PermissionsResourceType, ResourcePermissions } from '@stamhoofd/structures';
4
4
  import { STExpect, TestUtils } from '@stamhoofd/test-utils';
5
- import { testServer } from '../../../../tests/helpers/TestServer';
6
- import { GetRegistrationsEndpoint } from './GetRegistrationsEndpoint';
5
+ import { testServer } from '../../../../tests/helpers/TestServer.js';
6
+ import { GetRegistrationsEndpoint } from './GetRegistrationsEndpoint.js';
7
7
 
8
8
  const baseUrl = `/registrations`;
9
9
  const endpoint = new GetRegistrationsEndpoint();
@@ -3,10 +3,9 @@ import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-
3
3
  import { SimpleError } from '@simonbackx/simple-errors';
4
4
  import { Group, Member, Platform, Registration } from '@stamhoofd/models';
5
5
  import { SQL, SQLExpression, SQLSelect, SQLSortDefinitions, applySQLSorter, compileToSQLFilter } from '@stamhoofd/sql';
6
- import { CountFilteredRequest, GroupType, LimitedFilteredRequest, PaginatedResponse, PermissionLevel, RegistrationWithMemberBlob, StamhoofdFilter, assertSort } from '@stamhoofd/structures';
6
+ import { CountFilteredRequest, GroupType, LimitedFilteredRequest, PaginatedResponse, PermissionLevel, RegistrationWithMemberBlob, StamhoofdFilter, assertSort, RegistrationsBlob } from '@stamhoofd/structures';
7
7
 
8
8
  import { SQLResultNamespacedRow } from '@simonbackx/simple-database';
9
- import { RegistrationsBlob } from '@stamhoofd/structures/dist/src/members/RegistrationsBlob';
10
9
  import { AuthenticatedStructures } from '../../../helpers/AuthenticatedStructures.js';
11
10
  import { Context } from '../../../helpers/Context.js';
12
11
  import { LimitedFilteredRequestHelper } from '../../../helpers/LimitedFilteredRequestHelper.js';
@@ -3,8 +3,8 @@ import { BalanceItem, Member, Organization, Payment } from '@stamhoofd/models';
3
3
  import { DetailedPayableBalanceCollection, DetailedPayableBalance } from '@stamhoofd/structures';
4
4
 
5
5
  import { Formatter } from '@stamhoofd/utility';
6
- import { AuthenticatedStructures } from '../../../helpers/AuthenticatedStructures';
7
- import { Context } from '../../../helpers/Context';
6
+ import { AuthenticatedStructures } from '../../../helpers/AuthenticatedStructures.js';
7
+ import { Context } from '../../../helpers/Context.js';
8
8
 
9
9
  type Params = Record<string, never>;
10
10
  type Query = undefined;
@@ -3,7 +3,7 @@ import { Document, DocumentTemplate, Member } from '@stamhoofd/models';
3
3
  import { Document as DocumentStruct, DocumentStatus } from '@stamhoofd/structures';
4
4
  import { Sorter } from '@stamhoofd/utility';
5
5
 
6
- import { Context } from '../../../helpers/Context';
6
+ import { Context } from '../../../helpers/Context.js';
7
7
  type Params = Record<string, never>;
8
8
  type Query = undefined;
9
9
  type Body = undefined;
@@ -31,7 +31,7 @@ export class GetUserDocumentsEndpoint extends Endpoint<Params, Query, Body, Resp
31
31
  const organization = await Context.setUserOrganizationScope();
32
32
  const { user } = await Context.authenticate();
33
33
 
34
- const members = await Member.getMembersWithRegistrationForUser(user);
34
+ const members = await Member.getMembersForUser(user);
35
35
  let templates = organization ? await DocumentTemplate.where({ status: 'Published', organizationId: organization.id }) : null;
36
36
  const memberIds = members.map(m => m.id);
37
37
  const templateIds = templates ? templates.map(t => t.id) : null;
@@ -2,8 +2,8 @@ import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-
2
2
  import { Member } from '@stamhoofd/models';
3
3
  import { MembersBlob } from '@stamhoofd/structures';
4
4
 
5
- import { AuthenticatedStructures } from '../../../helpers/AuthenticatedStructures';
6
- import { Context } from '../../../helpers/Context';
5
+ import { AuthenticatedStructures } from '../../../helpers/AuthenticatedStructures.js';
6
+ import { Context } from '../../../helpers/Context.js';
7
7
 
8
8
  type Params = Record<string, never>;
9
9
  type Query = undefined;
@@ -3,8 +3,8 @@ import { CachedBalance, Organization } from '@stamhoofd/models';
3
3
  import { PayableBalance, PayableBalanceCollection, ReceivableBalanceType } from '@stamhoofd/structures';
4
4
 
5
5
  import { Formatter } from '@stamhoofd/utility';
6
- import { AuthenticatedStructures } from '../../../helpers/AuthenticatedStructures';
7
- import { Context } from '../../../helpers/Context';
6
+ import { AuthenticatedStructures } from '../../../helpers/AuthenticatedStructures.js';
7
+ import { Context } from '../../../helpers/Context.js';
8
8
 
9
9
  type Params = Record<string, never>;
10
10
  type Query = undefined;
@@ -1,7 +1,7 @@
1
1
  import { PatchMap } from '@simonbackx/simple-encoding';
2
2
  import { Request } from '@simonbackx/simple-endpoints';
3
3
  import { EmailMocker } from '@stamhoofd/email';
4
- import { BalanceItemFactory, Group, GroupFactory, Member, MemberFactory, MemberWithRegistrations, Organization, OrganizationFactory, OrganizationRegistrationPeriodFactory, Registration, RegistrationFactory, RegistrationPeriod, RegistrationPeriodFactory, Token, UserFactory } from '@stamhoofd/models';
4
+ import { BalanceItemFactory, Group, GroupFactory, Member, MemberFactory, MemberWithUsersRegistrationsAndGroups, Organization, OrganizationFactory, OrganizationRegistrationPeriodFactory, Registration, RegistrationFactory, RegistrationPeriod, RegistrationPeriodFactory, Token, UserFactory } from '@stamhoofd/models';
5
5
  import { AccessRight, BalanceItemCartItem, BalanceItemStatus, BalanceItemType, BooleanStatus, Company, GroupOption, GroupOptionMenu, IDRegisterCart, IDRegisterCheckout, IDRegisterItem, OrganizationPackages, PaymentCustomer, PaymentMethod, PermissionLevel, Permissions, PermissionsResourceType, ReduceablePrice, RegisterItemOption, ResourcePermissions, STPackageStatus, STPackageType, UitpasNumberDetails, UitpasSocialTariff, UitpasSocialTariffStatus, UserPermissions, Version } from '@stamhoofd/structures';
6
6
  import { STExpect, TestUtils } from '@stamhoofd/test-utils';
7
7
  import { v4 as uuidv4 } from 'uuid';
@@ -80,7 +80,7 @@ describe('Endpoint.RegisterMembers', () => {
80
80
  const member = await new MemberFactory({ organization, user: linkMembersToUser ? user : undefined })
81
81
  .create();
82
82
 
83
- const otherMembers: MemberWithRegistrations[] = [];
83
+ const otherMembers: MemberWithUsersRegistrationsAndGroups[] = [];
84
84
 
85
85
  for (let i = 0; i < otherMemberAmount; i++) {
86
86
  otherMembers.push(await new MemberFactory({ organization, user: linkMembersToUser ? user : undefined })
@@ -4,9 +4,9 @@ import { Decoder } from '@simonbackx/simple-encoding';
4
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
- import { BalanceItem, BalanceItemPayment, CachedBalance, Group, Member, MemberWithRegistrations, MolliePayment, MollieToken, Organization, PayconiqPayment, Payment, Platform, RateLimiter, Registration, User } from '@stamhoofd/models';
7
+ import { BalanceItem, BalanceItemPayment, CachedBalance, Group, Member, MemberWithUsersRegistrationsAndGroups, MolliePayment, MollieToken, Organization, PayconiqPayment, Payment, Platform, RateLimiter, Registration, User } from '@stamhoofd/models';
8
8
  import { BalanceItemRelation, BalanceItemRelationType, BalanceItemStatus, BalanceItem as BalanceItemStruct, BalanceItemType, IDRegisterCheckout, PaymentCustomer, PaymentMethod, PaymentMethodHelper, PaymentProvider, PaymentStatus, Payment as PaymentStruct, PaymentType, PermissionLevel, PlatformFamily, PlatformMember, ReceivableBalanceType, RegisterItem, RegisterResponse, TranslatedString, Version } from '@stamhoofd/structures';
9
- import { Formatter } from '@stamhoofd/utility';
9
+ import { Formatter, sleep } from '@stamhoofd/utility';
10
10
 
11
11
  import { AuthenticatedStructures } from '../../../helpers/AuthenticatedStructures.js';
12
12
  import { BuckarooHelper } from '../../../helpers/BuckarooHelper.js';
@@ -145,7 +145,7 @@ export class RegisterMembersEndpoint extends Endpoint<Params, Query, Body, Respo
145
145
  memberBalanceItemsStructs = balanceItemsModels.map(i => i.getStructure());
146
146
  }
147
147
 
148
- let members: MemberWithRegistrations[] = [];
148
+ let members: MemberWithUsersRegistrationsAndGroups[] = [];
149
149
  if (request.body.asOrganizationId) {
150
150
  const memberIds = Formatter.uniqueArray(
151
151
  [...request.body.memberIds, ...deleteRegistrationModels.map(i => i.memberId), ...balanceItemsModels.map(i => i.memberId).filter(m => m !== null)],
@@ -205,6 +205,8 @@ export class RegisterMembersEndpoint extends Endpoint<Params, Query, Body, Respo
205
205
 
206
206
  const platformMembers: PlatformMember[] = [];
207
207
 
208
+ let payingOrganization: Organization | null = null;
209
+
208
210
  if (request.body.asOrganizationId) {
209
211
  const memberIds = Formatter.uniqueArray(
210
212
  [...request.body.memberIds, ...deleteRegistrationModels.map(i => i.memberId), ...balanceItemsModels.map(i => i.memberId).filter(m => m !== null)],
@@ -233,6 +235,7 @@ export class RegisterMembersEndpoint extends Endpoint<Params, Query, Body, Respo
233
235
  platformMembers.push(platformMember);
234
236
  }
235
237
 
238
+ payingOrganization = await Context.auth.getOrganization(request.body.asOrganizationId);
236
239
  if (memberIds.length > 0 && request.body.asOrganizationId && request.body.asOrganizationId !== organization.id) {
237
240
  // For registering members at a different organization, you need full permissions
238
241
  if (!await Context.auth.hasFullAccess(request.body.asOrganizationId)) {
@@ -288,6 +291,7 @@ export class RegisterMembersEndpoint extends Endpoint<Params, Query, Body, Respo
288
291
  if (whoWillPayNow === 'nobody') {
289
292
  // Safe and important to ignore: we are only updating the outstanding amounts
290
293
  // If we would throw here, that could leak personal data (e.g. that the user uses financial support)
294
+ request.body.totalPrice = totalPrice;
291
295
  }
292
296
  else {
293
297
  // when whoWillPay = organization/member, we should throw or the payment amount could be different / incorrect.
@@ -450,37 +454,10 @@ export class RegisterMembersEndpoint extends Endpoint<Params, Query, Body, Respo
450
454
  registrations.push(registration);
451
455
  }
452
456
 
453
- // Validate payment method
454
- if (totalPrice > 0 && whoWillPayNow !== 'nobody') {
455
- const allowedPaymentMethods = organization.meta.registrationPaymentConfiguration.getAvailablePaymentMethods({
456
- amount: totalPrice,
457
- customer: checkout.customer,
458
- });
459
-
460
- if (!checkout.paymentMethod || !allowedPaymentMethods.includes(checkout.paymentMethod)) {
461
- throw new SimpleError({
462
- code: 'invalid_payment_method',
463
- message: $t(`2b1ca6a0-662e-4326-ada1-10239b6ddc6f`),
464
- });
465
- }
466
-
467
- if ((checkout.paymentMethod !== PaymentMethod.Transfer && checkout.paymentMethod !== PaymentMethod.PointOfSale) && (!request.body.redirectUrl || !request.body.cancelUrl)) {
468
- throw new SimpleError({
469
- code: 'missing_fields',
470
- message: 'redirectUrl or cancelUrl is missing and is required for non-zero online payments',
471
- human: $t(`ebe54b63-2de6-4f22-a5ed-d3fe65194562`),
472
- });
473
- }
474
- }
475
- else {
476
- checkout.paymentMethod = PaymentMethod.Unknown;
477
- }
478
-
479
457
  console.log('Registering members using whoWillPayNow', whoWillPayNow, checkout.paymentMethod, totalPrice);
480
458
 
481
459
  const createdBalanceItems: BalanceItem[] = [];
482
460
  const deletedBalanceItems: BalanceItem[] = [];
483
- const shouldMarkValid = whoWillPayNow === 'nobody' || checkout.paymentMethod === PaymentMethod.Transfer || checkout.paymentMethod === PaymentMethod.PointOfSale || checkout.paymentMethod === PaymentMethod.Unknown;
484
461
 
485
462
  // Create negative balance items
486
463
  for (const { registration: registrationStruct, deleted } of [
@@ -834,21 +811,6 @@ export class RegisterMembersEndpoint extends Endpoint<Params, Query, Body, Respo
834
811
  // Keep a copy because createdBalanceItems will be altered - and we don't want to mark added items as valid
835
812
  const markValidList = [...createdBalanceItems];
836
813
 
837
- async function markValidIfNeeded() {
838
- if (shouldMarkValid) {
839
- for (const balanceItem of markValidList) {
840
- // Mark valid
841
- await BalanceItemService.markPaid(balanceItem, payment, organization);
842
- }
843
-
844
- // Flush balance caches so we return an up-to-date balance
845
- await BalanceItemService.flushRegistrationDiscountsCache();
846
-
847
- // We'll need to update the returned registrations as their values will have changed by marking the registration as valid
848
- await Registration.refreshAll(registrations);
849
- }
850
- }
851
-
852
814
  if (whoWillPayNow !== 'nobody') {
853
815
  const mappedBalanceItems = new Map<BalanceItem, number>();
854
816
 
@@ -868,14 +830,15 @@ export class RegisterMembersEndpoint extends Endpoint<Params, Query, Body, Respo
868
830
  }
869
831
 
870
832
  try {
871
- const response = await this.createPayment({
833
+ const response = await PaymentService.createPayment({
872
834
  balanceItems: mappedBalanceItems,
873
835
  organization,
874
836
  user,
875
837
  checkout: request.body,
876
838
  members,
839
+ serviceFeeType: 'members',
840
+ payingOrganization,
877
841
  });
878
- await markValidIfNeeded();
879
842
 
880
843
  if (response) {
881
844
  paymentUrl = response.paymentUrl;
@@ -889,7 +852,10 @@ export class RegisterMembersEndpoint extends Endpoint<Params, Query, Body, Respo
889
852
  }
890
853
  }
891
854
  else {
892
- await markValidIfNeeded();
855
+ // Mark as paid/valid without creating a payment
856
+ for (const balanceItem of markValidList) {
857
+ await BalanceItemService.markPaid(balanceItem, null, organization);
858
+ }
893
859
  }
894
860
 
895
861
  // Update occupancy
@@ -900,353 +866,22 @@ export class RegisterMembersEndpoint extends Endpoint<Params, Query, Body, Respo
900
866
  }
901
867
  }
902
868
 
903
- const updatedMembers = await Member.getBlobByIds(...members.map(m => m.id));
869
+ // Flush caches so data is up to date in response
870
+ await BalanceItemService.flushCaches(organization.id);
871
+
872
+ // We'll need to update the returned registrations as their values will have changed by marking the registration as valid
873
+ await Registration.refreshAll(registrations);
874
+
875
+ // Force reload registrations and group data
876
+ Member.unloadRegistrations(members);
877
+ await Member.loadRegistrations(members, true);
904
878
 
905
879
  return new Response(RegisterResponse.create({
906
880
  payment: payment ? PaymentStruct.create(payment) : null,
907
- members: await AuthenticatedStructures.membersBlob(updatedMembers),
881
+ members: await AuthenticatedStructures.membersBlob(members),
908
882
  registrations: registrations.map(r => Member.getRegistrationWithTinyMemberStructure(r)),
909
883
  paymentUrl,
910
884
  paymentQRCode,
911
885
  }));
912
886
  }
913
-
914
- async createPayment({ balanceItems, organization, user, checkout, members }: { balanceItems: Map<BalanceItem, number>; organization: Organization; user: User; checkout: IDRegisterCheckout; members: MemberWithRegistrations[] }) {
915
- // Calculate total price to pay
916
- let totalPrice = 0;
917
- const payMembers: MemberWithRegistrations[] = [];
918
- let hasNegative = false;
919
-
920
- for (const [balanceItem, price] of balanceItems) {
921
- if (organization.id !== balanceItem.organizationId) {
922
- throw new Error('Unexpected balance item from other organization');
923
- }
924
-
925
- if (price > 0 && price > Math.max(balanceItem.priceOpen, balanceItem.price - balanceItem.pricePaid)) {
926
- throw new SimpleError({
927
- code: 'invalid_data',
928
- message: $t(`38ddccb2-7cf6-4b47-aa71-d11ad73386d8`),
929
- });
930
- }
931
-
932
- if (price < 0 && price < Math.min(balanceItem.priceOpen, balanceItem.price - balanceItem.pricePaid)) {
933
- throw new SimpleError({
934
- code: 'invalid_data',
935
- message: $t(`dd14a1d9-c569-4d5e-bb26-569ecede4c52`),
936
- });
937
- }
938
-
939
- if (price < 0) {
940
- hasNegative = true;
941
- }
942
-
943
- totalPrice += price;
944
-
945
- if (price > 0 && balanceItem.memberId) {
946
- const member = members.find(m => m.id === balanceItem.memberId);
947
- if (!member) {
948
- throw new SimpleError({
949
- code: 'invalid_data',
950
- message: $t(`e64b8269-1cda-434d-8d6f-35be23a9d6e9`),
951
- });
952
- }
953
- payMembers.push(member);
954
- }
955
- }
956
-
957
- if (totalPrice < 0) {
958
- // todo: try to make it non-negative by reducing some balance items
959
- throw new SimpleError({
960
- code: 'negative_price',
961
- message: $t(`725715e5-b0ac-43c1-adef-dd42b8907327`),
962
- });
963
- }
964
-
965
- if (totalPrice !== checkout.totalPrice) {
966
- // Changed!
967
- throw new SimpleError({
968
- code: 'changed_price',
969
- message: $t(`e424d549-2bb8-4103-9a14-ac4063d7d454`, { total: Formatter.price(totalPrice) }),
970
- });
971
- }
972
-
973
- const payment = new Payment();
974
- payment.method = checkout.paymentMethod ?? PaymentMethod.Unknown;
975
-
976
- if (totalPrice === 0) {
977
- if (balanceItems.size === 0) {
978
- return;
979
- }
980
- // Create an egalizing payment
981
- payment.method = PaymentMethod.Unknown;
982
-
983
- if (hasNegative) {
984
- payment.type = PaymentType.Reallocation;
985
- }
986
- }
987
- else if (payment.method === PaymentMethod.Unknown) {
988
- throw new SimpleError({
989
- code: 'invalid_data',
990
- message: $t(`86c7b6f7-3ec9-4af3-a5e6-b5de6de80d73`),
991
- });
992
- }
993
-
994
- // Who will receive this money?
995
- payment.organizationId = organization.id;
996
-
997
- // Who paid
998
- payment.payingUserId = user.id;
999
- payment.payingOrganizationId = checkout.asOrganizationId ?? null;
1000
-
1001
- // Fill in customer:
1002
- payment.customer = PaymentCustomer.create({
1003
- firstName: user.firstName,
1004
- lastName: user.lastName,
1005
- email: user.email,
1006
- });
1007
-
1008
- // Use structured transfer description prefix
1009
- let prefix = '';
1010
-
1011
- if (checkout.asOrganizationId) {
1012
- if (!checkout.customer) {
1013
- throw new SimpleError({
1014
- code: 'missing_fields',
1015
- message: 'customer is required when paying as an organization',
1016
- human: $t(`d483aa9a-289c-4c59-955f-d2f99ec533ab`),
1017
- });
1018
- }
1019
-
1020
- if (!checkout.customer.company) {
1021
- throw new SimpleError({
1022
- code: 'missing_fields',
1023
- message: 'customer.company is required when paying as an organization',
1024
- human: $t(`bc89861d-a799-4100-b06c-29d6808ba8d2`),
1025
- });
1026
- }
1027
-
1028
- const payingOrganization = await Organization.getByID(checkout.asOrganizationId);
1029
- if (!payingOrganization) {
1030
- throw new SimpleError({
1031
- code: 'invalid_data',
1032
- message: $t(`492117ce-4d5f-4cff-8f3f-8fa56bbb0fee`),
1033
- });
1034
- }
1035
-
1036
- // Search company id
1037
- // this avoids needing to check the VAT number every time
1038
- const id = checkout.customer.company.id;
1039
- const foundCompany = payingOrganization.meta.companies.find(c => c.id === id);
1040
-
1041
- if (!foundCompany) {
1042
- throw new SimpleError({
1043
- code: 'invalid_data',
1044
- message: $t(`0ab71307-8f4f-4701-b120-b552a1b6bdd0`),
1045
- });
1046
- }
1047
-
1048
- payment.customer.company = foundCompany;
1049
-
1050
- const orgNumber = parseInt(payingOrganization.uri);
1051
-
1052
- if (orgNumber !== 0 && !isNaN(orgNumber)) {
1053
- prefix = orgNumber + '';
1054
- }
1055
- }
1056
-
1057
- payment.status = PaymentStatus.Created;
1058
- payment.paidAt = null;
1059
- payment.price = totalPrice;
1060
- PaymentService.round(payment);
1061
- totalPrice = payment.price;
1062
-
1063
- if (totalPrice === 0) {
1064
- payment.status = PaymentStatus.Succeeded;
1065
- payment.paidAt = new Date();
1066
- }
1067
-
1068
- if (payment.method === PaymentMethod.Transfer) {
1069
- // remark: we cannot add the lastnames, these will get added in the frontend when it is decrypted
1070
- payment.transferSettings = organization.mappedTransferSettings;
1071
-
1072
- if (!payment.transferSettings.iban) {
1073
- throw new SimpleError({
1074
- code: 'no_iban',
1075
- message: 'No IBAN',
1076
- human: $t(`cc8b5066-a7e4-4eae-b556-f56de5d3502c`),
1077
- });
1078
- }
1079
-
1080
- const m = payMembers.map(r => r.details);
1081
- payment.generateDescription(
1082
- organization,
1083
- Formatter.groupNamesByFamily(m),
1084
- {
1085
- name: Formatter.groupNamesByFamily(m),
1086
- naam: Formatter.groupNamesByFamily(m),
1087
- email: user.email,
1088
- prefix,
1089
- },
1090
- );
1091
- }
1092
-
1093
- // Determine the payment provider
1094
- // Throws if invalid
1095
- const { provider, stripeAccount } = await organization.getPaymentProviderFor(payment.method, organization.privateMeta.registrationPaymentConfiguration);
1096
- payment.provider = provider;
1097
- payment.stripeAccountId = stripeAccount?.id ?? null;
1098
- ServiceFeeHelper.setServiceFee(payment, organization, 'members', [...balanceItems.entries()].map(([_, p]) => p));
1099
-
1100
- await payment.save();
1101
-
1102
- // Create balance item payments
1103
- const balanceItemPayments: (BalanceItemPayment & { balanceItem: BalanceItem })[] = [];
1104
-
1105
- for (const [balanceItem, price] of balanceItems) {
1106
- // Create one balance item payment to pay it in one payment
1107
- const balanceItemPayment = new BalanceItemPayment();
1108
- balanceItemPayment.balanceItemId = balanceItem.id;
1109
- balanceItemPayment.paymentId = payment.id;
1110
- balanceItemPayment.organizationId = organization.id;
1111
- balanceItemPayment.price = price;
1112
- await balanceItemPayment.save();
1113
-
1114
- balanceItemPayments.push(balanceItemPayment.setRelation(BalanceItemPayment.balanceItem, balanceItem));
1115
- }
1116
-
1117
- const description = $t(`33a926ea-9bc7-444e-becc-c0f2f70e1f0e`) + ' ' + organization.name;
1118
-
1119
- let paymentUrl: string | null = null;
1120
- let paymentQRCode: string | null = null;
1121
-
1122
- try {
1123
- // Update balance items
1124
- if (payment.method === PaymentMethod.Transfer) {
1125
- // Send a small reminder email
1126
- try {
1127
- await Registration.sendTransferEmail(user, organization, payment);
1128
- }
1129
- catch (e) {
1130
- console.error('Failed to send transfer email');
1131
- console.error(e);
1132
- }
1133
- }
1134
- else if (payment.method !== PaymentMethod.PointOfSale && payment.method !== PaymentMethod.Unknown) {
1135
- if (!checkout.redirectUrl || !checkout.cancelUrl) {
1136
- throw new Error('Should have been caught earlier');
1137
- }
1138
-
1139
- const _redirectUrl = new URL(checkout.redirectUrl);
1140
- _redirectUrl.searchParams.set('paymentId', payment.id);
1141
- _redirectUrl.searchParams.set('organizationId', organization.id); // makes sure the client uses the token associated with this organization when fetching payment polling status
1142
-
1143
- const _cancelUrl = new URL(checkout.cancelUrl);
1144
- _cancelUrl.searchParams.set('paymentId', payment.id);
1145
- _cancelUrl.searchParams.set('cancel', 'true');
1146
- _cancelUrl.searchParams.set('organizationId', organization.id); // makes sure the client uses the token associated with this organization when fetching payment polling status
1147
-
1148
- const redirectUrl = _redirectUrl.href;
1149
- const cancelUrl = _cancelUrl.href;
1150
-
1151
- const webhookUrl = 'https://' + organization.getApiHost() + '/v' + Version + '/payments/' + encodeURIComponent(payment.id) + '?exchange=true';
1152
-
1153
- if (payment.provider === PaymentProvider.Stripe) {
1154
- const stripeResult = await StripeHelper.createPayment({
1155
- payment,
1156
- stripeAccount,
1157
- redirectUrl,
1158
- cancelUrl,
1159
- statementDescriptor: organization.name,
1160
- metadata: {
1161
- organization: organization.id,
1162
- user: user.id,
1163
- payment: payment.id,
1164
- },
1165
- i18n: Context.i18n,
1166
- lineItems: balanceItemPayments,
1167
- organization,
1168
- customer: {
1169
- name: user.name ?? payMembers[0]?.details.name ?? $t(`bd1e59c8-3d4c-4097-ab35-0ce7b20d0e50`),
1170
- email: user.email,
1171
- },
1172
- });
1173
- paymentUrl = stripeResult.paymentUrl;
1174
- }
1175
- else if (payment.provider === PaymentProvider.Mollie) {
1176
- // Mollie payment
1177
- const token = await MollieToken.getTokenFor(organization.id);
1178
- if (!token) {
1179
- throw new SimpleError({
1180
- code: '',
1181
- message: $t(`b77e1f68-8928-42a2-802b-059fa73bedc3`, { method: PaymentMethodHelper.getName(payment.method) }),
1182
- });
1183
- }
1184
- const profileId = organization.privateMeta.mollieProfile?.id ?? await token.getProfileId(organization.getHost());
1185
- if (!profileId) {
1186
- throw new SimpleError({
1187
- code: '',
1188
- message: $t(`5574469f-8eee-47fe-9fb6-1b097142ac75`, { method: PaymentMethodHelper.getName(payment.method) }),
1189
- });
1190
- }
1191
- const mollieClient = createMollieClient({ accessToken: await token.getAccessToken() });
1192
- const locale = Context.i18n.locale.replace('-', '_');
1193
- const molliePayment = await mollieClient.payments.create({
1194
- amount: {
1195
- currency: 'EUR',
1196
- value: (totalPrice / 100).toFixed(2),
1197
- },
1198
- method: payment.method == PaymentMethod.Bancontact ? molliePaymentMethod.bancontact : (payment.method == PaymentMethod.iDEAL ? molliePaymentMethod.ideal : molliePaymentMethod.creditcard),
1199
- testmode: organization.privateMeta.useTestPayments ?? STAMHOOFD.environment !== 'production',
1200
- profileId,
1201
- description,
1202
- redirectUrl,
1203
- webhookUrl,
1204
- metadata: {
1205
- paymentId: payment.id,
1206
- },
1207
- locale: ['en_US', 'en_GB', 'nl_NL', 'nl_BE', 'fr_FR', 'fr_BE', 'de_DE', 'de_AT', 'de_CH', 'es_ES', 'ca_ES', 'pt_PT', 'it_IT', 'nb_NO', 'sv_SE', 'fi_FI', 'da_DK', 'is_IS', 'hu_HU', 'pl_PL', 'lv_LV', 'lt_LT'].includes(locale) ? (locale as any) : null,
1208
- });
1209
- paymentUrl = molliePayment.getCheckoutUrl();
1210
-
1211
- // Save payment
1212
- const dbPayment = new MolliePayment();
1213
- dbPayment.paymentId = payment.id;
1214
- dbPayment.mollieId = molliePayment.id;
1215
- await dbPayment.save();
1216
- }
1217
- else if (payment.provider === PaymentProvider.Payconiq) {
1218
- ({ paymentUrl, paymentQRCode } = await PayconiqPayment.createPayment(payment, organization, description, redirectUrl, webhookUrl));
1219
- }
1220
- else if (payment.provider == PaymentProvider.Buckaroo) {
1221
- // Increase request timeout because buckaroo is super slow (in development)
1222
- Context.request.request?.setTimeout(60 * 1000);
1223
- const buckaroo = new BuckarooHelper(organization.privateMeta?.buckarooSettings?.key ?? '', organization.privateMeta?.buckarooSettings?.secret ?? '', organization.privateMeta.useTestPayments ?? STAMHOOFD.environment !== 'production');
1224
- const ip = Context.request.getIP();
1225
- paymentUrl = await buckaroo.createPayment(payment, ip, description, redirectUrl, webhookUrl);
1226
- await payment.save();
1227
-
1228
- // TypeScript doesn't understand that the status can change and isn't a const....
1229
- if ((payment.status as any) === PaymentStatus.Failed) {
1230
- throw new SimpleError({
1231
- code: 'payment_failed',
1232
- message: $t(`b77e1f68-8928-42a2-802b-059fa73bedc3`, { method: PaymentMethodHelper.getName(payment.method) }),
1233
- });
1234
- }
1235
- }
1236
- }
1237
- }
1238
- catch (e) {
1239
- await PaymentService.handlePaymentStatusUpdate(payment, organization, PaymentStatus.Failed);
1240
- throw e;
1241
- }
1242
-
1243
- return {
1244
- payment,
1245
- balanceItemPayments,
1246
- provider,
1247
- stripeAccount,
1248
- paymentUrl,
1249
- paymentQRCode,
1250
- };
1251
- }
1252
887
  }
@@ -5,9 +5,9 @@ import { Decoder } from '@simonbackx/simple-encoding';
5
5
  import { SimpleError } from '@simonbackx/simple-errors';
6
6
  import { RegistrationPeriod } from '@stamhoofd/models';
7
7
  import { applySQLSorter, compileToSQLFilter, SQLFilterDefinitions, SQLSortDefinitions } from '@stamhoofd/sql';
8
- import { Context } from '../../../helpers/Context';
9
- import { registrationPeriodFilterCompilers } from '../../../sql-filters/registration-periods';
10
- import { registrationPeriodSorters } from '../../../sql-sorters/registration-periods';
8
+ import { Context } from '../../../helpers/Context.js';
9
+ import { registrationPeriodFilterCompilers } from '../../../sql-filters/registration-periods.js';
10
+ import { registrationPeriodSorters } from '../../../sql-sorters/registration-periods.js';
11
11
 
12
12
  type Params = Record<string, never>;
13
13
  type Query = LimitedFilteredRequest;
@@ -4,8 +4,8 @@ import { RegistrationPeriod as RegistrationPeriodStruct } from '@stamhoofd/struc
4
4
 
5
5
  import { SimpleError } from '@simonbackx/simple-errors';
6
6
  import { Organization, Platform, RegistrationPeriod } from '@stamhoofd/models';
7
- import { Context } from '../../../helpers/Context';
8
- import { PeriodHelper } from '../../../helpers/PeriodHelper';
7
+ import { Context } from '../../../helpers/Context.js';
8
+ import { PeriodHelper } from '../../../helpers/PeriodHelper.js';
9
9
 
10
10
  type Params = Record<string, never>;
11
11
  type Query = undefined;