@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
@@ -0,0 +1,321 @@
1
+ import { Order, Organization, Webshop } from '@stamhoofd/models';
2
+ import { BalanceItemPaymentsHtmlTableItem, BalanceItemRelationType, BalanceItemType, getBalanceItemPaymentsHtmlTable, PaymentGeneral, PaymentMethod, PaymentMethodHelper, Replacement, Webshop as WebshopStruct } from '@stamhoofd/structures';
3
+ import { Formatter } from '@stamhoofd/utility';
4
+ import { createOrderDataHTMLTable } from '../helpers/email-html-helpers.js';
5
+
6
+ export type ReplacementsOptions = {
7
+ /**
8
+ * If not set, defaults to true
9
+ */
10
+ shouldAddReplacementsForOrder?: boolean;
11
+
12
+ /**
13
+ * If not set, defaults to true
14
+ */
15
+ shouldAddReplacementsForTransfers?: boolean;
16
+ orderMap: Map<string, Order>;
17
+ webshopMap: Map<string, Webshop>;
18
+ organizationMap: Map<string, Organization>;
19
+ };
20
+
21
+ /**
22
+ * To reduce the amount of queries, payment options should be generated for the whole aray of payments you want to send emails to.
23
+ */
24
+ export async function buildReplacementOptions(payments: PaymentGeneral[], options?: { doesIncludePaymentWithoutOrders: boolean; areAllPaymentsTransfers: boolean }): Promise<ReplacementsOptions> {
25
+ // get all orders linked to the payments
26
+ const allOrderIdsSet = new Set<string>();
27
+ const allWebshopIdsSet = new Set<string>();
28
+ const organizationIdsForOrdersSet = new Set<string>();
29
+
30
+ for (const payment of payments) {
31
+ payment.webshopIds.forEach(id => allWebshopIdsSet.add(id));
32
+
33
+ for (const balanceItemPayment of payment.balanceItemPayments) {
34
+ const balanceItem = balanceItemPayment.balanceItem;
35
+ if (balanceItem.orderId) {
36
+ allOrderIdsSet.add(balanceItem.orderId);
37
+
38
+ // only important if balance item has order
39
+ organizationIdsForOrdersSet.add(balanceItem.organizationId);
40
+ }
41
+ }
42
+ }
43
+
44
+ // get all orders (for replacements later)
45
+ const orders = await Order.getByIDs(...allOrderIdsSet);
46
+ const orderMap = new Map<string, Order>(orders.map(o => [o.id, o] as [string, Order]));
47
+
48
+ // get all webshops (for replacements later)
49
+ const webshops = await Webshop.getByIDs(...allWebshopIdsSet);
50
+ const webshopMap = new Map<string, Webshop>(webshops.map(w => [w.id, w] as [string, Webshop]));
51
+
52
+ // get all organizations (for replacements later)
53
+ const organizations = await Organization.getByIDs(...organizationIdsForOrdersSet);
54
+ const organizationMap = new Map<string, Organization>(organizations.map(o => [o.id, o] as [string, Organization]));
55
+
56
+ return {
57
+ shouldAddReplacementsForOrder: options ? !options.doesIncludePaymentWithoutOrders : true,
58
+ shouldAddReplacementsForTransfers: options ? options.areAllPaymentsTransfers : true,
59
+ orderMap,
60
+ webshopMap,
61
+ organizationMap,
62
+ };
63
+ }
64
+
65
+ export function getEmailReplacementsForPayment(payment: PaymentGeneral, options: ReplacementsOptions): Replacement[] {
66
+ const { orderMap, webshopMap, organizationMap, shouldAddReplacementsForOrder, shouldAddReplacementsForTransfers } = options;
67
+ const orderIds = new Set<string>();
68
+
69
+ for (const balanceItemPayment of payment.balanceItemPayments) {
70
+ const orderId = balanceItemPayment.balanceItem.orderId;
71
+ if (orderId) {
72
+ orderIds.add(orderId);
73
+ }
74
+ }
75
+
76
+ // will be set if only 1 order is linked
77
+ let singleOrder: Order | null = null;
78
+
79
+ if (orderIds.size === 1) {
80
+ const singleOrderId = [...orderIds][0];
81
+ if (singleOrderId) {
82
+ const order = orderMap.get(singleOrderId);
83
+
84
+ if (order) {
85
+ singleOrder = order;
86
+ }
87
+ }
88
+ }
89
+
90
+ let orderUrlReplacement: Replacement | null = null;
91
+ let paymentUrl: string = '{{signInUrl}}';
92
+
93
+ // add replacement for order url if only 1 order is linked
94
+ if (shouldAddReplacementsForOrder ?? true) {
95
+ if (singleOrder) {
96
+ const webshop = webshopMap.get(singleOrder.webshopId);
97
+ const organization = organizationMap.get(singleOrder.organizationId);
98
+
99
+ if (webshop && organization) {
100
+ const webshopStruct = WebshopStruct.create(webshop);
101
+
102
+ orderUrlReplacement = Replacement.create({
103
+ token: 'orderUrl',
104
+ value: 'https://' + webshopStruct.getUrl(organization) + '/order/' + (singleOrder.id),
105
+ });
106
+ paymentUrl = 'https://' + webshopStruct.getUrl(organization) + '/order/' + (singleOrder.id);
107
+ }
108
+ }
109
+ else {
110
+ // Fallback (should not happen, but better than leaving {{orderUrl}} in place)
111
+ orderUrlReplacement = Replacement.create({
112
+ token: 'orderUrl',
113
+ value: paymentUrl,
114
+ });
115
+ }
116
+ }
117
+
118
+ const createPaymentDataHtml = () => {
119
+ if (singleOrder) {
120
+ const webshop = webshopMap.get(singleOrder.webshopId);
121
+ if (webshop) {
122
+ return createOrderDataHTMLTable(singleOrder, webshop);
123
+ }
124
+ }
125
+
126
+ return payment.getPaymentDataHTMLTable();
127
+ };
128
+
129
+ const paymentDataHtml = createPaymentDataHtml();
130
+
131
+ return ([
132
+ Replacement.create({
133
+ token: 'paymentUrl',
134
+ value: paymentUrl,
135
+ }),
136
+ Replacement.create({
137
+ token: 'priceToPay',
138
+ value: Formatter.price(payment.price),
139
+ }),
140
+ Replacement.create({
141
+ token: 'paymentMethod',
142
+ value: PaymentMethodHelper.getName(payment.method ?? PaymentMethod.Unknown),
143
+ }),
144
+ ...((shouldAddReplacementsForTransfers ?? true)
145
+ ? [
146
+ Replacement.create({
147
+ token: 'transferDescription',
148
+ value: (payment.transferDescription ?? ''),
149
+ }),
150
+ Replacement.create({
151
+ token: 'transferBankAccount',
152
+ value: payment.transferSettings?.iban ?? '',
153
+ }),
154
+ Replacement.create({
155
+ token: 'transferBankCreditor',
156
+ value: payment.transferSettings?.creditor ?? (payment.organizationId ? organizationMap.get(payment.organizationId)?.name : '') ?? '',
157
+ }),
158
+ ]
159
+ : [
160
+ Replacement.create({
161
+ token: 'transferDescription',
162
+ value: '',
163
+ }),
164
+ Replacement.create({
165
+ token: 'transferBankAccount',
166
+ value: '',
167
+ }),
168
+ Replacement.create({
169
+ token: 'transferBankCreditor',
170
+ value: '',
171
+ }),
172
+ ]),
173
+
174
+ Replacement.create({
175
+ token: 'overviewTable',
176
+ value: '',
177
+ html: getBalanceItemPaymentsHtmlTable(unboxBalanceItemPayments(payment, orderMap)),
178
+ }),
179
+ Replacement.create({
180
+ token: 'paymentTable',
181
+ value: '',
182
+ html: payment.getHTMLTable(),
183
+ }),
184
+ Replacement.create({
185
+ token: 'paymentData',
186
+ value: '',
187
+ html: paymentDataHtml,
188
+ }),
189
+ Replacement.create({
190
+ token: 'overviewContext',
191
+ value: getPaymentContext(payment, options),
192
+ }),
193
+ Replacement.create({
194
+ token: 'memberNames',
195
+ value: payment.memberNames,
196
+ }),
197
+ orderUrlReplacement,
198
+ ]).filter(replacementOrNull => replacementOrNull !== null);
199
+ }
200
+
201
+ function getPaymentContext(payment: PaymentGeneral, { orderMap, webshopMap }: ReplacementsOptions) {
202
+ const overviewContext = new Set<string>();
203
+ const registrationMemberNames = new Set<string>();
204
+
205
+ // only add to context if type is order or registration
206
+ for (const balanceItemPayment of payment.balanceItemPayments) {
207
+ const balanceItem = balanceItemPayment.balanceItem;
208
+ const type = balanceItem.type;
209
+
210
+ switch (type) {
211
+ case BalanceItemType.Order: {
212
+ if (balanceItem.orderId) {
213
+ const order = orderMap.get(balanceItem.orderId);
214
+
215
+ if (order) {
216
+ const webshop = webshopMap.get(order.webshopId);
217
+ if (webshop) {
218
+ if (order.number) {
219
+ overviewContext.add($t('80c86ad4-5ca1-481a-a408-db018a81f25e', {
220
+ webshop: webshop.meta.name,
221
+ orderNumber: order.number ?? '',
222
+ }));
223
+ }
224
+ else {
225
+ overviewContext.add(webshop.meta.name);
226
+ }
227
+ }
228
+ else {
229
+ overviewContext.add($t('8bb27033-cf3c-4af1-a3f4-3373734ab189', {
230
+ orderNumber: order.number ?? '',
231
+ }));
232
+ }
233
+ }
234
+ }
235
+ break;
236
+ }
237
+ case BalanceItemType.Registration: {
238
+ const memberName = balanceItem.relations.get(BalanceItemRelationType.Member)?.name.toString();
239
+ if (memberName) {
240
+ registrationMemberNames.add(memberName);
241
+ }
242
+ else {
243
+ overviewContext.add(balanceItem.itemTitle);
244
+ }
245
+
246
+ break;
247
+ }
248
+ default: {
249
+ break;
250
+ }
251
+ }
252
+ }
253
+
254
+ if (registrationMemberNames.size > 0) {
255
+ const memberNames = Formatter.joinLast([...registrationMemberNames], ', ', ' ' + $t(`6a156458-b396-4d0f-b562-adb3e38fc51b`) + ' ');
256
+ overviewContext.add($t(`01d5fd7e-2960-4eb4-ab3a-2ac6dcb2e39c`) + ' ' + memberNames);
257
+ }
258
+
259
+ if (overviewContext.size === 0) {
260
+ // add item title if no balance items with type order or registration
261
+ if (payment.balanceItemPayments.length === 1) {
262
+ const balanceItem = payment.balanceItemPayments[0].balanceItem;
263
+ return balanceItem.itemTitle;
264
+ }
265
+
266
+ if (payment.balanceItemPayments.length > 1) {
267
+ // return title if all balance items have the same title
268
+ const firstTitle = payment.balanceItemPayments[0].balanceItem.itemTitle;
269
+ const haveAllSameTitle = payment.balanceItemPayments.every(p => p.balanceItem.itemTitle === firstTitle);
270
+
271
+ if (haveAllSameTitle) {
272
+ return `${firstTitle} (${payment.balanceItemPayments.length}x)`;
273
+ }
274
+
275
+ // else return default text for multiple items
276
+ return $t('7462f89e-db05-452f-804f-b9f2d51bff0d', { count: payment.balanceItemPayments.length });
277
+ }
278
+
279
+ // else return default text for single item
280
+ return $t('fe349d88-fecf-4cd8-8ea4-9e3b13cfa0dc');
281
+ }
282
+
283
+ // join texts for balance items with type order or registration
284
+ return [...overviewContext].join(', ');
285
+ }
286
+
287
+ function unboxBalanceItemPayments({ balanceItemPayments }: PaymentGeneral, orderMap: Map<string, Order>): BalanceItemPaymentsHtmlTableItem[] {
288
+ const results: BalanceItemPaymentsHtmlTableItem[] = [];
289
+ for (const item of balanceItemPayments) {
290
+ const orderId = item.balanceItem.orderId;
291
+ if (orderId === null) {
292
+ results.push(item);
293
+ continue;
294
+ }
295
+
296
+ const order = orderMap.get(orderId);
297
+ if (!order) {
298
+ // if 1 order is not found -> do not unbox the payment
299
+ return balanceItemPayments;
300
+ }
301
+
302
+ for (const cartItem of order.data.cart.items) {
303
+ const price = cartItem.getPriceWithDiscounts();
304
+ const quantity = cartItem.amount;
305
+ const unitPrice = Math.abs(quantity) > 1 ? price / quantity : price;
306
+
307
+ results.push({
308
+ itemTitle: cartItem.product.name,
309
+ itemDescription: cartItem.description,
310
+ balanceItem: {
311
+ description: cartItem.description,
312
+ },
313
+ quantity,
314
+ unitPrice,
315
+ price,
316
+ });
317
+ }
318
+ }
319
+
320
+ return results;
321
+ }
@@ -1,7 +1,7 @@
1
1
  import { Decoder } from '@simonbackx/simple-encoding';
