diff --git a/src/constants/endpoints.js b/src/constants/endpoints.js
index c77b1bbad..bc5acba98 100644
--- a/src/constants/endpoints.js
+++ b/src/constants/endpoints.js
@@ -180,10 +180,6 @@ const endpoints = {
url: "/analytics/api/v1/analytics/log-part-questions",
method: "POST",
},
- LogDigitalConsumer: {
- url: "/analytics/api/v1/analytics/digitalconsumer-log",
- method: "POST",
- },
LogFmgSessionData: {
url: "/analytics/api/v1/analytics/digitalconsumer-session-logging",
method: "POST",
diff --git a/src/constants/experiments.js b/src/constants/experiments.js
index b9f38ca36..97e049df0 100644
--- a/src/constants/experiments.js
+++ b/src/constants/experiments.js
@@ -23,6 +23,7 @@ const experimentSettings = {
INSURANCE_TAB_TO_DISPLAY_THRESHOLD_INTERNAL: "NextGen_InternalInsuranceTabDisplayThreshold",
INSURANCE_TAB_TO_DISPLAY_THRESHOLD_EXTERNAL: "NextGen_ExternalInsuranceTabDisplayThreshold",
DISPLAY_MSR: "DisplayMSR",
+ ENABLE_MSR_SPLIT_PAY: "EnableMSRSplitPay",
DISPLAY_WAITLIST: "DisplayWaitlist2.0",
WAITLIST_THRESHOLD_DAYS: "Waitlist_Threshold_Days",
PRICING_BY_DAY: "DisplayPricingByDay",
diff --git a/src/constants/store-actions.js b/src/constants/store-actions.js
index 4f405eb0f..fff009619 100644
--- a/src/constants/store-actions.js
+++ b/src/constants/store-actions.js
@@ -64,7 +64,6 @@ const storeActions = {
LOG_CUSTOM_EVENT: "logCustomEvent",
INITIALIZE_SESSION: "initializeSession",
LOG_PART_QUESTIONS: "logPartQuestions",
- LOG_DIGITALCONSUMER: "logDigitalConsumer",
LOG_FMG_SESSION_DATA: "logFmgSessionData",
// DEPENDENCY MUTATIONS
@@ -115,6 +114,7 @@ const storeActions = {
SAVE_IS_RECAL_ACKNOWLEDGED_FOR_SCHEDULING: "saveIsRecalAcknowledgedForScheduling",
SAVE_IS_OEM_GLASS_SELECTED: "saveIsOemGlassSelected",
SAVE_IS_MSR_FEE_APPLICABLE: "saveIsMSRFeeApplicable",
+ SAVE_IS_MSR_FEE_COVERED_BY_INSURANCE: "saveIsMSRFeeCoveredByInsurance",
CREATE_SUBMITTED_STATE: "createSubmittedState",
RESET_SUBMITTED_STATE: "resetSubmittedState",
diff --git a/src/constants/store-mutations.js b/src/constants/store-mutations.js
index 567812702..78a9bfd39 100644
--- a/src/constants/store-mutations.js
+++ b/src/constants/store-mutations.js
@@ -72,6 +72,7 @@ const storeMutations = {
UPDATE_IS_RECAL_ACKNOWLEDGED_FOR_SCHEDULING: "updateIsRecalAcknowledgedForScheduling",
UPDATE_IS_OEM_GLASS_SELECTED: "updateIsOemGlassSelected",
UPDATE_IS_MSR_FEE_APPLICABLE: "updateIsMSRFeeApplicable",
+ UPDATE_IS_MSR_FEE_COVERED_BY_INSURANCE: "updateIsMSRFeeCoveredByInsurance",
UPDATE_CASH_PRICE_SUBTOTAL: "updateCashPriceSubTotal",
// EVENT BUS MUTATIONS
diff --git a/src/fmg-components/cart/cart.vue b/src/fmg-components/cart/cart.vue
index e890e53cc..f4626caa5 100644
--- a/src/fmg-components/cart/cart.vue
+++ b/src/fmg-components/cart/cart.vue
@@ -77,7 +77,7 @@
i % 2 == 0 ? 'even' : 'odd',
cartItem.isRemovable ? 'removable-cart-item' : '',
]">
- {{ cartItem.name }}
+ {{ cartItem.name }}
+
+ {{ msrFeeCartItem.name }}
+
+
+
+
+
+
@@ -162,6 +179,7 @@ import textLink from "@/ux-components/text-link/text-link";
import textBlock from "@/digital-components/text-block/text-block";
import contentGroupModal from "@/fmg-components/content-group-modal/content-group-modal";
import promoModalQuestion from "@/fmg-components/promo-modal-question/promo-modal-question";
+import removeMsrFeeModal from "./remove-msr-fee-modal/remove-msr-fee-modal.vue";
// Mixins
import baseMixin from "@/mixins/base-mixin.js";
@@ -183,6 +201,7 @@ import {
getSalesTax,
getAmountDueWithDonation,
} from "@/helpers/pricing-helper.js";
+import { formatToUSDollar } from "@/helpers/cms-content-helper";
// Constants
import { partTypeStrings } from "@/constants/part-type-strings";
@@ -191,6 +210,7 @@ import { cartItemTypes } from "@/constants/cart-item-types";
import { coverageStatus, cartItemTypesCoveredByInsurance } from "@/constants/insurance";
import { experimentSettings } from "@/constants/experiments";
import { quotePageDiscountTable } from "@/constants/quote-page-discounts";
+import { partNumberStrings } from "@/constants/part-number-strings";
export default {
name: "cart",
@@ -203,6 +223,7 @@ export default {
pageName: String,
allowItemRemoval: Boolean,
recyclingModalCmsWidgetName: String,
+ msrModalCmsWidgetName: String,
showAsPaid: Boolean,
isInsurance: Boolean,
insuranceDeductible: Number,
@@ -214,6 +235,7 @@ export default {
isExpandedOnLoad: Boolean,
isCollapsible: { type: Boolean, default: true },
isMSRFeeApplicable: Boolean,
+ IsMSRFeeCoveredByInsurance: Boolean,
donationCartItem: Object,
},
data() {
@@ -311,6 +333,10 @@ export default {
},
async removeItem(cartItemType, category) {
+ if (cartItemType == cartItemTypes.MOBILE_FEE && this.isMSRFeeApplicable) {
+ this.$refs.removeMsrFeeModal.openModal();
+ return false;
+ }
this.lineItems[category] = this.lineItems[category].filter(
(lineItemsToKeep) => lineItemsToKeep.cartItemType != cartItemType
);
@@ -375,6 +401,12 @@ export default {
}
return [];
},
+ shouldShowInfoIcon(cartItem) {
+ return cartItem == this.recycleFeeCartItem || cartItem == this.msrFeeCartItem;
+ },
+ switchToInshop() {
+ this.$emit("switchToInshop");
+ },
},
computed: {
isCartReadyToLoad() {
@@ -490,6 +522,10 @@ export default {
cartItems.push(this.mobileFeeCartItem);
}
+ if (this.msrFeeCartItem) {
+ cartItems.push(this.msrFeeCartItem);
+ }
+
if (this.quotePageDiscountCartItem) {
cartItems.push(this.quotePageDiscountCartItem);
}
@@ -892,7 +928,9 @@ export default {
let cartItem = null;
let showMobileFeeCartItem = false;
const mobileFeeLineItem = this.supportingItems.find(
- (lineItem) => lineItem.partType == partTypeStrings.MOBILE_FEE
+ (lineItem) =>
+ lineItem.partType == partTypeStrings.MOBILE_FEE &&
+ lineItem.partNumber == partTypeStrings.MOBILE_FEE
);
var mobileTotal =
@@ -929,6 +967,68 @@ export default {
}
return cartItem;
},
+ msrFeeCartItemName() {
+ return this.getCmsContent("MSRFeeTextWidget", "Text");
+ },
+ getMsrFeeLineItem() {
+ return this.supportingItems.find(
+ (lineItem) =>
+ lineItem.partType == partTypeStrings.MOBILE_FEE &&
+ lineItem.partNumber == partNumberStrings.MOBILE_STATIC_RECAL_FEE
+ );
+ },
+ msrFeeCartItem() {
+ let cartItem = null;
+ const msrFeeLineItem = this.getMsrFeeLineItem;
+ const shouldCreateMsrFeeCartItem =
+ this.isMSRFeeApplicable &&
+ this.isInsurance &&
+ !this.IsMSRFeeCoveredByInsurance &&
+ msrFeeLineItem &&
+ this.msrFeeAmount > 0;
+
+ if (shouldCreateMsrFeeCartItem) {
+ cartItem = {
+ name: this.msrFeeCartItemName,
+ category: cartItemCategories.SUPPORTING_ITEMS,
+ cartItemType: cartItemTypes.MOBILE_FEE,
+ isDisplayed: this.isInsurance,
+ isRemovable: true,
+ subTotal: 0,
+ salesTax: 0,
+ lineItems: [],
+ isCoveredByInsurance: this.IsMSRFeeCoveredByInsurance,
+ };
+ msrFeeLineItem.cartItemType = cartItem.cartItemType;
+ cartItem.lineItems.push(msrFeeLineItem);
+ cartItem.subTotal += this.msrFeeAmount;
+ cartItem.salesTax += msrFeeLineItem.salesTax ?? 0;
+ }
+ return cartItem;
+ },
+ msrFeeAmount() {
+ const msrFeeLineItem = this.getMsrFeeLineItem;
+ if (!msrFeeLineItem) {
+ return 0;
+ }
+ return (
+ msrFeeLineItem.laborAmount + msrFeeLineItem.sellingPrice + msrFeeLineItem.kitPrice
+ );
+ },
+ msrModalTextBlock() {
+ let cmsContentText = this.getCmsContent("MSRModal", "BodyText");
+ if (cmsContentText) {
+ cmsContentText = cmsContentText.replaceAll(
+ "{custom:mobileFee}",
+ formatToUSDollar(this.msrFeeAmount)
+ );
+ cmsContentText = cmsContentText.replaceAll(
+ "{custom:submittedOrder.policy.insuranceCompanyName}",
+ this.insuranceCompanyName
+ );
+ }
+ return cmsContentText;
+ },
quotePageDiscountCartItemName() {
return this.getCmsContent("ServicePackageDiscountTextWidget", "Text");
},
@@ -1189,6 +1289,7 @@ export default {
textLink,
contentGroupModal,
promoModalQuestion,
+ removeMsrFeeModal,
},
};
@@ -1289,6 +1390,10 @@ export default {
order: 3;
margin-right: 100%;
text-decoration: none;
+
+ msr-fee-cartItem {
+ margin: 0 0 0 0.2rem;
+ }
}
}
.package-type,
diff --git a/src/fmg-components/cart/remove-msr-fee-modal/remove-msr-fee-modal.vue b/src/fmg-components/cart/remove-msr-fee-modal/remove-msr-fee-modal.vue
new file mode 100644
index 000000000..6c2cd1fb6
--- /dev/null
+++ b/src/fmg-components/cart/remove-msr-fee-modal/remove-msr-fee-modal.vue
@@ -0,0 +1,153 @@
+
+
+
+
+
+ {{ modalSubHeaderText }}
+
+
+
+
+
+
+
+
+
+
diff --git a/src/fmg-components/content-group-modal/content-group-modal.vue b/src/fmg-components/content-group-modal/content-group-modal.vue
index 25c50b2df..e4a5241c4 100644
--- a/src/fmg-components/content-group-modal/content-group-modal.vue
+++ b/src/fmg-components/content-group-modal/content-group-modal.vue
@@ -26,6 +26,7 @@ export default {
name: "content-group-modal",
props: {
cmsWidgetName: String,
+ customBodyText: String,
footerButtonActionName: {
type: String,
default: null,
@@ -43,6 +44,9 @@ export default {
return this.getCmsContent(this.cmsWidgetName, "SubheaderText");
},
ModalBodyText() {
+ if (this.customBodyText) {
+ return this.customBodyText;
+ }
return this.getCmsContent(this.cmsWidgetName, "BodyText");
},
ModalSubBodyText() {
diff --git a/src/global-methods.js b/src/global-methods.js
index 4f1dc601b..f408230f8 100644
--- a/src/global-methods.js
+++ b/src/global-methods.js
@@ -102,7 +102,6 @@ export default {
},
(error) => {
if (
- endpoint.toLowerCase().includes(endpoints.LogDigitalConsumer.url) ||
endpoint.toLowerCase().includes(endpoints.LogFmgSessionData.url) ||
endpoint.toLowerCase().includes(endpoints.LogPageView.url) ||
endpoint.toLowerCase().includes(endpoints.LogCustomEvent.url) ||
diff --git a/src/helpers/pricing-helper.js b/src/helpers/pricing-helper.js
index 68de04515..9564b5c1f 100644
--- a/src/helpers/pricing-helper.js
+++ b/src/helpers/pricing-helper.js
@@ -2,6 +2,7 @@ import store from "@/store";
import { storeActions } from "@/constants/store-actions";
import baseMixin from "@/mixins/base-mixin.js";
import { deepClone } from "@/helpers/object-helper";
+import { partNumberStrings } from "@/constants/part-number-strings";
export function getDisplayAmountDue(lineItemsObject, includeTax = true) {
return getAmountDue(lineItemsObject, includeTax).toLocaleString("en-US", {
@@ -32,6 +33,10 @@ export function getAmountDue(lineItemsObject, includeTax = true) {
if (store.getters.coverageIsVerified && !order.policy.isNoComp && !order.policy.isItac) {
amountDue = order.policy.currentDeductible;
+
+ if (order.isMSRFeeApplicable && !order.isMSRFeeCoveredByInsurance) {
+ amountDue += getMSRFeePartPrice(lineItemsObject?.supportingItems, includeTax);
+ }
}
if (lineItemsObject?.vaps) {
@@ -100,6 +105,20 @@ export async function getPricingByDayPartWithPrice(pageNameToLog) {
return pricingResults[0];
}
+export function getMSRFeePartPrice(supportingItems, includeTax) {
+ let msrFeePrice = 0;
+ const msrFeeLineItem = supportingItems?.find(
+ (lineItem) => lineItem.partNumber === partNumberStrings.MOBILE_STATIC_RECAL_FEE
+ );
+ if (msrFeeLineItem) {
+ msrFeePrice = baseMixin?.methods?.getTotalPriceOfAllLineItemsAndChildParts(
+ [msrFeeLineItem],
+ includeTax
+ );
+ }
+ return msrFeePrice;
+}
+
export function addPricesToLineItems(lineItems, pricingLineItems) {
lineItems.forEach((lineItem) => {
const lineItemIndex = pricingLineItems.findIndex(
diff --git a/src/layouts/confirmation/confirmation.vue b/src/layouts/confirmation/confirmation.vue
index fa0e53425..e26c5f9b1 100644
--- a/src/layouts/confirmation/confirmation.vue
+++ b/src/layouts/confirmation/confirmation.vue
@@ -62,6 +62,7 @@
:showAsPaid="isPia"
servicePackageOptionsCmsName="ServicePackageTitle"
recyclingModalCmsWidgetName="RecycleModal"
+ msrModalCmsWidgetName="MSRModal"
:isInsurance="isInsurance"
:insuranceDeductible="currentDeductible"
:insuranceCompanyName="insuranceCompanyName"
@@ -70,7 +71,8 @@
:isItac="isItac"
:isNoComp="isNoComp"
:isExpandedOnLoad="false"
- :isMSRFeeApplicable="isMSRFeeApplicable" />
+ :isMSRFeeApplicable="isMSRFeeApplicable"
+ :IsMSRFeeCoveredByInsurance="isMSRFeeCoveredByInsurance" />
@@ -419,6 +421,9 @@ export default {
isMSRFeeApplicable() {
return this.submittedOrder?.isMSRFeeApplicable;
},
+ isMSRFeeCoveredByInsurance() {
+ return this.submittedOrder?.isMSRFeeCoveredByInsurance;
+ },
isInsurance() {
return this.submittedOrder?.payment?.isInsurance;
},
diff --git a/src/layouts/estimate/estimate.vue b/src/layouts/estimate/estimate.vue
index 60d050d73..36e27127a 100644
--- a/src/layouts/estimate/estimate.vue
+++ b/src/layouts/estimate/estimate.vue
@@ -62,6 +62,7 @@ import baseMixin from "@/mixins/base-mixin.js";
import { queryStrings } from "@/constants/query-strings";
import { nextTick } from "vue";
import { peekQueryFromStash } from "@/router/methods/helpers/querystring-stash";
+import { showFmgLoadingModal } from "@/helpers/loading-modal-helper";
// Define Validation Rules
defineRule("zip-required", required(errorMessages.SERVICE_ZIP_REQUIRED));
@@ -169,7 +170,7 @@ export default {
baseMixin.methods.ResetExternalParamsAndHideModal();
}
} else {
- baseMixin.methods.ResetExternalParamsAndHideModal();
+ showFmgLoadingModal(false);
}
} else {
baseMixin.methods.ResetExternalParamsAndHideModal();
diff --git a/src/layouts/payment-adyen/payment-adyen.vue b/src/layouts/payment-adyen/payment-adyen.vue
index 4a4936a7f..bcb827623 100644
--- a/src/layouts/payment-adyen/payment-adyen.vue
+++ b/src/layouts/payment-adyen/payment-adyen.vue
@@ -29,10 +29,12 @@
v-model="lineItems"
servicePackageOptionsCmsName="ServicePackageTitle"
recyclingModalCmsWidgetName="RecycleModal"
+ msrModalCmsWidgetName="MSRModal"
:isInsurance="isInsurance"
:insuranceDeductible="currentDeductible"
:insuranceCompanyName="insuranceCompanyName"
:showInsuranceCoverageAs="showInsuranceCoverageAs"
+ :isMSRFeeApplicable="isMSRFeeApplicable"
:isItac="isItac"
:isNoComp="isNoComp"
:isCollapsible="false" />
@@ -568,6 +570,9 @@ export default {
insuranceCompanyName() {
return this.$store.getters.policy.insuranceCompanyName;
},
+ isMSRFeeApplicable() {
+ return this.$store.getters.order.isMSRFeeApplicable;
+ },
lineItems() {
return deepClone(this.$store.getters.lineItems);
},
diff --git a/src/layouts/payment-method/payment-method.vue b/src/layouts/payment-method/payment-method.vue
index 48f076f84..e5b08bdbc 100644
--- a/src/layouts/payment-method/payment-method.vue
+++ b/src/layouts/payment-method/payment-method.vue
@@ -26,6 +26,7 @@
pageName="payment-method"
servicePackageOptionsCmsName="ServicePackageTitle"
recyclingModalCmsWidgetName="RecycleModal"
+ msrModalCmsWidgetName="MSRModal"
:isInsurance="isInsurance"
:insuranceDeductible="currentDeductible"
:insuranceCompanyName="insuranceCompanyName"
@@ -35,7 +36,9 @@
:isNoComp="isNoComp"
:isExpandedOnLoad="false"
:isMSRFeeApplicable="isMSRFeeApplicable"
- @itemRemoved="evaluatePromosAndTaxItemsOnOrder" />
+ :IsMSRFeeCoveredByInsurance="isMSRFeeCoveredByInsurance"
+ @itemRemoved="evaluatePromosAndTaxItemsOnOrder"
+ @switchToInshop="navigateToSchedulePage" />
@@ -410,6 +412,9 @@ export default {
insuranceCompanyName() {
return this.$store.getters.policy.insuranceCompanyName;
},
+ isMSRFeeApplicable() {
+ return this.$store.getters.order.isMSRFeeApplicable;
+ },
isPaypal() {
if (this.paymentType == "pp") {
return true;
diff --git a/src/layouts/quote/quote.vue b/src/layouts/quote/quote.vue
index b428ab905..106c04bfa 100644
--- a/src/layouts/quote/quote.vue
+++ b/src/layouts/quote/quote.vue
@@ -590,12 +590,6 @@ export default {
}
// there are no active or inactive external parameters; use internal threshold
if (internalThreshold) thresholdToUse = internalThreshold;
-
- vm.isInsuranceSelected = getIsInsuranceSelectedValue(
- vm.availableLineItems,
- thresholdToUse
- );
- baseMixin.methods.ResetExternalParamsAndHideModal();
} else {
// user came from an external source, however, the externalParms may have been reset on service-zip, property-questions, etc...
if (getBoolFromString(store.getters.externalParameterQuote?.isInsurance)) {
@@ -613,8 +607,6 @@ export default {
) {
await vm.skip(insuranceSelection, servicePackage);
}
-
- baseMixin.methods.ResetExternalParamsAndHideModal();
} else {
if (externalThreshold) thresholdToUse = externalThreshold;
@@ -622,15 +614,17 @@ export default {
{
debugLog("quote.vue tab select NOT EXTERNAL");
}
-
- vm.isInsuranceSelected = getIsInsuranceSelectedValue(
- vm.availableLineItems,
- thresholdToUse
- );
- baseMixin.methods.ResetExternalParamsAndHideModal();
}
}
+ if (vm.isInsuranceSelected == null) {
+ vm.isInsuranceSelected = getIsInsuranceSelectedValue(
+ vm.availableLineItems,
+ thresholdToUse
+ );
+ }
+ baseMixin.methods.ResetExternalParamsAndHideModal();
+
if (vm.skipToInsurance && !vm.showSaveProgressPopup) {
// skip ahead only if no email popup.
await vm.skip(true, externalParamPackageLabels.GLASS_ONLY);
diff --git a/src/layouts/schedule/schedule.vue b/src/layouts/schedule/schedule.vue
index ec8051cc4..8068ac6c1 100644
--- a/src/layouts/schedule/schedule.vue
+++ b/src/layouts/schedule/schedule.vue
@@ -704,8 +704,11 @@ export default {
},
isMobileStaticRecalibrationApplicable() {
return (
- this.displayMSR &&
- this.mobileFeePart?.partNumber == partNumberStrings.MOBILE_STATIC_RECAL_FEE
+ (this.displayMSR &&
+ this.mobileFeePart?.partNumber == partNumberStrings.MOBILE_STATIC_RECAL_FEE &&
+ this.enableMSRSplitPay) ||
+ this.isCashItacNoComp ||
+ this.mobileFeePart?.isInsurable
);
},
displayMSR() {
@@ -715,6 +718,13 @@ export default {
?.toLowerCase() === "true"
);
},
+ enableMSRSplitPay() {
+ return (
+ experimentMixin.methods
+ .getSettingValue(experimentSettings.ENABLE_MSR_SPLIT_PAY)
+ ?.toLowerCase() === "true"
+ );
+ },
isMSRFeeNotCoveredByInsurance() {
return (
this.isMobileSelected &&
@@ -1173,6 +1183,13 @@ export default {
isMSRFeeApplicable
);
},
+ updateAndSaveIsMSRFeeCoveredByInsurance() {
+ const isMSRFeeCoveredByInsurance = this.mobileFeePart?.isInsurable;
+ this.dispatchStoreAction(
+ this.storeActions.SAVE_IS_MSR_FEE_COVERED_BY_INSURANCE,
+ isMSRFeeCoveredByInsurance
+ );
+ },
updateAndSaveSupportingItems() {
let supportingItems = store.getters.lineItems.supportingItems;
let shouldSaveSupportingItems = false;
@@ -1528,6 +1545,7 @@ export default {
this.updateAndSaveSupportingItems();
this.updateAndSaveIsMSRFeeApplicable();
+ this.updateAndSaveIsMSRFeeCoveredByInsurance();
this.updateSupportingItems();
diff --git a/src/layouts/service-zip/service-zip.vue b/src/layouts/service-zip/service-zip.vue
index ab99adc6f..c82a0a0e3 100644
--- a/src/layouts/service-zip/service-zip.vue
+++ b/src/layouts/service-zip/service-zip.vue
@@ -80,6 +80,7 @@ import { saveSession } from "@/helpers/heritage-integration/order-helper.js";
import baseMixin from "@/mixins/base-mixin.js";
import { queryStrings } from "@/constants/query-strings";
import { routeData } from "@/router/constants/routes";
+import { showFmgLoadingModal } from "@/helpers/loading-modal-helper";
// Define Validation Rules
defineRule("zip-required", required(errorMessages.SERVICE_ZIP_REQUIRED));
@@ -137,6 +138,13 @@ export default {
},
false
);
+ vm.serviceZipCode = store.getters.externalParameterServiceZip.zipCode;
+ const isValid = await baseMixin.methods.isFormValid(vm.$refs.theForm);
+ if (isValid) {
+ showFmgLoadingModal(true);
+ vm.forwardButtonAction();
+ return;
+ }
}
if (store.getters.externalParameterCustomer?.phoneNumber) {
diff --git a/src/layouts/vehicle-damage/vehicle-damage.vue b/src/layouts/vehicle-damage/vehicle-damage.vue
index 5e128e867..abad0da7d 100644
--- a/src/layouts/vehicle-damage/vehicle-damage.vue
+++ b/src/layouts/vehicle-damage/vehicle-damage.vue
@@ -93,6 +93,7 @@ import { errorMessages } from "@/constants/error-messages";
import { damageLocationsCms } from "@/constants/damage-locations-cms.js";
import { damageLocationsSelected } from "@/constants/damage-locations-selected.js";
import { getFunnelCookie } from "@/helpers/heritage-integration/cookie-helper";
+import { showFmgLoadingModal } from "@/helpers/loading-modal-helper";
import { debugLog } from "@/helpers/debug-log-helper";
import store from "@/store";
@@ -199,7 +200,7 @@ export default {
return vm.forwardButtonAction();
}
}
- baseMixin.methods.ResetExternalParamsAndHideModal();
+ showFmgLoadingModal(false);
//clear any validation errors for external parameter flow
const form = vm.$refs.theForm;
@@ -209,7 +210,7 @@ export default {
}
}
} else {
- baseMixin.methods.ResetExternalParamsAndHideModal();
+ showFmgLoadingModal(false);
}
});
},
diff --git a/src/layouts/vehicle/vehicle.spec.js b/src/layouts/vehicle/vehicle.spec.js
index d4bc1f726..ba1c4c621 100644
--- a/src/layouts/vehicle/vehicle.spec.js
+++ b/src/layouts/vehicle/vehicle.spec.js
@@ -93,8 +93,11 @@ describe("vehicle.vue", () => {
});
describe("vehicle.vue", () => {
- test("should call forwardButtonAction if isExternalParameter is true and form is valid", async () => {
+ test("should call forwardButtonAction if isExternalParameter is true, has a year, make and model, and form is valid", async () => {
store.getters.externalParameterState.isExternalParameter = true;
+ store.getters.externalParameterVehicle.year = "1886";
+ store.getters.externalParameterVehicle.make = "Benz";
+ store.getters.externalParameterVehicle.model = "Patent-Motorwagen";
// Create a shallow mount of MyComponent
const { wrapper } = setupMocks();
// Set displayNoServiceAlert to false
diff --git a/src/layouts/vehicle/vehicle.vue b/src/layouts/vehicle/vehicle.vue
index 4521a6e2f..ac4a54f62 100644
--- a/src/layouts/vehicle/vehicle.vue
+++ b/src/layouts/vehicle/vehicle.vue
@@ -109,6 +109,7 @@ 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";
+import { showFmgLoadingModal } from "@/helpers/loading-modal-helper";
import { debugLog } from "@/helpers/debug-log-helper";
//define validation rules
@@ -252,17 +253,17 @@ export default {
const matchingMake = resultMap.makeQuestionInitialData?.filter(
(item) =>
item.toLowerCase() ===
- store.getters.externalParameterVehicle.make.toLowerCase()
+ store.getters.externalParameterVehicle.make?.toLowerCase()
);
const matchingModel = resultMap.modelQuestionInitialData?.filter(
(item) =>
item.toLowerCase() ===
- store.getters.externalParameterVehicle.model.toLowerCase()
+ store.getters.externalParameterVehicle.model?.toLowerCase()
);
const matchingStyle = resultMap.styleQuestionInitialData?.filter(
(item) =>
item.toLowerCase() ===
- store.getters.externalParameterVehicle.style.toLowerCase()
+ store.getters.externalParameterVehicle.style?.toLowerCase()
);
baseMixin.methods.dispatchStoreAction(
storeActions.UPDATE_EXTERNAL_PARAMETER_MMS,
@@ -291,7 +292,12 @@ export default {
resultMap.modelQuestionInitialData,
resultMap.styleQuestionInitialData
);
- if (store.getters.externalParameterState?.isExternalParameter) {
+ if (
+ store.getters.externalParameterState?.isExternalParameter &&
+ store.getters.externalParameterVehicle.year &&
+ store.getters.externalParameterVehicle.make &&
+ store.getters.externalParameterVehicle.model
+ ) {
await vm.getVehicleDetails();
if (!vm.displayNoServiceAlert) {
const isValid = await baseMixin.methods.isFormValid(vm.$refs.theForm);
@@ -304,7 +310,7 @@ export default {
baseMixin.methods.ResetExternalParamsAndHideModal();
}
} else {
- baseMixin.methods.ResetExternalParamsAndHideModal();
+ showFmgLoadingModal(false);
}
});
},
diff --git a/src/mixins/analytics-mixin.js b/src/mixins/analytics-mixin.js
index 781c0cb34..3ab575f58 100644
--- a/src/mixins/analytics-mixin.js
+++ b/src/mixins/analytics-mixin.js
@@ -132,51 +132,6 @@ export default {
}
},
- async logDigitalConsumer() {
- const currentPageName = getPageNameFromRouter();
- const universes = store.getters.applicationUser.experiments;
-
- const variationNames = universes
- .filter((item) => item.universeName === experimentUniverses.CONCEPT_FUNNEL)
- .map((item) => item.variationName)
- .filter(Boolean); // removes undefined/null
-
- const conceptVariation = variationNames.length > 0 ? variationNames[0] : "";
-
- const isConceptExposed = universes.find(
- (item) => item.universeName === experimentUniverses.CONCEPT_FUNNEL
- )?.isExposed;
-
- const submittedOrder = baseMixin.methods.getSubmittedOrder();
- const hasSubmittedOrder = baseMixin.methods.hasSubmittedOrder();
- const hasSubmittedOrderAtConfirmationPage =
- hasSubmittedOrder && currentPageName?.toLowerCase() == routeData.CONFIRMATION.name;
-
- var payload = {
- actionName: `Browser page:${currentPageName}`,
- referralSequenceNumber: hasSubmittedOrderAtConfirmationPage
- ? submittedOrder.referralSequenceNumber
- : store.getters.order.referralSequenceNumber,
- referralNumber: hasSubmittedOrderAtConfirmationPage
- ? submittedOrder.referralNumber
- : store.getters.order.referralNumber,
- workOrderId: hasSubmittedOrderAtConfirmationPage
- ? submittedOrder.workOrderId
- : store.getters.order.workOrderId,
- workOrderNumber: hasSubmittedOrderAtConfirmationPage
- ? submittedOrder.workOrderNumber
- : store.getters.order.workOrderNumber,
- conceptVariation: conceptVariation,
- isConceptExposed: isConceptExposed,
- };
-
- await baseMixin.methods.dispatchStoreAction(
- storeActions.LOG_DIGITALCONSUMER,
- payload,
- false
- );
- },
-
async pushEventForChatsToGA(category, action, label, pushToLogApp = false) {
const currentPageName = getPageNameFromRouter();
const value = `2.0_${currentPageName}`;
@@ -206,6 +161,11 @@ export default {
// S3 bucket, safelite-dev-digitalconsumer-session-data-us-east-2/1.
// This bucket data is then picked up by snowflake for analytics use.
async pushFmgSessionData() {
+ var currentPageName = getPageNameFromRouter(true);
+ if (!currentPageName) {
+ return;
+ }
+
const hasSubmittedOrder = baseMixin.methods.hasSubmittedOrder();
const submittedOrder = baseMixin.methods.getSubmittedOrder();
const order = hasSubmittedOrder ? submittedOrder : store.getters.order;
@@ -247,22 +207,6 @@ export default {
}
var appointment = `${order?.schedule?.date ?? ""} ${order?.schedule?.startTime ?? ""}`;
- var currentPageName = getPageNameFromRouter();
-
- // add query strings to the page name for debugging. on the vehicle page, if from an external link, pull it from the stash
- if (currentPageName === "vehicle") {
- if (!window.location.search) {
- if (store.getters.externalParameterState?.qsStash) {
- currentPageName += `${store.getters.externalParameterState.qsStash}`;
- }
- } else {
- currentPageName += `${window.location.search}`;
- }
- } else {
- if (window.location.search) {
- currentPageName += `${window.location.search}`;
- }
- }
var sessionData = {};
sessionData.currentPage = currentPageName;
@@ -911,6 +855,9 @@ export default {
setSessionIdIfUnset(response.data.sessionId);
}
}
+
+ // logging on session init so we capture complete query string data
+ await this.pushFmgSessionData();
},
noSession() {
@@ -977,7 +924,7 @@ function pushToDataLayerIfDefined(data) {
}
}
-function getPageNameFromRouter() {
+function getPageNameFromRouter(useDefaultUrl = false) {
if (
router &&
router.currentRoute &&
@@ -987,7 +934,9 @@ function getPageNameFromRouter() {
return router.currentRoute.value.name;
}
- return window.location.href.replace(/\/$/, "").split("/").pop();
+ return useDefaultUrl
+ ? window.location.search
+ : window.location.href.replace(/\/$/, "").split("/").pop();
}
function getValueToLog(value, valueToLogType) {
diff --git a/src/router/constants/navigation-scenarios.js b/src/router/constants/navigation-scenarios.js
index 0d0ee836f..21bcc46f3 100644
--- a/src/router/constants/navigation-scenarios.js
+++ b/src/router/constants/navigation-scenarios.js
@@ -64,6 +64,7 @@ const navigationScenarios = {
CLICKED_PAY_NOW: "CLICKED_PAY_NOW",
CLICKED_PAY_NOW_ADYEN: "CLICKED_PAY_NOW_ADYEN",
CLICKED_PAY_LATER: "CLICKED_PAY_LATER",
+ CLICKED_SWITCH_TO_INSHOP: "CLICKED_SWITCH_TO_INSHOP",
PIA_ERROR: "PIA_ERROR",
PIA_CC_ERROR: "PIA_CC_ERROR",
PIA_APPLE_ERROR: "PIA_APPLE_ERROR",
diff --git a/src/router/constants/routing-table.js b/src/router/constants/routing-table.js
index 2d2f49a25..a7be5f387 100644
--- a/src/router/constants/routing-table.js
+++ b/src/router/constants/routing-table.js
@@ -553,6 +553,10 @@ const routingTable = function () {
scenario: navigationScenarios.CLICKED_INSURANCE,
destinationPageData: routeData.INSURANCE_COMPANY,
},
+ {
+ scenario: navigationScenarios.CLICKED_SWITCH_TO_INSHOP,
+ destinationPageData: routeData.SCHEDULE,
+ },
],
},
{
diff --git a/src/router/methods/after-each.js b/src/router/methods/after-each.js
index 608119399..43ed0d4b5 100644
--- a/src/router/methods/after-each.js
+++ b/src/router/methods/after-each.js
@@ -5,9 +5,6 @@ import { storeMutations } from "@/constants/store-mutations";
export async function afterEach(to, from) {
store.commit(storeMutations.UPDATE_LAST_PAGE_VISITED, to.name);
- // digital consumer logging
- analyticsMixin.methods.logDigitalConsumer();
-
// digital consumer fmg session logging to snowflake
analyticsMixin.methods.pushFmgSessionData();
diff --git a/src/router/methods/helpers/initialize-from-querystrings.js b/src/router/methods/helpers/initialize-from-querystrings.js
index 24f137a8f..4d342cdc0 100644
--- a/src/router/methods/helpers/initialize-from-querystrings.js
+++ b/src/router/methods/helpers/initialize-from-querystrings.js
@@ -105,6 +105,7 @@ function updateExternalParameterState() {
}
if (externalParameterZipCode) {
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_ZIP_CODE, externalParameterZipCode);
+ store.commit(storeMutations.UPDATE_IS_EXTERNAL_PARAMETER, externalParameterStatus.ACTIVE);
}
if (externalParameterEmail) {
store.commit(
diff --git a/src/router/methods/route-logic/error.js b/src/router/methods/route-logic/error.js
index fb9dd2cbc..162e5b914 100644
--- a/src/router/methods/route-logic/error.js
+++ b/src/router/methods/route-logic/error.js
@@ -19,7 +19,6 @@ export async function errorBeforeEnter(to, from) {
nextPage: to?.name,
};
- analyticsMixin.methods.logDigitalConsumer();
await handleHardError(errorPayload);
return;
}
@@ -33,7 +32,6 @@ export async function errorBeforeEnter(to, from) {
nextPage: to?.name,
};
- analyticsMixin.methods.logDigitalConsumer();
await handleHardError(errorPayload);
return;
} else {
diff --git a/src/store/index.js b/src/store/index.js
index 23b8cf2a3..615313f96 100644
--- a/src/store/index.js
+++ b/src/store/index.js
@@ -192,6 +192,7 @@ const getDefaultState = () => {
isRecalAckOptIn: false,
isRecalAcknowledgedForScheduling: "",
isMSRFeeApplicable: false,
+ isMSRFeeCoveredByInsurance: false,
},
applicationUser: {
eventBus: [],
@@ -359,6 +360,9 @@ export const mutations = {
updateIsMSRFeeApplicable(state, isMSRFeeApplicable) {
state.order.isMSRFeeApplicable = isMSRFeeApplicable;
},
+ updateIsMSRFeeCoveredByInsurance(state, isMSRFeeCoveredByInsurance) {
+ state.order.isMSRFeeCoveredByInsurance = isMSRFeeCoveredByInsurance;
+ },
updateCashPriceSubTotal(state, cashPriceSubTotal) {
state.order.cashPriceSubTotal =
cashPriceSubTotal === "" ? null : cashPriceSubTotal.toString();
@@ -1630,38 +1634,6 @@ export const actions = {
});
},
- logDigitalConsumer(
- context,
- {
- actionName,
- referralSequenceNumber,
- referralNumber,
- workOrderId,
- workOrderNumber,
- conceptVariation,
- isConceptExposed,
- }
- ) {
- var payload = {
- sessionId: getSessionIdValue(),
- deviceId: getDeviceIdValue(),
- actionName: actionName ?? "",
- referralSequenceNumber: referralSequenceNumber ?? "",
- referralNumber: referralNumber ?? "",
- applicationName: baseMixin.methods.isMobileDevice() ? "2.0 Mobile" : "2.0",
- workOrderId: workOrderId ?? "",
- workOrderNumber: workOrderNumber ?? "",
- conceptVariation: conceptVariation,
- isConceptExposed: isConceptExposed,
- };
-
- return globalMethods.callHttpClient({
- method: endpoints.LogDigitalConsumer.method,
- endpoint: endpoints.LogDigitalConsumer.url,
- payload: payload,
- });
- },
-
logFmgSessionData(
context,
{
@@ -1770,6 +1742,7 @@ export const actions = {
method: endpoints.LogFmgSessionData.method,
endpoint: endpoints.LogFmgSessionData.url,
payload: payload,
+ logApiCall: false,
});
},
@@ -2077,52 +2050,27 @@ export const actions = {
},
getServiceabilityDetails(context, { payload: { serviceZipCode }, pageNameToLog }) {
- const escapeRecalibrationType = (rt) => rt.split("&").join("%26");
-
- const partialLineItemsObjects = context.getters.order.lineItems.glassParts?.map(
- (lineItem) => ({
- partNumber: lineItem.partNumber,
- recalibrationType:
- lineItem.recalibrationType && isRecalPartOrHasChildRecalPart(lineItem)
- ? escapeRecalibrationType(lineItem.recalibrationType)
- : undefined,
- })
+ const flattenedLineItemsWithChildParts = getFlattenedArrayOfLineItemsWithChildParts(
+ context.getters.order.lineItems.glassParts
);
- var lineItems = null;
- if (partialLineItemsObjects) {
- lineItems = buildQueryStringParameterFromArrayOfComplexObjects(
- partialLineItemsObjects,
- "lineItems"
- );
- }
+ const lineItemsList = flattenedLineItemsWithChildParts
+ .map((item) => item.partNumber)
+ .join(",");
const vehicle = context.getters.vehicle;
const carId = vehicle.carId;
const damage = context.getters.damage;
- const glassArray = convertGlassPieceNamingForApi(damage.glassToReplace);
-
- const glassPieces = buildQueryStringParameterFromArrayOfComplexObjects(
- glassArray,
- "glassPieces"
- );
const parentAccountNumber =
context.getters.order.payment.parentAccountNumber ??
applicationConfig.CASH_PARENT_ACCOUNT_NUMBER;
- const referralSequenceNumber = context.getters.order.referralSequenceNumber;
- var endPoint = `${endpoints.GetServiceabilityDetails.url}?zip=${serviceZipCode}&carId=${carId}&parentAccountNumber=${parentAccountNumber}&referralSequenceNumber=${referralSequenceNumber}&applicationName=${applicationConfig.ANALYTICS_APPLICATION_NAME}`;
- if (lineItems) {
- endPoint += `&${lineItems}`;
+ var endPoint = `${endpoints.GetServiceabilityDetails.url}?zip=${serviceZipCode}&carId=${carId}&parentAccountNumber=${parentAccountNumber}&isRepair=${damage.isRepair}`;
+ if (lineItemsList) {
+ endPoint += `&lineItems=${lineItemsList}`;
}
- if (glassPieces) {
- endPoint += `&${glassPieces}`;
- }
-
- endPoint += `&isHeavyTruckVehicle=${context.getters.order.vehicle.isBigTruck}`;
-
return globalMethods.callHttpClient({
method: endpoints.GetServiceabilityDetails.method,
endpoint: endPoint,
@@ -2630,6 +2578,7 @@ export const actions = {
lockToken: order.lockToken,
isRecalAckOptIn: order.isRecalAckOptIn,
isMSRFeeApplicable: order.isMSRFeeApplicable,
+ isMSRFeeCoveredByInsurance: order.isMSRFeeCoveredByInsurance,
cashPriceSubTotal: order.cashPriceSubTotal,
},
},
@@ -3062,6 +3011,13 @@ export const actions = {
context.commit(storeMutations.UPDATE_IS_MSR_FEE_APPLICABLE, isMSRFeeApplicable);
},
+ saveIsMSRFeeCoveredByInsurance(context, isMSRFeeCoveredByInsurance) {
+ context.commit(
+ storeMutations.UPDATE_IS_MSR_FEE_COVERED_BY_INSURANCE,
+ isMSRFeeCoveredByInsurance
+ );
+ },
+
saveParentAccountNumber(context, parentAccountNumber) {
context.commit(storeMutations.UPDATE_PARENT_ACCT_NUMBER, parentAccountNumber);
},