@stamhoofd/backend 2.119.0 → 2.120.1

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 (348) hide show
  1. package/package.json +32 -22
  2. package/src/audit-logs/ModelLogger.ts +4 -2
  3. package/src/boot.ts +40 -14
  4. package/src/crons/balance-emails.ts +4 -2
  5. package/src/crons/clearExcelCache.test.ts +8 -8
  6. package/src/crons/update-cached-balances.ts +40 -14
  7. package/src/debug.ts +3 -2
  8. package/src/decoders/StringArrayDecoder.ts +1 -1
  9. package/src/decoders/StringNullableDecoder.ts +1 -1
  10. package/src/email-recipient-loaders/documents.ts +2 -1
  11. package/src/email-recipient-loaders/members.ts +2 -1
  12. package/src/email-recipient-loaders/orders.ts +2 -1
  13. package/src/email-recipient-loaders/payments.ts +6 -3
  14. package/src/email-recipient-loaders/receivable-balances.ts +2 -1
  15. package/src/email-recipient-loaders/registrations.ts +2 -1
  16. package/src/email-replacements/getEmailReplacementsForPayment.ts +2 -1
  17. package/src/endpoints/admin/members/ChargeMembersEndpoint.ts +3 -2
  18. package/src/endpoints/admin/memberships/ChargeMembershipsEndpoint.ts +2 -1
  19. package/src/endpoints/admin/memberships/GetChargeMembershipsSummaryEndpoint.ts +2 -1
  20. package/src/endpoints/admin/organizations/ChargeOrganizationsEndpoint.ts +3 -2
  21. package/src/endpoints/admin/organizations/GetOrganizationsCountEndpoint.ts +3 -2
  22. package/src/endpoints/admin/organizations/GetOrganizationsEndpoint.ts +6 -4
  23. package/src/endpoints/admin/organizations/PatchOrganizationsEndpoint.ts +4 -2
  24. package/src/endpoints/admin/registrations/ChargeRegistrationsEndpoint.ts +3 -2
  25. package/src/endpoints/auth/CreateAdminEndpoint.ts +5 -3
  26. package/src/endpoints/auth/CreateTokenEndpoint.ts +4 -2
  27. package/src/endpoints/auth/DeleteTokenEndpoint.ts +2 -1
  28. package/src/endpoints/auth/DeleteUserEndpoint.ts +2 -1
  29. package/src/endpoints/auth/ForgotPasswordEndpoint.ts +3 -2
  30. package/src/endpoints/auth/GetOtherUserEndpoint.ts +3 -2
  31. package/src/endpoints/auth/GetUserEndpoint.ts +3 -2
  32. package/src/endpoints/auth/OpenIDConnectAuthTokenEndpoint.ts +2 -1
  33. package/src/endpoints/auth/OpenIDConnectCallbackEndpoint.ts +4 -2
  34. package/src/endpoints/auth/OpenIDConnectStartEndpoint.ts +3 -2
  35. package/src/endpoints/auth/PatchUserEndpoint.ts +6 -3
  36. package/src/endpoints/auth/PollEmailVerificationEndpoint.ts +3 -2
  37. package/src/endpoints/auth/RetryEmailVerificationEndpoint.ts +3 -2
  38. package/src/endpoints/auth/SignupEndpoint.ts +3 -2
  39. package/src/endpoints/auth/VerifyEmailEndpoint.ts +3 -2
  40. package/src/endpoints/frontend/FrontendEnvironmentEndpoint.ts +3 -2
  41. package/src/endpoints/global/addresses/SearchRegionsEndpoint.ts +8 -5
  42. package/src/endpoints/global/addresses/ValidateAddressEndpoint.ts +5 -3
  43. package/src/endpoints/global/audit-logs/GetAuditLogsEndpoint.ts +7 -4
  44. package/src/endpoints/global/billing/ActivatePackagesEndpoint.ts +6 -4
  45. package/src/endpoints/global/billing/DeactivatePackageEndpoint.ts +2 -1
  46. package/src/endpoints/global/caddy/CheckDomainCertEndpoint.ts +4 -2
  47. package/src/endpoints/global/email/CreateEmailEndpoint.ts +5 -3
  48. package/src/endpoints/global/email/GetAdminEmailsEndpoint.test.ts +2 -1
  49. package/src/endpoints/global/email/GetAdminEmailsEndpoint.ts +22 -19
  50. package/src/endpoints/global/email/GetEmailAddressEndpoint.ts +4 -2
  51. package/src/endpoints/global/email/GetEmailEndpoint.ts +3 -2
  52. package/src/endpoints/global/email/GetUserEmailsEndpoint.test.ts +2 -1
  53. package/src/endpoints/global/email/GetUserEmailsEndpoint.ts +7 -4
  54. package/src/endpoints/global/email/ManageEmailAddressEndpoint.ts +4 -2
  55. package/src/endpoints/global/email/PatchEmailEndpoint.test.ts +11 -11
  56. package/src/endpoints/global/email/PatchEmailEndpoint.ts +6 -3
  57. package/src/endpoints/global/email-recipients/GetEmailRecipientsCountEndpoint.ts +3 -2
  58. package/src/endpoints/global/email-recipients/GetEmailRecipientsEndpoint.test.ts +2 -1
  59. package/src/endpoints/global/email-recipients/GetEmailRecipientsEndpoint.ts +7 -4
  60. package/src/endpoints/global/email-recipients/RetryEmailRecipientEndpoint.ts +4 -2
  61. package/src/endpoints/global/email-recipients/helpers/validateEmailRecipientFilter.ts +2 -1
  62. package/src/endpoints/global/events/GetEventNotificationsCountEndpoint.ts +3 -2
  63. package/src/endpoints/global/events/GetEventNotificationsEndpoint.ts +8 -5
  64. package/src/endpoints/global/events/GetEventsEndpoint.ts +7 -4
  65. package/src/endpoints/global/events/PatchEventNotificationsEndpoint.test.ts +4 -2
  66. package/src/endpoints/global/events/PatchEventNotificationsEndpoint.ts +4 -2
  67. package/src/endpoints/global/events/PatchEventsEndpoint.test.ts +4 -2
  68. package/src/endpoints/global/events/PatchEventsEndpoint.ts +4 -2
  69. package/src/endpoints/global/files/ExportToExcelEndpoint.ts +7 -4
  70. package/src/endpoints/global/files/GetFileCache.ts +5 -3
  71. package/src/endpoints/global/files/UploadFile.ts +9 -3
  72. package/src/endpoints/global/files/UploadImage.ts +4 -2
  73. package/src/endpoints/global/groups/GetGroupsEndpoint.test.ts +4 -2
  74. package/src/endpoints/global/groups/GetGroupsEndpoint.ts +7 -4
  75. package/src/endpoints/global/members/GetMemberFamilyEndpoint.ts +5 -3
  76. package/src/endpoints/global/members/GetMembersCountEndpoint.ts +3 -2
  77. package/src/endpoints/global/members/GetMembersEndpoint.test.ts +4 -2
  78. package/src/endpoints/global/members/GetMembersEndpoint.ts +8 -6
  79. package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.test.ts +257 -6
  80. package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.ts +114 -59
  81. package/src/endpoints/global/members/helpers/validateGroupFilter.ts +2 -1
  82. package/src/endpoints/global/members/shouldCheckIfMemberIsDuplicate.ts +3 -2
  83. package/src/endpoints/global/organizations/CheckRegisterCodeEndpoint.ts +2 -1
  84. package/src/endpoints/global/organizations/CreateOrganizationEndpoint.test.ts +3 -2
  85. package/src/endpoints/global/organizations/CreateOrganizationEndpoint.ts +3 -2
  86. package/src/endpoints/global/organizations/GetOrganizationFromDomainEndpoint.ts +5 -3
  87. package/src/endpoints/global/organizations/GetOrganizationFromUriEndpoint.ts +5 -3
  88. package/src/endpoints/global/organizations/SearchOrganizationEndpoint.ts +8 -5
  89. package/src/endpoints/global/payments/StripeWebhookEndpoint.ts +4 -2
  90. package/src/endpoints/global/platform/GetPlatformAdminsEndpoint.ts +2 -1
  91. package/src/endpoints/global/platform/GetPlatformEndpoint.ts +3 -2
  92. package/src/endpoints/global/platform/PatchPlatformEnpoint.test.ts +3 -2
  93. package/src/endpoints/global/platform/PatchPlatformEnpoint.ts +6 -3
  94. package/src/endpoints/global/platform-memberships/GetPlatformMembershipsCountEndpoint.ts +47 -0
  95. package/src/endpoints/global/platform-memberships/GetPlatformMembershipsEndpoint.ts +211 -0
  96. package/src/endpoints/global/registration/GetRegistrationsCountEndpoint.ts +3 -2
  97. package/src/endpoints/global/registration/GetRegistrationsEndpoint.test.ts +2 -1
  98. package/src/endpoints/global/registration/GetRegistrationsEndpoint.ts +8 -5
  99. package/src/endpoints/global/registration/GetUserDetailedPayableBalanceEndpoint.ts +4 -2
  100. package/src/endpoints/global/registration/GetUserDocumentsEndpoint.ts +4 -2
  101. package/src/endpoints/global/registration/GetUserMembersEndpoint.ts +3 -2
  102. package/src/endpoints/global/registration/GetUserPayableBalanceEndpoint.ts +2 -1
  103. package/src/endpoints/global/registration/PatchUserMembersEndpoint.test.ts +5 -3
  104. package/src/endpoints/global/registration/PatchUserMembersEndpoint.ts +9 -5
  105. package/src/endpoints/global/registration/RegisterMembersEndpoint.test.ts +50 -49
  106. package/src/endpoints/global/registration/RegisterMembersEndpoint.ts +7 -4
  107. package/src/endpoints/global/registration-periods/GetRegistrationPeriodsEndpoint.ts +7 -4
  108. package/src/endpoints/global/registration-periods/PatchRegistrationPeriodsEndpoint.ts +4 -2
  109. package/src/endpoints/global/sso/GetSSOEndpoint.ts +4 -2
  110. package/src/endpoints/global/sso/SetSSOEndpoint.ts +3 -2
  111. package/src/endpoints/global/webshops/GetWebshopFromDomainEndpoint.ts +4 -2
  112. package/src/endpoints/global/webshops/GetWebshopsCountEndpoint.ts +43 -0
  113. package/src/endpoints/global/webshops/GetWebshopsEndpoint.test.ts +808 -0
  114. package/src/endpoints/global/webshops/GetWebshopsEndpoint.ts +221 -0
  115. package/src/endpoints/organization/dashboard/balance-items/GetBalanceItemEndpoint.ts +3 -2
  116. package/src/endpoints/organization/dashboard/balance-items/GetBalanceItemsCountEndpoint.ts +3 -2
  117. package/src/endpoints/organization/dashboard/balance-items/GetBalanceItemsEndpoint.ts +5 -3
  118. package/src/endpoints/organization/dashboard/balance-items/PatchBalanceItemsEndpoint.ts +4 -2
  119. package/src/endpoints/organization/dashboard/billing/GetOrganizationDetailedPayableBalanceEndpoint.ts +4 -2
  120. package/src/endpoints/organization/dashboard/billing/GetOrganizationPayableBalanceEndpoint.ts +4 -2
  121. package/src/endpoints/organization/dashboard/billing/GetPackagesEndpoint.ts +2 -1
  122. package/src/endpoints/organization/dashboard/documents/GetDocumentTemplateXML.ts +2 -1
  123. package/src/endpoints/organization/dashboard/documents/GetDocumentTemplatesCountEndpoint.ts +3 -2
  124. package/src/endpoints/organization/dashboard/documents/GetDocumentTemplatesEndpoint.ts +7 -4
  125. package/src/endpoints/organization/dashboard/documents/GetDocumentsCountEndpoint.ts +3 -2
  126. package/src/endpoints/organization/dashboard/documents/GetDocumentsEndpoint.ts +7 -4
  127. package/src/endpoints/organization/dashboard/documents/PatchDocumentEndpoint.ts +4 -2
  128. package/src/endpoints/organization/dashboard/documents/PatchDocumentTemplatesEndpoint.test.ts +4 -2
  129. package/src/endpoints/organization/dashboard/documents/PatchDocumentTemplatesEndpoint.ts +4 -2
  130. package/src/endpoints/organization/dashboard/email/CheckEmailBouncesEndpoint.ts +2 -1
  131. package/src/endpoints/organization/dashboard/email-templates/GetEmailTemplatesEndpoint.test.ts +36 -1
  132. package/src/endpoints/organization/dashboard/email-templates/GetEmailTemplatesEndpoint.ts +13 -4
  133. package/src/endpoints/organization/dashboard/email-templates/PatchEmailTemplatesEndpoint.test.ts +4 -2
  134. package/src/endpoints/organization/dashboard/email-templates/PatchEmailTemplatesEndpoint.ts +4 -2
  135. package/src/endpoints/organization/dashboard/invoices/GetInvoicesCountEndpoint.ts +3 -2
  136. package/src/endpoints/organization/dashboard/invoices/GetInvoicesEndpoint.ts +5 -3
  137. package/src/endpoints/organization/dashboard/invoices/PatchInvoicesEndpoint.ts +5 -3
  138. package/src/endpoints/organization/dashboard/mollie/CheckMollieEndpoint.ts +4 -2
  139. package/src/endpoints/organization/dashboard/mollie/ConnectMollieEndpoint.ts +6 -3
  140. package/src/endpoints/organization/dashboard/mollie/DisconnectMollieEndpoint.ts +4 -2
  141. package/src/endpoints/organization/dashboard/mollie/GetMollieDashboardEndpoint.ts +2 -1
  142. package/src/endpoints/organization/dashboard/nolt/CreateNoltTokenEndpoint.ts +2 -1
  143. package/src/endpoints/organization/dashboard/organization/GetOrganizationArchivedGroups.ts +4 -2
  144. package/src/endpoints/organization/dashboard/organization/GetOrganizationDeletedGroups.ts +3 -2
  145. package/src/endpoints/organization/dashboard/organization/GetUitpasClientIdEndpoint.ts +2 -1
  146. package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.test.ts +5 -3
  147. package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.ts +6 -3
  148. package/src/endpoints/organization/dashboard/organization/SearchUitpasOrganizersEndpoint.ts +5 -3
  149. package/src/endpoints/organization/dashboard/organization/SetOrganizationDomainEndpoint.ts +11 -9
  150. package/src/endpoints/organization/dashboard/organization/SetUitpasClientCredentialsEndpoint.ts +3 -2
  151. package/src/endpoints/organization/dashboard/payments/GetMemberBalanceEndpoint.ts +2 -1
  152. package/src/endpoints/organization/dashboard/payments/GetPaymentsCountEndpoint.ts +3 -2
  153. package/src/endpoints/organization/dashboard/payments/GetPaymentsEndpoint.ts +6 -4
  154. package/src/endpoints/organization/dashboard/payments/PatchPaymentsEndpoint.ts +5 -3
  155. package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalanceEndpoint.ts +2 -1
  156. package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalancesCountEndpoint.ts +3 -2
  157. package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalancesEndpoint.ts +5 -3
  158. package/src/endpoints/organization/dashboard/registration-periods/GetOrganizationRegistrationPeriodsEndpoint.test.ts +2 -1
  159. package/src/endpoints/organization/dashboard/registration-periods/GetOrganizationRegistrationPeriodsEndpoint.ts +7 -4
  160. package/src/endpoints/organization/dashboard/registration-periods/MoveRegistrationPeriods.test.ts +4 -2
  161. package/src/endpoints/organization/dashboard/registration-periods/PatchOrganizationRegistrationPeriodsEndpoint.test.ts +4 -2
  162. package/src/endpoints/organization/dashboard/registration-periods/PatchOrganizationRegistrationPeriodsEndpoint.ts +6 -3
  163. package/src/endpoints/organization/dashboard/registration-periods/SetupStepReviewEndpoint.ts +6 -3
  164. package/src/endpoints/organization/dashboard/stripe/ConnectStripeEndpoint.ts +3 -2
  165. package/src/endpoints/organization/dashboard/stripe/DeleteStripeAccountEndpoint.ts +2 -1
  166. package/src/endpoints/organization/dashboard/stripe/GetStripeAccountLinkEndpoint.ts +4 -2
  167. package/src/endpoints/organization/dashboard/stripe/GetStripeAccountsEndpoint.ts +2 -1
  168. package/src/endpoints/organization/dashboard/stripe/GetStripeLoginLinkEndpoint.ts +4 -2
  169. package/src/endpoints/organization/dashboard/stripe/UpdateStripeAccountEndpoint.ts +2 -1
  170. package/src/endpoints/organization/dashboard/users/CreateApiUserEndpoint.ts +3 -2
  171. package/src/endpoints/organization/dashboard/users/DeleteUserEndpoint.ts +2 -1
  172. package/src/endpoints/organization/dashboard/users/GetApiUsersEndpoint.ts +3 -2
  173. package/src/endpoints/organization/dashboard/users/GetOrganizationAdminsEndpoint.ts +2 -1
  174. package/src/endpoints/organization/dashboard/users/PatchApiUserEndpoint.ts +4 -2
  175. package/src/endpoints/organization/dashboard/webshops/CreateWebshopEndpoint.ts +3 -2
  176. package/src/endpoints/organization/dashboard/webshops/DeleteWebshopEndpoint.ts +2 -1
  177. package/src/endpoints/organization/dashboard/webshops/GetDiscountCodesEndpoint.ts +4 -2
  178. package/src/endpoints/organization/dashboard/webshops/GetWebshopOrdersCountEndpoint.ts +3 -2
  179. package/src/endpoints/organization/dashboard/webshops/GetWebshopOrdersEndpoint.ts +7 -4
  180. package/src/endpoints/organization/dashboard/webshops/{GetWebshopTicketsCountEndpoint → GetWebshopTicketsCountEndpoint.ts} +7 -7
  181. package/src/endpoints/organization/dashboard/webshops/GetWebshopTicketsEndpoint.ts +9 -6
  182. package/src/endpoints/organization/dashboard/webshops/GetWebshopUriAvailabilityEndpoint.ts +4 -2
  183. package/src/endpoints/organization/dashboard/webshops/PatchDiscountCodesEndpoint.ts +4 -2
  184. package/src/endpoints/organization/dashboard/webshops/PatchWebshopEndpoint.ts +4 -3
  185. package/src/endpoints/organization/dashboard/webshops/PatchWebshopOrdersEndpoint.ts +4 -2
  186. package/src/endpoints/organization/dashboard/webshops/PatchWebshopTicketsEndpoint.ts +4 -2
  187. package/src/endpoints/organization/dashboard/webshops/SearchUitpasEventsEndpoint.ts +5 -3
  188. package/src/endpoints/organization/dashboard/webshops/VerifyWebshopDomainEndpoint.ts +2 -1
  189. package/src/endpoints/organization/shared/ExchangePaymentEndpoint.ts +5 -3
  190. package/src/endpoints/organization/shared/GetDocumentHtml.ts +2 -1
  191. package/src/endpoints/organization/shared/GetPaymentEndpoint.ts +3 -2
  192. package/src/endpoints/organization/shared/GetUitpasNumberDetailsEndpoint.ts +3 -2
  193. package/src/endpoints/organization/shared/auth/GetOrganizationEndpoint.ts +3 -2
  194. package/src/endpoints/organization/webshops/CheckWebshopDiscountCodesEndpoint.ts +3 -2
  195. package/src/endpoints/organization/webshops/GetOrderByPaymentEndpoint.ts +3 -2
  196. package/src/endpoints/organization/webshops/GetOrderEndpoint.ts +3 -2
  197. package/src/endpoints/organization/webshops/GetTicketsEndpoint.ts +4 -2
  198. package/src/endpoints/organization/webshops/GetWebshopEndpoint.ts +3 -2
  199. package/src/endpoints/organization/webshops/PlaceOrderEndpoint.test.ts +7 -3
  200. package/src/endpoints/organization/webshops/PlaceOrderEndpoint.ts +3 -2
  201. package/src/endpoints/organization/webshops/RetrieveUitpasSocialTariffPriceEndpoint.ts +3 -2
  202. package/src/endpoints/system/HealthEndpoint.test.ts +44 -0
  203. package/src/endpoints/system/HealthEndpoint.ts +14 -6
  204. package/src/excel-loaders/balance-items.ts +4 -2
  205. package/src/excel-loaders/event-notifications.ts +7 -5
  206. package/src/excel-loaders/index.ts +1 -0
  207. package/src/excel-loaders/members.ts +6 -4
  208. package/src/excel-loaders/organizations.ts +8 -7
  209. package/src/excel-loaders/payments.ts +5 -3
  210. package/src/excel-loaders/platform-memberships.ts +262 -0
  211. package/src/excel-loaders/receivable-balances.ts +7 -5
  212. package/src/excel-loaders/registrations.ts +9 -7
  213. package/src/helpers/AddressValidator.test.ts +2 -1
  214. package/src/helpers/AddressValidator.ts +7 -4
  215. package/src/helpers/AdminPermissionChecker.ts +190 -92
  216. package/src/helpers/AuthenticatedStructures.ts +4 -2
  217. package/src/helpers/BuckarooHelper.ts +2 -1
  218. package/src/helpers/Context.ts +4 -2
  219. package/src/helpers/CookieHelper.ts +2 -2
  220. package/src/helpers/FileCache.ts +2 -2
  221. package/src/helpers/ForwardHandler.ts +2 -1
  222. package/src/helpers/GlobalHelper.ts +2 -0
  223. package/src/helpers/GroupBuilder.ts +2 -1
  224. package/src/helpers/GroupedThrottledQueue.test.ts +19 -19
  225. package/src/helpers/LimitedFilteredRequestHelper.ts +1 -1
  226. package/src/helpers/MemberCharger.ts +2 -1
  227. package/src/helpers/MemberUserSyncer.ts +6 -3
  228. package/src/helpers/OrganizationCharger.ts +2 -1
  229. package/src/helpers/PeriodHelper.ts +2 -1
  230. package/src/helpers/SQLTranslatedString.ts +3 -2
  231. package/src/helpers/ServiceFeeHelper.ts +1 -1
  232. package/src/helpers/SetupStepUpdater.ts +5 -4
  233. package/src/helpers/StripeHelper.ts +3 -2
  234. package/src/helpers/TagHelper.test.ts +5 -5
  235. package/src/helpers/TagHelper.ts +2 -1
  236. package/src/helpers/TemporaryMemberAccess.ts +2 -1
  237. package/src/helpers/ThrottledQueue.test.ts +20 -20
  238. package/src/helpers/ViesHelper.ts +4 -3
  239. package/src/helpers/XlsxTransformerColumnHelper.ts +4 -2
  240. package/src/helpers/email-html-helpers.ts +5 -4
  241. package/src/helpers/fetchToAsyncIterator.ts +1 -1
  242. package/src/helpers/outstandingBalanceJoin.ts +2 -1
  243. package/src/helpers/updateMemberDetailsUitpasNumber.ts +4 -3
  244. package/src/middleware/ContextMiddleware.ts +1 -1
  245. package/src/migrate.ts +21 -4
  246. package/src/seeds/0000000003-default-email-templates.ts +1 -1
  247. package/src/seeds/0000000004-single-organization.ts +2 -1
  248. package/src/seeds/1752848561-groups-registration-periods.ts +2 -1
  249. package/src/seeds/1754560914-groups-prices.test.ts +2 -1
  250. package/src/seeds/1754560914-groups-prices.ts +2 -1
  251. package/src/seeds/1755876819-remove-duplicate-members.ts +2 -1
  252. package/src/seeds/1765896674-document-update-year.test.ts +2 -1
  253. package/src/seeds/1773754928-force-save-members.ts +15 -0
  254. package/src/services/AuditLogService.ts +3 -2
  255. package/src/services/BalanceItemPaymentService.ts +2 -2
  256. package/src/services/BalanceItemService.ts +2 -1
  257. package/src/services/BootChecksService.test.ts +33 -0
  258. package/src/services/BootChecksService.ts +21 -0
  259. package/src/services/DatabaseCollationService.test.ts +18 -0
  260. package/src/services/DatabaseCollationService.ts +81 -0
  261. package/src/services/DocumentService.ts +1 -1
  262. package/src/services/EventNotificationService.ts +2 -1
  263. package/src/services/FileSignService.ts +1 -1
  264. package/src/services/MemberNumberService.ts +3 -1
  265. package/src/services/MemberRecordStore.ts +28 -19
  266. package/src/services/PaymentReallocationService.test.ts +2 -1
  267. package/src/services/PaymentReallocationService.ts +2 -1
  268. package/src/services/PaymentService.ts +5 -3
  269. package/src/services/RegistrationService.ts +65 -3
  270. package/src/services/SSOService.ts +8 -4
  271. package/src/services/STPackageService.ts +5 -3
  272. package/src/services/StartupHealthService.ts +15 -0
  273. package/src/services/uitpas/UitpasService.ts +6 -3
  274. package/src/sql-filters/audit-logs.ts +2 -1
  275. package/src/sql-filters/balance-item-payments.ts +2 -1
  276. package/src/sql-filters/balance-items.ts +2 -1
  277. package/src/sql-filters/base-registration-filter-compilers.ts +4 -2
  278. package/src/sql-filters/document-templates.ts +2 -1
  279. package/src/sql-filters/documents.ts +2 -1
  280. package/src/sql-filters/email-recipients.ts +2 -1
  281. package/src/sql-filters/emails.ts +2 -1
  282. package/src/sql-filters/event-notifications.ts +2 -1
  283. package/src/sql-filters/events.ts +2 -1
  284. package/src/sql-filters/groups.ts +2 -1
  285. package/src/sql-filters/invoiced-balance-items.ts +2 -1
  286. package/src/sql-filters/invoices.ts +2 -1
  287. package/src/sql-filters/member-responsibility-records.ts +2 -1
  288. package/src/sql-filters/members.ts +2 -1
  289. package/src/sql-filters/orders.ts +2 -1
  290. package/src/sql-filters/organization-registration-periods.ts +2 -1
  291. package/src/sql-filters/organizations.ts +2 -1
  292. package/src/sql-filters/payments.ts +2 -1
  293. package/src/sql-filters/platform-memberships.ts +72 -0
  294. package/src/sql-filters/receivable-balances.ts +2 -1
  295. package/src/sql-filters/registration-periods.ts +2 -1
  296. package/src/sql-filters/registrations.ts +2 -1
  297. package/src/sql-filters/tickets.ts +2 -1
  298. package/src/sql-filters/users.ts +2 -1
  299. package/src/sql-filters/webshops.ts +38 -0
  300. package/src/sql-sorters/audit-logs.ts +3 -2
  301. package/src/sql-sorters/balance-items.ts +3 -2
  302. package/src/sql-sorters/document-templates.ts +3 -2
  303. package/src/sql-sorters/documents.ts +3 -2
  304. package/src/sql-sorters/email-recipients.ts +3 -2
  305. package/src/sql-sorters/emails.ts +3 -2
  306. package/src/sql-sorters/event-notifications.ts +3 -2
  307. package/src/sql-sorters/events.ts +3 -2
  308. package/src/sql-sorters/groups.ts +3 -2
  309. package/src/sql-sorters/invoices.ts +3 -2
  310. package/src/sql-sorters/members.ts +3 -2
  311. package/src/sql-sorters/orders.ts +3 -2
  312. package/src/sql-sorters/organization-registration-periods.ts +3 -2
  313. package/src/sql-sorters/organizations.ts +3 -2
  314. package/src/sql-sorters/payments.ts +3 -2
  315. package/src/sql-sorters/platform-memberships.ts +40 -0
  316. package/src/sql-sorters/receivable-balances.ts +3 -2
  317. package/src/sql-sorters/registration-periods.ts +3 -2
  318. package/src/sql-sorters/registrations.ts +3 -2
  319. package/src/sql-sorters/tickets.ts +3 -2
  320. package/src/sql-sorters/webshops.ts +40 -0
  321. package/tests/actions/patchOrganizationMember.ts +5 -4
  322. package/tests/actions/patchPaymentStatus.ts +2 -2
  323. package/tests/actions/patchUserMember.ts +6 -4
  324. package/tests/e2e/api-rate-limits.test.ts +4 -5
  325. package/tests/e2e/bundle-discounts.test.ts +3 -2
  326. package/tests/e2e/charge-members.test.ts +7 -5
  327. package/tests/e2e/documents.test.ts +3 -2
  328. package/tests/e2e/private-files.test.ts +11 -13
  329. package/tests/e2e/register.test.ts +6 -5
  330. package/tests/e2e/stock.test.ts +6 -8
  331. package/tests/e2e/tickets.test.ts +4 -2
  332. package/tests/helpers/StripeMocker.ts +3 -3
  333. package/tests/init/initAdmin.ts +4 -2
  334. package/tests/init/initBundleDiscount.ts +3 -2
  335. package/tests/init/initPayconiq.ts +1 -1
  336. package/tests/init/initPermissionRole.ts +4 -2
  337. package/tests/init/initPlatformRecordCategory.ts +1 -1
  338. package/tests/init/initStripe.ts +1 -1
  339. package/tests/vitest.global.setup.ts +26 -0
  340. package/tests/{jest.setup.ts → vitest.setup.ts} +4 -3
  341. package/tsconfig.build.json +17 -0
  342. package/tsconfig.json +10 -41
  343. package/tsconfig.test.json +17 -0
  344. package/vitest.config.js +13 -0
  345. package/eslint.config.mjs +0 -5
  346. package/jest.config.cjs +0 -27
  347. package/tests/jest.global.setup.ts +0 -33
  348. package/tests/toMatchMap.ts +0 -68
