Merge pull request #1343 from Safelite/rlsmerge/2023.09.14-to-develop

Release merge 09.14 to develop
This commit is contained in:
scottkiener 2023-09-14 16:17:15 -04:00 committed by GitHub
commit 75c01cc445
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 146 additions and 79 deletions

View file

@ -2,6 +2,7 @@ const queryStrings = {
FMG_PAGE: "fmgPage", FMG_PAGE: "fmgPage",
START_TYPE: "start_type", START_TYPE: "start_type",
ZIP_CODE: "zipcode", ZIP_CODE: "zipcode",
PROMO: "promo",
}; };
export { queryStrings }; export { queryStrings };

View file

@ -0,0 +1,10 @@
export function getDateDifferenceInDays(startDate, endDate) {
var date1 = new Date(endDate);
date1.setHours(0, 0, 0, 0);
var date2 = new Date(startDate);
date2.setHours(0, 0, 0, 0);
// To calculate the time difference of two dates
var Difference_In_Time = date1.getTime() - date2.getTime();
// To calculate the no. of days between two dates
return Difference_In_Time / (1000 * 3600 * 24);
}

View file

@ -1,4 +1,5 @@
import { queryStrings } from "@/constants/query-strings"; import { queryStrings } from "@/constants/query-strings";
import { getQuerystringParameter } from "@/helpers/querystring-helper";
import { externalUrls } from "@/router/router-constants/externalUrl-values"; import { externalUrls } from "@/router/router-constants/externalUrl-values";
import { lazyLoadComponent } from "@/router/dynamic-routing/component-loader.js"; import { lazyLoadComponent } from "@/router/dynamic-routing/component-loader.js";
import { saveSession } from "@/helpers/heritage-integration/order-helper.js"; import { saveSession } from "@/helpers/heritage-integration/order-helper.js";
@ -16,15 +17,11 @@ import router from "@/router";
drop them so they don't start at the beginning again. This method will return 'heritage' if drop them so they don't start at the beginning again. This method will return 'heritage' if
the user has an existing order and they come back in from the Safelite.com CTA. the user has an existing order and they come back in from the Safelite.com CTA.
*/ */
export async function getPageToRouteExistingOrderTo(toRoute = {}, existingHeritageOrder = false) { export async function getPageToRouteExistingOrderTo(toRoute = {}) {
// If the user is coming in via the Safelite.Com CTA // If the user is coming in via the Safelite.Com CTA
if (toRoute.query[queryStrings.START_TYPE] === "fmg") { if (toRoute.query[queryStrings.START_TYPE] === "fmg") {
// If they have an existing order, return 'heritage' for the page name. const latestPageRoute = await getLatestPageForRedirection();
if (existingHeritageOrder) { return latestPageRoute;
return fmgPageValues.HERITAGE;
}
return await getLatestPageForRedirection();
} }
// If navigating to a specific page, and that page is not part of the vin pages. // If navigating to a specific page, and that page is not part of the vin pages.
@ -41,7 +38,6 @@ export async function getPageToRouteExistingOrderTo(toRoute = {}, existingHerita
// If this is not a direct link to a page using fmgPage, not from Safelite.com CTA or this is a vin related page. // If this is not a direct link to a page using fmgPage, not from Safelite.com CTA or this is a vin related page.
// Get the latest page for redirection. // Get the latest page for redirection.
const latestPageRoute = await getLatestPageForRedirection(); const latestPageRoute = await getLatestPageForRedirection();
return latestPageRoute; return latestPageRoute;
} }
@ -49,7 +45,7 @@ export async function getPageToRouteExistingOrderTo(toRoute = {}, existingHerita
Used to navigate to the heritage funnel with the correct query string and url. Used to navigate to the heritage funnel with the correct query string and url.
*/ */
export async function navigateToHeritageFunnel({ shouldSaveSession = true, loadingModal }) { export async function navigateToHeritageFunnel({ shouldSaveSession, loadingModal }) {
// Create the order (or save existing order) when navigating to Heritage Funnel. // Create the order (or save existing order) when navigating to Heritage Funnel.
if (shouldSaveSession) { if (shouldSaveSession) {
await saveSession({ shouldAwaitSaveSessionQueue: true }); await saveSession({ shouldAwaitSaveSessionQueue: true });
@ -59,21 +55,31 @@ export async function navigateToHeritageFunnel({ shouldSaveSession = true, loadi
loadingModal.showModal(); loadingModal.showModal();
} }
router.navigateToExternalUrl(externalUrls.HERITAGE_FUNNEL, { var heritageParms = {
corid: store.getters.order.referralCorrelationId, corid: store.getters.order.referralCorrelationId,
src: "concept-funnel", src: "concept-funnel",
conceptsqid: store.getters.applicationUser.savedSessionId, conceptsqid: store.getters.applicationUser.savedSessionId,
isInsurance: store.getters.payment.isInsurance, isInsurance: store.getters.payment.isInsurance,
}); };
const promo = getQuerystringParameter(queryStrings.PROMO);
if (promo) {
heritageParms["promo"] = promo;
}
router.navigateToExternalUrl(externalUrls.HERITAGE_FUNNEL, heritageParms);
} }
export async function skipVinLookup() { export async function skipVinLookup() {
if (store.getters.damage.isRepair) {
return true;
}
const isVinOptionalVehicle = store.getters.order.vehicle.make const isVinOptionalVehicle = store.getters.order.vehicle.make
? await store.dispatch(storeActions.IS_VIN_OPTIONAL_VEHICLE) ? await store.dispatch(storeActions.IS_VIN_OPTIONAL_VEHICLE)
: false; : false;
return ( return (
store.getters.damage.isRepair ||
isVinOptionalVehicle || isVinOptionalVehicle ||
!includesWindshieldReplacement() || !includesWindshieldReplacement() ||
experimentMixin.methods.hasSettingEqualTo(experimentSettings.SUPPRESS_VIN_CAPTURE, "true") experimentMixin.methods.hasSettingEqualTo(experimentSettings.SUPPRESS_VIN_CAPTURE, "true")
@ -81,18 +87,18 @@ export async function skipVinLookup() {
} }
export async function skipVinLookupNotRepair() { export async function skipVinLookupNotRepair() {
if (store.getters.damage.isRepair) {
return false;
}
const isVinOptionalVehicle = store.getters.order.vehicle.make const isVinOptionalVehicle = store.getters.order.vehicle.make
? await store.dispatch(storeActions.IS_VIN_OPTIONAL_VEHICLE) ? await store.dispatch(storeActions.IS_VIN_OPTIONAL_VEHICLE)
: false; : false;
return ( return (
!store.getters.damage.isRepair && isVinOptionalVehicle ||
(isVinOptionalVehicle || !includesWindshieldReplacement() ||
!includesWindshieldReplacement() || experimentMixin.methods.hasSettingEqualTo(experimentSettings.SUPPRESS_VIN_CAPTURE, "true")
experimentMixin.methods.hasSettingEqualTo(
experimentSettings.SUPPRESS_VIN_CAPTURE,
"true"
))
); );
} }

View file

@ -36,7 +36,7 @@ describe("getPageToRouteExistingOrderTo", () => {
}); });
// Act // Act
const result = await getPageToRouteExistingOrderTo(toRoute, false); const result = await getPageToRouteExistingOrderTo(toRoute);
//Assert //Assert
expect(result).toBe(fmgPageValues.VEHICLE); expect(result).toBe(fmgPageValues.VEHICLE);
@ -59,7 +59,7 @@ describe("getPageToRouteExistingOrderTo", () => {
}); });
// Act // Act
const result = await getPageToRouteExistingOrderTo(toRoute, false); const result = await getPageToRouteExistingOrderTo(toRoute);
//Assert //Assert
expect(result).toBe(fmgPageValues.VEHICLE_DAMAGE); expect(result).toBe(fmgPageValues.VEHICLE_DAMAGE);
@ -97,7 +97,7 @@ describe("getPageToRouteExistingOrderTo", () => {
}); });
// Act // Act
const result = await getPageToRouteExistingOrderTo(toRoute, false); const result = await getPageToRouteExistingOrderTo(toRoute);
//Assert //Assert
expect(result).toBe(fmgPageValues.ESTIMATE); expect(result).toBe(fmgPageValues.ESTIMATE);
@ -125,7 +125,7 @@ describe("getPageToRouteExistingOrderTo", () => {
}); });
// Act // Act
const result = await getPageToRouteExistingOrderTo(toRoute, false); const result = await getPageToRouteExistingOrderTo(toRoute);
//Assert //Assert
expect(result).toBe(fmgPageValues.ESTIMATE); expect(result).toBe(fmgPageValues.ESTIMATE);
@ -153,7 +153,7 @@ describe("getPageToRouteExistingOrderTo", () => {
}); });
// Act // Act
const result = await getPageToRouteExistingOrderTo(toRoute, false); const result = await getPageToRouteExistingOrderTo(toRoute);
//Assert //Assert
expect(result).toBe(fmgPageValues.CAPABILITY_QUESTIONS); expect(result).toBe(fmgPageValues.CAPABILITY_QUESTIONS);
@ -181,7 +181,7 @@ describe("getPageToRouteExistingOrderTo", () => {
}); });
// Act // Act
const result = await getPageToRouteExistingOrderTo(toRoute, false); const result = await getPageToRouteExistingOrderTo(toRoute);
//Assert //Assert
expect(result).toBe(fmgPageValues.MOLDING_QUESTIONS); expect(result).toBe(fmgPageValues.MOLDING_QUESTIONS);
@ -209,7 +209,7 @@ describe("getPageToRouteExistingOrderTo", () => {
}); });
// Act // Act
const result = await getPageToRouteExistingOrderTo(toRoute, false); const result = await getPageToRouteExistingOrderTo(toRoute);
//Assert //Assert
expect(result).toBe(fmgPageValues.VEHICLE_PARTS); expect(result).toBe(fmgPageValues.VEHICLE_PARTS);
@ -237,29 +237,11 @@ describe("getPageToRouteExistingOrderTo", () => {
}); });
// Act // Act
const result = await getPageToRouteExistingOrderTo(toRoute, false); const result = await getPageToRouteExistingOrderTo(toRoute);
//Assert //Assert
expect(result).toBe(fmgPageValues.PART_QUESTIONS); expect(result).toBe(fmgPageValues.PART_QUESTIONS);
}); });
test("existing order > should return heritage", async () => {
// Arrange
const toRoute = {
query: {
[queryStrings.START_TYPE]: "fmg",
},
};
store.commit(storeMutations.UPDATE_IS_REPAIR, false);
store.commit(storeMutations.UPDATE_MAKE, "acura");
// Act
const result = await getPageToRouteExistingOrderTo(toRoute, true);
// Assert
expect(result).toBe(fmgPageValues.HERITAGE);
});
}); });
describe("navigateToHeritageFunnel", () => { describe("navigateToHeritageFunnel", () => {
@ -295,7 +277,7 @@ describe("navigateToHeritageFunnel", () => {
router.navigateToExternalUrl = jest.fn(); router.navigateToExternalUrl = jest.fn();
// Act // Act
await navigateToHeritageFunnel({}); await navigateToHeritageFunnel({ loadingModal: null, shouldSaveSession: true });
// Assert // Assert
expect(saveSessionFunction).toHaveBeenCalled(); expect(saveSessionFunction).toHaveBeenCalled();

View file

@ -252,7 +252,10 @@ export default {
const vehicleChangedDuringPolicyLookupInHeritage = const vehicleChangedDuringPolicyLookupInHeritage =
payment.isInsurance && payment.insuranceCoverage.coverageStatus; payment.isInsurance && payment.insuranceCoverage.coverageStatus;
if (vehicleChangedDuringPolicyLookupInHeritage) { if (vehicleChangedDuringPolicyLookupInHeritage) {
navigateToHeritageFunnel({ loadingModal: this.$refs.loadingModal }); navigateToHeritageFunnel({
shouldSaveSession: true,
loadingModal: this.$refs.loadingModal,
});
} else if (this.$store.getters.order.referralNumber?.length === 6) { } else if (this.$store.getters.order.referralNumber?.length === 6) {
await this.navigateForwardWithSingleCarMatch(); await this.navigateForwardWithSingleCarMatch();
} else if (this.isRepair) { } else if (this.isRepair) {

View file

@ -121,6 +121,12 @@ export default {
false false
); );
baseMixin.methods.dispatchStoreAction(
storeActions.SAVE_SUPPORTING_ITEMS,
resultMap.supportingItems,
false
);
// Call the "next" function to complete the transition to this page. // Call the "next" function to complete the transition to this page.
next((vm) => { next((vm) => {
vm.setCmsContent(resultMap.cmsContent); vm.setCmsContent(resultMap.cmsContent);
@ -213,17 +219,14 @@ export default {
); );
} }
this.dispatchStoreAction(
this.storeActions.SAVE_SUPPORTING_ITEMS,
this.supportingItems,
false
);
this.dispatchStoreAction(this.storeActions.SAVE_VAPS, this.selectedVaps, false); this.dispatchStoreAction(this.storeActions.SAVE_VAPS, this.selectedVaps, false);
const payment = this.$store.getters.payment; const payment = this.$store.getters.payment;
if (payment.isInsurance) { if (payment.isInsurance) {
navigateToHeritageFunnel({ loadingModal: this.$refs.loadingModal }); navigateToHeritageFunnel({
shouldSaveSession: true,
loadingModal: this.$refs.loadingModal,
});
} else { } else {
this.$router.navigateWithSaving( this.$router.navigateWithSaving(
this.navigationScenarios.CLICKED_FORWARD_WITH_CASH, this.navigationScenarios.CLICKED_FORWARD_WITH_CASH,

View file

@ -116,6 +116,8 @@ import store from "@/store";
import { defineRule } from "vee-validate"; import { defineRule } from "vee-validate";
import { errorMessages } from "@/constants/error-messages"; import { errorMessages } from "@/constants/error-messages";
const MOBILE_FEE_PART_TYPE = "MOBILE FEE";
// DEFINE VALIDATION RULES // DEFINE VALIDATION RULES
defineRule("mobile-location-required", (value) => { defineRule("mobile-location-required", (value) => {
if ( if (
@ -375,6 +377,43 @@ export default {
backButtonAction() { backButtonAction() {
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route); this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
}, },
updateAndSaveSupportingItems() {
const supportingItems = store.getters.lineItems.supportingItems;
// if we have a mobile fee, then save/update supporting items
if (this.selectedAppointmentType == "Mobile") {
const mobileFeeIndex = supportingItems.findIndex(
(item) => item.partType == MOBILE_FEE_PART_TYPE
);
// If it already exists, update the price with latest data
if (mobileFeeIndex >= 0) {
supportingItems[mobileFeeIndex].laborAmount = this.mobileFeePart.laborAmount;
supportingItems[mobileFeeIndex].selingPrice = this.mobileFeePart.selingPrice;
supportingItems[mobileFeeIndex].kitPrice = this.mobileFeePart.kitPrice;
} else {
supportingItems.push(this.mobileFeePart);
}
this.dispatchStoreAction(
this.storeActions.SAVE_SUPPORTING_ITEMS_SUPPRESSING_STATE_RESETTING,
supportingItems,
false
);
} else {
// if it's not a mobile, then make sure we remove any that may have been added
const removeMobileFeeIndex = supportingItems.findIndex(
(item) => item.partType == MOBILE_FEE_PART_TYPE
);
if (removeMobileFeeIndex >= 0) {
supportingItems.splice(removeMobileFeeIndex, 1);
this.dispatchStoreAction(
this.storeActions.SAVE_SUPPORTING_ITEMS_SUPPRESSING_STATE_RESETTING,
supportingItems,
false
);
}
}
},
async forwardButtonAction() { async forwardButtonAction() {
await this.dispatchStoreAction( await this.dispatchStoreAction(
this.storeActions.SAVE_SERVICE_LOCATION, this.storeActions.SAVE_SERVICE_LOCATION,
@ -401,6 +440,7 @@ export default {
false false
); );
this.updateAndSaveSupportingItems();
this.$router.navigateWithSaving(this.navigationScenarios.CLICKED_FORWARD, this.$route); this.$router.navigateWithSaving(this.navigationScenarios.CLICKED_FORWARD, this.$route);
}, },
openModalAction(modalName) { openModalAction(modalName) {

View file

@ -447,9 +447,15 @@ export default {
const payment = store.getters.payment; const payment = store.getters.payment;
if (store.getters.order.referralNumber?.length === 6) { if (store.getters.order.referralNumber?.length === 6) {
navigateToHeritageFunnel({ loadingModal: self.$refs.loadingModal }); navigateToHeritageFunnel({
shouldSaveSession: true,
loadingModal: self.$refs.loadingModal,
});
} else if (payment.isInsurance && payment.insuranceCoverage.isVerified) { } else if (payment.isInsurance && payment.insuranceCoverage.isVerified) {
navigateToHeritageFunnel({ loadingModal: self.$refs.loadingModal }); navigateToHeritageFunnel({
shouldSaveSession: true,
loadingModal: self.$refs.loadingModal,
});
} else { } else {
self.$router.navigateWithSaving( self.$router.navigateWithSaving(
self.navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS, self.navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,

View file

@ -6,6 +6,7 @@ import { lazyLoadComponent } from "@/router/dynamic-routing/component-loader.js"
import { routingTable } from "@/router/router-constants/routing-table.js"; import { routingTable } from "@/router/router-constants/routing-table.js";
import { globalEvents, globalEventTypes } from "@/constants/events"; import { globalEvents, globalEventTypes } from "@/constants/events";
import { queryStrings } from "@/constants/query-strings"; import { queryStrings } from "@/constants/query-strings";
import { getQuerystringParameter } from "@/helpers/querystring-helper";
import { getDeviceIdValue } from "@/helpers/heritage-integration/cookie-helper"; import { getDeviceIdValue } from "@/helpers/heritage-integration/cookie-helper";
// Heritage integration // Heritage integration
@ -74,17 +75,7 @@ const routes = [
: null : null
); );
const pageToRedirectTo = await getPageToRouteExistingOrderTo( const pageToRedirectTo = await getPageToRouteExistingOrderTo(to);
to,
loadSessionResponse
);
// If getPageToRouteExistingOrderTo determines that the return user needs to
// go back to heritage funnel, send them there and stop our current navigation.
if (pageToRedirectTo === "heritage") {
await navigateToHeritageFunnel();
return next(false);
}
// Assign our fmgPage so it will load normally like the other pages. // Assign our fmgPage so it will load normally like the other pages.
to.query.fmgPage = pageToRedirectTo; to.query.fmgPage = pageToRedirectTo;
@ -284,14 +275,9 @@ async function navigate(
fmgPage: destinationFmgPageValue, fmgPage: destinationFmgPageValue,
}; };
const queryString = window.location.search; const hasZip = getQuerystringParameter(queryStrings.ZIP_CODE);
const urlParams = new URLSearchParams(queryString); const zip = getQuerystringParameter(queryStrings.ZIP_CODE);
const lowerCaseParams = new URLSearchParams(); const promo = getQuerystringParameter(queryStrings.PROMO);
for (const [name, value] of urlParams) {
lowerCaseParams.append(name.toLowerCase(), value);
}
const hasZip = lowerCaseParams.has(queryStrings.ZIP_CODE);
const zip = lowerCaseParams.get(queryStrings.ZIP_CODE);
if ( if (
hasZip && hasZip &&
@ -303,6 +289,10 @@ async function navigate(
queryStringsObject[queryStrings.ZIP_CODE] = zip; queryStringsObject[queryStrings.ZIP_CODE] = zip;
} }
if (promo) {
queryStringsObject[queryStrings.PROMO] = promo;
}
router.push({ router.push({
name: "root", name: "root",
query: Object.assign(optionalQuery, queryStringsObject), query: Object.assign(optionalQuery, queryStringsObject),

View file

@ -22,6 +22,7 @@ import {
getDisplayTextForDurationLength, getDisplayTextForDurationLength,
} from "@/layouts/schedule/helpers/schedule-helper"; } from "@/layouts/schedule/helpers/schedule-helper";
import { getDateDifferenceInDays } from "@/helpers/date-helper";
// Export State // Export State
const getDefaultState = () => { const getDefaultState = () => {
return { return {
@ -634,8 +635,24 @@ function getNonFalseValuesOfPropertyInArrayOfObjects(array, propertyName) {
return (array ?? []).map((x) => x[propertyName]).filter((x) => x); return (array ?? []).map((x) => x[propertyName]).filter((x) => x);
} }
function provisionalTriggersToString(provisionalTriggers) { function getTimeSlotsAdditionalEventData(
return "ProvisionalTriggers:" + provisionalTriggers.join(","); provisionalTriggers,
zipCode,
firstAvailableAppointmentDateString,
shopAppointmentType
) {
var numberOfDays = null;
if (firstAvailableAppointmentDateString)
numberOfDays = getDateDifferenceInDays(new Date(), firstAvailableAppointmentDateString);
if (shopAppointmentType)
return `FirstAvailableAppointment:${numberOfDays},Zip:${zipCode},ShopAppointmentType:${shopAppointmentType},ProvisionalTriggers:${provisionalTriggers.join(
","
)}`;
else
return `FirstAvailableAppointment:${numberOfDays},Zip:${zipCode},ProvisionalTriggers:${provisionalTriggers.join(
","
)}`;
} }
// Export Actions // Export Actions
@ -1315,7 +1332,12 @@ export const actions = {
endpoint: endpoints.GetShopTimeSlots.url, endpoint: endpoints.GetShopTimeSlots.url,
payload: payload, payload: payload,
additionalSuccessEventDataHandler: (response) => additionalSuccessEventDataHandler: (response) =>
provisionalTriggersToString(response.data.provisionalTriggers), getTimeSlotsAdditionalEventData(
response.data.provisionalTriggers,
order.serviceLocation.zipCode,
response.data.days?.[0]?.date,
shopAppointmentType
),
}); });
}, },
@ -1372,7 +1394,11 @@ export const actions = {
endpoint: endpoints.GetMobileTimeSlots.url, endpoint: endpoints.GetMobileTimeSlots.url,
payload: payload, payload: payload,
additionalSuccessEventDataHandler: (response) => additionalSuccessEventDataHandler: (response) =>
provisionalTriggersToString(response.data.provisionalTriggers), getTimeSlotsAdditionalEventData(
response.data.provisionalTriggers,
order.serviceLocation.zipCode,
response.data.days?.[0]?.date
),
}); });
}, },