@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,15 +1,17 @@
1
1
  import type { Response } from '@simonbackx/simple-endpoints';
2
2
  import { Request } from '@simonbackx/simple-endpoints';
3
- import type { Organization, StripeAccount, User} from '@stamhoofd/models';
3
+ import type { Organization, StripeAccount, User } from '@stamhoofd/models';
4
4
  import { OrganizationFactory, Token, UserFactory, Webshop, WebshopFactory } from '@stamhoofd/models';
5
- import type { OrderResponse} from '@stamhoofd/structures';
6
- import { Address, Cart, CartItem, CartItemOption, Customer, Option, OptionMenu, OrderData, PaymentConfiguration, PaymentMethod, PermissionLevel, Permissions, PrivatePaymentConfiguration, Product, ProductPrice, ProductType, SeatingPlan, SeatingPlanRow, SeatingPlanSeat, SeatingPlanSection, TransferSettings, WebshopDeliveryMethod, WebshopMetaData, WebshopOnSiteMethod, WebshopPrivateMetaData, WebshopTakeoutMethod, WebshopTimeSlot } from '@stamhoofd/structures';
5
+ import type { OrderResponse } from '@stamhoofd/structures';
6
+ import { Address, Cart, CartItem, CartItemOption, Customer, Option, OptionMenu, OrderData, PaymentConfiguration, PaymentMethod, PermissionLevel, Permissions, PrivatePaymentConfiguration, Product, ProductPrice, ProductType, SeatingPlan, SeatingPlanRow, SeatingPlanSeat, SeatingPlanSection, TransferSettings, WebshopAuthType, WebshopDeliveryMethod, WebshopMetaData, WebshopOnSiteMethod, WebshopPrivateMetaData, WebshopTakeoutMethod, WebshopTimeSlot } from '@stamhoofd/structures';
7
+ import { STExpect } from '@stamhoofd/test-utils';
7
8
  import { Country } from '@stamhoofd/types/Country';
8
9
  import sinon from 'sinon';
9
10
 
10
11
  import { StripeMocker } from '../../../../tests/helpers/StripeMocker.js';
11
12
  import { testServer } from '../../../../tests/helpers/TestServer.js';
12
13
  import { PatchWebshopOrdersEndpoint } from '../dashboard/webshops/PatchWebshopOrdersEndpoint.js';
14
+ import { GetOrderEndpoint } from './GetOrderEndpoint.js';
13
15
  import { PlaceOrderEndpoint } from './PlaceOrderEndpoint.js';
14
16
 
