@stamhoofd/backend 2.120.6 → 2.122.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (434) hide show
  1. package/output-2.txt +1 -0
  2. package/output.txt +1 -0
  3. package/package.json +70 -53
  4. package/src/audit-logs/EventNotificationLogger.ts +40 -0
  5. package/src/audit-logs/ModelLogger.ts +19 -15
  6. package/src/audit-logs/OrganizationLogger.ts +1 -1
  7. package/src/audit-logs/RegistrationInvitationLogger.ts +46 -0
  8. package/src/audit-logs/init.ts +9 -1
  9. package/src/boot.ts +19 -18
  10. package/src/crons/amazon-ses.ts +13 -26
  11. package/src/crons/balance-emails.ts +3 -5
  12. package/src/crons/clearExcelCache.test.ts +1 -1
  13. package/src/crons/clearExcelCache.ts +1 -2
  14. package/src/crons/drip-emails.ts +42 -0
  15. package/src/crons/endFunctionsOfUsersWithoutRegistration.ts +4 -0
  16. package/src/crons/helpers/isOutside.ts +11 -0
  17. package/src/crons/helpers/useSavedIterator.ts +32 -0
  18. package/src/crons/index.ts +7 -0
  19. package/src/crons/invoices.ts +160 -0
  20. package/src/crons/members-fees.ts +50 -0
  21. package/src/crons/mollie-chargebacks.ts +86 -0
  22. package/src/crons/service-fees.ts +152 -0
  23. package/src/crons/stripe-invoices.ts +48 -0
  24. package/src/crons/transfer-fees.ts +176 -0
  25. package/src/crons/update-cached-balances.ts +4 -4
  26. package/src/crons.ts +54 -74
  27. package/src/debug.ts +4 -2
  28. package/src/email-recipient-loaders/documents.ts +1 -1
  29. package/src/email-recipient-loaders/members.ts +1 -1
  30. package/src/email-recipient-loaders/payments.ts +87 -46
  31. package/src/email-recipient-loaders/registrations.ts +1 -1
  32. package/src/email-replacements/getEmailReplacementsForPayment.ts +5 -9
  33. package/src/endpoints/admin/members/ChargeMembersEndpoint.ts +1 -1
  34. package/src/endpoints/admin/memberships/ChargeMembershipsEndpoint.ts +1 -1
  35. package/src/endpoints/admin/memberships/GetChargeMembershipsSummaryEndpoint.ts +3 -5
  36. package/src/endpoints/admin/organizations/ChargeOrganizationsEndpoint.ts +1 -1
  37. package/src/endpoints/admin/organizations/GetOrganizationsCountEndpoint.ts +1 -1
  38. package/src/endpoints/admin/organizations/GetOrganizationsEndpoint.ts +13 -7
  39. package/src/endpoints/admin/organizations/PatchOrganizationsEndpoint.ts +4 -6
  40. package/src/endpoints/admin/organizations/PatchPackagesEndpoint.test.ts +10 -6
  41. package/src/endpoints/admin/organizations/PatchPackagesEndpoint.ts +39 -21
  42. package/src/endpoints/admin/registrations/ChargeRegistrationsEndpoint.ts +1 -1
  43. package/src/endpoints/auth/CreateAdminEndpoint.ts +23 -5
  44. package/src/endpoints/auth/CreateTokenEndpoint.ts +2 -2
  45. package/src/endpoints/auth/DeleteTokenEndpoint.ts +1 -1
  46. package/src/endpoints/auth/DeleteUserEndpoint.ts +3 -3
  47. package/src/endpoints/auth/ForgotPasswordEndpoint.ts +1 -1
  48. package/src/endpoints/auth/GetOtherUserEndpoint.ts +1 -1
  49. package/src/endpoints/auth/GetUserEndpoint.ts +1 -1
  50. package/src/endpoints/auth/OpenIDConnectAuthTokenEndpoint.ts +1 -1
  51. package/src/endpoints/auth/OpenIDConnectStartEndpoint.ts +1 -1
  52. package/src/endpoints/auth/PatchUserEndpoint.ts +5 -8
  53. package/src/endpoints/auth/PollEmailVerificationEndpoint.ts +1 -1
  54. package/src/endpoints/auth/RetryEmailVerificationEndpoint.ts +1 -1
  55. package/src/endpoints/auth/SignupEndpoint.ts +2 -3
  56. package/src/endpoints/auth/VerifyEmailEndpoint.ts +20 -3
  57. package/src/endpoints/frontend/FrontendEnvironmentEndpoint.ts +2 -1
  58. package/src/endpoints/global/addresses/SearchRegionsEndpoint.ts +2 -4
  59. package/src/endpoints/global/addresses/ValidateAddressEndpoint.ts +1 -1
  60. package/src/endpoints/global/audit-logs/GetAuditLogsEndpoint.ts +5 -7
  61. package/src/endpoints/global/caddy/CheckDomainCertEndpoint.ts +2 -2
  62. package/src/endpoints/global/email/CreateEmailEndpoint.ts +3 -4
  63. package/src/endpoints/global/email/GetAdminEmailsEndpoint.test.ts +1 -1
  64. package/src/endpoints/global/email/GetAdminEmailsEndpoint.ts +1 -2
  65. package/src/endpoints/global/email/GetEmailAddressEndpoint.ts +4 -6
  66. package/src/endpoints/global/email/GetEmailEndpoint.ts +1 -1
  67. package/src/endpoints/global/email/GetUserEmailsEndpoint.test.ts +1 -1
  68. package/src/endpoints/global/email/GetUserEmailsEndpoint.ts +1 -1
  69. package/src/endpoints/global/email/ManageEmailAddressEndpoint.ts +6 -10
  70. package/src/endpoints/global/email/PatchEmailEndpoint.test.ts +4 -7
  71. package/src/endpoints/global/email/PatchEmailEndpoint.ts +6 -9
  72. package/src/endpoints/global/email-recipients/GetEmailRecipientsCountEndpoint.ts +1 -1
  73. package/src/endpoints/global/email-recipients/GetEmailRecipientsEndpoint.test.ts +1 -1
  74. package/src/endpoints/global/email-recipients/GetEmailRecipientsEndpoint.ts +1 -1
  75. package/src/endpoints/global/email-recipients/RetryEmailRecipientEndpoint.ts +2 -2
  76. package/src/endpoints/global/events/GetEventNotificationsCountEndpoint.ts +1 -1
  77. package/src/endpoints/global/events/GetEventNotificationsEndpoint.ts +3 -3
  78. package/src/endpoints/global/events/GetEventsEndpoint.ts +3 -3
  79. package/src/endpoints/global/events/PatchEventNotificationsEndpoint.test.ts +49 -4
  80. package/src/endpoints/global/events/PatchEventNotificationsEndpoint.ts +5 -8
  81. package/src/endpoints/global/events/PatchEventsEndpoint.test.ts +12 -44
  82. package/src/endpoints/global/events/PatchEventsEndpoint.ts +128 -127
  83. package/src/endpoints/global/files/ExportToExcelEndpoint.ts +9 -9
  84. package/src/endpoints/global/files/GetFileCache.ts +3 -4
  85. package/src/endpoints/global/files/UploadFile.ts +3 -4
  86. package/src/endpoints/global/files/UploadImage.ts +3 -4
  87. package/src/endpoints/global/groups/GetGroupsCountEndpoint.ts +51 -0
  88. package/src/endpoints/global/groups/GetGroupsEndpoint.test.ts +1 -1
  89. package/src/endpoints/global/groups/GetGroupsEndpoint.ts +4 -2
  90. package/src/endpoints/global/members/GetMemberFamilyEndpoint.ts +2 -3
  91. package/src/endpoints/global/members/GetMembersCountEndpoint.ts +1 -1
  92. package/src/endpoints/global/members/GetMembersEndpoint.test.ts +2 -2
  93. package/src/endpoints/global/members/GetMembersEndpoint.ts +10 -12
  94. package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.test.ts +195 -12
  95. package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.ts +16 -22
  96. package/src/endpoints/global/members/helpers/validateGroupFilter.ts +6 -30
  97. package/src/endpoints/global/members/shouldCheckIfMemberIsDuplicate.ts +1 -1
  98. package/src/endpoints/global/organizations/CheckRegisterCodeEndpoint.ts +1 -1
  99. package/src/endpoints/global/organizations/CreateOrganizationEndpoint.ts +40 -8
  100. package/src/endpoints/global/organizations/GetOrganizationFromDomainEndpoint.ts +2 -2
  101. package/src/endpoints/global/organizations/GetOrganizationFromUriEndpoint.ts +2 -2
  102. package/src/endpoints/global/organizations/SearchOrganizationEndpoint.test.ts +4 -1
  103. package/src/endpoints/global/organizations/SearchOrganizationEndpoint.ts +4 -5
  104. package/src/endpoints/global/payments/StripeWebhookEndpoint.ts +9 -16
  105. package/src/endpoints/global/platform/GetPlatformAdminsEndpoint.ts +1 -1
  106. package/src/endpoints/global/platform/GetPlatformEndpoint.ts +1 -1
  107. package/src/endpoints/global/platform/PatchPlatformEnpoint.test.ts +1 -1
  108. package/src/endpoints/global/platform/PatchPlatformEnpoint.ts +32 -13
  109. package/src/endpoints/global/platform-memberships/GetPlatformMembershipsCountEndpoint.ts +31 -31
  110. package/src/endpoints/global/platform-memberships/GetPlatformMembershipsEndpoint.ts +18 -20
  111. package/src/endpoints/global/registration/GetRegistrationsCountEndpoint.ts +1 -1
  112. package/src/endpoints/global/registration/GetRegistrationsEndpoint.test.ts +1 -1
  113. package/src/endpoints/global/registration/GetRegistrationsEndpoint.ts +6 -10
  114. package/src/endpoints/global/registration/GetUserDetailedPayableBalanceEndpoint.ts +35 -6
  115. package/src/endpoints/global/registration/GetUserDocumentsEndpoint.ts +2 -2
  116. package/src/endpoints/global/registration/GetUserMembersEndpoint.ts +1 -1
  117. package/src/endpoints/global/registration/GetUserPayableBalanceEndpoint.ts +1 -1
  118. package/src/endpoints/global/registration/PatchUserMembersEndpoint.test.ts +2 -2
  119. package/src/endpoints/global/registration/PatchUserMembersEndpoint.ts +3 -3
  120. package/src/endpoints/global/registration/RegisterMembersEndpoint.test.ts +90 -6
  121. package/src/endpoints/global/registration/RegisterMembersEndpoint.ts +38 -33
  122. package/src/endpoints/global/registration-invitations/GetRegistrationInvitationsCountEndpoint.ts +45 -0
  123. package/src/endpoints/global/registration-invitations/GetRegistrationInvitationsEndpoint.test.ts +494 -0
  124. package/src/endpoints/global/registration-invitations/GetRegistrationInvitationsEndpoint.ts +213 -0
  125. package/src/endpoints/global/registration-invitations/PatchRegistrationInvitationsEndpoint.test.ts +404 -0
  126. package/src/endpoints/global/registration-invitations/PatchRegistrationInvitationsEndpoint.ts +167 -0
  127. package/src/endpoints/global/registration-periods/GetRegistrationPeriodsCountEndpoint.ts +43 -0
  128. package/src/endpoints/global/registration-periods/GetRegistrationPeriodsEndpoint.ts +1 -1
  129. package/src/endpoints/global/registration-periods/PatchRegistrationPeriodsEndpoint.ts +13 -5
  130. package/src/endpoints/global/sso/GetSSOEndpoint.ts +2 -3
  131. package/src/endpoints/global/sso/SetSSOEndpoint.ts +1 -1
  132. package/src/endpoints/global/webshops/GetWebshopFromDomainEndpoint.ts +2 -2
  133. package/src/endpoints/global/webshops/GetWebshopsEndpoint.test.ts +1 -2
  134. package/src/endpoints/global/webshops/GetWebshopsEndpoint.ts +2 -4
  135. package/src/endpoints/organization/dashboard/balance-items/GetBalanceItemEndpoint.ts +2 -2
  136. package/src/endpoints/organization/dashboard/balance-items/GetBalanceItemsCountEndpoint.ts +1 -1
  137. package/src/endpoints/organization/dashboard/balance-items/GetBalanceItemsEndpoint.ts +3 -4
  138. package/src/endpoints/organization/dashboard/balance-items/PatchBalanceItemsEndpoint.ts +19 -6
  139. package/src/endpoints/organization/dashboard/billing/ApplyRegisterCodeEndpoint.test.ts +73 -0
  140. package/src/endpoints/organization/dashboard/billing/ApplyRegisterCodeEndpoint.ts +89 -0
  141. package/src/endpoints/{global → organization/dashboard}/billing/DeactivatePackageEndpoint.ts +4 -9
  142. package/src/endpoints/organization/dashboard/billing/DeleteOrganizationMandateEndpoint.ts +62 -0
  143. package/src/endpoints/organization/dashboard/billing/GetOrganizationDetailedPayableBalanceCollectionEndpoint.ts +56 -0
  144. package/src/endpoints/organization/dashboard/billing/GetOrganizationDetailedPayableBalanceEndpoint.ts +41 -18
  145. package/src/endpoints/organization/dashboard/billing/GetOrganizationMandatesEndpoint.ts +64 -0
  146. package/src/endpoints/organization/dashboard/billing/GetOrganizationPayableBalanceEndpoint.ts +2 -2
  147. package/src/endpoints/organization/dashboard/billing/GetOrganizationPayableInvoicesEndpoint.ts +68 -0
  148. package/src/endpoints/organization/dashboard/billing/GetPackagesEndpoint.ts +12 -4
  149. package/src/endpoints/organization/dashboard/billing/GetRegisterCodeEndpoint.ts +66 -0
  150. package/src/endpoints/organization/dashboard/billing/OrganizationCheckoutEndpoint.test.ts +949 -0
  151. package/src/endpoints/organization/dashboard/billing/OrganizationCheckoutEndpoint.ts +311 -0
  152. package/src/endpoints/organization/dashboard/billing/PatchOrganizationMandatesEndpoint.ts +94 -0
  153. package/src/endpoints/organization/dashboard/documents/GetDocumentTemplateXML.ts +1 -1
  154. package/src/endpoints/organization/dashboard/documents/GetDocumentTemplatesCountEndpoint.ts +1 -1
  155. package/src/endpoints/organization/dashboard/documents/GetDocumentTemplatesEndpoint.ts +1 -1
  156. package/src/endpoints/organization/dashboard/documents/GetDocumentsCountEndpoint.ts +1 -1
  157. package/src/endpoints/organization/dashboard/documents/GetDocumentsEndpoint.ts +1 -1
  158. package/src/endpoints/organization/dashboard/documents/PatchDocumentEndpoint.ts +10 -2
  159. package/src/endpoints/organization/dashboard/documents/PatchDocumentTemplatesEndpoint.test.ts +2 -2
  160. package/src/endpoints/organization/dashboard/documents/PatchDocumentTemplatesEndpoint.ts +2 -2
  161. package/src/endpoints/organization/dashboard/email/CheckEmailBouncesEndpoint.ts +1 -1
  162. package/src/endpoints/organization/dashboard/email-templates/GetEmailTemplatesEndpoint.test.ts +1 -1
  163. package/src/endpoints/organization/dashboard/email-templates/GetEmailTemplatesEndpoint.ts +10 -8
  164. package/src/endpoints/organization/dashboard/email-templates/PatchEmailTemplatesEndpoint.test.ts +1 -1
  165. package/src/endpoints/organization/dashboard/email-templates/PatchEmailTemplatesEndpoint.ts +5 -6
  166. package/src/endpoints/organization/dashboard/invoices/GetInvoicesCountEndpoint.ts +1 -1
  167. package/src/endpoints/organization/dashboard/invoices/GetInvoicesEndpoint.ts +15 -4
  168. package/src/endpoints/organization/dashboard/invoices/PatchInvoicesEndpoint.ts +11 -2
  169. package/src/endpoints/organization/dashboard/mollie/CheckMollieEndpoint.ts +8 -8
  170. package/src/endpoints/organization/dashboard/mollie/ConnectMollieEndpoint.ts +10 -5
  171. package/src/endpoints/organization/dashboard/mollie/DisconnectMollieEndpoint.ts +2 -2
  172. package/src/endpoints/organization/dashboard/mollie/GetMollieDashboardEndpoint.ts +7 -7
  173. package/src/endpoints/organization/dashboard/nolt/CreateNoltTokenEndpoint.ts +1 -1
  174. package/src/endpoints/organization/dashboard/organization/GetOrganizationArchivedGroups.ts +2 -2
  175. package/src/endpoints/organization/dashboard/organization/GetOrganizationDeletedGroups.ts +1 -1
  176. package/src/endpoints/organization/dashboard/organization/GetUitpasClientIdEndpoint.ts +1 -1
  177. package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.test.ts +2 -2
  178. package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.ts +67 -20
  179. package/src/endpoints/organization/dashboard/organization/SearchUitpasOrganizersEndpoint.ts +2 -2
  180. package/src/endpoints/organization/dashboard/organization/SetOrganizationDomainEndpoint.ts +5 -10
  181. package/src/endpoints/organization/dashboard/organization/SetUitpasClientCredentialsEndpoint.ts +1 -1
  182. package/src/endpoints/organization/dashboard/payments/GetPaymentsCountEndpoint.ts +1 -1
  183. package/src/endpoints/organization/dashboard/payments/GetPaymentsEndpoint.ts +3 -4
  184. package/src/endpoints/organization/dashboard/payments/PatchPaymentsEndpoint.ts +24 -17
  185. package/src/endpoints/organization/dashboard/receivable-balances/ChargeReceivableBalancesEndpoint.ts +134 -0
  186. package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalanceEndpoint.ts +2 -3
  187. package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalancesCountEndpoint.ts +1 -1
  188. package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalancesEndpoint.ts +1 -1
  189. package/src/endpoints/organization/dashboard/registration-periods/GetOrganizationRegistrationPeriodsEndpoint.test.ts +1 -1
  190. package/src/endpoints/organization/dashboard/registration-periods/GetOrganizationRegistrationPeriodsEndpoint.ts +2 -3
  191. package/src/endpoints/organization/dashboard/registration-periods/MoveRegistrationPeriods.test.ts +1 -1
  192. package/src/endpoints/organization/dashboard/registration-periods/PatchOrganizationRegistrationPeriodsEndpoint.test.ts +1 -1
  193. package/src/endpoints/organization/dashboard/registration-periods/PatchOrganizationRegistrationPeriodsEndpoint.ts +32 -22
  194. package/src/endpoints/organization/dashboard/registration-periods/SetupStepReviewEndpoint.ts +4 -5
  195. package/src/endpoints/organization/dashboard/stripe/ConnectStripeEndpoint.ts +1 -1
  196. package/src/endpoints/organization/dashboard/stripe/DeleteStripeAccountEndpoint.ts +2 -3
  197. package/src/endpoints/organization/dashboard/stripe/GetStripeAccountLinkEndpoint.ts +2 -2
  198. package/src/endpoints/organization/dashboard/stripe/GetStripeAccountsEndpoint.ts +1 -1
  199. package/src/endpoints/organization/dashboard/stripe/GetStripeLoginLinkEndpoint.ts +2 -2
  200. package/src/endpoints/organization/dashboard/stripe/UpdateStripeAccountEndpoint.ts +1 -1
  201. package/src/endpoints/organization/dashboard/users/CreateApiUserEndpoint.ts +1 -1
  202. package/src/endpoints/organization/dashboard/users/DeleteUserEndpoint.ts +1 -1
  203. package/src/endpoints/organization/dashboard/users/GetApiUsersEndpoint.ts +1 -1
  204. package/src/endpoints/organization/dashboard/users/GetOrganizationAdminsEndpoint.ts +1 -1
  205. package/src/endpoints/organization/dashboard/users/PatchApiUserEndpoint.ts +4 -6
  206. package/src/endpoints/organization/dashboard/webshops/CreateWebshopEndpoint.ts +10 -15
  207. package/src/endpoints/organization/dashboard/webshops/DeleteWebshopEndpoint.ts +1 -1
  208. package/src/endpoints/organization/dashboard/webshops/GetDiscountCodesEndpoint.ts +2 -2
  209. package/src/endpoints/organization/dashboard/webshops/GetWebshopOrdersCountEndpoint.ts +1 -1
  210. package/src/endpoints/organization/dashboard/webshops/GetWebshopOrdersEndpoint.ts +1 -1
  211. package/src/endpoints/organization/dashboard/webshops/GetWebshopTicketsEndpoint.ts +1 -1
  212. package/src/endpoints/organization/dashboard/webshops/GetWebshopUriAvailabilityEndpoint.ts +11 -2
  213. package/src/endpoints/organization/dashboard/webshops/PatchDiscountCodesEndpoint.ts +4 -6
  214. package/src/endpoints/organization/dashboard/webshops/PatchWebshopEndpoint.ts +29 -8
  215. package/src/endpoints/organization/dashboard/webshops/PatchWebshopOrdersEndpoint.ts +21 -28
  216. package/src/endpoints/organization/dashboard/webshops/PatchWebshopTicketsEndpoint.ts +1 -1
  217. package/src/endpoints/organization/dashboard/webshops/SearchUitpasEventsEndpoint.ts +2 -2
  218. package/src/endpoints/organization/dashboard/webshops/VerifyWebshopDomainEndpoint.ts +2 -3
  219. package/src/endpoints/organization/dashboard/webshops/WebshopReservedPathSegments.test.ts +95 -0
  220. package/src/endpoints/organization/shared/ExchangePaymentEndpoint.ts +15 -13
  221. package/src/endpoints/organization/shared/GetDocumentHtml.ts +1 -1
  222. package/src/endpoints/organization/shared/GetPaymentEndpoint.ts +1 -1
  223. package/src/endpoints/organization/shared/GetUitpasNumberDetailsEndpoint.ts +3 -5
  224. package/src/endpoints/organization/shared/auth/GetOrganizationEndpoint.ts +1 -1
  225. package/src/endpoints/organization/webshops/CheckWebshopDiscountCodesEndpoint.ts +4 -1
  226. package/src/endpoints/organization/webshops/GetOrderByPaymentEndpoint.ts +14 -3
  227. package/src/endpoints/organization/webshops/GetOrderEndpoint.ts +14 -2
  228. package/src/endpoints/organization/webshops/GetTicketsEndpoint.ts +37 -16
  229. package/src/endpoints/organization/webshops/GetWebshopEndpoint.test.ts +34 -2
  230. package/src/endpoints/organization/webshops/GetWebshopEndpoint.ts +4 -2
  231. package/src/endpoints/organization/webshops/PlaceOrderEndpoint.test.ts +74 -3
  232. package/src/endpoints/organization/webshops/PlaceOrderEndpoint.ts +28 -50
  233. package/src/endpoints/organization/webshops/RetrieveUitpasSocialTariffPriceEndpoint.ts +3 -5
  234. package/src/endpoints/organization/webshops/WebshopAuthHelper.ts +36 -0
  235. package/src/endpoints/system/HealthEndpoint.ts +1 -1
  236. package/src/excel-loaders/balance-items.ts +1 -1
  237. package/src/excel-loaders/event-notifications.ts +1 -1
  238. package/src/excel-loaders/members.ts +1 -1
  239. package/src/excel-loaders/organizations.ts +3 -3
  240. package/src/excel-loaders/payments.ts +31 -1
  241. package/src/excel-loaders/platform-memberships.ts +13 -14
  242. package/src/excel-loaders/receivable-balances.ts +2 -2
  243. package/src/excel-loaders/registrations.ts +2 -3
  244. package/src/helpers/AddressValidator.ts +7 -14
  245. package/src/helpers/AdminPermissionChecker.ts +60 -65
  246. package/src/helpers/AuthenticatedStructures.ts +153 -51
  247. package/src/helpers/BalanceItemRelationsBackfiller.test.ts +174 -0
  248. package/src/helpers/BalanceItemRelationsBackfiller.ts +163 -0
  249. package/src/helpers/BuckarooHelper.ts +2 -4
  250. package/src/helpers/CheckSettlements.ts +12 -24
  251. package/src/helpers/Context.ts +15 -10
  252. package/src/helpers/CookieHelper.ts +1 -2
  253. package/src/helpers/EmailResumer.ts +1 -2
  254. package/src/helpers/FileCache.ts +2 -3
  255. package/src/helpers/FinancialSupportHelper.ts +21 -0
  256. package/src/helpers/FlagMomentCleanup.ts +1 -2
  257. package/src/helpers/ForwardHandler.ts +5 -10
  258. package/src/helpers/GlobalHelper.ts +3 -3
  259. package/src/helpers/LegacyBillingConverter.ts +787 -0
  260. package/src/helpers/MemberMerger.test.ts +782 -0
  261. package/src/helpers/MemberMerger.ts +600 -0
  262. package/src/helpers/MemberUserSyncer.ts +6 -12
  263. package/src/helpers/MembershipCharger.ts +2 -4
  264. package/src/helpers/PaymentCustomerResolver.test.ts +203 -0
  265. package/src/helpers/PaymentCustomerResolver.ts +144 -0
  266. package/src/helpers/PeriodHelper.ts +2 -3
  267. package/src/helpers/RecordAnswerHelper.test.ts +741 -0
  268. package/src/helpers/RecordAnswerHelper.ts +116 -0
  269. package/src/helpers/SeedTools.ts +106 -0
  270. package/src/helpers/ServiceFeeHelper.ts +125 -15
  271. package/src/helpers/SetupStepUpdater.ts +38 -32
  272. package/src/helpers/StamhoofdFilterAccessHelper.ts +52 -0
  273. package/src/helpers/StripeHelper.ts +15 -38
  274. package/src/helpers/StripeInvoicer.ts +419 -0
  275. package/src/helpers/StripePayoutChecker.ts +5 -10
  276. package/src/helpers/TagHelper.ts +7 -8
  277. package/src/helpers/TemporaryMemberAccess.ts +1 -2
  278. package/src/helpers/ThrottledQueue.ts +1 -2
  279. package/src/helpers/UitpasTokenRepository.ts +1 -2
  280. package/src/helpers/ViesHelper.ts +11 -11
  281. package/src/helpers/XlsxTransformerColumnHelper.ts +1 -1
  282. package/src/helpers/outstandingBalanceJoin.ts +2 -2
  283. package/src/helpers/updateMemberDetailsUitpasNumber.ts +3 -5
  284. package/src/migrate.ts +12 -5
  285. package/src/{seeds → migrations}/0000000004-single-organization.ts +10 -1
  286. package/src/migrations/0000000006-default-organization.ts +139 -0
  287. package/src/{seeds → migrations}/1715028563-user-permissions.ts +17 -27
  288. package/src/{seeds/1765896674-document-update-year.test.ts → migrations/1750090029-document-update-year.test.ts} +27 -26
  289. package/src/migrations/1750090029-document-update-year.ts +103 -0
  290. package/src/migrations/1750090030-records-configuration.ts +92 -0
  291. package/src/migrations/1750090031-records-configuration-webshops.ts +36 -0
  292. package/src/migrations/1752848540-national-numbers.ts +585 -0
  293. package/src/migrations/1752848550-records-configuration-group-filter.ts +1064 -0
  294. package/src/{seeds → migrations}/1752848561-groups-registration-periods.ts +95 -27
  295. package/src/{seeds → migrations}/1754560914-groups-prices.test.ts +1 -1
  296. package/src/{seeds → migrations}/1754560914-groups-prices.ts +9 -15
  297. package/src/{seeds → migrations}/1756293699-fill-previous-next-period-id.ts +1 -2
  298. package/src/migrations/1761665607-sync-member-users.ts +40 -0
  299. package/src/migrations/1779121239-default-invoice-email-template.sql +3 -0
  300. package/src/migrations/1779121240-invoice-email-template.sql +6 -0
  301. package/src/migrations/1779986893-default-payment-failed-email-templates.sql +4 -0
  302. package/src/migrations/1780578166-convert-legacy-billing.ts +13 -0
  303. package/src/{seeds/1755876819-remove-duplicate-members.ts → migrations/1780665426-remove-duplicate-members.ts} +23 -4
  304. package/src/migrations/1780933598-document-groups.ts +88 -0
  305. package/src/migrations/1781692342-balance-item-relations.ts +13 -0
  306. package/src/migrations/1781857866-platform-admins.ts +103 -0
  307. package/src/migrations/1781857867-rm-old-platform-admins.ts +25 -0
  308. package/src/seeds/0000000001-throw.ts +5 -0
  309. package/src/seeds/1760702452-update-balance-price-paid.ts +19 -0
  310. package/src/seeds/1760702453-update-balance-invoiced.ts +19 -0
  311. package/src/seeds/1760702454-update-cached-outstanding-balance-from-items.ts +51 -14
  312. package/src/seeds/1773754928-force-save-members.ts +41 -8
  313. package/src/seeds/1780665427-schedule-stock-updates.ts +45 -0
  314. package/src/seeds/1780665428-group-update-occupancy.ts +31 -0
  315. package/src/seeds/1780915001-fill-payment-customer.ts +70 -0
  316. package/src/seeds/1780915002-update-orders.ts +39 -0
  317. package/src/seeds/1782047708-organization-company-address.ts +44 -0
  318. package/src/seeds-temporary/1769088653-uitpas-status.ts +1 -2
  319. package/src/seeds-temporary/1780416000-migrate-audit-log-legacy-enums.test.ts +69 -0
  320. package/src/seeds-temporary/1780416000-migrate-audit-log-legacy-enums.ts +85 -0
  321. package/src/services/AuditLogService.test.ts +51 -0
  322. package/src/services/AuditLogService.ts +45 -0
  323. package/src/services/BalanceItemService.ts +148 -55
  324. package/src/services/CpuService.ts +3 -6
  325. package/src/services/DatabaseCollationService.test.ts +1 -2
  326. package/src/services/DocumentService.ts +1 -2
  327. package/src/services/EventNotificationService.ts +1 -1
  328. package/src/services/FileSignService.ts +2 -4
  329. package/src/services/InvoicePdfService.ts +286 -0
  330. package/src/services/InvoiceService.ts +330 -77
  331. package/src/services/InvoiceXMLService.ts +424 -0
  332. package/src/services/MemberNumberService.ts +6 -11
  333. package/src/services/MemberRecordStore.ts +8 -10
  334. package/src/services/MollieService.ts +530 -0
  335. package/src/services/PaymentMandateService.ts +214 -0
  336. package/src/services/PaymentReallocationService.test.ts +1 -1
  337. package/src/services/PaymentReallocationService.ts +7 -9
  338. package/src/services/PaymentService.ts +820 -328
  339. package/src/services/PlatformMembershipService.ts +5 -9
  340. package/src/services/ReferralService.ts +223 -0
  341. package/src/services/RegistrationService.ts +125 -54
  342. package/src/services/SSOService.test.ts +119 -0
  343. package/src/services/SSOService.ts +56 -49
  344. package/src/services/STPackageService.ts +97 -68
  345. package/src/services/UniqueMemberNumberService.ts +69 -0
  346. package/src/services/UniqueUserService.ts +3 -6
  347. package/src/services/VATService.ts +85 -0
  348. package/src/services/data/invoice.hbs.html +686 -0
  349. package/src/services/uitpas/PassholderEndpoints.ts +3 -6
  350. package/src/services/uitpas/UitpasService.ts +6 -10
  351. package/src/services/uitpas/checkUitpasNumbers.ts +2 -4
  352. package/src/services/uitpas/getSocialTariffForUitpasNumbers.ts +3 -6
  353. package/src/services/uitpas/searchUitpasEvents.ts +1 -2
  354. package/src/sql-filters/audit-logs.ts +1 -1
  355. package/src/sql-filters/balance-item-payments.ts +1 -1
  356. package/src/sql-filters/balance-items.ts +1 -1
  357. package/src/sql-filters/base-registration-filter-compilers.ts +5 -33
  358. package/src/sql-filters/document-templates.ts +1 -1
  359. package/src/sql-filters/documents.ts +1 -1
  360. package/src/sql-filters/email-recipients.ts +1 -1
  361. package/src/sql-filters/emails.ts +1 -1
  362. package/src/sql-filters/event-notifications.ts +1 -1
  363. package/src/sql-filters/events.ts +6 -1
  364. package/src/sql-filters/groups.ts +16 -1
  365. package/src/sql-filters/invoiced-balance-items.ts +1 -1
  366. package/src/sql-filters/invoices.ts +1 -1
  367. package/src/sql-filters/member-responsibility-records.ts +1 -1
  368. package/src/sql-filters/members.ts +1 -1
  369. package/src/sql-filters/orders.ts +4 -4
  370. package/src/sql-filters/organization-registration-periods.ts +1 -1
  371. package/src/sql-filters/organizations.ts +1 -1
  372. package/src/sql-filters/payments.ts +5 -0
  373. package/src/sql-filters/platform-memberships.ts +3 -3
  374. package/src/sql-filters/receivable-balances.ts +1 -1
  375. package/src/sql-filters/registration-invitations.ts +90 -0
  376. package/src/sql-filters/registration-periods.ts +1 -1
  377. package/src/sql-filters/registrations.ts +1 -1
  378. package/src/sql-filters/tickets.ts +1 -1
  379. package/src/sql-filters/users.ts +1 -1
  380. package/src/sql-sorters/groups.ts +23 -0
  381. package/src/sql-sorters/platform-memberships.ts +16 -16
  382. package/src/sql-sorters/registration-invitations.ts +36 -0
  383. package/tests/actions/patchOrganizationMember.ts +1 -1
  384. package/tests/actions/patchUserMember.ts +1 -1
  385. package/tests/assertions/assertBalances.ts +6 -12
  386. package/tests/e2e/api-rate-limits.test.ts +12 -24
  387. package/tests/e2e/bundle-discounts.test.ts +4 -1
  388. package/tests/e2e/charge-members.test.ts +13 -11
  389. package/tests/e2e/documents.test.ts +4 -1
  390. package/tests/e2e/register.test.ts +7 -9
  391. package/tests/e2e/stock.test.ts +4 -3
  392. package/tests/e2e/tickets.test.ts +1 -1
  393. package/tests/helpers/MollieMocker.ts +462 -0
  394. package/tests/helpers/PayconiqMocker.ts +138 -45
  395. package/tests/helpers/StripeMocker.ts +9 -6
  396. package/tests/helpers/index.ts +4 -0
  397. package/tests/init/initAdmin.ts +2 -2
  398. package/tests/init/initBundleDiscount.ts +1 -1
  399. package/tests/init/initMembershipOrganization.ts +13 -0
  400. package/tests/init/initPermissionRole.ts +3 -4
  401. package/tests/vitest.global.setup.ts +1 -1
  402. package/vitest.config.js +7 -0
  403. package/.nvmrc +0 -1
  404. package/src/endpoints/global/billing/ActivatePackagesEndpoint.ts +0 -216
  405. package/src/helpers/GroupBuilder.ts +0 -418
  406. package/src/seeds/0000000000-example.ts +0 -11
  407. package/src/seeds/1722256498-group-update-occupancy.ts +0 -52
  408. package/src/seeds/1726572303-schedule-stock-updates.ts +0 -52
  409. package/src/seeds/1726847064-setup-steps.ts +0 -16
  410. package/src/seeds/1728928974-update-cached-outstanding-balance-from-items.ts +0 -31
  411. package/src/seeds/1729253172-update-orders.ts +0 -21
  412. package/src/seeds/1733319079-fill-paying-organization-ids.ts +0 -68
  413. package/src/seeds/1733748412-update-deleted-order-numbers.ts +0 -109
  414. package/src/seeds/1733994455-balance-item-status-open.ts +0 -30
  415. package/src/seeds/1740046783-update-membership.ts +0 -17
  416. package/src/seeds/1741008870-fix-auditlog-description.ts +0 -50
  417. package/src/seeds/1741011468-fix-auditlog-description-uft16.ts +0 -88
  418. package/src/seeds/1741268179-fix-group-dates-of-events.ts +0 -32
  419. package/src/seeds/1750090030-records-configuration.ts +0 -26
  420. package/src/seeds/1751445358-upload-email-attachments.ts +0 -106
  421. package/src/seeds/1755532883-update-email-sender-ids.ts +0 -47
  422. package/src/seeds/1755790070-fill-email-recipient-errors.ts +0 -96
  423. package/src/seeds/1756115432-remove-old-drafts.ts +0 -16
  424. package/src/seeds/1756115433-fill-email-recipient-organization-id.ts +0 -30
  425. package/src/seeds/1756303697-update-email-counts.ts +0 -76
  426. package/src/seeds/1761665607-sync-member-users.ts +0 -59
  427. package/src/seeds/1765896674-document-update-year.ts +0 -66
  428. /package/src/{seeds → migrations}/0000000001-development-user.ts +0 -0
  429. /package/src/{seeds → migrations}/0000000002-clear-stamhoofd-email-templates.ts +0 -0
  430. /package/src/{seeds → migrations}/0000000003-default-email-templates.ts +0 -0
  431. /package/src/{seeds → migrations}/1752848561-groups-registration-periods.test.ts +0 -0
  432. /package/src/{seeds → migrations}/1766150402-document-published-at.test.ts +0 -0
  433. /package/src/{seeds → migrations}/1766150402-document-published-at.ts +0 -0
  434. /package/src/{seeds → migrations}/data/default-email-templates.sql +0 -0
