@stamhoofd/backend 2.118.1 → 2.120.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 (362) hide show
  1. package/package.json +32 -22
  2. package/src/audit-logs/ModelLogger.ts +4 -2
  3. package/src/audit-logs/OrderLogger.ts +1 -1
  4. package/src/boot.ts +32 -14
  5. package/src/crons/balance-emails.ts +4 -2
  6. package/src/crons/clearExcelCache.test.ts +8 -8
  7. package/src/crons/update-cached-balances.ts +40 -14
  8. package/src/debug.ts +3 -2
  9. package/src/decoders/StringArrayDecoder.ts +1 -1
  10. package/src/decoders/StringNullableDecoder.ts +1 -1
  11. package/src/email-recipient-loaders/documents.ts +2 -1
  12. package/src/email-recipient-loaders/members.ts +2 -1
  13. package/src/email-recipient-loaders/orders.ts +2 -1
  14. package/src/email-recipient-loaders/payments.ts +6 -3
  15. package/src/email-recipient-loaders/receivable-balances.ts +2 -1
  16. package/src/email-recipient-loaders/registrations.ts +2 -1
  17. package/src/email-replacements/getEmailReplacementsForPayment.ts +8 -7
  18. package/src/endpoints/admin/members/ChargeMembersEndpoint.ts +7 -6
  19. package/src/endpoints/admin/memberships/ChargeMembershipsEndpoint.ts +3 -2
  20. package/src/endpoints/admin/memberships/GetChargeMembershipsSummaryEndpoint.ts +2 -1
  21. package/src/endpoints/admin/organizations/ChargeOrganizationsEndpoint.ts +4 -3
  22. package/src/endpoints/admin/organizations/GetOrganizationsCountEndpoint.ts +3 -2
  23. package/src/endpoints/admin/organizations/GetOrganizationsEndpoint.ts +7 -5
  24. package/src/endpoints/admin/organizations/PatchOrganizationsEndpoint.ts +12 -10
  25. package/src/endpoints/admin/registrations/ChargeRegistrationsEndpoint.ts +4 -3
  26. package/src/endpoints/auth/CreateAdminEndpoint.ts +8 -6
  27. package/src/endpoints/auth/CreateTokenEndpoint.ts +14 -12
  28. package/src/endpoints/auth/DeleteTokenEndpoint.ts +2 -1
  29. package/src/endpoints/auth/DeleteUserEndpoint.ts +2 -1
  30. package/src/endpoints/auth/ForgotPasswordEndpoint.ts +5 -4
  31. package/src/endpoints/auth/GetOtherUserEndpoint.ts +3 -2
  32. package/src/endpoints/auth/GetUserEndpoint.ts +3 -2
  33. package/src/endpoints/auth/OpenIDConnectAuthTokenEndpoint.ts +2 -1
  34. package/src/endpoints/auth/OpenIDConnectCallbackEndpoint.ts +4 -2
  35. package/src/endpoints/auth/OpenIDConnectStartEndpoint.ts +3 -2
  36. package/src/endpoints/auth/PatchUserEndpoint.ts +15 -12
  37. package/src/endpoints/auth/PollEmailVerificationEndpoint.ts +3 -2
  38. package/src/endpoints/auth/RetryEmailVerificationEndpoint.ts +3 -2
  39. package/src/endpoints/auth/SignupEndpoint.ts +5 -4
  40. package/src/endpoints/auth/VerifyEmailEndpoint.ts +6 -5
  41. package/src/endpoints/frontend/FrontendEnvironmentEndpoint.ts +3 -2
  42. package/src/endpoints/global/addresses/SearchRegionsEndpoint.ts +8 -5
  43. package/src/endpoints/global/addresses/ValidateAddressEndpoint.ts +5 -3
  44. package/src/endpoints/global/audit-logs/GetAuditLogsEndpoint.ts +8 -5
  45. package/src/endpoints/global/billing/ActivatePackagesEndpoint.ts +9 -7
  46. package/src/endpoints/global/billing/DeactivatePackageEndpoint.ts +4 -3
  47. package/src/endpoints/global/caddy/CheckDomainCertEndpoint.ts +4 -2
  48. package/src/endpoints/global/email/CreateEmailEndpoint.ts +9 -7
  49. package/src/endpoints/global/email/GetAdminEmailsEndpoint.test.ts +2 -1
  50. package/src/endpoints/global/email/GetAdminEmailsEndpoint.ts +22 -19
  51. package/src/endpoints/global/email/GetEmailAddressEndpoint.ts +6 -4
  52. package/src/endpoints/global/email/GetEmailEndpoint.ts +4 -3
  53. package/src/endpoints/global/email/GetUserEmailsEndpoint.test.ts +3 -2
  54. package/src/endpoints/global/email/GetUserEmailsEndpoint.ts +7 -4
  55. package/src/endpoints/global/email/ManageEmailAddressEndpoint.ts +7 -5
  56. package/src/endpoints/global/email/PatchEmailEndpoint.test.ts +11 -11
  57. package/src/endpoints/global/email/PatchEmailEndpoint.ts +14 -11
  58. package/src/endpoints/global/email-recipients/GetEmailRecipientsCountEndpoint.ts +3 -2
  59. package/src/endpoints/global/email-recipients/GetEmailRecipientsEndpoint.test.ts +2 -1
  60. package/src/endpoints/global/email-recipients/GetEmailRecipientsEndpoint.ts +8 -5
  61. package/src/endpoints/global/email-recipients/RetryEmailRecipientEndpoint.ts +7 -5
  62. package/src/endpoints/global/email-recipients/helpers/validateEmailRecipientFilter.ts +4 -3
  63. package/src/endpoints/global/events/GetEventNotificationsCountEndpoint.ts +3 -2
  64. package/src/endpoints/global/events/GetEventNotificationsEndpoint.ts +9 -6
  65. package/src/endpoints/global/events/GetEventsEndpoint.ts +7 -4
  66. package/src/endpoints/global/events/PatchEventNotificationsEndpoint.test.ts +4 -2
  67. package/src/endpoints/global/events/PatchEventNotificationsEndpoint.ts +17 -15
  68. package/src/endpoints/global/events/PatchEventsEndpoint.test.ts +4 -2
  69. package/src/endpoints/global/events/PatchEventsEndpoint.ts +28 -26
  70. package/src/endpoints/global/files/ExportToExcelEndpoint.ts +8 -5
  71. package/src/endpoints/global/files/GetFileCache.ts +5 -3
  72. package/src/endpoints/global/files/UploadFile.ts +10 -4
  73. package/src/endpoints/global/files/UploadImage.ts +4 -2
  74. package/src/endpoints/global/groups/GetGroupsEndpoint.test.ts +4 -2
  75. package/src/endpoints/global/groups/GetGroupsEndpoint.ts +8 -5
  76. package/src/endpoints/global/members/GetMemberFamilyEndpoint.ts +7 -5
  77. package/src/endpoints/global/members/GetMembersCountEndpoint.ts +3 -2
  78. package/src/endpoints/global/members/GetMembersEndpoint.test.ts +4 -2
  79. package/src/endpoints/global/members/GetMembersEndpoint.ts +10 -8
  80. package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.test.ts +257 -6
  81. package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.ts +162 -107
  82. package/src/endpoints/global/members/helpers/validateGroupFilter.ts +4 -3
  83. package/src/endpoints/global/members/shouldCheckIfMemberIsDuplicate.ts +3 -2
  84. package/src/endpoints/global/organizations/CheckRegisterCodeEndpoint.ts +3 -2
  85. package/src/endpoints/global/organizations/CreateOrganizationEndpoint.test.ts +3 -2
  86. package/src/endpoints/global/organizations/CreateOrganizationEndpoint.ts +8 -7
  87. package/src/endpoints/global/organizations/GetOrganizationFromDomainEndpoint.ts +5 -3
  88. package/src/endpoints/global/organizations/GetOrganizationFromUriEndpoint.ts +5 -3
  89. package/src/endpoints/global/organizations/SearchOrganizationEndpoint.ts +8 -5
  90. package/src/endpoints/global/payments/StripeWebhookEndpoint.ts +4 -2
  91. package/src/endpoints/global/platform/GetPlatformAdminsEndpoint.ts +2 -1
  92. package/src/endpoints/global/platform/GetPlatformEndpoint.ts +3 -2
  93. package/src/endpoints/global/platform/PatchPlatformEnpoint.test.ts +3 -2
  94. package/src/endpoints/global/platform/PatchPlatformEnpoint.ts +7 -4
  95. package/src/endpoints/global/platform-memberships/GetPlatformMembershipsCountEndpoint.ts +47 -0
  96. package/src/endpoints/global/platform-memberships/GetPlatformMembershipsEndpoint.ts +206 -0
  97. package/src/endpoints/global/registration/GetRegistrationsCountEndpoint.ts +3 -2
  98. package/src/endpoints/global/registration/GetRegistrationsEndpoint.test.ts +2 -1
  99. package/src/endpoints/global/registration/GetRegistrationsEndpoint.ts +10 -7
  100. package/src/endpoints/global/registration/GetUserDetailedPayableBalanceEndpoint.ts +4 -2
  101. package/src/endpoints/global/registration/GetUserDocumentsEndpoint.ts +4 -2
  102. package/src/endpoints/global/registration/GetUserMembersEndpoint.ts +3 -2
  103. package/src/endpoints/global/registration/GetUserPayableBalanceEndpoint.ts +2 -1
  104. package/src/endpoints/global/registration/PatchUserMembersEndpoint.test.ts +5 -3
  105. package/src/endpoints/global/registration/PatchUserMembersEndpoint.ts +13 -9
  106. package/src/endpoints/global/registration/RegisterMembersEndpoint.test.ts +50 -49
  107. package/src/endpoints/global/registration/RegisterMembersEndpoint.ts +25 -22
  108. package/src/endpoints/global/registration-periods/GetRegistrationPeriodsEndpoint.ts +8 -5
  109. package/src/endpoints/global/registration-periods/PatchRegistrationPeriodsEndpoint.ts +9 -7
  110. package/src/endpoints/global/sso/GetSSOEndpoint.ts +4 -2
  111. package/src/endpoints/global/sso/SetSSOEndpoint.ts +3 -2
  112. package/src/endpoints/global/webshops/GetWebshopFromDomainEndpoint.ts +4 -2
  113. package/src/endpoints/global/webshops/GetWebshopsCountEndpoint.ts +43 -0
  114. package/src/endpoints/global/webshops/GetWebshopsEndpoint.test.ts +808 -0
  115. package/src/endpoints/global/webshops/GetWebshopsEndpoint.ts +221 -0
  116. package/src/endpoints/organization/dashboard/balance-items/GetBalanceItemEndpoint.ts +4 -3
  117. package/src/endpoints/organization/dashboard/balance-items/GetBalanceItemsCountEndpoint.ts +3 -2
  118. package/src/endpoints/organization/dashboard/balance-items/GetBalanceItemsEndpoint.ts +6 -4
  119. package/src/endpoints/organization/dashboard/balance-items/PatchBalanceItemsEndpoint.ts +15 -13
  120. package/src/endpoints/organization/dashboard/billing/GetOrganizationDetailedPayableBalanceEndpoint.ts +4 -2
  121. package/src/endpoints/organization/dashboard/billing/GetOrganizationPayableBalanceEndpoint.ts +4 -2
  122. package/src/endpoints/organization/dashboard/billing/GetPackagesEndpoint.ts +2 -1
  123. package/src/endpoints/organization/dashboard/documents/GetDocumentTemplateXML.ts +3 -2
  124. package/src/endpoints/organization/dashboard/documents/GetDocumentTemplatesCountEndpoint.ts +3 -2
  125. package/src/endpoints/organization/dashboard/documents/GetDocumentTemplatesEndpoint.ts +7 -4
  126. package/src/endpoints/organization/dashboard/documents/GetDocumentsCountEndpoint.ts +3 -2
  127. package/src/endpoints/organization/dashboard/documents/GetDocumentsEndpoint.ts +7 -4
  128. package/src/endpoints/organization/dashboard/documents/PatchDocumentEndpoint.ts +9 -7
  129. package/src/endpoints/organization/dashboard/documents/PatchDocumentTemplatesEndpoint.test.ts +4 -2
  130. package/src/endpoints/organization/dashboard/documents/PatchDocumentTemplatesEndpoint.ts +7 -5
  131. package/src/endpoints/organization/dashboard/email/CheckEmailBouncesEndpoint.ts +3 -2
  132. package/src/endpoints/organization/dashboard/email-templates/GetEmailTemplatesEndpoint.test.ts +36 -1
  133. package/src/endpoints/organization/dashboard/email-templates/GetEmailTemplatesEndpoint.ts +13 -4
  134. package/src/endpoints/organization/dashboard/email-templates/PatchEmailTemplatesEndpoint.test.ts +4 -2
  135. package/src/endpoints/organization/dashboard/email-templates/PatchEmailTemplatesEndpoint.ts +7 -5
  136. package/src/endpoints/organization/dashboard/invoices/GetInvoicesCountEndpoint.ts +3 -2
  137. package/src/endpoints/organization/dashboard/invoices/GetInvoicesEndpoint.ts +6 -4
  138. package/src/endpoints/organization/dashboard/invoices/PatchInvoicesEndpoint.ts +5 -3
  139. package/src/endpoints/organization/dashboard/mollie/CheckMollieEndpoint.ts +4 -2
  140. package/src/endpoints/organization/dashboard/mollie/ConnectMollieEndpoint.ts +6 -3
  141. package/src/endpoints/organization/dashboard/mollie/DisconnectMollieEndpoint.ts +4 -2
  142. package/src/endpoints/organization/dashboard/mollie/GetMollieDashboardEndpoint.ts +2 -1
  143. package/src/endpoints/organization/dashboard/nolt/CreateNoltTokenEndpoint.ts +2 -1
  144. package/src/endpoints/organization/dashboard/organization/GetOrganizationArchivedGroups.ts +4 -2
  145. package/src/endpoints/organization/dashboard/organization/GetOrganizationDeletedGroups.ts +3 -2
  146. package/src/endpoints/organization/dashboard/organization/GetUitpasClientIdEndpoint.ts +2 -1
  147. package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.test.ts +5 -3
  148. package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.ts +22 -19
  149. package/src/endpoints/organization/dashboard/organization/SearchUitpasOrganizersEndpoint.ts +5 -3
  150. package/src/endpoints/organization/dashboard/organization/SetOrganizationDomainEndpoint.ts +11 -9
  151. package/src/endpoints/organization/dashboard/organization/SetUitpasClientCredentialsEndpoint.ts +8 -7
  152. package/src/endpoints/organization/dashboard/payments/GetMemberBalanceEndpoint.ts +2 -1
  153. package/src/endpoints/organization/dashboard/payments/GetPaymentsCountEndpoint.ts +3 -2
  154. package/src/endpoints/organization/dashboard/payments/GetPaymentsEndpoint.ts +7 -5
  155. package/src/endpoints/organization/dashboard/payments/PatchPaymentsEndpoint.ts +18 -16
  156. package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalanceEndpoint.ts +2 -1
  157. package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalancesCountEndpoint.ts +3 -2
  158. package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalancesEndpoint.ts +5 -3
  159. package/src/endpoints/organization/dashboard/registration-periods/GetOrganizationRegistrationPeriodsEndpoint.test.ts +2 -1
  160. package/src/endpoints/organization/dashboard/registration-periods/GetOrganizationRegistrationPeriodsEndpoint.ts +8 -5
  161. package/src/endpoints/organization/dashboard/registration-periods/MoveRegistrationPeriods.test.ts +4 -2
  162. package/src/endpoints/organization/dashboard/registration-periods/PatchOrganizationRegistrationPeriodsEndpoint.test.ts +4 -2
  163. package/src/endpoints/organization/dashboard/registration-periods/PatchOrganizationRegistrationPeriodsEndpoint.ts +32 -29
  164. package/src/endpoints/organization/dashboard/registration-periods/SetupStepReviewEndpoint.ts +6 -3
  165. package/src/endpoints/organization/dashboard/stripe/ConnectStripeEndpoint.ts +3 -2
  166. package/src/endpoints/organization/dashboard/stripe/DeleteStripeAccountEndpoint.ts +3 -2
  167. package/src/endpoints/organization/dashboard/stripe/GetStripeAccountLinkEndpoint.ts +5 -3
  168. package/src/endpoints/organization/dashboard/stripe/GetStripeAccountsEndpoint.ts +2 -1
  169. package/src/endpoints/organization/dashboard/stripe/GetStripeLoginLinkEndpoint.ts +5 -3
  170. package/src/endpoints/organization/dashboard/stripe/UpdateStripeAccountEndpoint.ts +3 -2
  171. package/src/endpoints/organization/dashboard/users/CreateApiUserEndpoint.ts +4 -3
  172. package/src/endpoints/organization/dashboard/users/DeleteUserEndpoint.ts +4 -3
  173. package/src/endpoints/organization/dashboard/users/GetApiUsersEndpoint.ts +3 -2
  174. package/src/endpoints/organization/dashboard/users/GetOrganizationAdminsEndpoint.ts +2 -1
  175. package/src/endpoints/organization/dashboard/users/PatchApiUserEndpoint.ts +6 -4
  176. package/src/endpoints/organization/dashboard/webshops/CreateWebshopEndpoint.ts +7 -6
  177. package/src/endpoints/organization/dashboard/webshops/DeleteWebshopEndpoint.ts +3 -2
  178. package/src/endpoints/organization/dashboard/webshops/GetDiscountCodesEndpoint.ts +4 -2
  179. package/src/endpoints/organization/dashboard/webshops/GetWebshopOrdersCountEndpoint.ts +3 -2
  180. package/src/endpoints/organization/dashboard/webshops/GetWebshopOrdersEndpoint.ts +7 -4
  181. package/src/endpoints/organization/dashboard/webshops/{GetWebshopTicketsCountEndpoint → GetWebshopTicketsCountEndpoint.ts} +7 -7
  182. package/src/endpoints/organization/dashboard/webshops/GetWebshopTicketsEndpoint.ts +9 -6
  183. package/src/endpoints/organization/dashboard/webshops/GetWebshopUriAvailabilityEndpoint.ts +4 -2
  184. package/src/endpoints/organization/dashboard/webshops/PatchDiscountCodesEndpoint.ts +6 -4
  185. package/src/endpoints/organization/dashboard/webshops/PatchWebshopEndpoint.ts +13 -12
  186. package/src/endpoints/organization/dashboard/webshops/PatchWebshopOrdersEndpoint.ts +4 -2
  187. package/src/endpoints/organization/dashboard/webshops/PatchWebshopTicketsEndpoint.ts +5 -3
  188. package/src/endpoints/organization/dashboard/webshops/SearchUitpasEventsEndpoint.ts +6 -4
  189. package/src/endpoints/organization/dashboard/webshops/VerifyWebshopDomainEndpoint.ts +2 -1
  190. package/src/endpoints/organization/shared/ExchangePaymentEndpoint.ts +6 -4
  191. package/src/endpoints/organization/shared/GetDocumentHtml.ts +4 -3
  192. package/src/endpoints/organization/shared/GetPaymentEndpoint.ts +4 -3
  193. package/src/endpoints/organization/shared/GetUitpasNumberDetailsEndpoint.ts +3 -2
  194. package/src/endpoints/organization/shared/auth/GetOrganizationEndpoint.ts +3 -2
  195. package/src/endpoints/organization/webshops/CheckWebshopDiscountCodesEndpoint.ts +4 -3
  196. package/src/endpoints/organization/webshops/GetOrderByPaymentEndpoint.ts +5 -4
  197. package/src/endpoints/organization/webshops/GetOrderEndpoint.ts +4 -3
  198. package/src/endpoints/organization/webshops/GetTicketsEndpoint.ts +7 -5
  199. package/src/endpoints/organization/webshops/GetWebshopEndpoint.ts +4 -3
  200. package/src/endpoints/organization/webshops/PlaceOrderEndpoint.test.ts +7 -3
  201. package/src/endpoints/organization/webshops/PlaceOrderEndpoint.ts +11 -10
  202. package/src/endpoints/organization/webshops/RetrieveUitpasSocialTariffPriceEndpoint.ts +5 -4
  203. package/src/endpoints/system/HealthEndpoint.test.ts +44 -0
  204. package/src/endpoints/system/HealthEndpoint.ts +14 -6
  205. package/src/excel-loaders/balance-items.ts +19 -17
  206. package/src/excel-loaders/event-notifications.ts +15 -13
  207. package/src/excel-loaders/index.ts +1 -0
  208. package/src/excel-loaders/members.ts +45 -43
  209. package/src/excel-loaders/organizations.ts +26 -25
  210. package/src/excel-loaders/payments.ts +44 -42
  211. package/src/excel-loaders/platform-memberships.ts +202 -0
  212. package/src/excel-loaders/receivable-balances.ts +25 -23
  213. package/src/excel-loaders/registrations.ts +30 -28
  214. package/src/helpers/AddressValidator.test.ts +2 -1
  215. package/src/helpers/AddressValidator.ts +13 -10
  216. package/src/helpers/AdminPermissionChecker.ts +193 -95
  217. package/src/helpers/AuthenticatedStructures.ts +13 -11
  218. package/src/helpers/BuckarooHelper.ts +3 -2
  219. package/src/helpers/Context.ts +8 -6
  220. package/src/helpers/CookieHelper.ts +2 -2
  221. package/src/helpers/FileCache.ts +9 -9
  222. package/src/helpers/ForwardHandler.ts +3 -2
  223. package/src/helpers/GlobalHelper.ts +2 -0
  224. package/src/helpers/GroupBuilder.ts +2 -1
  225. package/src/helpers/GroupedThrottledQueue.test.ts +19 -19
  226. package/src/helpers/LimitedFilteredRequestHelper.ts +1 -1
  227. package/src/helpers/MemberCharger.ts +2 -1
  228. package/src/helpers/MemberUserSyncer.ts +6 -3
  229. package/src/helpers/MembershipCharger.ts +2 -2
  230. package/src/helpers/OrganizationCharger.ts +2 -1
  231. package/src/helpers/PeriodHelper.ts +2 -1
  232. package/src/helpers/SQLTranslatedString.ts +3 -2
  233. package/src/helpers/ServiceFeeHelper.ts +1 -1
  234. package/src/helpers/SetupStepUpdater.ts +6 -5
  235. package/src/helpers/StripeHelper.ts +9 -8
  236. package/src/helpers/TagHelper.test.ts +5 -5
  237. package/src/helpers/TagHelper.ts +2 -1
  238. package/src/helpers/TemporaryMemberAccess.ts +2 -1
  239. package/src/helpers/ThrottledQueue.test.ts +20 -20
  240. package/src/helpers/UitpasTokenRepository.ts +7 -7
  241. package/src/helpers/ViesHelper.ts +5 -4
  242. package/src/helpers/XlsxTransformerColumnHelper.ts +21 -19
  243. package/src/helpers/email-html-helpers.ts +13 -12
  244. package/src/helpers/fetchToAsyncIterator.ts +1 -1
  245. package/src/helpers/outstandingBalanceJoin.ts +2 -1
  246. package/src/helpers/updateMemberDetailsUitpasNumber.ts +5 -4
  247. package/src/middleware/ContextMiddleware.ts +1 -1
  248. package/src/migrate.ts +21 -4
  249. package/src/seeds/0000000003-default-email-templates.ts +1 -1
  250. package/src/seeds/0000000004-single-organization.ts +2 -1
  251. package/src/seeds/1752848561-groups-registration-periods.ts +3 -2
  252. package/src/seeds/1754560914-groups-prices.test.ts +2 -1
  253. package/src/seeds/1754560914-groups-prices.ts +2 -1
  254. package/src/seeds/1755790070-fill-email-recipient-errors.ts +6 -6
  255. package/src/seeds/1755876819-remove-duplicate-members.ts +2 -1
  256. package/src/seeds/1765896674-document-update-year.test.ts +2 -1
  257. package/src/seeds/1773754928-force-save-members.ts +15 -0
  258. package/src/services/AuditLogService.ts +3 -2
  259. package/src/services/BalanceItemPaymentService.ts +2 -2
  260. package/src/services/BalanceItemService.ts +2 -1
  261. package/src/services/BootChecksService.test.ts +33 -0
  262. package/src/services/BootChecksService.ts +21 -0
  263. package/src/services/DatabaseCollationService.test.ts +18 -0
  264. package/src/services/DatabaseCollationService.ts +81 -0
  265. package/src/services/DocumentService.ts +1 -1
  266. package/src/services/EventNotificationService.ts +5 -4
  267. package/src/services/FileSignService.ts +2 -2
  268. package/src/services/InvoiceService.ts +3 -3
  269. package/src/services/MemberNumberService.ts +6 -4
  270. package/src/services/MemberRecordStore.ts +28 -19
  271. package/src/services/PaymentReallocationService.test.ts +2 -1
  272. package/src/services/PaymentReallocationService.ts +2 -1
  273. package/src/services/PaymentService.ts +28 -26
  274. package/src/services/RegistrationService.ts +65 -3
  275. package/src/services/SSOService.ts +13 -9
  276. package/src/services/STPackageService.ts +7 -5
  277. package/src/services/StartupHealthService.ts +15 -0
  278. package/src/services/uitpas/PassholderEndpoints.ts +2 -2
  279. package/src/services/uitpas/UitpasService.ts +11 -8
  280. package/src/services/uitpas/cancelTicketSales.ts +1 -1
  281. package/src/services/uitpas/checkPermissionsFor.ts +9 -9
  282. package/src/services/uitpas/getSocialTariffForEvent.ts +4 -4
  283. package/src/services/uitpas/getSocialTariffForUitpasNumbers.ts +5 -5
  284. package/src/services/uitpas/handleUitpasResponse.ts +1 -1
  285. package/src/services/uitpas/registerTicketSales.ts +4 -4
  286. package/src/services/uitpas/searchUitpasEvents.ts +3 -3
  287. package/src/services/uitpas/searchUitpasOrganizers.ts +3 -3
  288. package/src/sql-filters/audit-logs.ts +2 -1
  289. package/src/sql-filters/balance-item-payments.ts +2 -1
  290. package/src/sql-filters/balance-items.ts +2 -1
  291. package/src/sql-filters/base-registration-filter-compilers.ts +6 -4
  292. package/src/sql-filters/document-templates.ts +2 -1
  293. package/src/sql-filters/documents.ts +2 -1
  294. package/src/sql-filters/email-recipients.ts +2 -1
  295. package/src/sql-filters/emails.ts +2 -1
  296. package/src/sql-filters/event-notifications.ts +2 -1
  297. package/src/sql-filters/events.ts +2 -1
  298. package/src/sql-filters/groups.ts +2 -1
  299. package/src/sql-filters/invoiced-balance-items.ts +2 -1
  300. package/src/sql-filters/invoices.ts +2 -1
  301. package/src/sql-filters/member-responsibility-records.ts +2 -1
  302. package/src/sql-filters/members.ts +8 -7
  303. package/src/sql-filters/orders.ts +3 -2
  304. package/src/sql-filters/organization-registration-periods.ts +2 -1
  305. package/src/sql-filters/organizations.ts +2 -1
  306. package/src/sql-filters/payments.ts +2 -1
  307. package/src/sql-filters/platform-memberships.ts +67 -0
  308. package/src/sql-filters/receivable-balances.ts +2 -1
  309. package/src/sql-filters/registration-periods.ts +2 -1
  310. package/src/sql-filters/registrations.ts +2 -1
  311. package/src/sql-filters/tickets.ts +2 -1
  312. package/src/sql-filters/users.ts +2 -1
  313. package/src/sql-filters/webshops.ts +38 -0
  314. package/src/sql-sorters/audit-logs.ts +3 -2
  315. package/src/sql-sorters/balance-items.ts +3 -2
  316. package/src/sql-sorters/document-templates.ts +3 -2
  317. package/src/sql-sorters/documents.ts +3 -2
  318. package/src/sql-sorters/email-recipients.ts +3 -2
  319. package/src/sql-sorters/emails.ts +3 -2
  320. package/src/sql-sorters/event-notifications.ts +3 -2
  321. package/src/sql-sorters/events.ts +3 -2
  322. package/src/sql-sorters/groups.ts +3 -2
  323. package/src/sql-sorters/invoices.ts +3 -2
  324. package/src/sql-sorters/members.ts +3 -2
  325. package/src/sql-sorters/orders.ts +3 -2
  326. package/src/sql-sorters/organization-registration-periods.ts +3 -2
  327. package/src/sql-sorters/organizations.ts +3 -2
  328. package/src/sql-sorters/payments.ts +3 -2
  329. package/src/sql-sorters/platform-memberships.ts +40 -0
  330. package/src/sql-sorters/receivable-balances.ts +3 -2
  331. package/src/sql-sorters/registration-periods.ts +3 -2
  332. package/src/sql-sorters/registrations.ts +3 -2
  333. package/src/sql-sorters/tickets.ts +3 -2
  334. package/src/sql-sorters/webshops.ts +40 -0
  335. package/tests/actions/patchOrganizationMember.ts +5 -4
  336. package/tests/actions/patchPaymentStatus.ts +2 -2
  337. package/tests/actions/patchUserMember.ts +6 -4
  338. package/tests/e2e/api-rate-limits.test.ts +4 -5
  339. package/tests/e2e/bundle-discounts.test.ts +3 -2
  340. package/tests/e2e/charge-members.test.ts +7 -5
  341. package/tests/e2e/documents.test.ts +3 -2
  342. package/tests/e2e/private-files.test.ts +11 -13
  343. package/tests/e2e/register.test.ts +6 -5
  344. package/tests/e2e/stock.test.ts +6 -8
  345. package/tests/e2e/tickets.test.ts +4 -2
  346. package/tests/helpers/StripeMocker.ts +3 -3
  347. package/tests/init/initAdmin.ts +4 -2
  348. package/tests/init/initBundleDiscount.ts +3 -2
  349. package/tests/init/initPayconiq.ts +1 -1
  350. package/tests/init/initPermissionRole.ts +4 -2
  351. package/tests/init/initPlatformRecordCategory.ts +1 -1
  352. package/tests/init/initStripe.ts +1 -1
  353. package/tests/vitest.global.setup.ts +26 -0
  354. package/tests/{jest.setup.ts → vitest.setup.ts} +4 -3
  355. package/tsconfig.build.json +17 -0
  356. package/tsconfig.json +10 -41
  357. package/tsconfig.test.json +17 -0
  358. package/vitest.config.js +13 -0
  359. package/eslint.config.mjs +0 -5
  360. package/jest.config.cjs +0 -27
  361. package/tests/jest.global.setup.ts +0 -33
  362. package/tests/toMatchMap.ts +0 -68
