diff --git a/src/constants/coverage-status.js b/src/constants/coverage-status.js
deleted file mode 100644
index 7cf757aed..000000000
--- a/src/constants/coverage-status.js
+++ /dev/null
@@ -1,18 +0,0 @@
-const coverageStatus = {
- PENDING: "Pending",
- NOCOMP: "NoComp",
- VERIFIED: "Verified",
-};
-
-export function coverageStatusValue(intCoverageStatus) {
- switch (intCoverageStatus) {
- case 0:
- return coverageStatus.PENDING;
- case 1:
- return coverageStatus.NOCOMP;
- case 2:
- return coverageStatus.VERIFIED;
- default:
- return null;
- }
-}
diff --git a/src/constants/experiments.js b/src/constants/experiments.js
index bd480636f..059f7f27e 100644
--- a/src/constants/experiments.js
+++ b/src/constants/experiments.js
@@ -4,7 +4,6 @@ const experimentUniverses = {
const experimentSettings = {
GOOGLE_CUSTOM_DIMENSION_INDEX: "Google Custom Dimension Index",
- SUPPRESS_VIN_CAPTURE: "SuppressVinCapture",
DISPLAY_AVAILABILITY_INDICATORS: "DisplayAvailabilityIndicators",
PIA_EXPERIENCE: "PIA Experience",
PIA_INSURANCE: "DisplayPIAInsurance",
diff --git a/src/constants/insurance.js b/src/constants/insurance.js
new file mode 100644
index 000000000..2574fdbc6
--- /dev/null
+++ b/src/constants/insurance.js
@@ -0,0 +1,30 @@
+import { cartItemTypes } from "@/constants/cart-item-types";
+
+export const payWithInsuranceStates = ["AZ", "CT", "FL", "KY", "MA", "MN", "NY", "SC"];
+
+export const cartItemTypesCoveredByInsurance = [
+ cartItemTypes.GLASS_PARTS,
+ cartItemTypes.SUPPORTING_ITEMS,
+ cartItemTypes.RECYCLE_FEE,
+ cartItemTypes.REPLACE_FEE,
+ cartItemTypes.SUPPLIES_REPAIR,
+];
+
+export const coverageStatus = {
+ PENDING: "Pending",
+ NOCOMP: "NoComp",
+ VERIFIED: "Verified",
+};
+
+export function coverageStatusValue(intCoverageStatus) {
+ switch (intCoverageStatus) {
+ case 0:
+ return coverageStatus.PENDING;
+ case 1:
+ return coverageStatus.NOCOMP;
+ case 2:
+ return coverageStatus.VERIFIED;
+ default:
+ return null;
+ }
+}
diff --git a/src/constants/pay-with-insurance-states.js b/src/constants/pay-with-insurance-states.js
deleted file mode 100644
index e65589557..000000000
--- a/src/constants/pay-with-insurance-states.js
+++ /dev/null
@@ -1 +0,0 @@
-export const payWithInsuranceStates = ["AZ", "CT", "FL", "KY", "MA", "MN", "NY", "SC"];
diff --git a/src/constants/tint-mapper.js b/src/constants/tint-mapper.js
index 519de0855..c290dd1db 100644
--- a/src/constants/tint-mapper.js
+++ b/src/constants/tint-mapper.js
@@ -33,6 +33,7 @@ const tintMap = {
{ name: "green tint", src: "Glass-NoShade-GreenTint.svg" },
{ name: "gray tint privacy", src: "Glass-NoShade-GrayTint.svg" },
{ name: "blue tint", src: "Glass-NoShade-BlueTint.svg" },
+ { name: "green tint privacy", src: "Glass-NoShade-Privacy.svg" },
// No shade or tint
{ name: "clear", src: "Glass-NoShade-NoTint.svg" },
diff --git a/src/fmg-components/cart/cart.spec.js b/src/fmg-components/cart/cart.spec.js
index bd0a2b096..cbb5a1610 100644
--- a/src/fmg-components/cart/cart.spec.js
+++ b/src/fmg-components/cart/cart.spec.js
@@ -5,6 +5,13 @@ import cart from "@/fmg-components/cart/cart.vue";
import { shallowMount } from "@vue/test-utils";
import { getMountOptions } from "@/helpers/unit-test-helper.js";
+global.$logger = {
+ logInformation: jest.fn(),
+ logWarning: jest.fn(),
+ logError: jest.fn(),
+ logCritical: jest.fn(),
+};
+
describe("cart.vue", () => {
describe("cartItem computeds", () => {
test("if there are one or more front wipers on the order, a front wiper cart item should be added to the cart", () => {
diff --git a/src/fmg-components/cart/cart.vue b/src/fmg-components/cart/cart.vue
index ebbaf530b..1ba5ea562 100644
--- a/src/fmg-components/cart/cart.vue
+++ b/src/fmg-components/cart/cart.vue
@@ -10,20 +10,36 @@
href="javascript:void(0)"
class="col d-flex justify-content-between py-0">
{{ amountDueText }}
- {{ getFormattedAmount("", amountDue) }}
+ {{
+ getLineItemAmount(amountDue, showCoverageAsPending)
+ }}
+
+
+
+
+ {{
+ getLineItemAmount(
+ deductibleLineItem.subTotal,
+ showCoverageAsPending
+ )
+ }}
+
+
+
+
- {{ getFormattedAmount("", packagePrice) }}
+ {{ getLineItemAmount(packagePrice) }}
- {{ getFormattedAmount("", packagePriceWithoutDiscount) }}
+ {{ getLineItemAmount(packagePriceWithoutDiscount) }}
@@ -78,27 +94,40 @@
{{ recycleFeeCartItem.name }}
-
{{ getFormattedAmount(cartItem.category, cartItem.subTotal) }}
+
{{
+ getLineItemAmount(cartItem.subTotal, null, cartItem.category)
+ }}
- {{ subtotalText }}{{ getFormattedAmount("", subTotal) }}
+ {{ subtotalText }}
+ {{ getLineItemAmount(subTotal, showCoverageAsPending) }}
- {{ salesTaxText }}{{ getFormattedAmount("", salesTax) }}
+ {{ salesTaxText }}
+ {{ getLineItemAmount(salesTax) }}
- {{ amountPaidText }}{{ getFormattedAmount("", amountPaid) }}
+ {{ amountPaidText }}
+ {{ getLineItemAmount(amountPaid) }}
- {{ amountDueText }}{{ getFormattedAmount("", amountDue) }}
+ {{ amountDueText }}
+ {{ getLineItemAmount(amountDue, showCoverageAsPending) }}
+
+ {{ insuranceCompanyName }}
+
lineItemsToKeep.cartItemType != cartItemType
@@ -255,6 +291,19 @@ export default {
this.$emit("update:modelValue", newValue);
},
},
+ showCoverageAsPending() {
+ return this.showInsuranceCoverageAs === coverageStatus.PENDING;
+ },
+ showCoverageAsVerified() {
+ return this.showInsuranceCoverageAs === coverageStatus.VERIFIED;
+ },
+ currentDeductible() {
+ const deductible = this.insuranceDeductible;
+ if (!(deductible === 0 || deductible > 0)) {
+ global.$logger.logError("Error: currentDeductible should not be null");
+ }
+ return deductible;
+ },
screenReaderTotalAmountDueText() {
return this.getCmsContent("ScreenReaderTotalAmountDueWidget", "Text");
},
@@ -364,11 +413,13 @@ export default {
return tier;
},
packagePrice() {
- let packagePrice = this.isInsuranceSelected
- ? 0
- : baseMixin.methods.getTierOnePackagePrice(
- baseMixin.methods.filterOutFees(this.availableLineItems)
- );
+ let packagePrice = 0;
+
+ if (!this.showCoverageAsVerified && !this.showCoverageAsPending) {
+ packagePrice = baseMixin.methods.getTierOnePackagePrice(
+ baseMixin.methods.filterOutFees(this.availableLineItems)
+ );
+ }
packagePrice += this.getVapsPrice(this.packageLevel);
@@ -410,7 +461,25 @@ export default {
const promos = this.lineItems?.promos;
return promos?.length > 0 ? promos : [];
},
- // Cart Items
+ deductibleLineItemName() {
+ return this.getCmsContent("DeductibleTextWidget", "Text");
+ },
+ deductibleLineItem() {
+ let lineItem = null;
+
+ if (this.showCoverageAsVerified || this.showCoverageAsPending) {
+ lineItem = {
+ name: this.deductibleLineItemName,
+ subTotal: this.currentDeductible,
+ };
+ }
+
+ return lineItem;
+ },
+ verifyingCoverageText() {
+ return this.getCmsContent("VerifyingCoverageTextWidget", "Text");
+ },
+ // Cart Item Groupings
packageCartItems() {
return this.getVapsCartItemsForSelectedPackage(this.packageLevel);
},
@@ -426,6 +495,7 @@ export default {
});
return nonpackageCartItems;
},
+ // Individual Cart Items
frontWiperCartItemName() {
return this.getCmsContentForVapsType(partTypeStrings.FRONT_WIPER);
},
@@ -446,6 +516,9 @@ export default {
subTotal: 0,
salesTax: 0,
lineItems: [],
+ isCoveredByInsurance: cartItemTypesCoveredByInsurance.includes(
+ cartItemTypes.FRONT_WIPERS
+ ),
};
frontWiperLineItems.forEach((lineItem) => {
@@ -483,6 +556,9 @@ export default {
subTotal: 0,
salesTax: 0,
lineItems: [],
+ isCoveredByInsurance: cartItemTypesCoveredByInsurance.includes(
+ cartItemTypes.REAR_WIPERS
+ ),
};
rearWiperLineItems.forEach((lineItem) => {
@@ -520,6 +596,9 @@ export default {
subTotal: 0,
salesTax: 0,
lineItems: [],
+ isCoveredByInsurance: cartItemTypesCoveredByInsurance.includes(
+ cartItemTypes.RAIN_DEFENSE
+ ),
};
rainDefenseLineItem.cartItemType = cartItem.cartItemType;
@@ -540,7 +619,7 @@ export default {
if (this.glassParts.length > 0) {
this.glassParts.forEach((lineItem) => {
- let glassPartCartItem = {
+ let cartItem = {
name: null,
category: cartItemCategories.GLASS_PARTS,
cartItemType: cartItemTypes.GLASS_PARTS,
@@ -550,23 +629,25 @@ export default {
(lineItem.kitPrice ?? 0) +
(lineItem.laborAmount ?? 0) +
(lineItem.sellingPrice ?? 0),
-
salesTax: lineItem.salesTax ?? 0,
lineItems: [],
+ isCoveredByInsurance: cartItemTypesCoveredByInsurance.includes(
+ cartItemTypes.GLASS_PARTS
+ ),
};
if (lineItem.childParts?.length > 0) {
lineItem.childParts.forEach((childPartLineItem) => {
- glassPartCartItem.subTotal +=
+ cartItem.subTotal +=
(childPartLineItem.kitPrice ?? 0) +
(childPartLineItem.laborAmount ?? 0) +
(childPartLineItem.sellingPrice ?? 0);
- glassPartCartItem.salesTax += childPartLineItem.salesTax;
+ cartItem.salesTax += childPartLineItem.salesTax;
});
}
- glassPartCartItems.push(glassPartCartItem);
+ glassPartCartItems.push(cartItem);
});
}
@@ -592,6 +673,9 @@ export default {
subTotal: 0,
salesTax: 0,
lineItems: [],
+ isCoveredByInsurance: cartItemTypesCoveredByInsurance.includes(
+ cartItemTypes.REPLACE_FEE
+ ),
};
recycleFeeLineItem.cartItemType = cartItem.cartItemType;
@@ -629,6 +713,9 @@ export default {
subTotal: 0,
salesTax: 0,
lineItems: [],
+ isCoveredByInsurance: cartItemTypesCoveredByInsurance.includes(
+ cartItemTypes.SUPPLIES_REPAIR
+ ),
};
suppliesRepairLineItem.cartItemType = cartItem.cartItemType;
@@ -664,6 +751,9 @@ export default {
subTotal: 0,
salesTax: 0,
lineItems: [],
+ isCoveredByInsurance: cartItemTypesCoveredByInsurance.includes(
+ cartItemTypes.MOBILE_FEE
+ ),
};
mobileFeeLineItem.cartItemType = cartItem.cartItemType;
@@ -697,6 +787,9 @@ export default {
subTotal: 0,
salesTax: 0,
lineItems: [],
+ isCoveredByInsurance: cartItemTypesCoveredByInsurance.includes(
+ cartItemTypes.SUPPORTING_ITEMS
+ ),
};
otherSupportingItemsLineItems.forEach((lineItem) => {
@@ -715,7 +808,7 @@ export default {
return cartItem;
},
premiumAppointmentDiscountCartItemName() {
- return "Early bird appointment"; // TODO: get from CMS
+ return this.getCmsContent("PremiumAppointmentTextWidget", "Text");
},
premiumAppointmentDiscountCartItem() {
let cartItem = null;
@@ -734,6 +827,9 @@ export default {
subTotal: 0,
salesTax: 0,
lineItems: [],
+ isCoveredByInsurance: cartItemTypesCoveredByInsurance.includes(
+ cartItemTypes.EARLY_BIRD
+ ),
};
premiumAppointmentDiscountLineItem.cartItemType = cartItem.cartItemType;
@@ -779,6 +875,7 @@ export default {
subTotal: 0,
salesTax: 0,
lineItems: [],
+ isCoveredByInsurance: cartItemTypesCoveredByInsurance.includes(promoCode),
};
promoLineItems.forEach((promoLineItem) => {
@@ -820,17 +917,38 @@ export default {
subTotal() {
let subTotal = 0;
- this.cartItems.forEach((cartItem) => {
- subTotal += cartItem.subTotal;
- });
+ if (this.showCoverageAsVerified || this.showCoverageAsPending) {
+ // only include items NOT covered by insurance
+ this.cartItems.forEach((cartItem) => {
+ if (!cartItem.isCoveredByInsurance) {
+ subTotal += cartItem.subTotal ?? 0;
+ }
+ });
+ // add deductible amount still to pay
+ subTotal += this.deductibleLineItem.subTotal ?? 0;
+ } else {
+ this.cartItems.forEach((cartItem) => {
+ subTotal += cartItem.subTotal ?? 0;
+ });
+ }
return subTotal;
},
salesTax() {
let salesTax = 0;
- this.cartItems.forEach((cartItem) => {
- salesTax += cartItem.salesTax ?? 0;
- });
+
+ if (this.showCoverageAsVerified || this.showCoverageAsPending) {
+ // only include items NOT covered by insurance
+ this.cartItems.forEach((cartItem) => {
+ if (!cartItem.isCoveredByInsurance) {
+ salesTax += cartItem.salesTax ?? 0;
+ }
+ });
+ } else {
+ this.cartItems.forEach((cartItem) => {
+ salesTax += cartItem.salesTax ?? 0;
+ });
+ }
return salesTax;
},
@@ -893,7 +1011,7 @@ export default {
display: flex;
justify-content: space-between;
padding: 0.5rem 1.5rem;
- &:nth-last-child(-n + 4) {
+ &:nth-last-child(-n + 3) {
background-color: $green-100;
}
&:last-child {
@@ -901,16 +1019,26 @@ export default {
color: #ffffff;
}
}
+ .deductible {
+ background-color: $gray-100;
+ }
.service-type {
background-color: $gray-100;
- align-items: center;
+ }
+ .deductible ~ .service-type {
+ background: $white;
+ }
+ .service-type ~ .packaged-cart-item {
+ background-color: $gray-100;
+ }
+ .deductible ~ .packaged-cart-item {
+ background: $white;
}
.struck-out-price {
text-decoration: line-through;
padding-left: 0.5rem;
}
.packaged-cart-item {
- background-color: $gray-100;
padding-left: 2.5rem;
align-items: center;
span {
@@ -937,6 +1065,11 @@ export default {
background: $gray-100;
}
}
+ .deductible ~ .non-packaged-cart-item {
+ &.odd {
+ background: $white;
+ }
+ }
.non-packaged-cart-item {
&.even {
background-color: $white;
@@ -945,6 +1078,11 @@ export default {
line-height: 1.625;
}
}
+ .deductible ~ .non-packaged-cart-item {
+ &.even {
+ background-color: $gray-100;
+ }
+ }
// Custom order/wrap for removable nonpackaged Cart Items
.removable-cart-item {
flex-wrap: wrap;
@@ -959,8 +1097,8 @@ export default {
}
}
.package-type,
- .service-type {
- //background-color: #f5f5f5;
+ .service-type,
+ .deductible {
align-items: center;
}
.sub-total,
@@ -973,15 +1111,19 @@ export default {
.sub-total {
border-top: 1px solid $green;
}
- .service-type {
- // background-color: #f5f5f5;
+ .service-type,
+ .deductible {
.text-block {
background: transparent;
margin-top: 0;
padding: 0;
+ width: 50%;
}
}
}
+ .insurance-company-name {
+ margin-top: 0.5rem;
+ }
.vin-toggle {
&:after {
content: "";
diff --git a/src/fmg-components/funnel-sub-header/funnel-sub-header.vue b/src/fmg-components/funnel-sub-header/funnel-sub-header.vue
index 20e18ba1c..b664e491c 100644
--- a/src/fmg-components/funnel-sub-header/funnel-sub-header.vue
+++ b/src/fmg-components/funnel-sub-header/funnel-sub-header.vue
@@ -53,7 +53,7 @@ export default {
return this.leftAlignHeader ? "justify-content-start" : "justify-content-center";
},
subText() {
- return this.getCmsContent(this.cmsWidgetName, "HeaderSubText");
+ return this.getCmsContent(this.cmsWidgetName, "SubheaderText");
},
backButtonAccessibleText() {
return this.getCmsContent(this.cmsWidgetName, "BackButtonAccessibleText");
diff --git a/src/helpers/heritage-integration/navigation-helper.js b/src/helpers/heritage-integration/navigation-helper.js
index cb3844bfc..a0d3bb92c 100644
--- a/src/helpers/heritage-integration/navigation-helper.js
+++ b/src/helpers/heritage-integration/navigation-helper.js
@@ -5,9 +5,6 @@ import { lazyLoadComponent } from "@/router/dynamic-routing/component-loader.js"
import { saveSession } from "@/helpers/heritage-integration/order-helper.js";
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
import { storeActions } from "@/constants/store-actions.js";
-import { settleAllPromises } from "@/helpers/layout-helper";
-import experimentMixin from "@/mixins/experiment-mixin";
-import { experimentSettings } from "@/constants/experiments";
import { includesWindshieldReplacement } from "@/helpers/damage-helper";
import store from "@/store";
import router from "@/router";
@@ -33,7 +30,7 @@ export async function getDirectNavigation(toRoute) {
// vehicle -> vehicle-damage
// quote -> vin-lookup/estimate
// insurance-company -> vin-lookup/estimate
- if (store.getters.payment.insuranceCoverage.isVerified) {
+ if (store.getters.requiresVerifiedRedirecting) {
if (fmgPageValue === fmgPageValues.VEHICLE) {
return fmgPageValues.VEHICLE_DAMAGE;
}
@@ -77,7 +74,7 @@ export async function getImplicitNavigation(toRoute) {
if (quoteComponent.methods.arePagePrerequisitesValid()) {
// Do not send to quote if verified insurance user.
- if (store.getters.payment.insuranceCoverage.isVerified) {
+ if (store.getters.requiresVerifiedRedirecting) {
return fmgPageValues.HERITAGE;
} else {
return fmgPageValues.QUOTE;
@@ -142,11 +139,7 @@ export async function skipVinLookup() {
? await store.dispatch(storeActions.IS_VIN_OPTIONAL_VEHICLE)
: false;
- return (
- isVinOptionalVehicle ||
- !includesWindshieldReplacement() ||
- experimentMixin.methods.hasSettingEqualTo(experimentSettings.SUPPRESS_VIN_CAPTURE, "true")
- );
+ return isVinOptionalVehicle || !includesWindshieldReplacement();
}
export async function skipVinLookupNotRepair() {
@@ -158,11 +151,7 @@ export async function skipVinLookupNotRepair() {
? await store.dispatch(storeActions.IS_VIN_OPTIONAL_VEHICLE)
: false;
- return (
- isVinOptionalVehicle ||
- !includesWindshieldReplacement() ||
- experimentMixin.methods.hasSettingEqualTo(experimentSettings.SUPPRESS_VIN_CAPTURE, "true")
- );
+ return isVinOptionalVehicle || !includesWindshieldReplacement();
}
async function getLazyLoadedComponent(pageName) {
diff --git a/src/helpers/heritage-integration/navigation-helper.spec.js b/src/helpers/heritage-integration/navigation-helper.spec.js
index 963a6434c..671a1b46e 100644
--- a/src/helpers/heritage-integration/navigation-helper.spec.js
+++ b/src/helpers/heritage-integration/navigation-helper.spec.js
@@ -115,16 +115,6 @@ describe("getPageToRouteExistingOrderTo", () => {
store.commit(storeMutations.UPDATE_IS_REPAIR, false);
store.commit(storeMutations.UPDATE_MAKE, "acura");
- const mockExperimentsList = [
- {
- universeName: "ConceptFunnel",
- settings: {
- SuppressVinCapture: false,
- },
- },
- ];
- store.commit(storeMutations.UPDATE_EXPERIMENTS, mockExperimentsList);
-
// Mock out the lazy load calls for all components.
mockLazyLoadComponentReturnValues({
[fmgPageValues.VEHICLE]: true,
@@ -371,6 +361,7 @@ describe("getPageToRouteExistingOrderTo", () => {
};
store.commit(storeMutations.UPDATE_IS_VERIFIED_INSURANCE, true);
+ store.commit(storeMutations.UPDATE_REFERRAL_NUMBER, "666666");
// Act
const result = await getPageToRouteExistingOrderTo(toRoute);
@@ -389,6 +380,7 @@ describe("getPageToRouteExistingOrderTo", () => {
};
store.commit(storeMutations.UPDATE_IS_VERIFIED_INSURANCE, true);
+ store.commit(storeMutations.UPDATE_REFERRAL_NUMBER, "666666");
store.commit(storeMutations.UPDATE_IS_REPAIR, true);
store.commit(storeMutations.UPDATE_MAKE, "acura");
@@ -408,6 +400,7 @@ describe("getPageToRouteExistingOrderTo", () => {
};
store.commit(storeMutations.UPDATE_IS_VERIFIED_INSURANCE, true);
+ store.commit(storeMutations.UPDATE_REFERRAL_NUMBER, "666666");
store.commit(storeMutations.UPDATE_IS_REPAIR, true);
store.commit(storeMutations.UPDATE_MAKE, "acura");
@@ -429,6 +422,7 @@ describe("getPageToRouteExistingOrderTo", () => {
};
store.commit(storeMutations.UPDATE_IS_VERIFIED_INSURANCE, true);
+ store.commit(storeMutations.UPDATE_REFERRAL_NUMBER, "666666");
store.commit(storeMutations.UPDATE_IS_REPAIR, false);
store.commit(storeMutations.UPDATE_MAKE, "acura");
store.commit(storeMutations.UPDATE_GLASS_TO_REPLACE, [
@@ -451,6 +445,7 @@ describe("getPageToRouteExistingOrderTo", () => {
};
store.commit(storeMutations.UPDATE_IS_VERIFIED_INSURANCE, true);
+ store.commit(storeMutations.UPDATE_REFERRAL_NUMBER, "666666");
store.commit(storeMutations.UPDATE_IS_REPAIR, false);
store.commit(storeMutations.UPDATE_MAKE, "acura");
store.commit(storeMutations.UPDATE_GLASS_TO_REPLACE, [
@@ -476,6 +471,7 @@ describe("getPageToRouteExistingOrderTo", () => {
};
store.commit(storeMutations.UPDATE_IS_VERIFIED_INSURANCE, false);
+ store.commit(storeMutations.UPDATE_REFERRAL_NUMBER, "55555");
// Act
const result = await getPageToRouteExistingOrderTo(toRoute);
@@ -493,6 +489,7 @@ describe("getPageToRouteExistingOrderTo", () => {
};
store.commit(storeMutations.UPDATE_IS_VERIFIED_INSURANCE, false);
+ store.commit(storeMutations.UPDATE_REFERRAL_NUMBER, "55555");
// Act
const result = await getPageToRouteExistingOrderTo(toRoute);
@@ -510,6 +507,7 @@ describe("getPageToRouteExistingOrderTo", () => {
};
store.commit(storeMutations.UPDATE_IS_VERIFIED_INSURANCE, false);
+ store.commit(storeMutations.UPDATE_REFERRAL_NUMBER, "55555");
// Act
const result = await getPageToRouteExistingOrderTo(toRoute);
diff --git a/src/layouts/confirmation/confirmation.spec.js b/src/layouts/confirmation/confirmation.spec.js
index 3c0ccee2f..0d8a1b273 100644
--- a/src/layouts/confirmation/confirmation.spec.js
+++ b/src/layouts/confirmation/confirmation.spec.js
@@ -58,6 +58,15 @@ beforeEach(() => {
},
payment: {
isPia: true,
+ isInsurance: false,
+ insuranceCoverage: {
+ coverageStatus: "test",
+ },
+ },
+ policy: {
+ isNoComp: false,
+ currentDeductible: 1,
+ insuranceCompanyName: "test name",
},
referralNumber: "1234567",
vehicle: {
diff --git a/src/layouts/confirmation/confirmation.vue b/src/layouts/confirmation/confirmation.vue
index 54e40214b..39da072a3 100644
--- a/src/layouts/confirmation/confirmation.vue
+++ b/src/layouts/confirmation/confirmation.vue
@@ -21,10 +21,12 @@
:displayVehicleImage="vehicleBannerImageUrl"
:displayGenericVehicleImage="false" />
+
{{ ScheduleDateFormatted }}
{{ ScheduleTimeFormatted }}
+
+
+
+ servicePackageOptionsCmsName="ServicePackageTitle"
+ :insuranceDeductible="currentDeductible"
+ :insuranceCompanyName="insuranceCompanyName"
+ :showInsuranceCoverageAs="showInsuranceCoverageAs" />
+
+
+
0) {
+ return true;
+ }
+ return false;
+ },
+ showInsuranceCoverageAs() {
+ if (!this.isInsurance) return null;
+ if (this.isNoComp) {
+ return coverageStatus.NOCOMP;
+ } else {
+ return store.getters.submittedOrder.payment.insuranceCoverage.coverageStatus;
+ }
+ },
+ currentDeductible() {
+ return store.getters.submittedOrder.policy.currentDeductible;
+ },
+ insuranceCompanyName() {
+ return store.getters.submittedOrder.policy.insuranceCompanyName;
+ },
isPia() {
return store.getters.submittedOrder?.payment.isPia;
},
diff --git a/src/layouts/estimate/estimate.vue b/src/layouts/estimate/estimate.vue
index 9c2ce4caf..b298132ca 100644
--- a/src/layouts/estimate/estimate.vue
+++ b/src/layouts/estimate/estimate.vue
@@ -112,8 +112,6 @@ import {
skipVinLookup,
skipVinLookupNotRepair,
} from "@/helpers/heritage-integration/navigation-helper";
-import experimentMixin from "@/mixins/experiment-mixin";
-import { experimentSettings } from "@/constants/experiments";
import vinPagesMixin from "@/mixins/vin-pages-mixin";
import { navigateToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper";
import { saveSession } from "@/helpers/heritage-integration/order-helper.js";
diff --git a/src/layouts/insurance-company/insurance-company-question.vue b/src/layouts/insurance-company/insurance-company-question.vue
index 49e1eb8c8..f8f7bbc6a 100644
--- a/src/layouts/insurance-company/insurance-company-question.vue
+++ b/src/layouts/insurance-company/insurance-company-question.vue
@@ -96,15 +96,29 @@ export default {
findMatches(request, response) {
const matches = [];
const term = request?.term?.toUpperCase();
+ const nonPriorityMatches = [];
+
this.searchableInsuranceCompanyList.forEach((company, index) => {
if (
- company.accountName.indexOf(term) !== -1 ||
- company.altTerms.indexOf(term) !== -1
+ company.accountName.toUpperCase().indexOf(term) !== -1 ||
+ company.altTerms.toUpperCase().indexOf(term) !== -1
) {
matches.push(company.accountName);
}
});
- response(matches);
+
+ // Prioritize matched typed entries to top of list
+ const priorityMatches = matches.filter((companyName, index) => {
+ if (companyName.toUpperCase().indexOf(term) === 0) {
+ return companyName;
+ } else {
+ nonPriorityMatches.push(companyName);
+ }
+ });
+
+ const prioritizedMatches = [...priorityMatches, ...nonPriorityMatches];
+
+ response(prioritizedMatches);
},
selectInsuranceCompany(parentAccountName) {
// this runs upon user selection within jQueryUI Autocomplete
@@ -112,9 +126,14 @@ export default {
console.error("No insurance companies found");
return;
}
- const parentAccountNumber = this.getParentAccountNumber(parentAccountName);
- this.selectedAccountNumber = parentAccountNumber;
- this.selectedAccountName = this.getParentAccountName(parentAccountNumber);
+ if (parentAccountName) {
+ const parentAccountNumber = this.getParentAccountNumber(parentAccountName);
+ this.selectedAccountNumber = parentAccountNumber;
+ this.selectedAccountName = this.getParentAccountName(parentAccountNumber);
+ } else {
+ this.selectedAccountNumber = "";
+ this.selectedAccountName = "";
+ }
},
},
mounted() {
@@ -131,20 +150,12 @@ export default {
},
minLength: 0, // Necessary to display fmenu when clearing input
- // Bold matching letters as you type in the input
- search: function (event, ui) {
- setTimeout(() => {
- let w = $(this).autocomplete("widget").find("div");
- let regExpString = "(" + this.value + ")";
- let re = new RegExp(regExpString, "i");
- w.html((i, html) =>
- html.replace(re, "$1")
- );
- }, 5);
- },
select: function (event, ui) {
select(ui.item.value);
},
+ change: function (event, ui) {
+ select(ui?.item?.value);
+ },
});
}, 0);
},
diff --git a/src/layouts/insurance-company/insurance-company.vue b/src/layouts/insurance-company/insurance-company.vue
index 55a8149e3..a15de8311 100644
--- a/src/layouts/insurance-company/insurance-company.vue
+++ b/src/layouts/insurance-company/insurance-company.vue
@@ -20,7 +20,7 @@
@@ -44,7 +44,7 @@ import { storeActions } from "@/constants/store-actions";
import { Form, defineRule } from "vee-validate";
import baseMixin from "@/mixins/base-mixin.js";
import { navigateToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper";
-
+import { applicationConfig } from "@/constants/application-config";
import store from "@/store";
export default {
@@ -84,9 +84,22 @@ export default {
originalList: [],
};
},
+ computed: {
+ isParentAccountNumber() {
+ return !!this.parentAccountNumber;
+ },
+ },
methods: {
+ isCashParentAccountNumber() {
+ return (
+ applicationConfig.CASH_PARENT_ACCOUNT_NUMBER.toString() ===
+ store.getters.order?.payment?.parentAccountNumber.toString()
+ );
+ },
parentAccountNumberFromStore() {
- const accountNumber = store.getters.order?.payment?.parentAccountNumber.toString();
+ const accountNumber = !this.isCashParentAccountNumber()
+ ? store.getters.order?.payment?.parentAccountNumber.toString()
+ : "";
return accountNumber;
},
arePagePrerequisitesValid() {
diff --git a/src/layouts/payment-method/payment-method.spec.js b/src/layouts/payment-method/payment-method.spec.js
index 8cba373de..ab0a0df99 100644
--- a/src/layouts/payment-method/payment-method.spec.js
+++ b/src/layouts/payment-method/payment-method.spec.js
@@ -53,6 +53,12 @@ function setupMocks() {
isPia: false,
},
},
+ policy: {
+ currentDeductible: 123,
+ },
+ payment: {
+ isInsurance: false,
+ },
};
const mountOptions = getMountOptions({
diff --git a/src/layouts/payment-method/payment-method.vue b/src/layouts/payment-method/payment-method.vue
index 207b7f041..0910920a9 100644
--- a/src/layouts/payment-method/payment-method.vue
+++ b/src/layouts/payment-method/payment-method.vue
@@ -28,7 +28,10 @@
v-model="lineItems"
pageName="payment-method"
servicePackageOptionsCmsName="ServicePackageTitle"
- recyclingModalCmsWidgetName="RecycleModal" />
+ recyclingModalCmsWidgetName="RecycleModal"
+ :insuranceDeductible="currentDeductible"
+ :insuranceCompanyName="insuranceCompanyName"
+ :showInsuranceCoverageAs="showInsuranceCoverageAs" />
@@ -110,6 +113,7 @@ import { errorMessages } from "@/constants/error-messages";
import { AppointmentTypeStrings } from "@/constants/schedule-constants";
import { partTypeStrings } from "@/constants/part-type-strings";
import { mapTaxedLineItemsToStoreFormat } from "../../store";
+import { coverageStatus } from "@/constants/insurance";
defineRule("option-required", required(errorMessages.OPTION_REQUIRED));
@@ -331,7 +335,21 @@ export default {
(isMobile && mobileReqs) || (!isMobile && dropOffInshopReqs);
// Insurance
- const isInsuranceSet = store.getters.order.payment.isInsurance !== null;
+ const isInsurance = store.getters.order.payment.isInsurance;
+ const insuranceCoverageStatus = store.getters.payment.insuranceCoverage.coverageStatus;
+ const currentDeductible = store.getters.policy.currentDeductible;
+ const isInsuranceSet = () => {
+ if (isInsurance !== null) {
+ if (
+ insuranceCoverageStatus === coverageStatus.VERIFIED &&
+ !(currentDeductible === 0 || currentDeductible > 0)
+ ) {
+ return false; // if coverageStatus is verified there must be a valid deductible also
+ }
+ return true;
+ }
+ return false;
+ };
// Schedule
const schedule = store.getters.order.schedule;
@@ -496,6 +514,32 @@ export default {
damageInfo() {
return this.$store.getters.damage;
},
+ isInsurance() {
+ return this.$store.getters.payment.isInsurance;
+ },
+ isNoComp() {
+ return this.$store.getters.policy.isNoComp;
+ },
+ hasVapsInCart() {
+ if (this.lineItems?.vaps?.length > 0) {
+ return true;
+ }
+ return false;
+ },
+ showInsuranceCoverageAs() {
+ if (!this.isInsurance) return null;
+ if (this.isNoComp) {
+ return coverageStatus.NOCOMP;
+ } else {
+ return this.$store.getters.payment.insuranceCoverage.coverageStatus;
+ }
+ },
+ currentDeductible() {
+ return this.$store.getters.policy.currentDeductible;
+ },
+ insuranceCompanyName() {
+ return this.$store.getters.policy.insuranceCompanyName;
+ },
noPiaDisclaimer() {
return this.getCmsContent("NoPiaDisclaimerWidget", "Text");
},
@@ -515,10 +559,12 @@ export default {
const piaExperience = this.getSettingValue(experimentSettings.PIA_EXPERIENCE);
const piaInsurance = this.getSettingValue(experimentSettings.PIA_INSURANCE);
- const isEnabled =
- piaExperience === "PIA Optional" ||
- piaExperience === "PIA Required" ||
- piaInsurance === "true";
+ var isEnabled = false;
+ if (this.isInsurance) {
+ isEnabled = piaInsurance === "true" && this.currentDeductible !== 0;
+ } else {
+ isEnabled = piaExperience === "PIA Optional" || piaExperience === "PIA Required";
+ }
return !isEnabled;
},
diff --git a/src/layouts/payment/payment.spec.js b/src/layouts/payment/payment.spec.js
index 34b282e8b..4290a97d4 100644
--- a/src/layouts/payment/payment.spec.js
+++ b/src/layouts/payment/payment.spec.js
@@ -202,6 +202,9 @@ describe("payment.vue", () => {
jobMaxMinutes: "45",
},
},
+ policy: {
+ currentDeductible: 1,
+ },
get payment() {
return this.order.payment;
},
diff --git a/src/layouts/payment/payment.vue b/src/layouts/payment/payment.vue
index bc3e365ad..e21780181 100644
--- a/src/layouts/payment/payment.vue
+++ b/src/layouts/payment/payment.vue
@@ -53,7 +53,10 @@
:allowItemRemoval="false"
v-model="lineItems"
servicePackageOptionsCmsName="ServicePackageTitle"
- recyclingModalCmsWidgetName="RecycleModal" />
+ recyclingModalCmsWidgetName="RecycleModal"
+ :insuranceDeductible="currentDeductible"
+ :insuranceCompanyName="insuranceCompanyName"
+ :showInsuranceCoverageAs="showInsuranceCoverageAs" />
@@ -219,9 +222,9 @@ import { queryStrings } from "@/constants/query-strings";
import { getQuerystringParameter } from "@/helpers/querystring-helper";
import { deepClone } from "@/helpers/object-helper";
import { submitWorkOrder } from "@/helpers/heritage-integration/order-helper.js";
-
import iframeResize from "../../../node_modules/iframe-resizer/js/iframeResizer.js";
import { routerParams } from "@/router/router-constants/router-params";
+import { coverageStatus } from "@/constants/insurance";
export default {
name: "payment",
@@ -425,6 +428,32 @@ export default {
damageInfo() {
return this.$store.getters.damage;
},
+ isInsurance() {
+ return this.$store.getters.payment.isInsurance;
+ },
+ isNoComp() {
+ return this.$store.getters.policy.isNoComp;
+ },
+ hasVapsInCart() {
+ if (this.lineItems?.vaps?.length > 0) {
+ return true;
+ }
+ return false;
+ },
+ showInsuranceCoverageAs() {
+ if (!this.isInsurance) return null;
+ if (this.isNoComp) {
+ return coverageStatus.NOCOMP;
+ } else {
+ return this.$store.getters.payment.insuranceCoverage.coverageStatus;
+ }
+ },
+ currentDeductible() {
+ return this.$store.getters.policy.currentDeductible;
+ },
+ insuranceCompanyName() {
+ return this.$store.getters.policy.insuranceCompanyName;
+ },
isPaypal() {
if (this.paymentType == "pp") {
return true;
diff --git a/src/layouts/quote/quote.vue b/src/layouts/quote/quote.vue
index 065d44e82..c9ddd2f89 100644
--- a/src/layouts/quote/quote.vue
+++ b/src/layouts/quote/quote.vue
@@ -96,7 +96,7 @@ import { required } from "@/helpers/validation-rules";
import { errorMessages } from "@/constants/error-messages";
import { Form, defineRule } from "vee-validate";
import { applicationConfig } from "@/constants/application-config";
-import { payWithInsuranceStates } from "@/constants/pay-with-insurance-states";
+import { payWithInsuranceStates } from "@/constants/insurance";
import {
revalidatePromosAndValidateQueryStringPromo,
buildToastMessagesFromRevalidateOrValidatePromoResponse,
diff --git a/src/layouts/service-location/appointment-type-question/appointment-type-question.vue b/src/layouts/service-location/appointment-type-question/appointment-type-question.vue
index ca452ac01..64bf159ff 100644
--- a/src/layouts/service-location/appointment-type-question/appointment-type-question.vue
+++ b/src/layouts/service-location/appointment-type-question/appointment-type-question.vue
@@ -32,6 +32,7 @@ export default {
cmsWidgetName: String,
isServiceableMobile: Boolean,
isServiceableInshop: Boolean,
+ mobileFeeApplies: Boolean,
},
computed: {
questionText() {
@@ -45,7 +46,8 @@ export default {
const shouldShowInshop = this.isServiceableInshop;
const shouldShowDropoff =
this.isServiceableInshop && !this.$store.getters.damage.isRepair;
- return this.answersFromCms
+
+ var answers = this.answersFromCms
? this.answersFromCms.filter((answer) => {
return (
(answer.Name == AppointmentTypeStrings.IN_SHOP && shouldShowInshop) ||
@@ -54,6 +56,15 @@ export default {
);
})
: [];
+
+ if (!this.mobileFeeApplies) {
+ answers.forEach((item) => {
+ if (item.Name.toLowerCase() === "mobile") {
+ item.SubText = item.SubText.replace("*", "");
+ }
+ });
+ }
+ return answers;
},
selectedValue: {
get: function () {
diff --git a/src/layouts/service-location/mobile-location-modal-questions/mobile-location-modal-questions.vue b/src/layouts/service-location/mobile-location-modal-questions/mobile-location-modal-questions.vue
index debc25f89..4558c3294 100644
--- a/src/layouts/service-location/mobile-location-modal-questions/mobile-location-modal-questions.vue
+++ b/src/layouts/service-location/mobile-location-modal-questions/mobile-location-modal-questions.vue
@@ -25,6 +25,7 @@
@@ -153,6 +154,7 @@ export default {
alertInvalidZipWidgetName: String,
customComponentId: String,
validationRules: String,
+ mobileFeeApplies: Boolean,
},
computed: {
mobileLocationLinkPromptText() {
diff --git a/src/layouts/service-location/service-location.vue b/src/layouts/service-location/service-location.vue
index 89b3320fd..b83db7ebc 100644
--- a/src/layouts/service-location/service-location.vue
+++ b/src/layouts/service-location/service-location.vue
@@ -67,6 +67,7 @@
:isServiceableMobile="isServiceableMobile"
:isServiceableInshop="isServiceableInshop"
:isDisplayed="isAppointmentTypeDisplayed"
+ :mobileFeeApplies="mobileFeeApplies"
ref="appointmentTypeQuestion"
groupName="appointmentTypeQuestion"
cmsWidgetName="AppointmentTypeQuestionWidget"
@@ -80,6 +81,7 @@
v-if="selectedAppointmentType === 'Mobile'"
v-model="mobileLocationQuestions"
:mobileFeePart="mobileFeePart"
+ :mobileFeeApplies="mobileFeeApplies"
@updated-mobile-fee-part="setMobileFeePart"
@updated-serviceability="setServiceabilityDetails"
@updated-contains-military-base="setContainsMilitaryBase"
@@ -139,7 +141,7 @@ import {
getShopProviderData,
} from "@/layouts/service-location/helpers/service-location-helper/service-location-helper";
import { navigateToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper";
-
+import { applicationConfig } from "@/constants/application-config";
import { Provider } from "@/layouts/service-location/classes/provider";
import store from "@/store";
@@ -300,6 +302,13 @@ export default {
return this.isGlassServiceableMobile;
}
},
+ mobileFeeApplies() {
+ if (this.mobileFeePart) {
+ return true;
+ } else {
+ return false;
+ }
+ },
isServiceableInshop() {
if (this.isRecalibrationServiceableInshop !== null) {
return this.isGlassServiceableInshop && this.isRecalibrationServiceableInshop;
@@ -350,17 +359,26 @@ export default {
methods: {
arePagePrerequisitesValid() {
// insurance drops the recycle fee on replace orders so it won't be in supportingItems
- if (store.getters.payment.isInsurance && !store.getters.order.damage.isRepair) {
- return (
- store.getters.order.serviceLocation.zipCode !== null &&
- store.getters.payment.isInsurance !== null
- );
+ if (store.getters.payment.isInsurance) {
+ if (
+ store.getters.payment.parentAccountNumber !==
+ applicationConfig.CASH_PARENT_ACCOUNT_NUMBER &&
+ store.getters.order.policy.policyNumber &&
+ store.getters.order.serviceLocation.zipCode
+ ) {
+ return true;
+ } else {
+ return false;
+ }
} else {
- return (
- store.getters.lineItems.supportingItems !== null &&
- store.getters.order.serviceLocation.zipCode !== null &&
- store.getters.payment.isInsurance !== null
- );
+ if (
+ store.getters.lineItems.supportingItems &&
+ store.getters.order.serviceLocation.zipCode
+ ) {
+ return true;
+ } else {
+ return false;
+ }
}
},
setData(zipCodeData, serviceabilityDetails, mobileFeePart, shopProviderData) {
diff --git a/src/layouts/vehicle-damage/vehicle-damage.spec.js b/src/layouts/vehicle-damage/vehicle-damage.spec.js
index 1a2939d3d..36f694d5e 100644
--- a/src/layouts/vehicle-damage/vehicle-damage.spec.js
+++ b/src/layouts/vehicle-damage/vehicle-damage.spec.js
@@ -728,6 +728,7 @@ describe("vehicle-damage.vue", () => {
getters: {
vehicle: {},
payment: { insuranceCoverage: { isVerified: true } },
+ requiresVerifiedRedirecting: true,
},
},
},
diff --git a/src/layouts/vehicle-damage/vehicle-damage.vue b/src/layouts/vehicle-damage/vehicle-damage.vue
index 3b613ad3a..ec19c3800 100644
--- a/src/layouts/vehicle-damage/vehicle-damage.vue
+++ b/src/layouts/vehicle-damage/vehicle-damage.vue
@@ -541,7 +541,7 @@ export default {
return this.$route.params[this.routerParams.DISPLAY_VEHICLE_CHANGE_ALERT];
},
shouldHideBackButton() {
- return this.$store.getters.payment.insuranceCoverage.isVerified;
+ return this.$store.getters.requiresVerifiedRedirecting;
},
},
diff --git a/src/layouts/vehicle/vehicle.vue b/src/layouts/vehicle/vehicle.vue
index e4a19d335..82dc54f22 100644
--- a/src/layouts/vehicle/vehicle.vue
+++ b/src/layouts/vehicle/vehicle.vue
@@ -348,7 +348,7 @@ export default {
isDisabled(options) {
if (
!options.length ||
- store.getters.payment?.insuranceCoverage?.isVerified ||
+ store.getters.requiresVerifiedRedirecting ||
getFunnelCookie()?.HasDelayedClaimRegistration
) {
return true;
diff --git a/src/layouts/vin-lookup/vin-lookup.spec.js b/src/layouts/vin-lookup/vin-lookup.spec.js
index 1d7d3f493..39aa0f008 100644
--- a/src/layouts/vin-lookup/vin-lookup.spec.js
+++ b/src/layouts/vin-lookup/vin-lookup.spec.js
@@ -22,6 +22,7 @@ jest.mock("@/store", () => ({
customer: {
emailAddress: "builddigitaltest@safelite.com",
},
+ referralNumber: "666666",
},
payment: {
insuranceCoverage: {
diff --git a/src/mixins/analytics-mixin.js b/src/mixins/analytics-mixin.js
index f49521b81..49ce3e29c 100644
--- a/src/mixins/analytics-mixin.js
+++ b/src/mixins/analytics-mixin.js
@@ -276,7 +276,8 @@ export default {
isDefined(order.payment.insuranceCoverage.isVerified) &&
order.payment.insuranceCoverage.isVerified &&
isDefined(order.policy.currentDeductible) &&
- order.policy.currentDeductible == 0
+ order.policy.currentDeductible > 0 &&
+ order.policy.currentDeductible != 9999
) {
payload.priceSubTotal = "";
} else if (isPricingAvailable) {
@@ -302,7 +303,8 @@ export default {
isDefined(order.payment.insuranceCoverage.isVerified) &&
order.payment.insuranceCoverage.isVerified &&
isDefined(order.policy.currentDeductible) &&
- order.policy.currentDeductible == 0
+ order.policy.currentDeductible > 0 &&
+ order.policy.currentDeductible != 9999
) {
payload.priceTotal = "";
} else if (isTaxAvailable) {
diff --git a/src/mixins/base-mixin.js b/src/mixins/base-mixin.js
index cf763fdff..ec49c3f0f 100644
--- a/src/mixins/base-mixin.js
+++ b/src/mixins/base-mixin.js
@@ -152,6 +152,15 @@ export default {
if (lineItems.promos) {
amountDue += this.getTotalPriceOfAllLineItemsAndChildParts(lineItems.promos, true);
}
+
+ if (
+ store.getters.payment.insuranceCoverage.isVerified &&
+ !store.getters.policy.isNoComp &&
+ !store.getters.policy.isItac
+ ) {
+ amountDue += store.getters.policy.currentDeductible;
+ }
+
return ((amountDue * 100) / 100).toFixed(2);
},
scrollToPageTop() {
diff --git a/src/mixins/base-mixin.spec.js b/src/mixins/base-mixin.spec.js
index 2ef76315e..1b0f919ba 100644
--- a/src/mixins/base-mixin.spec.js
+++ b/src/mixins/base-mixin.spec.js
@@ -120,6 +120,46 @@ describe("baseMixin.js", () => {
expect(mixIn.methods.dispatchStoreActionWithLogging).toBeCalled();
});
+
+ test("getAmountDue for verified deductible should be deductible plus any lineitems", () => {
+ const mixIn = getMixInInstance({});
+ const lineItems = {
+ glassParts: [],
+ supportingItems: [],
+ vaps: [
+ {
+ cartItemType: "FRONT WIPERS",
+ description: 'WIPER BLADE STANDARD 18"',
+ kitPrice: 0,
+ laborAmount: 0,
+ partNumber: "WB18",
+ partType: "FRONT WIPER",
+ salesTax: 2.0,
+ sellingPrice: 30.0,
+ },
+ {
+ cartItemType: "FRONT WIPERS",
+ description: 'WIPER BLADE STANDARD 26"',
+ kitPrice: 0,
+ laborAmount: 0,
+ partNumber: "WB26",
+ partType: "FRONT WIPER",
+ salesTax: 1.0,
+ sellingPrice: 20.0,
+ },
+ ],
+ promos: [],
+ };
+
+ store.getters = {
+ payment: { insuranceCoverage: { isVerified: true } },
+ policy: { isNoComp: false, isItac: false, currentDeductible: 250 },
+ };
+
+ var amtDue = mixIn.methods.getAmountDue(lineItems);
+
+ expect(amtDue).toEqual("303.00");
+ });
});
function getMixInInstance({ isDispatchSuccess = true }) {
diff --git a/src/router/index.js b/src/router/index.js
index 90ac5881b..2ce833135 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -116,6 +116,22 @@ const routes = [
}
}
+ // Reroute around pages that should not be available.
+
+ // Exception 1: Integrated Users should not see vehicle or quote pages.
+ if (store.getters.requiresVerifiedRedirecting) {
+ if (to.query.fmgPage === fmgPageValues.VEHICLE) {
+ to.query.fmgPage = fmgPageValues.VEHICLE_DAMAGE;
+ } else if (
+ to.query.fmgPage === fmgPageValues.QUOTE ||
+ to.query.fmgPage === fmgPageValues.INSURANCE_COMPANY
+ ) {
+ // Push to heritage if going to quote & integrated.
+ await navigateToHeritageFunnel({ shouldSaveSession: false });
+ return next(false);
+ }
+ }
+
await runExperiments(to.query.fmgPage);
// Process funnel cookie.
@@ -144,6 +160,7 @@ const routes = [
if (!isExistingFmgPageName(to.query.fmgPage)) {
console.log("Not an existing fmg page name:" + to.query.fmgPage);
GoToFunnelStartOn404(next);
+ return;
}
// Get route info for the given url. Names will have a 1:1 relationship with names in the Cms.
@@ -228,7 +245,7 @@ router.beforeEach(async (to, from, next) => {
// Refresh page if navigating to self to prevent locking.
// For now only carved out for vehicle; all modals are opened through anchor tags at the moment,
// which also self navigate, but relied on the page remaining the same on self-navigation.
- } else if (toQueryPage === fromQueryPage && toQueryPage === funnelStartPageName) {
+ } else if (toQueryPage === fromQueryPage && toQueryPage === getRedirectedStartPage()) {
router.go(0);
} else {
next();
@@ -477,7 +494,7 @@ async function DisplayPageError() {
// we use the pageError querystring as a counter to how many times a user has experienced an error and been routed here.
// once they receive more than 1 pageerrors, we'll reset their state to hopefully correct any issues they may be having.
var navPage = fmgPageValues.VEHICLE;
- if (store.getters.payment.insuranceCoverage.isVerified) {
+ if (store.getters.requiresVerifiedRedirecting) {
navPage = fmgPageValues.VEHICLE_DAMAGE;
}
@@ -542,4 +559,12 @@ async function runExperiments(nextPage) {
);
}
+function getRedirectedStartPage() {
+ if (store.getters.requiresVerifiedRedirecting) {
+ return fmgPageValues.VEHICLE_DAMAGE;
+ } else {
+ return funnelStartPageName;
+ }
+}
+
export default router;
diff --git a/src/store/index.js b/src/store/index.js
index 684aad2ce..aa1979e0a 100644
--- a/src/store/index.js
+++ b/src/store/index.js
@@ -33,7 +33,8 @@ import {
} from "@/helpers/promotions-helper";
import { getDateDifferenceInDays } from "@/helpers/date-helper";
import sharedMutations from "./vuex-shared-mutations/vuexSharedMutations";
-import { coverageStatusValue } from "@/constants/coverage-status";
+import { coverageStatus, coverageStatusValue } from "@/constants/insurance";
+
// Export State
const getDefaultState = () => {
return {
@@ -763,6 +764,21 @@ export const getters = {
.reduce((r, c) => Object.assign(r, c), {}) ?? {},
submittedOrder: (state) => JSON.parse(window.sessionStorage.getItem("submittedOrder")),
hasSubmittedOrder: (state) => window.sessionStorage.getItem("submittedOrder") !== null,
+ isVerifiedAndDeductibleZeroConfirmed: (state) => {
+ // used as a CMS variable on /payment-method, needed for FunnelSubHeaderWidget on cart pages
+ if (
+ (state.order.policy.currentDeductible === 0 ||
+ state.order.policy.currentDeductible > 0) &&
+ state.order.payment.insuranceCoverage.coverageStatus === coverageStatus.VERIFIED &&
+ !state.order.policy.isNoComp
+ ) {
+ return true;
+ }
+ return false;
+ },
+ requiresVerifiedRedirecting: (state) => {
+ return state.order?.referralNumber?.length === 6;
+ },
};
function getNonFalseValuesOfPropertyInArrayOfObjects(array, propertyName) {
@@ -1370,7 +1386,9 @@ export const actions = {
getMobileFeePart(context, { pageNameToLog }) {
const damageType = context.getters.damage.isRepair ? "Repair" : "Replace";
const parentAccountNumber = context.getters.payment.parentAccountNumber;
- const billToAccountNumber = context.getters.payment.billToAccountNumber;
+ const billToAccountNumber = context.getters.payment.billToAccountNumber
+ ? context.getters.payment.billToAccountNumber
+ : applicationConfig.CASH_DEFAULT_BILL_TO_ACCOUNT_NUMBER;
return globalMethods.callHttpClient({
method: endpoints.GetMobileFeePart.method,
@@ -2154,7 +2172,8 @@ export const actions = {
},
saveSupportingItems(context, supportingItems) {
- if (!deepEqual(supportingItems, context.state.order.lineItems.supportingItems)) {
+ syncLineItemIds(supportingItems, context.state.order.lineItems.supportingItems);
+ if (!supportingItemsEqual(supportingItems, context.state.order.lineItems.supportingItems)) {
context.dispatch(storeActions.RESET_SERVICE_LOCATION_STATE_AND_DEPENDENCIES);
}
addGuidToLineItemsIfNotAlreadyThere(supportingItems);
@@ -2247,7 +2266,7 @@ export const actions = {
// TODO: Insurance pricing...`ParentAccountNumber=${context.getters.order.payment.parentAccountNumber}`
let queryString =
- `ParentAccountNumber=${applicationConfig.CASH_PARENT_ACCOUNT_NUMBER}` +
+ `ParentAccountNumber=${context.getters.order.payment.parentAccountNumber}` +
`&CTU=${ctuToUse}` +
`&CarId=${vehicle.carId}` +
`&Make=${vehicle.make}` +
@@ -2311,7 +2330,7 @@ export const actions = {
let queryString = "";
if (appointmentType == "Mobile") {
queryString =
- `ParentAccountNumber=${applicationConfig.CASH_PARENT_ACCOUNT_NUMBER}` +
+ `ParentAccountNumber=${context.getters.order.payment.parentAccountNumber}` +
`&BillToAccountNumber=${billToAccountNumber}` +
`&ProviderNumber=${providerNumber}` +
`&AppointmentType=${appointmentType}` +
@@ -2321,7 +2340,7 @@ export const actions = {
`&${pricedLineItemsFormattedForRequest}`;
} else {
queryString =
- `ParentAccountNumber=${applicationConfig.CASH_PARENT_ACCOUNT_NUMBER}` +
+ `ParentAccountNumber=${context.getters.order.payment.parentAccountNumber}` +
`&BillToAccountNumber=${billToAccountNumber}` +
`&ProviderNumber=${providerNumber}` +
`&AppointmentType=${appointmentType}` +
@@ -2951,6 +2970,7 @@ function syncLineItemIds(lineItemsWithoutIds, lineItemsWithIds) {
}
});
if (matchedLineItemIndex > -1) {
+ // Remove the matched line item
clonedLineItemsWithIds.splice(matchedLineItemIndex, 1);
}
});
@@ -2967,6 +2987,29 @@ function providersEqual(providerA, providerB) {
//TODO: Change back to deepEqual once zipCodeCtu is added to saveSession.
}
+function supportingItemsEqual(supportingItemsA, supportingItemsB) {
+ if (typeof supportingItemsA !== typeof supportingItemsB) {
+ return false;
+ }
+ if (supportingItemsA === null || supportingItemsB === null) {
+ return supportingItemsA === supportingItemsB;
+ }
+ if (supportingItemsA.length != supportingItemsB.length) {
+ return false;
+ }
+ const sortedA = supportingItemsA.slice().sort();
+ const sortedB = supportingItemsB.slice().sort();
+ for (let i = 0; i < sortedA.length; i++) {
+ if (
+ sortedA[i].partNumber != sortedB[i].partNumber ||
+ sortedA[i].partType != sortedB[i].partType
+ ) {
+ return false;
+ }
+ }
+ return true;
+}
+
// This function will verify schedule info is still valid.
// check to see if we have an appointment date on the order object.
// if so, make sure it's not in the past. if in the past, clear schedule info in store.