@stamhoofd/backend 2.115.1 → 2.117.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (284) hide show
  1. package/migrations.ts +1 -1
  2. package/package.json +10 -10
  3. package/src/audit-logs/DocumentTemplateLogger.ts +1 -1
  4. package/src/audit-logs/EmailAddressLogger.ts +1 -1
  5. package/src/audit-logs/EmailLogger.ts +1 -1
  6. package/src/audit-logs/EmailTemplateLogger.ts +1 -1
  7. package/src/audit-logs/EventLogger.ts +1 -1
  8. package/src/audit-logs/GroupLogger.ts +1 -1
  9. package/src/audit-logs/MemberLogger.ts +1 -1
  10. package/src/audit-logs/MemberPlatformMembershipLogger.ts +1 -1
  11. package/src/audit-logs/MemberResponsibilityRecordLogger.ts +1 -1
  12. package/src/audit-logs/ModelLogger.ts +27 -19
  13. package/src/audit-logs/OrderLogger.ts +1 -1
  14. package/src/audit-logs/OrganizationLogger.ts +23 -3
  15. package/src/audit-logs/OrganizationRegistrationPeriodLogger.ts +1 -1
  16. package/src/audit-logs/PaymentLogger.ts +1 -1
  17. package/src/audit-logs/PlatformLogger.ts +1 -1
  18. package/src/audit-logs/RegistrationLogger.ts +1 -1
  19. package/src/audit-logs/RegistrationPeriodLogger.ts +1 -1
  20. package/src/audit-logs/StripeAccountLogger.ts +1 -1
  21. package/src/audit-logs/UserLogger.ts +1 -1
  22. package/src/audit-logs/WebshopLogger.ts +1 -1
  23. package/src/audit-logs/init.ts +40 -0
  24. package/src/boot.ts +6 -4
  25. package/src/crons/amazon-ses.ts +1 -1
  26. package/src/crons/balance-emails.ts +1 -1
  27. package/src/crons/clearExcelCache.test.ts +1 -1
  28. package/src/crons/delete-archived-data.ts +47 -0
  29. package/src/crons/endFunctionsOfUsersWithoutRegistration.ts +1 -1
  30. package/src/crons/index.ts +1 -0
  31. package/src/crons.ts +3 -3
  32. package/src/debug.ts +230 -0
  33. package/src/email-recipient-loaders/documents.ts +1 -1
  34. package/src/email-recipient-loaders/members.ts +1 -1
  35. package/src/email-recipient-loaders/orders.ts +3 -3
  36. package/src/email-recipient-loaders/payments.ts +118 -353
  37. package/src/email-replacements/getEmailReplacementsForPayment.ts +321 -0
  38. package/src/endpoints/admin/members/ChargeMembersEndpoint.ts +9 -7
  39. package/src/endpoints/admin/memberships/ChargeMembershipsEndpoint.ts +2 -2
  40. package/src/endpoints/admin/memberships/GetChargeMembershipsSummaryEndpoint.ts +1 -1
  41. package/src/endpoints/admin/organizations/ChargeOrganizationsEndpoint.ts +16 -50
  42. package/src/endpoints/admin/organizations/GetOrganizationsCountEndpoint.ts +2 -2
  43. package/src/endpoints/admin/organizations/GetOrganizationsEndpoint.ts +4 -4
  44. package/src/endpoints/admin/organizations/PatchOrganizationsEndpoint.ts +21 -6
  45. package/src/endpoints/admin/registrations/ChargeRegistrationsEndpoint.ts +9 -7
  46. package/src/endpoints/auth/CreateAdminEndpoint.ts +2 -2
  47. package/src/endpoints/auth/CreateTokenEndpoint.test.ts +2 -2
  48. package/src/endpoints/auth/CreateTokenEndpoint.ts +1 -1
  49. package/src/endpoints/auth/DeleteTokenEndpoint.ts +1 -1
  50. package/src/endpoints/auth/DeleteUserEndpoint.ts +1 -1
  51. package/src/endpoints/auth/ForgotPasswordEndpoint.ts +1 -1
  52. package/src/endpoints/auth/GetOtherUserEndpoint.ts +2 -2
  53. package/src/endpoints/auth/GetUserEndpoint.test.ts +2 -2
  54. package/src/endpoints/auth/GetUserEndpoint.ts +2 -2
  55. package/src/endpoints/auth/OpenIDConnectAuthTokenEndpoint.ts +2 -2
  56. package/src/endpoints/auth/OpenIDConnectCallbackEndpoint.ts +2 -2
  57. package/src/endpoints/auth/OpenIDConnectStartEndpoint.ts +2 -2
  58. package/src/endpoints/auth/PatchUserEndpoint.ts +4 -4
  59. package/src/endpoints/auth/PollEmailVerificationEndpoint.ts +1 -1
  60. package/src/endpoints/auth/RetryEmailVerificationEndpoint.ts +1 -1
  61. package/src/endpoints/auth/SignupEndpoint.ts +1 -1
  62. package/src/endpoints/auth/VerifyEmailEndpoint.ts +1 -1
  63. package/src/endpoints/global/addresses/ValidateAddressEndpoint.ts +1 -1
  64. package/src/endpoints/global/audit-logs/GetAuditLogsEndpoint.ts +4 -4
  65. package/src/endpoints/global/billing/ActivatePackagesEndpoint.ts +191 -7
  66. package/src/endpoints/global/billing/DeactivatePackageEndpoint.ts +64 -0
  67. package/src/endpoints/global/email/GetAdminEmailsEndpoint.test.ts +2 -2
  68. package/src/endpoints/global/email/GetAdminEmailsEndpoint.ts +3 -3
  69. package/src/endpoints/global/email/GetEmailAddressEndpoint.ts +1 -1
  70. package/src/endpoints/global/email/GetEmailEndpoint.ts +1 -1
  71. package/src/endpoints/global/email/GetUserEmailsEndpoint.test.ts +2 -2
  72. package/src/endpoints/global/email/GetUserEmailsEndpoint.ts +3 -3
  73. package/src/endpoints/global/email/ManageEmailAddressEndpoint.ts +62 -16
  74. package/src/endpoints/global/email/PatchEmailEndpoint.test.ts +6 -6
  75. package/src/endpoints/global/email-recipients/GetEmailRecipientsCountEndpoint.ts +2 -2
  76. package/src/endpoints/global/email-recipients/GetEmailRecipientsEndpoint.test.ts +2 -2
  77. package/src/endpoints/global/email-recipients/GetEmailRecipientsEndpoint.ts +4 -4
  78. package/src/endpoints/global/email-recipients/RetryEmailRecipientEndpoint.ts +1 -1
  79. package/src/endpoints/global/email-recipients/helpers/validateEmailRecipientFilter.ts +1 -1
  80. package/src/endpoints/global/events/GetEventNotificationsCountEndpoint.ts +2 -2
  81. package/src/endpoints/global/events/GetEventNotificationsEndpoint.ts +4 -4
  82. package/src/endpoints/global/events/GetEventsEndpoint.ts +4 -4
  83. package/src/endpoints/global/events/PatchEventNotificationsEndpoint.test.ts +2 -2
  84. package/src/endpoints/global/events/PatchEventNotificationsEndpoint.ts +3 -3
  85. package/src/endpoints/global/events/PatchEventsEndpoint.test.ts +2 -2
  86. package/src/endpoints/global/events/PatchEventsEndpoint.ts +5 -5
  87. package/src/endpoints/global/files/ExportToExcelEndpoint.ts +4 -4
  88. package/src/endpoints/global/files/GetFileCache.ts +2 -2
  89. package/src/endpoints/global/files/UploadFile.ts +2 -2
  90. package/src/endpoints/global/files/UploadImage.ts +1 -1
  91. package/src/endpoints/global/groups/GetGroupsEndpoint.test.ts +3 -3
  92. package/src/endpoints/global/groups/GetGroupsEndpoint.ts +4 -4
  93. package/src/endpoints/global/members/GetMemberFamilyEndpoint.ts +4 -4
  94. package/src/endpoints/global/members/GetMembersEndpoint.test.ts +3 -3
  95. package/src/endpoints/global/members/GetMembersEndpoint.ts +4 -16
  96. package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.ts +8 -7
  97. package/src/endpoints/global/members/helpers/validateGroupFilter.ts +1 -1
  98. package/src/endpoints/global/organizations/CreateOrganizationEndpoint.test.ts +2 -2
  99. package/src/endpoints/global/organizations/CreateOrganizationEndpoint.ts +23 -12
  100. package/src/endpoints/global/organizations/GetOrganizationFromDomainEndpoint.test.ts +2 -2
  101. package/src/endpoints/global/organizations/GetOrganizationFromDomainEndpoint.ts +1 -1
  102. package/src/endpoints/global/organizations/GetOrganizationFromUriEndpoint.ts +1 -1
  103. package/src/endpoints/global/organizations/SearchOrganizationEndpoint.test.ts +2 -2
  104. package/src/endpoints/global/organizations/SearchOrganizationEndpoint.ts +1 -1
  105. package/src/endpoints/global/payments/StripeWebhookEndpoint.ts +3 -3
  106. package/src/endpoints/global/platform/GetPlatformAdminsEndpoint.ts +1 -1
  107. package/src/endpoints/global/platform/GetPlatformEndpoint.test.ts +2 -2
  108. package/src/endpoints/global/platform/GetPlatformEndpoint.ts +1 -1
  109. package/src/endpoints/global/platform/PatchPlatformEnpoint.test.ts +2 -2
  110. package/src/endpoints/global/platform/PatchPlatformEnpoint.ts +7 -7
  111. package/src/endpoints/global/registration/GetRegistrationsEndpoint.test.ts +2 -2
  112. package/src/endpoints/global/registration/GetRegistrationsEndpoint.ts +1 -2
  113. package/src/endpoints/global/registration/GetUserDetailedPayableBalanceEndpoint.ts +2 -2
  114. package/src/endpoints/global/registration/GetUserDocumentsEndpoint.ts +2 -2
  115. package/src/endpoints/global/registration/GetUserMembersEndpoint.ts +2 -2
  116. package/src/endpoints/global/registration/GetUserPayableBalanceEndpoint.ts +2 -2
  117. package/src/endpoints/global/registration/RegisterMembersEndpoint.test.ts +2 -2
  118. package/src/endpoints/global/registration/RegisterMembersEndpoint.ts +24 -389
  119. package/src/endpoints/global/registration-periods/GetRegistrationPeriodsEndpoint.ts +3 -3
  120. package/src/endpoints/global/registration-periods/PatchRegistrationPeriodsEndpoint.ts +2 -2
  121. package/src/endpoints/global/sso/GetSSOEndpoint.ts +2 -2
  122. package/src/endpoints/global/sso/SetSSOEndpoint.ts +3 -3
  123. package/src/endpoints/organization/dashboard/balance-items/GetBalanceItemEndpoint.ts +55 -0
  124. package/src/endpoints/organization/dashboard/balance-items/GetBalanceItemsCountEndpoint.ts +43 -0
  125. package/src/endpoints/organization/dashboard/balance-items/GetBalanceItemsEndpoint.ts +160 -0
  126. package/src/endpoints/organization/dashboard/{payments → balance-items}/PatchBalanceItemsEndpoint.ts +1 -1
  127. package/src/endpoints/organization/dashboard/billing/GetOrganizationDetailedPayableBalanceEndpoint.ts +2 -2
  128. package/src/endpoints/organization/dashboard/billing/GetOrganizationPayableBalanceEndpoint.ts +2 -2
  129. package/src/endpoints/organization/dashboard/billing/GetPackagesEndpoint.test.ts +3 -3
  130. package/src/endpoints/organization/dashboard/billing/GetPackagesEndpoint.ts +3 -3
  131. package/src/endpoints/organization/dashboard/documents/GetDocumentTemplateXML.ts +1 -1
  132. package/src/endpoints/organization/dashboard/documents/GetDocumentsCountEndpoint.ts +2 -2
  133. package/src/endpoints/organization/dashboard/documents/PatchDocumentEndpoint.ts +2 -2
  134. package/src/endpoints/organization/dashboard/email/CheckEmailBouncesEndpoint.ts +37 -6
  135. package/src/endpoints/organization/dashboard/email-templates/GetEmailTemplatesEndpoint.test.ts +2 -2
  136. package/src/endpoints/organization/dashboard/email-templates/GetEmailTemplatesEndpoint.ts +3 -3
  137. package/src/endpoints/organization/dashboard/email-templates/PatchEmailTemplatesEndpoint.test.ts +2 -2
  138. package/src/endpoints/organization/dashboard/email-templates/PatchEmailTemplatesEndpoint.ts +1 -1
  139. package/src/endpoints/organization/dashboard/invoices/PatchInvoicesEndpoint.ts +53 -0
  140. package/src/endpoints/organization/dashboard/mollie/CheckMollieEndpoint.ts +2 -2
  141. package/src/endpoints/organization/dashboard/mollie/ConnectMollieEndpoint.ts +3 -3
  142. package/src/endpoints/organization/dashboard/mollie/DisconnectMollieEndpoint.ts +2 -2
  143. package/src/endpoints/organization/dashboard/mollie/GetMollieDashboardEndpoint.ts +1 -1
  144. package/src/endpoints/organization/dashboard/nolt/CreateNoltTokenEndpoint.ts +1 -1
  145. package/src/endpoints/organization/dashboard/organization/GetOrganizationArchivedGroups.ts +2 -2
  146. package/src/endpoints/organization/dashboard/organization/GetOrganizationDeletedGroups.ts +2 -2
  147. package/src/endpoints/organization/dashboard/organization/GetUitpasClientIdEndpoint.ts +2 -2
  148. package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.test.ts +2 -2
  149. package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.ts +12 -1
  150. package/src/endpoints/organization/dashboard/organization/SearchUitpasOrganizersEndpoint.ts +2 -2
  151. package/src/endpoints/organization/dashboard/organization/SetOrganizationDomainEndpoint.ts +2 -2
  152. package/src/endpoints/organization/dashboard/organization/SetUitpasClientCredentialsEndpoint.ts +2 -2
  153. package/src/endpoints/organization/dashboard/payments/GetPaymentsCountEndpoint.ts +2 -2
  154. package/src/endpoints/organization/dashboard/payments/GetPaymentsEndpoint.ts +4 -4
  155. package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalanceEndpoint.ts +12 -12
  156. package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalancesCountEndpoint.ts +2 -2
  157. package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalancesEndpoint.ts +4 -4
  158. package/src/endpoints/organization/dashboard/registration-periods/GetOrganizationRegistrationPeriodsEndpoint.test.ts +2 -2
  159. package/src/endpoints/organization/dashboard/registration-periods/GetOrganizationRegistrationPeriodsEndpoint.ts +4 -4
  160. package/src/endpoints/organization/dashboard/registration-periods/MoveRegistrationPeriods.test.ts +2 -2
  161. package/src/endpoints/organization/dashboard/registration-periods/PatchOrganizationRegistrationPeriodsEndpoint.test.ts +2 -2
  162. package/src/endpoints/organization/dashboard/registration-periods/PatchOrganizationRegistrationPeriodsEndpoint.ts +3 -3
  163. package/src/endpoints/organization/dashboard/registration-periods/SetupStepReviewEndpoint.ts +2 -2
  164. package/src/endpoints/organization/dashboard/stripe/ConnectStripeEndpoint.ts +3 -3
  165. package/src/endpoints/organization/dashboard/stripe/DeleteStripeAccountEndpoint.ts +3 -3
  166. package/src/endpoints/organization/dashboard/stripe/GetStripeAccountLinkEndpoint.ts +2 -2
  167. package/src/endpoints/organization/dashboard/stripe/GetStripeAccountsEndpoint.ts +1 -1
  168. package/src/endpoints/organization/dashboard/stripe/GetStripeLoginLinkEndpoint.ts +2 -2
  169. package/src/endpoints/organization/dashboard/stripe/UpdateStripeAccountEndpoint.ts +3 -3
  170. package/src/endpoints/organization/dashboard/users/CreateApiUserEndpoint.test.ts +3 -3
  171. package/src/endpoints/organization/dashboard/users/CreateApiUserEndpoint.ts +1 -1
  172. package/src/endpoints/organization/dashboard/users/DeleteUserEndpoint.ts +1 -1
  173. package/src/endpoints/organization/dashboard/users/GetApiUsersEndpoint.ts +1 -1
  174. package/src/endpoints/organization/dashboard/users/GetOrganizationAdminsEndpoint.ts +1 -1
  175. package/src/endpoints/organization/dashboard/users/PatchApiUserEndpoint.test.ts +3 -3
  176. package/src/endpoints/organization/dashboard/users/PatchApiUserEndpoint.ts +1 -1
  177. package/src/endpoints/organization/dashboard/webshops/CreateWebshopEndpoint.ts +1 -1
  178. package/src/endpoints/organization/dashboard/webshops/DeleteWebshopEndpoint.ts +2 -2
  179. package/src/endpoints/organization/dashboard/webshops/GetDiscountCodesEndpoint.ts +1 -1
  180. package/src/endpoints/organization/dashboard/webshops/GetWebshopOrdersCountEndpoint.ts +2 -2
  181. package/src/endpoints/organization/dashboard/webshops/GetWebshopOrdersEndpoint.ts +5 -5
  182. package/src/endpoints/organization/dashboard/webshops/GetWebshopTicketsEndpoint.ts +5 -5
  183. package/src/endpoints/organization/dashboard/webshops/GetWebshopUriAvailabilityEndpoint.ts +1 -1
  184. package/src/endpoints/organization/dashboard/webshops/PatchDiscountCodesEndpoint.ts +1 -1
  185. package/src/endpoints/organization/dashboard/webshops/PatchWebshopEndpoint.ts +1 -1
  186. package/src/endpoints/organization/dashboard/webshops/PatchWebshopOrdersEndpoint.ts +1 -1
  187. package/src/endpoints/organization/dashboard/webshops/PatchWebshopTicketsEndpoint.ts +1 -1
  188. package/src/endpoints/organization/dashboard/webshops/SearchUitpasEventsEndpoint.ts +2 -2
  189. package/src/endpoints/organization/dashboard/webshops/VerifyWebshopDomainEndpoint.ts +1 -1
  190. package/src/endpoints/organization/shared/ExchangePaymentEndpoint.ts +3 -3
  191. package/src/endpoints/organization/shared/GetDocumentHtml.ts +1 -1
  192. package/src/endpoints/organization/shared/GetPaymentEndpoint.ts +2 -2
  193. package/src/endpoints/organization/shared/auth/GetOrganizationEndpoint.test.ts +2 -2
  194. package/src/endpoints/organization/shared/auth/GetOrganizationEndpoint.ts +2 -2
  195. package/src/endpoints/organization/webshops/CheckWebshopDiscountCodesEndpoint.ts +1 -1
  196. package/src/endpoints/organization/webshops/GetOrderByPaymentEndpoint.ts +1 -1
  197. package/src/endpoints/organization/webshops/GetOrderEndpoint.ts +1 -1
  198. package/src/endpoints/organization/webshops/GetTicketsEndpoint.ts +1 -1
  199. package/src/endpoints/organization/webshops/GetWebshopEndpoint.test.ts +2 -2
  200. package/src/endpoints/organization/webshops/GetWebshopEndpoint.ts +2 -2
  201. package/src/endpoints/organization/webshops/PlaceOrderEndpoint.test.ts +4 -4
  202. package/src/excel-loaders/balance-items.ts +268 -0
  203. package/src/excel-loaders/event-notifications.ts +3 -3
  204. package/src/excel-loaders/index.ts +6 -5
  205. package/src/excel-loaders/organizations.ts +4 -4
  206. package/src/excel-loaders/payments.ts +11 -3
  207. package/src/excel-loaders/receivable-balances.ts +2 -2
  208. package/src/helpers/AddressValidator.test.ts +1 -1
  209. package/src/helpers/AddressValidator.ts +1 -1
  210. package/src/helpers/AdminPermissionChecker.ts +20 -17
  211. package/src/helpers/AuthenticatedStructures.ts +194 -109
  212. package/src/helpers/Context.ts +2 -0
  213. package/src/helpers/EmailResumer.ts +1 -1
  214. package/src/helpers/FlagMomentCleanup.ts +1 -1
  215. package/src/helpers/ForwardHandler.test.ts +1 -1
  216. package/src/helpers/ForwardHandler.ts +1 -1
  217. package/src/helpers/GlobalHelper.ts +4 -4
  218. package/src/helpers/GroupBuilder.ts +417 -0
  219. package/src/helpers/GroupedThrottledQueue.test.ts +1 -1
  220. package/src/helpers/GroupedThrottledQueue.ts +1 -1
  221. package/src/helpers/MemberUserSyncer.test.ts +1 -1
  222. package/src/helpers/MemberUserSyncer.ts +1 -1
  223. package/src/helpers/PeriodHelper.ts +5 -45
  224. package/src/helpers/ServiceFeeHelper.ts +5 -1
  225. package/src/helpers/SetupStepUpdater.ts +5 -4
  226. package/src/helpers/TagHelper.ts +1 -1
  227. package/src/helpers/ThrottledQueue.test.ts +1 -1
  228. package/src/helpers/ViesHelper.ts +9 -0
  229. package/src/helpers/email-html-helpers.ts +0 -41
  230. package/src/helpers/outstandingBalanceJoin.ts +3 -1
  231. package/src/middleware/ContextMiddleware.ts +1 -1
  232. package/src/seeds/1726572303-schedule-stock-updates.ts +1 -1
  233. package/src/seeds/1726847064-setup-steps.ts +1 -1
  234. package/src/seeds/1728928974-update-cached-outstanding-balance-from-items.ts +1 -1
  235. package/src/seeds/1740046783-update-membership.ts +1 -1
  236. package/src/seeds/1754560914-groups-prices.test.ts +1 -1
  237. package/src/seeds/1755876819-remove-duplicate-members.ts +1 -1
  238. package/src/seeds/1760702454-update-cached-outstanding-balance-from-items.ts +1 -1
  239. package/src/seeds/1761665607-sync-member-users.ts +1 -1
  240. package/src/seeds/data/default-email-templates.sql +1 -1
  241. package/src/seeds-temporary/1732117645-move-rrn.ts +1 -1
  242. package/src/services/AuditLogService.ts +1 -41
  243. package/src/services/BalanceItemPaymentService.ts +1 -1
  244. package/src/services/BalanceItemService.ts +12 -5
  245. package/src/services/EventNotificationService.ts +3 -3
  246. package/src/services/InvoiceService.ts +131 -17
  247. package/src/services/MemberRecordStore.ts +1 -1
  248. package/src/services/PaymentReallocationService.test.ts +9 -10
  249. package/src/services/PaymentReallocationService.ts +1 -1
  250. package/src/services/PaymentService.ts +560 -18
  251. package/src/services/PlatformMembershipService.ts +3 -3
  252. package/src/services/RegistrationService.ts +3 -3
  253. package/src/services/SSOService.ts +2 -2
  254. package/src/services/STPackageService.ts +241 -0
  255. package/src/services/uitpas/UitpasService.test.ts +1 -1
  256. package/src/sql-filters/balance-items.ts +56 -0
  257. package/src/sql-filters/emails.ts +1 -1
  258. package/src/sql-filters/event-notifications.ts +2 -2
  259. package/src/sql-filters/events.ts +51 -0
  260. package/src/sql-filters/members.ts +38 -2
  261. package/src/sql-filters/receivable-balances.ts +3 -3
  262. package/src/sql-filters/users.ts +10 -0
  263. package/src/sql-sorters/balance-items.ts +36 -0
  264. package/src/sql-sorters/document-templates.ts +2 -2
  265. package/src/sql-sorters/documents.ts +2 -2
  266. package/src/sql-sorters/event-notifications.ts +1 -1
  267. package/src/sql-sorters/members.ts +2 -2
  268. package/src/sql-sorters/orders.ts +2 -2
  269. package/src/sql-sorters/tickets.ts +2 -2
  270. package/tests/actions/patchOrganizationMember.ts +3 -3
  271. package/tests/actions/patchPaymentStatus.ts +3 -3
  272. package/tests/actions/patchUserMember.ts +2 -2
  273. package/tests/assertions/assertBalances.ts +1 -1
  274. package/tests/e2e/api-rate-limits.test.ts +3 -3
  275. package/tests/e2e/charge-members.test.ts +14 -14
  276. package/tests/e2e/documents.test.ts +8 -8
  277. package/tests/e2e/private-files.test.ts +4 -4
  278. package/tests/e2e/register.test.ts +10 -10
  279. package/tests/e2e/stock.test.ts +4 -4
  280. package/tests/e2e/tickets.test.ts +4 -4
  281. package/tests/helpers/TestServer.ts +2 -2
  282. package/tests/init/index.ts +7 -7
  283. package/tests/init/initAdmin.ts +1 -1
  284. package/src/endpoints/global/registration/GetPaymentRegistrations.ts +0 -67
