Merge pull request #1169 from Safelite/feature/skiener/INSR-2124

INSR-2124 | enable MSR scheduling
This commit is contained in:
scottkiener-at-safelite 2026-04-03 13:58:51 -04:00 committed by GitHub
commit ac70f1c76a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 25 additions and 12 deletions

View file

@ -6,7 +6,7 @@ const COVERAGE_BASE_URL = '/coverage/api/v1/coverage';
const EXPERIMENTS_BASE_URL = '/experiments/api/v1/experiments'; const EXPERIMENTS_BASE_URL = '/experiments/api/v1/experiments';
const LOCATION_BASE_URL = '/location/api/v1/location'; const LOCATION_BASE_URL = '/location/api/v1/location';
const ORDER_BASE_URL = '/order/api/v1/order'; const ORDER_BASE_URL = '/order/api/v1/order';
const PARTS_BASE_URL = '/parts/api/v1/parts'; const PARTS_BASE_URL = '/parts/api/v2/parts';
const PRICE_BASE_URL = '/price/api/v1/price'; const PRICE_BASE_URL = '/price/api/v1/price';
const SCHEDULE_BASE_URL = '/schedule/api/v1/schedule'; const SCHEDULE_BASE_URL = '/schedule/api/v1/schedule';
const VEHICLE_BASE_URL = '/vehicle/api/v1/vehicle'; const VEHICLE_BASE_URL = '/vehicle/api/v1/vehicle';

View file

@ -1,6 +1,8 @@
const partNumberStrings = Object.freeze({ const partNumberStrings = Object.freeze({
RECYCLE_FEE: 'RECYCLE FEE', RECYCLE_FEE: 'RECYCLE FEE',
LABOR2: 'LABOR2', LABOR2: 'LABOR2',
RECAL_MOBILE: 'RECAL MOBILE',
RECAL_MOBILEDUAL: 'RECAL MOBILEDUAL'
}); });
export default partNumberStrings; export default partNumberStrings;

View file

@ -52,14 +52,14 @@ export function buildURLSearchParams(data) {
} }
if (Array.isArray(value)) { if (Array.isArray(value)) {
value.forEach((arrayValue, index) => { value.forEach((arrayValue, index) => {
if (typeof value === 'object') { if (typeof arrayValue === 'object') {
Object.entries(arrayValue).forEach(([objectKey, objectValue]) => { Object.entries(arrayValue).forEach(([objectKey, objectValue]) => {
if (objectValue != null) { if (objectValue != null) {
params.append(`${key}[${index}].${objectKey}`, `${objectValue}`); params.append(`${key}[${index}].${objectKey}`, `${objectValue}`);
} }
}); });
} else { } else {
params.append(`${key}[${index}]`, `${value}`); params.append(`${key}[${index}]`, `${arrayValue}`);
} }
}); });
} else { } else {

View file

@ -44,7 +44,7 @@ export async function getPricedMobileFeePart(serviceZipCode) {
} }
// Get the Mobile Fee Part // Get the Mobile Fee Part
const mobileFeePart = await useMainStore().getMobileFeePart(); const mobileFeePart = await useMainStore().getMobileFeePart(serviceZipCode);
if (mobileFeePart?.data == null || mobileFeePart.data === '') { if (mobileFeePart?.data == null || mobileFeePart.data === '') {
return Promise.resolve(null); return Promise.resolve(null);

View file

@ -4,6 +4,7 @@ import { createTestingPinia } from '@pinia/testing';
import { AppointmentTypeStrings } from '@/constants/schedule-constants'; import { AppointmentTypeStrings } from '@/constants/schedule-constants';
import navigationScenarios from '@/router/router-constants/navigation-scenarios'; import navigationScenarios from '@/router/router-constants/navigation-scenarios';
import routerParams from '@/router/router-constants/router-params'; import routerParams from '@/router/router-constants/router-params';
import { getPricedMobileFeePart } from '@/helpers/service-location-helper';
import { useMainStore } from '@/store'; import { useMainStore } from '@/store';
import serviceLocation from '@/layouts/schedule-page/service-location/service-location.vue'; import serviceLocation from '@/layouts/schedule-page/service-location/service-location.vue';
@ -87,7 +88,8 @@ jest.mock(
'@/helpers/service-location-helper', '@/helpers/service-location-helper',
() => ({ () => ({
getZipCodeData: jest.fn((mockServiceZipCode) => mockZipcodeData(mockServiceZipCode)), getZipCodeData: jest.fn((mockServiceZipCode) => mockZipcodeData(mockServiceZipCode)),
getMobileZipCodeData: jest.fn((mockServiceZipCode) => mockZipcodeData(mockServiceZipCode)) getMobileZipCodeData: jest.fn((mockServiceZipCode) => mockZipcodeData(mockServiceZipCode)),
getPricedMobileFeePart: jest.fn(() => Promise.resolve(null))
}) })
); );

View file

@ -143,6 +143,7 @@ import shopAddress from '@/layouts/schedule-page/service-location/shop-address/s
import serviceZipQuestion from '@/layouts/schedule-page/service-location/service-zip-question/service-zip-question.vue'; import serviceZipQuestion from '@/layouts/schedule-page/service-location/service-zip-question/service-zip-question.vue';
import widgetFields from '@/constants/cms-widget-fields'; import widgetFields from '@/constants/cms-widget-fields';
import recalModal from '@/iss-components/recal-modal/recal-modal.vue'; import recalModal from '@/iss-components/recal-modal/recal-modal.vue';
import { getPricedMobileFeePart } from '@/helpers/service-location-helper';
const RECAL_MODAL_REF_NAME = 'RecalModal'; const RECAL_MODAL_REF_NAME = 'RecalModal';
@ -355,9 +356,7 @@ export default {
let provider = this.selectedProvider; let provider = this.selectedProvider;
this.mainStore.updateMobileFee(null); this.mainStore.updateMobileFee(null);
if (this.isMobile) { if (this.isMobile) {
if (this.mainStore.isNoComp || this.mainStore.isITAC) { this.mainStore.updateMobileFee(this.mobileFeePart);
this.mainStore.updateMobileFee(this.mobileFeePart);
}
provider = { provider = {
providerNumber: this.mobileProviderNumber, providerNumber: this.mobileProviderNumber,
@ -568,6 +567,11 @@ export default {
} }
} }
}); });
const mobileFeePromise = getPricedMobileFeePart(this.mobileZipCode);
await mobileFeePromise.then((result) => {
this.mobileFeePart = result ?? null;
});
} }
} }
} }