15
17
  const address = Address.create({
@@ -31,6 +33,7 @@ describe('Endpoint.PlaceOrderEndpoint', () => {
31
33
  // Test endpoint
32
34
  const endpoint = new PlaceOrderEndpoint();
33
35
  const patchWebshopOrdersEndpoint = new PatchWebshopOrdersEndpoint();
36
+ const getOrderEndpoint = new GetOrderEndpoint();
34
37
 
35
38
  let organization: Organization;
36
39
  let webshop: Webshop;
@@ -328,6 +331,31 @@ describe('Endpoint.PlaceOrderEndpoint', () => {
328
331
  });
329
332
 
330
333
  describe('User authentication', () => {
334
+ test('Required-auth webshop rejects anonymous orders', async () => {
335
+ webshop.meta.authType = WebshopAuthType.Required;
336
+ await webshop.save();
337
+
338
+ const orderData = OrderData.create({
339
+ paymentMethod: PaymentMethod.Unknown,
340
+ checkoutMethod: onSiteMethod,
341
+ timeSlot: slot4,
342
+ cart: Cart.create({
343
+ items: [
344
+ CartItem.create({
345
+ product,
346
+ productPrice: freeProductPrice,
347
+ amount: 1,
348
+ }),
349
+ ],
350
+ }),
351
+ customer,
352
+ });
353
+
354
+ const r = Request.buildJson('POST', `/webshop/${webshop.id}/order`, organization.getApiHost(), orderData);
355
+
356
+ await expect(testServer.test(endpoint, r)).rejects.toThrow(STExpect.errorWithCode('not_authenticated'));
357
+ });
358
+
331
359
  test('Placing an order with a signed in user overrides the order customer', async () => {
332
360
  const user = await new UserFactory({ organization, firstName: 'User', lastName: 'Tester' }).create();
333
361
  const token = await Token.createToken(user);
@@ -370,6 +398,49 @@ describe('Endpoint.PlaceOrderEndpoint', () => {
370
398
  expect(order.data.customer.lastName).toEqual(user.lastName);
371
399
  });
372
400
 
401
+ test('Required-auth webshop order can only be read by owner', async () => {
402
+ webshop.meta.authType = WebshopAuthType.Required;
403
+ await webshop.save();
404
+
405
+ const user = await new UserFactory({ organization, firstName: 'User', lastName: 'Tester' }).create();
406
+ const token = await Token.createToken(user);
407
+ const otherUser = await new UserFactory({ organization }).create();
408
+ const otherToken = await Token.createToken(otherUser);
409
+
410
+ const orderData = OrderData.create({
411
+ paymentMethod: PaymentMethod.Unknown,
412
+ checkoutMethod: onSiteMethod,
413
+ timeSlot: slot4,
414
+ cart: Cart.create({
415
+ items: [
416
+ CartItem.create({
417
+ product,
418
+ productPrice: freeProductPrice,
419
+ amount: 1,
420
+ }),
421
+ ],
422
+ }),
423
+ customer,
424
+ });
425
+
426
+ const placeRequest = Request.buildJson('POST', `/webshop/${webshop.id}/order`, organization.getApiHost(), orderData);
427
+ placeRequest.headers.authorization = 'Bearer ' + token.accessToken;
428
+ const placeResponse = await testServer.test(endpoint, placeRequest);
429
+ const order = placeResponse.body.order;
430
+
431
+ const anonymousRequest = Request.buildJson('GET', `/webshop/${webshop.id}/order/${order.id}`, organization.getApiHost());
432
+ await expect(testServer.test(getOrderEndpoint, anonymousRequest)).rejects.toThrow(STExpect.errorWithCode('not_authenticated'));
433
+
434
+ const otherUserRequest = Request.buildJson('GET', `/webshop/${webshop.id}/order/${order.id}`, organization.getApiHost());
435
+ otherUserRequest.headers.authorization = 'Bearer ' + otherToken.accessToken;
436
+ await expect(testServer.test(getOrderEndpoint, otherUserRequest)).rejects.toThrow(STExpect.errorWithCode('not_found'));
437
+
438
+ const ownerRequest = Request.buildJson('GET', `/webshop/${webshop.id}/order/${order.id}`, organization.getApiHost());
439
+ ownerRequest.headers.authorization = 'Bearer ' + token.accessToken;
440
+ const ownerResponse = await testServer.test(getOrderEndpoint, ownerRequest);
441
+ expect(ownerResponse.body.id).toEqual(order.id);
442
+ });
443
+
373
444
  /**
374
445
  * This checks if the authenticated context is passed when multiple orders are executed in a queue
375
446
  */
@@ -6,7 +6,7 @@ import { SimpleError } from '@simonbackx/simple-errors';
6
6
  import { Email } from '@stamhoofd/email';
7
7
  import { BalanceItem, BalanceItemPayment, MolliePayment, Order, PayconiqPayment, Payment, RateLimiter, Webshop, WebshopDiscountCode } from '@stamhoofd/models';
8
8
  import { QueueHandler } from '@stamhoofd/queues';
9
- import { AuditLogSource, BalanceItemRelation, BalanceItemRelationType, BalanceItemStatus, BalanceItemType, OrderData, OrderResponse, Order as OrderStruct, PaymentCustomer, PaymentMethod, PaymentMethodHelper, PaymentProvider, PaymentStatus, Payment as PaymentStruct, TranslatedString, Version, WebshopAuthType, Webshop as WebshopStruct, WebshopTicketType } from '@stamhoofd/structures';
9
+ import { AuditLogSource, BalanceItemRelation, BalanceItemRelationType, BalanceItemStatus, BalanceItemType, OrderData, OrderResponse, Order as OrderStruct, PaymentCustomer, PaymentMethod, PaymentMethodHelper, PaymentProvider, PaymentStatus, Payment as PaymentStruct, TranslatedString, Version, Webshop as WebshopStruct, WebshopTicketType } from '@stamhoofd/structures';
10
10
  import { Formatter } from '@stamhoofd/utility';
11
11
 
12
12
  import { BuckarooHelper } from '../../../helpers/BuckarooHelper.js';
@@ -17,6 +17,7 @@ import { AuditLogService } from '../../../services/AuditLogService.js';
17
17
  import { MollieService } from '../../../services/MollieService.js';
18
18
  import { PaymentService } from '../../../services/PaymentService.js';
19
19
  import { UitpasService } from '../../../services/uitpas/UitpasService.js';
20
+ import { WebshopAuthHelper } from './WebshopAuthHelper.js';
20
21
 
21
22
  type Params = { id: string };
22
23
  type Query = undefined;
@@ -59,7 +60,6 @@ export class PlaceOrderEndpoint extends Endpoint<Params, Query, Body, ResponseBo
59
60
 
60
61
  async handle(request: DecodedRequest<Params, Query, Body>) {
61
62
  const organization = await Context.setOrganizationScope();
62
- await Context.optionalAuthenticate();
63
63
 
64
64
  // Read + validate + update stock in one go, to prevent race conditions
65
65
  const { webshop, order } = await QueueHandler.schedule('webshop-stock/' + request.params.id, async () => {
@@ -74,15 +74,7 @@ export class PlaceOrderEndpoint extends Endpoint<Params, Query, Body, ResponseBo
74
74
 
75
75
  // const organization = (await Organization.getByID(webshopWithoutOrganization.organizationId))!
76
76
  const webshop = webshopWithoutOrganization.setRelation(Webshop.organization, organization);
77
-
78
- if (webshop.meta.authType === WebshopAuthType.Required && !Context.user) {
79
- throw new SimpleError({
80
- code: 'not_authenticated',
81
- message: 'Not authenticated',
82
- human: $t(`%w5`),
83
- statusCode: 401,
84
- });
85
- }
77
+ await WebshopAuthHelper.optionalAuthenticateForWebshop(webshop);
86
78
 
87
79
  // For non paid organizations, the limit is 10
88
80
  if (!organization.meta.packages.isPaid && STAMHOOFD.environment !== 'test') {
@@ -90,8 +82,7 @@ export class PlaceOrderEndpoint extends Endpoint<Params, Query, Body, ResponseBo
90
82
 
91
83
  try {
92
84
  limiter.track(organization.id, 1);
93
- }
94
- catch (e) {
85
+ } catch (e) {
95
86
  Email.sendWebmaster({
96
87
  subject: '[Limiet] Limiet bereikt voor aantal bestellingen',
97
88
  text: 'Beste, \nDe limiet werd bereikt voor het aantal bestellingen per dag. \nVereniging: ' + organization.id + ' (' + organization.name + ')' + '\n\n' + e.message + '\n\nStamhoofd',
@@ -174,8 +165,7 @@ export class PlaceOrderEndpoint extends Endpoint<Params, Query, Body, ResponseBo
174
165
  // Mark this order as paid
175
166
  await order.markPaid(null, organization, webshop);
176
167
  await order.save();
177
- }
178
- else {
168
+ } else {
179
169
  const payment = new Payment();
180
170
  payment.organizationId = organization.id;
181
171
  payment.method = request.body.paymentMethod;
@@ -195,13 +185,13 @@ export class PlaceOrderEndpoint extends Endpoint<Params, Query, Body, ResponseBo
195
185
  const { provider, stripeAccount } = await organization.getPaymentProviderFor(payment.method, null, webshop.privateMeta.paymentConfiguration);
196
186
  payment.provider = provider;
197
187
  payment.stripeAccountId = stripeAccount?.id ?? null;
198
- ServiceFeeHelper.setServiceFee(
188
+ await ServiceFeeHelper.setServiceFee(
199
189
  payment,
200
190
  organization,
201
191
  webshop.meta.ticketType === WebshopTicketType.None ? 'webshop' : 'tickets',
202
192
  order.data.cart.items.flatMap(i => i.calculatedPrices.map(p => p.discountedPrice)),
203
193
  );
204
-
194
+ await ServiceFeeHelper.setTransferFee({ payment, organization, stripeAccount });
205
195
  await payment.save();
206
196
 
207
197
  // Deprecated field
@@ -253,8 +243,7 @@ export class PlaceOrderEndpoint extends Endpoint<Params, Query, Body, ResponseBo
253
243
  balanceItem.status = BalanceItemStatus.Due;
254
244
  await balanceItem.save();
255
245
  await payment.save();
256
- }
257
- else if (payment.method === PaymentMethod.PointOfSale) {
246
+ } else if (payment.method === PaymentMethod.PointOfSale) {
258
247
  // Not really paid, but needed to create the tickets if needed
259
248
  await order.markPaid(payment, organization, webshop);
260
249
 
@@ -265,8 +254,7 @@ export class PlaceOrderEndpoint extends Endpoint<Params, Query, Body, ResponseBo
265
254
  balanceItem.status = BalanceItemStatus.Due;
266
255
  await balanceItem.save();
267
256
  await payment.save();
268
- }
269
- else {
257
+ } else {
270
258
  const cancelUrl = 'https://' + webshop.getHost() + '/payment?id=' + encodeURIComponent(payment.id) + '&cancel=true';
271
259
  const redirectUrl = 'https://' + webshop.getHost() + '/payment?id=' + encodeURIComponent(payment.id);
272
260
  const exchangeUrl = 'https://' + organization.getApiHost() + '/v' + Version + '/payments/' + encodeURIComponent(payment.id) + '?exchange=true';
@@ -292,10 +280,9 @@ export class PlaceOrderEndpoint extends Endpoint<Params, Query, Body, ResponseBo
292
280
  },
293
281
  });
294
282
  paymentUrl = stripeResult.paymentUrl;
295
- }
296
- else if (payment.provider === PaymentProvider.Mollie) {
283
+ } else if (payment.provider === PaymentProvider.Mollie) {
297
284
  // Mollie payment
298
- const mollieService = await MollieService.create({sellingOrganization: organization});
285
+ const mollieService = await MollieService.create({ sellingOrganization: organization });
299
286
  if (!mollieService) {
300
287
  throw new SimpleError({
301
288
  code: '',
@@ -326,7 +313,7 @@ export class PlaceOrderEndpoint extends Endpoint<Params, Query, Body, ResponseBo
326
313
  webshop: webshop.id,
327
314
  payment: payment.id,
328
315
  },
329
- locale: mollieService.locale
316
+ locale: mollieService.locale,
330
317
  });
331
318
  console.log(molliePayment);
332
319
  paymentUrl = molliePayment.getCheckoutUrl();
@@ -336,11 +323,9 @@ export class PlaceOrderEndpoint extends Endpoint<Params, Query, Body, ResponseBo
336
323
  dbPayment.paymentId = payment.id;
337
324
  dbPayment.mollieId = molliePayment.id;
338
325
  await dbPayment.save();
339
- }
340
- else if (payment.provider == PaymentProvider.Payconiq) {
326
+ } else if (payment.provider == PaymentProvider.Payconiq) {
341
327
  ({ paymentUrl, paymentQRCode } = await PayconiqPayment.createPayment(payment, organization, description, redirectUrl, exchangeUrl));
342
- }
343
- else if (payment.provider == PaymentProvider.Buckaroo) {
328
+ } else if (payment.provider == PaymentProvider.Buckaroo) {
344
329
  // Increase request timeout because buckaroo is super slow
345
330
  request.request.request?.setTimeout(60 * 1000);
346
331
  const buckaroo = new BuckarooHelper(organization.privateMeta?.buckarooSettings?.key ?? '', organization.privateMeta?.buckarooSettings?.secret ?? '', organization.privateMeta.useTestPayments ?? STAMHOOFD.environment !== 'production');
@@ -357,8 +342,7 @@ export class PlaceOrderEndpoint extends Endpoint<Params, Query, Body, ResponseBo
357
342
  }),
358
343
  });
359
344
  }
360
- }
361
- else {
345
+ } else {
362
346
  throw new Error('Unknown payment provider');
363
347
  }
364
348
  }
@@ -369,8 +353,7 @@ export class PlaceOrderEndpoint extends Endpoint<Params, Query, Body, ResponseBo
369
353
  order: OrderStruct.create({ ...order, payment: PaymentStruct.create(payment) }),
370
354
  }));
371
355
  }
372
- }
373
- catch (e) {
356
+ } catch (e) {
374
357
  // Mark order as failed to release stock
375
358
  if (order) {
376
359
  await order.deleteOrderBecauseOfCreationError();
@@ -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 { UitpasPriceCheckRequest, UitpasPriceCheckResponse } from '@stamhoofd/structures';
@@ -47,8 +47,7 @@ export class RetrieveUitpasSocialTariffPricesEndpoint extends Endpoint<Params, Q
47
47
  prices: [reducedPrice], // Convert to cents
48
48
  });
49
49
  return new Response(uitpasPriceCheckResponse);
50
- }
51
- else {
50
+ } else {
52
51
  // OFFICIAL FLOW with an UiTPAS number
53
52
  // request should include a reduced price (estimate by the frontend)
54
53
  const organization = await Context.setOrganizationScope({ willAuthenticate: false });
@@ -58,8 +57,7 @@ export class RetrieveUitpasSocialTariffPricesEndpoint extends Endpoint<Params, Q
58
57
  });