@@ -21,7 +21,7 @@ function assertIsUitpasTokenResponse(json: unknown): asserts json is UitpasToken
21
21
  throw new SimpleError({
22
22
  code: 'invalid_response_fetching_uitpas_token',
23
23
  message: `Invalid response when fetching UiTPAS token`,
24
- human: $t(`8f217db0-c672-46f0-a8f7-6eba6f080947`),
24
+ human: $t(`%18A`),
25
25
  });
26
26
  }
27
27
  }
@@ -79,7 +79,7 @@ export class UitpasTokenRepository {
79
79
  throw new SimpleError({
80
80
  code: 'uitpas_api_not_configured_for_platform',
81
81
  message: 'UiTPAS api is not configured for the platform',
82
- human: $t('71a8218b-c58e-4e95-9626-551b80eb8367'),
82
+ human: $t('%1BI'),
83
83
  });
84
84
  }
85
85
  const model = new UitpasClientCredential();
@@ -118,7 +118,7 @@ export class UitpasTokenRepository {
118
118
  throw new SimpleError({
119
119
  code: 'uitpas_unreachable_fetching_uitpas_token',
120
120
  message: `Network issue when fetching UiTPAS token`,
121
- human: $t(`6483c4c6-2fe8-456d-9110-f565952b6822`),
121
+ human: $t(`%18B`),
122
122
  });
123
123
  });
