@stamhoofd/backend 2.121.0 → 2.122.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (429) hide show
  1. package/output-2.txt +1 -0
  2. package/output.txt +1 -0
  3. package/package.json +69 -52
  4. package/src/audit-logs/EventNotificationLogger.ts +40 -0
  5. package/src/audit-logs/ModelLogger.ts +19 -15
  6. package/src/audit-logs/OrganizationLogger.ts +1 -1
  7. package/src/audit-logs/RegistrationInvitationLogger.ts +24 -24
  8. package/src/audit-logs/init.ts +8 -2
  9. package/src/boot.ts +19 -18
  10. package/src/crons/amazon-ses.ts +13 -26
  11. package/src/crons/balance-emails.ts +3 -5
  12. package/src/crons/clearExcelCache.test.ts +1 -1
  13. package/src/crons/clearExcelCache.ts +1 -2
  14. package/src/crons/drip-emails.ts +42 -0
  15. package/src/crons/endFunctionsOfUsersWithoutRegistration.ts +4 -0
  16. package/src/crons/helpers/isOutside.ts +11 -0
  17. package/src/crons/helpers/useSavedIterator.ts +32 -0
  18. package/src/crons/index.ts +5 -0
  19. package/src/crons/invoices.ts +32 -38
  20. package/src/crons/members-fees.ts +50 -0
  21. package/src/crons/mollie-chargebacks.ts +14 -15
  22. package/src/crons/service-fees.ts +152 -0
  23. package/src/crons/stripe-invoices.ts +48 -0
  24. package/src/crons/transfer-fees.ts +176 -0
  25. package/src/crons/update-cached-balances.ts +4 -4
  26. package/src/crons.ts +7 -64
  27. package/src/debug.ts +4 -2
  28. package/src/email-recipient-loaders/documents.ts +1 -1
  29. package/src/email-recipient-loaders/members.ts +1 -1
  30. package/src/email-recipient-loaders/payments.ts +4 -6
  31. package/src/email-recipient-loaders/registrations.ts +1 -1
  32. package/src/email-replacements/getEmailReplacementsForPayment.ts +5 -9
  33. package/src/endpoints/admin/members/ChargeMembersEndpoint.ts +1 -1
  34. package/src/endpoints/admin/memberships/ChargeMembershipsEndpoint.ts +1 -1
  35. package/src/endpoints/admin/memberships/GetChargeMembershipsSummaryEndpoint.ts +3 -5
  36. package/src/endpoints/admin/organizations/ChargeOrganizationsEndpoint.ts +1 -1
  37. package/src/endpoints/admin/organizations/GetOrganizationsCountEndpoint.ts +1 -1
  38. package/src/endpoints/admin/organizations/GetOrganizationsEndpoint.ts +13 -7
  39. package/src/endpoints/admin/organizations/PatchOrganizationsEndpoint.ts +4 -6
  40. package/src/endpoints/admin/organizations/PatchPackagesEndpoint.test.ts +10 -6
  41. package/src/endpoints/admin/organizations/PatchPackagesEndpoint.ts +39 -21
  42. package/src/endpoints/admin/registrations/ChargeRegistrationsEndpoint.ts +1 -1
  43. package/src/endpoints/auth/CreateAdminEndpoint.ts +23 -5
  44. package/src/endpoints/auth/CreateTokenEndpoint.ts +2 -2
  45. package/src/endpoints/auth/DeleteTokenEndpoint.ts +1 -1
  46. package/src/endpoints/auth/DeleteUserEndpoint.ts +3 -3
  47. package/src/endpoints/auth/ForgotPasswordEndpoint.ts +1 -1
  48. package/src/endpoints/auth/GetOtherUserEndpoint.ts +1 -1
  49. package/src/endpoints/auth/GetUserEndpoint.ts +1 -1
  50. package/src/endpoints/auth/OpenIDConnectAuthTokenEndpoint.ts +1 -1
  51. package/src/endpoints/auth/OpenIDConnectStartEndpoint.ts +1 -1
  52. package/src/endpoints/auth/PatchUserEndpoint.ts +5 -8
  53. package/src/endpoints/auth/PollEmailVerificationEndpoint.ts +1 -1
  54. package/src/endpoints/auth/RetryEmailVerificationEndpoint.ts +1 -1
  55. package/src/endpoints/auth/SignupEndpoint.ts +2 -3
  56. package/src/endpoints/auth/VerifyEmailEndpoint.ts +20 -3
  57. package/src/endpoints/frontend/FrontendEnvironmentEndpoint.ts +2 -1
  58. package/src/endpoints/global/addresses/SearchRegionsEndpoint.ts +2 -4
  59. package/src/endpoints/global/addresses/ValidateAddressEndpoint.ts +1 -1
  60. package/src/endpoints/global/audit-logs/GetAuditLogsEndpoint.ts +5 -7
  61. package/src/endpoints/global/caddy/CheckDomainCertEndpoint.ts +2 -2
  62. package/src/endpoints/global/email/CreateEmailEndpoint.ts +3 -4
  63. package/src/endpoints/global/email/GetAdminEmailsEndpoint.test.ts +1 -1
  64. package/src/endpoints/global/email/GetAdminEmailsEndpoint.ts +1 -2
  65. package/src/endpoints/global/email/GetEmailAddressEndpoint.ts +4 -6
  66. package/src/endpoints/global/email/GetEmailEndpoint.ts +1 -1
  67. package/src/endpoints/global/email/GetUserEmailsEndpoint.test.ts +1 -1
  68. package/src/endpoints/global/email/GetUserEmailsEndpoint.ts +1 -1
  69. package/src/endpoints/global/email/ManageEmailAddressEndpoint.ts +6 -10
  70. package/src/endpoints/global/email/PatchEmailEndpoint.test.ts +4 -7
  71. package/src/endpoints/global/email/PatchEmailEndpoint.ts +6 -9
  72. package/src/endpoints/global/email-recipients/GetEmailRecipientsCountEndpoint.ts +1 -1
  73. package/src/endpoints/global/email-recipients/GetEmailRecipientsEndpoint.test.ts +1 -1
  74. package/src/endpoints/global/email-recipients/GetEmailRecipientsEndpoint.ts +1 -1
  75. package/src/endpoints/global/email-recipients/RetryEmailRecipientEndpoint.ts +2 -2
  76. package/src/endpoints/global/events/GetEventNotificationsCountEndpoint.ts +1 -1
  77. package/src/endpoints/global/events/GetEventNotificationsEndpoint.ts +3 -3
  78. package/src/endpoints/global/events/GetEventsEndpoint.ts +3 -3
  79. package/src/endpoints/global/events/PatchEventNotificationsEndpoint.test.ts +49 -4
  80. package/src/endpoints/global/events/PatchEventNotificationsEndpoint.ts +5 -8
  81. package/src/endpoints/global/events/PatchEventsEndpoint.test.ts +12 -44
  82. package/src/endpoints/global/events/PatchEventsEndpoint.ts +128 -127
  83. package/src/endpoints/global/files/ExportToExcelEndpoint.ts +9 -9
  84. package/src/endpoints/global/files/GetFileCache.ts +3 -4
  85. package/src/endpoints/global/files/UploadFile.ts +3 -4
  86. package/src/endpoints/global/files/UploadImage.ts +3 -4
  87. package/src/endpoints/global/groups/GetGroupsCountEndpoint.ts +1 -1
  88. package/src/endpoints/global/groups/GetGroupsEndpoint.test.ts +1 -1
  89. package/src/endpoints/global/groups/GetGroupsEndpoint.ts +4 -2
  90. package/src/endpoints/global/members/GetMemberFamilyEndpoint.ts +2 -3
  91. package/src/endpoints/global/members/GetMembersCountEndpoint.ts +1 -1
  92. package/src/endpoints/global/members/GetMembersEndpoint.test.ts +2 -2
  93. package/src/endpoints/global/members/GetMembersEndpoint.ts +10 -12
  94. package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.test.ts +195 -12
  95. package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.ts +16 -22
  96. package/src/endpoints/global/members/helpers/validateGroupFilter.ts +6 -30
  97. package/src/endpoints/global/members/shouldCheckIfMemberIsDuplicate.ts +1 -1
  98. package/src/endpoints/global/organizations/CheckRegisterCodeEndpoint.ts +1 -1
  99. package/src/endpoints/global/organizations/CreateOrganizationEndpoint.ts +40 -8
  100. package/src/endpoints/global/organizations/GetOrganizationFromDomainEndpoint.ts +2 -2
  101. package/src/endpoints/global/organizations/GetOrganizationFromUriEndpoint.ts +2 -2
  102. package/src/endpoints/global/organizations/SearchOrganizationEndpoint.test.ts +4 -1
  103. package/src/endpoints/global/organizations/SearchOrganizationEndpoint.ts +4 -5
  104. package/src/endpoints/global/payments/StripeWebhookEndpoint.ts +9 -16
  105. package/src/endpoints/global/platform/GetPlatformAdminsEndpoint.ts +1 -1
  106. package/src/endpoints/global/platform/GetPlatformEndpoint.ts +1 -1
  107. package/src/endpoints/global/platform/PatchPlatformEnpoint.test.ts +1 -1
  108. package/src/endpoints/global/platform/PatchPlatformEnpoint.ts +11 -11
  109. package/src/endpoints/global/platform-memberships/GetPlatformMembershipsCountEndpoint.ts +31 -31
  110. package/src/endpoints/global/platform-memberships/GetPlatformMembershipsEndpoint.ts +18 -20
  111. package/src/endpoints/global/registration/GetRegistrationsCountEndpoint.ts +1 -1
  112. package/src/endpoints/global/registration/GetRegistrationsEndpoint.test.ts +1 -1
  113. package/src/endpoints/global/registration/GetRegistrationsEndpoint.ts +6 -10
  114. package/src/endpoints/global/registration/GetUserDetailedPayableBalanceEndpoint.ts +35 -6
  115. package/src/endpoints/global/registration/GetUserDocumentsEndpoint.ts +2 -2
  116. package/src/endpoints/global/registration/GetUserMembersEndpoint.ts +1 -1
  117. package/src/endpoints/global/registration/GetUserPayableBalanceEndpoint.ts +1 -1
  118. package/src/endpoints/global/registration/PatchUserMembersEndpoint.test.ts +2 -2
  119. package/src/endpoints/global/registration/PatchUserMembersEndpoint.ts +3 -3
  120. package/src/endpoints/global/registration/RegisterMembersEndpoint.test.ts +90 -6
  121. package/src/endpoints/global/registration/RegisterMembersEndpoint.ts +35 -34
  122. package/src/endpoints/global/registration-invitations/GetRegistrationInvitationsCountEndpoint.ts +1 -1
  123. package/src/endpoints/global/registration-invitations/GetRegistrationInvitationsEndpoint.test.ts +62 -63
  124. package/src/endpoints/global/registration-invitations/GetRegistrationInvitationsEndpoint.ts +6 -9
  125. package/src/endpoints/global/registration-invitations/PatchRegistrationInvitationsEndpoint.test.ts +51 -52
  126. package/src/endpoints/global/registration-invitations/PatchRegistrationInvitationsEndpoint.ts +6 -7
  127. package/src/endpoints/global/registration-periods/GetRegistrationPeriodsCountEndpoint.ts +43 -0
  128. package/src/endpoints/global/registration-periods/GetRegistrationPeriodsEndpoint.ts +1 -1
  129. package/src/endpoints/global/registration-periods/PatchRegistrationPeriodsEndpoint.ts +13 -5
  130. package/src/endpoints/global/sso/GetSSOEndpoint.ts +2 -3
  131. package/src/endpoints/global/sso/SetSSOEndpoint.ts +1 -1
  132. package/src/endpoints/global/webshops/GetWebshopFromDomainEndpoint.ts +2 -2
  133. package/src/endpoints/global/webshops/GetWebshopsEndpoint.test.ts +1 -2
  134. package/src/endpoints/global/webshops/GetWebshopsEndpoint.ts +2 -4
  135. package/src/endpoints/organization/dashboard/balance-items/GetBalanceItemEndpoint.ts +2 -2
  136. package/src/endpoints/organization/dashboard/balance-items/GetBalanceItemsCountEndpoint.ts +1 -1
  137. package/src/endpoints/organization/dashboard/balance-items/GetBalanceItemsEndpoint.ts +3 -4
  138. package/src/endpoints/organization/dashboard/balance-items/PatchBalanceItemsEndpoint.ts +7 -9
  139. package/src/endpoints/organization/dashboard/billing/ApplyRegisterCodeEndpoint.test.ts +73 -0
  140. package/src/endpoints/organization/dashboard/billing/ApplyRegisterCodeEndpoint.ts +89 -0
  141. package/src/endpoints/organization/dashboard/billing/DeactivatePackageEndpoint.ts +1 -5
  142. package/src/endpoints/organization/dashboard/billing/DeleteOrganizationMandateEndpoint.ts +11 -11
  143. package/src/endpoints/organization/dashboard/billing/GetOrganizationDetailedPayableBalanceCollectionEndpoint.ts +2 -2
  144. package/src/endpoints/organization/dashboard/billing/GetOrganizationDetailedPayableBalanceEndpoint.ts +8 -8
  145. package/src/endpoints/organization/dashboard/billing/GetOrganizationMandatesEndpoint.ts +9 -9
  146. package/src/endpoints/organization/dashboard/billing/GetOrganizationPayableBalanceEndpoint.ts +2 -2
  147. package/src/endpoints/organization/dashboard/billing/GetOrganizationPayableInvoicesEndpoint.ts +68 -0
  148. package/src/endpoints/organization/dashboard/billing/GetPackagesEndpoint.ts +4 -4
  149. package/src/endpoints/organization/dashboard/billing/GetRegisterCodeEndpoint.ts +66 -0
  150. package/src/endpoints/organization/dashboard/billing/OrganizationCheckoutEndpoint.test.ts +949 -0
  151. package/src/endpoints/organization/dashboard/billing/OrganizationCheckoutEndpoint.ts +60 -57
  152. package/src/endpoints/organization/dashboard/billing/PatchOrganizationMandatesEndpoint.ts +20 -20
  153. package/src/endpoints/organization/dashboard/documents/GetDocumentTemplateXML.ts +1 -1
  154. package/src/endpoints/organization/dashboard/documents/GetDocumentTemplatesCountEndpoint.ts +1 -1
  155. package/src/endpoints/organization/dashboard/documents/GetDocumentTemplatesEndpoint.ts +1 -1
  156. package/src/endpoints/organization/dashboard/documents/GetDocumentsCountEndpoint.ts +1 -1
  157. package/src/endpoints/organization/dashboard/documents/GetDocumentsEndpoint.ts +1 -1
  158. package/src/endpoints/organization/dashboard/documents/PatchDocumentEndpoint.ts +10 -2
  159. package/src/endpoints/organization/dashboard/documents/PatchDocumentTemplatesEndpoint.test.ts +2 -2
  160. package/src/endpoints/organization/dashboard/documents/PatchDocumentTemplatesEndpoint.ts +2 -2
  161. package/src/endpoints/organization/dashboard/email/CheckEmailBouncesEndpoint.ts +1 -1
  162. package/src/endpoints/organization/dashboard/email-templates/GetEmailTemplatesEndpoint.test.ts +1 -1
  163. package/src/endpoints/organization/dashboard/email-templates/GetEmailTemplatesEndpoint.ts +10 -8
  164. package/src/endpoints/organization/dashboard/email-templates/PatchEmailTemplatesEndpoint.test.ts +1 -1
  165. package/src/endpoints/organization/dashboard/email-templates/PatchEmailTemplatesEndpoint.ts +5 -6
  166. package/src/endpoints/organization/dashboard/invoices/GetInvoicesCountEndpoint.ts +1 -1
  167. package/src/endpoints/organization/dashboard/invoices/GetInvoicesEndpoint.ts +10 -6
  168. package/src/endpoints/organization/dashboard/invoices/PatchInvoicesEndpoint.ts +11 -2
  169. package/src/endpoints/organization/dashboard/mollie/CheckMollieEndpoint.ts +4 -5
  170. package/src/endpoints/organization/dashboard/mollie/ConnectMollieEndpoint.ts +5 -5
  171. package/src/endpoints/organization/dashboard/mollie/DisconnectMollieEndpoint.ts +2 -2
  172. package/src/endpoints/organization/dashboard/mollie/GetMollieDashboardEndpoint.ts +7 -7
  173. package/src/endpoints/organization/dashboard/nolt/CreateNoltTokenEndpoint.ts +1 -1
  174. package/src/endpoints/organization/dashboard/organization/GetOrganizationArchivedGroups.ts +2 -2
  175. package/src/endpoints/organization/dashboard/organization/GetOrganizationDeletedGroups.ts +1 -1
  176. package/src/endpoints/organization/dashboard/organization/GetUitpasClientIdEndpoint.ts +1 -1
  177. package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.test.ts +2 -2
  178. package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.ts +50 -12
  179. package/src/endpoints/organization/dashboard/organization/SearchUitpasOrganizersEndpoint.ts +2 -2
  180. package/src/endpoints/organization/dashboard/organization/SetOrganizationDomainEndpoint.ts +5 -10
  181. package/src/endpoints/organization/dashboard/organization/SetUitpasClientCredentialsEndpoint.ts +1 -1
  182. package/src/endpoints/organization/dashboard/payments/GetPaymentsCountEndpoint.ts +1 -1
  183. package/src/endpoints/organization/dashboard/payments/GetPaymentsEndpoint.ts +3 -4
  184. package/src/endpoints/organization/dashboard/payments/PatchPaymentsEndpoint.ts +21 -14
  185. package/src/endpoints/organization/dashboard/receivable-balances/ChargeReceivableBalancesEndpoint.ts +35 -28
  186. package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalanceEndpoint.ts +2 -3
  187. package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalancesCountEndpoint.ts +1 -1
  188. package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalancesEndpoint.ts +1 -1
  189. package/src/endpoints/organization/dashboard/registration-periods/GetOrganizationRegistrationPeriodsEndpoint.test.ts +1 -1
  190. package/src/endpoints/organization/dashboard/registration-periods/GetOrganizationRegistrationPeriodsEndpoint.ts +2 -3
  191. package/src/endpoints/organization/dashboard/registration-periods/MoveRegistrationPeriods.test.ts +1 -1
  192. package/src/endpoints/organization/dashboard/registration-periods/PatchOrganizationRegistrationPeriodsEndpoint.test.ts +1 -1
  193. package/src/endpoints/organization/dashboard/registration-periods/PatchOrganizationRegistrationPeriodsEndpoint.ts +19 -18
  194. package/src/endpoints/organization/dashboard/registration-periods/SetupStepReviewEndpoint.ts +4 -5
  195. package/src/endpoints/organization/dashboard/stripe/ConnectStripeEndpoint.ts +1 -1
  196. package/src/endpoints/organization/dashboard/stripe/DeleteStripeAccountEndpoint.ts +2 -3
  197. package/src/endpoints/organization/dashboard/stripe/GetStripeAccountLinkEndpoint.ts +2 -2
  198. package/src/endpoints/organization/dashboard/stripe/GetStripeAccountsEndpoint.ts +1 -1
  199. package/src/endpoints/organization/dashboard/stripe/GetStripeLoginLinkEndpoint.ts +2 -2
  200. package/src/endpoints/organization/dashboard/stripe/UpdateStripeAccountEndpoint.ts +1 -1
  201. package/src/endpoints/organization/dashboard/users/CreateApiUserEndpoint.ts +1 -1
  202. package/src/endpoints/organization/dashboard/users/DeleteUserEndpoint.ts +1 -1
  203. package/src/endpoints/organization/dashboard/users/GetApiUsersEndpoint.ts +1 -1
  204. package/src/endpoints/organization/dashboard/users/GetOrganizationAdminsEndpoint.ts +1 -1
  205. package/src/endpoints/organization/dashboard/users/PatchApiUserEndpoint.ts +4 -6
  206. package/src/endpoints/organization/dashboard/webshops/CreateWebshopEndpoint.ts +10 -15
  207. package/src/endpoints/organization/dashboard/webshops/DeleteWebshopEndpoint.ts +1 -1
  208. package/src/endpoints/organization/dashboard/webshops/GetDiscountCodesEndpoint.ts +2 -2
  209. package/src/endpoints/organization/dashboard/webshops/GetWebshopOrdersCountEndpoint.ts +1 -1
  210. package/src/endpoints/organization/dashboard/webshops/GetWebshopOrdersEndpoint.ts +1 -1
  211. package/src/endpoints/organization/dashboard/webshops/GetWebshopTicketsEndpoint.ts +1 -1
  212. package/src/endpoints/organization/dashboard/webshops/GetWebshopUriAvailabilityEndpoint.ts +11 -2
  213. package/src/endpoints/organization/dashboard/webshops/PatchDiscountCodesEndpoint.ts +4 -6
  214. package/src/endpoints/organization/dashboard/webshops/PatchWebshopEndpoint.ts +22 -7
  215. package/src/endpoints/organization/dashboard/webshops/PatchWebshopOrdersEndpoint.ts +20 -27
  216. package/src/endpoints/organization/dashboard/webshops/PatchWebshopTicketsEndpoint.ts +1 -1
  217. package/src/endpoints/organization/dashboard/webshops/SearchUitpasEventsEndpoint.ts +2 -2
  218. package/src/endpoints/organization/dashboard/webshops/VerifyWebshopDomainEndpoint.ts +2 -3
  219. package/src/endpoints/organization/dashboard/webshops/WebshopReservedPathSegments.test.ts +95 -0
  220. package/src/endpoints/organization/shared/ExchangePaymentEndpoint.ts +2 -2
  221. package/src/endpoints/organization/shared/GetDocumentHtml.ts +1 -1
  222. package/src/endpoints/organization/shared/GetPaymentEndpoint.ts +1 -1
  223. package/src/endpoints/organization/shared/GetUitpasNumberDetailsEndpoint.ts +3 -5
  224. package/src/endpoints/organization/shared/auth/GetOrganizationEndpoint.ts +1 -1
  225. package/src/endpoints/organization/webshops/CheckWebshopDiscountCodesEndpoint.ts +4 -1
  226. package/src/endpoints/organization/webshops/GetOrderByPaymentEndpoint.ts +14 -3
  227. package/src/endpoints/organization/webshops/GetOrderEndpoint.ts +14 -2
  228. package/src/endpoints/organization/webshops/GetTicketsEndpoint.ts +37 -16
  229. package/src/endpoints/organization/webshops/GetWebshopEndpoint.test.ts +34 -2
  230. package/src/endpoints/organization/webshops/GetWebshopEndpoint.ts +4 -2
  231. package/src/endpoints/organization/webshops/PlaceOrderEndpoint.test.ts +74 -3
  232. package/src/endpoints/organization/webshops/PlaceOrderEndpoint.ts +16 -33
  233. package/src/endpoints/organization/webshops/RetrieveUitpasSocialTariffPriceEndpoint.ts +3 -5
  234. package/src/endpoints/organization/webshops/WebshopAuthHelper.ts +36 -0
  235. package/src/endpoints/system/HealthEndpoint.ts +1 -1
  236. package/src/excel-loaders/balance-items.ts +1 -1
  237. package/src/excel-loaders/event-notifications.ts +1 -1
  238. package/src/excel-loaders/members.ts +1 -1
  239. package/src/excel-loaders/organizations.ts +3 -3
  240. package/src/excel-loaders/payments.ts +31 -1
  241. package/src/excel-loaders/platform-memberships.ts +13 -14
  242. package/src/excel-loaders/receivable-balances.ts +2 -2
  243. package/src/excel-loaders/registrations.ts +2 -3
  244. package/src/helpers/AddressValidator.ts +7 -14
  245. package/src/helpers/AdminPermissionChecker.ts +50 -63
  246. package/src/helpers/AuthenticatedStructures.ts +69 -55
  247. package/src/helpers/BalanceItemRelationsBackfiller.test.ts +174 -0
  248. package/src/helpers/BalanceItemRelationsBackfiller.ts +163 -0
  249. package/src/helpers/BuckarooHelper.ts +2 -4
  250. package/src/helpers/CheckSettlements.ts +12 -24
  251. package/src/helpers/Context.ts +15 -10
  252. package/src/helpers/CookieHelper.ts +1 -2
  253. package/src/helpers/EmailResumer.ts +1 -2
  254. package/src/helpers/FileCache.ts +2 -3
  255. package/src/helpers/FinancialSupportHelper.ts +2 -2
  256. package/src/helpers/FlagMomentCleanup.ts +1 -2
  257. package/src/helpers/ForwardHandler.ts +5 -10
  258. package/src/helpers/GlobalHelper.ts +3 -3
  259. package/src/helpers/LegacyBillingConverter.ts +787 -0
  260. package/src/helpers/MemberMerger.test.ts +782 -0
  261. package/src/helpers/MemberMerger.ts +600 -0
  262. package/src/helpers/MemberUserSyncer.ts +6 -12
  263. package/src/helpers/MembershipCharger.ts +2 -4
  264. package/src/helpers/PaymentCustomerResolver.test.ts +203 -0
  265. package/src/helpers/PaymentCustomerResolver.ts +144 -0
  266. package/src/helpers/PeriodHelper.ts +2 -3
  267. package/src/helpers/RecordAnswerHelper.test.ts +105 -110
  268. package/src/helpers/RecordAnswerHelper.ts +7 -7
  269. package/src/helpers/SeedTools.ts +106 -0
  270. package/src/helpers/ServiceFeeHelper.ts +125 -15
  271. package/src/helpers/SetupStepUpdater.ts +38 -32
  272. package/src/helpers/StamhoofdFilterAccessHelper.ts +52 -0
  273. package/src/helpers/StripeHelper.ts +14 -36
  274. package/src/helpers/StripeInvoicer.ts +419 -0
  275. package/src/helpers/StripePayoutChecker.ts +5 -10
  276. package/src/helpers/TagHelper.ts +7 -8
  277. package/src/helpers/TemporaryMemberAccess.ts +1 -2
  278. package/src/helpers/ThrottledQueue.ts +1 -2
  279. package/src/helpers/UitpasTokenRepository.ts +1 -2
  280. package/src/helpers/ViesHelper.ts +7 -11
  281. package/src/helpers/XlsxTransformerColumnHelper.ts +1 -1
  282. package/src/helpers/outstandingBalanceJoin.ts +2 -2
  283. package/src/helpers/updateMemberDetailsUitpasNumber.ts +3 -5
  284. package/src/migrate.ts +12 -5
  285. package/src/{seeds → migrations}/0000000004-single-organization.ts +10 -1
  286. package/src/migrations/0000000006-default-organization.ts +139 -0
  287. package/src/{seeds → migrations}/1715028563-user-permissions.ts +17 -27
  288. package/src/{seeds/1765896674-document-update-year.test.ts → migrations/1750090029-document-update-year.test.ts} +27 -26
  289. package/src/migrations/1750090029-document-update-year.ts +103 -0
  290. package/src/{seeds → migrations}/1750090030-records-configuration.ts +33 -32
  291. package/src/migrations/1750090031-records-configuration-webshops.ts +36 -0
  292. package/src/migrations/1752848540-national-numbers.ts +585 -0
  293. package/src/migrations/1752848550-records-configuration-group-filter.ts +1064 -0
  294. package/src/{seeds → migrations}/1752848561-groups-registration-periods.ts +70 -26
  295. package/src/{seeds → migrations}/1754560914-groups-prices.test.ts +1 -1
  296. package/src/{seeds → migrations}/1754560914-groups-prices.ts +9 -15
  297. package/src/{seeds → migrations}/1756293699-fill-previous-next-period-id.ts +1 -2
  298. package/src/migrations/1761665607-sync-member-users.ts +40 -0
  299. package/src/migrations/1779121240-invoice-email-template.sql +6 -0
  300. package/src/migrations/1779986893-default-payment-failed-email-templates.sql +4 -0
  301. package/src/migrations/1780578166-convert-legacy-billing.ts +13 -0
  302. package/src/{seeds/1755876819-remove-duplicate-members.ts → migrations/1780665426-remove-duplicate-members.ts} +23 -4
  303. package/src/migrations/1780933598-document-groups.ts +88 -0
  304. package/src/migrations/1781692342-balance-item-relations.ts +13 -0
  305. package/src/migrations/1781857866-platform-admins.ts +103 -0
  306. package/src/migrations/1781857867-rm-old-platform-admins.ts +25 -0
  307. package/src/seeds/0000000001-throw.ts +5 -0
  308. package/src/seeds/1760702452-update-balance-price-paid.ts +19 -0
  309. package/src/seeds/1760702453-update-balance-invoiced.ts +19 -0
  310. package/src/seeds/1760702454-update-cached-outstanding-balance-from-items.ts +51 -14
  311. package/src/seeds/1773754928-force-save-members.ts +41 -8
  312. package/src/seeds/1780665427-schedule-stock-updates.ts +45 -0
  313. package/src/seeds/1780665428-group-update-occupancy.ts +31 -0
  314. package/src/seeds/1780915001-fill-payment-customer.ts +70 -0
  315. package/src/seeds/1780915002-update-orders.ts +39 -0
  316. package/src/seeds/1782047708-organization-company-address.ts +44 -0
  317. package/src/seeds-temporary/1769088653-uitpas-status.ts +1 -2
  318. package/src/seeds-temporary/1780416000-migrate-audit-log-legacy-enums.test.ts +69 -0
  319. package/src/seeds-temporary/1780416000-migrate-audit-log-legacy-enums.ts +85 -0
  320. package/src/services/AuditLogService.test.ts +51 -0
  321. package/src/services/AuditLogService.ts +45 -0
  322. package/src/services/BalanceItemService.ts +141 -44
  323. package/src/services/CpuService.ts +3 -6
  324. package/src/services/DatabaseCollationService.test.ts +1 -2
  325. package/src/services/DocumentService.ts +1 -2
  326. package/src/services/EventNotificationService.ts +1 -1
  327. package/src/services/FileSignService.ts +2 -4
  328. package/src/services/InvoicePdfService.ts +286 -0
  329. package/src/services/InvoiceService.ts +204 -251
  330. package/src/services/InvoiceXMLService.ts +424 -0
  331. package/src/services/MemberNumberService.ts +6 -11
  332. package/src/services/MemberRecordStore.ts +8 -10
  333. package/src/services/MollieService.ts +114 -121
  334. package/src/services/PaymentMandateService.ts +45 -45
  335. package/src/services/PaymentReallocationService.test.ts +1 -1
  336. package/src/services/PaymentReallocationService.ts +7 -9
  337. package/src/services/PaymentService.ts +444 -308
  338. package/src/services/PlatformMembershipService.ts +4 -8
  339. package/src/services/ReferralService.ts +223 -0
  340. package/src/services/RegistrationService.ts +63 -53
  341. package/src/services/SSOService.test.ts +119 -0
  342. package/src/services/SSOService.ts +56 -49
  343. package/src/services/STPackageService.ts +97 -61
  344. package/src/services/UniqueMemberNumberService.ts +69 -0
  345. package/src/services/UniqueUserService.ts +3 -6
  346. package/src/services/VATService.ts +85 -0
  347. package/src/services/uitpas/PassholderEndpoints.ts +3 -6
  348. package/src/services/uitpas/UitpasService.ts +6 -10
  349. package/src/services/uitpas/checkUitpasNumbers.ts +2 -4
  350. package/src/services/uitpas/getSocialTariffForUitpasNumbers.ts +3 -6
  351. package/src/services/uitpas/searchUitpasEvents.ts +1 -2
  352. package/src/sql-filters/audit-logs.ts +1 -1
  353. package/src/sql-filters/balance-item-payments.ts +1 -1
  354. package/src/sql-filters/balance-items.ts +1 -1
  355. package/src/sql-filters/base-registration-filter-compilers.ts +5 -33
  356. package/src/sql-filters/document-templates.ts +1 -1
  357. package/src/sql-filters/documents.ts +1 -1
  358. package/src/sql-filters/email-recipients.ts +1 -1
  359. package/src/sql-filters/emails.ts +1 -1
  360. package/src/sql-filters/event-notifications.ts +1 -1
  361. package/src/sql-filters/events.ts +6 -1
  362. package/src/sql-filters/groups.ts +5 -0
  363. package/src/sql-filters/invoiced-balance-items.ts +1 -1
  364. package/src/sql-filters/invoices.ts +1 -1
  365. package/src/sql-filters/member-responsibility-records.ts +1 -1
  366. package/src/sql-filters/members.ts +1 -1
  367. package/src/sql-filters/orders.ts +4 -4
  368. package/src/sql-filters/organization-registration-periods.ts +1 -1
  369. package/src/sql-filters/organizations.ts +1 -1
  370. package/src/sql-filters/platform-memberships.ts +3 -3
  371. package/src/sql-filters/receivable-balances.ts +1 -1
  372. package/src/sql-filters/registration-periods.ts +1 -1
  373. package/src/sql-filters/registrations.ts +1 -1
  374. package/src/sql-filters/tickets.ts +1 -1
  375. package/src/sql-filters/users.ts +1 -1
  376. package/src/sql-sorters/groups.ts +23 -0
  377. package/src/sql-sorters/platform-memberships.ts +16 -16
  378. package/src/sql-sorters/registration-invitations.ts +2 -2
  379. package/tests/actions/patchOrganizationMember.ts +1 -1
  380. package/tests/actions/patchUserMember.ts +1 -1
  381. package/tests/assertions/assertBalances.ts +6 -12
  382. package/tests/e2e/api-rate-limits.test.ts +12 -24
  383. package/tests/e2e/bundle-discounts.test.ts +4 -1
  384. package/tests/e2e/charge-members.test.ts +13 -11
  385. package/tests/e2e/documents.test.ts +4 -1
  386. package/tests/e2e/register.test.ts +7 -9
  387. package/tests/e2e/stock.test.ts +4 -3
  388. package/tests/e2e/tickets.test.ts +1 -1
  389. package/tests/helpers/MollieMocker.ts +462 -0
  390. package/tests/helpers/PayconiqMocker.ts +138 -45
  391. package/tests/helpers/StripeMocker.ts +9 -6
  392. package/tests/helpers/index.ts +4 -0
  393. package/tests/init/initAdmin.ts +2 -2
  394. package/tests/init/initBundleDiscount.ts +1 -1
  395. package/tests/init/initMembershipOrganization.ts +13 -0
  396. package/tests/init/initPermissionRole.ts +3 -4
  397. package/tests/vitest.global.setup.ts +1 -1
  398. package/vitest.config.js +6 -0
  399. package/.nvmrc +0 -1
  400. package/src/helpers/GroupBuilder.ts +0 -418
  401. package/src/seeds/0000000000-example.ts +0 -11
  402. package/src/seeds/1722256498-group-update-occupancy.ts +0 -52
  403. package/src/seeds/1726572303-schedule-stock-updates.ts +0 -52
  404. package/src/seeds/1726847064-setup-steps.ts +0 -16
  405. package/src/seeds/1728928974-update-cached-outstanding-balance-from-items.ts +0 -31
  406. package/src/seeds/1729253172-update-orders.ts +0 -21
  407. package/src/seeds/1733319079-fill-paying-organization-ids.ts +0 -68
  408. package/src/seeds/1733748412-update-deleted-order-numbers.ts +0 -109
  409. package/src/seeds/1733994455-balance-item-status-open.ts +0 -30
  410. package/src/seeds/1740046783-update-membership.ts +0 -17
  411. package/src/seeds/1741008870-fix-auditlog-description.ts +0 -50
  412. package/src/seeds/1741011468-fix-auditlog-description-uft16.ts +0 -88
  413. package/src/seeds/1741268179-fix-group-dates-of-events.ts +0 -32
  414. package/src/seeds/1751445358-upload-email-attachments.ts +0 -106
  415. package/src/seeds/1755532883-update-email-sender-ids.ts +0 -47
  416. package/src/seeds/1755790070-fill-email-recipient-errors.ts +0 -96
  417. package/src/seeds/1756115432-remove-old-drafts.ts +0 -16
  418. package/src/seeds/1756115433-fill-email-recipient-organization-id.ts +0 -30
  419. package/src/seeds/1756303697-update-email-counts.ts +0 -76
  420. package/src/seeds/1761665607-sync-member-users.ts +0 -59
  421. package/src/seeds/1765896674-document-update-year.ts +0 -66
  422. /package/src/{seeds → migrations}/0000000001-development-user.ts +0 -0
  423. /package/src/{seeds → migrations}/0000000002-clear-stamhoofd-email-templates.ts +0 -0
  424. /package/src/{seeds → migrations}/0000000003-default-email-templates.ts +0 -0
  425. /package/src/{seeds → migrations}/1752848561-groups-registration-periods.test.ts +0 -0
  426. /package/src/{seeds → migrations}/1766150402-document-published-at.test.ts +0 -0
  427. /package/src/{seeds → migrations}/1766150402-document-published-at.ts +0 -0
  428. /package/src/{seeds → migrations}/1779121239-default-invoice-email-template.sql +0 -0
  429. /package/src/{seeds → migrations}/data/default-email-templates.sql +0 -0