59
58
  return new Response(uitpasPriceCheckResponse);
60
59
  }
61
- }
62
- else {
60
+ } else {
63
61
  // NON-OFFICIAL FLOW
64
62
  // request should include UiTPAS-numbers, reduced price AND base price
65
63
  if (request.body.reducedPrice === null) {
@@ -0,0 +1,36 @@
1
+ import { SimpleError } from '@simonbackx/simple-errors';
2
+ import type { Order, Webshop } from '@stamhoofd/models';
3
+ import { WebshopAuthType } from '@stamhoofd/structures';
4
+
5
+ import { Context } from '../../../helpers/Context.js';
6
+
7
+ export class WebshopAuthHelper {
8
+ static async optionalAuthenticateForWebshop(webshop: Webshop) {
9
+ await Context.optionalAuthenticate();
10
+
11
+ if (webshop.meta.authType === WebshopAuthType.Required && !Context.user) {
12
+ throw new SimpleError({
13
+ code: 'not_authenticated',
14
+ message: 'Not authenticated',
15
+ human: $t(`%w5`),
16
+ statusCode: 401,
17
+ });
18
+ }
19
+ }
20
+
21
+ static async checkOrderAccess(webshop: Webshop, order: Order) {
22
+ await this.optionalAuthenticateForWebshop(webshop);
23
+
24
+ if (webshop.meta.authType !== WebshopAuthType.Required) {
25
+ return;
26
+ }
27
+
28
+ if (order.userId !== Context.user?.id) {
29
+ throw new SimpleError({
30
+ code: 'not_found',
31
+ message: 'Order not found',
32
+ human: $t(`%FY`),
33
+ });
34
+ }
35
+ }
36
+ }
@@ -1,5 +1,5 @@
1
1
  import { ArrayDecoder, 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 { SimpleError } from '@simonbackx/simple-errors';
5
5
  import { CpuService } from '../../services/CpuService.js';
@@ -1,7 +1,7 @@
1
1
  import type { XlsxTransformerColumn } from '@stamhoofd/excel-writer';
2
2
  import { XlsxBuiltInNumberFormat } from '@stamhoofd/excel-writer';
3
3
  import { BalanceItem } from '@stamhoofd/models';
4
- import type { BalanceItemWithPayments} from '@stamhoofd/structures';
4
+ import type { BalanceItemWithPayments } from '@stamhoofd/structures';
5
5
  import { BalanceItemRelationType, ExcelExportType, getBalanceItemRelationTypeName, getBalanceItemTypeName, PaginatedResponse, PaymentStatus } from '@stamhoofd/structures';
6
6
  import { Formatter } from '@stamhoofd/utility';
7
7
  import { ExportToExcelEndpoint } from '../endpoints/global/files/ExportToExcelEndpoint.js';
@@ -1,6 +1,6 @@
1
1
  import type { XlsxTransformerSheet } from '@stamhoofd/excel-writer';
2
2
  import { XlsxBuiltInNumberFormat } from '@stamhoofd/excel-writer';
3
- import type { EventNotification, LimitedFilteredRequest} from '@stamhoofd/structures';
3
+ import type { EventNotification, LimitedFilteredRequest } from '@stamhoofd/structures';
4
4
  import { EventNotificationStatus, EventNotificationStatusHelper, ExcelExportType, Platform as PlatformStruct } from '@stamhoofd/structures';
5
5
  import { Formatter } from '@stamhoofd/utility';
6
6
  import { GetEventNotificationsEndpoint } from '../endpoints/global/events/GetEventNotificationsEndpoint.js';
@@ -1,7 +1,7 @@
1
1
  import type { XlsxTransformerColumn, XlsxTransformerSheet } from '@stamhoofd/excel-writer';
2
2
  import { XlsxBuiltInNumberFormat } from '@stamhoofd/excel-writer';
3
3
  import { Platform } from '@stamhoofd/models';
4
- import type { LimitedFilteredRequest, PlatformMember} from '@stamhoofd/structures';
4
+ import type { LimitedFilteredRequest, PlatformMember } from '@stamhoofd/structures';
5
5
  import { ExcelExportType, Gender, GroupType, MembershipStatus, PlatformFamily, Platform as PlatformStruct, UnencodeablePaginatedResponse } from '@stamhoofd/structures';
6
6
  import { Formatter } from '@stamhoofd/utility';
7
7
  import { ExportToExcelEndpoint } from '../endpoints/global/files/ExportToExcelEndpoint.js';
@@ -240,9 +240,9 @@ ExportToExcelEndpoint.loaders.set(ExcelExportType.Organizations, {
240
240
  const organizationIds = organizations.results.map(o => o.id);
241
241
  const responsibilities = organizationIds.length
242
242
  ? await MemberResponsibilityRecord.select()
243
- .where('organizationId', organizationIds)
244
- .where('endDate', null)
245
- .fetch()
243
+ .where('organizationId', organizationIds)
244
+ .where('endDate', null)
245
+ .fetch()
246
246
  : [];
247
247
 
248
248
  // Load groups and members
@@ -2,7 +2,7 @@ import { field } from '@simonbackx/simple-encoding';
2
2
  import type { XlsxTransformerColumn, XlsxTransformerConcreteColumn } from '@stamhoofd/excel-writer';
3
3
  import { XlsxBuiltInNumberFormat } from '@stamhoofd/excel-writer';
4
4
  import { StripeAccount } from '@stamhoofd/models';
5
- import type { BalanceItemPaymentDetailed} from '@stamhoofd/structures';
5
+ import type { BalanceItemPaymentDetailed } from '@stamhoofd/structures';
6
6
  import { BalanceItemRelationType, ExcelExportType, getBalanceItemRelationTypeName, getBalanceItemTypeName, PaginatedResponse, PaymentGeneral, PaymentMethodHelper, PaymentStatusHelper, StripeAccount as StripeAccountStruct } from '@stamhoofd/structures';
7
7
  import { Formatter } from '@stamhoofd/utility';
8
8
  import { ExportToExcelEndpoint } from '../endpoints/global/files/ExportToExcelEndpoint.js';
@@ -400,6 +400,36 @@ function getStripeColumns(): XlsxTransformerColumn<PaymentGeneral>[] {
400
400
  };
401
401
  },
402
402
  },
403
+ {
404
+ id: 'serviceFeeManual',
405
+ name: $t(`%1dO`),
406
+ width: 42,
407
+ getValue: (object: PaymentGeneralWithStripeAccount) => {
408
+ return {
409
+ value: object.serviceFeeManual / 1_0000,
410
+ style: {
411
+ numberFormat: {
412
+ id: XlsxBuiltInNumberFormat.Currency2DecimalWithRed,
413
+ },
414
+ },
415
+ };
416
+ },
417
+ },
418
+ {
419
+ id: 'serviceFeePayout',
420
+ name: $t(`%1VD`),
421
+ width: 50,
422
+ getValue: (object: PaymentGeneralWithStripeAccount) => {
423
+ return {
424
+ value: object.serviceFeePayout / 1_0000,
425
+ style: {
426
+ numberFormat: {
427
+ id: XlsxBuiltInNumberFormat.Currency2DecimalWithRed,
428
+ },
429
+ },
430
+ };
431
+ },
432
+ },
403
433
  {
404
434
  id: 'stripeAccountId',
405
435
  name: $t(`%1m`),
@@ -25,7 +25,7 @@ const sheet: XlsxTransformerSheet<PlatformMembership> = {
25
25
  getValue: (membership: PlatformMembership) => {
26
26
  const membershipType = Platform.shared.config.membershipTypes.find(m => m.id === membership.membershipTypeId);
27
27
  const value = membershipType ? membershipType.name : '';
28
- return {value};
28
+ return { value };
29
29
  },
30
30
  },
31
31
  {
@@ -66,25 +66,25 @@ const sheet: XlsxTransformerSheet<PlatformMembership> = {
66
66
  return {
67
67
  value: membership.price / 1_0000,
68
68
  style: {
69
- numberFormat: {
70
- id: XlsxBuiltInNumberFormat.Currency2DecimalWithRed,
69
+ numberFormat: {
70
+ id: XlsxBuiltInNumberFormat.Currency2DecimalWithRed,
71
+ },
71
72
  },
72
- },
73
73
  };
74
74
  },
75
75
  },
76
76
  {
77
77
  id: 'priceWithoutDiscount',
78
- name: $t(`%1Nm`),
78
+ name: $t(`%1Nm`),
79
79
  width: 10,
80
80
  getValue: (membership: PlatformMembership) => {
81
81
  return {
82
82
  value: membership.priceWithoutDiscount / 1_0000,
83
83
  style: {
84
- numberFormat: {
85
- id: XlsxBuiltInNumberFormat.Currency2DecimalWithRed,
84
+ numberFormat: {
85
+ id: XlsxBuiltInNumberFormat.Currency2DecimalWithRed,
86
+ },
86
87
  },
87
- },
88
88
  };
89
89
  },
90
90
  },
@@ -214,7 +214,7 @@ const sheet: XlsxTransformerSheet<PlatformMembership> = {
214
214
  id: 'member.firstName',
215
215
  name: $t(`%1O8`),
216
216
  width: 20,
217
- getValue:(membership: PlatformMembership) => ({
217
+ getValue: (membership: PlatformMembership) => ({
218
218
  value: membership.member.firstName,
219
219
  }),
220
220
  },
@@ -222,7 +222,7 @@ const sheet: XlsxTransformerSheet<PlatformMembership> = {
222
222
  id: 'member.lastName',
223
223
  name: $t(`%1Or`),
224
224
  width: 20,
225
- getValue:(membership: PlatformMembership) => ({
225
+ getValue: (membership: PlatformMembership) => ({
226
226
  value: membership.member.lastName,
227
227
  }),
228
228
  },
@@ -231,7 +231,7 @@ const sheet: XlsxTransformerSheet<PlatformMembership> = {
231
231
  id: 'organization.name',
232
232
  name: $t(`%1PW`),
233
233
  width: 20,
234
- getValue:(membership: PlatformMembership) => ({
234
+ getValue: (membership: PlatformMembership) => ({
235
235
  value: membership.organization.name,
236
236
  }),
237
237
  },
@@ -239,14 +239,13 @@ const sheet: XlsxTransformerSheet<PlatformMembership> = {
239
239
  id: 'organization.uri',
240
240
  name: $t(`%1PZ`),
241
241
  width: 20,
242
- getValue:(membership: PlatformMembership) => ({
242
+ getValue: (membership: PlatformMembership) => ({
243
243
  value: membership.organization.uri,
244
244
  }),
245
- }
245
+ },
246
246
  ],
247
247
  };
248
248
 
249
-
250
249
  ExportToExcelEndpoint.loaders.set(ExcelExportType.PlatformMemberships, {
251
250
  fetch: async (query: LimitedFilteredRequest) => {
252
251
  const data = await GetPlatformMembershipsEndpoint.buildData(query);
@@ -146,7 +146,7 @@ function getBalanceItemColumns(): XlsxTransformerColumn<ReceivableBalanceWithIte
146
146
  },
147
147
  {
148
148
  id: 'pricePending',
149
- name: $t(`%1PL`),
149
+ name: $t(`%1OL`),
150
150
  width: 20,
151
151
  getValue: (object: ReceivableBalanceWithItem) => ({
152
152
  value: object.balanceItem.pricePending / 1_0000,
@@ -273,7 +273,7 @@ function getGeneralColumns(): XlsxTransformerConcreteColumn<ReceivableBalance>[]
273
273
  },
274
274
  {
275
275
  id: 'amountPending',
276
- name: $t(`%1PL`),
276
+ name: $t(`%1OL`),
277
277
  width: 18,
278
278
  getValue: (object: ReceivableBalance) => ({
279
279
  value: object.amountPending / 1_0000,
@@ -1,7 +1,7 @@
1
1
  import type { XlsxTransformerSheet } from '@stamhoofd/excel-writer';
2
2
  import { XlsxBuiltInNumberFormat } from '@stamhoofd/excel-writer';
3
3
  import { Platform } from '@stamhoofd/models';
4
- import type { LimitedFilteredRequest, PlatformMember} from '@stamhoofd/structures';
4
+ import type { LimitedFilteredRequest, PlatformMember } from '@stamhoofd/structures';
5
5
  import { ExcelExportType, getGroupTypeName, PlatformRegistration, Platform as PlatformStruct, UnencodeablePaginatedResponse } from '@stamhoofd/structures';
6
6
  import { ExportToExcelEndpoint } from '../endpoints/global/files/ExportToExcelEndpoint.js';
7
7
  import { GetRegistrationsEndpoint } from '../endpoints/global/registration/GetRegistrationsEndpoint.js';
@@ -164,8 +164,7 @@ const sheet: XlsxTransformerSheet<PlatformMember, PlatformRegistration> = {
164
164
  if (registration.payingOrganizationId) {
165
165
  const organization = registration.member.organizations.find(o => o.id === registration.payingOrganizationId);
166
166
  value = organization ? organization.name : $t(`%Gr`);
167
- }
168
- else {
167
+ } else {
169
168
  value = $t(`%18s`);
170
169
  }
171
170
 
@@ -40,8 +40,7 @@ export class AddressValidatorStatic {
40
40
 
41
41
  // Don't do validation on last letters
42
42
  postalCode = numbers;
43
- }
44
- else {
43
+ } else {
45
44
  postalCode = postalCode.trim();
46
45
  }
47
46
 
@@ -50,8 +49,7 @@ export class AddressValidatorStatic {
50
49
  if (!/\d{4}/.test(numbers)) {
51
50
  postalCode = numbers;
52
51
  address.city = address.city.substring(4).trim();
53
- }
54
- else {
52
+ } else {
55
53
  throw new SimpleError({
56
54
  code: 'invalid_field',
57
55
  message: 'Postal code is required',
@@ -93,8 +91,7 @@ export class AddressValidatorStatic {
93
91
  const c = await City.getByID(city.parentCityId ?? city.id);
94
92
  try {
95
93
  await this.syncCity(c!);
96
- }
97
- catch (e) {
94
+ } catch (e) {
98
95
  console.error('Ignored error while syncing city');
99
96
  console.error(e);
100
97
  }
@@ -115,8 +112,7 @@ export class AddressValidatorStatic {
115
112
 
116
113
  if (bestStreet && bestScore < 3) {
117
114
  address.street = bestStreet.name;
118
- }
119
- else {
115
+ } else {
120
116
  // Search for the street
121
117
  bestScore = 0;
122
118
  bestStreet = undefined;
@@ -144,8 +140,7 @@ export class AddressValidatorStatic {
144
140
  field: 'street',
145
141
  });
146
142
  }
147
- }
148
- else {
143
+ } else {
149
144
  // Skip validation for some regions that don't support validation
150
145
  }
151
146
  }
@@ -180,8 +175,7 @@ export class AddressValidatorStatic {
180
175
  streetNames.push(...streets);
181
176
  url = result.volgende;
182
177
  }
183
- }
184
- catch (e) {
178
+ } catch (e) {
185
179
  console.error(e.response.data);
186
180
  throw new Error('Failed to fetch streets');
187
181
  }
@@ -238,8 +232,7 @@ export class AddressValidatorStatic {
238
232
  for (const city of cities) {
239
233
  try {
240
234
  await this.syncCity(city);
241
- }
242
- catch (e) {
235
+ } catch (e) {
243
236
  console.error('Failed city sync for ' + city.name, e);
244
237
  }
245
238
  }