124
124
  if (!response.ok) {
@@ -128,7 +128,7 @@ export class UitpasTokenRepository {
128
128
  statusCode: this.uitpasClientCredential.organizationId === null ? 500 : 400, // Internal, non visible error in case it is a built in credential
129
129
  code: 'invalid_uitpas_client_credentials',
130
130
  message: `Invalid UiTPAS client credentials`,
131
- human: $t(`1086bb24-5df4-4faf-9dc0-ab5a955b0d8f`),
131
+ human: $t(`%1BK`),
132
132
  });
133
133
  }
134
134
  console.error(`Unsuccessful response when fetching UiTPAS token for organization with id ${this.uitpasClientCredential.organizationId}:`, response.statusText);
@@ -136,7 +136,7 @@ export class UitpasTokenRepository {
136
136
  statusCode: this.uitpasClientCredential.organizationId === null ? 500 : 400, // Internal, non visible error in case it is a built in credential
137
137
  code: 'unsuccessful_response_fetching_uitpas_token',
138
138
  message: `Unsuccesful response when fetching UiTPAS token`,
139
- human: $t(`dd9b30ca-860f-47aa-8cb1-527fd156d9ca`),
139
+ human: $t(`%18C`),
140
140
  });
141
141
  }
142
142
  const json: unknown = await response.json().catch(() => {
@@ -145,7 +145,7 @@ export class UitpasTokenRepository {
145
145
  statusCode: this.uitpasClientCredential.organizationId === null ? 500 : 400, // Internal, non visible error in case it is a built in credential
146
146
  code: 'invalid_json_fetching_uitpas_token',
147
147
  message: `Invalid json when fetching UiTPAS token`,
148
- human: $t(`8f217db0-c672-46f0-a8f7-6eba6f080947`),
148
+ human: $t(`%18A`),
149
149
  });
150
150
  });
