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) {
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)
{
global.bailoutOnAxiosError({ method, url, payload, error });
global.bailoutOnAxiosError(errorData);
}
}
return reject(error.response);

View file

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

View file

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

View file

@ -48,7 +48,7 @@ function getPageName(vm) {
// Vue Error Handling
vueApp.config.errorHandler = (err, vm, info) => {
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) {
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
router.onError((err) => {
global.$logger.logError(err.message, err.cause);
global.$logger.logError('Router Error:', err);
if (applicationConfig.BAILOUT_ON_ROUTER_ERROR) {
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 { getDateForSavedSessionTimeout } from '@/helpers/session-helper';
import issPageValues from '@/router/router-constants/issPage-values';
import CoverageStatuses from '@/constants/coverage-statuses';
const storeId = 'main';
@ -528,12 +529,16 @@ export const useMainStore = defineStore({
payload: {}
});
},
getIsVinbyAddressPermissible() {
return globalMethods.callHttpClient({
method: endpoints.IsVinbyAddressPermissible.method,
endpoint: `${endpoints.IsVinbyAddressPermissible.url}?state=${this.order.customer.address.state}`,
payload: {}
});
async getIsVinbyAddressPermissible() {
try {
return globalMethods.callHttpClient({
method: endpoints.IsVinbyAddressPermissible.method,
endpoint: `${endpoints.IsVinbyAddressPermissible.url}?state=${this.order.customer.address.state}`,
payload: {}
});
} catch (e) {
return false;
}
},
async getCoveragePolicyInfo() {
const { order, issConfig, applicationUser } = this;
@ -547,42 +552,47 @@ export const useMainStore = defineStore({
this.applicationUser.coverageAttempts += 1;
console.log(`Coverage lookup attempt #${this.applicationUser.coverageAttempts}. Max attempts allowed: 10.`);
const response = await globalMethods.callHttpClient({
method: endpoints.CoveragePolicyInfo.method,
endpoint: endpoints.CoveragePolicyInfo.url,
payload: {
accountNumber: order.parentAccountNumber?.toString(),
policyNumber: policy.policyNumber,
dateOfLoss: policy.dateOfLoss,
zipCode: policy.policyZipCode,
referralCorrelationId: order.referralCorrelationId
try {
const response = await globalMethods.callHttpClient({
method: endpoints.CoveragePolicyInfo.method,
endpoint: endpoints.CoveragePolicyInfo.url,
payload: {
accountNumber: order.parentAccountNumber?.toString(),
policyNumber: policy.policyNumber,
dateOfLoss: policy.dateOfLoss,
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);
}
});
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 {
} catch (e) {
this.updateCoverageType(coverageType.NONE);
}
},
@ -601,82 +611,81 @@ export const useMainStore = defineStore({
updateIsItacOptimized(isItacOptimized) {
this.order.insuranceCoverage.isItacOptimized = isItacOptimized || false;
},
registerClaim() {
async registerClaim() {
const nonNumberCharRegex = /[^0-9]/g;
const { order, isITAC } = this;
return new Promise((resolve, reject) => {
globalMethods.callHttpClient({
const { isITAC } = this;
try {
const response = await globalMethods.callHttpClient({
method: endpoints.RegisterClaim.method,
endpoint: endpoints.RegisterClaim.url,
payload:
{
referralCorrelationId: this.order.referralCorrelationId,
accountNumber: this.order.parentAccountNumber?.toString() ?? '',
policyData: this.order.policy.policyData,
isItac: isITAC,
insured: {
firstName: this.order.customer.firstName,
lastName: this.order.customer.lastName,
address: {
addressLine1: this.order.customer.address.streetAddress,
addressLine2: this.order.customer.address.streetAddress2,
city: this.order.customer.address.city,
state: this.order.customer.address.state,
zipCode: this.order.customer.address.zipCode,
country: 'US' // TODO set from store
{
referralCorrelationId: this.order.referralCorrelationId,
accountNumber: this.order.parentAccountNumber?.toString() ?? '',
policyData: this.order.policy.policyData,
isItac: isITAC,
insured: {
firstName: this.order.customer.firstName,
lastName: this.order.customer.lastName,
address: {
addressLine1: this.order.customer.address.streetAddress,
addressLine2: this.order.customer.address.streetAddress2,
city: this.order.customer.address.city,
state: this.order.customer.address.state,
zipCode: this.order.customer.address.zipCode,
country: 'US' // TODO set from store
},
homePhone: {
number: this.contactInfo.homePhone?.replaceAll(nonNumberCharRegex, '') ?? ''
}
},
homePhone: {
number: this.contactInfo.homePhone?.replaceAll(nonNumberCharRegex, '') ?? ''
driver: {
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: {
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);
bailoutOnError: false
});
});
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 endorsementAnswers = this.order.policy.endorsementQuestionAnswers;
if (endorsementAnswers) {
@ -692,9 +701,9 @@ export const useMainStore = defineStore({
glassInformation?.forEach((glassPiece) => {
manualGlassNamesArray.push(glassPiece?.glassLocation?.toUpperCase());
});
return new Promise((resolve, reject) => {
globalMethods.callHttpClient({
try {
const r = await globalMethods.callHttpClient({
method: endpoints.FinalDeductible.method,
endpoint: endpoints.FinalDeductible.url,
payload: {
@ -716,16 +725,18 @@ export const useMainStore = defineStore({
vehicleVin: this.order.vehicle.vin,
policyData: this.order.policy.policyData,
isItac: this.isITAC
}
}).then((r) => {
this.order.policy.policyData = r.data.policyData;
this.updateDeductible(r.data);
return resolve(r);
}).catch((error) => reject(error));
});
},
bailoutOnError: false
});
this.order.policy.policyData = r.data.policyData;
this.updateDeductible(r.data);
return r;
} catch (e) {
this.updateCoverageStatus(CoverageStatuses.PENDING);
}
},
getDuplicateReferrals() {
async getDuplicateReferrals() {
const params = new URLSearchParams({
parentAccountNumber: this.order.parentAccountNumber,
customerPhoneNumber: this.order.contactInfo.servicePhone,
@ -734,18 +745,16 @@ export const useMainStore = defineStore({
dateOfLoss: this.order.policy.dateOfLoss
});
return new Promise((resolve, reject) => {
globalMethods.callHttpClient({
try {
const duplicates = await globalMethods.callHttpClient({
method: endpoints.DuplicateSearch.method,
endpoint: `${endpoints.DuplicateSearch.url}?${params.toString()}`
}).then((r) => {
this.applicationUser.duplicateOrders = r.data ?? [];
return resolve(r.data);
}).catch((error) => {
this.applicationUser.duplicateOrders = [];
return reject(error);
endpoint: `${endpoints.DuplicateSearch.url}?${params.toString()}`,
bailoutOnError: false
});
});
this.applicationUser.duplicateOrders = duplicates.data ?? [];
} catch (e) {
this.applicationUser.duplicateOrders = [];
}
},
async lookupVinByPlate(licensePlate, licenseState) {
try {

View file

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