Address comments about policy / deductible / coverage calls failing should not bailout and just switch to no coverage

IsVinAddressable API call failure now returns false
Improved logging for cases
Fixed Vehicle Style bailout when selecting select style value
This commit is contained in:
Josh Dassinger 2026-02-19 11:13:29 -06:00
parent 583a675fa3
commit ea5836b3e4
6 changed files with 169 additions and 156 deletions

View file

@ -94,10 +94,11 @@ export default {
} }
if (error.response.status !== 404) { if (error.response.status !== 404) {
global.$logger.logError(`${method}: ${endpoint}: ${error.message}`, error.response); const errorData = { method, url, payload, error };
global.$logger.logError(`${method}: ${endpoint}`, errorData);
if (bailoutOnError && global.bailoutOnAxiosError !== undefined) if (bailoutOnError && global.bailoutOnAxiosError !== undefined)
{ {
global.bailoutOnAxiosError({ method, url, payload, error }); global.bailoutOnAxiosError(errorData);
} }
} }
return reject(error.response); return reject(error.response);

View file

@ -214,7 +214,6 @@ export default {
}); });
this.navigateForward(); this.navigateForward();
} catch (e) { } catch (e) {
debugger;
if (e.isAxiosError && e.status === 404) { if (e.isAxiosError && e.status === 404) {
this.mainStore.resetVehicleState(); this.mainStore.resetVehicleState();
useMainStore().updateVehicle({ useMainStore().updateVehicle({

View file

@ -163,16 +163,18 @@ export default {
} }
}, },
selectedStyle(value) { selectedStyle(value) {
this.resetAlert(); if (value) {
this.mainStore.updateVehicleStyle(value); this.resetAlert();
this.mainStore.setVehicle( this.mainStore.updateVehicleStyle(value);
this.selectedYear, this.mainStore.setVehicle(
this.selectedMake, this.selectedYear,
this.selectedModel, this.selectedMake,
this.selectedStyle this.selectedModel,
).then((result) => { this.selectedStyle
this.displayNoServiceAlert = !result.data.canSafeliteService; ).then((result) => {
}); this.displayNoServiceAlert = !result.data.canSafeliteService;
});
}
} }
}, },
mounted() { mounted() {

View file

@ -48,7 +48,7 @@ function getPageName(vm) {
// Vue Error Handling // Vue Error Handling
vueApp.config.errorHandler = (err, vm, info) => { vueApp.config.errorHandler = (err, vm, info) => {
const pageName = getPageName(vm); const pageName = getPageName(vm);
global.$logger.logError(`Page Name - ${pageName} - ${info}: ${err.message}\n${err.stack}`); global.$logger.logError(`[${pageName}] ${info}`, err);
if (applicationConfig.BAILOUT_ON_APPLICATION_ERROR) { if (applicationConfig.BAILOUT_ON_APPLICATION_ERROR) {
router.navigateBailout(bailoutMessage.applicationError(`[${pageName}] ${info}: ${err.message}\n${err.stack}`)); router.navigateBailout(bailoutMessage.applicationError(`[${pageName}] ${info}: ${err.message}\n${err.stack}`));
} }
@ -56,7 +56,7 @@ vueApp.config.errorHandler = (err, vm, info) => {
// Vue Router Error Handling // Vue Router Error Handling
router.onError((err) => { router.onError((err) => {
global.$logger.logError(err.message, err.cause); global.$logger.logError('Router Error:', err);
if (applicationConfig.BAILOUT_ON_ROUTER_ERROR) { if (applicationConfig.BAILOUT_ON_ROUTER_ERROR) {
router.navigateBailout(bailoutMessage.routerError(`${err.message}\n${err.stack}`)); router.navigateBailout(bailoutMessage.routerError(`${err.message}\n${err.stack}`));
} }

View file

@ -25,6 +25,7 @@ import { buildURLSearchParams, getPartNumbersListForQueryString } from '@/helper
import { getTopLevelGlassPartsWithRecal } from '@/helpers/recal-helper'; import { getTopLevelGlassPartsWithRecal } from '@/helpers/recal-helper';
import { getDateForSavedSessionTimeout } from '@/helpers/session-helper'; import { getDateForSavedSessionTimeout } from '@/helpers/session-helper';
import issPageValues from '@/router/router-constants/issPage-values'; import issPageValues from '@/router/router-constants/issPage-values';
import CoverageStatuses from '@/constants/coverage-statuses';
const storeId = 'main'; const storeId = 'main';
@ -528,12 +529,16 @@ export const useMainStore = defineStore({
payload: {} payload: {}
}); });
}, },
getIsVinbyAddressPermissible() { async getIsVinbyAddressPermissible() {
return globalMethods.callHttpClient({ try {
method: endpoints.IsVinbyAddressPermissible.method, return globalMethods.callHttpClient({
endpoint: `${endpoints.IsVinbyAddressPermissible.url}?state=${this.order.customer.address.state}`, method: endpoints.IsVinbyAddressPermissible.method,
payload: {} endpoint: `${endpoints.IsVinbyAddressPermissible.url}?state=${this.order.customer.address.state}`,
}); payload: {}
});
} catch (e) {
return false;
}
}, },
async getCoveragePolicyInfo() { async getCoveragePolicyInfo() {
const { order, issConfig, applicationUser } = this; const { order, issConfig, applicationUser } = this;
@ -547,42 +552,47 @@ export const useMainStore = defineStore({
this.applicationUser.coverageAttempts += 1; this.applicationUser.coverageAttempts += 1;
console.log(`Coverage lookup attempt #${this.applicationUser.coverageAttempts}. Max attempts allowed: 10.`); console.log(`Coverage lookup attempt #${this.applicationUser.coverageAttempts}. Max attempts allowed: 10.`);
const response = await globalMethods.callHttpClient({ try {
method: endpoints.CoveragePolicyInfo.method, const response = await globalMethods.callHttpClient({
endpoint: endpoints.CoveragePolicyInfo.url, method: endpoints.CoveragePolicyInfo.method,
payload: { endpoint: endpoints.CoveragePolicyInfo.url,
accountNumber: order.parentAccountNumber?.toString(), payload: {
policyNumber: policy.policyNumber, accountNumber: order.parentAccountNumber?.toString(),
dateOfLoss: policy.dateOfLoss, policyNumber: policy.policyNumber,
zipCode: policy.policyZipCode, dateOfLoss: policy.dateOfLoss,
referralCorrelationId: order.referralCorrelationId zipCode: policy.policyZipCode,
referralCorrelationId: order.referralCorrelationId
},
bailoutOnError: false
});
const responsePolicy = response?.data?.policies?.[0];
if (responsePolicy) {
this.updateCoverageType(coverageType.Deductible);
const insured = responsePolicy.insureds?.[0];
// populate parent account number
if (response.data.accountNumber) {
order.parentAccountNumber = parseInt(response.data.accountNumber, 10);
}
// populate policy holder details from policy lookup
order.customer.address.streetAddress = insured?.address;
order.customer.address.city = insured?.city;
order.customer.address.state = insured?.state;
order.customer.address.zipCode = insured?.zipCode?.toString();
order.customer.firstName = insured?.firstName;
order.customer.lastName = insured?.lastName;
// populate additional fields
order.policy.policyData = responsePolicy.policyData;
// populate vehicles
order.policy.vehicles = responsePolicy.vehicles ?? [];
} else {
this.updateCoverageType(coverageType.NONE);
} }
}); } catch (e) {
const responsePolicy = response?.data?.policies?.[0];
if (responsePolicy) {
this.updateCoverageType(coverageType.Deductible);
const insured = responsePolicy.insureds?.[0];
// populate parent account number
if (response.data.accountNumber) {
order.parentAccountNumber = parseInt(response.data.accountNumber, 10);
}
// populate policy holder details from policy lookup
order.customer.address.streetAddress = insured?.address;
order.customer.address.city = insured?.city;
order.customer.address.state = insured?.state;
order.customer.address.zipCode = insured?.zipCode?.toString();
order.customer.firstName = insured?.firstName;
order.customer.lastName = insured?.lastName;
// populate additional fields
order.policy.policyData = responsePolicy.policyData;
// populate vehicles
order.policy.vehicles = responsePolicy.vehicles ?? [];
} else {
this.updateCoverageType(coverageType.NONE); this.updateCoverageType(coverageType.NONE);
} }
}, },
@ -601,82 +611,81 @@ export const useMainStore = defineStore({
updateIsItacOptimized(isItacOptimized) { updateIsItacOptimized(isItacOptimized) {
this.order.insuranceCoverage.isItacOptimized = isItacOptimized || false; this.order.insuranceCoverage.isItacOptimized = isItacOptimized || false;
}, },
registerClaim() { async registerClaim() {
const nonNumberCharRegex = /[^0-9]/g; const nonNumberCharRegex = /[^0-9]/g;
const { order, isITAC } = this; const { isITAC } = this;
return new Promise((resolve, reject) => {
globalMethods.callHttpClient({ try {
const response = await globalMethods.callHttpClient({
method: endpoints.RegisterClaim.method, method: endpoints.RegisterClaim.method,
endpoint: endpoints.RegisterClaim.url, endpoint: endpoints.RegisterClaim.url,
payload: payload:
{ {
referralCorrelationId: this.order.referralCorrelationId, referralCorrelationId: this.order.referralCorrelationId,
accountNumber: this.order.parentAccountNumber?.toString() ?? '', accountNumber: this.order.parentAccountNumber?.toString() ?? '',
policyData: this.order.policy.policyData, policyData: this.order.policy.policyData,
isItac: isITAC, isItac: isITAC,
insured: { insured: {
firstName: this.order.customer.firstName, firstName: this.order.customer.firstName,
lastName: this.order.customer.lastName, lastName: this.order.customer.lastName,
address: { address: {
addressLine1: this.order.customer.address.streetAddress, addressLine1: this.order.customer.address.streetAddress,
addressLine2: this.order.customer.address.streetAddress2, addressLine2: this.order.customer.address.streetAddress2,
city: this.order.customer.address.city, city: this.order.customer.address.city,
state: this.order.customer.address.state, state: this.order.customer.address.state,
zipCode: this.order.customer.address.zipCode, zipCode: this.order.customer.address.zipCode,
country: 'US' // TODO set from store country: 'US' // TODO set from store
},
homePhone: {
number: this.contactInfo.homePhone?.replaceAll(nonNumberCharRegex, '') ?? ''
}
}, },
homePhone: { driver: {
number: this.contactInfo.homePhone?.replaceAll(nonNumberCharRegex, '') ?? '' firstName: this.order.customer.firstName,
lastName: this.order.customer.lastName
},
caller: {
homePhone: {}
},
policyInfo: {
policyNumber: this.order.policy.policyNumber,
safelitePolicy: {
policies: []
},
actualDeductible: this.currentDeductible.toString() ?? ''
},
lossInfo: {
dateOfLoss: this.order.policy.dateOfLoss,
location: {
city: this.order.policy.damageCity,
state: this.order.policy.damageState,
country: 'US' // TODO set from store
},
vehicle: {
id: this.order.vehicle.policyVehicleId?.toString() ?? '',
year: this.order.vehicle.year?.toString() ?? '',
make: this.order.vehicle.make,
model: this.order.vehicle.model,
vin: this.order.vehicle.vin
},
cause: this.order.policy.damageCause,
damageDescription: this.order.policy.damageCause
} }
}, },
driver: { bailoutOnError: false
firstName: this.order.customer.firstName,
lastName: this.order.customer.lastName
},
caller: {
homePhone: {}
},
policyInfo: {
policyNumber: this.order.policy.policyNumber,
safelitePolicy: {
policies: []
},
actualDeductible: this.currentDeductible.toString() ?? ''
},
lossInfo: {
dateOfLoss: this.order.policy.dateOfLoss,
location: {
city: this.order.policy.damageCity,
state: this.order.policy.damageState,
country: 'US' // TODO set from store
},
vehicle: {
id: this.order.vehicle.policyVehicleId?.toString() ?? '',
year: this.order.vehicle.year?.toString() ?? '',
make: this.order.vehicle.make,
model: this.order.vehicle.model,
vin: this.order.vehicle.vin
},
cause: this.order.policy.damageCause,
damageDescription: this.order.policy.damageCause
}
}
}).then((response) => {
this.order.insuranceCoverage.claimNumber = response.data.claimNumber;
if (response.data.isSuccess) {
this.updateCoverageStatus(coverageStatuses.VERIFIED);
} else {
this.updateCoverageStatus(coverageStatuses.NO_COVERAGE);
}
return resolve(response);
}, (error) => {
this.updateCoverageStatus(coverageStatuses.NO_COVERAGE);
this.order.insuranceCoverage.claimNumber = null;
return reject(error);
}); });
}); this.order.insuranceCoverage.claimNumber = response.data.claimNumber;
if (response.data.isSuccess) {
this.updateCoverageStatus(coverageStatuses.VERIFIED);
} else {
this.updateCoverageStatus(coverageStatuses.NO_COVERAGE);
}
} catch (e) {
this.updateCoverageStatus(coverageStatuses.NO_COVERAGE);
this.order.insuranceCoverage.claimNumber = null;
}
}, },
getFinalDeductible() { async getFinalDeductible() {
const endorsementAnswersForPayload = []; const endorsementAnswersForPayload = [];
const endorsementAnswers = this.order.policy.endorsementQuestionAnswers; const endorsementAnswers = this.order.policy.endorsementQuestionAnswers;
if (endorsementAnswers) { if (endorsementAnswers) {
@ -692,9 +701,9 @@ export const useMainStore = defineStore({
glassInformation?.forEach((glassPiece) => { glassInformation?.forEach((glassPiece) => {
manualGlassNamesArray.push(glassPiece?.glassLocation?.toUpperCase()); manualGlassNamesArray.push(glassPiece?.glassLocation?.toUpperCase());
}); });
return new Promise((resolve, reject) => { try {
globalMethods.callHttpClient({ const r = await globalMethods.callHttpClient({
method: endpoints.FinalDeductible.method, method: endpoints.FinalDeductible.method,
endpoint: endpoints.FinalDeductible.url, endpoint: endpoints.FinalDeductible.url,
payload: { payload: {
@ -716,16 +725,18 @@ export const useMainStore = defineStore({
vehicleVin: this.order.vehicle.vin, vehicleVin: this.order.vehicle.vin,
policyData: this.order.policy.policyData, policyData: this.order.policy.policyData,
isItac: this.isITAC isItac: this.isITAC
} },
}).then((r) => { bailoutOnError: false
this.order.policy.policyData = r.data.policyData; });
this.updateDeductible(r.data); this.order.policy.policyData = r.data.policyData;
return resolve(r); this.updateDeductible(r.data);
}).catch((error) => reject(error)); return r;
}); } catch (e) {
this.updateCoverageStatus(CoverageStatuses.PENDING);
}
}, },
getDuplicateReferrals() { async getDuplicateReferrals() {
const params = new URLSearchParams({ const params = new URLSearchParams({
parentAccountNumber: this.order.parentAccountNumber, parentAccountNumber: this.order.parentAccountNumber,
customerPhoneNumber: this.order.contactInfo.servicePhone, customerPhoneNumber: this.order.contactInfo.servicePhone,
@ -734,18 +745,16 @@ export const useMainStore = defineStore({
dateOfLoss: this.order.policy.dateOfLoss dateOfLoss: this.order.policy.dateOfLoss
}); });
return new Promise((resolve, reject) => { try {
globalMethods.callHttpClient({ const duplicates = await globalMethods.callHttpClient({
method: endpoints.DuplicateSearch.method, method: endpoints.DuplicateSearch.method,
endpoint: `${endpoints.DuplicateSearch.url}?${params.toString()}` endpoint: `${endpoints.DuplicateSearch.url}?${params.toString()}`,
}).then((r) => { bailoutOnError: false
this.applicationUser.duplicateOrders = r.data ?? [];
return resolve(r.data);
}).catch((error) => {
this.applicationUser.duplicateOrders = [];
return reject(error);
}); });
}); this.applicationUser.duplicateOrders = duplicates.data ?? [];
} catch (e) {
this.applicationUser.duplicateOrders = [];
}
}, },
async lookupVinByPlate(licensePlate, licenseState) { async lookupVinByPlate(licensePlate, licenseState) {
try { try {

View file

@ -459,9 +459,9 @@ describe('Store', () => {
expect(store.order.insuranceCoverage.claimNumber).not.toBeNull(); expect(store.order.insuranceCoverage.claimNumber).not.toBeNull();
}); });
it('Call to client returns exception, resulting in object with error property being returned', async () => { it('Call to client returns exception, and no error is returned from registerClaim method', async () => {
// Arrange // Arrange
expect.assertions(4); expect.assertions(3);
const error = 'register claim error'; const error = 'register claim error';
globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.reject(error)); globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.reject(error));
store.order.insuranceCoverage.coverageStatus = coverageStatuses.PENDING; store.order.insuranceCoverage.coverageStatus = coverageStatuses.PENDING;
@ -1494,8 +1494,8 @@ describe('Store', () => {
// Assert // Assert
expect(globalMethods.callHttpClient).toHaveBeenCalled(); expect(globalMethods.callHttpClient).toHaveBeenCalled();
}); });
it('api call throws exception => insuranceCoverage.coverageType is NONE', async () => { it('api call throws exception => no error is thrown from getCoveragePolicyInfo and insuranceCoverage.coverageType is NONE', async () => {
expect.assertions(3); expect.assertions(2);
const error = 'get coverage policy info error'; const error = 'get coverage policy info error';
store.issConfig.isCoverageEnabled = true; store.issConfig.isCoverageEnabled = true;
store.applicationUser.coverageLookupAttempts = 0; store.applicationUser.coverageLookupAttempts = 0;
@ -1567,9 +1567,9 @@ describe('Store', () => {
expect(globalMethods.callHttpClient).toHaveBeenCalled(); expect(globalMethods.callHttpClient).toHaveBeenCalled();
expect(store.applicationUser.duplicateOrders).toEqual(expected); expect(store.applicationUser.duplicateOrders).toEqual(expected);
}); });
it('Call to client returns exception => object with error property returned and duplicateReferrals set to []', async () => { it('Call to client returns exception => object with error property returned and duplicateReferrals set to [] and no error is returned from getDuplicateReferrals', async () => {
// Arrange // Arrange
expect.assertions(3); expect.assertions(2);
const error = 'get duplicate referrals error'; const error = 'get duplicate referrals error';
globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.reject(error)); globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.reject(error));
@ -1807,7 +1807,8 @@ describe('Store', () => {
vehicleVin, vehicleVin,
policyData, policyData,
isItac: store.isITAC isItac: store.isITAC
}) }),
bailoutOnError: false
})); }));
}); });
it('only "Yes" endorsement answers are added to payload', () => { it('only "Yes" endorsement answers are added to payload', () => {
@ -1912,14 +1913,15 @@ describe('Store', () => {
vehicleVin, vehicleVin,
policyData, policyData,
isItac: store.isITAC isItac: store.isITAC
}) }),
bailoutOnError: false
})); }));
}); });
}); });
describe('unsuccessful api call', () => { describe('unsuccessful api call', () => {
it('api call throws exception', async () => { it('api call throws exception. no error from getFinalDeductible', async () => {
// Arrange // Arrange
expect.assertions(2); expect.assertions(1);
const error = 'final deductible error'; const error = 'final deductible error';
globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.reject(error)); globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.reject(error));
@ -2078,8 +2080,8 @@ describe('Store', () => {
expect(result.data.shopProviders[1]).toBe(provider2); expect(result.data.shopProviders[1]).toBe(provider2);
}); });
}); });
it('api call throws exception => coverageType none', async () => { it('api call throws exception => coverageType none and no error from getCoveragePolicyInfo', async () => {
expect.assertions(3); expect.assertions(2);
const error = 'get coverage policy info error'; const error = 'get coverage policy info error';
store.issConfig.isCoverageEnabled = true; store.issConfig.isCoverageEnabled = true;