@@ -0,0 +1,311 @@
1
+ import type { Decoder } from '@simonbackx/simple-encoding';
2
+ import type { DecodedRequest, Request } from '@simonbackx/simple-endpoints';
3
+ import { Endpoint, Response } from '@simonbackx/simple-endpoints';
4
+ import { SimpleError } from '@simonbackx/simple-errors';
5
+ import { BalanceItem, Organization, Platform, STPackage } from '@stamhoofd/models';
6
+ import { BalanceItemStatus, BalanceItemType, CheckoutResponse, OrganizationCheckout, OrganizationPackagesStatus, STPackageStruct } from '@stamhoofd/structures';
7
+ import { CreateMandateSettings } from '@stamhoofd/structures/checkout/CreateMandateSettings.js';
8
+ import { AuthenticatedStructures } from '../../../../helpers/AuthenticatedStructures.js';
9
+ import { Context } from '../../../../helpers/Context.js';
10
+ import { BalanceItemService } from '../../../../services/BalanceItemService.js';
11
+ import { PaymentService } from '../../../../services/PaymentService.js';
12
+ import { STPackageService } from '../../../../services/STPackageService.js';
13
+ import { VATService } from '../../../../services/VATService.js';
14
+
15
+ type Params = { sellingOrganizationId: string };
16
+ type Query = undefined;
17
+ type Body = OrganizationCheckout;
18
+ type ResponseBody = CheckoutResponse;
19
+
20
+ /**
21
+ * B2B billing (outstanding amount) and activating packages
22
+ */
23
+ export class OrganizationCheckoutEndpoint extends Endpoint<Params, Query, Body, ResponseBody> {
24
+ bodyDecoder = OrganizationCheckout as Decoder<Body>;
25
+
26
+ protected doesMatch(request: Request): [true, Params] | [false] {
27
+ if (request.method !== 'POST') {
28
+ return [false];
29
+ }
30
+
31
+ const params = Endpoint.parseParameters(request.url, '/billing/@sellingOrganizationId/checkout', { sellingOrganizationId: String });
32
+
33
+ if (params) {
34
+ return [true, params as Params];
35
+ }
36
+ return [false];
37
+ }
38
+
39
+ async handle(request: DecodedRequest<Params, Query, Body>) {
40
+ const organization = await Context.setOrganizationScope();
41
+ const { user } = await Context.authenticate();
42
+
43
+ // If the user has permission, we'll also search if he has access to the organization's key
44
+ if (!await Context.auth.canActivatePackages(organization.id)) {
45
+ throw Context.auth.error();
46
+ }
47
+ const checkout = request.body;
48
+
49
+ const id = request.params.sellingOrganizationId;
50
+ if (!id) {
51
+ throw new SimpleError({
52
+ code: 'unavailable',
53
+ message: 'This is temporarily unavailable',
54
+ human: $t('%1Rz'),
55
+ });
56
+ }
57
+
58
+ const sellingOrganization = await Organization.getByID(id);
59
+ if (!sellingOrganization || !sellingOrganization.active) {
60
+ throw new SimpleError({
61
+ statusCode: 404,
62
+ code: 'not_found',
63
+ message: 'Selling organization not found',
64
+ human: $t('%1R5'),
65
+ field: 'sellingOrganization',
66
+ });
67
+ }
68
+
69
+ if (sellingOrganization.id === organization.id) {
70
+ throw new SimpleError({
71
+ code: 'unavailable',
72
+ message: 'Cannot purchase from yourself',
73
+ });
74
+ }
75
+
76
+ const packages: STPackageStruct[] = [];
77
+ const models: STPackage[] = [];
78
+ const balanceItems: Map<BalanceItem, number> = new Map();
79
+
80
+ const membershipOrganizationId = (await Platform.getShared()).membershipOrganizationId;
81
+
82
+ if (STAMHOOFD.userMode === 'organization' && sellingOrganization.id === membershipOrganizationId) {
83
+ const currentPackages = await STPackageService.getActivePackages(organization.id);
84
+ const packageStatus = OrganizationPackagesStatus.create({
85
+ packages: currentPackages.map(p => STPackageStruct.create(p)),
86
+ });
87
+
88
+ packages.push(...checkout.purchases.getPackages(packageStatus));
89
+ }
90
+
91
+ // Create the real models for each package
92
+ // calculate the price for these packages and create a hidden balance item
93
+ for (const pack of packages) {
94
+ const model = new STPackage();
95
+ model.id = pack.id;
96
+ model.meta = pack.meta;
97
+ model.validUntil = pack.validUntil;
98
+ model.removeAt = pack.removeAt;
99
+
100
+ // Not yet valid / active (ignored until valid)
101
+ model.validAt = null;
102
+ model.organizationId = organization.id;
103
+
104
+ if (request.body.proForma) {
105
+ // Security addition
106
+ model.disableSave();
107
+ }
108
+
109
+ const balanceItem = await STPackageService.chargePackage(model, sellingOrganization, checkout.customer?.company);
110
+ if (balanceItem) {
111
+ balanceItem.VATExcempt = VATService.getVATExcempt({
112
+ company: checkout.customer?.company,
113
+ sellingOrganization,
114
+ type: 'services',
115
+ });
116
+ balanceItems.set(balanceItem, balanceItem.priceWithVAT);
117
+ }
118
+
119
+ if (!request.body.proForma) {
120
+ await model.save();
121
+ await balanceItem?.save();
122
+ } else {
123
+ // Security addition
124
+ if (balanceItem && balanceItem.id) {
125
+ throw new Error('Unexpected balance item save');
126
+ }
127
+ balanceItem?.disableSave();
128
+ }
129
+
130
+ models.push(model);
131
+
132
+ if (model.meta.requiresMandate) {
133
+ if (checkout.proForma) {
134
+ if (!checkout.createMandate) {
135
+ checkout.createMandate = CreateMandateSettings.create({ saveAsDefault: true });
136
+ }
137
+ } else {
138
+ // setting checkout.mandate is not enough - we also need to set it as default.
139
+
140
+ if (!checkout.createMandate) {
141
+ throw new SimpleError({
142
+ code: '',
143
+ message: $t('%1Rh'),
144
+ });
145
+ }
146
+
147
+ if (!checkout.createMandate.saveAsDefault) {
148
+ throw new SimpleError({
149
+ code: '',
150
+ message: $t('%1Qp'),
151
+ });
152
+ }
153
+ }
154
+ }
155
+ }
156
+
157
+ // Add pending items (balance items in request)
158
+ // Update balances before we start
159
+ await BalanceItemService.flushCaches(organization.id);
160
+
161
+ // Validate balance items (can only happen serverside)
162
+ const balanceItemIds = [...request.body.balances.keys()];
163
+
164
+ if (balanceItemIds.length > 0) {
165
+ const balanceItemsModels = await BalanceItem.select().where('id', balanceItemIds).andWhere('organizationId', sellingOrganization.id).limit(balanceItemIds.length).fetch();
166
+
167
+ if (balanceItemsModels.length !== balanceItemIds.length) {
168
+ throw new SimpleError({
169
+ code: 'balance_changed',
170
+ message: $t(`%vg`),
171
+ });
172
+ }
173
+
174
+ for (const [id, amount] of request.body.balances) {
175
+ if (amount === 0) {
176
+ continue;
177
+ }
178
+
179
+ const item = balanceItemsModels.find(b => b.id === id);
180
+ if (!item) {
181
+ throw new SimpleError({
182
+ code: 'balance_changed',
183
+ message: $t(`%vg`),
184
+ });
185
+ }
186
+
187
+ if (item.priceOpen === 0) {
188
+ throw new SimpleError({
189
+ code: 'balance_changed',
190
+ message: $t(`%vg`),
191
+ });
192
+ }
193
+
194
+ if (item.priceOpen > 0 && amount < 0 || amount > item.priceOpen) {
195
+ throw new SimpleError({
196
+ code: 'balance_changed',
197
+ message: $t(`%vg`),
198
+ });
199
+ }
200
+
201
+ if (item.priceOpen < 0 && amount > 0 || amount < item.priceOpen) {
202
+ throw new SimpleError({
203
+ code: 'balance_changed',
204
+ message: $t(`%vg`),
205
+ });
206
+ }
207
+ balanceItems.set(item, amount);
208
+ }
209
+ }
210
+
211
+ // If still zero payment
212
+ let { price: totalPrice, roundingAmount } = PaymentService.calculateTotalPrice({
213
+ balanceItems,
214
+ organization: sellingOrganization,
215
+ });
216
+ const minimumAmount = checkout.createMandate && !checkout.mandate ? 2_00 : 0;
217
+
218
+ // Automatically add discounts
219
+ await BalanceItemService.applyDiscountsToCheckout({
220
+ totalPrice: totalPrice - roundingAmount,
221
+ minimumAmount,
222
+ balanceItems,
223
+ sellingOrganizationId: sellingOrganization.id,
224
+ payingOrganizationId: organization.id,
225
+ });
226
+
227
+ // Update price and rounding
228
+ ({ price: totalPrice, roundingAmount } = PaymentService.calculateTotalPrice({
229
+ balanceItems,
230
+ organization: sellingOrganization,
231
+ }));
232
+
233
+ if (totalPrice < minimumAmount) {
234
+ const item = new BalanceItem();
235
+ item.type = BalanceItemType.AdministrationFee;
236
+ item.description = $t('%1Q4');
237
+ item.payingOrganizationId = organization.id;
238
+ item.organizationId = sellingOrganization.id;
239
+ item.VATPercentage = 21;
240
+ item.VATExcempt = VATService.getVATExcempt({
241
+ company: checkout.customer?.company,
242
+ sellingOrganization,
243
+ type: 'services',
244
+ });
245
+ item.VATIncluded = !item.VATExcempt; // Makes sure price with VAT always matches unitPrice
246
+ item.quantity = 1;
247
+ item.unitPrice = minimumAmount - (totalPrice - roundingAmount);
248
+ item.createdAt = new Date();
249
+ item.status = BalanceItemStatus.Hidden;
250
+
251
+ if (!request.body.proForma) {
252
+ await item.save();
253
+ } else {
254
+ item.disableSave();
255
+ }
256
+
257
+ balanceItems.set(item, item.priceWithVAT);
258
+ }
259
+
260
+ if (checkout.proForma) {
261
+ const result = await PaymentService.createProForma({
262
+ balanceItems,
263
+ checkout,
264
+ user,
265
+ organization: sellingOrganization,
266
+ payingOrganization: organization,
267
+ });
268
+
269
+ return new Response(CheckoutResponse.create({
270
+ payment: result.payment,
271
+ invoice: result.invoice,
272
+ }));
273
+ }
274
+
275
+ const result = await PaymentService.createPayment({
276
+ balanceItems,
277
+ checkout,
278
+ user,
279
+ organization: sellingOrganization,
280
+ payingOrganization: organization,
281
+ serviceFeeType: 'system',
282
+ createMandate: checkout.createMandate,
283
+ useMandate: checkout.mandate,
284
+ paymentConfiguration: sellingOrganization.meta.registrationPaymentConfiguration,
285
+ privatePaymentConfiguration: sellingOrganization.privateMeta.registrationPaymentConfiguration,
286
+ });
287
+
288
+ if (!result) {
289
+ // No payment needed
290
+ throw new SimpleError({
291
+ code: 'missing_data',
292
+ message: 'Checkout was empty',
293
+ human: $t('%1L2'),
294
+ });
295
+ }
296
+
297
+ for (const pack of models) {
298
+ await pack.save();
299
+ }
300
+
301
+ const { payment, paymentUrl, paymentQRCode } = result;
302
+
303
+ return new Response(CheckoutResponse.create({
304
+ payment: payment ? await AuthenticatedStructures.paymentGeneral(payment) : null,
305
+ paymentUrl,
306
+ paymentQRCode,
307
+ }));
308
+ }
309
+
310
+ setPayment;
311
+ }
@@ -0,0 +1,94 @@
1
+ import type { AutoEncoderPatchType, Decoder, PatchableArrayAutoEncoder } from '@simonbackx/simple-encoding';
2
+ import { PatchableArrayDecoder, StringDecoder } from '@simonbackx/simple-encoding';
3
+ import type { DecodedRequest, Request } from '@simonbackx/simple-endpoints';
4
+ import { Endpoint, Response } from '@simonbackx/simple-endpoints';
5
+ import { SimpleError } from '@simonbackx/simple-errors';
6
+ import { Organization } from '@stamhoofd/models';
7
+ import { PaymentMandate } from '@stamhoofd/structures/PaymentMandate.js';
8
+ import { Context } from '../../../../helpers/Context.js';
9
+ import { PaymentMandateService } from '../../../../services/PaymentMandateService.js';
10
+
11
+ type Params = { sellingOrganizationId: string };
12
+ type Query = undefined;
13
+ type Body = PatchableArrayAutoEncoder<PaymentMandate>;
14
+ type ResponseBody = PaymentMandate[];
15
+
16
+ export class DeleteOrganizationMandateEndpoint extends Endpoint<Params, Query, Body, ResponseBody> {
17
+ bodyDecoder = new PatchableArrayDecoder(
18
+ PaymentMandate as Decoder<PaymentMandate>,
19
+ PaymentMandate.patchType() as Decoder<AutoEncoderPatchType<PaymentMandate>>,
20
+ StringDecoder,
21
+ ) as Decoder<PatchableArrayAutoEncoder<PaymentMandate>>;
22
+
23
+ protected doesMatch(request: Request): [true, Params] | [false] {
24
+ if (request.method !== 'PATCH') {
25
+ return [false];
26
+ }
27
+
28
+ const params = Endpoint.parseParameters(request.url, '/billing/@sellingOrganizationId/mandates', { sellingOrganizationId: String });
29
+
30
+ if (params) {
31
+ return [true, params as Params];
32
+ }
33
+ return [false];
34
+ }
35
+
36
+ async handle(request: DecodedRequest<Params, Query, Body>) {
37
+ const payingOrganization = await Context.setOrganizationScope();
38
+ const { user } = await Context.authenticate();
39
+
40
+ const id = request.params.sellingOrganizationId;
41
+ if (!id) {
42
+ throw new SimpleError({
43
+ code: 'unavailable',
44
+ message: 'This is temporarily unavailable',
45
+ human: $t('%1Rz'),
46
+ });
47
+ }
48
+
49
+ const sellingOrganization = await Organization.getByID(id);
50
+ if (!sellingOrganization || !sellingOrganization.active) {
51
+ throw new SimpleError({
52
+ statusCode: 404,
53
+ code: 'not_found',
54
+ message: 'Selling organization not found',
55
+ human: $t('%1R5'),
56
+ field: 'sellingOrganization',
57
+ });
58
+ }
59
+
60
+ const mandates = await PaymentMandateService.getMandates({
61
+ sellingOrganization,
62
+ user,
63
+ payingOrganization,
64
+ });
65
+
66
+ for (const patch of request.body.getPatches()) {
67
+ const mandate = mandates.find(m => m.id === patch.id);
68
+ if (!mandate) {
69
+ throw new SimpleError({
70
+ code: 'not_found',
71
+ message: 'This payment mandate is not found',
72
+ human: $t('%1R8'),
73
+ });
74
+ }
75
+
76
+ if (patch.isDefault === true) {
77
+ await PaymentMandateService.setDefaultMandate({
78
+ mandateId: mandate.id,
79
+ sellingOrganizationId: sellingOrganization.id,
80
+ payingOrganizationId: payingOrganization,
81
+ payingUserId: null,
82
+ });
83
+ }
84
+ }
85
+
86
+ const updatedMandates = await PaymentMandateService.getMandates({
87
+ sellingOrganization,
88
+ user,
89
+ payingOrganization,
90
+ });
91
+
92
+ return new Response(PaymentMandateService.groupByMandate(updatedMandates).mandates);
93
+ }
94
+ }
@@ -1,4 +1,4 @@
1
- import type { DecodedRequest, Request} from '@simonbackx/simple-endpoints';
1
+ import type { DecodedRequest, Request } from '@simonbackx/simple-endpoints';
2
2
  import { Endpoint, Response } from '@simonbackx/simple-endpoints';
