@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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Migration } from '@simonbackx/simple-database';
|
|
2
2
|
import { logger } from '@simonbackx/simple-logging';
|
|
3
3
|
import { BalanceItem } from '@stamhoofd/models';
|
|
4
|
-
import { BalanceItemService } from '../services/BalanceItemService';
|
|
4
|
+
import { BalanceItemService } from '../services/BalanceItemService.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* This migration is required to keep '1733994455-balance-item-status-open' working
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Migration } from '@simonbackx/simple-database';
|
|
2
|
-
import { PlatformMembershipService } from '../services/PlatformMembershipService';
|
|
2
|
+
import { PlatformMembershipService } from '../services/PlatformMembershipService.js';
|
|
3
3
|
|
|
4
4
|
export default new Migration(async () => {
|
|
5
5
|
if (STAMHOOFD.environment == 'test') {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Group, GroupFactory, Organization, OrganizationFactory, OrganizationRegistrationPeriod, OrganizationRegistrationPeriodFactory, RegistrationPeriod, RegistrationPeriodFactory } from '@stamhoofd/models';
|
|
2
2
|
import { GroupCategory, GroupCategorySettings, GroupPriceDiscountType, GroupStatus, OldGroupPrice, OldGroupPrices, TranslatedString } from '@stamhoofd/structures';
|
|
3
|
-
import { migratePrices } from './1754560914-groups-prices';
|
|
3
|
+
import { migratePrices } from './1754560914-groups-prices.js';
|
|
4
4
|
|
|
5
5
|
describe('migration.migratePrices', () => {
|
|
6
6
|
/**
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Migration, SQLResultNamespacedRow } from '@simonbackx/simple-database';
|
|
2
2
|
import { Member, mergeTwoMembers } from '@stamhoofd/models';
|
|
3
3
|
import { SQL, SQLSelect } from '@stamhoofd/sql';
|
|
4
|
-
import { PatchOrganizationMembersEndpoint } from '../endpoints/global/members/PatchOrganizationMembersEndpoint';
|
|
4
|
+
import { PatchOrganizationMembersEndpoint } from '../endpoints/global/members/PatchOrganizationMembersEndpoint.js';
|
|
5
5
|
|
|
6
6
|
type MergeType = {
|
|
7
7
|
a: {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Migration } from '@simonbackx/simple-database';
|
|
2
2
|
import { logger } from '@simonbackx/simple-logging';
|
|
3
3
|
import { BalanceItem } from '@stamhoofd/models';
|
|
4
|
-
import { BalanceItemService } from '../services/BalanceItemService';
|
|
4
|
+
import { BalanceItemService } from '../services/BalanceItemService.js';
|
|
5
5
|
|
|
6
6
|
export default new Migration(async () => {
|
|
7
7
|
if (STAMHOOFD.environment == 'test') {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Migration } from '@simonbackx/simple-database';
|
|
2
2
|
import { Member } from '@stamhoofd/models';
|
|
3
|
-
import { MemberUserSyncer } from '../helpers/MemberUserSyncer';
|
|
3
|
+
import { MemberUserSyncer } from '../helpers/MemberUserSyncer.js';
|
|
4
4
|
import { logger } from '@simonbackx/simple-logging';
|
|
5
5
|
|
|
6
6
|
export default new Migration(async () => {
|
|
@@ -54,4 +54,4 @@ INSERT INTO `email_templates` (`id`, `subject`, `groupId`, `webshopId`, `organiz
|
|
|
54
54
|
('f3d1c594-7510-4f12-9899-ef6e0d3a64c0', 'Kampmelding voor {{eventName}} ({{dateRange}}) werd goedgekeurd', NULL, NULL, NULL, 'EventNotificationAccepted', '{{greeting}}Goed nieuws! Jullie kampmelding voor {{eventName}} ({{dateRange}}) van {{organizationName}} werd goedgekeurd. Deze werd ingediend door {{submitterName}}.\n\n \n \n \n \n Kampmelding bekijken ({{reviewUrl}})\n \n \n \n \n\n', '<!DOCTYPE html>\n<html>\n\n<head>\n<meta charset=\"utf-8\" />\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0\" />\n<title>Kampmelding voor {{eventName}} ({{dateRange}}) werd goedgekeurd</title>\n<style type=\"text/css\">body {\n color: #000716;\n color: var(--color-dark, #000716);\n font-family: -apple-system-body, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";\n font-size: 12pt;\n line-height: 1.4;\n}\n\np {\n margin: 0;\n padding: 0;\n line-height: 1.4;\n}\n\np.description {\n color: var(--color-gray-4, #5e5e5e);\n}\np.description a, p.description a:link, p.description a:visited, p.description a:active, p.description a:hover {\n text-decoration: underline;\n color: var(--color-gray-4, #5e5e5e);\n}\n\nstrong {\n font-weight: bold;\n}\n\nem {\n font-style: italic;\n}\n\nh1 {\n font-size: 30px;\n font-weight: bold;\n line-height: 1.2;\n margin: 0;\n padding: 0;\n}\n@media (max-width: 350px) {\n h1 {\n font-size: 24px;\n }\n}\n\nh2 {\n font-size: 20px;\n line-height: 1.2;\n font-weight: bold;\n margin: 0;\n padding: 0;\n}\n\nh3 {\n font-size: 16px;\n line-height: 1.2;\n font-weight: bold;\n margin: 0;\n padding: 0;\n}\n\nh4 {\n line-height: 1.2;\n font-weight: 500;\n margin: 0;\n padding: 0;\n}\n\nol, ul {\n list-style-position: outside;\n padding-left: 30px;\n}\n\nhr {\n height: 1px;\n background: var(--color-border, var(--color-gray-2, #dcdcdc));\n border-radius: 1px;\n padding: 0;\n margin: 20px 0;\n outline: none;\n border: 0;\n}\n\n.button {\n touch-action: inherit;\n user-select: auto;\n cursor: pointer;\n display: inline-block !important;\n line-height: 42px;\n font-size: 16px;\n font-weight: bold;\n}\n.button:active {\n transform: none;\n}\n\nimg {\n max-width: 100%;\n height: auto;\n}\n\na, a:link, a:visited, a:active, a:hover {\n text-decoration: underline;\n color: blue;\n}\n\n.email-data-table {\n width: 100%;\n border-collapse: collapse;\n}\n.email-data-table th, .email-data-table td {\n text-align: left;\n padding: 10px 10px 10px 0;\n border-bottom: 1px solid var(--color-border, var(--color-gray-2, #dcdcdc));\n vertical-align: middle;\n}\n.email-data-table th:last-child, .email-data-table td:last-child {\n text-align: right;\n padding-right: 0;\n}\n.email-data-table thead {\n font-weight: bold;\n}\n.email-data-table thead th {\n font-size: 10pt;\n}\n.email-data-table h4 ~ p {\n padding-top: 3px;\n opacity: 0.8;\n font-size: 11pt;\n}\n\n.email-style-inline-code {\n font-family: monospace;\n white-space: pre-wrap;\n display: inline-block;\n}\n\n.email-style-description-small {\n font-size: 14px;\n line-height: 1.5;\n font-weight: normal;\n color: var(--color-gray-4, #5e5e5e);\n font-variation-settings: \"opsz\" 19;\n}\n\n.email-style-title-list {\n font-size: 16px;\n line-height: 1.3;\n font-weight: 500;\n}\n.email-style-title-list + p {\n padding-top: 3px;\n}\n\n.email-style-title-prefix-list {\n font-size: 11px;\n line-height: 1.5;\n font-weight: bold;\n color: {{primaryColor}};\n text-transform: uppercase;\n margin-bottom: 3px;\n}\n.email-style-title-prefix-list.error {\n color: #f0153d;\n}\n\n.email-style-price-base, .email-style-discount-price, .email-style-discount-old-price, .email-style-price {\n font-size: 15px;\n line-height: 1.4;\n font-weight: 500;\n font-variant-numeric: tabular-nums;\n}\n.email-style-price-base.disabled, .disabled.email-style-discount-price, .disabled.email-style-discount-old-price, .disabled.email-style-price {\n opacity: 0.6;\n}\n.email-style-price-base.negative, .negative.email-style-discount-price, .negative.email-style-discount-old-price, .negative.email-style-price {\n color: #f0153d;\n}\n\n.email-style-price {\n font-weight: bold;\n color: {{primaryColor}};\n}\n\n.email-style-discount-old-price {\n text-decoration: line-through;\n color: var(--color-gray-4, #5e5e5e);\n}\n\n.email-style-discount-price {\n font-weight: bold;\n color: #ff4747;\n margin-left: 5px;\n}\n\n.pre-wrap {\n white-space: pre-wrap;\n} hr {height: 2px;background: #e7e7e7; border-radius: 1px; padding: 0; margin: 20px 0; outline: none; border: 0;} .button.primary { margin: 0; text-decoration: none; font-size: 16px; font-weight: bold; color: {{primaryColorContrast}}; padding: 0 27px; line-height: 42px; background: {{primaryColor}}; text-align: center; border-radius: 7px; touch-action: manipulation; display: inline-block; transition: 0.2s transform, 0.2s opacity; } .button.primary:active { transform: scale(0.95, 0.95); } .inline-link, .inline-link:link, .inline-link:visited, .inline-link:active, .inline-link:hover { margin: 0; text-decoration: underline; font-size: inherit; font-weight: inherit; color: inherit; touch-action: manipulation; } .inline-link:active { opacity: 0.5; } .description { color: #5e5e5e; } </style>\n</head>\n\n<body>\n<p style=\"margin: 0; padding: 0; line-height: 1.4;\">{{greeting}}</p><p style=\"margin: 0; padding: 0; line-height: 1.4;\"><br></p><p style=\"margin: 0; padding: 0; line-height: 1.4;\">Goed nieuws! Jullie kampmelding voor <strong>{{eventName}}</strong> ({{dateRange}}) van <strong>{{organizationName}}</strong> werd goedgekeurd. Deze werd ingediend door {{submitterName}}.</p><p style=\"margin: 0; padding: 0; line-height: 1.4;\"><br></p><div data-type=\"smartButton\" data-id=\"reviewUrl\"><table width=\"100%\" cellspacing=\"0\" cellpadding=\"0\" style=\"margin: 5px 0;\">\n<tbody><tr>\n <td>\n <table cellspacing=\"0\" cellpadding=\"0\">\n <tbody><tr>\n <td style=\"border-radius: 7px;\" bgcolor=\"{{primaryColor}}\">\n <a class=\"button primary\" href=\"{{reviewUrl}}\" target=\"\" style=\"margin: 0; text-decoration: none; font-size: 16px; font-weight: bold; color: {{primaryColorContrast}}; padding: 0 27px; line-height: 42px; background: {{primaryColor}}; text-align: center; border-radius: 7px; touch-action: manipulation; display: inline-block; transition: 0.2s transform, 0.2s opacity;\">Kampmelding bekijken</a>\n </td>\n </tr>\n </tbody></table>\n </td>\n</tr>\n</tbody></table></div><p style=\"margin: 0; padding: 0; line-height: 1.4;\"><br></p>\n</body>\n\n</html>', '{\"value\": {\"type\": \"doc\", \"content\": [{\"type\": \"paragraph\", \"content\": [{\"type\": \"smartVariable\", \"attrs\": {\"id\": \"greeting\"}}]}, {\"type\": \"paragraph\"}, {\"type\": \"paragraph\", \"content\": [{\"text\": \"Goed nieuws! Jullie kampmelding voor \", \"type\": \"text\"}, {\"type\": \"smartVariable\", \"attrs\": {\"id\": \"eventName\"}, \"marks\": [{\"type\": \"bold\"}]}, {\"text\": \" (\", \"type\": \"text\"}, {\"type\": \"smartVariable\", \"attrs\": {\"id\": \"dateRange\"}}, {\"text\": \") van \", \"type\": \"text\"}, {\"type\": \"smartVariable\", \"attrs\": {\"id\": \"organizationName\"}, \"marks\": [{\"type\": \"bold\"}]}, {\"text\": \" werd goedgekeurd. Deze werd ingediend door \", \"type\": \"text\"}, {\"type\": \"smartVariable\", \"attrs\": {\"id\": \"submitterName\"}}, {\"text\": \".\", \"type\": \"text\"}]}, {\"type\": \"paragraph\"}, {\"type\": \"smartButton\", \"attrs\": {\"id\": \"reviewUrl\"}, \"content\": [{\"text\": \"Kampmelding bekijken\", \"type\": \"text\"}]}, {\"type\": \"paragraph\"}]}, \"version\": 377}', '2025-07-15 09:35:18', '2025-07-15 09:35:18'),
|
|
55
55
|
('f5bf2c0a-0ac2-4d1d-a2d2-5c1c0139d399', 'Wachtwoord van {{organizationName}} vergeten', NULL, NULL, NULL, 'ForgotPasswordButNoAccount', '{{greeting}}Je gaf aan dat je jouw wachtwoord bent vergeten van {{organizationName}}, maar er bestaat geen account op het e-mailadres dat je hebt ingegeven ({{email}}). Niet zeker meer welk e-mailadres je kan gebruiken? Wij sturen altijd e-mails naar een e-mailadres waarmee je een account hebt. Lukt dat niet? Dan kan je via ons ledenportaal een nieuw account aanmaken met een e-mailadres naar keuze.{{organizationName}}', '<!DOCTYPE html>\n<html>\n\n<head>\n<meta charset=\"utf-8\" />\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0\" />\n<title>Wachtwoord van {{organizationName}} vergeten</title>\n<style type=\"text/css\">body {\n color: #000716;\n color: var(--color-dark, #000716);\n font-family: -apple-system-body, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";\n font-size: 12pt;\n line-height: 1.4;\n}\n\np {\n margin: 0;\n padding: 0;\n line-height: 1.4;\n}\n\np.description {\n color: var(--color-gray-4, #5e5e5e);\n}\np.description a, p.description a:link, p.description a:visited, p.description a:active, p.description a:hover {\n text-decoration: underline;\n color: var(--color-gray-4, #5e5e5e);\n}\n\nstrong {\n font-weight: bold;\n}\n\nem {\n font-style: italic;\n}\n\nh1 {\n font-size: 30px;\n font-weight: bold;\n line-height: 1.2;\n margin: 0;\n padding: 0;\n}\n@media (max-width: 350px) {\n h1 {\n font-size: 24px;\n }\n}\n\nh2 {\n font-size: 20px;\n line-height: 1.2;\n font-weight: bold;\n margin: 0;\n padding: 0;\n}\n\nh3 {\n font-size: 16px;\n line-height: 1.2;\n font-weight: bold;\n margin: 0;\n padding: 0;\n}\n\nh4 {\n line-height: 1.2;\n font-weight: 500;\n margin: 0;\n padding: 0;\n}\n\nol, ul {\n list-style-position: outside;\n padding-left: 30px;\n}\n\nhr {\n height: 1px;\n background: var(--color-border, var(--color-gray-2, #dcdcdc));\n border-radius: 1px;\n padding: 0;\n margin: 20px 0;\n outline: none;\n border: 0;\n}\n\n.button {\n touch-action: inherit;\n user-select: auto;\n cursor: pointer;\n display: inline-block !important;\n line-height: 42px;\n font-size: 16px;\n font-weight: bold;\n}\n.button:active {\n transform: none;\n}\n\nimg {\n max-width: 100%;\n height: auto;\n}\n\na, a:link, a:visited, a:active, a:hover {\n text-decoration: underline;\n color: blue;\n}\n\n.email-data-table {\n width: 100%;\n border-collapse: collapse;\n}\n.email-data-table th, .email-data-table td {\n text-align: left;\n padding: 10px 10px 10px 0;\n border-bottom: 1px solid var(--color-border, var(--color-gray-2, #dcdcdc));\n vertical-align: middle;\n}\n.email-data-table th:last-child, .email-data-table td:last-child {\n text-align: right;\n padding-right: 0;\n}\n.email-data-table thead {\n font-weight: bold;\n}\n.email-data-table thead th {\n font-size: 10pt;\n}\n.email-data-table h4 ~ p {\n padding-top: 3px;\n opacity: 0.8;\n font-size: 11pt;\n}\n\n.email-style-inline-code {\n font-family: monospace;\n white-space: pre-wrap;\n display: inline-block;\n}\n\n.email-style-description-small {\n font-size: 14px;\n line-height: 1.5;\n font-weight: normal;\n color: var(--color-gray-4, #5e5e5e);\n font-variation-settings: \"opsz\" 19;\n}\n\n.email-style-title-list {\n font-size: 16px;\n line-height: 1.3;\n font-weight: 500;\n}\n.email-style-title-list + p {\n padding-top: 3px;\n}\n\n.email-style-title-prefix-list {\n font-size: 11px;\n line-height: 1.5;\n font-weight: bold;\n color: {{primaryColor}};\n text-transform: uppercase;\n margin-bottom: 3px;\n}\n.email-style-title-prefix-list.error {\n color: #f0153d;\n}\n\n.email-style-price-base, .email-style-discount-price, .email-style-discount-old-price, .email-style-price {\n font-size: 15px;\n line-height: 1.4;\n font-weight: 500;\n font-variant-numeric: tabular-nums;\n}\n.email-style-price-base.disabled, .disabled.email-style-discount-price, .disabled.email-style-discount-old-price, .disabled.email-style-price {\n opacity: 0.6;\n}\n.email-style-price-base.negative, .negative.email-style-discount-price, .negative.email-style-discount-old-price, .negative.email-style-price {\n color: #f0153d;\n}\n\n.email-style-price {\n font-weight: bold;\n color: {{primaryColor}};\n}\n\n.email-style-discount-old-price {\n text-decoration: line-through;\n color: var(--color-gray-4, #5e5e5e);\n}\n\n.email-style-discount-price {\n font-weight: bold;\n color: #ff4747;\n margin-left: 5px;\n}\n\n.pre-wrap {\n white-space: pre-wrap;\n} hr {height: 2px;background: #e7e7e7; border-radius: 1px; padding: 0; margin: 20px 0; outline: none; border: 0;} .button.primary { margin: 0; text-decoration: none; font-size: 16px; font-weight: bold; color: {{primaryColorContrast}}; padding: 0 27px; line-height: 42px; background: {{primaryColor}}; text-align: center; border-radius: 7px; touch-action: manipulation; display: inline-block; transition: 0.2s transform, 0.2s opacity; } .button.primary:active { transform: scale(0.95, 0.95); } .inline-link, .inline-link:link, .inline-link:visited, .inline-link:active, .inline-link:hover { margin: 0; text-decoration: underline; font-size: inherit; font-weight: inherit; color: inherit; touch-action: manipulation; } .inline-link:active { opacity: 0.5; } .description { color: #5e5e5e; } </style>\n</head>\n\n<body>\n<p style=\"margin: 0; padding: 0; line-height: 1.4;\">{{greeting}}</p><p style=\"margin: 0; padding: 0; line-height: 1.4;\"><br></p><p style=\"margin: 0; padding: 0; line-height: 1.4;\">Je gaf aan dat je jouw wachtwoord bent vergeten van {{organizationName}}, maar er bestaat geen account op het e-mailadres dat je hebt ingegeven ({{email}}). Niet zeker meer welk e-mailadres je kan gebruiken? Wij sturen altijd e-mails naar een e-mailadres waarmee je een account hebt. Lukt dat niet? Dan kan je via ons ledenportaal een nieuw account aanmaken met een e-mailadres naar keuze.</p><p style=\"margin: 0; padding: 0; line-height: 1.4;\"><br></p><p style=\"margin: 0; padding: 0; line-height: 1.4;\">{{organizationName}}</p>\n</body>\n\n</html>', '{\"value\": {\"type\": \"doc\", \"content\": [{\"type\": \"paragraph\", \"content\": [{\"type\": \"smartVariable\", \"attrs\": {\"id\": \"greeting\"}}]}, {\"type\": \"paragraph\"}, {\"type\": \"paragraph\", \"content\": [{\"text\": \"Je gaf aan dat je jouw wachtwoord bent vergeten van \", \"type\": \"text\"}, {\"type\": \"smartVariable\", \"attrs\": {\"id\": \"organizationName\"}}, {\"text\": \", maar er bestaat geen account op het e-mailadres dat je hebt ingegeven (\", \"type\": \"text\"}, {\"type\": \"smartVariable\", \"attrs\": {\"id\": \"email\"}}, {\"text\": \"). Niet zeker meer welk e-mailadres je kan gebruiken? Wij sturen altijd e-mails naar een e-mailadres waarmee je een account hebt. Lukt dat niet? Dan kan je via ons ledenportaal een nieuw account aanmaken met een e-mailadres naar keuze.\", \"type\": \"text\"}]}, {\"type\": \"paragraph\"}, {\"type\": \"paragraph\", \"content\": [{\"type\": \"smartVariable\", \"attrs\": {\"id\": \"organizationName\"}}]}]}, \"version\": 377}', '2025-07-15 09:18:37', '2025-07-15 09:18:37'),
|
|
56
56
|
('fdf5ff55-5dd3-45e5-82d3-b5b4f511582d', 'DNS-records van {{mailDomain}} zijn onstabiel', NULL, NULL, NULL, 'OrganizationUnstableDNS', '{{greeting}}Dit is een technische e-mail bestemd voor jullie webmaster.Stamhoofd controleert elke dag automatisch of jullie domeinnaam {{mailDomain}}, die gekoppeld is aan {{organizationName}} op Stamhoofd nog correct is ingesteld. Dit is nodig voor het versturen van e-mails via jullie e-mailadressen, maar ook eventueel voor jullie ledenportaal als jullie de ledenadministratie gebruiken.Nu blijkt al even dat we merken dat op het ene moment jullie domeinnaam correct is ingesteld, en de volgende dag niet meer, en zo gaat dat maar door. Om te verhinderen dat je elke keer een e-mail van ons krijgt daarover, hebben we jullie e-mailadres als onstabiel gemarkeerd.Controleer of de nameservers van jullie domeinnaam wel correct zijn ingesteld en allemaal dezelfde DNS-records teruggeven.Je ontvangt terug een e-mail van ons als we merken dat het probleem werd verholpen. Contacteer ons gerust als jullie hierover vragen hebben.Stamhoofd', '<!DOCTYPE html>\n<html>\n\n<head>\n<meta charset=\"utf-8\" />\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0\" />\n<title>DNS-records van {{mailDomain}} zijn onstabiel</title>\n<style type=\"text/css\">body {\n color: #000716;\n color: var(--color-dark, #000716);\n font-family: -apple-system-body, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";\n font-size: 12pt;\n line-height: 1.4;\n}\n\np {\n margin: 0;\n padding: 0;\n line-height: 1.4;\n}\n\np.description {\n color: var(--color-gray-4, #5e5e5e);\n}\np.description a, p.description a:link, p.description a:visited, p.description a:active, p.description a:hover {\n text-decoration: underline;\n color: var(--color-gray-4, #5e5e5e);\n}\n\nstrong {\n font-weight: bold;\n}\n\nem {\n font-style: italic;\n}\n\nh1 {\n font-size: 30px;\n font-weight: bold;\n line-height: 1.2;\n margin: 0;\n padding: 0;\n}\n@media (max-width: 350px) {\n h1 {\n font-size: 24px;\n }\n}\n\nh2 {\n font-size: 20px;\n line-height: 1.2;\n font-weight: bold;\n margin: 0;\n padding: 0;\n}\n\nh3 {\n font-size: 16px;\n line-height: 1.2;\n font-weight: bold;\n margin: 0;\n padding: 0;\n}\n\nh4 {\n line-height: 1.2;\n font-weight: 500;\n margin: 0;\n padding: 0;\n}\n\nol, ul {\n list-style-position: outside;\n padding-left: 30px;\n}\n\nhr {\n height: 1px;\n background: var(--color-border, var(--color-gray-2, #dcdcdc));\n border-radius: 1px;\n padding: 0;\n margin: 20px 0;\n outline: none;\n border: 0;\n}\n\n.button {\n touch-action: inherit;\n user-select: auto;\n cursor: pointer;\n display: inline-block !important;\n line-height: 42px;\n font-size: 16px;\n font-weight: bold;\n}\n.button:active {\n transform: none;\n}\n\nimg {\n max-width: 100%;\n height: auto;\n}\n\na, a:link, a:visited, a:active, a:hover {\n text-decoration: underline;\n color: blue;\n}\n\n.email-data-table {\n width: 100%;\n border-collapse: collapse;\n}\n.email-data-table th, .email-data-table td {\n text-align: left;\n padding: 10px 10px 10px 0;\n border-bottom: 1px solid var(--color-border, var(--color-gray-2, #dcdcdc));\n vertical-align: middle;\n}\n.email-data-table th:last-child, .email-data-table td:last-child {\n text-align: right;\n padding-right: 0;\n}\n.email-data-table thead {\n font-weight: bold;\n}\n.email-data-table thead th {\n font-size: 10pt;\n}\n.email-data-table h4 ~ p {\n padding-top: 3px;\n opacity: 0.8;\n font-size: 11pt;\n}\n\n.email-style-inline-code {\n font-family: monospace;\n white-space: pre-wrap;\n display: inline-block;\n}\n\n.email-style-description-small {\n font-size: 14px;\n line-height: 1.5;\n font-weight: normal;\n color: var(--color-gray-4, #5e5e5e);\n font-variation-settings: \"opsz\" 19;\n}\n\n.email-style-title-list {\n font-size: 16px;\n line-height: 1.3;\n font-weight: 500;\n}\n.email-style-title-list + p {\n padding-top: 3px;\n}\n\n.email-style-title-prefix-list {\n font-size: 11px;\n line-height: 1.5;\n font-weight: bold;\n color: {{primaryColor}};\n text-transform: uppercase;\n margin-bottom: 3px;\n}\n.email-style-title-prefix-list.error {\n color: #f0153d;\n}\n\n.email-style-price-base, .email-style-discount-price, .email-style-discount-old-price, .email-style-price {\n font-size: 15px;\n line-height: 1.4;\n font-weight: 500;\n font-variant-numeric: tabular-nums;\n}\n.email-style-price-base.disabled, .disabled.email-style-discount-price, .disabled.email-style-discount-old-price, .disabled.email-style-price {\n opacity: 0.6;\n}\n.email-style-price-base.negative, .negative.email-style-discount-price, .negative.email-style-discount-old-price, .negative.email-style-price {\n color: #f0153d;\n}\n\n.email-style-price {\n font-weight: bold;\n color: {{primaryColor}};\n}\n\n.email-style-discount-old-price {\n text-decoration: line-through;\n color: var(--color-gray-4, #5e5e5e);\n}\n\n.email-style-discount-price {\n font-weight: bold;\n color: #ff4747;\n margin-left: 5px;\n}\n\n.pre-wrap {\n white-space: pre-wrap;\n} hr {height: 2px;background: #e7e7e7; border-radius: 1px; padding: 0; margin: 20px 0; outline: none; border: 0;} .button.primary { margin: 0; text-decoration: none; font-size: 16px; font-weight: bold; color: {{primaryColorContrast}}; padding: 0 27px; line-height: 42px; background: {{primaryColor}}; text-align: center; border-radius: 7px; touch-action: manipulation; display: inline-block; transition: 0.2s transform, 0.2s opacity; } .button.primary:active { transform: scale(0.95, 0.95); } .inline-link, .inline-link:link, .inline-link:visited, .inline-link:active, .inline-link:hover { margin: 0; text-decoration: underline; font-size: inherit; font-weight: inherit; color: inherit; touch-action: manipulation; } .inline-link:active { opacity: 0.5; } .description { color: #5e5e5e; } </style>\n</head>\n\n<body>\n<p style=\"margin: 0; padding: 0; line-height: 1.4;\">{{greeting}}</p><p style=\"margin: 0; padding: 0; line-height: 1.4;\"><br></p><p style=\"margin: 0; padding: 0; line-height: 1.4;\">Dit is een technische e-mail bestemd voor jullie webmaster.</p><p style=\"margin: 0; padding: 0; line-height: 1.4;\"><br></p><p style=\"margin: 0; padding: 0; line-height: 1.4;\">Stamhoofd controleert elke dag automatisch of jullie domeinnaam {{mailDomain}}, die gekoppeld is aan {{organizationName}} op Stamhoofd nog correct is ingesteld. Dit is nodig voor het versturen van e-mails via jullie e-mailadressen, maar ook eventueel voor jullie ledenportaal als jullie de ledenadministratie gebruiken.</p><p style=\"margin: 0; padding: 0; line-height: 1.4;\"><br></p><p style=\"margin: 0; padding: 0; line-height: 1.4;\">Nu blijkt al even dat we merken dat op het ene moment jullie domeinnaam correct is ingesteld, en de volgende dag niet meer, en zo gaat dat maar door. Om te verhinderen dat je elke keer een e-mail van ons krijgt daarover, hebben we jullie e-mailadres als onstabiel gemarkeerd.</p><p style=\"margin: 0; padding: 0; line-height: 1.4;\"><br></p><p style=\"margin: 0; padding: 0; line-height: 1.4;\">Controleer of de nameservers van jullie domeinnaam wel correct zijn ingesteld en allemaal dezelfde DNS-records teruggeven.</p><p style=\"margin: 0; padding: 0; line-height: 1.4;\"><br></p><p style=\"margin: 0; padding: 0; line-height: 1.4;\">Je ontvangt terug een e-mail van ons als we merken dat het probleem werd verholpen. Contacteer ons gerust als jullie hierover vragen hebben.</p><p style=\"margin: 0; padding: 0; line-height: 1.4;\"><br></p><p style=\"margin: 0; padding: 0; line-height: 1.4;\">Stamhoofd</p>\n</body>\n\n</html>', '{\"value\": {\"type\": \"doc\", \"content\": [{\"type\": \"paragraph\", \"content\": [{\"type\": \"smartVariable\", \"attrs\": {\"id\": \"greeting\"}}]}, {\"type\": \"paragraph\"}, {\"type\": \"paragraph\", \"content\": [{\"text\": \"Dit is een technische e-mail bestemd voor jullie webmaster.\", \"type\": \"text\"}]}, {\"type\": \"paragraph\"}, {\"type\": \"paragraph\", \"content\": [{\"text\": \"Stamhoofd controleert elke dag automatisch of jullie domeinnaam \", \"type\": \"text\"}, {\"type\": \"smartVariable\", \"attrs\": {\"id\": \"mailDomain\"}}, {\"text\": \", die gekoppeld is aan \", \"type\": \"text\"}, {\"type\": \"smartVariable\", \"attrs\": {\"id\": \"organizationName\"}}, {\"text\": \" op Stamhoofd nog correct is ingesteld. Dit is nodig voor het versturen van e-mails via jullie e-mailadressen, maar ook eventueel voor jullie ledenportaal als jullie de ledenadministratie gebruiken.\", \"type\": \"text\"}]}, {\"type\": \"paragraph\"}, {\"type\": \"paragraph\", \"content\": [{\"text\": \"Nu blijkt al even dat we merken dat op het ene moment jullie domeinnaam correct is ingesteld, en de volgende dag niet meer, en zo gaat dat maar door. Om te verhinderen dat je elke keer een e-mail van ons krijgt daarover, hebben we jullie e-mailadres als onstabiel gemarkeerd.\", \"type\": \"text\"}]}, {\"type\": \"paragraph\"}, {\"type\": \"paragraph\", \"content\": [{\"text\": \"Controleer of de nameservers van jullie domeinnaam wel correct zijn ingesteld en allemaal dezelfde DNS-records teruggeven.\", \"type\": \"text\"}]}, {\"type\": \"paragraph\"}, {\"type\": \"paragraph\", \"content\": [{\"text\": \"Je ontvangt terug een e-mail van ons als we merken dat het probleem werd verholpen. Contacteer ons gerust als jullie hierover vragen hebben.\", \"type\": \"text\"}]}, {\"type\": \"paragraph\"}, {\"type\": \"paragraph\", \"content\": [{\"text\": \"Stamhoofd\", \"type\": \"text\"}]}]}, \"version\": 377}', '2025-07-15 09:24:17', '2025-07-15 09:24:17'),
|
|
57
|
-
('61199699-492f-4fd3-a966-ca75179c3e71', '', NULL, NULL, NULL, 'DefaultPaymentsEmail', '{{greeting}}\n\nBetaalinstructies\n{{paymentTable}}\n\n{{overviewContext}}\n\n{{
|
|
57
|
+
('61199699-492f-4fd3-a966-ca75179c3e71', '', NULL, NULL, NULL, 'DefaultPaymentsEmail', '{{greeting}}\n\nBetaalinstructies\n{{paymentTable}}\n\n{{overviewContext}}\n\n{{overviewTable}}\nTotaal: {{priceToPay}}\n\nKomt deze e-mail bij jou terecht, maar weet je niet waarover dit gaat en denk je dat dit aan een andere persoon is gericht (bv. een typefout)? Dan schrijf je best uit voor onze e-mails via deze knop ({{unsubscribeUrl}}) — hierna zal je nooit meer een e-mail van ons ontvangen.\nUitschrijven ({{unsubscribeUrl}})', '<!DOCTYPE html>\n<html>\n\n<head>\n<meta charset=\"utf-8\" />\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0\" />\n<title></title>\n<style type=\"text/css\">body {\n color: #000716;\n color: var(--color-dark, #000716);\n font-family: -apple-system-body, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";\n font-size: 12pt;\n line-height: 1.4;\n}\n\np {\n margin: 0;\n padding: 0;\n line-height: 1.4;\n}\n\np.description {\n color: var(--color-gray-4, #5e5e5e);\n}\np.description a, p.description a:link, p.description a:visited, p.description a:active, p.description a:hover {\n text-decoration: underline;\n color: var(--color-gray-4, #5e5e5e);\n}\n\nstrong {\n font-weight: bold;\n}\n\nem {\n font-style: italic;\n}\n\nh1 {\n font-size: 30px;\n font-weight: bold;\n line-height: 1.2;\n margin: 0;\n padding: 0;\n}\n@media (max-width: 350px) {\n h1 {\n font-size: 24px;\n }\n}\n\nh2 {\n font-size: 20px;\n line-height: 1.2;\n font-weight: bold;\n margin: 0;\n padding: 0;\n}\n\nh3 {\n font-size: 16px;\n line-height: 1.2;\n font-weight: bold;\n margin: 0;\n padding: 0;\n}\n\nh4 {\n line-height: 1.2;\n font-weight: 500;\n margin: 0;\n padding: 0;\n}\n\nol, ul {\n list-style-position: outside;\n padding-left: 30px;\n}\n\nhr {\n height: 1px;\n background: var(--color-border, var(--color-gray-2, #dcdcdc));\n border-radius: 1px;\n padding: 0;\n margin: 20px 0;\n outline: none;\n border: 0;\n}\n\n.button {\n touch-action: inherit;\n user-select: auto;\n cursor: pointer;\n display: inline-block !important;\n line-height: 42px;\n font-size: 16px;\n font-weight: bold;\n}\n.button:active {\n transform: none;\n}\n\nimg {\n max-width: 100%;\n height: auto;\n}\n\na, a:link, a:visited, a:active, a:hover {\n text-decoration: underline;\n color: blue;\n}\n\n.email-data-table {\n width: 100%;\n border-collapse: collapse;\n}\n.email-data-table th, .email-data-table td {\n text-align: left;\n padding: 10px 10px 10px 0;\n border-bottom: 1px solid var(--color-border, var(--color-gray-2, #dcdcdc));\n vertical-align: middle;\n}\n.email-data-table th:last-child, .email-data-table td:last-child {\n text-align: right;\n padding-right: 0;\n}\n.email-data-table td.price {\n white-space: nowrap;\n}\n.email-data-table thead {\n font-weight: bold;\n}\n.email-data-table thead th {\n font-size: 10pt;\n}\n.email-data-table h4 ~ p {\n padding-top: 3px;\n opacity: 0.8;\n font-size: 11pt;\n}\n\n.email-style-inline-code {\n font-family: monospace;\n white-space: pre-wrap;\n display: inline-block;\n}\n\n.email-style-description-small {\n font-size: 14px;\n line-height: 1.5;\n font-weight: normal;\n color: var(--color-gray-4, #5e5e5e);\n font-variation-settings: \"opsz\" 19;\n}\n\n.email-style-title-list {\n font-size: 16px;\n line-height: 1.3;\n font-weight: 500;\n}\n.email-style-title-list + p {\n padding-top: 3px;\n}\n\n.email-style-title-prefix-list {\n font-size: 11px;\n line-height: 1.5;\n font-weight: bold;\n color: {{primaryColor}};\n text-transform: uppercase;\n margin-bottom: 3px;\n}\n.email-style-title-prefix-list.error {\n color: #f0153d;\n}\n\n.email-style-price-base, .email-style-discount-price, .email-style-discount-old-price, .email-style-price {\n font-size: 15px;\n line-height: 1.4;\n font-weight: 500;\n font-variant-numeric: tabular-nums;\n}\n.email-style-price-base.disabled, .disabled.email-style-discount-price, .disabled.email-style-discount-old-price, .disabled.email-style-price {\n opacity: 0.6;\n}\n.email-style-price-base.negative, .negative.email-style-discount-price, .negative.email-style-discount-old-price, .negative.email-style-price {\n color: #f0153d;\n}\n\n.email-style-price {\n font-weight: bold;\n color: {{primaryColor}};\n}\n\n.email-style-discount-old-price {\n text-decoration: line-through;\n color: var(--color-gray-4, #5e5e5e);\n}\n\n.email-style-discount-price {\n font-weight: bold;\n color: #ff4747;\n margin-left: 5px;\n}\n\n.pre-wrap {\n white-space: pre-wrap;\n} hr {height: 2px;background: #e7e7e7; border-radius: 1px; padding: 0; margin: 20px 0; outline: none; border: 0;} .button.primary { margin: 0; text-decoration: none; font-size: 16px; font-weight: bold; color: {{primaryColorContrast}}; padding: 0 27px; line-height: 42px; background: {{primaryColor}}; text-align: center; border-radius: 7px; touch-action: manipulation; display: inline-block; transition: 0.2s transform, 0.2s opacity; } .button.primary:active { transform: scale(0.95, 0.95); } .inline-link, .inline-link:link, .inline-link:visited, .inline-link:active, .inline-link:hover { margin: 0; text-decoration: underline; font-size: inherit; font-weight: inherit; color: inherit; touch-action: manipulation; } .inline-link:active { opacity: 0.5; } .description { color: #5e5e5e; } </style>\n</head>\n\n<body>\n<p style=\"margin: 0; padding: 0; line-height: 1.4;\">{{greeting}}</p><p style=\"margin: 0; padding: 0; line-height: 1.4;\"><br></p><hr style=\"height: 2px;background: #e7e7e7; border-radius: 1px; padding: 0; margin: 20px 0; outline: none; border: 0;\"><h2 style=\"margin: 0; padding: 0;\">Betaalinstructies</h2><div data-type=\"smartVariableBlock\" data-id=\"paymentTable\">{{paymentTable}}</div><p style=\"margin: 0; padding: 0; line-height: 1.4;\"><br></p><p style=\"margin: 0; padding: 0; line-height: 1.4;\"><br></p><h2 style=\"margin: 0; padding: 0;\">{{overviewContext}}</h2><p style=\"margin: 0; padding: 0; line-height: 1.4;\"><br></p><div data-type=\"smartVariableBlock\" data-id=\"overviewTable\">{{overviewTable}}</div><p style=\"margin: 0; padding: 0; line-height: 1.4;\"><br></p><h3 style=\"margin: 0; padding: 0;\">Totaal: {{priceToPay}}</h3><p style=\"margin: 0; padding: 0; line-height: 1.4;\"><br></p><p style=\"margin: 0; padding: 0; line-height: 1.4;\"><br></p><p class=\"description\" style=\"color: #5e5e5e;\"><em>Komt deze e-mail bij jou terecht, maar weet je niet waarover dit gaat en denk je dat dit aan een andere persoon is gericht (bv. een typefout)? Dan schrijf je best uit voor onze e-mails via </em><a class=\"inline-link\" href=\"{{unsubscribeUrl}}\" target=\"\" style=\"margin: 0; text-decoration: underline; font-size: inherit; font-weight: inherit; color: inherit; touch-action: manipulation;\"><em>deze knop</em></a><em> — hierna zal je nooit meer een e-mail van ons ontvangen.</em></p><p style=\"margin: 0; padding: 0; line-height: 1.4;\"><a class=\"inline-link\" href=\"{{unsubscribeUrl}}\" target=\"\" style=\"margin: 0; text-decoration: underline; font-size: inherit; font-weight: inherit; color: inherit; touch-action: manipulation;\">Uitschrijven</a></p>\n</body>\n\n</html>', '{\"value\": {\"type\": \"doc\", \"content\": [{\"type\": \"paragraph\", \"content\": [{\"type\": \"smartVariable\", \"attrs\": {\"id\": \"greeting\"}}]}, {\"type\": \"paragraph\"}, {\"type\": \"horizontalRule\"}, {\"type\": \"heading\", \"attrs\": {\"level\": 2}, \"content\": [{\"text\": \"Betaalinstructies\", \"type\": \"text\"}]}, {\"type\": \"smartVariableBlock\", \"attrs\": {\"id\": \"paymentTable\"}}, {\"type\": \"paragraph\"}, {\"type\": \"paragraph\"}, {\"type\": \"heading\", \"attrs\": {\"level\": 2}, \"content\": [{\"type\": \"smartVariable\", \"attrs\": {\"id\": \"overviewContext\"}}]}, {\"type\": \"paragraph\"}, {\"type\": \"smartVariableBlock\", \"attrs\": {\"id\": \"overviewTable\"}}, {\"type\": \"paragraph\"}, {\"type\": \"heading\", \"attrs\": {\"level\": 3}, \"content\": [{\"text\": \"Totaal: \", \"type\": \"text\"}, {\"type\": \"smartVariable\", \"attrs\": {\"id\": \"priceToPay\"}}]}, {\"type\": \"paragraph\"}, {\"type\": \"paragraph\"}, {\"type\": \"descriptiveText\", \"content\": [{\"text\": \"Komt deze e-mail bij jou terecht, maar weet je niet waarover dit gaat en denk je dat dit aan een andere persoon is gericht (bv. een typefout)? Dan schrijf je best uit voor onze e-mails via \", \"type\": \"text\", \"marks\": [{\"type\": \"italic\"}]}, {\"type\": \"smartButtonInline\", \"attrs\": {\"id\": \"unsubscribeUrl\"}, \"content\": [{\"text\": \"deze knop\", \"type\": \"text\", \"marks\": [{\"type\": \"italic\"}]}]}, {\"text\": \" — hierna zal je nooit meer een e-mail van ons ontvangen.\", \"type\": \"text\", \"marks\": [{\"type\": \"italic\"}]}]}, {\"type\": \"paragraph\", \"content\": [{\"type\": \"smartButtonInline\", \"attrs\": {\"id\": \"unsubscribeUrl\"}, \"content\": [{\"text\": \"Uitschrijven\", \"type\": \"text\"}]}]}]}, \"version\": 394}', '2026-02-10 17:44:20', '2026-02-10 17:44:20');
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Migration } from '@simonbackx/simple-database';
|
|
2
2
|
import { Member } from '@stamhoofd/models';
|
|
3
|
-
import { MemberUserSyncer } from '../helpers/MemberUserSyncer';
|
|
3
|
+
import { MemberUserSyncer } from '../helpers/MemberUserSyncer.js';
|
|
4
4
|
import { logger } from '@simonbackx/simple-logging';
|
|
5
5
|
|
|
6
6
|
export default new Migration(async () => {
|
|
@@ -1,25 +1,6 @@
|
|
|
1
1
|
import { Model, ModelEvent } from '@simonbackx/simple-database';
|
|
2
2
|
import { AuditLogSource } from '@stamhoofd/structures';
|
|
3
3
|
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
4
|
-
import { DocumentTemplateLogger } from '../audit-logs/DocumentTemplateLogger';
|
|
5
|
-
import { EventLogger } from '../audit-logs/EventLogger';
|
|
6
|
-
import { GroupLogger } from '../audit-logs/GroupLogger';
|
|
7
|
-
import { MemberLogger } from '../audit-logs/MemberLogger';
|
|
8
|
-
import { MemberPlatformMembershipLogger } from '../audit-logs/MemberPlatformMembershipLogger';
|
|
9
|
-
import { MemberResponsibilityRecordLogger } from '../audit-logs/MemberResponsibilityRecordLogger';
|
|
10
|
-
import { OrderLogger } from '../audit-logs/OrderLogger';
|
|
11
|
-
import { OrganizationLogger } from '../audit-logs/OrganizationLogger';
|
|
12
|
-
import { OrganizationRegistrationPeriodLogger } from '../audit-logs/OrganizationRegistrationPeriodLogger';
|
|
13
|
-
import { PaymentLogger } from '../audit-logs/PaymentLogger';
|
|
14
|
-
import { PlatformLogger } from '../audit-logs/PlatformLogger';
|
|
15
|
-
import { RegistrationLogger } from '../audit-logs/RegistrationLogger';
|
|
16
|
-
import { RegistrationPeriodLogger } from '../audit-logs/RegistrationPeriodLogger';
|
|
17
|
-
import { StripeAccountLogger } from '../audit-logs/StripeAccountLogger';
|
|
18
|
-
import { WebshopLogger } from '../audit-logs/WebshopLogger';
|
|
19
|
-
import { EmailLogger } from '../audit-logs/EmailLogger';
|
|
20
|
-
import { EmailTemplateLogger } from '../audit-logs/EmailTemplateLogger';
|
|
21
|
-
import { EmailAddressLogger } from '../audit-logs/EmailAddressLogger';
|
|
22
|
-
import { UserLogger } from '../audit-logs/UserLogger';
|
|
23
4
|
|
|
24
5
|
export type AuditLogContextSettings = {
|
|
25
6
|
disable?: boolean;
|
|
@@ -31,6 +12,7 @@ export type AuditLogContextSettings = {
|
|
|
31
12
|
fallbackUserId?: string | null;
|
|
32
13
|
fallbackOrganizationId?: string | null;
|
|
33
14
|
};
|
|
15
|
+
export const modelLogDefinitions = new Map<typeof Model, { logEvent: (event: ModelEvent) => Promise<any> }>();
|
|
34
16
|
|
|
35
17
|
export class AuditLogService {
|
|
36
18
|
private constructor() { }
|
|
@@ -85,25 +67,3 @@ export class AuditLogService {
|
|
|
85
67
|
});
|
|
86
68
|
}
|
|
87
69
|
};
|
|
88
|
-
|
|
89
|
-
const modelLogDefinitions = new Map<typeof Model, { logEvent: (event: ModelEvent) => Promise<any> }>();
|
|
90
|
-
|
|
91
|
-
modelLogDefinitions.set(RegistrationLogger.model, RegistrationLogger);
|
|
92
|
-
modelLogDefinitions.set(GroupLogger.model, GroupLogger);
|
|
93
|
-
modelLogDefinitions.set(OrganizationLogger.model, OrganizationLogger);
|
|
94
|
-
modelLogDefinitions.set(PlatformLogger.model, PlatformLogger);
|
|
95
|
-
modelLogDefinitions.set(EventLogger.model, EventLogger);
|
|
96
|
-
modelLogDefinitions.set(RegistrationPeriodLogger.model, RegistrationPeriodLogger);
|
|
97
|
-
modelLogDefinitions.set(OrganizationRegistrationPeriodLogger.model, OrganizationRegistrationPeriodLogger);
|
|
98
|
-
modelLogDefinitions.set(StripeAccountLogger.model, StripeAccountLogger);
|
|
99
|
-
modelLogDefinitions.set(MemberLogger.model, MemberLogger);
|
|
100
|
-
modelLogDefinitions.set(WebshopLogger.model, WebshopLogger);
|
|
101
|
-
modelLogDefinitions.set(OrderLogger.model, OrderLogger);
|
|
102
|
-
modelLogDefinitions.set(PaymentLogger.model, PaymentLogger);
|
|
103
|
-
modelLogDefinitions.set(MemberPlatformMembershipLogger.model, MemberPlatformMembershipLogger);
|
|
104
|
-
modelLogDefinitions.set(MemberResponsibilityRecordLogger.model, MemberResponsibilityRecordLogger);
|
|
105
|
-
modelLogDefinitions.set(DocumentTemplateLogger.model, DocumentTemplateLogger);
|
|
106
|
-
modelLogDefinitions.set(EmailLogger.model, EmailLogger);
|
|
107
|
-
modelLogDefinitions.set(EmailTemplateLogger.model, EmailTemplateLogger);
|
|
108
|
-
modelLogDefinitions.set(EmailAddressLogger.model, EmailAddressLogger);
|
|
109
|
-
modelLogDefinitions.set(UserLogger.model, UserLogger);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ManyToOneRelation } from '@simonbackx/simple-database';
|
|
2
2
|
import { BalanceItemPayment, Organization } from '@stamhoofd/models';
|
|
3
|
-
import { BalanceItemService } from './BalanceItemService';
|
|
3
|
+
import { BalanceItemService } from './BalanceItemService.js';
|
|
4
4
|
|
|
5
5
|
type Loaded<T> = (T) extends ManyToOneRelation<infer Key, infer Model> ? Record<Key, Model> : never;
|
|
6
6
|
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { Model } from '@simonbackx/simple-database';
|
|
2
2
|
import { BalanceItem, CachedBalance, Document, MemberUser, Order, Organization, Payment, Webshop } from '@stamhoofd/models';
|
|
3
3
|
import { AuditLogSource, BalanceItemStatus, BalanceItemType, OrderStatus, PaymentStatus, ReceivableBalanceType } from '@stamhoofd/structures';
|
|
4
|
-
import { GroupedThrottledQueue } from '../helpers/GroupedThrottledQueue';
|
|
5
|
-
import { ThrottledQueue } from '../helpers/ThrottledQueue';
|
|
6
|
-
import { AuditLogService } from './AuditLogService';
|
|
7
|
-
import { PaymentReallocationService } from './PaymentReallocationService';
|
|
8
|
-
import { RegistrationService } from './RegistrationService';
|
|
4
|
+
import { GroupedThrottledQueue } from '../helpers/GroupedThrottledQueue.js';
|
|
5
|
+
import { ThrottledQueue } from '../helpers/ThrottledQueue.js';
|
|
6
|
+
import { AuditLogService } from './AuditLogService.js';
|
|
7
|
+
import { PaymentReallocationService } from './PaymentReallocationService.js';
|
|
8
|
+
import { RegistrationService } from './RegistrationService.js';
|
|
9
|
+
import { STPackageService } from './STPackageService.js';
|
|
9
10
|
|
|
10
11
|
const memberUpdateQueue = new GroupedThrottledQueue(async (organizationId: string, memberIds: string[]) => {
|
|
11
12
|
await CachedBalance.updateForMembers(organizationId, memberIds);
|
|
@@ -240,6 +241,12 @@ export const BalanceItemService = {
|
|
|
240
241
|
}
|
|
241
242
|
}
|
|
242
243
|
|
|
244
|
+
if (balanceItem.packageId) {
|
|
245
|
+
if (balanceItem.type === BalanceItemType.STPackage) {
|
|
246
|
+
await STPackageService.markValid(balanceItem.packageId);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
243
250
|
balanceItem.paidAt = new Date();
|
|
244
251
|
await balanceItem.save();
|
|
245
252
|
},
|
|
@@ -2,9 +2,9 @@ import { SimpleError } from '@simonbackx/simple-errors';
|
|
|
2
2
|
import { EventNotification, Member, MemberResponsibilityRecord, Organization, Platform, sendEmailTemplate, User } from '@stamhoofd/models';
|
|
3
3
|
import { EmailTemplateType, PermissionLevel, Recipient, RecordCategory, Replacement } from '@stamhoofd/structures';
|
|
4
4
|
import { Formatter } from '@stamhoofd/utility';
|
|
5
|
-
import { AdminPermissionChecker } from '../helpers/AdminPermissionChecker';
|
|
6
|
-
import { Context } from '../helpers/Context';
|
|
7
|
-
import { AuthenticatedStructures } from '../helpers/AuthenticatedStructures';
|
|
5
|
+
import { AdminPermissionChecker } from '../helpers/AdminPermissionChecker.js';
|
|
6
|
+
import { Context } from '../helpers/Context.js';
|
|
7
|
+
import { AuthenticatedStructures } from '../helpers/AuthenticatedStructures.js';
|
|
8
8
|
|
|
9
9
|
export class EventNotificationService {
|
|
10
10
|
static async validateType(notification: EventNotification) {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { SimpleError } from '@simonbackx/simple-errors';
|
|
2
|
-
import { BalanceItem, BalanceItemPayment, Invoice, Organization, Payment } from '@stamhoofd/models';
|
|
2
|
+
import { BalanceItem, BalanceItemPayment, Invoice, InvoicedBalanceItem, Organization, Payment } from '@stamhoofd/models';
|
|
3
3
|
import { InvoicedBalanceItem as InvoicedBalanceItemStruct, Invoice as InvoiceStruct } from '@stamhoofd/structures';
|
|
4
4
|
import { Formatter } from '@stamhoofd/utility';
|
|
5
|
+
import { ViesHelper } from '../helpers/ViesHelper.js';
|
|
5
6
|
|
|
6
7
|
export class InvoiceService {
|
|
7
8
|
static async invoicePayment(payment: Payment) {
|
|
@@ -69,9 +70,36 @@ export class InvoiceService {
|
|
|
69
70
|
items,
|
|
70
71
|
});
|
|
71
72
|
|
|
72
|
-
|
|
73
|
+
return await this.createFrom(organization, struct, { payments: [payment], balanceItems });
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
static async createFrom(organization: { id: string }, struct: InvoiceStruct, options?: { payments?: Payment[]; balanceItems?: BalanceItem[] }) {
|
|
77
|
+
if (struct.number) {
|
|
78
|
+
throw new SimpleError({
|
|
79
|
+
code: 'invalid_field',
|
|
80
|
+
message: 'You cannot create new invoices with a fixed number. Numbers are auto-generated.',
|
|
81
|
+
field: 'number',
|
|
82
|
+
});
|
|
83
|
+
}
|
|
73
84
|
|
|
74
|
-
if (struct.
|
|
85
|
+
if (struct.items.length === 0) {
|
|
86
|
+
throw new SimpleError({
|
|
87
|
+
code: 'missing_items',
|
|
88
|
+
message: 'Cannot create invoice without items',
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const model = new Invoice();
|
|
93
|
+
model.customer = struct.customer;
|
|
94
|
+
|
|
95
|
+
if (model.customer.company) {
|
|
96
|
+
await ViesHelper.checkCompany(model.customer.company, model.customer.company);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
struct.updatePrices();
|
|
100
|
+
struct.validateVATRates();
|
|
101
|
+
|
|
102
|
+
if (struct.totalBalanceInvoicedAmount === 0) {
|
|
75
103
|
throw new SimpleError({
|
|
76
104
|
code: 'invalid_invoiced_amount',
|
|
77
105
|
message: 'Unexpected 0 totalBalanceInvoicedAmount',
|
|
@@ -86,29 +114,115 @@ export class InvoiceService {
|
|
|
86
114
|
});
|
|
87
115
|
}
|
|
88
116
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
117
|
+
model.seller = struct.seller;
|
|
118
|
+
model.organizationId = organization.id;
|
|
119
|
+
model.payingOrganizationId = struct.payingOrganizationId;
|
|
120
|
+
|
|
121
|
+
model.payableRoundingAmount = struct.payableRoundingAmount;
|
|
122
|
+
model.VATTotal = struct.VATTotal;
|
|
123
|
+
model.VATTotalAmount = struct.VATTotalAmount;
|
|
124
|
+
model.totalWithoutVAT = struct.totalWithoutVAT;
|
|
125
|
+
model.totalWithVAT = struct.totalWithVAT;
|
|
126
|
+
model.totalBalanceInvoicedAmount = struct.totalBalanceInvoicedAmount;
|
|
127
|
+
|
|
128
|
+
model.ipAddress = struct.ipAddress;
|
|
129
|
+
model.userAgent = struct.userAgent;
|
|
130
|
+
|
|
131
|
+
model.stripeAccountId = struct.stripeAccountId;
|
|
132
|
+
model.reference = struct.reference;
|
|
133
|
+
|
|
134
|
+
model.negativeInvoiceId = struct.negativeInvoiceId;
|
|
135
|
+
|
|
136
|
+
if (Math.abs(model.payableRoundingAmount) > 10_00) {
|
|
93
137
|
throw new SimpleError({
|
|
94
|
-
code: '
|
|
95
|
-
message: '
|
|
96
|
-
|
|
138
|
+
code: 'invalid_field',
|
|
139
|
+
message: 'payableRoundingAmount cannot be more than 10 cent',
|
|
140
|
+
human: $t('69832bb4-18a2-428d-a84d-89675ae67016'),
|
|
141
|
+
field: 'payableRoundingAmount',
|
|
97
142
|
});
|
|
98
143
|
}
|
|
144
|
+
const payments = options?.payments ?? await Payment.getByIDs(...struct.payments.map(p => p.id));
|
|
99
145
|
|
|
100
|
-
if (
|
|
146
|
+
if (payments.length !== struct.payments.length) {
|
|
101
147
|
throw new SimpleError({
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
148
|
+
statusCode: 404,
|
|
149
|
+
code: 'not_found',
|
|
150
|
+
message: 'Payment not found',
|
|
105
151
|
});
|
|
106
152
|
}
|
|
107
153
|
|
|
108
|
-
|
|
154
|
+
for (const payment of payments) {
|
|
155
|
+
if (payment.organizationId !== model.organizationId) {
|
|
156
|
+
throw new SimpleError({
|
|
157
|
+
statusCode: 404,
|
|
158
|
+
code: 'not_found',
|
|
159
|
+
message: 'Payment not found',
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (payment.invoiceId) {
|
|
164
|
+
throw new SimpleError({
|
|
165
|
+
code: 'already_invoiced',
|
|
166
|
+
message: 'You cannot invoice a payment multiple times',
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const balanceItems = options?.balanceItems ?? await BalanceItem.getByIDs(...Formatter.uniqueArray(struct.items.map(i => i.balanceItemId)));
|
|
172
|
+
await model.save();
|
|
173
|
+
|
|
174
|
+
try {
|
|
175
|
+
// Create balances
|
|
176
|
+
for (const item of struct.items) {
|
|
177
|
+
const balanceItem = balanceItems.find(b => b.id === item.balanceItemId);
|
|
178
|
+
if (!balanceItem || balanceItem.organizationId !== model.organizationId) {
|
|
179
|
+
throw new SimpleError({
|
|
180
|
+
statusCode: 404,
|
|
181
|
+
code: 'not_found',
|
|
182
|
+
message: 'Balance item not found',
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Todo: check we are not invoicing more than maximum invoiceable for these items
|
|
187
|
+
|
|
188
|
+
const invoiced = new InvoicedBalanceItem();
|
|
189
|
+
invoiced.invoiceId = model.id;
|
|
190
|
+
invoiced.organizationId = model.organizationId;
|
|
191
|
+
invoiced.balanceItemId = item.balanceItemId;
|
|
192
|
+
|
|
193
|
+
invoiced.VATExcempt = item.VATExcempt;
|
|
194
|
+
invoiced.VATPercentage = item.VATPercentage;
|
|
195
|
+
invoiced.VATIncluded = item.VATIncluded;
|
|
109
196
|
|
|
110
|
-
|
|
197
|
+
invoiced.unitPrice = item.unitPrice;
|
|
198
|
+
invoiced.quantity = item.quantity;
|
|
199
|
+
|
|
200
|
+
invoiced.balanceInvoicedAmount = item.balanceInvoicedAmount;
|
|
201
|
+
|
|
202
|
+
invoiced.totalWithoutVAT = item.totalWithoutVAT;
|
|
203
|
+
|
|
204
|
+
invoiced.name = item.name || balanceItem.description;
|
|
205
|
+
invoiced.description = item.description;
|
|
206
|
+
|
|
207
|
+
await invoiced.save();
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Link payments
|
|
211
|
+
for (const payment of payments) {
|
|
212
|
+
payment.invoiceId = model.id;
|
|
213
|
+
await payment.save();
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
catch (e) {
|
|
217
|
+
try {
|
|
218
|
+
await model.delete();
|
|
219
|
+
}
|
|
220
|
+
catch (ee) {
|
|
221
|
+
console.error('Error while trying to delete invoice because of fail save', ee, 'Deleting because of error', e);
|
|
222
|
+
}
|
|
223
|
+
throw e;
|
|
224
|
+
}
|
|
111
225
|
|
|
112
|
-
return
|
|
226
|
+
return model;
|
|
113
227
|
}
|
|
114
228
|
}
|
|
@@ -141,7 +141,7 @@ export class MemberRecordStore {
|
|
|
141
141
|
for (const recordCategory of organization.meta.recordsConfiguration.recordCategories) {
|
|
142
142
|
for (const record of recordCategory.getAllRecords()) {
|
|
143
143
|
if (this.cache.has(record.id)) {
|
|
144
|
-
console.error(`Duplicate record id ${record.id} found in organization ${organization.id} for record ${record.name} (${record.id}) in ${recordCategory.name}`);
|
|
144
|
+
console.error(`Duplicate record id ${record.id} found in organization ${organization.id} for record ${record.name.toString()} (${record.id}) in ${recordCategory.name.toString()}`);
|
|
145
145
|
continue;
|
|
146
146
|
}
|
|
147
147
|
// Add to cache
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { BalanceItem, BalanceItemPayment, MemberFactory, Organization, OrganizationFactory, Payment } from '@stamhoofd/models';
|
|
2
2
|
import { BalanceItemRelation, BalanceItemRelationType, BalanceItemStatus, PaymentMethod, PaymentStatus, ReceivableBalanceType, TranslatedString } from '@stamhoofd/structures';
|
|
3
|
-
import { PaymentReallocationService } from './PaymentReallocationService';
|
|
4
|
-
import { BalanceItemService } from './BalanceItemService';
|
|
3
|
+
import { PaymentReallocationService } from './PaymentReallocationService.js';
|
|
4
|
+
import { BalanceItemService } from './BalanceItemService.js';
|
|
5
5
|
|
|
6
6
|
let sharedOrganization: Organization | undefined;
|
|
7
7
|
|
|
@@ -651,8 +651,8 @@ describe('PaymentReallocationService', () => {
|
|
|
651
651
|
objectId: memberId,
|
|
652
652
|
relations: {
|
|
653
653
|
[BalanceItemRelationType.Group]: 'group1',
|
|
654
|
-
[BalanceItemRelationType.GroupPrice]: 'defaultprice',
|
|
655
|
-
[BalanceItemRelationType.Member]: 'member1',
|
|
654
|
+
[BalanceItemRelationType.GroupPrice]: 'defaultprice',
|
|
655
|
+
[BalanceItemRelationType.Member]: 'member1',
|
|
656
656
|
},
|
|
657
657
|
});
|
|
658
658
|
|
|
@@ -689,7 +689,7 @@ describe('PaymentReallocationService', () => {
|
|
|
689
689
|
|
|
690
690
|
it('Balances with one different relation are prioritized over same amount', async () => {
|
|
691
691
|
const memberId = (await getMember()).id;
|
|
692
|
-
|
|
692
|
+
|
|
693
693
|
const b3 = await createItem({
|
|
694
694
|
unitPrice: 30_00,
|
|
695
695
|
amount: 1,
|
|
@@ -697,7 +697,7 @@ describe('PaymentReallocationService', () => {
|
|
|
697
697
|
priceOpen: 30_00, // This adds internal assert
|
|
698
698
|
objectId: memberId,
|
|
699
699
|
});
|
|
700
|
-
|
|
700
|
+
|
|
701
701
|
const b1 = await createItem({
|
|
702
702
|
unitPrice: 30_00,
|
|
703
703
|
amount: 1,
|
|
@@ -720,7 +720,7 @@ describe('PaymentReallocationService', () => {
|
|
|
720
720
|
relations: {
|
|
721
721
|
[BalanceItemRelationType.Group]: 'group1',
|
|
722
722
|
[BalanceItemRelationType.GroupPrice]: 'price2', // This one is different
|
|
723
|
-
[BalanceItemRelationType.Member]: 'member1',
|
|
723
|
+
[BalanceItemRelationType.Member]: 'member1',
|
|
724
724
|
},
|
|
725
725
|
});
|
|
726
726
|
await PaymentReallocationService.reallocate(
|
|
@@ -746,7 +746,6 @@ describe('PaymentReallocationService', () => {
|
|
|
746
746
|
});
|
|
747
747
|
});
|
|
748
748
|
|
|
749
|
-
|
|
750
749
|
it('Balances with different amount should not create a reallocation payment', async () => {
|
|
751
750
|
const memberId = (await getMember()).id;
|
|
752
751
|
const b1 = await createItem({
|
|
@@ -792,7 +791,7 @@ describe('PaymentReallocationService', () => {
|
|
|
792
791
|
});
|
|
793
792
|
|
|
794
793
|
await expectItem(b2, {
|
|
795
|
-
priceOpen: 30_00,
|
|
794
|
+
priceOpen: 30_00,
|
|
796
795
|
paid: [],
|
|
797
796
|
});
|
|
798
797
|
|
|
@@ -909,7 +908,7 @@ describe('PaymentReallocationService', () => {
|
|
|
909
908
|
|
|
910
909
|
// Check if the balance items are now equal
|
|
911
910
|
await expectItem(b1, {
|
|
912
|
-
priceOpen: 0,
|
|
911
|
+
priceOpen: 0,
|
|
913
912
|
paid: [],
|
|
914
913
|
});
|
|
915
914
|
|
|
@@ -2,7 +2,7 @@ import { BalanceItem, BalanceItemPayment, CachedBalance, Payment } from '@stamho
|
|
|
2
2
|
import { SQL } from '@stamhoofd/sql';
|
|
3
3
|
import { BalanceItemStatus, doBalanceItemRelationsMatch, PaymentMethod, PaymentStatus, PaymentType, ReceivableBalanceType } from '@stamhoofd/structures';
|
|
4
4
|
import { Sorter } from '@stamhoofd/utility';
|
|
5
|
-
import { BalanceItemService } from './BalanceItemService';
|
|
5
|
+
import { BalanceItemService } from './BalanceItemService.js';
|
|
6
6
|
|
|
7
7
|
type BalanceItemWithRemaining = {
|
|
8
8
|
balanceItem: BalanceItem;
|