@stamhoofd/structures 2.83.4 → 2.84.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/dist/index.d.ts +11 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -2
- package/dist/index.js.map +1 -1
- package/dist/src/AppliedRegistrationDiscount.d.ts +15 -0
- package/dist/src/AppliedRegistrationDiscount.d.ts.map +1 -0
- package/dist/src/AppliedRegistrationDiscount.js +24 -0
- package/dist/src/AppliedRegistrationDiscount.js.map +1 -0
- package/dist/src/BalanceItem.d.ts +13 -4
- package/dist/src/BalanceItem.d.ts.map +1 -1
- package/dist/src/BalanceItem.js +68 -22
- package/dist/src/BalanceItem.js.map +1 -1
- package/dist/src/BalanceItemDetailed.d.ts +2 -2
- package/dist/src/BalanceItemDetailed.d.ts.map +1 -1
- package/dist/src/BalanceItemDetailed.js +2 -2
- package/dist/src/BalanceItemDetailed.js.map +1 -1
- package/dist/src/BundleDiscount.d.ts +79 -0
- package/dist/src/BundleDiscount.d.ts.map +1 -0
- package/dist/src/BundleDiscount.js +379 -0
- package/dist/src/BundleDiscount.js.map +1 -0
- package/dist/src/BundleDiscountGroupPriceSettings.d.ts +15 -0
- package/dist/src/BundleDiscountGroupPriceSettings.d.ts.map +1 -0
- package/dist/src/BundleDiscountGroupPriceSettings.js +29 -0
- package/dist/src/BundleDiscountGroupPriceSettings.js.map +1 -0
- package/dist/src/Group.d.ts +2 -0
- package/dist/src/Group.d.ts.map +1 -1
- package/dist/src/Group.js +10 -0
- package/dist/src/Group.js.map +1 -1
- package/dist/src/GroupPriceDiscount.d.ts +14 -0
- package/dist/src/GroupPriceDiscount.d.ts.map +1 -0
- package/dist/src/GroupPriceDiscount.js +39 -0
- package/dist/src/GroupPriceDiscount.js.map +1 -0
- package/dist/src/GroupSettings.d.ts +7 -8
- package/dist/src/GroupSettings.d.ts.map +1 -1
- package/dist/src/GroupSettings.js +15 -29
- package/dist/src/GroupSettings.js.map +1 -1
- package/dist/src/Organization.d.ts +1 -1
- package/dist/src/Organization.d.ts.map +1 -1
- package/dist/src/Organization.js +15 -2
- package/dist/src/Organization.js.map +1 -1
- package/dist/src/Permissions.d.ts.map +1 -1
- package/dist/src/Permissions.js +1 -1
- package/dist/src/Permissions.js.map +1 -1
- package/dist/src/Platform.d.ts +1 -1
- package/dist/src/Platform.d.ts.map +1 -1
- package/dist/src/Platform.js +3 -3
- package/dist/src/Platform.js.map +1 -1
- package/dist/src/ReduceablePrice.d.ts +9 -0
- package/dist/src/ReduceablePrice.d.ts.map +1 -0
- package/dist/src/ReduceablePrice.js +29 -0
- package/dist/src/ReduceablePrice.js.map +1 -0
- package/dist/src/RegistrationPeriod.d.ts +2 -0
- package/dist/src/RegistrationPeriod.d.ts.map +1 -1
- package/dist/src/RegistrationPeriod.js +5 -0
- package/dist/src/RegistrationPeriod.js.map +1 -1
- package/dist/src/Token.d.ts.map +1 -1
- package/dist/src/Token.js +7 -4
- package/dist/src/Token.js.map +1 -1
- package/dist/src/Version.d.ts +1 -1
- package/dist/src/Version.js +1 -1
- package/dist/src/email/Email.d.ts +5 -3
- package/dist/src/email/Email.d.ts.map +1 -1
- package/dist/src/email/Email.js +3 -0
- package/dist/src/email/Email.js.map +1 -1
- package/dist/src/endpoints/RegisterResponse.d.ts +2 -2
- package/dist/src/endpoints/RegisterResponse.d.ts.map +1 -1
- package/dist/src/endpoints/RegisterResponse.js +2 -2
- package/dist/src/endpoints/RegisterResponse.js.map +1 -1
- package/dist/src/filters/ExcelExportRequest.d.ts +1 -0
- package/dist/src/filters/ExcelExportRequest.d.ts.map +1 -1
- package/dist/src/filters/ExcelExportRequest.js +1 -0
- package/dist/src/filters/ExcelExportRequest.js.map +1 -1
- package/dist/src/filters/FilterCompilers.d.ts +18 -0
- package/dist/src/filters/FilterCompilers.d.ts.map +1 -0
- package/dist/src/filters/FilterCompilers.js +110 -0
- package/dist/src/filters/FilterCompilers.js.map +1 -0
- package/dist/src/filters/InMemoryFilter.d.ts +5 -3
- package/dist/src/filters/InMemoryFilter.d.ts.map +1 -1
- package/dist/src/filters/InMemoryFilter.js +20 -75
- package/dist/src/filters/InMemoryFilter.js.map +1 -1
- package/dist/src/filters/InMemoryFilter.test.d.ts +2 -0
- package/dist/src/filters/InMemoryFilter.test.d.ts.map +1 -0
- package/dist/src/filters/InMemoryFilter.test.js +293 -0
- package/dist/src/filters/InMemoryFilter.test.js.map +1 -0
- package/dist/src/helpers/MemberPlatformMembershipHelper.d.ts +12 -0
- package/dist/src/helpers/MemberPlatformMembershipHelper.d.ts.map +1 -0
- package/dist/src/helpers/MemberPlatformMembershipHelper.js +74 -0
- package/dist/src/helpers/MemberPlatformMembershipHelper.js.map +1 -0
- package/dist/src/members/Member.d.ts +1 -0
- package/dist/src/members/Member.d.ts.map +1 -1
- package/dist/src/members/Member.js +3 -0
- package/dist/src/members/Member.js.map +1 -1
- package/dist/src/members/MembershipStatus.d.ts +13 -0
- package/dist/src/members/MembershipStatus.d.ts.map +1 -0
- package/dist/src/members/MembershipStatus.js +18 -0
- package/dist/src/members/MembershipStatus.js.map +1 -0
- package/dist/src/members/PaymentGeneral.js +1 -1
- package/dist/src/members/PaymentGeneral.js.map +1 -1
- package/dist/src/members/PaymentWithRegistrations.d.ts +2 -2
- package/dist/src/members/PaymentWithRegistrations.d.ts.map +1 -1
- package/dist/src/members/PaymentWithRegistrations.js +2 -2
- package/dist/src/members/PaymentWithRegistrations.js.map +1 -1
- package/dist/src/members/PlatformMember.d.ts +24 -14
- package/dist/src/members/PlatformMember.d.ts.map +1 -1
- package/dist/src/members/PlatformMember.js +93 -116
- package/dist/src/members/PlatformMember.js.map +1 -1
- package/dist/src/members/PlatformMember.test.js +4 -7
- package/dist/src/members/PlatformMember.test.js.map +1 -1
- package/dist/src/members/Registration.d.ts +37 -0
- package/dist/src/members/Registration.d.ts.map +1 -1
- package/dist/src/members/Registration.js +48 -0
- package/dist/src/members/Registration.js.map +1 -1
- package/dist/src/members/RegistrationWithMember.d.ts +15 -3
- package/dist/src/members/RegistrationWithMember.d.ts.map +1 -1
- package/dist/src/members/RegistrationWithMember.js +32 -2
- package/dist/src/members/RegistrationWithMember.js.map +1 -1
- package/dist/src/members/RegistrationWithMemberBlob.d.ts +6 -0
- package/dist/src/members/RegistrationWithMemberBlob.d.ts.map +1 -0
- package/dist/src/members/RegistrationWithMemberBlob.js +14 -0
- package/dist/src/members/RegistrationWithMemberBlob.js.map +1 -0
- package/{esm/dist/src/members/RegistrationWithMember.d.ts → dist/src/members/RegistrationWithTinyMember.d.ts} +3 -3
- package/dist/src/members/RegistrationWithTinyMember.d.ts.map +1 -0
- package/dist/src/members/RegistrationWithTinyMember.js +20 -0
- package/dist/src/members/RegistrationWithTinyMember.js.map +1 -0
- package/dist/src/members/RegistrationsBlob.d.ts +8 -0
- package/dist/src/members/RegistrationsBlob.d.ts.map +1 -0
- package/dist/src/{endpoints/GroupsWithOrganizations.js → members/RegistrationsBlob.js} +9 -9
- package/dist/src/members/RegistrationsBlob.js.map +1 -0
- package/dist/src/members/checkout/RegisterCart.d.ts +18 -2
- package/dist/src/members/checkout/RegisterCart.d.ts.map +1 -1
- package/dist/src/members/checkout/RegisterCart.js +51 -2
- package/dist/src/members/checkout/RegisterCart.js.map +1 -1
- package/dist/src/members/checkout/RegisterCart.test.d.ts +2 -0
- package/dist/src/members/checkout/RegisterCart.test.d.ts.map +1 -0
- package/dist/src/members/checkout/RegisterCart.test.js +1384 -0
- package/dist/src/members/checkout/RegisterCart.test.js.map +1 -0
- package/dist/src/members/checkout/RegisterCheckout.d.ts +23 -3
- package/dist/src/members/checkout/RegisterCheckout.d.ts.map +1 -1
- package/dist/src/members/checkout/RegisterCheckout.js +108 -11
- package/dist/src/members/checkout/RegisterCheckout.js.map +1 -1
- package/dist/src/members/checkout/RegisterItem.d.ts +7 -13
- package/dist/src/members/checkout/RegisterItem.d.ts.map +1 -1
- package/dist/src/members/checkout/RegisterItem.js +50 -23
- package/dist/src/members/checkout/RegisterItem.js.map +1 -1
- package/dist/src/members/checkout/RegistrationWithPlatformMember.d.ts +13 -0
- package/dist/src/members/checkout/RegistrationWithPlatformMember.d.ts.map +1 -0
- package/dist/src/members/checkout/RegistrationWithPlatformMember.js +21 -0
- package/dist/src/members/checkout/RegistrationWithPlatformMember.js.map +1 -0
- package/dist/src/members/records/RecordCategory.d.ts +1 -0
- package/dist/src/members/records/RecordCategory.d.ts.map +1 -1
- package/dist/src/members/records/RecordCategory.js +10 -0
- package/dist/src/members/records/RecordCategory.js.map +1 -1
- package/dist/src/webshops/Webshop.d.ts +1 -0
- package/dist/src/webshops/Webshop.d.ts.map +1 -1
- package/dist/src/webshops/Webshop.js +4 -1
- package/dist/src/webshops/Webshop.js.map +1 -1
- package/dist/src/webshops/WebshopMetaData.d.ts +1 -0
- package/dist/src/webshops/WebshopMetaData.d.ts.map +1 -1
- package/dist/src/webshops/WebshopMetaData.js +4 -0
- package/dist/src/webshops/WebshopMetaData.js.map +1 -1
- package/esm/dist/index.d.ts +11 -2
- package/esm/dist/index.d.ts.map +1 -1
- package/esm/dist/index.js +11 -2
- package/esm/dist/index.js.map +1 -1
- package/esm/dist/src/AppliedRegistrationDiscount.d.ts +15 -0
- package/esm/dist/src/AppliedRegistrationDiscount.d.ts.map +1 -0
- package/esm/dist/src/AppliedRegistrationDiscount.js +20 -0
- package/esm/dist/src/AppliedRegistrationDiscount.js.map +1 -0
- package/esm/dist/src/BalanceItem.d.ts +13 -4
- package/esm/dist/src/BalanceItem.d.ts.map +1 -1
- package/esm/dist/src/BalanceItem.js +68 -22
- package/esm/dist/src/BalanceItem.js.map +1 -1
- package/esm/dist/src/BalanceItemDetailed.d.ts +2 -2
- package/esm/dist/src/BalanceItemDetailed.d.ts.map +1 -1
- package/esm/dist/src/BalanceItemDetailed.js +2 -2
- package/esm/dist/src/BalanceItemDetailed.js.map +1 -1
- package/esm/dist/src/BundleDiscount.d.ts +79 -0
- package/esm/dist/src/BundleDiscount.d.ts.map +1 -0
- package/esm/dist/src/BundleDiscount.js +374 -0
- package/esm/dist/src/BundleDiscount.js.map +1 -0
- package/esm/dist/src/BundleDiscountGroupPriceSettings.d.ts +15 -0
- package/esm/dist/src/BundleDiscountGroupPriceSettings.d.ts.map +1 -0
- package/esm/dist/src/BundleDiscountGroupPriceSettings.js +25 -0
- package/esm/dist/src/BundleDiscountGroupPriceSettings.js.map +1 -0
- package/esm/dist/src/Group.d.ts +2 -0
- package/esm/dist/src/Group.d.ts.map +1 -1
- package/esm/dist/src/Group.js +10 -0
- package/esm/dist/src/Group.js.map +1 -1
- package/esm/dist/src/GroupPriceDiscount.d.ts +14 -0
- package/esm/dist/src/GroupPriceDiscount.d.ts.map +1 -0
- package/esm/dist/src/GroupPriceDiscount.js +35 -0
- package/esm/dist/src/GroupPriceDiscount.js.map +1 -0
- package/esm/dist/src/GroupSettings.d.ts +7 -8
- package/esm/dist/src/GroupSettings.d.ts.map +1 -1
- package/esm/dist/src/GroupSettings.js +10 -23
- package/esm/dist/src/GroupSettings.js.map +1 -1
- package/esm/dist/src/Organization.d.ts +1 -1
- package/esm/dist/src/Organization.d.ts.map +1 -1
- package/esm/dist/src/Organization.js +14 -1
- package/esm/dist/src/Organization.js.map +1 -1
- package/esm/dist/src/Permissions.d.ts.map +1 -1
- package/esm/dist/src/Permissions.js +1 -1
- package/esm/dist/src/Permissions.js.map +1 -1
- package/esm/dist/src/Platform.d.ts +1 -1
- package/esm/dist/src/Platform.d.ts.map +1 -1
- package/esm/dist/src/Platform.js +1 -1
- package/esm/dist/src/Platform.js.map +1 -1
- package/esm/dist/src/ReduceablePrice.d.ts +9 -0
- package/esm/dist/src/ReduceablePrice.d.ts.map +1 -0
- package/esm/dist/src/ReduceablePrice.js +25 -0
- package/esm/dist/src/ReduceablePrice.js.map +1 -0
- package/esm/dist/src/RegistrationPeriod.d.ts +2 -0
- package/esm/dist/src/RegistrationPeriod.d.ts.map +1 -1
- package/esm/dist/src/RegistrationPeriod.js +5 -0
- package/esm/dist/src/RegistrationPeriod.js.map +1 -1
- package/esm/dist/src/Token.d.ts.map +1 -1
- package/esm/dist/src/Token.js +7 -4
- package/esm/dist/src/Token.js.map +1 -1
- package/esm/dist/src/Version.d.ts +1 -1
- package/esm/dist/src/Version.js +1 -1
- package/esm/dist/src/email/Email.d.ts +5 -3
- package/esm/dist/src/email/Email.d.ts.map +1 -1
- package/esm/dist/src/email/Email.js +3 -0
- package/esm/dist/src/email/Email.js.map +1 -1
- package/esm/dist/src/endpoints/RegisterResponse.d.ts +2 -2
- package/esm/dist/src/endpoints/RegisterResponse.d.ts.map +1 -1
- package/esm/dist/src/endpoints/RegisterResponse.js +2 -2
- package/esm/dist/src/endpoints/RegisterResponse.js.map +1 -1
- package/esm/dist/src/filters/ExcelExportRequest.d.ts +1 -0
- package/esm/dist/src/filters/ExcelExportRequest.d.ts.map +1 -1
- package/esm/dist/src/filters/ExcelExportRequest.js +1 -0
- package/esm/dist/src/filters/ExcelExportRequest.js.map +1 -1
- package/esm/dist/src/filters/FilterCompilers.d.ts +18 -0
- package/esm/dist/src/filters/FilterCompilers.d.ts.map +1 -0
- package/esm/dist/src/filters/FilterCompilers.js +104 -0
- package/esm/dist/src/filters/FilterCompilers.js.map +1 -0
- package/esm/dist/src/filters/InMemoryFilter.d.ts +5 -3
- package/esm/dist/src/filters/InMemoryFilter.d.ts.map +1 -1
- package/esm/dist/src/filters/InMemoryFilter.js +19 -74
- package/esm/dist/src/filters/InMemoryFilter.js.map +1 -1
- package/esm/dist/src/helpers/MemberPlatformMembershipHelper.d.ts +12 -0
- package/esm/dist/src/helpers/MemberPlatformMembershipHelper.d.ts.map +1 -0
- package/esm/dist/src/helpers/MemberPlatformMembershipHelper.js +70 -0
- package/esm/dist/src/helpers/MemberPlatformMembershipHelper.js.map +1 -0
- package/esm/dist/src/members/Member.d.ts +1 -0
- package/esm/dist/src/members/Member.d.ts.map +1 -1
- package/esm/dist/src/members/Member.js +3 -0
- package/esm/dist/src/members/Member.js.map +1 -1
- package/esm/dist/src/members/MembershipStatus.d.ts +13 -0
- package/esm/dist/src/members/MembershipStatus.d.ts.map +1 -0
- package/esm/dist/src/members/MembershipStatus.js +15 -0
- package/esm/dist/src/members/MembershipStatus.js.map +1 -0
- package/esm/dist/src/members/PaymentGeneral.js +1 -1
- package/esm/dist/src/members/PaymentGeneral.js.map +1 -1
- package/esm/dist/src/members/PaymentWithRegistrations.d.ts +2 -2
- package/esm/dist/src/members/PaymentWithRegistrations.d.ts.map +1 -1
- package/esm/dist/src/members/PaymentWithRegistrations.js +2 -2
- package/esm/dist/src/members/PaymentWithRegistrations.js.map +1 -1
- package/esm/dist/src/members/PlatformMember.d.ts +24 -14
- package/esm/dist/src/members/PlatformMember.d.ts.map +1 -1
- package/esm/dist/src/members/PlatformMember.js +91 -115
- package/esm/dist/src/members/PlatformMember.js.map +1 -1
- package/esm/dist/src/members/Registration.d.ts +37 -0
- package/esm/dist/src/members/Registration.d.ts.map +1 -1
- package/esm/dist/src/members/Registration.js +48 -0
- package/esm/dist/src/members/Registration.js.map +1 -1
- package/esm/dist/src/members/RegistrationWithMemberBlob.d.ts +6 -0
- package/esm/dist/src/members/RegistrationWithMemberBlob.d.ts.map +1 -0
- package/esm/dist/src/members/RegistrationWithMemberBlob.js +10 -0
- package/esm/dist/src/members/RegistrationWithMemberBlob.js.map +1 -0
- package/esm/dist/src/members/RegistrationWithTinyMember.d.ts +7 -0
- package/esm/dist/src/members/RegistrationWithTinyMember.d.ts.map +1 -0
- package/esm/dist/src/members/{RegistrationWithMember.js → RegistrationWithTinyMember.js} +4 -4
- package/esm/dist/src/members/RegistrationWithTinyMember.js.map +1 -0
- package/esm/dist/src/members/RegistrationsBlob.d.ts +8 -0
- package/esm/dist/src/members/RegistrationsBlob.d.ts.map +1 -0
- package/esm/dist/src/members/RegistrationsBlob.js +18 -0
- package/esm/dist/src/members/RegistrationsBlob.js.map +1 -0
- package/esm/dist/src/members/checkout/RegisterCart.d.ts +18 -2
- package/esm/dist/src/members/checkout/RegisterCart.d.ts.map +1 -1
- package/esm/dist/src/members/checkout/RegisterCart.js +51 -2
- package/esm/dist/src/members/checkout/RegisterCart.js.map +1 -1
- package/esm/dist/src/members/checkout/RegisterCheckout.d.ts +23 -3
- package/esm/dist/src/members/checkout/RegisterCheckout.d.ts.map +1 -1
- package/esm/dist/src/members/checkout/RegisterCheckout.js +108 -11
- package/esm/dist/src/members/checkout/RegisterCheckout.js.map +1 -1
- package/esm/dist/src/members/checkout/RegisterItem.d.ts +7 -13
- package/esm/dist/src/members/checkout/RegisterItem.d.ts.map +1 -1
- package/esm/dist/src/members/checkout/RegisterItem.js +48 -20
- package/esm/dist/src/members/checkout/RegisterItem.js.map +1 -1
- package/esm/dist/src/members/checkout/RegistrationWithPlatformMember.d.ts +13 -0
- package/esm/dist/src/members/checkout/RegistrationWithPlatformMember.d.ts.map +1 -0
- package/esm/dist/src/members/checkout/RegistrationWithPlatformMember.js +17 -0
- package/esm/dist/src/members/checkout/RegistrationWithPlatformMember.js.map +1 -0
- package/esm/dist/src/members/records/RecordCategory.d.ts +1 -0
- package/esm/dist/src/members/records/RecordCategory.d.ts.map +1 -1
- package/esm/dist/src/members/records/RecordCategory.js +11 -1
- package/esm/dist/src/members/records/RecordCategory.js.map +1 -1
- package/esm/dist/src/webshops/Webshop.d.ts +1 -0
- package/esm/dist/src/webshops/Webshop.d.ts.map +1 -1
- package/esm/dist/src/webshops/Webshop.js +4 -1
- package/esm/dist/src/webshops/Webshop.js.map +1 -1
- package/esm/dist/src/webshops/WebshopMetaData.d.ts +1 -0
- package/esm/dist/src/webshops/WebshopMetaData.d.ts.map +1 -1
- package/esm/dist/src/webshops/WebshopMetaData.js +4 -0
- package/esm/dist/src/webshops/WebshopMetaData.js.map +1 -1
- package/package.json +2 -2
- package/dist/src/endpoints/GroupsWithOrganizations.d.ts +0 -8
- package/dist/src/endpoints/GroupsWithOrganizations.d.ts.map +0 -1
- package/dist/src/endpoints/GroupsWithOrganizations.js.map +0 -1
- package/esm/dist/src/endpoints/GroupsWithOrganizations.d.ts +0 -8
- package/esm/dist/src/endpoints/GroupsWithOrganizations.d.ts.map +0 -1
- package/esm/dist/src/endpoints/GroupsWithOrganizations.js +0 -18
- package/esm/dist/src/endpoints/GroupsWithOrganizations.js.map +0 -1
- package/esm/dist/src/members/RegistrationWithMember.d.ts.map +0 -1
- package/esm/dist/src/members/RegistrationWithMember.js.map +0 -1
|
@@ -0,0 +1,1384 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const BundleDiscountGroupPriceSettings_js_1 = require("../../BundleDiscountGroupPriceSettings.js");
|
|
4
|
+
const Group_js_1 = require("../../Group.js");
|
|
5
|
+
const GroupPriceDiscount_js_1 = require("../../GroupPriceDiscount.js");
|
|
6
|
+
const GroupSettings_js_1 = require("../../GroupSettings.js");
|
|
7
|
+
const Organization_js_1 = require("../../Organization.js");
|
|
8
|
+
const Platform_js_1 = require("../../Platform.js");
|
|
9
|
+
const ReduceablePrice_js_1 = require("../../ReduceablePrice.js");
|
|
10
|
+
const RegistrationPeriod_js_1 = require("../../RegistrationPeriod.js");
|
|
11
|
+
const TranslatedString_js_1 = require("../../TranslatedString.js");
|
|
12
|
+
const MemberDetails_js_1 = require("../MemberDetails.js");
|
|
13
|
+
const PlatformMember_js_1 = require("../PlatformMember.js");
|
|
14
|
+
const RegisterItem_js_1 = require("./RegisterItem.js");
|
|
15
|
+
const MemberWithRegistrationsBlob_js_1 = require("../MemberWithRegistrationsBlob.js");
|
|
16
|
+
// Should be last because of circular dependencies
|
|
17
|
+
const BundleDiscount_js_1 = require("../../BundleDiscount.js");
|
|
18
|
+
const Registration_js_1 = require("../Registration.js");
|
|
19
|
+
const AppliedRegistrationDiscount_js_1 = require("../../AppliedRegistrationDiscount.js");
|
|
20
|
+
const RegistrationWithPlatformMember_js_1 = require("./RegistrationWithPlatformMember.js");
|
|
21
|
+
const GenericBalance_js_1 = require("../../GenericBalance.js");
|
|
22
|
+
// Helper functions to reduce code duplication
|
|
23
|
+
function createTestPeriod() {
|
|
24
|
+
const period = RegistrationPeriod_js_1.RegistrationPeriod.create({});
|
|
25
|
+
const organizationRegistrationPeriod = RegistrationPeriod_js_1.OrganizationRegistrationPeriod.create({
|
|
26
|
+
period,
|
|
27
|
+
});
|
|
28
|
+
const organization = Organization_js_1.Organization.create({
|
|
29
|
+
period: organizationRegistrationPeriod,
|
|
30
|
+
});
|
|
31
|
+
return { period, organizationRegistrationPeriod, organization };
|
|
32
|
+
}
|
|
33
|
+
function createTestGroups(organization, period, prices = [5000, 4000], names) {
|
|
34
|
+
return prices.map((price, index) => {
|
|
35
|
+
return Group_js_1.Group.create({
|
|
36
|
+
organizationId: organization.id,
|
|
37
|
+
periodId: period.id,
|
|
38
|
+
settings: GroupSettings_js_1.GroupSettings.create({
|
|
39
|
+
name: names ? new TranslatedString_js_1.TranslatedString(names[index]) : undefined,
|
|
40
|
+
prices: [
|
|
41
|
+
GroupSettings_js_1.GroupPrice.create({
|
|
42
|
+
price: ReduceablePrice_js_1.ReduceablePrice.create({
|
|
43
|
+
price,
|
|
44
|
+
}),
|
|
45
|
+
}),
|
|
46
|
+
],
|
|
47
|
+
}),
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
function createBundleDiscount({ name = 'Bundle discount', countWholeFamily = true, countPerGroup = false, discounts = [
|
|
52
|
+
{ value: 1000, type: GroupPriceDiscount_js_1.GroupPriceDiscountType.Fixed },
|
|
53
|
+
{ value: 1500, type: GroupPriceDiscount_js_1.GroupPriceDiscountType.Fixed },
|
|
54
|
+
], } = {}) {
|
|
55
|
+
return BundleDiscount_js_1.BundleDiscount.create({
|
|
56
|
+
name: new TranslatedString_js_1.TranslatedString(name),
|
|
57
|
+
countWholeFamily,
|
|
58
|
+
countPerGroup,
|
|
59
|
+
discounts: discounts.map(d => {
|
|
60
|
+
var _a;
|
|
61
|
+
return GroupPriceDiscount_js_1.GroupPriceDiscount.create({
|
|
62
|
+
value: ReduceablePrice_js_1.ReduceablePrice.create({
|
|
63
|
+
price: d.value,
|
|
64
|
+
reducedPrice: (_a = d.reducedValue) !== null && _a !== void 0 ? _a : null,
|
|
65
|
+
}),
|
|
66
|
+
type: d.type,
|
|
67
|
+
});
|
|
68
|
+
}),
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
function createTestFamily(memberCount = 3) {
|
|
72
|
+
const members = Array(memberCount).fill(null).map((_, i) => {
|
|
73
|
+
const names = ['John', 'Jane', 'Jack'];
|
|
74
|
+
return MemberWithRegistrationsBlob_js_1.MemberWithRegistrationsBlob.create({
|
|
75
|
+
details: MemberDetails_js_1.MemberDetails.create({
|
|
76
|
+
firstName: names[i] || `Member${i + 1}`,
|
|
77
|
+
lastName: 'Doe',
|
|
78
|
+
}),
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
const blob = MemberWithRegistrationsBlob_js_1.MembersBlob.create({
|
|
82
|
+
members,
|
|
83
|
+
});
|
|
84
|
+
return PlatformMember_js_1.PlatformFamily.create(blob, { platform: Platform_js_1.Platform.create({}) });
|
|
85
|
+
}
|
|
86
|
+
function setupDiscountTest({ memberCount = 3, groupPrices = [5000, 4000], groupNames, bundleDiscount, } = {}) {
|
|
87
|
+
const { period, organizationRegistrationPeriod, organization } = createTestPeriod();
|
|
88
|
+
const groups = createTestGroups(organization, period, groupPrices, groupNames);
|
|
89
|
+
organizationRegistrationPeriod.groups = groups;
|
|
90
|
+
const discount = bundleDiscount || createBundleDiscount();
|
|
91
|
+
organizationRegistrationPeriod.settings.bundleDiscounts.push(discount);
|
|
92
|
+
// Setup bundle discounts on all groups
|
|
93
|
+
groups.forEach((group) => {
|
|
94
|
+
group.settings.prices[0].bundleDiscounts.set(discount.id, BundleDiscountGroupPriceSettings_js_1.BundleDiscountGroupPriceSettings.create({
|
|
95
|
+
name: discount.name,
|
|
96
|
+
}));
|
|
97
|
+
});
|
|
98
|
+
const family = createTestFamily(memberCount);
|
|
99
|
+
return {
|
|
100
|
+
period,
|
|
101
|
+
organizationRegistrationPeriod,
|
|
102
|
+
organization,
|
|
103
|
+
groups,
|
|
104
|
+
discount,
|
|
105
|
+
family,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
function addHistoricRegistration(member, group, organization, appliedDiscounts = new Map()) {
|
|
109
|
+
const registration = Registration_js_1.Registration.create({
|
|
110
|
+
group: group,
|
|
111
|
+
groupPrice: group.settings.prices[0],
|
|
112
|
+
memberId: member.id,
|
|
113
|
+
organizationId: group.organizationId,
|
|
114
|
+
registeredAt: new Date('2023-01-01'),
|
|
115
|
+
startDate: new Date('2023-01-01'),
|
|
116
|
+
price: group.settings.prices[0].price.price,
|
|
117
|
+
balances: [
|
|
118
|
+
GenericBalance_js_1.GenericBalance.create({
|
|
119
|
+
organizationId: organization.id,
|
|
120
|
+
amountPaid: 0,
|
|
121
|
+
amountOpen: group.settings.prices[0].price.price - [...appliedDiscounts.values()].reduce((acc, d) => acc + d.amount, 0),
|
|
122
|
+
amountPending: 0,
|
|
123
|
+
}),
|
|
124
|
+
],
|
|
125
|
+
discounts: appliedDiscounts,
|
|
126
|
+
});
|
|
127
|
+
member.member.registrations.push(registration);
|
|
128
|
+
member.family.insertOrganization(organization);
|
|
129
|
+
return registration;
|
|
130
|
+
}
|
|
131
|
+
describe('Unit.RegisterCart', () => {
|
|
132
|
+
describe('Bundle Discounts', () => {
|
|
133
|
+
it('A fixed discount is granted for the second and third registration in a bundle', () => {
|
|
134
|
+
const { organization, groups, family } = setupDiscountTest({
|
|
135
|
+
bundleDiscount: createBundleDiscount({
|
|
136
|
+
name: 'Bundle discount',
|
|
137
|
+
discounts: [
|
|
138
|
+
{ value: 1000, type: GroupPriceDiscount_js_1.GroupPriceDiscountType.Fixed },
|
|
139
|
+
{ value: 1500, type: GroupPriceDiscount_js_1.GroupPriceDiscountType.Fixed },
|
|
140
|
+
],
|
|
141
|
+
}),
|
|
142
|
+
});
|
|
143
|
+
const [groupA, groupB] = groups;
|
|
144
|
+
const [memberA, memberB, memberC] = family.members;
|
|
145
|
+
const itemA = RegisterItem_js_1.RegisterItem.defaultFor(memberA, groupA, organization);
|
|
146
|
+
const itemB = RegisterItem_js_1.RegisterItem.defaultFor(memberB, groupB, organization);
|
|
147
|
+
const itemC = RegisterItem_js_1.RegisterItem.defaultFor(memberC, groupB, organization);
|
|
148
|
+
// Add to a single cart
|
|
149
|
+
const checkout = family.checkout;
|
|
150
|
+
const cart = checkout.cart;
|
|
151
|
+
cart.add(itemA);
|
|
152
|
+
cart.add(itemB);
|
|
153
|
+
cart.add(itemC);
|
|
154
|
+
cart.calculatePrices();
|
|
155
|
+
// Check price for item A is 50.00
|
|
156
|
+
expect(itemA.calculatedPrice).toEqual(5000);
|
|
157
|
+
expect(itemA.calculatedRefund).toEqual(0);
|
|
158
|
+
expect(itemA.calculatedPriceDueLater).toEqual(0);
|
|
159
|
+
// Check price for items B and C
|
|
160
|
+
expect(itemB.calculatedPrice).toEqual(4000);
|
|
161
|
+
expect(itemB.calculatedRefund).toEqual(0);
|
|
162
|
+
expect(itemB.calculatedPriceDueLater).toEqual(0);
|
|
163
|
+
expect(itemC.calculatedPrice).toEqual(4000);
|
|
164
|
+
expect(itemC.calculatedRefund).toEqual(0);
|
|
165
|
+
expect(itemC.calculatedPriceDueLater).toEqual(0);
|
|
166
|
+
// Check calculated discount is 10_00 + 15_00 = 25_00
|
|
167
|
+
expect(cart.bundleDiscounts).toHaveLength(1);
|
|
168
|
+
expect(cart.bundleDiscounts[0].total).toEqual(2500);
|
|
169
|
+
expect(cart.bundleDiscounts[0].totalAlreadyApplied).toEqual(0);
|
|
170
|
+
expect(cart.bundleDiscounts[0].netTotal).toEqual(2500);
|
|
171
|
+
expect(cart.price).toEqual(5000 + 4000 + 4000);
|
|
172
|
+
expect(checkout.totalPrice).toEqual(5000 + 4000 + 4000 - 2500);
|
|
173
|
+
expect(checkout.priceBreakown).toEqual([
|
|
174
|
+
expect.objectContaining({
|
|
175
|
+
price: 13000,
|
|
176
|
+
}),
|
|
177
|
+
{
|
|
178
|
+
name: 'Bundle discount',
|
|
179
|
+
price: -2500,
|
|
180
|
+
},
|
|
181
|
+
expect.objectContaining({
|
|
182
|
+
price: 13000 - 2500,
|
|
183
|
+
}),
|
|
184
|
+
]);
|
|
185
|
+
});
|
|
186
|
+
test('A percentage discount is granted for the second and third registration in a bundle', () => {
|
|
187
|
+
const { organization, groups, family } = setupDiscountTest({
|
|
188
|
+
bundleDiscount: createBundleDiscount({
|
|
189
|
+
name: 'Bundle discount',
|
|
190
|
+
discounts: [
|
|
191
|
+
{ value: 1000, type: GroupPriceDiscount_js_1.GroupPriceDiscountType.Percentage },
|
|
192
|
+
{ value: 1500, type: GroupPriceDiscount_js_1.GroupPriceDiscountType.Percentage },
|
|
193
|
+
],
|
|
194
|
+
}),
|
|
195
|
+
});
|
|
196
|
+
const [groupA, groupB] = groups;
|
|
197
|
+
const [memberA, memberB, memberC] = family.members;
|
|
198
|
+
const itemA = RegisterItem_js_1.RegisterItem.defaultFor(memberA, groupA, organization);
|
|
199
|
+
const itemB = RegisterItem_js_1.RegisterItem.defaultFor(memberB, groupB, organization);
|
|
200
|
+
const itemC = RegisterItem_js_1.RegisterItem.defaultFor(memberC, groupB, organization);
|
|
201
|
+
// Add to a single cart
|
|
202
|
+
const checkout = family.checkout;
|
|
203
|
+
const cart = checkout.cart;
|
|
204
|
+
cart.add(itemA);
|
|
205
|
+
cart.add(itemB);
|
|
206
|
+
cart.add(itemC);
|
|
207
|
+
cart.calculatePrices();
|
|
208
|
+
// Check price for items
|
|
209
|
+
expect(itemA.calculatedPrice).toEqual(5000);
|
|
210
|
+
expect(itemB.calculatedPrice).toEqual(4000);
|
|
211
|
+
expect(itemC.calculatedPrice).toEqual(4000);
|
|
212
|
+
// 15% will be applied to 50 euro (max), and 10% to one of the 40 euros
|
|
213
|
+
// Check calculated discount is 50_00 * 0.15 + 40_00 * 0.10 = 7_50 + 4_00 = 11_50
|
|
214
|
+
expect(cart.bundleDiscounts).toHaveLength(1);
|
|
215
|
+
expect(cart.bundleDiscounts[0].total).toEqual(1150);
|
|
216
|
+
expect(cart.bundleDiscounts[0].netTotal).toEqual(1150);
|
|
217
|
+
expect(cart.price).toEqual(5000 + 4000 + 4000);
|
|
218
|
+
expect(checkout.totalPrice).toEqual(5000 + 4000 + 4000 - 1150);
|
|
219
|
+
expect(checkout.priceBreakown).toEqual([
|
|
220
|
+
expect.objectContaining({
|
|
221
|
+
price: 13000,
|
|
222
|
+
}),
|
|
223
|
+
{
|
|
224
|
+
name: 'Bundle discount',
|
|
225
|
+
price: -1150,
|
|
226
|
+
},
|
|
227
|
+
expect.objectContaining({
|
|
228
|
+
price: 13000 - 1150,
|
|
229
|
+
}),
|
|
230
|
+
]);
|
|
231
|
+
});
|
|
232
|
+
test('Historic registrations are included in the calculation', () => {
|
|
233
|
+
const { organization, groups, family } = setupDiscountTest({
|
|
234
|
+
bundleDiscount: createBundleDiscount({
|
|
235
|
+
name: 'Bundle discount',
|
|
236
|
+
discounts: [
|
|
237
|
+
{ value: 1000, type: GroupPriceDiscount_js_1.GroupPriceDiscountType.Percentage },
|
|
238
|
+
{ value: 1500, type: GroupPriceDiscount_js_1.GroupPriceDiscountType.Percentage },
|
|
239
|
+
],
|
|
240
|
+
}),
|
|
241
|
+
});
|
|
242
|
+
const [groupA, groupB] = groups;
|
|
243
|
+
const [memberA, memberB, memberC] = family.members;
|
|
244
|
+
// Member A is already registered for group A in the past
|
|
245
|
+
addHistoricRegistration(memberA, groupA, organization);
|
|
246
|
+
const itemB = RegisterItem_js_1.RegisterItem.defaultFor(memberB, groupB, organization);
|
|
247
|
+
const itemC = RegisterItem_js_1.RegisterItem.defaultFor(memberC, groupB, organization);
|
|
248
|
+
// Add to a single cart
|
|
249
|
+
const checkout = family.checkout;
|
|
250
|
+
const cart = checkout.cart;
|
|
251
|
+
cart.add(itemB);
|
|
252
|
+
cart.add(itemC);
|
|
253
|
+
cart.calculatePrices();
|
|
254
|
+
// Check price for items
|
|
255
|
+
expect(itemB.calculatedPrice).toEqual(4000);
|
|
256
|
+
expect(itemC.calculatedPrice).toEqual(4000);
|
|
257
|
+
// 15% will be applied to 50 euro (max), and 10% to one of the 40 euros
|
|
258
|
+
// Check calculated discount is 50_00 * 0.15 + 40_00 * 0.10 = 7_50 + 4_00 = 11_50
|
|
259
|
+
expect(cart.bundleDiscounts).toHaveLength(1);
|
|
260
|
+
expect(cart.bundleDiscounts[0].total).toEqual(1150);
|
|
261
|
+
expect(cart.bundleDiscounts[0].netTotal).toEqual(1150);
|
|
262
|
+
expect(cart.price).toEqual(4000 + 4000);
|
|
263
|
+
expect(checkout.totalPrice).toEqual(4000 + 4000 - 1150);
|
|
264
|
+
expect(checkout.priceBreakown).toEqual([
|
|
265
|
+
expect.objectContaining({
|
|
266
|
+
price: 8000,
|
|
267
|
+
}),
|
|
268
|
+
{
|
|
269
|
+
name: 'Bundle discount',
|
|
270
|
+
price: -1150,
|
|
271
|
+
},
|
|
272
|
+
expect.objectContaining({
|
|
273
|
+
price: 8000 - 1150,
|
|
274
|
+
}),
|
|
275
|
+
]);
|
|
276
|
+
});
|
|
277
|
+
test('Deleting a registration also removes the attached discount', () => {
|
|
278
|
+
// We have two family members with existing registrations.
|
|
279
|
+
// One of those registrations received a discount earlier.
|
|
280
|
+
// But since we are adding a new registration in our cart, a more optimal discount
|
|
281
|
+
// would be if that registration would get the newly higher discount instead
|
|
282
|
+
// (because it is percentage based)
|
|
283
|
+
const { organization, groups, family, discount } = setupDiscountTest({
|
|
284
|
+
memberCount: 2,
|
|
285
|
+
bundleDiscount: createBundleDiscount({
|
|
286
|
+
name: 'Multiple family members discount',
|
|
287
|
+
countWholeFamily: true,
|
|
288
|
+
countPerGroup: false,
|
|
289
|
+
discounts: [
|
|
290
|
+
{ value: 1000, type: GroupPriceDiscount_js_1.GroupPriceDiscountType.Percentage },
|
|
291
|
+
{ value: 1500, type: GroupPriceDiscount_js_1.GroupPriceDiscountType.Percentage },
|
|
292
|
+
],
|
|
293
|
+
}),
|
|
294
|
+
groupPrices: [10000, 4000],
|
|
295
|
+
});
|
|
296
|
+
const [groupA, groupB] = groups;
|
|
297
|
+
const [memberA, memberB] = family.members;
|
|
298
|
+
const registrationA = addHistoricRegistration(memberA, groupA, organization);
|
|
299
|
+
const registrationB = addHistoricRegistration(memberB, groupB, organization, new Map([
|
|
300
|
+
[
|
|
301
|
+
discount.id,
|
|
302
|
+
AppliedRegistrationDiscount_js_1.AppliedRegistrationDiscount.create({
|
|
303
|
+
name: discount.name,
|
|
304
|
+
amount: 1000, // 10% discount on 100_00 = 10_00
|
|
305
|
+
}),
|
|
306
|
+
],
|
|
307
|
+
]));
|
|
308
|
+
// If we delete registration B, the discount won't be visible in the cart because it is included in the registration
|
|
309
|
+
const checkout = family.checkout;
|
|
310
|
+
const cart = checkout.cart;
|
|
311
|
+
cart.removeRegistration(new RegistrationWithPlatformMember_js_1.RegistrationWithPlatformMember({
|
|
312
|
+
registration: registrationB,
|
|
313
|
+
member: memberB,
|
|
314
|
+
}));
|
|
315
|
+
cart.calculatePrices();
|
|
316
|
+
expect(cart.bundleDiscounts).toHaveLength(0);
|
|
317
|
+
expect(checkout.totalPrice).toEqual(-3000);
|
|
318
|
+
expect(checkout.priceBreakown).toEqual([
|
|
319
|
+
expect.objectContaining({
|
|
320
|
+
price: -4000 + 1000,
|
|
321
|
+
}),
|
|
322
|
+
expect.objectContaining({
|
|
323
|
+
price: -4000 + 1000,
|
|
324
|
+
}),
|
|
325
|
+
]);
|
|
326
|
+
// Now readd the registration
|
|
327
|
+
cart.unremoveRegistration(new RegistrationWithPlatformMember_js_1.RegistrationWithPlatformMember({
|
|
328
|
+
registration: registrationB,
|
|
329
|
+
member: memberB,
|
|
330
|
+
}));
|
|
331
|
+
// Remove registration A, this should show the discount because it is a side effect of deleting the registration
|
|
332
|
+
cart.removeRegistration(new RegistrationWithPlatformMember_js_1.RegistrationWithPlatformMember({
|
|
333
|
+
registration: registrationA,
|
|
334
|
+
member: memberA,
|
|
335
|
+
}));
|
|
336
|
+
cart.calculatePrices();
|
|
337
|
+
expect(cart.bundleDiscounts).toHaveLength(1);
|
|
338
|
+
expect(cart.bundleDiscounts[0].total).toEqual(0);
|
|
339
|
+
expect(cart.bundleDiscounts[0].totalAlreadyApplied).toEqual(1000); // The previous discount
|
|
340
|
+
expect(cart.bundleDiscounts[0].netTotal).toEqual(-1000);
|
|
341
|
+
expect(checkout.totalPrice).toEqual(-9000);
|
|
342
|
+
expect(checkout.priceBreakown).toEqual([
|
|
343
|
+
expect.objectContaining({
|
|
344
|
+
price: -10000, // Reeds aangerekend
|
|
345
|
+
}),
|
|
346
|
+
{
|
|
347
|
+
name: '766a39be-a4af-4a04-baf0-1f064d2fed16 (Multiple family members discount)',
|
|
348
|
+
price: 1000,
|
|
349
|
+
},
|
|
350
|
+
expect.objectContaining({
|
|
351
|
+
price: -9000,
|
|
352
|
+
}),
|
|
353
|
+
]);
|
|
354
|
+
});
|
|
355
|
+
test('Deleting a registration with cancellation fees', () => {
|
|
356
|
+
// We have two family members with existing registrations.
|
|
357
|
+
// One of those registrations received a discount earlier.
|
|
358
|
+
// But since we are adding a new registration in our cart, a more optimal discount
|
|
359
|
+
// would be if that registration would get the newly higher discount instead
|
|
360
|
+
// (because it is percentage based)
|
|
361
|
+
const { organization, groups, family, discount } = setupDiscountTest({
|
|
362
|
+
memberCount: 2,
|
|
363
|
+
bundleDiscount: createBundleDiscount({
|
|
364
|
+
name: 'Multiple family members discount',
|
|
365
|
+
countWholeFamily: true,
|
|
366
|
+
countPerGroup: false,
|
|
367
|
+
discounts: [
|
|
368
|
+
{ value: 1000, type: GroupPriceDiscount_js_1.GroupPriceDiscountType.Percentage },
|
|
369
|
+
{ value: 1500, type: GroupPriceDiscount_js_1.GroupPriceDiscountType.Percentage },
|
|
370
|
+
],
|
|
371
|
+
}),
|
|
372
|
+
groupPrices: [10000, 4000],
|
|
373
|
+
});
|
|
374
|
+
const [groupA, groupB] = groups;
|
|
375
|
+
const [memberA, memberB] = family.members;
|
|
376
|
+
const registrationA = addHistoricRegistration(memberA, groupA, organization);
|
|
377
|
+
const registrationB = addHistoricRegistration(memberB, groupB, organization, new Map([
|
|
378
|
+
[
|
|
379
|
+
discount.id,
|
|
380
|
+
AppliedRegistrationDiscount_js_1.AppliedRegistrationDiscount.create({
|
|
381
|
+
name: discount.name,
|
|
382
|
+
amount: 1000, // 10% discount on 100_00 = 10_00
|
|
383
|
+
}),
|
|
384
|
+
],
|
|
385
|
+
]));
|
|
386
|
+
// If we delete registration B, the discount won't be visible in the cart because it is included in the registration
|
|
387
|
+
const checkout = family.checkout;
|
|
388
|
+
checkout.cancellationFeePercentage = 5000;
|
|
389
|
+
const cart = checkout.cart;
|
|
390
|
+
cart.removeRegistration(new RegistrationWithPlatformMember_js_1.RegistrationWithPlatformMember({
|
|
391
|
+
registration: registrationB,
|
|
392
|
+
member: memberB,
|
|
393
|
+
}));
|
|
394
|
+
cart.calculatePrices();
|
|
395
|
+
expect(cart.bundleDiscounts).toHaveLength(0);
|
|
396
|
+
expect(checkout.totalPrice).toEqual(-1500);
|
|
397
|
+
expect(checkout.priceBreakown).toEqual([
|
|
398
|
+
expect.objectContaining({
|
|
399
|
+
price: -4000 + 1000, // Already charged amount
|
|
400
|
+
}),
|
|
401
|
+
// Cancellation fee = 50% of the balance total, 30_00 = 15_00
|
|
402
|
+
expect.objectContaining({
|
|
403
|
+
price: 1500,
|
|
404
|
+
}),
|
|
405
|
+
expect.objectContaining({
|
|
406
|
+
price: -1500,
|
|
407
|
+
}),
|
|
408
|
+
]);
|
|
409
|
+
// Now readd the registration
|
|
410
|
+
cart.unremoveRegistration(new RegistrationWithPlatformMember_js_1.RegistrationWithPlatformMember({
|
|
411
|
+
registration: registrationB,
|
|
412
|
+
member: memberB,
|
|
413
|
+
}));
|
|
414
|
+
// Remove registration A, this should show the discount because it is a side effect of deleting the registration
|
|
415
|
+
cart.removeRegistration(new RegistrationWithPlatformMember_js_1.RegistrationWithPlatformMember({
|
|
416
|
+
registration: registrationA,
|
|
417
|
+
member: memberA,
|
|
418
|
+
}));
|
|
419
|
+
cart.calculatePrices();
|
|
420
|
+
expect(cart.bundleDiscounts).toHaveLength(1);
|
|
421
|
+
expect(cart.bundleDiscounts[0].total).toEqual(0);
|
|
422
|
+
expect(cart.bundleDiscounts[0].totalAlreadyApplied).toEqual(1000); // The previous discount
|
|
423
|
+
expect(cart.bundleDiscounts[0].netTotal).toEqual(-1000);
|
|
424
|
+
expect(checkout.totalPrice).toEqual(-4000);
|
|
425
|
+
expect(checkout.priceBreakown).toEqual([
|
|
426
|
+
expect.objectContaining({
|
|
427
|
+
price: -10000, // Already charged for registration A that is being deleted
|
|
428
|
+
}),
|
|
429
|
+
// Cancellation fee = 50% of the balance total, 100_00 = 50_00
|
|
430
|
+
expect.objectContaining({
|
|
431
|
+
price: 5000,
|
|
432
|
+
}),
|
|
433
|
+
{
|
|
434
|
+
// Side effect in registration B
|
|
435
|
+
name: '766a39be-a4af-4a04-baf0-1f064d2fed16 (Multiple family members discount)',
|
|
436
|
+
price: 1000,
|
|
437
|
+
},
|
|
438
|
+
expect.objectContaining({
|
|
439
|
+
price: -4000,
|
|
440
|
+
}),
|
|
441
|
+
]);
|
|
442
|
+
});
|
|
443
|
+
test('Replacing a registration without discount also removes the attached discount in another registration if the new registration in not elegible', () => {
|
|
444
|
+
// Create a family with two members, each with a registration
|
|
445
|
+
// Add a discount to one of the registrations (like it should have been calculated at the time)
|
|
446
|
+
// Next, move one of the registrations to a different group that does not have the discount
|
|
447
|
+
// The previously given discount should be added as an extra price on the cart as an adjustment for the discount that should have been given
|
|
448
|
+
const { organization, groups, family, discount } = setupDiscountTest({
|
|
449
|
+
memberCount: 2,
|
|
450
|
+
bundleDiscount: createBundleDiscount({
|
|
451
|
+
name: 'Multiple family members discount',
|
|
452
|
+
countWholeFamily: true,
|
|
453
|
+
countPerGroup: false,
|
|
454
|
+
discounts: [
|
|
455
|
+
{ value: 1000, type: GroupPriceDiscount_js_1.GroupPriceDiscountType.Percentage },
|
|
456
|
+
{ value: 1500, type: GroupPriceDiscount_js_1.GroupPriceDiscountType.Percentage },
|
|
457
|
+
],
|
|
458
|
+
}),
|
|
459
|
+
groupPrices: [10000, 4000],
|
|
460
|
+
});
|
|
461
|
+
const [groupA, groupB] = groups;
|
|
462
|
+
const [memberA, memberB] = family.members;
|
|
463
|
+
const registrationA = addHistoricRegistration(memberA, groupA, organization);
|
|
464
|
+
addHistoricRegistration(memberB, groupB, organization, new Map([
|
|
465
|
+
[
|
|
466
|
+
discount.id,
|
|
467
|
+
AppliedRegistrationDiscount_js_1.AppliedRegistrationDiscount.create({
|
|
468
|
+
name: discount.name,
|
|
469
|
+
amount: 1000, // 10% discount on 100_00 = 10_00
|
|
470
|
+
}),
|
|
471
|
+
],
|
|
472
|
+
]));
|
|
473
|
+
const groupCPrice = GroupSettings_js_1.GroupPrice.create({
|
|
474
|
+
price: ReduceablePrice_js_1.ReduceablePrice.create({
|
|
475
|
+
price: 5000,
|
|
476
|
+
}),
|
|
477
|
+
});
|
|
478
|
+
const groupC = Group_js_1.Group.create({
|
|
479
|
+
organizationId: organization.id,
|
|
480
|
+
periodId: organization.period.id,
|
|
481
|
+
settings: GroupSettings_js_1.GroupSettings.create({
|
|
482
|
+
name: new TranslatedString_js_1.TranslatedString('Group C'),
|
|
483
|
+
prices: [
|
|
484
|
+
groupCPrice,
|
|
485
|
+
],
|
|
486
|
+
}),
|
|
487
|
+
});
|
|
488
|
+
const checkout = family.checkout;
|
|
489
|
+
const cart = checkout.cart;
|
|
490
|
+
const itemA = RegisterItem_js_1.RegisterItem.defaultFor(memberA, groupC, organization);
|
|
491
|
+
itemA.replaceRegistrations = [
|
|
492
|
+
new RegistrationWithPlatformMember_js_1.RegistrationWithPlatformMember({
|
|
493
|
+
registration: registrationA,
|
|
494
|
+
member: memberA,
|
|
495
|
+
}),
|
|
496
|
+
];
|
|
497
|
+
cart.add(itemA);
|
|
498
|
+
cart.calculatePrices();
|
|
499
|
+
// Check price for items
|
|
500
|
+
expect(itemA.calculatedPrice).toEqual(5000);
|
|
501
|
+
expect(itemA.calculatedRefund).toEqual(10000);
|
|
502
|
+
expect(itemA.calculatedPriceDueLater).toEqual(0);
|
|
503
|
+
// Check discount should be given back
|
|
504
|
+
expect(cart.bundleDiscounts).toHaveLength(1);
|
|
505
|
+
expect(cart.bundleDiscounts[0].total).toEqual(0);
|
|
506
|
+
expect(cart.bundleDiscounts[0].totalAlreadyApplied).toEqual(1000); // The previous discount
|
|
507
|
+
expect(cart.bundleDiscounts[0].netTotal).toEqual(-1000);
|
|
508
|
+
expect(checkout.totalPrice).toEqual(5000 - 10000 + 1000);
|
|
509
|
+
expect(checkout.priceBreakown).toEqual([
|
|
510
|
+
expect.objectContaining({
|
|
511
|
+
// Subtotal (normal price)
|
|
512
|
+
price: 5000,
|
|
513
|
+
}),
|
|
514
|
+
expect.objectContaining({
|
|
515
|
+
// Refund for the previous registration
|
|
516
|
+
price: -10000,
|
|
517
|
+
}),
|
|
518
|
+
{
|
|
519
|
+
name: '766a39be-a4af-4a04-baf0-1f064d2fed16 (Multiple family members discount)',
|
|
520
|
+
price: 1000,
|
|
521
|
+
},
|
|
522
|
+
expect.objectContaining({
|
|
523
|
+
price: -5000 + 1000,
|
|
524
|
+
}),
|
|
525
|
+
]);
|
|
526
|
+
// Now, what if groupC does have a higher discount instead of no discount?
|
|
527
|
+
groupCPrice.bundleDiscounts.set(discount.id, BundleDiscountGroupPriceSettings_js_1.BundleDiscountGroupPriceSettings.create({
|
|
528
|
+
name: discount.name,
|
|
529
|
+
customDiscounts: [
|
|
530
|
+
// Custom discount for this price
|
|
531
|
+
GroupPriceDiscount_js_1.GroupPriceDiscount.create({
|
|
532
|
+
value: ReduceablePrice_js_1.ReduceablePrice.create({
|
|
533
|
+
price: 2500,
|
|
534
|
+
}),
|
|
535
|
+
type: GroupPriceDiscount_js_1.GroupPriceDiscountType.Fixed,
|
|
536
|
+
}),
|
|
537
|
+
],
|
|
538
|
+
}));
|
|
539
|
+
// Recalculate
|
|
540
|
+
cart.calculatePrices();
|
|
541
|
+
// Check discount should be given back
|
|
542
|
+
expect(cart.bundleDiscounts).toHaveLength(1);
|
|
543
|
+
expect(cart.bundleDiscounts[0].total).toEqual(2500);
|
|
544
|
+
expect(cart.bundleDiscounts[0].totalAlreadyApplied).toEqual(1000); // The previous discount
|
|
545
|
+
expect(cart.bundleDiscounts[0].netTotal).toEqual(1500);
|
|
546
|
+
expect(checkout.totalPrice).toEqual(5000 - 10000 - 1500);
|
|
547
|
+
expect(checkout.priceBreakown).toEqual([
|
|
548
|
+
expect.objectContaining({
|
|
549
|
+
// Subtotal (normal price)
|
|
550
|
+
price: 5000,
|
|
551
|
+
}),
|
|
552
|
+
expect.objectContaining({
|
|
553
|
+
// Refund for the previous registration
|
|
554
|
+
price: -10000,
|
|
555
|
+
}),
|
|
556
|
+
{
|
|
557
|
+
name: 'Multiple family members discount',
|
|
558
|
+
price: -1500,
|
|
559
|
+
},
|
|
560
|
+
expect.objectContaining({
|
|
561
|
+
price: -5000 - 1500,
|
|
562
|
+
}),
|
|
563
|
+
]);
|
|
564
|
+
});
|
|
565
|
+
test('Replacing a registration with discount also removes the attached discount registration if the new registration in not elegible', () => {
|
|
566
|
+
const { organization, groups, family, discount } = setupDiscountTest({
|
|
567
|
+
memberCount: 2,
|
|
568
|
+
bundleDiscount: createBundleDiscount({
|
|
569
|
+
name: 'Multiple family members discount',
|
|
570
|
+
countWholeFamily: true,
|
|
571
|
+
countPerGroup: false,
|
|
572
|
+
discounts: [
|
|
573
|
+
{ value: 1000, type: GroupPriceDiscount_js_1.GroupPriceDiscountType.Percentage },
|
|
574
|
+
{ value: 1500, type: GroupPriceDiscount_js_1.GroupPriceDiscountType.Percentage },
|
|
575
|
+
],
|
|
576
|
+
}),
|
|
577
|
+
groupPrices: [10000, 4000],
|
|
578
|
+
});
|
|
579
|
+
const [groupA, groupB] = groups;
|
|
580
|
+
const [memberA, memberB] = family.members;
|
|
581
|
+
const registrationA = addHistoricRegistration(memberA, groupA, organization, new Map([
|
|
582
|
+
[
|
|
583
|
+
discount.id,
|
|
584
|
+
AppliedRegistrationDiscount_js_1.AppliedRegistrationDiscount.create({
|
|
585
|
+
name: discount.name,
|
|
586
|
+
amount: 1000, // 10% discount on 100_00 = 10_00
|
|
587
|
+
}),
|
|
588
|
+
],
|
|
589
|
+
]));
|
|
590
|
+
addHistoricRegistration(memberB, groupB, organization);
|
|
591
|
+
const groupCPrice = GroupSettings_js_1.GroupPrice.create({
|
|
592
|
+
price: ReduceablePrice_js_1.ReduceablePrice.create({
|
|
593
|
+
price: 5000,
|
|
594
|
+
}),
|
|
595
|
+
});
|
|
596
|
+
const groupC = Group_js_1.Group.create({
|
|
597
|
+
organizationId: organization.id,
|
|
598
|
+
periodId: organization.period.id,
|
|
599
|
+
settings: GroupSettings_js_1.GroupSettings.create({
|
|
600
|
+
name: new TranslatedString_js_1.TranslatedString('Group C'),
|
|
601
|
+
prices: [
|
|
602
|
+
groupCPrice,
|
|
603
|
+
],
|
|
604
|
+
}),
|
|
605
|
+
});
|
|
606
|
+
const checkout = family.checkout;
|
|
607
|
+
const cart = checkout.cart;
|
|
608
|
+
const itemA = RegisterItem_js_1.RegisterItem.defaultFor(memberA, groupC, organization);
|
|
609
|
+
itemA.replaceRegistrations = [
|
|
610
|
+
new RegistrationWithPlatformMember_js_1.RegistrationWithPlatformMember({
|
|
611
|
+
registration: registrationA,
|
|
612
|
+
member: memberA,
|
|
613
|
+
}),
|
|
614
|
+
];
|
|
615
|
+
cart.add(itemA);
|
|
616
|
+
cart.calculatePrices();
|
|
617
|
+
// Check price for items
|
|
618
|
+
expect(itemA.calculatedPrice).toEqual(5000);
|
|
619
|
+
expect(itemA.calculatedRefund).toEqual(9000);
|
|
620
|
+
expect(itemA.calculatedPriceDueLater).toEqual(0);
|
|
621
|
+
// No discounts anymore
|
|
622
|
+
expect(cart.bundleDiscounts).toHaveLength(0);
|
|
623
|
+
expect(checkout.totalPrice).toEqual(5000 - 9000);
|
|
624
|
+
expect(checkout.priceBreakown).toEqual([
|
|
625
|
+
expect.objectContaining({
|
|
626
|
+
// Subtotal (normal price)
|
|
627
|
+
price: 5000,
|
|
628
|
+
}),
|
|
629
|
+
expect.objectContaining({
|
|
630
|
+
// Refund for the previous registration, without the discount that was granted
|
|
631
|
+
price: -9000,
|
|
632
|
+
}),
|
|
633
|
+
expect.objectContaining({
|
|
634
|
+
price: 5000 - 9000,
|
|
635
|
+
}),
|
|
636
|
+
]);
|
|
637
|
+
// Now, what if groupC does have a higher discount instead of no discount?
|
|
638
|
+
groupCPrice.bundleDiscounts.set(discount.id, BundleDiscountGroupPriceSettings_js_1.BundleDiscountGroupPriceSettings.create({
|
|
639
|
+
name: discount.name,
|
|
640
|
+
customDiscounts: [
|
|
641
|
+
// Custom discount for this price
|
|
642
|
+
GroupPriceDiscount_js_1.GroupPriceDiscount.create({
|
|
643
|
+
value: ReduceablePrice_js_1.ReduceablePrice.create({
|
|
644
|
+
price: 2500,
|
|
645
|
+
}),
|
|
646
|
+
type: GroupPriceDiscount_js_1.GroupPriceDiscountType.Fixed,
|
|
647
|
+
}),
|
|
648
|
+
],
|
|
649
|
+
}));
|
|
650
|
+
// Recalculate
|
|
651
|
+
cart.calculatePrices();
|
|
652
|
+
// Check discount should be given back
|
|
653
|
+
expect(cart.bundleDiscounts).toHaveLength(1);
|
|
654
|
+
expect(cart.bundleDiscounts[0].total).toEqual(2500);
|
|
655
|
+
expect(cart.bundleDiscounts[0].totalAlreadyApplied).toEqual(0); // Not included here, because the registration will be removed including the applied discount
|
|
656
|
+
expect(cart.bundleDiscounts[0].netTotal).toEqual(2500);
|
|
657
|
+
expect(checkout.totalPrice).toEqual(5000 - 9000 - 2500);
|
|
658
|
+
expect(checkout.priceBreakown).toEqual([
|
|
659
|
+
expect.objectContaining({
|
|
660
|
+
// Subtotal (normal price)
|
|
661
|
+
price: 5000,
|
|
662
|
+
}),
|
|
663
|
+
expect.objectContaining({
|
|
664
|
+
// Refund for the previous registration
|
|
665
|
+
price: -9000,
|
|
666
|
+
}),
|
|
667
|
+
{
|
|
668
|
+
name: 'Multiple family members discount',
|
|
669
|
+
price: -2500,
|
|
670
|
+
},
|
|
671
|
+
expect.objectContaining({
|
|
672
|
+
price: 5000 - 9000 - 2500,
|
|
673
|
+
}),
|
|
674
|
+
]);
|
|
675
|
+
});
|
|
676
|
+
test('The last discount is repeated', () => {
|
|
677
|
+
// Create a family with 3 members. Add 3 items to the cart.
|
|
678
|
+
// The bundle discount only defined one discount, but that should be repated for the second and third item
|
|
679
|
+
const { organization, groups, family, discount } = setupDiscountTest({
|
|
680
|
+
memberCount: 3,
|
|
681
|
+
groupPrices: [5000, 4000],
|
|
682
|
+
groupNames: ['Group A', 'Group B'],
|
|
683
|
+
bundleDiscount: createBundleDiscount({
|
|
684
|
+
name: 'Bundle discount',
|
|
685
|
+
discounts: [
|
|
686
|
+
{ value: 1000, type: GroupPriceDiscount_js_1.GroupPriceDiscountType.Percentage },
|
|
687
|
+
],
|
|
688
|
+
}),
|
|
689
|
+
});
|
|
690
|
+
const [groupA, groupB] = groups;
|
|
691
|
+
const [memberA, memberB, memberC] = family.members;
|
|
692
|
+
const itemA = RegisterItem_js_1.RegisterItem.defaultFor(memberA, groupA, organization);
|
|
693
|
+
const itemB = RegisterItem_js_1.RegisterItem.defaultFor(memberB, groupB, organization);
|
|
694
|
+
const itemC = RegisterItem_js_1.RegisterItem.defaultFor(memberC, groupB, organization);
|
|
695
|
+
// Add to a single cart
|
|
696
|
+
const checkout = family.checkout;
|
|
697
|
+
const cart = checkout.cart;
|
|
698
|
+
cart.add(itemA);
|
|
699
|
+
cart.add(itemB);
|
|
700
|
+
cart.add(itemC);
|
|
701
|
+
cart.calculatePrices();
|
|
702
|
+
// Check price for items
|
|
703
|
+
expect(itemA.calculatedPrice).toEqual(5000);
|
|
704
|
+
expect(itemA.calculatedRefund).toEqual(0);
|
|
705
|
+
expect(itemA.calculatedPriceDueLater).toEqual(0);
|
|
706
|
+
expect(itemB.calculatedPrice).toEqual(4000);
|
|
707
|
+
expect(itemB.calculatedRefund).toEqual(0);
|
|
708
|
+
expect(itemB.calculatedPriceDueLater).toEqual(0);
|
|
709
|
+
expect(itemC.calculatedPrice).toEqual(4000);
|
|
710
|
+
expect(itemC.calculatedRefund).toEqual(0);
|
|
711
|
+
expect(itemC.calculatedPriceDueLater).toEqual(0);
|
|
712
|
+
// Check calculated discount is 50_00 * 0.10 + 40_00 * 0.10 = 5_00 + 4_00 = 9_00
|
|
713
|
+
expect(cart.bundleDiscounts).toHaveLength(1);
|
|
714
|
+
expect(cart.bundleDiscounts[0].total).toEqual(900);
|
|
715
|
+
expect(cart.bundleDiscounts[0].totalAlreadyApplied).toEqual(0);
|
|
716
|
+
expect(cart.bundleDiscounts[0].netTotal).toEqual(900);
|
|
717
|
+
expect(cart.price).toEqual(5000 + 4000 + 4000);
|
|
718
|
+
expect(checkout.totalPrice).toEqual(5000 + 4000 + 4000 - 900);
|
|
719
|
+
expect(checkout.priceBreakown).toEqual([
|
|
720
|
+
expect.objectContaining({
|
|
721
|
+
price: 13000,
|
|
722
|
+
}),
|
|
723
|
+
{
|
|
724
|
+
name: 'Bundle discount',
|
|
725
|
+
price: -900,
|
|
726
|
+
},
|
|
727
|
+
expect.objectContaining({
|
|
728
|
+
price: 13000 - 900,
|
|
729
|
+
}),
|
|
730
|
+
]);
|
|
731
|
+
});
|
|
732
|
+
test('The highest possible discount is granted', () => {
|
|
733
|
+
const { organization, groups, family, discount } = setupDiscountTest({
|
|
734
|
+
memberCount: 3,
|
|
735
|
+
groupPrices: [5000, 4000],
|
|
736
|
+
groupNames: ['Group A', 'Group B'],
|
|
737
|
+
bundleDiscount: createBundleDiscount({
|
|
738
|
+
name: 'Bundle discount',
|
|
739
|
+
discounts: [
|
|
740
|
+
{ value: 1000, type: GroupPriceDiscount_js_1.GroupPriceDiscountType.Percentage },
|
|
741
|
+
],
|
|
742
|
+
}),
|
|
743
|
+
});
|
|
744
|
+
const [groupA, groupB] = groups;
|
|
745
|
+
const [memberA, memberB, memberC] = family.members;
|
|
746
|
+
const itemA = RegisterItem_js_1.RegisterItem.defaultFor(memberA, groupA, organization);
|
|
747
|
+
const itemB = RegisterItem_js_1.RegisterItem.defaultFor(memberB, groupB, organization);
|
|
748
|
+
const itemC = RegisterItem_js_1.RegisterItem.defaultFor(memberC, groupB, organization);
|
|
749
|
+
// Change group B to give 20 euro for the second item, and 0 for the third item
|
|
750
|
+
groupB.settings.prices[0].bundleDiscounts.set(discount.id, BundleDiscountGroupPriceSettings_js_1.BundleDiscountGroupPriceSettings.create({
|
|
751
|
+
name: discount.name,
|
|
752
|
+
customDiscounts: [
|
|
753
|
+
GroupPriceDiscount_js_1.GroupPriceDiscount.create({
|
|
754
|
+
value: ReduceablePrice_js_1.ReduceablePrice.create({
|
|
755
|
+
price: 2000,
|
|
756
|
+
}),
|
|
757
|
+
type: GroupPriceDiscount_js_1.GroupPriceDiscountType.Fixed,
|
|
758
|
+
}),
|
|
759
|
+
GroupPriceDiscount_js_1.GroupPriceDiscount.create({
|
|
760
|
+
value: ReduceablePrice_js_1.ReduceablePrice.create({
|
|
761
|
+
price: 0,
|
|
762
|
+
}),
|
|
763
|
+
type: GroupPriceDiscount_js_1.GroupPriceDiscountType.Fixed,
|
|
764
|
+
}),
|
|
765
|
+
],
|
|
766
|
+
}));
|
|
767
|
+
// Add to a single cart
|
|
768
|
+
const checkout = family.checkout;
|
|
769
|
+
const cart = checkout.cart;
|
|
770
|
+
cart.add(itemA);
|
|
771
|
+
cart.add(itemB);
|
|
772
|
+
cart.add(itemC);
|
|
773
|
+
cart.calculatePrices();
|
|
774
|
+
// Check price for items
|
|
775
|
+
expect(itemA.calculatedPrice).toEqual(5000);
|
|
776
|
+
expect(itemA.calculatedRefund).toEqual(0);
|
|
777
|
+
expect(itemA.calculatedPriceDueLater).toEqual(0);
|
|
778
|
+
expect(itemB.calculatedPrice).toEqual(4000);
|
|
779
|
+
expect(itemB.calculatedRefund).toEqual(0);
|
|
780
|
+
expect(itemB.calculatedPriceDueLater).toEqual(0);
|
|
781
|
+
expect(itemC.calculatedPrice).toEqual(4000);
|
|
782
|
+
expect(itemC.calculatedRefund).toEqual(0);
|
|
783
|
+
expect(itemC.calculatedPriceDueLater).toEqual(0);
|
|
784
|
+
// Check calculated discount is 50_00 * 0.10 + 20_00 fixed + 0 = 5_00 + 20_00 + 0 = 25_00
|
|
785
|
+
expect(cart.bundleDiscounts).toHaveLength(1);
|
|
786
|
+
expect(cart.bundleDiscounts[0].total).toEqual(2500);
|
|
787
|
+
expect(cart.bundleDiscounts[0].totalAlreadyApplied).toEqual(0);
|
|
788
|
+
expect(cart.bundleDiscounts[0].netTotal).toEqual(2500);
|
|
789
|
+
expect(cart.price).toEqual(5000 + 4000 + 4000);
|
|
790
|
+
expect(checkout.totalPrice).toEqual(5000 + 4000 + 4000 - 2500);
|
|
791
|
+
expect(checkout.priceBreakown).toEqual([
|
|
792
|
+
expect.objectContaining({
|
|
793
|
+
price: 13000,
|
|
794
|
+
}),
|
|
795
|
+
{
|
|
796
|
+
name: 'Bundle discount',
|
|
797
|
+
price: -2500,
|
|
798
|
+
},
|
|
799
|
+
expect.objectContaining({
|
|
800
|
+
price: 13000 - 2500,
|
|
801
|
+
}),
|
|
802
|
+
]);
|
|
803
|
+
});
|
|
804
|
+
test('Multiple bundles can be combined', () => {
|
|
805
|
+
// Situation: Camp A costs 100 euro
|
|
806
|
+
// Camp B costs 150 euro
|
|
807
|
+
// Camp A and/or campB gives a discount of 10, 20, 30... (all camp discount)
|
|
808
|
+
// On top of that there is an extra discount if you combine multiple expensive camps (camp B) of 5 euro, 10 ...
|
|
809
|
+
const { organization, groups, family, organizationRegistrationPeriod } = setupDiscountTest({
|
|
810
|
+
memberCount: 5,
|
|
811
|
+
groupPrices: [10000, 15000],
|
|
812
|
+
groupNames: ['Camp A', 'Camp B'],
|
|
813
|
+
bundleDiscount: createBundleDiscount({
|
|
814
|
+
name: 'All camp discount',
|
|
815
|
+
discounts: [
|
|
816
|
+
{ value: 1000, type: GroupPriceDiscount_js_1.GroupPriceDiscountType.Fixed },
|
|
817
|
+
],
|
|
818
|
+
}),
|
|
819
|
+
});
|
|
820
|
+
const [campA, campB] = groups;
|
|
821
|
+
const [memberA, memberB, memberC, memberD, memberE] = family.members;
|
|
822
|
+
const expensiveCampDiscount = createBundleDiscount({
|
|
823
|
+
name: 'Expensive camp discount',
|
|
824
|
+
discounts: [
|
|
825
|
+
{ value: 500, type: GroupPriceDiscount_js_1.GroupPriceDiscountType.Fixed },
|
|
826
|
+
],
|
|
827
|
+
});
|
|
828
|
+
// Add discount to organizationRegistrationPeriod
|
|
829
|
+
organizationRegistrationPeriod.settings.bundleDiscounts.push(expensiveCampDiscount);
|
|
830
|
+
// Add camp B to the expensive camp discount
|
|
831
|
+
campB.settings.prices[0].bundleDiscounts.set(expensiveCampDiscount.id, BundleDiscountGroupPriceSettings_js_1.BundleDiscountGroupPriceSettings.create({
|
|
832
|
+
name: expensiveCampDiscount.name,
|
|
833
|
+
}));
|
|
834
|
+
// Add to a single cart
|
|
835
|
+
const checkout = family.checkout;
|
|
836
|
+
const cart = checkout.cart;
|
|
837
|
+
const itemA = RegisterItem_js_1.RegisterItem.defaultFor(memberA, campA, organization);
|
|
838
|
+
const itemB = RegisterItem_js_1.RegisterItem.defaultFor(memberB, campB, organization); // +10_00 discount
|
|
839
|
+
const itemC = RegisterItem_js_1.RegisterItem.defaultFor(memberC, campB, organization); // +10_00 discount and +5_00 discount
|
|
840
|
+
const itemD = RegisterItem_js_1.RegisterItem.defaultFor(memberD, campA, organization); // +10_00 discount
|
|
841
|
+
const itemE = RegisterItem_js_1.RegisterItem.defaultFor(memberE, campB, organization); // +10_00 discount and +5_00 discount
|
|
842
|
+
cart.add(itemA);
|
|
843
|
+
cart.add(itemB);
|
|
844
|
+
cart.add(itemC);
|
|
845
|
+
cart.add(itemD);
|
|
846
|
+
cart.add(itemE);
|
|
847
|
+
cart.calculatePrices();
|
|
848
|
+
expect(cart.bundleDiscounts).toHaveLength(2);
|
|
849
|
+
expect(cart.bundleDiscounts.map((d) => {
|
|
850
|
+
return {
|
|
851
|
+
name: d.name,
|
|
852
|
+
total: d.total,
|
|
853
|
+
netTotal: d.netTotal,
|
|
854
|
+
};
|
|
855
|
+
})).toEqual([
|
|
856
|
+
{
|
|
857
|
+
name: 'All camp discount',
|
|
858
|
+
total: 1000 * 4,
|
|
859
|
+
netTotal: 1000 * 4,
|
|
860
|
+
},
|
|
861
|
+
{
|
|
862
|
+
name: 'Expensive camp discount',
|
|
863
|
+
total: 500 * 2,
|
|
864
|
+
netTotal: 500 * 2,
|
|
865
|
+
},
|
|
866
|
+
]);
|
|
867
|
+
expect(checkout.priceBreakown).toEqual([
|
|
868
|
+
expect.objectContaining({
|
|
869
|
+
price: 10000 * 2 + 15000 * 3,
|
|
870
|
+
}),
|
|
871
|
+
{
|
|
872
|
+
name: 'All camp discount',
|
|
873
|
+
price: -1000 * 4,
|
|
874
|
+
},
|
|
875
|
+
{
|
|
876
|
+
name: 'Expensive camp discount',
|
|
877
|
+
price: -500 * 2,
|
|
878
|
+
},
|
|
879
|
+
expect.objectContaining({
|
|
880
|
+
price: 10000 * 2 + 15000 * 3 - 1000 * 4 - 500 * 2,
|
|
881
|
+
}),
|
|
882
|
+
]);
|
|
883
|
+
});
|
|
884
|
+
test('Previous discounts can be altered if a better optimum is found later', () => {
|
|
885
|
+
// We have two family members with existing registrations.
|
|
886
|
+
// One of those registrations received a discount earlier.
|
|
887
|
+
// But since we are adding a new registration in our cart, a more optimal discount
|
|
888
|
+
// would be if that registration would get the newly higher discount instead
|
|
889
|
+
// (because it is percentage based)
|
|
890
|
+
const { organization, groups, family, discount } = setupDiscountTest({
|
|
891
|
+
memberCount: 2,
|
|
892
|
+
bundleDiscount: createBundleDiscount({
|
|
893
|
+
name: 'Multiple family members discount',
|
|
894
|
+
countWholeFamily: true,
|
|
895
|
+
countPerGroup: false,
|
|
896
|
+
discounts: [
|
|
897
|
+
{ value: 1000, type: GroupPriceDiscount_js_1.GroupPriceDiscountType.Percentage },
|
|
898
|
+
{ value: 1500, type: GroupPriceDiscount_js_1.GroupPriceDiscountType.Percentage },
|
|
899
|
+
],
|
|
900
|
+
}),
|
|
901
|
+
groupPrices: [10000, 4000],
|
|
902
|
+
});
|
|
903
|
+
const [groupA, groupB] = groups;
|
|
904
|
+
const [memberA, memberB] = family.members;
|
|
905
|
+
const registrationA = addHistoricRegistration(memberA, groupA, organization);
|
|
906
|
+
const registrationB = addHistoricRegistration(memberB, groupB, organization);
|
|
907
|
+
registrationA.discounts.set(discount.id, AppliedRegistrationDiscount_js_1.AppliedRegistrationDiscount.create({
|
|
908
|
+
name: discount.name,
|
|
909
|
+
amount: 1000, // 10% discount on 100_00 = 10_00
|
|
910
|
+
}));
|
|
911
|
+
// Now create itemC
|
|
912
|
+
const itemC = RegisterItem_js_1.RegisterItem.defaultFor(memberA, groupB, organization);
|
|
913
|
+
// Add to a single cart
|
|
914
|
+
const checkout = family.checkout;
|
|
915
|
+
const cart = checkout.cart;
|
|
916
|
+
cart.add(itemC);
|
|
917
|
+
cart.calculatePrices();
|
|
918
|
+
// Check price for items
|
|
919
|
+
expect(itemC.calculatedPrice).toEqual(4000);
|
|
920
|
+
expect(itemC.calculatedRefund).toEqual(0);
|
|
921
|
+
expect(itemC.calculatedPriceDueLater).toEqual(0);
|
|
922
|
+
// Check calculated discount is 100_00 * 0.15 + 40_00 * 0.10 = 15_00 + 4_00 = 19_00
|
|
923
|
+
expect(cart.bundleDiscounts).toHaveLength(1);
|
|
924
|
+
expect(cart.bundleDiscounts[0].total).toEqual(1900);
|
|
925
|
+
expect(cart.bundleDiscounts[0].totalAlreadyApplied).toEqual(1000); // The previous discount
|
|
926
|
+
expect(cart.bundleDiscounts[0].netTotal).toEqual(900);
|
|
927
|
+
expect(cart.price).toEqual(4000);
|
|
928
|
+
expect(checkout.totalPrice).toEqual(4000 - 900);
|
|
929
|
+
expect(checkout.priceBreakown).toEqual([
|
|
930
|
+
expect.objectContaining({
|
|
931
|
+
price: 4000,
|
|
932
|
+
}),
|
|
933
|
+
{
|
|
934
|
+
name: 'Multiple family members discount',
|
|
935
|
+
price: -900,
|
|
936
|
+
},
|
|
937
|
+
expect.objectContaining({
|
|
938
|
+
price: 4000 - 900,
|
|
939
|
+
}),
|
|
940
|
+
]);
|
|
941
|
+
});
|
|
942
|
+
test('The repeating behaviour can be stopped by setting the last discount to zero', () => {
|
|
943
|
+
// Create a family with 3 members. Add 3 items to the cart.
|
|
944
|
+
// The bundle discount only defined one discount, but that should be repated for the second and third item
|
|
945
|
+
const { organization, groups, family, discount } = setupDiscountTest({
|
|
946
|
+
memberCount: 3,
|
|
947
|
+
groupPrices: [5000, 4000],
|
|
948
|
+
groupNames: ['Group A', 'Group B'],
|
|
949
|
+
bundleDiscount: createBundleDiscount({
|
|
950
|
+
name: 'Bundle discount',
|
|
951
|
+
discounts: [
|
|
952
|
+
{ value: 1000, type: GroupPriceDiscount_js_1.GroupPriceDiscountType.Percentage },
|
|
953
|
+
{ value: 0, type: GroupPriceDiscount_js_1.GroupPriceDiscountType.Percentage }, // This should stop the repeating behaviour
|
|
954
|
+
],
|
|
955
|
+
}),
|
|
956
|
+
});
|
|
957
|
+
const [groupA, groupB] = groups;
|
|
958
|
+
const [memberA, memberB, memberC] = family.members;
|
|
959
|
+
const itemA = RegisterItem_js_1.RegisterItem.defaultFor(memberA, groupA, organization);
|
|
960
|
+
const itemB = RegisterItem_js_1.RegisterItem.defaultFor(memberB, groupB, organization);
|
|
961
|
+
const itemC = RegisterItem_js_1.RegisterItem.defaultFor(memberC, groupB, organization);
|
|
962
|
+
// Add to a single cart
|
|
963
|
+
const checkout = family.checkout;
|
|
964
|
+
const cart = checkout.cart;
|
|
965
|
+
cart.add(itemA);
|
|
966
|
+
cart.add(itemB);
|
|
967
|
+
cart.add(itemC);
|
|
968
|
+
cart.calculatePrices();
|
|
969
|
+
// Check price for items
|
|
970
|
+
expect(itemA.calculatedPrice).toEqual(5000);
|
|
971
|
+
expect(itemA.calculatedRefund).toEqual(0);
|
|
972
|
+
expect(itemA.calculatedPriceDueLater).toEqual(0);
|
|
973
|
+
expect(itemB.calculatedPrice).toEqual(4000);
|
|
974
|
+
expect(itemB.calculatedRefund).toEqual(0);
|
|
975
|
+
expect(itemB.calculatedPriceDueLater).toEqual(0);
|
|
976
|
+
expect(itemC.calculatedPrice).toEqual(4000);
|
|
977
|
+
expect(itemC.calculatedRefund).toEqual(0);
|
|
978
|
+
expect(itemC.calculatedPriceDueLater).toEqual(0);
|
|
979
|
+
// Check calculated discount is 50_00 * 0.10 = 5_00
|
|
980
|
+
expect(cart.bundleDiscounts).toHaveLength(1);
|
|
981
|
+
expect(cart.bundleDiscounts[0].total).toEqual(500);
|
|
982
|
+
expect(cart.bundleDiscounts[0].totalAlreadyApplied).toEqual(0);
|
|
983
|
+
expect(cart.bundleDiscounts[0].netTotal).toEqual(500);
|
|
984
|
+
expect(cart.price).toEqual(5000 + 4000 + 4000);
|
|
985
|
+
expect(checkout.totalPrice).toEqual(5000 + 4000 + 4000 - 500);
|
|
986
|
+
expect(checkout.priceBreakown).toEqual([
|
|
987
|
+
expect.objectContaining({
|
|
988
|
+
price: 13000,
|
|
989
|
+
}),
|
|
990
|
+
{
|
|
991
|
+
name: 'Bundle discount',
|
|
992
|
+
price: -500,
|
|
993
|
+
},
|
|
994
|
+
expect.objectContaining({
|
|
995
|
+
price: 13000 - 500,
|
|
996
|
+
}),
|
|
997
|
+
]);
|
|
998
|
+
});
|
|
999
|
+
test('Gives different discount for members with reduced price', () => {
|
|
1000
|
+
// Create familuy with 3 members.
|
|
1001
|
+
// One member has a reduced price.
|
|
1002
|
+
// The other two members have a normal price.
|
|
1003
|
+
// Create a 50%, 100% discount for the reduced price in a bundle discount (so it should be free in a family with 3 members)
|
|
1004
|
+
const { organization, groups, family } = setupDiscountTest({
|
|
1005
|
+
memberCount: 3,
|
|
1006
|
+
groupPrices: [5000, 4000],
|
|
1007
|
+
groupNames: ['Group A', 'Group B'],
|
|
1008
|
+
bundleDiscount: createBundleDiscount({
|
|
1009
|
+
name: 'Bundle discount',
|
|
1010
|
+
discounts: [
|
|
1011
|
+
{ value: 500, type: GroupPriceDiscount_js_1.GroupPriceDiscountType.Percentage, reducedValue: 5000 },
|
|
1012
|
+
{ value: 1000, type: GroupPriceDiscount_js_1.GroupPriceDiscountType.Percentage, reducedValue: 10000 },
|
|
1013
|
+
],
|
|
1014
|
+
}),
|
|
1015
|
+
});
|
|
1016
|
+
const [groupA, groupB] = groups;
|
|
1017
|
+
const [memberA, memberB, memberC] = family.members;
|
|
1018
|
+
// Make sure the last member has a reduced price
|
|
1019
|
+
memberC.member.details.requiresFinancialSupport = MemberDetails_js_1.BooleanStatus.create({ value: true });
|
|
1020
|
+
const itemA = RegisterItem_js_1.RegisterItem.defaultFor(memberA, groupA, organization);
|
|
1021
|
+
const itemB = RegisterItem_js_1.RegisterItem.defaultFor(memberB, groupB, organization);
|
|
1022
|
+
const itemC = RegisterItem_js_1.RegisterItem.defaultFor(memberC, groupB, organization);
|
|
1023
|
+
// Add to a single cart
|
|
1024
|
+
const checkout = family.checkout;
|
|
1025
|
+
const cart = checkout.cart;
|
|
1026
|
+
cart.add(itemA);
|
|
1027
|
+
cart.add(itemB);
|
|
1028
|
+
cart.add(itemC);
|
|
1029
|
+
cart.calculatePrices();
|
|
1030
|
+
// Check price for items
|
|
1031
|
+
expect(itemA.calculatedPrice).toEqual(5000);
|
|
1032
|
+
expect(itemB.calculatedPrice).toEqual(4000);
|
|
1033
|
+
expect(itemC.calculatedPrice).toEqual(4000);
|
|
1034
|
+
// Check calculated discount is 40_00 * 1 + 50_00 * 5% = 40_00 + 2_50 = 42_50
|
|
1035
|
+
expect(cart.bundleDiscounts).toHaveLength(1);
|
|
1036
|
+
expect(cart.bundleDiscounts[0].total).toEqual(4250);
|
|
1037
|
+
expect(cart.bundleDiscounts[0].totalAlreadyApplied).toEqual(0);
|
|
1038
|
+
expect(cart.bundleDiscounts[0].netTotal).toEqual(4250);
|
|
1039
|
+
expect(cart.price).toEqual(5000 + 4000 + 4000);
|
|
1040
|
+
expect(checkout.totalPrice).toEqual(5000 + 4000 + 4000 - 4250);
|
|
1041
|
+
expect(checkout.priceBreakown).toEqual([
|
|
1042
|
+
expect.objectContaining({
|
|
1043
|
+
price: 13000,
|
|
1044
|
+
}),
|
|
1045
|
+
{
|
|
1046
|
+
name: 'Bundle discount',
|
|
1047
|
+
price: -4250,
|
|
1048
|
+
},
|
|
1049
|
+
expect.objectContaining({
|
|
1050
|
+
price: 13000 - 4250,
|
|
1051
|
+
}),
|
|
1052
|
+
]);
|
|
1053
|
+
// Remove requires financial support, then recalculate
|
|
1054
|
+
memberC.member.details.requiresFinancialSupport = MemberDetails_js_1.BooleanStatus.create({ value: false });
|
|
1055
|
+
cart.calculatePrices();
|
|
1056
|
+
// 10% on 50_00 + 5% on 40_00 = 5_00 + 2_00 = 7_00
|
|
1057
|
+
expect(checkout.priceBreakown).toEqual([
|
|
1058
|
+
expect.objectContaining({
|
|
1059
|
+
price: 13000,
|
|
1060
|
+
}),
|
|
1061
|
+
{
|
|
1062
|
+
name: 'Bundle discount',
|
|
1063
|
+
price: -700,
|
|
1064
|
+
},
|
|
1065
|
+
expect.objectContaining({
|
|
1066
|
+
price: 13000 - 700,
|
|
1067
|
+
}),
|
|
1068
|
+
]);
|
|
1069
|
+
});
|
|
1070
|
+
test('Bundles without countWholeFamily only count per unique member', () => {
|
|
1071
|
+
// Register member A for both group A and group B
|
|
1072
|
+
// while member B is only registered for group A
|
|
1073
|
+
// Only member A should get the discount for either A or B (if the order matters)
|
|
1074
|
+
const { organization, groups, family } = setupDiscountTest({
|
|
1075
|
+
memberCount: 2,
|
|
1076
|
+
bundleDiscount: createBundleDiscount({
|
|
1077
|
+
name: 'Multiple lessons discount',
|
|
1078
|
+
countWholeFamily: false,
|
|
1079
|
+
countPerGroup: false,
|
|
1080
|
+
discounts: [
|
|
1081
|
+
{ value: 1000, type: GroupPriceDiscount_js_1.GroupPriceDiscountType.Percentage },
|
|
1082
|
+
],
|
|
1083
|
+
}),
|
|
1084
|
+
});
|
|
1085
|
+
const [groupA, groupB] = groups;
|
|
1086
|
+
const [memberA, memberB] = family.members;
|
|
1087
|
+
const itemA = RegisterItem_js_1.RegisterItem.defaultFor(memberA, groupA, organization);
|
|
1088
|
+
const itemB = RegisterItem_js_1.RegisterItem.defaultFor(memberA, groupB, organization);
|
|
1089
|
+
const itemC = RegisterItem_js_1.RegisterItem.defaultFor(memberB, groupA, organization);
|
|
1090
|
+
// Add to a single cart
|
|
1091
|
+
const checkout = family.checkout;
|
|
1092
|
+
const cart = checkout.cart;
|
|
1093
|
+
cart.add(itemA);
|
|
1094
|
+
cart.add(itemB);
|
|
1095
|
+
cart.add(itemC);
|
|
1096
|
+
cart.calculatePrices();
|
|
1097
|
+
// Check price for items
|
|
1098
|
+
expect(itemA.calculatedPrice).toEqual(5000);
|
|
1099
|
+
expect(itemB.calculatedPrice).toEqual(4000);
|
|
1100
|
+
expect(itemC.calculatedPrice).toEqual(5000);
|
|
1101
|
+
// Check calculated discount is 50_00 * 0.10 = 5_00
|
|
1102
|
+
expect(cart.bundleDiscounts.map(c => c.netTotal)).toHaveLength(1);
|
|
1103
|
+
expect(cart.bundleDiscounts[0].total).toEqual(500);
|
|
1104
|
+
expect(cart.bundleDiscounts[0].netTotal).toEqual(500);
|
|
1105
|
+
expect(cart.price).toEqual(5000 + 4000 + 5000);
|
|
1106
|
+
expect(checkout.totalPrice).toEqual(5000 + 4000 + 5000 - 500);
|
|
1107
|
+
expect(checkout.priceBreakown).toEqual([
|
|
1108
|
+
expect.objectContaining({
|
|
1109
|
+
price: 5000 + 4000 + 5000,
|
|
1110
|
+
}),
|
|
1111
|
+
{
|
|
1112
|
+
name: 'Multiple lessons discount (John)',
|
|
1113
|
+
price: -500,
|
|
1114
|
+
},
|
|
1115
|
+
expect.objectContaining({
|
|
1116
|
+
price: 5000 + 4000 + 5000 - 500,
|
|
1117
|
+
}),
|
|
1118
|
+
]);
|
|
1119
|
+
// Add a historic registration for member B, so it also gets a discount
|
|
1120
|
+
addHistoricRegistration(memberB, groupB, organization);
|
|
1121
|
+
cart.calculatePrices();
|
|
1122
|
+
expect(checkout.priceBreakown).toEqual([
|
|
1123
|
+
expect.objectContaining({
|
|
1124
|
+
price: 5000 + 4000 + 5000, // no change
|
|
1125
|
+
}),
|
|
1126
|
+
{
|
|
1127
|
+
name: 'Multiple lessons discount (John)',
|
|
1128
|
+
price: -500,
|
|
1129
|
+
},
|
|
1130
|
+
{
|
|
1131
|
+
name: 'Multiple lessons discount (Jane)',
|
|
1132
|
+
price: -500,
|
|
1133
|
+
},
|
|
1134
|
+
expect.objectContaining({
|
|
1135
|
+
price: 5000 + 4000 + 5000 - 500 - 500,
|
|
1136
|
+
}),
|
|
1137
|
+
]);
|
|
1138
|
+
});
|
|
1139
|
+
test('Bundles with countPerGroup only count per unique group', () => {
|
|
1140
|
+
const { organization, groups, family, discount } = setupDiscountTest({
|
|
1141
|
+
memberCount: 2,
|
|
1142
|
+
groupNames: ['Group A', 'Group B'],
|
|
1143
|
+
bundleDiscount: createBundleDiscount({
|
|
1144
|
+
name: 'Multiple family members discount',
|
|
1145
|
+
countWholeFamily: true,
|
|
1146
|
+
countPerGroup: true,
|
|
1147
|
+
discounts: [
|
|
1148
|
+
{ value: 1000, type: GroupPriceDiscount_js_1.GroupPriceDiscountType.Percentage },
|
|
1149
|
+
],
|
|
1150
|
+
}),
|
|
1151
|
+
});
|
|
1152
|
+
const [groupA, groupB] = groups;
|
|
1153
|
+
const [memberA, memberB] = family.members;
|
|
1154
|
+
// Both members register for the different groups, does not give the discount
|
|
1155
|
+
const itemA = RegisterItem_js_1.RegisterItem.defaultFor(memberA, groupA, organization);
|
|
1156
|
+
const itemB = RegisterItem_js_1.RegisterItem.defaultFor(memberB, groupB, organization);
|
|
1157
|
+
// Add to a single cart
|
|
1158
|
+
const checkout = family.checkout;
|
|
1159
|
+
const cart = checkout.cart;
|
|
1160
|
+
cart.add(itemA);
|
|
1161
|
+
cart.add(itemB);
|
|
1162
|
+
cart.calculatePrices();
|
|
1163
|
+
// No discount should be applied yet (need at least 2 different groups)
|
|
1164
|
+
expect(cart.bundleDiscounts).toHaveLength(0);
|
|
1165
|
+
expect(checkout.totalPrice).toEqual(5000 + 4000);
|
|
1166
|
+
// Now register one member for group B as well
|
|
1167
|
+
const itemC = RegisterItem_js_1.RegisterItem.defaultFor(memberA, groupB, organization);
|
|
1168
|
+
cart.add(itemC);
|
|
1169
|
+
cart.calculatePrices();
|
|
1170
|
+
// Now we should get a discount
|
|
1171
|
+
expect(cart.bundleDiscounts).toHaveLength(1);
|
|
1172
|
+
expect(cart.bundleDiscounts[0].total).toEqual(400); // 10% of 40_00 (not 50_00)
|
|
1173
|
+
expect(cart.bundleDiscounts[0].netTotal).toEqual(400);
|
|
1174
|
+
expect(cart.price).toEqual(5000 + 4000 + 4000);
|
|
1175
|
+
expect(checkout.totalPrice).toEqual(5000 + 4000 + 4000 - 400);
|
|
1176
|
+
expect(checkout.priceBreakown).toEqual([
|
|
1177
|
+
expect.objectContaining({
|
|
1178
|
+
price: 5000 + 4000 + 4000,
|
|
1179
|
+
}),
|
|
1180
|
+
{
|
|
1181
|
+
name: 'Multiple family members discount (Group B)',
|
|
1182
|
+
price: -400,
|
|
1183
|
+
},
|
|
1184
|
+
expect.objectContaining({
|
|
1185
|
+
price: 5000 + 4000 + 4000 - 400,
|
|
1186
|
+
}),
|
|
1187
|
+
]);
|
|
1188
|
+
// Change calculation to count across groups
|
|
1189
|
+
discount.countPerGroup = false;
|
|
1190
|
+
cart.calculatePrices();
|
|
1191
|
+
// Now we should get a discount for both groups
|
|
1192
|
+
expect(checkout.priceBreakown).toEqual([
|
|
1193
|
+
expect.objectContaining({
|
|
1194
|
+
price: 5000 + 4000 + 4000,
|
|
1195
|
+
}),
|
|
1196
|
+
{
|
|
1197
|
+
name: 'Multiple family members discount',
|
|
1198
|
+
price: -900,
|
|
1199
|
+
},
|
|
1200
|
+
expect.objectContaining({
|
|
1201
|
+
price: 5000 + 4000 + 4000 - 900,
|
|
1202
|
+
}),
|
|
1203
|
+
]);
|
|
1204
|
+
});
|
|
1205
|
+
test('countPerGroup = true is ignored if countWholeFamily is false', () => {
|
|
1206
|
+
const { organization, groups, family, discount } = setupDiscountTest({
|
|
1207
|
+
memberCount: 2,
|
|
1208
|
+
groupNames: ['Group A', 'Group B'],
|
|
1209
|
+
bundleDiscount: createBundleDiscount({
|
|
1210
|
+
name: 'Multiple lessons discount',
|
|
1211
|
+
countWholeFamily: false, // This means only count per unique member
|
|
1212
|
+
countPerGroup: true, // This should be ignored since countWholeFamily is false
|
|
1213
|
+
discounts: [
|
|
1214
|
+
{ value: 1000, type: GroupPriceDiscount_js_1.GroupPriceDiscountType.Percentage },
|
|
1215
|
+
],
|
|
1216
|
+
}),
|
|
1217
|
+
});
|
|
1218
|
+
const [groupA, groupB] = groups;
|
|
1219
|
+
const [memberA, memberB] = family.members;
|
|
1220
|
+
// Register member A for both group A and B
|
|
1221
|
+
// Register member B for group A
|
|
1222
|
+
const itemA = RegisterItem_js_1.RegisterItem.defaultFor(memberA, groupA, organization);
|
|
1223
|
+
const itemB = RegisterItem_js_1.RegisterItem.defaultFor(memberA, groupB, organization);
|
|
1224
|
+
const itemC = RegisterItem_js_1.RegisterItem.defaultFor(memberB, groupA, organization);
|
|
1225
|
+
// Add to a single cart
|
|
1226
|
+
const checkout = family.checkout;
|
|
1227
|
+
const cart = checkout.cart;
|
|
1228
|
+
cart.add(itemA);
|
|
1229
|
+
cart.add(itemB);
|
|
1230
|
+
cart.add(itemC);
|
|
1231
|
+
cart.calculatePrices();
|
|
1232
|
+
// Check price for items
|
|
1233
|
+
expect(itemA.calculatedPrice).toEqual(5000);
|
|
1234
|
+
expect(itemB.calculatedPrice).toEqual(4000);
|
|
1235
|
+
expect(itemC.calculatedPrice).toEqual(5000);
|
|
1236
|
+
// Check calculated discount - should only apply to member A (who has multiple registrations)
|
|
1237
|
+
expect(cart.bundleDiscounts).toHaveLength(1);
|
|
1238
|
+
expect(cart.bundleDiscounts[0].total).toEqual(500); // 10% of 50_00 (we always apply discounts to highest price first)
|
|
1239
|
+
expect(cart.bundleDiscounts[0].netTotal).toEqual(500);
|
|
1240
|
+
expect(cart.price).toEqual(5000 + 4000 + 5000);
|
|
1241
|
+
expect(checkout.totalPrice).toEqual(5000 + 4000 + 5000 - 500);
|
|
1242
|
+
expect(checkout.priceBreakown).toEqual([
|
|
1243
|
+
expect.objectContaining({
|
|
1244
|
+
price: 5000 + 4000 + 5000,
|
|
1245
|
+
}),
|
|
1246
|
+
{
|
|
1247
|
+
name: 'Multiple lessons discount (John)',
|
|
1248
|
+
price: -500,
|
|
1249
|
+
},
|
|
1250
|
+
expect.objectContaining({
|
|
1251
|
+
price: 5000 + 4000 + 5000 - 500,
|
|
1252
|
+
}),
|
|
1253
|
+
]);
|
|
1254
|
+
// Now explicitly turn on countPerGroup and set countWholeFamily to true
|
|
1255
|
+
// to verify it behaves differently (proving that countPerGroup was indeed ignored before)
|
|
1256
|
+
discount.countWholeFamily = true;
|
|
1257
|
+
discount.countPerGroup = true;
|
|
1258
|
+
cart.calculatePrices();
|
|
1259
|
+
// Now we should get a discount for group A (since two members are registered for it)
|
|
1260
|
+
expect(checkout.priceBreakown).toEqual([
|
|
1261
|
+
expect.objectContaining({
|
|
1262
|
+
price: 5000 + 4000 + 5000,
|
|
1263
|
+
}),
|
|
1264
|
+
{
|
|
1265
|
+
name: 'Multiple lessons discount (Group A)',
|
|
1266
|
+
price: -500, // 10% of the second 50_00
|
|
1267
|
+
},
|
|
1268
|
+
expect.objectContaining({
|
|
1269
|
+
price: 5000 + 4000 + 5000 - 500,
|
|
1270
|
+
}),
|
|
1271
|
+
]);
|
|
1272
|
+
});
|
|
1273
|
+
test('Past discounts are only altered if a related registration is added or removed', () => {
|
|
1274
|
+
// Create two historic registrations that didn't get an existing discount (= error)
|
|
1275
|
+
// now, add a new registration to the cart that is not applicable to the discount - the old discount should not be altered
|
|
1276
|
+
const { organization, groups, family, period, discount } = setupDiscountTest({
|
|
1277
|
+
memberCount: 2,
|
|
1278
|
+
groupPrices: [5000, 4000],
|
|
1279
|
+
groupNames: ['Group A', 'Group B'],
|
|
1280
|
+
bundleDiscount: createBundleDiscount({
|
|
1281
|
+
name: 'Multiple family members discount',
|
|
1282
|
+
countWholeFamily: true,
|
|
1283
|
+
countPerGroup: false,
|
|
1284
|
+
discounts: [
|
|
1285
|
+
{ value: 1000, type: GroupPriceDiscount_js_1.GroupPriceDiscountType.Percentage },
|
|
1286
|
+
],
|
|
1287
|
+
}),
|
|
1288
|
+
});
|
|
1289
|
+
const [groupA, groupB] = groups;
|
|
1290
|
+
const [memberA, memberB] = family.members;
|
|
1291
|
+
const registrationA = addHistoricRegistration(memberA, groupA, organization);
|
|
1292
|
+
const registrationB = addHistoricRegistration(memberB, groupB, organization);
|
|
1293
|
+
// Create a new group that is not applicable to the discount
|
|
1294
|
+
const [groupC] = createTestGroups(organization, period, [3000], ['Group C']);
|
|
1295
|
+
const itemC = RegisterItem_js_1.RegisterItem.defaultFor(memberA, groupC, organization);
|
|
1296
|
+
// Add to a single cart
|
|
1297
|
+
const checkout = family.checkout;
|
|
1298
|
+
const cart = checkout.cart;
|
|
1299
|
+
cart.add(itemC);
|
|
1300
|
+
cart.calculatePrices();
|
|
1301
|
+
expect(itemC.calculatedPrice).toEqual(3000);
|
|
1302
|
+
expect(cart.bundleDiscounts).toHaveLength(0);
|
|
1303
|
+
expect(checkout.totalPrice).toEqual(3000);
|
|
1304
|
+
expect(checkout.priceBreakown).toEqual([
|
|
1305
|
+
expect.objectContaining({
|
|
1306
|
+
price: 3000,
|
|
1307
|
+
}),
|
|
1308
|
+
]);
|
|
1309
|
+
// Now also register memberB for group A and add it to the cart
|
|
1310
|
+
const itemD = RegisterItem_js_1.RegisterItem.defaultFor(memberB, groupA, organization);
|
|
1311
|
+
cart.add(itemD);
|
|
1312
|
+
cart.calculatePrices();
|
|
1313
|
+
// Check price for items
|
|
1314
|
+
expect(itemD.calculatedPrice).toEqual(5000);
|
|
1315
|
+
expect(itemC.calculatedPrice).toEqual(3000);
|
|
1316
|
+
// Check calculated discount: should also take old registrations into account
|
|
1317
|
+
// 50_00 * 10% + 50_00 * 10% = 5_00 + 5_00 = 10_00
|
|
1318
|
+
expect(cart.bundleDiscounts).toHaveLength(1);
|
|
1319
|
+
expect(cart.bundleDiscounts[0].total).toEqual(1000);
|
|
1320
|
+
expect(cart.bundleDiscounts[0].totalAlreadyApplied).toEqual(0);
|
|
1321
|
+
expect(cart.bundleDiscounts[0].netTotal).toEqual(1000);
|
|
1322
|
+
expect(cart.price).toEqual(5000 + 3000);
|
|
1323
|
+
expect(checkout.totalPrice).toEqual(5000 + 3000 - 1000);
|
|
1324
|
+
expect(checkout.priceBreakown).toEqual([
|
|
1325
|
+
expect.objectContaining({
|
|
1326
|
+
price: 5000 + 3000,
|
|
1327
|
+
}),
|
|
1328
|
+
{
|
|
1329
|
+
name: 'Multiple family members discount',
|
|
1330
|
+
price: -1000,
|
|
1331
|
+
},
|
|
1332
|
+
expect.objectContaining({
|
|
1333
|
+
price: 5000 + 3000 - 1000,
|
|
1334
|
+
}),
|
|
1335
|
+
]);
|
|
1336
|
+
});
|
|
1337
|
+
test('Fixed discounts are limited to the group price', () => {
|
|
1338
|
+
const { organization, groups, family, discount } = setupDiscountTest({
|
|
1339
|
+
memberCount: 2,
|
|
1340
|
+
groupNames: ['Group A', 'Group B'],
|
|
1341
|
+
bundleDiscount: createBundleDiscount({
|
|
1342
|
+
name: 'Multiple family members discount',
|
|
1343
|
+
countWholeFamily: true,
|
|
1344
|
+
countPerGroup: false,
|
|
1345
|
+
discounts: [
|
|
1346
|
+
{ value: 100000, type: GroupPriceDiscount_js_1.GroupPriceDiscountType.Fixed },
|
|
1347
|
+
],
|
|
1348
|
+
}),
|
|
1349
|
+
});
|
|
1350
|
+
const [groupA, groupB] = groups;
|
|
1351
|
+
const [memberA, memberB] = family.members;
|
|
1352
|
+
const itemA = RegisterItem_js_1.RegisterItem.defaultFor(memberA, groupA, organization);
|
|
1353
|
+
const itemB = RegisterItem_js_1.RegisterItem.defaultFor(memberB, groupB, organization);
|
|
1354
|
+
// Add to a single cart
|
|
1355
|
+
const checkout = family.checkout;
|
|
1356
|
+
const cart = checkout.cart;
|
|
1357
|
+
cart.add(itemA);
|
|
1358
|
+
cart.add(itemB);
|
|
1359
|
+
cart.calculatePrices();
|
|
1360
|
+
expect(cart.bundleDiscounts).toHaveLength(1);
|
|
1361
|
+
expect(cart.bundleDiscounts[0].total).toEqual(5000);
|
|
1362
|
+
expect(cart.bundleDiscounts[0].totalAlreadyApplied).toEqual(0);
|
|
1363
|
+
expect(cart.bundleDiscounts[0].netTotal).toEqual(5000);
|
|
1364
|
+
expect(cart.price).toEqual(5000 + 4000);
|
|
1365
|
+
expect(checkout.totalPrice).toEqual(4000);
|
|
1366
|
+
expect(checkout.priceBreakown).toEqual([
|
|
1367
|
+
expect.objectContaining({
|
|
1368
|
+
price: 5000 + 4000,
|
|
1369
|
+
}),
|
|
1370
|
+
{
|
|
1371
|
+
name: 'Multiple family members discount',
|
|
1372
|
+
price: -5000,
|
|
1373
|
+
},
|
|
1374
|
+
expect.objectContaining({
|
|
1375
|
+
price: 4000,
|
|
1376
|
+
}),
|
|
1377
|
+
]);
|
|
1378
|
+
});
|
|
1379
|
+
test.todo('Can handle bundle discounts for a future period');
|
|
1380
|
+
test.todo('Families should be calculated correctly for admins');
|
|
1381
|
+
test.todo('The price per item can never be negative');
|
|
1382
|
+
});
|
|
1383
|
+
});
|
|
1384
|
+
//# sourceMappingURL=RegisterCart.test.js.map
|