@stamhoofd/backend 2.120.6 → 2.122.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/output-2.txt +1 -0
- package/output.txt +1 -0
- package/package.json +70 -53
- 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 +46 -0
- package/src/audit-logs/init.ts +9 -1
- 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 +7 -0
- package/src/crons/invoices.ts +160 -0
- package/src/crons/members-fees.ts +50 -0
- package/src/crons/mollie-chargebacks.ts +86 -0
- 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 +54 -74
- 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 +87 -46
- 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 +51 -0
- 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 +32 -13
- 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 +38 -33
- package/src/endpoints/global/registration-invitations/GetRegistrationInvitationsCountEndpoint.ts +45 -0
- package/src/endpoints/global/registration-invitations/GetRegistrationInvitationsEndpoint.test.ts +494 -0
- package/src/endpoints/global/registration-invitations/GetRegistrationInvitationsEndpoint.ts +213 -0
- package/src/endpoints/global/registration-invitations/PatchRegistrationInvitationsEndpoint.test.ts +404 -0
- package/src/endpoints/global/registration-invitations/PatchRegistrationInvitationsEndpoint.ts +167 -0
- 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 +19 -6
- package/src/endpoints/organization/dashboard/billing/ApplyRegisterCodeEndpoint.test.ts +73 -0
- package/src/endpoints/organization/dashboard/billing/ApplyRegisterCodeEndpoint.ts +89 -0
- package/src/endpoints/{global → organization/dashboard}/billing/DeactivatePackageEndpoint.ts +4 -9
- package/src/endpoints/organization/dashboard/billing/DeleteOrganizationMandateEndpoint.ts +62 -0
- package/src/endpoints/organization/dashboard/billing/GetOrganizationDetailedPayableBalanceCollectionEndpoint.ts +56 -0
- package/src/endpoints/organization/dashboard/billing/GetOrganizationDetailedPayableBalanceEndpoint.ts +41 -18
- package/src/endpoints/organization/dashboard/billing/GetOrganizationMandatesEndpoint.ts +64 -0
- 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 +12 -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 +311 -0
- package/src/endpoints/organization/dashboard/billing/PatchOrganizationMandatesEndpoint.ts +94 -0
- 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 +15 -4
- package/src/endpoints/organization/dashboard/invoices/PatchInvoicesEndpoint.ts +11 -2
- package/src/endpoints/organization/dashboard/mollie/CheckMollieEndpoint.ts +8 -8
- package/src/endpoints/organization/dashboard/mollie/ConnectMollieEndpoint.ts +10 -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 +67 -20
- 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 +24 -17
- package/src/endpoints/organization/dashboard/receivable-balances/ChargeReceivableBalancesEndpoint.ts +134 -0
- 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 +32 -22
- 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 +29 -8
- package/src/endpoints/organization/dashboard/webshops/PatchWebshopOrdersEndpoint.ts +21 -28
- 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 +15 -13
- 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 +28 -50
- 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 +60 -65
- package/src/helpers/AuthenticatedStructures.ts +153 -51
- 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 +21 -0
- 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 +741 -0
- package/src/helpers/RecordAnswerHelper.ts +116 -0
- 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 +15 -38
- 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 +11 -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/migrations/1750090030-records-configuration.ts +92 -0
- 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 +95 -27
- 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/1779121239-default-invoice-email-template.sql +3 -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 +148 -55
- 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 +330 -77
- 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 +530 -0
- package/src/services/PaymentMandateService.ts +214 -0
- package/src/services/PaymentReallocationService.test.ts +1 -1
- package/src/services/PaymentReallocationService.ts +7 -9
- package/src/services/PaymentService.ts +820 -328
- package/src/services/PlatformMembershipService.ts +5 -9
- package/src/services/ReferralService.ts +223 -0
- package/src/services/RegistrationService.ts +125 -54
- package/src/services/SSOService.test.ts +119 -0
- package/src/services/SSOService.ts +56 -49
- package/src/services/STPackageService.ts +97 -68
- package/src/services/UniqueMemberNumberService.ts +69 -0
- package/src/services/UniqueUserService.ts +3 -6
- package/src/services/VATService.ts +85 -0
- package/src/services/data/invoice.hbs.html +686 -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 +16 -1
- 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/payments.ts +5 -0
- package/src/sql-filters/platform-memberships.ts +3 -3
- package/src/sql-filters/receivable-balances.ts +1 -1
- package/src/sql-filters/registration-invitations.ts +90 -0
- 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 +36 -0
- 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 +7 -0
- package/.nvmrc +0 -1
- package/src/endpoints/global/billing/ActivatePackagesEndpoint.ts +0 -216
- 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/1750090030-records-configuration.ts +0 -26
- 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}/data/default-email-templates.sql +0 -0
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { SimpleError } from '@simonbackx/simple-errors';
|
|
2
|
-
import type { AuditLog, Document, EventNotification, MemberWithUsersRegistrationsAndGroups, Order, Ticket} from '@stamhoofd/models';
|
|
3
|
-
import { BalanceItem, CachedBalance, Event, Group, Invoice, Member, MemberPlatformMembership, MemberResponsibilityRecord, Organization, OrganizationRegistrationPeriod, Payment, Registration, RegistrationPeriod, User, Webshop } from '@stamhoofd/models';
|
|
4
|
-
import type { PaymentGeneral} from '@stamhoofd/structures';
|
|
5
|
-
import {
|
|
2
|
+
import type { AuditLog, Document, EventNotification, MemberWithUsersRegistrationsAndGroups, Order, Ticket } from '@stamhoofd/models';
|
|
3
|
+
import { BalanceItem, CachedBalance, Event, Group, Invoice, Member, MemberPlatformMembership, MemberResponsibilityRecord, Organization, OrganizationRegistrationPeriod, Payment, Registration, RegistrationInvitation, RegistrationPeriod, User, Webshop } from '@stamhoofd/models';
|
|
4
|
+
import type { PaymentGeneral } from '@stamhoofd/structures';
|
|
5
|
+
import { BaseOrganization, getAppHost } from '@stamhoofd/structures';
|
|
6
|
+
import { Payment as PaymentStruct, AuditLogReplacement, AuditLogReplacementType, AuditLog as AuditLogStruct, BalanceItem as BalanceItemStruct, DetailedReceivableBalance, Document as DocumentStruct, EventNotification as EventNotificationStruct, Event as EventStruct, GenericBalance, Group as GroupStruct, GroupType, InvitationGroupData, InvitationMemberData, InvoicedBalanceItem, InvoiceStruct, MemberPlatformMembership as MemberPlatformMembershipStruct, MemberRegistrationInvitation, MembersBlob, MemberWithRegistrationsBlob, NamedObject, OrganizationRegistrationPeriod as OrganizationRegistrationPeriodStruct, Organization as OrganizationStruct, PaymentCustomer, PermissionLevel, Platform, PrivateOrder, PrivateWebshop, ReceivableBalanceObject, ReceivableBalanceObjectContact, ReceivableBalance as ReceivableBalanceStruct, ReceivableBalanceType, RegistrationInvitation as RegistrationInvitationStruct, RegistrationsBlob, RegistrationWithMemberBlob, TicketPrivate, UserWithMembers, WebshopPreview, Webshop as WebshopStruct } from '@stamhoofd/structures';
|
|
6
7
|
import { Sorter } from '@stamhoofd/utility';
|
|
7
8
|
|
|
8
9
|
import { SQL } from '@stamhoofd/sql';
|
|
@@ -34,7 +35,7 @@ export class AuthenticatedStructures {
|
|
|
34
35
|
const { registrations, orders } = await Payment.loadBalanceItemRelations(balanceItems);
|
|
35
36
|
|
|
36
37
|
// Note: permission checking is moved here for performacne to avoid loading the data multiple times
|
|
37
|
-
if (!(await Context.
|
|
38
|
+
if (!(await Context.optionalAuth?.canAccessBalanceItems(balanceItems, PermissionLevel.Read, { registrations, orders }))) {
|
|
38
39
|
throw new SimpleError({
|
|
39
40
|
code: 'permission_denied',
|
|
40
41
|
message: 'Permission denied',
|
|
@@ -43,7 +44,7 @@ export class AuthenticatedStructures {
|
|
|
43
44
|
}
|
|
44
45
|
}
|
|
45
46
|
|
|
46
|
-
const includeSettlements = checkPermissions && !!Context.user && !!Context.user.permissions;
|
|
47
|
+
const includeSettlements = checkPermissions && !!Context.user && !!Context.user.permissions && payments.every(p => !!Context.optionalAuth?.checkScope(p.organizationId));
|
|
47
48
|
|
|
48
49
|
const { payingOrganizations } = await Payment.loadPayingOrganizations(payments);
|
|
49
50
|
|
|
@@ -55,6 +56,22 @@ export class AuthenticatedStructures {
|
|
|
55
56
|
}, includeSettlements);
|
|
56
57
|
}
|
|
57
58
|
|
|
59
|
+
/**
|
|
60
|
+
*
|
|
61
|
+
* @param payments
|
|
62
|
+
* @param checkPermissions Only set to undefined when not returned in the API + not for public use
|
|
63
|
+
* @returns
|
|
64
|
+
*/
|
|
65
|
+
static async payments(payments: Payment[]): Promise<PaymentStruct[]> {
|
|
66
|
+
if (payments.length === 0) {
|
|
67
|
+
return [];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return payments.map((p) => {
|
|
71
|
+
return PaymentStruct.create(p);
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
58
75
|
static async invoices(invoices: Invoice[]): Promise<InvoiceStruct[]> {
|
|
59
76
|
if (invoices.length === 0) {
|
|
60
77
|
return [];
|
|
@@ -92,8 +109,7 @@ export class AuthenticatedStructures {
|
|
|
92
109
|
|
|
93
110
|
if (existingGroup) {
|
|
94
111
|
waitingLists.push(existingGroup);
|
|
95
|
-
}
|
|
96
|
-
else {
|
|
112
|
+
} else {
|
|
97
113
|
waitingListsToFetch.push(waitingListId);
|
|
98
114
|
}
|
|
99
115
|
}
|
|
@@ -159,13 +175,11 @@ export class AuthenticatedStructures {
|
|
|
159
175
|
.where(whereGroupIds)
|
|
160
176
|
.orWhere(whereWaitingList)
|
|
161
177
|
.fetch();
|
|
162
|
-
}
|
|
163
|
-
else {
|
|
178
|
+
} else {
|
|
164
179
|
groups = await Group.select()
|
|
165
180
|
.where(whereGroupIds).fetch();
|
|
166
181
|
}
|
|
167
|
-
}
|
|
168
|
-
else if (organizationIds.length && periodIds.length) {
|
|
182
|
+
} else if (organizationIds.length && periodIds.length) {
|
|
169
183
|
groups = await Group.select()
|
|
170
184
|
.where(whereWaitingList)
|
|
171
185
|
.fetch();
|
|
@@ -222,6 +236,16 @@ export class AuthenticatedStructures {
|
|
|
222
236
|
return WebshopPreview.create(webshop);
|
|
223
237
|
}
|
|
224
238
|
|
|
239
|
+
static async baseOrganizations(organizations: Organization[]): Promise<BaseOrganization[]> {
|
|
240
|
+
if (organizations.length === 0) {
|
|
241
|
+
return [];
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return organizations.map((o) => {
|
|
245
|
+
return BaseOrganization.create(o);
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
|
|
225
249
|
static async organizations(organizations: Organization[]): Promise<OrganizationStruct[]> {
|
|
226
250
|
if (organizations.length === 0) {
|
|
227
251
|
return [];
|
|
@@ -235,8 +259,7 @@ export class AuthenticatedStructures {
|
|
|
235
259
|
const array = periodIdOrganizationsMap.get(periodId);
|
|
236
260
|
if (array !== undefined) {
|
|
237
261
|
array.push(organization);
|
|
238
|
-
}
|
|
239
|
-
else {
|
|
262
|
+
} else {
|
|
240
263
|
periodIdOrganizationsMap.set(periodId, [organization]);
|
|
241
264
|
}
|
|
242
265
|
}
|
|
@@ -287,8 +310,7 @@ export class AuthenticatedStructures {
|
|
|
287
310
|
organizationIdsToGetWebshopsFor.push(organization.id);
|
|
288
311
|
}
|
|
289
312
|
organizationData.set(organizationId, { organizationRegistrationPeriod, canAccessPrivateData });
|
|
290
|
-
}
|
|
291
|
-
else {
|
|
313
|
+
} else {
|
|
292
314
|
// Should never happen
|
|
293
315
|
throw new Error('Organization registration period model not found for organization id ' + organizationId + ' and period id ' + periodId);
|
|
294
316
|
}
|
|
@@ -298,14 +320,14 @@ export class AuthenticatedStructures {
|
|
|
298
320
|
// Get webshop previews
|
|
299
321
|
const webshops = organizationIdsToGetWebshopsFor.length > 0
|
|
300
322
|
? await Webshop.where(
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
323
|
+
{
|
|
324
|
+
organizationId: {
|
|
325
|
+
sign: 'IN',
|
|
326
|
+
value: organizationIdsToGetWebshopsFor,
|
|
327
|
+
},
|
|
305
328
|
},
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
)
|
|
329
|
+
{ select: Webshop.selectColumnsWithout(undefined, 'products', 'categories') },
|
|
330
|
+
)
|
|
309
331
|
: [];
|
|
310
332
|
|
|
311
333
|
const webshopPreviews = new Map<string, WebshopPreview[]>();
|
|
@@ -321,8 +343,7 @@ export class AuthenticatedStructures {
|
|
|
321
343
|
|
|
322
344
|
if (array) {
|
|
323
345
|
array.push(preview);
|
|
324
|
-
}
|
|
325
|
-
else {
|
|
346
|
+
} else {
|
|
326
347
|
webshopPreviews.set(organizationId, [preview]);
|
|
327
348
|
}
|
|
328
349
|
}
|
|
@@ -356,8 +377,7 @@ export class AuthenticatedStructures {
|
|
|
356
377
|
privateMeta: organization.privateMeta.removedPrivateKeys,
|
|
357
378
|
webshops: webshopPreviews.get(organization.id)?.sort((a, b) => Sorter.byDateValue(b.createdAt, a.createdAt)),
|
|
358
379
|
});
|
|
359
|
-
}
|
|
360
|
-
else {
|
|
380
|
+
} else {
|
|
361
381
|
result = OrganizationStruct.create({
|
|
362
382
|
...baseStruct,
|
|
363
383
|
period,
|
|
@@ -447,18 +467,25 @@ export class AuthenticatedStructures {
|
|
|
447
467
|
// Load responsibilities
|
|
448
468
|
const responsibilities = members.length > 0
|
|
449
469
|
? await MemberResponsibilityRecord.select()
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
470
|
+
.where('memberId', members.map(m => m.id))
|
|
471
|
+
.where(SQL.where('endDate', null).or('endDate', '>', new Date()))
|
|
472
|
+
.fetch()
|
|
453
473
|
: [];
|
|
454
474
|
const platformMemberships = members.length > 0
|
|
455
475
|
? await MemberPlatformMembership.select()
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
476
|
+
.where('memberId', members.map(m => m.id))
|
|
477
|
+
.where('deletedAt', null)
|
|
478
|
+
.where('periodId', relevantPeriodIds)
|
|
479
|
+
.fetch()
|
|
480
|
+
: [];
|
|
481
|
+
const registrationInvitations = members.length > 0
|
|
482
|
+
? await RegistrationInvitation.select()
|
|
483
|
+
.where('memberId', members.map(m => m.id))
|
|
484
|
+
.fetch()
|
|
460
485
|
: [];
|
|
461
486
|
|
|
487
|
+
const memberRegistrationInvitations: Map<string, MemberRegistrationInvitation[]> = registrationInvitations.length > 0 ? await this.memberRegistrationInvitations(registrationInvitations) : new Map();
|
|
488
|
+
|
|
462
489
|
// Load organizations
|
|
463
490
|
const organizationIds = responsibilities.map(r => r.organizationId)
|
|
464
491
|
.concat(
|
|
@@ -640,8 +667,7 @@ export class AuthenticatedStructures {
|
|
|
640
667
|
const g = allGroups.get(r.groupId);
|
|
641
668
|
if (g) {
|
|
642
669
|
base.group = g;
|
|
643
|
-
}
|
|
644
|
-
else {
|
|
670
|
+
} else {
|
|
645
671
|
console.error('Group not preloaded for registration', r.id, r.groupId);
|
|
646
672
|
}
|
|
647
673
|
|
|
@@ -663,6 +689,7 @@ export class AuthenticatedStructures {
|
|
|
663
689
|
return r.getStructure(group);
|
|
664
690
|
});
|
|
665
691
|
blob.platformMemberships = platformMemberships.filter(r => r.memberId == blob.id).map(r => MemberPlatformMembershipStruct.create(r));
|
|
692
|
+
blob.registrationInvitations = memberRegistrationInvitations.get(blob.id) ?? [];
|
|
666
693
|
}
|
|
667
694
|
|
|
668
695
|
return MembersBlob.create({
|
|
@@ -775,8 +802,7 @@ export class AuthenticatedStructures {
|
|
|
775
802
|
const array = eventIdsMapping.get(notificationId);
|
|
776
803
|
if (array) {
|
|
777
804
|
array.push(eventId);
|
|
778
|
-
}
|
|
779
|
-
else {
|
|
805
|
+
} else {
|
|
780
806
|
eventIdsMapping.set(notificationId, [eventId]);
|
|
781
807
|
}
|
|
782
808
|
|
|
@@ -935,7 +961,7 @@ export class AuthenticatedStructures {
|
|
|
935
961
|
return (await this.receivableBalancesHelper(balances)).map(({ balance, object }) => ReceivableBalanceStruct.create({ ...balance, object }));
|
|
936
962
|
}
|
|
937
963
|
|
|
938
|
-
private static async receivableBalancesHelper(balances: CachedBalance[]): Promise<
|
|
964
|
+
private static async receivableBalancesHelper(balances: CachedBalance[]): Promise<{ balance: CachedBalance; object: ReceivableBalanceObject }[]> {
|
|
939
965
|
if (balances.length === 0) {
|
|
940
966
|
return [];
|
|
941
967
|
}
|
|
@@ -972,7 +998,7 @@ export class AuthenticatedStructures {
|
|
|
972
998
|
const result: { balance: CachedBalance; object: ReceivableBalanceObject }[] = [];
|
|
973
999
|
|
|
974
1000
|
function getMemberContacts(member: Member, balance: CachedBalance) {
|
|
975
|
-
const url = Context.organization && Context.organization.id === balance.organizationId ? 'https://' + Context.organization
|
|
1001
|
+
const url = Context.organization && Context.organization.id === balance.organizationId ? 'https://' + getAppHost('registration', Context.organization, false) : '';
|
|
976
1002
|
return [
|
|
977
1003
|
...(member.details.getMemberEmails().length
|
|
978
1004
|
? [
|
|
@@ -1065,8 +1091,7 @@ export class AuthenticatedStructures {
|
|
|
1065
1091
|
})),
|
|
1066
1092
|
});
|
|
1067
1093
|
}
|
|
1068
|
-
}
|
|
1069
|
-
else if (balance.objectType === ReceivableBalanceType.member) {
|
|
1094
|
+
} else if (balance.objectType === ReceivableBalanceType.member) {
|
|
1070
1095
|
const member = members.find(m => m.id === balance.objectId) ?? null;
|
|
1071
1096
|
if (member) {
|
|
1072
1097
|
object = ReceivableBalanceObject.create({
|
|
@@ -1076,8 +1101,7 @@ export class AuthenticatedStructures {
|
|
|
1076
1101
|
contacts: getMemberContacts(member, balance),
|
|
1077
1102
|
});
|
|
1078
1103
|
}
|
|
1079
|
-
}
|
|
1080
|
-
else if (balance.objectType === ReceivableBalanceType.registration) {
|
|
1104
|
+
} else if (balance.objectType === ReceivableBalanceType.registration) {
|
|
1081
1105
|
const registration = registrations.find(r => r.id === balance.objectId) ?? null;
|
|
1082
1106
|
if (!registration) {
|
|
1083
1107
|
continue;
|
|
@@ -1091,11 +1115,10 @@ export class AuthenticatedStructures {
|
|
|
1091
1115
|
contacts: getMemberContacts(member, balance),
|
|
1092
1116
|
});
|
|
1093
1117
|
}
|
|
1094
|
-
}
|
|
1095
|
-
else if (balance.objectType === ReceivableBalanceType.user || balance.objectType === ReceivableBalanceType.userWithoutMembers) {
|
|
1118
|
+
} else if (balance.objectType === ReceivableBalanceType.user || balance.objectType === ReceivableBalanceType.userWithoutMembers) {
|
|
1096
1119
|
const user = users.find(m => m.id === balance.objectId) ?? null;
|
|
1097
1120
|
if (user) {
|
|
1098
|
-
const url = Context.organization && Context.organization.id === balance.organizationId ? 'https://' + Context.organization.
|
|
1121
|
+
const url = Context.organization && Context.organization.id === balance.organizationId ? 'https://' + getAppHost('registration', Context.organization, user.permissions?.forOrganization(Context.organization)?.isEmpty === false) : '';
|
|
1099
1122
|
object = ReceivableBalanceObject.create({
|
|
1100
1123
|
id: balance.objectId,
|
|
1101
1124
|
name: user.name || user.email,
|
|
@@ -1169,15 +1192,13 @@ export class AuthenticatedStructures {
|
|
|
1169
1192
|
id: '',
|
|
1170
1193
|
name: $t(`%wi`) + ' ' + Platform.shared.config.name,
|
|
1171
1194
|
});
|
|
1172
|
-
}
|
|
1173
|
-
else {
|
|
1195
|
+
} else {
|
|
1174
1196
|
userStruct = NamedObject.create({
|
|
1175
1197
|
id: '',
|
|
1176
1198
|
name: $t(`%Gr`),
|
|
1177
1199
|
});
|
|
1178
1200
|
}
|
|
1179
|
-
}
|
|
1180
|
-
else {
|
|
1201
|
+
} else {
|
|
1181
1202
|
userStruct = NamedObject.create({
|
|
1182
1203
|
id: user.id,
|
|
1183
1204
|
name: (user.firstName || user.lastName) ? (user.firstName + ' ' + user.lastName) : user.email,
|
|
@@ -1220,4 +1241,85 @@ export class AuthenticatedStructures {
|
|
|
1220
1241
|
static async balanceItemsWithPayments(balanceItems: BalanceItem[]) {
|
|
1221
1242
|
return await BalanceItem.getStructureWithPayments(balanceItems);
|
|
1222
1243
|
}
|
|
1244
|
+
|
|
1245
|
+
static async memberRegistrationInvitations(invitations: RegistrationInvitation[]): Promise<Map<string, MemberRegistrationInvitation[]>> {
|
|
1246
|
+
const results = new Map<string, MemberRegistrationInvitation[]>();
|
|
1247
|
+
const groups = await Group.getByIDs(...invitations.map(i => i.groupId));
|
|
1248
|
+
|
|
1249
|
+
for (const invitation of invitations) {
|
|
1250
|
+
const group = groups.find(g => g.id === invitation.groupId);
|
|
1251
|
+
if (!group) {
|
|
1252
|
+
throw new SimpleError({
|
|
1253
|
+
code: 'group_not_found',
|
|
1254
|
+
message: 'Group not found',
|
|
1255
|
+
human: $t(`%1SM`),
|
|
1256
|
+
});
|
|
1257
|
+
}
|
|
1258
|
+
|
|
1259
|
+
const result = MemberRegistrationInvitation.create({
|
|
1260
|
+
id: invitation.id,
|
|
1261
|
+
group: InvitationGroupData.create({
|
|
1262
|
+
id: invitation.groupId,
|
|
1263
|
+
name: group.settings.name,
|
|
1264
|
+
type: group.type,
|
|
1265
|
+
periodId: group.periodId,
|
|
1266
|
+
}),
|
|
1267
|
+
organizationId: invitation.organizationId,
|
|
1268
|
+
createdAt: invitation.createdAt,
|
|
1269
|
+
});
|
|
1270
|
+
|
|
1271
|
+
let array = results.get(invitation.memberId);
|
|
1272
|
+
if (!array) {
|
|
1273
|
+
array = [result];
|
|
1274
|
+
results.set(invitation.memberId, array);
|
|
1275
|
+
} else {
|
|
1276
|
+
array.push(result);
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
|
|
1280
|
+
return results;
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1283
|
+
static async registrationInvitations(invitations: RegistrationInvitation[]): Promise<RegistrationInvitationStruct[]> {
|
|
1284
|
+
const members = await Member.getByIDs(...invitations.map(i => i.memberId));
|
|
1285
|
+
const groups = await Group.getByIDs(...invitations.map(i => i.groupId));
|
|
1286
|
+
|
|
1287
|
+
return invitations.map((invitation) => {
|
|
1288
|
+
const member = members.find(m => m.id === invitation.memberId);
|
|
1289
|
+
if (!member) {
|
|
1290
|
+
throw new SimpleError({
|
|
1291
|
+
code: 'member_not_found',
|
|
1292
|
+
message: 'Member not found',
|
|
1293
|
+
human: $t(`%EO`),
|
|
1294
|
+
});
|
|
1295
|
+
}
|
|
1296
|
+
|
|
1297
|
+
const group = groups.find(g => g.id === invitation.groupId);
|
|
1298
|
+
if (!group) {
|
|
1299
|
+
throw new SimpleError({
|
|
1300
|
+
code: 'group_not_found',
|
|
1301
|
+
message: 'Group not found',
|
|
1302
|
+
human: $t(`%1SM`),
|
|
1303
|
+
});
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1306
|
+
return RegistrationInvitationStruct.create({
|
|
1307
|
+
id: invitation.id,
|
|
1308
|
+
group: InvitationGroupData.create({
|
|
1309
|
+
id: group.id,
|
|
1310
|
+
name: group.settings.name,
|
|
1311
|
+
type: group.type,
|
|
1312
|
+
periodId: group.periodId,
|
|
1313
|
+
}),
|
|
1314
|
+
organizationId: invitation.organizationId,
|
|
1315
|
+
member: InvitationMemberData.create({
|
|
1316
|
+
id: member.id,
|
|
1317
|
+
firstName: member.firstName,
|
|
1318
|
+
lastName: member.lastName,
|
|
1319
|
+
birthDay: member.details.birthDay,
|
|
1320
|
+
}),
|
|
1321
|
+
createdAt: invitation.createdAt,
|
|
1322
|
+
});
|
|
1323
|
+
});
|
|
1324
|
+
}
|
|
1223
1325
|
}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import type { Organization, RegistrationPeriod, Webshop } from '@stamhoofd/models';
|
|
2
|
+
import { BalanceItem, BalanceItemFactory, GroupFactory, MemberFactory, OrganizationFactory, OrganizationRegistrationPeriodFactory, Order, RegistrationFactory, RegistrationPeriodFactory, WebshopFactory } from '@stamhoofd/models';
|
|
3
|
+
import { BalanceItemRelation, BalanceItemRelationType, BalanceItemType, OrderData, ReduceablePrice, TranslatedString } from '@stamhoofd/structures';
|
|
4
|
+
import { TestUtils } from '@stamhoofd/test-utils';
|
|
5
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
6
|
+
import { backfillBalanceItemRelations } from './BalanceItemRelationsBackfiller.js';
|
|
7
|
+
|
|
8
|
+
describe('helper.BalanceItemRelationsBackfiller', () => {
|
|
9
|
+
let period: RegistrationPeriod;
|
|
10
|
+
|
|
11
|
+
beforeAll(async () => {
|
|
12
|
+
period = await new RegistrationPeriodFactory({
|
|
13
|
+
startDate: new Date(2023, 0, 1),
|
|
14
|
+
endDate: new Date(2030, 11, 31),
|
|
15
|
+
}).create();
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
beforeEach(() => {
|
|
19
|
+
TestUtils.setEnvironment('userMode', 'platform');
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
async function createOrder(organization: Organization, webshop: Webshop) {
|
|
23
|
+
const order = new Order();
|
|
24
|
+
order.organizationId = organization.id;
|
|
25
|
+
order.webshopId = webshop.id;
|
|
26
|
+
order.data = OrderData.create({});
|
|
27
|
+
await order.save();
|
|
28
|
+
return order;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
it('fills member, group and group price relations for registration balance items', async () => {
|
|
32
|
+
const organization = await new OrganizationFactory({ period }).create();
|
|
33
|
+
await new OrganizationRegistrationPeriodFactory({ organization, period }).create();
|
|
34
|
+
|
|
35
|
+
const member = await new MemberFactory({ organization, firstName: 'John', lastName: 'Doe' }).create();
|
|
36
|
+
const group = await new GroupFactory({ organization, period }).create();
|
|
37
|
+
const registration = await new RegistrationFactory({ member, group }).create();
|
|
38
|
+
|
|
39
|
+
const balanceItem = await new BalanceItemFactory({
|
|
40
|
+
organizationId: organization.id,
|
|
41
|
+
memberId: member.id,
|
|
42
|
+
registrationId: registration.id,
|
|
43
|
+
type: BalanceItemType.Registration,
|
|
44
|
+
amount: 1,
|
|
45
|
+
unitPrice: 25_00,
|
|
46
|
+
}).create();
|
|
47
|
+
|
|
48
|
+
expect(balanceItem.relations.size).toBe(0);
|
|
49
|
+
|
|
50
|
+
await backfillBalanceItemRelations();
|
|
51
|
+
|
|
52
|
+
const updated = await BalanceItem.getByID(balanceItem.id);
|
|
53
|
+
expect(updated?.relations.get(BalanceItemRelationType.Member)).toMatchObject({ id: member.id });
|
|
54
|
+
expect(updated?.relations.get(BalanceItemRelationType.Member)?.name.toString()).toBe('John Doe');
|
|
55
|
+
expect(updated?.relations.get(BalanceItemRelationType.Group)).toMatchObject({ id: group.id });
|
|
56
|
+
// Only one price configured, so no group price relation
|
|
57
|
+
expect(updated?.relations.has(BalanceItemRelationType.GroupPrice)).toBe(false);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('fills the group price relation when the group has multiple prices', async () => {
|
|
61
|
+
const organization = await new OrganizationFactory({ period }).create();
|
|
62
|
+
await new OrganizationRegistrationPeriodFactory({ organization, period }).create();
|
|
63
|
+
|
|
64
|
+
const member = await new MemberFactory({ organization }).create();
|
|
65
|
+
const group = await new GroupFactory({ organization, period }).create();
|
|
66
|
+
|
|
67
|
+
// Add a second price so the relation should be filled
|
|
68
|
+
group.settings.prices.push(group.settings.prices[0].clone());
|
|
69
|
+
group.settings.prices[1].id = uuidv4();
|
|
70
|
+
group.settings.prices[1].name = new TranslatedString('Late price');
|
|
71
|
+
group.settings.prices[1].price = ReduceablePrice.create({ price: 30_00 });
|
|
72
|
+
await group.save();
|
|
73
|
+
|
|
74
|
+
const registration = await new RegistrationFactory({ member, group, groupPrice: group.settings.prices[1] }).create();
|
|
75
|
+
|
|
76
|
+
const balanceItem = await new BalanceItemFactory({
|
|
77
|
+
organizationId: organization.id,
|
|
78
|
+
memberId: member.id,
|
|
79
|
+
registrationId: registration.id,
|
|
80
|
+
type: BalanceItemType.Registration,
|
|
81
|
+
amount: 1,
|
|
82
|
+
unitPrice: 30_00,
|
|
83
|
+
}).create();
|
|
84
|
+
|
|
85
|
+
await backfillBalanceItemRelations();
|
|
86
|
+
|
|
87
|
+
const updated = await BalanceItem.getByID(balanceItem.id);
|
|
88
|
+
expect(updated?.relations.get(BalanceItemRelationType.GroupPrice)).toMatchObject({ id: group.settings.prices[1].id });
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('copies the registration period dates onto the balance item', async () => {
|
|
92
|
+
const organization = await new OrganizationFactory({ period }).create();
|
|
93
|
+
await new OrganizationRegistrationPeriodFactory({ organization, period }).create();
|
|
94
|
+
|
|
95
|
+
const member = await new MemberFactory({ organization }).create();
|
|
96
|
+
const group = await new GroupFactory({ organization, period }).create();
|
|
97
|
+
const registration = await new RegistrationFactory({ member, group }).create();
|
|
98
|
+
|
|
99
|
+
const startDate = new Date(2024, 7, 1);
|
|
100
|
+
const endDate = new Date(2025, 6, 31);
|
|
101
|
+
registration.startDate = startDate;
|
|
102
|
+
registration.endDate = endDate;
|
|
103
|
+
await registration.save();
|
|
104
|
+
|
|
105
|
+
const balanceItem = await new BalanceItemFactory({
|
|
106
|
+
organizationId: organization.id,
|
|
107
|
+
memberId: member.id,
|
|
108
|
+
registrationId: registration.id,
|
|
109
|
+
type: BalanceItemType.Registration,
|
|
110
|
+
amount: 1,
|
|
111
|
+
unitPrice: 25_00,
|
|
112
|
+
}).create();
|
|
113
|
+
|
|
114
|
+
await backfillBalanceItemRelations();
|
|
115
|
+
|
|
116
|
+
const updated = await BalanceItem.getByID(balanceItem.id);
|
|
117
|
+
expect(updated?.startDate?.getTime()).toBe(startDate.getTime());
|
|
118
|
+
expect(updated?.endDate?.getTime()).toBe(endDate.getTime());
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it('fills the webshop relation for order balance items', async () => {
|
|
122
|
+
const organization = await new OrganizationFactory({ period }).create();
|
|
123
|
+
const webshop = await new WebshopFactory({ organizationId: organization.id, name: 'My webshop' }).create();
|
|
124
|
+
const order = await createOrder(organization, webshop);
|
|
125
|
+
|
|
126
|
+
const balanceItem = await new BalanceItemFactory({
|
|
127
|
+
organizationId: organization.id,
|
|
128
|
+
orderId: order.id,
|
|
129
|
+
type: BalanceItemType.Order,
|
|
130
|
+
amount: 1,
|
|
131
|
+
unitPrice: 12_00,
|
|
132
|
+
}).create();
|
|
133
|
+
|
|
134
|
+
expect(balanceItem.relations.size).toBe(0);
|
|
135
|
+
|
|
136
|
+
await backfillBalanceItemRelations();
|
|
137
|
+
|
|
138
|
+
const updated = await BalanceItem.getByID(balanceItem.id);
|
|
139
|
+
expect(updated?.relations.get(BalanceItemRelationType.Webshop)).toMatchObject({ id: webshop.id });
|
|
140
|
+
expect(updated?.relations.get(BalanceItemRelationType.Webshop)?.name.toString()).toBe('My webshop');
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it('does not overwrite existing relations', async () => {
|
|
144
|
+
const organization = await new OrganizationFactory({ period }).create();
|
|
145
|
+
await new OrganizationRegistrationPeriodFactory({ organization, period }).create();
|
|
146
|
+
|
|
147
|
+
const member = await new MemberFactory({ organization }).create();
|
|
148
|
+
const group = await new GroupFactory({ organization, period }).create();
|
|
149
|
+
const registration = await new RegistrationFactory({ member, group }).create();
|
|
150
|
+
|
|
151
|
+
const existingRelations = new Map([
|
|
152
|
+
[
|
|
153
|
+
BalanceItemRelationType.Member,
|
|
154
|
+
BalanceItemRelation.create({ id: member.id, name: new TranslatedString('Custom name') }),
|
|
155
|
+
],
|
|
156
|
+
]);
|
|
157
|
+
|
|
158
|
+
const balanceItem = await new BalanceItemFactory({
|
|
159
|
+
organizationId: organization.id,
|
|
160
|
+
memberId: member.id,
|
|
161
|
+
registrationId: registration.id,
|
|
162
|
+
type: BalanceItemType.Registration,
|
|
163
|
+
amount: 1,
|
|
164
|
+
unitPrice: 25_00,
|
|
165
|
+
relations: existingRelations,
|
|
166
|
+
}).create();
|
|
167
|
+
|
|
168
|
+
await backfillBalanceItemRelations();
|
|
169
|
+
|
|
170
|
+
const updated = await BalanceItem.getByID(balanceItem.id);
|
|
171
|
+
expect(updated?.relations.size).toBe(1);
|
|
172
|
+
expect(updated?.relations.get(BalanceItemRelationType.Member)?.name.toString()).toBe('Custom name');
|
|
173
|
+
});
|
|
174
|
+
});
|