@stamhoofd/backend 2.121.0 → 2.122.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 (429) hide show
  1. package/output-2.txt +1 -0
  2. package/output.txt +1 -0
  3. package/package.json +69 -52
  4. package/src/audit-logs/EventNotificationLogger.ts +40 -0
  5. package/src/audit-logs/ModelLogger.ts +19 -15
  6. package/src/audit-logs/OrganizationLogger.ts +1 -1
  7. package/src/audit-logs/RegistrationInvitationLogger.ts +24 -24
  8. package/src/audit-logs/init.ts +8 -2
  9. package/src/boot.ts +19 -18
  10. package/src/crons/amazon-ses.ts +13 -26
  11. package/src/crons/balance-emails.ts +3 -5
  12. package/src/crons/clearExcelCache.test.ts +1 -1
  13. package/src/crons/clearExcelCache.ts +1 -2
  14. package/src/crons/drip-emails.ts +42 -0
  15. package/src/crons/endFunctionsOfUsersWithoutRegistration.ts +4 -0
  16. package/src/crons/helpers/isOutside.ts +11 -0
  17. package/src/crons/helpers/useSavedIterator.ts +32 -0
  18. package/src/crons/index.ts +5 -0
  19. package/src/crons/invoices.ts +32 -38
  20. package/src/crons/members-fees.ts +50 -0
  21. package/src/crons/mollie-chargebacks.ts +14 -15
  22. package/src/crons/service-fees.ts +152 -0
  23. package/src/crons/stripe-invoices.ts +48 -0
  24. package/src/crons/transfer-fees.ts +176 -0
  25. package/src/crons/update-cached-balances.ts +4 -4
  26. package/src/crons.ts +7 -64
  27. package/src/debug.ts +4 -2
  28. package/src/email-recipient-loaders/documents.ts +1 -1
  29. package/src/email-recipient-loaders/members.ts +1 -1
  30. package/src/email-recipient-loaders/payments.ts +4 -6
  31. package/src/email-recipient-loaders/registrations.ts +1 -1
  32. package/src/email-replacements/getEmailReplacementsForPayment.ts +5 -9
  33. package/src/endpoints/admin/members/ChargeMembersEndpoint.ts +1 -1
  34. package/src/endpoints/admin/memberships/ChargeMembershipsEndpoint.ts +1 -1
  35. package/src/endpoints/admin/memberships/GetChargeMembershipsSummaryEndpoint.ts +3 -5
  36. package/src/endpoints/admin/organizations/ChargeOrganizationsEndpoint.ts +1 -1
  37. package/src/endpoints/admin/organizations/GetOrganizationsCountEndpoint.ts +1 -1
  38. package/src/endpoints/admin/organizations/GetOrganizationsEndpoint.ts +13 -7
  39. package/src/endpoints/admin/organizations/PatchOrganizationsEndpoint.ts +4 -6
  40. package/src/endpoints/admin/organizations/PatchPackagesEndpoint.test.ts +10 -6
  41. package/src/endpoints/admin/organizations/PatchPackagesEndpoint.ts +39 -21
  42. package/src/endpoints/admin/registrations/ChargeRegistrationsEndpoint.ts +1 -1
  43. package/src/endpoints/auth/CreateAdminEndpoint.ts +23 -5
  44. package/src/endpoints/auth/CreateTokenEndpoint.ts +2 -2
  45. package/src/endpoints/auth/DeleteTokenEndpoint.ts +1 -1
  46. package/src/endpoints/auth/DeleteUserEndpoint.ts +3 -3
  47. package/src/endpoints/auth/ForgotPasswordEndpoint.ts +1 -1
  48. package/src/endpoints/auth/GetOtherUserEndpoint.ts +1 -1
  49. package/src/endpoints/auth/GetUserEndpoint.ts +1 -1
  50. package/src/endpoints/auth/OpenIDConnectAuthTokenEndpoint.ts +1 -1
  51. package/src/endpoints/auth/OpenIDConnectStartEndpoint.ts +1 -1
  52. package/src/endpoints/auth/PatchUserEndpoint.ts +5 -8
  53. package/src/endpoints/auth/PollEmailVerificationEndpoint.ts +1 -1
  54. package/src/endpoints/auth/RetryEmailVerificationEndpoint.ts +1 -1
  55. package/src/endpoints/auth/SignupEndpoint.ts +2 -3
  56. package/src/endpoints/auth/VerifyEmailEndpoint.ts +20 -3
  57. package/src/endpoints/frontend/FrontendEnvironmentEndpoint.ts +2 -1
  58. package/src/endpoints/global/addresses/SearchRegionsEndpoint.ts +2 -4
  59. package/src/endpoints/global/addresses/ValidateAddressEndpoint.ts +1 -1
  60. package/src/endpoints/global/audit-logs/GetAuditLogsEndpoint.ts +5 -7
  61. package/src/endpoints/global/caddy/CheckDomainCertEndpoint.ts +2 -2
  62. package/src/endpoints/global/email/CreateEmailEndpoint.ts +3 -4
  63. package/src/endpoints/global/email/GetAdminEmailsEndpoint.test.ts +1 -1
  64. package/src/endpoints/global/email/GetAdminEmailsEndpoint.ts +1 -2
  65. package/src/endpoints/global/email/GetEmailAddressEndpoint.ts +4 -6
  66. package/src/endpoints/global/email/GetEmailEndpoint.ts +1 -1
  67. package/src/endpoints/global/email/GetUserEmailsEndpoint.test.ts +1 -1
  68. package/src/endpoints/global/email/GetUserEmailsEndpoint.ts +1 -1
  69. package/src/endpoints/global/email/ManageEmailAddressEndpoint.ts +6 -10
  70. package/src/endpoints/global/email/PatchEmailEndpoint.test.ts +4 -7
  71. package/src/endpoints/global/email/PatchEmailEndpoint.ts +6 -9
  72. package/src/endpoints/global/email-recipients/GetEmailRecipientsCountEndpoint.ts +1 -1
  73. package/src/endpoints/global/email-recipients/GetEmailRecipientsEndpoint.test.ts +1 -1
  74. package/src/endpoints/global/email-recipients/GetEmailRecipientsEndpoint.ts +1 -1
  75. package/src/endpoints/global/email-recipients/RetryEmailRecipientEndpoint.ts +2 -2
  76. package/src/endpoints/global/events/GetEventNotificationsCountEndpoint.ts +1 -1
  77. package/src/endpoints/global/events/GetEventNotificationsEndpoint.ts +3 -3
  78. package/src/endpoints/global/events/GetEventsEndpoint.ts +3 -3
  79. package/src/endpoints/global/events/PatchEventNotificationsEndpoint.test.ts +49 -4
  80. package/src/endpoints/global/events/PatchEventNotificationsEndpoint.ts +5 -8
  81. package/src/endpoints/global/events/PatchEventsEndpoint.test.ts +12 -44
  82. package/src/endpoints/global/events/PatchEventsEndpoint.ts +128 -127
  83. package/src/endpoints/global/files/ExportToExcelEndpoint.ts +9 -9
  84. package/src/endpoints/global/files/GetFileCache.ts +3 -4
  85. package/src/endpoints/global/files/UploadFile.ts +3 -4
  86. package/src/endpoints/global/files/UploadImage.ts +3 -4
  87. package/src/endpoints/global/groups/GetGroupsCountEndpoint.ts +1 -1
  88. package/src/endpoints/global/groups/GetGroupsEndpoint.test.ts +1 -1
  89. package/src/endpoints/global/groups/GetGroupsEndpoint.ts +4 -2
  90. package/src/endpoints/global/members/GetMemberFamilyEndpoint.ts +2 -3
  91. package/src/endpoints/global/members/GetMembersCountEndpoint.ts +1 -1
  92. package/src/endpoints/global/members/GetMembersEndpoint.test.ts +2 -2
  93. package/src/endpoints/global/members/GetMembersEndpoint.ts +10 -12
  94. package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.test.ts +195 -12
  95. package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.ts +16 -22
  96. package/src/endpoints/global/members/helpers/validateGroupFilter.ts +6 -30
  97. package/src/endpoints/global/members/shouldCheckIfMemberIsDuplicate.ts +1 -1
  98. package/src/endpoints/global/organizations/CheckRegisterCodeEndpoint.ts +1 -1
  99. package/src/endpoints/global/organizations/CreateOrganizationEndpoint.ts +40 -8
  100. package/src/endpoints/global/organizations/GetOrganizationFromDomainEndpoint.ts +2 -2
  101. package/src/endpoints/global/organizations/GetOrganizationFromUriEndpoint.ts +2 -2
  102. package/src/endpoints/global/organizations/SearchOrganizationEndpoint.test.ts +4 -1
  103. package/src/endpoints/global/organizations/SearchOrganizationEndpoint.ts +4 -5
  104. package/src/endpoints/global/payments/StripeWebhookEndpoint.ts +9 -16
  105. package/src/endpoints/global/platform/GetPlatformAdminsEndpoint.ts +1 -1
  106. package/src/endpoints/global/platform/GetPlatformEndpoint.ts +1 -1
  107. package/src/endpoints/global/platform/PatchPlatformEnpoint.test.ts +1 -1
  108. package/src/endpoints/global/platform/PatchPlatformEnpoint.ts +11 -11
  109. package/src/endpoints/global/platform-memberships/GetPlatformMembershipsCountEndpoint.ts +31 -31
  110. package/src/endpoints/global/platform-memberships/GetPlatformMembershipsEndpoint.ts +18 -20
  111. package/src/endpoints/global/registration/GetRegistrationsCountEndpoint.ts +1 -1
  112. package/src/endpoints/global/registration/GetRegistrationsEndpoint.test.ts +1 -1
  113. package/src/endpoints/global/registration/GetRegistrationsEndpoint.ts +6 -10
  114. package/src/endpoints/global/registration/GetUserDetailedPayableBalanceEndpoint.ts +35 -6
  115. package/src/endpoints/global/registration/GetUserDocumentsEndpoint.ts +2 -2
  116. package/src/endpoints/global/registration/GetUserMembersEndpoint.ts +1 -1
  117. package/src/endpoints/global/registration/GetUserPayableBalanceEndpoint.ts +1 -1
  118. package/src/endpoints/global/registration/PatchUserMembersEndpoint.test.ts +2 -2
  119. package/src/endpoints/global/registration/PatchUserMembersEndpoint.ts +3 -3
  120. package/src/endpoints/global/registration/RegisterMembersEndpoint.test.ts +90 -6
  121. package/src/endpoints/global/registration/RegisterMembersEndpoint.ts +35 -34
  122. package/src/endpoints/global/registration-invitations/GetRegistrationInvitationsCountEndpoint.ts +1 -1
  123. package/src/endpoints/global/registration-invitations/GetRegistrationInvitationsEndpoint.test.ts +62 -63
  124. package/src/endpoints/global/registration-invitations/GetRegistrationInvitationsEndpoint.ts +6 -9
  125. package/src/endpoints/global/registration-invitations/PatchRegistrationInvitationsEndpoint.test.ts +51 -52
  126. package/src/endpoints/global/registration-invitations/PatchRegistrationInvitationsEndpoint.ts +6 -7
  127. package/src/endpoints/global/registration-periods/GetRegistrationPeriodsCountEndpoint.ts +43 -0
  128. package/src/endpoints/global/registration-periods/GetRegistrationPeriodsEndpoint.ts +1 -1
  129. package/src/endpoints/global/registration-periods/PatchRegistrationPeriodsEndpoint.ts +13 -5
  130. package/src/endpoints/global/sso/GetSSOEndpoint.ts +2 -3
  131. package/src/endpoints/global/sso/SetSSOEndpoint.ts +1 -1
  132. package/src/endpoints/global/webshops/GetWebshopFromDomainEndpoint.ts +2 -2
  133. package/src/endpoints/global/webshops/GetWebshopsEndpoint.test.ts +1 -2
  134. package/src/endpoints/global/webshops/GetWebshopsEndpoint.ts +2 -4
  135. package/src/endpoints/organization/dashboard/balance-items/GetBalanceItemEndpoint.ts +2 -2
  136. package/src/endpoints/organization/dashboard/balance-items/GetBalanceItemsCountEndpoint.ts +1 -1
  137. package/src/endpoints/organization/dashboard/balance-items/GetBalanceItemsEndpoint.ts +3 -4
  138. package/src/endpoints/organization/dashboard/balance-items/PatchBalanceItemsEndpoint.ts +7 -9
  139. package/src/endpoints/organization/dashboard/billing/ApplyRegisterCodeEndpoint.test.ts +73 -0
  140. package/src/endpoints/organization/dashboard/billing/ApplyRegisterCodeEndpoint.ts +89 -0
  141. package/src/endpoints/organization/dashboard/billing/DeactivatePackageEndpoint.ts +1 -5
  142. package/src/endpoints/organization/dashboard/billing/DeleteOrganizationMandateEndpoint.ts +11 -11
  143. package/src/endpoints/organization/dashboard/billing/GetOrganizationDetailedPayableBalanceCollectionEndpoint.ts +2 -2
  144. package/src/endpoints/organization/dashboard/billing/GetOrganizationDetailedPayableBalanceEndpoint.ts +8 -8
  145. package/src/endpoints/organization/dashboard/billing/GetOrganizationMandatesEndpoint.ts +9 -9
  146. package/src/endpoints/organization/dashboard/billing/GetOrganizationPayableBalanceEndpoint.ts +2 -2
  147. package/src/endpoints/organization/dashboard/billing/GetOrganizationPayableInvoicesEndpoint.ts +68 -0
  148. package/src/endpoints/organization/dashboard/billing/GetPackagesEndpoint.ts +4 -4
  149. package/src/endpoints/organization/dashboard/billing/GetRegisterCodeEndpoint.ts +66 -0
  150. package/src/endpoints/organization/dashboard/billing/OrganizationCheckoutEndpoint.test.ts +949 -0
  151. package/src/endpoints/organization/dashboard/billing/OrganizationCheckoutEndpoint.ts +60 -57
  152. package/src/endpoints/organization/dashboard/billing/PatchOrganizationMandatesEndpoint.ts +20 -20
  153. package/src/endpoints/organization/dashboard/documents/GetDocumentTemplateXML.ts +1 -1
  154. package/src/endpoints/organization/dashboard/documents/GetDocumentTemplatesCountEndpoint.ts +1 -1
  155. package/src/endpoints/organization/dashboard/documents/GetDocumentTemplatesEndpoint.ts +1 -1
  156. package/src/endpoints/organization/dashboard/documents/GetDocumentsCountEndpoint.ts +1 -1
  157. package/src/endpoints/organization/dashboard/documents/GetDocumentsEndpoint.ts +1 -1
  158. package/src/endpoints/organization/dashboard/documents/PatchDocumentEndpoint.ts +10 -2
  159. package/src/endpoints/organization/dashboard/documents/PatchDocumentTemplatesEndpoint.test.ts +2 -2
  160. package/src/endpoints/organization/dashboard/documents/PatchDocumentTemplatesEndpoint.ts +2 -2
  161. package/src/endpoints/organization/dashboard/email/CheckEmailBouncesEndpoint.ts +1 -1
  162. package/src/endpoints/organization/dashboard/email-templates/GetEmailTemplatesEndpoint.test.ts +1 -1
  163. package/src/endpoints/organization/dashboard/email-templates/GetEmailTemplatesEndpoint.ts +10 -8
  164. package/src/endpoints/organization/dashboard/email-templates/PatchEmailTemplatesEndpoint.test.ts +1 -1
  165. package/src/endpoints/organization/dashboard/email-templates/PatchEmailTemplatesEndpoint.ts +5 -6
  166. package/src/endpoints/organization/dashboard/invoices/GetInvoicesCountEndpoint.ts +1 -1
  167. package/src/endpoints/organization/dashboard/invoices/GetInvoicesEndpoint.ts +10 -6
  168. package/src/endpoints/organization/dashboard/invoices/PatchInvoicesEndpoint.ts +11 -2
  169. package/src/endpoints/organization/dashboard/mollie/CheckMollieEndpoint.ts +4 -5
  170. package/src/endpoints/organization/dashboard/mollie/ConnectMollieEndpoint.ts +5 -5
  171. package/src/endpoints/organization/dashboard/mollie/DisconnectMollieEndpoint.ts +2 -2
  172. package/src/endpoints/organization/dashboard/mollie/GetMollieDashboardEndpoint.ts +7 -7
  173. package/src/endpoints/organization/dashboard/nolt/CreateNoltTokenEndpoint.ts +1 -1
  174. package/src/endpoints/organization/dashboard/organization/GetOrganizationArchivedGroups.ts +2 -2
  175. package/src/endpoints/organization/dashboard/organization/GetOrganizationDeletedGroups.ts +1 -1
  176. package/src/endpoints/organization/dashboard/organization/GetUitpasClientIdEndpoint.ts +1 -1
  177. package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.test.ts +2 -2
  178. package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.ts +50 -12
  179. package/src/endpoints/organization/dashboard/organization/SearchUitpasOrganizersEndpoint.ts +2 -2
  180. package/src/endpoints/organization/dashboard/organization/SetOrganizationDomainEndpoint.ts +5 -10
  181. package/src/endpoints/organization/dashboard/organization/SetUitpasClientCredentialsEndpoint.ts +1 -1
  182. package/src/endpoints/organization/dashboard/payments/GetPaymentsCountEndpoint.ts +1 -1
  183. package/src/endpoints/organization/dashboard/payments/GetPaymentsEndpoint.ts +3 -4
  184. package/src/endpoints/organization/dashboard/payments/PatchPaymentsEndpoint.ts +21 -14
  185. package/src/endpoints/organization/dashboard/receivable-balances/ChargeReceivableBalancesEndpoint.ts +35 -28
  186. package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalanceEndpoint.ts +2 -3
  187. package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalancesCountEndpoint.ts +1 -1
  188. package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalancesEndpoint.ts +1 -1
  189. package/src/endpoints/organization/dashboard/registration-periods/GetOrganizationRegistrationPeriodsEndpoint.test.ts +1 -1
  190. package/src/endpoints/organization/dashboard/registration-periods/GetOrganizationRegistrationPeriodsEndpoint.ts +2 -3
  191. package/src/endpoints/organization/dashboard/registration-periods/MoveRegistrationPeriods.test.ts +1 -1
  192. package/src/endpoints/organization/dashboard/registration-periods/PatchOrganizationRegistrationPeriodsEndpoint.test.ts +1 -1
  193. package/src/endpoints/organization/dashboard/registration-periods/PatchOrganizationRegistrationPeriodsEndpoint.ts +19 -18
  194. package/src/endpoints/organization/dashboard/registration-periods/SetupStepReviewEndpoint.ts +4 -5
  195. package/src/endpoints/organization/dashboard/stripe/ConnectStripeEndpoint.ts +1 -1
  196. package/src/endpoints/organization/dashboard/stripe/DeleteStripeAccountEndpoint.ts +2 -3
  197. package/src/endpoints/organization/dashboard/stripe/GetStripeAccountLinkEndpoint.ts +2 -2
  198. package/src/endpoints/organization/dashboard/stripe/GetStripeAccountsEndpoint.ts +1 -1
  199. package/src/endpoints/organization/dashboard/stripe/GetStripeLoginLinkEndpoint.ts +2 -2
  200. package/src/endpoints/organization/dashboard/stripe/UpdateStripeAccountEndpoint.ts +1 -1
  201. package/src/endpoints/organization/dashboard/users/CreateApiUserEndpoint.ts +1 -1
  202. package/src/endpoints/organization/dashboard/users/DeleteUserEndpoint.ts +1 -1
  203. package/src/endpoints/organization/dashboard/users/GetApiUsersEndpoint.ts +1 -1
  204. package/src/endpoints/organization/dashboard/users/GetOrganizationAdminsEndpoint.ts +1 -1
  205. package/src/endpoints/organization/dashboard/users/PatchApiUserEndpoint.ts +4 -6
  206. package/src/endpoints/organization/dashboard/webshops/CreateWebshopEndpoint.ts +10 -15
  207. package/src/endpoints/organization/dashboard/webshops/DeleteWebshopEndpoint.ts +1 -1
  208. package/src/endpoints/organization/dashboard/webshops/GetDiscountCodesEndpoint.ts +2 -2
  209. package/src/endpoints/organization/dashboard/webshops/GetWebshopOrdersCountEndpoint.ts +1 -1
  210. package/src/endpoints/organization/dashboard/webshops/GetWebshopOrdersEndpoint.ts +1 -1
  211. package/src/endpoints/organization/dashboard/webshops/GetWebshopTicketsEndpoint.ts +1 -1
  212. package/src/endpoints/organization/dashboard/webshops/GetWebshopUriAvailabilityEndpoint.ts +11 -2
  213. package/src/endpoints/organization/dashboard/webshops/PatchDiscountCodesEndpoint.ts +4 -6
  214. package/src/endpoints/organization/dashboard/webshops/PatchWebshopEndpoint.ts +22 -7
  215. package/src/endpoints/organization/dashboard/webshops/PatchWebshopOrdersEndpoint.ts +20 -27
  216. package/src/endpoints/organization/dashboard/webshops/PatchWebshopTicketsEndpoint.ts +1 -1
  217. package/src/endpoints/organization/dashboard/webshops/SearchUitpasEventsEndpoint.ts +2 -2
  218. package/src/endpoints/organization/dashboard/webshops/VerifyWebshopDomainEndpoint.ts +2 -3
  219. package/src/endpoints/organization/dashboard/webshops/WebshopReservedPathSegments.test.ts +95 -0
  220. package/src/endpoints/organization/shared/ExchangePaymentEndpoint.ts +2 -2
  221. package/src/endpoints/organization/shared/GetDocumentHtml.ts +1 -1
  222. package/src/endpoints/organization/shared/GetPaymentEndpoint.ts +1 -1
  223. package/src/endpoints/organization/shared/GetUitpasNumberDetailsEndpoint.ts +3 -5
  224. package/src/endpoints/organization/shared/auth/GetOrganizationEndpoint.ts +1 -1
  225. package/src/endpoints/organization/webshops/CheckWebshopDiscountCodesEndpoint.ts +4 -1
  226. package/src/endpoints/organization/webshops/GetOrderByPaymentEndpoint.ts +14 -3
  227. package/src/endpoints/organization/webshops/GetOrderEndpoint.ts +14 -2
  228. package/src/endpoints/organization/webshops/GetTicketsEndpoint.ts +37 -16
  229. package/src/endpoints/organization/webshops/GetWebshopEndpoint.test.ts +34 -2
  230. package/src/endpoints/organization/webshops/GetWebshopEndpoint.ts +4 -2
  231. package/src/endpoints/organization/webshops/PlaceOrderEndpoint.test.ts +74 -3
  232. package/src/endpoints/organization/webshops/PlaceOrderEndpoint.ts +16 -33
  233. package/src/endpoints/organization/webshops/RetrieveUitpasSocialTariffPriceEndpoint.ts +3 -5
  234. package/src/endpoints/organization/webshops/WebshopAuthHelper.ts +36 -0
  235. package/src/endpoints/system/HealthEndpoint.ts +1 -1
  236. package/src/excel-loaders/balance-items.ts +1 -1
  237. package/src/excel-loaders/event-notifications.ts +1 -1
  238. package/src/excel-loaders/members.ts +1 -1
  239. package/src/excel-loaders/organizations.ts +3 -3
  240. package/src/excel-loaders/payments.ts +31 -1
  241. package/src/excel-loaders/platform-memberships.ts +13 -14
  242. package/src/excel-loaders/receivable-balances.ts +2 -2
  243. package/src/excel-loaders/registrations.ts +2 -3
  244. package/src/helpers/AddressValidator.ts +7 -14
  245. package/src/helpers/AdminPermissionChecker.ts +50 -63
  246. package/src/helpers/AuthenticatedStructures.ts +69 -55
  247. package/src/helpers/BalanceItemRelationsBackfiller.test.ts +174 -0
  248. package/src/helpers/BalanceItemRelationsBackfiller.ts +163 -0
  249. package/src/helpers/BuckarooHelper.ts +2 -4
  250. package/src/helpers/CheckSettlements.ts +12 -24
  251. package/src/helpers/Context.ts +15 -10
  252. package/src/helpers/CookieHelper.ts +1 -2
  253. package/src/helpers/EmailResumer.ts +1 -2
  254. package/src/helpers/FileCache.ts +2 -3
  255. package/src/helpers/FinancialSupportHelper.ts +2 -2
  256. package/src/helpers/FlagMomentCleanup.ts +1 -2
  257. package/src/helpers/ForwardHandler.ts +5 -10
  258. package/src/helpers/GlobalHelper.ts +3 -3
  259. package/src/helpers/LegacyBillingConverter.ts +787 -0
  260. package/src/helpers/MemberMerger.test.ts +782 -0
  261. package/src/helpers/MemberMerger.ts +600 -0
  262. package/src/helpers/MemberUserSyncer.ts +6 -12
  263. package/src/helpers/MembershipCharger.ts +2 -4
  264. package/src/helpers/PaymentCustomerResolver.test.ts +203 -0
  265. package/src/helpers/PaymentCustomerResolver.ts +144 -0
  266. package/src/helpers/PeriodHelper.ts +2 -3
  267. package/src/helpers/RecordAnswerHelper.test.ts +105 -110
  268. package/src/helpers/RecordAnswerHelper.ts +7 -7
  269. package/src/helpers/SeedTools.ts +106 -0
  270. package/src/helpers/ServiceFeeHelper.ts +125 -15
  271. package/src/helpers/SetupStepUpdater.ts +38 -32
  272. package/src/helpers/StamhoofdFilterAccessHelper.ts +52 -0
  273. package/src/helpers/StripeHelper.ts +14 -36
  274. package/src/helpers/StripeInvoicer.ts +419 -0
  275. package/src/helpers/StripePayoutChecker.ts +5 -10
  276. package/src/helpers/TagHelper.ts +7 -8
  277. package/src/helpers/TemporaryMemberAccess.ts +1 -2
  278. package/src/helpers/ThrottledQueue.ts +1 -2
  279. package/src/helpers/UitpasTokenRepository.ts +1 -2
  280. package/src/helpers/ViesHelper.ts +7 -11
  281. package/src/helpers/XlsxTransformerColumnHelper.ts +1 -1
  282. package/src/helpers/outstandingBalanceJoin.ts +2 -2
  283. package/src/helpers/updateMemberDetailsUitpasNumber.ts +3 -5
  284. package/src/migrate.ts +12 -5
  285. package/src/{seeds → migrations}/0000000004-single-organization.ts +10 -1
  286. package/src/migrations/0000000006-default-organization.ts +139 -0
  287. package/src/{seeds → migrations}/1715028563-user-permissions.ts +17 -27
  288. package/src/{seeds/1765896674-document-update-year.test.ts → migrations/1750090029-document-update-year.test.ts} +27 -26
  289. package/src/migrations/1750090029-document-update-year.ts +103 -0
  290. package/src/{seeds → migrations}/1750090030-records-configuration.ts +33 -32
  291. package/src/migrations/1750090031-records-configuration-webshops.ts +36 -0
  292. package/src/migrations/1752848540-national-numbers.ts +585 -0
  293. package/src/migrations/1752848550-records-configuration-group-filter.ts +1064 -0
  294. package/src/{seeds → migrations}/1752848561-groups-registration-periods.ts +70 -26
  295. package/src/{seeds → migrations}/1754560914-groups-prices.test.ts +1 -1
  296. package/src/{seeds → migrations}/1754560914-groups-prices.ts +9 -15
  297. package/src/{seeds → migrations}/1756293699-fill-previous-next-period-id.ts +1 -2
  298. package/src/migrations/1761665607-sync-member-users.ts +40 -0
  299. package/src/migrations/1779121240-invoice-email-template.sql +6 -0
  300. package/src/migrations/1779986893-default-payment-failed-email-templates.sql +4 -0
  301. package/src/migrations/1780578166-convert-legacy-billing.ts +13 -0
  302. package/src/{seeds/1755876819-remove-duplicate-members.ts → migrations/1780665426-remove-duplicate-members.ts} +23 -4
  303. package/src/migrations/1780933598-document-groups.ts +88 -0
  304. package/src/migrations/1781692342-balance-item-relations.ts +13 -0
  305. package/src/migrations/1781857866-platform-admins.ts +103 -0
  306. package/src/migrations/1781857867-rm-old-platform-admins.ts +25 -0
  307. package/src/seeds/0000000001-throw.ts +5 -0
  308. package/src/seeds/1760702452-update-balance-price-paid.ts +19 -0
  309. package/src/seeds/1760702453-update-balance-invoiced.ts +19 -0
  310. package/src/seeds/1760702454-update-cached-outstanding-balance-from-items.ts +51 -14
  311. package/src/seeds/1773754928-force-save-members.ts +41 -8
  312. package/src/seeds/1780665427-schedule-stock-updates.ts +45 -0
  313. package/src/seeds/1780665428-group-update-occupancy.ts +31 -0
  314. package/src/seeds/1780915001-fill-payment-customer.ts +70 -0
  315. package/src/seeds/1780915002-update-orders.ts +39 -0
  316. package/src/seeds/1782047708-organization-company-address.ts +44 -0
  317. package/src/seeds-temporary/1769088653-uitpas-status.ts +1 -2
  318. package/src/seeds-temporary/1780416000-migrate-audit-log-legacy-enums.test.ts +69 -0
  319. package/src/seeds-temporary/1780416000-migrate-audit-log-legacy-enums.ts +85 -0
  320. package/src/services/AuditLogService.test.ts +51 -0
  321. package/src/services/AuditLogService.ts +45 -0
  322. package/src/services/BalanceItemService.ts +141 -44
  323. package/src/services/CpuService.ts +3 -6
  324. package/src/services/DatabaseCollationService.test.ts +1 -2
  325. package/src/services/DocumentService.ts +1 -2
  326. package/src/services/EventNotificationService.ts +1 -1
  327. package/src/services/FileSignService.ts +2 -4
  328. package/src/services/InvoicePdfService.ts +286 -0
  329. package/src/services/InvoiceService.ts +204 -251
  330. package/src/services/InvoiceXMLService.ts +424 -0
  331. package/src/services/MemberNumberService.ts +6 -11
  332. package/src/services/MemberRecordStore.ts +8 -10
  333. package/src/services/MollieService.ts +114 -121
  334. package/src/services/PaymentMandateService.ts +45 -45
  335. package/src/services/PaymentReallocationService.test.ts +1 -1
  336. package/src/services/PaymentReallocationService.ts +7 -9
  337. package/src/services/PaymentService.ts +444 -308
  338. package/src/services/PlatformMembershipService.ts +4 -8
  339. package/src/services/ReferralService.ts +223 -0
  340. package/src/services/RegistrationService.ts +63 -53
  341. package/src/services/SSOService.test.ts +119 -0
  342. package/src/services/SSOService.ts +56 -49
  343. package/src/services/STPackageService.ts +97 -61
  344. package/src/services/UniqueMemberNumberService.ts +69 -0
  345. package/src/services/UniqueUserService.ts +3 -6
  346. package/src/services/VATService.ts +85 -0
  347. package/src/services/uitpas/PassholderEndpoints.ts +3 -6
  348. package/src/services/uitpas/UitpasService.ts +6 -10
  349. package/src/services/uitpas/checkUitpasNumbers.ts +2 -4
  350. package/src/services/uitpas/getSocialTariffForUitpasNumbers.ts +3 -6
  351. package/src/services/uitpas/searchUitpasEvents.ts +1 -2
  352. package/src/sql-filters/audit-logs.ts +1 -1
  353. package/src/sql-filters/balance-item-payments.ts +1 -1
  354. package/src/sql-filters/balance-items.ts +1 -1
  355. package/src/sql-filters/base-registration-filter-compilers.ts +5 -33
  356. package/src/sql-filters/document-templates.ts +1 -1
  357. package/src/sql-filters/documents.ts +1 -1
  358. package/src/sql-filters/email-recipients.ts +1 -1
  359. package/src/sql-filters/emails.ts +1 -1
  360. package/src/sql-filters/event-notifications.ts +1 -1
  361. package/src/sql-filters/events.ts +6 -1
  362. package/src/sql-filters/groups.ts +5 -0
  363. package/src/sql-filters/invoiced-balance-items.ts +1 -1
  364. package/src/sql-filters/invoices.ts +1 -1
  365. package/src/sql-filters/member-responsibility-records.ts +1 -1
  366. package/src/sql-filters/members.ts +1 -1
  367. package/src/sql-filters/orders.ts +4 -4
  368. package/src/sql-filters/organization-registration-periods.ts +1 -1
  369. package/src/sql-filters/organizations.ts +1 -1
  370. package/src/sql-filters/platform-memberships.ts +3 -3
  371. package/src/sql-filters/receivable-balances.ts +1 -1
  372. package/src/sql-filters/registration-periods.ts +1 -1
  373. package/src/sql-filters/registrations.ts +1 -1
  374. package/src/sql-filters/tickets.ts +1 -1
  375. package/src/sql-filters/users.ts +1 -1
  376. package/src/sql-sorters/groups.ts +23 -0
  377. package/src/sql-sorters/platform-memberships.ts +16 -16
  378. package/src/sql-sorters/registration-invitations.ts +2 -2
  379. package/tests/actions/patchOrganizationMember.ts +1 -1
  380. package/tests/actions/patchUserMember.ts +1 -1
  381. package/tests/assertions/assertBalances.ts +6 -12
  382. package/tests/e2e/api-rate-limits.test.ts +12 -24
  383. package/tests/e2e/bundle-discounts.test.ts +4 -1
  384. package/tests/e2e/charge-members.test.ts +13 -11
  385. package/tests/e2e/documents.test.ts +4 -1
  386. package/tests/e2e/register.test.ts +7 -9
  387. package/tests/e2e/stock.test.ts +4 -3
  388. package/tests/e2e/tickets.test.ts +1 -1
  389. package/tests/helpers/MollieMocker.ts +462 -0
  390. package/tests/helpers/PayconiqMocker.ts +138 -45
  391. package/tests/helpers/StripeMocker.ts +9 -6
  392. package/tests/helpers/index.ts +4 -0
  393. package/tests/init/initAdmin.ts +2 -2
  394. package/tests/init/initBundleDiscount.ts +1 -1
  395. package/tests/init/initMembershipOrganization.ts +13 -0
  396. package/tests/init/initPermissionRole.ts +3 -4
  397. package/tests/vitest.global.setup.ts +1 -1
  398. package/vitest.config.js +6 -0
  399. package/.nvmrc +0 -1
  400. package/src/helpers/GroupBuilder.ts +0 -418
  401. package/src/seeds/0000000000-example.ts +0 -11
  402. package/src/seeds/1722256498-group-update-occupancy.ts +0 -52
  403. package/src/seeds/1726572303-schedule-stock-updates.ts +0 -52
  404. package/src/seeds/1726847064-setup-steps.ts +0 -16
  405. package/src/seeds/1728928974-update-cached-outstanding-balance-from-items.ts +0 -31
  406. package/src/seeds/1729253172-update-orders.ts +0 -21
  407. package/src/seeds/1733319079-fill-paying-organization-ids.ts +0 -68
  408. package/src/seeds/1733748412-update-deleted-order-numbers.ts +0 -109
  409. package/src/seeds/1733994455-balance-item-status-open.ts +0 -30
  410. package/src/seeds/1740046783-update-membership.ts +0 -17
  411. package/src/seeds/1741008870-fix-auditlog-description.ts +0 -50
  412. package/src/seeds/1741011468-fix-auditlog-description-uft16.ts +0 -88
  413. package/src/seeds/1741268179-fix-group-dates-of-events.ts +0 -32
  414. package/src/seeds/1751445358-upload-email-attachments.ts +0 -106
  415. package/src/seeds/1755532883-update-email-sender-ids.ts +0 -47
  416. package/src/seeds/1755790070-fill-email-recipient-errors.ts +0 -96
  417. package/src/seeds/1756115432-remove-old-drafts.ts +0 -16
  418. package/src/seeds/1756115433-fill-email-recipient-organization-id.ts +0 -30
  419. package/src/seeds/1756303697-update-email-counts.ts +0 -76
  420. package/src/seeds/1761665607-sync-member-users.ts +0 -59
  421. package/src/seeds/1765896674-document-update-year.ts +0 -66
  422. /package/src/{seeds → migrations}/0000000001-development-user.ts +0 -0
  423. /package/src/{seeds → migrations}/0000000002-clear-stamhoofd-email-templates.ts +0 -0
  424. /package/src/{seeds → migrations}/0000000003-default-email-templates.ts +0 -0
  425. /package/src/{seeds → migrations}/1752848561-groups-registration-periods.test.ts +0 -0
  426. /package/src/{seeds → migrations}/1766150402-document-published-at.test.ts +0 -0
  427. /package/src/{seeds → migrations}/1766150402-document-published-at.ts +0 -0
  428. /package/src/{seeds → migrations}/1779121239-default-invoice-email-template.sql +0 -0
  429. /package/src/{seeds → migrations}/data/default-email-templates.sql +0 -0