View file

@ -22,7 +22,7 @@ import {
repairWaivedForSelectedVehicle repairWaivedForSelectedVehicle
} from '@/helpers/policy-vehicle-helper'; } from '@/helpers/policy-vehicle-helper';
import { buildURLSearchParams, getPartNumbersListForQueryString } from '@/helpers/querystring-helper'; import { buildURLSearchParams, getPartNumbersListForQueryString } from '@/helpers/querystring-helper';
import { getTopLevelGlassPartsWithRecal } from '@/helpers/recal-helper'; import { getRecalPartNumbers, getTopLevelGlassPartsWithRecal } from '@/helpers/recal-helper';
import { getDateForSavedSessionTimeout } from '@/helpers/session-helper'; import { getDateForSavedSessionTimeout } from '@/helpers/session-helper';
import { isMobileDevice } from '@/helpers/useragent-helper'; import { isMobileDevice } from '@/helpers/useragent-helper';
import issPageValues from '@/router/router-constants/issPage-values'; import issPageValues from '@/router/router-constants/issPage-values';
@ -1320,13 +1320,14 @@ export const useMainStore = defineStore({
return availableLineItems; return availableLineItems;
}, },
getMobileFeePart() { getMobileFeePart(serviceZipCode) {
const { vehicle, insuranceCoverage } = this.order; const { vehicle, insuranceCoverage } = this.order;
const recalParts = getRecalPartNumbers(this.order.lineItems.glassParts);
if (!this.billToAccountNumber || !this.providerNumber) { if (!this.billToAccountNumber || !this.providerNumber) {
return null; return null;
} }
const params = new URLSearchParams({ const params = buildURLSearchParams({
serviceType: this.damage.isRepair ? 'Repair' : 'Install', serviceType: this.damage.isRepair ? 'Repair' : 'Install',
facilityType: 'Mobile', facilityType: 'Mobile',
parentAccountNumber: this.order.parentAccountNumber, parentAccountNumber: this.order.parentAccountNumber,
@ -1334,6 +1335,8 @@ export const useMainStore = defineStore({
isItacOptimized: insuranceCoverage.isItacOptimized, isItacOptimized: insuranceCoverage.isItacOptimized,
providerNumber: this.providerNumber, providerNumber: this.providerNumber,
carId: vehicle.carId, carId: vehicle.carId,
zipCode: serviceZipCode,
partNumbers: recalParts,
coverageStatus: coverageStatuses.mapToApi(insuranceCoverage.coverageStatus), coverageStatus: coverageStatuses.mapToApi(insuranceCoverage.coverageStatus),
coverageType: coverageType.mapToApi(insuranceCoverage.coverageType) coverageType: coverageType.mapToApi(insuranceCoverage.coverageType)
}); });
@ -1995,8 +1998,10 @@ export const useMainStore = defineStore({
updateMobileFee(fee) { updateMobileFee(fee) {
const isMobileFeeHidden = getExperimentSettingValue(this.experimentSettings, experimentSettings.ISS_FEATURE_TOGGLE_IS_MOBILE_FEE_HIDDEN) === 'true'; const isMobileFeeHidden = getExperimentSettingValue(this.experimentSettings, experimentSettings.ISS_FEATURE_TOGGLE_IS_MOBILE_FEE_HIDDEN) === 'true';
const isMSRFee = fee?.partNumber === partNumberStrings.RECAL_MOBILE || fee?.partNumber === partNumberStrings.RECAL_MOBILEDUAL;
// Mobile Fee is only added for NO COMP or ITAC and is NOT hidden // Mobile Fee is only added for NO COMP or ITAC and is NOT hidden
if (fee && this.isVerified && (this.isNoComp || this.isITAC) && !isMobileFeeHidden) { // MSR Fee is added for all orders
if ((fee && this.isVerified && (this.isNoComp || this.isITAC) && !isMobileFeeHidden) || isMSRFee) {
this.addPartTypeFeeItem(fee, partTypeStrings.MOBILE_FEE); this.addPartTypeFeeItem(fee, partTypeStrings.MOBILE_FEE);
} else { } else {
this.addPartTypeFeeItem(null, partTypeStrings.MOBILE_FEE); this.addPartTypeFeeItem(null, partTypeStrings.MOBILE_FEE);