2
2
  import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
3
3
  import { SimpleError } from '@simonbackx/simple-errors';
4
- import { ChargeMembersRequest, LimitedFilteredRequest, PermissionLevel } from '@stamhoofd/structures';
4
+ import { ChargeRequest, LimitedFilteredRequest, PermissionLevel } from '@stamhoofd/structures';
5
5
 
6
6
  import { QueueHandler } from '@stamhoofd/queues';
7
7
  import { Context } from '../../../helpers/Context.js';
@@ -10,13 +10,12 @@ import { MemberCharger } from '../../../helpers/MemberCharger.js';
10
10
  import { GetMembersEndpoint } from '../../global/members/GetMembersEndpoint.js';
11
11
 
12
12
  type Params = Record<string, never>;
13
- type Query = LimitedFilteredRequest;
14
- type Body = ChargeMembersRequest;
13
+ type Query = undefined;
14
+ type Body = ChargeRequest;
15
15
  type ResponseBody = undefined;
16
16
 
17
17
  export class ChargeMembersEndpoint extends Endpoint<Params, Query, Body, ResponseBody> {
18
- queryDecoder = LimitedFilteredRequest as Decoder<LimitedFilteredRequest>;
19
- bodyDecoder = ChargeMembersRequest as Decoder<ChargeMembersRequest>;
18
+ bodyDecoder = ChargeRequest as Decoder<ChargeRequest>;
20
19
 
21
20
  protected doesMatch(request: Request): [true, Params] | [false] {
22
21
  if (request.method !== 'POST') {
@@ -72,7 +71,7 @@ export class ChargeMembersEndpoint extends Endpoint<Params, Query, Body, Respons
72
71
 
73
72
  ChargeMembersEndpoint.throwIfInvalidBody(body);
74
73
 
75
- const queueId = 'charge-members';
74
+ const queueId = 'charge-members-' + organization.id;
76
75
 
77
76
  if (QueueHandler.isRunning(queueId)) {
78
77
  throw new SimpleError({
@@ -83,7 +82,10 @@ export class ChargeMembersEndpoint extends Endpoint<Params, Query, Body, Respons
83
82
  }
84
83
 
85
84
  await QueueHandler.schedule(queueId, async () => {
86
- const dataGenerator = fetchToAsyncIterator(request.query, {
85
+ const dataGenerator = fetchToAsyncIterator(new LimitedFilteredRequest({
86
+ filter: body.filter,
87
+ limit: 100,
88
+ }), {
87
89
  fetch: request => GetMembersEndpoint.buildData(request, PermissionLevel.Write),
88
90
  });
89
91
 
@@ -1,8 +1,8 @@
1
1
  import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
2
2
  import { SimpleError } from '@simonbackx/simple-errors';
3
3
  import { QueueHandler } from '@stamhoofd/queues';
4
- import { Context } from '../../../helpers/Context';
5
- import { MembershipCharger } from '../../../helpers/MembershipCharger';
4
+ import { Context } from '../../../helpers/Context.js';
5
+ import { MembershipCharger } from '../../../helpers/MembershipCharger.js';
6
6
 
7
7
  type Params = Record<string, never>;
8
8
  type Query = Record<string, never>;
@@ -3,7 +3,7 @@ import { Platform } from '@stamhoofd/models';
3
3
  import { QueueHandler } from '@stamhoofd/queues';
4
4
  import { SQL, SQLAlias, SQLCount, SQLDistinct, SQLSelectAs, SQLSum, SQLWhereSign } from '@stamhoofd/sql';
5
5
  import { ChargeMembershipsSummary, ChargeMembershipsTypeSummary } from '@stamhoofd/structures';
6
- import { Context } from '../../../helpers/Context';
6
+ import { Context } from '../../../helpers/Context.js';
7
7
 
8
8
  type Params = Record<string, never>;
9
9
  type Query = Record<string, never>;
@@ -1,22 +1,22 @@
1
1
  import { Decoder } from '@simonbackx/simple-encoding';
2
2
  import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
3
3
  import { SimpleError } from '@simonbackx/simple-errors';
4
- import { ChargeOrganizationsRequest, LimitedFilteredRequest } from '@stamhoofd/structures';
4
+ import { ChargeRequest, LimitedFilteredRequest } from '@stamhoofd/structures';
5
5
 
6
6
  import { QueueHandler } from '@stamhoofd/queues';
7
- import { Context } from '../../../helpers/Context';
8
- import { fetchToAsyncIterator } from '../../../helpers/fetchToAsyncIterator';
9
- import { OrganizationCharger } from '../../../helpers/OrganizationCharger';
10
- import { GetOrganizationsEndpoint } from './GetOrganizationsEndpoint';
7
+ import { Context } from '../../../helpers/Context.js';
8
+ import { fetchToAsyncIterator } from '../../../helpers/fetchToAsyncIterator.js';
9
+ import { OrganizationCharger } from '../../../helpers/OrganizationCharger.js';
10
+ import { GetOrganizationsEndpoint } from './GetOrganizationsEndpoint.js';
11
+ import { ChargeMembersEndpoint } from '../members/ChargeMembersEndpoint.js';
11
12
 
12
13
  type Params = Record<string, never>;
13
- type Query = LimitedFilteredRequest;
14
- type Body = ChargeOrganizationsRequest;
14
+ type Query = undefined;
15
+ type Body = ChargeRequest;
15
16
  type ResponseBody = undefined;
16
17
 
17
18
  export class ChargeOrganizationsEndpoint extends Endpoint<Params, Query, Body, ResponseBody> {
18
- queryDecoder = LimitedFilteredRequest as Decoder<LimitedFilteredRequest>;
19
- bodyDecoder = ChargeOrganizationsRequest as Decoder<ChargeOrganizationsRequest>;
19
+ bodyDecoder = ChargeRequest as Decoder<ChargeRequest>;
20
20
 
21
21
  protected doesMatch(request: Request): [true, Params] | [false] {
22
22
  if (request.method !== 'POST') {
@@ -31,45 +31,8 @@ export class ChargeOrganizationsEndpoint extends Endpoint<Params, Query, Body, R
31
31
  return [false];
32
32
  }
33
33
 
34
- private static throwIfInvalidBody(body: Body) {
35
- if (!body.description?.trim()?.length) {
36
- throw new SimpleError({
37
- code: 'invalid_field',
38
- message: 'Invalid description',
39
- human: $t(`2449fba5-99dc-496f-a9d6-a67263d56616`),
40
- field: 'description',
41
- });
42
- }
43
-
44
- if (!body.price) {
45
- throw new SimpleError({
46
- code: 'invalid_field',
47
- message: 'Invalid price',
48
- human: $t(`1e165aac-8a58-45c5-bdd8-c58131a7b7f5`),
49
- field: 'price',
50
- });
51
- }
52
-
53
- if (body.amount === 0) {
54
- throw new SimpleError({
55
- code: 'invalid_field',
56
- message: 'Invalid amount',
57
- human: $t(`0bdf4953-1eae-41fd-b142-5ad3287f17a7`),
58
- field: 'amount',
59
- });
60
- }
61
-
62
- if (!body.organizationId) {
63
- throw new SimpleError({
64
- code: 'invalid_field',
65
- message: 'Invalid organization id',
66
- human: $t(`ae7ac6ab-bb02-4cd6-823f-7076e4ce6f6c`),
67
- field: 'organizationId',
68
- });
69
- }
70
- }
71
-
72
34
  async handle(request: DecodedRequest<Params, Query, Body>) {
35
+ const organization = await Context.setOrganizationScope();
73
36
  await Context.authenticate();
74
37
 
75
38
  if (!Context.auth.hasPlatformFullAccess()) {
@@ -77,7 +40,7 @@ export class ChargeOrganizationsEndpoint extends Endpoint<Params, Query, Body, R
77
40
  }
78
41
 
79
42
  const body = request.body;
80
- ChargeOrganizationsEndpoint.throwIfInvalidBody(body);
43
+ ChargeMembersEndpoint.throwIfInvalidBody(body);
81
44
 
82
45
  const queueId = 'charge-organizations';
83
46
 
@@ -90,13 +53,16 @@ export class ChargeOrganizationsEndpoint extends Endpoint<Params, Query, Body, R
90
53
  }
91
54
 
92
55
  await QueueHandler.schedule(queueId, async () => {
93
- const dataGenerator = fetchToAsyncIterator(request.query, {
56
+ const dataGenerator = fetchToAsyncIterator(new LimitedFilteredRequest({
57
+ filter: body.filter,
58
+ limit: 100,
59
+ }), {
94
60
  fetch: GetOrganizationsEndpoint.buildData,
95
61
  });
96
62
 
97
63
  for await (const data of dataGenerator) {
98
64
  await OrganizationCharger.chargeMany({
99
- chargingOrganizationId: body.organizationId,
65
+ chargingOrganizationId: organization.id,
100
66
  organizationsToCharge: data,
101
67
  price: body.price,
102
68
  amount: body.amount ?? 1,
@@ -2,8 +2,8 @@ import { Decoder } from '@simonbackx/simple-encoding';
2
2
  import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
3
3
  import { CountFilteredRequest, CountResponse } from '@stamhoofd/structures';
4
4
 
5
- import { Context } from '../../../helpers/Context';
6
- import { GetOrganizationsEndpoint } from './GetOrganizationsEndpoint';
5
+ import { Context } from '../../../helpers/Context.js';
6
+ import { GetOrganizationsEndpoint } from './GetOrganizationsEndpoint.js';
7
7
 
8
8
  type Params = Record<string, never>;
9
9
  type Query = CountFilteredRequest;
@@ -6,10 +6,10 @@ import { SQL, applySQLSorter, compileToSQLFilter } from '@stamhoofd/sql';
6
6
  import { CountFilteredRequest, LimitedFilteredRequest, Organization as OrganizationStruct, PaginatedResponse, PermissionLevel, StamhoofdFilter, assertSort, getSortFilter } from '@stamhoofd/structures';
7
7
 
8
8
  import { SQLResultNamespacedRow } from '@simonbackx/simple-database';
9
- import { AuthenticatedStructures } from '../../../helpers/AuthenticatedStructures';
10
- import { Context } from '../../../helpers/Context';
11
- import { organizationFilterCompilers } from '../../../sql-filters/organizations';
12
- import { organizationSorters } from '../../../sql-sorters/organizations';
9
+ import { AuthenticatedStructures } from '../../../helpers/AuthenticatedStructures.js';
10
+ import { Context } from '../../../helpers/Context.js';
11
+ import { organizationFilterCompilers } from '../../../sql-filters/organizations.js';
12
+ import { organizationSorters } from '../../../sql-sorters/organizations.js';
13
13
 
14
14
  type Params = Record<string, never>;
15
15
  type Query = LimitedFilteredRequest;
@@ -1,12 +1,12 @@
1
1
  import { AutoEncoderPatchType, Decoder, PatchableArrayAutoEncoder, PatchableArrayDecoder, StringDecoder } from '@simonbackx/simple-encoding';
2
2
  import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
3
3
  import { SimpleError } from '@simonbackx/simple-errors';
4
- import { Organization, OrganizationRegistrationPeriod, Platform } from '@stamhoofd/models';
4
+ import { Organization, OrganizationRegistrationPeriod, Platform, RegistrationPeriod } from '@stamhoofd/models';
5
5
  import { Organization as OrganizationStruct } from '@stamhoofd/structures';
6
6
 
7
7
  import { Formatter } from '@stamhoofd/utility';
8
- import { AuthenticatedStructures } from '../../../helpers/AuthenticatedStructures';
9
- import { Context } from '../../../helpers/Context';
8
+ import { AuthenticatedStructures } from '../../../helpers/AuthenticatedStructures.js';
9
+ import { Context } from '../../../helpers/Context.js';
10
10
 
11
11
  type Params = Record<string, never>;
12
12
  type Query = undefined;
@@ -126,8 +126,18 @@ export class PatchOrganizationsEndpoint extends Endpoint<Params, Query, Body, Re
126
126
  organization.meta = put.meta;
127
127
  organization.address = put.address;
128
128
 
129
- const periodId = (await Platform.getShared()).periodIdIfPlatform;
130
- organization.periodId = periodId;
129
+ let period: RegistrationPeriod | null = null;
130
+
131
+ if (STAMHOOFD.userMode === 'platform') {
132
+ const periodId = (await Platform.getShared()).periodIdIfPlatform;
133
+ organization.periodId = periodId;
134
+ }
135
+ else {
136
+ period = new RegistrationPeriod();
137
+ period.configureForNewOrganization();
138
+ await period.save();
139
+ organization.periodId = period.id;
140
+ }
131
141
 
132
142
  if (put.privateMeta) {
133
143
  organization.privateMeta = put.privateMeta;
@@ -145,9 +155,14 @@ export class PatchOrganizationsEndpoint extends Endpoint<Params, Query, Body, Re
145
155
  });
146
156
  }
147
157
 
158
+ if (STAMHOOFD.userMode !== 'platform' && period) {
159
+ period.organizationId = organization.id;
160
+ await period.save();
161
+ }
162
+
148
163
  const organizationPeriod = new OrganizationRegistrationPeriod();
149
164
  organizationPeriod.organizationId = organization.id;
150
- organizationPeriod.periodId = periodId;
165
+ organizationPeriod.periodId = organization.periodId;
151
166
  await organizationPeriod.save();
152
167
 
153
168
  result.push(organization);
@@ -1,7 +1,7 @@
1
1
  import { Decoder } from '@simonbackx/simple-encoding';
2
2
  import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
3
3
  import { SimpleError } from '@simonbackx/simple-errors';
4
- import { ChargeMembersRequest, LimitedFilteredRequest, PermissionLevel } from '@stamhoofd/structures';
4
+ import { ChargeRequest, LimitedFilteredRequest, PermissionLevel } from '@stamhoofd/structures';
5
5
 
6
6
  import { QueueHandler } from '@stamhoofd/queues';
7
7
  import { Context } from '../../../helpers/Context.js';
@@ -11,13 +11,12 @@ import { GetRegistrationsEndpoint } from '../../global/registration/GetRegistrat
11
11
  import { ChargeMembersEndpoint } from '../members/ChargeMembersEndpoint.js';
12
12
 
13
13
  type Params = Record<string, never>;
14
- type Query = LimitedFilteredRequest;
15
- type Body = ChargeMembersRequest;
14
+ type Query = undefined;
15
+ type Body = ChargeRequest;
16
16
  type ResponseBody = undefined;
17
17
 
18
18
  export class ChargeRegistrationsEndpoint extends Endpoint<Params, Query, Body, ResponseBody> {
19
- queryDecoder = LimitedFilteredRequest as Decoder<LimitedFilteredRequest>;
20
- bodyDecoder = ChargeMembersRequest as Decoder<ChargeMembersRequest>;
19
+ bodyDecoder = ChargeRequest as Decoder<ChargeRequest>;
21
20
 
22
21
  protected doesMatch(request: Request): [true, Params] | [false] {
23
22
  if (request.method !== 'POST') {
@@ -44,7 +43,7 @@ export class ChargeRegistrationsEndpoint extends Endpoint<Params, Query, Body, R
44
43
 
45
44
  ChargeMembersEndpoint.throwIfInvalidBody(body);
46
45
 
47
- const queueId = 'charge-registrations';
46
+ const queueId = 'charge-registrations-' + organization.id;
48
47
 
49
48
  if (QueueHandler.isRunning(queueId)) {
50
49
  throw new SimpleError({
@@ -55,7 +54,10 @@ export class ChargeRegistrationsEndpoint extends Endpoint<Params, Query, Body, R
55
54
  }
56
55
 
57
56
  await QueueHandler.schedule(queueId, async () => {
58
- const dataGenerator = fetchToAsyncIterator(request.query, {
57
+ const dataGenerator = fetchToAsyncIterator(new LimitedFilteredRequest({
58
+ filter: body.filter,
59
+ limit: 100,
60
+ }), {
59
61
  fetch: request => GetRegistrationsEndpoint.buildData(request, PermissionLevel.Write),
60
62
  });
61
63
 
@@ -5,8 +5,8 @@ import { PasswordToken, Platform, sendEmailTemplate, User } from '@stamhoofd/mod
5
5
  import { EmailTemplateType, Recipient, Replacement, UserPermissions, User as UserStruct, UserWithMembers } from '@stamhoofd/structures';
6
6
  import { Formatter } from '@stamhoofd/utility';
7
7
 
8
- import { AuthenticatedStructures } from '../../helpers/AuthenticatedStructures';
9
- import { Context } from '../../helpers/Context';
8
+ import { AuthenticatedStructures } from '../../helpers/AuthenticatedStructures.js';
9
+ import { Context } from '../../helpers/Context.js';
10
10
  type Params = Record<string, never>;
11
11
  type Query = undefined;
12
12
  type Body = UserStruct;
@@ -2,8 +2,8 @@ import { Request } from '@simonbackx/simple-endpoints';
2
2
  import { OrganizationFactory, Token, UserFactory } from '@stamhoofd/models';
3
3
  import { Token as TokenStruct } from '@stamhoofd/structures';
4
4
 
5
- import { testServer } from '../../../tests/helpers/TestServer';
6
- import { CreateTokenEndpoint } from './CreateTokenEndpoint';
5
+ import { testServer } from '../../../tests/helpers/TestServer.js';
6
+ import { CreateTokenEndpoint } from './CreateTokenEndpoint.js';
7
7
 
8
8
  describe('Endpoint.CreateToken', () => {
9
9
  // Test endpoint
@@ -3,7 +3,7 @@ import { SimpleError } from '@simonbackx/simple-errors';
3
3
  import { EmailVerificationCode, PasswordToken, Platform, Token, User } from '@stamhoofd/models';
4
4
  import { ChallengeGrantStruct, CreateTokenStruct, LoginMethod, PasswordGrantStruct, PasswordTokenGrantStruct, RefreshTokenGrantStruct, RequestChallengeGrantStruct, SignupResponse, Token as TokenStruct } from '@stamhoofd/structures';
5
5
 
6
- import { Context } from '../../helpers/Context';
6
+ import { Context } from '../../helpers/Context.js';
7
7
 
8
8
  type Params = Record<string, never>;
9
9
  type Query = undefined;
@@ -1,6 +1,6 @@
1
1
  import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
2
2
 
3
- import { Context } from '../../helpers/Context';
3
+ import { Context } from '../../helpers/Context.js';
4
4
 
5
5
  type Params = Record<string, never>;
6
6
  type Query = undefined;