3
3
  import { SimpleError } from '@simonbackx/simple-errors';
4
4
  import { DocumentTemplate } from '@stamhoofd/models';
@@ -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,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 { DocumentTemplate } from '@stamhoofd/models';
4
4
  import type { CountFilteredRequest, DocumentTemplatePrivate, StamhoofdFilter } 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,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 { Document } from '@stamhoofd/models';
4
4
  import type { CountFilteredRequest, Document as DocumentStruct, StamhoofdFilter } from '@stamhoofd/structures';
@@ -1,6 +1,6 @@
1
- import type { AutoEncoderPatchType, Decoder, PatchableArrayAutoEncoder} from '@simonbackx/simple-encoding';
1
+ import type { AutoEncoderPatchType, Decoder, PatchableArrayAutoEncoder } from '@simonbackx/simple-encoding';
2
2
  import { PatchableArrayDecoder, StringDecoder } from '@simonbackx/simple-encoding';
3
- import type { DecodedRequest, Request} from '@simonbackx/simple-endpoints';
3
+ import type { DecodedRequest, Request } from '@simonbackx/simple-endpoints';
4
4
  import { Endpoint, Response } from '@simonbackx/simple-endpoints';
5
5
  import { SimpleError } from '@simonbackx/simple-errors';
6
6
  import { Document, DocumentTemplate, Member, Registration } from '@stamhoofd/models';
