@stamhoofd/backend 2.115.1 → 2.117.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/migrations.ts +1 -1
- package/package.json +10 -10
- package/src/audit-logs/DocumentTemplateLogger.ts +1 -1
- package/src/audit-logs/EmailAddressLogger.ts +1 -1
- package/src/audit-logs/EmailLogger.ts +1 -1
- package/src/audit-logs/EmailTemplateLogger.ts +1 -1
- package/src/audit-logs/EventLogger.ts +1 -1
- package/src/audit-logs/GroupLogger.ts +1 -1
- package/src/audit-logs/MemberLogger.ts +1 -1
- package/src/audit-logs/MemberPlatformMembershipLogger.ts +1 -1
- package/src/audit-logs/MemberResponsibilityRecordLogger.ts +1 -1
- package/src/audit-logs/ModelLogger.ts +27 -19
- package/src/audit-logs/OrderLogger.ts +1 -1
- package/src/audit-logs/OrganizationLogger.ts +23 -3
- package/src/audit-logs/OrganizationRegistrationPeriodLogger.ts +1 -1
- package/src/audit-logs/PaymentLogger.ts +1 -1
- package/src/audit-logs/PlatformLogger.ts +1 -1
- package/src/audit-logs/RegistrationLogger.ts +1 -1
- package/src/audit-logs/RegistrationPeriodLogger.ts +1 -1
- package/src/audit-logs/StripeAccountLogger.ts +1 -1
- package/src/audit-logs/UserLogger.ts +1 -1
- package/src/audit-logs/WebshopLogger.ts +1 -1
- package/src/audit-logs/init.ts +40 -0
- package/src/boot.ts +6 -4
- package/src/crons/amazon-ses.ts +1 -1
- package/src/crons/balance-emails.ts +1 -1
- package/src/crons/clearExcelCache.test.ts +1 -1
- package/src/crons/delete-archived-data.ts +47 -0
- package/src/crons/endFunctionsOfUsersWithoutRegistration.ts +1 -1
- package/src/crons/index.ts +1 -0
- package/src/crons.ts +3 -3
- package/src/debug.ts +230 -0
- package/src/email-recipient-loaders/documents.ts +1 -1
- package/src/email-recipient-loaders/members.ts +1 -1
- package/src/email-recipient-loaders/orders.ts +3 -3
- package/src/email-recipient-loaders/payments.ts +118 -353
- package/src/email-replacements/getEmailReplacementsForPayment.ts +321 -0
- package/src/endpoints/admin/members/ChargeMembersEndpoint.ts +9 -7
- package/src/endpoints/admin/memberships/ChargeMembershipsEndpoint.ts +2 -2
- package/src/endpoints/admin/memberships/GetChargeMembershipsSummaryEndpoint.ts +1 -1
- package/src/endpoints/admin/organizations/ChargeOrganizationsEndpoint.ts +16 -50
- package/src/endpoints/admin/organizations/GetOrganizationsCountEndpoint.ts +2 -2
- package/src/endpoints/admin/organizations/GetOrganizationsEndpoint.ts +4 -4
- package/src/endpoints/admin/organizations/PatchOrganizationsEndpoint.ts +21 -6
- package/src/endpoints/admin/registrations/ChargeRegistrationsEndpoint.ts +9 -7
- package/src/endpoints/auth/CreateAdminEndpoint.ts +2 -2
- package/src/endpoints/auth/CreateTokenEndpoint.test.ts +2 -2
- package/src/endpoints/auth/CreateTokenEndpoint.ts +1 -1
- package/src/endpoints/auth/DeleteTokenEndpoint.ts +1 -1
- package/src/endpoints/auth/DeleteUserEndpoint.ts +1 -1
- package/src/endpoints/auth/ForgotPasswordEndpoint.ts +1 -1
- package/src/endpoints/auth/GetOtherUserEndpoint.ts +2 -2
- package/src/endpoints/auth/GetUserEndpoint.test.ts +2 -2
- package/src/endpoints/auth/GetUserEndpoint.ts +2 -2
- package/src/endpoints/auth/OpenIDConnectAuthTokenEndpoint.ts +2 -2
- package/src/endpoints/auth/OpenIDConnectCallbackEndpoint.ts +2 -2
- package/src/endpoints/auth/OpenIDConnectStartEndpoint.ts +2 -2
- package/src/endpoints/auth/PatchUserEndpoint.ts +4 -4
- package/src/endpoints/auth/PollEmailVerificationEndpoint.ts +1 -1
- package/src/endpoints/auth/RetryEmailVerificationEndpoint.ts +1 -1
- package/src/endpoints/auth/SignupEndpoint.ts +1 -1
- package/src/endpoints/auth/VerifyEmailEndpoint.ts +1 -1
- package/src/endpoints/global/addresses/ValidateAddressEndpoint.ts +1 -1
- package/src/endpoints/global/audit-logs/GetAuditLogsEndpoint.ts +4 -4
- package/src/endpoints/global/billing/ActivatePackagesEndpoint.ts +191 -7
- package/src/endpoints/global/billing/DeactivatePackageEndpoint.ts +64 -0
- package/src/endpoints/global/email/GetAdminEmailsEndpoint.test.ts +2 -2
- package/src/endpoints/global/email/GetAdminEmailsEndpoint.ts +3 -3
- package/src/endpoints/global/email/GetEmailAddressEndpoint.ts +1 -1
- package/src/endpoints/global/email/GetEmailEndpoint.ts +1 -1
- package/src/endpoints/global/email/GetUserEmailsEndpoint.test.ts +2 -2
- package/src/endpoints/global/email/GetUserEmailsEndpoint.ts +3 -3
- package/src/endpoints/global/email/ManageEmailAddressEndpoint.ts +62 -16
- package/src/endpoints/global/email/PatchEmailEndpoint.test.ts +6 -6
- package/src/endpoints/global/email-recipients/GetEmailRecipientsCountEndpoint.ts +2 -2
- package/src/endpoints/global/email-recipients/GetEmailRecipientsEndpoint.test.ts +2 -2
- package/src/endpoints/global/email-recipients/GetEmailRecipientsEndpoint.ts +4 -4
- package/src/endpoints/global/email-recipients/RetryEmailRecipientEndpoint.ts +1 -1
- package/src/endpoints/global/email-recipients/helpers/validateEmailRecipientFilter.ts +1 -1
- package/src/endpoints/global/events/GetEventNotificationsCountEndpoint.ts +2 -2
- package/src/endpoints/global/events/GetEventNotificationsEndpoint.ts +4 -4
- package/src/endpoints/global/events/GetEventsEndpoint.ts +4 -4
- package/src/endpoints/global/events/PatchEventNotificationsEndpoint.test.ts +2 -2
- package/src/endpoints/global/events/PatchEventNotificationsEndpoint.ts +3 -3
- package/src/endpoints/global/events/PatchEventsEndpoint.test.ts +2 -2
- package/src/endpoints/global/events/PatchEventsEndpoint.ts +5 -5
- package/src/endpoints/global/files/ExportToExcelEndpoint.ts +4 -4
- package/src/endpoints/global/files/GetFileCache.ts +2 -2
- package/src/endpoints/global/files/UploadFile.ts +2 -2
- package/src/endpoints/global/files/UploadImage.ts +1 -1
- package/src/endpoints/global/groups/GetGroupsEndpoint.test.ts +3 -3
- package/src/endpoints/global/groups/GetGroupsEndpoint.ts +4 -4
- package/src/endpoints/global/members/GetMemberFamilyEndpoint.ts +4 -4
- package/src/endpoints/global/members/GetMembersEndpoint.test.ts +3 -3
- package/src/endpoints/global/members/GetMembersEndpoint.ts +4 -16
- package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.ts +8 -7
- package/src/endpoints/global/members/helpers/validateGroupFilter.ts +1 -1
- package/src/endpoints/global/organizations/CreateOrganizationEndpoint.test.ts +2 -2
- package/src/endpoints/global/organizations/CreateOrganizationEndpoint.ts +23 -12
- package/src/endpoints/global/organizations/GetOrganizationFromDomainEndpoint.test.ts +2 -2
- package/src/endpoints/global/organizations/GetOrganizationFromDomainEndpoint.ts +1 -1
- package/src/endpoints/global/organizations/GetOrganizationFromUriEndpoint.ts +1 -1
- package/src/endpoints/global/organizations/SearchOrganizationEndpoint.test.ts +2 -2
- package/src/endpoints/global/organizations/SearchOrganizationEndpoint.ts +1 -1
- package/src/endpoints/global/payments/StripeWebhookEndpoint.ts +3 -3
- package/src/endpoints/global/platform/GetPlatformAdminsEndpoint.ts +1 -1
- package/src/endpoints/global/platform/GetPlatformEndpoint.test.ts +2 -2
- package/src/endpoints/global/platform/GetPlatformEndpoint.ts +1 -1
- package/src/endpoints/global/platform/PatchPlatformEnpoint.test.ts +2 -2
- package/src/endpoints/global/platform/PatchPlatformEnpoint.ts +7 -7
- package/src/endpoints/global/registration/GetRegistrationsEndpoint.test.ts +2 -2
- package/src/endpoints/global/registration/GetRegistrationsEndpoint.ts +1 -2
- package/src/endpoints/global/registration/GetUserDetailedPayableBalanceEndpoint.ts +2 -2
- package/src/endpoints/global/registration/GetUserDocumentsEndpoint.ts +2 -2
- package/src/endpoints/global/registration/GetUserMembersEndpoint.ts +2 -2
- package/src/endpoints/global/registration/GetUserPayableBalanceEndpoint.ts +2 -2
- package/src/endpoints/global/registration/RegisterMembersEndpoint.test.ts +2 -2
- package/src/endpoints/global/registration/RegisterMembersEndpoint.ts +24 -389
- package/src/endpoints/global/registration-periods/GetRegistrationPeriodsEndpoint.ts +3 -3
- package/src/endpoints/global/registration-periods/PatchRegistrationPeriodsEndpoint.ts +2 -2
- package/src/endpoints/global/sso/GetSSOEndpoint.ts +2 -2
- package/src/endpoints/global/sso/SetSSOEndpoint.ts +3 -3
- package/src/endpoints/organization/dashboard/balance-items/GetBalanceItemEndpoint.ts +55 -0
- package/src/endpoints/organization/dashboard/balance-items/GetBalanceItemsCountEndpoint.ts +43 -0
- package/src/endpoints/organization/dashboard/balance-items/GetBalanceItemsEndpoint.ts +160 -0
- package/src/endpoints/organization/dashboard/{payments → balance-items}/PatchBalanceItemsEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/billing/GetOrganizationDetailedPayableBalanceEndpoint.ts +2 -2
- package/src/endpoints/organization/dashboard/billing/GetOrganizationPayableBalanceEndpoint.ts +2 -2
- package/src/endpoints/organization/dashboard/billing/GetPackagesEndpoint.test.ts +3 -3
- package/src/endpoints/organization/dashboard/billing/GetPackagesEndpoint.ts +3 -3
- package/src/endpoints/organization/dashboard/documents/GetDocumentTemplateXML.ts +1 -1
- package/src/endpoints/organization/dashboard/documents/GetDocumentsCountEndpoint.ts +2 -2
- package/src/endpoints/organization/dashboard/documents/PatchDocumentEndpoint.ts +2 -2
- package/src/endpoints/organization/dashboard/email/CheckEmailBouncesEndpoint.ts +37 -6
- package/src/endpoints/organization/dashboard/email-templates/GetEmailTemplatesEndpoint.test.ts +2 -2
- package/src/endpoints/organization/dashboard/email-templates/GetEmailTemplatesEndpoint.ts +3 -3
- package/src/endpoints/organization/dashboard/email-templates/PatchEmailTemplatesEndpoint.test.ts +2 -2
- package/src/endpoints/organization/dashboard/email-templates/PatchEmailTemplatesEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/invoices/PatchInvoicesEndpoint.ts +53 -0
- package/src/endpoints/organization/dashboard/mollie/CheckMollieEndpoint.ts +2 -2
- package/src/endpoints/organization/dashboard/mollie/ConnectMollieEndpoint.ts +3 -3
- package/src/endpoints/organization/dashboard/mollie/DisconnectMollieEndpoint.ts +2 -2
- package/src/endpoints/organization/dashboard/mollie/GetMollieDashboardEndpoint.ts +1 -1
- 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 +2 -2
- package/src/endpoints/organization/dashboard/organization/GetUitpasClientIdEndpoint.ts +2 -2
- package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.test.ts +2 -2
- package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.ts +12 -1
- package/src/endpoints/organization/dashboard/organization/SearchUitpasOrganizersEndpoint.ts +2 -2
- package/src/endpoints/organization/dashboard/organization/SetOrganizationDomainEndpoint.ts +2 -2
- package/src/endpoints/organization/dashboard/organization/SetUitpasClientCredentialsEndpoint.ts +2 -2
- package/src/endpoints/organization/dashboard/payments/GetPaymentsCountEndpoint.ts +2 -2
- package/src/endpoints/organization/dashboard/payments/GetPaymentsEndpoint.ts +4 -4
- package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalanceEndpoint.ts +12 -12
- package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalancesCountEndpoint.ts +2 -2
- package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalancesEndpoint.ts +4 -4
- package/src/endpoints/organization/dashboard/registration-periods/GetOrganizationRegistrationPeriodsEndpoint.test.ts +2 -2
- package/src/endpoints/organization/dashboard/registration-periods/GetOrganizationRegistrationPeriodsEndpoint.ts +4 -4
- package/src/endpoints/organization/dashboard/registration-periods/MoveRegistrationPeriods.test.ts +2 -2
- package/src/endpoints/organization/dashboard/registration-periods/PatchOrganizationRegistrationPeriodsEndpoint.test.ts +2 -2
- package/src/endpoints/organization/dashboard/registration-periods/PatchOrganizationRegistrationPeriodsEndpoint.ts +3 -3
- package/src/endpoints/organization/dashboard/registration-periods/SetupStepReviewEndpoint.ts +2 -2
- package/src/endpoints/organization/dashboard/stripe/ConnectStripeEndpoint.ts +3 -3
- package/src/endpoints/organization/dashboard/stripe/DeleteStripeAccountEndpoint.ts +3 -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 +3 -3
- package/src/endpoints/organization/dashboard/users/CreateApiUserEndpoint.test.ts +3 -3
- 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.test.ts +3 -3
- package/src/endpoints/organization/dashboard/users/PatchApiUserEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/webshops/CreateWebshopEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/webshops/DeleteWebshopEndpoint.ts +2 -2
- package/src/endpoints/organization/dashboard/webshops/GetDiscountCodesEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/webshops/GetWebshopOrdersCountEndpoint.ts +2 -2
- package/src/endpoints/organization/dashboard/webshops/GetWebshopOrdersEndpoint.ts +5 -5
- package/src/endpoints/organization/dashboard/webshops/GetWebshopTicketsEndpoint.ts +5 -5
- package/src/endpoints/organization/dashboard/webshops/GetWebshopUriAvailabilityEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/webshops/PatchDiscountCodesEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/webshops/PatchWebshopEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/webshops/PatchWebshopOrdersEndpoint.ts +1 -1
- 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 +1 -1
- package/src/endpoints/organization/shared/ExchangePaymentEndpoint.ts +3 -3
- package/src/endpoints/organization/shared/GetDocumentHtml.ts +1 -1
- package/src/endpoints/organization/shared/GetPaymentEndpoint.ts +2 -2
- package/src/endpoints/organization/shared/auth/GetOrganizationEndpoint.test.ts +2 -2
- package/src/endpoints/organization/shared/auth/GetOrganizationEndpoint.ts +2 -2
- package/src/endpoints/organization/webshops/CheckWebshopDiscountCodesEndpoint.ts +1 -1
- package/src/endpoints/organization/webshops/GetOrderByPaymentEndpoint.ts +1 -1
- package/src/endpoints/organization/webshops/GetOrderEndpoint.ts +1 -1
- package/src/endpoints/organization/webshops/GetTicketsEndpoint.ts +1 -1
- package/src/endpoints/organization/webshops/GetWebshopEndpoint.test.ts +2 -2
- package/src/endpoints/organization/webshops/GetWebshopEndpoint.ts +2 -2
- package/src/endpoints/organization/webshops/PlaceOrderEndpoint.test.ts +4 -4
- package/src/excel-loaders/balance-items.ts +268 -0
- package/src/excel-loaders/event-notifications.ts +3 -3
- package/src/excel-loaders/index.ts +6 -5
- package/src/excel-loaders/organizations.ts +4 -4
- package/src/excel-loaders/payments.ts +11 -3
- package/src/excel-loaders/receivable-balances.ts +2 -2
- package/src/helpers/AddressValidator.test.ts +1 -1
- package/src/helpers/AddressValidator.ts +1 -1
- package/src/helpers/AdminPermissionChecker.ts +20 -17
- package/src/helpers/AuthenticatedStructures.ts +194 -109
- package/src/helpers/Context.ts +2 -0
- package/src/helpers/EmailResumer.ts +1 -1
- package/src/helpers/FlagMomentCleanup.ts +1 -1
- package/src/helpers/ForwardHandler.test.ts +1 -1
- package/src/helpers/ForwardHandler.ts +1 -1
- package/src/helpers/GlobalHelper.ts +4 -4
- package/src/helpers/GroupBuilder.ts +417 -0
- package/src/helpers/GroupedThrottledQueue.test.ts +1 -1
- package/src/helpers/GroupedThrottledQueue.ts +1 -1
- package/src/helpers/MemberUserSyncer.test.ts +1 -1
- package/src/helpers/MemberUserSyncer.ts +1 -1
- package/src/helpers/PeriodHelper.ts +5 -45
- package/src/helpers/ServiceFeeHelper.ts +5 -1
- package/src/helpers/SetupStepUpdater.ts +5 -4
- package/src/helpers/TagHelper.ts +1 -1
- package/src/helpers/ThrottledQueue.test.ts +1 -1
- package/src/helpers/ViesHelper.ts +9 -0
- package/src/helpers/email-html-helpers.ts +0 -41
- package/src/helpers/outstandingBalanceJoin.ts +3 -1
- package/src/middleware/ContextMiddleware.ts +1 -1
- package/src/seeds/1726572303-schedule-stock-updates.ts +1 -1
- package/src/seeds/1726847064-setup-steps.ts +1 -1
- package/src/seeds/1728928974-update-cached-outstanding-balance-from-items.ts +1 -1
- package/src/seeds/1740046783-update-membership.ts +1 -1
- package/src/seeds/1754560914-groups-prices.test.ts +1 -1
- package/src/seeds/1755876819-remove-duplicate-members.ts +1 -1
- package/src/seeds/1760702454-update-cached-outstanding-balance-from-items.ts +1 -1
- package/src/seeds/1761665607-sync-member-users.ts +1 -1
- package/src/seeds/data/default-email-templates.sql +1 -1
- package/src/seeds-temporary/1732117645-move-rrn.ts +1 -1
- package/src/services/AuditLogService.ts +1 -41
- package/src/services/BalanceItemPaymentService.ts +1 -1
- package/src/services/BalanceItemService.ts +12 -5
- package/src/services/EventNotificationService.ts +3 -3
- package/src/services/InvoiceService.ts +131 -17
- package/src/services/MemberRecordStore.ts +1 -1
- package/src/services/PaymentReallocationService.test.ts +9 -10
- package/src/services/PaymentReallocationService.ts +1 -1
- package/src/services/PaymentService.ts +560 -18
- package/src/services/PlatformMembershipService.ts +3 -3
- package/src/services/RegistrationService.ts +3 -3
- package/src/services/SSOService.ts +2 -2
- package/src/services/STPackageService.ts +241 -0
- package/src/services/uitpas/UitpasService.test.ts +1 -1
- package/src/sql-filters/balance-items.ts +56 -0
- package/src/sql-filters/emails.ts +1 -1
- package/src/sql-filters/event-notifications.ts +2 -2
- package/src/sql-filters/events.ts +51 -0
- package/src/sql-filters/members.ts +38 -2
- package/src/sql-filters/receivable-balances.ts +3 -3
- package/src/sql-filters/users.ts +10 -0
- package/src/sql-sorters/balance-items.ts +36 -0
- package/src/sql-sorters/document-templates.ts +2 -2
- package/src/sql-sorters/documents.ts +2 -2
- package/src/sql-sorters/event-notifications.ts +1 -1
- package/src/sql-sorters/members.ts +2 -2
- package/src/sql-sorters/orders.ts +2 -2
- package/src/sql-sorters/tickets.ts +2 -2
- package/tests/actions/patchOrganizationMember.ts +3 -3
- package/tests/actions/patchPaymentStatus.ts +3 -3
- package/tests/actions/patchUserMember.ts +2 -2
- package/tests/assertions/assertBalances.ts +1 -1
- package/tests/e2e/api-rate-limits.test.ts +3 -3
- package/tests/e2e/charge-members.test.ts +14 -14
- package/tests/e2e/documents.test.ts +8 -8
- package/tests/e2e/private-files.test.ts +4 -4
- package/tests/e2e/register.test.ts +10 -10
- package/tests/e2e/stock.test.ts +4 -4
- package/tests/e2e/tickets.test.ts +4 -4
- package/tests/helpers/TestServer.ts +2 -2
- package/tests/init/index.ts +7 -7
- package/tests/init/initAdmin.ts +1 -1
- package/src/endpoints/global/registration/GetPaymentRegistrations.ts +0 -67
|
@@ -4,8 +4,8 @@ import { PermissionLevel, Permissions, PlatformConfig, Platform as PlatformStruc
|
|
|
4
4
|
|
|
5
5
|
import { AutoEncoderPatchType } from '@simonbackx/simple-encoding';
|
|
6
6
|
import { TestUtils } from '@stamhoofd/test-utils';
|
|
7
|
-
import { testServer } from '../../../../tests/helpers/TestServer';
|
|
8
|
-
import { PatchPlatformEndpoint } from './PatchPlatformEnpoint';
|
|
7
|
+
import { testServer } from '../../../../tests/helpers/TestServer.js';
|
|
8
|
+
import { PatchPlatformEndpoint } from './PatchPlatformEnpoint.js';
|
|
9
9
|
|
|
10
10
|
describe('Endpoint.PatchPlatform', () => {
|
|
11
11
|
// Test endpoint
|
|
@@ -5,13 +5,13 @@ import { MemberResponsibility, PlatformConfig, PlatformPremiseType, Platform as
|
|
|
5
5
|
|
|
6
6
|
import { SimpleError } from '@simonbackx/simple-errors';
|
|
7
7
|
import { QueueHandler } from '@stamhoofd/queues';
|
|
8
|
-
import { Context } from '../../../helpers/Context';
|
|
9
|
-
import { MembershipCharger } from '../../../helpers/MembershipCharger';
|
|
10
|
-
import { MemberUserSyncer } from '../../../helpers/MemberUserSyncer';
|
|
11
|
-
import { PeriodHelper } from '../../../helpers/PeriodHelper';
|
|
12
|
-
import { SetupStepUpdater } from '../../../helpers/SetupStepUpdater';
|
|
13
|
-
import { TagHelper } from '../../../helpers/TagHelper';
|
|
14
|
-
import { PlatformMembershipService } from '../../../services/PlatformMembershipService';
|
|
8
|
+
import { Context } from '../../../helpers/Context.js';
|
|
9
|
+
import { MembershipCharger } from '../../../helpers/MembershipCharger.js';
|
|
10
|
+
import { MemberUserSyncer } from '../../../helpers/MemberUserSyncer.js';
|
|
11
|
+
import { PeriodHelper } from '../../../helpers/PeriodHelper.js';
|
|
12
|
+
import { SetupStepUpdater } from '../../../helpers/SetupStepUpdater.js';
|
|
13
|
+
import { TagHelper } from '../../../helpers/TagHelper.js';
|
|
14
|
+
import { PlatformMembershipService } from '../../../services/PlatformMembershipService.js';
|
|
15
15
|
|
|
16
16
|
type Params = Record<string, never>;
|
|
17
17
|
type Query = undefined;
|
|
@@ -2,8 +2,8 @@ import { Request } from '@simonbackx/simple-endpoints';
|
|
|
2
2
|
import { EventFactory, GroupFactory, MemberFactory, OrganizationFactory, RegistrationFactory, RegistrationPeriod, RegistrationPeriodFactory, Token, UserFactory } from '@stamhoofd/models';
|
|
3
3
|
import { AccessRight, EventMeta, GroupType, LimitedFilteredRequest, NamedObject, PermissionLevel, PermissionRoleDetailed, Permissions, PermissionsResourceType, ResourcePermissions } from '@stamhoofd/structures';
|
|
4
4
|
import { STExpect, TestUtils } from '@stamhoofd/test-utils';
|
|
5
|
-
import { testServer } from '../../../../tests/helpers/TestServer';
|
|
6
|
-
import { GetRegistrationsEndpoint } from './GetRegistrationsEndpoint';
|
|
5
|
+
import { testServer } from '../../../../tests/helpers/TestServer.js';
|
|
6
|
+
import { GetRegistrationsEndpoint } from './GetRegistrationsEndpoint.js';
|
|
7
7
|
|
|
8
8
|
const baseUrl = `/registrations`;
|
|
9
9
|
const endpoint = new GetRegistrationsEndpoint();
|
|
@@ -3,10 +3,9 @@ import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-
|
|
|
3
3
|
import { SimpleError } from '@simonbackx/simple-errors';
|
|
4
4
|
import { Group, Member, Platform, Registration } from '@stamhoofd/models';
|
|
5
5
|
import { SQL, SQLExpression, SQLSelect, SQLSortDefinitions, applySQLSorter, compileToSQLFilter } from '@stamhoofd/sql';
|
|
6
|
-
import { CountFilteredRequest, GroupType, LimitedFilteredRequest, PaginatedResponse, PermissionLevel, RegistrationWithMemberBlob, StamhoofdFilter, assertSort } from '@stamhoofd/structures';
|
|
6
|
+
import { CountFilteredRequest, GroupType, LimitedFilteredRequest, PaginatedResponse, PermissionLevel, RegistrationWithMemberBlob, StamhoofdFilter, assertSort, RegistrationsBlob } from '@stamhoofd/structures';
|
|
7
7
|
|
|
8
8
|
import { SQLResultNamespacedRow } from '@simonbackx/simple-database';
|
|
9
|
-
import { RegistrationsBlob } from '@stamhoofd/structures/dist/src/members/RegistrationsBlob';
|
|
10
9
|
import { AuthenticatedStructures } from '../../../helpers/AuthenticatedStructures.js';
|
|
11
10
|
import { Context } from '../../../helpers/Context.js';
|
|
12
11
|
import { LimitedFilteredRequestHelper } from '../../../helpers/LimitedFilteredRequestHelper.js';
|
|
@@ -3,8 +3,8 @@ import { BalanceItem, Member, Organization, Payment } from '@stamhoofd/models';
|
|
|
3
3
|
import { DetailedPayableBalanceCollection, DetailedPayableBalance } from '@stamhoofd/structures';
|
|
4
4
|
|
|
5
5
|
import { Formatter } from '@stamhoofd/utility';
|
|
6
|
-
import { AuthenticatedStructures } from '../../../helpers/AuthenticatedStructures';
|
|
7
|
-
import { Context } from '../../../helpers/Context';
|
|
6
|
+
import { AuthenticatedStructures } from '../../../helpers/AuthenticatedStructures.js';
|
|
7
|
+
import { Context } from '../../../helpers/Context.js';
|
|
8
8
|
|
|
9
9
|
type Params = Record<string, never>;
|
|
10
10
|
type Query = undefined;
|
|
@@ -3,7 +3,7 @@ import { Document, DocumentTemplate, Member } from '@stamhoofd/models';
|
|
|
3
3
|
import { Document as DocumentStruct, DocumentStatus } from '@stamhoofd/structures';
|
|
4
4
|
import { Sorter } from '@stamhoofd/utility';
|
|
5
5
|
|
|
6
|
-
import { Context } from '../../../helpers/Context';
|
|
6
|
+
import { Context } from '../../../helpers/Context.js';
|
|
7
7
|
type Params = Record<string, never>;
|
|
8
8
|
type Query = undefined;
|
|
9
9
|
type Body = undefined;
|
|
@@ -31,7 +31,7 @@ export class GetUserDocumentsEndpoint extends Endpoint<Params, Query, Body, Resp
|
|
|
31
31
|
const organization = await Context.setUserOrganizationScope();
|
|
32
32
|
const { user } = await Context.authenticate();
|
|
33
33
|
|
|
34
|
-
const members = await Member.
|
|
34
|
+
const members = await Member.getMembersForUser(user);
|
|
35
35
|
let templates = organization ? await DocumentTemplate.where({ status: 'Published', organizationId: organization.id }) : null;
|
|
36
36
|
const memberIds = members.map(m => m.id);
|
|
37
37
|
const templateIds = templates ? templates.map(t => t.id) : null;
|
|
@@ -2,8 +2,8 @@ import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-
|
|
|
2
2
|
import { Member } from '@stamhoofd/models';
|
|
3
3
|
import { MembersBlob } from '@stamhoofd/structures';
|
|
4
4
|
|
|
5
|
-
import { AuthenticatedStructures } from '../../../helpers/AuthenticatedStructures';
|
|
6
|
-
import { Context } from '../../../helpers/Context';
|
|
5
|
+
import { AuthenticatedStructures } from '../../../helpers/AuthenticatedStructures.js';
|
|
6
|
+
import { Context } from '../../../helpers/Context.js';
|
|
7
7
|
|
|
8
8
|
type Params = Record<string, never>;
|
|
9
9
|
type Query = undefined;
|
|
@@ -3,8 +3,8 @@ import { CachedBalance, Organization } from '@stamhoofd/models';
|
|
|
3
3
|
import { PayableBalance, PayableBalanceCollection, ReceivableBalanceType } from '@stamhoofd/structures';
|
|
4
4
|
|
|
5
5
|
import { Formatter } from '@stamhoofd/utility';
|
|
6
|
-
import { AuthenticatedStructures } from '../../../helpers/AuthenticatedStructures';
|
|
7
|
-
import { Context } from '../../../helpers/Context';
|
|
6
|
+
import { AuthenticatedStructures } from '../../../helpers/AuthenticatedStructures.js';
|
|
7
|
+
import { Context } from '../../../helpers/Context.js';
|
|
8
8
|
|
|
9
9
|
type Params = Record<string, never>;
|
|
10
10
|
type Query = undefined;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { PatchMap } from '@simonbackx/simple-encoding';
|
|
2
2
|
import { Request } from '@simonbackx/simple-endpoints';
|
|
3
3
|
import { EmailMocker } from '@stamhoofd/email';
|
|
4
|
-
import { BalanceItemFactory, Group, GroupFactory, Member, MemberFactory,
|
|
4
|
+
import { BalanceItemFactory, Group, GroupFactory, Member, MemberFactory, MemberWithUsersRegistrationsAndGroups, Organization, OrganizationFactory, OrganizationRegistrationPeriodFactory, Registration, RegistrationFactory, RegistrationPeriod, RegistrationPeriodFactory, Token, UserFactory } from '@stamhoofd/models';
|
|
5
5
|
import { AccessRight, BalanceItemCartItem, BalanceItemStatus, BalanceItemType, BooleanStatus, Company, GroupOption, GroupOptionMenu, IDRegisterCart, IDRegisterCheckout, IDRegisterItem, OrganizationPackages, PaymentCustomer, PaymentMethod, PermissionLevel, Permissions, PermissionsResourceType, ReduceablePrice, RegisterItemOption, ResourcePermissions, STPackageStatus, STPackageType, UitpasNumberDetails, UitpasSocialTariff, UitpasSocialTariffStatus, UserPermissions, Version } from '@stamhoofd/structures';
|
|
6
6
|
import { STExpect, TestUtils } from '@stamhoofd/test-utils';
|
|
7
7
|
import { v4 as uuidv4 } from 'uuid';
|
|
@@ -80,7 +80,7 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
80
80
|
const member = await new MemberFactory({ organization, user: linkMembersToUser ? user : undefined })
|
|
81
81
|
.create();
|
|
82
82
|
|
|
83
|
-
const otherMembers:
|
|
83
|
+
const otherMembers: MemberWithUsersRegistrationsAndGroups[] = [];
|
|
84
84
|
|
|
85
85
|
for (let i = 0; i < otherMemberAmount; i++) {
|
|
86
86
|
otherMembers.push(await new MemberFactory({ organization, user: linkMembersToUser ? user : undefined })
|
|
@@ -4,9 +4,9 @@ import { Decoder } from '@simonbackx/simple-encoding';
|
|
|
4
4
|
import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
|
|
5
5
|
import { SimpleError } from '@simonbackx/simple-errors';
|
|
6
6
|
import { Email } from '@stamhoofd/email';
|
|
7
|
-
import { BalanceItem, BalanceItemPayment, CachedBalance, Group, Member,
|
|
7
|
+
import { BalanceItem, BalanceItemPayment, CachedBalance, Group, Member, MemberWithUsersRegistrationsAndGroups, MolliePayment, MollieToken, Organization, PayconiqPayment, Payment, Platform, RateLimiter, Registration, User } from '@stamhoofd/models';
|
|
8
8
|
import { BalanceItemRelation, BalanceItemRelationType, BalanceItemStatus, BalanceItem as BalanceItemStruct, BalanceItemType, IDRegisterCheckout, PaymentCustomer, PaymentMethod, PaymentMethodHelper, PaymentProvider, PaymentStatus, Payment as PaymentStruct, PaymentType, PermissionLevel, PlatformFamily, PlatformMember, ReceivableBalanceType, RegisterItem, RegisterResponse, TranslatedString, Version } from '@stamhoofd/structures';
|
|
9
|
-
import { Formatter } from '@stamhoofd/utility';
|
|
9
|
+
import { Formatter, sleep } from '@stamhoofd/utility';
|
|
10
10
|
|
|
11
11
|
import { AuthenticatedStructures } from '../../../helpers/AuthenticatedStructures.js';
|
|
12
12
|
import { BuckarooHelper } from '../../../helpers/BuckarooHelper.js';
|
|
@@ -145,7 +145,7 @@ export class RegisterMembersEndpoint extends Endpoint<Params, Query, Body, Respo
|
|
|
145
145
|
memberBalanceItemsStructs = balanceItemsModels.map(i => i.getStructure());
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
-
let members:
|
|
148
|
+
let members: MemberWithUsersRegistrationsAndGroups[] = [];
|
|
149
149
|
if (request.body.asOrganizationId) {
|
|
150
150
|
const memberIds = Formatter.uniqueArray(
|
|
151
151
|
[...request.body.memberIds, ...deleteRegistrationModels.map(i => i.memberId), ...balanceItemsModels.map(i => i.memberId).filter(m => m !== null)],
|
|
@@ -205,6 +205,8 @@ export class RegisterMembersEndpoint extends Endpoint<Params, Query, Body, Respo
|
|
|
205
205
|
|
|
206
206
|
const platformMembers: PlatformMember[] = [];
|
|
207
207
|
|
|
208
|
+
let payingOrganization: Organization | null = null;
|
|
209
|
+
|
|
208
210
|
if (request.body.asOrganizationId) {
|
|
209
211
|
const memberIds = Formatter.uniqueArray(
|
|
210
212
|
[...request.body.memberIds, ...deleteRegistrationModels.map(i => i.memberId), ...balanceItemsModels.map(i => i.memberId).filter(m => m !== null)],
|
|
@@ -233,6 +235,7 @@ export class RegisterMembersEndpoint extends Endpoint<Params, Query, Body, Respo
|
|
|
233
235
|
platformMembers.push(platformMember);
|
|
234
236
|
}
|
|
235
237
|
|
|
238
|
+
payingOrganization = await Context.auth.getOrganization(request.body.asOrganizationId);
|
|
236
239
|
if (memberIds.length > 0 && request.body.asOrganizationId && request.body.asOrganizationId !== organization.id) {
|
|
237
240
|
// For registering members at a different organization, you need full permissions
|
|
238
241
|
if (!await Context.auth.hasFullAccess(request.body.asOrganizationId)) {
|
|
@@ -288,6 +291,7 @@ export class RegisterMembersEndpoint extends Endpoint<Params, Query, Body, Respo
|
|
|
288
291
|
if (whoWillPayNow === 'nobody') {
|
|
289
292
|
// Safe and important to ignore: we are only updating the outstanding amounts
|
|
290
293
|
// If we would throw here, that could leak personal data (e.g. that the user uses financial support)
|
|
294
|
+
request.body.totalPrice = totalPrice;
|
|
291
295
|
}
|
|
292
296
|
else {
|
|
293
297
|
// when whoWillPay = organization/member, we should throw or the payment amount could be different / incorrect.
|
|
@@ -450,37 +454,10 @@ export class RegisterMembersEndpoint extends Endpoint<Params, Query, Body, Respo
|
|
|
450
454
|
registrations.push(registration);
|
|
451
455
|
}
|
|
452
456
|
|
|
453
|
-
// Validate payment method
|
|
454
|
-
if (totalPrice > 0 && whoWillPayNow !== 'nobody') {
|
|
455
|
-
const allowedPaymentMethods = organization.meta.registrationPaymentConfiguration.getAvailablePaymentMethods({
|
|
456
|
-
amount: totalPrice,
|
|
457
|
-
customer: checkout.customer,
|
|
458
|
-
});
|
|
459
|
-
|
|
460
|
-
if (!checkout.paymentMethod || !allowedPaymentMethods.includes(checkout.paymentMethod)) {
|
|
461
|
-
throw new SimpleError({
|
|
462
|
-
code: 'invalid_payment_method',
|
|
463
|
-
message: $t(`2b1ca6a0-662e-4326-ada1-10239b6ddc6f`),
|
|
464
|
-
});
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
if ((checkout.paymentMethod !== PaymentMethod.Transfer && checkout.paymentMethod !== PaymentMethod.PointOfSale) && (!request.body.redirectUrl || !request.body.cancelUrl)) {
|
|
468
|
-
throw new SimpleError({
|
|
469
|
-
code: 'missing_fields',
|
|
470
|
-
message: 'redirectUrl or cancelUrl is missing and is required for non-zero online payments',
|
|
471
|
-
human: $t(`ebe54b63-2de6-4f22-a5ed-d3fe65194562`),
|
|
472
|
-
});
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
else {
|
|
476
|
-
checkout.paymentMethod = PaymentMethod.Unknown;
|
|
477
|
-
}
|
|
478
|
-
|
|
479
457
|
console.log('Registering members using whoWillPayNow', whoWillPayNow, checkout.paymentMethod, totalPrice);
|
|
480
458
|
|
|
481
459
|
const createdBalanceItems: BalanceItem[] = [];
|
|
482
460
|
const deletedBalanceItems: BalanceItem[] = [];
|
|
483
|
-
const shouldMarkValid = whoWillPayNow === 'nobody' || checkout.paymentMethod === PaymentMethod.Transfer || checkout.paymentMethod === PaymentMethod.PointOfSale || checkout.paymentMethod === PaymentMethod.Unknown;
|
|
484
461
|
|
|
485
462
|
// Create negative balance items
|
|
486
463
|
for (const { registration: registrationStruct, deleted } of [
|
|
@@ -834,21 +811,6 @@ export class RegisterMembersEndpoint extends Endpoint<Params, Query, Body, Respo
|
|
|
834
811
|
// Keep a copy because createdBalanceItems will be altered - and we don't want to mark added items as valid
|
|
835
812
|
const markValidList = [...createdBalanceItems];
|
|
836
813
|
|
|
837
|
-
async function markValidIfNeeded() {
|
|
838
|
-
if (shouldMarkValid) {
|
|
839
|
-
for (const balanceItem of markValidList) {
|
|
840
|
-
// Mark valid
|
|
841
|
-
await BalanceItemService.markPaid(balanceItem, payment, organization);
|
|
842
|
-
}
|
|
843
|
-
|
|
844
|
-
// Flush balance caches so we return an up-to-date balance
|
|
845
|
-
await BalanceItemService.flushRegistrationDiscountsCache();
|
|
846
|
-
|
|
847
|
-
// We'll need to update the returned registrations as their values will have changed by marking the registration as valid
|
|
848
|
-
await Registration.refreshAll(registrations);
|
|
849
|
-
}
|
|
850
|
-
}
|
|
851
|
-
|
|
852
814
|
if (whoWillPayNow !== 'nobody') {
|
|
853
815
|
const mappedBalanceItems = new Map<BalanceItem, number>();
|
|
854
816
|
|
|
@@ -868,14 +830,15 @@ export class RegisterMembersEndpoint extends Endpoint<Params, Query, Body, Respo
|
|
|
868
830
|
}
|
|
869
831
|
|
|
870
832
|
try {
|
|
871
|
-
const response = await
|
|
833
|
+
const response = await PaymentService.createPayment({
|
|
872
834
|
balanceItems: mappedBalanceItems,
|
|
873
835
|
organization,
|
|
874
836
|
user,
|
|
875
837
|
checkout: request.body,
|
|
876
838
|
members,
|
|
839
|
+
serviceFeeType: 'members',
|
|
840
|
+
payingOrganization,
|
|
877
841
|
});
|
|
878
|
-
await markValidIfNeeded();
|
|
879
842
|
|
|
880
843
|
if (response) {
|
|
881
844
|
paymentUrl = response.paymentUrl;
|
|
@@ -889,7 +852,10 @@ export class RegisterMembersEndpoint extends Endpoint<Params, Query, Body, Respo
|
|
|
889
852
|
}
|
|
890
853
|
}
|
|
891
854
|
else {
|
|
892
|
-
|
|
855
|
+
// Mark as paid/valid without creating a payment
|
|
856
|
+
for (const balanceItem of markValidList) {
|
|
857
|
+
await BalanceItemService.markPaid(balanceItem, null, organization);
|
|
858
|
+
}
|
|
893
859
|
}
|
|
894
860
|
|
|
895
861
|
// Update occupancy
|
|
@@ -900,353 +866,22 @@ export class RegisterMembersEndpoint extends Endpoint<Params, Query, Body, Respo
|
|
|
900
866
|
}
|
|
901
867
|
}
|
|
902
868
|
|
|
903
|
-
|
|
869
|
+
// Flush caches so data is up to date in response
|
|
870
|
+
await BalanceItemService.flushCaches(organization.id);
|
|
871
|
+
|
|
872
|
+
// We'll need to update the returned registrations as their values will have changed by marking the registration as valid
|
|
873
|
+
await Registration.refreshAll(registrations);
|
|
874
|
+
|
|
875
|
+
// Force reload registrations and group data
|
|
876
|
+
Member.unloadRegistrations(members);
|
|
877
|
+
await Member.loadRegistrations(members, true);
|
|
904
878
|
|
|
905
879
|
return new Response(RegisterResponse.create({
|
|
906
880
|
payment: payment ? PaymentStruct.create(payment) : null,
|
|
907
|
-
members: await AuthenticatedStructures.membersBlob(
|
|
881
|
+
members: await AuthenticatedStructures.membersBlob(members),
|
|
908
882
|
registrations: registrations.map(r => Member.getRegistrationWithTinyMemberStructure(r)),
|
|
909
883
|
paymentUrl,
|
|
910
884
|
paymentQRCode,
|
|
911
885
|
}));
|
|
912
886
|
}
|
|
913
|
-
|
|
914
|
-
async createPayment({ balanceItems, organization, user, checkout, members }: { balanceItems: Map<BalanceItem, number>; organization: Organization; user: User; checkout: IDRegisterCheckout; members: MemberWithRegistrations[] }) {
|
|
915
|
-
// Calculate total price to pay
|
|
916
|
-
let totalPrice = 0;
|
|
917
|
-
const payMembers: MemberWithRegistrations[] = [];
|
|
918
|
-
let hasNegative = false;
|
|
919
|
-
|
|
920
|
-
for (const [balanceItem, price] of balanceItems) {
|
|
921
|
-
if (organization.id !== balanceItem.organizationId) {
|
|
922
|
-
throw new Error('Unexpected balance item from other organization');
|
|
923
|
-
}
|
|
924
|
-
|
|
925
|
-
if (price > 0 && price > Math.max(balanceItem.priceOpen, balanceItem.price - balanceItem.pricePaid)) {
|
|
926
|
-
throw new SimpleError({
|
|
927
|
-
code: 'invalid_data',
|
|
928
|
-
message: $t(`38ddccb2-7cf6-4b47-aa71-d11ad73386d8`),
|
|
929
|
-
});
|
|
930
|
-
}
|
|
931
|
-
|
|
932
|
-
if (price < 0 && price < Math.min(balanceItem.priceOpen, balanceItem.price - balanceItem.pricePaid)) {
|
|
933
|
-
throw new SimpleError({
|
|
934
|
-
code: 'invalid_data',
|
|
935
|
-
message: $t(`dd14a1d9-c569-4d5e-bb26-569ecede4c52`),
|
|
936
|
-
});
|
|
937
|
-
}
|
|
938
|
-
|
|
939
|
-
if (price < 0) {
|
|
940
|
-
hasNegative = true;
|
|
941
|
-
}
|
|
942
|
-
|
|
943
|
-
totalPrice += price;
|
|
944
|
-
|
|
945
|
-
if (price > 0 && balanceItem.memberId) {
|
|
946
|
-
const member = members.find(m => m.id === balanceItem.memberId);
|
|
947
|
-
if (!member) {
|
|
948
|
-
throw new SimpleError({
|
|
949
|
-
code: 'invalid_data',
|
|
950
|
-
message: $t(`e64b8269-1cda-434d-8d6f-35be23a9d6e9`),
|
|
951
|
-
});
|
|
952
|
-
}
|
|
953
|
-
payMembers.push(member);
|
|
954
|
-
}
|
|
955
|
-
}
|
|
956
|
-
|
|
957
|
-
if (totalPrice < 0) {
|
|
958
|
-
// todo: try to make it non-negative by reducing some balance items
|
|
959
|
-
throw new SimpleError({
|
|
960
|
-
code: 'negative_price',
|
|
961
|
-
message: $t(`725715e5-b0ac-43c1-adef-dd42b8907327`),
|
|
962
|
-
});
|
|
963
|
-
}
|
|
964
|
-
|
|
965
|
-
if (totalPrice !== checkout.totalPrice) {
|
|
966
|
-
// Changed!
|
|
967
|
-
throw new SimpleError({
|
|
968
|
-
code: 'changed_price',
|
|
969
|
-
message: $t(`e424d549-2bb8-4103-9a14-ac4063d7d454`, { total: Formatter.price(totalPrice) }),
|
|
970
|
-
});
|
|
971
|
-
}
|
|
972
|
-
|
|
973
|
-
const payment = new Payment();
|
|
974
|
-
payment.method = checkout.paymentMethod ?? PaymentMethod.Unknown;
|
|
975
|
-
|
|
976
|
-
if (totalPrice === 0) {
|
|
977
|
-
if (balanceItems.size === 0) {
|
|
978
|
-
return;
|
|
979
|
-
}
|
|
980
|
-
// Create an egalizing payment
|
|
981
|
-
payment.method = PaymentMethod.Unknown;
|
|
982
|
-
|
|
983
|
-
if (hasNegative) {
|
|
984
|
-
payment.type = PaymentType.Reallocation;
|
|
985
|
-
}
|
|
986
|
-
}
|
|
987
|
-
else if (payment.method === PaymentMethod.Unknown) {
|
|
988
|
-
throw new SimpleError({
|
|
989
|
-
code: 'invalid_data',
|
|
990
|
-
message: $t(`86c7b6f7-3ec9-4af3-a5e6-b5de6de80d73`),
|
|
991
|
-
});
|
|
992
|
-
}
|
|
993
|
-
|
|
994
|
-
// Who will receive this money?
|
|
995
|
-
payment.organizationId = organization.id;
|
|
996
|
-
|
|
997
|
-
// Who paid
|
|
998
|
-
payment.payingUserId = user.id;
|
|
999
|
-
payment.payingOrganizationId = checkout.asOrganizationId ?? null;
|
|
1000
|
-
|
|
1001
|
-
// Fill in customer:
|
|
1002
|
-
payment.customer = PaymentCustomer.create({
|
|
1003
|
-
firstName: user.firstName,
|
|
1004
|
-
lastName: user.lastName,
|
|
1005
|
-
email: user.email,
|
|
1006
|
-
});
|
|
1007
|
-
|
|
1008
|
-
// Use structured transfer description prefix
|
|
1009
|
-
let prefix = '';
|
|
1010
|
-
|
|
1011
|
-
if (checkout.asOrganizationId) {
|
|
1012
|
-
if (!checkout.customer) {
|
|
1013
|
-
throw new SimpleError({
|
|
1014
|
-
code: 'missing_fields',
|
|
1015
|
-
message: 'customer is required when paying as an organization',
|
|
1016
|
-
human: $t(`d483aa9a-289c-4c59-955f-d2f99ec533ab`),
|
|
1017
|
-
});
|
|
1018
|
-
}
|
|
1019
|
-
|
|
1020
|
-
if (!checkout.customer.company) {
|
|
1021
|
-
throw new SimpleError({
|
|
1022
|
-
code: 'missing_fields',
|
|
1023
|
-
message: 'customer.company is required when paying as an organization',
|
|
1024
|
-
human: $t(`bc89861d-a799-4100-b06c-29d6808ba8d2`),
|
|
1025
|
-
});
|
|
1026
|
-
}
|
|
1027
|
-
|
|
1028
|
-
const payingOrganization = await Organization.getByID(checkout.asOrganizationId);
|
|
1029
|
-
if (!payingOrganization) {
|
|
1030
|
-
throw new SimpleError({
|
|
1031
|
-
code: 'invalid_data',
|
|
1032
|
-
message: $t(`492117ce-4d5f-4cff-8f3f-8fa56bbb0fee`),
|
|
1033
|
-
});
|
|
1034
|
-
}
|
|
1035
|
-
|
|
1036
|
-
// Search company id
|
|
1037
|
-
// this avoids needing to check the VAT number every time
|
|
1038
|
-
const id = checkout.customer.company.id;
|
|
1039
|
-
const foundCompany = payingOrganization.meta.companies.find(c => c.id === id);
|
|
1040
|
-
|
|
1041
|
-
if (!foundCompany) {
|
|
1042
|
-
throw new SimpleError({
|
|
1043
|
-
code: 'invalid_data',
|
|
1044
|
-
message: $t(`0ab71307-8f4f-4701-b120-b552a1b6bdd0`),
|
|
1045
|
-
});
|
|
1046
|
-
}
|
|
1047
|
-
|
|
1048
|
-
payment.customer.company = foundCompany;
|
|
1049
|
-
|
|
1050
|
-
const orgNumber = parseInt(payingOrganization.uri);
|
|
1051
|
-
|
|
1052
|
-
if (orgNumber !== 0 && !isNaN(orgNumber)) {
|
|
1053
|
-
prefix = orgNumber + '';
|
|
1054
|
-
}
|
|
1055
|
-
}
|
|
1056
|
-
|
|
1057
|
-
payment.status = PaymentStatus.Created;
|
|
1058
|
-
payment.paidAt = null;
|
|
1059
|
-
payment.price = totalPrice;
|
|
1060
|
-
PaymentService.round(payment);
|
|
1061
|
-
totalPrice = payment.price;
|
|
1062
|
-
|
|
1063
|
-
if (totalPrice === 0) {
|
|
1064
|
-
payment.status = PaymentStatus.Succeeded;
|
|
1065
|
-
payment.paidAt = new Date();
|
|
1066
|
-
}
|
|
1067
|
-
|
|
1068
|
-
if (payment.method === PaymentMethod.Transfer) {
|
|
1069
|
-
// remark: we cannot add the lastnames, these will get added in the frontend when it is decrypted
|
|
1070
|
-
payment.transferSettings = organization.mappedTransferSettings;
|
|
1071
|
-
|
|
1072
|
-
if (!payment.transferSettings.iban) {
|
|
1073
|
-
throw new SimpleError({
|
|
1074
|
-
code: 'no_iban',
|
|
1075
|
-
message: 'No IBAN',
|
|
1076
|
-
human: $t(`cc8b5066-a7e4-4eae-b556-f56de5d3502c`),
|
|
1077
|
-
});
|
|
1078
|
-
}
|
|
1079
|
-
|
|
1080
|
-
const m = payMembers.map(r => r.details);
|
|
1081
|
-
payment.generateDescription(
|
|
1082
|
-
organization,
|
|
1083
|
-
Formatter.groupNamesByFamily(m),
|
|
1084
|
-
{
|
|
1085
|
-
name: Formatter.groupNamesByFamily(m),
|
|
1086
|
-
naam: Formatter.groupNamesByFamily(m),
|
|
1087
|
-
email: user.email,
|
|
1088
|
-
prefix,
|
|
1089
|
-
},
|
|
1090
|
-
);
|
|
1091
|
-
}
|
|
1092
|
-
|
|
1093
|
-
// Determine the payment provider
|
|
1094
|
-
// Throws if invalid
|
|
1095
|
-
const { provider, stripeAccount } = await organization.getPaymentProviderFor(payment.method, organization.privateMeta.registrationPaymentConfiguration);
|
|
1096
|
-
payment.provider = provider;
|
|
1097
|
-
payment.stripeAccountId = stripeAccount?.id ?? null;
|
|
1098
|
-
ServiceFeeHelper.setServiceFee(payment, organization, 'members', [...balanceItems.entries()].map(([_, p]) => p));
|
|
1099
|
-
|
|
1100
|
-
await payment.save();
|
|
1101
|
-
|
|
1102
|
-
// Create balance item payments
|
|
1103
|
-
const balanceItemPayments: (BalanceItemPayment & { balanceItem: BalanceItem })[] = [];
|
|
1104
|
-
|
|
1105
|
-
for (const [balanceItem, price] of balanceItems) {
|
|
1106
|
-
// Create one balance item payment to pay it in one payment
|
|
1107
|
-
const balanceItemPayment = new BalanceItemPayment();
|
|
1108
|
-
balanceItemPayment.balanceItemId = balanceItem.id;
|
|
1109
|
-
balanceItemPayment.paymentId = payment.id;
|
|
1110
|
-
balanceItemPayment.organizationId = organization.id;
|
|
1111
|
-
balanceItemPayment.price = price;
|
|
1112
|
-
await balanceItemPayment.save();
|
|
1113
|
-
|
|
1114
|
-
balanceItemPayments.push(balanceItemPayment.setRelation(BalanceItemPayment.balanceItem, balanceItem));
|
|
1115
|
-
}
|
|
1116
|
-
|
|
1117
|
-
const description = $t(`33a926ea-9bc7-444e-becc-c0f2f70e1f0e`) + ' ' + organization.name;
|
|
1118
|
-
|
|
1119
|
-
let paymentUrl: string | null = null;
|
|
1120
|
-
let paymentQRCode: string | null = null;
|
|
1121
|
-
|
|
1122
|
-
try {
|
|
1123
|
-
// Update balance items
|
|
1124
|
-
if (payment.method === PaymentMethod.Transfer) {
|
|
1125
|
-
// Send a small reminder email
|
|
1126
|
-
try {
|
|
1127
|
-
await Registration.sendTransferEmail(user, organization, payment);
|
|
1128
|
-
}
|
|
1129
|
-
catch (e) {
|
|
1130
|
-
console.error('Failed to send transfer email');
|
|
1131
|
-
console.error(e);
|
|
1132
|
-
}
|
|
1133
|
-
}
|
|
1134
|
-
else if (payment.method !== PaymentMethod.PointOfSale && payment.method !== PaymentMethod.Unknown) {
|
|
1135
|
-
if (!checkout.redirectUrl || !checkout.cancelUrl) {
|
|
1136
|
-
throw new Error('Should have been caught earlier');
|
|
1137
|
-
}
|
|
1138
|
-
|
|
1139
|
-
const _redirectUrl = new URL(checkout.redirectUrl);
|
|
1140
|
-
_redirectUrl.searchParams.set('paymentId', payment.id);
|
|
1141
|
-
_redirectUrl.searchParams.set('organizationId', organization.id); // makes sure the client uses the token associated with this organization when fetching payment polling status
|
|
1142
|
-
|
|
1143
|
-
const _cancelUrl = new URL(checkout.cancelUrl);
|
|
1144
|
-
_cancelUrl.searchParams.set('paymentId', payment.id);
|
|
1145
|
-
_cancelUrl.searchParams.set('cancel', 'true');
|
|
1146
|
-
_cancelUrl.searchParams.set('organizationId', organization.id); // makes sure the client uses the token associated with this organization when fetching payment polling status
|
|
1147
|
-
|
|
1148
|
-
const redirectUrl = _redirectUrl.href;
|
|
1149
|
-
const cancelUrl = _cancelUrl.href;
|
|
1150
|
-
|
|
1151
|
-
const webhookUrl = 'https://' + organization.getApiHost() + '/v' + Version + '/payments/' + encodeURIComponent(payment.id) + '?exchange=true';
|
|
1152
|
-
|
|
1153
|
-
if (payment.provider === PaymentProvider.Stripe) {
|
|
1154
|
-
const stripeResult = await StripeHelper.createPayment({
|
|
1155
|
-
payment,
|
|
1156
|
-
stripeAccount,
|
|
1157
|
-
redirectUrl,
|
|
1158
|
-
cancelUrl,
|
|
1159
|
-
statementDescriptor: organization.name,
|
|
1160
|
-
metadata: {
|
|
1161
|
-
organization: organization.id,
|
|
1162
|
-
user: user.id,
|
|
1163
|
-
payment: payment.id,
|
|
1164
|
-
},
|
|
1165
|
-
i18n: Context.i18n,
|
|
1166
|
-
lineItems: balanceItemPayments,
|
|
1167
|
-
organization,
|
|
1168
|
-
customer: {
|
|
1169
|
-
name: user.name ?? payMembers[0]?.details.name ?? $t(`bd1e59c8-3d4c-4097-ab35-0ce7b20d0e50`),
|
|
1170
|
-
email: user.email,
|
|
1171
|
-
},
|
|
1172
|
-
});
|
|
1173
|
-
paymentUrl = stripeResult.paymentUrl;
|
|
1174
|
-
}
|
|
1175
|
-
else if (payment.provider === PaymentProvider.Mollie) {
|
|
1176
|
-
// Mollie payment
|
|
1177
|
-
const token = await MollieToken.getTokenFor(organization.id);
|
|
1178
|
-
if (!token) {
|
|
1179
|
-
throw new SimpleError({
|
|
1180
|
-
code: '',
|
|
1181
|
-
message: $t(`b77e1f68-8928-42a2-802b-059fa73bedc3`, { method: PaymentMethodHelper.getName(payment.method) }),
|
|
1182
|
-
});
|
|
1183
|
-
}
|
|
1184
|
-
const profileId = organization.privateMeta.mollieProfile?.id ?? await token.getProfileId(organization.getHost());
|
|
1185
|
-
if (!profileId) {
|
|
1186
|
-
throw new SimpleError({
|
|
1187
|
-
code: '',
|
|
1188
|
-
message: $t(`5574469f-8eee-47fe-9fb6-1b097142ac75`, { method: PaymentMethodHelper.getName(payment.method) }),
|
|
1189
|
-
});
|
|
1190
|
-
}
|
|
1191
|
-
const mollieClient = createMollieClient({ accessToken: await token.getAccessToken() });
|
|
1192
|
-
const locale = Context.i18n.locale.replace('-', '_');
|
|
1193
|
-
const molliePayment = await mollieClient.payments.create({
|
|
1194
|
-
amount: {
|
|
1195
|
-
currency: 'EUR',
|
|
1196
|
-
value: (totalPrice / 100).toFixed(2),
|
|
1197
|
-
},
|
|
1198
|
-
method: payment.method == PaymentMethod.Bancontact ? molliePaymentMethod.bancontact : (payment.method == PaymentMethod.iDEAL ? molliePaymentMethod.ideal : molliePaymentMethod.creditcard),
|
|
1199
|
-
testmode: organization.privateMeta.useTestPayments ?? STAMHOOFD.environment !== 'production',
|
|
1200
|
-
profileId,
|
|
1201
|
-
description,
|
|
1202
|
-
redirectUrl,
|
|
1203
|
-
webhookUrl,
|
|
1204
|
-
metadata: {
|
|
1205
|
-
paymentId: payment.id,
|
|
1206
|
-
},
|
|
1207
|
-
locale: ['en_US', 'en_GB', 'nl_NL', 'nl_BE', 'fr_FR', 'fr_BE', 'de_DE', 'de_AT', 'de_CH', 'es_ES', 'ca_ES', 'pt_PT', 'it_IT', 'nb_NO', 'sv_SE', 'fi_FI', 'da_DK', 'is_IS', 'hu_HU', 'pl_PL', 'lv_LV', 'lt_LT'].includes(locale) ? (locale as any) : null,
|
|
1208
|
-
});
|
|
1209
|
-
paymentUrl = molliePayment.getCheckoutUrl();
|
|
1210
|
-
|
|
1211
|
-
// Save payment
|
|
1212
|
-
const dbPayment = new MolliePayment();
|
|
1213
|
-
dbPayment.paymentId = payment.id;
|
|
1214
|
-
dbPayment.mollieId = molliePayment.id;
|
|
1215
|
-
await dbPayment.save();
|
|
1216
|
-
}
|
|
1217
|
-
else if (payment.provider === PaymentProvider.Payconiq) {
|
|
1218
|
-
({ paymentUrl, paymentQRCode } = await PayconiqPayment.createPayment(payment, organization, description, redirectUrl, webhookUrl));
|
|
1219
|
-
}
|
|
1220
|
-
else if (payment.provider == PaymentProvider.Buckaroo) {
|
|
1221
|
-
// Increase request timeout because buckaroo is super slow (in development)
|
|
1222
|
-
Context.request.request?.setTimeout(60 * 1000);
|
|
1223
|
-
const buckaroo = new BuckarooHelper(organization.privateMeta?.buckarooSettings?.key ?? '', organization.privateMeta?.buckarooSettings?.secret ?? '', organization.privateMeta.useTestPayments ?? STAMHOOFD.environment !== 'production');
|
|
1224
|
-
const ip = Context.request.getIP();
|
|
1225
|
-
paymentUrl = await buckaroo.createPayment(payment, ip, description, redirectUrl, webhookUrl);
|
|
1226
|
-
await payment.save();
|
|
1227
|
-
|
|
1228
|
-
// TypeScript doesn't understand that the status can change and isn't a const....
|
|
1229
|
-
if ((payment.status as any) === PaymentStatus.Failed) {
|
|
1230
|
-
throw new SimpleError({
|
|
1231
|
-
code: 'payment_failed',
|
|
1232
|
-
message: $t(`b77e1f68-8928-42a2-802b-059fa73bedc3`, { method: PaymentMethodHelper.getName(payment.method) }),
|
|
1233
|
-
});
|
|
1234
|
-
}
|
|
1235
|
-
}
|
|
1236
|
-
}
|
|
1237
|
-
}
|
|
1238
|
-
catch (e) {
|
|
1239
|
-
await PaymentService.handlePaymentStatusUpdate(payment, organization, PaymentStatus.Failed);
|
|
1240
|
-
throw e;
|
|
1241
|
-
}
|
|
1242
|
-
|
|
1243
|
-
return {
|
|
1244
|
-
payment,
|
|
1245
|
-
balanceItemPayments,
|
|
1246
|
-
provider,
|
|
1247
|
-
stripeAccount,
|
|
1248
|
-
paymentUrl,
|
|
1249
|
-
paymentQRCode,
|
|
1250
|
-
};
|
|
1251
|
-
}
|
|
1252
887
|
}
|
|
@@ -5,9 +5,9 @@ import { Decoder } from '@simonbackx/simple-encoding';
|
|
|
5
5
|
import { SimpleError } from '@simonbackx/simple-errors';
|
|
6
6
|
import { RegistrationPeriod } from '@stamhoofd/models';
|
|
7
7
|
import { applySQLSorter, compileToSQLFilter, SQLFilterDefinitions, SQLSortDefinitions } from '@stamhoofd/sql';
|
|
8
|
-
import { Context } from '../../../helpers/Context';
|
|
9
|
-
import { registrationPeriodFilterCompilers } from '../../../sql-filters/registration-periods';
|
|
10
|
-
import { registrationPeriodSorters } from '../../../sql-sorters/registration-periods';
|
|
8
|
+
import { Context } from '../../../helpers/Context.js';
|
|
9
|
+
import { registrationPeriodFilterCompilers } from '../../../sql-filters/registration-periods.js';
|
|
10
|
+
import { registrationPeriodSorters } from '../../../sql-sorters/registration-periods.js';
|
|
11
11
|
|
|
12
12
|
type Params = Record<string, never>;
|
|
13
13
|
type Query = LimitedFilteredRequest;
|
|
@@ -4,8 +4,8 @@ import { RegistrationPeriod as RegistrationPeriodStruct } from '@stamhoofd/struc
|
|
|
4
4
|
|
|
5
5
|
import { SimpleError } from '@simonbackx/simple-errors';
|
|
6
6
|
import { Organization, Platform, RegistrationPeriod } from '@stamhoofd/models';
|
|
7
|
-
import { Context } from '../../../helpers/Context';
|
|
8
|
-
import { PeriodHelper } from '../../../helpers/PeriodHelper';
|
|
7
|
+
import { Context } from '../../../helpers/Context.js';
|
|
8
|
+
import { PeriodHelper } from '../../../helpers/PeriodHelper.js';
|
|
9
9
|
|
|
10
10
|
type Params = Record<string, never>;
|
|
11
11
|
type Query = undefined;
|