@stamhoofd/backend 2.39.0 → 2.40.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/eslint.config.mjs +5 -0
- package/index.ts +81 -74
- package/jest.config.cjs +10 -0
- package/migrations.ts +16 -14
- package/package.json +11 -11
- package/src/crons/clear-excel-cache.test.ts +48 -50
- package/src/crons/clear-excel-cache.ts +18 -18
- package/src/crons/setup-steps.ts +2 -2
- package/src/crons.ts +325 -306
- package/src/decoders/StringArrayDecoder.ts +7 -7
- package/src/decoders/StringNullableDecoder.ts +1 -2
- package/src/email-recipient-loaders/members.ts +22 -22
- package/src/endpoints/admin/memberships/ChargeMembershipsEndpoint.ts +8 -9
- package/src/endpoints/admin/memberships/GetChargeMembershipsSummaryEndpoint.ts +39 -40
- package/src/endpoints/admin/organizations/GetOrganizationsCountEndpoint.ts +8 -8
- package/src/endpoints/admin/organizations/GetOrganizationsEndpoint.ts +44 -45
- package/src/endpoints/admin/organizations/PatchOrganizationsEndpoint.ts +58 -57
- package/src/endpoints/auth/CreateAdminEndpoint.ts +48 -45
- package/src/endpoints/auth/CreateTokenEndpoint.test.ts +31 -31
- package/src/endpoints/auth/CreateTokenEndpoint.ts +146 -147
- package/src/endpoints/auth/DeleteTokenEndpoint.ts +7 -7
- package/src/endpoints/auth/DeleteUserEndpoint.ts +15 -15
- package/src/endpoints/auth/ForgotPasswordEndpoint.ts +17 -18
- package/src/endpoints/auth/GetOtherUserEndpoint.ts +9 -10
- package/src/endpoints/auth/GetUserEndpoint.test.ts +32 -35
- package/src/endpoints/auth/GetUserEndpoint.ts +5 -6
- package/src/endpoints/auth/PatchApiUserEndpoint.ts +35 -33
- package/src/endpoints/auth/PatchUserEndpoint.ts +55 -52
- package/src/endpoints/auth/PollEmailVerificationEndpoint.ts +9 -9
- package/src/endpoints/auth/RetryEmailVerificationEndpoint.ts +8 -8
- package/src/endpoints/auth/SignupEndpoint.ts +37 -36
- package/src/endpoints/auth/VerifyEmailEndpoint.ts +29 -28
- package/src/endpoints/global/addresses/SearchRegionsEndpoint.ts +33 -33
- package/src/endpoints/global/addresses/ValidateAddressEndpoint.ts +7 -7
- package/src/endpoints/global/caddy/CheckDomainCertEndpoint.ts +37 -37
- package/src/endpoints/global/email/CreateEmailEndpoint.ts +30 -30
- package/src/endpoints/global/email/GetEmailAddressEndpoint.ts +13 -13
- package/src/endpoints/global/email/GetEmailEndpoint.ts +13 -13
- package/src/endpoints/global/email/ManageEmailAddressEndpoint.ts +16 -16
- package/src/endpoints/global/email/PatchEmailEndpoint.ts +25 -25
- package/src/endpoints/global/events/GetEventsEndpoint.ts +43 -44
- package/src/endpoints/global/events/PatchEventsEndpoint.ts +127 -172
- package/src/endpoints/global/files/ExportToExcelEndpoint.ts +49 -50
- package/src/endpoints/global/files/GetFileCache.ts +13 -13
- package/src/endpoints/global/files/UploadFile.ts +51 -54
- package/src/endpoints/global/files/UploadImage.ts +53 -53
- package/src/endpoints/global/groups/GetGroupsEndpoint.ts +25 -25
- package/src/endpoints/global/members/GetMemberFamilyEndpoint.ts +24 -23
- package/src/endpoints/global/members/GetMembersCountEndpoint.ts +8 -8
- package/src/endpoints/global/members/GetMembersEndpoint.ts +105 -102
- package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.ts +240 -239
- package/src/endpoints/global/organizations/CheckRegisterCodeEndpoint.ts +12 -14
- package/src/endpoints/global/organizations/CreateOrganizationEndpoint.test.ts +32 -33
- package/src/endpoints/global/organizations/CreateOrganizationEndpoint.ts +48 -57
- package/src/endpoints/global/organizations/GetOrganizationFromDomainEndpoint.test.ts +21 -22
- package/src/endpoints/global/organizations/GetOrganizationFromDomainEndpoint.ts +28 -28
- package/src/endpoints/global/organizations/GetOrganizationFromUriEndpoint.ts +18 -18
- package/src/endpoints/global/organizations/SearchOrganizationEndpoint.test.ts +20 -20
- package/src/endpoints/global/organizations/SearchOrganizationEndpoint.ts +17 -17
- package/src/endpoints/global/payments/StripeWebhookEndpoint.ts +81 -75
- package/src/endpoints/global/platform/GetPlatformAdminsEndpoint.ts +14 -14
- package/src/endpoints/global/platform/GetPlatformEnpoint.ts +11 -11
- package/src/endpoints/global/platform/PatchPlatformEnpoint.ts +71 -68
- package/src/endpoints/global/registration/GetPaymentRegistrations.ts +27 -27
- package/src/endpoints/global/registration/GetUserBillingStatusEndpoint.ts +30 -30
- package/src/endpoints/global/registration/GetUserDetailedBillingStatusEndpoint.ts +34 -34
- package/src/endpoints/global/registration/GetUserDocumentsEndpoint.ts +26 -26
- package/src/endpoints/global/registration/GetUserMembersEndpoint.ts +12 -12
- package/src/endpoints/global/registration/PatchUserMembersEndpoint.ts +90 -90
- package/src/endpoints/global/registration/RegisterMembersEndpoint.test.ts +118 -121
- package/src/endpoints/global/registration/RegisterMembersEndpoint.ts +362 -350
- package/src/endpoints/global/registration-periods/GetRegistrationPeriodsEndpoint.ts +8 -9
- package/src/endpoints/global/registration-periods/PatchRegistrationPeriodsEndpoint.ts +21 -21
- package/src/endpoints/global/webshops/GetWebshopFromDomainEndpoint.ts +65 -65
- package/src/endpoints/organization/dashboard/billing/GetOrganizationBillingStatusEndpoint.ts +9 -9
- package/src/endpoints/organization/dashboard/billing/GetOrganizationDetailedBillingStatusEndpoint.ts +14 -14
- package/src/endpoints/organization/dashboard/documents/GetDocumentTemplateXML.ts +17 -17
- package/src/endpoints/organization/dashboard/documents/GetDocumentTemplatesEndpoint.ts +21 -21
- package/src/endpoints/organization/dashboard/documents/GetDocumentsEndpoint.ts +15 -15
- package/src/endpoints/organization/dashboard/documents/PatchDocumentEndpoint.ts +52 -52
- package/src/endpoints/organization/dashboard/documents/PatchDocumentTemplateEndpoint.ts +37 -37
- package/src/endpoints/organization/dashboard/email/CheckEmailBouncesEndpoint.ts +14 -14
- package/src/endpoints/organization/dashboard/email/EmailEndpoint.ts +113 -112
- package/src/endpoints/organization/dashboard/email-templates/GetEmailTemplatesEndpoint.ts +29 -29
- package/src/endpoints/organization/dashboard/email-templates/PatchEmailTemplatesEndpoint.ts +48 -47
- package/src/endpoints/organization/dashboard/mollie/CheckMollieEndpoint.ts +22 -21
- package/src/endpoints/organization/dashboard/mollie/ConnectMollieEndpoint.ts +13 -14
- package/src/endpoints/organization/dashboard/mollie/DisconnectMollieEndpoint.ts +12 -13
- package/src/endpoints/organization/dashboard/mollie/GetMollieDashboardEndpoint.ts +24 -24
- package/src/endpoints/organization/dashboard/nolt/CreateNoltTokenEndpoint.ts +10 -12
- package/src/endpoints/organization/dashboard/organization/GetOrganizationArchivedGroups.ts +14 -14
- package/src/endpoints/organization/dashboard/organization/GetOrganizationDeletedGroups.ts +13 -13
- package/src/endpoints/organization/dashboard/organization/GetOrganizationSSOEndpoint.ts +12 -12
- package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.test.ts +120 -124
- package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.ts +172 -173
- package/src/endpoints/organization/dashboard/organization/SetOrganizationDomainEndpoint.ts +88 -89
- package/src/endpoints/organization/dashboard/organization/SetOrganizationSSOEndpoint.ts +12 -12
- package/src/endpoints/organization/dashboard/payments/GetMemberBalanceEndpoint.ts +17 -17
- package/src/endpoints/organization/dashboard/payments/GetPaymentsCountEndpoint.ts +8 -8
- package/src/endpoints/organization/dashboard/payments/GetPaymentsEndpoint.ts +66 -67
- package/src/endpoints/organization/dashboard/payments/PatchBalanceItemsEndpoint.ts +47 -47
- package/src/endpoints/organization/dashboard/payments/PatchPaymentsEndpoint.ts +93 -91
- package/src/endpoints/organization/dashboard/registration-periods/GetOrganizationRegistrationPeriodsEndpoint.ts +16 -17
- package/src/endpoints/organization/dashboard/registration-periods/PatchOrganizationRegistrationPeriodsEndpoint.ts +170 -167
- package/src/endpoints/organization/dashboard/registration-periods/SetupStepReviewEndpoint.ts +25 -24
- package/src/endpoints/organization/dashboard/stripe/ConnectStripeEndpoint.ts +22 -23
- package/src/endpoints/organization/dashboard/stripe/DeleteStripeAccountEndpoint.ts +22 -22
- package/src/endpoints/organization/dashboard/stripe/GetStripeAccountLinkEndpoint.ts +17 -18
- package/src/endpoints/organization/dashboard/stripe/GetStripeAccountsEndpoint.ts +8 -9
- package/src/endpoints/organization/dashboard/stripe/GetStripeLoginLinkEndpoint.ts +17 -18
- package/src/endpoints/organization/dashboard/stripe/UpdateStripeAccountEndpoint.ts +14 -15
- package/src/endpoints/organization/dashboard/users/CreateApiUserEndpoint.ts +19 -19
- package/src/endpoints/organization/dashboard/users/DeleteUserEndpoint.ts +19 -19
- package/src/endpoints/organization/dashboard/users/GetApiUsersEndpoint.ts +14 -14
- package/src/endpoints/organization/dashboard/users/GetOrganizationAdminsEndpoint.ts +12 -12
- package/src/endpoints/organization/dashboard/webshops/CreateWebshopEndpoint.ts +103 -100
- package/src/endpoints/organization/dashboard/webshops/DeleteWebshopEndpoint.ts +11 -12
- package/src/endpoints/organization/dashboard/webshops/GetDiscountCodesEndpoint.ts +15 -15
- package/src/endpoints/organization/dashboard/webshops/GetWebshopOrdersEndpoint.ts +14 -14
- package/src/endpoints/organization/dashboard/webshops/GetWebshopTicketsEndpoint.ts +14 -14
- package/src/endpoints/organization/dashboard/webshops/GetWebshopUriAvailabilityEndpoint.ts +23 -23
- package/src/endpoints/organization/dashboard/webshops/PatchDiscountCodesEndpoint.ts +54 -52
- package/src/endpoints/organization/dashboard/webshops/PatchWebshopEndpoint.ts +84 -81
- package/src/endpoints/organization/dashboard/webshops/PatchWebshopOrdersEndpoint.ts +120 -111
- package/src/endpoints/organization/dashboard/webshops/PatchWebshopTicketsEndpoint.ts +24 -24
- package/src/endpoints/organization/dashboard/webshops/VerifyWebshopDomainEndpoint.ts +18 -18
- package/src/endpoints/organization/shared/ExchangePaymentEndpoint.ts +141 -130
- package/src/endpoints/organization/shared/GetDocumentHtml.ts +25 -25
- package/src/endpoints/organization/shared/GetPaymentEndpoint.ts +18 -18
- package/src/endpoints/organization/shared/auth/GetOrganizationEndpoint.test.ts +36 -37
- package/src/endpoints/organization/shared/auth/GetOrganizationEndpoint.ts +9 -9
- package/src/endpoints/organization/shared/auth/OpenIDConnectCallbackEndpoint.ts +11 -11
- package/src/endpoints/organization/shared/auth/OpenIDConnectStartEndpoint.ts +28 -27
- package/src/endpoints/organization/webshops/CheckWebshopDiscountCodesEndpoint.ts +20 -20
- package/src/endpoints/organization/webshops/GetOrderByPaymentEndpoint.ts +22 -22
- package/src/endpoints/organization/webshops/GetOrderEndpoint.ts +14 -14
- package/src/endpoints/organization/webshops/GetTicketsEndpoint.ts +57 -56
- package/src/endpoints/organization/webshops/GetWebshopEndpoint.test.ts +65 -66
- package/src/endpoints/organization/webshops/GetWebshopEndpoint.ts +18 -17
- package/src/endpoints/organization/webshops/PlaceOrderEndpoint.test.ts +124 -128
- package/src/endpoints/organization/webshops/PlaceOrderEndpoint.ts +154 -145
- package/src/excel-loaders/members.ts +102 -103
- package/src/excel-loaders/payments.ts +155 -156
- package/src/helpers/AddressValidator.test.ts +32 -32
- package/src/helpers/AddressValidator.ts +128 -122
- package/src/helpers/AdminPermissionChecker.ts +339 -236
- package/src/helpers/AuthenticatedStructures.ts +233 -134
- package/src/helpers/BuckarooHelper.ts +134 -134
- package/src/helpers/CheckSettlements.ts +94 -88
- package/src/helpers/Context.ts +87 -86
- package/src/helpers/CookieHelper.ts +23 -22
- package/src/helpers/EmailResumer.ts +10 -10
- package/src/helpers/FileCache.ts +62 -62
- package/src/helpers/ForwardHandler.test.ts +122 -124
- package/src/helpers/ForwardHandler.ts +76 -70
- package/src/helpers/MemberUserSyncer.ts +101 -96
- package/src/helpers/MembershipCharger.ts +69 -69
- package/src/helpers/MembershipHelper.ts +11 -12
- package/src/helpers/OpenIDConnectHelper.ts +85 -82
- package/src/helpers/PeriodHelper.ts +65 -70
- package/src/helpers/StripeHelper.ts +146 -137
- package/src/helpers/StripePayoutChecker.ts +51 -52
- package/src/helpers/ViesHelper.ts +46 -44
- package/src/helpers/fetchToAsyncIterator.ts +14 -14
- package/src/helpers/xlsxAddressTransformerColumnFactory.ts +50 -52
- package/src/middleware/ContextMiddleware.ts +5 -5
- package/src/migrations/1646578856-validate-addresses.ts +6 -9
- package/src/seeds/0000000000-example.ts +3 -5
- package/src/seeds/1715028563-user-permissions.ts +16 -18
- package/src/seeds/1722256498-group-update-occupancy.ts +12 -12
- package/src/seeds/1722344162-sync-member-users.ts +14 -15
- package/src/seeds/1722344162-update-membership.ts +6 -6
- package/src/seeds/1726055544-balance-item-paid.ts +4 -4
- package/src/seeds/1726055545-balance-item-pending.ts +4 -4
- package/src/seeds/1726494419-update-cached-outstanding-balance.ts +16 -16
- package/src/seeds/1726494420-update-cached-outstanding-balance-from-items.ts +12 -12
- package/src/seeds/1726572303-schedule-stock-updates.ts +12 -12
- package/src/seeds/1726847064-setup-steps.ts +16 -0
- package/src/sql-filters/balance-item-payments.ts +7 -7
- package/src/sql-filters/events.ts +14 -14
- package/src/sql-filters/members.ts +96 -96
- package/src/sql-filters/organizations.ts +139 -75
- package/src/sql-filters/payments.ts +28 -28
- package/src/sql-filters/registrations.ts +14 -14
- package/src/sql-sorters/events.ts +25 -25
- package/src/sql-sorters/members.ts +26 -26
- package/src/sql-sorters/organizations.ts +36 -36
- package/src/sql-sorters/payments.ts +26 -26
- package/tests/e2e/stock.test.ts +616 -621
- package/tests/e2e/tickets.test.ts +255 -260
- package/tests/helpers/StripeMocker.ts +177 -179
- package/tests/helpers/TestServer.ts +9 -9
- package/tests/jest.global.setup.ts +14 -13
- package/tests/jest.setup.ts +33 -32
- package/.eslintrc.js +0 -61
- package/jest.config.js +0 -11
- package/src/helpers/SetupStepsUpdater.ts +0 -359
- package/src/seeds/1724076679-setup-steps.ts +0 -16
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { Member, MemberResponsibilityRecord, MemberWithRegistrations, User } from
|
|
2
|
-
import { SQL } from
|
|
3
|
-
import { MemberDetails, Permissions, UserPermissions } from
|
|
4
|
-
import crypto from
|
|
5
|
-
import basex from
|
|
1
|
+
import { Member, MemberResponsibilityRecord, MemberWithRegistrations, User } from '@stamhoofd/models';
|
|
2
|
+
import { SQL } from '@stamhoofd/sql';
|
|
3
|
+
import { MemberDetails, Permissions, UserPermissions } from '@stamhoofd/structures';
|
|
4
|
+
import crypto from 'crypto';
|
|
5
|
+
import basex from 'base-x';
|
|
6
6
|
|
|
7
|
-
const ALPHABET = '123456789ABCDEFGHJKMNPQRSTUVWXYZ' // Note: we removed 0, O, I and l to make it easier for humans
|
|
8
|
-
const customBase = basex(ALPHABET)
|
|
7
|
+
const ALPHABET = '123456789ABCDEFGHJKMNPQRSTUVWXYZ'; // Note: we removed 0, O, I and l to make it easier for humans
|
|
8
|
+
const customBase = basex(ALPHABET);
|
|
9
9
|
|
|
10
10
|
async function randomBytes(size: number): Promise<Buffer> {
|
|
11
11
|
return new Promise((resolve, reject) => {
|
|
@@ -26,23 +26,23 @@ export class MemberUserSyncerStatic {
|
|
|
26
26
|
* - email addresses have changed
|
|
27
27
|
*/
|
|
28
28
|
async onChangeMember(member: MemberWithRegistrations, unlinkUsers: boolean = false) {
|
|
29
|
-
const {userEmails, parentAndUnverifiedEmails} = this.getMemberAccessEmails(member.details)
|
|
29
|
+
const { userEmails, parentAndUnverifiedEmails } = this.getMemberAccessEmails(member.details);
|
|
30
30
|
|
|
31
31
|
// Make sure all these users have access to the member
|
|
32
32
|
for (const email of userEmails) {
|
|
33
33
|
// Link users that are found with these email addresses.
|
|
34
|
-
await this.linkUser(email, member, false, true)
|
|
34
|
+
await this.linkUser(email, member, false, true);
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
for (const email of parentAndUnverifiedEmails) {
|
|
38
38
|
if (userEmails.includes(email)) {
|
|
39
39
|
continue;
|
|
40
40
|
}
|
|
41
|
-
|
|
41
|
+
|
|
42
42
|
// Link parents and unverified emails
|
|
43
43
|
// Now we add the responsibility permissions to the parent if there are no userEmails
|
|
44
44
|
const asParent = userEmails.length > 0 || !member.details.unverifiedEmails.includes(email) || member.details.defaultAge < 16;
|
|
45
|
-
await this.linkUser(email, member, asParent, true)
|
|
45
|
+
await this.linkUser(email, member, asParent, true);
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
if (unlinkUsers && !member.details.parentsHaveAccess) {
|
|
@@ -53,226 +53,231 @@ export class MemberUserSyncerStatic {
|
|
|
53
53
|
|
|
54
54
|
for (const user of member.users) {
|
|
55
55
|
if (!userEmails.includes(user.email) && !parentAndUnverifiedEmails.includes(user.email)) {
|
|
56
|
-
await this.unlinkUser(user, member)
|
|
56
|
+
await this.unlinkUser(user, member);
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
|
-
}
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
60
61
|
// Only auto unlink users that do not have an account
|
|
61
62
|
for (const user of member.users) {
|
|
62
63
|
if (!userEmails.includes(user.email) && !parentAndUnverifiedEmails.includes(user.email)) {
|
|
63
64
|
if (!user.hasAccount()) {
|
|
64
|
-
await this.unlinkUser(user, member)
|
|
65
|
-
}
|
|
65
|
+
await this.unlinkUser(user, member);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
66
68
|
// Make sure only linked as a parent, not as user self
|
|
67
69
|
// This makes sure we don't inherit permissions and aren't counted as 'being' the member
|
|
68
|
-
await this.linkUser(user.email, member, true)
|
|
70
|
+
await this.linkUser(user.email, member, true);
|
|
69
71
|
}
|
|
70
72
|
}
|
|
71
73
|
}
|
|
72
74
|
}
|
|
73
75
|
|
|
74
76
|
if (member.details.securityCode === null) {
|
|
75
|
-
console.log(
|
|
77
|
+
console.log('Generating security code for member ' + member.id);
|
|
76
78
|
|
|
77
79
|
const length = 16;
|
|
78
80
|
const code = customBase.encode(await randomBytes(100)).toUpperCase().substring(0, length);
|
|
79
|
-
member.details.securityCode = code
|
|
80
|
-
await member.save()
|
|
81
|
+
member.details.securityCode = code;
|
|
82
|
+
await member.save();
|
|
81
83
|
}
|
|
82
84
|
}
|
|
83
85
|
|
|
84
86
|
getMemberAccessEmails(details: MemberDetails) {
|
|
85
|
-
const userEmails = [...details.alternativeEmails]
|
|
87
|
+
const userEmails = [...details.alternativeEmails];
|
|
86
88
|
|
|
87
89
|
if (details.email) {
|
|
88
|
-
userEmails.push(details.email)
|
|
90
|
+
userEmails.push(details.email);
|
|
89
91
|
}
|
|
90
92
|
|
|
91
93
|
const unverifiedEmails: string[] = details.unverifiedEmails;
|
|
92
|
-
const parentAndUnverifiedEmails = details.parentsHaveAccess ? details.parents.flatMap(p => p.email ? [p.email, ...p.alternativeEmails] : p.alternativeEmails).concat(unverifiedEmails) : details.unverifiedEmails
|
|
94
|
+
const parentAndUnverifiedEmails = details.parentsHaveAccess ? details.parents.flatMap(p => p.email ? [p.email, ...p.alternativeEmails] : p.alternativeEmails).concat(unverifiedEmails) : details.unverifiedEmails;
|
|
93
95
|
|
|
94
96
|
return {
|
|
95
97
|
userEmails,
|
|
96
98
|
parentAndUnverifiedEmails,
|
|
97
|
-
emails: userEmails.concat(parentAndUnverifiedEmails)
|
|
98
|
-
}
|
|
99
|
+
emails: userEmails.concat(parentAndUnverifiedEmails),
|
|
100
|
+
};
|
|
99
101
|
}
|
|
100
102
|
|
|
101
103
|
doesEmailHaveAccess(details: MemberDetails, email: string) {
|
|
102
|
-
const {emails} = this.getMemberAccessEmails(details)
|
|
103
|
-
return emails.includes(email)
|
|
104
|
+
const { emails } = this.getMemberAccessEmails(details);
|
|
105
|
+
return emails.includes(email);
|
|
104
106
|
}
|
|
105
107
|
|
|
106
108
|
async onDeleteMember(member: MemberWithRegistrations) {
|
|
107
109
|
for (const u of member.users) {
|
|
108
|
-
console.log(
|
|
109
|
-
await this.unlinkUser(u, member)
|
|
110
|
+
console.log('Unlinking user ' + u.email + ' from deleted member ' + member.id);
|
|
111
|
+
await this.unlinkUser(u, member);
|
|
110
112
|
}
|
|
111
113
|
}
|
|
112
114
|
|
|
113
115
|
async getResponsibilitiesForMembers(memberIds: string[]) {
|
|
114
116
|
const rows = await SQL.select()
|
|
115
117
|
.from(SQL.table(MemberResponsibilityRecord.table))
|
|
116
|
-
.where(SQL.column(
|
|
117
|
-
.where(SQL.column(
|
|
118
|
+
.where(SQL.column('memberId'), memberIds)
|
|
119
|
+
.where(SQL.column('endDate'), null)
|
|
118
120
|
.fetch();
|
|
119
121
|
|
|
120
|
-
return MemberResponsibilityRecord.fromRows(rows, MemberResponsibilityRecord.table)
|
|
122
|
+
return MemberResponsibilityRecord.fromRows(rows, MemberResponsibilityRecord.table);
|
|
121
123
|
}
|
|
122
124
|
|
|
123
125
|
async updateInheritedPermissions(user: User) {
|
|
124
|
-
const responsibilities = user.memberId ? (await this.getResponsibilitiesForMembers([user.memberId])) : []
|
|
126
|
+
const responsibilities = user.memberId ? (await this.getResponsibilitiesForMembers([user.memberId])) : [];
|
|
125
127
|
|
|
126
128
|
// Check if the member has active registrations
|
|
127
129
|
// otherwise -> do not inherit any permissions
|
|
128
130
|
|
|
129
|
-
user.permissions = user.permissions ?? UserPermissions.create({})
|
|
131
|
+
user.permissions = user.permissions ?? UserPermissions.create({});
|
|
130
132
|
|
|
131
133
|
// Group responsibilities by organization
|
|
132
|
-
const responsibilitiesByOrganization: Map<string|null, MemberResponsibilityRecord[]> = new Map()
|
|
134
|
+
const responsibilitiesByOrganization: Map<string | null, MemberResponsibilityRecord[]> = new Map();
|
|
133
135
|
|
|
134
|
-
responsibilitiesByOrganization.set(null, [])
|
|
136
|
+
responsibilitiesByOrganization.set(null, []);
|
|
135
137
|
|
|
136
138
|
for (const organizationId of user.permissions.organizationPermissions.keys()) {
|
|
137
139
|
// Make sure we reset responsibilities for organizations that are not in the list
|
|
138
|
-
responsibilitiesByOrganization.set(organizationId, [])
|
|
140
|
+
responsibilitiesByOrganization.set(organizationId, []);
|
|
139
141
|
}
|
|
140
142
|
|
|
141
143
|
for (const responsibility of responsibilities) {
|
|
142
|
-
const v = responsibilitiesByOrganization.get(responsibility.organizationId) ?? []
|
|
143
|
-
responsibilitiesByOrganization.set(responsibility.organizationId, v)
|
|
144
|
-
v.push(responsibility)
|
|
144
|
+
const v = responsibilitiesByOrganization.get(responsibility.organizationId) ?? [];
|
|
145
|
+
responsibilitiesByOrganization.set(responsibility.organizationId, v);
|
|
146
|
+
v.push(responsibility);
|
|
145
147
|
}
|
|
146
148
|
|
|
147
149
|
for (const organizationId of responsibilitiesByOrganization.keys()) {
|
|
148
150
|
if (organizationId === null) {
|
|
149
151
|
const patch = user.permissions.convertPlatformPatch(
|
|
150
152
|
Permissions.patch({
|
|
151
|
-
responsibilities: (responsibilitiesByOrganization.get(organizationId) ?? []).map(r => r.getBaseStructure()) as any
|
|
152
|
-
})
|
|
153
|
-
)
|
|
154
|
-
user.permissions = user.permissions.patch(patch)
|
|
155
|
-
}
|
|
153
|
+
responsibilities: (responsibilitiesByOrganization.get(organizationId) ?? []).map(r => r.getBaseStructure()) as any,
|
|
154
|
+
}),
|
|
155
|
+
);
|
|
156
|
+
user.permissions = user.permissions.patch(patch);
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
156
159
|
const patch = user.permissions.convertPatch(
|
|
157
160
|
Permissions.patch({
|
|
158
|
-
responsibilities: (responsibilitiesByOrganization.get(organizationId) ?? []).map(r => r.getBaseStructure()) as any
|
|
161
|
+
responsibilities: (responsibilitiesByOrganization.get(organizationId) ?? []).map(r => r.getBaseStructure()) as any,
|
|
159
162
|
}),
|
|
160
|
-
organizationId
|
|
161
|
-
)
|
|
162
|
-
user.permissions = user.permissions.patch(patch)
|
|
163
|
+
organizationId,
|
|
164
|
+
);
|
|
165
|
+
user.permissions = user.permissions.patch(patch);
|
|
163
166
|
}
|
|
164
|
-
|
|
165
167
|
}
|
|
166
168
|
|
|
167
169
|
// Platform permissions
|
|
168
|
-
user.permissions.clearEmptyPermissions()
|
|
170
|
+
user.permissions.clearEmptyPermissions();
|
|
169
171
|
|
|
170
172
|
if (user.permissions.isEmpty) {
|
|
171
173
|
user.permissions = null;
|
|
172
174
|
}
|
|
173
175
|
|
|
174
|
-
await user.save()
|
|
176
|
+
await user.save();
|
|
175
177
|
}
|
|
176
178
|
|
|
177
179
|
async unlinkUser(user: User, member: MemberWithRegistrations) {
|
|
178
|
-
console.log(
|
|
179
|
-
await Member.users.reverse(
|
|
180
|
+
console.log('Removing access for ' + user.id + ' to member ' + member.id);
|
|
181
|
+
await Member.users.reverse('members').unlink(user, member);
|
|
180
182
|
|
|
181
183
|
if (user.memberId === member.id) {
|
|
182
184
|
user.memberId = null;
|
|
183
|
-
await user.save()
|
|
185
|
+
await user.save();
|
|
184
186
|
}
|
|
185
187
|
|
|
186
188
|
// Update model relation to correct response
|
|
187
|
-
const existingIndex = member.users.findIndex(u => u.id === user.id)
|
|
189
|
+
const existingIndex = member.users.findIndex(u => u.id === user.id);
|
|
188
190
|
if (existingIndex !== -1) {
|
|
189
|
-
member.users.splice(existingIndex, 1)
|
|
191
|
+
member.users.splice(existingIndex, 1);
|
|
190
192
|
}
|
|
191
193
|
|
|
192
|
-
await this.updateInheritedPermissions(user)
|
|
194
|
+
await this.updateInheritedPermissions(user);
|
|
193
195
|
}
|
|
194
196
|
|
|
195
197
|
async linkUser(email: string, member: MemberWithRegistrations, asParent: boolean, updateNameIfEqual = true) {
|
|
196
|
-
console.log('Linking user', email, 'to member', member.id, 'as parent', asParent, 'update name if equal', updateNameIfEqual)
|
|
198
|
+
console.log('Linking user', email, 'to member', member.id, 'as parent', asParent, 'update name if equal', updateNameIfEqual);
|
|
197
199
|
|
|
198
|
-
let user = member.users.find(u => u.email.toLocaleLowerCase() === email.toLocaleLowerCase()) ?? await User.getForAuthentication(member.organizationId, email, {allowWithoutAccount: true})
|
|
200
|
+
let user = member.users.find(u => u.email.toLocaleLowerCase() === email.toLocaleLowerCase()) ?? await User.getForAuthentication(member.organizationId, email, { allowWithoutAccount: true });
|
|
199
201
|
|
|
200
202
|
if (user) {
|
|
201
|
-
//console.log("Giving an existing user access to a member: " + user.id + ' - ' + member.id)
|
|
203
|
+
// console.log("Giving an existing user access to a member: " + user.id + ' - ' + member.id)
|
|
202
204
|
if (!asParent) {
|
|
203
205
|
if (user.memberId && user.memberId !== member.id) {
|
|
204
|
-
console.error('Found conflicting user with multiple members', user.id, 'members', user.memberId, 'to', member.id)
|
|
205
|
-
|
|
206
|
-
const otherMember = await Member.getWithRegistrations(user.memberId)
|
|
206
|
+
console.error('Found conflicting user with multiple members', user.id, 'members', user.memberId, 'to', member.id);
|
|
207
|
+
|
|
208
|
+
const otherMember = await Member.getWithRegistrations(user.memberId);
|
|
207
209
|
|
|
208
210
|
if (otherMember) {
|
|
209
211
|
if (otherMember.registrations.length > 0 && member.registrations.length === 0) {
|
|
210
212
|
// Choose the other member
|
|
211
213
|
// don't make changes
|
|
212
|
-
console.error('Resolved to current member - no changes made')
|
|
213
|
-
return
|
|
214
|
+
console.error('Resolved to current member - no changes made');
|
|
215
|
+
return;
|
|
214
216
|
}
|
|
215
217
|
|
|
216
|
-
const responsibilities = await this.getResponsibilitiesForMembers([otherMember.id, member.id])
|
|
217
|
-
const responsibilitiesOther = responsibilities.filter(r => r.memberId === otherMember.id)
|
|
218
|
-
const responsibilitiesCurrent = responsibilities.filter(r => r.memberId === member.id)
|
|
218
|
+
const responsibilities = await this.getResponsibilitiesForMembers([otherMember.id, member.id]);
|
|
219
|
+
const responsibilitiesOther = responsibilities.filter(r => r.memberId === otherMember.id);
|
|
220
|
+
const responsibilitiesCurrent = responsibilities.filter(r => r.memberId === member.id);
|
|
219
221
|
|
|
220
222
|
if (responsibilitiesOther.length >= responsibilitiesCurrent.length) {
|
|
221
|
-
console.error('Resolved to current member because of more responsibilities - no changes made')
|
|
222
|
-
return
|
|
223
|
+
console.error('Resolved to current member because of more responsibilities - no changes made');
|
|
224
|
+
return;
|
|
223
225
|
}
|
|
224
226
|
}
|
|
225
227
|
}
|
|
226
228
|
|
|
227
229
|
if (updateNameIfEqual) {
|
|
228
|
-
user.firstName = member.details.firstName
|
|
229
|
-
user.lastName = member.details.lastName
|
|
230
|
+
user.firstName = member.details.firstName;
|
|
231
|
+
user.lastName = member.details.lastName;
|
|
230
232
|
}
|
|
231
233
|
user.memberId = member.id;
|
|
232
|
-
await this.updateInheritedPermissions(user)
|
|
233
|
-
}
|
|
234
|
+
await this.updateInheritedPermissions(user);
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
234
237
|
if (user.memberId === member.id) {
|
|
235
238
|
// Unlink: parents are never 'equal' to the member
|
|
236
239
|
user.memberId = null;
|
|
237
|
-
await this.updateInheritedPermissions(user)
|
|
240
|
+
await this.updateInheritedPermissions(user);
|
|
238
241
|
}
|
|
239
242
|
|
|
240
243
|
if (!user.firstName && !user.lastName) {
|
|
241
|
-
const parents = member.details.parents.filter(p => p.email === email)
|
|
244
|
+
const parents = member.details.parents.filter(p => p.email === email);
|
|
242
245
|
if (parents.length === 1) {
|
|
243
246
|
if (updateNameIfEqual) {
|
|
244
|
-
user.firstName = parents[0].firstName
|
|
245
|
-
user.lastName = parents[0].lastName
|
|
247
|
+
user.firstName = parents[0].firstName;
|
|
248
|
+
user.lastName = parents[0].lastName;
|
|
246
249
|
}
|
|
247
|
-
await user.save()
|
|
250
|
+
await user.save();
|
|
248
251
|
}
|
|
249
252
|
}
|
|
250
253
|
|
|
251
254
|
if (user.firstName === member.details.firstName && user.lastName === member.details.lastName) {
|
|
252
255
|
user.firstName = null;
|
|
253
256
|
user.lastName = null;
|
|
254
|
-
await user.save()
|
|
257
|
+
await user.save();
|
|
255
258
|
}
|
|
256
259
|
}
|
|
257
|
-
}
|
|
260
|
+
}
|
|
261
|
+
else {
|
|
258
262
|
// Create a new placeholder user
|
|
259
|
-
user = new User()
|
|
260
|
-
user.organizationId = member.organizationId
|
|
261
|
-
user.email = email
|
|
263
|
+
user = new User();
|
|
264
|
+
user.organizationId = member.organizationId;
|
|
265
|
+
user.email = email;
|
|
262
266
|
|
|
263
267
|
if (!asParent) {
|
|
264
268
|
if (updateNameIfEqual) {
|
|
265
|
-
user.firstName = member.details.firstName
|
|
266
|
-
user.lastName = member.details.lastName
|
|
269
|
+
user.firstName = member.details.firstName;
|
|
270
|
+
user.lastName = member.details.lastName;
|
|
267
271
|
}
|
|
268
272
|
user.memberId = member.id;
|
|
269
|
-
await this.updateInheritedPermissions(user)
|
|
270
|
-
}
|
|
271
|
-
|
|
273
|
+
await this.updateInheritedPermissions(user);
|
|
274
|
+
}
|
|
275
|
+
else {
|
|
276
|
+
const parents = member.details.parents.filter(p => p.email === email);
|
|
272
277
|
if (parents.length === 1) {
|
|
273
278
|
if (updateNameIfEqual) {
|
|
274
|
-
user.firstName = parents[0].firstName
|
|
275
|
-
user.lastName = parents[0].lastName
|
|
279
|
+
user.firstName = parents[0].firstName;
|
|
280
|
+
user.lastName = parents[0].lastName;
|
|
276
281
|
}
|
|
277
282
|
}
|
|
278
283
|
|
|
@@ -281,18 +286,18 @@ export class MemberUserSyncerStatic {
|
|
|
281
286
|
user.lastName = null;
|
|
282
287
|
}
|
|
283
288
|
|
|
284
|
-
await user.save()
|
|
289
|
+
await user.save();
|
|
285
290
|
}
|
|
286
291
|
|
|
287
|
-
console.log(
|
|
292
|
+
console.log('Created new (placeholder) user that has access to a member: ' + user.id);
|
|
288
293
|
}
|
|
289
294
|
|
|
290
295
|
// Update model relation to correct response
|
|
291
296
|
if (!member.users.find(u => u.id === user.id)) {
|
|
292
|
-
await Member.users.reverse(
|
|
293
|
-
member.users.push(user)
|
|
297
|
+
await Member.users.reverse('members').link(user, [member]);
|
|
298
|
+
member.users.push(user);
|
|
294
299
|
}
|
|
295
300
|
}
|
|
296
301
|
}
|
|
297
302
|
|
|
298
|
-
export const MemberUserSyncer = new MemberUserSyncerStatic()
|
|
303
|
+
export const MemberUserSyncer = new MemberUserSyncerStatic();
|
|
@@ -1,35 +1,34 @@
|
|
|
1
|
-
import { SimpleError } from
|
|
2
|
-
import { BalanceItem, Member, MemberPlatformMembership, Platform } from
|
|
3
|
-
import { SQL, SQLOrderBy, SQLWhereSign } from
|
|
4
|
-
import { BalanceItemRelation, BalanceItemRelationType, BalanceItemType } from
|
|
5
|
-
import { Formatter } from
|
|
1
|
+
import { SimpleError } from '@simonbackx/simple-errors';
|
|
2
|
+
import { BalanceItem, Member, MemberPlatformMembership, Platform } from '@stamhoofd/models';
|
|
3
|
+
import { SQL, SQLOrderBy, SQLWhereSign } from '@stamhoofd/sql';
|
|
4
|
+
import { BalanceItemRelation, BalanceItemRelationType, BalanceItemType } from '@stamhoofd/structures';
|
|
5
|
+
import { Formatter } from '@stamhoofd/utility';
|
|
6
6
|
|
|
7
7
|
export const MembershipCharger = {
|
|
8
8
|
async charge() {
|
|
9
|
-
console.log('Charging memberships...')
|
|
10
|
-
|
|
9
|
+
console.log('Charging memberships...');
|
|
10
|
+
|
|
11
11
|
// Loop all
|
|
12
|
-
let lastId =
|
|
13
|
-
const platform = await Platform.getShared()
|
|
14
|
-
const chargeVia = platform.membershipOrganizationId
|
|
12
|
+
let lastId = '';
|
|
13
|
+
const platform = await Platform.getShared();
|
|
14
|
+
const chargeVia = platform.membershipOrganizationId;
|
|
15
15
|
|
|
16
16
|
if (!chargeVia) {
|
|
17
17
|
throw new SimpleError({
|
|
18
18
|
code: 'missing_membership_organization',
|
|
19
19
|
message: 'Missing membershipOrganizationId',
|
|
20
|
-
human: 'Er is geen lokale groep verantwoordelijk voor de aanrekening van aansluitingen geconfigureerd'
|
|
21
|
-
})
|
|
20
|
+
human: 'Er is geen lokale groep verantwoordelijk voor de aanrekening van aansluitingen geconfigureerd',
|
|
21
|
+
});
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
function getType(id: string) {
|
|
25
|
-
return platform.config.membershipTypes.find(t => t.id === id)
|
|
25
|
+
return platform.config.membershipTypes.find(t => t.id === id);
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
let createdCount = 0;
|
|
29
29
|
let createdPrice = 0;
|
|
30
30
|
const chunkSize = 100;
|
|
31
31
|
|
|
32
|
-
// eslint-disable-next-line no-constant-condition
|
|
33
32
|
while (true) {
|
|
34
33
|
const memberships = await MemberPlatformMembership.select()
|
|
35
34
|
.where('id', SQLWhereSign.Greater, lastId)
|
|
@@ -40,18 +39,18 @@ export const MembershipCharger = {
|
|
|
40
39
|
.orderBy(
|
|
41
40
|
new SQLOrderBy({
|
|
42
41
|
column: SQL.column('id'),
|
|
43
|
-
direction: 'ASC'
|
|
44
|
-
})
|
|
42
|
+
direction: 'ASC',
|
|
43
|
+
}),
|
|
45
44
|
)
|
|
46
45
|
.fetch();
|
|
47
|
-
|
|
46
|
+
|
|
48
47
|
if (memberships.length === 0) {
|
|
49
48
|
break;
|
|
50
49
|
}
|
|
51
50
|
|
|
52
|
-
const memberIds = Formatter.uniqueArray(memberships.map(m => m.memberId))
|
|
53
|
-
const members = await Member.getByIDs(...memberIds)
|
|
54
|
-
const createdBalanceItems: BalanceItem[] = []
|
|
51
|
+
const memberIds = Formatter.uniqueArray(memberships.map(m => m.memberId));
|
|
52
|
+
const members = await Member.getByIDs(...memberIds);
|
|
53
|
+
const createdBalanceItems: BalanceItem[] = [];
|
|
55
54
|
|
|
56
55
|
for (const membership of memberships) {
|
|
57
56
|
// charge
|
|
@@ -61,7 +60,7 @@ export const MembershipCharger = {
|
|
|
61
60
|
|
|
62
61
|
const type = getType(membership.membershipTypeId);
|
|
63
62
|
if (!type) {
|
|
64
|
-
console.error('Unknown membership type id ', membership.membershipTypeId)
|
|
63
|
+
console.error('Unknown membership type id ', membership.membershipTypeId);
|
|
65
64
|
continue;
|
|
66
65
|
}
|
|
67
66
|
|
|
@@ -69,83 +68,83 @@ export const MembershipCharger = {
|
|
|
69
68
|
continue;
|
|
70
69
|
}
|
|
71
70
|
|
|
72
|
-
const member = members.find(m => m.id === membership.memberId)
|
|
71
|
+
const member = members.find(m => m.id === membership.memberId);
|
|
73
72
|
|
|
74
73
|
if (!member) {
|
|
75
|
-
console.error('Unexpected missing member id ', membership.memberId, 'for membership', membership.id)
|
|
74
|
+
console.error('Unexpected missing member id ', membership.memberId, 'for membership', membership.id);
|
|
76
75
|
continue;
|
|
77
76
|
}
|
|
78
77
|
|
|
79
78
|
// Force price update (required because could have changed - especially for free memberships in combination with deletes)
|
|
80
79
|
try {
|
|
81
|
-
await membership.calculatePrice(member)
|
|
82
|
-
}
|
|
83
|
-
|
|
80
|
+
await membership.calculatePrice(member);
|
|
81
|
+
}
|
|
82
|
+
catch (e) {
|
|
83
|
+
console.error('Failed to update price for membership. Not charged.', membership.id, e);
|
|
84
84
|
continue;
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
const balanceItem = new BalanceItem();
|
|
88
|
-
balanceItem.unitPrice = membership.price
|
|
89
|
-
balanceItem.amount = 1
|
|
90
|
-
balanceItem.description = Formatter.dateNumber(membership.startDate, true) +
|
|
88
|
+
balanceItem.unitPrice = membership.price;
|
|
89
|
+
balanceItem.amount = 1;
|
|
90
|
+
balanceItem.description = Formatter.dateNumber(membership.startDate, true) + ' tot ' + Formatter.dateNumber(membership.expireDate ?? membership.endDate, true);
|
|
91
91
|
balanceItem.relations = new Map([
|
|
92
92
|
[
|
|
93
|
-
BalanceItemRelationType.Member,
|
|
93
|
+
BalanceItemRelationType.Member,
|
|
94
94
|
BalanceItemRelation.create({
|
|
95
95
|
id: member.id,
|
|
96
|
-
name: member.details.name
|
|
97
|
-
})
|
|
96
|
+
name: member.details.name,
|
|
97
|
+
}),
|
|
98
98
|
],
|
|
99
99
|
[
|
|
100
|
-
BalanceItemRelationType.MembershipType,
|
|
100
|
+
BalanceItemRelationType.MembershipType,
|
|
101
101
|
BalanceItemRelation.create({
|
|
102
102
|
id: type.id,
|
|
103
|
-
name: type.name
|
|
104
|
-
})
|
|
105
|
-
]
|
|
106
|
-
])
|
|
103
|
+
name: type.name,
|
|
104
|
+
}),
|
|
105
|
+
],
|
|
106
|
+
]);
|
|
107
107
|
|
|
108
|
-
balanceItem.type = BalanceItemType.PlatformMembership
|
|
109
|
-
balanceItem.organizationId = chargeVia
|
|
110
|
-
balanceItem.payingOrganizationId = membership.organizationId
|
|
108
|
+
balanceItem.type = BalanceItemType.PlatformMembership;
|
|
109
|
+
balanceItem.organizationId = chargeVia;
|
|
110
|
+
balanceItem.payingOrganizationId = membership.organizationId;
|
|
111
111
|
|
|
112
112
|
await balanceItem.save();
|
|
113
113
|
membership.balanceItemId = balanceItem.id;
|
|
114
114
|
membership.maximumFreeAmount = membership.freeAmount;
|
|
115
|
-
await membership.save()
|
|
115
|
+
await membership.save();
|
|
116
116
|
|
|
117
|
-
createdBalanceItems.push(balanceItem)
|
|
117
|
+
createdBalanceItems.push(balanceItem);
|
|
118
118
|
|
|
119
119
|
createdCount += 1;
|
|
120
|
-
createdPrice += membership.price
|
|
120
|
+
createdPrice += membership.price;
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
-
await BalanceItem.updateOutstanding(createdBalanceItems)
|
|
123
|
+
await BalanceItem.updateOutstanding(createdBalanceItems);
|
|
124
124
|
|
|
125
125
|
if (memberships.length < chunkSize) {
|
|
126
126
|
break;
|
|
127
127
|
}
|
|
128
|
-
|
|
128
|
+
|
|
129
129
|
const z = lastId;
|
|
130
130
|
lastId = memberships[memberships.length - 1].id;
|
|
131
131
|
|
|
132
132
|
if (lastId === z) {
|
|
133
|
-
throw new Error('Unexpected infinite loop found in MembershipCharger')
|
|
133
|
+
throw new Error('Unexpected infinite loop found in MembershipCharger');
|
|
134
134
|
}
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
-
console.log('Charged ' + Formatter.integer(createdCount) +' memberships, for a total value of ' + Formatter.price(createdPrice))
|
|
137
|
+
console.log('Charged ' + Formatter.integer(createdCount) + ' memberships, for a total value of ' + Formatter.price(createdPrice));
|
|
138
138
|
},
|
|
139
139
|
|
|
140
140
|
async updatePrices(organizationId?: string) {
|
|
141
|
-
console.log('Update prices...')
|
|
142
|
-
|
|
141
|
+
console.log('Update prices...');
|
|
142
|
+
|
|
143
143
|
// Loop all
|
|
144
|
-
let lastId =
|
|
144
|
+
let lastId = '';
|
|
145
145
|
let createdCount = 0;
|
|
146
146
|
const chunkSize = 100;
|
|
147
147
|
|
|
148
|
-
// eslint-disable-next-line no-constant-condition
|
|
149
148
|
while (true) {
|
|
150
149
|
const q = MemberPlatformMembership.select()
|
|
151
150
|
.where('id', SQLWhereSign.Greater, lastId)
|
|
@@ -153,58 +152,59 @@ export const MembershipCharger = {
|
|
|
153
152
|
.where('deletedAt', null);
|
|
154
153
|
|
|
155
154
|
if (organizationId) {
|
|
156
|
-
q.where('organizationId', organizationId)
|
|
155
|
+
q.where('organizationId', organizationId);
|
|
157
156
|
}
|
|
158
|
-
|
|
157
|
+
|
|
159
158
|
const memberships = await q
|
|
160
159
|
.limit(chunkSize)
|
|
161
160
|
.orderBy(
|
|
162
161
|
new SQLOrderBy({
|
|
163
162
|
column: SQL.column('id'),
|
|
164
|
-
direction: 'ASC'
|
|
165
|
-
})
|
|
163
|
+
direction: 'ASC',
|
|
164
|
+
}),
|
|
166
165
|
)
|
|
167
166
|
.fetch();
|
|
168
|
-
|
|
167
|
+
|
|
169
168
|
if (memberships.length === 0) {
|
|
170
169
|
break;
|
|
171
170
|
}
|
|
172
171
|
|
|
173
|
-
const memberIds = Formatter.uniqueArray(memberships.map(m => m.memberId))
|
|
174
|
-
const members = await Member.getByIDs(...memberIds)
|
|
172
|
+
const memberIds = Formatter.uniqueArray(memberships.map(m => m.memberId));
|
|
173
|
+
const members = await Member.getByIDs(...memberIds);
|
|
175
174
|
|
|
176
175
|
for (const membership of memberships) {
|
|
177
|
-
const member = members.find(m => m.id === membership.memberId)
|
|
176
|
+
const member = members.find(m => m.id === membership.memberId);
|
|
178
177
|
|
|
179
178
|
if (!member) {
|
|
180
|
-
console.error('Unexpected missing member id ', membership.memberId, 'for membership', membership.id)
|
|
179
|
+
console.error('Unexpected missing member id ', membership.memberId, 'for membership', membership.id);
|
|
181
180
|
continue;
|
|
182
181
|
}
|
|
183
182
|
|
|
184
183
|
// Force price update (required because could have changed - especially for free memberships in combination with deletes)
|
|
185
184
|
try {
|
|
186
|
-
await membership.calculatePrice(member)
|
|
187
|
-
await membership.save()
|
|
188
|
-
}
|
|
189
|
-
|
|
185
|
+
await membership.calculatePrice(member);
|
|
186
|
+
await membership.save();
|
|
187
|
+
}
|
|
188
|
+
catch (e) {
|
|
189
|
+
console.error('Failed to update price for membership', membership.id, e);
|
|
190
190
|
continue;
|
|
191
191
|
}
|
|
192
|
-
console.log('Updated price for membership', membership.id, membership.price)
|
|
192
|
+
console.log('Updated price for membership', membership.id, membership.price);
|
|
193
193
|
createdCount += 1;
|
|
194
194
|
}
|
|
195
195
|
|
|
196
196
|
if (memberships.length < chunkSize) {
|
|
197
197
|
break;
|
|
198
198
|
}
|
|
199
|
-
|
|
199
|
+
|
|
200
200
|
const z = lastId;
|
|
201
201
|
lastId = memberships[memberships.length - 1].id;
|
|
202
202
|
|
|
203
203
|
if (lastId === z) {
|
|
204
|
-
throw new Error('Unexpected infinite loop found in MembershipCharger')
|
|
204
|
+
throw new Error('Unexpected infinite loop found in MembershipCharger');
|
|
205
205
|
}
|
|
206
206
|
}
|
|
207
207
|
|
|
208
|
-
console.log('Updated prices of ' + Formatter.integer(createdCount) +' memberships')
|
|
209
|
-
}
|
|
208
|
+
console.log('Updated prices of ' + Formatter.integer(createdCount) + ' memberships');
|
|
209
|
+
},
|
|
210
210
|
};
|