@@ -1,9 +1,9 @@
1
- import type { Decoder} from '@simonbackx/simple-encoding';
1
+ import type { Decoder } from '@simonbackx/simple-encoding';
2
2
  import { AutoEncoder, field, 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 { MollieToken } from '@stamhoofd/models';
6
- import type { Organization as OrganizationStruct} from '@stamhoofd/structures';
6
+ import type { Organization as OrganizationStruct } from '@stamhoofd/structures';
7
7
  import { PermissionLevel } from '@stamhoofd/structures';
8
8
 
9
9
  import { AuthenticatedStructures } from '../../../../helpers/AuthenticatedStructures.js';
@@ -48,9 +48,9 @@ export class ConnectMollieEndpoint extends Endpoint<Params, Query, Body, Respons
48
48
  }
49
49
 
50
50
  const mollieToken = await MollieToken.create(organization, request.body.code);
51
- const service = await MollieService.create({sellingOrganization: organization})
51
+ const service = await MollieService.create({ sellingOrganization: organization });
52
52
  if (service) {
53
- await service.setupOnboarding()
53
+ await service.setupOnboarding();
54
54
 
55
55
  // Check settlements after linking (shouldn't block)
56
56
  checkMollieSettlementsFor(mollieToken.accessToken, true).catch(console.error);
@@ -1,7 +1,7 @@
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 { MollieToken } from '@stamhoofd/models';
4
- import type { Organization as OrganizationStruct} from '@stamhoofd/structures';
4
+ import type { Organization as OrganizationStruct } from '@stamhoofd/structures';
5
5
  import { PermissionLevel } from '@stamhoofd/structures';
6
6
 
7
7
  import { AuthenticatedStructures } from '../../../../helpers/AuthenticatedStructures.js';
@@ -1,15 +1,15 @@
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 { isSimpleError, isSimpleErrors, SimpleError } from '@simonbackx/simple-errors';
4
4
  import { MollieToken } from '@stamhoofd/models';
5
5
  import { PermissionLevel } from '@stamhoofd/structures';
6
-
6
+ import { GetMollieDashboardResponse } from '@stamhoofd/structures/endpoints/GetMollieDashboardResponse.js';
7
7
  import { Context } from '../../../../helpers/Context.js';
8
8
 
9
9
  type Params = Record<string, never>;
10
10
  type Body = undefined;
11
11
  type Query = undefined;
12
- type ResponseBody = string;
12
+ type ResponseBody = GetMollieDashboardResponse;
13
13
 
14
14
  export class GetMollieDashboardEndpoint extends Endpoint<Params, Query, Body, ResponseBody> {
15
15
  protected doesMatch(request: Request): [true, Params] | [false] {
@@ -46,11 +46,11 @@ export class GetMollieDashboardEndpoint extends Endpoint<Params, Query, Body, Re
46
46
  try {
47
47
  const url = await mollie.getOnboardingLink() as string;
48
48
 
49
- const response = new Response(url);
50
- response.headers['Content-Type'] = 'text/plain';
49
+ const response = new Response(GetMollieDashboardResponse.create({
50
+ url,
51
+ }));
51
52
  return response;
52
- }
53
- catch (e) {
53
+ } catch (e) {
54
54
  if (isSimpleErrors(e) || isSimpleError(e)) {
55
55
  throw e;
56
56
  }
@@ -1,5 +1,5 @@
1
1
  import { AutoEncoder, field, StringDecoder } 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 jwt from 'jsonwebtoken';
5
5
 
@@ -1,8 +1,8 @@
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 { Group, Token } from '@stamhoofd/models';
5
- import type { Group as GroupStruct} from '@stamhoofd/structures';
5
+ import type { Group as GroupStruct } from '@stamhoofd/structures';
6
6
  import { GroupStatus } from '@stamhoofd/structures';
7
7
 
8
8
  import { AuthenticatedStructures } from '../../../../helpers/AuthenticatedStructures.js';
@@ -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 { Group } from '@stamhoofd/models';
4
4
  import type { Group as GroupStruct } from '@stamhoofd/structures';
@@ -1,4 +1,4 @@
1
- import type { Request} from '@simonbackx/simple-endpoints';
1
+ import type { Request } from '@simonbackx/simple-endpoints';
2
2
  import { Endpoint, Response } from '@simonbackx/simple-endpoints';
3
3
  import { UitpasGetClientIdResponse } from '@stamhoofd/structures';
4
4
 
@@ -1,9 +1,9 @@
1
1
  import { Request } from '@simonbackx/simple-endpoints';
2
- import type { Organization, User, Webshop} from '@stamhoofd/models';
2
+ import type { Organization, User, Webshop } from '@stamhoofd/models';
3
3
  import { GroupFactory, OrganizationFactory, OrganizationRegistrationPeriod, RegistrationPeriodFactory, Token, UserFactory, WebshopFactory } from '@stamhoofd/models';
4
4
  import { AccessRight, MemberResponsibility, OrganizationPrivateMetaData, OrganizationRegistrationPeriod as OrganizationRegistrationPeriodStruct, Organization as OrganizationStruct, PermissionLevel, PermissionRoleDetailed, PermissionRoleForResponsibility, Permissions, PermissionsResourceType, ResourcePermissions, Version } from '@stamhoofd/structures';
5
5
 
6
- import type { AutoEncoderPatchType, PatchableArrayAutoEncoder} from '@simonbackx/simple-encoding';
6
+ import type { AutoEncoderPatchType, PatchableArrayAutoEncoder } from '@simonbackx/simple-encoding';
7
7
  import { PatchableArray, PatchMap } from '@simonbackx/simple-encoding';
8
8
  import { STExpect, TestUtils } from '@stamhoofd/test-utils';
9
9
  import { testServer } from '../../../../../tests/helpers/TestServer.js';
@@ -17,6 +17,8 @@ import { SetupStepUpdater } from '../../../../helpers/SetupStepUpdater.js';
17
17
  import { TagHelper } from '../../../../helpers/TagHelper.js';
18
18
  import { ViesHelper } from '../../../../helpers/ViesHelper.js';
19
19
  import { UitpasService } from '../../../../services/uitpas/UitpasService.js';
20
+ import { VATService } from '../../../../services/VATService.js';
21
+ import { isAbortedError, isCanceledError } from '@stamhoofd/queues';
20
22
 
21
23
  type Params = Record<string, never>;
22
24
  type Query = undefined;
@@ -71,6 +73,7 @@ export class PatchOrganizationEndpoint extends Endpoint<Params, Query, Body, Res
71
73
 
72
74
  const errors = new SimpleErrors();
73
75
  let shouldUpdateSetupSteps = false;
76
+ let shouldUpdateVATExcempt = false;
74
77
  let shouldUpdateUserPermissions = false;
75
78
  let updateTags = false;
76
79
 
@@ -220,8 +223,7 @@ export class PatchOrganizationEndpoint extends Endpoint<Params, Query, Body, Res
220
223
  if (request.body.privateMeta.buckarooSettings !== undefined) {
221
224
  if (request.body.privateMeta.buckarooSettings === null) {
222
225
  organization.privateMeta.buckarooSettings = null;
223
- }
224
- else {
226
+ } else {
225
227
  organization.privateMeta.buckarooSettings = organization.privateMeta.buckarooSettings ?? BuckarooSettings.create({});
226
228
  organization.privateMeta.buckarooSettings.patchOrPut(request.body.privateMeta.buckarooSettings);
227
229
 
@@ -257,6 +259,7 @@ export class PatchOrganizationEndpoint extends Endpoint<Params, Query, Body, Res
257
259
  if (request.body.meta.companies) {
258
260
  await this.validateCompanies(organization, request.body.meta.companies);
259
261
  shouldUpdateSetupSteps = true;
262
+ shouldUpdateVATExcempt = true;
260
263
  }
261
264
 
262
265
  if (request.body.meta.recordsConfiguration?.recordCategories) {
@@ -429,21 +432,37 @@ export class PatchOrganizationEndpoint extends Endpoint<Params, Query, Body, Res
429
432
  throw new SimpleError({
430
433
  code: 'invalid_field',
431
434
  message: 'The period you want to set is already closed',
432
- human: $t('%15i'),
435
+ human: $t('%1X8'),
433
436
  field: 'period',
434
437
  });
435
438
  }
436
439
 
437
- const maximumStart = 1000 * 60 * 60 * 24 * 31 * 2; // 2 months in advance
438
- if (period.startDate > new Date(Date.now() + maximumStart) && STAMHOOFD.environment !== 'development') {
440
+ const struct = period.getBaseStructure();
441
+ if (struct.switchDate && struct.switchDate > new Date()) {
439
442
  throw new SimpleError({
440
443
  code: 'invalid_field',
441
444
  message: 'The period you want to set has not started yet',
442
- human: $t('%15k'),
445
+ human: $t('%1ca', { date: Formatter.date(struct.switchDate) }),
443
446
  field: 'period',
444
447
  });
445
448
  }
446
449
 
450
+ if (period.organizationId === null) {
451
+ // Not allowed to return to a period lower than the currently active platform period
452
+ const platform = await Platform.getShared();
453
+ const platformPeriod = await RegistrationPeriod.getByID(platform.periodId);
454
+ if (platformPeriod) {
455
+ if (period.startDate < platformPeriod.startDate) {
456
+ throw new SimpleError({
457
+ code: 'invalid_field',
458
+ message: 'Cannot return to period with a start date before the currently active platform period',
459
+ human: $t('%1Wt', {}),
460
+ field: 'period',
461
+ });
462
+ }
463
+ }
464
+ }
465
+
447
466
  organization.periodId = period.id;
448
467
  shouldUpdateSetupSteps = true;
449
468
  }
@@ -451,8 +470,7 @@ export class PatchOrganizationEndpoint extends Endpoint<Params, Query, Body, Res
451
470
 
452
471
  // Save the organization
453
472
  await organization.save();
454
- }
455
- else {
473
+ } else {
456
474
  if (request.body.name || request.body.address || request.body.website || request.body.meta?.companies || request.body.meta?.recordsConfiguration || request.body.meta?.registrationPaymentConfiguration) {
457
475
  throw new SimpleError({
458
476
  code: 'permission_denied',
@@ -614,12 +632,29 @@ export class PatchOrganizationEndpoint extends Endpoint<Params, Query, Body, Res
614
632
  await SetupStepUpdater.updateForOrganization(organization);
615
633
  }
616
634
 
635
+ if (shouldUpdateVATExcempt) {
636
+ const platform = await Platform.getShared();
637
+ const sellingOrganizationId = platform.membershipOrganizationId;
638
+ if (sellingOrganizationId) {
639
+ const sellingOrganization = await Organization.getByID(sellingOrganizationId, true);
640
+
641
+ await VATService.updateVATExcempt({
642
+ organization,
643
+ sellingOrganization,
644
+ });
645
+ }
646
+ }
647
+
617
648
  if (shouldUpdateUserPermissions) {
618
649
  await MemberUserSyncer.updatePermissionsForOrganization(organization.id);
619
650
  }
620
651
 
621
652
  if (updateTags) {
622
- await TagHelper.updateOrganizations();
653
+ try {
654
+ await TagHelper.updateOrganizations();
655
+ } catch (e) {
656
+ if (!isAbortedError(e) && !isCanceledError(e)) throw e;
657
+ }
623
658
  }
624
659
  const struct = await AuthenticatedStructures.organization(organization);
625
660
  return new Response(struct);
@@ -632,7 +667,11 @@ export class PatchOrganizationEndpoint extends Endpoint<Params, Query, Body, Res
632
667
  const original = organization.meta.companies.find(c => c.id === patch.id);
633
668
 
634
669
  if (!original) {
635
- throw new Error('Could not find company');
670
+ throw new SimpleError({
671
+ code: 'not_found',
672
+ message: 'Company not found',
673
+ human: $t('%1cw'),
674
+ });
636
675
  }
637
676
 
638
677
  // Changed VAT number
@@ -655,8 +694,7 @@ export class PatchOrganizationEndpoint extends Endpoint<Params, Query, Body, Res
655
694
 
656
695
  await ViesHelper.checkCompany(put, put);
657
696
  }
658
- }
659
- else {
697
+ } else {
660
698
  if (companies.length > 5) {
661
699
  throw new SimpleError({
662
700
  code: 'invalid_field',
@@ -1,8 +1,8 @@
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 { UitpasService } from '../../../../services/uitpas/UitpasService.js';
4
4
  import type { UitpasOrganizersResponse } from '@stamhoofd/structures';
5
- import type { Decoder} from '@simonbackx/simple-encoding';
5
+ import type { Decoder } from '@simonbackx/simple-encoding';
6
6
  import { AutoEncoder, field, StringDecoder } from '@simonbackx/simple-encoding';
7
7
  import { Context } from '../../../../helpers/Context.js';
8
8
 
@@ -104,8 +104,7 @@ export class SetOrganizationDomainEndpoint extends Endpoint<Params, Query, Body,
104
104
  // We set a custom domainname for webshops already
105
105
  // This is not used at this moment
106
106
  organization.privateMeta.mailFromDomain = defaultFromDomain;
107
- }
108
- else {
107
+ } else {
109
108
  // CNAME domain: for SPF + MX + A record
110
109
  organization.privateMeta.mailFromDomain = organization.privateMeta.pendingRegisterDomain;
111
110
  }
@@ -126,8 +125,7 @@ export class SetOrganizationDomainEndpoint extends Endpoint<Params, Query, Body,
126
125
  value: (STAMHOOFD.domains.registrationCname[organization.address.country] ?? STAMHOOFD.domains.registrationCname['']) + '.',
127
126
  }));
128
127
  }
129
- }
130
- else {
128
+ } else {
131
129
  organization.privateMeta.dnsRecords.push(DNSRecord.create({
132
130
  type: DNSRecordType.CNAME,
133
131
  name: organization.privateMeta.mailFromDomain + '.',
@@ -149,8 +147,7 @@ export class SetOrganizationDomainEndpoint extends Endpoint<Params, Query, Body,
149
147
 
150
148
  organization.serverMeta.privateDKIMKey = priv;
151
149
  organization.serverMeta.publicDKIMKey = pub;
152
- }
153
- else {
150
+ } else {
154
151
  priv = organization.serverMeta.privateDKIMKey;
155
152
  pub = organization.serverMeta.publicDKIMKey;
156
153
  }
@@ -170,8 +167,7 @@ export class SetOrganizationDomainEndpoint extends Endpoint<Params, Query, Body,
170
167
  description: $t(`%Ee`),
171
168
  optional: true,
172
169
  }));
173
- }
174
- else {
170
+ } else {
175
171
  if (oldMailDomain) {
176
172
  organization.deleteAWSMailIdenitity(oldMailDomain).catch(console.error);
177
173
  }
@@ -189,8 +185,7 @@ export class SetOrganizationDomainEndpoint extends Endpoint<Params, Query, Body,
189
185
  }
190
186
 
191
187
  await organization.save();
192
- }
193
- else {
188
+ } else {
194
189
  // Validate DNS-records if not empty
195
190
  console.log('Validating domains');
196
191
  await organization.updateDNSRecords();
@@ -1,5 +1,5 @@
1
1
  import type { AutoEncoderPatchType, 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 { UitpasClientCredentialsStatus, UitpasClientIdAndSecret, UitpasSetClientCredentialsResponse } 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 { Payment } from '@stamhoofd/models';
6
6
  import { SQL, applySQLSorter, compileToSQLFilter } from '@stamhoofd/sql';
7
- import type { CountFilteredRequest, PaymentGeneral, StamhoofdFilter} from '@stamhoofd/structures';
7
+ import type { CountFilteredRequest, PaymentGeneral, StamhoofdFilter } from '@stamhoofd/structures';
8
8
  import { LimitedFilteredRequest, PaginatedResponse, TransferSettings, assertSort, getSortFilter } from '@stamhoofd/structures';
9
9
 
10
10
  import type { SQLResultNamespacedRow } from '@simonbackx/simple-database';
@@ -167,8 +167,7 @@ export class GetPaymentsEndpoint extends Endpoint<Params, Query, Body, ResponseB
167
167
 
168
168
  try {
169
169
  data = await query.fetch();
170
- }
171
- catch (error) {
170
+ } catch (error) {
172
171
  if (error.message.includes('ER_QUERY_TIMEOUT')) {
173
172
  throw new SimpleError({
174
173
  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, patchObject, 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 { BalanceItem, BalanceItemPayment, Payment, User } from '@stamhoofd/models';
@@ -40,7 +40,7 @@ export class PatchPaymentsEndpoint extends Endpoint<Params, Query, Body, Respons
40
40
 
41
41
  async handle(request: DecodedRequest<Params, Query, Body>) {
42
42
  const organization = await Context.setOrganizationScope();
43
- await Context.authenticate();
43
+ const { user } = await Context.authenticate();
44
44
 
45
45
  if (!await Context.auth.hasSomeAccess(organization.id)) {
46
46
  throw Context.auth.error();
@@ -74,6 +74,7 @@ export class PatchPaymentsEndpoint extends Endpoint<Params, Query, Body, Respons
74
74
  payment.status = PaymentStatus.Created;
75
75
  payment.method = put.method;
76
76
  payment.customer = put.customer;
77
+ payment.adminUserId = user.id;
77
78
 
78
79
  const payingOrganizationId = put.payingOrganizationId ?? put.payingOrganization?.id ?? null;
79
80
 
@@ -81,8 +82,7 @@ export class PatchPaymentsEndpoint extends Endpoint<Params, Query, Body, Respons
81
82
  if (Context.auth.hasSomePlatformAccess()) {
82
83
  if (await Context.auth.hasFullAccess(payingOrganizationId, PermissionLevel.Full)) {
83
84
  payment.payingOrganizationId = payingOrganizationId;
84
- }
85
- else {
85
+ } else {
86
86
  // silently ignore
87
87
  }
88
88
  }
@@ -233,8 +233,7 @@ export class PatchPaymentsEndpoint extends Endpoint<Params, Query, Body, Respons
233
233
  payment.paidAt = put.paidAt;
234
234
  await payment.save();
235
235
  }
236
- }
237
- else {
236
+ } else {
238
237
  for (const balanceItem of balanceItems) {
239
238
  await BalanceItemService.markUpdated(balanceItem, payment, organization);
240
239
  }
@@ -255,8 +254,18 @@ export class PatchPaymentsEndpoint extends Endpoint<Params, Query, Body, Respons
255
254
  });
256
255
  }
257
256
 
258
- if (patch.method || patch.paidAt !== undefined || patch.status !== undefined) {
259
- if (payment.method && ![PaymentMethod.Unknown, PaymentMethod.Transfer, PaymentMethod.PointOfSale].includes(payment.method)) {
257
+ if (patch.method || patch.paidAt !== undefined) {
258
+ if (![PaymentMethod.Unknown, PaymentMethod.Transfer, PaymentMethod.PointOfSale].includes(payment.method)) {
259
+ throw new SimpleError({
260
+ code: 'invalid_field',
261
+ message: 'Invalid payment method',
262
+ human: $t(`%Ex`),
263
+ });
264
+ }
265
+ }
266
+
267
+ if (patch.status !== undefined && patch.status !== payment.status) {
268
+ if (!payment.canChangeStatus) {
260
269
  throw new SimpleError({
261
270
  code: 'invalid_field',
262
271
  message: 'Invalid payment method',
@@ -268,8 +277,7 @@ export class PatchPaymentsEndpoint extends Endpoint<Params, Query, Body, Respons
268
277
  if (patch.transferSettings && payment.method == PaymentMethod.Transfer) {
269
278
  if (patch.transferSettings.isPut()) {
270
279
  payment.transferSettings = patch.transferSettings;
271
- }
272
- else if (payment.transferSettings !== null) {
280
+ } else if (payment.transferSettings !== null) {
273
281
  payment.transferSettings = payment.transferSettings.patch(patch.transferSettings);
274
282
  }
275
283
  }
@@ -311,8 +319,7 @@ export class PatchPaymentsEndpoint extends Endpoint<Params, Query, Body, Respons
311
319
  if (Context.auth.hasSomePlatformAccess()) {
312
320
  if (await Context.auth.hasFullAccess(payingOrganizationId, PermissionLevel.Full)) {
313
321
  payment.payingOrganizationId = payingOrganizationId;
314
- }
315
- else {
322
+ } else {
316
323
  // silently ignore
317
324
  }
318
325
  }
@@ -335,7 +342,7 @@ export class PatchPaymentsEndpoint extends Endpoint<Params, Query, Body, Respons
335
342
 
336
343
  await payment.save();
337
344
 
338
- if (patch.status) {
345
+ if (patch.status && patch.status !== payment.status) {
339
346
  await PaymentService.handlePaymentStatusUpdate(payment, organization, patch.status);
340
347
  }
341
348
 
@@ -1,12 +1,12 @@
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
- import { CountFilteredRequest, CountResponse, PaymentCustomer, PaymentMethod, PermissionLevel, ReceivableBalanceType } from '@stamhoofd/structures';
4
+ import { CountFilteredRequest, CountResponse, PaymentCustomer, PaymentMethod, PermissionLevel, ReceivableBalanceType } from '@stamhoofd/structures';
5
5
 
6
6
  import { Context } from '../../../../helpers/Context.js';
7
7
  import { GetReceivableBalancesEndpoint } from './GetReceivableBalancesEndpoint.js';
8
- import type { BalanceItem} from '@stamhoofd/models';
9
- import { Organization, User} from '@stamhoofd/models';
8
+ import type { BalanceItem } from '@stamhoofd/models';
9
+ import { Organization, User } from '@stamhoofd/models';
10
10
  import { CachedBalance } from '@stamhoofd/models';
11
11
  import { PaymentService } from '../../../../services/PaymentService.js';
12
12
  import { SimpleError } from '@simonbackx/simple-errors';
@@ -36,35 +36,41 @@ export class ChargeReceivableBalancesEndpoint extends Endpoint<Params, Query, Bo
36
36
 
37
37
  async handle(request: DecodedRequest<Params, Query, Body>) {
38
38
  const sellingOrganization = await Context.setOrganizationScope();
39
- await Context.authenticate();
39
+ const { user } = await Context.authenticate();
40
40
  const query = await GetReceivableBalancesEndpoint.buildQuery(request.query);
41
41
 
42
42
  for await (const cachedBalance of query.all()) {
43
43
  if (cachedBalance.organizationId !== sellingOrganization.id) {
44
44
  throw new SimpleError({
45
45
  code: 'wrong_organization',
46
- message: 'Cannot charge a cached balance from a different organization'
47
- })
46
+ message: 'Cannot charge a cached balance from a different organization',
47
+ });
48
48
  }
49
49
  // todo
50
50
  const items = await CachedBalance.balanceForObjects(cachedBalance.organizationId, [cachedBalance.objectId], cachedBalance.objectType);
51
51
 
52
52
  if (items.length === 0) {
53
- console.log('Nothing to charge for', cachedBalance.id)
53
+ console.log('Nothing to charge for', cachedBalance.id);
54
54
  continue;
55
55
  }
56
56
 
57
57
  const map: Map<BalanceItem, number> = new Map();
58
+ let total = 0;
58
59
  for (const i of items) {
59
- map.set(i, i.priceOpen)
60
+ map.set(i, i.priceOpen);
61
+ total += i.priceOpen;
60
62
  }
63
+ if (total <= 0) {
64
+ continue;
65
+ }
66
+
61
67
  let payingOrganization: Organization | null = null;
62
- let user: User | null = null;
68
+ let customerUser: User | null = null;
63
69
  if (cachedBalance.objectType === ReceivableBalanceType.organization) {
64
70
  const p = await Organization.getByID(cachedBalance.objectId);
65
71
  if (!p || !(await Context.auth.hasFullAccess(p))) {
66
- console.error('Unexpected missing paying organization id', cachedBalance)
67
- continue
72
+ console.error('Unexpected missing paying organization id', cachedBalance);
73
+ continue;
68
74
  }
69
75
  payingOrganization = p;
70
76
  }
@@ -72,34 +78,34 @@ export class ChargeReceivableBalancesEndpoint extends Endpoint<Params, Query, Bo
72
78
  if (cachedBalance.objectType === ReceivableBalanceType.user || cachedBalance.objectType === ReceivableBalanceType.userWithoutMembers) {
73
79
  const p = await User.getByID(cachedBalance.objectId);
74
80
  if (!p || !(Context.auth.checkScope(p.organizationId))) {
75
- console.error('Unexpected missing user id', cachedBalance)
76
- continue
81
+ console.error('Unexpected missing customer user id', cachedBalance);
82
+ continue;
77
83
  }
78
- user = p
84
+ customerUser = p;
79
85
  }
80
86
 
81
87
  const mandates = await PaymentMandateService.getMandates({
82
88
  sellingOrganization,
83
- user,
84
- payingOrganization
89
+ user: customerUser,
90
+ payingOrganization,
85
91
  });
86
92
 
87
- const mandate = mandates.find(m => m.isDefault)
93
+ const mandate = mandates.find(m => m.isDefault);
88
94
 
89
95
  if (!mandate) {
90
96
  // Not possible
91
- console.error('No mandates found for', cachedBalance.id)
97
+ console.error('No mandates found for', cachedBalance.id);
92
98
  continue;
93
99
  }
94
100
 
95
- const customerUser = user ?? (payingOrganization ? (await payingOrganization.getFullAdmins())[0] : null)
101
+ customerUser = customerUser ?? (payingOrganization ? (await payingOrganization.getFullAdmins())[0] : null);
96
102
  const customer = PaymentCustomer.create({
97
103
  firstName: customerUser?.firstName,
98
104
  lastName: customerUser?.lastName,
99
105
  email: customerUser?.email ?? (payingOrganization ? (await payingOrganization.getReplyEmails())[0].email : null),
100
- company: payingOrganization?.defaultCompanies[0]
101
- })
102
-
106
+ company: payingOrganization?.defaultCompanies[0],
107
+ });
108
+
103
109
  await PaymentService.createPayment({
104
110
  balanceItems: map,
105
111
  checkout: {
@@ -107,21 +113,22 @@ export class ChargeReceivableBalancesEndpoint extends Endpoint<Params, Query, Bo
107
113
  totalPrice: null,
108
114
  customer,
109
115
  cancelUrl: null,
110
- redirectUrl: null
116
+ redirectUrl: null,
111
117
  },
112
- user,
118
+ user: customerUser,
119
+ adminUserId: user.id,
113
120
  organization: sellingOrganization,
114
121
  payingOrganization,
115
122
  serviceFeeType: 'system',
116
123
  createMandate: null,
117
124
  useMandate: mandate,
118
125
  paymentConfiguration: sellingOrganization.meta.registrationPaymentConfiguration,
119
- privatePaymentConfiguration: sellingOrganization.privateMeta.registrationPaymentConfiguration
120
- })
126
+ privatePaymentConfiguration: sellingOrganization.privateMeta.registrationPaymentConfiguration,
127
+ });
121
128
  }
122
129
 
123
130
  // Make sure the user can refresh data and see the updated cached amounts
124
- await BalanceItemService.flushCaches(sellingOrganization.id)
131
+ await BalanceItemService.flushCaches(sellingOrganization.id);
125
132
  return new Response(undefined, 201);
126
133
  }
127
134
  }
@@ -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 { DetailedReceivableBalance, PaymentStatus, ReceivableBalanceType } from '@stamhoofd/structures';
4
4
 
@@ -113,8 +113,7 @@ export class GetReceivableBalanceEndpoint extends Endpoint<Params, Query, Body,
113
113
 
114
114
  if (memberIds.length === 0) {
115
115
  q.where(SQL.column(BalanceItem.table, 'userId'), request.params.id);
116
- }
117
- else {
116
+ } else {
118
117
  q.where(
119
118
  SQL.where(SQL.column(BalanceItem.table, 'userId'), request.params.id)
120
119
  .or(SQL.column(BalanceItem.table, 'memberId'), memberIds),
@@ -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,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 { CachedBalance } from '@stamhoofd/models';
@@ -1,5 +1,5 @@
1
1
  import { Request } from '@simonbackx/simple-endpoints';
2
- import type { Organization, RegistrationPeriod} from '@stamhoofd/models';
2
+ import type { Organization, RegistrationPeriod } from '@stamhoofd/models';
3
3
  import { GroupFactory, OrganizationFactory, OrganizationRegistrationPeriodFactory, RegistrationPeriodFactory, Token, UserFactory } from '@stamhoofd/models';
4
4
  import { GroupType, LimitedFilteredRequest, PermissionLevel, Permissions } from '@stamhoofd/structures';
5
5
  import { testServer } from '../../../../../tests/helpers/TestServer.js';