Refactoring welcome page to extract policy lookup and incorporate dupe check navigation

This commit is contained in:
Michaela Brydon 2023-10-11 13:35:21 -04:00
parent a16f4364fa
commit 2594595f2d
4 changed files with 867 additions and 495 deletions

View file

@ -179,13 +179,8 @@ describe('navigation', () => {
test('if duplicates found, navigate to duplicate check page', async () => {
// Arrange
const { wrapper } = getMountedComponent({});
const duplicatesExist = {
policyLookupResponse: {},
duplicateCheckResponse: [{ test: 'a'}]
};
settleAllPromises.mockImplementation(() => Promise.resolve(duplicatesExist));
useMainStore().getDuplicateReferrals = jest.fn().mockImplementation(() => Promise.resolve({}));
useMainStore().applicationUser.duplicateOrders = [{ test: 'a' }];
// Act
await wrapper.vm.forwardButtonAction();
@ -199,39 +194,18 @@ describe('navigation', () => {
{ [routerParams.SAVE_SESSION_SYNCHRONOUS]: true }
);
});
test('if policy and vehicles are found, navigate to policy-vehicle page', async () => {
test('if policy and vehicles are found but no duplicates, navigate to policy-vehicle page', async () => {
// Arrange
const mockvehicles = [
{
vin: 'TEST_VIN'
},
{
vin: 'TEST_VIN2'
}
const { wrapper } = setupMocks({});
useMainStore().getDuplicateReferrals = jest.fn().mockImplementation(() => Promise.resolve({}));
useMainStore().applicationUser.duplicateOrders = [];
useMainStore().order.policy.policyLookupSuccessful = true;
useMainStore().order.policy.vehicles = [
{ vin: 'TEST_VIN' },
{ vin: 'TEST_VIN2' }
];
const { wrapper } = setupMocks({
policies: [{
vehicles: [
{
vin: 'TEST_VIN'
},
{
vin: 'TEST_VIN2'
}
]
}]
});
await wrapper.setData({
vehiclesFound: mockvehicles
});
useMainStore().issConfig.isCoverageEnabled = true;
useMainStore().order.policy.policyNumber = 'p_0001';
useMainStore().order.policy.dateOfLoss = '2022-01-28';
useMainStore().order.accountNumber = '00000';
// Act
await wrapper.vm.forwardButtonAction();
@ -243,20 +217,14 @@ describe('navigation', () => {
{ [routerParams.SAVE_SESSION_SYNCHRONOUS]: true }
);
});
test('if policy is found, but no vehicles, navigate to vehicle-selection page', async () => {
test('if policy is found, but no vehicles and no duplicates, navigate to vehicle-selection page', async () => {
// Arrange
const { wrapper } = setupMocks({
policies: [{}]
});
const { wrapper } = setupMocks({});
useMainStore().getDuplicateReferrals = jest.fn().mockImplementation(() => Promise.resolve({}));
await wrapper.setData({
vehiclesFound: null
});
useMainStore().issConfig.isCoverageEnabled = true;
useMainStore().order.policy.policyNumber = 'p_0001';
useMainStore().order.policy.dateOfLoss = '2022-01-28';
useMainStore().order.accountNumber = '00000';
useMainStore().applicationUser.duplicateOrders = [];
useMainStore().order.policy.policyLookupSuccessful = true;
useMainStore().order.policy.vehicles = [];
// Act
@ -270,16 +238,34 @@ describe('navigation', () => {
{ [routerParams.SAVE_SESSION_SYNCHRONOUS]: true }
);
});
test('if policy is not found, navigate to policy-holder-details page', async () => {
test('if policy is found, but null vehicles and no duplicates, navigate to vehicle-selection page', async () => {
// Arrange
const { wrapper } = setupMocks({
policies: null
});
const { wrapper } = setupMocks({});
useMainStore().getDuplicateReferrals = jest.fn().mockImplementation(() => Promise.resolve({}));
useMainStore().issConfig.isCoverageEnabled = true;
useMainStore().order.policy.policyNumber = 'p_0001';
useMainStore().order.policy.dateOfLoss = '2022-01-28';
useMainStore().order.accountNumber = '00000';
useMainStore().applicationUser.duplicateOrders = [];
useMainStore().order.policy.policyLookupSuccessful = true;
useMainStore().order.policy.vehicles = null;
// Act
await wrapper.vm.forwardButtonAction();
// Assert
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(
navigationScenarios.CLICKED_FORWARD_POLICY_VERIFIED_NO_VEHICLES,
undefined,
{},
{ [routerParams.SAVE_SESSION_SYNCHRONOUS]: true }
);
});
test('if policy is not found and no duplicates, navigate to policy-holder-details page', async () => {
// Arrange
const { wrapper } = setupMocks({});
useMainStore().getDuplicateReferrals = jest.fn().mockImplementation(() => Promise.resolve({}));
useMainStore().order.policy.policyLookupSuccessful = false;
useMainStore().applicationUser.duplicateOrders = [];
// Act
await wrapper.vm.navigateForward();

View file

@ -167,6 +167,7 @@
<script>
// Components
import { Form, defineRule } from 'vee-validate';
import siteHeader from '@/iss-components/site-header/site-header.vue';
import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header.vue';
import siteFooter from '@/iss-components/site-footer/site-footer.vue';
@ -178,7 +179,6 @@ import textBlock from '@/digital-components/text-block/text-block.vue';
// Supporting files
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
import settleAllPromises from '@/helpers/layout-helper';
import { Form, defineRule } from 'vee-validate';
import { required, regex } from '@/helpers/validation-rules';
import errorMessages from '@/constants/error-messages';
import BaseFormMixin from '@/mixins/base-form-mixin.js';
@ -243,7 +243,6 @@ export default {
data() {
return {
welcomePageModel: this.getWelcomePageModelFromStore(),
vehiclesFound: [],
duplicates: [],
rules: {
policyNumber: 'policy-number-required',
@ -298,76 +297,27 @@ export default {
},
methods: {
async forwardButtonAction() {
this.mainStore.updatePolicyData(this.welcomePageModel);
const duplicateCheckResponse = await useMainStore().getDuplicateReferrals();
const duplicatePromiseResultMap = [
{
resultKey: 'duplicateCheckResponse',
promise: duplicateCheckResponse
}
];
const duplicateResultMap = await settleAllPromises(duplicatePromiseResultMap);
this.mainStore.applicationUser.duplicateOrders = duplicateResultMap.duplicateCheckResponse ?? [];
this.duplicates = duplicateResultMap.duplicateCheckResponse;
// call coverage policy lookup if isCoverageEnabled flag enabled
if (this.isCoverageEnabled) {
const policyLookupResponse = useMainStore().getCoveragePolicyInfo({
accountNumber: this.mainStore.order.accountNumber.toString(),
policyNumber: this.mainStore.order.policy.policyNumber,
dateOfLoss: this.mainStore.order.policy.dateOfLoss,
zipCode: this.mainStore.order.policy.policyZipCode
});
const policyPromiseResultMap = [
{
resultKey: 'policyLookupResponse',
promise: policyLookupResponse
useMainStore().updatePolicyData(this.welcomePageModel);
await useMainStore().getDuplicateReferrals()
.finally(async () => {
if (this.isCoverageEnabled) {
await useMainStore().getCoveragePolicyInfo();
}
];
const policyResultMap = await settleAllPromises(policyPromiseResultMap);
const policyInfo = policyResultMap.policyLookupResponse;
// if policy lookup fails, navigate directly to policy-holder-details page
if (!policyInfo) {
this.navigateForward();
}
const policy = policyInfo.policies?.[0];
if (policy) {
// populate policy holder details from policy lookup
this.mainStore.order.customer.address.streetAddress = policy.insureds?.[0]?.address;
this.mainStore.order.customer.address.city = policy.insureds?.[0]?.city;
this.mainStore.order.customer.address.state = policy.insureds?.[0]?.state;
this.mainStore.order.customer.address.zipCode = policy.insureds?.[0]?.zipCode;
this.mainStore.order.customer.firstName = policy.insureds?.[0]?.firstName;
this.mainStore.order.customer.lastName = policy.insureds?.[0]?.lastName;
// populate additional fields
this.mainStore.order.serviceLocation.zipCode = policy.insureds?.[0]?.zipCode;
// populate vehicles
this.mainStore.order.policy.vehicles = policy.vehicles;
this.vehiclesFound = policy.vehicles;
}
return this.navigateForward(policy);
}
return this.navigateForward();
});
},
navigateForward(policy) {
if (this.duplicates?.length > 0 ?? false) {
navigateForward() {
if (useMainStore().applicationUser.duplicateOrders?.length > 0 ?? false) {
this.$router.navigate(
this.navigationScenarios.CLICKED_FORWARD_WITH_DUPLICATES,
this.$route,
{},
{ [routerParams.SAVE_SESSION_SYNCHRONOUS]: true }
);
} else if (policy) {
if (this.vehiclesFound) {
// if policy lookup is successful and vehicles are found, navigate to policy-vehicles page
} else if (this.mainStore.policy.policyLookupSuccessful) {
if (this.mainStore.order.policy.vehicles?.length > 0 ?? false) {
// navigate to policy-vehicles page
this.$router.navigate(
this.navigationScenarios.CLICKED_FORWARD_POLICY_VERIFIED_WITH_VEHICLES,
this.$route,
@ -375,7 +325,6 @@ export default {
{ [routerParams.SAVE_SESSION_SYNCHRONOUS]: true }
);
} else {
// if policy lookup is successful, but no vehicles are associated with the policy
// navigate to vehicle-selection page (manual entry)
this.$router.navigate(
this.navigationScenarios.CLICKED_FORWARD_POLICY_VERIFIED_NO_VEHICLES,

View file

@ -28,7 +28,7 @@ const getDefaultState = () => ({
imageUrl: null,
imageVifNumber: null,
imageColor: null,
registration: {
registration: { // TODO only licensePlate saved in save session
licensePlate: null,
address: null,
city: null,
@ -136,15 +136,16 @@ const getDefaultState = () => ({
},
applicationUser: {
experiments: [],
eventBus: [],
eventBus: [], // TODO not in save session
pageData: {},
savedSessionTimeout: getDateForSavedSessionTimeout(),
saveSessionPromise: null,
savedSessionId: '00000000-0000-0000-0000-000000000000',
crmCustomerId: null,
lastPageVisited: null,
triggeredSiteEntry: false,
duplicateOrders: []
triggeredSiteEntry: false, // TODO not in save session
duplicateOrders: [],
hasSentSaveQuoteEmail: null
},
issConfig: {
clientName: 'Generic Insurance', // this is the default and will be overriden by the client's name
@ -365,36 +366,45 @@ export const useMainStore = defineStore({
};
}
},
getCoveragePolicyInfo({ accountNumber, policyNumber, dateOfLoss, zipCode }) {
getCoveragePolicyInfo() {
const { policy } = this.order;
try {
const response = globalMethods.callHttpClient({
return new Promise((resolve, reject) => {
globalMethods.callHttpClient({
method: endpoints.CoveragePolicyInfo.method,
endpoint: endpoints.CoveragePolicyInfo.url,
payload: {
accountNumber,
policyNumber,
dateOfLoss,
zipCode,
accountNumber: this.order.accountNumber.toString(),
policyNumber: policy.policyNumber,
dateOfLoss: policy.dateOfLoss,
zipCode: policy.policyZipCode,
correlationId: this.order.referralCorrelationId
}
}).then((r) => {
const responsePolicy = r.data.policies?.[0];
policy.policyLookupSuccessful = !!responsePolicy;
return r;
if (policy.policyLookupSuccessful) {
const insured = responsePolicy?.insureds?.[0];
// populate policy holder details from policy lookup
this.order.customer.address.streetAddress = insured?.address;
this.order.customer.address.city = insured?.city;
this.order.customer.address.state = insured?.state;
this.order.customer.address.zipCode = insured?.zipCode;
this.order.customer.firstName = insured?.firstName;
this.order.customer.lastName = insured?.lastName;
// populate additional fields
this.order.serviceLocation.zipCode = insured?.zipCode;
// populate vehicles
this.order.policy.vehicles = responsePolicy?.vehicles ?? [];
}
return resolve(r);
}).catch((error) => {
policy.policyLookupSuccessful = false;
return error;
return reject(error);
});
return response;
} catch (responseError) {
policy.policyLookupSuccessful = false;
return {
error: {
status: responseError.status
}
};
}
});
},
registerClaim() {
const nonNumberCharRegex = /[^0-9]/g;
@ -938,72 +948,126 @@ export const useMainStore = defineStore({
},
loadSession() {
const { applicationUser } = this;
// TODO how to get savedSessionId for a duplicate referral?
const result = globalMethods.callHttpClient({
method: endpoints.SaveSession.method,
endpoint: endpoints.SaveSession.url,
payload: {
savedSessionId: this.applicationUser.savedSessionId?.toString(),
referralNumber: this.order.referralNumber?.toString(),
referralDate: this.order.referralDate?.toString(),
parentAccountNumber: this.issConfig.parentAccountNumber,
referralCorrelationId: this.order.referralCorrelationId
}
return new Promise((resolve, reject) => {
globalMethods.callHttpClient({
method: endpoints.LoadSession.method,
endpoint: endpoints.LoadSession.url,
payload: {
savedSessionId: this.applicationUser.savedSessionId?.toString(),
referralNumber: this.order.referralNumber?.toString(),
referralDate: this.order.referralDate?.toString(),
parentAccountNumber: this.issConfig.parentAccountNumber,
referralCorrelationId: this.order.referralCorrelationId
}
}).then((result) => {
applicationUser.crmCustomerId = result?.applicationUser?.crmCustomerId;
this.applicationUser.experiments = result?.applicationUser?.experiments;
this.applicationUser.lastPageVisited = result?.applicationUser?.lastPage;
this.applicationUser.pageData = result?.applicationUser?.pageData;
this.applicationUser.savedSessionId = result?.applicationUser?.savedSessionId; // TODO this might just be what is passed
this.applicationUser.hasSentSaveQuoteEmail = result?.applicationUser?.hasSentSaveQuoteEmail;
this.order.vehicle.registration.licensePlate = result?.order?.vehicle?.registration?.licensePlateNumber;
this.order.vehicle.imageUrl = result?.order?.vehicle?.imageUrl;
this.order.vehicle.imageColor = result?.order?.vehicle?.imageVifColor;
this.order.vehicle.imageVifNumber = result?.order?.vehicle?.imageVifNumber;
this.order.vehicle.year = result?.order?.vehicle?.year;
this.order.vehicle.make = result?.order?.vehicle?.make;
this.order.vehicle.model = result?.order?.vehicle?.model;
this.order.vehicle.style = result?.order?.vehicle?.style;
this.order.vehicle.carId = result?.order?.vehicle?.carId;
this.order.vehicle.category = result?.order?.vehicle?.category;
this.order.vehicle.vin = result?.order?.vehicle?.vin;
this.order.customer.emailAddress = result?.order?.customer?.emailAddress;
this.order.customer.firstName = result?.order?.policy?.policyHolder?.policyFirstName;
this.order.customer.lastName = result?.order?.policy?.policyHolder?.policyLastName;
this.order.customer.phoneNumber = result?.order?.policy?.policyHolder?.policyPhoneNumber;
// TODO policy state
this.order.customer.address.streetAddress = result?.order?.customer?.address?.streetAddress;
this.order.customer.address.streetAddress2 = result?.order?.customer?.address?.streetAddress2;
this.order.customer.address.city = result?.order?.customer?.address?.city;
this.order.customer.address.state = result?.order?.customer?.address?.state;
this.order.customer.address.zipCode = result?.order?.customer?.address?.zipCode;
this.order.damage.isRepair = result?.order?.damage?.isRepair;
this.order.damage.numberOfChips = result?.order?.damage?.numberOfChips;
this.order.damage.glassToReplace = result?.order?.damage?.glassToReplace; // TODO this might need transformed
this.order.damage.capabilityQuestionAnswers = result?.order?.damage?.capabilityQuestionAnswers;
this.order.damage.moldingQuestionAnswers = result?.order?.damage?.moldingQuestionAnswers;
this.order.damage.partQuestionAnswers = result?.order?.damage?.partQuestionAnswers;
this.order.policy.policyNumber = result?.order?.policy?.policyNumber;
this.order.policy.policyZipCode = result?.order?.policy?.policyZipCode;
this.order.policy.noCoverage = result?.order?.policy?.noCoverage;
this.order.policy.policyLookupSuccessful = result?.order?.policy?.policyLookupSuccessful; // TODO probably don't need to load this
this.order.policy.dateOfLoss = result?.order?.damage?.dateOfLoss;
this.order.policy.damageCause = result?.order?.damage?.damageCause;
this.order.policy.damageState = result?.order?.damage?.damageState;
this.order.policy.damageCity = result?.order?.damage?.damageCity;
this.order.policy.isDamageGlassOnly = result?.order?.damage?.isDamageGlassOnly;
this.order.originalDeductible = result?.order?.policy?.originalDeductible;
this.order.currentDeductible = result?.order?.policy?.currentDeductible;
this.order.lineItems.glassParts = result?.order?.lineItems?.glassParts;
// TODO otherParts
this.order.lineItems.supportingItems = result?.order?.lineItems?.supportingItems;
this.order.lineItems.vaps = result?.order?.lineItems?.vaps;
this.order.payment.isInsurance = result?.order?.payment?.isInsurance;
this.order.payment.insuranceCoverage.isVerified = result?.order?.payment?.insuranceCoverage?.isVerified;
this.order.payment.insuranceCoverage.coverageStatus = result?.order?.payment?.insuranceCoverage?.coverageStatus;
this.order.payment.parentAccountNumber = result?.order?.payment?.parentAccountNumber;
this.issConfig.parentAccountNumber = result?.order?.payment?.parentAccountNumber;
// TODO result.order.payment.insuranceCoverage.claimNumber
this.order.serviceLocation.address = result?.order?.serviceLocation?.streetAddress;
this.order.serviceLocation.address2 = result?.order?.serviceLocation?.streetAddress2;
this.order.serviceLocation.city = result?.order?.serviceLocation?.city;
this.order.serviceLocation.state = result?.order?.serviceLocation?.state;
this.order.serviceLocation.zipCode = result?.order?.serviceLocation?.zipCode;
this.order.serviceLocation.zipCodeCtu = result?.order?.serviceLocation?.zipCodeCtu;
this.order.serviceLocation.appointmentType = result?.order?.serviceLocation?.appointmentType;
this.order.serviceLocation.isVehicleProtected = result?.order?.serviceLocation?.isVehicleProtected;
this.order.serviceLocation.provider.providerNumber = result?.order?.serviceLocation?.provider?.providerNumber;
this.order.serviceLocation.provider.address.streetAddress = result?.order?.serviceLocation?.provider?.address?.streetAddress;
this.order.serviceLocation.provider.address.city = result?.order?.serviceLocation?.provider?.address?.city;
this.order.serviceLocation.provider.address.state = result?.order?.serviceLocation?.provider?.address?.state;
this.order.serviceLocation.provider.address.zipCode = result?.order?.serviceLocation?.provider?.address?.zipCode;
this.order.serviceLocation.provider.address.zipCodeCtu = result?.order?.serviceLocation?.provider?.address?.zipCodeCtu;
this.order.contactInfo.firstName = result?.order?.customer?.firstName;
this.order.contactInfo.lastName = result?.order?.customer?.lastName;
this.order.contactInfo.emailAddress = result?.order?.customer?.emailAddress;
this.order.contactInfo.phoneNumber = result?.order?.customer?.phoneNumber;
this.order.contactInfo.requestTextUpdates = result?.order?.customer?.isSmsOptIn; // TODO confirm
this.order.contactInfo.notesForTechnician = result?.order?.serviceLocation?.techNotes;
// TODO service phone number ??
// TODO isSmsOptIn service ??
this.order.schedule.date = result?.order?.schedule?.date;
this.order.schedule.startTime = result?.order?.schedule?.startTime;
this.order.schedule.endTime = result?.order?.schedule?.endTime;
this.order.schedule.routeCode = result?.order?.schedule?.routeCode;
this.order.schedule.jobMaxMinutes = result?.order?.schedule?.jobMaxMinutes;
// TODO result.order.schedule.jobMinMinutes
this.order.referralNumber = result?.order?.referralNumber;
this.order.referralDate = result?.order?.referralDate;
this.order.referralCorrelationId = result?.order?.referralCorrelationId;
this.order.referralSequenceNumber = result?.order?.referralSequenceNumber;
this.order.eon = result?.order?.eon;
// TODO this.order.workOrderNumber not set
return resolve(result);
}, (error) => {
console.log(error);
reject(error);
});
});
this.applicationUser.crmCustomerId = result.applicationUser.crmCustomerId;
this.applicationUser.experiments = result.applicationUser.experiments;
this.applicationUser.lastPageVisited = result.applicationUser.lastPage;
this.applicationUser.pageData = result.applicationUser.pageData;
this.applicationUser.savedSessionId = result.applicationUser.savedSessionId; // TODO this might just be what is passed
this.order.vehicle.registration.licensePlate = result.order.vehicle.registration.licensePlateNumber;
this.order.vehicle.imageUrl = result.order.vehicle.imageUrl;
this.order.vehicle.imageColor = result.order.vehicle.imageVifColor;
this.order.vehicle.imageVifNumber = result.order.vehicle.imageNumber;
this.order.vehicle.year = result.order.vehicle.year;
this.order.vehicle.make = result.order.vehicle.make;
this.order.vehicle.model = result.order.vehicle.model;
this.order.vehicle.style = result.order.vehicle.style;
this.order.vehicle.carId = result.order.vehicle.carId;
this.order.vehicle.category = result.order.vehicle.category;
this.order.vehicle.vin = result.order.vehicle.vin;
this.order.damage.isRepair = result.order.damage.isRepair;
this.order.damage.numberOfChips = result.order.damage.numberOfChips;
this.order.damage.glassToReplace = result.order.damage.glassToReplace; // TODO this might need transformed
this.order.damage.capabilityQuestionAnswers = result.order.damage.capabilityQuestionAnswers;
this.order.damage.moldingQuestionAnswers = result.order.damage.moldingQuestionAnswers;
this.order.damage.partQuestionAnswers = result.order.damage.partQuestionAnswers;
this.order.policy.policyNumber = result.order.policy.policyNumber;
this.order.policy.policyZipCode = result.order.policy.policyZipCode;
this.order.policy.noCoverage = result.order.policy.noCoverage;
this.order.policy.policyLookupSuccessful = result.order.policy.policyLookupSuccessful; // TODO probably don't need to load this
this.order.policy.dateOfLoss = result.order.damage.dateOfLoss;
this.order.policy.damageCause = result.order.damage.damageCause;
this.order.policy.damageState = result.order.damage.damageState;
this.order.policy.damageCity = result.order.damage.damageCity;
this.order.policy.isDamageGlassOnly = result.order.damage.isDamageGlassOnly;
this.order.originalDeductible = result.order.policy.originalDeductible;
this.order.currentDeductible = result.order.policies.currentDeductible;
// customer: {
// address: {
// streetAddress: null,
// streetAddress2: null,
// city: null,
// state: null,
// zipCode: null
// },
// firstName: null,
// lastName: null,
// emailAddress: null,
// phoneNumber: null
// },
},
setSaveSessionPromise(promise) {

File diff suppressed because it is too large Load diff