@@ -0,0 +1,40 @@
1
+ import { EventNotification, Platform } from '@stamhoofd/models';
2
+ import { AuditLogReplacement, AuditLogReplacementType, AuditLogType } from '@stamhoofd/structures';
3
+ import { getDefaultGenerator, ModelLogger } from './ModelLogger.js';
4
+
5
+ const defaultGenerator = getDefaultGenerator<EventNotification>({
6
+ created: AuditLogType.EventNotificationAdded,
7
+ updated: AuditLogType.EventNotificationEdited,
8
+ deleted: AuditLogType.EventNotificationDeleted,
9
+ });
10
+
11
+ export const EventNotificationLogger = new ModelLogger(EventNotification, {
12
+ skipKeys: ['createdBy', 'submittedBy', 'submittedAt', 'acceptedRecordAnswers'],
13
+
14
+ async optionsGenerator(event) {
15
+ const result = await defaultGenerator(event);
16
+ if (!result) {
17
+ return;
18
+ }
19
+
20
+ const platform = await Platform.getSharedPrivateStruct();
21
+ const type = platform.config.eventNotificationTypes.find(type => type.id === event.model.typeId);
22
+
23
+ return {
24
+ ...result,
25
+ data: {
26
+ title: type?.title || event.model.id,
27
+ },
28
+ };
29
+ },
30
+
31
+ createReplacements(model, { data }) {
32
+ return new Map([
33
+ ['n', AuditLogReplacement.create({
34
+ id: model.id,
35
+ value: data.title,
36
+ type: AuditLogReplacementType.EventNotification,
37
+ })],
38
+ ]);
39
+ },
40
+ });
@@ -125,8 +125,7 @@ export class ModelLogger<ModelType extends typeof Model, M extends InstanceType<
125
125
  if (!settings?.source) {
126
126
  if (settings) {
127
127
  settings.source = AuditLogSource.System;
128
- }
129
- else {
128
+ } else {
130
129
  settings = { source: AuditLogSource.System };
131
130
  }
132
131
  }