@@ -45,6 +45,14 @@ export class PatchDocumentEndpoint extends Endpoint<Params, Query, Body, Respons
45
45
  throw Context.auth.notFoundOrNoAccess($t(`%EK`));
46
46
  }
47
47
 
48
+ if (document.isLocked) {
49
+ throw new SimpleError({
50
+ code: 'locked',
51
+ message: 'Document is locked',
52
+ human: $t(`%1Uc`),
53
+ });
54
+ }
55
+
48
56
  if (patch.data) {
49
57
  document.data.patchOrPut(patch.data);
50
58
  }
@@ -1,7 +1,7 @@
1
1
  import { PatchableArray } from '@simonbackx/simple-encoding';
2
- import type { Endpoint} from '@simonbackx/simple-endpoints';
2
+ import type { Endpoint } from '@simonbackx/simple-endpoints';
3
3
  import { Request } from '@simonbackx/simple-endpoints';
4
- import type { Organization, RegistrationPeriod, User} from '@stamhoofd/models';
4
+ import type { Organization, RegistrationPeriod, User } from '@stamhoofd/models';
5
5
  import { DocumentTemplate, DocumentTemplateFactory, OrganizationFactory, RegistrationPeriodFactory, Token, UserFactory } from '@stamhoofd/models';
6
6
  import { SQL } from '@stamhoofd/sql';
