@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
|
@@ -5,8 +5,8 @@ import { QueueHandler } from '@stamhoofd/queues';
|
|
|
5
5
|
import { SQL, SQLWhereSign } from '@stamhoofd/sql';
|
|
6
6
|
import { AuditLogSource, PlatformMembershipTypeBehaviour } from '@stamhoofd/structures';
|
|
7
7
|
import { Formatter, Sorter } from '@stamhoofd/utility';
|
|
8
|
-
import { AuditLogService } from './AuditLogService';
|
|
9
|
-
import { MemberNumberService } from './MemberNumberService';
|
|
8
|
+
import { AuditLogService } from './AuditLogService.js';
|
|
9
|
+
import { MemberNumberService } from './MemberNumberService.js';
|
|
10
10
|
|
|
11
11
|
export class PlatformMembershipService {
|
|
12
12
|
static listen() {
|
|
@@ -147,7 +147,7 @@ export class PlatformMembershipService {
|
|
|
147
147
|
console.log('update memberships for id ', id);
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
-
const me = await Member.
|
|
150
|
+
const me = await Member.getByIdWithRegistrationsAndGroups(id);
|
|
151
151
|
if (!me) {
|
|
152
152
|
if (!silent) {
|
|
153
153
|
console.log('Skipping automatic membership for: ' + id, ' - member not found');
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { ManyToOneRelation } from '@simonbackx/simple-database';
|
|
2
2
|
import { BalanceItem, Document, Group, Member, Registration } from '@stamhoofd/models';
|
|
3
3
|
import { AppliedRegistrationDiscount, AuditLogSource, BalanceItemRelationType, BalanceItemStatus, BalanceItemType, EmailTemplateType, StockReservation, TranslatedString, Version } from '@stamhoofd/structures';
|
|
4
|
-
import { AuditLogService } from './AuditLogService';
|
|
5
|
-
import { GroupService } from './GroupService';
|
|
6
|
-
import { PlatformMembershipService } from './PlatformMembershipService';
|
|
4
|
+
import { AuditLogService } from './AuditLogService.js';
|
|
5
|
+
import { GroupService } from './GroupService.js';
|
|
6
|
+
import { PlatformMembershipService } from './PlatformMembershipService.js';
|
|
7
7
|
import { QueueHandler } from '@stamhoofd/queues';
|
|
8
8
|
import { Formatter } from '@stamhoofd/utility';
|
|
9
9
|
import { encodeObject } from '@simonbackx/simple-encoding';
|
|
@@ -4,9 +4,9 @@ import { Organization, Platform, Token, User, Webshop } from '@stamhoofd/models'
|
|
|
4
4
|
import { LoginMethod, LoginProviderType, OpenIDClientConfiguration, StartOpenIDFlowStruct, Token as TokenStruct } from '@stamhoofd/structures';
|
|
5
5
|
import crypto from 'crypto';
|
|
6
6
|
import { generators, Issuer } from 'openid-client';
|
|
7
|
-
import { Context } from '../helpers/Context';
|
|
7
|
+
import { Context } from '../helpers/Context.js';
|
|
8
8
|
|
|
9
|
-
import { CookieHelper, ObjectWithHeaders } from '../helpers/CookieHelper';
|
|
9
|
+
import { CookieHelper, ObjectWithHeaders } from '../helpers/CookieHelper.js';
|
|
10
10
|
|
|
11
11
|
async function randomBytes(size: number): Promise<Buffer> {
|
|
12
12
|
return new Promise((resolve, reject) => {
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import { SimpleError } from '@simonbackx/simple-errors';
|
|
2
|
+
import { BalanceItem, Organization, Platform, Registration, STPackage } from '@stamhoofd/models';
|
|
3
|
+
import { SQL } from '@stamhoofd/sql';
|
|
4
|
+
import { BalanceItemRelation, BalanceItemRelationType, BalanceItemStatus, BalanceItemType, Country, PaymentCustomer, STPackageStatus, STPackageType, STPricingType, TranslatedString, VATExcemptReason } from '@stamhoofd/structures';
|
|
5
|
+
import { Formatter } from '@stamhoofd/utility';
|
|
6
|
+
import { GroupBuilder } from '../helpers/GroupBuilder.js';
|
|
7
|
+
|
|
8
|
+
export class STPackageService {
|
|
9
|
+
static async getActivePackages(organizationId: string) {
|
|
10
|
+
return await STPackage.select()
|
|
11
|
+
.where('organizationId', organizationId)
|
|
12
|
+
.andWhere('validAt', '!=', null)
|
|
13
|
+
.andWhere(
|
|
14
|
+
SQL.where('removeAt', null)
|
|
15
|
+
.or('removeAt', '>', new Date()),
|
|
16
|
+
)
|
|
17
|
+
.fetch();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Returns an up to date amount that should be charged for this package.
|
|
22
|
+
* Note that this value could be smaller than the already charged amount.
|
|
23
|
+
*/
|
|
24
|
+
static async getChargeableQuantity(pack: STPackage) {
|
|
25
|
+
// If type is
|
|
26
|
+
let amount = 1;
|
|
27
|
+
let membersCount: number | null = null;
|
|
28
|
+
|
|
29
|
+
if (membersCount === null && pack.meta.pricingType === STPricingType.PerMember) {
|
|
30
|
+
membersCount = await Registration.getActiveMembers(pack.organizationId);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (pack.meta.pricingType === STPricingType.PerMember) {
|
|
34
|
+
amount = membersCount ?? 1;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (amount < pack.meta.minimumAmount) {
|
|
38
|
+
amount = pack.meta.minimumAmount;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return amount;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
static async markValid(packageId: string) {
|
|
45
|
+
const pack = await STPackage.getByID(packageId);
|
|
46
|
+
if (!pack) {
|
|
47
|
+
console.error('Missing STPackage when marking STPackage as valid', packageId);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (pack.validAt) {
|
|
51
|
+
// Already valid
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
console.log('Marking STPackage as valid', packageId);
|
|
56
|
+
pack.validAt = new Date();
|
|
57
|
+
await pack.save();
|
|
58
|
+
|
|
59
|
+
if (pack.meta.didRenewId) {
|
|
60
|
+
const didRenewPackage = await STPackage.getByID(pack.meta.didRenewId);
|
|
61
|
+
if (didRenewPackage && didRenewPackage.organizationId === pack.organizationId) {
|
|
62
|
+
await this.didRenew(didRenewPackage, pack);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
await this.updateOrganizationPackages(pack.organizationId);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
static async didRenew(old: STPackage, renewedBy: STPackage) {
|
|
70
|
+
old.removeAt = renewedBy.meta.startDate ?? renewedBy.validAt ?? new Date();
|
|
71
|
+
old.meta.allowRenew = false;
|
|
72
|
+
await old.save();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
static async getPaidOrPendingQuantity(pack: STPackage) {
|
|
76
|
+
if (!pack.existsInDatabase || pack.createdAt.getTime() > Date.now() - 1_000) {
|
|
77
|
+
return 0;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return await BalanceItem.select()
|
|
81
|
+
.where('packageId', pack.id)
|
|
82
|
+
.where('status', BalanceItemStatus.Due)
|
|
83
|
+
.count(SQL.column('amount'));
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Create a balance item to charge an increase in amount of a given package.
|
|
88
|
+
*
|
|
89
|
+
* Convertable into STInvoiceItem (or the diffence if amount is increased)
|
|
90
|
+
* Use this to calculate prices or create an invoice
|
|
91
|
+
* This will calculate the price to expand the package to the given amount.
|
|
92
|
+
* If you want to renew a package, you need to create a new package first
|
|
93
|
+
*/
|
|
94
|
+
static async chargePackage(pack: STPackage, date?: Date, customer?: PaymentCustomer): Promise<BalanceItem | null> {
|
|
95
|
+
let unitPrice = Math.round(pack.meta.unitPrice);
|
|
96
|
+
|
|
97
|
+
let amount = await this.getChargeableQuantity(pack);
|
|
98
|
+
|
|
99
|
+
if (amount < pack.meta.minimumAmount) {
|
|
100
|
+
// Minimum should get applied first, because we might already have paid for the minimum (paid amount)
|
|
101
|
+
amount = pack.meta.minimumAmount;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const paid = await this.getPaidOrPendingQuantity(pack);
|
|
105
|
+
amount -= paid;
|
|
106
|
+
|
|
107
|
+
if (amount <= 0) {
|
|
108
|
+
amount = 0;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (amount <= 0) {
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/// When pricing type is memebrs, the price is calculated per year.
|
|
116
|
+
/// If a shorter period is remaining, we give a discount in order
|
|
117
|
+
/// to no need to handle it more complicated
|
|
118
|
+
let now = date ?? new Date();
|
|
119
|
+
if (now < pack.meta.startDate) {
|
|
120
|
+
// When creating a new package, we sometimes buy it for the future, so use that date instead of now
|
|
121
|
+
now = pack.meta.startDate;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (pack.validUntil && pack.meta.pricingType !== STPricingType.Fixed) {
|
|
125
|
+
const totalDays = Math.round((pack.validUntil.getTime() - pack.meta.startDate.getTime()) / (1000 * 60 * 60 * 24));
|
|
126
|
+
let remainingDays = Math.round((pack.validUntil.getTime() - now.getTime()) / (1000 * 60 * 60 * 24));
|
|
127
|
+
|
|
128
|
+
/// First 3 months are full price
|
|
129
|
+
const paidDays = 30 * 3;
|
|
130
|
+
|
|
131
|
+
if (remainingDays > totalDays) {
|
|
132
|
+
remainingDays = totalDays;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (totalDays > 366) {
|
|
136
|
+
// Increase unit price
|
|
137
|
+
unitPrice = unitPrice * (totalDays / 365);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (pack.meta.pricingType === STPricingType.PerMember) {
|
|
141
|
+
unitPrice = Math.round(Math.min(unitPrice, unitPrice * remainingDays / (Math.max(365, totalDays) - paidDays)));
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
unitPrice = Math.round(unitPrice);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const item = new BalanceItem();
|
|
149
|
+
item.type = BalanceItemType.STPackage;
|
|
150
|
+
item.description = pack.meta.name + ' ' + (
|
|
151
|
+
pack.validUntil
|
|
152
|
+
? $t('58b2c936-9025-4613-a9be-9d9bab212ea6', { startDate: Formatter.date(now, true), endDate: Formatter.date(pack.validUntil, true) })
|
|
153
|
+
: $t('33b8f500-248a-4020-b775-4dd437ca0173', { startDate: Formatter.date(pack.meta.startDate, true) })
|
|
154
|
+
);
|
|
155
|
+
item.relations.set(BalanceItemRelationType.STPackage, BalanceItemRelation.create({
|
|
156
|
+
id: pack.id,
|
|
157
|
+
name: TranslatedString.create(pack.meta.name),
|
|
158
|
+
}));
|
|
159
|
+
item.packageId = pack.id;
|
|
160
|
+
item.startDate = now;
|
|
161
|
+
|
|
162
|
+
if (pack.validUntil) {
|
|
163
|
+
item.endDate = pack.validUntil;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
item.payingOrganizationId = pack.organizationId;
|
|
167
|
+
const membershipOrganizationId = (await Platform.getShared()).membershipOrganizationId;
|
|
168
|
+
if (!membershipOrganizationId) {
|
|
169
|
+
throw new SimpleError({
|
|
170
|
+
code: 'unavailable',
|
|
171
|
+
message: 'No membership organization id set on the platform',
|
|
172
|
+
human: 'Package purchases are currently unavailable',
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
item.organizationId = membershipOrganizationId;
|
|
176
|
+
item.VATPercentage = 21;
|
|
177
|
+
item.VATIncluded = false;
|
|
178
|
+
item.VATExcempt = null;
|
|
179
|
+
item.quantity = amount;
|
|
180
|
+
item.unitPrice = unitPrice;
|
|
181
|
+
item.createdAt = now;
|
|
182
|
+
item.status = BalanceItemStatus.Hidden;
|
|
183
|
+
|
|
184
|
+
if (customer && customer.company && customer.company.address) {
|
|
185
|
+
// Reverse charged vat applicable?
|
|
186
|
+
if (customer.company.address.country !== Country.Belgium) {
|
|
187
|
+
item.VATExcempt = VATExcemptReason.IntraCommunity;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return item;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
private static async getForOrganizationIncludingExpired(organizationId: string) {
|
|
195
|
+
const packages = await STPackage.select()
|
|
196
|
+
.where('organizationId', organizationId)
|
|
197
|
+
.where('validAt', '!=', null)
|
|
198
|
+
.orderBy('validAt', 'DESC')
|
|
199
|
+
.fetch();
|
|
200
|
+
|
|
201
|
+
return packages;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
private static async getOrganizationPackagesMap(organizationId: string): Promise<Map<STPackageType, STPackageStatus>> {
|
|
205
|
+
const packages = await this.getForOrganizationIncludingExpired(organizationId);
|
|
206
|
+
|
|
207
|
+
const map = new Map<STPackageType, STPackageStatus>();
|
|
208
|
+
for (const pack of packages) {
|
|
209
|
+
const exist = map.get(pack.meta.type);
|
|
210
|
+
if (exist) {
|
|
211
|
+
exist.merge(pack.createStatus());
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
map.set(pack.meta.type, pack.createStatus());
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return map;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
static async updateOrganizationPackages(organizationId: string) {
|
|
222
|
+
console.log('Updating packages for organization ' + organizationId);
|
|
223
|
+
const map = await this.getOrganizationPackagesMap(organizationId);
|
|
224
|
+
|
|
225
|
+
const organization = await Organization.getByID(organizationId);
|
|
226
|
+
if (organization) {
|
|
227
|
+
const didUseMembers = organization.meta.packages.useMembers && organization.meta.packages.useActivities;
|
|
228
|
+
organization.meta.packages.packages = map;
|
|
229
|
+
await organization.save();
|
|
230
|
+
|
|
231
|
+
if (!didUseMembers && organization.meta.packages.useMembers && organization.meta.packages.useActivities) {
|
|
232
|
+
console.log('Building groups and categories for ' + organization.id);
|
|
233
|
+
const builder = new GroupBuilder(organization);
|
|
234
|
+
await builder.build();
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
console.error("Couldn't find organization when updating packages " + organizationId);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { STExpect } from '@stamhoofd/test-utils';
|
|
2
|
-
import { UitpasService } from './UitpasService';
|
|
2
|
+
import { UitpasService } from './UitpasService.js';
|
|
3
3
|
|
|
4
4
|
describe.skip('UitpasService', () => {
|
|
5
5
|
it('should validate a correct Uitpas number with kansentarief', async () => {
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { baseSQLFilterCompilers, createColumnFilter, SQL, SQLFilterDefinitions, SQLValueType } from '@stamhoofd/sql';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Defines how to filter balance items in the database from StamhoofdFilter objects
|
|
5
|
+
*/
|
|
6
|
+
export const balanceItemFilterCompilers: SQLFilterDefinitions = {
|
|
7
|
+
...baseSQLFilterCompilers,
|
|
8
|
+
id: createColumnFilter({
|
|
9
|
+
expression: SQL.column('id'),
|
|
10
|
+
type: SQLValueType.String,
|
|
11
|
+
nullable: false,
|
|
12
|
+
}),
|
|
13
|
+
organizationId: createColumnFilter({
|
|
14
|
+
expression: SQL.column('organizationId'),
|
|
15
|
+
type: SQLValueType.String,
|
|
16
|
+
nullable: false,
|
|
17
|
+
}),
|
|
18
|
+
type: createColumnFilter({
|
|
19
|
+
expression: SQL.column('type'),
|
|
20
|
+
type: SQLValueType.String,
|
|
21
|
+
nullable: false,
|
|
22
|
+
}),
|
|
23
|
+
status: createColumnFilter({
|
|
24
|
+
expression: SQL.column('status'),
|
|
25
|
+
type: SQLValueType.String,
|
|
26
|
+
nullable: false,
|
|
27
|
+
}),
|
|
28
|
+
createdAt: createColumnFilter({
|
|
29
|
+
expression: SQL.column('createdAt'),
|
|
30
|
+
type: SQLValueType.Datetime,
|
|
31
|
+
nullable: false,
|
|
32
|
+
}),
|
|
33
|
+
updatedAt: createColumnFilter({
|
|
34
|
+
expression: SQL.column('updatedAt'),
|
|
35
|
+
type: SQLValueType.Datetime,
|
|
36
|
+
nullable: false,
|
|
37
|
+
}),
|
|
38
|
+
|
|
39
|
+
description: createColumnFilter({
|
|
40
|
+
expression: SQL.column('description'),
|
|
41
|
+
type: SQLValueType.String,
|
|
42
|
+
nullable: false,
|
|
43
|
+
}),
|
|
44
|
+
|
|
45
|
+
priceWithVAT: createColumnFilter({
|
|
46
|
+
expression: SQL.column('priceTotal'),
|
|
47
|
+
type: SQLValueType.Number,
|
|
48
|
+
nullable: false,
|
|
49
|
+
}),
|
|
50
|
+
|
|
51
|
+
priceOpen: createColumnFilter({
|
|
52
|
+
expression: SQL.column('priceOpen'),
|
|
53
|
+
type: SQLValueType.Number,
|
|
54
|
+
nullable: false,
|
|
55
|
+
}),
|
|
56
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { baseSQLFilterCompilers, createColumnFilter, createExistsFilter, SQL, SQLFilterDefinitions, SQLValueType } from '@stamhoofd/sql';
|
|
2
|
-
import { emailRecipientsFilterCompilers } from './email-recipients';
|
|
2
|
+
import { emailRecipientsFilterCompilers } from './email-recipients.js';
|
|
3
3
|
|
|
4
4
|
export const userEmailFilterCompilers: SQLFilterDefinitions = {
|
|
5
5
|
...baseSQLFilterCompilers,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { baseSQLFilterCompilers, createColumnFilter, createJoinedRelationFilter, createExistsFilter, SQL, SQLFilterDefinitions, SQLValueType } from '@stamhoofd/sql';
|
|
2
|
-
import { eventFilterCompilers } from './events';
|
|
3
|
-
import { organizationFilterCompilers } from './organizations';
|
|
2
|
+
import { eventFilterCompilers } from './events.js';
|
|
3
|
+
import { organizationFilterCompilers } from './organizations.js';
|
|
4
4
|
|
|
5
5
|
export const organizationJoin = SQL.join('organizations').where(SQL.column('organizations', 'id'), SQL.column('event_notifications', 'organizationId'));
|
|
6
6
|
|
|
@@ -37,6 +37,11 @@ export const eventFilterCompilers: SQLFilterDefinitions = {
|
|
|
37
37
|
type: SQLValueType.String,
|
|
38
38
|
nullable: true,
|
|
39
39
|
}),
|
|
40
|
+
'webshopId': createColumnFilter({
|
|
41
|
+
expression: SQL.column('webshopId'),
|
|
42
|
+
type: SQLValueType.String,
|
|
43
|
+
nullable: true,
|
|
44
|
+
}),
|
|
40
45
|
'typeId': createColumnFilter({
|
|
41
46
|
expression: SQL.column('typeId'),
|
|
42
47
|
type: SQLValueType.String,
|
|
@@ -81,6 +86,52 @@ export const eventFilterCompilers: SQLFilterDefinitions = {
|
|
|
81
86
|
type: SQLValueType.String,
|
|
82
87
|
nullable: false,
|
|
83
88
|
}),
|
|
89
|
+
status: createColumnFilter({
|
|
90
|
+
expression: SQL.column('status'),
|
|
91
|
+
type: SQLValueType.String,
|
|
92
|
+
nullable: false,
|
|
93
|
+
}),
|
|
94
|
+
registrationStartDate: createColumnFilter({
|
|
95
|
+
expression: SQL.jsonExtract(SQL.column('settings'), '$.value.registrationStartDate'),
|
|
96
|
+
type: SQLValueType.JSONNumber,
|
|
97
|
+
nullable: true,
|
|
98
|
+
}),
|
|
99
|
+
registrationEndDate: createColumnFilter({
|
|
100
|
+
expression: SQL.jsonExtract(SQL.column('settings'), '$.value.registrationEndDate'),
|
|
101
|
+
type: SQLValueType.JSONNumber,
|
|
102
|
+
nullable: true,
|
|
103
|
+
}),
|
|
104
|
+
preRegistrationsDate: createColumnFilter({
|
|
105
|
+
expression: SQL.jsonExtract(SQL.column('settings'), '$.value.preRegistrationsDate'),
|
|
106
|
+
type: SQLValueType.JSONNumber,
|
|
107
|
+
nullable: true,
|
|
108
|
+
}),
|
|
109
|
+
},
|
|
110
|
+
),
|
|
111
|
+
'webshop': createExistsFilter(
|
|
112
|
+
SQL.select()
|
|
113
|
+
.from(SQL.table('webshops'))
|
|
114
|
+
.where(
|
|
115
|
+
SQL.column('id'),
|
|
116
|
+
SQL.column('events', 'webshopId'),
|
|
117
|
+
),
|
|
118
|
+
{
|
|
119
|
+
...baseSQLFilterCompilers,
|
|
120
|
+
status: createColumnFilter({
|
|
121
|
+
expression: SQL.jsonExtract(SQL.column('meta'), '$.value.status'),
|
|
122
|
+
type: SQLValueType.JSONString,
|
|
123
|
+
nullable: false,
|
|
124
|
+
}),
|
|
125
|
+
availableUntil: createColumnFilter({
|
|
126
|
+
expression: SQL.jsonExtract(SQL.column('meta'), '$.value.availableUntil'),
|
|
127
|
+
type: SQLValueType.JSONNumber,
|
|
128
|
+
nullable: true,
|
|
129
|
+
}),
|
|
130
|
+
openAt: createColumnFilter({
|
|
131
|
+
expression: SQL.jsonExtract(SQL.column('meta'), '$.value.openAt'),
|
|
132
|
+
type: SQLValueType.JSONNumber,
|
|
133
|
+
nullable: true,
|
|
134
|
+
}),
|
|
84
135
|
},
|
|
85
136
|
),
|
|
86
137
|
};
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { SimpleError } from '@simonbackx/simple-errors';
|
|
2
|
-
import { Email, Member } from '@stamhoofd/models';
|
|
2
|
+
import { Email, Member, MemberUser } from '@stamhoofd/models';
|
|
3
3
|
import { baseSQLFilterCompilers, createColumnFilter, createExistsFilter, createWildcardColumnFilter, SQL, SQLAge, SQLCast, SQLConcat, SQLFilterDefinitions, SQLJsonExtract, SQLScalar, SQLValueType } from '@stamhoofd/sql';
|
|
4
4
|
import { AccessRight } from '@stamhoofd/structures';
|
|
5
5
|
import { Context } from '../helpers/Context.js';
|
|
6
6
|
import { baseRegistrationFilterCompilers } from './base-registration-filter-compilers.js';
|
|
7
7
|
import { organizationFilterCompilers } from './organizations.js';
|
|
8
|
+
import { userFilterCompilers } from './users.js';
|
|
8
9
|
|
|
9
10
|
const membersTable = SQL.table(Member.table);
|
|
10
11
|
|
|
@@ -84,6 +85,11 @@ export const memberFilterCompilers: SQLFilterDefinitions = {
|
|
|
84
85
|
await throwIfNoFinancialReadAccess();
|
|
85
86
|
},
|
|
86
87
|
}),
|
|
88
|
+
'details.dataPermissions': createColumnFilter({
|
|
89
|
+
expression: SQL.jsonExtract(SQL.column(membersTable, 'details'), '$.value.dataPermissions.value'),
|
|
90
|
+
type: SQLValueType.JSONBoolean,
|
|
91
|
+
nullable: true,
|
|
92
|
+
}),
|
|
87
93
|
'email': createColumnFilter({
|
|
88
94
|
expression: SQL.jsonExtract(SQL.column(membersTable, 'details'), '$.value.email'),
|
|
89
95
|
type: SQLValueType.JSONString,
|
|
@@ -94,6 +100,16 @@ export const memberFilterCompilers: SQLFilterDefinitions = {
|
|
|
94
100
|
type: SQLValueType.JSONArray,
|
|
95
101
|
nullable: true,
|
|
96
102
|
}),
|
|
103
|
+
'details.emergencyContacts.length': createColumnFilter({
|
|
104
|
+
expression: SQL.jsonLength(SQL.column(membersTable, 'details'), '$.value.emergencyContacts'),
|
|
105
|
+
type: SQLValueType.Number,
|
|
106
|
+
nullable: false,
|
|
107
|
+
}),
|
|
108
|
+
'details.parents.length': createColumnFilter({
|
|
109
|
+
expression: SQL.jsonLength(SQL.column(membersTable, 'details'), '$.value.parents'),
|
|
110
|
+
type: SQLValueType.Number,
|
|
111
|
+
nullable: false,
|
|
112
|
+
}),
|
|
97
113
|
'details.parents[0]': {
|
|
98
114
|
...baseSQLFilterCompilers,
|
|
99
115
|
name: createColumnFilter({
|
|
@@ -154,6 +170,12 @@ export const memberFilterCompilers: SQLFilterDefinitions = {
|
|
|
154
170
|
type: SQLValueType.JSONString,
|
|
155
171
|
nullable: true,
|
|
156
172
|
}),
|
|
173
|
+
// for checking if the address is null
|
|
174
|
+
value: createColumnFilter({
|
|
175
|
+
expression: SQL.jsonExtract(SQL.column(membersTable, 'details'), '$.value.address'),
|
|
176
|
+
type: SQLValueType.JSONObject,
|
|
177
|
+
nullable: true,
|
|
178
|
+
}),
|
|
157
179
|
},
|
|
158
180
|
'details.parents[*].address': {
|
|
159
181
|
...baseSQLFilterCompilers,
|
|
@@ -217,7 +239,7 @@ export const memberFilterCompilers: SQLFilterDefinitions = {
|
|
|
217
239
|
...baseRegistrationFilterCompilers,
|
|
218
240
|
// Override the registration periodId - can be outdated - and always use the group periodId
|
|
219
241
|
periodId: createColumnFilter({
|
|
220
|
-
expression: SQL.column('
|
|
242
|
+
expression: SQL.column('registrations', 'periodId'),
|
|
221
243
|
type: SQLValueType.String,
|
|
222
244
|
nullable: false,
|
|
223
245
|
}),
|
|
@@ -497,6 +519,20 @@ export const memberFilterCompilers: SQLFilterDefinitions = {
|
|
|
497
519
|
},
|
|
498
520
|
),
|
|
499
521
|
},
|
|
522
|
+
'users': createExistsFilter(
|
|
523
|
+
SQL.select()
|
|
524
|
+
.from(
|
|
525
|
+
SQL.table('users'),
|
|
526
|
+
).join(
|
|
527
|
+
SQL.innerJoin(MemberUser.table)
|
|
528
|
+
.where(
|
|
529
|
+
SQL.parentColumn('id'),
|
|
530
|
+
SQL.column('usersId'),
|
|
531
|
+
),
|
|
532
|
+
)
|
|
533
|
+
.where(SQL.column(MemberUser.table, 'membersId'), SQL.column('members', 'id')),
|
|
534
|
+
userFilterCompilers,
|
|
535
|
+
),
|
|
500
536
|
};
|
|
501
537
|
|
|
502
538
|
async function throwIfNoFinancialReadAccess() {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { baseSQLFilterCompilers, createColumnFilter, createExistsFilter, SQL, SQLConcat, SQLFilterDefinitions, SQLValueType, SQLScalar } from '@stamhoofd/sql';
|
|
2
|
-
import { memberFilterCompilers } from './members';
|
|
3
|
-
import { organizationFilterCompilers } from './organizations';
|
|
4
|
-
import { EmailRelationFilterCompilers } from './shared/EmailRelationFilterCompilers';
|
|
2
|
+
import { memberFilterCompilers } from './members.js';
|
|
3
|
+
import { organizationFilterCompilers } from './organizations.js';
|
|
4
|
+
import { EmailRelationFilterCompilers } from './shared/EmailRelationFilterCompilers.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Defines how to filter cached balance items in the database from StamhoofdFilter objects
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { baseSQLFilterCompilers, createColumnFilter, SQL, SQLFilterDefinitions, SQLValueType } from '@stamhoofd/sql';
|
|
2
|
+
|
|
3
|
+
export const userFilterCompilers: SQLFilterDefinitions = {
|
|
4
|
+
...baseSQLFilterCompilers,
|
|
5
|
+
verified: createColumnFilter({
|
|
6
|
+
expression: SQL.column('verified'),
|
|
7
|
+
type: SQLValueType.Boolean,
|
|
8
|
+
nullable: false,
|
|
9
|
+
}),
|
|
10
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { BalanceItem } from '@stamhoofd/models';
|
|
2
|
+
import { SQL, SQLOrderBy, SQLOrderByDirection, SQLSortDefinitions } from '@stamhoofd/sql';
|
|
3
|
+
import { Formatter } from '@stamhoofd/utility';
|
|
4
|
+
|
|
5
|
+
export const balanceItemSorters: SQLSortDefinitions<BalanceItem> = {
|
|
6
|
+
// WARNING! TEST NEW SORTERS THOROUGHLY!
|
|
7
|
+
// Try to avoid creating sorters on fields that er not 1:1 with the database, that often causes pagination issues if not thought through
|
|
8
|
+
// An example: sorting on 'name' is not a good idea, because it is a concatenation of two fields.
|
|
9
|
+
// You might be tempted to use ORDER BY firstName, lastName, but that will not work as expected and it needs to be ORDER BY CONCAT(firstName, ' ', lastName)
|
|
10
|
+
// Why? Because ORDER BY firstName, lastName produces a different order dan ORDER BY CONCAT(firstName, ' ', lastName) if there are multiple people with spaces in the first name
|
|
11
|
+
// And that again causes issues with pagination because the next query will append a filter of name > 'John Doe' - causing duplicate and/or skipped results
|
|
12
|
+
// What if you need mapping? simply map the sorters in the frontend: name -> firstname, lastname, age -> birthDay, etc.
|
|
13
|
+
|
|
14
|
+
id: {
|
|
15
|
+
getValue(a) {
|
|
16
|
+
return a.id;
|
|
17
|
+
},
|
|
18
|
+
toSQL: (direction: SQLOrderByDirection): SQLOrderBy => {
|
|
19
|
+
return new SQLOrderBy({
|
|
20
|
+
column: SQL.column('id'),
|
|
21
|
+
direction,
|
|
22
|
+
});
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
createdAt: {
|
|
26
|
+
getValue(a) {
|
|
27
|
+
return Formatter.dateTimeIso(a.createdAt, 'UTC');
|
|
28
|
+
},
|
|
29
|
+
toSQL: (direction: SQLOrderByDirection): SQLOrderBy => {
|
|
30
|
+
return new SQLOrderBy({
|
|
31
|
+
column: SQL.column('createdAt'),
|
|
32
|
+
direction,
|
|
33
|
+
});
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
};
|
|
@@ -45,7 +45,7 @@ export const documentTemplateSorters: SQLSortDefinitions<DocumentTemplate> = {
|
|
|
45
45
|
},
|
|
46
46
|
updatedAt: {
|
|
47
47
|
getValue(a) {
|
|
48
|
-
return Formatter.dateTimeIso(a.updatedAt);
|
|
48
|
+
return Formatter.dateTimeIso(a.updatedAt, 'UTC');
|
|
49
49
|
},
|
|
50
50
|
toSQL: (direction: SQLOrderByDirection): SQLOrderBy => {
|
|
51
51
|
return new SQLOrderBy({
|
|
@@ -56,7 +56,7 @@ export const documentTemplateSorters: SQLSortDefinitions<DocumentTemplate> = {
|
|
|
56
56
|
},
|
|
57
57
|
createdAt: {
|
|
58
58
|
getValue(a) {
|
|
59
|
-
return Formatter.dateTimeIso(a.createdAt);
|
|
59
|
+
return Formatter.dateTimeIso(a.createdAt, 'UTC');
|
|
60
60
|
},
|
|
61
61
|
toSQL: (direction: SQLOrderByDirection): SQLOrderBy => {
|
|
62
62
|
return new SQLOrderBy({
|
|
@@ -34,7 +34,7 @@ export const documentSorters: SQLSortDefinitions<Document> = {
|
|
|
34
34
|
},
|
|
35
35
|
createdAt: {
|
|
36
36
|
getValue(a) {
|
|
37
|
-
return Formatter.dateTimeIso(a.createdAt);
|
|
37
|
+
return Formatter.dateTimeIso(a.createdAt, 'UTC');
|
|
38
38
|
},
|
|
39
39
|
toSQL: (direction: SQLOrderByDirection): SQLOrderBy => {
|
|
40
40
|
return new SQLOrderBy({
|
|
@@ -45,7 +45,7 @@ export const documentSorters: SQLSortDefinitions<Document> = {
|
|
|
45
45
|
},
|
|
46
46
|
updatedAt: {
|
|
47
47
|
getValue(a) {
|
|
48
|
-
return Formatter.dateTimeIso(a.updatedAt);
|
|
48
|
+
return Formatter.dateTimeIso(a.updatedAt, 'UTC');
|
|
49
49
|
},
|
|
50
50
|
toSQL: (direction: SQLOrderByDirection): SQLOrderBy => {
|
|
51
51
|
return new SQLOrderBy({
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { SQLResultNamespacedRow } from '@simonbackx/simple-database';
|
|
2
2
|
import { SQL, SQLOrderBy, SQLOrderByDirection, SQLSortDefinitions } from '@stamhoofd/sql';
|
|
3
3
|
import { Formatter } from '@stamhoofd/utility';
|
|
4
|
-
import { organizationJoin } from '../sql-filters/event-notifications';
|
|
4
|
+
import { organizationJoin } from '../sql-filters/event-notifications.js';
|
|
5
5
|
|
|
6
6
|
export const eventNotificationsSorters: SQLSortDefinitions<SQLResultNamespacedRow> = {
|
|
7
7
|
// WARNING! TEST NEW SORTERS THOROUGHLY!
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { MemberWithUsersRegistrationsAndGroups } from '@stamhoofd/models';
|
|
2
2
|
import { SQL, SQLOrderBy, SQLOrderByDirection, SQLSortDefinitions } from '@stamhoofd/sql';
|
|
3
3
|
import { Formatter } from '@stamhoofd/utility';
|
|
4
4
|
|
|
5
|
-
export const memberSorters: SQLSortDefinitions<
|
|
5
|
+
export const memberSorters: SQLSortDefinitions<MemberWithUsersRegistrationsAndGroups> = {
|
|
6
6
|
// WARNING! TEST NEW SORTERS THOROUGHLY!
|
|
7
7
|
// Try to avoid creating sorters on fields that er not 1:1 with the database, that often causes pagination issues if not thought through
|
|
8
8
|
// An example: sorting on 'name' is not a good idea, because it is a concatenation of two fields.
|
|
@@ -12,7 +12,7 @@ export const orderSorters: SQLSortDefinitions<Order> = {
|
|
|
12
12
|
// What if you need mapping? simply map the sorters in the frontend: name -> firstname, lastname, age -> birthDay, etc.
|
|
13
13
|
createdAt: {
|
|
14
14
|
getValue(a) {
|
|
15
|
-
return Formatter.dateTimeIso(a.createdAt);
|
|
15
|
+
return Formatter.dateTimeIso(a.createdAt, 'UTC');
|
|
16
16
|
},
|
|
17
17
|
toSQL: (direction: SQLOrderByDirection): SQLOrderBy => {
|
|
18
18
|
return new SQLOrderBy({
|
|
@@ -23,7 +23,7 @@ export const orderSorters: SQLSortDefinitions<Order> = {
|
|
|
23
23
|
},
|
|
24
24
|
updatedAt: {
|
|
25
25
|
getValue(a) {
|
|
26
|
-
return Formatter.dateTimeIso(a.updatedAt);
|
|
26
|
+
return Formatter.dateTimeIso(a.updatedAt, 'UTC');
|
|
27
27
|
},
|
|
28
28
|
toSQL: (direction: SQLOrderByDirection): SQLOrderBy => {
|
|
29
29
|
return new SQLOrderBy({
|