@@ -1,19 +1,126 @@
1
1
  import { BalanceItem, BalanceItemPayment, Email, Member, MemberResponsibilityRecord, Order, Organization, Payment, RecipientLoader, User, Webshop } from '@stamhoofd/models';
2
2
  import { compileToSQLFilter, SQL } from '@stamhoofd/sql';
3
- import { BalanceItemRelationType, BalanceItemType, CountFilteredRequest, EmailRecipient, EmailRecipientFilterType, LimitedFilteredRequest, PaginatedResponse, PaymentGeneral, PaymentMethod, PaymentMethodHelper, Replacement, StamhoofdFilter, Webshop as WebshopStruct } from '@stamhoofd/structures';
3
+ import { CountFilteredRequest, EmailRecipient, EmailRecipientFilterType, LimitedFilteredRequest, PaginatedResponse, PaymentGeneral, PaymentMethod, StamhoofdFilter } from '@stamhoofd/structures';
4
4
  import { Formatter } from '@stamhoofd/utility';
5
5
  import { GetPaymentsEndpoint } from '../endpoints/organization/dashboard/payments/GetPaymentsEndpoint.js';
6
- import { createOrderDataHTMLTable, createPaymentDataHTMLTable } from '../helpers/email-html-helpers.js';
7
6
  import { memberResponsibilityRecordFilterCompilers } from '../sql-filters/member-responsibility-records.js';