7
7
  import { DocumentPrivateSettings, DocumentStatus, DocumentTemplateDefinition, DocumentTemplatePrivate, PermissionLevel, Permissions } from '@stamhoofd/structures';
@@ -1,6 +1,6 @@
1
- import type { AutoEncoderPatchType, Decoder, PatchableArrayAutoEncoder} from '@simonbackx/simple-encoding';
1
+ import type { AutoEncoderPatchType, Decoder, PatchableArrayAutoEncoder } from '@simonbackx/simple-encoding';
2
2
  import { PatchableArrayDecoder, StringDecoder } from '@simonbackx/simple-encoding';
3
- import type { DecodedRequest, Request} from '@simonbackx/simple-endpoints';
3
+ import type { DecodedRequest, Request } from '@simonbackx/simple-endpoints';
4
4
  import { Endpoint, Response } from '@simonbackx/simple-endpoints';
5
5
  import { SimpleError } from '@simonbackx/simple-errors';
6
6
  import { DocumentTemplate } from '@stamhoofd/models';
@@ -1,5 +1,5 @@
1
1
  import { ArrayDecoder, 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 { SimpleError } from '@simonbackx/simple-errors';
5
5
  import { EmailAddress } from '@stamhoofd/email';
@@ -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 { EmailTemplate, GroupFactory, OrganizationFactory, Platform, RegistrationPeriodFactory, Token, UserFactory } from '@stamhoofd/models';
4
4
  import { EmailTemplateType, PermissionLevel, PermissionRoleDetailed, Permissions, PermissionsResourceType, ResourcePermissions, Version } from '@stamhoofd/structures';
5
5
  import { TestUtils } from '@stamhoofd/test-utils';
@@ -1,8 +1,8 @@
1
- import type { Decoder} from '@simonbackx/simple-encoding';
1
+ import type { Decoder } from '@simonbackx/simple-encoding';
2
2
  import { AutoEncoder, EnumDecoder, 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
- import { EmailTemplate } from '@stamhoofd/models';
5
+ import { EmailTemplate, Platform } from '@stamhoofd/models';
6
6
  import { EmailTemplate as EmailTemplateStruct, EmailTemplateType } from '@stamhoofd/structures';
7
7
  import { Formatter } from '@stamhoofd/utility';
8
8
 
@@ -60,11 +60,13 @@ export class GetEmailTemplatesEndpoint extends Endpoint<Params, Query, Body, Res
60
60
  });