@@ -148,11 +147,9 @@ export class ModelLogger<ModelType extends typeof Model, M extends InstanceType<
148
147
 
149
148
  if (settings?.source) {
150
149
  log.source = settings.source;
151
- }
152
- else if (context) {
150
+ } else if (context) {
153
151
  log.source = userId ? AuditLogSource.User : AuditLogSource.Anonymous;
154
- }
155
- else {
152
+ } else {
156
153
  log.source = AuditLogSource.System;
157
154
  }
158
155
 
@@ -179,25 +176,34 @@ export class ModelLogger<ModelType extends typeof Model, M extends InstanceType<
179
176
  key: AuditLogReplacement.key(renamedKey),
180
177
  type: AuditLogPatchItemType.Changed,
181
178
  }));
182
- }
183
- else {
179
+ } else {
180
+ const column = event.model.static.columns?.get(key);
184
181
  log.patchList.push(...ObjectDiffer.diff(
185
182
  key in oldModel ? oldModel[key] : undefined,
186
183
  key in event.model ? event.model[key] : undefined,
187
184
  AuditLogReplacement.key(renamedKey),
185
+ column?.decoder,
188
186
  ));
189
187
  }
190
188
  }
191
189
 
192
190
  // Remove skipped keys
193
- log.patchList = log.patchList.filter(p => !this.skipKeys?.includes(p.key.toKey()));
191
+ if (this.skipKeys) {
192
+ log.patchList = log.patchList.filter((p) => {
193
+ for (const s of this.skipKeys) {
194
+ if (p.key.toKey().startsWith(s)) {
195
+ return false;
196
+ }
197
+ }
198
+ return true;
199
+ });
200
+ }
194
201
 
