@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
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
import { Order, Organization, Webshop } from '@stamhoofd/models';
|
|
2
|
+
import { BalanceItemPaymentsHtmlTableItem, BalanceItemRelationType, BalanceItemType, getBalanceItemPaymentsHtmlTable, PaymentGeneral, PaymentMethod, PaymentMethodHelper, Replacement, Webshop as WebshopStruct } from '@stamhoofd/structures';
|
|
3
|
+
import { Formatter } from '@stamhoofd/utility';
|
|
4
|
+
import { createOrderDataHTMLTable } from '../helpers/email-html-helpers.js';
|
|
5
|
+
|
|
6
|
+
export type ReplacementsOptions = {
|
|
7
|
+
/**
|
|
8
|
+
* If not set, defaults to true
|
|
9
|
+
*/
|
|
10
|
+
shouldAddReplacementsForOrder?: boolean;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* If not set, defaults to true
|
|
14
|
+
*/
|
|
15
|
+
shouldAddReplacementsForTransfers?: boolean;
|
|
16
|
+
orderMap: Map<string, Order>;
|
|
17
|
+
webshopMap: Map<string, Webshop>;
|
|
18
|
+
organizationMap: Map<string, Organization>;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* To reduce the amount of queries, payment options should be generated for the whole aray of payments you want to send emails to.
|
|
23
|
+
*/
|
|
24
|
+
export async function buildReplacementOptions(payments: PaymentGeneral[], options?: { doesIncludePaymentWithoutOrders: boolean; areAllPaymentsTransfers: boolean }): Promise<ReplacementsOptions> {
|
|
25
|
+
// get all orders linked to the payments
|
|
26
|
+
const allOrderIdsSet = new Set<string>();
|
|
27
|
+
const allWebshopIdsSet = new Set<string>();
|
|
28
|
+
const organizationIdsForOrdersSet = new Set<string>();
|
|
29
|
+
|
|
30
|
+
for (const payment of payments) {
|
|
31
|
+
payment.webshopIds.forEach(id => allWebshopIdsSet.add(id));
|
|
32
|
+
|
|
33
|
+
for (const balanceItemPayment of payment.balanceItemPayments) {
|
|
34
|
+
const balanceItem = balanceItemPayment.balanceItem;
|
|
35
|
+
if (balanceItem.orderId) {
|
|
36
|
+
allOrderIdsSet.add(balanceItem.orderId);
|
|
37
|
+
|
|
38
|
+
// only important if balance item has order
|
|
39
|
+
organizationIdsForOrdersSet.add(balanceItem.organizationId);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// get all orders (for replacements later)
|
|
45
|
+
const orders = await Order.getByIDs(...allOrderIdsSet);
|
|
46
|
+
const orderMap = new Map<string, Order>(orders.map(o => [o.id, o] as [string, Order]));
|
|
47
|
+
|
|
48
|
+
// get all webshops (for replacements later)
|
|
49
|
+
const webshops = await Webshop.getByIDs(...allWebshopIdsSet);
|
|
50
|
+
const webshopMap = new Map<string, Webshop>(webshops.map(w => [w.id, w] as [string, Webshop]));
|
|
51
|
+
|
|
52
|
+
// get all organizations (for replacements later)
|
|
53
|
+
const organizations = await Organization.getByIDs(...organizationIdsForOrdersSet);
|
|
54
|
+
const organizationMap = new Map<string, Organization>(organizations.map(o => [o.id, o] as [string, Organization]));
|
|
55
|
+
|
|
56
|
+
return {
|
|
57
|
+
shouldAddReplacementsForOrder: options ? !options.doesIncludePaymentWithoutOrders : true,
|
|
58
|
+
shouldAddReplacementsForTransfers: options ? options.areAllPaymentsTransfers : true,
|
|
59
|
+
orderMap,
|
|
60
|
+
webshopMap,
|
|
61
|
+
organizationMap,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function getEmailReplacementsForPayment(payment: PaymentGeneral, options: ReplacementsOptions): Replacement[] {
|
|
66
|
+
const { orderMap, webshopMap, organizationMap, shouldAddReplacementsForOrder, shouldAddReplacementsForTransfers } = options;
|
|
67
|
+
const orderIds = new Set<string>();
|
|
68
|
+
|
|
69
|
+
for (const balanceItemPayment of payment.balanceItemPayments) {
|
|
70
|
+
const orderId = balanceItemPayment.balanceItem.orderId;
|
|
71
|
+
if (orderId) {
|
|
72
|
+
orderIds.add(orderId);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// will be set if only 1 order is linked
|
|
77
|
+
let singleOrder: Order | null = null;
|
|
78
|
+
|
|
79
|
+
if (orderIds.size === 1) {
|
|
80
|
+
const singleOrderId = [...orderIds][0];
|
|
81
|
+
if (singleOrderId) {
|
|
82
|
+
const order = orderMap.get(singleOrderId);
|
|
83
|
+
|
|
84
|
+
if (order) {
|
|
85
|
+
singleOrder = order;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
let orderUrlReplacement: Replacement | null = null;
|
|
91
|
+
let paymentUrl: string = '{{signInUrl}}';
|
|
92
|
+
|
|
93
|
+
// add replacement for order url if only 1 order is linked
|
|
94
|
+
if (shouldAddReplacementsForOrder ?? true) {
|
|
95
|
+
if (singleOrder) {
|
|
96
|
+
const webshop = webshopMap.get(singleOrder.webshopId);
|
|
97
|
+
const organization = organizationMap.get(singleOrder.organizationId);
|
|
98
|
+
|
|
99
|
+
if (webshop && organization) {
|
|
100
|
+
const webshopStruct = WebshopStruct.create(webshop);
|
|
101
|
+
|
|
102
|
+
orderUrlReplacement = Replacement.create({
|
|
103
|
+
token: 'orderUrl',
|
|
104
|
+
value: 'https://' + webshopStruct.getUrl(organization) + '/order/' + (singleOrder.id),
|
|
105
|
+
});
|
|
106
|
+
paymentUrl = 'https://' + webshopStruct.getUrl(organization) + '/order/' + (singleOrder.id);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
// Fallback (should not happen, but better than leaving {{orderUrl}} in place)
|
|
111
|
+
orderUrlReplacement = Replacement.create({
|
|
112
|
+
token: 'orderUrl',
|
|
113
|
+
value: paymentUrl,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const createPaymentDataHtml = () => {
|
|
119
|
+
if (singleOrder) {
|
|
120
|
+
const webshop = webshopMap.get(singleOrder.webshopId);
|
|
121
|
+
if (webshop) {
|
|
122
|
+
return createOrderDataHTMLTable(singleOrder, webshop);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return payment.getPaymentDataHTMLTable();
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
const paymentDataHtml = createPaymentDataHtml();
|
|
130
|
+
|
|
131
|
+
return ([
|
|
132
|
+
Replacement.create({
|
|
133
|
+
token: 'paymentUrl',
|
|
134
|
+
value: paymentUrl,
|
|
135
|
+
}),
|
|
136
|
+
Replacement.create({
|
|
137
|
+
token: 'priceToPay',
|
|
138
|
+
value: Formatter.price(payment.price),
|
|
139
|
+
}),
|
|
140
|
+
Replacement.create({
|
|
141
|
+
token: 'paymentMethod',
|
|
142
|
+
value: PaymentMethodHelper.getName(payment.method ?? PaymentMethod.Unknown),
|
|
143
|
+
}),
|
|
144
|
+
...((shouldAddReplacementsForTransfers ?? true)
|
|
145
|
+
? [
|
|
146
|
+
Replacement.create({
|
|
147
|
+
token: 'transferDescription',
|
|
148
|
+
value: (payment.transferDescription ?? ''),
|
|
149
|
+
}),
|
|
150
|
+
Replacement.create({
|
|
151
|
+
token: 'transferBankAccount',
|
|
152
|
+
value: payment.transferSettings?.iban ?? '',
|
|
153
|
+
}),
|
|
154
|
+
Replacement.create({
|
|
155
|
+
token: 'transferBankCreditor',
|
|
156
|
+
value: payment.transferSettings?.creditor ?? (payment.organizationId ? organizationMap.get(payment.organizationId)?.name : '') ?? '',
|
|
157
|
+
}),
|
|
158
|
+
]
|
|
159
|
+
: [
|
|
160
|
+
Replacement.create({
|
|
161
|
+
token: 'transferDescription',
|
|
162
|
+
value: '',
|
|
163
|
+
}),
|
|
164
|
+
Replacement.create({
|
|
165
|
+
token: 'transferBankAccount',
|
|
166
|
+
value: '',
|
|
167
|
+
}),
|
|
168
|
+
Replacement.create({
|
|
169
|
+
token: 'transferBankCreditor',
|
|
170
|
+
value: '',
|
|
171
|
+
}),
|
|
172
|
+
]),
|
|
173
|
+
|
|
174
|
+
Replacement.create({
|
|
175
|
+
token: 'overviewTable',
|
|
176
|
+
value: '',
|
|
177
|
+
html: getBalanceItemPaymentsHtmlTable(unboxBalanceItemPayments(payment, orderMap)),
|
|
178
|
+
}),
|
|
179
|
+
Replacement.create({
|
|
180
|
+
token: 'paymentTable',
|
|
181
|
+
value: '',
|
|
182
|
+
html: payment.getHTMLTable(),
|
|
183
|
+
}),
|
|
184
|
+
Replacement.create({
|
|
185
|
+
token: 'paymentData',
|
|
186
|
+
value: '',
|
|
187
|
+
html: paymentDataHtml,
|
|
188
|
+
}),
|
|
189
|
+
Replacement.create({
|
|
190
|
+
token: 'overviewContext',
|
|
191
|
+
value: getPaymentContext(payment, options),
|
|
192
|
+
}),
|
|
193
|
+
Replacement.create({
|
|
194
|
+
token: 'memberNames',
|
|
195
|
+
value: payment.memberNames,
|
|
196
|
+
}),
|
|
197
|
+
orderUrlReplacement,
|
|
198
|
+
]).filter(replacementOrNull => replacementOrNull !== null);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function getPaymentContext(payment: PaymentGeneral, { orderMap, webshopMap }: ReplacementsOptions) {
|
|
202
|
+
const overviewContext = new Set<string>();
|
|
203
|
+
const registrationMemberNames = new Set<string>();
|
|
204
|
+
|
|
205
|
+
// only add to context if type is order or registration
|
|
206
|
+
for (const balanceItemPayment of payment.balanceItemPayments) {
|
|
207
|
+
const balanceItem = balanceItemPayment.balanceItem;
|
|
208
|
+
const type = balanceItem.type;
|
|
209
|
+
|
|
210
|
+
switch (type) {
|
|
211
|
+
case BalanceItemType.Order: {
|
|
212
|
+
if (balanceItem.orderId) {
|
|
213
|
+
const order = orderMap.get(balanceItem.orderId);
|
|
214
|
+
|
|
215
|
+
if (order) {
|
|
216
|
+
const webshop = webshopMap.get(order.webshopId);
|
|
217
|
+
if (webshop) {
|
|
218
|
+
if (order.number) {
|
|
219
|
+
overviewContext.add($t('80c86ad4-5ca1-481a-a408-db018a81f25e', {
|
|
220
|
+
webshop: webshop.meta.name,
|
|
221
|
+
orderNumber: order.number ?? '',
|
|
222
|
+
}));
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
overviewContext.add(webshop.meta.name);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
overviewContext.add($t('8bb27033-cf3c-4af1-a3f4-3373734ab189', {
|
|
230
|
+
orderNumber: order.number ?? '',
|
|
231
|
+
}));
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
break;
|
|
236
|
+
}
|
|
237
|
+
case BalanceItemType.Registration: {
|
|
238
|
+
const memberName = balanceItem.relations.get(BalanceItemRelationType.Member)?.name.toString();
|
|
239
|
+
if (memberName) {
|
|
240
|
+
registrationMemberNames.add(memberName);
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
overviewContext.add(balanceItem.itemTitle);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
break;
|
|
247
|
+
}
|
|
248
|
+
default: {
|
|
249
|
+
break;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
if (registrationMemberNames.size > 0) {
|
|
255
|
+
const memberNames = Formatter.joinLast([...registrationMemberNames], ', ', ' ' + $t(`6a156458-b396-4d0f-b562-adb3e38fc51b`) + ' ');
|
|
256
|
+
overviewContext.add($t(`01d5fd7e-2960-4eb4-ab3a-2ac6dcb2e39c`) + ' ' + memberNames);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (overviewContext.size === 0) {
|
|
260
|
+
// add item title if no balance items with type order or registration
|
|
261
|
+
if (payment.balanceItemPayments.length === 1) {
|
|
262
|
+
const balanceItem = payment.balanceItemPayments[0].balanceItem;
|
|
263
|
+
return balanceItem.itemTitle;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
if (payment.balanceItemPayments.length > 1) {
|
|
267
|
+
// return title if all balance items have the same title
|
|
268
|
+
const firstTitle = payment.balanceItemPayments[0].balanceItem.itemTitle;
|
|
269
|
+
const haveAllSameTitle = payment.balanceItemPayments.every(p => p.balanceItem.itemTitle === firstTitle);
|
|
270
|
+
|
|
271
|
+
if (haveAllSameTitle) {
|
|
272
|
+
return `${firstTitle} (${payment.balanceItemPayments.length}x)`;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// else return default text for multiple items
|
|
276
|
+
return $t('7462f89e-db05-452f-804f-b9f2d51bff0d', { count: payment.balanceItemPayments.length });
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// else return default text for single item
|
|
280
|
+
return $t('fe349d88-fecf-4cd8-8ea4-9e3b13cfa0dc');
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// join texts for balance items with type order or registration
|
|
284
|
+
return [...overviewContext].join(', ');
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
function unboxBalanceItemPayments({ balanceItemPayments }: PaymentGeneral, orderMap: Map<string, Order>): BalanceItemPaymentsHtmlTableItem[] {
|
|
288
|
+
const results: BalanceItemPaymentsHtmlTableItem[] = [];
|
|
289
|
+
for (const item of balanceItemPayments) {
|
|
290
|
+
const orderId = item.balanceItem.orderId;
|
|
291
|
+
if (orderId === null) {
|
|
292
|
+
results.push(item);
|
|
293
|
+
continue;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
const order = orderMap.get(orderId);
|
|
297
|
+
if (!order) {
|
|
298
|
+
// if 1 order is not found -> do not unbox the payment
|
|
299
|
+
return balanceItemPayments;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
for (const cartItem of order.data.cart.items) {
|
|
303
|
+
const price = cartItem.getPriceWithDiscounts();
|
|
304
|
+
const quantity = cartItem.amount;
|
|
305
|
+
const unitPrice = Math.abs(quantity) > 1 ? price / quantity : price;
|
|
306
|
+
|
|
307
|
+
results.push({
|
|
308
|
+
itemTitle: cartItem.product.name,
|
|
309
|
+
itemDescription: cartItem.description,
|
|
310
|
+
balanceItem: {
|
|
311
|
+
description: cartItem.description,
|
|
312
|
+
},
|
|
313
|
+
quantity,
|
|
314
|
+
unitPrice,
|
|
315
|
+
price,
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
return results;
|
|
321
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Decoder } from '@simonbackx/simple-encoding';
|
|
2
2
|
import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
|
|
3
3
|
import { SimpleError } from '@simonbackx/simple-errors';
|
|
4
|
-
import {
|
|
4
|
+
import { ChargeRequest, LimitedFilteredRequest, PermissionLevel } from '@stamhoofd/structures';
|
|
5
5
|
|
|
6
6
|
import { QueueHandler } from '@stamhoofd/queues';
|
|
7
7
|
import { Context } from '../../../helpers/Context.js';
|
|
@@ -10,13 +10,12 @@ import { MemberCharger } from '../../../helpers/MemberCharger.js';
|
|
|
10
10
|
import { GetMembersEndpoint } from '../../global/members/GetMembersEndpoint.js';
|
|
11
11
|
|
|
12
12
|
type Params = Record<string, never>;
|
|
13
|
-
type Query =
|
|
14
|
-
type Body =
|
|
13
|
+
type Query = undefined;
|
|
14
|
+
type Body = ChargeRequest;
|
|
15
15
|
type ResponseBody = undefined;
|
|
16
16
|
|
|
17
17
|
export class ChargeMembersEndpoint extends Endpoint<Params, Query, Body, ResponseBody> {
|
|
18
|
-
|
|
19
|
-
bodyDecoder = ChargeMembersRequest as Decoder<ChargeMembersRequest>;
|
|
18
|
+
bodyDecoder = ChargeRequest as Decoder<ChargeRequest>;
|
|
20
19
|
|
|
21
20
|
protected doesMatch(request: Request): [true, Params] | [false] {
|
|
22
21
|
if (request.method !== 'POST') {
|
|
@@ -72,7 +71,7 @@ export class ChargeMembersEndpoint extends Endpoint<Params, Query, Body, Respons
|
|
|
72
71
|
|
|
73
72
|
ChargeMembersEndpoint.throwIfInvalidBody(body);
|
|
74
73
|
|
|
75
|
-
const queueId = 'charge-members';
|
|
74
|
+
const queueId = 'charge-members-' + organization.id;
|
|
76
75
|
|
|
77
76
|
if (QueueHandler.isRunning(queueId)) {
|
|
78
77
|
throw new SimpleError({
|
|
@@ -83,7 +82,10 @@ export class ChargeMembersEndpoint extends Endpoint<Params, Query, Body, Respons
|
|
|
83
82
|
}
|
|
84
83
|
|
|
85
84
|
await QueueHandler.schedule(queueId, async () => {
|
|
86
|
-
const dataGenerator = fetchToAsyncIterator(
|
|
85
|
+
const dataGenerator = fetchToAsyncIterator(new LimitedFilteredRequest({
|
|
86
|
+
filter: body.filter,
|
|
87
|
+
limit: 100,
|
|
88
|
+
}), {
|
|
87
89
|
fetch: request => GetMembersEndpoint.buildData(request, PermissionLevel.Write),
|
|
88
90
|
});
|
|
89
91
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
|
|
2
2
|
import { SimpleError } from '@simonbackx/simple-errors';
|
|
3
3
|
import { QueueHandler } from '@stamhoofd/queues';
|
|
4
|
-
import { Context } from '../../../helpers/Context';
|
|
5
|
-
import { MembershipCharger } from '../../../helpers/MembershipCharger';
|
|
4
|
+
import { Context } from '../../../helpers/Context.js';
|
|
5
|
+
import { MembershipCharger } from '../../../helpers/MembershipCharger.js';
|
|
6
6
|
|
|
7
7
|
type Params = Record<string, never>;
|
|
8
8
|
type Query = Record<string, never>;
|
|
@@ -3,7 +3,7 @@ import { Platform } from '@stamhoofd/models';
|
|
|
3
3
|
import { QueueHandler } from '@stamhoofd/queues';
|
|
4
4
|
import { SQL, SQLAlias, SQLCount, SQLDistinct, SQLSelectAs, SQLSum, SQLWhereSign } from '@stamhoofd/sql';
|
|
5
5
|
import { ChargeMembershipsSummary, ChargeMembershipsTypeSummary } from '@stamhoofd/structures';
|
|
6
|
-
import { Context } from '../../../helpers/Context';
|
|
6
|
+
import { Context } from '../../../helpers/Context.js';
|
|
7
7
|
|
|
8
8
|
type Params = Record<string, never>;
|
|
9
9
|
type Query = Record<string, never>;
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import { Decoder } from '@simonbackx/simple-encoding';
|
|
2
2
|
import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
|
|
3
3
|
import { SimpleError } from '@simonbackx/simple-errors';
|
|
4
|
-
import {
|
|
4
|
+
import { ChargeRequest, LimitedFilteredRequest } from '@stamhoofd/structures';
|
|
5
5
|
|
|
6
6
|
import { QueueHandler } from '@stamhoofd/queues';
|
|
7
|
-
import { Context } from '../../../helpers/Context';
|
|
8
|
-
import { fetchToAsyncIterator } from '../../../helpers/fetchToAsyncIterator';
|
|
9
|
-
import { OrganizationCharger } from '../../../helpers/OrganizationCharger';
|
|
10
|
-
import { GetOrganizationsEndpoint } from './GetOrganizationsEndpoint';
|
|
7
|
+
import { Context } from '../../../helpers/Context.js';
|
|
8
|
+
import { fetchToAsyncIterator } from '../../../helpers/fetchToAsyncIterator.js';
|
|
9
|
+
import { OrganizationCharger } from '../../../helpers/OrganizationCharger.js';
|
|
10
|
+
import { GetOrganizationsEndpoint } from './GetOrganizationsEndpoint.js';
|
|
11
|
+
import { ChargeMembersEndpoint } from '../members/ChargeMembersEndpoint.js';
|
|
11
12
|
|
|
12
13
|
type Params = Record<string, never>;
|
|
13
|
-
type Query =
|
|
14
|
-
type Body =
|
|
14
|
+
type Query = undefined;
|
|
15
|
+
type Body = ChargeRequest;
|
|
15
16
|
type ResponseBody = undefined;
|
|
16
17
|
|
|
17
18
|
export class ChargeOrganizationsEndpoint extends Endpoint<Params, Query, Body, ResponseBody> {
|
|
18
|
-
|
|
19
|
-
bodyDecoder = ChargeOrganizationsRequest as Decoder<ChargeOrganizationsRequest>;
|
|
19
|
+
bodyDecoder = ChargeRequest as Decoder<ChargeRequest>;
|
|
20
20
|
|
|
21
21
|
protected doesMatch(request: Request): [true, Params] | [false] {
|
|
22
22
|
if (request.method !== 'POST') {
|
|
@@ -31,45 +31,8 @@ export class ChargeOrganizationsEndpoint extends Endpoint<Params, Query, Body, R
|
|
|
31
31
|
return [false];
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
private static throwIfInvalidBody(body: Body) {
|
|
35
|
-
if (!body.description?.trim()?.length) {
|
|
36
|
-
throw new SimpleError({
|
|
37
|
-
code: 'invalid_field',
|
|
38
|
-
message: 'Invalid description',
|
|
39
|
-
human: $t(`2449fba5-99dc-496f-a9d6-a67263d56616`),
|
|
40
|
-
field: 'description',
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
if (!body.price) {
|
|
45
|
-
throw new SimpleError({
|
|
46
|
-
code: 'invalid_field',
|
|
47
|
-
message: 'Invalid price',
|
|
48
|
-
human: $t(`1e165aac-8a58-45c5-bdd8-c58131a7b7f5`),
|
|
49
|
-
field: 'price',
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
if (body.amount === 0) {
|
|
54
|
-
throw new SimpleError({
|
|
55
|
-
code: 'invalid_field',
|
|
56
|
-
message: 'Invalid amount',
|
|
57
|
-
human: $t(`0bdf4953-1eae-41fd-b142-5ad3287f17a7`),
|
|
58
|
-
field: 'amount',
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
if (!body.organizationId) {
|
|
63
|
-
throw new SimpleError({
|
|
64
|
-
code: 'invalid_field',
|
|
65
|
-
message: 'Invalid organization id',
|
|
66
|
-
human: $t(`ae7ac6ab-bb02-4cd6-823f-7076e4ce6f6c`),
|
|
67
|
-
field: 'organizationId',
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
34
|
async handle(request: DecodedRequest<Params, Query, Body>) {
|
|
35
|
+
const organization = await Context.setOrganizationScope();
|
|
73
36
|
await Context.authenticate();
|
|
74
37
|
|
|
75
38
|
if (!Context.auth.hasPlatformFullAccess()) {
|
|
@@ -77,7 +40,7 @@ export class ChargeOrganizationsEndpoint extends Endpoint<Params, Query, Body, R
|
|
|
77
40
|
}
|
|
78
41
|
|
|
79
42
|
const body = request.body;
|
|
80
|
-
|
|
43
|
+
ChargeMembersEndpoint.throwIfInvalidBody(body);
|
|
81
44
|
|
|
82
45
|
const queueId = 'charge-organizations';
|
|
83
46
|
|
|
@@ -90,13 +53,16 @@ export class ChargeOrganizationsEndpoint extends Endpoint<Params, Query, Body, R
|
|
|
90
53
|
}
|
|
91
54
|
|
|
92
55
|
await QueueHandler.schedule(queueId, async () => {
|
|
93
|
-
const dataGenerator = fetchToAsyncIterator(
|
|
56
|
+
const dataGenerator = fetchToAsyncIterator(new LimitedFilteredRequest({
|
|
57
|
+
filter: body.filter,
|
|
58
|
+
limit: 100,
|
|
59
|
+
}), {
|
|
94
60
|
fetch: GetOrganizationsEndpoint.buildData,
|
|
95
61
|
});
|
|
96
62
|
|
|
97
63
|
for await (const data of dataGenerator) {
|
|
98
64
|
await OrganizationCharger.chargeMany({
|
|
99
|
-
chargingOrganizationId:
|
|
65
|
+
chargingOrganizationId: organization.id,
|
|
100
66
|
organizationsToCharge: data,
|
|
101
67
|
price: body.price,
|
|
102
68
|
amount: body.amount ?? 1,
|
|
@@ -2,8 +2,8 @@ import { Decoder } from '@simonbackx/simple-encoding';
|
|
|
2
2
|
import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
|
|
3
3
|
import { CountFilteredRequest, CountResponse } from '@stamhoofd/structures';
|
|
4
4
|
|
|
5
|
-
import { Context } from '../../../helpers/Context';
|
|
6
|
-
import { GetOrganizationsEndpoint } from './GetOrganizationsEndpoint';
|
|
5
|
+
import { Context } from '../../../helpers/Context.js';
|
|
6
|
+
import { GetOrganizationsEndpoint } from './GetOrganizationsEndpoint.js';
|
|
7
7
|
|
|
8
8
|
type Params = Record<string, never>;
|
|
9
9
|
type Query = CountFilteredRequest;
|
|
@@ -6,10 +6,10 @@ import { SQL, applySQLSorter, compileToSQLFilter } from '@stamhoofd/sql';
|
|
|
6
6
|
import { CountFilteredRequest, LimitedFilteredRequest, Organization as OrganizationStruct, PaginatedResponse, PermissionLevel, StamhoofdFilter, assertSort, getSortFilter } from '@stamhoofd/structures';
|
|
7
7
|
|
|
8
8
|
import { SQLResultNamespacedRow } from '@simonbackx/simple-database';
|
|
9
|
-
import { AuthenticatedStructures } from '../../../helpers/AuthenticatedStructures';
|
|
10
|
-
import { Context } from '../../../helpers/Context';
|
|
11
|
-
import { organizationFilterCompilers } from '../../../sql-filters/organizations';
|
|
12
|
-
import { organizationSorters } from '../../../sql-sorters/organizations';
|
|
9
|
+
import { AuthenticatedStructures } from '../../../helpers/AuthenticatedStructures.js';
|
|
10
|
+
import { Context } from '../../../helpers/Context.js';
|
|
11
|
+
import { organizationFilterCompilers } from '../../../sql-filters/organizations.js';
|
|
12
|
+
import { organizationSorters } from '../../../sql-sorters/organizations.js';
|
|
13
13
|
|
|
14
14
|
type Params = Record<string, never>;
|
|
15
15
|
type Query = LimitedFilteredRequest;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { AutoEncoderPatchType, Decoder, PatchableArrayAutoEncoder, PatchableArrayDecoder, StringDecoder } from '@simonbackx/simple-encoding';
|
|
2
2
|
import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
|
|
3
3
|
import { SimpleError } from '@simonbackx/simple-errors';
|
|
4
|
-
import { Organization, OrganizationRegistrationPeriod, Platform } from '@stamhoofd/models';
|
|
4
|
+
import { Organization, OrganizationRegistrationPeriod, Platform, RegistrationPeriod } from '@stamhoofd/models';
|
|
5
5
|
import { Organization as OrganizationStruct } from '@stamhoofd/structures';
|
|
6
6
|
|
|
7
7
|
import { Formatter } from '@stamhoofd/utility';
|
|
8
|
-
import { AuthenticatedStructures } from '../../../helpers/AuthenticatedStructures';
|
|
9
|
-
import { Context } from '../../../helpers/Context';
|
|
8
|
+
import { AuthenticatedStructures } from '../../../helpers/AuthenticatedStructures.js';
|
|
9
|
+
import { Context } from '../../../helpers/Context.js';
|
|
10
10
|
|
|
11
11
|
type Params = Record<string, never>;
|
|
12
12
|
type Query = undefined;
|
|
@@ -126,8 +126,18 @@ export class PatchOrganizationsEndpoint extends Endpoint<Params, Query, Body, Re
|
|
|
126
126
|
organization.meta = put.meta;
|
|
127
127
|
organization.address = put.address;
|
|
128
128
|
|
|
129
|
-
|
|
130
|
-
|
|
129
|
+
let period: RegistrationPeriod | null = null;
|
|
130
|
+
|
|
131
|
+
if (STAMHOOFD.userMode === 'platform') {
|
|
132
|
+
const periodId = (await Platform.getShared()).periodIdIfPlatform;
|
|
133
|
+
organization.periodId = periodId;
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
period = new RegistrationPeriod();
|
|
137
|
+
period.configureForNewOrganization();
|
|
138
|
+
await period.save();
|
|
139
|
+
organization.periodId = period.id;
|
|
140
|
+
}
|
|
131
141
|
|
|
132
142
|
if (put.privateMeta) {
|
|
133
143
|
organization.privateMeta = put.privateMeta;
|
|
@@ -145,9 +155,14 @@ export class PatchOrganizationsEndpoint extends Endpoint<Params, Query, Body, Re
|
|
|
145
155
|
});
|
|
146
156
|
}
|
|
147
157
|
|
|
158
|
+
if (STAMHOOFD.userMode !== 'platform' && period) {
|
|
159
|
+
period.organizationId = organization.id;
|
|
160
|
+
await period.save();
|
|
161
|
+
}
|
|
162
|
+
|
|
148
163
|
const organizationPeriod = new OrganizationRegistrationPeriod();
|
|
149
164
|
organizationPeriod.organizationId = organization.id;
|
|
150
|
-
organizationPeriod.periodId = periodId;
|
|
165
|
+
organizationPeriod.periodId = organization.periodId;
|
|
151
166
|
await organizationPeriod.save();
|
|
152
167
|
|
|
153
168
|
result.push(organization);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Decoder } from '@simonbackx/simple-encoding';
|
|
2
2
|
import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
|
|
3
3
|
import { SimpleError } from '@simonbackx/simple-errors';
|
|
4
|
-
import {
|
|
4
|
+
import { ChargeRequest, LimitedFilteredRequest, PermissionLevel } from '@stamhoofd/structures';
|
|
5
5
|
|
|
6
6
|
import { QueueHandler } from '@stamhoofd/queues';
|
|
7
7
|
import { Context } from '../../../helpers/Context.js';
|
|
@@ -11,13 +11,12 @@ import { GetRegistrationsEndpoint } from '../../global/registration/GetRegistrat
|
|
|
11
11
|
import { ChargeMembersEndpoint } from '../members/ChargeMembersEndpoint.js';
|
|
12
12
|
|
|
13
13
|
type Params = Record<string, never>;
|
|
14
|
-
type Query =
|
|
15
|
-
type Body =
|
|
14
|
+
type Query = undefined;
|
|
15
|
+
type Body = ChargeRequest;
|
|
16
16
|
type ResponseBody = undefined;
|
|
17
17
|
|
|
18
18
|
export class ChargeRegistrationsEndpoint extends Endpoint<Params, Query, Body, ResponseBody> {
|
|
19
|
-
|
|
20
|
-
bodyDecoder = ChargeMembersRequest as Decoder<ChargeMembersRequest>;
|
|
19
|
+
bodyDecoder = ChargeRequest as Decoder<ChargeRequest>;
|
|
21
20
|
|
|
22
21
|
protected doesMatch(request: Request): [true, Params] | [false] {
|
|
23
22
|
if (request.method !== 'POST') {
|
|
@@ -44,7 +43,7 @@ export class ChargeRegistrationsEndpoint extends Endpoint<Params, Query, Body, R
|
|
|
44
43
|
|
|
45
44
|
ChargeMembersEndpoint.throwIfInvalidBody(body);
|
|
46
45
|
|
|
47
|
-
const queueId = 'charge-registrations';
|
|
46
|
+
const queueId = 'charge-registrations-' + organization.id;
|
|
48
47
|
|
|
49
48
|
if (QueueHandler.isRunning(queueId)) {
|
|
50
49
|
throw new SimpleError({
|
|
@@ -55,7 +54,10 @@ export class ChargeRegistrationsEndpoint extends Endpoint<Params, Query, Body, R
|
|
|
55
54
|
}
|
|
56
55
|
|
|
57
56
|
await QueueHandler.schedule(queueId, async () => {
|
|
58
|
-
const dataGenerator = fetchToAsyncIterator(
|
|
57
|
+
const dataGenerator = fetchToAsyncIterator(new LimitedFilteredRequest({
|
|
58
|
+
filter: body.filter,
|
|
59
|
+
limit: 100,
|
|
60
|
+
}), {
|
|
59
61
|
fetch: request => GetRegistrationsEndpoint.buildData(request, PermissionLevel.Write),
|
|
60
62
|
});
|
|
61
63
|
|
|
@@ -5,8 +5,8 @@ import { PasswordToken, Platform, sendEmailTemplate, User } from '@stamhoofd/mod
|
|
|
5
5
|
import { EmailTemplateType, Recipient, Replacement, UserPermissions, User as UserStruct, UserWithMembers } from '@stamhoofd/structures';
|
|
6
6
|
import { Formatter } from '@stamhoofd/utility';
|
|
7
7
|
|
|
8
|
-
import { AuthenticatedStructures } from '../../helpers/AuthenticatedStructures';
|
|
9
|
-
import { Context } from '../../helpers/Context';
|
|
8
|
+
import { AuthenticatedStructures } from '../../helpers/AuthenticatedStructures.js';
|
|
9
|
+
import { Context } from '../../helpers/Context.js';
|
|
10
10
|
type Params = Record<string, never>;
|
|
11
11
|
type Query = undefined;
|
|
12
12
|
type Body = UserStruct;
|
|
@@ -2,8 +2,8 @@ import { Request } from '@simonbackx/simple-endpoints';
|
|
|
2
2
|
import { OrganizationFactory, Token, UserFactory } from '@stamhoofd/models';
|
|
3
3
|
import { Token as TokenStruct } from '@stamhoofd/structures';
|
|
4
4
|
|
|
5
|
-
import { testServer } from '../../../tests/helpers/TestServer';
|
|
6
|
-
import { CreateTokenEndpoint } from './CreateTokenEndpoint';
|
|
5
|
+
import { testServer } from '../../../tests/helpers/TestServer.js';
|
|
6
|
+
import { CreateTokenEndpoint } from './CreateTokenEndpoint.js';
|
|
7
7
|
|
|
8
8
|
describe('Endpoint.CreateToken', () => {
|
|
9
9
|
// Test endpoint
|
|
@@ -3,7 +3,7 @@ import { SimpleError } from '@simonbackx/simple-errors';
|
|
|
3
3
|
import { EmailVerificationCode, PasswordToken, Platform, Token, User } from '@stamhoofd/models';
|
|
4
4
|
import { ChallengeGrantStruct, CreateTokenStruct, LoginMethod, PasswordGrantStruct, PasswordTokenGrantStruct, RefreshTokenGrantStruct, RequestChallengeGrantStruct, SignupResponse, Token as TokenStruct } from '@stamhoofd/structures';
|
|
5
5
|
|
|
6
|
-
import { Context } from '../../helpers/Context';
|
|
6
|
+
import { Context } from '../../helpers/Context.js';
|
|
7
7
|
|
|
8
8
|
type Params = Record<string, never>;
|
|
9
9
|
type Query = undefined;
|