61
61
  }
62
62
 
63
+ const platform = await Platform.getShared();
64
+
63
65
  const types = (request.query.types ?? [...Object.values(EmailTemplateType)]).filter((type) => {
64
66
  if (!organization) {
65
67
  return EmailTemplateStruct.allowPlatformLevel(type);
66
68
  }
67
- return EmailTemplateStruct.allowOrganizationLevel(type);
69
+ return EmailTemplateStruct.allowOrganizationLevel(type, organization, platform);
68
70
  });
69
71
 
70
72
  if (types.length === 0) {
@@ -86,10 +88,10 @@ export class GetEmailTemplatesEndpoint extends Endpoint<Params, Query, Body, Res
86
88
  // Required for event emails when logged in as the platform admin
87
89
  (request.query.webshopId || request.query.groupIds)
88
90
  ? await EmailTemplate.where({
89
- webshopId: request.query.webshopId ?? null,
90
- groupId: request.query.groupIds ? { sign: 'IN', value: request.query.groupIds } : null,
91
- type: { sign: 'IN', value: types },
92
- })
91
+ webshopId: request.query.webshopId ?? null,
92
+ groupId: request.query.groupIds ? { sign: 'IN', value: request.query.groupIds } : null,
93
+ type: { sign: 'IN', value: types },
94
+ })
93
95
  : []