@@ -1,6 +1,7 @@
1
1
  import { Migration } from '@simonbackx/simple-database';
2
2
  import { Group, OrganizationRegistrationPeriod } from '@stamhoofd/models';
3
- import { BundleDiscount, BundleDiscountGroupPriceSettings, GroupCategory, GroupPrice, GroupPriceDiscount, GroupPriceDiscountType, GroupStatus, GroupType, OldGroupPrice, OldGroupPrices, ReduceablePrice, TranslatedString } from '@stamhoofd/structures';
3
+ import type { GroupCategory} from '@stamhoofd/structures';
4
+ import { BundleDiscount, BundleDiscountGroupPriceSettings, GroupPrice, GroupPriceDiscount, GroupPriceDiscountType, GroupStatus, GroupType, OldGroupPrice, OldGroupPrices, ReduceablePrice, TranslatedString } from '@stamhoofd/structures';
4
5
  import { Formatter } from '@stamhoofd/utility';
5
6
 
6
7
  const UNNASSIGNED_KEY = 'unassigned';
@@ -1,4 +1,5 @@
1
- import { Migration, SQLResultNamespacedRow } from '@simonbackx/simple-database';
1
+ import type { SQLResultNamespacedRow } from '@simonbackx/simple-database';
2
+ import { Migration } from '@simonbackx/simple-database';
2
3
  import { Member, mergeTwoMembers } from '@stamhoofd/models';
