@stamhoofd/backend 2.120.6 → 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 (434) hide show
  1. package/output-2.txt +1 -0
  2. package/output.txt +1 -0
  3. package/package.json +70 -53
  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 +46 -0
  8. package/src/audit-logs/init.ts +9 -1
  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 +7 -0
  19. package/src/crons/invoices.ts +160 -0
  20. package/src/crons/members-fees.ts +50 -0
  21. package/src/crons/mollie-chargebacks.ts +86 -0
  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 +54 -74
  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 +87 -46
  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 +51 -0
  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 +32 -13
  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 +38 -33
  122. package/src/endpoints/global/registration-invitations/GetRegistrationInvitationsCountEndpoint.ts +45 -0
  123. package/src/endpoints/global/registration-invitations/GetRegistrationInvitationsEndpoint.test.ts +494 -0
  124. package/src/endpoints/global/registration-invitations/GetRegistrationInvitationsEndpoint.ts +213 -0
  125. package/src/endpoints/global/registration-invitations/PatchRegistrationInvitationsEndpoint.test.ts +404 -0
  126. package/src/endpoints/global/registration-invitations/PatchRegistrationInvitationsEndpoint.ts +167 -0
  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 +19 -6
  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/{global → organization/dashboard}/billing/DeactivatePackageEndpoint.ts +4 -9
  142. package/src/endpoints/organization/dashboard/billing/DeleteOrganizationMandateEndpoint.ts +62 -0
  143. package/src/endpoints/organization/dashboard/billing/GetOrganizationDetailedPayableBalanceCollectionEndpoint.ts +56 -0
  144. package/src/endpoints/organization/dashboard/billing/GetOrganizationDetailedPayableBalanceEndpoint.ts +41 -18
  145. package/src/endpoints/organization/dashboard/billing/GetOrganizationMandatesEndpoint.ts +64 -0
  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 +12 -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 +311 -0
  152. package/src/endpoints/organization/dashboard/billing/PatchOrganizationMandatesEndpoint.ts +94 -0
  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 +15 -4
  168. package/src/endpoints/organization/dashboard/invoices/PatchInvoicesEndpoint.ts +11 -2
  169. package/src/endpoints/organization/dashboard/mollie/CheckMollieEndpoint.ts +8 -8
  170. package/src/endpoints/organization/dashboard/mollie/ConnectMollieEndpoint.ts +10 -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 +67 -20
  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 +24 -17
  185. package/src/endpoints/organization/dashboard/receivable-balances/ChargeReceivableBalancesEndpoint.ts +134 -0
  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 +32 -22
  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 +29 -8
  215. package/src/endpoints/organization/dashboard/webshops/PatchWebshopOrdersEndpoint.ts +21 -28
  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 +15 -13
  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 +28 -50
  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 +60 -65
  246. package/src/helpers/AuthenticatedStructures.ts +153 -51
  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 +21 -0
  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 +741 -0
  268. package/src/helpers/RecordAnswerHelper.ts +116 -0
  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 +15 -38
  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 +11 -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/migrations/1750090030-records-configuration.ts +92 -0
  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 +95 -27
  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/1779121239-default-invoice-email-template.sql +3 -0
  300. package/src/migrations/1779121240-invoice-email-template.sql +6 -0
  301. package/src/migrations/1779986893-default-payment-failed-email-templates.sql +4 -0
  302. package/src/migrations/1780578166-convert-legacy-billing.ts +13 -0
  303. package/src/{seeds/1755876819-remove-duplicate-members.ts → migrations/1780665426-remove-duplicate-members.ts} +23 -4
  304. package/src/migrations/1780933598-document-groups.ts +88 -0
  305. package/src/migrations/1781692342-balance-item-relations.ts +13 -0
  306. package/src/migrations/1781857866-platform-admins.ts +103 -0
  307. package/src/migrations/1781857867-rm-old-platform-admins.ts +25 -0
  308. package/src/seeds/0000000001-throw.ts +5 -0
  309. package/src/seeds/1760702452-update-balance-price-paid.ts +19 -0
  310. package/src/seeds/1760702453-update-balance-invoiced.ts +19 -0
  311. package/src/seeds/1760702454-update-cached-outstanding-balance-from-items.ts +51 -14
  312. package/src/seeds/1773754928-force-save-members.ts +41 -8
  313. package/src/seeds/1780665427-schedule-stock-updates.ts +45 -0
  314. package/src/seeds/1780665428-group-update-occupancy.ts +31 -0
  315. package/src/seeds/1780915001-fill-payment-customer.ts +70 -0
  316. package/src/seeds/1780915002-update-orders.ts +39 -0
  317. package/src/seeds/1782047708-organization-company-address.ts +44 -0
  318. package/src/seeds-temporary/1769088653-uitpas-status.ts +1 -2
  319. package/src/seeds-temporary/1780416000-migrate-audit-log-legacy-enums.test.ts +69 -0
  320. package/src/seeds-temporary/1780416000-migrate-audit-log-legacy-enums.ts +85 -0
  321. package/src/services/AuditLogService.test.ts +51 -0
  322. package/src/services/AuditLogService.ts +45 -0
  323. package/src/services/BalanceItemService.ts +148 -55
  324. package/src/services/CpuService.ts +3 -6
  325. package/src/services/DatabaseCollationService.test.ts +1 -2
  326. package/src/services/DocumentService.ts +1 -2
  327. package/src/services/EventNotificationService.ts +1 -1
  328. package/src/services/FileSignService.ts +2 -4
  329. package/src/services/InvoicePdfService.ts +286 -0
  330. package/src/services/InvoiceService.ts +330 -77
  331. package/src/services/InvoiceXMLService.ts +424 -0
  332. package/src/services/MemberNumberService.ts +6 -11
  333. package/src/services/MemberRecordStore.ts +8 -10
  334. package/src/services/MollieService.ts +530 -0
  335. package/src/services/PaymentMandateService.ts +214 -0
  336. package/src/services/PaymentReallocationService.test.ts +1 -1
  337. package/src/services/PaymentReallocationService.ts +7 -9
  338. package/src/services/PaymentService.ts +820 -328
  339. package/src/services/PlatformMembershipService.ts +5 -9
  340. package/src/services/ReferralService.ts +223 -0
  341. package/src/services/RegistrationService.ts +125 -54
  342. package/src/services/SSOService.test.ts +119 -0
  343. package/src/services/SSOService.ts +56 -49
  344. package/src/services/STPackageService.ts +97 -68
  345. package/src/services/UniqueMemberNumberService.ts +69 -0
  346. package/src/services/UniqueUserService.ts +3 -6
  347. package/src/services/VATService.ts +85 -0
  348. package/src/services/data/invoice.hbs.html +686 -0
  349. package/src/services/uitpas/PassholderEndpoints.ts +3 -6
  350. package/src/services/uitpas/UitpasService.ts +6 -10
  351. package/src/services/uitpas/checkUitpasNumbers.ts +2 -4
  352. package/src/services/uitpas/getSocialTariffForUitpasNumbers.ts +3 -6
  353. package/src/services/uitpas/searchUitpasEvents.ts +1 -2
  354. package/src/sql-filters/audit-logs.ts +1 -1
  355. package/src/sql-filters/balance-item-payments.ts +1 -1
  356. package/src/sql-filters/balance-items.ts +1 -1
  357. package/src/sql-filters/base-registration-filter-compilers.ts +5 -33
  358. package/src/sql-filters/document-templates.ts +1 -1
  359. package/src/sql-filters/documents.ts +1 -1
  360. package/src/sql-filters/email-recipients.ts +1 -1
  361. package/src/sql-filters/emails.ts +1 -1
  362. package/src/sql-filters/event-notifications.ts +1 -1
  363. package/src/sql-filters/events.ts +6 -1
  364. package/src/sql-filters/groups.ts +16 -1
  365. package/src/sql-filters/invoiced-balance-items.ts +1 -1
  366. package/src/sql-filters/invoices.ts +1 -1
  367. package/src/sql-filters/member-responsibility-records.ts +1 -1
  368. package/src/sql-filters/members.ts +1 -1
  369. package/src/sql-filters/orders.ts +4 -4
  370. package/src/sql-filters/organization-registration-periods.ts +1 -1
  371. package/src/sql-filters/organizations.ts +1 -1
  372. package/src/sql-filters/payments.ts +5 -0
  373. package/src/sql-filters/platform-memberships.ts +3 -3
  374. package/src/sql-filters/receivable-balances.ts +1 -1
  375. package/src/sql-filters/registration-invitations.ts +90 -0
  376. package/src/sql-filters/registration-periods.ts +1 -1
  377. package/src/sql-filters/registrations.ts +1 -1
  378. package/src/sql-filters/tickets.ts +1 -1
  379. package/src/sql-filters/users.ts +1 -1
  380. package/src/sql-sorters/groups.ts +23 -0
  381. package/src/sql-sorters/platform-memberships.ts +16 -16
  382. package/src/sql-sorters/registration-invitations.ts +36 -0
  383. package/tests/actions/patchOrganizationMember.ts +1 -1
  384. package/tests/actions/patchUserMember.ts +1 -1
  385. package/tests/assertions/assertBalances.ts +6 -12
  386. package/tests/e2e/api-rate-limits.test.ts +12 -24
  387. package/tests/e2e/bundle-discounts.test.ts +4 -1
  388. package/tests/e2e/charge-members.test.ts +13 -11
  389. package/tests/e2e/documents.test.ts +4 -1
  390. package/tests/e2e/register.test.ts +7 -9
  391. package/tests/e2e/stock.test.ts +4 -3
  392. package/tests/e2e/tickets.test.ts +1 -1
  393. package/tests/helpers/MollieMocker.ts +462 -0
  394. package/tests/helpers/PayconiqMocker.ts +138 -45
  395. package/tests/helpers/StripeMocker.ts +9 -6
  396. package/tests/helpers/index.ts +4 -0
  397. package/tests/init/initAdmin.ts +2 -2
  398. package/tests/init/initBundleDiscount.ts +1 -1
  399. package/tests/init/initMembershipOrganization.ts +13 -0
  400. package/tests/init/initPermissionRole.ts +3 -4
  401. package/tests/vitest.global.setup.ts +1 -1
  402. package/vitest.config.js +7 -0
  403. package/.nvmrc +0 -1
  404. package/src/endpoints/global/billing/ActivatePackagesEndpoint.ts +0 -216
  405. package/src/helpers/GroupBuilder.ts +0 -418
  406. package/src/seeds/0000000000-example.ts +0 -11
  407. package/src/seeds/1722256498-group-update-occupancy.ts +0 -52
  408. package/src/seeds/1726572303-schedule-stock-updates.ts +0 -52
  409. package/src/seeds/1726847064-setup-steps.ts +0 -16
  410. package/src/seeds/1728928974-update-cached-outstanding-balance-from-items.ts +0 -31
  411. package/src/seeds/1729253172-update-orders.ts +0 -21
  412. package/src/seeds/1733319079-fill-paying-organization-ids.ts +0 -68
  413. package/src/seeds/1733748412-update-deleted-order-numbers.ts +0 -109
  414. package/src/seeds/1733994455-balance-item-status-open.ts +0 -30
  415. package/src/seeds/1740046783-update-membership.ts +0 -17
  416. package/src/seeds/1741008870-fix-auditlog-description.ts +0 -50
  417. package/src/seeds/1741011468-fix-auditlog-description-uft16.ts +0 -88
  418. package/src/seeds/1741268179-fix-group-dates-of-events.ts +0 -32
  419. package/src/seeds/1750090030-records-configuration.ts +0 -26
  420. package/src/seeds/1751445358-upload-email-attachments.ts +0 -106
  421. package/src/seeds/1755532883-update-email-sender-ids.ts +0 -47
  422. package/src/seeds/1755790070-fill-email-recipient-errors.ts +0 -96
  423. package/src/seeds/1756115432-remove-old-drafts.ts +0 -16
  424. package/src/seeds/1756115433-fill-email-recipient-organization-id.ts +0 -30
  425. package/src/seeds/1756303697-update-email-counts.ts +0 -76
  426. package/src/seeds/1761665607-sync-member-users.ts +0 -59
  427. package/src/seeds/1765896674-document-update-year.ts +0 -66
  428. /package/src/{seeds → migrations}/0000000001-development-user.ts +0 -0
  429. /package/src/{seeds → migrations}/0000000002-clear-stamhoofd-email-templates.ts +0 -0
  430. /package/src/{seeds → migrations}/0000000003-default-email-templates.ts +0 -0
  431. /package/src/{seeds → migrations}/1752848561-groups-registration-periods.test.ts +0 -0
  432. /package/src/{seeds → migrations}/1766150402-document-published-at.test.ts +0 -0
  433. /package/src/{seeds → migrations}/1766150402-document-published-at.ts +0 -0
  434. /package/src/{seeds → migrations}/data/default-email-templates.sql +0 -0