94
96
  );
95
97
 
@@ -1,7 +1,7 @@
1
1
  import type { PatchableArrayAutoEncoder } from '@simonbackx/simple-encoding';
2
2
  import { PatchableArray } from '@simonbackx/simple-encoding';
3
3
  import { Request } from '@simonbackx/simple-endpoints';
4
- import type { Organization, RegistrationPeriod} from '@stamhoofd/models';
4
+ import type { Organization, RegistrationPeriod } from '@stamhoofd/models';
5
5
  import { EmailTemplate, GroupFactory, OrganizationFactory, Platform, RegistrationPeriodFactory, Token, UserFactory } from '@stamhoofd/models';
6
6
  import { EmailTemplate as EmailTemplateStruct, EmailTemplateType, PermissionLevel, PermissionRoleDetailed, Permissions, PermissionsResourceType, ResourcePermissions, Version } from '@stamhoofd/structures';
7
7
  import { TestUtils } from '@stamhoofd/test-utils';
@@ -1,8 +1,8 @@
1
- import type { AutoEncoderPatchType, Decoder, PatchableArrayAutoEncoder} from '@simonbackx/simple-encoding';
1
+ import type { AutoEncoderPatchType, Decoder, PatchableArrayAutoEncoder } from '@simonbackx/simple-encoding';
2
2
  import { PatchableArrayDecoder, StringDecoder } from '@simonbackx/simple-encoding';
