@stamhoofd/backend 2.90.2 → 2.91.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/package.json +10 -10
- package/src/audit-logs/ModelLogger.ts +0 -1
- package/src/crons/endFunctionsOfUsersWithoutRegistration.ts +14 -0
- package/src/endpoints/admin/organizations/GetOrganizationsEndpoint.ts +2 -0
- package/src/endpoints/global/email/CreateEmailEndpoint.ts +2 -3
- package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.ts +6 -4
- package/src/endpoints/global/platform/PatchPlatformEnpoint.ts +9 -7
- package/src/endpoints/global/registration/RegisterMembersEndpoint.ts +112 -105
- package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/organization/SetUitpasClientCredentialsEndpoint.ts +5 -5
- package/src/endpoints/organization/dashboard/registration-periods/PatchOrganizationRegistrationPeriodsEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/webshops/SearchUitpasEventsEndpoint.ts +1 -1
- package/src/endpoints/organization/webshops/PlaceOrderEndpoint.ts +2 -2
- package/src/helpers/AdminPermissionChecker.ts +0 -5
- package/src/helpers/FlagMomentCleanup.ts +13 -1
- package/src/helpers/GroupedThrottledQueue.ts +5 -3
- package/src/helpers/PeriodHelper.ts +10 -137
- package/src/helpers/SetupStepUpdater.ts +54 -7
- package/src/helpers/UitpasTokenRepository.ts +3 -3
- package/src/seeds/1750090030-records-configuration.ts +5 -1
- package/src/services/BalanceItemService.ts +12 -7
- package/src/services/DocumentService.ts +0 -1
- package/src/services/RegistrationService.ts +30 -1
- package/src/services/uitpas/UitpasService.ts +1 -1
- package/src/services/uitpas/cancelTicketSales.ts +1 -1
- package/src/services/uitpas/checkPermissionsFor.ts +9 -9
- package/src/services/uitpas/checkUitpasNumbers.ts +2 -2
- package/src/services/uitpas/getSocialTariffForEvent.ts +4 -4
- package/src/services/uitpas/getSocialTariffForUitpasNumbers.ts +5 -5
- package/src/services/uitpas/registerTicketSales.ts +4 -4
- package/src/services/uitpas/searchUitpasEvents.ts +3 -3
- package/src/services/uitpas/searchUitpasOrganizers.ts +3 -3
- package/src/sql-filters/members.ts +1 -1
- package/src/sql-filters/organizations.ts +52 -0
- package/tests/e2e/register.test.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stamhoofd/backend",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.91.0",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -45,14 +45,14 @@
|
|
|
45
45
|
"@simonbackx/simple-encoding": "2.22.0",
|
|
46
46
|
"@simonbackx/simple-endpoints": "1.20.1",
|
|
47
47
|
"@simonbackx/simple-logging": "^1.0.1",
|
|
48
|
-
"@stamhoofd/backend-i18n": "2.
|
|
49
|
-
"@stamhoofd/backend-middleware": "2.
|
|
50
|
-
"@stamhoofd/email": "2.
|
|
51
|
-
"@stamhoofd/models": "2.
|
|
52
|
-
"@stamhoofd/queues": "2.
|
|
53
|
-
"@stamhoofd/sql": "2.
|
|
54
|
-
"@stamhoofd/structures": "2.
|
|
55
|
-
"@stamhoofd/utility": "2.
|
|
48
|
+
"@stamhoofd/backend-i18n": "2.91.0",
|
|
49
|
+
"@stamhoofd/backend-middleware": "2.91.0",
|
|
50
|
+
"@stamhoofd/email": "2.91.0",
|
|
51
|
+
"@stamhoofd/models": "2.91.0",
|
|
52
|
+
"@stamhoofd/queues": "2.91.0",
|
|
53
|
+
"@stamhoofd/sql": "2.91.0",
|
|
54
|
+
"@stamhoofd/structures": "2.91.0",
|
|
55
|
+
"@stamhoofd/utility": "2.91.0",
|
|
56
56
|
"archiver": "^7.0.1",
|
|
57
57
|
"axios": "^1.8.2",
|
|
58
58
|
"cookie": "^0.7.0",
|
|
@@ -70,5 +70,5 @@
|
|
|
70
70
|
"publishConfig": {
|
|
71
71
|
"access": "public"
|
|
72
72
|
},
|
|
73
|
-
"gitHead": "
|
|
73
|
+
"gitHead": "37ff6e89f07320c0736d32c9b911c8c1c35dc421"
|
|
74
74
|
}
|
|
@@ -193,7 +193,6 @@ export class ModelLogger<ModelType extends typeof Model, M extends InstanceType<
|
|
|
193
193
|
|
|
194
194
|
if (log.patchList.length === 0 && !log.description) {
|
|
195
195
|
// No changes or all skipped
|
|
196
|
-
console.log('No changes after secundary filtering');
|
|
197
196
|
return false;
|
|
198
197
|
}
|
|
199
198
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { registerCron } from '@stamhoofd/crons';
|
|
2
2
|
import { FlagMomentCleanup } from '../helpers/FlagMomentCleanup';
|
|
3
|
+
import { Platform, RegistrationPeriod } from '@stamhoofd/models';
|
|
3
4
|
|
|
4
5
|
// Only delete responsibilities when the server is running during a month change.
|
|
5
6
|
// Chances are almost zero that we reboot during a month change
|
|
@@ -19,6 +20,19 @@ export async function endFunctionsOfUsersWithoutRegistration() {
|
|
|
19
20
|
return;
|
|
20
21
|
}
|
|
21
22
|
|
|
23
|
+
// Check if the current period is active for more than 2 months
|
|
24
|
+
const platform = await Platform.getShared();
|
|
25
|
+
const period = await RegistrationPeriod.getByID(platform.periodId);
|
|
26
|
+
if (!period) {
|
|
27
|
+
console.warn('No active registration period found, skipping cleanup.');
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (period.startDate > new Date(Date.now() - 1000 * 60 * 60 * 24 * 55)) {
|
|
32
|
+
console.warn('Current registration period is less than 2 months old, skipping cleanup.');
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
22
36
|
await FlagMomentCleanup.endFunctionsOfUsersWithoutRegistration();
|
|
23
37
|
lastCleanupYear = currentYear;
|
|
24
38
|
lastCleanupMonth = currentMonth;
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { Decoder } from '@simonbackx/simple-encoding';
|
|
2
2
|
import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
|
|
3
|
-
import { Email,
|
|
4
|
-
import { EmailPreview, EmailStatus, Email as EmailStruct,
|
|
3
|
+
import { Email, RateLimiter } from '@stamhoofd/models';
|
|
4
|
+
import { EmailPreview, EmailStatus, Email as EmailStruct, EmailTemplate as EmailTemplateStruct } from '@stamhoofd/structures';
|
|
5
5
|
|
|
6
6
|
import { Context } from '../../../helpers/Context';
|
|
7
|
-
import { SQL } from '@stamhoofd/sql';
|
|
8
7
|
|
|
9
8
|
type Params = Record<string, never>;
|
|
10
9
|
type Query = undefined;
|
|
@@ -3,7 +3,7 @@ import { AutoEncoderPatchType, ConvertArrayToPatchableArray, Decoder, isEmptyPat
|
|
|
3
3
|
import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
|
|
4
4
|
import { SimpleError } from '@simonbackx/simple-errors';
|
|
5
5
|
import { AuditLog, BalanceItem, Document, Group, Member, MemberFactory, MemberPlatformMembership, MemberResponsibilityRecord, MemberWithRegistrations, mergeTwoMembers, Organization, Platform, RateLimiter, Registration, RegistrationPeriod, User } from '@stamhoofd/models';
|
|
6
|
-
import { AuditLogReplacement, AuditLogReplacementType, AuditLogSource, AuditLogType, EmergencyContact, GroupType, MemberDetails, MemberResponsibility, MembersBlob, MemberWithRegistrationsBlob, Parent, PermissionLevel } from '@stamhoofd/structures';
|
|
6
|
+
import { AuditLogReplacement, AuditLogReplacementType, AuditLogSource, AuditLogType, EmergencyContact, GroupType, MemberDetails, MemberResponsibility, MembersBlob, MemberWithRegistrationsBlob, Parent, PermissionLevel, SetupStepType } from '@stamhoofd/structures';
|
|
7
7
|
import { Formatter } from '@stamhoofd/utility';
|
|
8
8
|
|
|
9
9
|
import { Email } from '@stamhoofd/email';
|
|
@@ -317,7 +317,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
317
317
|
throw new SimpleError({
|
|
318
318
|
code: 'invalid_field',
|
|
319
319
|
message: 'Invalid organization',
|
|
320
|
-
human:
|
|
320
|
+
human: platformResponsibility ? $t('ec6a555e-6bb1-4b5f-b17e-38eaa8a478b5') : $t('d41cdbe3-57e3-4a2e-83bc-cb9e65c9c840'),
|
|
321
321
|
});
|
|
322
322
|
}
|
|
323
323
|
|
|
@@ -688,7 +688,9 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
688
688
|
}
|
|
689
689
|
|
|
690
690
|
if (shouldUpdateSetupSteps && organization) {
|
|
691
|
-
SetupStepUpdater.updateForOrganization(organization
|
|
691
|
+
SetupStepUpdater.updateForOrganization(organization, { types: [
|
|
692
|
+
SetupStepType.Responsibilities,
|
|
693
|
+
] }).catch(console.error);
|
|
692
694
|
}
|
|
693
695
|
|
|
694
696
|
return new Response(
|
|
@@ -957,7 +959,7 @@ export class PatchOrganizationMembersEndpoint extends Endpoint<Params, Query, Bo
|
|
|
957
959
|
throw new SimpleError({
|
|
958
960
|
code: 'known_member_missing_rights',
|
|
959
961
|
message: 'Creating known member without sufficient access rights',
|
|
960
|
-
human: $t(`
|
|
962
|
+
human: $t(`510807a1-d4c7-45fa-9e3b-ddc8764d3f6e`, { member: member.details.firstName }),
|
|
961
963
|
statusCode: 400,
|
|
962
964
|
});
|
|
963
965
|
}
|
|
@@ -90,6 +90,10 @@ export class PatchPlatformEndpoint extends Endpoint<
|
|
|
90
90
|
throw Context.auth.error();
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
+
if (request.body.config.organizationLevelRecordsConfiguration) {
|
|
94
|
+
shouldUpdateSetupSteps = true;
|
|
95
|
+
}
|
|
96
|
+
|
|
93
97
|
const newConfig = request.body.config;
|
|
94
98
|
|
|
95
99
|
// Update config
|
|
@@ -100,13 +104,11 @@ export class PatchPlatformEndpoint extends Endpoint<
|
|
|
100
104
|
platform.config = patchObject(platform.config, newConfig);
|
|
101
105
|
const currentConfig: PlatformConfig = platform.config;
|
|
102
106
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
);
|
|
109
|
-
}
|
|
107
|
+
shouldUpdateSetupSteps = shouldUpdateSetupSteps || this.shouldUpdateSetupSteps(
|
|
108
|
+
currentConfig,
|
|
109
|
+
newConfig,
|
|
110
|
+
oldConfig,
|
|
111
|
+
);
|
|
110
112
|
}
|
|
111
113
|
else {
|
|
112
114
|
platform.config = patchObject(platform.config, newConfig);
|
|
@@ -14,6 +14,7 @@ import { Context } from '../../../helpers/Context';
|
|
|
14
14
|
import { StripeHelper } from '../../../helpers/StripeHelper';
|
|
15
15
|
import { BalanceItemService } from '../../../services/BalanceItemService';
|
|
16
16
|
import { RegistrationService } from '../../../services/RegistrationService';
|
|
17
|
+
import { PaymentService } from '../../../services/PaymentService';
|
|
17
18
|
type Params = Record<string, never>;
|
|
18
19
|
type Query = undefined;
|
|
19
20
|
type Body = IDRegisterCheckout;
|
|
@@ -1047,120 +1048,126 @@ export class RegisterMembersEndpoint extends Endpoint<Params, Query, Body, Respo
|
|
|
1047
1048
|
|
|
1048
1049
|
let paymentUrl: string | null = null;
|
|
1049
1050
|
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
else if (payment.method !== PaymentMethod.PointOfSale && payment.method !== PaymentMethod.Unknown) {
|
|
1062
|
-
if (!checkout.redirectUrl || !checkout.cancelUrl) {
|
|
1063
|
-
throw new Error('Should have been caught earlier');
|
|
1051
|
+
try {
|
|
1052
|
+
// Update balance items
|
|
1053
|
+
if (payment.method === PaymentMethod.Transfer) {
|
|
1054
|
+
// Send a small reminder email
|
|
1055
|
+
try {
|
|
1056
|
+
await Registration.sendTransferEmail(user, organization, payment);
|
|
1057
|
+
}
|
|
1058
|
+
catch (e) {
|
|
1059
|
+
console.error('Failed to send transfer email');
|
|
1060
|
+
console.error(e);
|
|
1061
|
+
}
|
|
1064
1062
|
}
|
|
1063
|
+
else if (payment.method !== PaymentMethod.PointOfSale && payment.method !== PaymentMethod.Unknown) {
|
|
1064
|
+
if (!checkout.redirectUrl || !checkout.cancelUrl) {
|
|
1065
|
+
throw new Error('Should have been caught earlier');
|
|
1066
|
+
}
|
|
1065
1067
|
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
});
|
|
1100
|
-
paymentUrl = stripeResult.paymentUrl;
|
|
1101
|
-
}
|
|
1102
|
-
else if (payment.provider === PaymentProvider.Mollie) {
|
|
1103
|
-
// Mollie payment
|
|
1104
|
-
const token = await MollieToken.getTokenFor(organization.id);
|
|
1105
|
-
if (!token) {
|
|
1106
|
-
throw new SimpleError({
|
|
1107
|
-
code: '',
|
|
1108
|
-
message: $t(`b77e1f68-8928-42a2-802b-059fa73bedc3`, { method: PaymentMethodHelper.getName(payment.method) }),
|
|
1068
|
+
const _redirectUrl = new URL(checkout.redirectUrl);
|
|
1069
|
+
_redirectUrl.searchParams.set('paymentId', payment.id);
|
|
1070
|
+
_redirectUrl.searchParams.set('organizationId', organization.id); // makes sure the client uses the token associated with this organization when fetching payment polling status
|
|
1071
|
+
|
|
1072
|
+
const _cancelUrl = new URL(checkout.cancelUrl);
|
|
1073
|
+
_cancelUrl.searchParams.set('paymentId', payment.id);
|
|
1074
|
+
_cancelUrl.searchParams.set('cancel', 'true');
|
|
1075
|
+
_cancelUrl.searchParams.set('organizationId', organization.id); // makes sure the client uses the token associated with this organization when fetching payment polling status
|
|
1076
|
+
|
|
1077
|
+
const redirectUrl = _redirectUrl.href;
|
|
1078
|
+
const cancelUrl = _cancelUrl.href;
|
|
1079
|
+
|
|
1080
|
+
const webhookUrl = 'https://' + organization.getApiHost() + '/v' + Version + '/payments/' + encodeURIComponent(payment.id) + '?exchange=true';
|
|
1081
|
+
|
|
1082
|
+
if (payment.provider === PaymentProvider.Stripe) {
|
|
1083
|
+
const stripeResult = await StripeHelper.createPayment({
|
|
1084
|
+
payment,
|
|
1085
|
+
stripeAccount,
|
|
1086
|
+
redirectUrl,
|
|
1087
|
+
cancelUrl,
|
|
1088
|
+
statementDescriptor: organization.name,
|
|
1089
|
+
metadata: {
|
|
1090
|
+
organization: organization.id,
|
|
1091
|
+
user: user.id,
|
|
1092
|
+
payment: payment.id,
|
|
1093
|
+
},
|
|
1094
|
+
i18n: Context.i18n,
|
|
1095
|
+
lineItems: balanceItemPayments,
|
|
1096
|
+
organization,
|
|
1097
|
+
customer: {
|
|
1098
|
+
name: user.name ?? payMembers[0]?.details.name ?? $t(`bd1e59c8-3d4c-4097-ab35-0ce7b20d0e50`),
|
|
1099
|
+
email: user.email,
|
|
1100
|
+
},
|
|
1109
1101
|
});
|
|
1102
|
+
paymentUrl = stripeResult.paymentUrl;
|
|
1110
1103
|
}
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1104
|
+
else if (payment.provider === PaymentProvider.Mollie) {
|
|
1105
|
+
// Mollie payment
|
|
1106
|
+
const token = await MollieToken.getTokenFor(organization.id);
|
|
1107
|
+
if (!token) {
|
|
1108
|
+
throw new SimpleError({
|
|
1109
|
+
code: '',
|
|
1110
|
+
message: $t(`b77e1f68-8928-42a2-802b-059fa73bedc3`, { method: PaymentMethodHelper.getName(payment.method) }),
|
|
1111
|
+
});
|
|
1112
|
+
}
|
|
1113
|
+
const profileId = organization.privateMeta.mollieProfile?.id ?? await token.getProfileId(organization.getHost());
|
|
1114
|
+
if (!profileId) {
|
|
1115
|
+
throw new SimpleError({
|
|
1116
|
+
code: '',
|
|
1117
|
+
message: $t(`5574469f-8eee-47fe-9fb6-1b097142ac75`, { method: PaymentMethodHelper.getName(payment.method) }),
|
|
1118
|
+
});
|
|
1119
|
+
}
|
|
1120
|
+
const mollieClient = createMollieClient({ accessToken: await token.getAccessToken() });
|
|
1121
|
+
const locale = Context.i18n.locale.replace('-', '_');
|
|
1122
|
+
const molliePayment = await mollieClient.payments.create({
|
|
1123
|
+
amount: {
|
|
1124
|
+
currency: 'EUR',
|
|
1125
|
+
value: (totalPrice / 100).toFixed(2),
|
|
1126
|
+
},
|
|
1127
|
+
method: payment.method == PaymentMethod.Bancontact ? molliePaymentMethod.bancontact : (payment.method == PaymentMethod.iDEAL ? molliePaymentMethod.ideal : molliePaymentMethod.creditcard),
|
|
1128
|
+
testmode: organization.privateMeta.useTestPayments ?? STAMHOOFD.environment !== 'production',
|
|
1129
|
+
profileId,
|
|
1130
|
+
description,
|
|
1131
|
+
redirectUrl,
|
|
1132
|
+
webhookUrl,
|
|
1133
|
+
metadata: {
|
|
1134
|
+
paymentId: payment.id,
|
|
1135
|
+
},
|
|
1136
|
+
locale: ['en_US', 'en_GB', 'nl_NL', 'nl_BE', 'fr_FR', 'fr_BE', 'de_DE', 'de_AT', 'de_CH', 'es_ES', 'ca_ES', 'pt_PT', 'it_IT', 'nb_NO', 'sv_SE', 'fi_FI', 'da_DK', 'is_IS', 'hu_HU', 'pl_PL', 'lv_LV', 'lt_LT'].includes(locale) ? (locale as any) : null,
|
|
1116
1137
|
});
|
|
1117
|
-
|
|
1118
|
-
const mollieClient = createMollieClient({ accessToken: await token.getAccessToken() });
|
|
1119
|
-
const locale = Context.i18n.locale.replace('-', '_');
|
|
1120
|
-
const molliePayment = await mollieClient.payments.create({
|
|
1121
|
-
amount: {
|
|
1122
|
-
currency: 'EUR',
|
|
1123
|
-
value: (totalPrice / 100).toFixed(2),
|
|
1124
|
-
},
|
|
1125
|
-
method: payment.method == PaymentMethod.Bancontact ? molliePaymentMethod.bancontact : (payment.method == PaymentMethod.iDEAL ? molliePaymentMethod.ideal : molliePaymentMethod.creditcard),
|
|
1126
|
-
testmode: organization.privateMeta.useTestPayments ?? STAMHOOFD.environment !== 'production',
|
|
1127
|
-
profileId,
|
|
1128
|
-
description,
|
|
1129
|
-
redirectUrl,
|
|
1130
|
-
webhookUrl,
|
|
1131
|
-
metadata: {
|
|
1132
|
-
paymentId: payment.id,
|
|
1133
|
-
},
|
|
1134
|
-
locale: ['en_US', 'en_GB', 'nl_NL', 'nl_BE', 'fr_FR', 'fr_BE', 'de_DE', 'de_AT', 'de_CH', 'es_ES', 'ca_ES', 'pt_PT', 'it_IT', 'nb_NO', 'sv_SE', 'fi_FI', 'da_DK', 'is_IS', 'hu_HU', 'pl_PL', 'lv_LV', 'lt_LT'].includes(locale) ? (locale as any) : null,
|
|
1135
|
-
});
|
|
1136
|
-
paymentUrl = molliePayment.getCheckoutUrl();
|
|
1138
|
+
paymentUrl = molliePayment.getCheckoutUrl();
|
|
1137
1139
|
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1140
|
+
// Save payment
|
|
1141
|
+
const dbPayment = new MolliePayment();
|
|
1142
|
+
dbPayment.paymentId = payment.id;
|
|
1143
|
+
dbPayment.mollieId = molliePayment.id;
|
|
1144
|
+
await dbPayment.save();
|
|
1145
|
+
}
|
|
1146
|
+
else if (payment.provider === PaymentProvider.Payconiq) {
|
|
1147
|
+
paymentUrl = await PayconiqPayment.createPayment(payment, organization, description, redirectUrl, webhookUrl);
|
|
1148
|
+
}
|
|
1149
|
+
else if (payment.provider == PaymentProvider.Buckaroo) {
|
|
1150
|
+
// Increase request timeout because buckaroo is super slow (in development)
|
|
1151
|
+
Context.request.request?.setTimeout(60 * 1000);
|
|
1152
|
+
const buckaroo = new BuckarooHelper(organization.privateMeta?.buckarooSettings?.key ?? '', organization.privateMeta?.buckarooSettings?.secret ?? '', organization.privateMeta.useTestPayments ?? STAMHOOFD.environment !== 'production');
|
|
1153
|
+
const ip = Context.request.getIP();
|
|
1154
|
+
paymentUrl = await buckaroo.createPayment(payment, ip, description, redirectUrl, webhookUrl);
|
|
1155
|
+
await payment.save();
|
|
1156
|
+
|
|
1157
|
+
// TypeScript doesn't understand that the status can change and isn't a const....
|
|
1158
|
+
if ((payment.status as any) === PaymentStatus.Failed) {
|
|
1159
|
+
throw new SimpleError({
|
|
1160
|
+
code: 'payment_failed',
|
|
1161
|
+
message: $t(`b77e1f68-8928-42a2-802b-059fa73bedc3`, { method: PaymentMethodHelper.getName(payment.method) }),
|
|
1162
|
+
});
|
|
1163
|
+
}
|
|
1161
1164
|
}
|
|
1162
1165
|
}
|
|
1163
1166
|
}
|
|
1167
|
+
catch (e) {
|
|
1168
|
+
await PaymentService.handlePaymentStatusUpdate(payment, organization, PaymentStatus.Failed);
|
|
1169
|
+
throw e;
|
|
1170
|
+
}
|
|
1164
1171
|
|
|
1165
1172
|
return {
|
|
1166
1173
|
payment,
|
|
@@ -303,7 +303,7 @@ export class PatchOrganizationEndpoint extends Endpoint<Params, Query, Body, Res
|
|
|
303
303
|
throw new SimpleError({
|
|
304
304
|
code: 'invalid_field',
|
|
305
305
|
message: 'You cannot set the uitpasClientCredentialsStatus manually',
|
|
306
|
-
human: $t('
|
|
306
|
+
human: $t('d8937ba8-6689-4c76-9841-d5a00c99074b'),
|
|
307
307
|
});
|
|
308
308
|
}
|
|
309
309
|
|
package/src/endpoints/organization/dashboard/organization/SetUitpasClientCredentialsEndpoint.ts
CHANGED
|
@@ -51,7 +51,7 @@ export class SetUitpasClientCredentialsEndpoint extends Endpoint<Params, Query,
|
|
|
51
51
|
throw new SimpleError({
|
|
52
52
|
message: 'You must provide a client id',
|
|
53
53
|
code: 'missing_client_id',
|
|
54
|
-
human: $t('
|
|
54
|
+
human: $t('9b9ec483-63b8-4696-ade6-0eb18f9008e6'),
|
|
55
55
|
field: 'clientId',
|
|
56
56
|
});
|
|
57
57
|
}
|
|
@@ -59,7 +59,7 @@ export class SetUitpasClientCredentialsEndpoint extends Endpoint<Params, Query,
|
|
|
59
59
|
throw new SimpleError({
|
|
60
60
|
message: 'You must provide a client secret',
|
|
61
61
|
code: 'missing_client_secret',
|
|
62
|
-
human: $t('
|
|
62
|
+
human: $t('58de00fb-3b0a-45a6-9214-7d11b4175779'),
|
|
63
63
|
field: 'clientSecret',
|
|
64
64
|
});
|
|
65
65
|
}
|
|
@@ -67,7 +67,7 @@ export class SetUitpasClientCredentialsEndpoint extends Endpoint<Params, Query,
|
|
|
67
67
|
throw new SimpleError({
|
|
68
68
|
message: 'You cannot use the placeholder client secret for a different client id',
|
|
69
69
|
code: 'invalid_client_secret',
|
|
70
|
-
human: $t('
|
|
70
|
+
human: $t('bbc79280-7ae2-4b8d-a900-2d7cbb552428'),
|
|
71
71
|
field: 'clientSecret',
|
|
72
72
|
});
|
|
73
73
|
}
|
|
@@ -77,7 +77,7 @@ export class SetUitpasClientCredentialsEndpoint extends Endpoint<Params, Query,
|
|
|
77
77
|
throw new SimpleError({
|
|
78
78
|
message: 'This organization does not have a uitpas organizer id set',
|
|
79
79
|
code: 'missing_uitpas_organizer_id',
|
|
80
|
-
human: $t('
|
|
80
|
+
human: $t('80fcde9c-c8c7-4fe1-b9a6-51684a23d850'),
|
|
81
81
|
});
|
|
82
82
|
}
|
|
83
83
|
|
|
@@ -88,7 +88,7 @@ export class SetUitpasClientCredentialsEndpoint extends Endpoint<Params, Query,
|
|
|
88
88
|
throw new SimpleError({
|
|
89
89
|
message: 'The provided client credentials are not valid',
|
|
90
90
|
code: 'invalid_client_credentials',
|
|
91
|
-
human: $t('
|
|
91
|
+
human: $t('42bbd5c0-8789-4ca1-b667-1c9ecf4d0190'),
|
|
92
92
|
});
|
|
93
93
|
}
|
|
94
94
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-endpoints';
|
|
2
|
-
import { GroupPrivateSettings, Group as GroupStruct, GroupType, OrganizationRegistrationPeriod as OrganizationRegistrationPeriodStruct, PermissionLevel, PermissionsResourceType, ResourcePermissions, Version } from '@stamhoofd/structures';
|
|
2
|
+
import { GroupPrivateSettings, Group as GroupStruct, GroupType, OrganizationRegistrationPeriod as OrganizationRegistrationPeriodStruct, PermissionLevel, PermissionsResourceType, ResourcePermissions, SetupStepType, Version } from '@stamhoofd/structures';
|
|
3
3
|
|
|
4
4
|
import { AutoEncoderPatchType, Decoder, PatchableArrayAutoEncoder, PatchableArrayDecoder, StringDecoder } from '@simonbackx/simple-encoding';
|
|
5
5
|
import { SimpleError } from '@simonbackx/simple-errors';
|
|
@@ -41,7 +41,7 @@ export class SearchUitpasEventsEndpoint extends Endpoint<Params, Query, Body, Re
|
|
|
41
41
|
throw new SimpleError({
|
|
42
42
|
code: 'no_uitpas_organizer_id',
|
|
43
43
|
message: `No UiTPAS organizer ID set for organization`,
|
|
44
|
-
human: $t(`
|
|
44
|
+
human: $t(`aaf56535-c13b-4f92-9ba4-7309cae3e078`),
|
|
45
45
|
});
|
|
46
46
|
}
|
|
47
47
|
const uitpasOrganizersResponse = await UitpasService.searchUitpasEvents(organization.id, organization.meta.uitpasOrganizerId, request.query.text);
|
|
@@ -179,7 +179,7 @@ export class PlaceOrderEndpoint extends Endpoint<Params, Query, Body, ResponseBo
|
|
|
179
179
|
throw new SimpleError({
|
|
180
180
|
code: 'uitpas_social_tariff_price_mismatch',
|
|
181
181
|
message: 'UiTPAS wrong number of prices retruned',
|
|
182
|
-
human: $t('
|
|
182
|
+
human: $t('2d1983fa-2224-422f-9ea0-fdae77cb4914'),
|
|
183
183
|
field: 'cart.items.uitpasNumbers',
|
|
184
184
|
});
|
|
185
185
|
}
|
|
@@ -188,7 +188,7 @@ export class PlaceOrderEndpoint extends Endpoint<Params, Query, Body, ResponseBo
|
|
|
188
188
|
throw new SimpleError({
|
|
189
189
|
code: 'uitpas_social_tariff_price_mismatch',
|
|
190
190
|
message: 'UiTPAS social tariff have a different price',
|
|
191
|
-
human: $t('
|
|
191
|
+
human: $t('2f4b9572-4b9c-42e0-91f1-b0984624d225', { correctPrice: Formatter.price(reducedPrices[i].price), orderPrice: Formatter.price(expectedReducedPrices[i].price) }),
|
|
192
192
|
field: 'uitpasNumbers.' + i.toString(),
|
|
193
193
|
});
|
|
194
194
|
}
|
|
@@ -379,11 +379,6 @@ export class AdminPermissionChecker {
|
|
|
379
379
|
return false;
|
|
380
380
|
}
|
|
381
381
|
|
|
382
|
-
// Check permissions aren't scoped to a specific organization, and they mismatch
|
|
383
|
-
if (!this.checkScope(registration.organizationId)) {
|
|
384
|
-
return false;
|
|
385
|
-
}
|
|
386
|
-
|
|
387
382
|
const organizationPermissions = await this.getOrganizationPermissions(registration.organizationId);
|
|
388
383
|
|
|
389
384
|
if (!organizationPermissions) {
|
|
@@ -26,7 +26,9 @@ export class FlagMomentCleanup {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
static async getActiveMemberResponsibilityRecordsForOrganizationWithoutRegistrationInCurrentPeriod() {
|
|
29
|
-
const
|
|
29
|
+
const platform = await Platform.getShared();
|
|
30
|
+
const currentPeriodId = platform.periodId;
|
|
31
|
+
const platformResponsibilityIds = platform.config.responsibilities.map(r => r.id);
|
|
30
32
|
|
|
31
33
|
return await MemberResponsibilityRecord.select()
|
|
32
34
|
.whereNot('organizationId', null)
|
|
@@ -62,6 +64,16 @@ export class FlagMomentCleanup {
|
|
|
62
64
|
).where(
|
|
63
65
|
SQL.column(Group.table, 'type'),
|
|
64
66
|
GroupType.Membership,
|
|
67
|
+
).where(
|
|
68
|
+
SQL.where(
|
|
69
|
+
SQL.column(Group.table, 'defaultAgeGroupId'),
|
|
70
|
+
'!=',
|
|
71
|
+
null,
|
|
72
|
+
).or(
|
|
73
|
+
SQL.column(MemberResponsibilityRecord.table, 'responsibilityId'),
|
|
74
|
+
'!=',
|
|
75
|
+
platformResponsibilityIds,
|
|
76
|
+
),
|
|
65
77
|
).where(
|
|
66
78
|
SQL.column(Group.table, 'deletedAt'),
|
|
67
79
|
null,
|
|
@@ -15,13 +15,15 @@ export class GroupedThrottledQueue<T> {
|
|
|
15
15
|
* In milliseconds.
|
|
16
16
|
*/
|
|
17
17
|
maxDelay: number | null = 10_000;
|
|
18
|
+
itemDelay: number | null = null;
|
|
18
19
|
|
|
19
20
|
constructor(
|
|
20
21
|
handler: (group: string, items: T[]) => Promise<void> | void,
|
|
21
|
-
options: { maxDelay?: number | null } = {},
|
|
22
|
+
options: { maxDelay?: number | null; itemDelay?: number | null } = {},
|
|
22
23
|
) {
|
|
23
24
|
this.handler = handler;
|
|
24
|
-
this.maxDelay = options.maxDelay ?? 10_000;
|
|
25
|
+
this.maxDelay = options.maxDelay !== null ? (options.maxDelay ?? 10_000) : null;
|
|
26
|
+
this.itemDelay = options.itemDelay ?? null;
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
addItems(group: string, items: T[]): void {
|
|
@@ -32,7 +34,7 @@ export class GroupedThrottledQueue<T> {
|
|
|
32
34
|
return;
|
|
33
35
|
}
|
|
34
36
|
const newQueue = new ThrottledQueue<T>(items => this.handler(group, items), {
|
|
35
|
-
maxDelay:
|
|
37
|
+
maxDelay: this.itemDelay,
|
|
36
38
|
emptyHandler: () => {
|
|
37
39
|
this.queues.delete(group);
|
|
38
40
|
},
|