@@ -17,10 +17,10 @@ async function updateCachedBalances() {
17
17
  * Cached balances of member should be updated before the cached balances of the user
18
18
  * because the cached balances of the user are dependent on the cached balances of the member.
19
19
  */
20
- .orderBy('objectType', 'ASC')
20
+ .orderBy('objectType', 'ASC')
21
21
  // minimize the number of queries when updating
22
- .orderBy('organizationId', 'ASC')
23
- .limit(100).fetch();
22
+ .orderBy('organizationId', 'ASC')
23
+ .limit(100).fetch();
24
24
 
25
25
  // Group by object type, next by organization id
26
26
  const grouped = new Map<ReceivableBalanceType, Map<string, CachedBalance[]>>();
@@ -51,7 +51,7 @@ async function updateCachedBalances() {
51
51
  const bIsMember = b[0] === ReceivableBalanceType.member;
52
52
  if (aIsMember && !bIsMember) return -1;
53
53
  if (!aIsMember && bIsMember) return 1;
54
- return 0;
54
+ return 0;
55
55
  });
56
56
 
57
57
  for (const [objectType, organizationMap] of objectTypeMemberFirst) {
package/src/crons.ts CHANGED
@@ -1,9 +1,8 @@
1
1
  import { Database } from '@simonbackx/simple-database';
2
+ import { registerCron } from '@stamhoofd/crons';
2
3
  import { Group, Organization, Payment, Registration, STPackage, Webshop } from '@stamhoofd/models';
3
- import { PaymentMethod, PaymentProvider, PaymentStatus } from '@stamhoofd/structures';
4
- import { Formatter } from '@stamhoofd/utility';
5
4
  import { SQL } from '@stamhoofd/sql';
6
- import { registerCron } from '@stamhoofd/crons';
5
+ import { PaymentMethod, PaymentProvider, PaymentStatus } from '@stamhoofd/structures';
7
6
  import { checkSettlements } from './helpers/CheckSettlements.js';
8
7
  import { PaymentService } from './services/PaymentService.js';
9
8
  import { RegistrationService } from './services/RegistrationService.js';
@@ -41,8 +40,7 @@ async function checkDNS() {
41
40
  }
42
41
  try {
43
42
  await organization.updateDNSRecords();
44
- }
45
- catch (e) {
43
+ } catch (e) {
46
44
  console.error(e);
47
45
  }
48
46
  }
