@stamhoofd/backend 2.118.1 → 2.120.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.
- package/package.json +32 -22
- package/src/audit-logs/ModelLogger.ts +4 -2
- package/src/audit-logs/OrderLogger.ts +1 -1
- package/src/boot.ts +32 -14
- package/src/crons/balance-emails.ts +4 -2
- package/src/crons/clearExcelCache.test.ts +8 -8
- package/src/crons/update-cached-balances.ts +40 -14
- package/src/debug.ts +3 -2
- package/src/decoders/StringArrayDecoder.ts +1 -1
- package/src/decoders/StringNullableDecoder.ts +1 -1
- package/src/email-recipient-loaders/documents.ts +2 -1
- package/src/email-recipient-loaders/members.ts +2 -1
- package/src/email-recipient-loaders/orders.ts +2 -1
- package/src/email-recipient-loaders/payments.ts +6 -3
- package/src/email-recipient-loaders/receivable-balances.ts +2 -1
- package/src/email-recipient-loaders/registrations.ts +2 -1
- package/src/email-replacements/getEmailReplacementsForPayment.ts +8 -7
- package/src/endpoints/admin/members/ChargeMembersEndpoint.ts +7 -6
- package/src/endpoints/admin/memberships/ChargeMembershipsEndpoint.ts +3 -2
- package/src/endpoints/admin/memberships/GetChargeMembershipsSummaryEndpoint.ts +2 -1
- package/src/endpoints/admin/organizations/ChargeOrganizationsEndpoint.ts +4 -3
- package/src/endpoints/admin/organizations/GetOrganizationsCountEndpoint.ts +3 -2
- package/src/endpoints/admin/organizations/GetOrganizationsEndpoint.ts +7 -5
- package/src/endpoints/admin/organizations/PatchOrganizationsEndpoint.ts +12 -10
- package/src/endpoints/admin/registrations/ChargeRegistrationsEndpoint.ts +4 -3
- package/src/endpoints/auth/CreateAdminEndpoint.ts +8 -6
- package/src/endpoints/auth/CreateTokenEndpoint.ts +14 -12
- package/src/endpoints/auth/DeleteTokenEndpoint.ts +2 -1
- package/src/endpoints/auth/DeleteUserEndpoint.ts +2 -1
- package/src/endpoints/auth/ForgotPasswordEndpoint.ts +5 -4
- package/src/endpoints/auth/GetOtherUserEndpoint.ts +3 -2
- package/src/endpoints/auth/GetUserEndpoint.ts +3 -2
- package/src/endpoints/auth/OpenIDConnectAuthTokenEndpoint.ts +2 -1
- package/src/endpoints/auth/OpenIDConnectCallbackEndpoint.ts +4 -2
- package/src/endpoints/auth/OpenIDConnectStartEndpoint.ts +3 -2
- package/src/endpoints/auth/PatchUserEndpoint.ts +15 -12
- package/src/endpoints/auth/PollEmailVerificationEndpoint.ts +3 -2
- package/src/endpoints/auth/RetryEmailVerificationEndpoint.ts +3 -2
- package/src/endpoints/auth/SignupEndpoint.ts +5 -4
- package/src/endpoints/auth/VerifyEmailEndpoint.ts +6 -5
- package/src/endpoints/frontend/FrontendEnvironmentEndpoint.ts +3 -2
- package/src/endpoints/global/addresses/SearchRegionsEndpoint.ts +8 -5
- package/src/endpoints/global/addresses/ValidateAddressEndpoint.ts +5 -3
- package/src/endpoints/global/audit-logs/GetAuditLogsEndpoint.ts +8 -5
- package/src/endpoints/global/billing/ActivatePackagesEndpoint.ts +9 -7
- package/src/endpoints/global/billing/DeactivatePackageEndpoint.ts +4 -3
- package/src/endpoints/global/caddy/CheckDomainCertEndpoint.ts +4 -2
- package/src/endpoints/global/email/CreateEmailEndpoint.ts +9 -7
- package/src/endpoints/global/email/GetAdminEmailsEndpoint.test.ts +2 -1
- package/src/endpoints/global/email/GetAdminEmailsEndpoint.ts +22 -19
- package/src/endpoints/global/email/GetEmailAddressEndpoint.ts +6 -4
- package/src/endpoints/global/email/GetEmailEndpoint.ts +4 -3
- package/src/endpoints/global/email/GetUserEmailsEndpoint.test.ts +3 -2
- package/src/endpoints/global/email/GetUserEmailsEndpoint.ts +7 -4
- package/src/endpoints/global/email/ManageEmailAddressEndpoint.ts +7 -5
- package/src/endpoints/global/email/PatchEmailEndpoint.test.ts +11 -11
- package/src/endpoints/global/email/PatchEmailEndpoint.ts +14 -11
- package/src/endpoints/global/email-recipients/GetEmailRecipientsCountEndpoint.ts +3 -2
- package/src/endpoints/global/email-recipients/GetEmailRecipientsEndpoint.test.ts +2 -1
- package/src/endpoints/global/email-recipients/GetEmailRecipientsEndpoint.ts +8 -5
- package/src/endpoints/global/email-recipients/RetryEmailRecipientEndpoint.ts +7 -5
- package/src/endpoints/global/email-recipients/helpers/validateEmailRecipientFilter.ts +4 -3
- package/src/endpoints/global/events/GetEventNotificationsCountEndpoint.ts +3 -2
- package/src/endpoints/global/events/GetEventNotificationsEndpoint.ts +9 -6
- package/src/endpoints/global/events/GetEventsEndpoint.ts +7 -4
- package/src/endpoints/global/events/PatchEventNotificationsEndpoint.test.ts +4 -2
- package/src/endpoints/global/events/PatchEventNotificationsEndpoint.ts +17 -15
- package/src/endpoints/global/events/PatchEventsEndpoint.test.ts +4 -2
- package/src/endpoints/global/events/PatchEventsEndpoint.ts +28 -26
- package/src/endpoints/global/files/ExportToExcelEndpoint.ts +8 -5
- package/src/endpoints/global/files/GetFileCache.ts +5 -3
- package/src/endpoints/global/files/UploadFile.ts +10 -4
- package/src/endpoints/global/files/UploadImage.ts +4 -2
- package/src/endpoints/global/groups/GetGroupsEndpoint.test.ts +4 -2
- package/src/endpoints/global/groups/GetGroupsEndpoint.ts +8 -5
- package/src/endpoints/global/members/GetMemberFamilyEndpoint.ts +7 -5
- package/src/endpoints/global/members/GetMembersCountEndpoint.ts +3 -2
- package/src/endpoints/global/members/GetMembersEndpoint.test.ts +4 -2
- package/src/endpoints/global/members/GetMembersEndpoint.ts +10 -8
- package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.test.ts +257 -6
- package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.ts +162 -107
- package/src/endpoints/global/members/helpers/validateGroupFilter.ts +4 -3
- package/src/endpoints/global/members/shouldCheckIfMemberIsDuplicate.ts +3 -2
- package/src/endpoints/global/organizations/CheckRegisterCodeEndpoint.ts +3 -2
- package/src/endpoints/global/organizations/CreateOrganizationEndpoint.test.ts +3 -2
- package/src/endpoints/global/organizations/CreateOrganizationEndpoint.ts +8 -7
- package/src/endpoints/global/organizations/GetOrganizationFromDomainEndpoint.ts +5 -3
- package/src/endpoints/global/organizations/GetOrganizationFromUriEndpoint.ts +5 -3
- package/src/endpoints/global/organizations/SearchOrganizationEndpoint.ts +8 -5
- package/src/endpoints/global/payments/StripeWebhookEndpoint.ts +4 -2
- package/src/endpoints/global/platform/GetPlatformAdminsEndpoint.ts +2 -1
- package/src/endpoints/global/platform/GetPlatformEndpoint.ts +3 -2
- package/src/endpoints/global/platform/PatchPlatformEnpoint.test.ts +3 -2
- package/src/endpoints/global/platform/PatchPlatformEnpoint.ts +7 -4
- package/src/endpoints/global/platform-memberships/GetPlatformMembershipsCountEndpoint.ts +47 -0
- package/src/endpoints/global/platform-memberships/GetPlatformMembershipsEndpoint.ts +206 -0
- package/src/endpoints/global/registration/GetRegistrationsCountEndpoint.ts +3 -2
- package/src/endpoints/global/registration/GetRegistrationsEndpoint.test.ts +2 -1
- package/src/endpoints/global/registration/GetRegistrationsEndpoint.ts +10 -7
- package/src/endpoints/global/registration/GetUserDetailedPayableBalanceEndpoint.ts +4 -2
- package/src/endpoints/global/registration/GetUserDocumentsEndpoint.ts +4 -2
- package/src/endpoints/global/registration/GetUserMembersEndpoint.ts +3 -2
- package/src/endpoints/global/registration/GetUserPayableBalanceEndpoint.ts +2 -1
- package/src/endpoints/global/registration/PatchUserMembersEndpoint.test.ts +5 -3
- package/src/endpoints/global/registration/PatchUserMembersEndpoint.ts +13 -9
- package/src/endpoints/global/registration/RegisterMembersEndpoint.test.ts +50 -49
- package/src/endpoints/global/registration/RegisterMembersEndpoint.ts +25 -22
- package/src/endpoints/global/registration-periods/GetRegistrationPeriodsEndpoint.ts +8 -5
- package/src/endpoints/global/registration-periods/PatchRegistrationPeriodsEndpoint.ts +9 -7
- package/src/endpoints/global/sso/GetSSOEndpoint.ts +4 -2
- package/src/endpoints/global/sso/SetSSOEndpoint.ts +3 -2
- package/src/endpoints/global/webshops/GetWebshopFromDomainEndpoint.ts +4 -2
- package/src/endpoints/global/webshops/GetWebshopsCountEndpoint.ts +43 -0
- package/src/endpoints/global/webshops/GetWebshopsEndpoint.test.ts +808 -0
- package/src/endpoints/global/webshops/GetWebshopsEndpoint.ts +221 -0
- package/src/endpoints/organization/dashboard/balance-items/GetBalanceItemEndpoint.ts +4 -3
- package/src/endpoints/organization/dashboard/balance-items/GetBalanceItemsCountEndpoint.ts +3 -2
- package/src/endpoints/organization/dashboard/balance-items/GetBalanceItemsEndpoint.ts +6 -4
- package/src/endpoints/organization/dashboard/balance-items/PatchBalanceItemsEndpoint.ts +15 -13
- package/src/endpoints/organization/dashboard/billing/GetOrganizationDetailedPayableBalanceEndpoint.ts +4 -2
- package/src/endpoints/organization/dashboard/billing/GetOrganizationPayableBalanceEndpoint.ts +4 -2
- package/src/endpoints/organization/dashboard/billing/GetPackagesEndpoint.ts +2 -1
- package/src/endpoints/organization/dashboard/documents/GetDocumentTemplateXML.ts +3 -2
- package/src/endpoints/organization/dashboard/documents/GetDocumentTemplatesCountEndpoint.ts +3 -2
- package/src/endpoints/organization/dashboard/documents/GetDocumentTemplatesEndpoint.ts +7 -4
- package/src/endpoints/organization/dashboard/documents/GetDocumentsCountEndpoint.ts +3 -2
- package/src/endpoints/organization/dashboard/documents/GetDocumentsEndpoint.ts +7 -4
- package/src/endpoints/organization/dashboard/documents/PatchDocumentEndpoint.ts +9 -7
- package/src/endpoints/organization/dashboard/documents/PatchDocumentTemplatesEndpoint.test.ts +4 -2
- package/src/endpoints/organization/dashboard/documents/PatchDocumentTemplatesEndpoint.ts +7 -5
- package/src/endpoints/organization/dashboard/email/CheckEmailBouncesEndpoint.ts +3 -2
- package/src/endpoints/organization/dashboard/email-templates/GetEmailTemplatesEndpoint.test.ts +36 -1
- package/src/endpoints/organization/dashboard/email-templates/GetEmailTemplatesEndpoint.ts +13 -4
- package/src/endpoints/organization/dashboard/email-templates/PatchEmailTemplatesEndpoint.test.ts +4 -2
- package/src/endpoints/organization/dashboard/email-templates/PatchEmailTemplatesEndpoint.ts +7 -5
- package/src/endpoints/organization/dashboard/invoices/GetInvoicesCountEndpoint.ts +3 -2
- package/src/endpoints/organization/dashboard/invoices/GetInvoicesEndpoint.ts +6 -4
- package/src/endpoints/organization/dashboard/invoices/PatchInvoicesEndpoint.ts +5 -3
- package/src/endpoints/organization/dashboard/mollie/CheckMollieEndpoint.ts +4 -2
- package/src/endpoints/organization/dashboard/mollie/ConnectMollieEndpoint.ts +6 -3
- package/src/endpoints/organization/dashboard/mollie/DisconnectMollieEndpoint.ts +4 -2
- package/src/endpoints/organization/dashboard/mollie/GetMollieDashboardEndpoint.ts +2 -1
- package/src/endpoints/organization/dashboard/nolt/CreateNoltTokenEndpoint.ts +2 -1
- package/src/endpoints/organization/dashboard/organization/GetOrganizationArchivedGroups.ts +4 -2
- package/src/endpoints/organization/dashboard/organization/GetOrganizationDeletedGroups.ts +3 -2
- package/src/endpoints/organization/dashboard/organization/GetUitpasClientIdEndpoint.ts +2 -1
- package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.test.ts +5 -3
- package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.ts +22 -19
- package/src/endpoints/organization/dashboard/organization/SearchUitpasOrganizersEndpoint.ts +5 -3
- package/src/endpoints/organization/dashboard/organization/SetOrganizationDomainEndpoint.ts +11 -9
- package/src/endpoints/organization/dashboard/organization/SetUitpasClientCredentialsEndpoint.ts +8 -7
- package/src/endpoints/organization/dashboard/payments/GetMemberBalanceEndpoint.ts +2 -1
- package/src/endpoints/organization/dashboard/payments/GetPaymentsCountEndpoint.ts +3 -2
- package/src/endpoints/organization/dashboard/payments/GetPaymentsEndpoint.ts +7 -5
- package/src/endpoints/organization/dashboard/payments/PatchPaymentsEndpoint.ts +18 -16
- package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalanceEndpoint.ts +2 -1
- package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalancesCountEndpoint.ts +3 -2
- package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalancesEndpoint.ts +5 -3
- package/src/endpoints/organization/dashboard/registration-periods/GetOrganizationRegistrationPeriodsEndpoint.test.ts +2 -1
- package/src/endpoints/organization/dashboard/registration-periods/GetOrganizationRegistrationPeriodsEndpoint.ts +8 -5
- package/src/endpoints/organization/dashboard/registration-periods/MoveRegistrationPeriods.test.ts +4 -2
- package/src/endpoints/organization/dashboard/registration-periods/PatchOrganizationRegistrationPeriodsEndpoint.test.ts +4 -2
- package/src/endpoints/organization/dashboard/registration-periods/PatchOrganizationRegistrationPeriodsEndpoint.ts +32 -29
- package/src/endpoints/organization/dashboard/registration-periods/SetupStepReviewEndpoint.ts +6 -3
- package/src/endpoints/organization/dashboard/stripe/ConnectStripeEndpoint.ts +3 -2
- package/src/endpoints/organization/dashboard/stripe/DeleteStripeAccountEndpoint.ts +3 -2
- package/src/endpoints/organization/dashboard/stripe/GetStripeAccountLinkEndpoint.ts +5 -3
- package/src/endpoints/organization/dashboard/stripe/GetStripeAccountsEndpoint.ts +2 -1
- package/src/endpoints/organization/dashboard/stripe/GetStripeLoginLinkEndpoint.ts +5 -3
- package/src/endpoints/organization/dashboard/stripe/UpdateStripeAccountEndpoint.ts +3 -2
- package/src/endpoints/organization/dashboard/users/CreateApiUserEndpoint.ts +4 -3
- package/src/endpoints/organization/dashboard/users/DeleteUserEndpoint.ts +4 -3
- package/src/endpoints/organization/dashboard/users/GetApiUsersEndpoint.ts +3 -2
- package/src/endpoints/organization/dashboard/users/GetOrganizationAdminsEndpoint.ts +2 -1
- package/src/endpoints/organization/dashboard/users/PatchApiUserEndpoint.ts +6 -4
- package/src/endpoints/organization/dashboard/webshops/CreateWebshopEndpoint.ts +7 -6
- package/src/endpoints/organization/dashboard/webshops/DeleteWebshopEndpoint.ts +3 -2
- package/src/endpoints/organization/dashboard/webshops/GetDiscountCodesEndpoint.ts +4 -2
- package/src/endpoints/organization/dashboard/webshops/GetWebshopOrdersCountEndpoint.ts +3 -2
- package/src/endpoints/organization/dashboard/webshops/GetWebshopOrdersEndpoint.ts +7 -4
- package/src/endpoints/organization/dashboard/webshops/{GetWebshopTicketsCountEndpoint → GetWebshopTicketsCountEndpoint.ts} +7 -7
- package/src/endpoints/organization/dashboard/webshops/GetWebshopTicketsEndpoint.ts +9 -6
- package/src/endpoints/organization/dashboard/webshops/GetWebshopUriAvailabilityEndpoint.ts +4 -2
- package/src/endpoints/organization/dashboard/webshops/PatchDiscountCodesEndpoint.ts +6 -4
- package/src/endpoints/organization/dashboard/webshops/PatchWebshopEndpoint.ts +13 -12
- package/src/endpoints/organization/dashboard/webshops/PatchWebshopOrdersEndpoint.ts +4 -2
- package/src/endpoints/organization/dashboard/webshops/PatchWebshopTicketsEndpoint.ts +5 -3
- package/src/endpoints/organization/dashboard/webshops/SearchUitpasEventsEndpoint.ts +6 -4
- package/src/endpoints/organization/dashboard/webshops/VerifyWebshopDomainEndpoint.ts +2 -1
- package/src/endpoints/organization/shared/ExchangePaymentEndpoint.ts +6 -4
- package/src/endpoints/organization/shared/GetDocumentHtml.ts +4 -3
- package/src/endpoints/organization/shared/GetPaymentEndpoint.ts +4 -3
- package/src/endpoints/organization/shared/GetUitpasNumberDetailsEndpoint.ts +3 -2
- package/src/endpoints/organization/shared/auth/GetOrganizationEndpoint.ts +3 -2
- package/src/endpoints/organization/webshops/CheckWebshopDiscountCodesEndpoint.ts +4 -3
- package/src/endpoints/organization/webshops/GetOrderByPaymentEndpoint.ts +5 -4
- package/src/endpoints/organization/webshops/GetOrderEndpoint.ts +4 -3
- package/src/endpoints/organization/webshops/GetTicketsEndpoint.ts +7 -5
- package/src/endpoints/organization/webshops/GetWebshopEndpoint.ts +4 -3
- package/src/endpoints/organization/webshops/PlaceOrderEndpoint.test.ts +7 -3
- package/src/endpoints/organization/webshops/PlaceOrderEndpoint.ts +11 -10
- package/src/endpoints/organization/webshops/RetrieveUitpasSocialTariffPriceEndpoint.ts +5 -4
- package/src/endpoints/system/HealthEndpoint.test.ts +44 -0
- package/src/endpoints/system/HealthEndpoint.ts +14 -6
- package/src/excel-loaders/balance-items.ts +19 -17
- package/src/excel-loaders/event-notifications.ts +15 -13
- package/src/excel-loaders/index.ts +1 -0
- package/src/excel-loaders/members.ts +45 -43
- package/src/excel-loaders/organizations.ts +26 -25
- package/src/excel-loaders/payments.ts +44 -42
- package/src/excel-loaders/platform-memberships.ts +202 -0
- package/src/excel-loaders/receivable-balances.ts +25 -23
- package/src/excel-loaders/registrations.ts +30 -28
- package/src/helpers/AddressValidator.test.ts +2 -1
- package/src/helpers/AddressValidator.ts +13 -10
- package/src/helpers/AdminPermissionChecker.ts +193 -95
- package/src/helpers/AuthenticatedStructures.ts +13 -11
- package/src/helpers/BuckarooHelper.ts +3 -2
- package/src/helpers/Context.ts +8 -6
- package/src/helpers/CookieHelper.ts +2 -2
- package/src/helpers/FileCache.ts +9 -9
- package/src/helpers/ForwardHandler.ts +3 -2
- package/src/helpers/GlobalHelper.ts +2 -0
- package/src/helpers/GroupBuilder.ts +2 -1
- package/src/helpers/GroupedThrottledQueue.test.ts +19 -19
- package/src/helpers/LimitedFilteredRequestHelper.ts +1 -1
- package/src/helpers/MemberCharger.ts +2 -1
- package/src/helpers/MemberUserSyncer.ts +6 -3
- package/src/helpers/MembershipCharger.ts +2 -2
- package/src/helpers/OrganizationCharger.ts +2 -1
- package/src/helpers/PeriodHelper.ts +2 -1
- package/src/helpers/SQLTranslatedString.ts +3 -2
- package/src/helpers/ServiceFeeHelper.ts +1 -1
- package/src/helpers/SetupStepUpdater.ts +6 -5
- package/src/helpers/StripeHelper.ts +9 -8
- package/src/helpers/TagHelper.test.ts +5 -5
- package/src/helpers/TagHelper.ts +2 -1
- package/src/helpers/TemporaryMemberAccess.ts +2 -1
- package/src/helpers/ThrottledQueue.test.ts +20 -20
- package/src/helpers/UitpasTokenRepository.ts +7 -7
- package/src/helpers/ViesHelper.ts +5 -4
- package/src/helpers/XlsxTransformerColumnHelper.ts +21 -19
- package/src/helpers/email-html-helpers.ts +13 -12
- package/src/helpers/fetchToAsyncIterator.ts +1 -1
- package/src/helpers/outstandingBalanceJoin.ts +2 -1
- package/src/helpers/updateMemberDetailsUitpasNumber.ts +5 -4
- package/src/middleware/ContextMiddleware.ts +1 -1
- package/src/migrate.ts +21 -4
- package/src/seeds/0000000003-default-email-templates.ts +1 -1
- package/src/seeds/0000000004-single-organization.ts +2 -1
- package/src/seeds/1752848561-groups-registration-periods.ts +3 -2
- package/src/seeds/1754560914-groups-prices.test.ts +2 -1
- package/src/seeds/1754560914-groups-prices.ts +2 -1
- package/src/seeds/1755790070-fill-email-recipient-errors.ts +6 -6
- package/src/seeds/1755876819-remove-duplicate-members.ts +2 -1
- package/src/seeds/1765896674-document-update-year.test.ts +2 -1
- package/src/seeds/1773754928-force-save-members.ts +15 -0
- package/src/services/AuditLogService.ts +3 -2
- package/src/services/BalanceItemPaymentService.ts +2 -2
- package/src/services/BalanceItemService.ts +2 -1
- package/src/services/BootChecksService.test.ts +33 -0
- package/src/services/BootChecksService.ts +21 -0
- package/src/services/DatabaseCollationService.test.ts +18 -0
- package/src/services/DatabaseCollationService.ts +81 -0
- package/src/services/DocumentService.ts +1 -1
- package/src/services/EventNotificationService.ts +5 -4
- package/src/services/FileSignService.ts +2 -2
- package/src/services/InvoiceService.ts +3 -3
- package/src/services/MemberNumberService.ts +6 -4
- package/src/services/MemberRecordStore.ts +28 -19
- package/src/services/PaymentReallocationService.test.ts +2 -1
- package/src/services/PaymentReallocationService.ts +2 -1
- package/src/services/PaymentService.ts +28 -26
- package/src/services/RegistrationService.ts +65 -3
- package/src/services/SSOService.ts +13 -9
- package/src/services/STPackageService.ts +7 -5
- package/src/services/StartupHealthService.ts +15 -0
- package/src/services/uitpas/PassholderEndpoints.ts +2 -2
- package/src/services/uitpas/UitpasService.ts +11 -8
- package/src/services/uitpas/cancelTicketSales.ts +1 -1
- package/src/services/uitpas/checkPermissionsFor.ts +9 -9
- package/src/services/uitpas/getSocialTariffForEvent.ts +4 -4
- package/src/services/uitpas/getSocialTariffForUitpasNumbers.ts +5 -5
- package/src/services/uitpas/handleUitpasResponse.ts +1 -1
- package/src/services/uitpas/registerTicketSales.ts +4 -4
- package/src/services/uitpas/searchUitpasEvents.ts +3 -3
- package/src/services/uitpas/searchUitpasOrganizers.ts +3 -3
- package/src/sql-filters/audit-logs.ts +2 -1
- package/src/sql-filters/balance-item-payments.ts +2 -1
- package/src/sql-filters/balance-items.ts +2 -1
- package/src/sql-filters/base-registration-filter-compilers.ts +6 -4
- package/src/sql-filters/document-templates.ts +2 -1
- package/src/sql-filters/documents.ts +2 -1
- package/src/sql-filters/email-recipients.ts +2 -1
- package/src/sql-filters/emails.ts +2 -1
- package/src/sql-filters/event-notifications.ts +2 -1
- package/src/sql-filters/events.ts +2 -1
- package/src/sql-filters/groups.ts +2 -1
- package/src/sql-filters/invoiced-balance-items.ts +2 -1
- package/src/sql-filters/invoices.ts +2 -1
- package/src/sql-filters/member-responsibility-records.ts +2 -1
- package/src/sql-filters/members.ts +8 -7
- package/src/sql-filters/orders.ts +3 -2
- package/src/sql-filters/organization-registration-periods.ts +2 -1
- package/src/sql-filters/organizations.ts +2 -1
- package/src/sql-filters/payments.ts +2 -1
- package/src/sql-filters/platform-memberships.ts +67 -0
- package/src/sql-filters/receivable-balances.ts +2 -1
- package/src/sql-filters/registration-periods.ts +2 -1
- package/src/sql-filters/registrations.ts +2 -1
- package/src/sql-filters/tickets.ts +2 -1
- package/src/sql-filters/users.ts +2 -1
- package/src/sql-filters/webshops.ts +38 -0
- package/src/sql-sorters/audit-logs.ts +3 -2
- package/src/sql-sorters/balance-items.ts +3 -2
- package/src/sql-sorters/document-templates.ts +3 -2
- package/src/sql-sorters/documents.ts +3 -2
- package/src/sql-sorters/email-recipients.ts +3 -2
- package/src/sql-sorters/emails.ts +3 -2
- package/src/sql-sorters/event-notifications.ts +3 -2
- package/src/sql-sorters/events.ts +3 -2
- package/src/sql-sorters/groups.ts +3 -2
- package/src/sql-sorters/invoices.ts +3 -2
- package/src/sql-sorters/members.ts +3 -2
- package/src/sql-sorters/orders.ts +3 -2
- package/src/sql-sorters/organization-registration-periods.ts +3 -2
- package/src/sql-sorters/organizations.ts +3 -2
- package/src/sql-sorters/payments.ts +3 -2
- package/src/sql-sorters/platform-memberships.ts +40 -0
- package/src/sql-sorters/receivable-balances.ts +3 -2
- package/src/sql-sorters/registration-periods.ts +3 -2
- package/src/sql-sorters/registrations.ts +3 -2
- package/src/sql-sorters/tickets.ts +3 -2
- package/src/sql-sorters/webshops.ts +40 -0
- package/tests/actions/patchOrganizationMember.ts +5 -4
- package/tests/actions/patchPaymentStatus.ts +2 -2
- package/tests/actions/patchUserMember.ts +6 -4
- package/tests/e2e/api-rate-limits.test.ts +4 -5
- package/tests/e2e/bundle-discounts.test.ts +3 -2
- package/tests/e2e/charge-members.test.ts +7 -5
- package/tests/e2e/documents.test.ts +3 -2
- package/tests/e2e/private-files.test.ts +11 -13
- package/tests/e2e/register.test.ts +6 -5
- package/tests/e2e/stock.test.ts +6 -8
- package/tests/e2e/tickets.test.ts +4 -2
- package/tests/helpers/StripeMocker.ts +3 -3
- package/tests/init/initAdmin.ts +4 -2
- package/tests/init/initBundleDiscount.ts +3 -2
- package/tests/init/initPayconiq.ts +1 -1
- package/tests/init/initPermissionRole.ts +4 -2
- package/tests/init/initPlatformRecordCategory.ts +1 -1
- package/tests/init/initStripe.ts +1 -1
- package/tests/vitest.global.setup.ts +26 -0
- package/tests/{jest.setup.ts → vitest.setup.ts} +4 -3
- package/tsconfig.build.json +17 -0
- package/tsconfig.json +10 -41
- package/tsconfig.test.json +17 -0
- package/vitest.config.js +13 -0
- package/eslint.config.mjs +0 -5
- package/jest.config.cjs +0 -27
- package/tests/jest.global.setup.ts +0 -33
- package/tests/toMatchMap.ts +0 -68
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Database } from '@simonbackx/simple-database';
|
|
2
|
+
import { DatabaseCollationService } from './DatabaseCollationService.js';
|
|
3
|
+
|
|
4
|
+
describe('DatabaseCollationService', () => {
|
|
5
|
+
test('Detects collation_connection mismatch', async () => {
|
|
6
|
+
await Database.statement('SET collation_connection = \'utf8mb4_general_ci\'');
|
|
7
|
+
|
|
8
|
+
try {
|
|
9
|
+
const error = await DatabaseCollationService.getMismatchError();
|
|
10
|
+
expect(error).toContain('MySQL collation mismatch');
|
|
11
|
+
expect(error).toContain('expected utf8mb4_0900_ai_ci');
|
|
12
|
+
expect(error).toContain('collation_connection=utf8mb4_general_ci');
|
|
13
|
+
}
|
|
14
|
+
finally {
|
|
15
|
+
await Database.statement('SET collation_connection = DEFAULT');
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
});
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { Database } from '@simonbackx/simple-database';
|
|
2
|
+
|
|
3
|
+
const EXPECTED_COLLATION = 'utf8mb4_0900_ai_ci';
|
|
4
|
+
|
|
5
|
+
type CollationRow = {
|
|
6
|
+
collationConnection: string;
|
|
7
|
+
collationDatabase: string;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export class DatabaseCollationService {
|
|
11
|
+
static expectedCollation = EXPECTED_COLLATION;
|
|
12
|
+
|
|
13
|
+
static async getCurrentCollations() {
|
|
14
|
+
const connectionResult = await Database.statement("SHOW VARIABLES LIKE 'collation_connection'");
|
|
15
|
+
const databaseResult = await Database.statement("SHOW VARIABLES LIKE 'collation_database'");
|
|
16
|
+
|
|
17
|
+
const collationConnection = this.extractVariableValue(connectionResult);
|
|
18
|
+
const collationDatabase = this.extractVariableValue(databaseResult);
|
|
19
|
+
|
|
20
|
+
return {
|
|
21
|
+
collationConnection: typeof collationConnection === 'string' ? collationConnection : '',
|
|
22
|
+
collationDatabase: typeof collationDatabase === 'string' ? collationDatabase : '',
|
|
23
|
+
} as CollationRow;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
private static extractVariableValue(result: unknown) {
|
|
27
|
+
if (result && typeof result === 'object' && 'rows' in result) {
|
|
28
|
+
return this.extractVariableValue((result as { rows: unknown }).rows);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (Array.isArray(result) && result.length > 0 && Array.isArray(result[0])) {
|
|
32
|
+
return this.extractVariableValue(result[0]);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (!Array.isArray(result) || result.length === 0) {
|
|
36
|
+
return '';
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const firstRow = result[0] as Record<string, unknown> | undefined;
|
|
40
|
+
|
|
41
|
+
if (!firstRow) {
|
|
42
|
+
return '';
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const value = firstRow.Value
|
|
46
|
+
?? firstRow.value
|
|
47
|
+
?? firstRow.VARIABLE_VALUE
|
|
48
|
+
?? firstRow.variable_value;
|
|
49
|
+
|
|
50
|
+
if (typeof value === 'string') {
|
|
51
|
+
return value;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
for (const candidate of Object.values(firstRow)) {
|
|
55
|
+
if (typeof candidate === 'string' && candidate.startsWith('utf8mb4_')) {
|
|
56
|
+
return candidate;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return '';
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
static async getMismatchError() {
|
|
64
|
+
const collations = await this.getCurrentCollations();
|
|
65
|
+
const mismatches: string[] = [];
|
|
66
|
+
|
|
67
|
+
if (collations.collationConnection !== this.expectedCollation) {
|
|
68
|
+
mismatches.push(`collation_connection=${collations.collationConnection}`);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (collations.collationDatabase !== this.expectedCollation) {
|
|
72
|
+
mismatches.push(`collation_database=${collations.collationDatabase}`);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (mismatches.length === 0) {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return `MySQL collation mismatch: expected ${this.expectedCollation}, got ${mismatches.join(', ')}`;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Model } from '@simonbackx/simple-database';
|
|
2
|
-
import { PlainObject } from '@simonbackx/simple-encoding';
|
|
2
|
+
import type { PlainObject } from '@simonbackx/simple-encoding';
|
|
3
3
|
import { Document, Group } from '@stamhoofd/models';
|
|
4
4
|
|
|
5
5
|
function getGroupFieldsAffectingDocuments(group: Group): PlainObject {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { SimpleError } from '@simonbackx/simple-errors';
|
|
2
2
|
import { EventNotification, Member, MemberResponsibilityRecord, Organization, Platform, sendEmailTemplate, User } from '@stamhoofd/models';
|
|
3
|
-
import { EmailTemplateType
|
|
3
|
+
import type { EmailTemplateType} from '@stamhoofd/structures';
|
|
4
|
+
import { PermissionLevel, Recipient, RecordCategory, Replacement } from '@stamhoofd/structures';
|
|
4
5
|
import { Formatter } from '@stamhoofd/utility';
|
|
5
6
|
import { AdminPermissionChecker } from '../helpers/AdminPermissionChecker.js';
|
|
6
7
|
import { Context } from '../helpers/Context.js';
|
|
@@ -15,7 +16,7 @@ export class EventNotificationService {
|
|
|
15
16
|
throw new SimpleError({
|
|
16
17
|
code: 'invalid_field',
|
|
17
18
|
message: 'Invalid type',
|
|
18
|
-
human: Context.i18n.$t('
|
|
19
|
+
human: Context.i18n.$t('%AT'),
|
|
19
20
|
field: 'typeId',
|
|
20
21
|
});
|
|
21
22
|
}
|
|
@@ -132,7 +133,7 @@ export class EventNotificationService {
|
|
|
132
133
|
}
|
|
133
134
|
const events = EventNotification.events.isLoaded(notification) ? notification.events : await EventNotification.events.load(notification);
|
|
134
135
|
const type = await this.validateType(notification);
|
|
135
|
-
let submitterName = $t(`
|
|
136
|
+
let submitterName = $t(`%wq`);
|
|
136
137
|
|
|
137
138
|
if (notification.submittedBy) {
|
|
138
139
|
const user = await User.getByID(notification.submittedBy);
|
|
@@ -164,7 +165,7 @@ export class EventNotificationService {
|
|
|
164
165
|
}),
|
|
165
166
|
Replacement.create({
|
|
166
167
|
token: 'feedbackText',
|
|
167
|
-
html: notification.feedbackText ? `<p class="pre-wrap"><em>${Formatter.escapeHtml(notification.feedbackText)}</em></p>` : `<p class="pre-wrap"><em>${Formatter.escapeHtml($t('
|
|
168
|
+
html: notification.feedbackText ? `<p class="pre-wrap"><em>${Formatter.escapeHtml(notification.feedbackText)}</em></p>` : `<p class="pre-wrap"><em>${Formatter.escapeHtml($t('%Av'))}</em></p>`,
|
|
168
169
|
}),
|
|
169
170
|
];
|
|
170
171
|
}
|
|
@@ -2,7 +2,7 @@ import { GetObjectCommand, S3Client } from '@aws-sdk/client-s3'; // ES Modules i
|
|
|
2
2
|
import {
|
|
3
3
|
getSignedUrl,
|
|
4
4
|
} from '@aws-sdk/s3-request-presigner';
|
|
5
|
-
import { DecodedRequest, Request, Response } from '@simonbackx/simple-endpoints';
|
|
5
|
+
import type { DecodedRequest, Request, Response } from '@simonbackx/simple-endpoints';
|
|
6
6
|
import { SimpleError } from '@simonbackx/simple-errors';
|
|
7
7
|
import { File } from '@stamhoofd/structures';
|
|
8
8
|
import chalk from 'chalk';
|
|
@@ -191,7 +191,7 @@ export class FileSignService {
|
|
|
191
191
|
throw new SimpleError({
|
|
192
192
|
code: 'invalid_signature',
|
|
193
193
|
message: 'Invalid signature for file',
|
|
194
|
-
human: $t('
|
|
194
|
+
human: $t('%B7'),
|
|
195
195
|
});
|
|
196
196
|
}
|
|
197
197
|
return;
|
|
@@ -11,7 +11,7 @@ export class InvoiceService {
|
|
|
11
11
|
code: 'missing_customer',
|
|
12
12
|
message: 'Missing customer',
|
|
13
13
|
field: 'customer',
|
|
14
|
-
human: $t('
|
|
14
|
+
human: $t('%1Iw'),
|
|
15
15
|
});
|
|
16
16
|
}
|
|
17
17
|
|
|
@@ -38,7 +38,7 @@ export class InvoiceService {
|
|
|
38
38
|
throw new SimpleError({
|
|
39
39
|
code: 'missing_company',
|
|
40
40
|
message: 'Missing invoice settings (companies)',
|
|
41
|
-
human: $t('
|
|
41
|
+
human: $t('%1Ix', {
|
|
42
42
|
'organization-name': organization.name,
|
|
43
43
|
}),
|
|
44
44
|
});
|
|
@@ -137,7 +137,7 @@ export class InvoiceService {
|
|
|
137
137
|
throw new SimpleError({
|
|
138
138
|
code: 'invalid_field',
|
|
139
139
|
message: 'payableRoundingAmount cannot be more than 10 cent',
|
|
140
|
-
human: $t('
|
|
140
|
+
human: $t('%1LG'),
|
|
141
141
|
field: 'payableRoundingAmount',
|
|
142
142
|
});
|
|
143
143
|
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { isSimpleError, isSimpleErrors, SimpleError } from '@simonbackx/simple-errors';
|
|
2
|
-
import { Member, MemberPlatformMembership
|
|
2
|
+
import type { Member, MemberPlatformMembership} from '@stamhoofd/models';
|
|
3
|
+
import { Organization } from '@stamhoofd/models';
|
|
3
4
|
import { QueueHandler } from '@stamhoofd/queues';
|
|
4
5
|
import { scalarToSQLExpression, SQL, SQLCharLength, SQLWhereLike } from '@stamhoofd/sql';
|
|
6
|
+
import { MemberNumberAlgorithm } from '@stamhoofd/types/MemberNumberAlgorithm';
|
|
5
7
|
|
|
6
8
|
export class MemberNumberService {
|
|
7
9
|
static async assignMemberNumber(member: Member, membership: MemberPlatformMembership) {
|
|
@@ -36,7 +38,7 @@ export class MemberNumberService {
|
|
|
36
38
|
throw new SimpleError({
|
|
37
39
|
code: 'assign_member_number',
|
|
38
40
|
message: error.message,
|
|
39
|
-
human: $t(`
|
|
41
|
+
human: $t(`%Fw`),
|
|
40
42
|
});
|
|
41
43
|
}
|
|
42
44
|
}
|
|
@@ -61,7 +63,7 @@ export class MemberNumberService {
|
|
|
61
63
|
throw new SimpleError({
|
|
62
64
|
code: 'assign_member_number',
|
|
63
65
|
message: 'Missing birthDay',
|
|
64
|
-
human: $t(`
|
|
66
|
+
human: $t(`%Fx`),
|
|
65
67
|
});
|
|
66
68
|
}
|
|
67
69
|
|
|
@@ -123,7 +125,7 @@ export class MemberNumberService {
|
|
|
123
125
|
throw new SimpleError({
|
|
124
126
|
code: 'assign_member_number',
|
|
125
127
|
message: `Duplicate member numbers (last try: ${memberNumber}, tries: ${tries})`,
|
|
126
|
-
human: $t(`
|
|
128
|
+
human: $t(`%Fy`),
|
|
127
129
|
});
|
|
128
130
|
}
|
|
129
131
|
}
|
|
@@ -1,33 +1,31 @@
|
|
|
1
1
|
import { Model } from '@simonbackx/simple-database';
|
|
2
2
|
import { Organization, Platform } from '@stamhoofd/models';
|
|
3
3
|
import { QueueHandler } from '@stamhoofd/queues';
|
|
4
|
-
import { RecordSettings } from '@stamhoofd/structures';
|
|
4
|
+
import type { RecordSettings } from '@stamhoofd/structures';
|
|
5
5
|
|
|
6
6
|
export type RecordCacheEntry = { record: RecordSettings; rootCategoryId: string; organizationId: string | null };
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Service that caches all available member records in the system.
|
|
10
|
-
* - It
|
|
10
|
+
* - It verifies whether ids are unique system wide
|
|
11
11
|
* - It allows fast retrieving of record settings by id (for permission checking)
|
|
12
12
|
*/
|
|
13
|
-
|
|
14
|
-
private
|
|
13
|
+
class MemberRecordStoreService {
|
|
14
|
+
private cache = new Map<string, RecordCacheEntry>();
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
init() {
|
|
17
|
+
// Should only be used in userMode platform
|
|
18
|
+
if (STAMHOOFD.userMode !== 'platform') {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
19
21
|
|
|
20
|
-
static init() {
|
|
21
22
|
// Load initial data
|
|
22
23
|
this.loadIfNeeded().catch(console.error);
|
|
23
|
-
|
|
24
|
-
// Create listeners to update data as organizations and platform is updated
|
|
25
|
-
this.listen();
|
|
26
24
|
}
|
|
27
25
|
|
|
28
|
-
private
|
|
26
|
+
private listening = false;
|
|
29
27
|
|
|
30
|
-
private
|
|
28
|
+
private listen() {
|
|
31
29
|
// Create listeners to update data as organizations and platform is updated
|
|
32
30
|
if (this.listening) {
|
|
33
31
|
return;
|
|
@@ -66,7 +64,7 @@ export class MemberRecordStore {
|
|
|
66
64
|
}
|
|
67
65
|
|
|
68
66
|
if (event.model instanceof Organization) {
|
|
69
|
-
// Delete all records
|
|
67
|
+
// Delete all records where organizationId equals the organization
|
|
70
68
|
for (const [id, entry] of this.cache) {
|
|
71
69
|
if (entry.organizationId === event.model.id) {
|
|
72
70
|
this.cache.delete(id);
|
|
@@ -88,10 +86,10 @@ export class MemberRecordStore {
|
|
|
88
86
|
});
|
|
89
87
|
}
|
|
90
88
|
|
|
91
|
-
|
|
92
|
-
|
|
89
|
+
private _loadAllPromise: Promise<void> | null = null;
|
|
90
|
+
private _didLoadAll = false;
|
|
93
91
|
|
|
94
|
-
|
|
92
|
+
private async loadIfNeeded() {
|
|
95
93
|
if (this._didLoadAll) {
|
|
96
94
|
return;
|
|
97
95
|
}
|
|
@@ -100,6 +98,11 @@ export class MemberRecordStore {
|
|
|
100
98
|
await this._loadAllPromise;
|
|
101
99
|
}
|
|
102
100
|
else {
|
|
101
|
+
if (STAMHOOFD.userMode !== 'platform') {
|
|
102
|
+
// Important to throw an error because in tests the userMode can change in between tests
|
|
103
|
+
throw new Error('Should only be loaded in userMode platform.');
|
|
104
|
+
}
|
|
105
|
+
|
|
103
106
|
this._loadAllPromise = (async () => {
|
|
104
107
|
try {
|
|
105
108
|
await this.loadAll();
|
|
@@ -116,7 +119,7 @@ export class MemberRecordStore {
|
|
|
116
119
|
}
|
|
117
120
|
}
|
|
118
121
|
|
|
119
|
-
|
|
122
|
+
private async loadAll() {
|
|
120
123
|
this.cache = new Map<string, RecordCacheEntry>();
|
|
121
124
|
|
|
122
125
|
// We use a queue here so we can abort this long running task properly
|
|
@@ -155,10 +158,16 @@ export class MemberRecordStore {
|
|
|
155
158
|
abort.throwIfAborted();
|
|
156
159
|
}
|
|
157
160
|
});
|
|
161
|
+
|
|
162
|
+
// Create listeners to update data as organizations and platform is updated.
|
|
163
|
+
// Should be checked on every loadAll because the userMode can change for tests.
|
|
164
|
+
this.listen();
|
|
158
165
|
}
|
|
159
166
|
|
|
160
|
-
|
|
167
|
+
async getRecord(id: string): Promise<RecordCacheEntry | null> {
|
|
161
168
|
await this.loadIfNeeded();
|
|
162
169
|
return this.cache.get(id) ?? null;
|
|
163
170
|
}
|
|
164
171
|
}
|
|
172
|
+
|
|
173
|
+
export const MemberRecordStore = new MemberRecordStoreService();
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { Organization} from '@stamhoofd/models';
|
|
2
|
+
import { BalanceItem, BalanceItemPayment, MemberFactory, OrganizationFactory, Payment } from '@stamhoofd/models';
|
|
2
3
|
import { BalanceItemRelation, BalanceItemRelationType, BalanceItemStatus, PaymentMethod, PaymentStatus, ReceivableBalanceType, TranslatedString } from '@stamhoofd/structures';
|
|
3
4
|
import { PaymentReallocationService } from './PaymentReallocationService.js';
|
|
4
5
|
import { BalanceItemService } from './BalanceItemService.js';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { BalanceItem, BalanceItemPayment, CachedBalance, Payment } from '@stamhoofd/models';
|
|
2
2
|
import { SQL } from '@stamhoofd/sql';
|
|
3
|
-
import {
|
|
3
|
+
import type { ReceivableBalanceType } from '@stamhoofd/structures';
|
|
4
|
+
import { BalanceItemStatus, doBalanceItemRelationsMatch, PaymentMethod, PaymentStatus, PaymentType } from '@stamhoofd/structures';
|
|
4
5
|
import { Sorter } from '@stamhoofd/utility';
|
|
5
6
|
import { BalanceItemService } from './BalanceItemService.js';
|
|
6
7
|
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import createMollieClient,
|
|
1
|
+
import { createMollieClient, PaymentMethod as molliePaymentMethod, PaymentStatus as MolliePaymentStatus } from '@mollie/api-client';
|
|
2
2
|
import { SimpleError } from '@simonbackx/simple-errors';
|
|
3
|
-
import { BalanceItem,
|
|
3
|
+
import type { BalanceItem, Member, User } from '@stamhoofd/models';
|
|
4
|
+
import { BalanceItemPayment, Group, MolliePayment, MollieToken, Organization, PayconiqPayment, Payment, sendEmailTemplate } from '@stamhoofd/models';
|
|
4
5
|
import { QueueHandler } from '@stamhoofd/queues';
|
|
5
|
-
import {
|
|
6
|
+
import type { Checkoutable, PaymentConfiguration } from '@stamhoofd/structures';
|
|
7
|
+
import { AuditLogSource, BalanceItemType, EmailTemplateType, PaymentCustomer, PaymentMethod, PaymentMethodHelper, PaymentProvider, PaymentStatus, PaymentType, Recipient, VATExcemptReason, Version } from '@stamhoofd/structures';
|
|
6
8
|
import { Formatter } from '@stamhoofd/utility';
|
|
7
9
|
import { buildReplacementOptions, getEmailReplacementsForPayment } from '../email-replacements/getEmailReplacementsForPayment.js';
|
|
8
10
|
import { BuckarooHelper } from '../helpers/BuckarooHelper.js';
|
|
@@ -403,14 +405,14 @@ export class PaymentService {
|
|
|
403
405
|
if (price > 0 && price > Math.max(balanceItem.priceOpen, balanceItem.priceDue - balanceItem.pricePaid)) {
|
|
404
406
|
throw new SimpleError({
|
|
405
407
|
code: 'invalid_data',
|
|
406
|
-
message: $t(`
|
|
408
|
+
message: $t(`%vv`),
|
|
407
409
|
});
|
|
408
410
|
}
|
|
409
411
|
|
|
410
412
|
if (price < 0 && price < Math.min(balanceItem.priceOpen, balanceItem.priceDue - balanceItem.pricePaid)) {
|
|
411
413
|
throw new SimpleError({
|
|
412
414
|
code: 'invalid_data',
|
|
413
|
-
message: $t(`
|
|
415
|
+
message: $t(`%vw`),
|
|
414
416
|
});
|
|
415
417
|
}
|
|
416
418
|
|
|
@@ -425,7 +427,7 @@ export class PaymentService {
|
|
|
425
427
|
if (!member) {
|
|
426
428
|
throw new SimpleError({
|
|
427
429
|
code: 'invalid_data',
|
|
428
|
-
message: $t(`
|
|
430
|
+
message: $t(`%vx`),
|
|
429
431
|
});
|
|
430
432
|
}
|
|
431
433
|
names.push({
|
|
@@ -440,7 +442,7 @@ export class PaymentService {
|
|
|
440
442
|
// todo: try to make it non-negative by reducing some balance items
|
|
441
443
|
throw new SimpleError({
|
|
442
444
|
code: 'negative_price',
|
|
443
|
-
message: $t(`
|
|
445
|
+
message: $t(`%vl`),
|
|
444
446
|
});
|
|
445
447
|
}
|
|
446
448
|
|
|
@@ -448,7 +450,7 @@ export class PaymentService {
|
|
|
448
450
|
// Changed!
|
|
449
451
|
throw new SimpleError({
|
|
450
452
|
code: 'changed_price',
|
|
451
|
-
message: $t(
|
|
453
|
+
message: $t(`%vk`, { total: Formatter.price(totalPrice) }),
|
|
452
454
|
});
|
|
453
455
|
}
|
|
454
456
|
|
|
@@ -477,7 +479,7 @@ export class PaymentService {
|
|
|
477
479
|
throw new SimpleError({
|
|
478
480
|
code: 'missing_fields',
|
|
479
481
|
message: 'customer is required when paying as an organization',
|
|
480
|
-
human: $t(`
|
|
482
|
+
human: $t(`%vz`),
|
|
481
483
|
});
|
|
482
484
|
}
|
|
483
485
|
|
|
@@ -485,7 +487,7 @@ export class PaymentService {
|
|
|
485
487
|
throw new SimpleError({
|
|
486
488
|
code: 'missing_fields',
|
|
487
489
|
message: 'customer.company is required when paying as an organization',
|
|
488
|
-
human: $t(`
|
|
490
|
+
human: $t(`%w0`),
|
|
489
491
|
});
|
|
490
492
|
}
|
|
491
493
|
|
|
@@ -497,7 +499,7 @@ export class PaymentService {
|
|
|
497
499
|
if (!foundCompany) {
|
|
498
500
|
throw new SimpleError({
|
|
499
501
|
code: 'invalid_data',
|
|
500
|
-
message: $t(`
|
|
502
|
+
message: $t(`%w1`),
|
|
501
503
|
});
|
|
502
504
|
}
|
|
503
505
|
|
|
@@ -545,7 +547,7 @@ export class PaymentService {
|
|
|
545
547
|
throw new SimpleError({
|
|
546
548
|
code: 'missing_fields',
|
|
547
549
|
message: 'redirectUrl or cancelUrl is missing and is required for non-zero online payments',
|
|
548
|
-
human: $t(`
|
|
550
|
+
human: $t(`%vq`),
|
|
549
551
|
});
|
|
550
552
|
}
|
|
551
553
|
|
|
@@ -558,7 +560,7 @@ export class PaymentService {
|
|
|
558
560
|
throw new SimpleError({
|
|
559
561
|
code: 'no_iban',
|
|
560
562
|
message: 'No IBAN',
|
|
561
|
-
human: $t(`
|
|
563
|
+
human: $t(`%w2`),
|
|
562
564
|
});
|
|
563
565
|
}
|
|
564
566
|
|
|
@@ -649,7 +651,7 @@ export class PaymentService {
|
|
|
649
651
|
lineItems: balanceItemPayments,
|
|
650
652
|
organization,
|
|
651
653
|
customer: {
|
|
652
|
-
name: user.name ?? names[0]?.name ?? $t(`
|
|
654
|
+
name: user.name ?? names[0]?.name ?? $t(`%Gr`),
|
|
653
655
|
email: user.email,
|
|
654
656
|
},
|
|
655
657
|
});
|
|
@@ -661,14 +663,14 @@ export class PaymentService {
|
|
|
661
663
|
if (!token) {
|
|
662
664
|
throw new SimpleError({
|
|
663
665
|
code: '',
|
|
664
|
-
message: $t(
|
|
666
|
+
message: $t(`%w3`, { method: PaymentMethodHelper.getName(payment.method) }),
|
|
665
667
|
});
|
|
666
668
|
}
|
|
667
669
|
const profileId = organization.privateMeta.mollieProfile?.id ?? await token.getProfileId(organization.getHost());
|
|
668
670
|
if (!profileId) {
|
|
669
671
|
throw new SimpleError({
|
|
670
672
|
code: '',
|
|
671
|
-
message: $t(
|
|
673
|
+
message: $t(`%w4`, { method: PaymentMethodHelper.getName(payment.method) }),
|
|
672
674
|
});
|
|
673
675
|
}
|
|
674
676
|
const mollieClient = createMollieClient({ accessToken: await token.getAccessToken() });
|
|
@@ -712,7 +714,7 @@ export class PaymentService {
|
|
|
712
714
|
if ((payment.status as any) === PaymentStatus.Failed) {
|
|
713
715
|
throw new SimpleError({
|
|
714
716
|
code: 'payment_failed',
|
|
715
|
-
message: $t(
|
|
717
|
+
message: $t(`%w3`, { method: PaymentMethodHelper.getName(payment.method) }),
|
|
716
718
|
});
|
|
717
719
|
}
|
|
718
720
|
}
|
|
@@ -799,7 +801,7 @@ export class PaymentService {
|
|
|
799
801
|
else if (payment.method === PaymentMethod.Unknown) {
|
|
800
802
|
throw new SimpleError({
|
|
801
803
|
code: 'invalid_data',
|
|
802
|
-
message: $t(`
|
|
804
|
+
message: $t(`%vy`),
|
|
803
805
|
});
|
|
804
806
|
}
|
|
805
807
|
else {
|
|
@@ -812,7 +814,7 @@ export class PaymentService {
|
|
|
812
814
|
if (!allowedPaymentMethods.includes(payment.method)) {
|
|
813
815
|
throw new SimpleError({
|
|
814
816
|
code: 'invalid_payment_method',
|
|
815
|
-
message: $t(`
|
|
817
|
+
message: $t(`%vp`),
|
|
816
818
|
});
|
|
817
819
|
}
|
|
818
820
|
}
|
|
@@ -827,7 +829,7 @@ export class PaymentService {
|
|
|
827
829
|
throw new SimpleError({
|
|
828
830
|
code: 'missing_field',
|
|
829
831
|
message: 'Company address missing',
|
|
830
|
-
human: $t('
|
|
832
|
+
human: $t('%1LH'),
|
|
831
833
|
field: 'customer.company.address',
|
|
832
834
|
});
|
|
833
835
|
}
|
|
@@ -840,7 +842,7 @@ export class PaymentService {
|
|
|
840
842
|
throw new SimpleError({
|
|
841
843
|
code: 'VAT_error',
|
|
842
844
|
message: 'Intra community VAT reverse charge not supported for this purchase',
|
|
843
|
-
human: $t('
|
|
845
|
+
human: $t('%1LI'),
|
|
844
846
|
});
|
|
845
847
|
}
|
|
846
848
|
|
|
@@ -850,7 +852,7 @@ export class PaymentService {
|
|
|
850
852
|
throw new SimpleError({
|
|
851
853
|
code: 'VAT_error',
|
|
852
854
|
message: 'Intra community VAT reverse charge is not supported for this purchase because of missing VAT rates',
|
|
853
|
-
human: $t('
|
|
855
|
+
human: $t('%1LJ'),
|
|
854
856
|
});
|
|
855
857
|
}
|
|
856
858
|
}
|
|
@@ -862,7 +864,7 @@ export class PaymentService {
|
|
|
862
864
|
throw new SimpleError({
|
|
863
865
|
code: 'VAT_error',
|
|
864
866
|
message: 'Unexpected reverse charge applied',
|
|
865
|
-
human: $t('
|
|
867
|
+
human: $t('%1LK'),
|
|
866
868
|
});
|
|
867
869
|
}
|
|
868
870
|
|
|
@@ -870,7 +872,7 @@ export class PaymentService {
|
|
|
870
872
|
throw new SimpleError({
|
|
871
873
|
code: 'VAT_error',
|
|
872
874
|
message: 'Missing VAT percentage',
|
|
873
|
-
human: $t('
|
|
875
|
+
human: $t('%1LL'),
|
|
874
876
|
});
|
|
875
877
|
}
|
|
876
878
|
}
|
|
@@ -885,7 +887,7 @@ export class PaymentService {
|
|
|
885
887
|
throw new SimpleError({
|
|
886
888
|
code: 'VAT_error',
|
|
887
889
|
message: 'Unexpected reverse charge applied',
|
|
888
|
-
human: $t('
|
|
890
|
+
human: $t('%1LK'),
|
|
889
891
|
});
|
|
890
892
|
}
|
|
891
893
|
|
|
@@ -894,7 +896,7 @@ export class PaymentService {
|
|
|
894
896
|
throw new SimpleError({
|
|
895
897
|
code: 'VAT_error',
|
|
896
898
|
message: 'Missing VAT percentage',
|
|
897
|
-
human: $t('
|
|
899
|
+
human: $t('%1LL'),
|
|
898
900
|
});
|
|
899
901
|
}
|
|
900
902
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ManyToOneRelation } from '@simonbackx/simple-database';
|
|
2
|
-
import { BalanceItem, Document, Group, Member, Registration } from '@stamhoofd/models';
|
|
3
|
-
import { AppliedRegistrationDiscount, AuditLogSource, BalanceItemRelationType, BalanceItemStatus, BalanceItemType, EmailTemplateType, StockReservation, TranslatedString, Version } from '@stamhoofd/structures';
|
|
2
|
+
import { BalanceItem, Document, Group, Member, Organization, Registration, sendEmailTemplate } from '@stamhoofd/models';
|
|
3
|
+
import { AppliedRegistrationDiscount, AuditLogSource, BalanceItemRelationType, BalanceItemStatus, BalanceItemType, EmailTemplateType, Recipient, Replacement, StockReservation, TranslatedString, Version } from '@stamhoofd/structures';
|
|
4
4
|
import { AuditLogService } from './AuditLogService.js';
|
|
5
5
|
import { GroupService } from './GroupService.js';
|
|
6
6
|
import { PlatformMembershipService } from './PlatformMembershipService.js';
|
|
@@ -58,7 +58,7 @@ export const RegistrationService = {
|
|
|
58
58
|
await PlatformMembershipService.updateMembershipsForId(registration.memberId);
|
|
59
59
|
|
|
60
60
|
if (registration.sendConfirmationEmail) {
|
|
61
|
-
await
|
|
61
|
+
await RegistrationService.sendEmailTemplate(registration, {
|
|
62
62
|
type: EmailTemplateType.RegistrationConfirmation,
|
|
63
63
|
});
|
|
64
64
|
}
|
|
@@ -76,6 +76,68 @@ export const RegistrationService = {
|
|
|
76
76
|
return true;
|
|
77
77
|
},
|
|
78
78
|
|
|
79
|
+
async getRecipients(registration: Registration, organization: Organization, group: Group) {
|
|
80
|
+
const member = await Member.getByIdWithUsers(registration.memberId);
|
|
81
|
+
|
|
82
|
+
if (!member) {
|
|
83
|
+
return [];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const allowedEmails = member.details.getNotificationEmails();
|
|
87
|
+
|
|
88
|
+
return member.users.map(user => Recipient.create({
|
|
89
|
+
firstName: user.firstName,
|
|
90
|
+
lastName: user.lastName,
|
|
91
|
+
email: user.email,
|
|
92
|
+
userId: user.id,
|
|
93
|
+
replacements: [
|
|
94
|
+
Replacement.create({
|
|
95
|
+
token: 'firstNameMember',
|
|
96
|
+
value: member.details.firstName,
|
|
97
|
+
}),
|
|
98
|
+
Replacement.create({
|
|
99
|
+
token: 'lastNameMember',
|
|
100
|
+
value: member.details.lastName,
|
|
101
|
+
}),
|
|
102
|
+
Replacement.create({
|
|
103
|
+
token: 'registerUrl',
|
|
104
|
+
value: 'https://' + organization.getHost(),
|
|
105
|
+
}),
|
|
106
|
+
Replacement.create({
|
|
107
|
+
token: 'groupName',
|
|
108
|
+
value: group.settings.name.toString(),
|
|
109
|
+
}),
|
|
110
|
+
],
|
|
111
|
+
})).filter(r => allowedEmails.includes(r.email.toLocaleLowerCase()));
|
|
112
|
+
},
|
|
113
|
+
|
|
114
|
+
async sendEmailTemplate(registration: Registration, data: {
|
|
115
|
+
type: EmailTemplateType;
|
|
116
|
+
}) {
|
|
117
|
+
const group = await Group.getByID(registration.groupId);
|
|
118
|
+
|
|
119
|
+
if (!group) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const organization = await Organization.getByID(group.organizationId);
|
|
124
|
+
if (!organization) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const recipients = await RegistrationService.getRecipients(registration, organization, group);
|
|
129
|
+
|
|
130
|
+
// Create e-mail builder
|
|
131
|
+
await sendEmailTemplate(organization, {
|
|
132
|
+
template: {
|
|
133
|
+
type: data.type,
|
|
134
|
+
group,
|
|
135
|
+
},
|
|
136
|
+
recipients,
|
|
137
|
+
type: 'transactional',
|
|
138
|
+
});
|
|
139
|
+
},
|
|
140
|
+
|
|
79
141
|
async updateDiscounts(registrationId: string) {
|
|
80
142
|
await AuditLogService.setContext({ source: AuditLogSource.System }, async () => {
|
|
81
143
|
await QueueHandler.schedule('registration-discounts-update-' + registrationId, async function (this: undefined) {
|