7
+ import { buildReplacementOptions, getEmailReplacementsForPayment, ReplacementsOptions } from '../email-replacements/getEmailReplacementsForPayment.js';
8
8
 
9
- type ReplacementsOptions = {
10
- shouldAddReplacementsForOrder: boolean;
11
- shouldAddReplacementsForTransfers: boolean;
12
- orderMap: Map<string, Order>;
13
- webshopMap: Map<string, Webshop>;
14
- organizationMap: Map<string, Organization>;
9
+ type BeforeFetchAllResult = {
10
+ doesIncludePaymentWithoutOrders: boolean;
11
+ areAllPaymentsTransfers: boolean;
12
+ };
13
+
14
+ async function fetchPaymentRecipients(query: LimitedFilteredRequest, subfilter: StamhoofdFilter, beforeFetchAllResult?: BeforeFetchAllResult) {
15
+ const result = await GetPaymentsEndpoint.buildData(query);
16
+
17
+ return new PaginatedResponse({
18
+ results: await getRecipients(result, EmailRecipientFilterType.Payment, subfilter, beforeFetchAllResult),
19
+ next: result.next,
20
+ });
21
+ }
22
+
23
+ const paymentRecipientLoader: RecipientLoader<BeforeFetchAllResult> = {
24
+ beforeFetchAll: async (query: LimitedFilteredRequest) => {
25
+ const doesIncludePaymentWithoutOrders = await doesQueryIncludePaymentsWithoutOrder(query);
26
+ const areAllPaymentsTransfers = await doesQueryIncludePaymentsOtherThanTransfers(query);
27
+
28
+ return {
29
+ doesIncludePaymentWithoutOrders,
30
+ areAllPaymentsTransfers,
31
+ };
32
+ },
33
+ fetch: fetchPaymentRecipients,
34
+ // For now: only count the number of payments - not the amount of emails
35
+ count: async (query: LimitedFilteredRequest, _subfilter) => {
36
+ const q = await GetPaymentsEndpoint.buildQuery(query);
37
+ const base = await q.count();
38
+
39
+ if (base < 1000) {
40
+ // Do full scan
41
+ query.limit = 1000;
42
+ const result = await fetchPaymentRecipients(query, _subfilter);
43
+ return result.results.length;
44
+ }
45
+
46
+ return base;
47
+ },
15
48
  };
16
49
 
50
+ Email.recipientLoaders.set(EmailRecipientFilterType.Payment, paymentRecipientLoader);
51
+
52
+ async function doesQueryIncludePaymentsWithoutOrder(filterRequest: LimitedFilteredRequest) {
53
+ // create count request (without limit and page filter)
54
+ const countRequest = new CountFilteredRequest({
55
+ filter: filterRequest.filter,
56
+ search: filterRequest.search,
57
+ });
58
+
59
+ const baseQuery = await GetPaymentsEndpoint.buildQuery(countRequest);
60
+
61
+ const balanceItemPaymentsJoin = SQL.innerJoin(BalanceItemPayment.table)
62
+ .where(
63
+ SQL.column(BalanceItemPayment.table, 'paymentId'),
64
+ SQL.column(Payment.table, 'id'),
65
+ );
66
+
67
+ const balanceItemJoin = SQL.innerJoin(BalanceItem.table)
68
+ .where(
69
+ SQL.column(BalanceItem.table, 'id'),
70
+ SQL.column(BalanceItemPayment.table, 'balanceItemId'),
71
+ );
72
+
73
+ // check if 1 payment without order
74
+ const results = await baseQuery
75
+ .join(balanceItemPaymentsJoin)
76
+ .join(balanceItemJoin)
77
+ // where no order
78
+ .where(SQL.column(BalanceItem.table, 'orderId'), null)
79
+ .limit(1)
80
+ .count();
81
+
82
+ return results > 0;
83
+ }
84
+
85
+ async function doesQueryIncludePaymentsOtherThanTransfers(filterRequest: LimitedFilteredRequest) {
86
+ // create count request (without limit and page filter)
87
+ const countRequest = new CountFilteredRequest({
88
+ filter: filterRequest.filter,
89
+ search: filterRequest.search,
90
+ });
91
+
92
+ const baseQuery = await GetPaymentsEndpoint.buildQuery(countRequest);
93
+
94
+ // check if 1 payment with other method than transfer
95
+ const results = await baseQuery
96
+ // where method is not transfer
97
+ .whereNot(SQL.column(Payment.table, 'method'), PaymentMethod.Transfer)
98
+ .limit(1)
99
+ .count();
100
+
101
+ return results === 0;
102
+ }
103
+
104
+ async function fetchPaymentOrganizationRecipients(query: LimitedFilteredRequest, subfilter: StamhoofdFilter | null, beforeFetchAllResult?: BeforeFetchAllResult) {
105
+ const result = await GetPaymentsEndpoint.buildData(query);
106
+
107
+ return new PaginatedResponse({
108
+ results: await getRecipients(result, EmailRecipientFilterType.PaymentOrganization, subfilter, beforeFetchAllResult),
109
+ next: result.next,
110
+ });
111
+ }
112
+
113
+ const paymentOrganizationRecipientLoader: RecipientLoader<BeforeFetchAllResult> = {
114
+ fetch: async (query: LimitedFilteredRequest, subfilter: StamhoofdFilter | null, beforeFetchAllResult) => fetchPaymentOrganizationRecipients(query, subfilter, beforeFetchAllResult),
115
+ // For now: only count the number of payments - not the amount of emails
116
+ count: async (query: LimitedFilteredRequest, subfilter: StamhoofdFilter | null) => {
117
+ const q = await GetPaymentsEndpoint.buildQuery(query);
118
+ return await q.count();
119
+ },
120
+ };
121
+
122
+ Email.recipientLoaders.set(EmailRecipientFilterType.PaymentOrganization, paymentOrganizationRecipientLoader);
123
+
17
124
  async function getRecipients(result: PaginatedResponse<PaymentGeneral[], LimitedFilteredRequest>, type: EmailRecipientFilterType.Payment | EmailRecipientFilterType.PaymentOrganization, subFilter: StamhoofdFilter | null, beforeFetchAllResult: BeforeFetchAllResult | undefined) {
18
125
  const recipients: EmailRecipient[] = [];
19
126
  const userIds: { userId: string; payment: PaymentGeneral }[] = [];
@@ -80,44 +187,7 @@ async function getRecipients(result: PaginatedResponse<PaymentGeneral[], Limited
80
187
  }
81
188
  }
82
189
 
83
- // get all orders linked to the payments
84
- const allOrderIdsSet = new Set<string>();
85
- const allWebshopIdsSet = new Set<string>();
86
- const organizationIdsForOrdersSet = new Set<string>();
87
-
88
- for (const payment of result.results) {
89
- payment.webshopIds.forEach(id => allWebshopIdsSet.add(id));
90
-
91
- for (const balanceItemPayment of payment.balanceItemPayments) {
92
- const balanceItem = balanceItemPayment.balanceItem;
93
- if (balanceItem.orderId) {
94
- allOrderIdsSet.add(balanceItem.orderId);
95
-
96
- // only important if balance item has order
97
- organizationIdsForOrdersSet.add(balanceItem.organizationId);
98
- }
99
- }
100
- }
101
-
102
- // get all orders (for replacements later)
103
- const orders = await Order.getByIDs(...allOrderIdsSet);
104
- const orderMap = new Map<string, Order>(orders.map(o => [o.id, o] as [string, Order]));
105
-
106
- // get all webshops (for replacements later)
107
- const webshops = await Webshop.getByIDs(...allWebshopIdsSet);
108
- const webshopMap = new Map<string, Webshop>(webshops.map(w => [w.id, w] as [string, Webshop]));
109
-
110
- // get all organizations (for replacements later)
111
- const organizations = await Organization.getByIDs(...organizationIdsForOrdersSet);
112
- const organizationMap = new Map<string, Organization>(organizations.map(o => [o.id, o] as [string, Organization]));
113
-
114
- const replacementOptions: ReplacementsOptions = {
115
- shouldAddReplacementsForOrder: beforeFetchAllResult ? !beforeFetchAllResult.doesIncludePaymentWithoutOrders : false,
116
- shouldAddReplacementsForTransfers: beforeFetchAllResult ? beforeFetchAllResult.areAllPaymentsTransfers : false,
117
- orderMap,
118
- webshopMap,
119
- organizationMap,
120
- };
190
+ const replacementOptions = await buildReplacementOptions(result.results, beforeFetchAllResult);
121
191
 
122
192
  if (type === EmailRecipientFilterType.Payment) {
123
193
  recipients.push(...await getUserRecipients(userIds, replacementOptions));
@@ -230,7 +300,7 @@ async function getOrganizationRecipients(ids: { organizationId: string; payment:
230
300
  const replacements = getEmailReplacementsForPayment(payment, replacementOptions);
231
301
 
232
302
  for (const member of members) {
233
- for (const email of member.details.getMemberEmails()) {
303
+ for (const email of member.details.getNotificationEmails()) {
234
304
  results.push(EmailRecipient.create({
235
305
  objectId: payment.id,
236
306
  name: organization.name,
@@ -254,7 +324,7 @@ async function getMemberRecipients(ids: { memberId: string; payment: PaymentGene
254
324
  }
255
325
 
256
326
  const allMemberIds = Formatter.uniqueArray(ids.map(i => i.memberId));
257
- const members = await Member.getBlobByIds(...allMemberIds);
327
+ const members = await Member.getByIdsWithUsers(...allMemberIds);
258
328
 
259
329
  const results: EmailRecipient[] = [];
260
330
 
@@ -313,308 +383,3 @@ async function getOrderRecipients(ids: { orderId: string; payment: PaymentGenera
313
383
 
314
384
  return results;
315
385
  }
316
-
317
- function getEmailReplacementsForPayment(payment: PaymentGeneral, options: ReplacementsOptions): Replacement[] {
318
- const { orderMap, webshopMap, organizationMap, shouldAddReplacementsForOrder, shouldAddReplacementsForTransfers } = options;
319
- const orderIds = new Set<string>();
320
-
321
- for (const balanceItemPayment of payment.balanceItemPayments) {
322
- const orderId = balanceItemPayment.balanceItem.orderId;
323
- if (orderId) {
324
- orderIds.add(orderId);
325
- }
326
- }
327
-
328
- // will be set if only 1 order is linked
329
- let singleOrder: Order | null = null;
330
-
331
- if (orderIds.size === 1) {
332
- const singleOrderId = [...orderIds][0];
333
- if (singleOrderId) {
334
- const order = orderMap.get(singleOrderId);
335
-
336
- if (order) {
337
- singleOrder = order;
338
- }
339
- }
340
- }
341
-
342
- let orderUrlReplacement: Replacement | null = null;
343
-
344
- // add replacement for order url if only 1 order is linked
345
- if (singleOrder && shouldAddReplacementsForOrder) {
346
- const webshop = webshopMap.get(singleOrder.webshopId);
347
- const organization = organizationMap.get(singleOrder.organizationId);
348
-
349
- if (webshop && organization) {
350
- const webshopStruct = WebshopStruct.create(webshop);
351
-
352
- orderUrlReplacement = Replacement.create({
353
- token: 'orderUrl',
354
- value: 'https://' + webshopStruct.getUrl(organization) + '/order/' + (singleOrder.id),
355
- });
356
- }
357
- }
358
-
359
- const createPaymentDataHtml = () => {
360
- if (singleOrder) {
361
- const webshop = webshopMap.get(singleOrder.webshopId);
362
- if (webshop) {
363
- return createOrderDataHTMLTable(singleOrder, webshop);
364
- }
365
- }
366
-
367
- return createPaymentDataHTMLTable(payment);
368
- };
369
-
370
- const paymentDataHtml = createPaymentDataHtml();
371
- const paymentDataReplacement = paymentDataHtml
372
- ? Replacement.create({
373
- token: 'paymentData',
374
- value: '',
375
- html: paymentDataHtml,
376
- })
377
- : null;
378
-
379
- return ([
380
- Replacement.create({
381
- token: 'paymentPrice',
382
- value: Formatter.price(payment.price),
383
- }),
384
- Replacement.create({
385
- token: 'paymentMethod',
386
- value: PaymentMethodHelper.getName(payment.method ?? PaymentMethod.Unknown),
387
- }),
388
- ...(shouldAddReplacementsForTransfers
389
- ? [
390
- Replacement.create({
391
- token: 'transferDescription',
392
- value: (payment.transferDescription ?? ''),
393
- }),
394
- Replacement.create({
395
- token: 'transferBankAccount',
396
- value: payment.transferSettings?.iban ?? '',
397
- }),
398
- Replacement.create({
399
- token: 'transferBankCreditor',
400
- // todo?
401
- value: payment.transferSettings?.creditor ?? (payment.organizationId ? organizationMap.get(payment.organizationId)?.name : ''),
402
- }),
403
- ]
404
- : []),
405
-
406
- Replacement.create({
407
- token: 'balanceItemPaymentsTable',
408
- value: '',
409
- // todo: unbox orders?
410
- html: payment.getBalanceItemPaymentsHtmlTable(),
411
- }),
412
- Replacement.create({
413
- token: 'paymentTable',
414
- value: '',
415
- html: payment.getHTMLTable(),
416
- }),
417
- Replacement.create({
418
- token: 'overviewContext',
419
- value: getPaymentContext(payment, options),
420
- }),
421
- orderUrlReplacement,
422
- paymentDataReplacement,
423
- ]).filter(replacementOrNull => replacementOrNull !== null);
424
- }
425
-
426
- function getPaymentContext(payment: PaymentGeneral, { orderMap, webshopMap }: ReplacementsOptions) {
427
- const overviewContext = new Set<string>();
428
- const registrationMemberNames = new Set<string>();
429
-
430
- // only add to context if type is order or registration
431
- for (const balanceItemPayment of payment.balanceItemPayments) {
432
- const balanceItem = balanceItemPayment.balanceItem;
433
- const type = balanceItem.type;
434
-
435
- switch (type) {
436
- case BalanceItemType.Order: {
437
- if (balanceItem.orderId) {
438
- const order = orderMap.get(balanceItem.orderId);
439
-
440
- if (order) {
441
- const webshop = webshopMap.get(order.webshopId);
442
- if (webshop) {
443
- overviewContext.add($t('{webshop} (bestelling {orderNumber})', {
444
- webshop: webshop.meta.name,
445
- orderNumber: order.number ?? '',
446
- }));
447
- }
448
- else {
449
- overviewContext.add($t('Bestelling {orderNumber}', {
450
- orderNumber: order.number ?? '',
451
- }));
452
- }
453
- }
454
- }
455
- break;
456
- }
457
- case BalanceItemType.Registration: {
458
- const memberName = balanceItem.relations.get(BalanceItemRelationType.Member)?.name.toString();
459
- if (memberName) {
460
- registrationMemberNames.add(memberName);
461
- }
462
- else {
463
- overviewContext.add(balanceItem.itemTitle);
464
- }
465
-
466
- break;
467
- }
468
- default: {
469
- break;
470
- }
471
- }
472
- }
473
-
474
- if (registrationMemberNames.size > 0) {
475
- const memberNames = Formatter.joinLast([...registrationMemberNames], ', ', ' ' + $t(`6a156458-b396-4d0f-b562-adb3e38fc51b`) + ' ');
476
- overviewContext.add($t(`01d5fd7e-2960-4eb4-ab3a-2ac6dcb2e39c`) + ' ' + memberNames);
477
- }
478
-
479
- if (overviewContext.size === 0) {
480
- // add item title if no balance items with type order or registration
481
- if (payment.balanceItemPayments.length === 1) {
482
- const balanceItem = payment.balanceItemPayments[0].balanceItem;
483
- return balanceItem.itemTitle;
484
- }
485
-
486
- if (payment.balanceItemPayments.length > 1) {
487
- // return title if all balance items have the same title
488
- const firstTitle = payment.balanceItemPayments[0].balanceItem.itemTitle;
489
- const haveAllSameTitle = payment.balanceItemPayments.every(p => p.balanceItem.itemTitle === firstTitle);
490
-
491
- if (haveAllSameTitle) {
492
- return `${firstTitle} (${payment.balanceItemPayments.length}x)`;
493
- }
494
-
495
- // else return default text for multiple items
496
- return $t('Betaling voor {count} items', { count: payment.balanceItemPayments.length });
497
- }
498
-
499
- // else return default text for single item
500
- return $t('Betaling voor 1 item');
501
- }
502
-
503
- // join texts for balance items with type order or registration
504
- return [...overviewContext].join(', ');
505
- }
506
-
507
- type BeforeFetchAllResult = {
508
- doesIncludePaymentWithoutOrders: boolean;
509
- areAllPaymentsTransfers: boolean;
510
- };
511
-
512
- async function fetchPaymentRecipients(query: LimitedFilteredRequest, beforeFetchAllResult?: BeforeFetchAllResult) {
513
- const result = await GetPaymentsEndpoint.buildData(query);
514
-
515
- return new PaginatedResponse({
516
- results: await getRecipients(result, EmailRecipientFilterType.Payment, null, beforeFetchAllResult),
517
- next: result.next,
518
- });
519
- }
520
-
521
- const paymentRecipientLoader: RecipientLoader<BeforeFetchAllResult> = {
522
- beforeFetchAll: async (query: LimitedFilteredRequest) => {
523
- const doesIncludePaymentWithoutOrders = await doesQueryIncludePaymentsWithoutOrder(query);
524
- const areAllPaymentsTransfers = await doesQueryIncludePaymentsOtherThanTransfers(query);
525
-
526
- return {
527
- doesIncludePaymentWithoutOrders,
528
- areAllPaymentsTransfers,
529
- };
530
- },
531
- fetch: async (query: LimitedFilteredRequest, _subfilter, beforeFetchAllResult) => fetchPaymentRecipients(query, beforeFetchAllResult),
532
- // For now: only count the number of payments - not the amount of emails
533
- count: async (query: LimitedFilteredRequest, _subfilter) => {
534
- const q = await GetPaymentsEndpoint.buildQuery(query);
535
- const base = await q.count();
536
-
537
- if (base < 1000) {
538
- // Do full scan
539
- query.limit = 1000;
540
- const result = await fetchPaymentRecipients(query);
541
- return result.results.length;
542
- }
543
-
544
- return base;
545
- },
546
- };
547
-
548
- Email.recipientLoaders.set(EmailRecipientFilterType.Payment, paymentRecipientLoader);
549
-
550
- async function doesQueryIncludePaymentsWithoutOrder(filterRequest: LimitedFilteredRequest) {
551
- // create count request (without limit and page filter)
552
- const countRequest = new CountFilteredRequest({
553
- filter: filterRequest.filter,
554
- search: filterRequest.search,
555
- });
556
-
557
- const baseQuery = await GetPaymentsEndpoint.buildQuery(countRequest);
558
-
559
- const balanceItemPaymentsJoin = SQL.innerJoin(BalanceItemPayment.table)
560
- .where(
561
- SQL.column(BalanceItemPayment.table, 'paymentId'),
562
- SQL.column(Payment.table, 'id'),
563
- );
564
-
565
- const balanceItemJoin = SQL.innerJoin(BalanceItem.table)
566
- .where(
567
- SQL.column(BalanceItem.table, 'id'),
568
- SQL.column(BalanceItemPayment.table, 'balanceItemId'),
569
- );
570
-
571
- // check if 1 payment without order
572
- const results = await baseQuery
573
- .join(balanceItemPaymentsJoin)
574
- .join(balanceItemJoin)
575
- // where no order
576
- .where(SQL.column(BalanceItem.table, 'orderId'), null)
577
- .limit(1)
578
- .count();
579
-
580
- return results > 0;
581
- }
582
-
583
- async function doesQueryIncludePaymentsOtherThanTransfers(filterRequest: LimitedFilteredRequest) {
584
- // create count request (without limit and page filter)
585
- const countRequest = new CountFilteredRequest({
586
- filter: filterRequest.filter,
587
- search: filterRequest.search,
588
- });
589
-
590
- const baseQuery = await GetPaymentsEndpoint.buildQuery(countRequest);
591
-
592
- // check if 1 payment with other method than transfer
593
- const results = await baseQuery
594
- // where method is not transfer
595
- .whereNot(SQL.column(Payment.table, 'method'), PaymentMethod.Transfer)
596
- .limit(1)
597
- .count();
598
-
599
- return results === 0;
600
- }
601
-
602
- async function fetchPaymentOrganizationRecipients(query: LimitedFilteredRequest, subfilter: StamhoofdFilter | null, beforeFetchAllResult?: BeforeFetchAllResult) {
603
- const result = await GetPaymentsEndpoint.buildData(query);
604
-
605
- return new PaginatedResponse({
606
- results: await getRecipients(result, EmailRecipientFilterType.PaymentOrganization, subfilter, beforeFetchAllResult),
607
- next: result.next,
608
- });
609
- }
610
-
611
- const paymentOrganizationRecipientLoader: RecipientLoader<BeforeFetchAllResult> = {
612
- fetch: async (query: LimitedFilteredRequest, subfilter: StamhoofdFilter | null, beforeFetchAllResult) => fetchPaymentOrganizationRecipients(query, subfilter, beforeFetchAllResult),
613
- // For now: only count the number of payments - not the amount of emails
614
- count: async (query: LimitedFilteredRequest, subfilter: StamhoofdFilter | null) => {
615
- const q = await GetPaymentsEndpoint.buildQuery(query);
616
- return await q.count();
617
- },
618
- };
619
-
620
- Email.recipientLoaders.set(EmailRecipientFilterType.PaymentOrganization, paymentOrganizationRecipientLoader);