3
- import type { DecodedRequest, Request} from '@simonbackx/simple-endpoints';
3
+ import type { DecodedRequest, Request } from '@simonbackx/simple-endpoints';
4
4
  import { Endpoint, Response } from '@simonbackx/simple-endpoints';
5
- import { EmailTemplate, Group, Webshop } from '@stamhoofd/models';
5
+ import { EmailTemplate, Group, Platform, Webshop } from '@stamhoofd/models';
6
6
  import { EmailTemplate as EmailTemplateStruct, PermissionLevel } from '@stamhoofd/structures';
7
7
 
8
8
  import { Context } from '../../../../helpers/Context.js';
@@ -38,7 +38,6 @@ export class PatchEmailTemplatesEndpoint extends Endpoint<Params, Query, Body, R
38
38
  throw Context.auth.error();
39
39
  }
40
40
  }
41
-
42
41
  const templates: EmailTemplate[] = [];
43
42
 
44
43
  // Get all patches
@@ -61,11 +60,11 @@ export class PatchEmailTemplatesEndpoint extends Endpoint<Params, Query, Body, R
61
60
  for (const put of request.body.getPuts()) {
62
61
  const struct = put.put;
63
62
 
64
- if (!EmailTemplateStruct.allowOrganizationLevel(struct.type) && organization) {
63
+ if (organization && !EmailTemplateStruct.allowOrganizationLevel(struct.type, organization, await Platform.getShared())) {
65
64
  throw Context.auth.error();
66
65
  }
67
66
 
68
- if (!EmailTemplateStruct.allowPlatformLevel(struct.type) && !organization) {
67
+ if (!organization && !EmailTemplateStruct.allowPlatformLevel(struct.type)) {
69
68
  throw Context.auth.error();
70
69
  }
71
70
 
@@ -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,14 +1,16 @@
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 { Invoice } from '@stamhoofd/models';
6
6
  import { applySQLSorter, compileToSQLFilter } from '@stamhoofd/sql';
7
- import type { CountFilteredRequest, InvoiceStruct, StamhoofdFilter} from '@stamhoofd/structures';
7
+ import type { CountFilteredRequest, InvoiceStruct, StamhoofdFilter } from '@stamhoofd/structures';
8
8
  import { LimitedFilteredRequest, PaginatedResponse, assertSort, getSortFilter } from '@stamhoofd/structures';
9
9
 
10
10
  import { AuthenticatedStructures } from '../../../../helpers/AuthenticatedStructures.js';
11
11
  import { Context } from '../../../../helpers/Context.js';
12
+ import { InvoicePdfService } from '../../../../services/InvoicePdfService.js';
13
+ import { InvoiceXMlService } from '../../../../services/InvoiceXMLService.js';
12
14
  import { invoiceFilterCompilers } from '../../../../sql-filters/invoices.js';
13
15
  import { invoiceSorters } from '../../../../sql-sorters/invoices.js';
14
16
 
@@ -154,8 +156,7 @@ export class GetInvoicesEndpoint extends Endpoint<Params, Query, Body, ResponseB
154
156
 
155
157
  try {
156
158
  invoices = await query.fetch();
157
- }
158
- catch (error) {
159
+ } catch (error) {
159
160
  if (error.message.includes('ER_QUERY_TIMEOUT')) {
160
161
  throw new SimpleError({
161
162
  code: 'timeout',
@@ -186,6 +187,16 @@ export class GetInvoicesEndpoint extends Endpoint<Params, Query, Body, ResponseB
186
187
  }
187
188
  }
188
189
 
190
+ for (const invoice of invoices) {
191
+ if (invoice.number && !invoice.pdf && STAMHOOFD.environment === 'development') {
192
+ await InvoicePdfService.generatePdf(invoice);
193
+ }
194
+
195
+ if (invoice.number && STAMHOOFD.environment === 'development') {
196
+ await InvoiceXMlService.generateXml(invoice);
197
+ }
198
+ }
199
+
189
200
  return new PaginatedResponse<InvoiceStruct[], LimitedFilteredRequest>({
190
201
  results: await AuthenticatedStructures.invoices(invoices),
191
202
  next,