195
202
  if (log.patchList.length === 0 && !log.description) {
196
203
  // No changes or all skipped
197
204
  return false;
198
205
  }
199
- }
200
- else {
206
+ } else {
201
207
  return false;
202
208
  }
203
209
  }
@@ -235,8 +241,7 @@ export class ModelLogger<ModelType extends typeof Model, M extends InstanceType<
235
241
 
236
242
  try {
237
243
  log.validate();
238
- }
239
- catch (e) {
244
+ } catch (e) {
240
245
  console.error('AuditLog dit not pass validation', log);
241
246
  }
242
247
 
@@ -250,8 +255,7 @@ export class ModelLogger<ModelType extends typeof Model, M extends InstanceType<
250
255
  events: d.slice(0, 1),
251
256
  });
252
257
  return saved;
253
- }
254
- catch (e) {
258
+ } catch (e) {
255
259
  console.error('Failed to save log', e, log);
256
260
  }
257
261
  return false;
@@ -3,7 +3,7 @@ import { AuditLogReplacement, AuditLogReplacementType, AuditLogType } from '@sta
3
3
  import { getDefaultGenerator, ModelLogger } from './ModelLogger.js';
4
4
 
5
5
  export const OrganizationLogger = new ModelLogger(Organization, {
6
- skipKeys: ['searchIndex', 'serverMeta'],
6
+ skipKeys: ['searchIndex', 'serverMeta', 'meta.packages'],
7
7
  optionsGenerator: getDefaultGenerator<Organization>({
8
8
  created: AuditLogType.OrganizationAdded,
9
9
  updated: AuditLogType.OrganizationEdited,
@@ -3,33 +3,33 @@ import { AuditLogReplacement, AuditLogReplacementType, AuditLogType } from '@sta
3
3
  import { getDefaultGenerator, ModelLogger } from './ModelLogger.js';
4
4
 
5
5
  const defaultGenerator = getDefaultGenerator<RegistrationInvitation>({
6
- created: AuditLogType.RegistrationInvitationAdded,
7
- deleted: AuditLogType.RegistrationInvitationDeleted,
6
+ created: AuditLogType.RegistrationInvitationAdded,
7
+ deleted: AuditLogType.RegistrationInvitationDeleted,
8
8
  });
9
9
 
10
10
  export const RegistrationInvitationLogger = new ModelLogger(RegistrationInvitation, {
11
- async optionsGenerator(event) {
12
- const result = await defaultGenerator(event);
13
- if (!result) {
14
- return;
15
- }
16
-
17
- const member = await Member.getByID(event.model.memberId);
18
- const group = await Group.getByID(event.model.groupId);
19
-
20
- if (!member || !group) {
21
- return;
22
- }
23
-
24
- return {
25
- ...result,
26
- data: {
27
- member,
28
- group,
29
- },
30
- };
31
- },
32
- createReplacements(_, { data }) {
11
+ async optionsGenerator(event) {
12
+ const result = await defaultGenerator(event);
13
+ if (!result) {
14
+ return;
15
+ }
16
+
17
+ const member = await Member.getByID(event.model.memberId);
18
+ const group = await Group.getByID(event.model.groupId);
19
+
20
+ if (!member || !group) {
21
+ return;
22
+ }
23
+
24
+ return {
25
+ ...result,
26
+ data: {
27
+ member,
28
+ group,
29
+ },
30
+ };
31
+ },
32
+ createReplacements(_, { data }) {
33
33
  return new Map([
34
34
  ['m', AuditLogReplacement.create({
35
35
  id: data.member.id,
@@ -1,8 +1,10 @@
1
+ import { AuditLogService, modelLogDefinitions } from '../services/AuditLogService.js';
1
2
  import { DocumentTemplateLogger } from './DocumentTemplateLogger.js';
2
3
  import { EmailAddressLogger } from './EmailAddressLogger.js';
3
4
  import { EmailLogger } from './EmailLogger.js';
4
5
  import { EmailTemplateLogger } from './EmailTemplateLogger.js';
5
6
  import { EventLogger } from './EventLogger.js';
7
+ import { EventNotificationLogger } from './EventNotificationLogger.js';
6
8
  import { GroupLogger } from './GroupLogger.js';
7
9
  import { MemberLogger } from './MemberLogger.js';
8
10
  import { MemberPlatformMembershipLogger } from './MemberPlatformMembershipLogger.js';
@@ -12,19 +14,19 @@ import { OrganizationLogger } from './OrganizationLogger.js';
12
14
  import { OrganizationRegistrationPeriodLogger } from './OrganizationRegistrationPeriodLogger.js';
13
15
  import { PaymentLogger } from './PaymentLogger.js';
14
16
  import { PlatformLogger } from './PlatformLogger.js';
17
+ import { RegistrationInvitationLogger } from './RegistrationInvitationLogger.js';
15
18
  import { RegistrationLogger } from './RegistrationLogger.js';
16
19
  import { RegistrationPeriodLogger } from './RegistrationPeriodLogger.js';
17
20
  import { StripeAccountLogger } from './StripeAccountLogger.js';
18
21
  import { UserLogger } from './UserLogger.js';
19
22
  import { WebshopLogger } from './WebshopLogger.js';
20
- import { modelLogDefinitions } from '../services/AuditLogService.js';
21
- import { RegistrationInvitationLogger } from './RegistrationInvitationLogger.js';
22
23
 
23
24
  modelLogDefinitions.set(RegistrationLogger.model, RegistrationLogger);
24
25
  modelLogDefinitions.set(GroupLogger.model, GroupLogger);
25
26
  modelLogDefinitions.set(OrganizationLogger.model, OrganizationLogger);
26
27
  modelLogDefinitions.set(PlatformLogger.model, PlatformLogger);
27
28
  modelLogDefinitions.set(EventLogger.model, EventLogger);
29
+ modelLogDefinitions.set(EventNotificationLogger.model, EventNotificationLogger);
28
30
  modelLogDefinitions.set(RegistrationPeriodLogger.model, RegistrationPeriodLogger);
29
31
  modelLogDefinitions.set(OrganizationRegistrationPeriodLogger.model, OrganizationRegistrationPeriodLogger);
30
32
  modelLogDefinitions.set(StripeAccountLogger.model, StripeAccountLogger);
@@ -40,3 +42,7 @@ modelLogDefinitions.set(EmailTemplateLogger.model, EmailTemplateLogger);
40
42
  modelLogDefinitions.set(EmailAddressLogger.model, EmailAddressLogger);
41
43
  modelLogDefinitions.set(UserLogger.model, UserLogger);
42
44
  modelLogDefinitions.set(RegistrationInvitationLogger.model, RegistrationInvitationLogger);
45
+
46
+ if (STAMHOOFD.environment !== 'production') {
47
+ AuditLogService.validateAuditLogEnumTranslations();
48
+ }
package/src/boot.ts CHANGED
@@ -1,14 +1,16 @@
1
1
  import { Column, Database, Migration } from '@simonbackx/simple-database';
2
2
  import { CORSPreflightEndpoint, Router, RouterServer } from '@simonbackx/simple-endpoints';
3
3
  import { CORSMiddleware, LogMiddleware, VersionMiddleware } from '@stamhoofd/backend-middleware';
4
+ import { checkReadOnly } from '@stamhoofd/crons';
4
5
  import { Email } from '@stamhoofd/email';
5
6
  import { loadLogger } from '@stamhoofd/logging';
6
7
  import { Version } from '@stamhoofd/structures';
7
8
  import { sleep } from '@stamhoofd/utility';
8
- import { checkReadOnly } from '@stamhoofd/crons';
9
9
 
10
+ import { AutoEncoder } from '@simonbackx/simple-encoding';
10
11
  import { SimpleError } from '@simonbackx/simple-errors';
11
- import { startCrons, stopCrons, waitForCrons } from '@stamhoofd/crons';
12
+ import { StyledText } from '@simonbackx/simple-logging';
13
+ import { markAllSeedsFinished, startCrons, stopCrons, waitForCrons } from '@stamhoofd/crons';
12
14
  import { Platform } from '@stamhoofd/models';
13
15
  import { QueueHandler } from '@stamhoofd/queues';
14
16
  import { resumeEmails } from './helpers/EmailResumer.js';
@@ -23,9 +25,9 @@ import { DocumentService } from './services/DocumentService.js';
23
25
  import { FileSignService } from './services/FileSignService.js';
24
26
  import { PlatformMembershipService } from './services/PlatformMembershipService.js';
25
27
  import { UitpasService } from './services/uitpas/UitpasService.js';
28
+ import { UniqueMemberNumberService } from './services/UniqueMemberNumberService.js';
26
29
  import { UniqueUserService } from './services/UniqueUserService.js';
27
- import { AutoEncoder } from '@simonbackx/simple-encoding';
28
- import { StyledText } from '@simonbackx/simple-logging';
30
+ import { QueryableModel } from '@stamhoofd/sql';
29
31
 
30
32
  process.on('unhandledRejection', (error: Error) => {
31
33
  console.error('unhandledRejection');
@@ -36,7 +38,7 @@ process.on('unhandledRejection', (error: Error) => {
36
38
  // Set version of saved structures
37
39
  Column.setJSONVersion(Version);
38
40
 
39
- // Set timezone
41
+ // Set timezone to UTC
40
42
  process.env.TZ = 'UTC';
41
43
 
42
44
  if (STAMHOOFD.environment === 'development') {
@@ -48,7 +50,7 @@ if (new Date().getTimezoneOffset() !== 0) {
48
50
  throw new Error('Process should always run in UTC timezone');
49
51
  }
50
52
 
51
- const seeds = async (options: {shutdown: () => Promise<void>}) => {
53
+ const seeds = async (options: { shutdown: () => Promise<void> }) => {
52
54
  if (await checkReadOnly()) {
53
55
  console.error(new StyledText(`[SEEDS] `).addClass('migration', 'tag'), new StyledText('MySQL is in read-only mode: Seeds are disabled.').addClass('error'));
54
56
  return;
@@ -63,10 +65,11 @@ const seeds = async (options: {shutdown: () => Promise<void>}) => {
63
65
  if (STAMHOOFD.environment === 'test' || STAMHOOFD.environment === 'development') {
64
66
  await options.shutdown();
65
67
  }
68
+ } else {
69
+ markAllSeedsFinished();
66
70
  }
67
71
  });
68
- }
69
- catch (e) {
72
+ } catch (e) {
70
73
  console.error('Failed to run seeds:');
71
74
  console.error(e);
72
75
  }
@@ -81,19 +84,20 @@ function productionLog(message: string) {
81
84
 
82
85
  export const boot = async (options: { killProcess: boolean }) => {
83
86
  // Make sure we use the current environment for connecting to the database
84
- await Database.reload({})
87
+ await Database.reload({});
85
88
 
86
89
  productionLog('Running server at v' + Version);
87
90
  productionLog('Running server at port ' + STAMHOOFD.PORT);
88
91
  productionLog('Running server on DB ' + process.env.DB_DATABASE); // note, should always use process env here
89
92
  console.log('Node version is: ' + process.version);
90
-
93
+
91
94
  AutoEncoder.skipDefaultValuesVersion = 10000; // todo
92
95
 
93
96
  loadLogger();
94
97
 
95
98
  await GlobalHelper.load();
96
99
  await UniqueUserService.check();
100
+ await UniqueMemberNumberService.check();
97
101
  await BootChecksService.checkDatabaseCollation();
98
102
 
99
103
  // Init platform shared struct: otherwise permissions won't work with missing responsibilities
@@ -172,8 +176,7 @@ export const boot = async (options: { killProcess: boolean }) => {
172
176
 
173
177
  if (STAMHOOFD.environment !== 'development' && STAMHOOFD.environment !== 'test') {
174
178
  CpuService.startMonitoring();
175
- }
176
- else if (STAMHOOFD.environment === 'development') {
179
+ } else if (STAMHOOFD.environment === 'development') {
177
180
  const { loadDebugFunctions } = await import('./debug.js');
178
181
  loadDebugFunctions({ routerServer });
179
182
  }
@@ -189,6 +192,7 @@ export const boot = async (options: { killProcess: boolean }) => {
189
192
  return;
190
193
  }
191
194
  shuttingDown = true;
195
+ QueryableModel.shutdownMigrations = true;
192
196
  productionLog('Shutting down...');
193
197
  // Disable keep alive
194
198
  routerServer.defaultHeaders = Object.assign(routerServer.defaultHeaders, { Connection: 'close' });
@@ -209,8 +213,7 @@ export const boot = async (options: { killProcess: boolean }) => {
209
213
  try {
210
214
  await routerServer.close();
211
215
  productionLog('HTTP server stopped');
212
- }
213
- catch (err) {
216
+ } catch (err) {
214
217
  console.error('Failed to stop HTTP server:');
215
218
  console.error(err);
216
219
  }
@@ -231,8 +234,7 @@ export const boot = async (options: { killProcess: boolean }) => {
231
234
  console.log(`${Email.currentQueue.length} emails still in queue. Waiting 500ms...`);
232
235
  await sleep(500);
233
236
  }
234
- }
235
- catch (err) {
237
+ } catch (err) {
236
238
  console.error('Failed to wait for emails to finish:');
237
239
  console.error(err);
238
240
  }
@@ -240,8 +242,7 @@ export const boot = async (options: { killProcess: boolean }) => {
240
242
  try {
241
243
  await Database.end();
242
244
  productionLog('MySQL connections closed');
243
- }
244
- catch (err) {
245
+ } catch (err) {
245
246
  console.error('Failed to close MySQL connection:');
246
247
  console.error(err);
247
248
  }
@@ -114,13 +114,11 @@ function readHeaders(message: any) {
114
114
  headers[(header.name as string).toLowerCase()] = header.value;
115
115
  }
116
116
  }
117
- }
118
- else {
117
+ } else {
119
118
  console.log('[AWS] Missing mail headers', message);
120
119
  }
121
120
  return headers;
122
- }
123
- catch (e) {
121
+ } catch (e) {
124
122
  console.log('[AWS] Failed to read headers', e, message);
125
123
  return {};
126
124
  }
@@ -172,8 +170,7 @@ async function handleBounce(message: any) {
172
170
  response: recipient.diagnosticCode || '',
173
171
  subject: message.mail.commonHeaders?.subject || '',
174
172
  });
175
- }
176
- else if (
173
+ } else if (
177
174
  type === 'Transient'
178
175
  ) {
179
176
  const organization: Organization | undefined = source ? await Organization.getByEmail(source) : undefined;
@@ -197,8 +194,7 @@ async function handleBounce(message: any) {
197
194
  }
198
195
  }
199
196
  console.log('[AWS BOUNCES] For domain ' + source);
200
- }
201
- else {
197
+ } else {
202
198
  console.log("[AWS BOUNCES] 'bounce' field missing in bounce message");
203
199
  }
204
200
  }
@@ -236,8 +232,7 @@ async function handleComplaint(message: any) {
236
232
  response: recipient.diagnosticCode || '',
237
233
  subject: message.mail.commonHeaders?.subject || '',
238
234
  });
239
- }
240
- else {
235
+ } else {
241
236
  await saveLog({
242
237
  id: b.feedbackId,
243
238
  email,
@@ -262,8 +257,7 @@ async function handleComplaint(message: any) {
262
257
  });
263
258
  }
264
259
  }
265
- }
266
- else {
260
+ } else {
267
261
  console.log('[AWS COMPLAINTS] Missing complaint field');
268
262
  }
269
263
  }
@@ -286,8 +280,7 @@ async function handleForward(message: any) {
286
280
  Email.send(options);
287
281
  }
288
282
  }
289
- }
290
- else {
283
+ } else {
291
284
  console.log('[AWS FORWARDING] Missing mail, content or receipt field');
292
285
  }
293
286
  }
@@ -341,28 +334,23 @@ async function readFromQueue(queueUrl: string) {
341
334
  // Docs: https://docs.aws.amazon.com/ses/latest/dg/event-publishing-retrieving-sns-contents.html
342
335
  if (message.bounce) {
343
336
  await handleBounce(message);
344
- }
345
- else if (message.complaint) {
337
+ } else if (message.complaint) {
346
338
  await handleComplaint(message);
347
339
  }
348
340
  // Read message content
349
341
  // https://docs.aws.amazon.com/ses/latest/dg/receiving-email-notifications-contents.html
350
342
  else if (message.mail && message.content && message.receipt) {
351
343
  await handleForward(message);
352
- }
353
- else {
344
+ } else {
354
345
  console.log('[AWS Queue] Unsupported message');
355
346
  }
356
- }
357
- else {
347
+ } else {
358
348
  console.log("[AWS Queue] 'Message' field missing");
359
349
  }
360
- }
361
- else {
350
+ } else {
362
351
  console.log('[AWS Queue] Message Body missing in bounce');
363
352
  }
364
- }
365
- catch (e) {
353
+ } catch (e) {
366
354
  console.log('[AWS Queue] Message processing failed:');
367
355
  console.log('[AWS Queue]', e);
368
356
 
@@ -374,8 +362,7 @@ async function readFromQueue(queueUrl: string) {
374
362
 
375
363
  if (didProcess) {
376
364
  console.log(`[AWS Queue] Processed ${didProcess} message(s) from queue`);
377
- }
378
- else {
365
+ } else {
379
366
  console.log(`[AWS Queue] No message to process from queue`);
380
367
  }
381
368
  return didProcess;
@@ -205,8 +205,7 @@ async function sendTemplate({
205
205
 
206
206
  if (!upToDate) {
207
207
  console.log('No recipients found for organization', organization.name, organization.id);
208
- }
209
- else {
208
+ } else {
210
209
  const now = new Date();
211
210
  now.setMilliseconds(0);
212
211
 
@@ -221,7 +220,7 @@ async function sendTemplate({
221
220
  .set(
222
221
  'reminderEmailCount',
223
222
  SQL.calculation(SQL.column('reminderEmailCount'))
224
- .add(readDynamicSQLExpression(1))
223
+ .add(readDynamicSQLExpression(1)),
225
224
  )
226
225
  .where('id', balanceItemIds)
227
226
  .where('organizationId', organization.id)
@@ -230,8 +229,7 @@ async function sendTemplate({
230
229
  .update();
231
230
  }
232
231
  }
233
- }
234
- catch (e) {
232
+ } catch (e) {
235
233
  console.error('Error sending email for organization', e, organization.name, organization.id);
236
234
  }
237
235
  }
@@ -132,7 +132,7 @@ describe('clearExcelCacheHelper', () => {
132
132
  });
133
133
 
134
134
  fsMock.readdir.mockReturnValue(
135
-
135
+
136
136
  Promise.resolve([...directories, file1]) as any,
137
137
  );
138
138
  // #endregion
@@ -59,8 +59,7 @@ export async function clearExcelCacheHelper({ lastExcelClear, now, cachePath, en
59
59
  await fs.rm(path, { recursive: true, force: true });
60
60
  console.log('Removed', path);
61
61
  }
62
- }
63
- catch (error) {
62
+ } catch (error) {
64
63
  console.error(error);
65
64
  }
66
65
  }
@@ -0,0 +1,42 @@
1
+ import { registerCron } from '@stamhoofd/crons';
2
+ import { Organization } from '@stamhoofd/models';
3
+ import { isOutside } from './helpers/isOutside.js';
4
+ import { useSavedIterator } from './helpers/useSavedIterator.js';
5
+
6
+ const { iterate, isHoursAgo } = useSavedIterator(() => {
7
+ return Organization.select();
8
+ }, { limit: 10, maxQueries: 5 });
9
+
10
+ async function checkDrips() {
11
+ if (STAMHOOFD.environment === 'development') {
12
+ // For now reenabled on development for testing
13
+ // return;
14
+ }
15
+
16
+ if (STAMHOOFD.userMode === 'platform') {
17
+ return;
18
+ }
19
+
20
+ // Only send emails between 8:00 - 18:00 CET
21
+ if (isOutside('08:00', '18:00') && STAMHOOFD.environment === 'production') {
22
+ console.log('Skip Drip check: outside hours');
23
+ return;
24
+ }
25
+
26
+ if (!isHoursAgo(6)) {
27
+ return;
28
+ }
29
+
30
+ // Get the next x organization to send e-mails for
31
+ for await (const organization of iterate()) {
32
+ try {
33
+ await organization.checkDrips();
34
+ } catch (e) {
35
+ console.error(e);
36
+ }
37
+ }
38
+ }
39
+
40
+ if (STAMHOOFD.userMode !== 'platform') {
41
+ registerCron('checkDrips', checkDrips);
42
+ }
@@ -12,6 +12,10 @@ let lastCleanupMonth: number = now.getMonth();
12
12
  registerCron('endFunctionsOfUsersWithoutRegistration', endFunctionsOfUsersWithoutRegistration);
13
13
 
14
14
  export async function endFunctionsOfUsersWithoutRegistration() {
15
+ if (STAMHOOFD.userMode === 'organization') {
16
+ return;
17
+ }
18
+
15
19
  const now = new Date();
16
20
  const currentYear = now.getFullYear();
17
21
  const currentMonth = now.getMonth();
@@ -0,0 +1,11 @@
1
+ import { Formatter } from '@stamhoofd/utility';
2
+
3
+ type TimeString = `${0 | 1 | 2}${0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9}:${0 | 1 | 2 | 3 | 4 | 5 | 6}${0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9}`;
4
+ export function isOutside(start: TimeString, end: TimeString) {
5
+ // Only send emails between 8:00 - 18:00 CET
6
+ const CETTime = Formatter.timeIso(new Date());
7
+ if ((CETTime < start || CETTime > end)) {
8
+ return true;
9
+ }
10
+ return false;
11
+ }
@@ -0,0 +1,32 @@
1
+ import type { SQLResultNamespacedRow } from '@simonbackx/simple-database';
2
+ import type { IterableSQLSelect, SQLSelect } from '@stamhoofd/sql';
3
+
4
+ export function useSavedIterator<T extends object = SQLResultNamespacedRow>(start: () => SQLSelect<T>, options: { limit: number; maxQueries?: number }) {
5
+ let savedIterator: IterableSQLSelect<T> | null = null;
6
+ let lastFullRun: Date = new Date(0);
7
+
8
+ function updateStatus() {
9
+ if (savedIterator && savedIterator.isDone) {
10
+ savedIterator = null;
11
+ lastFullRun = new Date();
12
+
13
+ console.log('Done full loop');
14
+ }
15
+ }
16
+
17
+ const iterate = function () {
18
+ if (savedIterator === null) {
19
+ savedIterator = start().limit(options.limit).all({
20
+ nextEachHook: updateStatus,
21
+ });
22
+ }
23
+
24
+ return savedIterator.maxQueries(options.maxQueries ?? 1);
25
+ };
26
+
27
+ const isHoursAgo = function (hours: number) {
28
+ return lastFullRun.getTime() < new Date().getTime() - 1000 * 60 * 60 * hours;
29
+ };
30
+
31
+ return { iterate, lastFullRun, isHoursAgo };
32
+ }
@@ -7,3 +7,8 @@ import './delete-old-email-drafts.js';
7
7
  import './delete-archived-data.js';
8
8
  import './mollie-chargebacks.js';
9
9
  import './invoices.js';
10
+ import './service-fees.js';
11
+ import './members-fees.js';
12
+ import './stripe-invoices.js';
13
+ import './transfer-fees.js';
14
+ import './drip-emails.js';