151
151
  assertIsUitpasTokenResponse(json);
@@ -200,7 +200,7 @@ export class UitpasTokenRepository {
200
200
  throw new SimpleError({
201
201
  code: 'uitpas_api_not_configured_for_this_organization',
202
202
  message: `UiTPAS api not configured for organization with id ${organizationId}`,
203
- human: $t('6b333cb4-21fd-42be-b0c9-6d899f2fd348'),
203
+ human: $t('%1BJ'),
204
204
  });
205
205
  }
206
206
  repo = UitpasTokenRepository.setRepoInMemory(organizationId, new UitpasTokenRepository(model)); // store in memory
@@ -1,6 +1,7 @@
1
- import { AutoEncoderPatchType } from '@simonbackx/simple-encoding';
1
+ import type { AutoEncoderPatchType } from '@simonbackx/simple-encoding';
2
2
  import { isSimpleError, isSimpleErrors, SimpleError } from '@simonbackx/simple-errors';
3
- import { Company, Country } from '@stamhoofd/structures';
3
+ import type { Company } from '@stamhoofd/structures';
4
+ import { Country } from '@stamhoofd/types/Country';
4
5
  import axios from 'axios';
5
6
  import * as jsvat from 'jsvat-next'; // has no default export, so we need the wildcard
6
7
 
