From e6df30696b9ec9b43dca4fb838b07cc8d9f6d2ba Mon Sep 17 00:00:00 2001 From: Adam Caouette Date: Tue, 28 Jan 2025 09:59:00 -0500 Subject: [PATCH 1/6] CASH-48: front end work to call new log-part-questions endpoint --- src/constants/endpoints.js | 4 +++ src/constants/store-actions.js | 11 ++++--- src/layouts/confirmation/confirmation.vue | 37 +++++++++++++++++++++++ src/store/index.js | 34 +++++++++++++++++++++ 4 files changed, 82 insertions(+), 4 deletions(-) diff --git a/src/constants/endpoints.js b/src/constants/endpoints.js index c972d8118..43bf8c926 100644 --- a/src/constants/endpoints.js +++ b/src/constants/endpoints.js @@ -168,6 +168,10 @@ const endpoints = { url: "/analytics/api/v1/analytics/initialize", method: "POST", }, + LogPartQuestions: { + url: "/analytics/api/v1/analytics/log-part-questions", + method: "POST", + }, GetExperimentsByUser: { url: "/analytics/api/v1/analytics/get-experiments", method: "GET", diff --git a/src/constants/store-actions.js b/src/constants/store-actions.js index 45a18bace..aee8d705f 100644 --- a/src/constants/store-actions.js +++ b/src/constants/store-actions.js @@ -42,10 +42,6 @@ const storeActions = { VALIDATE_ZIP: "validateZip", PRICE_ORDER_ITEMS_AND_SAVE_SERVER_DATA: "priceOrderItemsAndSaveServerData", TAX_ORDER_ITEMS_AND_SAVE_SERVER_DATA: "taxOrderItemsAndSaveServerData", - LOG_EXPERIMENT_EXPOSURE: "logExperimentExposure", - LOG_PAGE_VIEW: "logPageView", - LOG_CUSTOM_EVENT: "logCustomEvent", - INITIALIZE_SESSION: "initializeSession", GET_EXPERIMENTS_BY_USER: "GetExperimentsByUser", RUN_EXPERIMENTS_FOR_TRIGGER: "runExperimentsForTrigger", CLEAR_VIN: "clearVin", @@ -57,6 +53,13 @@ const storeActions = { GET_BILL_TO_ACCOUNT_NUMBER: "getBillToAccountNumber", GET_RECAL_PARTS_AND_SAVE_TO_LINE_ITEMS: "getRecalPartsAndSaveToLineItems", + // Analytics + LOG_EXPERIMENT_EXPOSURE: "logExperimentExposure", + LOG_PAGE_VIEW: "logPageView", + LOG_CUSTOM_EVENT: "logCustomEvent", + INITIALIZE_SESSION: "initializeSession", + LOG_PART_QUESTIONS: "logPartQuestions", + // DEPENDENCY MUTATIONS RESET_VEHICLE_STATE_AND_DEPENDENCIES: "resetVehicleStateAndDependencies", RESET_DAMAGE_STATE_AND_DEPENDENCIES: "resetDamageAndDependencies", diff --git a/src/layouts/confirmation/confirmation.vue b/src/layouts/confirmation/confirmation.vue index 90886a9b7..26c0fd4a5 100644 --- a/src/layouts/confirmation/confirmation.vue +++ b/src/layouts/confirmation/confirmation.vue @@ -114,6 +114,43 @@ export default { async beforeRouteEnter(to, from, next) { const hasRecalPriceRemoveExperiment = await store.getters.shouldHideRecalibration; + // send part question data to SPS API for logging + const orderFromStore = await deepClone(store.getters.order); + const applicationUserFromStore = await deepClone(store.getters.applicationUser); + const ctu = orderFromStore.workOrderNumber?.split("-")[0]; + const partsOrQuestions = applicationUserFromStore.pageData["part-questions"].partsOrQuestions; + const onlyPartsWithQuestions = partsOrQuestions.filter((part) => { + return part.partQuestions?.length > 0; + }); + + onlyPartsWithQuestions.forEach(part => { + const payloadPartQuestions = []; + part.partQuestions.forEach(question => { + payloadPartQuestions.push({ + questionSeq: question.questionSequence, + questionText: question.questionText, + answerText: question.answerSelected.split("|")[3], + basePart: question.answerSelected.split("|")[2], + }); + }); + const payload = { + eon: orderFromStore.eon, + ctu: ctu, + workOrderId: orderFromStore.workOrderId, + workOrderNumber: orderFromStore.workOrderNumber, + carId: orderFromStore.vehicle.carId, + glassLocation: part.glassLocation, + partQuestions: payloadPartQuestions, + }; + + baseMixin.methods.dispatchStoreAction( + storeActions.LOG_PART_QUESTIONS, + payload, + false + ); + }); + + // Create order await baseMixin.methods.dispatchStoreAction(storeActions.CREATE_SUBMITTED_ORDER); // This nulls the Store order // Call APIs diff --git a/src/store/index.js b/src/store/index.js index f423fb58d..ede3955cc 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -1437,6 +1437,40 @@ export const actions = { }); }, + logPartQuestions( + context, + { + eon, + ctu, + workOrderId, + workOrderNumber, + carId, + glassLocation, + partQuestions, + userAgent, + } + ) { + + var payload = { + applicationName: applicationConfig.ANALYTICS_APPLICATION_NAME, + eon: eon, + ctu: ctu, + workOrderId: workOrderId, + workOrderNumber: workOrderNumber, + carId: carId, + glassLocation: glassLocation, + partQuestions: partQuestions, + userAgent: navigator.userAgent + }; + + return globalMethods + .callHttpClient({ + method: endpoints.LogPartQuestions.method, + endpoint: endpoints.LogPartQuestions.url, + payload: payload, + }); + }, + // Misc Actions setReferralInformation(context, { referralNumber, referralDate, referralCorrelationId, eon }) { context.commit(storeMutations.UPDATE_REFERRAL_NUMBER, referralNumber); From e6df11f3f6472edd7761103b2440dfb55dd29a08 Mon Sep 17 00:00:00 2001 From: Johnny shultz Date: Tue, 28 Jan 2025 14:31:24 -0500 Subject: [PATCH 2/6] Cash-93 CASH-93 added log-enabled header --- src/constants/header-keys.js | 1 + src/global-methods.js | 1 + 2 files changed, 2 insertions(+) diff --git a/src/constants/header-keys.js b/src/constants/header-keys.js index 2f7598244..d9b3578c4 100644 --- a/src/constants/header-keys.js +++ b/src/constants/header-keys.js @@ -5,4 +5,5 @@ export const headerKeys = { SESSION_SEQUENCE_NUMBER: "X-Session-Sequence-Number", TRANSACTION_ID: "X-Transaction-Id", EON: "X-Enterprise-Order-Number", + LOG_ENABLED: "log-enabled" }; diff --git a/src/global-methods.js b/src/global-methods.js index 77255e99d..ce82a4c3f 100644 --- a/src/global-methods.js +++ b/src/global-methods.js @@ -70,6 +70,7 @@ export default { [headerKeys.REFERRAL_SEQUENCE_NUMBER]: order?.referralSequenceNumber, [headerKeys.TRANSACTION_ID]: crypto.randomUUID(), [headerKeys.EON]: order?.eon, + [headerKeys.LOG_ENABLED]: store.getters.applicationUser.loggingOption, }; axios({ From 134c78204c26fe96d5b1010e56ebff67539df412 Mon Sep 17 00:00:00 2001 From: Johnny shultz Date: Tue, 28 Jan 2025 14:44:36 -0500 Subject: [PATCH 3/6] CASH-93 CASH-93 added null check to header --- src/global-methods.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/global-methods.js b/src/global-methods.js index ce82a4c3f..164900c33 100644 --- a/src/global-methods.js +++ b/src/global-methods.js @@ -70,7 +70,7 @@ export default { [headerKeys.REFERRAL_SEQUENCE_NUMBER]: order?.referralSequenceNumber, [headerKeys.TRANSACTION_ID]: crypto.randomUUID(), [headerKeys.EON]: order?.eon, - [headerKeys.LOG_ENABLED]: store.getters.applicationUser.loggingOption, + [headerKeys.LOG_ENABLED]: store.getters.applicationUser.loggingOption ?? false, }; axios({ From c9b9476976cf691265a4d075706672f38eb85a52 Mon Sep 17 00:00:00 2001 From: Johnny shultz Date: Tue, 28 Jan 2025 15:04:12 -0500 Subject: [PATCH 4/6] Cash-93 CASH- 93 include undefined in check --- src/global-methods.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/global-methods.js b/src/global-methods.js index 164900c33..ba6cec1ec 100644 --- a/src/global-methods.js +++ b/src/global-methods.js @@ -70,7 +70,7 @@ export default { [headerKeys.REFERRAL_SEQUENCE_NUMBER]: order?.referralSequenceNumber, [headerKeys.TRANSACTION_ID]: crypto.randomUUID(), [headerKeys.EON]: order?.eon, - [headerKeys.LOG_ENABLED]: store.getters.applicationUser.loggingOption ?? false, + [headerKeys.LOG_ENABLED]: store.getters.applicationUser?.loggingOption ?? false, }; axios({ From 833d6f248a483a88a4113449a390ce5289a4197c Mon Sep 17 00:00:00 2001 From: Adam Caouette Date: Tue, 28 Jan 2025 19:14:43 -0500 Subject: [PATCH 5/6] CASH-48: update application name value --- src/store/index.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/store/index.js b/src/store/index.js index c45fe7eee..fa83032d5 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -1458,9 +1458,8 @@ export const actions = { userAgent, } ) { - var payload = { - applicationName: applicationConfig.ANALYTICS_APPLICATION_NAME, + applicationName: applicationConfig.APPLICATION_NAME, eon: eon, ctu: ctu, workOrderId: workOrderId, From 042e8962352a96f3623a831b55caf34b7d645c48 Mon Sep 17 00:00:00 2001 From: Chris Redelinghuys Date: Wed, 29 Jan 2025 11:14:31 -0500 Subject: [PATCH 6/6] CASH-69: Add MSR experiment. Filter recal part by partType instead of part number --- src/constants/experiments.js | 2 ++ src/constants/part-number-strings.js | 7 +++++++ .../service-location/service-location.spec.js | 4 ++++ src/layouts/service-location/service-location.vue | 14 ++++++++++++-- src/store/index.js | 14 ++++++++------ 5 files changed, 33 insertions(+), 8 deletions(-) create mode 100644 src/constants/part-number-strings.js diff --git a/src/constants/experiments.js b/src/constants/experiments.js index 83555fc04..92d27a4a1 100644 --- a/src/constants/experiments.js +++ b/src/constants/experiments.js @@ -1,6 +1,7 @@ const experimentUniverses = { CONCEPT_FUNNEL: "ConceptFunnel", RECAL_PRICE_REMOVAL: "NextGen_RecalPriceRemoval", + MSR: "MSR", }; const experimentSettings = { @@ -16,6 +17,7 @@ const experimentSettings = { RECAL_PRICE_REMOVE: "RecalPriceRemove", INSURANCE_TAB_TO_DISPLAY_THRESHOLD_INTERNAL: "NextGen_InternalInsuranceTabDisplayThreshold", INSURANCE_TAB_TO_DISPLAY_THRESHOLD_EXTERNAL: "NextGen_ExternalInsuranceTabDisplayThreshold", + DISPLAY_MSR: "DisplayMSR", }; const experimentTriggers = { diff --git a/src/constants/part-number-strings.js b/src/constants/part-number-strings.js new file mode 100644 index 000000000..c32864a87 --- /dev/null +++ b/src/constants/part-number-strings.js @@ -0,0 +1,7 @@ +const partNumberStrings = { + // Recalibration + MOBILE_STATIC_RECAL_FEE: "RECAL MOBILE", + MOBILE_DUAL_RECAL_FEE: "RECAL MOBILEDUAL", +}; + +export { partNumberStrings }; diff --git a/src/layouts/service-location/service-location.spec.js b/src/layouts/service-location/service-location.spec.js index 6333082ec..54f28a89c 100644 --- a/src/layouts/service-location/service-location.spec.js +++ b/src/layouts/service-location/service-location.spec.js @@ -7,6 +7,7 @@ import { getMountOptions } from "@/helpers/unit-test-helper"; import store from "@/store"; import baseMixin from "@/mixins/base-mixin"; +import { experimentSettings } from "@/constants/experiments"; // Define Mocks jest.mock("@/helpers/cms-content-helper", () => ({ @@ -199,6 +200,9 @@ beforeEach(() => { zipCode: "43054", }, }, + experimentSettings: { + settingName: experimentSettings.DISPLAY_MSR, + }, }; }); diff --git a/src/layouts/service-location/service-location.vue b/src/layouts/service-location/service-location.vue index 71bfa4b01..9addea705 100644 --- a/src/layouts/service-location/service-location.vue +++ b/src/layouts/service-location/service-location.vue @@ -139,6 +139,8 @@ import contentGroupModal from "@/fmg-components/content-group-modal/content-grou // Supporting files import baseMixin from "@/mixins/base-mixin.js"; +import experimentMixin from "@/mixins/experiment-mixin.js"; +import { experimentSettings } from "@/constants/experiments"; import { AppointmentTypeStrings } from "@/constants/schedule-constants"; import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; @@ -151,6 +153,7 @@ import { import { navigateToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper"; import { applicationConfig } from "@/constants/application-config"; import { Provider } from "@/layouts/service-location/classes/provider"; +import { partNumberStrings } from "@/constants/part-number-strings"; import store from "@/store"; @@ -159,7 +162,6 @@ import { defineRule } from "vee-validate"; import { errorMessages } from "@/constants/error-messages"; const MOBILE_FEE_PART_TYPE = "MOBILE FEE"; -const MOBILE_STATIC_RECAL_FEE_PART_NUMBER = "RECAL MOBILE"; // DEFINE VALIDATION RULES defineRule("mobile-location-required", (value) => { @@ -319,11 +321,19 @@ export default { }, isMobileStaticRecalibrationApplicable() { return ( + this.displayMSR && this.isVehicleMobileStaticRecalibrationApplicable && - this.mobileFeePart?.partNumber == MOBILE_STATIC_RECAL_FEE_PART_NUMBER && + this.mobileFeePart?.partNumber == partNumberStrings.MOBILE_STATIC_RECAL_FEE && (this.isInsurance ? this.mobileFeePart?.isInsurable : true) ); }, + displayMSR() { + return ( + experimentMixin.methods + .getSettingValue(experimentSettings.DISPLAY_MSR) + ?.toLowerCase() === "true" + ); + }, mobileFeeApplies() { if ( this.mobileFeePart?.laborAmount > 0 || diff --git a/src/store/index.js b/src/store/index.js index fa83032d5..48c6078c7 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -1671,10 +1671,10 @@ export const actions = { var endPoint = `${endpoints.GetMobileFeePart.url}/?serviceType=${serviceType}&facilityType=${facilityType}&parentAccountNumber=${parentAccountNumber}&billToAccountNumber=${billToAccountNumber}&providerNumber=${providerNumber}&isItacOptimized=${isItacOptimized}&zipCode=${zipCode}`; if (isMobileStaticRecalibrationApplicable) { - const staticRecalPartNumber = getStaticRecalPartNumber(order.lineItems?.glassParts[0]); + const recalPartNumber = getRecalPartNumber(order.lineItems?.glassParts[0]); const carId = order.vehicle?.carId; - if (staticRecalPartNumber && carId) { - endPoint = `${endPoint}&partNumbers=${staticRecalPartNumber}&carId=${carId}`; + if (recalPartNumber && carId) { + endPoint = `${endPoint}&partNumbers=${recalPartNumber}&carId=${carId}`; } } @@ -3718,9 +3718,11 @@ function saveExternalParameterState(externalParameterState) { window.sessionStorage.setItem("externalParameterState", JSON.stringify(externalParameterState)); } -//This function checks if static recalibration is available for the vehicle and returns the part number for it. -function getStaticRecalPartNumber(glassPartsArray) { - const recalPart = glassPartsArray.childParts.find((item) => item.partNumber === "RECAL STATIC"); +//This function finds the recalibration part and returns the part number for it. +function getRecalPartNumber(glassPartsArray) { + const recalPart = glassPartsArray.childParts.find( + (item) => item.partType === partTypeStrings.ADAS_RECALIBRATION + ); if (recalPart) { return recalPart.partNumber; } else {