@stamhoofd/backend 2.83.5 → 2.84.1
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/index.ts +19 -4
- package/package.json +18 -14
- package/src/crons/amazon-ses.ts +26 -5
- package/src/crons/balance-emails.ts +18 -17
- package/src/email-recipient-loaders/registrations.ts +87 -0
- package/src/endpoints/global/addresses/SearchRegionsEndpoint.ts +5 -2
- package/src/endpoints/global/email/PatchEmailEndpoint.test.ts +40 -40
- package/src/endpoints/global/events/PatchEventNotificationsEndpoint.test.ts +28 -22
- package/src/endpoints/global/events/PatchEventsEndpoint.ts +81 -49
- package/src/endpoints/global/files/UploadFile.ts +11 -16
- package/src/endpoints/global/groups/GetGroupsEndpoint.test.ts +234 -0
- package/src/endpoints/global/groups/GetGroupsEndpoint.ts +117 -43
- package/src/endpoints/global/members/GetMembersEndpoint.test.ts +1054 -0
- package/src/endpoints/global/members/GetMembersEndpoint.ts +163 -141
- package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.test.ts +6 -6
- package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.ts +0 -16
- package/src/endpoints/global/members/helpers/validateGroupFilter.ts +73 -0
- package/src/endpoints/global/registration/GetPaymentRegistrations.ts +1 -2
- package/src/endpoints/global/registration/GetRegistrationsCountEndpoint.ts +43 -0
- package/src/endpoints/global/registration/GetRegistrationsEndpoint.test.ts +1016 -0
- package/src/endpoints/global/registration/GetRegistrationsEndpoint.ts +234 -0
- package/src/endpoints/global/registration/PatchUserMembersEndpoint.test.ts +5 -5
- package/src/endpoints/global/registration/RegisterMembersEndpoint.test.ts +474 -554
- package/src/endpoints/global/registration/RegisterMembersEndpoint.ts +191 -52
- package/src/endpoints/global/registration-periods/GetRegistrationPeriodsEndpoint.ts +107 -9
- package/src/endpoints/organization/dashboard/email-templates/GetEmailTemplatesEndpoint.test.ts +89 -0
- package/src/endpoints/organization/dashboard/email-templates/GetEmailTemplatesEndpoint.ts +9 -6
- package/src/endpoints/organization/dashboard/email-templates/PatchEmailTemplatesEndpoint.test.ts +88 -0
- package/src/endpoints/organization/dashboard/email-templates/PatchEmailTemplatesEndpoint.ts +0 -6
- package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.ts +10 -6
- package/src/endpoints/organization/dashboard/payments/GetMemberBalanceEndpoint.ts +10 -25
- package/src/endpoints/organization/dashboard/payments/PatchBalanceItemsEndpoint.ts +0 -5
- package/src/endpoints/organization/dashboard/payments/PatchPaymentsEndpoint.ts +0 -5
- package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalanceEndpoint.ts +4 -0
- package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalancesEndpoint.ts +1 -0
- package/src/endpoints/organization/dashboard/registration-periods/GetOrganizationRegistrationPeriodsEndpoint.test.ts +44 -19
- package/src/endpoints/organization/dashboard/registration-periods/GetOrganizationRegistrationPeriodsEndpoint.ts +140 -25
- package/src/endpoints/organization/dashboard/registration-periods/PatchOrganizationRegistrationPeriodsEndpoint.ts +40 -10
- package/src/endpoints/organization/dashboard/users/CreateApiUserEndpoint.test.ts +2 -2
- package/src/endpoints/organization/dashboard/users/PatchApiUserEndpoint.test.ts +2 -2
- package/src/endpoints/organization/dashboard/webshops/PatchWebshopEndpoint.ts +4 -1
- package/src/endpoints/organization/dashboard/webshops/PatchWebshopOrdersEndpoint.ts +2 -2
- package/src/endpoints/organization/webshops/PlaceOrderEndpoint.ts +2 -2
- package/src/excel-loaders/members.ts +233 -232
- package/src/excel-loaders/payments.ts +1 -1
- package/src/excel-loaders/receivable-balances.ts +1 -1
- package/src/excel-loaders/registrations.ts +153 -0
- package/src/helpers/AdminPermissionChecker.ts +65 -37
- package/src/helpers/AuthenticatedStructures.ts +43 -3
- package/src/helpers/Context.ts +29 -1
- package/src/helpers/GlobalHelper.ts +3 -1
- package/src/helpers/GroupedThrottledQueue.test.ts +219 -0
- package/src/helpers/GroupedThrottledQueue.ts +108 -0
- package/src/helpers/LimitedFilteredRequestHelper.ts +26 -1
- package/src/helpers/MemberCharger.ts +0 -5
- package/src/helpers/MembershipCharger.ts +3 -9
- package/src/helpers/OrganizationCharger.ts +0 -5
- package/src/helpers/ThrottledQueue.test.ts +194 -0
- package/src/helpers/ThrottledQueue.ts +145 -0
- package/src/helpers/XlsxTransformerColumnHelper.ts +44 -1
- package/src/middleware/ContextMiddleware.ts +1 -1
- package/src/seeds/1728928974-update-cached-outstanding-balance-from-items.ts +2 -1
- package/src/seeds/1735577912-update-cached-outstanding-balance-from-items.ts +2 -1
- package/src/services/BalanceItemPaymentService.ts +1 -33
- package/src/services/BalanceItemService.ts +167 -48
- package/src/services/FileSignService.ts +18 -13
- package/src/services/MemberRecordStore.ts +28 -19
- package/src/services/PaymentReallocationService.test.ts +25 -14
- package/src/services/PaymentReallocationService.ts +29 -10
- package/src/services/PaymentService.ts +4 -16
- package/src/services/PlatformMembershipService.ts +8 -4
- package/src/services/RegistrationService.ts +66 -2
- package/src/sql-filters/base-registration-filter-compilers.ts +43 -0
- package/src/sql-filters/groups.ts +67 -0
- package/src/sql-filters/members.ts +33 -58
- package/src/sql-filters/organization-registration-periods.ts +8 -0
- package/src/sql-filters/registration-periods.ts +8 -0
- package/src/sql-filters/registrations.ts +11 -22
- package/src/sql-sorters/groups.ts +24 -0
- package/src/sql-sorters/organization-registration-periods.ts +24 -0
- package/src/sql-sorters/registration-periods.ts +47 -0
- package/src/sql-sorters/registrations.ts +77 -0
- package/tests/actions/patchOrganizationMember.ts +27 -0
- package/tests/actions/patchPaymentStatus.ts +45 -0
- package/tests/actions/patchUserMember.ts +27 -0
- package/tests/assertions/assertBalances.ts +49 -0
- package/tests/e2e/api-rate-limits.test.ts +5 -5
- package/tests/e2e/bundle-discounts.test.ts +4060 -0
- package/tests/e2e/charge-members.test.ts +27 -24
- package/tests/e2e/documents.test.ts +398 -0
- package/tests/e2e/register.test.ts +292 -312
- package/tests/helpers/PayconiqMocker.ts +55 -0
- package/tests/init/index.ts +5 -0
- package/tests/init/initAdmin.ts +14 -0
- package/tests/init/initBundleDiscount.ts +47 -0
- package/tests/init/initPayconiq.ts +9 -0
- package/tests/init/initPlatformAdmin.ts +13 -0
- package/tests/init/initStripe.ts +21 -0
- package/tests/jest.setup.ts +29 -0
- package/src/seeds-temporary/1736266448-recall-balance-item-price-paid.ts +0 -70
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { Request } from '@simonbackx/simple-endpoints';
|
|
2
|
-
import {
|
|
3
|
-
import { BalanceItemFactory, Group, GroupFactory, MemberFactory, MemberWithRegistrations, Organization, OrganizationFactory, Registration, RegistrationFactory, RegistrationPeriod, RegistrationPeriodFactory, Token, UserFactory } from '@stamhoofd/models';
|
|
4
|
-
import { BalanceItemCartItem, BalanceItemType, Company, GroupOption, GroupOptionMenu, IDRegisterCart, IDRegisterCheckout, IDRegisterItem, OrganizationPackages,
|
|
5
|
-
import
|
|
2
|
+
import { EmailMocker } from '@stamhoofd/email';
|
|
3
|
+
import { BalanceItem, BalanceItemFactory, Group, GroupFactory, MemberFactory, MemberWithRegistrations, Organization, OrganizationFactory, OrganizationRegistrationPeriodFactory, Registration, RegistrationFactory, RegistrationPeriod, RegistrationPeriodFactory, Token, UserFactory } from '@stamhoofd/models';
|
|
4
|
+
import { BalanceItemCartItem, BalanceItemType, Company, GroupOption, GroupOptionMenu, IDRegisterCart, IDRegisterCheckout, IDRegisterItem, OrganizationPackages, PaymentCustomer, PaymentMethod, PermissionLevel, Permissions, ReduceablePrice, RegisterItemOption, STPackageStatus, STPackageType, UserPermissions, Version } from '@stamhoofd/structures';
|
|
5
|
+
import { STExpect, TestUtils } from '@stamhoofd/test-utils';
|
|
6
6
|
import { v4 as uuidv4 } from 'uuid';
|
|
7
7
|
import { testServer } from '../../../../tests/helpers/TestServer';
|
|
8
|
+
import { initPayconiq } from '../../../../tests/init/initPayconiq';
|
|
8
9
|
import { RegisterMembersEndpoint } from './RegisterMembersEndpoint';
|
|
9
10
|
|
|
10
11
|
const baseUrl = `/v${Version}/members/register`;
|
|
@@ -13,16 +14,12 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
13
14
|
// #region global
|
|
14
15
|
const endpoint = new RegisterMembersEndpoint();
|
|
15
16
|
let period: RegistrationPeriod;
|
|
16
|
-
|
|
17
|
-
// #region helpers
|
|
17
|
+
let defaultPermissionLevel = PermissionLevel.None;
|
|
18
18
|
const post = async (body: IDRegisterCheckout, organization: Organization, token: Token) => {
|
|
19
19
|
const request = Request.buildJson('POST', baseUrl, organization.getApiHost(), body);
|
|
20
20
|
request.headers.authorization = 'Bearer ' + token.accessToken;
|
|
21
21
|
return await testServer.test(endpoint, request);
|
|
22
22
|
};
|
|
23
|
-
// #endregion
|
|
24
|
-
|
|
25
|
-
// #endregion
|
|
26
23
|
|
|
27
24
|
beforeAll(async () => {
|
|
28
25
|
const previousPeriod = await new RegistrationPeriodFactory({
|
|
@@ -32,28 +29,39 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
32
29
|
|
|
33
30
|
period = await new RegistrationPeriodFactory({
|
|
34
31
|
startDate: new Date(2023, 0, 1),
|
|
35
|
-
endDate: new Date(
|
|
32
|
+
endDate: new Date(2030, 11, 31),
|
|
36
33
|
previousPeriodId: previousPeriod.id,
|
|
37
34
|
}).create();
|
|
38
35
|
});
|
|
39
36
|
|
|
37
|
+
beforeEach(async () => {
|
|
38
|
+
TestUtils.setEnvironment('userMode', 'platform');
|
|
39
|
+
});
|
|
40
|
+
|
|
40
41
|
afterEach(() => {
|
|
41
42
|
jest.restoreAllMocks();
|
|
43
|
+
jest.useRealTimers();
|
|
42
44
|
});
|
|
43
45
|
|
|
44
46
|
const initOrganization = async (registrationPeriod: RegistrationPeriod = period) => {
|
|
45
|
-
|
|
47
|
+
const organization = await new OrganizationFactory({ period: registrationPeriod })
|
|
46
48
|
.create();
|
|
49
|
+
|
|
50
|
+
const organizationRegistrationPeriod = await new OrganizationRegistrationPeriodFactory({ organization, period: registrationPeriod }).create();
|
|
51
|
+
|
|
52
|
+
return { organization, organizationRegistrationPeriod };
|
|
47
53
|
};
|
|
48
54
|
|
|
49
|
-
|
|
50
|
-
const organization = await initOrganization(period);
|
|
55
|
+
async function initData({ otherMemberAmount = 0, permissionLevel = defaultPermissionLevel }: { otherMemberAmount?: number; permissionLevel?: PermissionLevel } = {}) {
|
|
56
|
+
const { organization, organizationRegistrationPeriod } = await initOrganization(period);
|
|
51
57
|
|
|
52
58
|
const user = await new UserFactory({
|
|
53
59
|
organization,
|
|
54
|
-
permissions:
|
|
55
|
-
|
|
56
|
-
|
|
60
|
+
permissions: permissionLevel !== PermissionLevel.None
|
|
61
|
+
? Permissions.create({
|
|
62
|
+
level: permissionLevel,
|
|
63
|
+
})
|
|
64
|
+
: null,
|
|
57
65
|
})
|
|
58
66
|
.create();
|
|
59
67
|
|
|
@@ -71,8 +79,8 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
71
79
|
|
|
72
80
|
const group = await new GroupFactory({
|
|
73
81
|
organization,
|
|
74
|
-
price:
|
|
75
|
-
stock:
|
|
82
|
+
price: 25_00,
|
|
83
|
+
stock: 500,
|
|
76
84
|
})
|
|
77
85
|
.create();
|
|
78
86
|
|
|
@@ -80,6 +88,7 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
80
88
|
|
|
81
89
|
return {
|
|
82
90
|
organization,
|
|
91
|
+
organizationRegistrationPeriod,
|
|
83
92
|
user,
|
|
84
93
|
token,
|
|
85
94
|
member,
|
|
@@ -87,60 +96,15 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
87
96
|
group,
|
|
88
97
|
groupPrice,
|
|
89
98
|
};
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
describe('Register', () => {
|
|
93
|
-
test('Should fail if cannot manage finances', async () => {
|
|
94
|
-
// #region arrange
|
|
95
|
-
const { member, group, groupPrice, organization, token } = await initData();
|
|
96
|
-
const organization2 = await initOrganization();
|
|
97
|
-
|
|
98
|
-
const registration = await new RegistrationFactory({
|
|
99
|
-
member,
|
|
100
|
-
group,
|
|
101
|
-
groupPrice,
|
|
102
|
-
}).create();
|
|
103
|
-
|
|
104
|
-
const body = IDRegisterCheckout.create({
|
|
105
|
-
cart: IDRegisterCart.create({
|
|
106
|
-
items: [
|
|
107
|
-
IDRegisterItem.create({
|
|
108
|
-
id: uuidv4(),
|
|
109
|
-
replaceRegistrationIds: [],
|
|
110
|
-
options: [],
|
|
111
|
-
groupPrice,
|
|
112
|
-
organizationId: organization.id,
|
|
113
|
-
groupId: group.id,
|
|
114
|
-
memberId: member.id,
|
|
115
|
-
}),
|
|
116
|
-
],
|
|
117
|
-
balanceItems: [],
|
|
118
|
-
deleteRegistrationIds: [registration.id],
|
|
119
|
-
}),
|
|
120
|
-
administrationFee: 0,
|
|
121
|
-
freeContribution: 0,
|
|
122
|
-
paymentMethod: PaymentMethod.PointOfSale,
|
|
123
|
-
totalPrice: 5,
|
|
124
|
-
asOrganizationId: organization2.id,
|
|
125
|
-
customer: null,
|
|
126
|
-
});
|
|
127
|
-
// #endregion
|
|
99
|
+
}
|
|
128
100
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
.toThrow('No permission to register as this organization for a different organization');
|
|
133
|
-
// #endregion
|
|
101
|
+
describe('Register as member', () => {
|
|
102
|
+
beforeEach(() => {
|
|
103
|
+
defaultPermissionLevel = PermissionLevel.None;
|
|
134
104
|
});
|
|
135
105
|
|
|
136
106
|
test('Should fail if demo limit reached', async () => {
|
|
137
|
-
|
|
138
|
-
(STAMHOOFD.userMode as string) = 'organization';
|
|
139
|
-
|
|
140
|
-
const spySendWebmaster = jest.spyOn(Email, 'sendWebmaster').mockImplementation(() => {
|
|
141
|
-
// do nothing
|
|
142
|
-
});
|
|
143
|
-
|
|
107
|
+
TestUtils.setEnvironment('userMode', 'organization');
|
|
144
108
|
const { member, group, groupPrice, organization, token, otherMembers } = await initData({ otherMemberAmount: 10 });
|
|
145
109
|
|
|
146
110
|
organization.meta.packages = OrganizationPackages.create({
|
|
@@ -171,8 +135,7 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
171
135
|
administrationFee: 0,
|
|
172
136
|
freeContribution: 0,
|
|
173
137
|
paymentMethod: PaymentMethod.PointOfSale,
|
|
174
|
-
totalPrice:
|
|
175
|
-
asOrganizationId: organization.id,
|
|
138
|
+
totalPrice: 25_00,
|
|
176
139
|
customer: null,
|
|
177
140
|
});
|
|
178
141
|
|
|
@@ -198,27 +161,24 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
198
161
|
administrationFee: 0,
|
|
199
162
|
freeContribution: 0,
|
|
200
163
|
paymentMethod: PaymentMethod.PointOfSale,
|
|
201
|
-
totalPrice:
|
|
202
|
-
asOrganizationId: organization.id,
|
|
164
|
+
totalPrice: 25_00,
|
|
203
165
|
customer: null,
|
|
204
166
|
});
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
// #region act and assert
|
|
208
|
-
|
|
209
|
-
await expect(async () => await post(body, organization, token))
|
|
167
|
+
await expect(post(body, organization, token))
|
|
210
168
|
.rejects
|
|
211
|
-
.toThrow(
|
|
212
|
-
|
|
213
|
-
expect(spySendWebmaster).toHaveBeenCalledOnce();
|
|
214
|
-
// #endregion
|
|
169
|
+
.toThrow(STExpect.simpleError({ code: 'too_many_emails_period' }));
|
|
215
170
|
|
|
216
|
-
(
|
|
171
|
+
expect(await EmailMocker.transactional.getSucceededEmails()).toEqual([
|
|
172
|
+
expect.objectContaining({
|
|
173
|
+
to: '"Stamhoofd" <hallo@stamhoofd.be>',
|
|
174
|
+
from: '"Ravot" <webmaster@stamhoofd.be>',
|
|
175
|
+
subject: '[Limiet] Limiet bereikt voor aantal inschrijvingen',
|
|
176
|
+
}),
|
|
177
|
+
]);
|
|
217
178
|
});
|
|
218
179
|
|
|
219
|
-
test('Should fail if balance
|
|
220
|
-
|
|
221
|
-
const { member, group, user, groupPrice, organization, token } = await initData();
|
|
180
|
+
test('Should fail if balance item deleted', async () => {
|
|
181
|
+
const { member, user, organization, token } = await initData();
|
|
222
182
|
|
|
223
183
|
const balanceItem1 = await new BalanceItemFactory({
|
|
224
184
|
organizationId: organization.id,
|
|
@@ -237,17 +197,7 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
237
197
|
|
|
238
198
|
const body = IDRegisterCheckout.create({
|
|
239
199
|
cart: IDRegisterCart.create({
|
|
240
|
-
items: [
|
|
241
|
-
IDRegisterItem.create({
|
|
242
|
-
id: uuidv4(),
|
|
243
|
-
replaceRegistrationIds: [],
|
|
244
|
-
options: [],
|
|
245
|
-
groupPrice,
|
|
246
|
-
organizationId: organization.id,
|
|
247
|
-
groupId: group.id,
|
|
248
|
-
memberId: member.id,
|
|
249
|
-
}),
|
|
250
|
-
],
|
|
200
|
+
items: [],
|
|
251
201
|
balanceItems: [
|
|
252
202
|
cartItem,
|
|
253
203
|
],
|
|
@@ -256,23 +206,19 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
256
206
|
administrationFee: 0,
|
|
257
207
|
freeContribution: 0,
|
|
258
208
|
paymentMethod: PaymentMethod.PointOfSale,
|
|
259
|
-
totalPrice:
|
|
209
|
+
totalPrice: 20,
|
|
260
210
|
customer: null,
|
|
261
211
|
});
|
|
262
|
-
// #endregion
|
|
263
212
|
|
|
264
|
-
// #region act and assert
|
|
265
213
|
await balanceItem1.delete();
|
|
266
214
|
|
|
267
215
|
await expect(async () => await post(body, organization, token))
|
|
268
216
|
.rejects
|
|
269
217
|
.toThrow(new RegExp('Oeps, één of meerdere openstaande bedragen in jouw winkelmandje zijn aangepast'));
|
|
270
|
-
// #endregion
|
|
271
218
|
});
|
|
272
219
|
|
|
273
|
-
test('Should fail
|
|
274
|
-
|
|
275
|
-
const { member, group, user, groupPrice, organization, token } = await initData();
|
|
220
|
+
test('Should fail if balance item price difference', async () => {
|
|
221
|
+
const { member, user, organization, token } = await initData();
|
|
276
222
|
|
|
277
223
|
const balanceItem1 = await new BalanceItemFactory({
|
|
278
224
|
organizationId: organization.id,
|
|
@@ -286,22 +232,12 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
286
232
|
|
|
287
233
|
const cartItem = BalanceItemCartItem.create({
|
|
288
234
|
item: balanceItem1.getStructure(),
|
|
289
|
-
price:
|
|
235
|
+
price: 30, // too much
|
|
290
236
|
});
|
|
291
237
|
|
|
292
238
|
const body = IDRegisterCheckout.create({
|
|
293
239
|
cart: IDRegisterCart.create({
|
|
294
|
-
items: [
|
|
295
|
-
IDRegisterItem.create({
|
|
296
|
-
id: uuidv4(),
|
|
297
|
-
replaceRegistrationIds: [],
|
|
298
|
-
options: [],
|
|
299
|
-
groupPrice,
|
|
300
|
-
organizationId: organization.id,
|
|
301
|
-
groupId: group.id,
|
|
302
|
-
memberId: member.id,
|
|
303
|
-
}),
|
|
304
|
-
],
|
|
240
|
+
items: [],
|
|
305
241
|
balanceItems: [
|
|
306
242
|
cartItem,
|
|
307
243
|
],
|
|
@@ -310,17 +246,13 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
310
246
|
administrationFee: 0,
|
|
311
247
|
freeContribution: 0,
|
|
312
248
|
paymentMethod: PaymentMethod.PointOfSale,
|
|
313
|
-
totalPrice:
|
|
314
|
-
asOrganizationId: organization.id,
|
|
249
|
+
totalPrice: 30,
|
|
315
250
|
customer: null,
|
|
316
251
|
});
|
|
317
|
-
// #endregion
|
|
318
252
|
|
|
319
|
-
|
|
320
|
-
await expect(async () => await post(body, organization, token))
|
|
253
|
+
await expect(post(body, organization, token))
|
|
321
254
|
.rejects
|
|
322
|
-
.toThrow(
|
|
323
|
-
// #endregion
|
|
255
|
+
.toThrow(STExpect.simpleError({ code: 'changed_price' }));
|
|
324
256
|
});
|
|
325
257
|
|
|
326
258
|
test('Should fail if has no write access for member', async () => {
|
|
@@ -348,7 +280,7 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
348
280
|
administrationFee: 0,
|
|
349
281
|
freeContribution: 0,
|
|
350
282
|
paymentMethod: PaymentMethod.PointOfSale,
|
|
351
|
-
totalPrice:
|
|
283
|
+
totalPrice: 25_00,
|
|
352
284
|
customer: null,
|
|
353
285
|
});
|
|
354
286
|
// #endregion
|
|
@@ -356,7 +288,7 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
356
288
|
// #region act and assert
|
|
357
289
|
await expect(async () => await post(body, organization, token))
|
|
358
290
|
.rejects
|
|
359
|
-
.toThrow(new RegExp('
|
|
291
|
+
.toThrow(new RegExp('Member not found'));
|
|
360
292
|
// #endregion
|
|
361
293
|
});
|
|
362
294
|
|
|
@@ -400,7 +332,6 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
400
332
|
});
|
|
401
333
|
|
|
402
334
|
test('Should fail if price changed', async () => {
|
|
403
|
-
// #region arrange
|
|
404
335
|
const { member, group, groupPrice, organization, token } = await initData();
|
|
405
336
|
|
|
406
337
|
const body = IDRegisterCheckout.create({
|
|
@@ -421,22 +352,16 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
421
352
|
administrationFee: 0,
|
|
422
353
|
freeContribution: 0,
|
|
423
354
|
paymentMethod: PaymentMethod.PointOfSale,
|
|
424
|
-
totalPrice:
|
|
425
|
-
asOrganizationId: organization.id,
|
|
355
|
+
totalPrice: groupPrice.price.price + 5, // too much
|
|
426
356
|
customer: null,
|
|
427
357
|
});
|
|
428
|
-
// #endregion
|
|
429
|
-
|
|
430
|
-
// #region act and assert
|
|
431
358
|
|
|
432
359
|
await expect(async () => await post(body, organization, token))
|
|
433
360
|
.rejects
|
|
434
|
-
.toThrow(
|
|
435
|
-
// #endregion
|
|
361
|
+
.toThrow(STExpect.simpleError({ code: 'changed_price' }));
|
|
436
362
|
});
|
|
437
363
|
|
|
438
364
|
test('Should fail if member is already registered', async () => {
|
|
439
|
-
// #region arrange
|
|
440
365
|
const { organization, group, groupPrice, token, member } = await initData();
|
|
441
366
|
|
|
442
367
|
const body = IDRegisterCheckout.create({
|
|
@@ -459,24 +384,20 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
459
384
|
administrationFee: 0,
|
|
460
385
|
freeContribution: 0,
|
|
461
386
|
paymentMethod: PaymentMethod.PointOfSale,
|
|
462
|
-
totalPrice:
|
|
387
|
+
totalPrice: 25_00,
|
|
463
388
|
customer: null,
|
|
464
389
|
});
|
|
465
|
-
// #endregion
|
|
466
390
|
|
|
467
|
-
// #region act and assert
|
|
468
391
|
// register first time
|
|
469
392
|
await post(body, organization, token);
|
|
470
393
|
|
|
471
394
|
// second time should fail
|
|
472
395
|
await expect(async () => await post(body, organization, token))
|
|
473
396
|
.rejects
|
|
474
|
-
.toThrow(
|
|
475
|
-
// #endregion
|
|
397
|
+
.toThrow(STExpect.simpleError({ code: 'already_registered' }));
|
|
476
398
|
});
|
|
477
399
|
|
|
478
400
|
test('Should fail if duplicate registration in cart', async () => {
|
|
479
|
-
// #region arrange
|
|
480
401
|
const { organization, group, groupPrice, token, member } = await initData();
|
|
481
402
|
|
|
482
403
|
const body = IDRegisterCheckout.create({
|
|
@@ -501,9 +422,6 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
501
422
|
memberId: member.id,
|
|
502
423
|
}),
|
|
503
424
|
],
|
|
504
|
-
balanceItems: [
|
|
505
|
-
],
|
|
506
|
-
deleteRegistrationIds: [],
|
|
507
425
|
}),
|
|
508
426
|
administrationFee: 0,
|
|
509
427
|
freeContribution: 0,
|
|
@@ -511,30 +429,18 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
511
429
|
totalPrice: 50,
|
|
512
430
|
customer: null,
|
|
513
431
|
});
|
|
514
|
-
// #endregion
|
|
515
432
|
|
|
516
|
-
// #region act and assert
|
|
517
433
|
await expect(async () => await post(body, organization, token))
|
|
518
434
|
.rejects
|
|
519
|
-
.toThrow(
|
|
520
|
-
|
|
435
|
+
.toThrow(STExpect.simpleErrors([
|
|
436
|
+
{ code: 'duplicate_register_item' },
|
|
437
|
+
{ code: 'duplicate_register_item' },
|
|
438
|
+
]));
|
|
521
439
|
});
|
|
522
440
|
|
|
523
|
-
test('Should fail
|
|
441
|
+
test('Should fail if invalid payment', async () => {
|
|
524
442
|
// #region arrange
|
|
525
|
-
const { organization, group, groupPrice, token, member
|
|
526
|
-
|
|
527
|
-
const { organization: organization2 } = await initData();
|
|
528
|
-
|
|
529
|
-
user.permissions = UserPermissions.create({
|
|
530
|
-
organizationPermissions: new Map([
|
|
531
|
-
[organization2.id, Permissions.create({
|
|
532
|
-
level: PermissionLevel.Full,
|
|
533
|
-
})],
|
|
534
|
-
]),
|
|
535
|
-
});
|
|
536
|
-
|
|
537
|
-
await user.save();
|
|
443
|
+
const { organization, group, groupPrice, token, member } = await initData();
|
|
538
444
|
|
|
539
445
|
const body = IDRegisterCheckout.create({
|
|
540
446
|
cart: IDRegisterCart.create({
|
|
@@ -555,23 +461,24 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
555
461
|
}),
|
|
556
462
|
administrationFee: 0,
|
|
557
463
|
freeContribution: 0,
|
|
558
|
-
paymentMethod: PaymentMethod.
|
|
559
|
-
totalPrice:
|
|
464
|
+
paymentMethod: PaymentMethod.CreditCard,
|
|
465
|
+
totalPrice: 25_00,
|
|
560
466
|
customer: null,
|
|
561
|
-
asOrganizationId: organization2.id,
|
|
562
467
|
});
|
|
563
468
|
// #endregion
|
|
564
469
|
|
|
565
470
|
// #region act and assert
|
|
566
471
|
await expect(async () => await post(body, organization, token))
|
|
567
472
|
.rejects
|
|
568
|
-
.toThrow(new RegExp('
|
|
473
|
+
.toThrow(new RegExp('Oeps, je hebt geen geldige betaalmethode geselecteerd'));
|
|
569
474
|
// #endregion
|
|
570
475
|
});
|
|
571
476
|
|
|
572
|
-
test('Should fail if
|
|
477
|
+
test('Should fail if no redirect url for online payment', async () => {
|
|
573
478
|
// #region arrange
|
|
574
479
|
const { organization, group, groupPrice, token, member } = await initData();
|
|
480
|
+
organization.meta.registrationPaymentConfiguration.paymentMethods.push(PaymentMethod.Bancontact);
|
|
481
|
+
await organization.save();
|
|
575
482
|
|
|
576
483
|
const body = IDRegisterCheckout.create({
|
|
577
484
|
cart: IDRegisterCart.create({
|
|
@@ -592,8 +499,9 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
592
499
|
}),
|
|
593
500
|
administrationFee: 0,
|
|
594
501
|
freeContribution: 0,
|
|
595
|
-
paymentMethod: PaymentMethod.
|
|
596
|
-
totalPrice:
|
|
502
|
+
paymentMethod: PaymentMethod.Bancontact,
|
|
503
|
+
totalPrice: 25_00,
|
|
504
|
+
cancelUrl: new URL('https://www.stamhoofd.be'),
|
|
597
505
|
customer: null,
|
|
598
506
|
});
|
|
599
507
|
// #endregion
|
|
@@ -601,12 +509,11 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
601
509
|
// #region act and assert
|
|
602
510
|
await expect(async () => await post(body, organization, token))
|
|
603
511
|
.rejects
|
|
604
|
-
.toThrow(new RegExp('
|
|
512
|
+
.toThrow(new RegExp('redirectUrl or cancelUrl is missing'));
|
|
605
513
|
// #endregion
|
|
606
514
|
});
|
|
607
515
|
|
|
608
|
-
test('Should fail if no
|
|
609
|
-
// #region arrange
|
|
516
|
+
test('Should fail if no cancel url for online payment', async () => {
|
|
610
517
|
const { organization, group, groupPrice, token, member } = await initData();
|
|
611
518
|
organization.meta.registrationPaymentConfiguration.paymentMethods.push(PaymentMethod.Bancontact);
|
|
612
519
|
await organization.save();
|
|
@@ -624,31 +531,24 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
624
531
|
memberId: member.id,
|
|
625
532
|
}),
|
|
626
533
|
],
|
|
627
|
-
balanceItems: [
|
|
628
|
-
],
|
|
629
|
-
deleteRegistrationIds: [],
|
|
630
534
|
}),
|
|
631
535
|
administrationFee: 0,
|
|
632
536
|
freeContribution: 0,
|
|
633
537
|
paymentMethod: PaymentMethod.Bancontact,
|
|
634
|
-
totalPrice:
|
|
635
|
-
|
|
538
|
+
totalPrice: 25_00,
|
|
539
|
+
redirectUrl: new URL('https://www.stamhoofd.be'),
|
|
636
540
|
customer: null,
|
|
637
541
|
});
|
|
638
|
-
// #endregion
|
|
639
542
|
|
|
640
|
-
// #region act and assert
|
|
641
543
|
await expect(async () => await post(body, organization, token))
|
|
642
544
|
.rejects
|
|
643
545
|
.toThrow(new RegExp('redirectUrl or cancelUrl is missing'));
|
|
644
|
-
// #endregion
|
|
645
546
|
});
|
|
646
547
|
|
|
647
|
-
test('Should
|
|
648
|
-
// #region arrange
|
|
548
|
+
test('Should not reserve for point of sale payment method if group has max members', async () => {
|
|
649
549
|
const { organization, group, groupPrice, token, member } = await initData();
|
|
650
|
-
|
|
651
|
-
await
|
|
550
|
+
group.settings.maxMembers = 5;
|
|
551
|
+
await group.save();
|
|
652
552
|
|
|
653
553
|
const body = IDRegisterCheckout.create({
|
|
654
554
|
cart: IDRegisterCart.create({
|
|
@@ -663,38 +563,39 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
663
563
|
memberId: member.id,
|
|
664
564
|
}),
|
|
665
565
|
],
|
|
666
|
-
balanceItems: [
|
|
667
|
-
],
|
|
668
|
-
deleteRegistrationIds: [],
|
|
669
566
|
}),
|
|
670
567
|
administrationFee: 0,
|
|
671
568
|
freeContribution: 0,
|
|
672
|
-
paymentMethod: PaymentMethod.
|
|
673
|
-
totalPrice:
|
|
674
|
-
redirectUrl: new URL('https://www.stamhoofd.be'),
|
|
675
|
-
customer: null,
|
|
569
|
+
paymentMethod: PaymentMethod.PointOfSale,
|
|
570
|
+
totalPrice: 25_00,
|
|
676
571
|
});
|
|
677
|
-
// #endregion
|
|
678
572
|
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
573
|
+
const response = await post(body, organization, token);
|
|
574
|
+
expect(response.body.registrations.length).toBe(1);
|
|
575
|
+
|
|
576
|
+
const updatedRegistration = (await Registration.getByID(response.body.registrations[0].id))!;
|
|
577
|
+
expect(updatedRegistration.registeredAt).not.toBeNull();
|
|
578
|
+
expect(updatedRegistration.reservedUntil).toBeNull();
|
|
579
|
+
|
|
580
|
+
// Check if response is up-to-date (if it fails here, data storage is okay, but returned API response is not up-to-date)
|
|
581
|
+
expect(response.body.registrations[0].registeredAt).not.toBeNull();
|
|
582
|
+
expect(response.body.registrations[0].reservedUntil).toBeNull();
|
|
684
583
|
});
|
|
685
584
|
|
|
686
|
-
test('Should
|
|
687
|
-
// #region arrange
|
|
585
|
+
test('Should reuse recently deactivated registration if it has zero balance', async () => {
|
|
688
586
|
const { organization, group, groupPrice, token, member } = await initData();
|
|
689
|
-
|
|
690
|
-
|
|
587
|
+
const firstRegistration = await new RegistrationFactory({
|
|
588
|
+
member,
|
|
589
|
+
group: group,
|
|
590
|
+
groupPrice: group.settings.prices[0],
|
|
591
|
+
deactivatedAt: new Date(new Date().getTime() - 1 * 24 * 60 * 60 * 1000), // 1 day ago
|
|
592
|
+
}).create();
|
|
691
593
|
|
|
692
594
|
const body = IDRegisterCheckout.create({
|
|
693
595
|
cart: IDRegisterCart.create({
|
|
694
596
|
items: [
|
|
695
597
|
IDRegisterItem.create({
|
|
696
598
|
id: uuidv4(),
|
|
697
|
-
replaceRegistrationIds: [],
|
|
698
599
|
options: [],
|
|
699
600
|
groupPrice,
|
|
700
601
|
organizationId: organization.id,
|
|
@@ -702,50 +603,26 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
702
603
|
memberId: member.id,
|
|
703
604
|
}),
|
|
704
605
|
],
|
|
705
|
-
balanceItems: [
|
|
706
|
-
],
|
|
707
|
-
deleteRegistrationIds: [],
|
|
708
606
|
}),
|
|
709
607
|
administrationFee: 0,
|
|
710
608
|
freeContribution: 0,
|
|
711
609
|
paymentMethod: PaymentMethod.PointOfSale,
|
|
712
|
-
totalPrice:
|
|
610
|
+
totalPrice: 25_00,
|
|
713
611
|
});
|
|
714
|
-
// #endregion
|
|
715
612
|
|
|
716
|
-
// #region act and assert
|
|
717
613
|
const response = await post(body, organization, token);
|
|
718
614
|
expect(response.body.registrations.length).toBe(1);
|
|
719
|
-
expect(response.body.registrations[0].
|
|
720
|
-
// #endregion
|
|
615
|
+
expect(response.body.registrations[0].id).toEqual(firstRegistration.id);
|
|
721
616
|
});
|
|
722
617
|
|
|
723
|
-
test('Should reuse existing registration', async () => {
|
|
724
|
-
|
|
725
|
-
const { organization, group, groupPrice, token, member, user } = await initData();
|
|
726
|
-
group.settings.allowRegistrationsByOrganization = true;
|
|
727
|
-
await group.save();
|
|
728
|
-
|
|
729
|
-
user.permissions = UserPermissions.create({
|
|
730
|
-
organizationPermissions: new Map([
|
|
731
|
-
[organization.id, Permissions.create({
|
|
732
|
-
level: PermissionLevel.Full,
|
|
733
|
-
})],
|
|
734
|
-
]),
|
|
735
|
-
});
|
|
736
|
-
|
|
737
|
-
await user.save();
|
|
738
|
-
|
|
739
|
-
const group2 = await new GroupFactory({
|
|
740
|
-
organization,
|
|
741
|
-
price: 25,
|
|
742
|
-
stock: 5,
|
|
743
|
-
}).create();
|
|
618
|
+
test('Should not reuse existing registration if it is older than 7 days', async () => {
|
|
619
|
+
const { organization, group, groupPrice, token, member } = await initData();
|
|
744
620
|
|
|
745
621
|
const firstRegistration = await new RegistrationFactory({
|
|
746
622
|
member,
|
|
747
|
-
group:
|
|
748
|
-
groupPrice:
|
|
623
|
+
group: group,
|
|
624
|
+
groupPrice: group.settings.prices[0],
|
|
625
|
+
deactivatedAt: new Date(new Date().getTime() - 8 * 24 * 60 * 60 * 1000), // 8 days ago
|
|
749
626
|
}).create();
|
|
750
627
|
|
|
751
628
|
const body = IDRegisterCheckout.create({
|
|
@@ -753,7 +630,6 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
753
630
|
items: [
|
|
754
631
|
IDRegisterItem.create({
|
|
755
632
|
id: uuidv4(),
|
|
756
|
-
replaceRegistrationIds: [firstRegistration.id],
|
|
757
633
|
options: [],
|
|
758
634
|
groupPrice,
|
|
759
635
|
organizationId: organization.id,
|
|
@@ -761,57 +637,46 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
761
637
|
memberId: member.id,
|
|
762
638
|
}),
|
|
763
639
|
],
|
|
764
|
-
balanceItems: [
|
|
765
|
-
],
|
|
766
|
-
deleteRegistrationIds: [],
|
|
767
640
|
}),
|
|
768
641
|
administrationFee: 0,
|
|
769
642
|
freeContribution: 0,
|
|
770
643
|
paymentMethod: PaymentMethod.PointOfSale,
|
|
771
|
-
totalPrice:
|
|
772
|
-
asOrganizationId: organization.id,
|
|
644
|
+
totalPrice: 25_00,
|
|
773
645
|
});
|
|
774
646
|
|
|
775
|
-
// #endregion
|
|
776
|
-
|
|
777
|
-
// #region act and assert
|
|
778
647
|
const response = await post(body, organization, token);
|
|
779
648
|
expect(response.body.registrations.length).toBe(1);
|
|
780
|
-
expect(response.body.registrations[0].id).toEqual(firstRegistration.id);
|
|
781
|
-
// #endregion
|
|
649
|
+
expect(response.body.registrations[0].id).not.toEqual(firstRegistration.id);
|
|
782
650
|
});
|
|
783
651
|
|
|
784
|
-
test('Should reuse
|
|
785
|
-
// #region arrange
|
|
652
|
+
test('Should not reuse existing registration if has a non-zero balance', async () => {
|
|
786
653
|
const { organization, group, groupPrice, token, member, user } = await initData();
|
|
787
|
-
group.settings.allowRegistrationsByOrganization = true;
|
|
788
|
-
await group.save();
|
|
789
|
-
|
|
790
|
-
user.permissions = UserPermissions.create({
|
|
791
|
-
organizationPermissions: new Map([
|
|
792
|
-
[organization.id, Permissions.create({
|
|
793
|
-
level: PermissionLevel.Full,
|
|
794
|
-
})],
|
|
795
|
-
]),
|
|
796
|
-
});
|
|
797
|
-
|
|
798
|
-
await user.save();
|
|
799
|
-
|
|
800
654
|
const firstRegistration = await new RegistrationFactory({
|
|
801
655
|
member,
|
|
802
656
|
group,
|
|
803
|
-
groupPrice,
|
|
657
|
+
groupPrice: group.settings.prices[0],
|
|
658
|
+
deactivatedAt: new Date(new Date().getTime() - 1 * 24 * 60 * 60 * 1000), // 1 day ago
|
|
804
659
|
}).create();
|
|
805
660
|
|
|
806
|
-
|
|
807
|
-
await
|
|
661
|
+
// Create a balance item for the first registration
|
|
662
|
+
const item = await new BalanceItemFactory({
|
|
663
|
+
organizationId: organization.id,
|
|
664
|
+
memberId: member.id,
|
|
665
|
+
userId: user.id,
|
|
666
|
+
type: BalanceItemType.Registration,
|
|
667
|
+
amount: 1,
|
|
668
|
+
unitPrice: group.settings.prices[0].price.price,
|
|
669
|
+
registrationId: firstRegistration.id,
|
|
670
|
+
}).create();
|
|
671
|
+
|
|
672
|
+
// Update outstanding cache
|
|
673
|
+
// await BalanceItem.updateOutstanding([item]);
|
|
808
674
|
|
|
809
675
|
const body = IDRegisterCheckout.create({
|
|
810
676
|
cart: IDRegisterCart.create({
|
|
811
677
|
items: [
|
|
812
678
|
IDRegisterItem.create({
|
|
813
679
|
id: uuidv4(),
|
|
814
|
-
replaceRegistrationIds: [],
|
|
815
680
|
options: [],
|
|
816
681
|
groupPrice,
|
|
817
682
|
organizationId: organization.id,
|
|
@@ -819,24 +684,16 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
819
684
|
memberId: member.id,
|
|
820
685
|
}),
|
|
821
686
|
],
|
|
822
|
-
balanceItems: [
|
|
823
|
-
],
|
|
824
|
-
deleteRegistrationIds: [],
|
|
825
687
|
}),
|
|
826
688
|
administrationFee: 0,
|
|
827
689
|
freeContribution: 0,
|
|
828
690
|
paymentMethod: PaymentMethod.PointOfSale,
|
|
829
|
-
totalPrice:
|
|
830
|
-
asOrganizationId: organization.id,
|
|
691
|
+
totalPrice: 25_00,
|
|
831
692
|
});
|
|
832
693
|
|
|
833
|
-
// #endregion
|
|
834
|
-
|
|
835
|
-
// #region act and assert
|
|
836
694
|
const response = await post(body, organization, token);
|
|
837
695
|
expect(response.body.registrations.length).toBe(1);
|
|
838
|
-
expect(response.body.registrations[0].id).toEqual(firstRegistration.id);
|
|
839
|
-
// #endregion
|
|
696
|
+
expect(response.body.registrations[0].id).not.toEqual(firstRegistration.id);
|
|
840
697
|
});
|
|
841
698
|
|
|
842
699
|
test('Should update registered members', async () => {
|
|
@@ -862,8 +719,7 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
862
719
|
administrationFee: 0,
|
|
863
720
|
freeContribution: 0,
|
|
864
721
|
paymentMethod: PaymentMethod.PointOfSale,
|
|
865
|
-
totalPrice:
|
|
866
|
-
asOrganizationId: organization.id,
|
|
722
|
+
totalPrice: 25_00,
|
|
867
723
|
customer: null,
|
|
868
724
|
});
|
|
869
725
|
// #endregion
|
|
@@ -880,23 +736,9 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
880
736
|
expect(updatedGroup!.settings.reservedMembers).toBe(0);
|
|
881
737
|
});
|
|
882
738
|
|
|
883
|
-
test('Should
|
|
884
|
-
// #region arrange
|
|
739
|
+
test('Should set reserved members when using online payments', async () => {
|
|
885
740
|
const { member, organization, token } = await initData();
|
|
886
|
-
|
|
887
|
-
organization.meta.registrationPaymentConfiguration.paymentMethods = [PaymentMethod.PointOfSale, PaymentMethod.Payconiq];
|
|
888
|
-
|
|
889
|
-
organization.privateMeta.payconiqAccounts = [PayconiqAccount.create({
|
|
890
|
-
id: uuidv4(),
|
|
891
|
-
apiKey: 'testKey',
|
|
892
|
-
merchantId: 'test',
|
|
893
|
-
profileId: 'test',
|
|
894
|
-
name: 'test',
|
|
895
|
-
iban: 'BE56587127952688', // = random IBAN
|
|
896
|
-
callbackUrl: 'https://www.example.com',
|
|
897
|
-
})];
|
|
898
|
-
|
|
899
|
-
await organization.save();
|
|
741
|
+
await initPayconiq({ organization });
|
|
900
742
|
|
|
901
743
|
const group2 = await new GroupFactory({
|
|
902
744
|
organization,
|
|
@@ -912,54 +754,40 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
912
754
|
items: [
|
|
913
755
|
IDRegisterItem.create({
|
|
914
756
|
id: uuidv4(),
|
|
915
|
-
replaceRegistrationIds: [],
|
|
916
|
-
options: [],
|
|
917
757
|
groupPrice: groupPrice2,
|
|
918
758
|
organizationId: organization.id,
|
|
919
759
|
groupId: group2.id,
|
|
920
760
|
memberId: member.id,
|
|
921
761
|
}),
|
|
922
762
|
],
|
|
923
|
-
balanceItems: [],
|
|
924
|
-
deleteRegistrationIds: [],
|
|
925
763
|
}),
|
|
926
|
-
administrationFee: 0,
|
|
927
|
-
freeContribution: 0,
|
|
928
764
|
paymentMethod: PaymentMethod.Payconiq,
|
|
929
765
|
redirectUrl: new URL('https://www.example.com'),
|
|
930
766
|
cancelUrl: new URL('https://www.example.com'),
|
|
931
767
|
totalPrice: 15,
|
|
932
|
-
customer: null,
|
|
933
768
|
});
|
|
934
769
|
|
|
935
|
-
nock('https://api.ext.payconiq.com')
|
|
936
|
-
.post('/v3/payments')
|
|
937
|
-
.reply(200, {
|
|
938
|
-
paymentId: 'testPaymentId',
|
|
939
|
-
_links: {
|
|
940
|
-
checkout: {
|
|
941
|
-
href: 'https://www.example.com',
|
|
942
|
-
},
|
|
943
|
-
},
|
|
944
|
-
});
|
|
945
|
-
// #endregion
|
|
946
|
-
|
|
947
|
-
// act
|
|
948
770
|
const response = await post(body, organization, token);
|
|
949
771
|
|
|
950
|
-
// assert
|
|
951
772
|
expect(response.body).toBeDefined();
|
|
952
773
|
expect(response.body.registrations.length).toBe(1);
|
|
774
|
+
expect(response.body.paymentUrl).toMatch(/payconiq\.com/);
|
|
775
|
+
|
|
776
|
+
expect(response.body.registrations[0]).toMatchObject({
|
|
777
|
+
registeredAt: null,
|
|
778
|
+
deactivatedAt: null,
|
|
779
|
+
reservedUntil: expect.any(Date),
|
|
780
|
+
});
|
|
953
781
|
|
|
954
|
-
|
|
955
|
-
expect(
|
|
956
|
-
expect(
|
|
782
|
+
await group2.refresh();
|
|
783
|
+
expect(group2.settings.registeredMembers).toBe(0);
|
|
784
|
+
expect(group2.settings.reservedMembers).toBe(1);
|
|
957
785
|
});
|
|
958
786
|
|
|
959
|
-
test('Register for group with trial should set
|
|
787
|
+
test('Register for group with trial should set trial period', async () => {
|
|
960
788
|
// #region arrange
|
|
961
789
|
const date = new Date('2023-05-14');
|
|
962
|
-
jest.useFakeTimers().setSystemTime(date);
|
|
790
|
+
jest.useFakeTimers({ advanceTimers: true, doNotFake: ['setTimeout', 'clearTimeout', 'hrtime', 'nextTick', 'performance', 'queueMicrotask', 'setImmediate', 'clearImmediate'] }).setSystemTime(date);
|
|
963
791
|
|
|
964
792
|
try {
|
|
965
793
|
const { member, group, groupPrice, organization, token } = await initData();
|
|
@@ -987,7 +815,6 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
987
815
|
freeContribution: 0,
|
|
988
816
|
paymentMethod: PaymentMethod.PointOfSale,
|
|
989
817
|
totalPrice: 0,
|
|
990
|
-
asOrganizationId: organization.id,
|
|
991
818
|
customer: null,
|
|
992
819
|
});
|
|
993
820
|
// #endregion
|
|
@@ -1006,9 +833,9 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
1006
833
|
expect(trialUntil!.getDate()).toBe(19);
|
|
1007
834
|
}
|
|
1008
835
|
finally {
|
|
1009
|
-
jest.
|
|
836
|
+
jest.useRealTimers();
|
|
1010
837
|
}
|
|
1011
|
-
});
|
|
838
|
+
}, 20_000);
|
|
1012
839
|
|
|
1013
840
|
test('Should update group stock reservations', async () => {
|
|
1014
841
|
// #region arrange
|
|
@@ -1035,8 +862,7 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
1035
862
|
administrationFee: 0,
|
|
1036
863
|
freeContribution: 0,
|
|
1037
864
|
paymentMethod: PaymentMethod.PointOfSale,
|
|
1038
|
-
totalPrice:
|
|
1039
|
-
asOrganizationId: organization.id,
|
|
865
|
+
totalPrice: 25_00,
|
|
1040
866
|
customer: null,
|
|
1041
867
|
});
|
|
1042
868
|
// #endregion
|
|
@@ -1178,7 +1004,6 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
1178
1004
|
});
|
|
1179
1005
|
|
|
1180
1006
|
test('Should fail if max option exceeded', async () => {
|
|
1181
|
-
// #region arrange
|
|
1182
1007
|
const { organization, group, groupPrice, token, member } = await initData();
|
|
1183
1008
|
|
|
1184
1009
|
const option1 = GroupOption.create({
|
|
@@ -1187,8 +1012,8 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
1187
1012
|
maximum: 5,
|
|
1188
1013
|
allowAmount: true,
|
|
1189
1014
|
price: ReduceablePrice.create({
|
|
1190
|
-
price:
|
|
1191
|
-
reducedPrice:
|
|
1015
|
+
price: 5_00,
|
|
1016
|
+
reducedPrice: 3_00,
|
|
1192
1017
|
}),
|
|
1193
1018
|
});
|
|
1194
1019
|
|
|
@@ -1198,8 +1023,8 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
1198
1023
|
maximum: 2,
|
|
1199
1024
|
allowAmount: true,
|
|
1200
1025
|
price: ReduceablePrice.create({
|
|
1201
|
-
price:
|
|
1202
|
-
reducedPrice:
|
|
1026
|
+
price: 3_00,
|
|
1027
|
+
reducedPrice: 1_00,
|
|
1203
1028
|
}),
|
|
1204
1029
|
});
|
|
1205
1030
|
|
|
@@ -1213,7 +1038,252 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
1213
1038
|
optionMenu,
|
|
1214
1039
|
];
|
|
1215
1040
|
|
|
1216
|
-
await group.save();
|
|
1041
|
+
await group.save();
|
|
1042
|
+
|
|
1043
|
+
const body = IDRegisterCheckout.create({
|
|
1044
|
+
cart: IDRegisterCart.create({
|
|
1045
|
+
items: [
|
|
1046
|
+
IDRegisterItem.create({
|
|
1047
|
+
id: uuidv4(),
|
|
1048
|
+
replaceRegistrationIds: [],
|
|
1049
|
+
options: [
|
|
1050
|
+
RegisterItemOption.create({
|
|
1051
|
+
option: option1,
|
|
1052
|
+
amount: 2,
|
|
1053
|
+
optionMenu,
|
|
1054
|
+
}),
|
|
1055
|
+
RegisterItemOption.create({
|
|
1056
|
+
option: option2,
|
|
1057
|
+
amount: 5,
|
|
1058
|
+
optionMenu,
|
|
1059
|
+
}),
|
|
1060
|
+
],
|
|
1061
|
+
groupPrice,
|
|
1062
|
+
organizationId: organization.id,
|
|
1063
|
+
groupId: group.id,
|
|
1064
|
+
memberId: member.id,
|
|
1065
|
+
}),
|
|
1066
|
+
],
|
|
1067
|
+
balanceItems: [
|
|
1068
|
+
],
|
|
1069
|
+
deleteRegistrationIds: [],
|
|
1070
|
+
}),
|
|
1071
|
+
administrationFee: 0,
|
|
1072
|
+
freeContribution: 0,
|
|
1073
|
+
paymentMethod: PaymentMethod.PointOfSale,
|
|
1074
|
+
totalPrice: 50_00,
|
|
1075
|
+
customer: null,
|
|
1076
|
+
});
|
|
1077
|
+
|
|
1078
|
+
await expect(async () => await post(body, organization, token))
|
|
1079
|
+
.rejects
|
|
1080
|
+
.toThrow(new RegExp('Option maximum exceeded'));
|
|
1081
|
+
});
|
|
1082
|
+
|
|
1083
|
+
test('Should not fail if max option not exceeded', async () => {
|
|
1084
|
+
const { organization, group, groupPrice, token, member } = await initData();
|
|
1085
|
+
|
|
1086
|
+
const option1 = GroupOption.create({
|
|
1087
|
+
name: 'option 1',
|
|
1088
|
+
stock: 4,
|
|
1089
|
+
maximum: 5,
|
|
1090
|
+
allowAmount: true,
|
|
1091
|
+
price: ReduceablePrice.create({
|
|
1092
|
+
price: 5_00,
|
|
1093
|
+
reducedPrice: 3_00,
|
|
1094
|
+
}),
|
|
1095
|
+
});
|
|
1096
|
+
|
|
1097
|
+
const option2 = GroupOption.create({
|
|
1098
|
+
name: 'option 2',
|
|
1099
|
+
stock: 5,
|
|
1100
|
+
maximum: 5,
|
|
1101
|
+
allowAmount: true,
|
|
1102
|
+
price: ReduceablePrice.create({
|
|
1103
|
+
price: 3_00,
|
|
1104
|
+
reducedPrice: 1_00,
|
|
1105
|
+
}),
|
|
1106
|
+
});
|
|
1107
|
+
|
|
1108
|
+
const optionMenu = GroupOptionMenu.create({
|
|
1109
|
+
name: 'option menu 1',
|
|
1110
|
+
multipleChoice: true,
|
|
1111
|
+
options: [option1, option2],
|
|
1112
|
+
});
|
|
1113
|
+
|
|
1114
|
+
group.settings.optionMenus = [
|
|
1115
|
+
optionMenu,
|
|
1116
|
+
];
|
|
1117
|
+
|
|
1118
|
+
await group.save();
|
|
1119
|
+
|
|
1120
|
+
const body = IDRegisterCheckout.create({
|
|
1121
|
+
cart: IDRegisterCart.create({
|
|
1122
|
+
items: [
|
|
1123
|
+
IDRegisterItem.create({
|
|
1124
|
+
id: uuidv4(),
|
|
1125
|
+
replaceRegistrationIds: [],
|
|
1126
|
+
options: [
|
|
1127
|
+
RegisterItemOption.create({
|
|
1128
|
+
option: option1,
|
|
1129
|
+
amount: 2,
|
|
1130
|
+
optionMenu,
|
|
1131
|
+
}),
|
|
1132
|
+
RegisterItemOption.create({
|
|
1133
|
+
option: option2,
|
|
1134
|
+
amount: 5,
|
|
1135
|
+
optionMenu,
|
|
1136
|
+
}),
|
|
1137
|
+
],
|
|
1138
|
+
groupPrice,
|
|
1139
|
+
organizationId: organization.id,
|
|
1140
|
+
groupId: group.id,
|
|
1141
|
+
memberId: member.id,
|
|
1142
|
+
}),
|
|
1143
|
+
],
|
|
1144
|
+
balanceItems: [
|
|
1145
|
+
],
|
|
1146
|
+
deleteRegistrationIds: [],
|
|
1147
|
+
}),
|
|
1148
|
+
administrationFee: 0,
|
|
1149
|
+
freeContribution: 0,
|
|
1150
|
+
paymentMethod: PaymentMethod.PointOfSale,
|
|
1151
|
+
totalPrice: 50_00,
|
|
1152
|
+
customer: null,
|
|
1153
|
+
});
|
|
1154
|
+
|
|
1155
|
+
const result = await post(body, organization, token);
|
|
1156
|
+
expect(result).toBeDefined();
|
|
1157
|
+
});
|
|
1158
|
+
});
|
|
1159
|
+
|
|
1160
|
+
describe('Register as organization', () => {
|
|
1161
|
+
beforeEach(() => {
|
|
1162
|
+
defaultPermissionLevel = PermissionLevel.Full;
|
|
1163
|
+
});
|
|
1164
|
+
|
|
1165
|
+
test('Should reuse recently deactivated registration', async () => {
|
|
1166
|
+
const { organization, group, groupPrice, token, member } = await initData();
|
|
1167
|
+
group.settings.allowRegistrationsByOrganization = true;
|
|
1168
|
+
await group.save();
|
|
1169
|
+
|
|
1170
|
+
const firstRegistration = await new RegistrationFactory({
|
|
1171
|
+
member,
|
|
1172
|
+
group,
|
|
1173
|
+
groupPrice,
|
|
1174
|
+
}).create();
|
|
1175
|
+
|
|
1176
|
+
firstRegistration.deactivatedAt = new Date();
|
|
1177
|
+
await firstRegistration.save();
|
|
1178
|
+
|
|
1179
|
+
const body = IDRegisterCheckout.create({
|
|
1180
|
+
cart: IDRegisterCart.create({
|
|
1181
|
+
items: [
|
|
1182
|
+
IDRegisterItem.create({
|
|
1183
|
+
id: uuidv4(),
|
|
1184
|
+
replaceRegistrationIds: [],
|
|
1185
|
+
options: [],
|
|
1186
|
+
groupPrice,
|
|
1187
|
+
organizationId: organization.id,
|
|
1188
|
+
groupId: group.id,
|
|
1189
|
+
memberId: member.id,
|
|
1190
|
+
}),
|
|
1191
|
+
],
|
|
1192
|
+
balanceItems: [
|
|
1193
|
+
],
|
|
1194
|
+
deleteRegistrationIds: [],
|
|
1195
|
+
}),
|
|
1196
|
+
administrationFee: 0,
|
|
1197
|
+
freeContribution: 0,
|
|
1198
|
+
paymentMethod: PaymentMethod.PointOfSale,
|
|
1199
|
+
totalPrice: 25_00,
|
|
1200
|
+
asOrganizationId: organization.id,
|
|
1201
|
+
});
|
|
1202
|
+
|
|
1203
|
+
const response = await post(body, organization, token);
|
|
1204
|
+
expect(response.body.registrations.length).toBe(1);
|
|
1205
|
+
expect(response.body.registrations[0].id).toEqual(firstRegistration.id);
|
|
1206
|
+
});
|
|
1207
|
+
|
|
1208
|
+
test('Cannot pay balances as organization', async () => {
|
|
1209
|
+
const { member, user, organization, token } = await initData();
|
|
1210
|
+
|
|
1211
|
+
const balanceItem1 = await new BalanceItemFactory({
|
|
1212
|
+
organizationId: organization.id,
|
|
1213
|
+
memberId: member.id,
|
|
1214
|
+
userId: user.id,
|
|
1215
|
+
payingOrganizationId: organization.id,
|
|
1216
|
+
type: BalanceItemType.Registration,
|
|
1217
|
+
amount: 10,
|
|
1218
|
+
unitPrice: 2,
|
|
1219
|
+
}).create();
|
|
1220
|
+
|
|
1221
|
+
const cartItem = BalanceItemCartItem.create({
|
|
1222
|
+
item: balanceItem1.getStructure(),
|
|
1223
|
+
price: 20,
|
|
1224
|
+
});
|
|
1225
|
+
|
|
1226
|
+
const body = IDRegisterCheckout.create({
|
|
1227
|
+
cart: IDRegisterCart.create({
|
|
1228
|
+
items: [],
|
|
1229
|
+
balanceItems: [
|
|
1230
|
+
cartItem,
|
|
1231
|
+
],
|
|
1232
|
+
deleteRegistrationIds: [],
|
|
1233
|
+
}),
|
|
1234
|
+
administrationFee: 0,
|
|
1235
|
+
freeContribution: 0,
|
|
1236
|
+
paymentMethod: PaymentMethod.PointOfSale,
|
|
1237
|
+
totalPrice: 20,
|
|
1238
|
+
asOrganizationId: organization.id,
|
|
1239
|
+
customer: null,
|
|
1240
|
+
});
|
|
1241
|
+
|
|
1242
|
+
await expect(post(body, organization, token))
|
|
1243
|
+
.rejects
|
|
1244
|
+
.toThrow(STExpect.simpleError({
|
|
1245
|
+
code: 'cannot_pay_balance_items',
|
|
1246
|
+
}));
|
|
1247
|
+
});
|
|
1248
|
+
});
|
|
1249
|
+
|
|
1250
|
+
describe('Register by other organization', () => {
|
|
1251
|
+
beforeEach(() => {
|
|
1252
|
+
defaultPermissionLevel = PermissionLevel.Full;
|
|
1253
|
+
});
|
|
1254
|
+
|
|
1255
|
+
async function initDualData(options?: Parameters<typeof initData>[0]) {
|
|
1256
|
+
const base = await initData(options);
|
|
1257
|
+
|
|
1258
|
+
base.group.settings.allowRegistrationsByOrganization = true;
|
|
1259
|
+
await base.group.save();
|
|
1260
|
+
|
|
1261
|
+
// Give the user permission for a different organization
|
|
1262
|
+
const { organization: organization2 } = await initOrganization();
|
|
1263
|
+
base.user.permissions = UserPermissions.create({
|
|
1264
|
+
organizationPermissions: new Map([
|
|
1265
|
+
[organization2.id, Permissions.create({
|
|
1266
|
+
level: options?.permissionLevel ?? defaultPermissionLevel,
|
|
1267
|
+
})],
|
|
1268
|
+
]),
|
|
1269
|
+
});
|
|
1270
|
+
await base.user.save();
|
|
1271
|
+
|
|
1272
|
+
return {
|
|
1273
|
+
...base,
|
|
1274
|
+
organization2,
|
|
1275
|
+
};
|
|
1276
|
+
}
|
|
1277
|
+
|
|
1278
|
+
test('Should set paying organization id', async () => {
|
|
1279
|
+
const { organization, group, groupPrice, member, token, organization2 } = await initDualData();
|
|
1280
|
+
|
|
1281
|
+
const company = Company.create({
|
|
1282
|
+
name: 'test company',
|
|
1283
|
+
});
|
|
1284
|
+
|
|
1285
|
+
organization2.meta.companies.push(company);
|
|
1286
|
+
await organization2.save();
|
|
1217
1287
|
|
|
1218
1288
|
const body = IDRegisterCheckout.create({
|
|
1219
1289
|
cart: IDRegisterCart.create({
|
|
@@ -1221,18 +1291,7 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
1221
1291
|
IDRegisterItem.create({
|
|
1222
1292
|
id: uuidv4(),
|
|
1223
1293
|
replaceRegistrationIds: [],
|
|
1224
|
-
options: [
|
|
1225
|
-
RegisterItemOption.create({
|
|
1226
|
-
option: option1,
|
|
1227
|
-
amount: 2,
|
|
1228
|
-
optionMenu,
|
|
1229
|
-
}),
|
|
1230
|
-
RegisterItemOption.create({
|
|
1231
|
-
option: option2,
|
|
1232
|
-
amount: 5,
|
|
1233
|
-
optionMenu,
|
|
1234
|
-
}),
|
|
1235
|
-
],
|
|
1294
|
+
options: [],
|
|
1236
1295
|
groupPrice,
|
|
1237
1296
|
organizationId: organization.id,
|
|
1238
1297
|
groupId: group.id,
|
|
@@ -1246,55 +1305,27 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
1246
1305
|
administrationFee: 0,
|
|
1247
1306
|
freeContribution: 0,
|
|
1248
1307
|
paymentMethod: PaymentMethod.PointOfSale,
|
|
1249
|
-
totalPrice:
|
|
1250
|
-
customer:
|
|
1308
|
+
totalPrice: 25_00,
|
|
1309
|
+
customer: PaymentCustomer.create({
|
|
1310
|
+
company,
|
|
1311
|
+
}),
|
|
1312
|
+
asOrganizationId: organization2.id,
|
|
1251
1313
|
});
|
|
1252
|
-
// #endregion
|
|
1253
1314
|
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
.toThrow(new RegExp('Option maximum exceeded'));
|
|
1258
|
-
// #endregion
|
|
1315
|
+
const response = await post(body, organization, token);
|
|
1316
|
+
expect(response.body.registrations.length).toBe(1);
|
|
1317
|
+
expect(response.body.registrations[0].payingOrganizationId).toEqual(organization2.id);
|
|
1259
1318
|
});
|
|
1260
1319
|
|
|
1261
|
-
test('Should
|
|
1262
|
-
|
|
1263
|
-
const { organization, group, groupPrice, token, member } = await initData();
|
|
1264
|
-
|
|
1265
|
-
const option1 = GroupOption.create({
|
|
1266
|
-
name: 'option 1',
|
|
1267
|
-
stock: 4,
|
|
1268
|
-
maximum: 5,
|
|
1269
|
-
allowAmount: true,
|
|
1270
|
-
price: ReduceablePrice.create({
|
|
1271
|
-
price: 5,
|
|
1272
|
-
reducedPrice: 3,
|
|
1273
|
-
}),
|
|
1274
|
-
});
|
|
1275
|
-
|
|
1276
|
-
const option2 = GroupOption.create({
|
|
1277
|
-
name: 'option 2',
|
|
1278
|
-
stock: 5,
|
|
1279
|
-
maximum: 5,
|
|
1280
|
-
allowAmount: true,
|
|
1281
|
-
price: ReduceablePrice.create({
|
|
1282
|
-
price: 3,
|
|
1283
|
-
reducedPrice: 1,
|
|
1284
|
-
}),
|
|
1285
|
-
});
|
|
1320
|
+
test('Should fail if not sufficient permissions', async () => {
|
|
1321
|
+
const { organization, group, groupPrice, member, token, organization2 } = await initDualData({ permissionLevel: PermissionLevel.Read });
|
|
1286
1322
|
|
|
1287
|
-
const
|
|
1288
|
-
name: '
|
|
1289
|
-
multipleChoice: true,
|
|
1290
|
-
options: [option1, option2],
|
|
1323
|
+
const company = Company.create({
|
|
1324
|
+
name: 'test company',
|
|
1291
1325
|
});
|
|
1292
1326
|
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
];
|
|
1296
|
-
|
|
1297
|
-
await group.save();
|
|
1327
|
+
organization2.meta.companies.push(company);
|
|
1328
|
+
await organization2.save();
|
|
1298
1329
|
|
|
1299
1330
|
const body = IDRegisterCheckout.create({
|
|
1300
1331
|
cart: IDRegisterCart.create({
|
|
@@ -1302,18 +1333,7 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
1302
1333
|
IDRegisterItem.create({
|
|
1303
1334
|
id: uuidv4(),
|
|
1304
1335
|
replaceRegistrationIds: [],
|
|
1305
|
-
options: [
|
|
1306
|
-
RegisterItemOption.create({
|
|
1307
|
-
option: option1,
|
|
1308
|
-
amount: 2,
|
|
1309
|
-
optionMenu,
|
|
1310
|
-
}),
|
|
1311
|
-
RegisterItemOption.create({
|
|
1312
|
-
option: option2,
|
|
1313
|
-
amount: 5,
|
|
1314
|
-
optionMenu,
|
|
1315
|
-
}),
|
|
1316
|
-
],
|
|
1336
|
+
options: [],
|
|
1317
1337
|
groupPrice,
|
|
1318
1338
|
organizationId: organization.id,
|
|
1319
1339
|
groupId: group.id,
|
|
@@ -1327,34 +1347,23 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
1327
1347
|
administrationFee: 0,
|
|
1328
1348
|
freeContribution: 0,
|
|
1329
1349
|
paymentMethod: PaymentMethod.PointOfSale,
|
|
1330
|
-
totalPrice:
|
|
1331
|
-
customer:
|
|
1350
|
+
totalPrice: 25_00,
|
|
1351
|
+
customer: PaymentCustomer.create({
|
|
1352
|
+
company,
|
|
1353
|
+
}),
|
|
1354
|
+
asOrganizationId: organization2.id,
|
|
1332
1355
|
});
|
|
1333
|
-
// #endregion
|
|
1334
1356
|
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
// #endregion
|
|
1357
|
+
await expect(async () => await post(body, organization, token))
|
|
1358
|
+
.rejects
|
|
1359
|
+
.toThrow(STExpect.simpleError({ code: 'forbidden' }));
|
|
1339
1360
|
});
|
|
1340
|
-
});
|
|
1341
1361
|
|
|
1342
|
-
describe('Register by other organization', () => {
|
|
1343
1362
|
test('Should fail if disabled by group', async () => {
|
|
1344
|
-
|
|
1345
|
-
const { organization, group, groupPrice, token, member, user } = await initData();
|
|
1346
|
-
|
|
1347
|
-
const { organization: organization2 } = await initData();
|
|
1348
|
-
|
|
1349
|
-
user.permissions = UserPermissions.create({
|
|
1350
|
-
organizationPermissions: new Map([
|
|
1351
|
-
[organization2.id, Permissions.create({
|
|
1352
|
-
level: PermissionLevel.Full,
|
|
1353
|
-
})],
|
|
1354
|
-
]),
|
|
1355
|
-
});
|
|
1363
|
+
const { organization, group, groupPrice, member, token, organization2 } = await initDualData();
|
|
1356
1364
|
|
|
1357
|
-
|
|
1365
|
+
group.settings.allowRegistrationsByOrganization = false;
|
|
1366
|
+
await group.save();
|
|
1358
1367
|
|
|
1359
1368
|
const body = IDRegisterCheckout.create({
|
|
1360
1369
|
cart: IDRegisterCart.create({
|
|
@@ -1376,36 +1385,18 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
1376
1385
|
administrationFee: 0,
|
|
1377
1386
|
freeContribution: 0,
|
|
1378
1387
|
paymentMethod: PaymentMethod.PointOfSale,
|
|
1379
|
-
totalPrice:
|
|
1388
|
+
totalPrice: 25_00,
|
|
1380
1389
|
customer: null,
|
|
1381
1390
|
asOrganizationId: organization2.id,
|
|
1382
1391
|
});
|
|
1383
|
-
// #endregion
|
|
1384
1392
|
|
|
1385
|
-
// #region act and assert
|
|
1386
1393
|
await expect(async () => await post(body, organization, token))
|
|
1387
1394
|
.rejects
|
|
1388
|
-
.toThrow(
|
|
1389
|
-
// #endregion
|
|
1395
|
+
.toThrow(STExpect.simpleError({ code: 'as_organization_disabled' }));
|
|
1390
1396
|
});
|
|
1391
1397
|
|
|
1392
1398
|
test('Should fail if no customer', async () => {
|
|
1393
|
-
|
|
1394
|
-
const { organization, group, groupPrice, token, member, user } = await initData();
|
|
1395
|
-
group.settings.allowRegistrationsByOrganization = true;
|
|
1396
|
-
await group.save();
|
|
1397
|
-
|
|
1398
|
-
const { organization: organization2 } = await initData();
|
|
1399
|
-
|
|
1400
|
-
user.permissions = UserPermissions.create({
|
|
1401
|
-
organizationPermissions: new Map([
|
|
1402
|
-
[organization2.id, Permissions.create({
|
|
1403
|
-
level: PermissionLevel.Full,
|
|
1404
|
-
})],
|
|
1405
|
-
]),
|
|
1406
|
-
});
|
|
1407
|
-
|
|
1408
|
-
await user.save();
|
|
1399
|
+
const { organization, group, groupPrice, member, token, organization2 } = await initDualData();
|
|
1409
1400
|
|
|
1410
1401
|
const body = IDRegisterCheckout.create({
|
|
1411
1402
|
cart: IDRegisterCart.create({
|
|
@@ -1427,36 +1418,24 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
1427
1418
|
administrationFee: 0,
|
|
1428
1419
|
freeContribution: 0,
|
|
1429
1420
|
paymentMethod: PaymentMethod.PointOfSale,
|
|
1430
|
-
totalPrice:
|
|
1421
|
+
totalPrice: 25_00,
|
|
1431
1422
|
customer: null,
|
|
1432
1423
|
asOrganizationId: organization2.id,
|
|
1433
1424
|
});
|
|
1434
|
-
// #endregion
|
|
1435
1425
|
|
|
1436
|
-
// #region act and assert
|
|
1437
1426
|
await expect(async () => await post(body, organization, token))
|
|
1438
1427
|
.rejects
|
|
1439
1428
|
.toThrow(new RegExp('customer is required when paying as an organization'));
|
|
1440
|
-
// #endregion
|
|
1441
1429
|
});
|
|
1442
1430
|
|
|
1443
|
-
test('
|
|
1444
|
-
|
|
1445
|
-
const { organization, group, groupPrice, token, member, user } = await initData();
|
|
1446
|
-
group.settings.allowRegistrationsByOrganization = true;
|
|
1447
|
-
await group.save();
|
|
1448
|
-
|
|
1449
|
-
const { organization: organization2 } = await initData();
|
|
1450
|
-
|
|
1451
|
-
user.permissions = UserPermissions.create({
|
|
1452
|
-
organizationPermissions: new Map([
|
|
1453
|
-
[organization2.id, Permissions.create({
|
|
1454
|
-
level: PermissionLevel.Full,
|
|
1455
|
-
})],
|
|
1456
|
-
]),
|
|
1457
|
-
});
|
|
1431
|
+
test('Deleting registrations is not allowed', async () => {
|
|
1432
|
+
const { member, group, groupPrice, organization, token, organization2 } = await initDualData();
|
|
1458
1433
|
|
|
1459
|
-
await
|
|
1434
|
+
const registration = await new RegistrationFactory({
|
|
1435
|
+
member,
|
|
1436
|
+
group,
|
|
1437
|
+
groupPrice,
|
|
1438
|
+
}).create();
|
|
1460
1439
|
|
|
1461
1440
|
const body = IDRegisterCheckout.create({
|
|
1462
1441
|
cart: IDRegisterCart.create({
|
|
@@ -1471,45 +1450,24 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
1471
1450
|
memberId: member.id,
|
|
1472
1451
|
}),
|
|
1473
1452
|
],
|
|
1474
|
-
balanceItems: [
|
|
1475
|
-
],
|
|
1476
|
-
deleteRegistrationIds: [],
|
|
1453
|
+
balanceItems: [],
|
|
1454
|
+
deleteRegistrationIds: [registration.id],
|
|
1477
1455
|
}),
|
|
1478
1456
|
administrationFee: 0,
|
|
1479
1457
|
freeContribution: 0,
|
|
1480
1458
|
paymentMethod: PaymentMethod.PointOfSale,
|
|
1481
|
-
totalPrice:
|
|
1482
|
-
customer: PaymentCustomer.create({
|
|
1483
|
-
company: null,
|
|
1484
|
-
}),
|
|
1459
|
+
totalPrice: 5,
|
|
1485
1460
|
asOrganizationId: organization2.id,
|
|
1461
|
+
customer: null,
|
|
1486
1462
|
});
|
|
1487
|
-
// #endregion
|
|
1488
1463
|
|
|
1489
|
-
// #region act and assert
|
|
1490
1464
|
await expect(async () => await post(body, organization, token))
|
|
1491
1465
|
.rejects
|
|
1492
|
-
.toThrow(
|
|
1493
|
-
// #endregion
|
|
1466
|
+
.toThrow(STExpect.simpleError({ code: 'forbidden' }));
|
|
1494
1467
|
});
|
|
1495
1468
|
|
|
1496
|
-
test('Should fail if company
|
|
1497
|
-
|
|
1498
|
-
const { organization, group, groupPrice, token, member, user } = await initData();
|
|
1499
|
-
group.settings.allowRegistrationsByOrganization = true;
|
|
1500
|
-
await group.save();
|
|
1501
|
-
|
|
1502
|
-
const { organization: organization2 } = await initData();
|
|
1503
|
-
|
|
1504
|
-
user.permissions = UserPermissions.create({
|
|
1505
|
-
organizationPermissions: new Map([
|
|
1506
|
-
[organization2.id, Permissions.create({
|
|
1507
|
-
level: PermissionLevel.Full,
|
|
1508
|
-
})],
|
|
1509
|
-
]),
|
|
1510
|
-
});
|
|
1511
|
-
|
|
1512
|
-
await user.save();
|
|
1469
|
+
test('Should fail if no company on customer', async () => {
|
|
1470
|
+
const { organization, group, groupPrice, member, token, organization2 } = await initDualData();
|
|
1513
1471
|
|
|
1514
1472
|
const body = IDRegisterCheckout.create({
|
|
1515
1473
|
cart: IDRegisterCart.create({
|
|
@@ -1531,46 +1489,20 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
1531
1489
|
administrationFee: 0,
|
|
1532
1490
|
freeContribution: 0,
|
|
1533
1491
|
paymentMethod: PaymentMethod.PointOfSale,
|
|
1534
|
-
totalPrice:
|
|
1492
|
+
totalPrice: 25_00,
|
|
1535
1493
|
customer: PaymentCustomer.create({
|
|
1536
|
-
company:
|
|
1537
|
-
name: 'test company',
|
|
1538
|
-
}),
|
|
1494
|
+
company: null,
|
|
1539
1495
|
}),
|
|
1540
1496
|
asOrganizationId: organization2.id,
|
|
1541
1497
|
});
|
|
1542
|
-
// #endregion
|
|
1543
1498
|
|
|
1544
|
-
// #region act and assert
|
|
1545
1499
|
await expect(async () => await post(body, organization, token))
|
|
1546
1500
|
.rejects
|
|
1547
|
-
.toThrow(new RegExp('
|
|
1548
|
-
// #endregion
|
|
1501
|
+
.toThrow(new RegExp('customer.company is required'));
|
|
1549
1502
|
});
|
|
1550
1503
|
|
|
1551
|
-
test('Should
|
|
1552
|
-
|
|
1553
|
-
const { organization, group, groupPrice, token, member, user } = await initData();
|
|
1554
|
-
group.settings.allowRegistrationsByOrganization = true;
|
|
1555
|
-
await group.save();
|
|
1556
|
-
|
|
1557
|
-
const { organization: organization2 } = await initData();
|
|
1558
|
-
const company = Company.create({
|
|
1559
|
-
name: 'test company',
|
|
1560
|
-
});
|
|
1561
|
-
|
|
1562
|
-
organization2.meta.companies.push(company);
|
|
1563
|
-
await organization2.save();
|
|
1564
|
-
|
|
1565
|
-
user.permissions = UserPermissions.create({
|
|
1566
|
-
organizationPermissions: new Map([
|
|
1567
|
-
[organization2.id, Permissions.create({
|
|
1568
|
-
level: PermissionLevel.Full,
|
|
1569
|
-
})],
|
|
1570
|
-
]),
|
|
1571
|
-
});
|
|
1572
|
-
|
|
1573
|
-
await user.save();
|
|
1504
|
+
test('Should fail if company does not exist on organization', async () => {
|
|
1505
|
+
const { organization, group, groupPrice, member, token, organization2 } = await initDualData();
|
|
1574
1506
|
|
|
1575
1507
|
const body = IDRegisterCheckout.create({
|
|
1576
1508
|
cart: IDRegisterCart.create({
|
|
@@ -1592,25 +1524,27 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
1592
1524
|
administrationFee: 0,
|
|
1593
1525
|
freeContribution: 0,
|
|
1594
1526
|
paymentMethod: PaymentMethod.PointOfSale,
|
|
1595
|
-
totalPrice:
|
|
1527
|
+
totalPrice: 25_00,
|
|
1596
1528
|
customer: PaymentCustomer.create({
|
|
1597
|
-
company
|
|
1529
|
+
company: Company.create({
|
|
1530
|
+
name: 'test company',
|
|
1531
|
+
}),
|
|
1598
1532
|
}),
|
|
1599
1533
|
asOrganizationId: organization2.id,
|
|
1600
1534
|
});
|
|
1601
|
-
// #endregion
|
|
1602
1535
|
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
expect(response.body.registrations[0].payingOrganizationId).toEqual(organization2.id);
|
|
1607
|
-
// #endregion
|
|
1536
|
+
await expect(async () => await post(body, organization, token))
|
|
1537
|
+
.rejects
|
|
1538
|
+
.toThrow(new RegExp('Oeps, de facturatiegegevens die je probeerde te selecteren lijken niet meer te bestaan.'));
|
|
1608
1539
|
});
|
|
1609
1540
|
});
|
|
1610
1541
|
|
|
1611
1542
|
describe('Replace registrations', () => {
|
|
1543
|
+
beforeEach(() => {
|
|
1544
|
+
defaultPermissionLevel = PermissionLevel.Full;
|
|
1545
|
+
});
|
|
1546
|
+
|
|
1612
1547
|
test('Should update registered members', async () => {
|
|
1613
|
-
// #region arrange
|
|
1614
1548
|
const { organization, group: group1, groupPrice: groupPrice1, token, member } = await initData();
|
|
1615
1549
|
|
|
1616
1550
|
const registration = await new RegistrationFactory({
|
|
@@ -1651,11 +1585,7 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
1651
1585
|
asOrganizationId: organization.id,
|
|
1652
1586
|
customer: null,
|
|
1653
1587
|
});
|
|
1654
|
-
// #endregion
|
|
1655
|
-
|
|
1656
|
-
// #region act and assert
|
|
1657
1588
|
|
|
1658
|
-
// update occupancy to be sure occupancy is 1
|
|
1659
1589
|
await group1.updateOccupancy();
|
|
1660
1590
|
expect(group1.settings.registeredMembers).toBe(1);
|
|
1661
1591
|
|
|
@@ -1673,16 +1603,14 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
1673
1603
|
// occupancy should go from 1 to 0 because the registration should be replaced
|
|
1674
1604
|
expect(updatedGroup1After!.settings.registeredMembers).toBe(0);
|
|
1675
1605
|
expect(updatedGroup1After!.settings.reservedMembers).toBe(0);
|
|
1676
|
-
// #endregion
|
|
1677
1606
|
});
|
|
1678
1607
|
|
|
1679
|
-
test('
|
|
1680
|
-
// #region arrange
|
|
1608
|
+
test('When replacing a registration, we should keep the original paying organization id', async () => {
|
|
1681
1609
|
const { organization, group: group1, groupPrice: groupPrice1, token, member, user } = await initData();
|
|
1682
1610
|
|
|
1683
1611
|
group1.settings.allowRegistrationsByOrganization = true;
|
|
1684
1612
|
await group1.save();
|
|
1685
|
-
const organization2 = await initOrganization();
|
|
1613
|
+
const { organization: organization2 } = await initOrganization();
|
|
1686
1614
|
|
|
1687
1615
|
user.permissions = UserPermissions.create({
|
|
1688
1616
|
organizationPermissions: new Map([
|
|
@@ -1726,7 +1654,7 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
1726
1654
|
administrationFee: 0,
|
|
1727
1655
|
freeContribution: 0,
|
|
1728
1656
|
paymentMethod: PaymentMethod.PointOfSale,
|
|
1729
|
-
totalPrice:
|
|
1657
|
+
totalPrice: 25_00,
|
|
1730
1658
|
asOrganizationId: organization2.id,
|
|
1731
1659
|
customer: PaymentCustomer.create({
|
|
1732
1660
|
company,
|
|
@@ -1739,7 +1667,7 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
1739
1667
|
|
|
1740
1668
|
const group = await new GroupFactory({
|
|
1741
1669
|
organization,
|
|
1742
|
-
price:
|
|
1670
|
+
price: 30_00,
|
|
1743
1671
|
stock: 5,
|
|
1744
1672
|
}).create();
|
|
1745
1673
|
|
|
@@ -1764,15 +1692,13 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
1764
1692
|
administrationFee: 0,
|
|
1765
1693
|
freeContribution: 0,
|
|
1766
1694
|
paymentMethod: PaymentMethod.PointOfSale,
|
|
1767
|
-
totalPrice:
|
|
1695
|
+
totalPrice: 30_00 - 25_00,
|
|
1768
1696
|
asOrganizationId: organization.id,
|
|
1769
1697
|
customer: PaymentCustomer.create({
|
|
1770
1698
|
company,
|
|
1771
1699
|
}),
|
|
1772
1700
|
});
|
|
1773
|
-
// #endregion
|
|
1774
1701
|
|
|
1775
|
-
// #region act and assert
|
|
1776
1702
|
const response = await post(body2, organization, token);
|
|
1777
1703
|
|
|
1778
1704
|
expect(response.body).toBeDefined();
|
|
@@ -1780,7 +1706,6 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
1780
1706
|
|
|
1781
1707
|
// the payingOrganizationId should equal the id of the paying organization of the replaced registration
|
|
1782
1708
|
expect(response.body.registrations[0].payingOrganizationId).toEqual(organization2.id);
|
|
1783
|
-
// #endregion
|
|
1784
1709
|
});
|
|
1785
1710
|
|
|
1786
1711
|
test('Replace registration by registration of other member should fail', async () => {
|
|
@@ -1887,6 +1812,10 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
1887
1812
|
});
|
|
1888
1813
|
|
|
1889
1814
|
describe('Delete registrations', () => {
|
|
1815
|
+
beforeEach(() => {
|
|
1816
|
+
defaultPermissionLevel = PermissionLevel.Full;
|
|
1817
|
+
});
|
|
1818
|
+
|
|
1890
1819
|
test('Should update registered members', async () => {
|
|
1891
1820
|
// #region arrange
|
|
1892
1821
|
const { member, group: group1, groupPrice: groupPrice1, organization: organization1, token } = await initData();
|
|
@@ -1954,9 +1883,10 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
1954
1883
|
// #endregion
|
|
1955
1884
|
});
|
|
1956
1885
|
|
|
1957
|
-
test('Should throw error if
|
|
1886
|
+
test('Should throw error if deleting registrations as normal member', async () => {
|
|
1958
1887
|
// #region arrange
|
|
1959
1888
|
const { member, group: group1, groupPrice: groupPrice1, organization: organization1, token } = await initData();
|
|
1889
|
+
await initPayconiq({ organization: organization1 });
|
|
1960
1890
|
|
|
1961
1891
|
const registration = await new RegistrationFactory({
|
|
1962
1892
|
member,
|
|
@@ -1969,7 +1899,6 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
1969
1899
|
organization: organization1,
|
|
1970
1900
|
price: 30,
|
|
1971
1901
|
stock: 5,
|
|
1972
|
-
maxMembers: 1,
|
|
1973
1902
|
}).create();
|
|
1974
1903
|
|
|
1975
1904
|
const groupPrice = group.settings.prices[0];
|
|
@@ -1998,16 +1927,8 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
1998
1927
|
totalPrice: 5,
|
|
1999
1928
|
customer: null,
|
|
2000
1929
|
});
|
|
2001
|
-
// #endregion
|
|
2002
|
-
|
|
2003
|
-
// #region act and assert
|
|
2004
|
-
|
|
2005
|
-
// update occupancy to be sure occupancy is 1
|
|
2006
|
-
await group1.updateOccupancy();
|
|
2007
|
-
expect(group1.settings.registeredMembers).toBe(1);
|
|
2008
1930
|
|
|
2009
1931
|
await expect(async () => await post(body, organization1, token)).rejects.toThrow('Permission denied: you are not allowed to delete registrations');
|
|
2010
|
-
// #endregion
|
|
2011
1932
|
});
|
|
2012
1933
|
|
|
2013
1934
|
test('Should deactivate registration', async () => {
|
|
@@ -2064,7 +1985,6 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
2064
1985
|
|
|
2065
1986
|
test('Should fail if invalid cancelation fee', async () => {
|
|
2066
1987
|
for (const cancellationFeePercentage of [10001, -1]) {
|
|
2067
|
-
// #region arrange
|
|
2068
1988
|
const { member, group: group1, groupPrice: groupPrice1, organization, token } = await initData();
|
|
2069
1989
|
|
|
2070
1990
|
const body1 = IDRegisterCheckout.create({
|
|
@@ -2086,7 +2006,7 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
2086
2006
|
administrationFee: 0,
|
|
2087
2007
|
freeContribution: 0,
|
|
2088
2008
|
paymentMethod: PaymentMethod.PointOfSale,
|
|
2089
|
-
totalPrice:
|
|
2009
|
+
totalPrice: 25_00,
|
|
2090
2010
|
asOrganizationId: organization.id,
|
|
2091
2011
|
customer: null,
|
|
2092
2012
|
});
|
|
@@ -2124,17 +2044,17 @@ describe('Endpoint.RegisterMembers', () => {
|
|
|
2124
2044
|
administrationFee: 0,
|
|
2125
2045
|
freeContribution: 0,
|
|
2126
2046
|
paymentMethod: PaymentMethod.PointOfSale,
|
|
2127
|
-
totalPrice: 30,
|
|
2047
|
+
totalPrice: 30 - 25 + Math.round(25 * cancellationFeePercentage / 10000),
|
|
2128
2048
|
asOrganizationId: organization.id,
|
|
2129
2049
|
customer: null,
|
|
2130
2050
|
});
|
|
2131
|
-
// #endregion
|
|
2132
2051
|
|
|
2133
|
-
// #region act and assert
|
|
2134
2052
|
await expect(async () => await post(body2, organization, token))
|
|
2135
2053
|
.rejects
|
|
2136
|
-
.toThrow(
|
|
2137
|
-
|
|
2054
|
+
.toThrow(STExpect.simpleError({
|
|
2055
|
+
field: 'cancellationFeePercentage',
|
|
2056
|
+
code: 'invalid_field',
|
|
2057
|
+
}));
|
|
2138
2058
|
}
|
|
2139
2059
|
});
|
|
2140
2060
|
|