@@ -123,19 +121,22 @@ async function checkWebshopDNS() {
123
121
 
124
122
  // 11 min - 2 hours
125
123
  async function checkPayments() {
124
+ let timeout = 60 * 1000 * 11;
125
+ const methods = [
126
+ PaymentMethod.Bancontact, PaymentMethod.iDEAL, PaymentMethod.Payconiq, PaymentMethod.CreditCard,
127
+ ];
128
+
126
129
  if (STAMHOOFD.environment === 'development') {
127
- // return;
130
+ // For Mollie, webhooks won't work, so we poll in the backend
131
+ timeout = 0;
128
132
  }
129
133
 
130
- const timeout = 60 * 1000 * 11;
131
134
  const timeout2 = 60 * 1000 * 60 * 2;
132
135
 
133
136
  // TODO: only select the ID + organizationId
134
137
  const payments = await Payment.select()
135
138
  .where(
136
- SQL.where('method', [
137
- PaymentMethod.Bancontact, PaymentMethod.iDEAL, PaymentMethod.Payconiq, PaymentMethod.CreditCard,
138
- ])
139
+ SQL.where('method', methods)
139
140
  .and('status', [PaymentStatus.Created, PaymentStatus.Pending])
140
141
  .and('createdAt', '<', new Date(new Date().getTime() - timeout))
141
142
  .and('createdAt', '>', new Date(new Date().getTime() - timeout2)),
@@ -152,9 +153,10 @@ async function checkPayments() {
152
153
  .orderBy('createdAt', 'ASC')
153
154
  .limit(500)
154
155
  .fetch();
155
-
156
- console.log('[DELAYED PAYMENTS] Checking pending payments: ' + payments.length);
157
- await doCheckPayments(payments);
156
+ if (payments.length) {
157
+ console.log('[DELAYED PAYMENTS] Checking pending payments: ' + payments.length);
158
+ await doCheckPayments(payments);
159
+ }
158
160
  }
159
161
 
160
162
  // 2 hours - 3 days
@@ -180,8 +182,40 @@ async function checkOldPayments() {
180
182
  .limit(500)
181
183
  .fetch();
182
184
 
183
- console.log('[DELAYED PAYMENTS] Checking old pending payments: ' + payments.length);
184
- await doCheckPayments(payments);
185
+ if (payments.length) {
186
+ console.log('[DELAYED PAYMENTS] Checking old pending payments: ' + payments.length);
187
+ await doCheckPayments(payments);
188
+ }
189
+ }
190
+
191
+ // 5 days - 10 days
192
+ async function checkOldDirectDebitPayments() {
193
+ let timeout = 60 * 1000 * 60 * 24 * 5;
194
+ const timeout2 = 60 * 1000 * 60 * 24 * 10;
195
+
196
+ if (STAMHOOFD.environment === 'development') {
197
+ // For Mollie, webhooks won't work, so we poll in the backend
198
+ timeout = 0;
199
+ }
200
+
201
+ // TODO: only select the ID + organizationId
202
+ const payments = await Payment.select()
203
+ .where(
204
+ SQL.where('method', [
205
+ PaymentMethod.DirectDebit,
206
+ ])
207
+ .and('status', [PaymentStatus.Created, PaymentStatus.Pending])
208
+ .and('createdAt', '<', new Date(new Date().getTime() - timeout))
209
+ .and('createdAt', '>', new Date(new Date().getTime() - timeout2)),
210
+ )
211
+ .orderBy('createdAt', 'ASC')
212
+ .limit(500)
213
+ .fetch();
214
+
215
+ if (payments.length) {
216
+ console.log('[DELAYED PAYMENTS] Checking old direct debit pending payments: ' + payments.length);
217
+ await doCheckPayments(payments);
218
+ }
185
219
  }
186
220
 
187
221
  async function doCheckPayments(payments: Payment[]) {
@@ -193,8 +227,7 @@ async function doCheckPayments(payments: Payment[]) {
193
227
  await PaymentService.pollStatus(payment.id, organization);
194
228
  continue;
195
229
  }
196
- }
197
- else {
230
+ } else {
198
231
  // deprecated
199
232
  }
200
233
 
@@ -204,8 +237,7 @@ async function doCheckPayments(payments: Payment[]) {
204
237
  payment.status = PaymentStatus.Failed;
205
238
  await payment.save();
206
239
  }
207
- }
208
- catch (e) {
240
+ } catch (e) {
209
241
  console.error(e);
210
242
  }
211
243
  }
@@ -267,8 +299,7 @@ async function checkFailedBuckarooPayments() {
267
299
  continue;
268
300
  }
269
301
  }
