Merge remote-tracking branch 'origin/develop' into feature/CSR-2150
This commit is contained in:
commit
81b846d044
29 changed files with 594 additions and 153 deletions
|
|
@ -12,6 +12,8 @@ const GaEvents = {
|
||||||
const GaCategories = {
|
const GaCategories = {
|
||||||
API_RESPONSE: "Api_Response",
|
API_RESPONSE: "Api_Response",
|
||||||
EVOX: "Evox",
|
EVOX: "Evox",
|
||||||
|
APPOINTMENT: "Appointment",
|
||||||
|
SERVICE_LOCATION: "service-location",
|
||||||
};
|
};
|
||||||
|
|
||||||
const GaActions = {
|
const GaActions = {
|
||||||
|
|
@ -21,6 +23,10 @@ const GaActions = {
|
||||||
SUBMITTED: "Submitted",
|
SUBMITTED: "Submitted",
|
||||||
DISPLAYED: "Displayed",
|
DISPLAYED: "Displayed",
|
||||||
CASH_QUOTE_DISPLAYED: "Cash quote displayed",
|
CASH_QUOTE_DISPLAYED: "Cash quote displayed",
|
||||||
|
SERVICE_PACKAGE_PRICE: "Service package price",
|
||||||
|
MOBILE_AVAILABLE: "mobile_available",
|
||||||
|
SHOPS_FIRST_DISPLAYED: "shops_first_displayed",
|
||||||
|
MORE_LOCATIONS_CLICKED: "more_locations_clicked",
|
||||||
};
|
};
|
||||||
|
|
||||||
const GaLabels = {
|
const GaLabels = {
|
||||||
|
|
@ -29,6 +35,8 @@ const GaLabels = {
|
||||||
LICENSE_PLATE_LOOKUP: "License_Plate_Look_Up",
|
LICENSE_PLATE_LOOKUP: "License_Plate_Look_Up",
|
||||||
VIN_LOOKUP: "Vin_Look_Up",
|
VIN_LOOKUP: "Vin_Look_Up",
|
||||||
ADDRESS_LOOKUP: "Address_Look_up",
|
ADDRESS_LOOKUP: "Address_Look_up",
|
||||||
|
YES: "yes",
|
||||||
|
NO: "no",
|
||||||
};
|
};
|
||||||
|
|
||||||
const ValueToLogTypes = {
|
const ValueToLogTypes = {
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,10 @@ const endpoints = {
|
||||||
url: "/parts/api/v1/parts/supporting-items",
|
url: "/parts/api/v1/parts/supporting-items",
|
||||||
method: "POST",
|
method: "POST",
|
||||||
},
|
},
|
||||||
|
GetRecalPart: {
|
||||||
|
url: "/parts/api/v1/parts/recal-parts",
|
||||||
|
method: "GET",
|
||||||
|
},
|
||||||
GetAlertReasons: {
|
GetAlertReasons: {
|
||||||
url: "/location/api/v1/location/alert-reasons",
|
url: "/location/api/v1/location/alert-reasons",
|
||||||
method: "GET",
|
method: "GET",
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,8 @@ const experimentSettings = {
|
||||||
IS_EMAIL_OPTIONAL: "isEmailOptional",
|
IS_EMAIL_OPTIONAL: "isEmailOptional",
|
||||||
SERVICE_PACKAGE_DISCOUNT: "OfferServicePackageDiscount",
|
SERVICE_PACKAGE_DISCOUNT: "OfferServicePackageDiscount",
|
||||||
RECAL_PRICE_REMOVE: "RecalPriceRemove",
|
RECAL_PRICE_REMOVE: "RecalPriceRemove",
|
||||||
|
INSURANCE_TAB_TO_DISPLAY_THRESHOLD_INTERNAL: "NextGen_InternalInsuranceTabDisplayThreshold",
|
||||||
|
INSURANCE_TAB_TO_DISPLAY_THRESHOLD_EXTERNAL: "NextGen_ExternalInsuranceTabDisplayThreshold",
|
||||||
};
|
};
|
||||||
|
|
||||||
const experimentTriggers = {
|
const experimentTriggers = {
|
||||||
|
|
|
||||||
|
|
@ -4,5 +4,5 @@ export const headerKeys = {
|
||||||
REFERRAL_SEQUENCE_NUMBER: "X-Referral-Sequence-Number",
|
REFERRAL_SEQUENCE_NUMBER: "X-Referral-Sequence-Number",
|
||||||
SESSION_SEQUENCE_NUMBER: "X-Session-Sequence-Number",
|
SESSION_SEQUENCE_NUMBER: "X-Session-Sequence-Number",
|
||||||
TRANSACTION_ID: "X-Transaction-Id",
|
TRANSACTION_ID: "X-Transaction-Id",
|
||||||
EON: "X-EON",
|
EON: "X-Enterprise-Order-Number",
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,19 @@ export function coverageStatusValue(intCoverageStatus) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function coverageStatusEnum(strCoverageStatus) {
|
||||||
|
switch (strCoverageStatus) {
|
||||||
|
case coverageStatus.PENDING:
|
||||||
|
return 0;
|
||||||
|
case coverageStatus.NOCOMP:
|
||||||
|
return 1;
|
||||||
|
case coverageStatus.VERIFIED:
|
||||||
|
return 2;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const coverageType = {
|
export const coverageType = {
|
||||||
NONE: "None",
|
NONE: "None",
|
||||||
DEDUCTIBLE: "Deductible",
|
DEDUCTIBLE: "Deductible",
|
||||||
|
|
@ -50,3 +63,18 @@ export function coverageTypeValue(intCoverageType) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function coverageTypeEnum(strCoverageType) {
|
||||||
|
switch (strCoverageType) {
|
||||||
|
case coverageType.NONE:
|
||||||
|
return 0;
|
||||||
|
case coverageType.DEDUCTIBLE:
|
||||||
|
return 1;
|
||||||
|
case coverageType.ITAC:
|
||||||
|
return 2;
|
||||||
|
case coverageType.NOCOMP:
|
||||||
|
return 3;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ const partTypeStrings = {
|
||||||
FRONT_WIPER: "FRONT WIPER",
|
FRONT_WIPER: "FRONT WIPER",
|
||||||
REAR_WIPER: "REAR WIPER",
|
REAR_WIPER: "REAR WIPER",
|
||||||
RAIN_DEFENSE: "RAIN DEFENSE",
|
RAIN_DEFENSE: "RAIN DEFENSE",
|
||||||
|
ADAS_RECALIBRATION: "ADAS RECALIBRATION",
|
||||||
RECALIBRATION: "RECALIBRATION",
|
RECALIBRATION: "RECALIBRATION",
|
||||||
REPLACE_FEE: "REPLACE FEE",
|
REPLACE_FEE: "REPLACE FEE",
|
||||||
RECYCLE_FEE: "RECYCLE FEE",
|
RECYCLE_FEE: "RECYCLE FEE",
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,7 @@ const storeActions = {
|
||||||
REVALIDATE_ORDER_PROMOS_AND_SAVE_SERVER_DATA: "revalidateOrderPromosAndSaveServerData",
|
REVALIDATE_ORDER_PROMOS_AND_SAVE_SERVER_DATA: "revalidateOrderPromosAndSaveServerData",
|
||||||
GET_INSURANCE_COMPANY_LIST: "getInsuranceCompanyList",
|
GET_INSURANCE_COMPANY_LIST: "getInsuranceCompanyList",
|
||||||
GET_BILL_TO_ACCOUNT_NUMBER: "getBillToAccountNumber",
|
GET_BILL_TO_ACCOUNT_NUMBER: "getBillToAccountNumber",
|
||||||
|
GET_RECAL_PARTS_AND_SAVE_TO_LINE_ITEMS: "getRecalPartsAndSaveToLineItems",
|
||||||
|
|
||||||
// DEPENDENCY MUTATIONS
|
// DEPENDENCY MUTATIONS
|
||||||
RESET_DAMAGE_STATE_AND_DEPENDENCIES: "resetDamageAndDependencies",
|
RESET_DAMAGE_STATE_AND_DEPENDENCIES: "resetDamageAndDependencies",
|
||||||
|
|
|
||||||
|
|
@ -305,8 +305,8 @@ export default {
|
||||||
if (!this.lineItems || this.lineItems.length < 1) return;
|
if (!this.lineItems || this.lineItems.length < 1) return;
|
||||||
|
|
||||||
const lineItemsCopy = deepClone(this.lineItems);
|
const lineItemsCopy = deepClone(this.lineItems);
|
||||||
lineItemsCopy.supportingItems = lineItemsCopy.supportingItems
|
lineItemsCopy.glassParts = lineItemsCopy.glassParts
|
||||||
? baseMixin.methods.filterOutRecalibration(lineItemsCopy?.supportingItems)
|
? baseMixin.methods.filterOutRecalibration(lineItemsCopy?.glassParts)
|
||||||
: [];
|
: [];
|
||||||
return lineItemsCopy;
|
return lineItemsCopy;
|
||||||
},
|
},
|
||||||
|
|
@ -1007,6 +1007,11 @@ export default {
|
||||||
},
|
},
|
||||||
salesTax() {
|
salesTax() {
|
||||||
if (!this.lineItems || this.lineItems.length < 1) return;
|
if (!this.lineItems || this.lineItems.length < 1) return;
|
||||||
|
|
||||||
|
if (this.isInsurance && !this.showCoverageAsVerified) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return this.isInsurance || !this.shouldHideRecalibration
|
return this.isInsurance || !this.shouldHideRecalibration
|
||||||
? baseMixin.methods.getSalesTax(this.lineItems) // calculate with recal (if on order)
|
? baseMixin.methods.getSalesTax(this.lineItems) // calculate with recal (if on order)
|
||||||
: baseMixin.methods.getSalesTax(this.lineItemsWithoutRecal); // calculated without recal
|
: baseMixin.methods.getSalesTax(this.lineItemsWithoutRecal); // calculated without recal
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ export default {
|
||||||
return this.leftAlignHeader ? "justify-content-start" : "justify-content-center";
|
return this.leftAlignHeader ? "justify-content-start" : "justify-content-center";
|
||||||
},
|
},
|
||||||
subText() {
|
subText() {
|
||||||
return this.getCmsContent(this.cmsWidgetName, "HeaderSubText");
|
return this.getCmsContent(this.cmsWidgetName, "SubheaderText");
|
||||||
},
|
},
|
||||||
backButtonAccessibleText() {
|
backButtonAccessibleText() {
|
||||||
return this.getCmsContent(this.cmsWidgetName, "BackButtonAccessibleText");
|
return this.getCmsContent(this.cmsWidgetName, "BackButtonAccessibleText");
|
||||||
|
|
|
||||||
|
|
@ -109,8 +109,10 @@ export async function getImplicitNavigation(toRoute) {
|
||||||
export async function navigateToHeritageFunnel({ shouldSaveSession, pageNameToLog }) {
|
export async function navigateToHeritageFunnel({ shouldSaveSession, pageNameToLog }) {
|
||||||
const log = getQuerystringParameter(queryStrings.LOG);
|
const log = getQuerystringParameter(queryStrings.LOG);
|
||||||
if (eval(log)) {
|
if (eval(log)) {
|
||||||
|
console.log("------------- Navigate to heritage start -----------------");
|
||||||
console.log(new Date() + " applicationConfig: " + JSON.stringify(applicationConfig));
|
console.log(new Date() + " applicationConfig: " + JSON.stringify(applicationConfig));
|
||||||
console.log(new Date() + " navigateToHeritageFunnel: " + applicationConfig.HERITAGE_FUNNEL);
|
console.log(new Date() + " navigateToHeritageFunnel: " + applicationConfig.HERITAGE_FUNNEL);
|
||||||
|
console.log("------------- Navigate to heritage end -----------------");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the order (or save existing order) when navigating to Heritage Funnel.
|
// Create the order (or save existing order) when navigating to Heritage Funnel.
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ export async function saveSession({
|
||||||
pageNameToLog,
|
pageNameToLog,
|
||||||
shouldAwaitSaveSessionQueue = false,
|
shouldAwaitSaveSessionQueue = false,
|
||||||
submitAfterSave = false,
|
submitAfterSave = false,
|
||||||
createDeleteStatusWorkOrderForPia = false,
|
createUnscheduledStatusWorkOrderForPIA = false,
|
||||||
}) {
|
}) {
|
||||||
var saveSessionPromise;
|
var saveSessionPromise;
|
||||||
if (store.getters.applicationUser.saveSessionPromise) {
|
if (store.getters.applicationUser.saveSessionPromise) {
|
||||||
|
|
@ -67,7 +67,7 @@ export async function saveSession({
|
||||||
return saveSessionHelper(
|
return saveSessionHelper(
|
||||||
pageNameToLog,
|
pageNameToLog,
|
||||||
submitAfterSave,
|
submitAfterSave,
|
||||||
createDeleteStatusWorkOrderForPia
|
createUnscheduledStatusWorkOrderForPIA
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -75,7 +75,7 @@ export async function saveSession({
|
||||||
saveSessionPromise = saveSessionHelper(
|
saveSessionPromise = saveSessionHelper(
|
||||||
pageNameToLog,
|
pageNameToLog,
|
||||||
submitAfterSave,
|
submitAfterSave,
|
||||||
createDeleteStatusWorkOrderForPia
|
createUnscheduledStatusWorkOrderForPIA
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
store.commit(storeMutations.UPDATE_SAVE_SESSION_PROMISE, saveSessionPromise);
|
store.commit(storeMutations.UPDATE_SAVE_SESSION_PROMISE, saveSessionPromise);
|
||||||
|
|
@ -88,13 +88,13 @@ export async function saveSession({
|
||||||
export async function submitWorkOrder({
|
export async function submitWorkOrder({
|
||||||
pageNameToLog,
|
pageNameToLog,
|
||||||
submitAfterSave = false,
|
submitAfterSave = false,
|
||||||
createDeleteStatusWorkOrderForPia = false,
|
createUnscheduledStatusWorkOrderForPIA = false,
|
||||||
}) {
|
}) {
|
||||||
await saveSession({
|
await saveSession({
|
||||||
pageNameToLog: pageNameToLog,
|
pageNameToLog: pageNameToLog,
|
||||||
shouldAwaitSaveSessionQueue: true,
|
shouldAwaitSaveSessionQueue: true,
|
||||||
submitAfterSave: submitAfterSave,
|
submitAfterSave: submitAfterSave,
|
||||||
createDeleteStatusWorkOrderForPia: createDeleteStatusWorkOrderForPia,
|
createUnscheduledStatusWorkOrderForPIA: createUnscheduledStatusWorkOrderForPIA,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -139,13 +139,13 @@ async function loadSession(
|
||||||
async function saveSessionHelper(
|
async function saveSessionHelper(
|
||||||
pageNameToLog,
|
pageNameToLog,
|
||||||
submitAfterSave = false,
|
submitAfterSave = false,
|
||||||
createDeleteStatusWorkOrderForPia = false
|
createUnscheduledStatusWorkOrderForPIA = false
|
||||||
) {
|
) {
|
||||||
const savedSessionInfo = await baseMixin.methods.dispatchStoreActionWithLogging(
|
const savedSessionInfo = await baseMixin.methods.dispatchStoreActionWithLogging(
|
||||||
storeActions.SAVE_SESSION,
|
storeActions.SAVE_SESSION,
|
||||||
{
|
{
|
||||||
submitAfterSave: submitAfterSave,
|
submitAfterSave: submitAfterSave,
|
||||||
createDeleteStatusWorkOrderForPia: createDeleteStatusWorkOrderForPia,
|
createUnscheduledStatusWorkOrderForPIA: createUnscheduledStatusWorkOrderForPIA,
|
||||||
},
|
},
|
||||||
pageNameToLog
|
pageNameToLog
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -179,7 +179,7 @@ describe("saveSession", () => {
|
||||||
// Assert
|
// Assert
|
||||||
expect(mocks.baseMixin.methods.dispatchStoreActionWithLogging).toHaveBeenCalledWith(
|
expect(mocks.baseMixin.methods.dispatchStoreActionWithLogging).toHaveBeenCalledWith(
|
||||||
storeActions.SAVE_SESSION,
|
storeActions.SAVE_SESSION,
|
||||||
{ createDeleteStatusWorkOrderForPia: false, submitAfterSave: false },
|
{ createUnscheduledStatusWorkOrderForPIA: false, submitAfterSave: false },
|
||||||
"test"
|
"test"
|
||||||
);
|
);
|
||||||
expect(mocks.baseMixin.methods.dispatchStoreAction).toHaveBeenCalledWith(
|
expect(mocks.baseMixin.methods.dispatchStoreAction).toHaveBeenCalledWith(
|
||||||
|
|
@ -287,7 +287,7 @@ describe("submitWorkOrder", () => {
|
||||||
// Assert
|
// Assert
|
||||||
expect(mocks.baseMixin.methods.dispatchStoreActionWithLogging).toHaveBeenCalledWith(
|
expect(mocks.baseMixin.methods.dispatchStoreActionWithLogging).toHaveBeenCalledWith(
|
||||||
storeActions.SAVE_SESSION,
|
storeActions.SAVE_SESSION,
|
||||||
{ createDeleteStatusWorkOrderForPia: false, submitAfterSave: true },
|
{ createUnscheduledStatusWorkOrderForPIA: false, submitAfterSave: true },
|
||||||
"test"
|
"test"
|
||||||
);
|
);
|
||||||
expect(mocks.baseMixin.methods.dispatchStoreAction).toHaveBeenCalledWith(
|
expect(mocks.baseMixin.methods.dispatchStoreAction).toHaveBeenCalledWith(
|
||||||
|
|
|
||||||
52
src/helpers/recal-helper.js
Normal file
52
src/helpers/recal-helper.js
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
import { deepClone } from "@/helpers/object-helper";
|
||||||
|
import { partTypeStrings } from "@/constants/part-type-strings";
|
||||||
|
|
||||||
|
const recalPartTypes = [partTypeStrings.RECALIBRATION, partTypeStrings.ADAS_RECALIBRATION];
|
||||||
|
|
||||||
|
export function isRecalPartOrHasChildRecalPart(lineItem) {
|
||||||
|
if (lineItem.childParts && lineItem.childParts.length > 0) {
|
||||||
|
return isRecalPart(lineItem) || containsRecalParts(lineItem.childParts);
|
||||||
|
} else {
|
||||||
|
return isRecalPart(lineItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isRecalPart(lineItem) {
|
||||||
|
return recalPartTypes.some((type) => lineItem.partType === type);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function containsRecalParts(lineItems) {
|
||||||
|
if (!lineItems) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(lineItems)) {
|
||||||
|
return lineItems.some((li) => isRecalPartOrHasChildRecalPart(li));
|
||||||
|
} else {
|
||||||
|
// complex object form -- flatten and re-call.
|
||||||
|
const flattened = [
|
||||||
|
...(lineItems.glassParts ?? []),
|
||||||
|
...(lineItems.supportingItems ?? []),
|
||||||
|
...(lineItems.vaps ?? []),
|
||||||
|
...(lineItems.promos ?? []),
|
||||||
|
];
|
||||||
|
|
||||||
|
return flattened.some((li) => isRecalPartOrHasChildRecalPart(li));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getItemsWithoutRecalParts(lineItems) {
|
||||||
|
const copy = deepClone(lineItems);
|
||||||
|
|
||||||
|
const firstLevelFiltered = copy.filter((li) => !isRecalPart(li));
|
||||||
|
|
||||||
|
const childrenFiltered = firstLevelFiltered.map((li) => {
|
||||||
|
if (li.childParts && li.childParts.length > 0) {
|
||||||
|
li.childParts = getItemsWithoutRecalParts(li.childParts);
|
||||||
|
}
|
||||||
|
|
||||||
|
return li;
|
||||||
|
});
|
||||||
|
|
||||||
|
return childrenFiltered;
|
||||||
|
}
|
||||||
|
|
@ -60,6 +60,7 @@
|
||||||
v-model="lineItems"
|
v-model="lineItems"
|
||||||
:showAsPaid="isPia"
|
:showAsPaid="isPia"
|
||||||
servicePackageOptionsCmsName="ServicePackageTitle"
|
servicePackageOptionsCmsName="ServicePackageTitle"
|
||||||
|
:isInsurance="isInsurance"
|
||||||
:insuranceDeductible="currentDeductible"
|
:insuranceDeductible="currentDeductible"
|
||||||
:insuranceCompanyName="insuranceCompanyName"
|
:insuranceCompanyName="insuranceCompanyName"
|
||||||
:showInsuranceCoverageAs="showInsuranceCoverageAs"
|
:showInsuranceCoverageAs="showInsuranceCoverageAs"
|
||||||
|
|
@ -93,7 +94,6 @@ import textBlock from "@/digital-components/text-block/text-block";
|
||||||
|
|
||||||
//Supporting files
|
//Supporting files
|
||||||
import baseMixin from "@/mixins/base-mixin.js";
|
import baseMixin from "@/mixins/base-mixin.js";
|
||||||
import analyticsMixin from "@/mixins/analytics-mixin";
|
|
||||||
import store from "@/store";
|
import store from "@/store";
|
||||||
import { storeActions } from "@/constants/store-actions";
|
import { storeActions } from "@/constants/store-actions";
|
||||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||||
|
|
@ -107,7 +107,9 @@ import { get12HourTimeFormat, get12HourTimeMobileFormat } from "@/helpers/date-h
|
||||||
import { coverageStatus } from "@/constants/insurance";
|
import { coverageStatus } from "@/constants/insurance";
|
||||||
import { getDisplayTextForDurationLength } from "@/helpers/duration-length-helper";
|
import { getDisplayTextForDurationLength } from "@/helpers/duration-length-helper";
|
||||||
import { experimentSettings } from "@/constants/experiments";
|
import { experimentSettings } from "@/constants/experiments";
|
||||||
import experimentMixin from "@/mixins/experiment-mixin.js";
|
import { partTypeStrings } from "@/constants/part-type-strings";
|
||||||
|
import { containsLineItemWithPartType } from "@/helpers/service-package-helper";
|
||||||
|
import { containsRecalParts } from "@/helpers/recal-helper.js";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "confirmation",
|
name: "confirmation",
|
||||||
|
|
@ -169,8 +171,14 @@ export default {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
isRecalibrationOnOrder() {
|
||||||
|
return containsRecalParts(this?.lineItems);
|
||||||
|
},
|
||||||
shouldHideRecalibration() {
|
shouldHideRecalibration() {
|
||||||
return this.getSettingValue(experimentSettings.RECAL_PRICE_REMOVE);
|
return (
|
||||||
|
this.getSettingValue(experimentSettings.RECAL_PRICE_REMOVE)?.toLowerCase() ===
|
||||||
|
"true" && this.isRecalibrationOnOrder
|
||||||
|
);
|
||||||
},
|
},
|
||||||
ShowCart() {
|
ShowCart() {
|
||||||
if (this.isPia && this.submittedOrder?.settledTenderAmount == 0) {
|
if (this.isPia && this.submittedOrder?.settledTenderAmount == 0) {
|
||||||
|
|
|
||||||
|
|
@ -153,6 +153,7 @@ import { partTypeStrings } from "@/constants/part-type-strings";
|
||||||
import { mapTaxedLineItemsToStoreFormat } from "../../store";
|
import { mapTaxedLineItemsToStoreFormat } from "../../store";
|
||||||
import { coverageStatus } from "@/constants/insurance";
|
import { coverageStatus } from "@/constants/insurance";
|
||||||
import { containsLineItemWithPartType } from "@/helpers/service-package-helper";
|
import { containsLineItemWithPartType } from "@/helpers/service-package-helper";
|
||||||
|
import { containsRecalParts } from "@/helpers/recal-helper";
|
||||||
|
|
||||||
defineRule("payment-method-required", required(errorMessages.OPTION_REQUIRED));
|
defineRule("payment-method-required", required(errorMessages.OPTION_REQUIRED));
|
||||||
defineRule("recal-ack-required", required(errorMessages.RECAL_ACK_REQUIRED));
|
defineRule("recal-ack-required", required(errorMessages.RECAL_ACK_REQUIRED));
|
||||||
|
|
@ -551,23 +552,21 @@ export default {
|
||||||
},
|
},
|
||||||
async setupPia() {
|
async setupPia() {
|
||||||
this.$refs.loadingModal.showModal();
|
this.$refs.loadingModal.showModal();
|
||||||
|
|
||||||
// if we don't have a work order in delete substatus, set the flag and submit.
|
|
||||||
// we need a work order number for pia so we can pass it to safeliteHop.
|
// we need a work order number for pia so we can pass it to safeliteHop.
|
||||||
if (!store.getters.order.workOrderNumber) {
|
// this will create one in delete substatus.
|
||||||
try {
|
try {
|
||||||
await submitWorkOrder({
|
await submitWorkOrder({
|
||||||
pageNameToLog: "payment-method",
|
pageNameToLog: "payment-method",
|
||||||
submitAfterSave: false,
|
submitAfterSave: false,
|
||||||
createDeleteStatusWorkOrderForPia: true,
|
createUnscheduledStatusWorkOrderForPIA: true,
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("error: response from pia submit work order:" + error.message);
|
console.log("error: response from pia submit work order:" + error.message);
|
||||||
this.dispatchStoreAction(storeActions.RESET_SAVE_SESSION_PROMISE);
|
this.dispatchStoreAction(storeActions.RESET_SAVE_SESSION_PROMISE);
|
||||||
this.$route.query[queryStrings.DISPLAY_PIA_ALERT] = true;
|
this.$route.query[queryStrings.DISPLAY_PIA_ALERT] = true;
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.dispatchStoreAction(storeActions.RESET_SAVE_SESSION_PROMISE);
|
this.dispatchStoreAction(storeActions.RESET_SAVE_SESSION_PROMISE);
|
||||||
this.$router.navigateWithoutSaving(
|
this.$router.navigateWithoutSaving(
|
||||||
this.navigationScenarios.CLICKED_PAY_NOW,
|
this.navigationScenarios.CLICKED_PAY_NOW,
|
||||||
|
|
@ -588,13 +587,17 @@ export default {
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
isRecalibrationOnOrder() {
|
isRecalibrationOnOrder() {
|
||||||
return containsLineItemWithPartType(
|
const order = baseMixin.methods.hasSubmittedOrder()
|
||||||
partTypeStrings.RECALIBRATION,
|
? baseMixin.methods.getSubmittedOrder()
|
||||||
this.$store.getters.order.lineItems?.supportingItems
|
: this.$store.getters.order;
|
||||||
);
|
|
||||||
|
return containsRecalParts(order.lineItems);
|
||||||
},
|
},
|
||||||
shouldHideRecalibration() {
|
shouldHideRecalibration() {
|
||||||
return this.getSettingValue(experimentSettings.RECAL_PRICE_REMOVE);
|
return (
|
||||||
|
this.getSettingValue(experimentSettings.RECAL_PRICE_REMOVE)?.toLowerCase() ===
|
||||||
|
"true" && this.isRecalibrationOnOrder
|
||||||
|
);
|
||||||
},
|
},
|
||||||
showApplePay() {
|
showApplePay() {
|
||||||
return baseMixin.methods.showApplePay();
|
return baseMixin.methods.showApplePay();
|
||||||
|
|
@ -625,13 +628,16 @@ export default {
|
||||||
},
|
},
|
||||||
showInsuranceCoverageAs() {
|
showInsuranceCoverageAs() {
|
||||||
if (!this.isInsurance) return null;
|
if (!this.isInsurance) return null;
|
||||||
|
|
||||||
if (this.isNoComp || this.isItac) {
|
if (this.isNoComp || this.isItac) {
|
||||||
return coverageStatus.NOCOMP;
|
return coverageStatus.NOCOMP;
|
||||||
} else {
|
|
||||||
return this.hasSubmittedOrder()
|
|
||||||
? this.getSubmittedOrder()?.payment.insuranceCoverage.coverageStatus
|
|
||||||
: this.$store.getters.payment.insuranceCoverage.coverageStatus;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.$store.getters.coverageIsVerified) {
|
||||||
|
return coverageStatus.VERIFIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return coverageStatus.PENDING;
|
||||||
},
|
},
|
||||||
currentDeductible() {
|
currentDeductible() {
|
||||||
return this.hasSubmittedOrder()
|
return this.hasSubmittedOrder()
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import store from "@/store";
|
||||||
import * as navigateToHeritage from "@/helpers/heritage-integration/navigation-helper";
|
import * as navigateToHeritage from "@/helpers/heritage-integration/navigation-helper";
|
||||||
import { nextTick } from "vue";
|
import { nextTick } from "vue";
|
||||||
import { experimentSettings } from "@/constants/experiments";
|
import { experimentSettings } from "@/constants/experiments";
|
||||||
|
import experimentMixin from "@/mixins/experiment-mixin.js";
|
||||||
import baseMixin from "@/mixins/base-mixin.js";
|
import baseMixin from "@/mixins/base-mixin.js";
|
||||||
import { containsLineItemWithPartType } from "../../helpers/service-package-helper";
|
import { containsLineItemWithPartType } from "../../helpers/service-package-helper";
|
||||||
|
|
||||||
|
|
@ -391,12 +392,11 @@ describe("quote.vue", () => {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const { wrapper } = setupMocks({});
|
const { wrapper } = setupMocks({});
|
||||||
wrapper.vm.$route = { query: { isInsurance: "false" } };
|
|
||||||
|
|
||||||
//Act
|
//Act
|
||||||
await quote.beforeRouteEnter.call(
|
await quote.beforeRouteEnter.call(
|
||||||
wrapper.vm,
|
wrapper.vm,
|
||||||
{ query: { fmgPage: "quote" } },
|
{ query: { fmgPage: "quote", isInsurance: false } },
|
||||||
undefined,
|
undefined,
|
||||||
(c) => c(wrapper.vm)
|
(c) => c(wrapper.vm)
|
||||||
);
|
);
|
||||||
|
|
@ -747,6 +747,14 @@ function setupMocks({ customMountOptions }) {
|
||||||
...customMountOptions,
|
...customMountOptions,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
mountOptions.mixins = [
|
||||||
|
{
|
||||||
|
methods: {
|
||||||
|
getSettingValue: jest.fn(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
baseMixin.methods.ResetExternalParamsAndHideModal = jest.fn();
|
baseMixin.methods.ResetExternalParamsAndHideModal = jest.fn();
|
||||||
baseMixin.methods.isFormValid = jest.fn().mockReturnValue(true);
|
baseMixin.methods.isFormValid = jest.fn().mockReturnValue(true);
|
||||||
mountOptions.global.mocks["$store"] = store;
|
mountOptions.global.mocks["$store"] = store;
|
||||||
|
|
|
||||||
|
|
@ -113,8 +113,7 @@ import { storeActions } from "@/constants/store-actions";
|
||||||
import { deepClone } from "@/helpers/object-helper";
|
import { deepClone } from "@/helpers/object-helper";
|
||||||
import store from "@/store";
|
import store from "@/store";
|
||||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||||
import { experimentUniverses, experimentSettings } from "@/constants/experiments";
|
import { experimentSettings } from "@/constants/experiments";
|
||||||
import { getSessionKeyValue, getUserIdValue } from "@/helpers/heritage-integration/cookie-helper";
|
|
||||||
import { required } from "@/helpers/validation-rules";
|
import { required } from "@/helpers/validation-rules";
|
||||||
import { errorMessages } from "@/constants/error-messages";
|
import { errorMessages } from "@/constants/error-messages";
|
||||||
import { Form, defineRule } from "vee-validate";
|
import { Form, defineRule } from "vee-validate";
|
||||||
|
|
@ -129,12 +128,18 @@ import { queryStrings } from "@/constants/query-strings";
|
||||||
import { getQuerystringParameter } from "@/helpers/querystring-helper";
|
import { getQuerystringParameter } from "@/helpers/querystring-helper";
|
||||||
import promoModalQuestion from "@/fmg-components/promo-modal-question/promo-modal-question";
|
import promoModalQuestion from "@/fmg-components/promo-modal-question/promo-modal-question";
|
||||||
import { partTypeStrings } from "@/constants/part-type-strings";
|
import { partTypeStrings } from "@/constants/part-type-strings";
|
||||||
import { containsLineItemWithPartType } from "@/helpers/service-package-helper";
|
import {
|
||||||
|
containsLineItemWithPartType,
|
||||||
|
findLineItemsWithPartType,
|
||||||
|
} from "@/helpers/service-package-helper";
|
||||||
import { nextTick } from "vue";
|
import { nextTick } from "vue";
|
||||||
import { packageNames } from "@/constants/package-names";
|
import { packageNames } from "@/constants/package-names";
|
||||||
import { navigateToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper";
|
import { navigateToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper";
|
||||||
|
import { containsRecalParts } from "@/helpers/recal-helper";
|
||||||
defineRule("option-required", required(errorMessages.OPTION_REQUIRED));
|
defineRule("option-required", required(errorMessages.OPTION_REQUIRED));
|
||||||
|
|
||||||
|
const INSURANCE_TAB_TO_DISPLAY_THRESHOLD_DEFAULT = 300;
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "quote",
|
name: "quote",
|
||||||
async beforeRouteEnter(to, from, next) {
|
async beforeRouteEnter(to, from, next) {
|
||||||
|
|
@ -262,7 +267,6 @@ export default {
|
||||||
vm.addableVaps = addableVaps;
|
vm.addableVaps = addableVaps;
|
||||||
vm.lineItems = lineItems;
|
vm.lineItems = lineItems;
|
||||||
vm.availableLineItems = pricingResults;
|
vm.availableLineItems = pricingResults;
|
||||||
vm.isInsuranceSelected = vm.getDefaultIsInsuranceSelectedValue(vm.availableLineItems);
|
|
||||||
vm.holdParentAccountNumber = holdParentAccountNumber;
|
vm.holdParentAccountNumber = holdParentAccountNumber;
|
||||||
vm.holdBillToAccountNumber = holdBillToAccountNumber;
|
vm.holdBillToAccountNumber = holdBillToAccountNumber;
|
||||||
|
|
||||||
|
|
@ -291,8 +295,62 @@ export default {
|
||||||
navigateToHeritageFunnel({ shouldSaveSession: true, pageNameToLog: "quote" });
|
navigateToHeritageFunnel({ shouldSaveSession: true, pageNameToLog: "quote" });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (store.getters.externalParameterState?.isExternalParameter) {
|
const getIsInsuranceSelectedValue = (availableLineItems, insuranceThreshold) => {
|
||||||
|
const serviceLocationState = store.getters.order.serviceLocation.state;
|
||||||
|
// Override if coming back from QuoteDetails. Remove override after Quote release
|
||||||
|
const isInsuranceOverrideValue = to.query?.isInsurance;
|
||||||
|
const defaultIsInsuranceSelectedValue = store.getters.order.payment.isInsurance;
|
||||||
|
const hideRecalCost =
|
||||||
|
experimentMixin.methods
|
||||||
|
.getSettingValue(experimentSettings.RECAL_PRICE_REMOVE)
|
||||||
|
?.toLowerCase() === "true";
|
||||||
|
|
||||||
|
//Default to Insurance Tab if user Service zip is from certain States
|
||||||
|
if (
|
||||||
|
serviceLocationState != null &&
|
||||||
|
payWithInsuranceStates.find((item) => item === serviceLocationState)
|
||||||
|
)
|
||||||
|
return true;
|
||||||
|
else if (isInsuranceOverrideValue != null) {
|
||||||
|
return isInsuranceOverrideValue == "true";
|
||||||
|
} else if (defaultIsInsuranceSelectedValue != null) {
|
||||||
|
return defaultIsInsuranceSelectedValue;
|
||||||
|
} else {
|
||||||
|
if (availableLineItems) {
|
||||||
|
const lineItemsForCalculatingPrice = hideRecalCost
|
||||||
|
? baseMixin.methods.filterOutFees(
|
||||||
|
baseMixin.methods.filterOutRecalibration(availableLineItems) // Strip out recal before filtering out fees
|
||||||
|
)
|
||||||
|
: baseMixin.methods.filterOutFees(availableLineItems);
|
||||||
|
|
||||||
|
return (
|
||||||
|
baseMixin.methods.getTierOnePackagePrice(lineItemsForCalculatingPrice) >
|
||||||
|
insuranceThreshold
|
||||||
|
); // compare base price vs arbitrary threshold (representing insurance price)
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let thresholdToUse = INSURANCE_TAB_TO_DISPLAY_THRESHOLD_DEFAULT;
|
||||||
|
let internalThreshold = experimentMixin.methods.getSettingValue(
|
||||||
|
experimentSettings.INSURANCE_TAB_TO_DISPLAY_THRESHOLD_INTERNAL
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!store.getters.externalParameterState?.isExternalParameter) {
|
||||||
|
// there are no external parameters
|
||||||
|
|
||||||
|
if (internalThreshold) thresholdToUse = internalThreshold;
|
||||||
|
vm.isInsuranceSelected = getIsInsuranceSelectedValue(
|
||||||
|
vm.availableLineItems,
|
||||||
|
thresholdToUse
|
||||||
|
);
|
||||||
|
baseMixin.methods.ResetExternalParamsAndHideModal();
|
||||||
|
} else {
|
||||||
|
// there ARE external parameters
|
||||||
|
|
||||||
if (store.getters.externalParameterQuote.isInsurance == true) {
|
if (store.getters.externalParameterQuote.isInsurance == true) {
|
||||||
|
// did user intentionally select insurance?
|
||||||
vm.isInsuranceSelected = true;
|
vm.isInsuranceSelected = true;
|
||||||
vm.servicePackage = store.getters.externalParameterQuote.servicePackage;
|
vm.servicePackage = store.getters.externalParameterQuote.servicePackage;
|
||||||
await nextTick();
|
await nextTick();
|
||||||
|
|
@ -303,10 +361,26 @@ export default {
|
||||||
baseMixin.methods.ResetExternalParamsAndHideModal();
|
baseMixin.methods.ResetExternalParamsAndHideModal();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// did user come from external source (LeadGen)?
|
||||||
|
let externalSource = store.getters.externalParameterSource
|
||||||
|
? store.getters.externalParameterSource
|
||||||
|
: null;
|
||||||
|
|
||||||
|
// Business logic to determine what "external" source is
|
||||||
|
if (externalSource?.includes("LeadGen")) {
|
||||||
|
const externalThreshold = experimentMixin.methods.getSettingValue(
|
||||||
|
experimentSettings.INSURANCE_TAB_TO_DISPLAY_THRESHOLD_EXTERNAL
|
||||||
|
);
|
||||||
|
if (externalThreshold) thresholdToUse = externalThreshold;
|
||||||
|
} else {
|
||||||
|
if (internalThreshold) thresholdToUse = internalThreshold;
|
||||||
|
}
|
||||||
|
vm.isInsuranceSelected = getIsInsuranceSelectedValue(
|
||||||
|
vm.availableLineItems,
|
||||||
|
thresholdToUse
|
||||||
|
);
|
||||||
baseMixin.methods.ResetExternalParamsAndHideModal();
|
baseMixin.methods.ResetExternalParamsAndHideModal();
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
baseMixin.methods.ResetExternalParamsAndHideModal();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
@ -326,16 +400,25 @@ export default {
|
||||||
return Object.assign({}, this.lineItems);
|
return Object.assign({}, this.lineItems);
|
||||||
},
|
},
|
||||||
isRecalibrationOnOrder() {
|
isRecalibrationOnOrder() {
|
||||||
|
return containsRecalParts(this.lineItems);
|
||||||
|
},
|
||||||
|
isServicePackageDiscountOnOrder() {
|
||||||
return containsLineItemWithPartType(
|
return containsLineItemWithPartType(
|
||||||
partTypeStrings.RECALIBRATION,
|
partTypeStrings.SERVICE_PACKAGE_DISCOUNT,
|
||||||
this?.availableLineItems
|
this.availableLineItems
|
||||||
|
);
|
||||||
|
},
|
||||||
|
servicePackageDiscountParts() {
|
||||||
|
return findLineItemsWithPartType(
|
||||||
|
partTypeStrings.SERVICE_PACKAGE_DISCOUNT,
|
||||||
|
this.availableLineItems
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
shouldHideRecalibration() {
|
shouldHideRecalibration() {
|
||||||
const recalSettingValue = experimentMixin.methods.getSettingValue(
|
return (
|
||||||
experimentSettings.RECAL_PRICE_REMOVE
|
this.getSettingValue(experimentSettings.RECAL_PRICE_REMOVE)?.toLowerCase() ===
|
||||||
|
"true" && this.isRecalibrationOnOrder
|
||||||
);
|
);
|
||||||
return recalSettingValue;
|
|
||||||
},
|
},
|
||||||
showAfterpayBanner() {
|
showAfterpayBanner() {
|
||||||
return (
|
return (
|
||||||
|
|
@ -355,7 +438,7 @@ export default {
|
||||||
const payment = store.getters.order.payment;
|
const payment = store.getters.order.payment;
|
||||||
const log = getQuerystringParameter(queryStrings.LOG);
|
const log = getQuerystringParameter(queryStrings.LOG);
|
||||||
if (eval(log)) {
|
if (eval(log)) {
|
||||||
console.log("quote.vue pagePrereqs:");
|
console.log("------------- quote.vue pagePrereqs start -----------------");
|
||||||
console.log(
|
console.log(
|
||||||
new Date() +
|
new Date() +
|
||||||
" store.getters.order.serviceLocation.zipCode: " +
|
" store.getters.order.serviceLocation.zipCode: " +
|
||||||
|
|
@ -381,6 +464,7 @@ export default {
|
||||||
" store.getters.order.payment.insuranceCoverage?.isVerified: " +
|
" store.getters.order.payment.insuranceCoverage?.isVerified: " +
|
||||||
payment?.insuranceCoverage?.isVerified
|
payment?.insuranceCoverage?.isVerified
|
||||||
);
|
);
|
||||||
|
console.log("----------------- quote.vue pagePrereqs end -----------------");
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
store.getters.order.serviceLocation.zipCode &&
|
store.getters.order.serviceLocation.zipCode &&
|
||||||
|
|
@ -392,30 +476,6 @@ export default {
|
||||||
payment.insuranceCoverage?.isVerified === false)
|
payment.insuranceCoverage?.isVerified === false)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
getDefaultIsInsuranceSelectedValue(availableLineItems) {
|
|
||||||
const serviceLocationState = store.getters.order.serviceLocation.state;
|
|
||||||
// Override if coming back from QuoteDetails. Remove override after Quote release
|
|
||||||
const isInsuranceOverrideValue = this.$route.query?.isInsurance;
|
|
||||||
|
|
||||||
const defaultIsInsuranceSelectedValue = this.$store.getters.order.payment.isInsurance;
|
|
||||||
//Default to Insurance Tab if user Service zip is from certain States
|
|
||||||
if (
|
|
||||||
serviceLocationState != null &&
|
|
||||||
payWithInsuranceStates.find((item) => item === serviceLocationState)
|
|
||||||
)
|
|
||||||
return true;
|
|
||||||
else if (isInsuranceOverrideValue != null) {
|
|
||||||
return isInsuranceOverrideValue == "true";
|
|
||||||
} else if (defaultIsInsuranceSelectedValue != null) {
|
|
||||||
return defaultIsInsuranceSelectedValue;
|
|
||||||
} else {
|
|
||||||
return availableLineItems
|
|
||||||
? baseMixin.methods.getTierOnePackagePrice(
|
|
||||||
baseMixin.methods.filterOutFees(availableLineItems)
|
|
||||||
) > 300
|
|
||||||
: null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
vapsItemsSelectedAction(vapsItemsSelected) {
|
vapsItemsSelectedAction(vapsItemsSelected) {
|
||||||
this.lineItems.vaps = vapsItemsSelected;
|
this.lineItems.vaps = vapsItemsSelected;
|
||||||
},
|
},
|
||||||
|
|
@ -517,6 +577,40 @@ export default {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
this.$nextTick(() => {
|
||||||
|
const availablePackageNames = this.$refs.servicePackage.servicePackageAnswers;
|
||||||
|
var eventLabel = "";
|
||||||
|
availablePackageNames?.forEach((tier) => {
|
||||||
|
if (tier) {
|
||||||
|
let lineItemsToPrice = this.availableLineItems;
|
||||||
|
if (this.isRecalibrationOnOrder && this.shouldHideRecalibration) {
|
||||||
|
lineItemsToPrice =
|
||||||
|
baseMixin.methods.filterOutRecalibration(lineItemsToPrice);
|
||||||
|
}
|
||||||
|
if (this.isServicePackageDiscountOnOrder) {
|
||||||
|
lineItemsToPrice = lineItemsToPrice?.filter((item) => {
|
||||||
|
return (
|
||||||
|
item.partType != this.servicePackageDiscountParts[0].partType
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let price = 0;
|
||||||
|
if (tier.value == "TierTwo" && this.isServicePackageDiscountOnOrder) {
|
||||||
|
lineItemsToPrice.push(...this.servicePackageDiscountParts);
|
||||||
|
}
|
||||||
|
price += baseMixin.methods.getTierOnePackagePrice(
|
||||||
|
baseMixin.methods.filterOutFees(lineItemsToPrice)
|
||||||
|
);
|
||||||
|
price += this.$refs.servicePackage.getVapsPrice(tier.value);
|
||||||
|
const formattedPrice = parseFloat(price).toFixed(2);
|
||||||
|
eventLabel += tier.value + "_" + formattedPrice;
|
||||||
|
}
|
||||||
|
eventLabel += ",";
|
||||||
|
});
|
||||||
|
eventLabel = eventLabel.slice(0, -1);
|
||||||
|
|
||||||
|
this.pushEventToGA("quote", this.GaActions.SERVICE_PACKAGE_PRICE, eventLabel, true);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@
|
||||||
import buttonQuestion from "@/digital-components/button-question/button-question";
|
import buttonQuestion from "@/digital-components/button-question/button-question";
|
||||||
import baseMixin from "@/mixins/base-mixin.js";
|
import baseMixin from "@/mixins/base-mixin.js";
|
||||||
import { processIfStatements } from "@/helpers/cms-content-helper";
|
import { processIfStatements } from "@/helpers/cms-content-helper";
|
||||||
import { damageLocationsSelected as glassLocations } from "@/constants/damage-locations-selected";
|
|
||||||
import servicePackageRadio from "./service-package-radio/service-package-radio";
|
import servicePackageRadio from "./service-package-radio/service-package-radio";
|
||||||
import { partTypeStrings } from "@/constants/part-type-strings";
|
import { partTypeStrings } from "@/constants/part-type-strings";
|
||||||
import { packageNames } from "@/constants/package-names";
|
import { packageNames } from "@/constants/package-names";
|
||||||
|
|
@ -36,6 +35,7 @@ import {
|
||||||
getPromosWithAddableVaps,
|
getPromosWithAddableVaps,
|
||||||
getLineItemsThatMatchPromos,
|
getLineItemsThatMatchPromos,
|
||||||
} from "@/helpers/promotions-helper";
|
} from "@/helpers/promotions-helper";
|
||||||
|
import { containsRecalParts, getItemsWithoutRecalParts } from "@/helpers/recal-helper";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "servicePackageQuestion",
|
name: "servicePackageQuestion",
|
||||||
|
|
@ -237,12 +237,10 @@ export default {
|
||||||
return (this.isInsuranceSelected ? "As little as $" : "$") + formattedPriceFloat;
|
return (this.isInsuranceSelected ? "As little as $" : "$") + formattedPriceFloat;
|
||||||
},
|
},
|
||||||
getPackagePrice(packageName, { discountedPrice = false, servicePackageDiscount = false }) {
|
getPackagePrice(packageName, { discountedPrice = false, servicePackageDiscount = false }) {
|
||||||
var lineItemsToPrice = [...this.nullSafeAvailableLineItems];
|
let lineItemsToPrice = [...this.nullSafeAvailableLineItems];
|
||||||
|
|
||||||
if (this.isRecalibrationOnOrder && this.shouldHideRecalibration) {
|
if (this.isRecalibrationOnOrder && this.shouldHideRecalibration) {
|
||||||
lineItemsToPrice = lineItemsToPrice.filter((item) => {
|
lineItemsToPrice = getItemsWithoutRecalParts(lineItemsToPrice);
|
||||||
return item.partType != partTypeStrings.RECALIBRATION;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//remove service package discount part
|
//remove service package discount part
|
||||||
|
|
|
||||||
|
|
@ -433,6 +433,18 @@ export default {
|
||||||
if (shopProviderData) {
|
if (shopProviderData) {
|
||||||
this.shopProviderData = shopProviderData;
|
this.shopProviderData = shopProviderData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var gaLabel = this.GaLabels.NO;
|
||||||
|
if (this.isServiceableMobile) {
|
||||||
|
gaLabel = this.GaLabels.YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.pushEventToGA(
|
||||||
|
this.GaCategories.APPOINTMENT,
|
||||||
|
this.GaActions.MOBILE_AVAILABLE,
|
||||||
|
gaLabel,
|
||||||
|
true
|
||||||
|
);
|
||||||
},
|
},
|
||||||
setContainsMilitaryBase(val) {
|
setContainsMilitaryBase(val) {
|
||||||
if (this.zipContainsMilitaryBase !== val) {
|
if (this.zipContainsMilitaryBase !== val) {
|
||||||
|
|
@ -607,7 +619,7 @@ export default {
|
||||||
},
|
},
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
console.log(this.billToAccountNumber);
|
|
||||||
if (this.billToAccountNumber) {
|
if (this.billToAccountNumber) {
|
||||||
this.dispatchStoreAction(
|
this.dispatchStoreAction(
|
||||||
this.storeActions.SAVE_BILL_TO_ACCOUNT_NUMBER,
|
this.storeActions.SAVE_BILL_TO_ACCOUNT_NUMBER,
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@ import { nextTick } from "vue";
|
||||||
import { getAvailabilityRating } from "@/layouts/service-location/helpers/service-location-helper/service-location-helper";
|
import { getAvailabilityRating } from "@/layouts/service-location/helpers/service-location-helper/service-location-helper";
|
||||||
|
|
||||||
import { Provider } from "@/layouts/service-location/classes/provider";
|
import { Provider } from "@/layouts/service-location/classes/provider";
|
||||||
|
import { AppointmentTypeStrings } from "@/constants/schedule-constants";
|
||||||
|
|
||||||
defineRule("option-required", required(errorMessages.OPTION_REQUIRED));
|
defineRule("option-required", required(errorMessages.OPTION_REQUIRED));
|
||||||
|
|
||||||
|
|
@ -125,6 +126,8 @@ export default {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async getNextShopsFromList(numberToGet = 3) {
|
async getNextShopsFromList(numberToGet = 3) {
|
||||||
|
const logFirstShopsDisplayed = this.shopIndex == 0;
|
||||||
|
|
||||||
const shopIterator = (array, n) => {
|
const shopIterator = (array, n) => {
|
||||||
const l = array.length;
|
const l = array.length;
|
||||||
return () => {
|
return () => {
|
||||||
|
|
@ -160,6 +163,27 @@ export default {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var gaAction = this.GaActions.MORE_LOCATIONS_CLICKED;
|
||||||
|
if (logFirstShopsDisplayed) {
|
||||||
|
gaAction = this.GaActions.SHOPS_FIRST_DISPLAYED;
|
||||||
|
}
|
||||||
|
if (this.selectedAppointmentType === AppointmentTypeStrings.IN_SHOP) {
|
||||||
|
var shops = mappedData.map((shop) => {
|
||||||
|
if (shop.value.length > 5 && shop.value.startsWith("00")) {
|
||||||
|
return shop.value.substring(1);
|
||||||
|
} else {
|
||||||
|
return shop.value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.pushEventToGA(
|
||||||
|
this.GaCategories.SERVICE_LOCATION,
|
||||||
|
gaAction,
|
||||||
|
shops.join("/"),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (this.answers.length === 0) {
|
if (this.answers.length === 0) {
|
||||||
this.answers = mappedData;
|
this.answers = mappedData;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -213,7 +213,7 @@ export default {
|
||||||
const supportingItemsPromise = await this.dispatchStoreActionWithLogging(
|
const supportingItemsPromise = await this.dispatchStoreActionWithLogging(
|
||||||
storeActions.GET_SUPPORTING_ITEMS,
|
storeActions.GET_SUPPORTING_ITEMS,
|
||||||
null,
|
null,
|
||||||
"estimate"
|
"service-zip"
|
||||||
);
|
);
|
||||||
|
|
||||||
const promiseResultMap = [
|
const promiseResultMap = [
|
||||||
|
|
@ -232,7 +232,7 @@ export default {
|
||||||
);
|
);
|
||||||
|
|
||||||
// call saveSession here - navigateWithSaving saves too late in the flow
|
// call saveSession here - navigateWithSaving saves too late in the flow
|
||||||
await saveSession({ pageNameToLog: "estimate" });
|
await saveSession({ pageNameToLog: "service-zip" });
|
||||||
return this.$router.navigateWithSaving(
|
return this.$router.navigateWithSaving(
|
||||||
this.navigationScenarios.CLICKED_FORWARD_WITH_NO_QUESTIONS,
|
this.navigationScenarios.CLICKED_FORWARD_WITH_NO_QUESTIONS,
|
||||||
this.$route
|
this.$route
|
||||||
|
|
|
||||||
|
|
@ -98,6 +98,9 @@ import store from "@/store";
|
||||||
import { storeActions } from "@/constants/store-actions.js";
|
import { storeActions } from "@/constants/store-actions.js";
|
||||||
import baseMixin from "@/mixins/base-mixin.js";
|
import baseMixin from "@/mixins/base-mixin.js";
|
||||||
import { getFunnelCookie } from "@/helpers/heritage-integration/cookie-helper";
|
import { getFunnelCookie } from "@/helpers/heritage-integration/cookie-helper";
|
||||||
|
import { applicationConfig } from "../../constants/application-config";
|
||||||
|
import { queryStrings } from "@/constants/query-strings";
|
||||||
|
import { getQuerystringParameter } from "@/helpers/querystring-helper";
|
||||||
|
|
||||||
//define validation rules
|
//define validation rules
|
||||||
defineRule("year-required", required(errorMessages.YEAR_REQUIRED));
|
defineRule("year-required", required(errorMessages.YEAR_REQUIRED));
|
||||||
|
|
@ -127,6 +130,12 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
async beforeRouteEnter(to, from, next) {
|
async beforeRouteEnter(to, from, next) {
|
||||||
|
const log = getQuerystringParameter(queryStrings.LOG);
|
||||||
|
if (eval(log)) {
|
||||||
|
console.log("----------------- applicationConfig start -----------------");
|
||||||
|
console.log(new Date() + JSON.stringify(applicationConfig));
|
||||||
|
console.log("----------------- applicationConfig end -----------------");
|
||||||
|
}
|
||||||
// Call APIs
|
// Call APIs
|
||||||
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
|
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
|
||||||
const experimentForLogging = store.getters.applicationUser.experiments.find(
|
const experimentForLogging = store.getters.applicationUser.experiments.find(
|
||||||
|
|
|
||||||
|
|
@ -211,6 +211,13 @@ export default {
|
||||||
payload.glassToReplace = glassString;
|
payload.glassToReplace = glassString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//EON
|
||||||
|
if (order.eon) {
|
||||||
|
payload.eon = order.eon;
|
||||||
|
} else {
|
||||||
|
payload.eon = "";
|
||||||
|
}
|
||||||
|
|
||||||
// Work Order Id
|
// Work Order Id
|
||||||
if (order.workOrderId) {
|
if (order.workOrderId) {
|
||||||
const parsedId = parseInt(order.workOrderId);
|
const parsedId = parseInt(order.workOrderId);
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import { queryStrings } from "@/constants/query-strings";
|
||||||
import { dynamicStrings } from "@/constants/dynamic-strings";
|
import { dynamicStrings } from "@/constants/dynamic-strings";
|
||||||
import { partTypeStrings } from "../constants/part-type-strings";
|
import { partTypeStrings } from "../constants/part-type-strings";
|
||||||
import { showFmgLoadingModal } from "@/helpers/loading-modal-helper";
|
import { showFmgLoadingModal } from "@/helpers/loading-modal-helper";
|
||||||
|
import { getItemsWithoutRecalParts } from "@/helpers/recal-helper";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
|
|
@ -82,7 +83,7 @@ export default {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
getTierOnePackagePrice(lineItems) {
|
getTierOnePackagePrice(lineItems) {
|
||||||
let lineItemsToPrice = lineItems.filter((lineItem) => {
|
let lineItemsToPrice = lineItems?.filter((lineItem) => {
|
||||||
return (
|
return (
|
||||||
lineItem.partType != partTypeStrings.FRONT_WIPER &&
|
lineItem.partType != partTypeStrings.FRONT_WIPER &&
|
||||||
lineItem.partType != partTypeStrings.REAR_WIPER &&
|
lineItem.partType != partTypeStrings.REAR_WIPER &&
|
||||||
|
|
@ -94,7 +95,7 @@ export default {
|
||||||
return totalPrice;
|
return totalPrice;
|
||||||
},
|
},
|
||||||
filterOutFees(lineItems) {
|
filterOutFees(lineItems) {
|
||||||
const filteredLineItems = lineItems.filter((item) => {
|
const filteredLineItems = lineItems?.filter((item) => {
|
||||||
return (
|
return (
|
||||||
(!item.partType.includes("FEE") && !item.partType.includes("EARLY BIRD")) ||
|
(!item.partType.includes("FEE") && !item.partType.includes("EARLY BIRD")) ||
|
||||||
(item.partType === "REPAIR FEE" && item.partNumber != "SUPPLIES-REPAIR")
|
(item.partType === "REPAIR FEE" && item.partNumber != "SUPPLIES-REPAIR")
|
||||||
|
|
@ -103,14 +104,11 @@ export default {
|
||||||
return filteredLineItems;
|
return filteredLineItems;
|
||||||
},
|
},
|
||||||
filterOutRecalibration(lineItems) {
|
filterOutRecalibration(lineItems) {
|
||||||
const filteredLineItems = lineItems.filter((item) => {
|
return getItemsWithoutRecalParts(lineItems);
|
||||||
return !item.partType.includes(partTypeStrings.RECALIBRATION);
|
|
||||||
});
|
|
||||||
return filteredLineItems;
|
|
||||||
},
|
},
|
||||||
getTotalPriceOfAllLineItemsAndChildParts(lineItems, includeTax) {
|
getTotalPriceOfAllLineItemsAndChildParts(lineItems, includeTax) {
|
||||||
let totalPrice = 0;
|
let totalPrice = 0;
|
||||||
lineItems.forEach((lineItem) => {
|
lineItems?.forEach((lineItem) => {
|
||||||
totalPrice += this.getTotalLineItemPrice(lineItem, includeTax);
|
totalPrice += this.getTotalLineItemPrice(lineItem, includeTax);
|
||||||
if (lineItem.childParts) {
|
if (lineItem.childParts) {
|
||||||
totalPrice += this.getTotalPriceOfAllLineItemsAndChildParts(
|
totalPrice += this.getTotalPriceOfAllLineItemsAndChildParts(
|
||||||
|
|
@ -141,41 +139,43 @@ export default {
|
||||||
},
|
},
|
||||||
getAmountDue(lineItems, includeTax = true) {
|
getAmountDue(lineItems, includeTax = true) {
|
||||||
var amountDue = 0;
|
var amountDue = 0;
|
||||||
if (lineItems.glassParts) {
|
if (lineItems?.glassParts) {
|
||||||
amountDue += this.getTotalPriceOfAllLineItemsAndChildParts(
|
amountDue += this.getTotalPriceOfAllLineItemsAndChildParts(
|
||||||
lineItems.glassParts,
|
lineItems.glassParts,
|
||||||
includeTax
|
includeTax
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (lineItems.supportingItems) {
|
|
||||||
|
if (lineItems?.supportingItems) {
|
||||||
amountDue += this.getTotalPriceOfAllLineItemsAndChildParts(
|
amountDue += this.getTotalPriceOfAllLineItemsAndChildParts(
|
||||||
lineItems.supportingItems,
|
lineItems.supportingItems,
|
||||||
includeTax
|
includeTax
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (lineItems.vaps) {
|
|
||||||
|
const order = this.hasSubmittedOrder() ? this.getSubmittedOrder() : store.getters.order;
|
||||||
|
if (
|
||||||
|
store.getters.coverageIsVerified &&
|
||||||
|
!order.policy.isNoComp &&
|
||||||
|
!order.policy.isItac
|
||||||
|
) {
|
||||||
|
amountDue = order.policy.currentDeductible;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lineItems?.vaps) {
|
||||||
amountDue += this.getTotalPriceOfAllLineItemsAndChildParts(
|
amountDue += this.getTotalPriceOfAllLineItemsAndChildParts(
|
||||||
lineItems.vaps,
|
lineItems.vaps,
|
||||||
includeTax
|
includeTax
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (lineItems.promos) {
|
|
||||||
|
if (lineItems?.promos) {
|
||||||
amountDue += this.getTotalPriceOfAllLineItemsAndChildParts(
|
amountDue += this.getTotalPriceOfAllLineItemsAndChildParts(
|
||||||
lineItems.promos,
|
lineItems.promos,
|
||||||
includeTax
|
includeTax
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const order = this.hasSubmittedOrder() ? this.getSubmittedOrder() : store.getters.order;
|
|
||||||
|
|
||||||
if (
|
|
||||||
order.payment.insuranceCoverage.isVerified &&
|
|
||||||
!order.policy.isNoComp &&
|
|
||||||
!order.policy.isItac
|
|
||||||
) {
|
|
||||||
amountDue += order.policy.currentDeductible;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ((amountDue * 100) / 100).toFixed(2);
|
return ((amountDue * 100) / 100).toFixed(2);
|
||||||
},
|
},
|
||||||
getSubTotal(lineItems) {
|
getSubTotal(lineItems) {
|
||||||
|
|
|
||||||
|
|
@ -175,7 +175,7 @@ describe("baseMixin.js", () => {
|
||||||
promos: [],
|
promos: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
const payment = { insuranceCoverage: { isVerified: true } };
|
const payment = { insuranceCoverage: { isVerified: false } };
|
||||||
const policy = { isNoComp: false, isItac: false, currentDeductible: 250 };
|
const policy = { isNoComp: false, isItac: false, currentDeductible: 250 };
|
||||||
|
|
||||||
store.getters = {
|
store.getters = {
|
||||||
|
|
@ -190,7 +190,7 @@ describe("baseMixin.js", () => {
|
||||||
|
|
||||||
var amtDue = mixIn.methods.getAmountDue(lineItems);
|
var amtDue = mixIn.methods.getAmountDue(lineItems);
|
||||||
|
|
||||||
expect(amtDue).toEqual("303.00");
|
expect(amtDue).toEqual("53.00");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("getAmountDue should function with a submitted order", () => {
|
test("getAmountDue should function with a submitted order", () => {
|
||||||
|
|
@ -223,7 +223,7 @@ describe("baseMixin.js", () => {
|
||||||
promos: [],
|
promos: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
const payment = { insuranceCoverage: { isVerified: true } };
|
const payment = { insuranceCoverage: { isVerified: false } };
|
||||||
const policy = { isNoComp: false, isItac: false, currentDeductible: 250 };
|
const policy = { isNoComp: false, isItac: false, currentDeductible: 250 };
|
||||||
|
|
||||||
mixIn.methods.hasSubmittedOrder = jest.fn().mockReturnValue(true);
|
mixIn.methods.hasSubmittedOrder = jest.fn().mockReturnValue(true);
|
||||||
|
|
@ -240,7 +240,7 @@ describe("baseMixin.js", () => {
|
||||||
|
|
||||||
var amtDue = mixIn.methods.getAmountDue(lineItems);
|
var amtDue = mixIn.methods.getAmountDue(lineItems);
|
||||||
|
|
||||||
expect(amtDue).toEqual("303.00");
|
expect(amtDue).toEqual("53.00");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("getAmountDue for cash should sum lineitems", () => {
|
test("getAmountDue for cash should sum lineitems", () => {
|
||||||
|
|
|
||||||
|
|
@ -450,7 +450,17 @@ export default {
|
||||||
const collectedGlassParts = this.reducedGlassPartsArray(partsOrQuestions);
|
const collectedGlassParts = this.reducedGlassPartsArray(partsOrQuestions);
|
||||||
|
|
||||||
// save to store lineItems.glassParts
|
// save to store lineItems.glassParts
|
||||||
self.dispatchStoreAction(storeActions.SAVE_GLASS_PARTS, collectedGlassParts, false);
|
await self.dispatchStoreAction(
|
||||||
|
storeActions.SAVE_GLASS_PARTS,
|
||||||
|
collectedGlassParts,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
|
await self.dispatchStoreActionWithLogging(
|
||||||
|
storeActions.GET_RECAL_PARTS_AND_SAVE_TO_LINE_ITEMS,
|
||||||
|
null,
|
||||||
|
currentPage
|
||||||
|
);
|
||||||
|
|
||||||
const payment = store.getters.payment;
|
const payment = store.getters.payment;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -683,10 +683,7 @@ function updateExternalParameterState() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (externalParameterSource) {
|
if (externalParameterSource) {
|
||||||
store.commit(
|
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_SOURCE, externalParameterSource);
|
||||||
storeMutations.UPDATE_EXTERNAL_PARAMETER_SOURCE,
|
|
||||||
externalParameterSource
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,9 +36,12 @@ import sharedMutations from "./vuex-shared-mutations/vuexSharedMutations";
|
||||||
import {
|
import {
|
||||||
coverageStatus,
|
coverageStatus,
|
||||||
coverageStatusValue,
|
coverageStatusValue,
|
||||||
|
coverageStatusEnum,
|
||||||
coverageType,
|
coverageType,
|
||||||
coverageTypeValue,
|
coverageTypeValue,
|
||||||
|
coverageTypeEnum,
|
||||||
} from "@/constants/insurance";
|
} from "@/constants/insurance";
|
||||||
|
import { containsRecalParts } from "@/helpers/recal-helper";
|
||||||
|
|
||||||
// Export State
|
// Export State
|
||||||
const getDefaultState = () => {
|
const getDefaultState = () => {
|
||||||
|
|
@ -109,6 +112,7 @@ const getDefaultState = () => {
|
||||||
insuranceCoverage: {
|
insuranceCoverage: {
|
||||||
isVerified: null,
|
isVerified: null,
|
||||||
coverageStatus: null,
|
coverageStatus: null,
|
||||||
|
coverageSubStatus: null,
|
||||||
coverageType: null,
|
coverageType: null,
|
||||||
coverageVerificationType: null,
|
coverageVerificationType: null,
|
||||||
},
|
},
|
||||||
|
|
@ -690,6 +694,8 @@ export const mutations = {
|
||||||
state.order.payment.insuranceCoverage.coverageStatus = coverageStatusValue(
|
state.order.payment.insuranceCoverage.coverageStatus = coverageStatusValue(
|
||||||
sessionInformation?.order.insuranceCoverage.coverageStatus
|
sessionInformation?.order.insuranceCoverage.coverageStatus
|
||||||
);
|
);
|
||||||
|
state.order.payment.insuranceCoverage.coverageSubStatus =
|
||||||
|
sessionInformation?.order.insuranceCoverage.coverageSubStatus;
|
||||||
state.order.payment.insuranceCoverage.coverageType = coverageTypeValue(
|
state.order.payment.insuranceCoverage.coverageType = coverageTypeValue(
|
||||||
sessionInformation?.order.insuranceCoverage.coverageType
|
sessionInformation?.order.insuranceCoverage.coverageType
|
||||||
);
|
);
|
||||||
|
|
@ -769,6 +775,24 @@ export const getters = {
|
||||||
);
|
);
|
||||||
return !!nonWindshieldItems?.length;
|
return !!nonWindshieldItems?.length;
|
||||||
},
|
},
|
||||||
|
coverageIsVerified: (state) => {
|
||||||
|
let order;
|
||||||
|
if (window.sessionStorage.getItem("submittedOrder") !== null) {
|
||||||
|
order = JSON.parse(window.sessionStorage.getItem("submittedOrder"));
|
||||||
|
} else {
|
||||||
|
order = state.order;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
order.payment?.insuranceCoverage?.isVerified &&
|
||||||
|
order.policy?.currentDeductible != 9999 &&
|
||||||
|
order.policy?.currentDeductible != 7777
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
isMobileAppointment: (state) => {
|
isMobileAppointment: (state) => {
|
||||||
return state.order.serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE;
|
return state.order.serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE;
|
||||||
},
|
},
|
||||||
|
|
@ -894,13 +918,13 @@ export const getters = {
|
||||||
isVerifiedAndDeductibleZeroConfirmed: (state) => {
|
isVerifiedAndDeductibleZeroConfirmed: (state) => {
|
||||||
// used as a CMS variable on /payment-method, needed for FunnelSubHeaderWidget on cart pages
|
// used as a CMS variable on /payment-method, needed for FunnelSubHeaderWidget on cart pages
|
||||||
if (
|
if (
|
||||||
(state.order.policy.currentDeductible === 0 ||
|
state.order.policy.currentDeductible === 0 &&
|
||||||
state.order.policy.currentDeductible > 0) &&
|
getters.coverageIsVerified(state) &&
|
||||||
state.order.payment.insuranceCoverage.coverageStatus === coverageStatus.VERIFIED &&
|
|
||||||
!state.order.policy.isNoComp
|
!state.order.policy.isNoComp
|
||||||
) {
|
) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
requiresVerifiedRedirecting: (state) => {
|
requiresVerifiedRedirecting: (state) => {
|
||||||
|
|
@ -1528,15 +1552,38 @@ export const actions = {
|
||||||
},
|
},
|
||||||
|
|
||||||
getMobileFeePart(context, { pageNameToLog }) {
|
getMobileFeePart(context, { pageNameToLog }) {
|
||||||
const damageType = context.getters.damage.isRepair ? "Repair" : "Replace";
|
const serviceType = context.getters.damage.isRepair ? "Repair" : "Install";
|
||||||
|
const facilityType = "Mobile";
|
||||||
const parentAccountNumber = context.getters.payment.parentAccountNumber;
|
const parentAccountNumber = context.getters.payment.parentAccountNumber;
|
||||||
const billToAccountNumber = context.getters.payment.billToAccountNumber
|
const billToAccountNumber = context.getters.payment.billToAccountNumber
|
||||||
? context.getters.payment.billToAccountNumber
|
? context.getters.payment.billToAccountNumber
|
||||||
: applicationConfig.CASH_DEFAULT_BILL_TO_ACCOUNT_NUMBER;
|
: applicationConfig.CASH_DEFAULT_BILL_TO_ACCOUNT_NUMBER;
|
||||||
|
|
||||||
|
const order = context.getters.order;
|
||||||
|
const coverageStatus = coverageStatusEnum(order.payment?.insuranceCoverage?.coverageStatus);
|
||||||
|
const coverageType = coverageTypeEnum(order.payment?.insuranceCoverage?.coverageType);
|
||||||
|
const isItacOptimized = order.policy?.isItac ?? false;
|
||||||
|
const zipCode =
|
||||||
|
order.serviceLocation?.provider?.address?.zipCode ?? order.serviceLocation?.zipCode;
|
||||||
|
|
||||||
|
var providerNumber =
|
||||||
|
order.serviceLocation?.provider?.providerNumber ?? order.serviceLocation?.zipCodeCtu;
|
||||||
|
if (providerNumber.startsWith("00") && providerNumber.length > 5) {
|
||||||
|
providerNumber = providerNumber.substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
var endPoint = `${endpoints.GetMobileFeePart.url}/?serviceType=${serviceType}&facilityType=${facilityType}&parentAccountNumber=${parentAccountNumber}&billToAccountNumber=${billToAccountNumber}&providerNumber=${providerNumber}&isItacOptimized=${isItacOptimized}&zipCode=${zipCode}`;
|
||||||
|
if (coverageStatus) {
|
||||||
|
endPoint = `${endPoint}&coverageStatus=${coverageStatus}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (coverageType) {
|
||||||
|
endPoint = `${endPoint}&coverageType=${coverageType}`;
|
||||||
|
}
|
||||||
|
|
||||||
return globalMethods.callHttpClient({
|
return globalMethods.callHttpClient({
|
||||||
method: endpoints.GetMobileFeePart.method,
|
method: endpoints.GetMobileFeePart.method,
|
||||||
endpoint: `${endpoints.GetMobileFeePart.url}/${damageType}/${parentAccountNumber}/${billToAccountNumber}`,
|
endpoint: endPoint,
|
||||||
logApiCall: true,
|
logApiCall: true,
|
||||||
pageNameToLog: pageNameToLog,
|
pageNameToLog: pageNameToLog,
|
||||||
});
|
});
|
||||||
|
|
@ -1818,8 +1865,8 @@ export const actions = {
|
||||||
const lineItems = context.state.order.lineItems;
|
const lineItems = context.state.order.lineItems;
|
||||||
|
|
||||||
const submitAfterSave = payload?.submitAfterSave === "true";
|
const submitAfterSave = payload?.submitAfterSave === "true";
|
||||||
const createDeleteStatusWorkOrderForPia =
|
const createUnscheduledStatusWorkOrderForPIA =
|
||||||
payload?.createDeleteStatusWorkOrderForPia === "true";
|
payload?.createUnscheduledStatusWorkOrderForPIA === "true";
|
||||||
|
|
||||||
// create a new array to avoid mutating state
|
// create a new array to avoid mutating state
|
||||||
const newGlassToReplace = convertGlassPieceNamingForApi(damage.glassToReplace);
|
const newGlassToReplace = convertGlassPieceNamingForApi(damage.glassToReplace);
|
||||||
|
|
@ -1954,7 +2001,7 @@ export const actions = {
|
||||||
referralNumber: order.referralNumber?.toString(),
|
referralNumber: order.referralNumber?.toString(),
|
||||||
referralSequenceNumber: order.referralSequenceNumber,
|
referralSequenceNumber: order.referralSequenceNumber,
|
||||||
eon: order.eon,
|
eon: order.eon,
|
||||||
createDeleteStatusWorkOrderForPia: createDeleteStatusWorkOrderForPia,
|
createUnscheduledStatusWorkOrderForPIA: createUnscheduledStatusWorkOrderForPIA,
|
||||||
lockToken: order.lockToken,
|
lockToken: order.lockToken,
|
||||||
isRecalAckOptIn: order.isRecalAckOptIn,
|
isRecalAckOptIn: order.isRecalAckOptIn,
|
||||||
},
|
},
|
||||||
|
|
@ -2900,6 +2947,46 @@ export const actions = {
|
||||||
externalParameterMMS.externalParameterStyle
|
externalParameterMMS.externalParameterStyle
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async getRecalPartsAndSaveToLineItems(context, { pageNameToLog }) {
|
||||||
|
// identify each part that needs recal
|
||||||
|
const glassParts = context.state.order?.lineItems?.glassParts ?? [];
|
||||||
|
|
||||||
|
for (let i = 0; i < glassParts.length; i++) {
|
||||||
|
// does this part need recal?
|
||||||
|
const needsRecal =
|
||||||
|
!!glassParts[i].requiresRecalibration && !!glassParts[i].recalibrationType;
|
||||||
|
|
||||||
|
if (needsRecal) {
|
||||||
|
const recalType = glassParts[i].recalibrationType;
|
||||||
|
const parentAccountNumber =
|
||||||
|
context.state.order.payment.parentAccountNumber ??
|
||||||
|
applicationConfig.CASH_PARENT_ACCOUNT_NUMBER;
|
||||||
|
|
||||||
|
// Get part from API
|
||||||
|
const urlExtension = `${context.state.order.vehicle.carId}/${glassParts[i].partNumber}/${recalType}/${parentAccountNumber}/${context.state.order.serviceLocation.zipCode}/${applicationConfig.ANALYTICS_APPLICATION_NAME}/${context.state.order.referralSequenceNumber}`;
|
||||||
|
|
||||||
|
const recalPartResponse = await globalMethods.callHttpClient({
|
||||||
|
method: endpoints.GetRecalPart.method,
|
||||||
|
endpoint: `${endpoints.GetRecalPart.url}/${urlExtension}`,
|
||||||
|
payload: {},
|
||||||
|
pageNameToLog: pageNameToLog,
|
||||||
|
});
|
||||||
|
|
||||||
|
// If any parts retrieved, add as children to the glass part.
|
||||||
|
if (
|
||||||
|
recalPartResponse.status === 200 &&
|
||||||
|
recalPartResponse.data.recalibrationParts?.length > 0
|
||||||
|
) {
|
||||||
|
if (!glassParts[i].childParts) {
|
||||||
|
glassParts[i].childParts = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
glassParts[i].childParts.push(...recalPartResponse.data.recalibrationParts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default createStore({
|
export default createStore({
|
||||||
|
|
@ -2922,34 +3009,7 @@ export default createStore({
|
||||||
// Private Functions
|
// Private Functions
|
||||||
|
|
||||||
function getHasRecalibrationPart(state) {
|
function getHasRecalibrationPart(state) {
|
||||||
var hasRequiresRecalibration =
|
return containsRecalParts(state.order.lineItems);
|
||||||
getNonFalseValuesOfPropertyInArrayOfObjects(
|
|
||||||
state.order.lineItems.glassParts,
|
|
||||||
"requiresRecalibration"
|
|
||||||
)?.length > 0;
|
|
||||||
var hasRecalibrationType =
|
|
||||||
getNonFalseValuesOfPropertyInArrayOfObjects(
|
|
||||||
state.order.lineItems.glassParts,
|
|
||||||
"recalibrationType"
|
|
||||||
)?.length > 0;
|
|
||||||
|
|
||||||
if (hasRequiresRecalibration) {
|
|
||||||
if (hasRecalibrationType) {
|
|
||||||
// Has both 'requiresRecalibration' and 'recalibrationType' and 'recalibrationType'
|
|
||||||
return (
|
|
||||||
getNonFalseValuesOfPropertyInArrayOfObjects(
|
|
||||||
state.order.lineItems.glassParts,
|
|
||||||
"recalibrationType"
|
|
||||||
)[0].toLowerCase() != "unknown"
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
// Has 'requiresRecalibration' but no 'recalibrationType' at all
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Does not have 'requiresRecalibration'
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function sortArrayOfObjectsByPropertyValue(arrayOfObjects, propertyName) {
|
function sortArrayOfObjectsByPropertyValue(arrayOfObjects, propertyName) {
|
||||||
|
|
|
||||||
|
|
@ -3950,6 +3950,111 @@ describe("Getters", () => {
|
||||||
mutations.updateVaps(storeState, mockStateValues.funnelVaps);
|
mutations.updateVaps(storeState, mockStateValues.funnelVaps);
|
||||||
mutations.updateGlassToReplace(storeState, mockStateValues.glassToReplace);
|
mutations.updateGlassToReplace(storeState, mockStateValues.glassToReplace);
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(getters.experimentOrder(storeState)).toEqual({
|
||||||
|
funnelVehicleYear: mockStateValues.vehicleYear,
|
||||||
|
funnelVehicleMake: mockStateValues.vehicleMake,
|
||||||
|
funnelVehicleModel: mockStateValues.vehicleModel,
|
||||||
|
funnelVehicleStyle: mockStateValues.vehicleStyle,
|
||||||
|
funnelIsRepair: mockStateValues.isRepair,
|
||||||
|
funnelNumberOfChips: mockStateValues.numberOfChips,
|
||||||
|
funnelCarId: mockStateValues.carId,
|
||||||
|
funnelServiceCity: mockStateValues.serviceCity,
|
||||||
|
funnelServiceState: mockStateValues.serviceState,
|
||||||
|
funnelServiceZipCode: mockStateValues.serviceZipCode,
|
||||||
|
funnelParentAccountNumber: mockStateValues.parentAccountNumber,
|
||||||
|
funnelIsCoverageVerified: mockStateValues.isCoverageVerified,
|
||||||
|
funnelOrderPartNumbers: ["WINDSHIELDPARTNUMBER"],
|
||||||
|
funnelOrderPartTypes: ["ADAS, maybe"],
|
||||||
|
funnelHasRecalibrationPart: false,
|
||||||
|
funnelSelectedMultiGlass: false,
|
||||||
|
funnelSelectedWindshieldGlass: true,
|
||||||
|
funnelSelectedBackGlass: false,
|
||||||
|
funnelSelectedDriverSideGlass: false,
|
||||||
|
funnelSelectedPassengerSideGlass: false,
|
||||||
|
funnelProviderNumber: mockStateValues.funnelProviderNumber,
|
||||||
|
funnelReferralType: mockStateValues.funnelReferralType,
|
||||||
|
funnelServiceZipCodeCtu: mockStateValues.funnelServiceZipCodeCtu,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Single windshield with recalibration child part > return correct experimentOrder values", () => {
|
||||||
|
// Arrange
|
||||||
|
const storeState = state;
|
||||||
|
const mockStateValues = {
|
||||||
|
vehicleYear: 1000,
|
||||||
|
vehicleMake: "CarMake",
|
||||||
|
vehicleModel: "CarModel",
|
||||||
|
vehicleStyle: "SuperCoolStyle",
|
||||||
|
isRepair: false,
|
||||||
|
numberOfChips: 0,
|
||||||
|
carId: "Gibberish",
|
||||||
|
serviceCity: "Columbus",
|
||||||
|
serviceState: "OH-IO",
|
||||||
|
serviceZipCode: 43215,
|
||||||
|
parentAccountNumber: "999999",
|
||||||
|
isCoverageVerified: false,
|
||||||
|
glassParts: [
|
||||||
|
{
|
||||||
|
partNumber: "WINDSHIELDPARTNUMBER",
|
||||||
|
description: "This is a windshield",
|
||||||
|
recalibrationType: "ADAS, maybe",
|
||||||
|
requiresRecalibration: true,
|
||||||
|
requiresCapabilityQuestions: false,
|
||||||
|
childParts: [
|
||||||
|
{
|
||||||
|
partNumber: "THIRD RECAL",
|
||||||
|
description: "Additional Static Recal",
|
||||||
|
recalibrationType:
|
||||||
|
"DUAL & RECAL THIRD & HC FUNCTION TEST & RL SENSOR",
|
||||||
|
ribCode: "RL",
|
||||||
|
safelitePartNumber: "THIRD RECAL",
|
||||||
|
status: "ACTIVE",
|
||||||
|
partType: "ADAS RECALIBRATION",
|
||||||
|
childParts: [],
|
||||||
|
recalibrationFees: [],
|
||||||
|
salesTax: null,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
otherParts: [],
|
||||||
|
glassToReplace: [
|
||||||
|
{
|
||||||
|
glassLocation: "Windshield",
|
||||||
|
glassName: "Single",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
funnelProviderNumber: "1",
|
||||||
|
funnelReferralType: "CASH QUOTE",
|
||||||
|
funnelServiceZipCodeCtu: "11111",
|
||||||
|
};
|
||||||
|
|
||||||
|
//Act
|
||||||
|
mutations.updateYear(storeState, mockStateValues.vehicleYear);
|
||||||
|
mutations.updateMake(storeState, mockStateValues.vehicleMake);
|
||||||
|
mutations.updateModel(storeState, mockStateValues.vehicleModel);
|
||||||
|
mutations.updateStyle(storeState, mockStateValues.vehicleStyle);
|
||||||
|
mutations.updateIsRepair(storeState, mockStateValues.isRepair);
|
||||||
|
mutations.updateNumberOfChips(storeState, mockStateValues.numberOfChips);
|
||||||
|
mutations.updateCarId(storeState, mockStateValues.carId);
|
||||||
|
mutations.updateServiceLocation(storeState, {
|
||||||
|
city: mockStateValues.serviceCity,
|
||||||
|
state: mockStateValues.serviceState,
|
||||||
|
zipCode: mockStateValues.serviceZipCode,
|
||||||
|
zipCodeCtu: mockStateValues.funnelServiceZipCodeCtu,
|
||||||
|
provider: {
|
||||||
|
providerNumber: mockStateValues.funnelProviderNumber,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
mutations.updateParentAcctNumber(storeState, mockStateValues.parentAccountNumber);
|
||||||
|
mutations.updateInsuranceVerifiedStatus(storeState, mockStateValues.isCoverageVerified);
|
||||||
|
mutations.updateIsInsurance(storeState, false);
|
||||||
|
mutations.updateGlassParts(storeState, mockStateValues.glassParts);
|
||||||
|
mutations.updateSupportingItems(storeState, mockStateValues.funnelSupportingItems);
|
||||||
|
mutations.updateVaps(storeState, mockStateValues.funnelVaps);
|
||||||
|
mutations.updateGlassToReplace(storeState, mockStateValues.glassToReplace);
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
expect(getters.experimentOrder(storeState)).toEqual({
|
expect(getters.experimentOrder(storeState)).toEqual({
|
||||||
funnelVehicleYear: mockStateValues.vehicleYear,
|
funnelVehicleYear: mockStateValues.vehicleYear,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue