@stamhoofd/backend 2.116.0 → 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 +25 -16
- 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 +3 -0
- 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/endFunctionsOfUsersWithoutRegistration.ts +1 -1
- package/src/crons.ts +3 -3
- 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 +117 -352
- 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/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/GetMembersEndpoint.test.ts +3 -3
- 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/GetUserMembersEndpoint.ts +2 -2
- package/src/endpoints/global/registration/GetUserPayableBalanceEndpoint.ts +2 -2
- package/src/endpoints/global/registration/RegisterMembersEndpoint.ts +14 -384
- 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/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/email/CheckEmailBouncesEndpoint.ts +30 -2
- 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/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 +1 -1
- package/src/helpers/AuthenticatedStructures.ts +17 -2
- 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/ServiceFeeHelper.ts +5 -1
- 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/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 +548 -18
- 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 +37 -1
- 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/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/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/organization/dashboard/{payments → balance-items}/PatchBalanceItemsEndpoint.ts +0 -0
|
@@ -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
|
|
@@ -903,6 +869,9 @@ export class RegisterMembersEndpoint extends Endpoint<Params, Query, Body, Respo
|
|
|
903
869
|
// Flush caches so data is up to date in response
|
|
904
870
|
await BalanceItemService.flushCaches(organization.id);
|
|
905
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
|
+
|
|
906
875
|
// Force reload registrations and group data
|
|
907
876
|
Member.unloadRegistrations(members);
|
|
908
877
|
await Member.loadRegistrations(members, true);
|
|
@@ -915,343 +884,4 @@ export class RegisterMembersEndpoint extends Endpoint<Params, Query, Body, Respo
|
|
|
915
884
|
paymentQRCode,
|
|
916
885
|
}));
|
|
917
886
|
}
|
|
918
|
-
|
|
919
|
-
async createPayment({ balanceItems, organization, user, checkout, members }: { balanceItems: Map<BalanceItem, number>; organization: Organization; user: User; checkout: IDRegisterCheckout; members: MemberWithUsersRegistrationsAndGroups[] }) {
|
|
920
|
-
// Calculate total price to pay
|
|
921
|
-
let totalPrice = 0;
|
|
922
|
-
const payMembers: MemberWithUsersRegistrationsAndGroups[] = [];
|
|
923
|
-
let hasNegative = false;
|
|
924
|
-
|
|
925
|
-
for (const [balanceItem, price] of balanceItems) {
|
|
926
|
-
if (organization.id !== balanceItem.organizationId) {
|
|
927
|
-
throw new Error('Unexpected balance item from other organization');
|
|
928
|
-
}
|
|
929
|
-
|
|
930
|
-
if (price > 0 && price > Math.max(balanceItem.priceOpen, balanceItem.price - balanceItem.pricePaid)) {
|
|
931
|
-
throw new SimpleError({
|
|
932
|
-
code: 'invalid_data',
|
|
933
|
-
message: $t(`38ddccb2-7cf6-4b47-aa71-d11ad73386d8`),
|
|
934
|
-
});
|
|
935
|
-
}
|
|
936
|
-
|
|
937
|
-
if (price < 0 && price < Math.min(balanceItem.priceOpen, balanceItem.price - balanceItem.pricePaid)) {
|
|
938
|
-
throw new SimpleError({
|
|
939
|
-
code: 'invalid_data',
|
|
940
|
-
message: $t(`dd14a1d9-c569-4d5e-bb26-569ecede4c52`),
|
|
941
|
-
});
|
|
942
|
-
}
|
|
943
|
-
|
|
944
|
-
if (price < 0) {
|
|
945
|
-
hasNegative = true;
|
|
946
|
-
}
|
|
947
|
-
|
|
948
|
-
totalPrice += price;
|
|
949
|
-
|
|
950
|
-
if (price > 0 && balanceItem.memberId) {
|
|
951
|
-
const member = members.find(m => m.id === balanceItem.memberId);
|
|
952
|
-
if (!member) {
|
|
953
|
-
throw new SimpleError({
|
|
954
|
-
code: 'invalid_data',
|
|
955
|
-
message: $t(`e64b8269-1cda-434d-8d6f-35be23a9d6e9`),
|
|
956
|
-
});
|
|
957
|
-
}
|
|
958
|
-
payMembers.push(member);
|
|
959
|
-
}
|
|
960
|
-
}
|
|
961
|
-
|
|
962
|
-
if (totalPrice < 0) {
|
|
963
|
-
// todo: try to make it non-negative by reducing some balance items
|
|
964
|
-
throw new SimpleError({
|
|
965
|
-
code: 'negative_price',
|
|
966
|
-
message: $t(`725715e5-b0ac-43c1-adef-dd42b8907327`),
|
|
967
|
-
});
|
|
968
|
-
}
|
|
969
|
-
|
|
970
|
-
if (totalPrice !== checkout.totalPrice) {
|
|
971
|
-
// Changed!
|
|
972
|
-
throw new SimpleError({
|
|
973
|
-
code: 'changed_price',
|
|
974
|
-
message: $t(`e424d549-2bb8-4103-9a14-ac4063d7d454`, { total: Formatter.price(totalPrice) }),
|
|
975
|
-
});
|
|
976
|
-
}
|
|
977
|
-
|
|
978
|
-
const payment = new Payment();
|
|
979
|
-
payment.method = checkout.paymentMethod ?? PaymentMethod.Unknown;
|
|
980
|
-
|
|
981
|
-
if (totalPrice === 0) {
|
|
982
|
-
if (balanceItems.size === 0) {
|
|
983
|
-
return;
|
|
984
|
-
}
|
|
985
|
-
// Create an egalizing payment
|
|
986
|
-
payment.method = PaymentMethod.Unknown;
|
|
987
|
-
|
|
988
|
-
if (hasNegative) {
|
|
989
|
-
payment.type = PaymentType.Reallocation;
|
|
990
|
-
}
|
|
991
|
-
}
|
|
992
|
-
else if (payment.method === PaymentMethod.Unknown) {
|
|
993
|
-
throw new SimpleError({
|
|
994
|
-
code: 'invalid_data',
|
|
995
|
-
message: $t(`86c7b6f7-3ec9-4af3-a5e6-b5de6de80d73`),
|
|
996
|
-
});
|
|
997
|
-
}
|
|
998
|
-
|
|
999
|
-
// Who will receive this money?
|
|
1000
|
-
payment.organizationId = organization.id;
|
|
1001
|
-
|
|
1002
|
-
// Who paid
|
|
1003
|
-
payment.payingUserId = user.id;
|
|
1004
|
-
payment.payingOrganizationId = checkout.asOrganizationId ?? null;
|
|
1005
|
-
|
|
1006
|
-
// Fill in customer:
|
|
1007
|
-
payment.customer = PaymentCustomer.create({
|
|
1008
|
-
firstName: user.firstName,
|
|
1009
|
-
lastName: user.lastName,
|
|
1010
|
-
email: user.email,
|
|
1011
|
-
});
|
|
1012
|
-
|
|
1013
|
-
// Use structured transfer description prefix
|
|
1014
|
-
let prefix = '';
|
|
1015
|
-
|
|
1016
|
-
if (checkout.asOrganizationId) {
|
|
1017
|
-
if (!checkout.customer) {
|
|
1018
|
-
throw new SimpleError({
|
|
1019
|
-
code: 'missing_fields',
|
|
1020
|
-
message: 'customer is required when paying as an organization',
|
|
1021
|
-
human: $t(`d483aa9a-289c-4c59-955f-d2f99ec533ab`),
|
|
1022
|
-
});
|
|
1023
|
-
}
|
|
1024
|
-
|
|
1025
|
-
if (!checkout.customer.company) {
|
|
1026
|
-
throw new SimpleError({
|
|
1027
|
-
code: 'missing_fields',
|
|
1028
|
-
message: 'customer.company is required when paying as an organization',
|
|
1029
|
-
human: $t(`bc89861d-a799-4100-b06c-29d6808ba8d2`),
|
|
1030
|
-
});
|
|
1031
|
-
}
|
|
1032
|
-
|
|
1033
|
-
const payingOrganization = await Organization.getByID(checkout.asOrganizationId);
|
|
1034
|
-
if (!payingOrganization) {
|
|
1035
|
-
throw new SimpleError({
|
|
1036
|
-
code: 'invalid_data',
|
|
1037
|
-
message: $t(`492117ce-4d5f-4cff-8f3f-8fa56bbb0fee`),
|
|
1038
|
-
});
|
|
1039
|
-
}
|
|
1040
|
-
|
|
1041
|
-
// Search company id
|
|
1042
|
-
// this avoids needing to check the VAT number every time
|
|
1043
|
-
const id = checkout.customer.company.id;
|
|
1044
|
-
const foundCompany = payingOrganization.meta.companies.find(c => c.id === id);
|
|
1045
|
-
|
|
1046
|
-
if (!foundCompany) {
|
|
1047
|
-
throw new SimpleError({
|
|
1048
|
-
code: 'invalid_data',
|
|
1049
|
-
message: $t(`0ab71307-8f4f-4701-b120-b552a1b6bdd0`),
|
|
1050
|
-
});
|
|
1051
|
-
}
|
|
1052
|
-
|
|
1053
|
-
payment.customer.company = foundCompany;
|
|
1054
|
-
|
|
1055
|
-
const orgNumber = parseInt(payingOrganization.uri);
|
|
1056
|
-
|
|
1057
|
-
if (orgNumber !== 0 && !isNaN(orgNumber)) {
|
|
1058
|
-
prefix = orgNumber + '';
|
|
1059
|
-
}
|
|
1060
|
-
}
|
|
1061
|
-
|
|
1062
|
-
payment.status = PaymentStatus.Created;
|
|
1063
|
-
payment.paidAt = null;
|
|
1064
|
-
payment.price = totalPrice;
|
|
1065
|
-
PaymentService.round(payment);
|
|
1066
|
-
totalPrice = payment.price;
|
|
1067
|
-
|
|
1068
|
-
if (totalPrice === 0) {
|
|
1069
|
-
payment.status = PaymentStatus.Succeeded;
|
|
1070
|
-
payment.paidAt = new Date();
|
|
1071
|
-
}
|
|
1072
|
-
|
|
1073
|
-
if (payment.method === PaymentMethod.Transfer) {
|
|
1074
|
-
// remark: we cannot add the lastnames, these will get added in the frontend when it is decrypted
|
|
1075
|
-
payment.transferSettings = organization.mappedTransferSettings;
|
|
1076
|
-
|
|
1077
|
-
if (!payment.transferSettings.iban) {
|
|
1078
|
-
throw new SimpleError({
|
|
1079
|
-
code: 'no_iban',
|
|
1080
|
-
message: 'No IBAN',
|
|
1081
|
-
human: $t(`cc8b5066-a7e4-4eae-b556-f56de5d3502c`),
|
|
1082
|
-
});
|
|
1083
|
-
}
|
|
1084
|
-
|
|
1085
|
-
const m = payMembers.map(r => r.details);
|
|
1086
|
-
payment.generateDescription(
|
|
1087
|
-
organization,
|
|
1088
|
-
Formatter.groupNamesByFamily(m),
|
|
1089
|
-
{
|
|
1090
|
-
name: Formatter.groupNamesByFamily(m),
|
|
1091
|
-
naam: Formatter.groupNamesByFamily(m),
|
|
1092
|
-
email: user.email,
|
|
1093
|
-
prefix,
|
|
1094
|
-
},
|
|
1095
|
-
);
|
|
1096
|
-
}
|
|
1097
|
-
|
|
1098
|
-
// Determine the payment provider
|
|
1099
|
-
// Throws if invalid
|
|
1100
|
-
const { provider, stripeAccount } = await organization.getPaymentProviderFor(payment.method, organization.privateMeta.registrationPaymentConfiguration);
|
|
1101
|
-
payment.provider = provider;
|
|
1102
|
-
payment.stripeAccountId = stripeAccount?.id ?? null;
|
|
1103
|
-
ServiceFeeHelper.setServiceFee(payment, organization, 'members', [...balanceItems.entries()].map(([_, p]) => p));
|
|
1104
|
-
|
|
1105
|
-
await payment.save();
|
|
1106
|
-
|
|
1107
|
-
// Create balance item payments
|
|
1108
|
-
const balanceItemPayments: (BalanceItemPayment & { balanceItem: BalanceItem })[] = [];
|
|
1109
|
-
|
|
1110
|
-
for (const [balanceItem, price] of balanceItems) {
|
|
1111
|
-
// Create one balance item payment to pay it in one payment
|
|
1112
|
-
const balanceItemPayment = new BalanceItemPayment();
|
|
1113
|
-
balanceItemPayment.balanceItemId = balanceItem.id;
|
|
1114
|
-
balanceItemPayment.paymentId = payment.id;
|
|
1115
|
-
balanceItemPayment.organizationId = organization.id;
|
|
1116
|
-
balanceItemPayment.price = price;
|
|
1117
|
-
await balanceItemPayment.save();
|
|
1118
|
-
|
|
1119
|
-
balanceItemPayments.push(balanceItemPayment.setRelation(BalanceItemPayment.balanceItem, balanceItem));
|
|
1120
|
-
}
|
|
1121
|
-
|
|
1122
|
-
const description = $t(`33a926ea-9bc7-444e-becc-c0f2f70e1f0e`) + ' ' + organization.name;
|
|
1123
|
-
|
|
1124
|
-
let paymentUrl: string | null = null;
|
|
1125
|
-
let paymentQRCode: string | null = null;
|
|
1126
|
-
|
|
1127
|
-
try {
|
|
1128
|
-
// Update balance items
|
|
1129
|
-
if (payment.method === PaymentMethod.Transfer) {
|
|
1130
|
-
// Send a small reminder email
|
|
1131
|
-
try {
|
|
1132
|
-
await Registration.sendTransferEmail(user, organization, payment);
|
|
1133
|
-
}
|
|
1134
|
-
catch (e) {
|
|
1135
|
-
console.error('Failed to send transfer email');
|
|
1136
|
-
console.error(e);
|
|
1137
|
-
}
|
|
1138
|
-
}
|
|
1139
|
-
else if (payment.method !== PaymentMethod.PointOfSale && payment.method !== PaymentMethod.Unknown) {
|
|
1140
|
-
if (!checkout.redirectUrl || !checkout.cancelUrl) {
|
|
1141
|
-
throw new Error('Should have been caught earlier');
|
|
1142
|
-
}
|
|
1143
|
-
|
|
1144
|
-
const _redirectUrl = new URL(checkout.redirectUrl);
|
|
1145
|
-
_redirectUrl.searchParams.set('paymentId', payment.id);
|
|
1146
|
-
_redirectUrl.searchParams.set('organizationId', organization.id); // makes sure the client uses the token associated with this organization when fetching payment polling status
|
|
1147
|
-
|
|
1148
|
-
const _cancelUrl = new URL(checkout.cancelUrl);
|
|
1149
|
-
_cancelUrl.searchParams.set('paymentId', payment.id);
|
|
1150
|
-
_cancelUrl.searchParams.set('cancel', 'true');
|
|
1151
|
-
_cancelUrl.searchParams.set('organizationId', organization.id); // makes sure the client uses the token associated with this organization when fetching payment polling status
|
|
1152
|
-
|
|
1153
|
-
const redirectUrl = _redirectUrl.href;
|
|
1154
|
-
const cancelUrl = _cancelUrl.href;
|
|
1155
|
-
|
|
1156
|
-
const webhookUrl = 'https://' + organization.getApiHost() + '/v' + Version + '/payments/' + encodeURIComponent(payment.id) + '?exchange=true';
|
|
1157
|
-
|
|
1158
|
-
if (payment.provider === PaymentProvider.Stripe) {
|
|
1159
|
-
const stripeResult = await StripeHelper.createPayment({
|
|
1160
|
-
payment,
|
|
1161
|
-
stripeAccount,
|
|
1162
|
-
redirectUrl,
|
|
1163
|
-
cancelUrl,
|
|
1164
|
-
statementDescriptor: organization.name,
|
|
1165
|
-
metadata: {
|
|
1166
|
-
organization: organization.id,
|
|
1167
|
-
user: user.id,
|
|
1168
|
-
payment: payment.id,
|
|
1169
|
-
},
|
|
1170
|
-
i18n: Context.i18n,
|
|
1171
|
-
lineItems: balanceItemPayments,
|
|
1172
|
-
organization,
|
|
1173
|
-
customer: {
|
|
1174
|
-
name: user.name ?? payMembers[0]?.details.name ?? $t(`bd1e59c8-3d4c-4097-ab35-0ce7b20d0e50`),
|
|
1175
|
-
email: user.email,
|
|
1176
|
-
},
|
|
1177
|
-
});
|
|
1178
|
-
paymentUrl = stripeResult.paymentUrl;
|
|
1179
|
-
}
|
|
1180
|
-
else if (payment.provider === PaymentProvider.Mollie) {
|
|
1181
|
-
// Mollie payment
|
|
1182
|
-
const token = await MollieToken.getTokenFor(organization.id);
|
|
1183
|
-
if (!token) {
|
|
1184
|
-
throw new SimpleError({
|
|
1185
|
-
code: '',
|
|
1186
|
-
message: $t(`b77e1f68-8928-42a2-802b-059fa73bedc3`, { method: PaymentMethodHelper.getName(payment.method) }),
|
|
1187
|
-
});
|
|
1188
|
-
}
|
|
1189
|
-
const profileId = organization.privateMeta.mollieProfile?.id ?? await token.getProfileId(organization.getHost());
|
|
1190
|
-
if (!profileId) {
|
|
1191
|
-
throw new SimpleError({
|
|
1192
|
-
code: '',
|
|
1193
|
-
message: $t(`5574469f-8eee-47fe-9fb6-1b097142ac75`, { method: PaymentMethodHelper.getName(payment.method) }),
|
|
1194
|
-
});
|
|
1195
|
-
}
|
|
1196
|
-
const mollieClient = createMollieClient({ accessToken: await token.getAccessToken() });
|
|
1197
|
-
const locale = Context.i18n.locale.replace('-', '_');
|
|
1198
|
-
const molliePayment = await mollieClient.payments.create({
|
|
1199
|
-
amount: {
|
|
1200
|
-
currency: 'EUR',
|
|
1201
|
-
value: (totalPrice / 100).toFixed(2),
|
|
1202
|
-
},
|
|
1203
|
-
method: payment.method == PaymentMethod.Bancontact ? molliePaymentMethod.bancontact : (payment.method == PaymentMethod.iDEAL ? molliePaymentMethod.ideal : molliePaymentMethod.creditcard),
|
|
1204
|
-
testmode: organization.privateMeta.useTestPayments ?? STAMHOOFD.environment !== 'production',
|
|
1205
|
-
profileId,
|
|
1206
|
-
description,
|
|
1207
|
-
redirectUrl,
|
|
1208
|
-
webhookUrl,
|
|
1209
|
-
metadata: {
|
|
1210
|
-
paymentId: payment.id,
|
|
1211
|
-
},
|
|
1212
|
-
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,
|
|
1213
|
-
});
|
|
1214
|
-
paymentUrl = molliePayment.getCheckoutUrl();
|
|
1215
|
-
|
|
1216
|
-
// Save payment
|
|
1217
|
-
const dbPayment = new MolliePayment();
|
|
1218
|
-
dbPayment.paymentId = payment.id;
|
|
1219
|
-
dbPayment.mollieId = molliePayment.id;
|
|
1220
|
-
await dbPayment.save();
|
|
1221
|
-
}
|
|
1222
|
-
else if (payment.provider === PaymentProvider.Payconiq) {
|
|
1223
|
-
({ paymentUrl, paymentQRCode } = await PayconiqPayment.createPayment(payment, organization, description, redirectUrl, webhookUrl));
|
|
1224
|
-
}
|
|
1225
|
-
else if (payment.provider == PaymentProvider.Buckaroo) {
|
|
1226
|
-
// Increase request timeout because buckaroo is super slow (in development)
|
|
1227
|
-
Context.request.request?.setTimeout(60 * 1000);
|
|
1228
|
-
const buckaroo = new BuckarooHelper(organization.privateMeta?.buckarooSettings?.key ?? '', organization.privateMeta?.buckarooSettings?.secret ?? '', organization.privateMeta.useTestPayments ?? STAMHOOFD.environment !== 'production');
|
|
1229
|
-
const ip = Context.request.getIP();
|
|
1230
|
-
paymentUrl = await buckaroo.createPayment(payment, ip, description, redirectUrl, webhookUrl);
|
|
1231
|
-
await payment.save();
|
|
1232
|
-
|
|
1233
|
-
// TypeScript doesn't understand that the status can change and isn't a const....
|
|
1234
|
-
if ((payment.status as any) === PaymentStatus.Failed) {
|
|
1235
|
-
throw new SimpleError({
|
|
1236
|
-
code: 'payment_failed',
|
|
1237
|
-
message: $t(`b77e1f68-8928-42a2-802b-059fa73bedc3`, { method: PaymentMethodHelper.getName(payment.method) }),
|
|
1238
|
-
});
|
|
1239
|
-
}
|
|
1240
|
-
}
|
|
1241
|
-
}
|
|
1242
|
-
}
|
|
1243
|
-
catch (e) {
|
|
1244
|
-
await PaymentService.handlePaymentStatusUpdate(payment, organization, PaymentStatus.Failed);
|
|
1245
|
-
throw e;
|
|
1246
|
-
}
|
|
1247
|
-
|
|
1248
|
-
return {
|
|
1249
|
-
payment,
|
|
1250
|
-
balanceItemPayments,
|
|
1251
|
-
provider,
|
|
1252
|
-
stripeAccount,
|
|
1253
|
-
paymentUrl,
|
|
1254
|
-
paymentQRCode,
|
|
1255
|
-
};
|
|
1256
|
-
}
|
|
1257
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;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
|
|
2
2
|
import { LoginProviderType, OpenIDClientConfiguration } from '@stamhoofd/structures';
|
|
3
3
|
|
|
4
|
-
import { Context } from '../../../helpers/Context';
|
|
4
|
+
import { Context } from '../../../helpers/Context.js';
|
|
5
5
|
import { Platform } from '@stamhoofd/models';
|
|
6
6
|
import { AutoEncoder, Decoder, EnumDecoder, field } from '@simonbackx/simple-encoding';
|
|
7
|
-
import { SSOService } from '../../../services/SSOService';
|
|
7
|
+
import { SSOService } from '../../../services/SSOService.js';
|
|
8
8
|
|
|
9
9
|
type Params = Record<string, never>;
|
|
10
10
|
export class SSOQuery extends AutoEncoder {
|
|
@@ -2,9 +2,9 @@ import { AutoEncoderPatchType, Decoder } from '@simonbackx/simple-encoding';
|
|
|
2
2
|
import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
|
|
3
3
|
import { OpenIDClientConfiguration } from '@stamhoofd/structures';
|
|
4
4
|
|
|
5
|
-
import { Context } from '../../../helpers/Context';
|
|
6
|
-
import { SSOService } from '../../../services/SSOService';
|
|
7
|
-
import { SSOQuery } from './GetSSOEndpoint';
|
|
5
|
+
import { Context } from '../../../helpers/Context.js';
|
|
6
|
+
import { SSOService } from '../../../services/SSOService.js';
|
|
7
|
+
import { SSOQuery } from './GetSSOEndpoint.js';
|
|
8
8
|
|
|
9
9
|
type Params = Record<string, never>;
|
|
10
10
|
type Query = SSOQuery;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
|
|
2
|
+
import { SimpleError } from '@simonbackx/simple-errors';
|
|
3
|
+
import { BalanceItem } from '@stamhoofd/models';
|
|
4
|
+
import { BalanceItemWithPayments } from '@stamhoofd/structures';
|
|
5
|
+
|
|
6
|
+
import { AuthenticatedStructures } from '../../../../helpers/AuthenticatedStructures.js';
|
|
7
|
+
import { Context } from '../../../../helpers/Context.js';
|
|
8
|
+
|
|
9
|
+
type Params = { id: string };
|
|
10
|
+
type Query = undefined;
|
|
11
|
+
type Body = undefined;
|
|
12
|
+
type ResponseBody = BalanceItemWithPayments;
|
|
13
|
+
|
|
14
|
+
export class GetBalanceItemEndpoint extends Endpoint<Params, Query, Body, ResponseBody> {
|
|
15
|
+
protected doesMatch(request: Request): [true, Params] | [false] {
|
|
16
|
+
if (request.method !== 'GET') {
|
|
17
|
+
return [false];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const params = Endpoint.parseParameters(request.url, '/balance-items/@id', { id: String });
|
|
21
|
+
|
|
22
|
+
if (params) {
|
|
23
|
+
return [true, params as Params];
|
|
24
|
+
}
|
|
25
|
+
return [false];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async handle(request: DecodedRequest<Params, Query, Body>) {
|
|
29
|
+
const organization = await Context.setOrganizationScope();
|
|
30
|
+
await Context.authenticate();
|
|
31
|
+
|
|
32
|
+
if (!await Context.auth.hasSomeAccess(organization.id)) {
|
|
33
|
+
throw Context.auth.error();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const balanceItem = await BalanceItem.getByID(request.params.id);
|
|
37
|
+
|
|
38
|
+
if (!balanceItem || balanceItem.organizationId !== organization.id) {
|
|
39
|
+
throw new SimpleError({
|
|
40
|
+
code: 'not_found',
|
|
41
|
+
statusCode: 404,
|
|
42
|
+
message: 'Balance item not found',
|
|
43
|
+
human: $t('7bc08947-2409-4a7c-b597-2d6d43884a96'),
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (!await Context.auth.canAccessBalanceItems([balanceItem])) {
|
|
48
|
+
throw Context.auth.error();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return new Response(
|
|
52
|
+
(await AuthenticatedStructures.balanceItemsWithPayments([balanceItem]))[0],
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Decoder } from '@simonbackx/simple-encoding';
|
|
2
|
+
import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
|
|
3
|
+
import { CountFilteredRequest, CountResponse } from '@stamhoofd/structures';
|
|
4
|
+
|
|
5
|
+
import { Context } from '../../../../helpers/Context.js';
|
|
6
|
+
import { GetBalanceItemsEndpoint } from './GetBalanceItemsEndpoint.js';
|
|
7
|
+
|
|
8
|
+
type Params = Record<string, never>;
|
|
9
|
+
type Query = CountFilteredRequest;
|
|
10
|
+
type Body = undefined;
|
|
11
|
+
type ResponseBody = CountResponse;
|
|
12
|
+
|
|
13
|
+
export class GetBalanceItemsCountEndpoint extends Endpoint<Params, Query, Body, ResponseBody> {
|
|
14
|
+
queryDecoder = CountFilteredRequest as Decoder<CountFilteredRequest>;
|
|
15
|
+
|
|
16
|
+
protected doesMatch(request: Request): [true, Params] | [false] {
|
|
17
|
+
if (request.method !== 'GET') {
|
|
18
|
+
return [false];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const params = Endpoint.parseParameters(request.url, '/balance-items/count', {});
|
|
22
|
+
|
|
23
|
+
if (params) {
|
|
24
|
+
return [true, params as Params];
|
|
25
|
+
}
|
|
26
|
+
return [false];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async handle(request: DecodedRequest<Params, Query, Body>) {
|
|
30
|
+
await Context.setOrganizationScope();
|
|
31
|
+
await Context.authenticate();
|
|
32
|
+
const query = await GetBalanceItemsEndpoint.buildQuery(request.query);
|
|
33
|
+
|
|
34
|
+
const count = await query
|
|
35
|
+
.count();
|
|
36
|
+
|
|
37
|
+
return new Response(
|
|
38
|
+
CountResponse.create({
|
|
39
|
+
count,
|
|
40
|
+
}),
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
}
|