270
- }
271
- catch (e) {
302
+ } catch (e) {
272
303
  console.error(e);
273
304
  }
274
305
  }
@@ -276,8 +307,7 @@ async function checkFailedBuckarooPayments() {
276
307
  if (payments.length === 0) {
277
308
  didCheckBuckaroo = true;
278
309
  lastBuckarooId = '';
279
- }
280
- else {
310
+ } else {
281
311
  lastBuckarooId = payments[payments.length - 1].id;
282
312
  }
283
313
  }
@@ -325,56 +355,6 @@ async function checkReservedUntil() {
325
355
  }
326
356
  }
327
357
 
328
- let lastDripCheck: Date | null = null;
329
- let lastDripId = '';
330
- async function checkDrips() {
331
- if (STAMHOOFD.environment === 'development') {
332
- return;
333
- }
334
-
335
- if (STAMHOOFD.userMode === 'platform') {
336
- return;
337
- }
338
-
339
- if (lastDripCheck && lastDripCheck > new Date(new Date().getTime() - 6 * 60 * 60 * 1000)) {
340
- console.log('Skip Drip check');
341
- return;
342
- }
343
-
344
- // Only send emails between 8:00 - 18:00 CET
345
- const CETTime = Formatter.timeIso(new Date());
346
- if ((CETTime < '08:00' || CETTime > '18:00') && STAMHOOFD.environment === 'production') {
347
- console.log('Skip Drip check: outside hours');
348
- return;
349
- }
350
-
351
- const organizations = await Organization.where({ id: { sign: '>', value: lastDripId } }, {
352
- limit: STAMHOOFD.environment === 'production' ? 30 : 100,
353
- sort: ['id'],
354
- });
355
-
356
- if (organizations.length == 0) {
357
- // Wait before starting again
358
- lastDripId = '';
359
- lastDripCheck = new Date();
360
- return;
361
- }
362
-
363
- console.log('Checking drips...');
364
-
365
- for (const organization of organizations) {
366
- console.log(organization.name);
367
- try {
368
- await organization.checkDrips();
369
- }
370
- catch (e) {
371
- console.error(e);
372
- }
373
- }
374
-
375
- lastDripId = organizations[organizations.length - 1].id;
376
- }
377
-
378
358
  registerCron('checkSettlements', checkSettlements);
379
359
  registerCron('checkExpirationEmails', checkExpirationEmails);
380
360
  registerCron('checkReservedUntil', checkReservedUntil);
@@ -382,7 +362,7 @@ registerCron('checkDNS', checkDNS);
382
362
  registerCron('checkWebshopDNS', checkWebshopDNS);