3
4
  import { SQL, SQLSelect } from '@stamhoofd/sql';
4
5
  import { PatchOrganizationMembersEndpoint } from '../endpoints/global/members/PatchOrganizationMembersEndpoint.js';
@@ -1,4 +1,5 @@
1
- import { DocumentTemplate, DocumentTemplateFactory, GroupFactory, OrganizationFactory, RegistrationPeriod, RegistrationPeriodFactory } from '@stamhoofd/models';
1
+ import type { RegistrationPeriod} from '@stamhoofd/models';
2
+ import { DocumentTemplate, DocumentTemplateFactory, GroupFactory, OrganizationFactory, RegistrationPeriodFactory } from '@stamhoofd/models';
2
3
  import { migrateDocumentYears } from './1765896674-document-update-year.js';
3
4
 
4
5
  describe('migration.document-update-year', () => {
@@ -0,0 +1,15 @@
1
+ import { Migration } from '@simonbackx/simple-database';
2
+ import { Member, Registration } from '@stamhoofd/models';
3
+
4
+ export default new Migration(async () => {
5
+ process.stdout.write('\n');
6
+ for await (const member of Member.select().all()) {
7
+ member.forceSaveProperty('details');
8
+ await member.save();
9
+ }
10
+
11
+ for await (const registration of Registration.select().all()) {
12
+ registration.forceSaveProperty('groupPrice');
13
+ await registration.save();
14
+ }
15
+ });
@@ -1,5 +1,6 @@
1
- import { Model, ModelEvent } from '@simonbackx/simple-database';
2
- import { AuditLogSource } from '@stamhoofd/structures';
1
+ import type { ModelEvent } from '@simonbackx/simple-database';
2
+ import { Model } from '@simonbackx/simple-database';
3
+ import type { AuditLogSource } from '@stamhoofd/structures';
3
4
  import { AsyncLocalStorage } from 'node:async_hooks';
4
5
 
5
6
  export type AuditLogContextSettings = {
@@ -1,5 +1,5 @@
1
- import { ManyToOneRelation } from '@simonbackx/simple-database';
2
- import { BalanceItemPayment, Organization } from '@stamhoofd/models';
1
+ import type { ManyToOneRelation } from '@simonbackx/simple-database';
2
+ import type { BalanceItemPayment, Organization } from '@stamhoofd/models';
3
3
  import { BalanceItemService } from './BalanceItemService.js';
4
4
 
5
5
  type Loaded<T> = (T) extends ManyToOneRelation<infer Key, infer Model> ? Record<Key, Model> : never;
@@ -1,5 +1,6 @@
1
1
  import { Model } from '@simonbackx/simple-database';
2
- import { BalanceItem, CachedBalance, Document, MemberUser, Order, Organization, Payment, Webshop } from '@stamhoofd/models';
2
+ import type { Organization, Payment} from '@stamhoofd/models';
3
+ import { BalanceItem, CachedBalance, Document, MemberUser, Order, Webshop } from '@stamhoofd/models';
3
4
  import { AuditLogSource, BalanceItemStatus, BalanceItemType, OrderStatus, PaymentStatus, ReceivableBalanceType } from '@stamhoofd/structures';
4
5
  import { GroupedThrottledQueue } from '../helpers/GroupedThrottledQueue.js';
5
6
  import { ThrottledQueue } from '../helpers/ThrottledQueue.js';
@@ -0,0 +1,33 @@
1
+ import { TestUtils } from '@stamhoofd/test-utils';
2
+ import { BootChecksService } from './BootChecksService.js';
3
+ import { DatabaseCollationService } from './DatabaseCollationService.js';
4
+ import { StartupHealthService } from './StartupHealthService.js';
5
+
6
+ describe('BootChecksService', () => {
7
+ beforeEach(() => {
8
+ vi.restoreAllMocks();
9
+ StartupHealthService.clearForTesting();
10
+ });
11
+
12
+ afterEach(() => {
13
+ vi.restoreAllMocks();
14
+ StartupHealthService.clearForTesting();
15
+ });
16
+
17
+ test('Throws outside production when collation mismatches', async () => {
18
+ TestUtils.setEnvironment('environment', 'development');
19
+
20
+ vi.spyOn(DatabaseCollationService, 'getMismatchError').mockResolvedValue('MySQL collation mismatch test error');
21
+
22
+ await expect(BootChecksService.checkDatabaseCollation()).rejects.toThrow('MySQL collation mismatch test error');
23
+ });
24
+
25
+ test('Marks startup unhealthy in production when collation mismatches', async () => {
26
+ TestUtils.setEnvironment('environment', 'production');
27
+
28
+ vi.spyOn(DatabaseCollationService, 'getMismatchError').mockResolvedValue('MySQL collation mismatch test error');
29
+
30
+ await expect(BootChecksService.checkDatabaseCollation()).resolves.toBeUndefined();
31
+ expect(StartupHealthService.getErrors()).toContain('MySQL collation mismatch test error');
32
+ });
33
+ });
@@ -0,0 +1,21 @@
1
+ import { DatabaseCollationService } from './DatabaseCollationService.js';
2
+ import { StartupHealthService } from './StartupHealthService.js';
3
+
4
+ export class BootChecksService {
5
+ static async checkDatabaseCollation() {
6
+ const collationMismatchError = await DatabaseCollationService.getMismatchError();
7
+
8
+ if (!collationMismatchError) {
9
+ return;
10
+ }
11
+
12
+ if (STAMHOOFD.environment === 'production') {
13
+ console.error(collationMismatchError);
14
+ console.error('Health endpoint will keep returning a non-2xx status until the process is restarted with a fixed database collation.');
15
+ StartupHealthService.markUnhealthy(collationMismatchError);
16
+ return;
17
+ }
18
+
19
+ throw new Error(collationMismatchError);
20
+ }
21
+ }
@@ -0,0 +1,18 @@
1
+ import { Database } from '@simonbackx/simple-database';
2
+ import { DatabaseCollationService } from './DatabaseCollationService.js';
3
+
4
+ describe('DatabaseCollationService', () => {
5
+ test('Detects collation_connection mismatch', async () => {
6
+ await Database.statement('SET collation_connection = \'utf8mb4_general_ci\'');
7
+
8
+ try {
9
+ const error = await DatabaseCollationService.getMismatchError();
10
+ expect(error).toContain('MySQL collation mismatch');
11
+ expect(error).toContain('expected utf8mb4_0900_ai_ci');
12
+ expect(error).toContain('collation_connection=utf8mb4_general_ci');
13
+ }
14
+ finally {
15
+ await Database.statement('SET collation_connection = DEFAULT');
16
+ }
17
+ });
18
+ });
@@ -0,0 +1,81 @@
1
+ import { Database } from '@simonbackx/simple-database';
2
+
3
+ const EXPECTED_COLLATION = 'utf8mb4_0900_ai_ci';
4
+
5
+ type CollationRow = {
6
+ collationConnection: string;
7
+ collationDatabase: string;
8
+ };
9
+
10
+ export class DatabaseCollationService {
11
+ static expectedCollation = EXPECTED_COLLATION;
12
+
13
+ static async getCurrentCollations() {
14
+ const connectionResult = await Database.statement("SHOW VARIABLES LIKE 'collation_connection'");
15
+ const databaseResult = await Database.statement("SHOW VARIABLES LIKE 'collation_database'");
16
+
17
+ const collationConnection = this.extractVariableValue(connectionResult);
18
+ const collationDatabase = this.extractVariableValue(databaseResult);
19
+
20
+ return {
21
+ collationConnection: typeof collationConnection === 'string' ? collationConnection : '',
22
+ collationDatabase: typeof collationDatabase === 'string' ? collationDatabase : '',
23
+ } as CollationRow;
24
+ }
25
+
26
+ private static extractVariableValue(result: unknown) {
27
+ if (result && typeof result === 'object' && 'rows' in result) {
28
+ return this.extractVariableValue((result as { rows: unknown }).rows);
29
+ }
30
+
31
+ if (Array.isArray(result) && result.length > 0 && Array.isArray(result[0])) {
32
+ return this.extractVariableValue(result[0]);
33
+ }
34
+
35
+ if (!Array.isArray(result) || result.length === 0) {
36
+ return '';
37
+ }
38
+
39
+ const firstRow = result[0] as Record<string, unknown> | undefined;
40
+
41
+ if (!firstRow) {
42
+ return '';
43
+ }
44
+
45
+ const value = firstRow.Value
46
+ ?? firstRow.value
47
+ ?? firstRow.VARIABLE_VALUE
48
+ ?? firstRow.variable_value;
49
+
50
+ if (typeof value === 'string') {
51
+ return value;
52
+ }
53
+
54
+ for (const candidate of Object.values(firstRow)) {
55
+ if (typeof candidate === 'string' && candidate.startsWith('utf8mb4_')) {
56
+ return candidate;
57
+ }
58
+ }
59
+
60
+ return '';
61
+ }
62
+
63
+ static async getMismatchError() {
64
+ const collations = await this.getCurrentCollations();
65
+ const mismatches: string[] = [];
66
+
67
+ if (collations.collationConnection !== this.expectedCollation) {
68
+ mismatches.push(`collation_connection=${collations.collationConnection}`);
69
+ }
70
+
71
+ if (collations.collationDatabase !== this.expectedCollation) {
72
+ mismatches.push(`collation_database=${collations.collationDatabase}`);
73
+ }
74
+
75
+ if (mismatches.length === 0) {
76
+ return null;
77
+ }
78
+
79
+ return `MySQL collation mismatch: expected ${this.expectedCollation}, got ${mismatches.join(', ')}`;
80
+ }
81
+ }
@@ -1,5 +1,5 @@
1
1
  import { Model } from '@simonbackx/simple-database';
2
- import { PlainObject } from '@simonbackx/simple-encoding';
2
+ import type { PlainObject } from '@simonbackx/simple-encoding';
3
3
  import { Document, Group } from '@stamhoofd/models';
4
4
 
5
5
  function getGroupFieldsAffectingDocuments(group: Group): PlainObject {
@@ -1,6 +1,7 @@
1
1
  import { SimpleError } from '@simonbackx/simple-errors';
2
2
  import { EventNotification, Member, MemberResponsibilityRecord, Organization, Platform, sendEmailTemplate, User } from '@stamhoofd/models';
3
- import { EmailTemplateType, PermissionLevel, Recipient, RecordCategory, Replacement } from '@stamhoofd/structures';
3
+ import type { EmailTemplateType} from '@stamhoofd/structures';
4
+ import { PermissionLevel, Recipient, RecordCategory, Replacement } from '@stamhoofd/structures';
4
5
  import { Formatter } from '@stamhoofd/utility';
5
6
  import { AdminPermissionChecker } from '../helpers/AdminPermissionChecker.js';
6
7
  import { Context } from '../helpers/Context.js';
@@ -2,7 +2,7 @@ import { GetObjectCommand, S3Client } from '@aws-sdk/client-s3'; // ES Modules i
2
2
  import {
3
3
  getSignedUrl,
4
4
  } from '@aws-sdk/s3-request-presigner';
5
- import { DecodedRequest, Request, Response } from '@simonbackx/simple-endpoints';
5
+ import type { DecodedRequest, Request, Response } from '@simonbackx/simple-endpoints';
6
6
  import { SimpleError } from '@simonbackx/simple-errors';
7
7
  import { File } from '@stamhoofd/structures';
8
8
  import chalk from 'chalk';
@@ -1,7 +1,9 @@
1
1
  import { isSimpleError, isSimpleErrors, SimpleError } from '@simonbackx/simple-errors';
2
- import { Member, MemberPlatformMembership, Organization } from '@stamhoofd/models';
2
+ import type { Member, MemberPlatformMembership} from '@stamhoofd/models';
3
+ import { Organization } from '@stamhoofd/models';
3
4
  import { QueueHandler } from '@stamhoofd/queues';
4
5
  import { scalarToSQLExpression, SQL, SQLCharLength, SQLWhereLike } from '@stamhoofd/sql';
6
+ import { MemberNumberAlgorithm } from '@stamhoofd/types/MemberNumberAlgorithm';
5
7
 
6
8
  export class MemberNumberService {
7
9
  static async assignMemberNumber(member: Member, membership: MemberPlatformMembership) {
@@ -1,33 +1,31 @@
1
1
  import { Model } from '@simonbackx/simple-database';
2
2
  import { Organization, Platform } from '@stamhoofd/models';
3
3
  import { QueueHandler } from '@stamhoofd/queues';
4
- import { RecordSettings } from '@stamhoofd/structures';
4
+ import type { RecordSettings } from '@stamhoofd/structures';
5
5
 
6
6
  export type RecordCacheEntry = { record: RecordSettings; rootCategoryId: string; organizationId: string | null };
7
7
 
8
8
  /**
9
9
  * Service that caches all available member records in the system.
10
- * - It verified whether ids are unique system wide
10
+ * - It verifies whether ids are unique system wide
11
11
  * - It allows fast retrieving of record settings by id (for permission checking)
12
12
  */
13
- export class MemberRecordStore {
14
- private static cache = new Map<string, RecordCacheEntry>();
13
+ class MemberRecordStoreService {
14
+ private cache = new Map<string, RecordCacheEntry>();
15
15
 
16
- constructor() {
17
-
18
- }
16
+ init() {
17
+ // Should only be used in userMode platform
18
+ if (STAMHOOFD.userMode !== 'platform') {
19
+ return;
20
+ }
19
21
 
20
- static init() {
21
22
  // Load initial data
22
23
  this.loadIfNeeded().catch(console.error);
23
-
24
- // Create listeners to update data as organizations and platform is updated
25
- this.listen();
26
24
  }
27
25
 
28
- private static listening = false;
26
+ private listening = false;
29
27
 
30
- private static listen() {
28
+ private listen() {
31
29
  // Create listeners to update data as organizations and platform is updated
32
30
  if (this.listening) {
33
31
  return;
@@ -66,7 +64,7 @@ export class MemberRecordStore {
66
64
  }
67
65
 
68
66
  if (event.model instanceof Organization) {
69
- // Delete all records with organizationId = null
67
+ // Delete all records where organizationId equals the organization
70
68
  for (const [id, entry] of this.cache) {
71
69
  if (entry.organizationId === event.model.id) {
72
70
  this.cache.delete(id);
@@ -88,10 +86,10 @@ export class MemberRecordStore {
88
86
  });
89
87
  }
90
88
 
91
- static _loadAllPromise: Promise<void> | null = null;
92
- static _didLoadAll = false;
89
+ private _loadAllPromise: Promise<void> | null = null;
90
+ private _didLoadAll = false;
93
91
 
94
- static async loadIfNeeded() {
92
+ private async loadIfNeeded() {
95
93
  if (this._didLoadAll) {
96
94
  return;
97
95
  }
@@ -100,6 +98,11 @@ export class MemberRecordStore {
100
98
  await this._loadAllPromise;
101
99
  }
102
100
  else {
101
+ if (STAMHOOFD.userMode !== 'platform') {
102
+ // Important to throw an error because in tests the userMode can change in between tests
103
+ throw new Error('Should only be loaded in userMode platform.');
104
+ }
105
+
103
106
  this._loadAllPromise = (async () => {
104
107
  try {
105
108
  await this.loadAll();
@@ -116,7 +119,7 @@ export class MemberRecordStore {
116
119
  }
117
120
  }
118
121
 
119
- static async loadAll() {
122
+ private async loadAll() {
120
123
  this.cache = new Map<string, RecordCacheEntry>();
121
124
 
122
125
  // We use a queue here so we can abort this long running task properly
@@ -155,10 +158,16 @@ export class MemberRecordStore {
155
158
  abort.throwIfAborted();
156
159
  }
157
160
  });
161
+
162
+ // Create listeners to update data as organizations and platform is updated.
163
+ // Should be checked on every loadAll because the userMode can change for tests.
164
+ this.listen();
158
165
  }
159
166
 
160
- static async getRecord(id: string): Promise<RecordCacheEntry | null> {
167
+ async getRecord(id: string): Promise<RecordCacheEntry | null> {
161
168
  await this.loadIfNeeded();
162
169
  return this.cache.get(id) ?? null;
163
170
  }
164
171
  }
172
+
173
+ export const MemberRecordStore = new MemberRecordStoreService();
@@ -1,4 +1,5 @@
1
- import { BalanceItem, BalanceItemPayment, MemberFactory, Organization, OrganizationFactory, Payment } from '@stamhoofd/models';
1
+ import type { Organization} from '@stamhoofd/models';
2
+ import { BalanceItem, BalanceItemPayment, MemberFactory, OrganizationFactory, Payment } from '@stamhoofd/models';
2
3
  import { BalanceItemRelation, BalanceItemRelationType, BalanceItemStatus, PaymentMethod, PaymentStatus, ReceivableBalanceType, TranslatedString } from '@stamhoofd/structures';
3
4
  import { PaymentReallocationService } from './PaymentReallocationService.js';
4
5
  import { BalanceItemService } from './BalanceItemService.js';
@@ -1,6 +1,7 @@
1
1
  import { BalanceItem, BalanceItemPayment, CachedBalance, Payment } from '@stamhoofd/models';
2
2
  import { SQL } from '@stamhoofd/sql';
3
- import { BalanceItemStatus, doBalanceItemRelationsMatch, PaymentMethod, PaymentStatus, PaymentType, ReceivableBalanceType } from '@stamhoofd/structures';
3
+ import type { ReceivableBalanceType } from '@stamhoofd/structures';
4
+ import { BalanceItemStatus, doBalanceItemRelationsMatch, PaymentMethod, PaymentStatus, PaymentType } from '@stamhoofd/structures';
4
5
  import { Sorter } from '@stamhoofd/utility';
5
6
  import { BalanceItemService } from './BalanceItemService.js';
6
7
 
@@ -1,8 +1,10 @@
1
- import createMollieClient, { PaymentMethod as molliePaymentMethod, PaymentStatus as MolliePaymentStatus } from '@mollie/api-client';
1
+ import { createMollieClient, PaymentMethod as molliePaymentMethod, PaymentStatus as MolliePaymentStatus } from '@mollie/api-client';
2
2
  import { SimpleError } from '@simonbackx/simple-errors';
3
- import { BalanceItem, BalanceItemPayment, Group, Member, MolliePayment, MollieToken, Organization, PayconiqPayment, Payment, sendEmailTemplate, User } from '@stamhoofd/models';
3
+ import type { BalanceItem, Member, User } from '@stamhoofd/models';
4
+ import { BalanceItemPayment, Group, MolliePayment, MollieToken, Organization, PayconiqPayment, Payment, sendEmailTemplate } from '@stamhoofd/models';
4
5
  import { QueueHandler } from '@stamhoofd/queues';
5
- import { AuditLogSource, BalanceItemType, Checkoutable, Country, EmailTemplateType, PaymentConfiguration, PaymentCustomer, PaymentMethod, PaymentMethodHelper, PaymentProvider, PaymentStatus, PaymentType, Recipient, VATExcemptReason, Version } from '@stamhoofd/structures';
6
+ import type { Checkoutable, PaymentConfiguration } from '@stamhoofd/structures';
7
+ import { AuditLogSource, BalanceItemType, EmailTemplateType, PaymentCustomer, PaymentMethod, PaymentMethodHelper, PaymentProvider, PaymentStatus, PaymentType, Recipient, VATExcemptReason, Version } from '@stamhoofd/structures';
6
8
  import { Formatter } from '@stamhoofd/utility';
7
9
  import { buildReplacementOptions, getEmailReplacementsForPayment } from '../email-replacements/getEmailReplacementsForPayment.js';
8
10
  import { BuckarooHelper } from '../helpers/BuckarooHelper.js';
@@ -1,6 +1,6 @@
1
1
  import { ManyToOneRelation } from '@simonbackx/simple-database';
2
- import { BalanceItem, Document, Group, Member, Registration } from '@stamhoofd/models';
3
- import { AppliedRegistrationDiscount, AuditLogSource, BalanceItemRelationType, BalanceItemStatus, BalanceItemType, EmailTemplateType, StockReservation, TranslatedString, Version } from '@stamhoofd/structures';
2
+ import { BalanceItem, Document, Group, Member, Organization, Registration, sendEmailTemplate } from '@stamhoofd/models';
3
+ import { AppliedRegistrationDiscount, AuditLogSource, BalanceItemRelationType, BalanceItemStatus, BalanceItemType, EmailTemplateType, Recipient, Replacement, StockReservation, TranslatedString, Version } from '@stamhoofd/structures';
4
4
  import { AuditLogService } from './AuditLogService.js';
5
5
  import { GroupService } from './GroupService.js';
6
6
  import { PlatformMembershipService } from './PlatformMembershipService.js';
@@ -58,7 +58,7 @@ export const RegistrationService = {
58
58
  await PlatformMembershipService.updateMembershipsForId(registration.memberId);
59
59
 
60
60
  if (registration.sendConfirmationEmail) {
61
- await registration.sendEmailTemplate({
61
+ await RegistrationService.sendEmailTemplate(registration, {
62
62
  type: EmailTemplateType.RegistrationConfirmation,
63
63
  });
64
64
  }
@@ -76,6 +76,68 @@ export const RegistrationService = {
76
76
  return true;
77
77
  },
78
78
 
79
+ async getRecipients(registration: Registration, organization: Organization, group: Group) {
80
+ const member = await Member.getByIdWithUsers(registration.memberId);
81
+
82
+ if (!member) {
83
+ return [];
84
+ }
85
+
86
+ const allowedEmails = member.details.getNotificationEmails();
87
+
88
+ return member.users.map(user => Recipient.create({
89
+ firstName: user.firstName,
90
+ lastName: user.lastName,
91
+ email: user.email,
92
+ userId: user.id,
93
+ replacements: [
94
+ Replacement.create({
95
+ token: 'firstNameMember',
96
+ value: member.details.firstName,
97
+ }),
98
+ Replacement.create({
99
+ token: 'lastNameMember',
100
+ value: member.details.lastName,
101
+ }),
102
+ Replacement.create({
103
+ token: 'registerUrl',
104
+ value: 'https://' + organization.getHost(),
105
+ }),
106
+ Replacement.create({
107
+ token: 'groupName',
108
+ value: group.settings.name.toString(),
109
+ }),
110
+ ],
111
+ })).filter(r => allowedEmails.includes(r.email.toLocaleLowerCase()));
112
+ },
113
+
114
+ async sendEmailTemplate(registration: Registration, data: {
115
+ type: EmailTemplateType;
116
+ }) {
117
+ const group = await Group.getByID(registration.groupId);
118
+
119
+ if (!group) {
120
+ return;
121
+ }
122
+
123
+ const organization = await Organization.getByID(group.organizationId);
124
+ if (!organization) {
125
+ return;
126
+ }
127
+
128
+ const recipients = await RegistrationService.getRecipients(registration, organization, group);
129
+
130
+ // Create e-mail builder
131
+ await sendEmailTemplate(organization, {
132
+ template: {
133
+ type: data.type,
134
+ group,
135
+ },
136
+ recipients,
137
+ type: 'transactional',
138
+ });
139
+ },
140
+
79
141
  async updateDiscounts(registrationId: string) {
80
142
  await AuditLogService.setContext({ source: AuditLogSource.System }, async () => {
81
143
  await QueueHandler.schedule('registration-discounts-update-' + registrationId, async function (this: undefined) {
@@ -1,12 +1,16 @@
1
- import { DecodedRequest, Response } from '@simonbackx/simple-endpoints';
1
+ import type { DecodedRequest} from '@simonbackx/simple-endpoints';
2
+ import { Response } from '@simonbackx/simple-endpoints';
2
3
  import { isSimpleError, isSimpleErrors, SimpleError } from '@simonbackx/simple-errors';
3
- import { Organization, Platform, Token, User, Webshop } from '@stamhoofd/models';
4
- import { LoginMethod, LoginProviderType, OpenIDClientConfiguration, StartOpenIDFlowStruct, Token as TokenStruct } from '@stamhoofd/structures';
4
+ import type { Organization} from '@stamhoofd/models';
5
+ import { Platform, Token, User, Webshop } from '@stamhoofd/models';
6
+ import type { LoginMethod, StartOpenIDFlowStruct} from '@stamhoofd/structures';
7
+ import { LoginProviderType, OpenIDClientConfiguration, Token as TokenStruct } from '@stamhoofd/structures';
5
8
  import crypto from 'crypto';
6
9
  import { generators, Issuer } from 'openid-client';
7
10
  import { Context } from '../helpers/Context.js';
8
11
 
9
- import { CookieHelper, ObjectWithHeaders } from '../helpers/CookieHelper.js';
12
+ import type { ObjectWithHeaders } from '../helpers/CookieHelper.js';
13
+ import { CookieHelper } from '../helpers/CookieHelper.js';
10
14
 
11
15
  async function randomBytes(size: number): Promise<Buffer> {
12
16
  return new Promise((resolve, reject) => {
@@ -1,7 +1,9 @@
1
1
  import { SimpleError } from '@simonbackx/simple-errors';
2
- import { BalanceItem, Organization, Platform, Registration, STPackage } from '@stamhoofd/models';
2
+ import { BalanceItem, Organization, Platform, STPackage } from '@stamhoofd/models';
3
3
  import { SQL } from '@stamhoofd/sql';
4
- import { BalanceItemRelation, BalanceItemRelationType, BalanceItemStatus, BalanceItemType, Country, PaymentCustomer, STPackageStatus, STPackageType, STPricingType, TranslatedString, VATExcemptReason } from '@stamhoofd/structures';
4
+ import type { PaymentCustomer, STPackageStatus, STPackageType } from '@stamhoofd/structures';
5
+ import { BalanceItemRelation, BalanceItemRelationType, BalanceItemStatus, BalanceItemType, STPricingType, TranslatedString, VATExcemptReason } from '@stamhoofd/structures';
6
+ import { Country } from '@stamhoofd/types/Country';
5
7
  import { Formatter } from '@stamhoofd/utility';
6
8
  import { GroupBuilder } from '../helpers/GroupBuilder.js';
7
9
 
@@ -27,7 +29,7 @@ export class STPackageService {
27
29
  let membersCount: number | null = null;
28
30
 
29
31
  if (membersCount === null && pack.meta.pricingType === STPricingType.PerMember) {
30
- membersCount = await Registration.getActiveMembers(pack.organizationId);
32
+ membersCount = await Organization.getActiveMembers(pack.organizationId);
31
33
  }
32
34
 
33
35
  if (pack.meta.pricingType === STPricingType.PerMember) {
@@ -0,0 +1,15 @@
1
+ export class StartupHealthService {
2
+ private static readonly errors = new Set<string>();
3
+
4
+ static markUnhealthy(error: string) {
5
+ this.errors.add(error);
6
+ }
7
+
8
+ static getErrors() {
9
+ return [...this.errors];
10
+ }
11
+
12
+ static clearForTesting() {
13
+ this.errors.clear();
14
+ }
15
+ }
@@ -2,7 +2,8 @@ import { Model } from '@simonbackx/simple-database';
2
2
  import { isSimpleError, SimpleError } from '@simonbackx/simple-errors';
3
3
  import { Order, WebshopUitpasNumber } from '@stamhoofd/models';
4
4
  import { QueueHandler } from '@stamhoofd/queues';
5
- import { Cart, OrderStatus, Product, ProductPrice, UitpasClientCredentialsStatus, UitpasOrganizersResponse } from '@stamhoofd/structures';
5
+ import type { Cart, Product, ProductPrice, UitpasClientCredentialsStatus, UitpasOrganizersResponse } from '@stamhoofd/structures';
6
+ import { OrderStatus } from '@stamhoofd/structures';
6
7
  import { Formatter } from '@stamhoofd/utility';
7
8
  import { v4 as uuidv4 } from 'uuid';
8
9
  import { UitpasTokenRepository } from '../../helpers/UitpasTokenRepository.js';
@@ -11,8 +12,10 @@ import { checkPermissionsFor } from './checkPermissionsFor.js';
11
12
  import { checkUitpasNumbers } from './checkUitpasNumbers.js';
12
13
  import { getSocialTariffForEvent } from './getSocialTariffForEvent.js';
13
14
  import { getSocialTariffForUitpasNumbers } from './getSocialTariffForUitpasNumbers.js';
14
- import { GetPassResponse, PassholderEndpoints } from './PassholderEndpoints.js';
15
- import { RegisterTicketSaleRequest, RegisterTicketSaleResponse, registerTicketSales } from './registerTicketSales.js';
15
+ import type { GetPassResponse} from './PassholderEndpoints.js';
16
+ import { PassholderEndpoints } from './PassholderEndpoints.js';
17
+ import type { RegisterTicketSaleRequest, RegisterTicketSaleResponse} from './registerTicketSales.js';
18
+ import { registerTicketSales } from './registerTicketSales.js';
16
19
  import { searchUitpasEvents } from './searchUitpasEvents.js';
17
20
  import { searchUitpasOrganizers } from './searchUitpasOrganizers.js';
18
21
 
@@ -1,4 +1,5 @@
1
- import { baseSQLFilterCompilers, createColumnFilter, SQL, SQLFilterDefinitions, SQLValueType } from '@stamhoofd/sql';
1
+ import type { SQLFilterDefinitions} from '@stamhoofd/sql';
2
+ import { baseSQLFilterCompilers, createColumnFilter, SQL, SQLValueType } from '@stamhoofd/sql';
2
3
 
3
4
  export const auditLogFilterCompilers: SQLFilterDefinitions = {
4
5
  ...baseSQLFilterCompilers,
@@ -1,4 +1,5 @@
1
- import { baseSQLFilterCompilers, createColumnFilter, SQL, SQLFilterDefinitions, SQLValueType } from '@stamhoofd/sql';
1
+ import type { SQLFilterDefinitions} from '@stamhoofd/sql';
2
+ import { baseSQLFilterCompilers, createColumnFilter, SQL, SQLValueType } from '@stamhoofd/sql';
2
3
 
3
4
  export const balanceItemPaymentsCompilers: SQLFilterDefinitions = {
4
5
  ...baseSQLFilterCompilers,
@@ -1,4 +1,5 @@
1
- import { baseSQLFilterCompilers, createColumnFilter, SQL, SQLFilterDefinitions, SQLValueType } from '@stamhoofd/sql';
1
+ import type { SQLFilterDefinitions} from '@stamhoofd/sql';
2
+ import { baseSQLFilterCompilers, createColumnFilter, SQL, SQLValueType } from '@stamhoofd/sql';
2
3
 
3
4
  /**
4
5
  * Defines how to filter balance items in the database from StamhoofdFilter objects
@@ -1,6 +1,8 @@
1
1
  import { SimpleError } from '@simonbackx/simple-errors';
2
- import { baseSQLFilterCompilers, createColumnFilter, createExistsFilter, createJoinedRelationFilter, SQL, SQLFilterDefinitions, SQLIfNull, SQLValueType } from '@stamhoofd/sql';
3
- import { FilterWrapperMarker, PermissionLevel, StamhoofdFilter, unwrapFilter } from '@stamhoofd/structures';
2
+ import type { SQLFilterDefinitions} from '@stamhoofd/sql';
3
+ import { baseSQLFilterCompilers, createColumnFilter, createExistsFilter, createJoinedRelationFilter, SQL, SQLIfNull, SQLValueType } from '@stamhoofd/sql';
4
+ import type { StamhoofdFilter} from '@stamhoofd/structures';
5
+ import { FilterWrapperMarker, PermissionLevel, unwrapFilter } from '@stamhoofd/structures';
4
6
  import { Context } from '../helpers/Context.js';
5
7
  import { memberCachedBalanceForOrganizationJoin, registrationCachedBalanceJoin } from '../helpers/outstandingBalanceJoin.js';
6
8
  import { SQLTranslatedString } from '../helpers/SQLTranslatedString.js';
@@ -1,4 +1,5 @@
1
- import { baseSQLFilterCompilers, createColumnFilter, SQL, SQLFilterDefinitions, SQLValueType } from '@stamhoofd/sql';
1
+ import type { SQLFilterDefinitions} from '@stamhoofd/sql';
2
+ import { baseSQLFilterCompilers, createColumnFilter, SQL, SQLValueType } from '@stamhoofd/sql';
2
3
 
3
4
  export const documentTemplateFilterCompilers: SQLFilterDefinitions = {
4
5
  ...baseSQLFilterCompilers,
@@ -1,4 +1,5 @@
1
- import { baseSQLFilterCompilers, createColumnFilter, SQL, SQLFilterDefinitions, SQLValueType } from '@stamhoofd/sql';
1
+ import type { SQLFilterDefinitions} from '@stamhoofd/sql';
2
+ import { baseSQLFilterCompilers, createColumnFilter, SQL, SQLValueType } from '@stamhoofd/sql';
2
3
 
3
4
  export const documentFilterCompilers: SQLFilterDefinitions = {
4
5
  ...baseSQLFilterCompilers,