diff --git a/src/constants/cart-item-categories.js b/src/constants/cart-item-categories.js index 509cc626b..6bbb960b9 100644 --- a/src/constants/cart-item-categories.js +++ b/src/constants/cart-item-categories.js @@ -3,6 +3,7 @@ const cartItemCategories = { GLASS_PARTS: "glassParts", SUPPORTING_ITEMS: "supportingItems", PROMOS: "promos", + SERVICE_PACKAGE_DISCOUNT: "servicePackageDiscount", }; export { cartItemCategories }; diff --git a/src/constants/cart-item-types.js b/src/constants/cart-item-types.js index 342a4e672..d8ab9f66f 100644 --- a/src/constants/cart-item-types.js +++ b/src/constants/cart-item-types.js @@ -10,6 +10,7 @@ const cartItemTypes = { PROMOS: "PROMOS", EARLY_BIRD: "EARLY BIRD", SUPPLIES_REPAIR: "SUPPLIES-REPAIR", + SERVICE_PACKAGE_DISCOUNT: "SERVICE PACKAGE DISCOUNT", }; export { cartItemTypes }; diff --git a/src/constants/endpoints.js b/src/constants/endpoints.js index 592d2d668..3bc5a3069 100644 --- a/src/constants/endpoints.js +++ b/src/constants/endpoints.js @@ -72,6 +72,10 @@ const endpoints = { url: "/parts/api/v1/parts/mobile-fee", method: "GET", }, + CashServicePackageDiscount: { + url: "/parts/api/v1/parts/service-package-discount", + method: "POST", + }, GetServiceabilityDetails: { url: "/location/api/v1/location/serviceability-details", method: "GET", diff --git a/src/constants/experiments.js b/src/constants/experiments.js index 059f7f27e..ee83ec447 100644 --- a/src/constants/experiments.js +++ b/src/constants/experiments.js @@ -9,6 +9,7 @@ const experimentSettings = { PIA_INSURANCE: "DisplayPIAInsurance", SUBMIT_ORDER_ENABLE_PIA: "SubmitOrder_Enable_PIA", IS_EMAIL_OPTIONAL: "isEmailOptional", + SERVICE_PACKAGE_DISCOUNT: "OfferServicePackageDiscount", }; const experimentTriggers = { diff --git a/src/constants/part-type-strings.js b/src/constants/part-type-strings.js index aa56d1ed2..3ad66c40a 100644 --- a/src/constants/part-type-strings.js +++ b/src/constants/part-type-strings.js @@ -8,6 +8,7 @@ const partTypeStrings = { MOBILE_FEE: "MOBILE FEE", REPAIR_FEE: "REPAIR FEE", EARLY_BIRD: "EARLY BIRD", + SERVICE_PACKAGE_DISCOUNT: "SERVICE PACKAGE DISCOUNT", }; export { partTypeStrings }; diff --git a/src/constants/store-actions.js b/src/constants/store-actions.js index aa8c0ccb0..4ff481e64 100644 --- a/src/constants/store-actions.js +++ b/src/constants/store-actions.js @@ -29,6 +29,7 @@ const storeActions = { GET_PART_FROM_CAPABILITY_QUESTION_ANSWER: "getPartFromCapabilityQuestionAnswer", GET_MOLDING_QUESTIONS: "getMoldingQuestions", GET_MOBILE_FEE_PART: "getMobileFeePart", + CASH_SERVICE_PACKAGE_DISCOUNT: "cashServicePackageDiscount", GET_SERVICEABILITY_DETAILS: "getServiceabilityDetails", GET_SHOP_TIME_SLOTS: "getShopTimeSlots", GET_MOBILE_TIME_SLOTS: "getMobileTimeSlots", diff --git a/src/fmg-components/cart/cart.spec.js b/src/fmg-components/cart/cart.spec.js index cbb5a1610..10207c8bb 100644 --- a/src/fmg-components/cart/cart.spec.js +++ b/src/fmg-components/cart/cart.spec.js @@ -306,6 +306,49 @@ describe("cart.vue", () => { expect(found).toBe(true); }); + // Service package discount Fee Cart Item + test("if there is service package discount fee on the order, a service package discount cart item should be added to the cart", () => { + // Arrange + const lineItems = { + glassParts: [], + supportingItems: [ + { + description: null, + id: "bc00294e-6baa-403e-866e-52c267187a15", + kitPrice: 0, + laborAmount: 0, + partNumber: "DISC CASHSAVE70", + partType: "SERVICE PACKAGE DISCOUNT", + salesTax: null, + sellingPrice: -70, + }, + ], + vaps: [], + promos: [], + }; + + const availableVaps = []; + + // Act + const { wrapper } = setupMocks({ + props: { + modelValue: lineItems, + availableVaps: availableVaps, + }, + }); + + // Assert + expect(wrapper.vm.servicePackageDiscountCartItem).not.toBeNull(); + expect(wrapper.vm.servicePackageDiscountCartItem.subTotal).toEqual(-70); + expect(wrapper.vm.servicePackageDiscountCartItem.salesTax).toEqual(0); + + const found = + wrapper.vm.cartItems.findIndex( + (cartItem) => cartItem == wrapper.vm.servicePackageDiscountCartItem + ) >= 0; + expect(found).toBe(true); + }); + // Other Supporting Items Cart Item test("if there are other supporting items on the order, an other supporting items cart item should be added to the cart but should not be displayed", () => { // Arrange diff --git a/src/fmg-components/cart/cart.vue b/src/fmg-components/cart/cart.vue index dcf1375b7..74b856498 100644 --- a/src/fmg-components/cart/cart.vue +++ b/src/fmg-components/cart/cart.vue @@ -225,6 +225,13 @@ export default { return subTotal; }, + getServicePackageDiscount() { + const servicePackageDiscountLineItems = this.servicePackageDiscountCartItem; + let subTotal = 0; + + subTotal += servicePackageDiscountLineItems?.subTotal; + return subTotal; + }, getVapsCartItemsForSelectedPackage(packageName) { const packageContentTypes = getPackageContents( this.glassToReplace, @@ -265,7 +272,7 @@ export default { getLineItemAmount(amount, useVerifyingText, category) { if (useVerifyingText) return this.verifyingCoverageText; - return category == "promos" + return category == ("promos" && "servicePackageDiscount") ? "(" + this.currencyFormatter.format(amount * -1) + ")" : this.currencyFormatter.format(amount); }, @@ -372,6 +379,9 @@ export default { if (this.mobileFeeCartItem) { cartItems.push(this.mobileFeeCartItem); } + if (this.servicePackageDiscountCartItem) { + cartItems.push(this.servicePackageDiscountCartItem); + } if (this.premiumAppointmentDiscountCartItem) { cartItems.push(this.premiumAppointmentDiscountCartItem); @@ -422,6 +432,9 @@ export default { } packagePrice += this.getVapsPrice(this.packageLevel); + if (this.servicePackageDiscountCartItem) { + packagePrice -= this.getServicePackageDiscount(); + } return packagePrice; }, @@ -769,13 +782,58 @@ export default { return cartItem; }, + servicePackageDiscountCartItemName() { + return this.getCmsContent("ServicePackageDiscountTextWidget", "Text"); + }, + servicePackageDiscountCartItem() { + let cartItem = null; + + const servicePackageDiscountLineItem = this.supportingItems.find( + (lineItem) => lineItem.partType == partTypeStrings.SERVICE_PACKAGE_DISCOUNT + ); + + if (servicePackageDiscountLineItem) { + cartItem = { + name: + this.servicePackageDiscountCartItemName + + Math.abs( + baseMixin.methods.getTotalLineItemPrice(servicePackageDiscountLineItem) + ), + category: cartItemCategories.SERVICE_PACKAGE_DISCOUNT, + cartItemType: cartItemTypes.SERVICE_PACKAGE_DISCOUNT, + isDisplayed: true, + isRemovable: false, + subTotal: 0, + salesTax: 0, + lineItems: [], + isCoveredByInsurance: false, + }; + + servicePackageDiscountLineItem.cartItemType = cartItem.cartItemType; + cartItem.lineItems.push(servicePackageDiscountLineItem); + + cartItem.subTotal += + (servicePackageDiscountLineItem.kitPrice ?? 0) + + (servicePackageDiscountLineItem.laborAmount ?? 0) + + (servicePackageDiscountLineItem.sellingPrice ?? 0); + + cartItem.salesTax += servicePackageDiscountLineItem.salesTax ?? 0; + } + + return cartItem; + }, otherSupportingItemsCartItem() { let cartItem = null; - // Don't include fees they are part of the package total - let otherSupportingItemsLineItems = baseMixin.methods.filterOutFees( - this.supportingItems + const servicePackageDiscountLineItem = this.supportingItems.find( + (lineItem) => lineItem.partType == partTypeStrings.SERVICE_PACKAGE_DISCOUNT ); + const otherSupportingItems = this.supportingItems.filter((item) => { + return item != servicePackageDiscountLineItem; + }); + // Don't include fees they are part of the package total + let otherSupportingItemsLineItems = + baseMixin.methods.filterOutFees(otherSupportingItems); if (otherSupportingItemsLineItems.length > 0) { cartItem = { diff --git a/src/layouts/quote/quote.spec.js b/src/layouts/quote/quote.spec.js index 323b9a7d5..56a8d66e6 100644 --- a/src/layouts/quote/quote.spec.js +++ b/src/layouts/quote/quote.spec.js @@ -6,6 +6,8 @@ import quote from "@/layouts/quote/quote.vue"; import store from "@/store"; import * as navigateToHeritage from "@/helpers/heritage-integration/navigation-helper"; import { nextTick } from "vue"; +import { experimentSettings } from "@/constants/experiments"; +import baseMixin from "@/mixins/base-mixin.js"; jest.mock("@/store", () => ({ commit: jest.fn(), @@ -60,9 +62,14 @@ const mockMixin = { filterOutFees: jest.fn().mockImplementation(() => { return null; }), + getSettingValue: jest.fn((settingName) => { + if (settingName === experimentSettings.SERVICE_PACKAGE_DISCOUNT) { + return true; + } + return false; + }), }, }; - let mockTierOnePrice = 501; const mockPriceOrderStoreAction = storeActions.PRICE_ORDER_ITEMS_AND_SAVE_SERVER_DATA; @@ -234,8 +241,12 @@ describe("quote.vue", () => { vehicle: { cardId: "123", }, + experimentSettings: { + settingName: "SERVICE_PACKAGE_DISCOUNT", + }, }; const { wrapper } = setupMocks({}); + //mock this to avoid needing to populate this.$route in an unrelated test wrapper.vm.getDefaultIsInsuranceSelectedValue = jest.fn(); @@ -254,6 +265,47 @@ describe("quote.vue", () => { // This should have its own test //expect(vm.isInsuranceSelected !== null).toBe(true); }); + test("Returns true if service package discount setting is true", async () => { + //Arrange + store.getters = { + lineItems: { + glassParts: ["item", "item2"], + }, + order: { + lineItems: { + glassParts: ["item", "item2"], + }, + payment: {}, + serviceLocation: { + zipCode: "12345", + zipCodeCtu: "value", + }, + }, + vehicle: { + cardId: "123", + }, + experimentSettings: { + settingName: "SERVICE_PACKAGE_DISCOUNT", + }, + }; + const { wrapper } = setupMocks({}); + + wrapper.vm.$route = { query: { isInsurance: "false" } }; + + const isServicePackageDiscount = mockMixin.methods.getSettingValue( + experimentSettings.SERVICE_PACKAGE_DISCOUNT + ); + + //Act + await quote.beforeRouteEnter.call( + wrapper.vm, + { query: { fmgPage: "quote" } }, + undefined, + (c) => c(wrapper.vm) + ); + //Assert + expect(isServicePackageDiscount).toBe(true); + }); test("should default to insurance if query param 'isInsurance' is true", async () => { //Arrange store.getters = { @@ -274,6 +326,9 @@ describe("quote.vue", () => { vehicle: { cardId: "123", }, + experimentSettings: { + settingName: "SERVICE_PACKAGE_DISCOUNT", + }, }; const { wrapper } = setupMocks({}); wrapper.vm.$route = { query: { isInsurance: "true" } }; @@ -309,6 +364,9 @@ describe("quote.vue", () => { vehicle: { cardId: "123", }, + experimentSettings: { + settingName: "SERVICE_PACKAGE_DISCOUNT", + }, }; const { wrapper } = setupMocks({}); wrapper.vm.$route = { query: { isInsurance: "false" } }; @@ -345,6 +403,9 @@ describe("quote.vue", () => { vehicle: { cardId: "123", }, + experimentSettings: { + settingName: "SERVICE_PACKAGE_DISCOUNT", + }, }; const { wrapper } = setupMocks({}); // Ensure that query param isn't overriding selection @@ -381,6 +442,9 @@ describe("quote.vue", () => { vehicle: { cardId: "123", }, + experimentSettings: { + settingName: "SERVICE_PACKAGE_DISCOUNT", + }, }; const { wrapper } = setupMocks({}); // Ensure that query param isn't overriding selection @@ -418,6 +482,9 @@ describe("quote.vue", () => { vehicle: { cardId: "123", }, + experimentSettings: { + settingName: "SERVICE_PACKAGE_DISCOUNT", + }, }; mockTierOnePrice = 200; const { wrapper } = setupMocks({}); @@ -457,6 +524,9 @@ describe("quote.vue", () => { vehicle: { cardId: "123", }, + experimentSettings: { + settingName: "SERVICE_PACKAGE_DISCOUNT", + }, }; mockTierOnePrice = 505; const { wrapper } = setupMocks({}); @@ -495,6 +565,9 @@ describe("quote.vue", () => { vehicle: { cardId: "123", }, + experimentSettings: { + settingName: "SERVICE_PACKAGE_DISCOUNT", + }, }; const { wrapper } = setupMocks({}); wrapper.vm.$route = { query: null }; @@ -533,6 +606,35 @@ describe("quote.vue", () => { expect(wrapper.vm.lineItems.promos !== null).toBe(true); }); + test("On forward button action save supporting lineItems", async () => { + //Arrange + store.getters.payment = { + insuranceCoverage: {}, + isInsurance: false, + }; + store.getters.order = { + lineItems: [], + payment: { + parentAccountNumber: 167132, + }, + }; + const { wrapper } = setupMocks({ + customMountOptions: { + router: { + navigateWithSaving: jest.fn(), + }, + route: { quote }, + }, + }); + + wrapper.vm.forwardButtonAction(); + + expect(wrapper.vm.dispatchStoreAction).toHaveBeenCalledWith( + "saveSupportingItems", + wrapper.vm.lineItems.supportingItems, + false + ); + }); }); function setupMocks({ customMountOptions }) { diff --git a/src/layouts/quote/quote.vue b/src/layouts/quote/quote.vue index c9ddd2f89..a09b18bdc 100644 --- a/src/layouts/quote/quote.vue +++ b/src/layouts/quote/quote.vue @@ -29,6 +29,7 @@ :availableLineItems="availableLineItems" :isInsuranceSelected="isInsuranceSelected" @vapsItemsSelected="vapsItemsSelectedAction" + @servicePackageDiscountSelected="servicePackageDiscountSelectedAction" :activePromos="lineItems.promos" v-on="{ 'buttonEvent.openModal': openModalAction }" validationRules="option-required" @@ -86,6 +87,7 @@ import contentGroupModal from "@/fmg-components/content-group-modal/content-grou import loadingModal from "@/fmg-components/loading-modal/loading-modal.vue"; import afterpayModalBanner from "@/layouts/quote/afterpay-modal-banner/afterpay-modal-banner"; import baseMixin from "@/mixins/base-mixin.js"; +import experimentMixin from "@/mixins/experiment-mixin.js"; import vehicleQuestionsMixin from "../../mixins/vehicle-questions-mixin"; import { settleAllPromises } from "@/helpers/layout-helper"; import { storeActions } from "@/constants/store-actions"; @@ -105,7 +107,7 @@ import { import { queryStrings } from "@/constants/query-strings"; import { getQuerystringParameter } from "@/helpers/querystring-helper"; import promoModalQuestion from "@/fmg-components/promo-modal-question/promo-modal-question"; - +import { experimentSettings } from "@/constants/experiments"; defineRule("option-required", required(errorMessages.OPTION_REQUIRED)); export default { @@ -155,11 +157,27 @@ export default { const lineItems = deepClone(store.getters.order.lineItems); lineItems.vaps = lineItems.vaps ?? []; const nullSafeGlassParts = lineItems.glassParts ?? []; + const servicePackageDiscountSettingValue = experimentMixin.methods.getSettingValue( + experimentSettings.SERVICE_PACKAGE_DISCOUNT + ); + const isServicePackageDiscount = servicePackageDiscountSettingValue === "True"; + //Service package cash discount api call when experiment is active + var servicePackageDiscountPart = []; + if (isServicePackageDiscount) { + const servicePackageDiscountPartResponse = + await baseMixin.methods.dispatchStoreActionWithLogging( + storeActions.CASH_SERVICE_PACKAGE_DISCOUNT, + null, + "quote" + ); + servicePackageDiscountPart.push(servicePackageDiscountPartResponse.data); + } const availableLineItems = [ resultMap.rainDefense, ...resultMap.supportingItems, ...resultMap.wipers, ...nullSafeGlassParts, + ...servicePackageDiscountPart, ]; const pricingResults = await baseMixin.methods.dispatchStoreActionWithLogging( @@ -278,6 +296,9 @@ export default { vapsItemsSelectedAction(vapsItemsSelected) { this.lineItems.vaps = vapsItemsSelected; }, + servicePackageDiscountSelectedAction(servicePackageDiscountSelected) { + this.lineItems.supportingItems = servicePackageDiscountSelected; + }, backButtonAction() { vehicleQuestionsMixin.methods.navigateBack(this); }, @@ -315,7 +336,11 @@ export default { false ); } - + this.dispatchStoreAction( + this.storeActions.SAVE_SUPPORTING_ITEMS, + this.lineItems.supportingItems, + false + ); this.dispatchStoreAction(this.storeActions.SAVE_VAPS, this.lineItems.vaps, false); this.dispatchStoreAction( storeActions.SAVE_ACTIVE_AND_OR_INACTIVE_PROMOS, diff --git a/src/layouts/quote/service-package-question/service-package-question.spec.js b/src/layouts/quote/service-package-question/service-package-question.spec.js index 8163c6324..80a769ec3 100644 --- a/src/layouts/quote/service-package-question/service-package-question.spec.js +++ b/src/layouts/quote/service-package-question/service-package-question.spec.js @@ -6,6 +6,12 @@ import { mockProcessedCmsContent, inputQuestionWidgetAnswers, } from "./service-package-question-test-helper"; +import { + containsLineItemWithPartType, + findLineItemsWithPartType, +} from "@/helpers/service-package-helper"; +import baseMixin from "@/mixins/base-mixin.js"; +import { partTypeStrings } from "@/constants/part-type-strings"; import { nextTick } from "vue"; jest.mock("@/store", () => ({ @@ -45,7 +51,46 @@ describe("service-package-question.vue", () => { partType: "RAIN DEFENSE", price: 35.5, }, + { + partNumber: "DISC CASHSAVE70", + description: null, + partType: "SERVICE PACKAGE DISCOUNT", + price: -70, + }, ], + lineItems: { + supportingItems: [ + { + description: null, + id: "b0c68683-da85-46ba-bc86-2642bd9d5fdb", + kitPrice: 0, + laborAmount: 0, + partNumber: "RECYCLE FEE", + partType: "REPLACE FEE", + salesTax: null, + sellingPrice: 0, + }, + { + description: null, + id: "5f205a07-3c08-4244-9935-76d63a7bcd19", + kitPrice: 0, + laborAmount: 395, + partNumber: "RECAL STATIC", + partType: "RECALIBRATION", + salesTax: null, + sellingPrice: 0, + }, + { + description: null, + kitPrice: 0, + laborAmount: 0, + partNumber: "DISC CASHSAVE70", + partType: "SERVICE PACKAGE DISCOUNT", + salesTax: null, + sellingPrice: -70, + }, + ], + }, activePromos: [], }; const packageNameKey = "05_01_CSR_Quote_Standard_Repair"; @@ -68,6 +113,44 @@ describe("service-package-question.vue", () => { }, ]); }); + it("should return price when there is discount", () => { + const wrapper = setupMocks({}); + const partType = partTypeStrings.SERVICE_PACKAGE_DISCOUNT; + + wrapper.vm.isServicePackageDiscountOnOrder = containsLineItemWithPartType( + partType, + mockProps.lineItems.supportingItems + ); + const servicePackageDiscountLineItem = findLineItemsWithPartType( + partType, + mockProps.lineItems.supportingItems + ); + wrapper.vm.getServicePackageDiscountPrice(); + const price = baseMixin.methods.getTotalLineItemPrice(servicePackageDiscountLineItem[0]); + + expect(Math.abs(price)).toEqual(70); + }); + it("isServicePackageDiscountOnOrder returns true if it contains service package discount lineItems", () => { + // Arrange + const wrapper = setupMocks({}); + + // Assert + expect(wrapper.vm.isServicePackageDiscountOnOrder).toBe(true); + }); + it("servicePackageDiscountParts should returns service package discount lineItems", () => { + // Arrange + const wrapper = setupMocks({}); + + // Assert + expect(wrapper.vm.servicePackageDiscountParts).toEqual([ + { + partNumber: "DISC CASHSAVE70", + description: null, + partType: "SERVICE PACKAGE DISCOUNT", + price: -70, + }, + ]); + }); it("should have the correct insurance pricing text when insurance is selected", () => { // Arrange mockProps.isInsuranceSelected = true; diff --git a/src/layouts/quote/service-package-question/service-package-question.vue b/src/layouts/quote/service-package-question/service-package-question.vue index 2d0ba515e..c9e55ef3e 100644 --- a/src/layouts/quote/service-package-question/service-package-question.vue +++ b/src/layouts/quote/service-package-question/service-package-question.vue @@ -69,12 +69,34 @@ export default { selectedPackageName(newValue) { const VapsProductsInSelectedPackage = this.getVapsLineItemsForSelectedPackage(newValue); this.$emit("vapsItemsSelected", VapsProductsInSelectedPackage); + const servicePackageDiscountPartInSelectedPackage = + this.getServicePackageDiscountPartForSelectedPackage(newValue); + let supportingItems = this.supportingLineItems; + if (servicePackageDiscountPartInSelectedPackage?.length > 0) { + supportingItems?.push(servicePackageDiscountPartInSelectedPackage[0]); + } else { + if ( + supportingItems?.length > 0 && + containsLineItemWithPartType( + partTypeStrings.SERVICE_PACKAGE_DISCOUNT, + supportingItems + ) + ) { + supportingItems = supportingItems.filter( + (item) => item.partType !== partTypeStrings.SERVICE_PACKAGE_DISCOUNT + ); + } + } + this.$emit("servicePackageDiscountSelected", supportingItems); }, }, computed: { nullSafeAvailableLineItems() { return this.availableLineItems ?? []; }, + supportingLineItems() { + return this.$store.getters.lineItems?.supportingItems; + }, servicePackageAnswers() { const cmsWidgetName = this.isInsuranceSelected ? this.insuranceCmsWidgetName @@ -99,10 +121,16 @@ export default { buttonLabel: this.getHeaderTextFromCms(answer.SubWidgetName), buttonLabelSubCopy: this.getSubheaderTextFromCms(answer.SubWidgetName), buttonBodyCopy: this.getBodyTextFromCms(answer.SubWidgetName), - buttonAuxillaryCopy: this.getDiscountedPackagePriceString(answer.Name), + buttonAuxillaryCopy: this.getDiscountedPackagePriceString( + answer.Name, + this.isServicePackageDiscountOnOrder && answer.Text != "" + ), buttonFooterCopy: this.getFooterTextFromCms(answer.SubWidgetName), additionalButtonData: { strikeThroughPrice: this.getPackagePriceString(answer.Name), + servicePackageDiscount: + this.isServicePackageDiscountOnOrder && answer.Text != "", + Text: answer.Text + this.getServicePackageDiscountPrice(), }, })); return modifiedAnswers; @@ -113,6 +141,12 @@ export default { this.nullSafeAvailableLineItems ); }, + isServicePackageDiscountOnOrder() { + return containsLineItemWithPartType( + partTypeStrings.SERVICE_PACKAGE_DISCOUNT, + this.nullSafeAvailableLineItems + ); + }, frontWipersApplicableForTierTwo() { return shouldFrontWipersBeAvailable( this.glassToReplace, @@ -159,6 +193,12 @@ export default { isRepair() { return this.$store.getters.order.damage.isRepair; }, + servicePackageDiscountParts() { + return findLineItemsWithPartType( + partTypeStrings.SERVICE_PACKAGE_DISCOUNT, + this.nullSafeAvailableLineItems + ); + }, }, methods: { processIfStatements, @@ -178,21 +218,35 @@ export default { }, getPackagePriceString(packageName) { const formattedPriceFloat = parseFloat( - this.getPackagePrice(packageName, { discountedPrice: false }) + this.getPackagePrice(packageName, { + discountedPrice: false, + servicePackageDiscount: false, + }) ).toFixed(2); return "$" + formattedPriceFloat; }, - getDiscountedPackagePriceString(packageName) { + getDiscountedPackagePriceString(packageName, servicePackageDiscount) { const formattedPriceFloat = parseFloat( - this.getPackagePrice(packageName, { discountedPrice: true }) + this.getPackagePrice(packageName, { discountedPrice: true, servicePackageDiscount }) ).toFixed(2); return (this.isInsuranceSelected ? "As little as $" : "$") + formattedPriceFloat; }, - getPackagePrice(packageName, { discountedPrice = false }) { - const lineItemsToPrice = [...this.nullSafeAvailableLineItems]; + getPackagePrice(packageName, { discountedPrice = false, servicePackageDiscount = false }) { + var lineItemsToPrice = [...this.nullSafeAvailableLineItems]; + + //remove service package discount part + if (this.isServicePackageDiscountOnOrder) { + lineItemsToPrice = this.nullSafeAvailableLineItems.filter((item) => { + return item.partType != this.servicePackageDiscountParts[0].partType; + }); + } + if (discountedPrice) { lineItemsToPrice.push(...removeVapsPromosFromPromoArray(this.activePromos)); } + if (servicePackageDiscount) { + lineItemsToPrice.push(...this.servicePackageDiscountParts); + } let priceFloat = this.isInsuranceSelected ? 0 : baseMixin.methods.getTierOnePackagePrice( @@ -203,9 +257,17 @@ export default { return priceFloat; }, + getServicePackageDiscountPrice() { + if (this.isServicePackageDiscountOnOrder) { + let price = 0; + price += baseMixin.methods.getTotalLineItemPrice( + this.servicePackageDiscountParts[0] + ); + return Math.abs(price); + } + }, getVapsPrice(packageName, applyPromoDiscounts = false) { const vapsItems = this.getVapsLineItemsForSelectedPackage(packageName); - let price = 0; vapsItems.forEach((item) => { @@ -261,6 +323,14 @@ export default { return vapsLineItemsForSelectedPackage; }, + getServicePackageDiscountPartForSelectedPackage(packageName) { + const selectedPackage = this.servicePackageAnswers.filter( + (item) => item.value === packageName + ); + if (selectedPackage?.[0]?.additionalButtonData?.servicePackageDiscount) { + return this.servicePackageDiscountParts; + } else return []; + }, combineLineItemsWithoutDuplicates(lineItemsOne, lineItemsTwo) { const combinedLineItemArray = [...lineItemsTwo]; lineItemsOne.forEach((lineItemOne) => { diff --git a/src/layouts/quote/service-package-question/service-package-radio/service-package-radio.spec.js b/src/layouts/quote/service-package-question/service-package-radio/service-package-radio.spec.js index fe42a73d0..83bf0a02e 100644 --- a/src/layouts/quote/service-package-question/service-package-radio/service-package-radio.spec.js +++ b/src/layouts/quote/service-package-question/service-package-radio/service-package-radio.spec.js @@ -18,21 +18,6 @@ describe("service-package-radio.vue", () => { expect(outputHtml).toEqual(expect.stringContaining(mockProps["buttonLabel"])); }); - it("Should include buttonLabelAuxillaryCopy in html", async () => { - // Arrange - let { wrapper } = setupMocks({ - mountOptionsMockData: { - propsData: mockProps, - }, - }); - - // Act - const outputHtml = wrapper.html(); - - // Assert - expect(outputHtml).toEqual(expect.stringContaining(mockProps["buttonLabelAuxillaryCopy"])); - }); - it("Should include buttonLabelSubCopy in html", async () => { // Arrange let { wrapper } = setupMocks({ @@ -123,7 +108,11 @@ const mockProps = { "
-
-
-
+
+
+
+ + + + * + +
+ +