From 4d9b5c92b8964e9485de3f8fae671cd889c566b9 Mon Sep 17 00:00:00 2001 From: CarlNation Date: Thu, 24 Oct 2024 08:34:29 -0400 Subject: [PATCH 1/8] CSR-2276 if request is from leadgen then use external threshold CSR-2276 if request is from leadgen then use external threshold --- .../capability-questions/capability-questions.vue | 2 +- src/layouts/part-questions/part-questions.vue | 2 +- src/layouts/quote/quote.vue | 14 +++++++++----- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/layouts/capability-questions/capability-questions.vue b/src/layouts/capability-questions/capability-questions.vue index 4679fcb19..4d637c978 100644 --- a/src/layouts/capability-questions/capability-questions.vue +++ b/src/layouts/capability-questions/capability-questions.vue @@ -66,7 +66,7 @@ export default { }, false ); - } + } baseMixin.methods.ResetExternalParamsAndHideModal(); } }); diff --git a/src/layouts/part-questions/part-questions.vue b/src/layouts/part-questions/part-questions.vue index ae1146aad..a6ca552bc 100644 --- a/src/layouts/part-questions/part-questions.vue +++ b/src/layouts/part-questions/part-questions.vue @@ -66,7 +66,7 @@ export default { }, false ); - } + } baseMixin.methods.ResetExternalParamsAndHideModal(); } }); diff --git a/src/layouts/quote/quote.vue b/src/layouts/quote/quote.vue index 823caf323..fc4aa402b 100644 --- a/src/layouts/quote/quote.vue +++ b/src/layouts/quote/quote.vue @@ -346,6 +346,9 @@ export default { let internalThreshold = experimentMixin.methods.getSettingValue( experimentSettings.INSURANCE_TAB_TO_DISPLAY_THRESHOLD_INTERNAL ); + let externalThreshold = experimentMixin.methods.getSettingValue( + experimentSettings.INSURANCE_TAB_TO_DISPLAY_THRESHOLD_EXTERNAL + ); const isExternalParameter = store.getters.externalParameterState?.isExternalParameter; if ( @@ -353,7 +356,11 @@ export default { isExternalParameter === externalParameterStatus.INACTIVE ) { // there are no active or inactive external parameters; use internal threshold - if (internalThreshold) thresholdToUse = internalThreshold; + if (isExternalParameter === externalParameterStatus.INACTIVE) { + if (internalThreshold) thresholdToUse = externalThreshold; + } else { + if (internalThreshold) thresholdToUse = internalThreshold; + } vm.isInsuranceSelected = getIsInsuranceSelectedValue( vm.availableLineItems, @@ -374,9 +381,6 @@ export default { baseMixin.methods.ResetExternalParamsAndHideModal(); } } else { - const externalThreshold = experimentMixin.methods.getSettingValue( - experimentSettings.INSURANCE_TAB_TO_DISPLAY_THRESHOLD_EXTERNAL - ); thresholdToUse = externalThreshold; vm.isInsuranceSelected = getIsInsuranceSelectedValue( @@ -437,7 +441,7 @@ export default { }, arePagePrerequisitesValid() { const payment = store.getters.order.payment; - + // prettier-ignore { const log = getQuerystringParameter(queryStrings.LOG); From 4ce93d06c18438e67c85b879e23bd4e892b61b0a Mon Sep 17 00:00:00 2001 From: CarlNation Date: Thu, 24 Oct 2024 14:07:18 -0400 Subject: [PATCH 2/8] make application name a parameter to serviceability endpoint make application name a parameter to serviceability endpoint --- src/store/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/store/index.js b/src/store/index.js index 14b9ff7f9..9071bcdfc 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -1656,7 +1656,7 @@ export const actions = { applicationConfig.CASH_PARENT_ACCOUNT_NUMBER; const referralSequenceNumber = context.getters.order.referralSequenceNumber; - var endPoint = `${endpoints.GetServiceabilityDetails.url}?zip=${serviceZipCode}&carId=${carId}&parentAccountNumber=${parentAccountNumber}&referralSequenceNumber=${referralSequenceNumber}`; + var endPoint = `${endpoints.GetServiceabilityDetails.url}?zip=${serviceZipCode}&carId=${carId}&parentAccountNumber=${parentAccountNumber}&referralSequenceNumber=${referralSequenceNumber}&applicationName=${applicationConfig.ANALYTICS_APPLICATION_NAME}`; if (lineItems) { endPoint += `&${lineItems}`; } From df99b06743af3cd60ab92b209bedef7c87a27c3c Mon Sep 17 00:00:00 2001 From: CarlNation Date: Fri, 25 Oct 2024 13:30:24 -0400 Subject: [PATCH 3/8] CSR-2276 restructure the external parm checking for isinsurance to properly check the experimet thresholds CSR-2276 restructure the external parm checking for isinsurance to properly check the experimet thresholds --- src/layouts/quote/quote.vue | 42 ++++++++++++++++++++++--------------- src/router/index.js | 6 ++++++ src/store/index.js | 1 - 3 files changed, 31 insertions(+), 18 deletions(-) diff --git a/src/layouts/quote/quote.vue b/src/layouts/quote/quote.vue index fc4aa402b..a54e7645e 100644 --- a/src/layouts/quote/quote.vue +++ b/src/layouts/quote/quote.vue @@ -351,16 +351,21 @@ export default { ); const isExternalParameter = store.getters.externalParameterState?.isExternalParameter; - if ( - isExternalParameter === externalParameterStatus.NOT_SET || - isExternalParameter === externalParameterStatus.INACTIVE - ) { - // there are no active or inactive external parameters; use internal threshold - if (isExternalParameter === externalParameterStatus.INACTIVE) { - if (internalThreshold) thresholdToUse = externalThreshold; - } else { - if (internalThreshold) thresholdToUse = internalThreshold; + // prettier-ignore + { + const log = getQuerystringParameter(queryStrings.LOG); + if (eval(log)) { + console.log("------------- quote.vue thresholds start -----------------"); + console.log(new Date() + " isExternalParameter: " + isExternalParameter); + console.log(new Date() + " internalThreshold: " + internalThreshold); + console.log(new Date() + " externalThreshold: " + externalThreshold); + console.log("------------- quote.vue thresholds end -----------------"); } + } + + if (isExternalParameter === externalParameterStatus.NOT_SET) { + // there are no active or inactive external parameters; use internal threshold + if (internalThreshold) thresholdToUse = internalThreshold; vm.isInsuranceSelected = getIsInsuranceSelectedValue( vm.availableLineItems, @@ -368,20 +373,23 @@ export default { ); baseMixin.methods.ResetExternalParamsAndHideModal(); } else { - // user came from an external source - if (store.getters.externalParameterQuote?.isInsurance == true) { + // user came from an external source, however, the externalParms may have been reset on service-zip, property-questions, etc... + if (eval(store.getters.externalParameterQuote?.isInsurance)) { // did user intentionally select insurance? vm.isInsuranceSelected = true; vm.servicePackage = store.getters.externalParameterQuote.servicePackage; await nextTick(); - const isValid = await baseMixin.methods.isFormValid(vm.$refs.theForm); - if (isValid) { - vm.forwardButtonAction(); - } else { - baseMixin.methods.ResetExternalParamsAndHideModal(); + + if (vm.servicePackage != null && isExternalParameter === externalParameterStatus.ACTIVE) { + const isValid = await baseMixin.methods.isFormValid(vm.$refs.theForm); + if (isValid) { + baseMixin.methods.ResetExternalParamsAndHideModal(); + vm.forwardButtonAction(); + } } + baseMixin.methods.ResetExternalParamsAndHideModal(); } else { - thresholdToUse = externalThreshold; + if (externalThreshold) thresholdToUse = externalThreshold; vm.isInsuranceSelected = getIsInsuranceSelectedValue( vm.availableLineItems, diff --git a/src/router/index.js b/src/router/index.js index 04eb1fe9e..73605c543 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -669,6 +669,12 @@ function updateExternalParameterState() { if (externalParameterZipCode) { store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_ZIP_CODE, externalParameterZipCode); } + if (externalParameterEmail) { + store.commit( + storeMutations.UPDATE_EXTERNAL_PARAMETER_EMAIL_ADDRESS, + externalParameterEmail + ); + } if (externalParameterIsInsurance?.toUpperCase() == "TRUE") { store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_IS_INSURANCE, true); store.commit( diff --git a/src/store/index.js b/src/store/index.js index 9071bcdfc..7fe13f59b 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -505,7 +505,6 @@ export const mutations = { saveExternalParameterState(externalParameterState); }, resetExternalParameterQuoteState(state) { - externalParameterState.quote.isInsurance = null; externalParameterState.quote.servicePackage = null; saveExternalParameterState(externalParameterState); }, From 2e7e5d4eaeecc25b826864dd76318223b586f576 Mon Sep 17 00:00:00 2001 From: CarlNation Date: Fri, 25 Oct 2024 13:50:05 -0400 Subject: [PATCH 4/8] prettier --- src/layouts/quote/quote.vue | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/layouts/quote/quote.vue b/src/layouts/quote/quote.vue index a54e7645e..3bd9e26eb 100644 --- a/src/layouts/quote/quote.vue +++ b/src/layouts/quote/quote.vue @@ -361,8 +361,8 @@ export default { console.log(new Date() + " externalThreshold: " + externalThreshold); console.log("------------- quote.vue thresholds end -----------------"); } - } - + } + if (isExternalParameter === externalParameterStatus.NOT_SET) { // there are no active or inactive external parameters; use internal threshold if (internalThreshold) thresholdToUse = internalThreshold; @@ -379,8 +379,11 @@ export default { vm.isInsuranceSelected = true; vm.servicePackage = store.getters.externalParameterQuote.servicePackage; await nextTick(); - - if (vm.servicePackage != null && isExternalParameter === externalParameterStatus.ACTIVE) { + + if ( + vm.servicePackage != null && + isExternalParameter === externalParameterStatus.ACTIVE + ) { const isValid = await baseMixin.methods.isFormValid(vm.$refs.theForm); if (isValid) { baseMixin.methods.ResetExternalParamsAndHideModal(); From 3ebbc47e9f169070e2b21831fade8a6265f83ce1 Mon Sep 17 00:00:00 2001 From: Sneha Date: Mon, 28 Oct 2024 17:12:59 +0530 Subject: [PATCH 5/8] CSR-2249 --- src/constants/experiments.js | 1 + .../service-package-question.spec.js | 26 ++++++ .../service-package-question.vue | 35 ++++++-- .../service-package-radio.vue | 84 +++++++++++-------- 4 files changed, 105 insertions(+), 41 deletions(-) diff --git a/src/constants/experiments.js b/src/constants/experiments.js index eeabeb7d6..83555fc04 100644 --- a/src/constants/experiments.js +++ b/src/constants/experiments.js @@ -12,6 +12,7 @@ const experimentSettings = { SUBMIT_ORDER_ENABLE_PIA: "SubmitOrder_Enable_PIA", IS_EMAIL_OPTIONAL: "isEmailOptional", SERVICE_PACKAGE_DISCOUNT: "OfferServicePackageDiscount", + PROMO_ON_PACKAGE: "Offer_Promo_On_Pkg", RECAL_PRICE_REMOVE: "RecalPriceRemove", INSURANCE_TAB_TO_DISPLAY_THRESHOLD_INTERNAL: "NextGen_InternalInsuranceTabDisplayThreshold", INSURANCE_TAB_TO_DISPLAY_THRESHOLD_EXTERNAL: "NextGen_ExternalInsuranceTabDisplayThreshold", 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 e24b77f6a..d8edb254c 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 @@ -10,6 +10,7 @@ import { containsLineItemWithPartType, findLineItemsWithPartType, } from "@/helpers/service-package-helper"; +import { experimentSettings } from "@/constants/experiments"; import baseMixin from "@/mixins/base-mixin.js"; import { partTypeStrings } from "@/constants/part-type-strings"; import { nextTick } from "vue"; @@ -19,6 +20,18 @@ jest.mock("@/store", () => ({ dispatch: jest.fn(), })); +const mockExperimentSettings = experimentSettings; + +jest.mock("@/mixins/experiment-mixin.js", () => ({ + methods: { + getSettingValue(settingName) { + if (settingName === mockExperimentSettings.PROMO_ON_PACKAGE) { + return true; + } + }, + }, +})); + describe("service-package-question.vue", () => { beforeEach(async () => { processedCmsContent = inputQuestionWidgetAnswers; @@ -162,6 +175,19 @@ describe("service-package-question.vue", () => { wrapper.vm.servicePackageAnswers[0].buttonAuxillaryCopy.includes("As little as") ).toBe(true); }); + it("should show service package discount when insurance is not selected", () => { + // Arrange + mockProps.isInsuranceSelected = false; + const wrapper = setupMocks({}); + // Act + + // Assert + expect( + wrapper.vm.servicePackageAnswers[0].additionalButtonData.Text.includes( + "Special: Save $" + ) + ).toBe(true); + }); it("should return [] from nullSafeAvailableLineItems and not error out if availableLineItems is null", () => { // Arrange mockProps.availableLineItems = null; 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 2a544e8ce..e475becd5 100644 --- a/src/layouts/quote/service-package-question/service-package-question.vue +++ b/src/layouts/quote/service-package-question/service-package-question.vue @@ -36,6 +36,8 @@ import { getLineItemsThatMatchPromos, } from "@/helpers/promotions-helper"; import { containsRecalParts, getItemsWithoutRecalParts } from "@/helpers/recal-helper"; +import experimentMixin from "@/mixins/experiment-mixin.js"; +import { experimentSettings } from "@/constants/experiments"; export default { name: "servicePackageQuestion", @@ -129,16 +131,22 @@ export default { buttonLabelSubCopy: this.getSubheaderTextFromCms(answer.SubWidgetName), buttonBodyCopy: this.getBodyTextFromCms(answer.SubWidgetName), //The package supports service-package-discount if it has the text value in CMS - buttonAuxillaryCopy: this.getDiscountedPackagePriceString( - answer.Name, - this.isServicePackageDiscountOnOrder && answer.Text != "" - ), + buttonAuxillaryCopy: this.isInsuranceSelected + ? this.getDiscountedPackagePriceString(answer.Name, false) + : this.getDiscountedPackagePriceString( + answer.Name, + this.isServicePackageDiscountOnOrder && + this.discountPackageNames == answer.Name + ), buttonFooterCopy: this.getFooterTextFromCms(answer.SubWidgetName), additionalButtonData: { strikeThroughPrice: this.getPackagePriceString(answer.Name), servicePackageDiscount: - this.isServicePackageDiscountOnOrder && answer.Text != "", - Text: answer.Text + this.getServicePackageDiscountPrice(), + this.isServicePackageDiscountOnOrder && + this.discountPackageNames == answer.Name, + Text: this.isInsuranceSelected + ? false + : "Special: Save $" + this.getServicePackageDiscountPrice(), }, })); return modifiedAnswers; @@ -149,6 +157,21 @@ export default { this.nullSafeAvailableLineItems ); }, + discountPackageNames() { + const discountServicePackage = experimentMixin.methods.getSettingValue( + experimentSettings.PROMO_ON_PACKAGE + ); + switch (discountServicePackage) { + case "ECON": + return packageNames.TIER_ONE; + case "STANDARD": + return packageNames.TIER_TWO; + case "PREMIUM": + return packageNames.TIER_THREE; + default: + return null; + } + }, frontWipersApplicableForTierTwo() { return shouldFrontWipersBeAvailable( this.glassToReplace, diff --git a/src/layouts/quote/service-package-question/service-package-radio/service-package-radio.vue b/src/layouts/quote/service-package-question/service-package-radio/service-package-radio.vue index 4a7fd38d4..a4bd1a6b4 100644 --- a/src/layouts/quote/service-package-question/service-package-radio/service-package-radio.vue +++ b/src/layouts/quote/service-package-question/service-package-radio/service-package-radio.vue @@ -1,15 +1,8 @@