383
363
  registerCron('checkPayments', checkPayments);
384
364
  registerCron('checkOldPayments', checkOldPayments);
385
- registerCron('checkDrips', checkDrips);
365
+ registerCron('checkOldDirectDebitPayments', checkOldDirectDebitPayments);
386
366
 
387
367
  // Register other crons
388
368
  import './crons/index.js';
package/src/debug.ts CHANGED
@@ -10,8 +10,10 @@ import { SQLLogger } from '@stamhoofd/sql';
10
10
  import { ContextInstance } from './helpers/Context.js';
11
11
 
12
12
  export function loadDebugFunctions({ routerServer }: { routerServer: RouterServer }) {
13
- SQLLogger.slowQueryThresholdMs = 75;
14
- SQLLogger.explainAllAndLogInefficient = true;
13
+ if (process.env.LOG_SLOW_QUERIES) {
14
+ SQLLogger.slowQueryThresholdMs = 75;
15
+ SQLLogger.explainAllAndLogInefficient = true;
16
+ }
15
17
 
16
18
  if (process.env.LOG_REQUEST_QUERIES) {
17
19
  loadRequestQueries({ routerServer });
@@ -1,6 +1,6 @@
1
1
  import { Email, Member } from '@stamhoofd/models';
2
2
  import { SQL } from '@stamhoofd/sql';
3
- import type { LimitedFilteredRequest} from '@stamhoofd/structures';
3
+ import type { LimitedFilteredRequest } from '@stamhoofd/structures';
4
4
  import { EmailRecipient, EmailRecipientFilterType, PaginatedResponse, Replacement } from '@stamhoofd/structures';
5
5
  import { GetDocumentsEndpoint } from '../endpoints/organization/dashboard/documents/GetDocumentsEndpoint.js';
6
6
 
@@ -1,6 +1,6 @@
1
1
  import { Email } from '@stamhoofd/models';
2
2
  import { SQL } from '@stamhoofd/sql';
3
- import type { EmailRecipient, LimitedFilteredRequest, MembersBlob} from '@stamhoofd/structures';
3
+ import type { EmailRecipient, LimitedFilteredRequest, MembersBlob } from '@stamhoofd/structures';
4
4
  import { EmailRecipientFilterType, PaginatedResponse, mergeFilters } from '@stamhoofd/structures';
5
5
  import { GetMembersEndpoint } from '../endpoints/global/members/GetMembersEndpoint.js';
6
6
 
@@ -1,4 +1,4 @@
1
- import type { RecipientLoader} from '@stamhoofd/models';
1
+ import type { RecipientLoader } from '@stamhoofd/models';
2
2
  import { BalanceItem, BalanceItemPayment, Email, Member, MemberResponsibilityRecord, Order, Organization, Payment, User, Webshop } from '@stamhoofd/models';
3
3
  import { compileToSQLFilter, SQL } from '@stamhoofd/sql';
4
4
  import type { LimitedFilteredRequest, PaymentGeneral, StamhoofdFilter } from '@stamhoofd/structures';
@@ -14,15 +14,6 @@ type BeforeFetchAllResult = {
14
14
  areAllPaymentsTransfers: boolean;
15
15
  };
16
16
 
17
- async function fetchPaymentRecipients(query: LimitedFilteredRequest, subfilter: StamhoofdFilter, beforeFetchAllResult?: BeforeFetchAllResult) {
18
- const result = await GetPaymentsEndpoint.buildData(query);
19
-
20
- return new PaginatedResponse({
21
- results: await getRecipients(result, EmailRecipientFilterType.Payment, subfilter, beforeFetchAllResult),
22
- next: result.next,
23
- });
24
- }
25
-
26
17
  const paymentRecipientLoader: RecipientLoader<BeforeFetchAllResult> = {
27
18
  beforeFetchAll: async (query: LimitedFilteredRequest) => {
28
19
  const doesIncludePaymentWithoutOrders = await doesQueryIncludePaymentsWithoutOrder(query);
@@ -39,9 +30,9 @@ const paymentRecipientLoader: RecipientLoader<BeforeFetchAllResult> = {
39
30
  const q = await GetPaymentsEndpoint.buildQuery(query);
40
31
  const base = await q.count();
41
32
 
42
- if (base < 1000) {
33
+ if (base < 100) {
43
34
  // Do full scan
44
- query.limit = 1000;
35
+ query.limit = 100;
45
36
  const result = await fetchPaymentRecipients(query, _subfilter);
46
37
  return result.results.length;
47
38
  }
@@ -52,6 +43,36 @@ const paymentRecipientLoader: RecipientLoader<BeforeFetchAllResult> = {
52
43
 
53
44
  Email.recipientLoaders.set(EmailRecipientFilterType.Payment, paymentRecipientLoader);
54
45
 
46
+ const paymentOrganizationRecipientLoader: RecipientLoader<BeforeFetchAllResult> = {
47
+ fetch: async (query: LimitedFilteredRequest, subfilter: StamhoofdFilter | null, beforeFetchAllResult) => fetchPaymentOrganizationRecipients(query, subfilter, beforeFetchAllResult),
48
+
49
+ // For now: only count the number of payments - not the amount of emails
50
+ count: async (query: LimitedFilteredRequest, _subfilter) => {
51
+ const q = await GetPaymentsEndpoint.buildQuery(query);
52
+ const base = await q.count();
53
+
54
+ if (base < 100) {
55
+ // Do full scan
56
+ query.limit = 100;
57
+ const result = await fetchPaymentOrganizationRecipients(query, _subfilter);
58
+ return result.results.length;
59
+ }
60
+
61
+ return base;
62
+ },
63
+ };
64
+
65
+ Email.recipientLoaders.set(EmailRecipientFilterType.PaymentOrganization, paymentOrganizationRecipientLoader);
66
+
67
+ async function fetchPaymentRecipients(query: LimitedFilteredRequest, subfilter: StamhoofdFilter, beforeFetchAllResult?: BeforeFetchAllResult) {
68
+ const result = await GetPaymentsEndpoint.buildData(query);
69
+
70
+ return new PaginatedResponse({
71
+ results: await getRecipients(result, EmailRecipientFilterType.Payment, subfilter, beforeFetchAllResult),
72
+ next: result.next,
73
+ });
74
+ }
75
+
55
76
  async function doesQueryIncludePaymentsWithoutOrder(filterRequest: LimitedFilteredRequest) {
56
77
  // create count request (without limit and page filter)
57
78
  const countRequest = new CountFilteredRequest({
@@ -113,17 +134,6 @@ async function fetchPaymentOrganizationRecipients(query: LimitedFilteredRequest,
113
134
  });
114
135
  }
115
136
 
116
- const paymentOrganizationRecipientLoader: RecipientLoader<BeforeFetchAllResult> = {
117
- fetch: async (query: LimitedFilteredRequest, subfilter: StamhoofdFilter | null, beforeFetchAllResult) => fetchPaymentOrganizationRecipients(query, subfilter, beforeFetchAllResult),
118
- // For now: only count the number of payments - not the amount of emails
119
- count: async (query: LimitedFilteredRequest, subfilter: StamhoofdFilter | null) => {
120
- const q = await GetPaymentsEndpoint.buildQuery(query);
121
- return await q.count();
122
- },
123
- };
124
-
125
- Email.recipientLoaders.set(EmailRecipientFilterType.PaymentOrganization, paymentOrganizationRecipientLoader);
126
-
127
137
  async function getRecipients(result: PaginatedResponse<PaymentGeneral[], LimitedFilteredRequest>, type: EmailRecipientFilterType.Payment | EmailRecipientFilterType.PaymentOrganization, subFilter: StamhoofdFilter | null, beforeFetchAllResult: BeforeFetchAllResult | undefined) {
128
138
  const recipients: EmailRecipient[] = [];
129
139
  const userIds: { userId: string; payment: PaymentGeneral }[] = [];
@@ -196,8 +206,7 @@ async function getRecipients(result: PaginatedResponse<PaymentGeneral[], Limited
196
206
  recipients.push(...await getUserRecipients(userIds, replacementOptions));
197
207
  recipients.push(...await getMemberRecipients(memberIds, replacementOptions));
198
208
  recipients.push(...await getOrderRecipients(orderIds, replacementOptions));
199
- }
200
- else {
209
+ } else {
201
210
  recipients.push(...await getOrganizationRecipients(organizationIds, replacementOptions, subFilter));
202
211
  }
203
212
 
@@ -263,8 +272,7 @@ async function getMembersForOrganizations(organizationIds: string[], filter: Sta
263
272
  const membersForOrganization = result.get(organizationId);
264
273
  if (membersForOrganization) {
265
274
  membersForOrganization.push(member);
266
- }
267
- else {
275
+ } else {
268
276
  result.set(organizationId, [member]);
269
277
  }
270
278
  }
@@ -273,7 +281,7 @@ async function getMembersForOrganizations(organizationIds: string[], filter: Sta
273
281
  }
274
282
 
275
283
  async function getOrganizationRecipients(ids: { organizationId: string; payment: PaymentGeneral }[], replacementOptions: ReplacementsOptions, subFilter: StamhoofdFilter | null): Promise<EmailRecipient[]> {
276
- if (ids.length === 0 || subFilter === null) {
284
+ if (ids.length === 0) {
277
285
  return [];
278
286
  }
279
287
 
@@ -287,32 +295,65 @@ async function getOrganizationRecipients(ids: { organizationId: string; payment:
287
295
  organizationMap.set(organization.id, organization);
288
296
  }
289
297
 
290
- const membersForOrganizations = await getMembersForOrganizations(allOrganizationIds, subFilter);
291
-
292
298
  const results: EmailRecipient[] = [];
293
299
 
294
- for (const { organizationId, payment } of ids) {
295
- const organization = organizationMap.get(organizationId);
300
+ if (subFilter === null) {
301
+ // Use full admins instead
302
+ const admins = await User.getAdmins(allOrganizationIds, { verified: true });
303
+ for (const { organizationId, payment } of ids) {
304
+ const organization = organizationMap.get(organizationId);
305
+ if (!organization) {
306
+ continue;
307
+ }
308
+ const users = admins.filter(a => a.permissions?.forOrganization(organization)?.hasFullAccess());
296
309
 
297
- if (organization) {
298
- const members = membersForOrganizations.get(organizationId);
299
- if (!members) {
310
+ if (users.length === 0) {
311
+ console.warn('No admins found for organization with id ', organizationId, ' while fetching email recipients for payment with id ', payment.id);
300
312
  continue;
301
313
  }
302
314
 
303
315
  const replacements = getEmailReplacementsForPayment(payment, replacementOptions);
304
316
 
305
- for (const member of members) {
306
- for (const email of member.details.getNotificationEmails()) {
307
- results.push(EmailRecipient.create({
308
- objectId: payment.id,
309
- name: organization.name,
310
- memberId: member.id,
311
- firstName: member.details.firstName,
312
- lastName: member.details.lastName,
313
- email,
314
- replacements,
315
- }));
317
+ for (const user of users) {
318
+ results.push(EmailRecipient.create({
319
+ objectId: payment.id,
320
+ name: organization.name,
321
+ userId: user.id,
322
+ firstName: user.firstName,
323
+ lastName: user.lastName,
324
+ email: user.email,
325
+ replacements,
326
+ }));
327
+ }
328
+ }
329
+ } else {
330
+ const membersForOrganizations = await getMembersForOrganizations(allOrganizationIds, subFilter);
331
+
332
+ for (const { organizationId, payment } of ids) {
333
+ const organization = organizationMap.get(organizationId);
334
+
335
+ if (organization) {
336
+ const members = membersForOrganizations.get(organizationId);
337
+ if (!members || members.length === 0) {
338
+ // Use admins by default
339
+
340
+ continue;
341
+ }
342
+
343
+ const replacements = getEmailReplacementsForPayment(payment, replacementOptions);
344
+
345
+ for (const member of members) {
346
+ for (const email of member.details.getNotificationEmails()) {
347
+ results.push(EmailRecipient.create({
348
+ objectId: payment.id,
349
+ name: organization.name,
350
+ memberId: member.id,
351
+ firstName: member.details.firstName,
352
+ lastName: member.details.lastName,
353
+ email,
354
+ replacements,
355
+ }));
356
+ }
316
357
  }
317
358
  }
318
359
  }
@@ -1,6 +1,6 @@
1
1
  import { Email, Member } from '@stamhoofd/models';
2
2
  import { SQL } from '@stamhoofd/sql';
3
- import type { EmailRecipient, LimitedFilteredRequest, RegistrationsBlob} from '@stamhoofd/structures';
3
+ import type { EmailRecipient, LimitedFilteredRequest, RegistrationsBlob } from '@stamhoofd/structures';
4
4
  import { EmailRecipientFilterType, PaginatedResponse, mergeFilters } from '@stamhoofd/structures';
5
5
  import { GetRegistrationsEndpoint } from '../endpoints/global/registration/GetRegistrationsEndpoint.js';
6
6
  import { memberJoin } from '../sql-filters/registrations.js';
@@ -1,5 +1,5 @@
1
1
  import { Order, Organization, Webshop } from '@stamhoofd/models';
2
- import type { BalanceItemPaymentsHtmlTableItem, PaymentGeneral} from '@stamhoofd/structures';
2
+ import type { BalanceItemPaymentsHtmlTableItem, PaymentGeneral } from '@stamhoofd/structures';
3
3
  import { BalanceItemRelationType, BalanceItemType, getBalanceItemPaymentsHtmlTable, PaymentMethod, PaymentMethodHelper, Replacement, Webshop as WebshopStruct } from '@stamhoofd/structures';
4
4
  import { Formatter } from '@stamhoofd/utility';
5
5
  import { createOrderDataHTMLTable } from '../helpers/email-html-helpers.js';
@@ -106,8 +106,7 @@ export function getEmailReplacementsForPayment(payment: PaymentGeneral, options:
106
106
  });
107
107
  paymentUrl = 'https://' + webshopStruct.getUrl(organization) + '/order/' + (singleOrder.id);
108
108
  }
109
- }
110
- else {
109
+ } else {
111
110
  // Fallback (should not happen, but better than leaving {{orderUrl}} in place)
112
111
  orderUrlReplacement = Replacement.create({
113
112
  token: 'orderUrl',
@@ -221,12 +220,10 @@ function getPaymentContext(payment: PaymentGeneral, { orderMap, webshopMap }: Re
221
220
  webshop: webshop.meta.name,
222
221
  orderNumber: order.number ?? '',
223
222
  }));
224
- }
225
- else {
223
+ } else {
226
224
  overviewContext.add(webshop.meta.name);
227
225
  }
228
- }
229
- else {
226
+ } else {
230
227
  overviewContext.add($t('%1L0', {
231
228
  orderNumber: order.number ?? '',
232
229
  }));
@@ -239,8 +236,7 @@ function getPaymentContext(payment: PaymentGeneral, { orderMap, webshopMap }: Re
239
236
  const memberName = balanceItem.relations.get(BalanceItemRelationType.Member)?.name.toString();
240
237
  if (memberName) {
241
238
  registrationMemberNames.add(memberName);
242
- }
243
- else {
239
+ } else {
244
240
  overviewContext.add(balanceItem.itemTitle);
245
241
  }
246
242
 
@@ -1,5 +1,5 @@
1
1
  import type { Decoder } from '@simonbackx/simple-encoding';
2
- import type { DecodedRequest, Request} from '@simonbackx/simple-endpoints';
2
+ import type { DecodedRequest, Request } from '@simonbackx/simple-endpoints';
3
3
  import { Endpoint, Response } from '@simonbackx/simple-endpoints';
4
4
  import { SimpleError } from '@simonbackx/simple-errors';
5
5
  import { ChargeRequest, LimitedFilteredRequest, PermissionLevel } from '@stamhoofd/structures';
@@ -1,4 +1,4 @@
1
- import type { DecodedRequest, Request} from '@simonbackx/simple-endpoints';
1
+ import type { DecodedRequest, Request } from '@simonbackx/simple-endpoints';
2
2
  import { Endpoint, Response } from '@simonbackx/simple-endpoints';
3
3
  import { SimpleError } from '@simonbackx/simple-errors';
4
4
  import { QueueHandler } from '@stamhoofd/queues';
@@ -1,4 +1,4 @@
1
- import type { DecodedRequest, Request} from '@simonbackx/simple-endpoints';
1
+ import type { DecodedRequest, Request } from '@simonbackx/simple-endpoints';
2
2
  import { Endpoint, Response } from '@simonbackx/simple-endpoints';
3
3
  import { Platform } from '@stamhoofd/models';
4
4
  import { QueueHandler } from '@stamhoofd/queues';
@@ -107,8 +107,7 @@ export class GetChargeMembershipsSummaryEndpoint extends Endpoint<Params, Query,
107
107
 
108
108
  if (!trial) {
109
109
  query.where(noTrial);
110
- }
111
- else {
110
+ } else {
112
111
  query.whereNot(noTrial);
113
112
  }
114
113
 
@@ -174,8 +173,7 @@ export class GetChargeMembershipsSummaryEndpoint extends Endpoint<Params, Query,
174
173
 
175
174
  if (!trial) {
176
175
  query.where(trialQ);
177
- }
178
- else {
176
+ } else {
179
177
  query.whereNot(trialQ);
180
178
  }
181
179
 
@@ -1,5 +1,5 @@
1
1
  import type { Decoder } from '@simonbackx/simple-encoding';
2
- import type { DecodedRequest, Request} from '@simonbackx/simple-endpoints';
2
+ import type { DecodedRequest, Request } from '@simonbackx/simple-endpoints';
3
3
  import { Endpoint, Response } from '@simonbackx/simple-endpoints';
4
4
  import { SimpleError } from '@simonbackx/simple-errors';
5
5
  import { ChargeRequest, LimitedFilteredRequest } from '@stamhoofd/structures';
@@ -1,5 +1,5 @@
1
1
  import type { Decoder } from '@simonbackx/simple-encoding';
2
- import type { DecodedRequest, Request} from '@simonbackx/simple-endpoints';
2
+ import type { DecodedRequest, Request } from '@simonbackx/simple-endpoints';
3
3
  import { Endpoint, Response } from '@simonbackx/simple-endpoints';
4
4
  import { CountFilteredRequest, CountResponse } from '@stamhoofd/structures';
5
5
 
@@ -1,10 +1,10 @@
1
1
  import type { Decoder } from '@simonbackx/simple-encoding';
2
- import type { DecodedRequest, Request} from '@simonbackx/simple-endpoints';
2
+ import type { DecodedRequest, Request } from '@simonbackx/simple-endpoints';
3
3
  import { Endpoint, Response } from '@simonbackx/simple-endpoints';
4
4
  import { SimpleError } from '@simonbackx/simple-errors';
5
5
  import { Organization } from '@stamhoofd/models';
6
6
  import { SQL, applySQLSorter, compileToSQLFilter } from '@stamhoofd/sql';
7
- import type { CountFilteredRequest, Organization as OrganizationStruct, StamhoofdFilter} from '@stamhoofd/structures';
7
+ import type { CountFilteredRequest, Organization as OrganizationStruct, StamhoofdFilter } from '@stamhoofd/structures';
8
8
  import { LimitedFilteredRequest, PaginatedResponse, PermissionLevel, assertSort, getSortFilter } from '@stamhoofd/structures';
9
9
 
10
10
  import type { SQLResultNamespacedRow } from '@simonbackx/simple-database';
@@ -76,9 +76,16 @@ export class GetOrganizationsEndpoint extends Endpoint<Params, Query, Body, Resp
76
76
 
77
77
  // todo: auto detect e-mailaddresses and search on admins
78
78
  searchFilter = {
79
- name: {
80
- $contains: q.search,
81
- },
79
+ $or: [
80
+ {
81
+ name: {
82
+ $contains: q.search,
83
+ },
84
+ },
85
+ {
86
+ uri: q.search,
87
+ },
88
+ ],
82
89
  };
83
90
 
84
91
  if (searchFilter) {
@@ -125,8 +132,7 @@ export class GetOrganizationsEndpoint extends Endpoint<Params, Query, Body, Resp
125
132
 
126
133
  try {
127
134
  data = await query.fetch();
128
- }
129
- catch (error) {
135
+ } catch (error) {
130
136
  if (error.message.includes('ER_QUERY_TIMEOUT')) {
131
137
  throw new SimpleError({
132
138
  code: 'timeout',
@@ -1,6 +1,6 @@
1
- import type { AutoEncoderPatchType, Decoder, PatchableArrayAutoEncoder} from '@simonbackx/simple-encoding';
1
+ import type { AutoEncoderPatchType, Decoder, PatchableArrayAutoEncoder } from '@simonbackx/simple-encoding';
2
2
  import { PatchableArrayDecoder, StringDecoder } from '@simonbackx/simple-encoding';
3
- import type { DecodedRequest, Request} from '@simonbackx/simple-endpoints';
3
+ import type { DecodedRequest, Request } from '@simonbackx/simple-endpoints';
4
4
  import { Endpoint, Response } from '@simonbackx/simple-endpoints';
5
5
  import { SimpleError } from '@simonbackx/simple-errors';
6
6
  import { Organization, OrganizationRegistrationPeriod, Platform, RegistrationPeriod } from '@stamhoofd/models';
@@ -133,8 +133,7 @@ export class PatchOrganizationsEndpoint extends Endpoint<Params, Query, Body, Re
133
133
  if (STAMHOOFD.userMode === 'platform') {
134
134
  const periodId = (await Platform.getShared()).periodIdIfPlatform;
135
135
  organization.periodId = periodId;
136
- }
137
- else {
136
+ } else {
138
137
  period = new RegistrationPeriod();
139
138
  period.configureForNewOrganization();
140
139
  await period.save();
@@ -147,8 +146,7 @@ export class PatchOrganizationsEndpoint extends Endpoint<Params, Query, Body, Re
147
146
 
148
147
  try {
149
148
  await organization.save();
150
- }
151
- catch (e) {
149
+ } catch (e) {
152
150
  console.error(e);
153
151
  throw new SimpleError({
154
152
  code: 'creating_organization',