@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.
- package/output-2.txt +1 -0
- package/output.txt +1 -0
- package/package.json +69 -52
- package/src/audit-logs/EventNotificationLogger.ts +40 -0
- package/src/audit-logs/ModelLogger.ts +19 -15
- package/src/audit-logs/OrganizationLogger.ts +1 -1
- package/src/audit-logs/RegistrationInvitationLogger.ts +24 -24
- package/src/audit-logs/init.ts +8 -2
- package/src/boot.ts +19 -18
- package/src/crons/amazon-ses.ts +13 -26
- package/src/crons/balance-emails.ts +3 -5
- package/src/crons/clearExcelCache.test.ts +1 -1
- package/src/crons/clearExcelCache.ts +1 -2
- package/src/crons/drip-emails.ts +42 -0
- package/src/crons/endFunctionsOfUsersWithoutRegistration.ts +4 -0
- package/src/crons/helpers/isOutside.ts +11 -0
- package/src/crons/helpers/useSavedIterator.ts +32 -0
- package/src/crons/index.ts +5 -0
- package/src/crons/invoices.ts +32 -38
- package/src/crons/members-fees.ts +50 -0
- package/src/crons/mollie-chargebacks.ts +14 -15
- package/src/crons/service-fees.ts +152 -0
- package/src/crons/stripe-invoices.ts +48 -0
- package/src/crons/transfer-fees.ts +176 -0
- package/src/crons/update-cached-balances.ts +4 -4
- package/src/crons.ts +7 -64
- package/src/debug.ts +4 -2
- package/src/email-recipient-loaders/documents.ts +1 -1
- package/src/email-recipient-loaders/members.ts +1 -1
- package/src/email-recipient-loaders/payments.ts +4 -6
- package/src/email-recipient-loaders/registrations.ts +1 -1
- package/src/email-replacements/getEmailReplacementsForPayment.ts +5 -9
- package/src/endpoints/admin/members/ChargeMembersEndpoint.ts +1 -1
- package/src/endpoints/admin/memberships/ChargeMembershipsEndpoint.ts +1 -1
- package/src/endpoints/admin/memberships/GetChargeMembershipsSummaryEndpoint.ts +3 -5
- package/src/endpoints/admin/organizations/ChargeOrganizationsEndpoint.ts +1 -1
- package/src/endpoints/admin/organizations/GetOrganizationsCountEndpoint.ts +1 -1
- package/src/endpoints/admin/organizations/GetOrganizationsEndpoint.ts +13 -7
- package/src/endpoints/admin/organizations/PatchOrganizationsEndpoint.ts +4 -6
- package/src/endpoints/admin/organizations/PatchPackagesEndpoint.test.ts +10 -6
- package/src/endpoints/admin/organizations/PatchPackagesEndpoint.ts +39 -21
- package/src/endpoints/admin/registrations/ChargeRegistrationsEndpoint.ts +1 -1
- package/src/endpoints/auth/CreateAdminEndpoint.ts +23 -5
- package/src/endpoints/auth/CreateTokenEndpoint.ts +2 -2
- package/src/endpoints/auth/DeleteTokenEndpoint.ts +1 -1
- package/src/endpoints/auth/DeleteUserEndpoint.ts +3 -3
- package/src/endpoints/auth/ForgotPasswordEndpoint.ts +1 -1
- package/src/endpoints/auth/GetOtherUserEndpoint.ts +1 -1
- package/src/endpoints/auth/GetUserEndpoint.ts +1 -1
- package/src/endpoints/auth/OpenIDConnectAuthTokenEndpoint.ts +1 -1
- package/src/endpoints/auth/OpenIDConnectStartEndpoint.ts +1 -1
- package/src/endpoints/auth/PatchUserEndpoint.ts +5 -8
- package/src/endpoints/auth/PollEmailVerificationEndpoint.ts +1 -1
- package/src/endpoints/auth/RetryEmailVerificationEndpoint.ts +1 -1
- package/src/endpoints/auth/SignupEndpoint.ts +2 -3
- package/src/endpoints/auth/VerifyEmailEndpoint.ts +20 -3
- package/src/endpoints/frontend/FrontendEnvironmentEndpoint.ts +2 -1
- package/src/endpoints/global/addresses/SearchRegionsEndpoint.ts +2 -4
- package/src/endpoints/global/addresses/ValidateAddressEndpoint.ts +1 -1
- package/src/endpoints/global/audit-logs/GetAuditLogsEndpoint.ts +5 -7
- package/src/endpoints/global/caddy/CheckDomainCertEndpoint.ts +2 -2
- package/src/endpoints/global/email/CreateEmailEndpoint.ts +3 -4
- package/src/endpoints/global/email/GetAdminEmailsEndpoint.test.ts +1 -1
- package/src/endpoints/global/email/GetAdminEmailsEndpoint.ts +1 -2
- package/src/endpoints/global/email/GetEmailAddressEndpoint.ts +4 -6
- package/src/endpoints/global/email/GetEmailEndpoint.ts +1 -1
- package/src/endpoints/global/email/GetUserEmailsEndpoint.test.ts +1 -1
- package/src/endpoints/global/email/GetUserEmailsEndpoint.ts +1 -1
- package/src/endpoints/global/email/ManageEmailAddressEndpoint.ts +6 -10
- package/src/endpoints/global/email/PatchEmailEndpoint.test.ts +4 -7
- package/src/endpoints/global/email/PatchEmailEndpoint.ts +6 -9
- package/src/endpoints/global/email-recipients/GetEmailRecipientsCountEndpoint.ts +1 -1
- package/src/endpoints/global/email-recipients/GetEmailRecipientsEndpoint.test.ts +1 -1
- package/src/endpoints/global/email-recipients/GetEmailRecipientsEndpoint.ts +1 -1
- package/src/endpoints/global/email-recipients/RetryEmailRecipientEndpoint.ts +2 -2
- package/src/endpoints/global/events/GetEventNotificationsCountEndpoint.ts +1 -1
- package/src/endpoints/global/events/GetEventNotificationsEndpoint.ts +3 -3
- package/src/endpoints/global/events/GetEventsEndpoint.ts +3 -3
- package/src/endpoints/global/events/PatchEventNotificationsEndpoint.test.ts +49 -4
- package/src/endpoints/global/events/PatchEventNotificationsEndpoint.ts +5 -8
- package/src/endpoints/global/events/PatchEventsEndpoint.test.ts +12 -44
- package/src/endpoints/global/events/PatchEventsEndpoint.ts +128 -127
- package/src/endpoints/global/files/ExportToExcelEndpoint.ts +9 -9
- package/src/endpoints/global/files/GetFileCache.ts +3 -4
- package/src/endpoints/global/files/UploadFile.ts +3 -4
- package/src/endpoints/global/files/UploadImage.ts +3 -4
- package/src/endpoints/global/groups/GetGroupsCountEndpoint.ts +1 -1
- package/src/endpoints/global/groups/GetGroupsEndpoint.test.ts +1 -1
- package/src/endpoints/global/groups/GetGroupsEndpoint.ts +4 -2
- package/src/endpoints/global/members/GetMemberFamilyEndpoint.ts +2 -3
- package/src/endpoints/global/members/GetMembersCountEndpoint.ts +1 -1
- package/src/endpoints/global/members/GetMembersEndpoint.test.ts +2 -2
- package/src/endpoints/global/members/GetMembersEndpoint.ts +10 -12
- package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.test.ts +195 -12
- package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.ts +16 -22
- package/src/endpoints/global/members/helpers/validateGroupFilter.ts +6 -30
- package/src/endpoints/global/members/shouldCheckIfMemberIsDuplicate.ts +1 -1
- package/src/endpoints/global/organizations/CheckRegisterCodeEndpoint.ts +1 -1
- package/src/endpoints/global/organizations/CreateOrganizationEndpoint.ts +40 -8
- package/src/endpoints/global/organizations/GetOrganizationFromDomainEndpoint.ts +2 -2
- package/src/endpoints/global/organizations/GetOrganizationFromUriEndpoint.ts +2 -2
- package/src/endpoints/global/organizations/SearchOrganizationEndpoint.test.ts +4 -1
- package/src/endpoints/global/organizations/SearchOrganizationEndpoint.ts +4 -5
- package/src/endpoints/global/payments/StripeWebhookEndpoint.ts +9 -16
- package/src/endpoints/global/platform/GetPlatformAdminsEndpoint.ts +1 -1
- package/src/endpoints/global/platform/GetPlatformEndpoint.ts +1 -1
- package/src/endpoints/global/platform/PatchPlatformEnpoint.test.ts +1 -1
- package/src/endpoints/global/platform/PatchPlatformEnpoint.ts +11 -11
- package/src/endpoints/global/platform-memberships/GetPlatformMembershipsCountEndpoint.ts +31 -31
- package/src/endpoints/global/platform-memberships/GetPlatformMembershipsEndpoint.ts +18 -20
- package/src/endpoints/global/registration/GetRegistrationsCountEndpoint.ts +1 -1
- package/src/endpoints/global/registration/GetRegistrationsEndpoint.test.ts +1 -1
- package/src/endpoints/global/registration/GetRegistrationsEndpoint.ts +6 -10
- package/src/endpoints/global/registration/GetUserDetailedPayableBalanceEndpoint.ts +35 -6
- package/src/endpoints/global/registration/GetUserDocumentsEndpoint.ts +2 -2
- package/src/endpoints/global/registration/GetUserMembersEndpoint.ts +1 -1
- package/src/endpoints/global/registration/GetUserPayableBalanceEndpoint.ts +1 -1
- package/src/endpoints/global/registration/PatchUserMembersEndpoint.test.ts +2 -2
- package/src/endpoints/global/registration/PatchUserMembersEndpoint.ts +3 -3
- package/src/endpoints/global/registration/RegisterMembersEndpoint.test.ts +90 -6
- package/src/endpoints/global/registration/RegisterMembersEndpoint.ts +35 -34
- package/src/endpoints/global/registration-invitations/GetRegistrationInvitationsCountEndpoint.ts +1 -1
- package/src/endpoints/global/registration-invitations/GetRegistrationInvitationsEndpoint.test.ts +62 -63
- package/src/endpoints/global/registration-invitations/GetRegistrationInvitationsEndpoint.ts +6 -9
- package/src/endpoints/global/registration-invitations/PatchRegistrationInvitationsEndpoint.test.ts +51 -52
- package/src/endpoints/global/registration-invitations/PatchRegistrationInvitationsEndpoint.ts +6 -7
- package/src/endpoints/global/registration-periods/GetRegistrationPeriodsCountEndpoint.ts +43 -0
- package/src/endpoints/global/registration-periods/GetRegistrationPeriodsEndpoint.ts +1 -1
- package/src/endpoints/global/registration-periods/PatchRegistrationPeriodsEndpoint.ts +13 -5
- package/src/endpoints/global/sso/GetSSOEndpoint.ts +2 -3
- package/src/endpoints/global/sso/SetSSOEndpoint.ts +1 -1
- package/src/endpoints/global/webshops/GetWebshopFromDomainEndpoint.ts +2 -2
- package/src/endpoints/global/webshops/GetWebshopsEndpoint.test.ts +1 -2
- package/src/endpoints/global/webshops/GetWebshopsEndpoint.ts +2 -4
- package/src/endpoints/organization/dashboard/balance-items/GetBalanceItemEndpoint.ts +2 -2
- package/src/endpoints/organization/dashboard/balance-items/GetBalanceItemsCountEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/balance-items/GetBalanceItemsEndpoint.ts +3 -4
- package/src/endpoints/organization/dashboard/balance-items/PatchBalanceItemsEndpoint.ts +7 -9
- package/src/endpoints/organization/dashboard/billing/ApplyRegisterCodeEndpoint.test.ts +73 -0
- package/src/endpoints/organization/dashboard/billing/ApplyRegisterCodeEndpoint.ts +89 -0
- package/src/endpoints/organization/dashboard/billing/DeactivatePackageEndpoint.ts +1 -5
- package/src/endpoints/organization/dashboard/billing/DeleteOrganizationMandateEndpoint.ts +11 -11
- package/src/endpoints/organization/dashboard/billing/GetOrganizationDetailedPayableBalanceCollectionEndpoint.ts +2 -2
- package/src/endpoints/organization/dashboard/billing/GetOrganizationDetailedPayableBalanceEndpoint.ts +8 -8
- package/src/endpoints/organization/dashboard/billing/GetOrganizationMandatesEndpoint.ts +9 -9
- package/src/endpoints/organization/dashboard/billing/GetOrganizationPayableBalanceEndpoint.ts +2 -2
- package/src/endpoints/organization/dashboard/billing/GetOrganizationPayableInvoicesEndpoint.ts +68 -0
- package/src/endpoints/organization/dashboard/billing/GetPackagesEndpoint.ts +4 -4
- package/src/endpoints/organization/dashboard/billing/GetRegisterCodeEndpoint.ts +66 -0
- package/src/endpoints/organization/dashboard/billing/OrganizationCheckoutEndpoint.test.ts +949 -0
- package/src/endpoints/organization/dashboard/billing/OrganizationCheckoutEndpoint.ts +60 -57
- package/src/endpoints/organization/dashboard/billing/PatchOrganizationMandatesEndpoint.ts +20 -20
- package/src/endpoints/organization/dashboard/documents/GetDocumentTemplateXML.ts +1 -1
- package/src/endpoints/organization/dashboard/documents/GetDocumentTemplatesCountEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/documents/GetDocumentTemplatesEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/documents/GetDocumentsCountEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/documents/GetDocumentsEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/documents/PatchDocumentEndpoint.ts +10 -2
- package/src/endpoints/organization/dashboard/documents/PatchDocumentTemplatesEndpoint.test.ts +2 -2
- package/src/endpoints/organization/dashboard/documents/PatchDocumentTemplatesEndpoint.ts +2 -2
- package/src/endpoints/organization/dashboard/email/CheckEmailBouncesEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/email-templates/GetEmailTemplatesEndpoint.test.ts +1 -1
- package/src/endpoints/organization/dashboard/email-templates/GetEmailTemplatesEndpoint.ts +10 -8
- package/src/endpoints/organization/dashboard/email-templates/PatchEmailTemplatesEndpoint.test.ts +1 -1
- package/src/endpoints/organization/dashboard/email-templates/PatchEmailTemplatesEndpoint.ts +5 -6
- package/src/endpoints/organization/dashboard/invoices/GetInvoicesCountEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/invoices/GetInvoicesEndpoint.ts +10 -6
- package/src/endpoints/organization/dashboard/invoices/PatchInvoicesEndpoint.ts +11 -2
- package/src/endpoints/organization/dashboard/mollie/CheckMollieEndpoint.ts +4 -5
- package/src/endpoints/organization/dashboard/mollie/ConnectMollieEndpoint.ts +5 -5
- package/src/endpoints/organization/dashboard/mollie/DisconnectMollieEndpoint.ts +2 -2
- package/src/endpoints/organization/dashboard/mollie/GetMollieDashboardEndpoint.ts +7 -7
- package/src/endpoints/organization/dashboard/nolt/CreateNoltTokenEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/organization/GetOrganizationArchivedGroups.ts +2 -2
- package/src/endpoints/organization/dashboard/organization/GetOrganizationDeletedGroups.ts +1 -1
- package/src/endpoints/organization/dashboard/organization/GetUitpasClientIdEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.test.ts +2 -2
- package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.ts +50 -12
- package/src/endpoints/organization/dashboard/organization/SearchUitpasOrganizersEndpoint.ts +2 -2
- package/src/endpoints/organization/dashboard/organization/SetOrganizationDomainEndpoint.ts +5 -10
- package/src/endpoints/organization/dashboard/organization/SetUitpasClientCredentialsEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/payments/GetPaymentsCountEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/payments/GetPaymentsEndpoint.ts +3 -4
- package/src/endpoints/organization/dashboard/payments/PatchPaymentsEndpoint.ts +21 -14
- package/src/endpoints/organization/dashboard/receivable-balances/ChargeReceivableBalancesEndpoint.ts +35 -28
- package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalanceEndpoint.ts +2 -3
- package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalancesCountEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalancesEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/registration-periods/GetOrganizationRegistrationPeriodsEndpoint.test.ts +1 -1
- package/src/endpoints/organization/dashboard/registration-periods/GetOrganizationRegistrationPeriodsEndpoint.ts +2 -3
- package/src/endpoints/organization/dashboard/registration-periods/MoveRegistrationPeriods.test.ts +1 -1
- package/src/endpoints/organization/dashboard/registration-periods/PatchOrganizationRegistrationPeriodsEndpoint.test.ts +1 -1
- package/src/endpoints/organization/dashboard/registration-periods/PatchOrganizationRegistrationPeriodsEndpoint.ts +19 -18
- package/src/endpoints/organization/dashboard/registration-periods/SetupStepReviewEndpoint.ts +4 -5
- package/src/endpoints/organization/dashboard/stripe/ConnectStripeEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/stripe/DeleteStripeAccountEndpoint.ts +2 -3
- package/src/endpoints/organization/dashboard/stripe/GetStripeAccountLinkEndpoint.ts +2 -2
- package/src/endpoints/organization/dashboard/stripe/GetStripeAccountsEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/stripe/GetStripeLoginLinkEndpoint.ts +2 -2
- package/src/endpoints/organization/dashboard/stripe/UpdateStripeAccountEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/users/CreateApiUserEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/users/DeleteUserEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/users/GetApiUsersEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/users/GetOrganizationAdminsEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/users/PatchApiUserEndpoint.ts +4 -6
- package/src/endpoints/organization/dashboard/webshops/CreateWebshopEndpoint.ts +10 -15
- package/src/endpoints/organization/dashboard/webshops/DeleteWebshopEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/webshops/GetDiscountCodesEndpoint.ts +2 -2
- package/src/endpoints/organization/dashboard/webshops/GetWebshopOrdersCountEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/webshops/GetWebshopOrdersEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/webshops/GetWebshopTicketsEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/webshops/GetWebshopUriAvailabilityEndpoint.ts +11 -2
- package/src/endpoints/organization/dashboard/webshops/PatchDiscountCodesEndpoint.ts +4 -6
- package/src/endpoints/organization/dashboard/webshops/PatchWebshopEndpoint.ts +22 -7
- package/src/endpoints/organization/dashboard/webshops/PatchWebshopOrdersEndpoint.ts +20 -27
- package/src/endpoints/organization/dashboard/webshops/PatchWebshopTicketsEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/webshops/SearchUitpasEventsEndpoint.ts +2 -2
- package/src/endpoints/organization/dashboard/webshops/VerifyWebshopDomainEndpoint.ts +2 -3
- package/src/endpoints/organization/dashboard/webshops/WebshopReservedPathSegments.test.ts +95 -0
- package/src/endpoints/organization/shared/ExchangePaymentEndpoint.ts +2 -2
- package/src/endpoints/organization/shared/GetDocumentHtml.ts +1 -1
- package/src/endpoints/organization/shared/GetPaymentEndpoint.ts +1 -1
- package/src/endpoints/organization/shared/GetUitpasNumberDetailsEndpoint.ts +3 -5
- package/src/endpoints/organization/shared/auth/GetOrganizationEndpoint.ts +1 -1
- package/src/endpoints/organization/webshops/CheckWebshopDiscountCodesEndpoint.ts +4 -1
- package/src/endpoints/organization/webshops/GetOrderByPaymentEndpoint.ts +14 -3
- package/src/endpoints/organization/webshops/GetOrderEndpoint.ts +14 -2
- package/src/endpoints/organization/webshops/GetTicketsEndpoint.ts +37 -16
- package/src/endpoints/organization/webshops/GetWebshopEndpoint.test.ts +34 -2
- package/src/endpoints/organization/webshops/GetWebshopEndpoint.ts +4 -2
- package/src/endpoints/organization/webshops/PlaceOrderEndpoint.test.ts +74 -3
- package/src/endpoints/organization/webshops/PlaceOrderEndpoint.ts +16 -33
- package/src/endpoints/organization/webshops/RetrieveUitpasSocialTariffPriceEndpoint.ts +3 -5
- package/src/endpoints/organization/webshops/WebshopAuthHelper.ts +36 -0
- package/src/endpoints/system/HealthEndpoint.ts +1 -1
- package/src/excel-loaders/balance-items.ts +1 -1
- package/src/excel-loaders/event-notifications.ts +1 -1
- package/src/excel-loaders/members.ts +1 -1
- package/src/excel-loaders/organizations.ts +3 -3
- package/src/excel-loaders/payments.ts +31 -1
- package/src/excel-loaders/platform-memberships.ts +13 -14
- package/src/excel-loaders/receivable-balances.ts +2 -2
- package/src/excel-loaders/registrations.ts +2 -3
- package/src/helpers/AddressValidator.ts +7 -14
- package/src/helpers/AdminPermissionChecker.ts +50 -63
- package/src/helpers/AuthenticatedStructures.ts +69 -55
- package/src/helpers/BalanceItemRelationsBackfiller.test.ts +174 -0
- package/src/helpers/BalanceItemRelationsBackfiller.ts +163 -0
- package/src/helpers/BuckarooHelper.ts +2 -4
- package/src/helpers/CheckSettlements.ts +12 -24
- package/src/helpers/Context.ts +15 -10
- package/src/helpers/CookieHelper.ts +1 -2
- package/src/helpers/EmailResumer.ts +1 -2
- package/src/helpers/FileCache.ts +2 -3
- package/src/helpers/FinancialSupportHelper.ts +2 -2
- package/src/helpers/FlagMomentCleanup.ts +1 -2
- package/src/helpers/ForwardHandler.ts +5 -10
- package/src/helpers/GlobalHelper.ts +3 -3
- package/src/helpers/LegacyBillingConverter.ts +787 -0
- package/src/helpers/MemberMerger.test.ts +782 -0
- package/src/helpers/MemberMerger.ts +600 -0
- package/src/helpers/MemberUserSyncer.ts +6 -12
- package/src/helpers/MembershipCharger.ts +2 -4
- package/src/helpers/PaymentCustomerResolver.test.ts +203 -0
- package/src/helpers/PaymentCustomerResolver.ts +144 -0
- package/src/helpers/PeriodHelper.ts +2 -3
- package/src/helpers/RecordAnswerHelper.test.ts +105 -110
- package/src/helpers/RecordAnswerHelper.ts +7 -7
- package/src/helpers/SeedTools.ts +106 -0
- package/src/helpers/ServiceFeeHelper.ts +125 -15
- package/src/helpers/SetupStepUpdater.ts +38 -32
- package/src/helpers/StamhoofdFilterAccessHelper.ts +52 -0
- package/src/helpers/StripeHelper.ts +14 -36
- package/src/helpers/StripeInvoicer.ts +419 -0
- package/src/helpers/StripePayoutChecker.ts +5 -10
- package/src/helpers/TagHelper.ts +7 -8
- package/src/helpers/TemporaryMemberAccess.ts +1 -2
- package/src/helpers/ThrottledQueue.ts +1 -2
- package/src/helpers/UitpasTokenRepository.ts +1 -2
- package/src/helpers/ViesHelper.ts +7 -11
- package/src/helpers/XlsxTransformerColumnHelper.ts +1 -1
- package/src/helpers/outstandingBalanceJoin.ts +2 -2
- package/src/helpers/updateMemberDetailsUitpasNumber.ts +3 -5
- package/src/migrate.ts +12 -5
- package/src/{seeds → migrations}/0000000004-single-organization.ts +10 -1
- package/src/migrations/0000000006-default-organization.ts +139 -0
- package/src/{seeds → migrations}/1715028563-user-permissions.ts +17 -27
- package/src/{seeds/1765896674-document-update-year.test.ts → migrations/1750090029-document-update-year.test.ts} +27 -26
- package/src/migrations/1750090029-document-update-year.ts +103 -0
- package/src/{seeds → migrations}/1750090030-records-configuration.ts +33 -32
- package/src/migrations/1750090031-records-configuration-webshops.ts +36 -0
- package/src/migrations/1752848540-national-numbers.ts +585 -0
- package/src/migrations/1752848550-records-configuration-group-filter.ts +1064 -0
- package/src/{seeds → migrations}/1752848561-groups-registration-periods.ts +70 -26
- package/src/{seeds → migrations}/1754560914-groups-prices.test.ts +1 -1
- package/src/{seeds → migrations}/1754560914-groups-prices.ts +9 -15
- package/src/{seeds → migrations}/1756293699-fill-previous-next-period-id.ts +1 -2
- package/src/migrations/1761665607-sync-member-users.ts +40 -0
- package/src/migrations/1779121240-invoice-email-template.sql +6 -0
- package/src/migrations/1779986893-default-payment-failed-email-templates.sql +4 -0
- package/src/migrations/1780578166-convert-legacy-billing.ts +13 -0
- package/src/{seeds/1755876819-remove-duplicate-members.ts → migrations/1780665426-remove-duplicate-members.ts} +23 -4
- package/src/migrations/1780933598-document-groups.ts +88 -0
- package/src/migrations/1781692342-balance-item-relations.ts +13 -0
- package/src/migrations/1781857866-platform-admins.ts +103 -0
- package/src/migrations/1781857867-rm-old-platform-admins.ts +25 -0
- package/src/seeds/0000000001-throw.ts +5 -0
- package/src/seeds/1760702452-update-balance-price-paid.ts +19 -0
- package/src/seeds/1760702453-update-balance-invoiced.ts +19 -0
- package/src/seeds/1760702454-update-cached-outstanding-balance-from-items.ts +51 -14
- package/src/seeds/1773754928-force-save-members.ts +41 -8
- package/src/seeds/1780665427-schedule-stock-updates.ts +45 -0
- package/src/seeds/1780665428-group-update-occupancy.ts +31 -0
- package/src/seeds/1780915001-fill-payment-customer.ts +70 -0
- package/src/seeds/1780915002-update-orders.ts +39 -0
- package/src/seeds/1782047708-organization-company-address.ts +44 -0
- package/src/seeds-temporary/1769088653-uitpas-status.ts +1 -2
- package/src/seeds-temporary/1780416000-migrate-audit-log-legacy-enums.test.ts +69 -0
- package/src/seeds-temporary/1780416000-migrate-audit-log-legacy-enums.ts +85 -0
- package/src/services/AuditLogService.test.ts +51 -0
- package/src/services/AuditLogService.ts +45 -0
- package/src/services/BalanceItemService.ts +141 -44
- package/src/services/CpuService.ts +3 -6
- package/src/services/DatabaseCollationService.test.ts +1 -2
- package/src/services/DocumentService.ts +1 -2
- package/src/services/EventNotificationService.ts +1 -1
- package/src/services/FileSignService.ts +2 -4
- package/src/services/InvoicePdfService.ts +286 -0
- package/src/services/InvoiceService.ts +204 -251
- package/src/services/InvoiceXMLService.ts +424 -0
- package/src/services/MemberNumberService.ts +6 -11
- package/src/services/MemberRecordStore.ts +8 -10
- package/src/services/MollieService.ts +114 -121
- package/src/services/PaymentMandateService.ts +45 -45
- package/src/services/PaymentReallocationService.test.ts +1 -1
- package/src/services/PaymentReallocationService.ts +7 -9
- package/src/services/PaymentService.ts +444 -308
- package/src/services/PlatformMembershipService.ts +4 -8
- package/src/services/ReferralService.ts +223 -0
- package/src/services/RegistrationService.ts +63 -53
- package/src/services/SSOService.test.ts +119 -0
- package/src/services/SSOService.ts +56 -49
- package/src/services/STPackageService.ts +97 -61
- package/src/services/UniqueMemberNumberService.ts +69 -0
- package/src/services/UniqueUserService.ts +3 -6
- package/src/services/VATService.ts +85 -0
- package/src/services/uitpas/PassholderEndpoints.ts +3 -6
- package/src/services/uitpas/UitpasService.ts +6 -10
- package/src/services/uitpas/checkUitpasNumbers.ts +2 -4
- package/src/services/uitpas/getSocialTariffForUitpasNumbers.ts +3 -6
- package/src/services/uitpas/searchUitpasEvents.ts +1 -2
- package/src/sql-filters/audit-logs.ts +1 -1
- package/src/sql-filters/balance-item-payments.ts +1 -1
- package/src/sql-filters/balance-items.ts +1 -1
- package/src/sql-filters/base-registration-filter-compilers.ts +5 -33
- package/src/sql-filters/document-templates.ts +1 -1
- package/src/sql-filters/documents.ts +1 -1
- package/src/sql-filters/email-recipients.ts +1 -1
- package/src/sql-filters/emails.ts +1 -1
- package/src/sql-filters/event-notifications.ts +1 -1
- package/src/sql-filters/events.ts +6 -1
- package/src/sql-filters/groups.ts +5 -0
- package/src/sql-filters/invoiced-balance-items.ts +1 -1
- package/src/sql-filters/invoices.ts +1 -1
- package/src/sql-filters/member-responsibility-records.ts +1 -1
- package/src/sql-filters/members.ts +1 -1
- package/src/sql-filters/orders.ts +4 -4
- package/src/sql-filters/organization-registration-periods.ts +1 -1
- package/src/sql-filters/organizations.ts +1 -1
- package/src/sql-filters/platform-memberships.ts +3 -3
- package/src/sql-filters/receivable-balances.ts +1 -1
- package/src/sql-filters/registration-periods.ts +1 -1
- package/src/sql-filters/registrations.ts +1 -1
- package/src/sql-filters/tickets.ts +1 -1
- package/src/sql-filters/users.ts +1 -1
- package/src/sql-sorters/groups.ts +23 -0
- package/src/sql-sorters/platform-memberships.ts +16 -16
- package/src/sql-sorters/registration-invitations.ts +2 -2
- package/tests/actions/patchOrganizationMember.ts +1 -1
- package/tests/actions/patchUserMember.ts +1 -1
- package/tests/assertions/assertBalances.ts +6 -12
- package/tests/e2e/api-rate-limits.test.ts +12 -24
- package/tests/e2e/bundle-discounts.test.ts +4 -1
- package/tests/e2e/charge-members.test.ts +13 -11
- package/tests/e2e/documents.test.ts +4 -1
- package/tests/e2e/register.test.ts +7 -9
- package/tests/e2e/stock.test.ts +4 -3
- package/tests/e2e/tickets.test.ts +1 -1
- package/tests/helpers/MollieMocker.ts +462 -0
- package/tests/helpers/PayconiqMocker.ts +138 -45
- package/tests/helpers/StripeMocker.ts +9 -6
- package/tests/helpers/index.ts +4 -0
- package/tests/init/initAdmin.ts +2 -2
- package/tests/init/initBundleDiscount.ts +1 -1
- package/tests/init/initMembershipOrganization.ts +13 -0
- package/tests/init/initPermissionRole.ts +3 -4
- package/tests/vitest.global.setup.ts +1 -1
- package/vitest.config.js +6 -0
- package/.nvmrc +0 -1
- package/src/helpers/GroupBuilder.ts +0 -418
- package/src/seeds/0000000000-example.ts +0 -11
- package/src/seeds/1722256498-group-update-occupancy.ts +0 -52
- package/src/seeds/1726572303-schedule-stock-updates.ts +0 -52
- package/src/seeds/1726847064-setup-steps.ts +0 -16
- package/src/seeds/1728928974-update-cached-outstanding-balance-from-items.ts +0 -31
- package/src/seeds/1729253172-update-orders.ts +0 -21
- package/src/seeds/1733319079-fill-paying-organization-ids.ts +0 -68
- package/src/seeds/1733748412-update-deleted-order-numbers.ts +0 -109
- package/src/seeds/1733994455-balance-item-status-open.ts +0 -30
- package/src/seeds/1740046783-update-membership.ts +0 -17
- package/src/seeds/1741008870-fix-auditlog-description.ts +0 -50
- package/src/seeds/1741011468-fix-auditlog-description-uft16.ts +0 -88
- package/src/seeds/1741268179-fix-group-dates-of-events.ts +0 -32
- package/src/seeds/1751445358-upload-email-attachments.ts +0 -106
- package/src/seeds/1755532883-update-email-sender-ids.ts +0 -47
- package/src/seeds/1755790070-fill-email-recipient-errors.ts +0 -96
- package/src/seeds/1756115432-remove-old-drafts.ts +0 -16
- package/src/seeds/1756115433-fill-email-recipient-organization-id.ts +0 -30
- package/src/seeds/1756303697-update-email-counts.ts +0 -76
- package/src/seeds/1761665607-sync-member-users.ts +0 -59
- package/src/seeds/1765896674-document-update-year.ts +0 -66
- /package/src/{seeds → migrations}/0000000001-development-user.ts +0 -0
- /package/src/{seeds → migrations}/0000000002-clear-stamhoofd-email-templates.ts +0 -0
- /package/src/{seeds → migrations}/0000000003-default-email-templates.ts +0 -0
- /package/src/{seeds → migrations}/1752848561-groups-registration-periods.test.ts +0 -0
- /package/src/{seeds → migrations}/1766150402-document-published-at.test.ts +0 -0
- /package/src/{seeds → migrations}/1766150402-document-published-at.ts +0 -0
- /package/src/{seeds → migrations}/1779121239-default-invoice-email-template.sql +0 -0
- /package/src/{seeds → migrations}/data/default-email-templates.sql +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type { AutoEncoderPatchType, Decoder, PatchableArrayAutoEncoder} from '@simonbackx/simple-encoding';
|
|
1
|
+
import type { AutoEncoderPatchType, Decoder, PatchableArrayAutoEncoder } from '@simonbackx/simple-encoding';
|
|
2
2
|
import { PatchableArrayDecoder, patchObject, StringDecoder } from '@simonbackx/simple-encoding';
|
|
3
|
-
import type { DecodedRequest, Request} from '@simonbackx/simple-endpoints';
|
|
3
|
+
import type { DecodedRequest, Request } from '@simonbackx/simple-endpoints';
|
|
4
4
|
import { Endpoint, Response } from '@simonbackx/simple-endpoints';
|
|
5
5
|
import { Event, Group, OrganizationRegistrationPeriod, Platform, RegistrationPeriod, Webshop } from '@stamhoofd/models';
|
|
6
|
-
import { AuditLogSource, Event as EventStruct, Group as GroupStruct, GroupType, NamedObject, PermissionLevel } from '@stamhoofd/structures';
|
|
6
|
+
import { AuditLogSource, Event as EventStruct, Group as GroupStruct, GroupType, NamedObject, OrganizationEventType, PermissionLevel, PlatformEventType } from '@stamhoofd/structures';
|
|
7
7
|
|
|
8
8
|
import { SimpleError } from '@simonbackx/simple-errors';
|
|
9
9
|
import { SQL, SQLWhereSign } from '@stamhoofd/sql';
|
|
@@ -67,8 +67,7 @@ export class PatchEventsEndpoint extends Endpoint<Params, Query, Body, ResponseB
|
|
|
67
67
|
period,
|
|
68
68
|
{ allowedIds: [putGroup.id] },
|
|
69
69
|
);
|
|
70
|
-
}
|
|
71
|
-
else {
|
|
70
|
+
} else {
|
|
72
71
|
if (group.type !== GroupType.EventRegistration) {
|
|
73
72
|
throw new SimpleError({
|
|
74
73
|
code: 'invalid_group',
|
|
@@ -88,8 +87,7 @@ export class PatchEventsEndpoint extends Endpoint<Params, Query, Body, ResponseB
|
|
|
88
87
|
if (!await Context.auth.hasSomeAccess(organization.id)) {
|
|
89
88
|
throw Context.auth.error();
|
|
90
89
|
}
|
|
91
|
-
}
|
|
92
|
-
else {
|
|
90
|
+
} else {
|
|
93
91
|
if (!Context.auth.hasSomePlatformAccess()) {
|
|
94
92
|
throw Context.auth.error();
|
|
95
93
|
}
|
|
@@ -138,13 +136,16 @@ export class PatchEventsEndpoint extends Endpoint<Params, Query, Body, ResponseB
|
|
|
138
136
|
event.endDate = put.endDate;
|
|
139
137
|
event.typeId = put.typeId;
|
|
140
138
|
|
|
139
|
+
event.meta = put.meta;
|
|
141
140
|
event.meta.organizationCache = eventOrganization ? NamedObject.create({ id: eventOrganization.id, name: eventOrganization.name }) : null;
|
|
141
|
+
|
|
142
|
+
PatchEventsEndpoint.validateOrCorrectEventMeta(event);
|
|
143
|
+
|
|
142
144
|
await PatchEventsEndpoint.checkEventLimits(event);
|
|
143
145
|
|
|
144
146
|
if (put.group) {
|
|
145
147
|
await this.saveEventAndLinkExistingGroup(event, put.group);
|
|
146
|
-
}
|
|
147
|
-
else {
|
|
148
|
+
} else {
|
|
148
149
|
await event.save();
|
|
149
150
|
}
|
|
150
151
|
|
|
@@ -181,40 +182,12 @@ export class PatchEventsEndpoint extends Endpoint<Params, Query, Body, ResponseB
|
|
|
181
182
|
event.organizationId = patch.organizationId;
|
|
182
183
|
}
|
|
183
184
|
|
|
184
|
-
|
|
185
|
-
event.meta.groups = null;
|
|
186
|
-
console.error('Removed groups because organizationId is null for event', event.id);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
if (event.meta.groups && event.meta.groups.length === 0) {
|
|
190
|
-
throw new SimpleError({
|
|
191
|
-
code: 'invalid_field',
|
|
192
|
-
message: 'Empty groups',
|
|
193
|
-
human: $t(`%DV`),
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
if (event.meta.defaultAgeGroupIds && event.meta.defaultAgeGroupIds.length === 0) {
|
|
198
|
-
throw new SimpleError({
|
|
199
|
-
code: 'invalid_field',
|
|
200
|
-
message: 'Empty default age groups',
|
|
201
|
-
human: $t(`%DW`),
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
if (event.meta.organizationTagIds && event.meta.organizationTagIds.length === 0) {
|
|
206
|
-
throw new SimpleError({
|
|
207
|
-
code: 'invalid_field',
|
|
208
|
-
message: 'Empty organization tag ids',
|
|
209
|
-
human: $t(`%DX`),
|
|
210
|
-
});
|
|
211
|
-
}
|
|
185
|
+
PatchEventsEndpoint.validateOrCorrectEventMeta(event);
|
|
212
186
|
|
|
213
187
|
const eventOrganization = await Context.auth.checkEventAccess(event);
|
|
214
188
|
if (eventOrganization) {
|
|
215
189
|
event.meta.organizationCache = NamedObject.create({ id: eventOrganization.id, name: eventOrganization.name });
|
|
216
|
-
}
|
|
217
|
-
else {
|
|
190
|
+
} else {
|
|
218
191
|
event.meta.organizationCache = null;
|
|
219
192
|
}
|
|
220
193
|
|
|
@@ -237,8 +210,7 @@ export class PatchEventsEndpoint extends Endpoint<Params, Query, Body, ResponseB
|
|
|
237
210
|
await PatchOrganizationRegistrationPeriodsEndpoint.deleteGroup(event.groupId);
|
|
238
211
|
event.groupId = null;
|
|
239
212
|
}
|
|
240
|
-
}
|
|
241
|
-
else if (patch.group.isPatch()) {
|
|
213
|
+
} else if (patch.group.isPatch()) {
|
|
242
214
|
if (!event.groupId) {
|
|
243
215
|
throw new SimpleError({
|
|
244
216
|
code: 'invalid_field',
|
|
@@ -251,13 +223,11 @@ export class PatchEventsEndpoint extends Endpoint<Params, Query, Body, ResponseB
|
|
|
251
223
|
|
|
252
224
|
const period = await RegistrationPeriod.getByDate(event.startDate, event.organizationId);
|
|
253
225
|
group = await PatchOrganizationRegistrationPeriodsEndpoint.patchGroup(patch.group, period, { isPatchingEvent: true });
|
|
254
|
-
}
|
|
255
|
-
else {
|
|
226
|
+
} else {
|
|
256
227
|
if (event.groupId === patch.group.id) {
|
|
257
228
|
// ignore: bad practice: puts are not allowed like this
|
|
258
229
|
// risk of deleting data
|
|
259
|
-
}
|
|
260
|
-
else {
|
|
230
|
+
} else {
|
|
261
231
|
if (event.groupId) {
|
|
262
232
|
// need to delete old group first
|
|
263
233
|
await PatchOrganizationRegistrationPeriodsEndpoint.deleteGroup(event.groupId);
|
|
@@ -267,8 +237,7 @@ export class PatchEventsEndpoint extends Endpoint<Params, Query, Body, ResponseB
|
|
|
267
237
|
event.groupId = group.id;
|
|
268
238
|
}
|
|
269
239
|
}
|
|
270
|
-
}
|
|
271
|
-
else {
|
|
240
|
+
} else {
|
|
272
241
|
if (patch.startDate || patch.endDate) {
|
|
273
242
|
// Correct period id if needed
|
|
274
243
|
const period = await RegistrationPeriod.getByDate(event.startDate, event.organizationId);
|
|
@@ -292,8 +261,7 @@ export class PatchEventsEndpoint extends Endpoint<Params, Query, Body, ResponseB
|
|
|
292
261
|
if (group || patch.organizationId !== undefined) {
|
|
293
262
|
if (event.organizationId === null) {
|
|
294
263
|
// No validation required
|
|
295
|
-
}
|
|
296
|
-
else {
|
|
264
|
+
} else {
|
|
297
265
|
// Validate organizationId of group
|
|
298
266
|
if (event.groupId) {
|
|
299
267
|
group = group ?? (await Group.getByID(event.groupId) ?? null);
|
|
@@ -312,8 +280,7 @@ export class PatchEventsEndpoint extends Endpoint<Params, Query, Body, ResponseB
|
|
|
312
280
|
if (patch.webshopId !== undefined) {
|
|
313
281
|
if (patch.webshopId === null) {
|
|
314
282
|
event.webshopId = null;
|
|
315
|
-
}
|
|
316
|
-
else {
|
|
283
|
+
} else {
|
|
317
284
|
const webshop = await Webshop.getByID(patch.webshopId);
|
|
318
285
|
if (!webshop || (event.organizationId && webshop.organizationId !== event.organizationId)) {
|
|
319
286
|
throw new SimpleError({
|
|
@@ -366,13 +333,47 @@ export class PatchEventsEndpoint extends Endpoint<Params, Query, Body, ResponseB
|
|
|
366
333
|
);
|
|
367
334
|
}
|
|
368
335
|
|
|
369
|
-
static
|
|
370
|
-
|
|
336
|
+
static validateOrCorrectEventMeta(event: Event) {
|
|
337
|
+
if (event.organizationId === null && event.meta.groups !== null) {
|
|
338
|
+
event.meta.groups = null;
|
|
339
|
+
console.error('Removed groups because organizationId is null for event', event.id);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
if (event.meta.groups && event.meta.groups.length === 0) {
|
|
343
|
+
throw new SimpleError({
|
|
344
|
+
code: 'invalid_field',
|
|
345
|
+
message: 'Empty groups',
|
|
346
|
+
human: $t(`%DV`),
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
if (event.meta.defaultAgeGroupIds && event.meta.defaultAgeGroupIds.length === 0) {
|
|
351
|
+
throw new SimpleError({
|
|
352
|
+
code: 'invalid_field',
|
|
353
|
+
message: 'Empty default age groups',
|
|
354
|
+
human: $t(`%DW`),
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
if (event.meta.organizationTagIds && event.meta.organizationTagIds.length === 0) {
|
|
359
|
+
throw new SimpleError({
|
|
360
|
+
code: 'invalid_field',
|
|
361
|
+
message: 'Empty organization tag ids',
|
|
362
|
+
human: $t(`%DX`),
|
|
363
|
+
});
|
|
364
|
+
}
|
|
371
365
|
}
|
|
372
366
|
|
|
373
|
-
static async getEventType(typeId: string) {
|
|
374
|
-
|
|
375
|
-
|
|
367
|
+
static async getEventType(typeId: string): Promise<OrganizationEventType | PlatformEventType> {
|
|
368
|
+
let type: OrganizationEventType | PlatformEventType | undefined = undefined;
|
|
369
|
+
|
|
370
|
+
if (STAMHOOFD.userMode === 'platform') {
|
|
371
|
+
const platform = await Platform.getSharedStruct();
|
|
372
|
+
type = platform.config.eventTypes.find(t => t.id === typeId);
|
|
373
|
+
} else if (typeId === OrganizationEventType.DEFAULT_ID) {
|
|
374
|
+
type = OrganizationEventType.createDefault();
|
|
375
|
+
}
|
|
376
|
+
|
|
376
377
|
if (!type) {
|
|
377
378
|
throw new SimpleError({
|
|
378
379
|
code: 'invalid_field',
|
|
@@ -387,21 +388,6 @@ export class PatchEventsEndpoint extends Endpoint<Params, Query, Body, ResponseB
|
|
|
387
388
|
static async checkEventLimits(event: Event) {
|
|
388
389
|
const type = await this.getEventType(event.typeId);
|
|
389
390
|
|
|
390
|
-
if (type.isLocationRequired) {
|
|
391
|
-
const address = event.meta.location?.address;
|
|
392
|
-
|
|
393
|
-
if (!address) {
|
|
394
|
-
throw new SimpleError({
|
|
395
|
-
code: 'invalid_field',
|
|
396
|
-
message: 'Empty number',
|
|
397
|
-
human: $t(`%vQ`),
|
|
398
|
-
field: 'event_required',
|
|
399
|
-
});
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
address.throwIfIncomplete();
|
|
403
|
-
}
|
|
404
|
-
|
|
405
391
|
if (event.name.length < 2) {
|
|
406
392
|
throw new SimpleError({
|
|
407
393
|
code: 'invalid_field',
|
|
@@ -420,69 +406,85 @@ export class PatchEventsEndpoint extends Endpoint<Params, Query, Body, ResponseB
|
|
|
420
406
|
});
|
|
421
407
|
}
|
|
422
408
|
|
|
423
|
-
if (type
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
const days = end.diff(start, 'days').days + 1;
|
|
409
|
+
if (type instanceof PlatformEventType) {
|
|
410
|
+
if (type.isLocationRequired) {
|
|
411
|
+
const address = event.meta.location?.address;
|
|
428
412
|
|
|
429
|
-
|
|
413
|
+
if (!address) {
|
|
414
|
+
throw new SimpleError({
|
|
415
|
+
code: 'invalid_field',
|
|
416
|
+
message: 'Empty number',
|
|
417
|
+
human: $t(`%vQ`),
|
|
418
|
+
field: 'event_required',
|
|
419
|
+
});
|
|
420
|
+
}
|
|
430
421
|
|
|
431
|
-
|
|
432
|
-
throw new SimpleError({
|
|
433
|
-
code: 'minimum_days',
|
|
434
|
-
message: 'An event with this type has a minimum of ' + type.minimumDays + ' days',
|
|
435
|
-
human: $t(`%14D`, {
|
|
436
|
-
name: type.name,
|
|
437
|
-
days: Formatter.pluralText(type.minimumDays, $t(`%1N7`), $t(`%1N6`)),
|
|
438
|
-
}),
|
|
439
|
-
field: 'startDate',
|
|
440
|
-
});
|
|
422
|
+
address.throwIfIncomplete();
|
|
441
423
|
}
|
|
442
424
|
|
|
443
|
-
if (type.maximumDays !== null
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
}),
|
|
451
|
-
field: 'startDate',
|
|
452
|
-
});
|
|
453
|
-
}
|
|
454
|
-
}
|
|
425
|
+
if (type.maximumDays !== null || type.minimumDays !== null) {
|
|
426
|
+
const start = Formatter.luxon(event.startDate).startOf('day');
|
|
427
|
+
const end = Formatter.luxon(event.endDate).startOf('day');
|
|
428
|
+
|
|
429
|
+
const days = end.diff(start, 'days').days + 1;
|
|
430
|
+
|
|
431
|
+
console.log('Detected days:', days);
|
|
455
432
|
|
|
456
|
-
|
|
457
|
-
const currentPeriod = await RegistrationPeriod.getByDate(event.startDate, event.organizationId);
|
|
458
|
-
console.log('event.startDate', event.startDate);
|
|
459
|
-
if (currentPeriod) {
|
|
460
|
-
const count = await SQL.select().from(
|
|
461
|
-
SQL.table(Event.table),
|
|
462
|
-
)
|
|
463
|
-
.where(SQL.column('organizationId'), event.organizationId)
|
|
464
|
-
.where(SQL.column('typeId'), event.typeId)
|
|
465
|
-
.where(SQL.column('id'), SQLWhereSign.NotEqual, event.id)
|
|
466
|
-
.where(SQL.column('startDate'), SQLWhereSign.GreaterEqual, currentPeriod.startDate)
|
|
467
|
-
.where(SQL.column('endDate'), SQLWhereSign.LessEqual, currentPeriod.endDate)
|
|
468
|
-
.count();
|
|
469
|
-
|
|
470
|
-
if (count >= type.maximum) {
|
|
433
|
+
if (type.minimumDays !== null && days < type.minimumDays) {
|
|
471
434
|
throw new SimpleError({
|
|
472
|
-
code: '
|
|
473
|
-
message: '
|
|
474
|
-
human: $t(`%
|
|
475
|
-
|
|
435
|
+
code: 'minimum_days',
|
|
436
|
+
message: 'An event with this type has a minimum of ' + type.minimumDays + ' days',
|
|
437
|
+
human: $t(`%14D`, {
|
|
438
|
+
name: type.name,
|
|
439
|
+
days: Formatter.pluralText(type.minimumDays, $t(`%1N7`), $t(`%1N6`)),
|
|
440
|
+
}),
|
|
441
|
+
field: 'startDate',
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
if (type.maximumDays !== null && days > type.maximumDays) {
|
|
446
|
+
throw new SimpleError({
|
|
447
|
+
code: 'maximum_days',
|
|
448
|
+
message: 'An event with this type has a maximum of ' + type.maximumDays + ' days',
|
|
449
|
+
human: $t(`%14E`, {
|
|
450
|
+
name: type.name,
|
|
451
|
+
days: Formatter.pluralText(type.maximumDays, $t(`%1N7`), $t(`%1N6`)),
|
|
452
|
+
}),
|
|
453
|
+
field: 'startDate',
|
|
476
454
|
});
|
|
477
455
|
}
|
|
478
456
|
}
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
457
|
+
|
|
458
|
+
if (type.maximum && (!event.existsInDatabase || ('typeId' in (event.getChangedDatabaseProperties()).fields))) {
|
|
459
|
+
const currentPeriod = await RegistrationPeriod.getByDate(event.startDate, event.organizationId);
|
|
460
|
+
console.log('event.startDate', event.startDate);
|
|
461
|
+
if (currentPeriod) {
|
|
462
|
+
const count = await SQL.select().from(
|
|
463
|
+
SQL.table(Event.table),
|
|
464
|
+
)
|
|
465
|
+
.where(SQL.column('organizationId'), event.organizationId)
|
|
466
|
+
.where(SQL.column('typeId'), event.typeId)
|
|
467
|
+
.where(SQL.column('id'), SQLWhereSign.NotEqual, event.id)
|
|
468
|
+
.where(SQL.column('startDate'), SQLWhereSign.GreaterEqual, currentPeriod.startDate)
|
|
469
|
+
.where(SQL.column('endDate'), SQLWhereSign.LessEqual, currentPeriod.endDate)
|
|
470
|
+
.count();
|
|
471
|
+
|
|
472
|
+
if (count >= type.maximum) {
|
|
473
|
+
throw new SimpleError({
|
|
474
|
+
code: 'type_maximum_reached',
|
|
475
|
+
message: 'Maximum number of events with this type reached',
|
|
476
|
+
human: $t(`%Dd`) + ' ' + type.name + ' ' + $t(`%De`) + type.maximum + ')',
|
|
477
|
+
field: 'typeId',
|
|
478
|
+
});
|
|
479
|
+
}
|
|
480
|
+
} else {
|
|
481
|
+
throw new SimpleError({
|
|
482
|
+
code: 'invalid_period',
|
|
483
|
+
message: 'No period found for this start date',
|
|
484
|
+
human: $t(`%Df`),
|
|
485
|
+
field: 'startDate',
|
|
486
|
+
});
|
|
487
|
+
}
|
|
486
488
|
}
|
|
487
489
|
}
|
|
488
490
|
}
|
|
@@ -553,8 +555,7 @@ export class PatchEventsEndpoint extends Endpoint<Params, Query, Body, ResponseB
|
|
|
553
555
|
await AuditLogService.setContext({ source: AuditLogSource.System }, async () => {
|
|
554
556
|
await event.syncGroupRequirements(existingGroup);
|
|
555
557
|
});
|
|
556
|
-
}
|
|
557
|
-
catch (e) {
|
|
558
|
+
} catch (e) {
|
|
558
559
|
// reset the group
|
|
559
560
|
existingGroup.type = originalGroupType;
|
|
560
561
|
existingGroup.settings.eventId = null;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { Decoder } from '@simonbackx/simple-encoding';
|
|
2
|
-
import type { DecodedRequest, Request} from '@simonbackx/simple-endpoints';
|
|
2
|
+
import type { DecodedRequest, Request } from '@simonbackx/simple-endpoints';
|
|
3
3
|
import { Endpoint, Response } from '@simonbackx/simple-endpoints';
|
|
4
4
|
import { SimpleError } from '@simonbackx/simple-errors';
|
|
5
|
-
import type { XlsxTransformerSheet} from '@stamhoofd/excel-writer';
|
|
5
|
+
import type { XlsxTransformerSheet } from '@stamhoofd/excel-writer';
|
|
6
6
|
import { ArchiverWriterAdapter, exportToExcel, XlsxWriter } from '@stamhoofd/excel-writer';
|
|
7
7
|
import { Platform, RateLimiter, sendEmailTemplate } from '@stamhoofd/models';
|
|
8
8
|
import { QueueHandler } from '@stamhoofd/queues';
|
|
9
|
-
import type { ExcelExportType, IPaginatedResponse, LimitedFilteredRequest} from '@stamhoofd/structures';
|
|
9
|
+
import type { ExcelExportType, IPaginatedResponse, LimitedFilteredRequest } from '@stamhoofd/structures';
|
|
10
10
|
import { EmailTemplateType, ExcelExportRequest, ExcelExportResponse, Replacement, Version } from '@stamhoofd/structures';
|
|
11
11
|
import { sleep } from '@stamhoofd/utility';
|
|
12
12
|
import { Context } from '../../../helpers/Context.js';
|
|
@@ -89,7 +89,7 @@ export class ExportToExcelEndpoint extends Endpoint<Params, Query, Body, Respons
|
|
|
89
89
|
await Platform.getSharedStruct();
|
|
90
90
|
|
|
91
91
|
const result = await Promise.race([
|
|
92
|
-
this.job(loader, request.body, request.params.type).then(async (url: string) => {
|
|
92
|
+
this.job(loader, request.body, request.params.type, user.id).then(async (url: string) => {
|
|
93
93
|
if (sendEmail) {
|
|
94
94
|
await sendEmailTemplate(null, {
|
|
95
95
|
template: {
|
|
@@ -138,10 +138,10 @@ export class ExportToExcelEndpoint extends Endpoint<Params, Query, Body, Respons
|
|
|
138
138
|
}));
|
|
139
139
|
}
|
|
140
140
|
|
|
141
|
-
async job(loader: ExcelExporter<unknown>, request: ExcelExportRequest, type: string): Promise<string> {
|
|
141
|
+
async job(loader: ExcelExporter<unknown>, request: ExcelExportRequest, type: string, userId: string): Promise<string> {
|
|
142
142
|
// Only run 1 export per user at the same time
|
|
143
|
-
return await QueueHandler.schedule('user-export-to-excel-' +
|
|
144
|
-
// Allow maximum
|
|
143
|
+
return await QueueHandler.schedule('user-export-to-excel-' + userId, async () => {
|
|
144
|
+
// Allow maximum 5 running Excel jobs at the same time for all users; queue the rest.
|
|
145
145
|
return await QueueHandler.schedule('export-to-excel', async () => {
|
|
146
146
|
// Estimate how long it will take.
|
|
147
147
|
// If too long, we'll schedule it and write it to Digitalocean Spaces
|
|
@@ -163,9 +163,9 @@ export class ExportToExcelEndpoint extends Endpoint<Params, Query, Body, Respons
|
|
|
163
163
|
|
|
164
164
|
console.log('Done writing excel file');
|
|
165
165
|
|
|
166
|
-
const url = 'https://' + STAMHOOFD.domains.api + '/v' + Version + '/file-cache?file=' + encodeURIComponent(file) + '&name=' + encodeURIComponent(type);
|
|
166
|
+
const url = 'https://' + STAMHOOFD.domains.api + '/v' + Version + '/file-cache?file=' + encodeURIComponent(file) + '&name=' + encodeURIComponent(request.title ?? type);
|
|
167
167
|
return url;
|
|
168
|
-
},
|
|
168
|
+
}, 5);
|
|
169
169
|
});
|
|
170
170
|
}
|
|
171
171
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { Decoder} from '@simonbackx/simple-encoding';
|
|
1
|
+
import type { Decoder } from '@simonbackx/simple-encoding';
|
|
2
2
|
import { AutoEncoder, field, StringDecoder } from '@simonbackx/simple-encoding';
|
|
3
|
-
import type { DecodedRequest, Request} from '@simonbackx/simple-endpoints';
|
|
3
|
+
import type { DecodedRequest, Request } from '@simonbackx/simple-endpoints';
|
|
4
4
|
import { Endpoint, Response } from '@simonbackx/simple-endpoints';
|
|
5
5
|
import type { Readable } from 'node:stream';
|
|
6
6
|
import { Context } from '../../../helpers/Context.js';
|
|
@@ -60,8 +60,7 @@ export class GetFileCache extends Endpoint<Params, Query, Body, ResponseBody> {
|
|
|
60
60
|
if (request.query.name) {
|
|
61
61
|
const slug = Formatter.fileSlug(request.query.name) + extension;
|
|
62
62
|
response.headers['Content-Disposition'] = `attachment; filename="${slug}"`;
|
|
63
|
-
}
|
|
64
|
-
else {
|
|
63
|
+
} else {
|
|
65
64
|
response.headers['Content-Disposition'] = `attachment; filename="bestand${extension}"`;
|
|
66
65
|
}
|
|
67
66
|
response.headers['Content-Length'] = contentLength.toString();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PutObjectCommand, S3Client } from '@aws-sdk/client-s3'; // ES Modules import
|
|
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 { File } from '@stamhoofd/structures';
|
|
@@ -8,7 +8,7 @@ import formidable from 'formidable';
|
|
|
8
8
|
import { promises as fs } from 'fs';
|
|
9
9
|
import { v4 as uuidv4 } from 'uuid';
|
|
10
10
|
|
|
11
|
-
import type { Decoder} from '@simonbackx/simple-encoding';
|
|
11
|
+
import type { Decoder } from '@simonbackx/simple-encoding';
|
|
12
12
|
import { AutoEncoder, BooleanDecoder, field } from '@simonbackx/simple-encoding';
|
|
13
13
|
import { Context } from '../../../helpers/Context.js';
|
|
14
14
|
import { limiter } from './UploadImage.js';
|
|
@@ -133,8 +133,7 @@ export class UploadFile extends Endpoint<Params, Query, Body, ResponseBody> {
|
|
|
133
133
|
if (request.query.isPrivate && user) {
|
|
134
134
|
// Private files
|
|
135
135
|
prefix += 'users/' + user.id + '/';
|
|
136
|
-
}
|
|
137
|
-
else {
|
|
136
|
+
} else {
|
|
138
137
|
// Public files
|
|
139
138
|
prefix += 'p/';
|
|
140
139
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { Decoder} from '@simonbackx/simple-encoding';
|
|
1
|
+
import type { Decoder } from '@simonbackx/simple-encoding';
|
|
2
2
|
import { AutoEncoder, BooleanDecoder, field, ObjectData } from '@simonbackx/simple-encoding';
|
|
3
|
-
import type { DecodedRequest, Request} from '@simonbackx/simple-endpoints';
|
|
3
|
+
import type { DecodedRequest, Request } from '@simonbackx/simple-endpoints';
|
|
4
4
|
import { Endpoint, Response } from '@simonbackx/simple-endpoints';
|
|
5
5
|
import { SimpleError } from '@simonbackx/simple-errors';
|
|
6
6
|
import { Image, RateLimiter } from '@stamhoofd/models';
|
|
@@ -125,8 +125,7 @@ export class UploadImage extends Endpoint<Params, Query, Body, ResponseBody> {
|
|
|
125
125
|
try {
|
|
126
126
|
const resolutions = new ObjectData(JSON.parse(fields.resolutions[0]), { version: request.request.getVersion() }).array(ResolutionRequest as Decoder<ResolutionRequest>);
|
|
127
127
|
resolve([files.file[0], resolutions]);
|
|
128
|
-
}
|
|
129
|
-
catch (e) {
|
|
128
|
+
} catch (e) {
|
|
130
129
|
reject(e);
|
|
131
130
|
}
|
|
132
131
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Request } from '@simonbackx/simple-endpoints';
|
|
2
|
-
import type { Organization, RegistrationPeriod} from '@stamhoofd/models';
|
|
2
|
+
import type { Organization, RegistrationPeriod } from '@stamhoofd/models';
|
|
3
3
|
import { GroupFactory, OrganizationFactory, OrganizationRegistrationPeriodFactory, RegistrationPeriodFactory, Token, UserFactory } from '@stamhoofd/models';
|
|
4
4
|
import type { StamhoofdFilter } from '@stamhoofd/structures';
|
|
5
5
|
import { BundleDiscountGroupPriceSettings, GroupPrice, GroupType, LimitedFilteredRequest } from '@stamhoofd/structures';
|
|
@@ -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 type { CountFilteredRequest, Group as GroupStruct, StamhoofdFilter } from '@stamhoofd/structures';
|
|
4
4
|
import { assertSort, getSortFilter, LimitedFilteredRequest, PaginatedResponse } from '@stamhoofd/structures';
|
|
@@ -61,7 +61,9 @@ export class GetGroupsEndpoint extends Endpoint<Params, Query, Body, ResponseBod
|
|
|
61
61
|
let searchFilter: StamhoofdFilter | null = null;
|
|
62
62
|
|
|
63
63
|
searchFilter = {
|
|
64
|
-
|
|
64
|
+
name: {
|
|
65
|
+
$contains: q.search,
|
|
66
|
+
},
|
|
65
67
|
};
|
|
66
68
|
|
|
67
69
|
if (searchFilter) {
|
|
@@ -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 type { MemberWithUsersRegistrationsAndGroups } from '@stamhoofd/models';
|
|
4
4
|
import { Member } from '@stamhoofd/models';
|
|
@@ -38,8 +38,7 @@ export class GetMemberFamilyEndpoint extends Endpoint<Params, Query, Body, Respo
|
|
|
38
38
|
if (!await Context.auth.hasSomeAccess(organization.id)) {
|
|
39
39
|
throw Context.auth.error();
|
|
40
40
|
}
|
|
41
|
-
}
|
|
42
|
-
else {
|
|
41
|
+
} else {
|
|
43
42
|
if (!Context.auth.hasSomePlatformAccess()) {
|
|
44
43
|
throw Context.auth.error();
|
|
45
44
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Decoder } from '@simonbackx/simple-encoding';
|
|
2
|
-
import type { DecodedRequest, Request} from '@simonbackx/simple-endpoints';
|
|
2
|
+
import type { DecodedRequest, Request } from '@simonbackx/simple-endpoints';
|
|
3
3
|
import { Endpoint, Response } from '@simonbackx/simple-endpoints';
|
|
4
4
|
import { CountFilteredRequest, CountResponse } from '@stamhoofd/structures';
|
|
5
5
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { Endpoint} from '@simonbackx/simple-endpoints';
|
|
1
|
+
import type { Endpoint } from '@simonbackx/simple-endpoints';
|
|
2
2
|
import { Request } from '@simonbackx/simple-endpoints';
|
|
3
|
-
import type { RegistrationPeriod} from '@stamhoofd/models';
|
|
3
|
+
import type { RegistrationPeriod } from '@stamhoofd/models';
|
|
4
4
|
import { EventFactory, GroupFactory, MemberFactory, OrganizationFactory, RecordCategoryFactory, RegistrationFactory, RegistrationPeriodFactory, Token, UserFactory } from '@stamhoofd/models';
|
|
5
5
|
import { AccessRight, EventMeta, GroupType, LimitedFilteredRequest, NamedObject, PermissionLevel, PermissionRoleDetailed, Permissions, PermissionsResourceType, RecordAnswer, RecordTextAnswer, RecordType, ResourcePermissions } from '@stamhoofd/structures';
|
|
6
6
|
import { STExpect, TestUtils } from '@stamhoofd/test-utils';
|
|
@@ -83,8 +83,7 @@ export class GetMembersEndpoint extends Endpoint<Params, Query, Body, ResponseBo
|
|
|
83
83
|
},
|
|
84
84
|
},
|
|
85
85
|
};
|
|
86
|
-
}
|
|
87
|
-
else {
|
|
86
|
+
} else {
|
|
88
87
|
// Can only access current period
|
|
89
88
|
scopeFilter = {
|
|
90
89
|
registrations: {
|
|
@@ -95,8 +94,7 @@ export class GetMembersEndpoint extends Endpoint<Params, Query, Body, ResponseBo
|
|
|
95
94
|
},
|
|
96
95
|
};
|
|
97
96
|
}
|
|
98
|
-
}
|
|
99
|
-
else {
|
|
97
|
+
} else {
|
|
100
98
|
// Check which normal membership groups we have access to and filter on those
|
|
101
99
|
const groups = await Group.getAll(organization.id, organization.periodId, true, [GroupType.Membership, GroupType.WaitingList]);
|
|
102
100
|
Context.auth.cacheGroups(groups);
|
|
@@ -134,6 +132,10 @@ export class GetMembersEndpoint extends Endpoint<Params, Query, Body, ResponseBo
|
|
|
134
132
|
SQL.table('members'),
|
|
135
133
|
);
|
|
136
134
|
|
|
135
|
+
if (organization && STAMHOOFD.userMode === 'organization') {
|
|
136
|
+
query.where('organizationId', organization.id);
|
|
137
|
+
}
|
|
138
|
+
|
|
137
139
|
if (scopeFilter) {
|
|
138
140
|
query.where(await compileToSQLFilter(scopeFilter, filterCompilers));
|
|
139
141
|
}
|
|
@@ -197,8 +199,7 @@ export class GetMembersEndpoint extends Endpoint<Params, Query, Body, ResponseBo
|
|
|
197
199
|
],
|
|
198
200
|
};
|
|
199
201
|
}
|
|
200
|
-
}
|
|
201
|
-
catch (e) {
|
|
202
|
+
} catch (e) {
|
|
202
203
|
console.error('Failed to parse phone number', search, e);
|
|
203
204
|
}
|
|
204
205
|
}
|
|
@@ -216,8 +217,7 @@ export class GetMembersEndpoint extends Endpoint<Params, Query, Body, ResponseBo
|
|
|
216
217
|
// e-mail or name based searching
|
|
217
218
|
if (searchFilter) {
|
|
218
219
|
// already done
|
|
219
|
-
}
|
|
220
|
-
else if (search.includes('@')) {
|
|
220
|
+
} else if (search.includes('@')) {
|
|
221
221
|
const isCompleteAddress = DataValidator.isEmailValid(search);
|
|
222
222
|
|
|
223
223
|
// Member email address contains, or member parent contains
|
|
@@ -240,8 +240,7 @@ export class GetMembersEndpoint extends Endpoint<Params, Query, Body, ResponseBo
|
|
|
240
240
|
},
|
|
241
241
|
],
|
|
242
242
|
} as any as StamhoofdFilter;
|
|
243
|
-
}
|
|
244
|
-
else {
|
|
243
|
+
} else {
|
|
245
244
|
searchFilter = {
|
|
246
245
|
name: {
|
|
247
246
|
$contains: search,
|
|
@@ -260,8 +259,7 @@ export class GetMembersEndpoint extends Endpoint<Params, Query, Body, ResponseBo
|
|
|
260
259
|
|
|
261
260
|
try {
|
|
262
261
|
data = await query.fetch();
|
|
263
|
-
}
|
|
264
|
-
catch (error) {
|
|
262
|
+
} catch (error) {
|
|
265
263
|
if (error.message.includes('ER_QUERY_TIMEOUT')) {
|
|
266
264
|
throw new SimpleError({
|
|
267
265
|
code: 'timeout',
|