@@ -37,7 +38,7 @@ export class ViesHelperStatic {
37
38
  throw new SimpleError({
38
39
  code: 'invalid_company_name',
39
40
  message: 'Company name is too short',
40
- human: $t('31bd2a76-8b01-4658-a18d-b63795f4be63'),
41
+ human: $t('%1LF'),
41
42
  field: 'companyName',
42
43
  });
43
44
  }
@@ -135,7 +136,7 @@ export class ViesHelperStatic {
135
136
  const formatted = result.value ?? vatNumber;
136
137
 
137
138
  try {
138
- const cleaned = formatted.substring(2).replace(/(\.-\s)+/g, '');
139
+ const cleaned = formatted.substring(2).replace(/(?:\.-\s)+/g, '');
139
140
  const response = await this.request('POST', 'https://ec.europa.eu/taxation_customs/vies/rest-api/check-vat-number', {
140
141
  countryCode: country,
141
142
  vatNumber: cleaned,
@@ -1,14 +1,16 @@
1
- import { isXlsxTransformerConcreteColumn, XlsxTransformerColumn, XlsxTransformerConcreteColumn } from '@stamhoofd/excel-writer';
2
- import { Address, CountryHelper, Parent, ParentTypeHelper, PlatformMember, RecordAnswer, RecordCategory, RecordSettings, RecordType } from '@stamhoofd/structures';
1
+ import type { XlsxTransformerColumn, XlsxTransformerConcreteColumn } from '@stamhoofd/excel-writer';
2
+ import { isXlsxTransformerConcreteColumn } from '@stamhoofd/excel-writer';
3
+ import type { Address, Parent, PlatformMember, RecordAnswer, RecordSettings} from '@stamhoofd/structures';
4
+ import { CountryHelper, ParentTypeHelper, RecordCategory, RecordType } from '@stamhoofd/structures';
3
5
 
4
6
  export class XlsxTransformerColumnHelper {
5
7
  static formatBoolean(value: boolean | undefined | null): string {
6
8
  if (value === true) {
7
- return $t(`1ae8cbc7-9ef5-43db-b9a3-0117dfa43be1`);
9
+ return $t(`%wo`);
8
10
  }
9
11
 
10
12
  if (value === false) {
11
- return $t(`b8b730fb-f1a3-4c13-8ec4-0aebe08a1449`);
13
+ return $t(`%18s`);
12
14
  }
13
15
 
14
16
  return '';
@@ -48,7 +50,7 @@ export class XlsxTransformerColumnHelper {
48
50
  return [
49
51
  {
50
52
  id: getId('type'),
51
- name: getName($t(`f97ad8c1-31d2-4b61-9e09-3be86eaeba08`)),
53
+ name: getName($t(`%1B`)),
52
54
  width: 20,
53
55
  getValue: (member: PlatformMember) => {
54
56
  const parent = getParent(member);
@@ -60,7 +62,7 @@ export class XlsxTransformerColumnHelper {
60
62
  },
61
63
  {
62
64
  id: getId('firstName'),
63
- name: getName($t(`efca0579-0543-4636-a996-384bc9f0527e`)),
65
+ name: getName($t(`%1MT`)),
64
66
  width: 20,
65
67
  getValue: (member: PlatformMember) => ({
66
68
  value: getParent(member)?.firstName ?? '',
@@ -68,7 +70,7 @@ export class XlsxTransformerColumnHelper {
68
70
  },
69
71
  {
70
72
  id: getId('lastName'),
71
- name: getName($t(`4a5e438e-08a1-411e-9b66-410eea7ded73`)),
73
+ name: getName($t(`%1MU`)),
72
74
  width: 20,
73
75
  getValue: (member: PlatformMember) => ({
74
76
  value: getParent(member)?.lastName ?? '',
@@ -76,7 +78,7 @@ export class XlsxTransformerColumnHelper {
76
78
  },
77
79
  {
78
80
  id: getId('phone'),
79
- name: getName($t(`856aaa1c-bc62-4e45-9ae5-4c7e7dca23ab`)),
81
+ name: getName($t(`%wD`)),
80
82
  width: 20,
81
83
  getValue: (member: PlatformMember) => ({
82
84
  value: getParent(member)?.phone ?? '',
@@ -84,7 +86,7 @@ export class XlsxTransformerColumnHelper {
84
86
  },
85
87
  {
86
88
  id: getId('email'),
87
- name: getName($t(`82f4b6ed-afee-4655-9f07-22802e0e7ad9`)),
89
+ name: getName($t(`%1FK`)),
88
90
  width: 20,
89
91
  getValue: (member: PlatformMember) => ({
90
92
  value: getParent(member)?.email ?? '',
@@ -92,7 +94,7 @@ export class XlsxTransformerColumnHelper {
92
94
  },
93
95
  {
94
96
  id: getId('nationalRegisterNumber'),
95
- name: getName($t(`00881b27-7501-4c56-98de-55618be2bf11`)),
97
+ name: getName($t(`%wK`)),
96
98
  width: 20,
97
99
  getValue: (member: PlatformMember) => ({
98
100
  value: getParent(member)?.nationalRegisterNumber?.toString() ?? '',
@@ -115,7 +117,7 @@ export class XlsxTransformerColumnHelper {
115
117
  {
116
118
  id: getId('street'),
117
119
  name: `Straat`,
118
- defaultCategory: $t(`2f10996e-ea97-4345-b997-c93198c7d67f`), // Ignore this name
120
+ defaultCategory: $t(`%Cn`), // Ignore this name
119
121
  width: 40,
120
122
  getValue: (object: T) => {
121
123
  const address = getAddress(object);
@@ -126,8 +128,8 @@ export class XlsxTransformerColumnHelper {
126
128
  },
127
129
  {
128
130
  id: getId('number'),
129
- name: $t(`cc1cf4a7-0bd2-4fa7-8ff2-0a12470a738d`),
130
- defaultCategory: $t(`2f10996e-ea97-4345-b997-c93198c7d67f`), // Ignore this name
131
+ name: $t(`%cH`),
132
+ defaultCategory: $t(`%Cn`), // Ignore this name
131
133
  width: 20,
132
134
  getValue: (object: T) => {
133
135
  const address = getAddress(object);
@@ -138,8 +140,8 @@ export class XlsxTransformerColumnHelper {
138
140
  },
139
141
  {
140
142
  id: getId('postalCode'),
141
- name: $t(`dafc7b04-dfb2-4dbc-8bcf-f7e9c6356442`),
142
- defaultCategory: $t(`2f10996e-ea97-4345-b997-c93198c7d67f`), // Ignore this name
143
+ name: $t(`%c`),
144
+ defaultCategory: $t(`%Cn`), // Ignore this name
143
145
  width: 20,
144
146
  getValue: (object: T) => {
145
147
  const address = getAddress(object);
@@ -150,8 +152,8 @@ export class XlsxTransformerColumnHelper {
150
152
  },
151
153
  {
152
154
  id: getId('city'),
153
- name: $t(`3d538399-3585-4be6-b03d-c12afa7183e8`),
154
- defaultCategory: $t(`2f10996e-ea97-4345-b997-c93198c7d67f`), // Ignore this name
155
+ name: $t(`%wp`),
156
+ defaultCategory: $t(`%Cn`), // Ignore this name
155
157
  width: 20,
156
158
  getValue: (object: T) => {
157
159
  const address = getAddress(object);
@@ -162,8 +164,8 @@ export class XlsxTransformerColumnHelper {
162
164
  },
163
165
  {
164
166
  id: getId('country'),
165
- name: $t(`cce830e0-6c05-405f-a800-4c217dc3235f`),
166
- defaultCategory: $t(`2f10996e-ea97-4345-b997-c93198c7d67f`), // Ignore this name
167
+ name: $t(`%Cp`),
168
+ defaultCategory: $t(`%Cn`), // Ignore this name
167
169
  width: 20,
168
170
  getValue: (object: T) => {
169
171
  const address = getAddress(object);
@@ -1,5 +1,6 @@
1
- import { Order, Webshop } from '@stamhoofd/models';
2
- import { CheckoutMethodType, PaymentGeneral, PaymentMethod, PaymentMethodHelper, RecordCategory, RecordCheckboxAnswer, WebshopTakeoutMethod } from '@stamhoofd/structures';
1
+ import type { Order, Webshop } from '@stamhoofd/models';
2
+ import type { WebshopTakeoutMethod } from '@stamhoofd/structures';
3
+ import { CheckoutMethodType, PaymentGeneral, PaymentMethod, PaymentMethodHelper, RecordCategory, RecordCheckboxAnswer } from '@stamhoofd/structures';
3
4
  import { Formatter } from '@stamhoofd/utility';
4
5
 
5
6
  export function createOrderDataHTMLTable(order: Order, webshop: Webshop): string {
@@ -7,20 +8,20 @@ export function createOrderDataHTMLTable(order: Order, webshop: Webshop): string
7
8
 
8
9
  const data = [
9
10
  {
10
- title: $t('4d496edf-0203-4df3-a6e9-3e58d226d6c5'),
11
+ title: $t('%xA'),
11
12
  value: '' + (order.number ?? '?'),
12
13
  },
13
14
  {
14
15
  title: ((order) => {
15
16
  if (order.data.checkoutMethod?.type === CheckoutMethodType.Takeout) {
16
- return $t(`8113733b-00ea-42ae-8829-6056774a8be0`);
17
+ return $t(`%Uq`);
17
18
  }
18
19
 
19
20
  if (order.data.checkoutMethod?.type === CheckoutMethodType.OnSite) {
20
- return $t(`7eec15d0-4d60-423f-b860-4f3824271578`);
21
+ return $t(`%TW`);
21
22
  }
22
23
 
23
- return $t(`8a910c54-1b2d-4963-9128-2cab93b0151b`);
24
+ return $t(`%Us`);
24
25
  })(order),
25
26
  value: ((order) => {
26
27
  if (order.data.checkoutMethod?.type === CheckoutMethodType.Takeout) {
@@ -38,7 +39,7 @@ export function createOrderDataHTMLTable(order: Order, webshop: Webshop): string
38
39
  (order.data.checkoutMethod?.type === CheckoutMethodType.Takeout || order.data.checkoutMethod?.type === CheckoutMethodType.OnSite) && ((order.data.checkoutMethod as any)?.address)
39
40
  ? [
40
41
  {
41
- title: $t(`f7e792ed-2265-41e9-845f-e3ce0bc5da7c`),
42
+ title: $t(`%Cn`),
42
43
  value: ((order) => {
43
44
  return (order.data.checkoutMethod as WebshopTakeoutMethod)?.address?.shortString() ?? '';
44
45
  })(order),
@@ -47,21 +48,21 @@ export function createOrderDataHTMLTable(order: Order, webshop: Webshop): string
47
48
  : []
48
49
  ),
49
50
  {
50
- title: $t(`40aabd99-0331-4267-9b6a-a87c06b3f7fe`),
51
+ title: $t(`%7R`),
51
52
  value: Formatter.capitalizeFirstLetter(order.data.timeSlot?.dateString() ?? ''),
52
53
  },
53
54
  {
54
- title: $t(`7853cca1-c41a-4687-9502-190849405f76`),
55
+ title: $t(`%1GD`),
55
56
  value: order.data.timeSlot?.timeRangeString() ?? '',
56
57
  },
57
58
  {
58
- title: $t(`17edcdd6-4fb2-4882-adec-d3a4f43a1926`),
59
+ title: $t(`%Gq`),
59
60
  value: order.data.customer.name,
60
61
  },
61
62
  ...(order.data.customer.phone
62
63
  ? [
63
64
  {
64
- title: $t(`feea3664-9353-4bd4-b17d-aff005d3e265`),
65
+ title: $t(`%18Z`),
65
66
  value: order.data.customer.phone,
66
67
  },
67
68
  ]
@@ -78,7 +79,7 @@ export function createOrderDataHTMLTable(order: Order, webshop: Webshop): string
78
79
  (order.data.paymentMethod !== PaymentMethod.Unknown)
79
80
  ? [
80
81
  {
81
- title: $t(`07e7025c-0bfb-41be-87bc-1023d297a1a2`),
82
+ title: $t(`%M7`),
82
83
  value: Formatter.capitalizeFirstLetter(PaymentMethodHelper.getName(order.data.paymentMethod)),
83
84
  },
84
85
  ]
@@ -1,4 +1,4 @@
1
- import { IPaginatedResponse, LimitedFilteredRequest } from '@stamhoofd/structures';
1
+ import type { IPaginatedResponse, LimitedFilteredRequest } from '@stamhoofd/structures';
2
2
  import { FileSignService } from '../services/FileSignService.js';
3
3
 
4
4
  export function fetchToAsyncIterator<T>(
@@ -1,5 +1,6 @@
1
1
  import { CachedBalance, Registration } from '@stamhoofd/models';
2
- import { SQL, SQLAlias, SQLCalculation, SQLNamedExpression, SQLPlusSign, SQLSelectAs, SQLSum } from '@stamhoofd/sql';
2
+ import type { SQLNamedExpression} from '@stamhoofd/sql';
3
+ import { SQL, SQLAlias, SQLCalculation, SQLPlusSign, SQLSelectAs, SQLSum } from '@stamhoofd/sql';
3
4
 
4
5
  export const memberCachedBalanceForOrganizationJoin = SQL.leftJoin(
5
6
  SQL.select('objectId', 'organizationId',
@@ -1,8 +1,9 @@
1
- import { AutoEncoderPatchType } from '@simonbackx/simple-encoding';
1
+ import type { AutoEncoderPatchType } from '@simonbackx/simple-encoding';
2
2
  import { isSimpleError, SimpleError } from '@simonbackx/simple-errors';
3
3
  import { Member } from '@stamhoofd/models';
4
- import { MemberDetails, ReviewTimes, UitpasSocialTariff, UitpasSocialTariffStatus } from '@stamhoofd/structures';
5
- import { GetPassResponse } from '../services/uitpas/PassholderEndpoints.js';
4
+ import type { MemberDetails, ReviewTimes} from '@stamhoofd/structures';
5
+ import { UitpasSocialTariff, UitpasSocialTariffStatus } from '@stamhoofd/structures';
6
+ import type { GetPassResponse } from '../services/uitpas/PassholderEndpoints.js';
6
7
  import { UitpasService } from '../services/uitpas/UitpasService.js';
7
8
  import { throwIfInvalidUitpasNumber } from '../services/uitpas/checkUitpasNumbers.js';
8
9
 
@@ -102,7 +103,7 @@ export function uitpasApiResponseToSocialTariff(response: GetPassResponse): Uitp
102
103
  throw new SimpleError({
103
104
  code: 'invalid_data',
104
105
  message: 'Invalid social tariff end date',
105
- human: $t('abc1a491-8038-4435-9007-c77cc00c0886'),
106
+ human: $t('%1Iv'),
106
107
  });
107
108
  }
108
109
  }
@@ -1,4 +1,4 @@
1
- import { Request, RequestMiddleware } from '@simonbackx/simple-endpoints';
1
+ import type { Request, RequestMiddleware } from '@simonbackx/simple-endpoints';
2
2
 
3
3
  import { ContextInstance } from '../helpers/Context.js';
4
4
 
package/src/migrate.ts CHANGED
@@ -1,12 +1,16 @@
1
1
  import chalk from 'chalk';
2
2
 
3
- import { Column, DatabaseInstance, Migration } from '@simonbackx/simple-database';
3
+ import { Column, Database, DatabaseInstance, Migration } from '@simonbackx/simple-database';
4
4
  import { Version } from '@stamhoofd/structures';
5
5
  import path from 'path';
6
6
 
7
7
  Column.setJSONVersion(Version);
8
8
  process.env.TZ = 'UTC';
9
9
 
10
+ // Polyfill require.resolve, since import.meta.resolve is not supported by vitest
11
+ import { createRequire } from 'node:module';
12
+ const require = createRequire(import.meta.url);
13
+
10
14
  const emailPath = require.resolve('@stamhoofd/email');
11
15
  const modelsPath = require.resolve('@stamhoofd/models');
12
16
 
@@ -20,6 +24,10 @@ const start = async () => {
20
24
  throw new Error('STAMHOOFD.DB_DATABASE is not set');
21
25
  }
22
26
 
27
+ // Reload database so we are sure we are running on the correct database in the
28
+ // environment
29
+ await Database.reload({})
30
+
23
31
  let killSignalReceived = false;
24
32
  const handler = () => {
25
33
  // Ignore
@@ -41,17 +49,26 @@ const start = async () => {
41
49
  await globalDatabase.statement(query);
42
50
 
43
51
  // External migrations
44
- await Migration.runAll(path.dirname(modelsPath) + '/migrations');
45
- await Migration.runAll(path.dirname(emailPath) + '/migrations');
52
+ if (!await Migration.runAll(path.dirname(modelsPath) + '/migrations')) {
53
+ throw new Error('Migrations failed')
54
+ }
55
+ if (!await Migration.runAll(path.dirname(emailPath) + '/../migrations')) {
56
+ throw new Error('Email migrations failed')
57
+ }
46
58
 
47
59
  // Internal
48
- await Migration.runAll(__dirname + '/src/migrations');
60
+ if (!await Migration.runAll(import.meta.dirname + '/migrations')) {
61
+ throw new Error('Internal migrations failed')
62
+ }
49
63
 
50
64
  if (killSignalReceived) {
51
65
  console.error(chalk.red('Killing process due to received signal during migration'));
52
66
  process.exit(1);
53
67
  }
54
68
 
69
+ // Reload database to prevent connection state leakage
70
+ await Database.reload({})
71
+
55
72
  process.off('SIGTERM', handler);
56
73
  process.off('SIGINT', handler);
57
74
  };
@@ -12,7 +12,7 @@ export default new Migration(async () => {
12
12
 
13
13
  // Insert defaults
14
14
  console.log('Inserting default email templates');
15
- const sqlStatement = await fs.readFile(__dirname + '/data/default-email-templates.sql', { encoding: 'utf-8' });
15
+ const sqlStatement = await fs.readFile(import.meta.dirname + '/data/default-email-templates.sql', { encoding: 'utf-8' });
16
16
  await Database.statement(sqlStatement);
17
17
 
18
18
  // Do something here
@@ -1,6 +1,7 @@
1
1
  import { Migration } from '@simonbackx/simple-database';
2
2
  import { Organization, RegistrationPeriod } from '@stamhoofd/models';
3
- import { Address, Country } from '@stamhoofd/structures';
3
+ import { Address } from '@stamhoofd/structures';
4
+ import { Country } from '@stamhoofd/types/Country';
4
5
  import { Formatter } from '@stamhoofd/utility';
5
6
 
6
7
  export default new Migration(async () => {
@@ -1,6 +1,7 @@
1
1
  import { Migration } from '@simonbackx/simple-database';
2
2
  import { Group, Organization, OrganizationRegistrationPeriod, Registration, RegistrationPeriod } from '@stamhoofd/models';
3
- import { CycleInformation, GroupCategory, GroupCategorySettings, GroupPrivateSettings, GroupSettings, GroupStatus, GroupType, RegistrationPeriodSettings, TranslatedString } from '@stamhoofd/structures';
3
+ import type { CycleInformation} from '@stamhoofd/structures';
4
+ import { GroupCategory, GroupCategorySettings, GroupPrivateSettings, GroupSettings, GroupStatus, GroupType, RegistrationPeriodSettings, TranslatedString } from '@stamhoofd/structures';
4
5
 
5
6
  export default new Migration(async () => {
6
7
  if (STAMHOOFD.environment === 'test') {
@@ -401,7 +402,7 @@ async function migrateRegistrations({ organization, period, originalGroup, newGr
401
402
  newWaitingList.organizationId = organization.id;
402
403
  newWaitingList.periodId = period.id;
403
404
  newWaitingList.settings = GroupSettings.create({
404
- name: TranslatedString.create($t(`c1f1d9d0-3fa1-4633-8e14-8c4fc98b4f0f`) + ' ' + newGroup.settings.name.toString()),
405
+ name: TranslatedString.create($t(`%yh`) + ' ' + newGroup.settings.name.toString()),
405
406
  });
406
407
 
407
408
  if (!dryRun) {
@@ -1,4 +1,5 @@
1
- import { Group, GroupFactory, Organization, OrganizationFactory, OrganizationRegistrationPeriod, OrganizationRegistrationPeriodFactory, RegistrationPeriod, RegistrationPeriodFactory } from '@stamhoofd/models';
1
+ import type { Organization, RegistrationPeriod} from '@stamhoofd/models';
2
+ import { Group, GroupFactory, OrganizationFactory, OrganizationRegistrationPeriod, OrganizationRegistrationPeriodFactory, RegistrationPeriodFactory } from '@stamhoofd/models';
2
3
  import { GroupCategory, GroupCategorySettings, GroupPriceDiscountType, GroupStatus, OldGroupPrice, OldGroupPrices, TranslatedString } from '@stamhoofd/structures';
3
4
  import { migratePrices } from './1754560914-groups-prices.js';
4
5
 
@@ -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';
@@ -8,7 +8,7 @@ function stringToError(message: string) {
8
8
  new SimpleError({
9
9
  code: 'email_skipped_hard_bounce',
10
10
  message: 'The recipient has hard bounced. This means that the email address is invalid or no longer exists.',
11
- human: $t(`af49a569-ce88-48d9-ac37-81e594e16c03`),
11
+ human: $t(`%ws`),
12
12
  }),
13
13
  );
14
14
  }
@@ -18,7 +18,7 @@ function stringToError(message: string) {
18
18
  new SimpleError({
19
19
  code: 'email_skipped_spam',
20
20
  message: 'Recipient has marked as spam',
21
- human: $t(`e6523f56-397e-4127-8bf7-8396f6f25a62`),
21
+ human: $t(`%wt`),
22
22
  }),
23
23
  );
24
24
  }
@@ -28,7 +28,7 @@ function stringToError(message: string) {
28
28
  new SimpleError({
29
29
  code: 'email_skipped_unsubscribed',
30
30
  message: 'Recipient has unsubscribed',
31
- human: $t('ffbebae7-eac3-44fe-863b-25942c5be7d0'),
31
+ human: $t('%1E3'),
32
32
  }),
33
33
  );
34
34
  }
@@ -38,7 +38,7 @@ function stringToError(message: string) {
38
38
  new SimpleError({
39
39
  code: 'email_skipped_unsubscribed',
40
40
  message: 'Recipient has unsubscribed from marketing',
41
- human: $t('ffbebae7-eac3-44fe-863b-25942c5be7d0'),
41
+ human: $t('%1E3'),
42
42
  }),
43
43
  );
44
44
  }
@@ -48,7 +48,7 @@ function stringToError(message: string) {
48
48
  new SimpleError({
49
49
  code: 'all_filtered',
50
50
  message: 'All recipients are filtered due to hard bounce or spam',
51
- human: $t('f6ca0939-f191-4aba-9c53-cd370453c0bc'),
51
+ human: $t('%1E4'),
52
52
  }),
53
53
  );
54
54
  }
@@ -58,7 +58,7 @@ function stringToError(message: string) {
58
58
  new SimpleError({
59
59
  code: 'invalid_email_address',
60
60
  message: 'Invalid email address',
61
- human: $t(`cbbff442-758c-4f76-b8c2-26bb176fefcc`),
61
+ human: $t(`%1Mi`),
62
62
  }),
63
63
  );
64
64
  }
@@ -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
+ }