DigitalConsumer.ISS/src/store/index.js
Josh Dassinger ea5836b3e4 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
2026-02-19 11:13:29 -06:00

3070 lines
138 KiB
JavaScript

import { defineStore } from 'pinia';
import applicationConfig from '@/constants/application-config';
import bailoutCode from '@/constants/bailoutCode';
import coverageStatuses from '@/constants/coverage-statuses';
import coverageType from '@/constants/coverage-type';
import damageLocationsSelected from '@/constants/damage-locations-selected';
import endpoints from '@/constants/endpoints';
import { experimentSettings, experimentTriggers, experimentUniverses } from '@/constants/experiments';
import partNumberStrings from '@/constants/part-number-strings';
import partTypeStrings from '@/constants/part-type-strings';
import { paymentMethods } from '@/constants/payment-method-constants';
import { AppointmentTypeStrings } from '@/constants/schedule-constants';
import webStorageConstants from '@/constants/web-storage-constants';
import globalMethods from '@/global-methods';
import { getSessionKeyValue, getUserIdValue, deleteISSCookie, getDeviceIdValue } from '@/helpers/cookie-helper';
import { convertDateStringToDate, getDateDifferenceInDays, militaryToTwelveHourTime } from '@/helpers/date-helper';
import { getExperimentSettingValue, getFeatureTogglesPayloadObject } from '@/helpers/experiment-helper';
import { findLineItemIndex, getLineItemsFlattened } from '@/helpers/line-items-helper';
import {
deductibleForSelectedVehicle, endorsementsForSelectedVehicle,
noCoverageForSelectedVehicle,
repairWaivedForSelectedVehicle
} from '@/helpers/policy-vehicle-helper';
import { buildURLSearchParams, getPartNumbersListForQueryString } from '@/helpers/querystring-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';
function getDisplayTextForDurationLength(durationMinimum, durationMaximum) {
const isLongAppointment = durationMaximum >= 120;
const isDurationRange = durationMinimum !== durationMaximum;
const adjustedMinimum = isLongAppointment ? durationMinimum / 60 : durationMinimum;
const adjustedMaximum = isLongAppointment ? durationMaximum / 60 : durationMaximum;
const durationText = isDurationRange
? `${adjustedMinimum} - ${adjustedMaximum}`
: adjustedMinimum;
const unitText = isLongAppointment ? 'hours' : 'minutes';
return `${durationText} ${unitText}`;
}
function getTimeSlotsAdditionalEventData(
provisionalTriggers,
zipCode,
firstAvailableAppointmentDateString,
shopAppointmentType
) {
let numberOfDays = null;
if (firstAvailableAppointmentDateString) numberOfDays = getDateDifferenceInDays(new Date(), firstAvailableAppointmentDateString);
if (shopAppointmentType) return `FirstAvailableAppointment:${numberOfDays},Zip:${zipCode},ShopAppointmentType:${shopAppointmentType},ProvisionalTriggers:${provisionalTriggers.join(',')}`;
return `FirstAvailableAppointment:${numberOfDays},Zip:${zipCode},ProvisionalTriggers:${provisionalTriggers.join(',')}`;
}
export const getDefaultState = () => ({
order: {
vehicle: {
policyVehicleId: null,
year: null,
make: null,
model: null,
style: null,
carId: null,
category: null,
vin: null,
imageUrl: null,
imageVifNumber: null,
imageColor: null,
registration: { // TODO only licensePlate saved in save session
licensePlate: null,
address: null,
city: null,
state: null,
zipCode: null,
firstName: null,
lastName: null
},
isBigTruck: null,
canSafeliteService: null
},
damage: {
isRepair: null,
numberOfChips: null,
glassToReplace: null,
partQuestionAnswers: null,
moldingQuestionAnswers: null,
capabilityQuestionAnswers: null
},
policy: {
policyNumber: null,
policyZipCode: null,
dateOfLoss: null,
damageCause: null,
damageState: null,
damageCity: null,
isDamageGlassOnly: null,
deductible: {
repair: null, // numerical value; how much customer owes on deductible in repair case
replace: null // numerical value; how much customer owes on deductible in replace case,
},
vehicles: [],
endorsements: [],
endorsementQuestionAnswers: [],
status: null,
policyData: null
},
customer: {
address: {
streetAddress: null,
streetAddress2: null,
city: null,
state: null,
zipCode: null
},
firstName: null,
lastName: null,
emailAddress: null
},
serviceLocation: {
address: null,
address2: null,
city: null,
state: null,
zipCode: null,
zipCodeCtu: null,
defaultProviderNumber: null,
appointmentType: null,
isVehicleProtected: null,
IsSafeliteProvider: null,
tpaSearchRadius: null,
provider: {
providerNumber: null,
address: {
streetAddress: null,
city: null,
state: null,
zipCode: null,
zipCodeCtu: null
},
companyName: null,
phoneNumber: null
}
},
lineItems: {
glassParts: null,
otherParts: null,
supportingItems: null,
feeItems: [],
vaps: null,
serverData: null
},
insuranceCoverage: {
coverageStatus: coverageStatuses.PENDING,
coverageType: coverageType.NONE,
isItacOptimized: false,
claimNumber: null
},
payment: {
parentAccountNumber: 0,
nextGenSettledAmount: 0,
paymentMethod: null,
paypalToken: null,
creditCardToken: {
subscriptionId: null,
expMonth: null,
expYear: null,
cardType: null,
billToPostalCode: null,
billToFirstName: null,
billToLastName: null,
referenceNumber: null,
authCode: null,
transactionId: null,
transReferenceNumber: null,
lastFour: null
}
},
contactInfo: {
homePhone: null,
alternativePhone: null,
servicePhone: null,
extension: null,
requestTextUpdates: false,
notesForTechnician: ''
},
schedule: {
date: null,
startTime: null,
endTime: null,
routeCode: null,
jobMaxMinutes: null,
jobMinMinutes: null
},
parentAccountNumber: null,
referralNumber: null,
referralDate: null,
referralCorrelationId: '00000000-0000-0000-0000-000000000000',
referralSequenceNumber: null,
eon: null,
workOrderId: null,
workOrderNumber: null,
settledTenderAmount: null,
lockToken: null,
customerPortalLoginToken: null,
originalDeductible: {
repair: null,
replace: null
},
currentDeductible: {
repair: null,
replace: null
},
totalTaxAmount: null,
waiverReasons: null,
carrierPhoneNumber: null,
loadedFromCookie: false,
loadedFromDupeCheck: null,
loadedSessionClearedPreviousData: null,
availableVaps: null,
visitedDuplicateCheckPage: false
},
applicationUser: {
experiments: [],
eventBus: [], // TODO not in save session
pageData: {},
savedSessionTimeout: getDateForSavedSessionTimeout(),
saveSessionPromise: null,
savedSessionId: '00000000-0000-0000-0000-000000000000',
crmCustomerId: null,
lastPageVisited: null,
triggeredSiteEntry: false, // TODO not in save session
duplicateOrders: [],
hasSentSaveQuoteEmail: null,
coverageLookupAttempts: 0
},
issConfig: {
clientName: 'Generic Insurance', // this is the default and will be overriden by the client's name
clientFullName: 'Generic Insurance', // this is the default and will be overriden by the client's name or client's full name.
clientDisplayName: 'Generic Insurance', // this is the default and will be overridden by the client's name or client display name.
clientPossessiveName: 'Generic Insurance\'s', // this is the default and will be overridden by the client's name or client display name converted to possessive or the clients possessive name.
clientHeader: {},
styleSheet: '', // Stylesheet used by the client.
parentAccountNumber: 0, // Parent account number used by the client.
billToAccountNumber: null,
isCoverageEnabled: false, // Indicates if we should be calling coverage on this flow.
isClaimRegistrationRequired: false, // Indicates if the claim registration call needs to be made for a client to complete coverage verification.
isAuthenticated: false, // Indicates if user is authenticated or not.
enableContinueFromCookie: false, // Indicates if the continue from cookie modal should appear.
enableTPAFlow: false, // Indicates if the TPA flow is supported for this client.
successReturnURL: null, // Client URL to return the user to upon a successfull flow completetion (order submission).
failureReturnURL: null, // Client URL to return the user to when they encounter an error or bailout and are unable to complete the flow.
disabledFields: { // Fields that are disabled and read only if sent over from a client.
policyNumber: null,
policyZipCode: null,
dateOfLoss: null
},
siteType: null,
enableNoCompQuote: false
}
});
export const state = getDefaultState();
export const useMainStore = defineStore({
id: storeId,
state: () => state,
getters: {
billToAccountNumber: (storeState) => storeState.issConfig.billToAccountNumber,
hasRecalibrationPart: (storeState) => getHasRecalibrationPart(storeState),
vehicle: (storeState) => storeState.order.vehicle,
damage: (storeState) => storeState.order.damage,
lineItems: (state) => state.order.lineItems,
payment: (state) => state.order.payment,
policy: (state) => state.order.policy,
serviceLocation: (state) => state.order.serviceLocation,
hasExactlyOneChip: () => state.order.damage.numberOfChips === 1,
isPolicyVehicle: () => state.order.vehicle.policyVehicleId != null,
hasWindshieldReplacement: (s) => {
const { damage, lineItems } = s.order;
return !damage.isRepair
&& (lineItems.glassParts?.some((gp) => gp.partType === partTypeStrings.WINDSHIELD) ?? false);
},
hasAnyNonWindshieldGlassParts: (s) => {
const { damage } = s.order;
const nonWindshieldItems = damage.glassToReplace?.filter((glass) => glass.glassLocation !== damageLocationsSelected.WINDSHIELD);
return !!nonWindshieldItems?.length;
},
hasMoldingPart: (s) => {
return s.order.lineItems.glassParts?.some((glassPart) => {
return glassPart.childParts?.some((childPart) => childPart.partType === partTypeStrings.MOLDING);
});
},
isMobileAppointment: (state) => state.order.serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE
|| state.order.serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP,
isDropOffAppointment: (state) => state.order.serviceLocation.appointmentType === AppointmentTypeStrings.DROP_OFF,
isInShopAppointment: (state) => state.order.serviceLocation.appointmentType === AppointmentTypeStrings.IN_SHOP,
isClaimRegistrationRequired: (state) => state.issConfig.isClaimRegistrationRequired,
isClaimAlreadyRegistered: (state) => state.order.insuranceCoverage.claimNumber !== null,
isBailout: (state) => state.applicationUser.pageData[issPageValues.BAILOUT_PAGE] != null,
bailoutCode: (state) => state.applicationUser.pageData[issPageValues.BAILOUT_PAGE]?.bailoutCode,
isPolicyLookupSuccessful: (s) => s.order.insuranceCoverage.coverageType !== coverageType.NONE,
isNoComp: (s) => s.order.insuranceCoverage.coverageType === coverageType.NO_COMP,
isNoCompQuoteEnabled: (s) => s.issConfig.enableNoCompQuote,
isITAC: (state) => state.order.insuranceCoverage.coverageType === coverageType.ITAC,
isDeductible: (state) => state.order.insuranceCoverage.coverageType === coverageType.Deductible,
isUnverified: (s) => s.order.insuranceCoverage.coverageStatus !== coverageStatuses.VERIFIED,
isVerified: (state) => state.order.insuranceCoverage.coverageStatus === coverageStatuses.VERIFIED,
isPendingClaimRegistration: (state) => state.order.insuranceCoverage.coverageStatus === coverageStatuses.PENDING,
isPayInAdvance: (state) => state.order.payment.paymentMethod != null && state.order.payment.paymentMethod !== paymentMethods.PAY_AT_TIME_OF_SERVICE,
providerNumber: (state) => state.order.serviceLocation.provider.providerNumber || state.order.serviceLocation.defaultProviderNumber,
hasOemEndorsement: (state) => state.order.policy.endorsements?.indexOf('OEM Approved') !== -1 ?? false,
eventBusItem: (state) => (eventCategory, eventSubCategory) => {
const matchedEvent = state.applicationUser.eventBus.find(({ category, subCategory }) => category === eventCategory && subCategory === eventSubCategory);
return matchedEvent?.eventValue;
},
eventBus: (state) => state.applicationUser.eventBus,
applicationUserObj: (state) => state.applicationUser,
pageData: (state) => (page) => (page in state.applicationUser.pageData
? state.applicationUser.pageData[page]
: undefined),
customerData: (state) => {
if (state.order.vehicle.registration.address) {
const { registration } = state.order.vehicle;
return {
addressQuestions: {
streetAddress: registration.address,
city: registration.city,
state: registration.state,
zipCode: registration.zipCode
},
firstName: registration.firstName,
lastName: registration.lastName
};
}
const { address } = state.order.customer;
return {
addressQuestions: {
streetAddress: address.streetAddress,
city: address.city,
state: address.state,
zipCode: address.zipCode
},
firstName: state.order.customer.firstName,
lastName: state.order.customer.lastName
};
},
contactInfo: (s) => ({
firstName: s.order.customer.firstName,
lastName: s.order.customer.lastName,
emailAddress: s.order.customer.emailAddress,
homePhone: s.order.contactInfo.homePhone,
alternativePhone: s.order.contactInfo.alternativePhone,
servicePhone: s.order.contactInfo.servicePhone,
extension: s.order.contactInfo.extension,
requestTextUpdates: s.order.contactInfo.requestTextUpdates ?? false,
notesForTechnician: s.order.contactInfo.notesForTechnician
}),
scheduleDisplayText: (s) => {
const dateModel = convertDateStringToDate(s.order.schedule.date);
const readableDate = dateModel?.toLocaleDateString('en-us', {
weekday: 'long',
month: 'long',
day: 'numeric',
year: 'numeric'
});
const readableStartTime = militaryToTwelveHourTime(s.order.schedule.startTime);
const readableEndTime = militaryToTwelveHourTime(s.order.schedule.endTime);
const readableDuration = getDisplayTextForDurationLength(
s.order.schedule.jobMinMinutes,
s.order.schedule.jobMaxMinutes
);
return {
date: readableDate,
startTime: readableStartTime,
endTime: readableEndTime,
duration: readableDuration
};
},
experimentOrder: (s) => {
const ctuToUse = (s.order.serviceLocation.appointmentType === AppointmentTypeStrings.IN_SHOP
|| s.order.serviceLocation.appointmentType === AppointmentTypeStrings.DROP_OFF)
? s.order.serviceLocation.provider?.address?.zipCodeCtu : s.order.serviceLocation.zipCodeCtu;
return {
funnelVehicleYear: s.order.vehicle.year,
funnelVehicleMake: s.order.vehicle.make,
funnelVehicleModel: s.order.vehicle.model,
funnelVehicleStyle: s.order.vehicle.style,
funnelIsRepair: s.order.damage.isRepair,
funnelNumberOfChips: s.order.damage.numberOfChips,
funnelCarId: s.order.vehicle.carId,
funnelServiceCity: s.order.serviceLocation.city,
funnelServices: s.order.serviceLocation.state,
funnelServiceZipCode: s.order.serviceLocation.zipCode,
funnelServiceZipCodeCtu: ctuToUse,
funnelParentAccountNumber: s.order.parentAccountNumber,
funnelProviderNumber: s.providerNumber,
funnelIsCoverageVerified: s.isVerified,
funnelHasRecalibrationPart: getHasRecalibrationPart(s),
funnelSelectedMultiGlass: s.order.damage.glassToReplace?.length > 1,
funnelSelectedWindshieldGlass: getNonFalseValuesOfPropertyInArrayOfObjects(s.order.damage.glassToReplace, 'glassLocation')
.includes(damageLocationsSelected.WINDSHIELD),
funnelSelectedBackGlass: getNonFalseValuesOfPropertyInArrayOfObjects(s.order.damage.glassToReplace, 'glassLocation')
.includes(damageLocationsSelected.REAR),
funnelSelectedDriverSideGlass: getNonFalseValuesOfPropertyInArrayOfObjects(s.order.damage.glassToReplace, 'glassLocation')
.includes(damageLocationsSelected.DRIVER),
funnelSelectedPassengerSideGlass: getNonFalseValuesOfPropertyInArrayOfObjects(s.order.damage.glassToReplace, 'glassLocation')
.includes(damageLocationsSelected.PASSENGER),
funnelOrderPartNumbers: [
...getNonFalseValuesOfPropertyInArrayOfObjects(
s.order.lineItems.glassParts,
'partNumber'
),
...getNonFalseValuesOfPropertyInArrayOfObjects(
s.order.lineItems.otherParts,
'partNumber'
)
],
funnelOrderPartTypes: [
...getNonFalseValuesOfPropertyInArrayOfObjects(
s.order.lineItems.glassParts,
'recalibrationType'
),
...getNonFalseValuesOfPropertyInArrayOfObjects(
s.order.lineItems.otherParts,
'recalibrationType'
)
]
};
},
experimentSettings: (state) => state.applicationUser.experiments
.filter((x) => !!x.isActive)
.map((x) => x.settings)
.reduce((r, c) => Object.assign(r, c), {}) ?? {},
originalDeductible: (state) => (state.order.damage.isRepair ? state.order.originalDeductible.repair : state.order.originalDeductible.replace),
currentDeductible: (state) => (state.order.damage.isRepair ? state.order.currentDeductible.repair : state.order.currentDeductible.replace)
},
actions:
{
// Content API Actions
lookupVinByAddress({ licenseLastName, licenseStreetAddress, licenseZip, licenseState }) {
return globalMethods.callHttpClient({
method: endpoints.LookupVinByAddress.method,
endpoint: endpoints.LookupVinByAddress.url,
payload: {
licenseLastName,
licenseStreetAddress,
licenseZip,
licenseState
}
});
},
getRouteInfo(pageName) {
return globalMethods.callHttpClient({
method: endpoints.GetRouteInfo.method,
endpoint: endpoints.GetRouteInfo.url(applicationConfig.APPLICATION_ABBREVIATION),
payload: {
pageName
}
});
},
getHomepageName() {
return globalMethods.callHttpClient({
method: endpoints.GetHomepageInfo.method,
endpoint: endpoints.GetHomepageInfo.url(applicationConfig.APPLICATION_ABBREVIATION)
});
},
getPageData(pageName) {
return globalMethods.callHttpClient({
method: endpoints.GetPageData.method,
endpoint: endpoints.GetPageData.url(applicationConfig.APPLICATION_ABBREVIATION, pageName),
payload: {}
});
},
// Vehicle API Actions
getVehicleYears() {
return globalMethods.callHttpClient({
method: endpoints.GetVehicleYears.method,
endpoint: endpoints.GetVehicleYears.url,
payload: {}
});
},
getVehicleMakes() {
return globalMethods.callHttpClient({
method: endpoints.GetVehicleMakes.method,
endpoint: endpoints.GetVehicleMakes.url + this.order.vehicle.year,
payload: {}
});
},
getVehicleModels() {
const encodedMake = encodeURIComponent(this.order.vehicle.make);
return globalMethods.callHttpClient({
method: endpoints.GetVehicleModels.method,
endpoint: `${endpoints.GetVehicleModels.url}/${this.order.vehicle.year}/${encodedMake}`,
payload: {}
});
},
getVehicleStyles() {
const encodedMake = encodeURIComponent(this.order.vehicle.make);
const encodedModel = encodeURIComponent(this.order.vehicle.model);
return globalMethods.callHttpClient({
method: endpoints.GetVehicleStyles.method,
endpoint: `${endpoints.GetVehicleStyles.url}/${this.order.vehicle.year}/${encodedMake}/${encodedModel}`,
payload: {}
});
},
getDamageOptions(carId) {
return globalMethods.callHttpClient({
method: endpoints.GetDamageOptions.method,
endpoint: `${endpoints.GetDamageOptions.url}/${carId}`,
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;
const { policy } = order;
if (!issConfig.isCoverageEnabled || applicationUser.coverageLookupAttempts > 10) {
this.updateCoverageType(coverageType.NONE);
return;
}
this.applicationUser.coverageAttempts += 1;
console.log(`Coverage lookup attempt #${this.applicationUser.coverageAttempts}. Max attempts allowed: 10.`);
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);
}
} catch (e) {
this.updateCoverageType(coverageType.NONE);
}
},
clearDuplicateOrders() {
this.applicationUser.duplicateOrders = [];
},
updateDuplicateCheckVisited(visited) {
this.order.visitedDuplicateCheckPage = visited;
},
updateCoverageStatus(status) {
this.order.insuranceCoverage.coverageStatus = status;
},
updateCoverageType(type) {
this.order.insuranceCoverage.coverageType = type;
},
updateIsItacOptimized(isItacOptimized) {
this.order.insuranceCoverage.isItacOptimized = isItacOptimized || false;
},
async registerClaim() {
const nonNumberCharRegex = /[^0-9]/g;
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
},
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
}
},
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;
}
},
async getFinalDeductible() {
const endorsementAnswersForPayload = [];
const endorsementAnswers = this.order.policy.endorsementQuestionAnswers;
if (endorsementAnswers) {
endorsementAnswers.forEach((endorsement) => {
if (endorsement.selectedAnswer === 'Yes') {
endorsementAnswersForPayload.push(endorsement.endorsementName);
}
});
}
const manualGlassNamesArray = [];
const glassInformation = this.order.damage.glassToReplace;
glassInformation?.forEach((glassPiece) => {
manualGlassNamesArray.push(glassPiece?.glassLocation?.toUpperCase());
});
try {
const r = await globalMethods.callHttpClient({
method: endpoints.FinalDeductible.method,
endpoint: endpoints.FinalDeductible.url,
payload: {
referralCorrelationId: this.order.referralCorrelationId,
accountNumber: this.order.parentAccountNumber?.toString() ?? '',
endorsements: endorsementAnswersForPayload,
manualGlassNames: manualGlassNamesArray,
policyState: this.order.customer.address.state,
status: this.order.policy.status,
originalDeductible: this.originalDeductible,
currentDeductible: this.currentDeductible,
noCoverage: false,
isRepair: this.order.damage.isRepair,
policyNumber: this.order.policy.policyNumber,
insuredFirstName: this.order.customer.firstName,
insuredLastName: this.order.customer.lastName,
insuredZipCode: this.order.customer.address.zipCode,
policyVehicleId: this.order.vehicle.policyVehicleId?.toString() ?? '',
vehicleVin: this.order.vehicle.vin,
policyData: this.order.policy.policyData,
isItac: this.isITAC
},
bailoutOnError: false
});
this.order.policy.policyData = r.data.policyData;
this.updateDeductible(r.data);
return r;
} catch (e) {
this.updateCoverageStatus(CoverageStatuses.PENDING);
}
},
async getDuplicateReferrals() {
const params = new URLSearchParams({
parentAccountNumber: this.order.parentAccountNumber,
customerPhoneNumber: this.order.contactInfo.servicePhone,
policyNumber: this.order.policy.policyNumber,
emailAddress: this.order.customer.emailAddress,
dateOfLoss: this.order.policy.dateOfLoss
});
try {
const duplicates = await globalMethods.callHttpClient({
method: endpoints.DuplicateSearch.method,
endpoint: `${endpoints.DuplicateSearch.url}?${params.toString()}`,
bailoutOnError: false
});
this.applicationUser.duplicateOrders = duplicates.data ?? [];
} catch (e) {
this.applicationUser.duplicateOrders = [];
}
},
async lookupVinByPlate(licensePlate, licenseState) {
try {
const response = await globalMethods.callHttpClient({
method: endpoints.LookupVinByPlate.method,
endpoint: endpoints.LookupVinByPlate.url,
payload: {
licensePlate,
licenseState
}
});
return response;
} catch (responseError) {
return {
error: {
status: responseError.status
}
};
}
},
// PartsOrQuestions API Actions
async getPartsOrQuestions() {
this.resetPartsAndDependencies();
const { vehicle } = this;
const { damage } = this;
const { order } = this;
const { carId } = vehicle;
const glassArray = damage.glassToReplace;
const zipCode = vehicle.registration.zipCode ? vehicle.registration.zipCode : order.customer.address.zipCode;
const { vin } = vehicle;
// create a new array to avoid mutating state
const glassArrayForPayload = convertGlassPieceNamingForApi(glassArray);
const response = await globalMethods.callHttpClient({
method: endpoints.GetPartsOrQuestions.method,
endpoint: endpoints.GetPartsOrQuestions.url,
payload: {
carId,
glassPieces: glassArrayForPayload,
zip: zipCode,
vin,
oemEndorsementFlag: this.hasOemEndorsement
}
});
// Flatten location and name properties
response.data.partsOrQuestions = convertGlassPieceNamingFromApi(response.data.partsOrQuestions);
return response;
},
async getParts() {
const { vehicle } = this.order;
const { damage } = this.order;
const { order } = this;
const { carId } = vehicle;
const glassArray = damage.glassToReplace;
const resultsArray = damage.partQuestionAnswers;
const zipCode = vehicle.registration.zipCode ? vehicle.registration.zipCode : order.customer.address.zipCode;
const { vin } = vehicle;
// create a new array to avoid mutating state
const glassArrayForPayload = convertGlassPieceNamingForApi(glassArray);
const resultsArrayForPayload = convertResultsForApi(resultsArray);
const response = await globalMethods.callHttpClient({
method: endpoints.GetParts.method,
endpoint: endpoints.GetParts.url,
payload: {
carId,
glassPieces: glassArrayForPayload,
answerResults: resultsArrayForPayload,
zip: zipCode,
vin,
oemEndorsementFlag: this.hasOemEndorsement
}
});
// Flatten location and name properties
response.data.glassPieceParts = convertGlassPieceNamingFromApi(response.data.glassPieceParts);
return response;
},
getCapabilityQuestions(carId, partNumber) {
return globalMethods.callHttpClient({
method: endpoints.GetCapabilityQuestions.method,
endpoint: `${endpoints.GetCapabilityQuestions.url}/${carId}/${partNumber}`
});
},
async updatePartFromCapabilityQuestionAnswer(part, capabilityQuestionAnswersForPart) {
return (await globalMethods.callHttpClient({
method: endpoints.GetPartFromCapabilityAnswer.method,
endpoint: endpoints.GetPartFromCapabilityAnswer.url,
payload: {
part,
capabilityAnswerResults: capabilityQuestionAnswersForPart
}
})).data[0];
},
getMobilePremiumFee() {
const damageType = this.damage.isRepair ? 'Repair' : 'Replace';
const paymentType = 'Insurance';
return globalMethods.callHttpClient({
method: endpoints.GetMobilePremiumFee.method,
endpoint: `${endpoints.GetMobilePremiumFee.url}/${paymentType}/${damageType}`
});
},
getMobileTimeSlots(startDate, endDate, zipCodeOverride = null) {
const { order } = this;
const { vehicle } = this.order;
let lineItems = [
...(order.lineItems.supportingItems ?? []),
...(order.lineItems.vaps ?? []),
...(order.lineItems.glassParts ?? [])
];
lineItems = getLineItemsFlattened(lineItems);
lineItems = lineItems.map((lineItem) => ({
partNumber: lineItem.partNumber,
partType: lineItem.partType
}));
const glassPieces = order.damage.glassToReplace
? convertGlassPieceToBackEndCompatibleFormat(order.damage.glassToReplace)
: [];
const payload = {
startDate,
endDate,
applicationName: applicationConfig.APPLICATION_NAME,
billToAccountNumber: this.billToAccountNumber,
parentAccountNumber: order.parentAccountNumber, // this.payment.parentAccountNumber,
carId: vehicle.carId,
lineItems,
glassPieces,
eon: order.eon,
coverage: {
status: '',
deductible: 0,
additionalAuthFlag: ''
},
partSelection: {
hasAnsweredPartQuestions: !!order.damage.partQuestionAnswers?.length,
hasAnsweredMoldingQuestions: !!order.damage.moldingQuestionAnswers?.length,
hasAnsweredCapabilityQuestions: !!order.damage.capabilityQuestionAnswers?.length,
hasManuallySelectedParts:
!!this.applicationUser.pageData['vehicle-parts']?.partsOrQuestions
.length
},
vehicle: {
year: vehicle.year,
make: vehicle.make,
model: vehicle.model,
style: vehicle.style,
vin: vehicle.vin ?? ''
},
zipCode: zipCodeOverride ?? order.serviceLocation.zipCode
};
return globalMethods.callHttpClient({
method: endpoints.GetMobileTimeSlots.method,
endpoint: endpoints.GetMobileTimeSlots.url,
payload
});
},
getShopTimeSlots(startDate, endDate, shopAppointmentType, providerNumber) {
const { order } = this;
const { vehicle } = this.order;
let lineItems = [
...(order.lineItems.supportingItems ?? []),
...(order.lineItems.vaps ?? []),
...(order.lineItems.glassParts ?? [])
];
lineItems = getLineItemsFlattened(lineItems);
lineItems = lineItems.map((lineItem) => ({
partNumber: lineItem.partNumber,
partType: lineItem.partType
}));
const glassPieces = order.damage.glassToReplace
? convertGlassPieceToBackEndCompatibleFormat(order.damage.glassToReplace)
: [];
const payload = {
providerNumber,
startDate,
endDate,
shopAppointmentType: (shopAppointmentType === AppointmentTypeStrings.IN_SHOP
|| shopAppointmentType === AppointmentTypeStrings.DROP_OFF) ? 'InShopOrDropoff' : shopAppointmentType,
applicationName: applicationConfig.APPLICATION_NAME,
billToAccountNumber: this.billToAccountNumber,
parentAccountNumber: this.order.parentAccountNumber, // this.payment.parentAccountNumber,
carId: vehicle.carId,
lineItems,
glassPieces,
eon: order.eon,
coverage: {
status: '',
deductible: 0,
additionalAuthFlag: ''
},
partSelection: {
hasAnsweredPartQuestions: !!order.damage.partQuestionAnswers?.length,
hasAnsweredMoldingQuestions: !!order.damage.moldingQuestionAnswers?.length,
hasAnsweredCapabilityQuestions: !!order.damage.capabilityQuestionAnswers?.length,
hasManuallySelectedParts: !!this.applicationUser.pageData['vehicle-parts']?.partsOrQuestions.length
},
vehicle: {
year: vehicle.year,
make: vehicle.make,
model: vehicle.model,
style: vehicle.style,
vin: vehicle.vin ?? ''
}
};
return globalMethods.callHttpClient({
method: endpoints.GetShopTimeSlots.method,
endpoint: endpoints.GetShopTimeSlots.url,
payload
});
},
async getWipers() {
const { carId } = this.order.vehicle;
const serviceZipCode = this.order.serviceLocation.zipCode;
return globalMethods
.callHttpClient({
method: endpoints.GetWipers.method,
endpoint: `${endpoints.GetWipers.url}/${carId}/${serviceZipCode}`
})
.catch((error) => {
// The wiper service sometimes returns 500s on legitimate carId/zipCode combination - return empty array instead of breaking flow
console.error(error);
return [];
});
},
async getRainDefense() {
return globalMethods
.callHttpClient({
method: endpoints.GetRainDefense.method,
endpoint: `${endpoints.GetRainDefense.url}`
})
.catch((error) => {
// The wiper service sometimes returns 500s on legitimate carId/zipCode combination - return empty array instead of breaking flow
console.error(error);
return [];
});
},
getSafeliteProviders(zipCode, radius = 100) {
return this.getProviders(zipCode, radius, true)
},
getTpaAndSafeliteProviders(zipCode, provderNameSearchString = "") {
const { parentAccountNumber } = this.order;
const carId = this.order.vehicle.carId;
const damageType = this.damage.isRepair ? 'Repair' : 'Install';
const parts = getLineItemsFlattened(this.order.lineItems.glassParts);
const partNumbers = parts.map((part) => part.partNumber).join(',');
let url = `${endpoints.GetTpaAndSafeliteProviders.url}/${zipCode}?accountNumber=${parentAccountNumber}&carId=${carId}&damageType=${damageType}&partNumbers=${partNumbers}`;
if (provderNameSearchString) {
url += `&providerNameSearchString=${provderNameSearchString}`;
}
return new Promise((resolve, reject) => {
globalMethods.callHttpClient({
method: endpoints.GetTpaAndSafeliteProviders.method,
endpoint: url
}).then((response) => resolve(response), (error) => reject(error));
});
},
getProviders(zipcode, radius, safeliteOnly) {
const { carId, isBigTruck } = this.order.vehicle;
const damageType = this.damage.isRepair ? 'Repair' : 'Replace';
const { parentAccountNumber } = this.order;
const partsWithRecal = getTopLevelGlassPartsWithRecal(this.order.lineItems.glassParts);
const windshieldPartWithRecal = partsWithRecal?.length > 0 ? partsWithRecal[0] : null;
return globalMethods.callHttpClient({
method: endpoints.GetProviders.method,
endpoint: endpoints.GetProviders.url(
zipcode,
damageType,
radius,
parentAccountNumber,
safeliteOnly,
carId,
windshieldPartWithRecal?.partNumber,
isBigTruck
)
});
},
getCarrierAccountInfo() {
return new Promise((resolve, reject) => {
globalMethods.callHttpClient({
method: endpoints.GetAccountInfo.method,
endpoint: endpoints.GetAccountInfo.url + this.order.parentAccountNumber
}).then((response) => {
this.order.carrierPhoneNumber = response.data.phoneNumber;
return resolve(response.data);
}).catch((error) => reject(error));
});
},
async getRecalParts() {
const { glassParts } = this.lineItems;
const { carId } = this.vehicle;
const { parentAccountNumber, referralSequenceNumber } = this.order;
const { zipCode } = this.order.serviceLocation;
if (glassParts && glassParts.length > 0) {
const recalPromises = [];
glassParts.forEach((glassPart) => {
if (glassPart.requiresRecalibration) {
const partNumberChecked = glassPart.partNumber;
recalPromises.push(globalMethods
.callHttpClient({
method: endpoints.GetRecalParts.method,
endpoint: endpoints.GetRecalParts.url(
carId,
partNumberChecked,
glassPart.recalibrationType,
parentAccountNumber,
zipCode,
applicationConfig.APPLICATION_NAME,
referralSequenceNumber
)
})
.then((response) => {
const recalResponse = response.data;
if (recalResponse && recalResponse.recalibrationParts && recalResponse.recalibrationParts.length > 0) {
this.addGlassPartRecalibrationInfo(partNumberChecked, recalResponse.recalibrationParts[0]);
}
}));
}
});
await Promise.allSettled(recalPromises);
}
},
addGlassPartRecalibrationInfo(partNumber, recalPartInformation) {
const glassPart = this.lineItems.glassParts.find((gp) => gp.partNumber === partNumber);
if (glassPart) {
const recalChildPart = glassPart.childParts?.find((cp) => cp.partNumber === recalPartInformation.partNumber);
if (!recalChildPart) {
if (!Array.isArray(glassPart.childParts) || !glassPart.childParts.length) {
glassPart.childParts = [];
}
glassPart.childParts.push(recalPartInformation);
}
}
},
async getGlassFees() {
const { insuranceCoverage, vehicle } = this.order;
const { glassParts } = this.lineItems;
const { isRepair } = this.damage;
const { defaultProviderNumber, provider, zipCode } = this.order.serviceLocation;
const damageType = isRepair ? 'Repair' : 'Install';
const facilityType = this.isMobileAppointment ? 'Mobile' : 'InShop';
const providerToUse = provider?.providerNumber ?? defaultProviderNumber;
const partNumberListQueryString = getPartNumbersListForQueryString(glassParts, 'PartNumbers');
const params = new URLSearchParams({
serviceType: damageType,
facilityType,
parentAccountNumber: this.order.parentAccountNumber,
billToAccountNumber: this.billToAccountNumber,
isPremiumAppointment: false,
isItacOptimized: insuranceCoverage.isItacOptimized,
zipCode,
coverageStatus: coverageStatuses.mapToApi(insuranceCoverage.coverageStatus),
coverageType: coverageType.mapToApi(insuranceCoverage.coverageType),
providerNumber: providerToUse,
carId: vehicle.carId
});
return globalMethods.callHttpClient({
method: endpoints.GetGlassFees.method,
endpoint: `${endpoints.GetGlassFees.url}?${params.toString()}${partNumberListQueryString}`
});
},
async getSupportingItems() {
const { glassParts } = this.lineItems;
const { carId } = this.vehicle;
const { isRepair, numberOfChips } = this.damage;
return globalMethods
.callHttpClient({
method: endpoints.GetSupportingItems.method,
endpoint: endpoints.GetSupportingItems.url,
payload: {
carId,
damageType: isRepair ? 'Repair' : 'Replace',
parentAccountNumber: applicationConfig.CASH_PARENT_ACCOUNT_NUMBER,
parts: glassParts ?? [],
numberOfRepairChips: isRepair ? numberOfChips : 0
}
});
},
async getITACPriceOrderItems(availableLineItems) {
const { policy, vehicle, contactInfo, serviceLocation, insuranceCoverage } = this.order;
const response = await globalMethods
.callHttpClient({
method: endpoints.GetITACPriceOrderItems.method,
endpoint: endpoints.GetITACPriceOrderItems.url,
payload: {
lineItems: getLineItemsFlattened(availableLineItems),
ServerData: this.order.lineItems.serverData,
Customer: {
PhoneNumber: contactInfo.servicePhone,
State: policy.damageState || this.order.customer.address.state,
ZipCode: policy.policyZipCode
},
Account: {
ParentAccountNumber: this.order.parentAccountNumber,
LineOfBusiness: 'PERSONAL'
},
Provider: {
ProviderNumber: this.providerNumber,
ProviderCtuNumber: serviceLocation.zipCodeCtu,
ProviderState: serviceLocation.state
},
Vehicle: {
CarId: vehicle.carId,
Year: vehicle.year,
Make: vehicle.make,
Model: vehicle.model
},
Insurance: {
Deductible: this.currentDeductible ?? 0,
PolicyNumber: policy.policyNumber,
CoverageStatus: insuranceCoverage.coverageStatus,
CoverageType: insuranceCoverage.coverageType
},
Order: {
Eon: this.order.eon,
ReferralNumber: this.order.referralNumber,
ReferralSequenceNumber: this.order.referralSequenceNumber,
ReferralDate: `${this.order.referralDate}Z`,
ServiceZipCode: serviceLocation.zipCode,
IsReplacement: !this.isRepair,
IsOEMRequest: this.hasOemEndorsement
}
}
});
const { lineItems, serverData, isItac, primaryBillToNumber, partsWerePriced, isItacOptimized } = response.data;
if (serverData) {
this.order.lineItems.serverData = serverData;
}
if (partsWerePriced) {
this.updateIsItacOptimized(isItacOptimized);
if (isItac) {
// if the ITAC Pricing API call returns isItac = true then we should switch to ITAC coverage type
this.updateCoverageType(coverageType.ITAC);
} else if (this.isITAC) {
// If the ITAC pricing API call returns isItac = false, and we are currently ITAC in the store then we should switch to deductible coverage type
this.updateCoverageType(coverageType.Deductible);
}
}
if (primaryBillToNumber && primaryBillToNumber.length !== 0) {
this.issConfig.billToAccountNumber = primaryBillToNumber;
} else {
await this.getBillToInfo();
}
if (lineItems) {
const retAvailableLineItems = addPricesToLineItems(availableLineItems, lineItems);
return retAvailableLineItems;
}
return availableLineItems;
},
async getCombinedQuote(availableLineItems) {
if (availableLineItems && availableLineItems.length > 0) {
const { vehicle, serviceLocation, policy, eon, referralNumber, referralDate, referralSequenceNumber, lineItems } = this.order;
const availableLineItemsFiltered = availableLineItems.filter((lineItem) => !!(lineItem.partNumber));
const lineItemsWithOnlyPartNumbers = availableLineItemsFiltered.map((lineItem) => ({ partNumber: lineItem.partNumber }));
const payload = {
ParentAccountNumber: this.order.parentAccountNumber,
BillToAccountNumber: this.billToAccountNumber,
ProviderNumber: this.providerNumber,
CarId: vehicle.carId,
Make: vehicle.make,
Model: vehicle.model,
Year: vehicle.year,
EON: eon,
ZipCode: policy.policyZipCode,
State: this.order.customer.address.state,
ReferralNumber: referralNumber,
ReferralDate: referralDate,
ReferralSequenceNumber: referralSequenceNumber,
ServiceZipCode: serviceLocation.zipCode,
IsReplacement: !this.isRepair,
ServerData: lineItems.serverData,
LineItems: lineItemsWithOnlyPartNumbers,
FeatureToggles: getFeatureTogglesPayloadObject(this.experimentSettings)
};
const response = await globalMethods
.callHttpClient({
method: endpoints.GetCombinedQuote.method,
endpoint: endpoints.GetCombinedQuote.url,
payload
})
.catch((error) => {
console.error(error);
return [];
});
const { lineItems: pricedLinedItems, serverData } = response.data;
if (serverData) {
this.order.lineItems.serverData = serverData;
}
if (pricedLinedItems) {
return addPricesToLineItems(availableLineItems, pricedLinedItems);
}
return availableLineItems;
}
return [];
},
getMobileFeePart() {
const { vehicle, insuranceCoverage } = this.order;
const params = new URLSearchParams({
serviceType: this.damage.isRepair ? 'Repair' : 'Install',
facilityType: 'Mobile',
parentAccountNumber: this.order.parentAccountNumber,
billToAccountNumber: this.billToAccountNumber,
isItacOptimized: insuranceCoverage.isItacOptimized,
providerNumber: this.providerNumber,
carId: vehicle.carId,
coverageStatus: coverageStatuses.mapToApi(insuranceCoverage.coverageStatus),
coverageType: coverageType.mapToApi(insuranceCoverage.coverageType)
});
return globalMethods.callHttpClient({
method: endpoints.GetMobileFeePart.method,
endpoint: `${endpoints.GetMobileFeePart.url}?${params.toString()}`
});
},
getServiceabilityDetails({ serviceZipCode }) {
const { vehicle, damage, parentAccountNumber, referralSequenceNumber, lineItems } = this.order;
const { carId } = vehicle;
const glassArray = convertGlassPieceNamingForApi(damage.glassToReplace);
const lineItemParts = [...(lineItems.glassParts || []), ...(lineItems.supportingItems || [])].map((part) => ({
partNumber: part.partNumber,
recalibrationType: part.recalibrationType
}));
const params = buildURLSearchParams({
applicationName: applicationConfig.APPLICATION_NAME,
parentAccountNumber,
referralSequenceNumber,
zip: serviceZipCode,
carId,
glassPieces: glassArray,
lineItems: lineItemParts
});
return globalMethods.callHttpClient({
method: endpoints.GetServiceabilityDetails.method,
endpoint: `${endpoints.GetServiceabilityDetails.url}?${params.toString()}`
});
},
lookupVehicleByVin(vin) {
return globalMethods.callHttpClient({
method: endpoints.LookupVehicleByVin.method,
endpoint: endpoints.LookupVehicleByVin.url,
payload: {
vin
},
bailoutOnError: false
});
},
async setVehicle() {
const encodedMake = encodeURIComponent(this.order.vehicle.make);
const encodedModel = encodeURIComponent(this.order.vehicle.model);
const encodedStyle = encodeURIComponent(this.order.vehicle.style);
const response = await globalMethods
.callHttpClient({
method: endpoints.GetVehicle.method,
endpoint: `${endpoints.GetVehicle.url}/${this.order.vehicle.year}/${encodedMake}/${encodedModel}/${encodedStyle}`,
payload: {}
});
this.updateVehicle(response.data);
return response;
},
setSaveSessionInfo(response) {
this.order.referralNumber = response.referralNumber;
this.order.referralSequenceNumber = response.referralSequenceNumber;
this.order.referralDate = response.referralDate;
this.order.referralCorrelationId = response.referralCorrelationId;
this.order.eon = response.eon;
this.order.workOrderNumber = response.workOrderNumber;
this.order.settledTenderAmount = response.settledTenderAmount;
this.order.lockToken = response.lockToken;
this.order.customerPortalLoginToken = response.customerPortalLoginToken;
this.applicationUser.savedSessionId = response.savedSessionId;
this.applicationUser.crmCustomerId = response.crmCustomerId.toString();
},
saveSession({ submitAfterSave, createWorkOrderNumberForPIA, bailoutOnError }) {
const { vehicle, damage, policy, customer, contactInfo, payment,
lineItems, serviceLocation, schedule, insuranceCoverage } = this.order;
// We don't want to save the session for a loaded session until the car ID is set
if (this.order.loadedFromDupeCheck && !vehicle.carId) {
return Promise.resolve(null);
}
if (this.hasSubmittedOrder()) {
return Promise.resolve(null);
}
const loadedFromDupeCheck = !!(this.order.loadedFromDupeCheck && !this.order.loadedSessionClearedPreviousData);
const newGlassToReplace = convertGlassPieceNamingForApi(damage.glassToReplace);
const shouldClearOnSubmit = this.isVerified && this.isDeductible;
const payloadGlassParts = setClearOnSubmit(lineItems.glassParts, shouldClearOnSubmit);
const payloadSupportingItems = setClearOnSubmit(lineItems.supportingItems, shouldClearOnSubmit);
const payloadVapsItems = setClearOnSubmit(lineItems.vaps, shouldClearOnSubmit);
const payloadFeeItems = setClearOnSubmit(lineItems.feeItems, shouldClearOnSubmit);
const payload = {
applicationUser: {
crmCustomerId: this.applicationUser.crmCustomerId,
experiments: this.applicationUser.experiments,
lastPage: this.applicationUser.lastPageVisited,
pageData: this.applicationUser.pageData,
savedSessionId: this.applicationUser.savedSessionId
},
vehicle: {
year: vehicle.year,
make: vehicle.make,
model: vehicle.model,
style: vehicle.style,
vin: vehicle.vin,
carId: vehicle.carId,
licensePlateNumber: vehicle.registration?.licensePlate
},
damage: {
numberOfChips: damage.numberOfChips,
glassToReplace: newGlassToReplace,
isRepair: damage.isRepair,
partQuestionAnswers: damage.partQuestionAnswers,
moldingQuestionAnswers: damage.moldingQuestionAnswers,
capabilityQuestionAnswers: damage.capabilityQuestionAnswers,
dateOfLoss: policy.dateOfLoss,
damageCause: policy.damageCause,
damageState: policy.damageState,
damageCity: policy.damageCity,
isDamageGlassOnly: policy.isDamageGlassOnly
},
policy: {
policyHolder: {
policyFirstName: customer.firstName,
policyLastName: customer.lastName,
policyPhoneNumber: contactInfo.servicePhone,
policyEmail: customer.emailAddress,
policyState: customer.address.state
},
policyNumber: policy.policyNumber,
policyZipCode: policy.policyZipCode,
originalDeductible: this.originalDeductible,
currentDeductible: this.currentDeductible,
OemEndorsement: this.hasOemEndorsement,
noCoverage: this.isNoComp,
isItac: this.isITAC
},
customer: {
address: {
streetAddress: customer.address?.streetAddress,
streetAddress2: customer.address?.streetAddress2,
city: customer.address?.city,
state: customer.address?.state,
zipCode: customer.address?.zipCode?.toString()
},
emailAddress: customer.emailAddress,
firstName: customer.firstName,
lastName: customer.lastName,
homePhone: contactInfo.extension && contactInfo.homePhone ? contactInfo.homePhone + contactInfo.extension : contactInfo.homePhone,
servicePhone: contactInfo.servicePhone,
alternativePhone: contactInfo.alternativePhone,
isSmsOptIn: contactInfo.requestTextUpdates ?? false
},
lineItems: {
glassParts: payloadGlassParts,
serverData: lineItems.serverData,
supportingItems: [...payloadSupportingItems, ...payloadFeeItems],
vaps: payloadVapsItems
},
insuranceCoverage: {
coverageType: insuranceCoverage.coverageType,
coverageStatus: insuranceCoverage.coverageStatus,
claimNumber: insuranceCoverage.claimNumber
},
payment: {
parentAccountNumber: this.order.parentAccountNumber ?? this.issConfig.parentAccountNumber,
billToAccountNumber: this.billToAccountNumber,
paypalToken: payment.paypalToken,
paymentMethod: payment.paymentMethod === paymentMethods.PayNow ? null : payment.paymentMethod,
nextGenSettledAmount: payment.nextGenSettledAmount,
CCToken: payment.creditCardToken
},
serviceLocation: {
address: {
streetAddress: serviceLocation.address,
city: serviceLocation.city,
state: serviceLocation.state,
zipCode: serviceLocation.zipCode,
zipCodeCtu: serviceLocation.zipCodeCtu
},
appointmentType: (serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE
|| serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP)
? AppointmentTypeStrings.MOBILE : serviceLocation.appointmentType,
isVehicleProtected: serviceLocation.isVehicleProtected,
provider: {
IsSafeliteProvider: serviceLocation?.IsSafeliteProvider,
providerNumber: this.providerNumber,
address: {
streetAddress: serviceLocation.provider?.address?.streetAddress,
city: serviceLocation.provider?.address?.city,
state: serviceLocation.provider?.address?.state,
zipCode: serviceLocation.provider?.address?.zipCode,
zipCodeCtu: serviceLocation.provider?.address?.zipCodeCtu
}
},
techNotes: contactInfo.notesForTechnician
},
schedule: {
date: schedule.date,
startTime: schedule.startTime,
endTime: schedule.endTime,
routeCode: schedule.routeCode,
jobMaxMinutes: schedule.jobMaxMinutes,
jobMinMinutes: schedule.jobMinMinutes
},
referralDate: this.order.referralDate,
referralNumber: this.order.referralNumber?.toString(),
referralCorrelationId: this.order.referralCorrelationId,
referralSequenceNumber: this.order.referralSequenceNumber,
eon: this.order.eon,
submitToMainframe: !!this.order.referralNumber,
createWorkOrderNumberForPIA,
lockToken: this.order.lockToken,
loadedFromDupeCheck,
submitAfterSave: !!submitAfterSave
};
return new Promise((resolve, reject) => {
globalMethods.callHttpClient({
method: endpoints.SaveSession.method,
endpoint: endpoints.SaveSession.url,
payload,
bailoutOnError
}).then((response) => {
if (loadedFromDupeCheck) {
this.order.loadedSessionClearedPreviousData = true;
}
resolve(response);
}, (error) => reject(error));
});
},
/**
* @function getCookieValueByName
* @param {object} payload
* referralNumber: the sv2 referral's referralNumber
* responseDate: the sv2 referral's referralDate or the responseDate associated with the returned duplicate-check record
* parentAccountNumber: the client's parentAccountNumber associated with the sv2 referral
* correlationId: the correlationId associated with the sv2 referral
* @summary
* Gets cookie value by name, returns empty string if not found.
* @returns {object} returns the response object for the load session api, which returns the sv2 referral information
*/
async getReferralByPayload(payload) {
return await globalMethods.callHttpClient({
method: endpoints.LoadSession.method,
endpoint: endpoints.LoadSession.url,
payload: {
referralNumber: payload.referralNumber,
referralDate: payload.responseDate,
parentAccountNumber: payload.parentAccountNumber,
referralCorrelationId: payload.correlationId
}
});
},
async loadSession(duplicate) {
const { order } = this;
const response = await globalMethods.callHttpClient({
method: endpoints.LoadSession.method,
endpoint: endpoints.LoadSession.url,
payload: {
referralNumber: duplicate.referralNumber,
referralDate: duplicate.referralDate,
parentAccountNumber: order.parentAccountNumber,
referralCorrelationId: duplicate.correlationId
}
});
const { data } = response;
if (!data) {
return;
}
if (data?.customer) {
order.customer.firstName = data?.customer?.firstName;
order.customer.lastName = data?.customer?.lastName;
order.customer.emailAddress = data?.customer?.emailAddress;
order.contactInfo.extension = data?.customer?.homePhone?.slice(10);
order.contactInfo.homePhone = data?.customer?.homePhone?.slice(0, 10);
order.contactInfo.servicePhone = data?.customer?.servicePhone;
order.contactInfo.alternativePhone = data?.customer?.alternativePhone;
order.contactInfo.requestTextUpdates = data?.customer?.isSmsOptIn;
if (data?.customer?.address) {
order.customer.address.streetAddress = data.customer?.address?.streetAddress;
order.customer.address.streetAddress2 = data.customer?.address?.streetAddress2;
order.customer.address.city = data.customer?.address?.city;
order.customer.address.state = data.customer?.address?.state;
order.customer.address.zipCode = data.customer?.address?.zipCode;
}
}
if (data?.vehicle) {
order.vehicle.year = data?.vehicle?.year;
order.vehicle.make = data?.vehicle?.make;
order.vehicle.model = data?.vehicle?.model;
order.vehicle.style = data?.vehicle?.style;
}
if (this.isPolicyLookupSuccessful) {
if (data.insuranceCoverage) {
order.insuranceCoverage.coverageType = data?.insuranceCoverage?.coverageType;
order.insuranceCoverage.coverageStatus = data?.insuranceCoverage?.coverageStatus;
order.insuranceCoverage.claimNumber = data?.insuranceCoverage?.claimNumber;
} else if (data?.payment?.insuranceCoverage) {
if (data?.payment?.insuranceCoverage?.isVerified) {
order.insuranceCoverage.coverageStatus = coverageStatuses.VERIFIED;
}
order.insuranceCoverage.claimNumber = data?.payment?.insuranceCoverage?.claimNumber;
}
if (order.policy.vehicles.length !== 0 && data.vehicle?.carId) {
order.vehicle.registration.licensePlate = data?.vehicle?.licensePlateNumber;
if (data.vehicle.vin) {
const vehicle = order.policy.vehicles.find((v) => v.vin === data.vehicle.vin);
if (vehicle) {
const vehicleResponse = await this.lookupVehicleByVin(vehicle.vin);
if (vehicleResponse) {
this.updateVehicle({
...vehicleResponse.data,
policyVehicleId: vehicle.id,
vin: vehicle.vin
});
this.updateVehicleCoverage({
noCoverage: noCoverageForSelectedVehicle(vehicle),
deductible: deductibleForSelectedVehicle(vehicle),
repairWaived: repairWaivedForSelectedVehicle(vehicle),
endorsements: endorsementsForSelectedVehicle(vehicle)
});
}
}
}
}
}
order.referralNumber = data?.referralNumber;
order.referralDate = data?.referralDate;
order.referralCorrelationId = data?.referralCorrelationId;
order.referralSequenceNumber = data?.referralSequenceNumber;
order.eon = data?.eon;
order.loadedFromDupeCheck = true;
order.loadedSessionClearedPreviousData = false;
},
async loadSessionFromCookie(cookie) {
const { order, issConfig } = this;
const response = await this.getReferralByPayload(cookie);
const { data } = response;
if (data) {
order.customer.address.streetAddress = data.customer?.address?.streetAddress;
order.customer.address.streetAddress2 = data.customer?.address?.streetAddress2;
order.customer.address.city = data.customer?.address?.city;
order.customer.address.state = data.customer?.address?.state;
order.customer.address.zipCode = data.customer?.address?.zipCode;
order.customer.firstName = data?.customer?.firstName;
order.customer.lastName = data?.customer?.lastName;
order.customer.emailAddress = data?.customer?.emailAddress;
order.contactInfo.extension = data?.customer?.homePhone?.slice(10);
order.contactInfo.homePhone = data?.customer?.homePhone?.slice(0, 10);
order.contactInfo.servicePhone = data?.customer?.servicePhone;
order.contactInfo.alternativePhone = data?.customer?.alternativePhone;
order.contactInfo.requestTextUpdates = data?.customer?.isSmsOptIn;
if (data.insuranceCoverage) {
order.insuranceCoverage.coverageType = data?.insuranceCoverage?.coverageType;
order.insuranceCoverage.coverageStatus = data?.insuranceCoverage?.coverageStatus;
order.insuranceCoverage.claimNumber = data?.insuranceCoverage?.claimNumber;
} else if (data?.payment?.insuranceCoverage) {
if (data?.payment?.insuranceCoverage?.isVerified) {
order.insuranceCoverage.coverageStatus = coverageStatuses.VERIFIED;
}
order.insuranceCoverage.claimNumber = data?.payment?.insuranceCoverage?.claimNumber;
} else {
order.customer.firstName = data?.customer?.firstName;
order.customer.lastName = data?.customer?.lastName;
}
if (order.policy.vehicles.length !== 0 && data.vehicle?.carId) {
order.vehicle.registration.licensePlate = data?.vehicle?.licensePlateNumber;
if (data.vehicle.vin) {
const vehicle = order.policy.vehicles.find((v) => v.vin === data.vehicle.vin);
if (vehicle) {
const vehicleResponse = await this.lookupVehicleByVin(vehicle.vin);
if (vehicleResponse) {
this.updateVehicle({
...vehicleResponse.data,
policyVehicleId: vehicle.id,
vin: vehicle.vin
});
this.updateVehicleCoverage({
noCoverage: noCoverageForSelectedVehicle(vehicle),
deductible: deductibleForSelectedVehicle(vehicle),
repairWaived: repairWaivedForSelectedVehicle(vehicle),
endorsements: endorsementsForSelectedVehicle(vehicle)
});
}
}
}
order.vehicle.year = data.vehicle.year;
order.vehicle.make = data.vehicle.make;
order.vehicle.model = data.vehicle.model;
order.vehicle.style = data.vehicle.style;
}
order.policy.damageCause = data?.policy?.damageCause;
order.policy.damageCity = data?.policy?.damageCity;
order.policy.damageState = data?.policy?.damageState;
order.policy.dateOfLoss = data?.policy?.dateOfLoss;
order.policy.isDamageGlassOnly = data?.policy?.isDamageGlassOnly;
order.policy.policyNumber = data?.policy?.policyNumber;
order.policy.policyZipCode = data?.policy?.policyZipCode;
order.referralNumber = data?.referralNumber;
order.referralDate = data?.referralDate;
order.referralCorrelationId = data?.referralCorrelationId;
order.referralSequenceNumber = data?.referralSequenceNumber;
order.eon = data?.eon;
order.workOrderId = data?.workOrderId;
order.loadedFromCookie = true;
order.visitedDuplicateCheckPage = true;
order.loadedSessionClearedPreviousData = false;
issConfig.enableContinueFromCookie = false;
this.updateIsSafeliteProvider(data?.provider?.isSafeliteProvider);
}
return data;
},
updateCreditCardToken(token) {
this.order.payment.creditCardToken.subscriptionId = token.subscriptionId;
this.order.payment.creditCardToken.expMonth = token.expMonth;
this.order.payment.creditCardToken.expYear = token.expYear;
this.order.payment.creditCardToken.cardType = token.cardType;
this.order.payment.creditCardToken.billToPostalCode = token.billToPostalCode;
this.order.payment.creditCardToken.billToFirstName = token.billToFirstName;
this.order.payment.creditCardToken.billToLastName = token.billToLastName;
this.order.payment.creditCardToken.referenceNumber = token.referenceNumber;
this.order.payment.creditCardToken.authCode = token.authCode;
this.order.payment.creditCardToken.transactionId = token.transactionId;
this.order.payment.creditCardToken.transReferenceNumber = token.transReferenceNumber;
this.order.payment.creditCardToken.lastFour = token.lastFour;
},
updatePaypalToken(token) {
this.order.payment.paypalToken = token;
},
setSaveSessionPromise(promise) {
this.applicationUser.saveSessionPromise = promise;
},
clearSaveSessionPromise() {
this.applicationUser.saveSessionPromise = null;
},
saveEndorsementQuestionAnswers(endorsementQuestionAnswersArray) {
// if endorsement question answers have changed, reset question answers
const sortedPreviousResultsArray = sortArrayOfObjectsByPropertyValue(this.order.policy.endorsementQuestionAnswers, 'result');
const sortedEndorsementQuestionAnswersArray = sortArrayOfObjectsByPropertyValue(endorsementQuestionAnswersArray, 'result');
const haveEndorsementQuestionAnswersChanged = sortedPreviousResultsArray?.length !== sortedEndorsementQuestionAnswersArray.length
|| !sortedPreviousResultsArray?.every((x, i) => x.result === sortedEndorsementQuestionAnswersArray[i].result);
if (haveEndorsementQuestionAnswersChanged) {
this.updateEndorsementQuestionAnswers(null);
}
this.updateEndorsementQuestionAnswers(endorsementQuestionAnswersArray);
},
saveVehicleDamage(isWindshieldRepair, selectedGlassToReplace, selectedWindshieldChipCount) {
const selectedGlassPassedInSorted = selectedGlassToReplace.slice().sort();
const isGlassToReplaceTheSame = this.order.damage.glassToReplace?.length === selectedGlassToReplace.length
&& this.order.damage.glassToReplace
.slice()
.sort()
.every((obj, index) => obj.glassLocation === selectedGlassPassedInSorted[index].glassLocation
&& obj.glassName === selectedGlassPassedInSorted[index].glassName);
const isWindshieldRepairTheSame = isWindshieldRepair === this.order.damage.isRepair;
const isChipCountTheSame = selectedWindshieldChipCount === this.order.damage.numberOfChips;
const isDamageChanging = !isGlassToReplaceTheSame || !isWindshieldRepairTheSame
|| (isWindshieldRepair && !isChipCountTheSame);
if (isDamageChanging) {
// Reset dependent state when changing
// Was resetGlassPartsState, added dependencies for SSR-290
this.resetPartsAndDependencies();
// Save new values
this.updateIsRepair(isWindshieldRepair);
this.updateNumberOfChips(isWindshieldRepair ? parseInt(selectedWindshieldChipCount) : null);
this.updateGlassToReplace(selectedGlassToReplace);
}
},
updateRegistration(registrationInfo) {
this.order.vehicle.registration.licensePlate = registrationInfo?.licensePlate;
this.order.vehicle.registration.address = registrationInfo?.address;
this.order.vehicle.registration.city = registrationInfo?.city;
this.order.vehicle.registration.state = registrationInfo?.state;
this.order.vehicle.registration.zipCode = registrationInfo?.zipCode;
this.order.vehicle.registration.firstName = registrationInfo?.firstName;
this.order.vehicle.registration.lastName = registrationInfo?.lastName;
},
updateServiceLocation(serviceLocationInfo) {
this.order.serviceLocation.address = serviceLocationInfo.address ?? this.order.serviceLocation.address;
this.order.serviceLocation.address2 = serviceLocationInfo.address2 ?? this.order.serviceLocation.address2;
this.order.serviceLocation.city = serviceLocationInfo.city ?? this.order.serviceLocation.city;
this.order.serviceLocation.state = serviceLocationInfo.state ?? this.order.serviceLocation.state;
this.order.serviceLocation.zipCode = serviceLocationInfo.zipCode ?? this.order.serviceLocation.zipCode;
this.order.serviceLocation.zipCodeCtu = serviceLocationInfo.zipCodeCtu ?? this.order.serviceLocation.zipCodeCtu;
this.order.serviceLocation.appointmentType = serviceLocationInfo.appointmentType ?? this.order.serviceLocation.appointmentType;
this.order.serviceLocation.isVehicleProtected = serviceLocationInfo.isVehicleProtected ?? this.order.serviceLocation.isVehicleProtected;
if (serviceLocationInfo.provider) {
this.order.serviceLocation.provider = {
providerNumber: serviceLocationInfo.provider?.providerNumber,
address: {
streetAddress: serviceLocationInfo.provider?.address?.streetAddress,
city: serviceLocationInfo.provider?.address?.city,
state: serviceLocationInfo.provider?.address?.state,
zipCode: serviceLocationInfo.provider?.address?.zipCode,
zipCodeCtu: serviceLocationInfo.provider?.address?.zipCodeCtu
},
companyName: serviceLocationInfo.provider?.companyName,
phoneNumber: serviceLocationInfo.provider?.phoneNumber
};
}
this.order.serviceLocation.tpaSearchRadius = serviceLocationInfo.tpaSearchRadius;
},
updateServiceLocationProvider(providerInfo) {
this.order.serviceLocation.provider = {
providerNumber: providerInfo?.providerNumber,
address: {
streetAddress: providerInfo?.address?.streetAddress,
city: providerInfo?.address?.city,
state: providerInfo?.address?.state,
zipCode: providerInfo?.address?.zipCode,
zipCodeCtu: providerInfo?.address?.zipCodeCtu
},
companyName: providerInfo?.companyName,
phoneNumber: providerInfo?.phoneNumber
};
},
resetState() {
Object.assign(this, getDefaultState());
},
resetRegistrationState() {
this.order.vehicle.registration.licensePlate = null;
this.order.vehicle.registration.address = null;
this.order.vehicle.registration.city = null;
this.order.vehicle.registration.state = null;
this.order.vehicle.registration.zipCode = null;
this.order.vehicle.registration.firstName = null;
this.order.vehicle.registration.lastName = null;
},
resetServiceLocationAndDependencies() {
this.resetServiceLocationAppointmentType();
this.resetServiceLocationProvider();
this.resetSchedule();
},
resetServiceLocationAppointmentType() {
this.order.serviceLocation.appointmentType = null;
},
resetServiceLocationProvider() {
this.order.serviceLocation.provider = {
providerNumber: null,
companyName: null,
phoneNumber: null,
address: {
streetAddress: null,
city: null,
state: null,
zipCode: null,
zipCodeCtu: null
}
};
},
resetServiceLocationMobileAddress() {
this.order.serviceLocation.address = null;
this.order.serviceLocation.address2 = null;
this.order.serviceLocation.city = null;
this.order.serviceLocation.state = null;
this.order.serviceLocation.isVehicleProtected = null;
},
resetBailout() {
this.updatePageData({
page: issPageValues.BAILOUT_PAGE,
data: null
});
},
resetInsurance() {
this.order.insuranceCoverage.coverageStatus = coverageStatuses.PENDING;
this.order.insuranceCoverage.coverageType = coverageType.NONE;
this.order.insuranceCoverage.isItacOptimized = false;
this.order.insuranceCoverage.claimNumber = null;
},
updateGlassFees(feeData) {
if (feeData == null) {
this.order.lineItems.feeItems = null;
return;
}
feeData.forEach((fee) => {
if (fee.partNumber === partTypeStrings.MOBILE_FEE) {
this.updateMobileFee(fee);
} else if (fee.partNumber === partNumberStrings.RECYCLE_FEE) {
this.updateRecycleFee(fee);
} else {
this.addPartNumberFeeItem(fee, fee.partNumber);
}
});
},
updateSupportingItems(partsData) {
if (partsData == null) {
this.order.lineItems.supportingItems = [];
return;
}
// Process Recycle Fee
this.updateRecycleFee(partsData.find((rf) => rf.partNumber === partNumberStrings.RECYCLE_FEE));
// Remove RecycleFee from supported items as it's saved in feeItems;
this.order.lineItems.supportingItems = partsData.filter((i) => i.partNumber !== partNumberStrings.RECYCLE_FEE);
},
updateVaps(partsData) {
this.order.lineItems.vaps = partsData;
},
updateMobileFee(fee) {
const isMobileFeeHidden = getExperimentSettingValue(this.experimentSettings, experimentSettings.ISS_FEATURE_TOGGLE_IS_MOBILE_FEE_HIDDEN) === 'true';
// Mobile Fee is only added for NO COMP or ITAC and is NOT hidden
if (fee && this.isVerified && (this.isNoComp || this.isITAC) && !isMobileFeeHidden) {
this.addPartTypeFeeItem(fee, partTypeStrings.MOBILE_FEE);
} else {
this.addPartTypeFeeItem(null, partTypeStrings.MOBILE_FEE);
}
},
updateRecycleFee(fee) {
const isRecycleFeeHidden = getExperimentSettingValue(this.experimentSettings, experimentSettings.ISS_FEATURE_TOGGLE_IS_RECYCLE_FEE_HIDDEN) === 'true';
// Recycle Fee is only added for NO COMP or ITAC and has Windshield Replacement and is NOT hidden
if (fee && this.isVerified && (this.isNoComp || this.isITAC) && this.hasWindshieldReplacement && !isRecycleFeeHidden) {
this.addPartNumberFeeItem(fee, partNumberStrings.RECYCLE_FEE);
} else {
this.addPartNumberFeeItem(null, partNumberStrings.RECYCLE_FEE);
}
},
addPartNumberFeeItem(feeItem, partNumber) {
this.addFeeItem(feeItem, (fi) => fi.partNumber !== partNumber);
},
addPartTypeFeeItem(feeItem, partType) {
this.addFeeItem(feeItem, (fi) => fi.partType !== partType);
},
addFeeItem(feeItem, filter) {
let { feeItems } = this.order.lineItems;
// Remove all fee items with the given filter
feeItems = feeItems.filter(filter);
if (feeItem) {
feeItems.push(feeItem);
}
this.order.lineItems.feeItems = feeItems;
},
async setPriceAndSalesTaxForOrderLineItems() {
let lineItemsToTax;
if (this.isVerified && !this.isDeductible) {
lineItemsToTax = [
...(this.order.lineItems.supportingItems ?? []),
...(this.order.lineItems.glassParts ?? []),
...(this.order.lineItems.otherParts ?? []),
...(this.order.lineItems.vaps ?? []),
...(this.order.lineItems.feeItems ?? [])
];
} else {
lineItemsToTax = [
...(this.order.lineItems.vaps ?? []),
...(this.order.lineItems.feeItems ?? [])
];
}
if (lineItemsToTax && lineItemsToTax.length > 0) {
await this.getTaxOrderItems(lineItemsToTax);
}
},
updateVehicle(vehicle) {
// Assuming that the method caller pass all the properties.
// otherwise need to check for undefined for every property.
if (this.order.vehicle.carId !== vehicle.carId
|| (!this.order.vehicle.vin && vehicle.vin)
|| (this.order.vehicle.vin && vehicle.vin && this.order.vehicle.vin !== vehicle.vin)) {
this.order.vehicle.vin = vehicle.vin;
}
this.order.vehicle.policyVehicleId = vehicle.policyVehicleId;
this.order.vehicle.carId = vehicle.carId;
this.order.vehicle.category = vehicle.category;
this.order.vehicle.year = vehicle.year;
this.order.vehicle.make = vehicle.make;
this.order.vehicle.model = vehicle.model;
this.order.vehicle.style = vehicle.style;
this.order.vehicle.imageUrl = vehicle.imageUrl;
this.order.vehicle.imageVifNumber = vehicle.imageVifNumber;
this.order.vehicle.imageColor = vehicle.imageVifColor;
this.order.vehicle.isBigTruck = vehicle.isBigTruck;
this.order.vehicle.canSafeliteService = vehicle.canSafeliteService;
this.updateSupportingItems(null);
this.updateVaps(null);
},
updateVehicleCoverage(coverage) {
if (coverage.noCoverage) {
if (this.isNoCompQuoteEnabled) {
this.updateCoverageType(coverageType.NO_COMP);
} else {
this.updateCoverageType(coverageType.NONE);
}
} else {
this.updateCoverageType(coverageType.Deductible);
}
if (!this.isClaimRegistrationRequired) {
this.updateCoverageStatus(coverageStatuses.VERIFIED);
}
this.order.policy.deductible.replace = coverage.deductible;
this.order.policy.deductible.repair = coverage?.repairWaived ?? false ? 0 : coverage.deductible;
this.order.policy.endorsements = coverage?.endorsements;
this.order.originalDeductible.replace = this.order.policy.deductible.replace;
this.order.currentDeductible.replace = this.order.policy.deductible.replace;
this.order.originalDeductible.repair = this.order.policy.deductible.repair;
this.order.currentDeductible.repair = this.order.policy.deductible.repair;
},
resetOrder() {
this.order.referralNumber = null;
this.order.referralSequenceNumber = null;
this.order.referralDate = null;
this.order.referralSequenceNumber = null;
this.order.workOrderId = null;
this.order.workOrderNumber = null;
this.order.settledTenderAmount = null;
this.order.lockToken = null;
this.order.eon = null;
this.order.originalDeductible.repair = null;
this.order.originalDeductible.replace = null;
this.order.currentDeductible.repair = null;
this.order.currentDeductible.replace = null;
this.order.loadedFromDupeCheck = null;
this.order.loadedSessionClearedPreviousData = null;
this.order.availableVaps = null;
this.order.carrierPhoneNumber = null;
this.order.customerPortalLoginToken = null;
this.order.loadedFromCookie = false;
this.order.visitedDuplicateCheckPage = false;
},
resetPolicy() {
this.order.policy.policyNumber = null;
this.order.policy.policyZipCode = null;
this.order.policy.dateOfLoss = null;
this.order.policy.damageCause = null;
this.order.policy.damageCity = null;
this.order.policy.damageState = null;
this.order.policy.vehicles = [];
this.order.policy.endorsements = [];
this.order.policy.endorsementQuestionAnswers = [];
this.order.policy.policyData = null;
this.order.policy.deductible.repair = null;
this.order.policy.deductible.replace = null;
},
resetPayment() {
this.order.payment.parentAccountNumber = 0;
this.order.payment.nextGenSettledAmount = 0;
this.order.payment.paymentMethod = null;
this.order.payment.paypalToken = null;
this.order.payment.creditCardToken.subscriptionId = null;
this.order.payment.creditCardToken.expMonth = null;
this.order.payment.creditCardToken.expYear = null;
this.order.payment.creditCardToken.cardType = null;
this.order.payment.creditCardToken.billToPostalCode = null;
this.order.payment.creditCardToken.billToFirstName = null;
this.order.payment.creditCardToken.billToLastName = null;
this.order.payment.creditCardToken.referenceNumber = null;
this.order.payment.creditCardToken.authCode = null;
this.order.payment.creditCardToken.transactionId = null;
this.order.payment.creditCardToken.transReferenceNumber = null;
this.order.payment.creditCardToken.lastFour = null;
},
resetCustomer() {
this.order.customer.emailAddress = null;
this.order.customer.firstName = null;
this.order.customer.lastName = null;
this.order.customer.address.city = null;
this.order.customer.address.state = null;
this.order.customer.address.zipCode = null;
this.order.customer.address.streetAddress = null;
this.order.customer.address.streetAddress2 = null;
},
resetContactInfo() {
this.order.contactInfo.homePhone = null;
this.order.contactInfo.alternativePhone = null;
this.order.contactInfo.servicePhone = null;
this.order.contactInfo.extension = null;
this.order.contactInfo.requestTextUpdates = false;
this.order.contactInfo.notesForTechnician = '';
},
resetVehicleState() {
this.order.vehicle.policyVehicleId = null;
this.order.vehicle.year = null;
this.order.vehicle.make = null;
this.order.vehicle.model = null;
this.order.vehicle.style = null;
this.order.vehicle.carId = null;
this.order.vehicle.category = null;
this.order.vehicle.vin = null;
this.order.vehicle.imageUrl = null;
this.order.vehicle.imageVifNumber = null;
this.order.vehicle.imageColor = null;
this.order.vehicle.registration.licensePlate = null;
this.order.vehicle.registration.state = null;
this.order.vehicle.registration.address = null;
this.order.vehicle.registration.city = null;
this.order.vehicle.registration.zipCode = null;
this.order.vehicle.registration.firstName = null;
this.order.vehicle.registration.lastName = null;
this.order.vehicle.isBigTruck = null;
this.order.vehicle.canSafeliteService = null;
if (this.isBailout && this.bailoutCode === bailoutCode.HeavyTruckVehicle) {
this.resetBailout();
}
},
resetGlassPartsState() {
this.order.lineItems.glassParts = null;
this.order.lineItems.supportingItems = [];
this.order.lineItems.vaps = null;
this.order.lineItems.feeItems = [];
this.order.lineItems.serverData = null;
this.order.damage.partQuestionAnswers = null;
this.order.damage.moldingQuestionAnswers = null;
this.order.damage.capabilityQuestionAnswers = null;
this.applicationUser.pageData[issPageValues.PART_QUESTIONS] = null;
this.applicationUser.pageData[issPageValues.VEHICLE_PARTS] = null;
this.applicationUser.pageData[issPageValues.MOLDING_QUESTIONS] = null;
this.applicationUser.pageData[issPageValues.CAPABILITY_QUESTIONS] = null;
},
resetSchedule() {
this.order.schedule.date = null;
this.order.schedule.startTime = null;
this.order.schedule.endTime = null;
this.order.schedule.routeCode = null;
this.order.schedule.jobMaxMinutes = null;
this.order.schedule.jobMinMinutes = null;
},
resetDamageState() {
this.order.damage.isRepair = null;
this.order.damage.numberOfChips = null;
this.order.damage.glassToReplace = null;
},
resetISSConfigState() {
this.issConfig.clientName = 'Generic Insurance';
this.issConfig.clientFullName = 'Generic Insurance';
this.issConfig.clientDisplayName = 'Generic Insurance';
this.issConfig.clientHeader = {};
this.issConfig.parentAccountNumber = 0;
this.issConfig.styleSheet = '';
this.issConfig.isCoverageEnabled = false;
this.issConfig.isAuthenticated = false;
this.issConfig.enableContinueFromCookie = false;
this.issConfig.enableTPAFlow = false;
this.issConfig.isClaimRegistrationRequired = false;
this.issConfig.successReturnURL = null;
this.issConfig.failureReturnURL = null;
this.issConfig.disabledFields.policyNumber = false;
this.issConfig.disabledFields.policyZipCode = false;
this.issConfig.disabledFields.dateOfLoss = false;
this.issConfig.siteType = null;
this.issConfig.enableNoCompQuote = false;
this.issConfig.billToAccountNumber = null;
},
disableKeyFields() {
this.issConfig.disabledFields.policyNumber = true;
this.issConfig.disabledFields.policyZipCode = true;
this.issConfig.disabledFields.dateOfLoss = true;
},
updateVehicleYear(year) {
if (this.order.vehicle.year !== year) {
this.resetVehicleState();
this.resetDamageAndDependencies();
this.order.vehicle.year = year;
}
},
updateVehicleMake(make) {
if (this.order.vehicle.make !== make) {
const { year } = this.order.vehicle;
this.resetVehicleState();
this.resetDamageAndDependencies();
this.order.vehicle.year = year;
this.order.vehicle.make = make;
}
},
updateVehicleModel(model) {
if (this.order.vehicle.model !== model) {
const { year } = this.order.vehicle;
const { make } = this.order.vehicle;
this.resetVehicleState();
this.resetDamageAndDependencies();
this.order.vehicle.year = year;
this.order.vehicle.make = make;
this.order.vehicle.model = model;
}
},
updateVehicleStyle(style) {
if (this.order.vehicle.style !== style) {
const { year } = this.order.vehicle;
const { make } = this.order.vehicle;
const { model } = this.order.vehicle;
this.resetVehicleState();
this.resetDamageAndDependencies();
this.order.vehicle.year = year;
this.order.vehicle.make = make;
this.order.vehicle.model = model;
this.order.vehicle.style = style;
}
},
updateEndorsementQuestionAnswers(answersArray) {
this.order.policy.endorsementQuestionAnswers = answersArray;
},
updateIsRepair(isRepair) {
this.order.damage.isRepair = isRepair;
},
updateNumberOfChips(numberOfChips) {
this.order.damage.numberOfChips = numberOfChips;
},
updateGlassToReplace(glassToReplace) {
this.order.damage.glassToReplace = glassToReplace;
},
updateGlassParts(partsData) {
this.order.lineItems.glassParts = partsData;
},
updateMoldingQuestionAnswers(answersArray) {
this.order.damage.moldingQuestionAnswers = answersArray;
},
updateCapabilityQuestionAnswers(answersArray) {
this.order.damage.capabilityQuestionAnswers = answersArray;
},
updatePartQuestionAnswers(answersArray) {
this.order.damage.partQuestionAnswers = answersArray;
},
updatePageData(pageData) {
this.applicationUser.pageData[pageData.page] = pageData.data;
},
updatePolicyData(welcomePageModel) {
this.order.policy.policyNumber = welcomePageModel?.policyNumber;
this.order.policy.policyZipCode = welcomePageModel?.policyZipCode;
this.order.policy.dateOfLoss = welcomePageModel?.dateOfLoss;
this.order.policy.damageCause = welcomePageModel?.damageCause;
this.order.policy.damageState = welcomePageModel?.damageState;
this.order.policy.damageCity = welcomePageModel?.damageCity;
this.order.policy.isDamageGlassOnly = welcomePageModel?.isDamageGlassOnly;
this.order.serviceLocation.zipCode = welcomePageModel?.policyZipCode;
this.updatePhoneNumbers({
home: welcomePageModel?.phoneNumber,
service: welcomePageModel?.phoneNumber,
extension: welcomePageModel?.extension
});
},
updatePolicyHolderDetails(customerQuestions) {
this.order.customer.address.streetAddress = customerQuestions.addressQuestions.streetAddress;
this.order.customer.address.streetAddress2 = customerQuestions.addressQuestions.streetAddress2;
this.order.customer.address.city = customerQuestions.addressQuestions.city;
this.order.customer.address.state = customerQuestions.addressQuestions.state;
this.order.customer.address.zipCode = customerQuestions.addressQuestions.zipCode;
this.order.customer.firstName = customerQuestions.firstName;
this.order.customer.lastName = customerQuestions.lastName;
this.order.customer.emailAddress = customerQuestions.email;
this.updatePhoneNumbers({
home: customerQuestions.phoneNumber,
service: customerQuestions.phoneNumber,
extension: customerQuestions.extension
});
this.order.serviceLocation.zipCode = customerQuestions.addressQuestions.zipCode;
},
updateIsSafeliteProvider(isSafelite) {
this.order.serviceLocation.IsSafeliteProvider = isSafelite;
},
updateDeductible(deductibleInfo) {
if (this.order.damage.isRepair) {
this.order.currentDeductible.repair = deductibleInfo.deductible;
} else {
this.order.currentDeductible.replace = deductibleInfo.deductible;
}
},
savePartQuestionAnswers(partQuestionAnswersArray) {
// if part question answers have changed, reset subsequent question answers
const sortedPreviousResultsArray = sortArrayOfObjectsByPropertyValue(this.order.damage.partQuestionAnswers, 'result');
const sortedPartQuestionAnswersArray = sortArrayOfObjectsByPropertyValue(partQuestionAnswersArray, 'result');
const havePartQuestionAnswersChanged = sortedPreviousResultsArray?.length !== sortedPartQuestionAnswersArray.length
|| !sortedPreviousResultsArray?.every((x, i) => x.result === sortedPartQuestionAnswersArray[i].result);
if (havePartQuestionAnswersChanged) {
this.resetServiceLocationAndDependencies();
this.updateGlassParts(null);
this.updateMoldingQuestionAnswers(null);
this.updateCapabilityQuestionAnswers(null);
this.updateSupportingItems(null);
this.updateVaps(null);
this.updatePageData({ page: issPageValues.VEHICLE_PARTS, data: null });
this.updatePageData({ page: issPageValues.MOLDING_QUESTIONS, data: null });
this.updatePageData({ page: issPageValues.CAPABILITY_QUESTIONS, data: null });
}
// Save new values
this.updatePartQuestionAnswers(partQuestionAnswersArray);
},
saveMoldingQuestionAnswers(moldingQuestionAnswersArray) {
const sortedPreviousResultsArray = sortArrayOfObjectsByPropertyValue(this.order.damage.moldingQuestionAnswers, 'result');
const sortedMoldingQuestionAnswersArray = sortArrayOfObjectsByPropertyValue(moldingQuestionAnswersArray, 'result');
const haveMoldingQuestionAnswersChanged = sortedPreviousResultsArray?.length !== sortedMoldingQuestionAnswersArray.length
|| !sortedPreviousResultsArray?.every((x, i) => x.result === sortedMoldingQuestionAnswersArray[i].result);
if (haveMoldingQuestionAnswersChanged) {
this.resetServiceLocationAndDependencies();
this.updateGlassParts(null);
this.updateSupportingItems(null);
this.updateCapabilityQuestionAnswers(null);
this.updatePageData({ page: issPageValues.CAPABILITY_QUESTIONS, data: null });
}
// Save new values
this.updateMoldingQuestionAnswers(moldingQuestionAnswersArray);
},
saveCapabilityQuestionAnswers(capabilityQuestionAnswersArray) {
const sortedPreviousResultsArray = sortArrayOfObjectsByPropertyValue(this.order.damage.capabilityQuestionAnswers, 'result');
const sortedCapabilityQuestionAnswersArray = sortArrayOfObjectsByPropertyValue(capabilityQuestionAnswersArray, 'result');
const haveCapabilityQuestionAnswersChanged = sortedPreviousResultsArray?.length !== sortedCapabilityQuestionAnswersArray.length
|| !sortedPreviousResultsArray?.every((x, i) => x.result === sortedCapabilityQuestionAnswersArray[i].result);
if (haveCapabilityQuestionAnswersChanged) {
this.resetServiceLocationAndDependencies();
this.updateGlassParts(null);
this.updateSupportingItems(null);
}
// Save new values
this.updateCapabilityQuestionAnswers(capabilityQuestionAnswersArray);
},
// Tax order actions
async getTaxOrderItems(pricedLineItems) {
const { order } = this;
const { serviceLocation } = order;
const { appointmentType } = serviceLocation;
const serviceLocationCity = serviceLocation.city;
const serviceLocationState = serviceLocation.state;
const serviceLocationZipCode = serviceLocation.zipCode;
const lineItemServerData = this.order.lineItems.serverData;
const isMobileApt = appointmentType === AppointmentTypeStrings.MOBILE
|| appointmentType === AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP;
const retPricedLineItems = await globalMethods.callHttpClient({
method: endpoints.TaxOrderItems.method,
endpoint: endpoints.TaxOrderItems.url,
payload: {
ParentAccountNumber: this.order.parentAccountNumber,
BillToAccountNumber: this.billToAccountNumber,
ProviderNumber: this.providerNumber,
AppointmentType: appointmentType,
PricedLineItems: getLineItemsFlattened(pricedLineItems),
ServiceLocation: {
City: isMobileApt ? serviceLocationCity : null,
State: isMobileApt ? serviceLocationState : null,
ZipCode: isMobileApt ? serviceLocationZipCode : null
},
ServerData: lineItemServerData || ''
}
}).then((response) => {
this.order.lineItems.serverData = response.data.serverData;
return addTaxesToPricedLineItems(pricedLineItems, response.data.taxedLineItems);
});
return retPricedLineItems;
},
addEventToBus(event) {
this.applicationUser.eventBus.push(event);
},
removeEventFromBus(eventData) {
const matchedEvent = this.applicationUser.eventBus.find(({ category, subCategory }) => category === eventData.category && subCategory === eventData.subCategory);
const itemIndex = this.applicationUser.eventBus.indexOf(matchedEvent);
// If the item exists, remove it.
if (itemIndex > -1) {
this.applicationUser.eventBus.splice(itemIndex, 1);
}
},
// populate initial state
populateInitialState(forceReset) {
if (!sessionStorage.getItem(storeId) || forceReset) {
this.$state = getDefaultState();
this.resetSubmittedOrder();
}
},
// Location API Actions
getAlertReasonsByCtu(ctu) {
return globalMethods.callHttpClient({
method: endpoints.GetAlertReasons.method,
endpoint: `${endpoints.GetAlertReasons.url}/${ctu}`,
payload: {}
});
},
// Schedule Actions
saveSchedule(scheduleInfo) {
this.updateSchedule(scheduleInfo);
},
updateSchedule(scheduleInfo) {
if (scheduleInfo) {
this.order.schedule.date = scheduleInfo.date;
this.order.schedule.startTime = scheduleInfo.startTime;
this.order.schedule.endTime = scheduleInfo.endTime;
this.order.schedule.routeCode = scheduleInfo.routeCode;
this.order.schedule.jobMaxMinutes = scheduleInfo.jobMaxMinutes;
this.order.schedule.jobMinMinutes = scheduleInfo.jobMinMinutes;
}
},
// Analytics Actions
logExperimentExposure(pageName, experiment) {
return globalMethods.callHttpClient({
method: endpoints.LogExperimentExposureIfAssigned.method,
endpoint: endpoints.LogExperimentExposureIfAssigned.url,
payload: {
experimentForLogging: {
userId: getUserIdValue(),
deviceId: getDeviceIdValue(),
experimentUniverseId: experiment.universeId,
experimentUniverseName: experiment.universeName,
experimentTestId: experiment.testId,
experimentTestName: experiment.testName,
experimentVariationId: experiment.variationId,
experimentVariationName: experiment.variationName,
enabled: experiment.isActive,
isExposed: experiment.isExposed,
userPartitionNumber: experiment.userPartitionNumber,
assignmentId: experiment.assignmentId,
sessionKey: getSessionKeyValue(),
pageName
}
}
});
},
logExperimentIfExists(pageName, universe) {
const experiment = this.applicationUser.experiments.find((e) => e.universeName === universe);
if (experiment !== undefined) {
this.logExperimentExposure(pageName, experiment);
}
},
logPageView({ userId, sessionKey, pageName, sessionId, action, event, shouldUseSessionId, experimentsForUser }) {
const payload = {
userId,
sessionKey,
sessionId,
pageName,
applicationName: applicationConfig.APPLICATION_NAME,
action,
event,
shouldUseSessionId,
experimentsForUser
};
return globalMethods.callHttpClient({
method: endpoints.LogPageView.method,
endpoint: endpoints.LogPageView.url,
payload,
logApiCall: false
}).then(
(response) => response,
(error) => {
console.log(`Analytics Service Error: ${error.data}`);
}
);
},
logCustomEvent({ userId, sessionKey, pageName, sessionId, category, action, label, value, shouldUseSessionId, experimentsForUser }) {
if (pageName == null || pageName.length === 0) { pageName = 'none'; }
const payload = {
userId,
sessionKey,
sessionId,
pageName,
applicationName: applicationConfig.APPLICATION_NAME,
category,
action,
label,
value,
shouldUseSessionId,
experimentsForUser
};
return globalMethods.callHttpClient({
method: endpoints.LogCustomEvent.method,
endpoint: endpoints.LogCustomEvent.url,
payload,
logApiCall: false
}).then(
(response) => response,
(error) => {
console.log(`Analytics Service Error: ${error.data}`);
}
);
},
logWelcomePageExperiments(issPage) {
this.logExperimentIfExists(issPage, experimentUniverses.ISS_FEATURETOGGLE_AREFEES_HIDDEN);
this.logExperimentIfExists(issPage, experimentUniverses.ISS_FEATURETOGGLE_AREFEES_OVERRIDDEN);
},
initializeSession({ userId, sessionId, userAgent, referrer }) {
const payload = {
applicationName: applicationConfig.APPLICATION_NAME,
userId,
deviceId: userId,
sessionId,
userAgent,
operatorId: 'WEB',
userName: 'SafeliteISS',
referrer
};
return globalMethods.callHttpClient({
method: endpoints.InitializeSession.method,
endpoint: endpoints.InitializeSession.url,
payload,
logApiCall: false
}).then(
(response) => response,
(error) => {
console.log(`Analytics Service Error: ${error.data}`);
}
);
},
updateLastPageVisited(lastPageVisited) {
this.applicationUser.lastPageVisited = lastPageVisited;
},
updateExperiments(experiments) {
this.applicationUser.experiments = experiments;
},
updateTriggeredSiteEntry(wasSiteEntryTriggered) {
this.applicationUser.triggeredSiteEntry = wasSiteEntryTriggered;
},
updateContactInfo(contactInfo) {
this.order.customer.firstName = contactInfo?.firstName ?? this.order.customer.firstName;
this.order.customer.lastName = contactInfo?.lastName ?? this.order.customer.lastName;
this.order.customer.emailAddress = contactInfo?.emailAddress ?? this.order.customer.emailAddress;
this.order.contactInfo.requestTextUpdates = contactInfo?.requestTextUpdates ?? false;
this.order.contactInfo.notesForTechnician = contactInfo?.notesForTechnician ?? '';
},
updatePhoneNumbers(phoneNumbers) {
const contact = this.order.contactInfo;
contact.homePhone = phoneNumbers.home !== undefined ? phoneNumbers.home : contact.homePhone;
contact.alternativePhone = phoneNumbers.alternative !== undefined ? phoneNumbers.alternative : contact.alternativePhone;
contact.servicePhone = phoneNumbers.service !== undefined ? phoneNumbers.service : contact.servicePhone;
contact.extension = phoneNumbers.extension !== undefined ? phoneNumbers.extension : contact.extension;
},
GetExperimentsByUser(userId) {
return globalMethods.callHttpClient({
method: endpoints.GetExperimentsByUser.method,
endpoint: `${endpoints.GetExperimentsByUser.url}/${userId}`,
payload: {}
});
},
async runExperimentsForTrigger({ deviceId, triggerEvent, triggerValue }) {
if (triggerEvent === experimentTriggers.SITE_ENTRY) {
this.updateTriggeredSiteEntry(true);
}
const payload = {
applicationName: applicationConfig.APPLICATION_NAME,
deviceId,
triggerEvent,
triggerValue,
experimentOrder: this.experimentOrder
};
const response = await globalMethods.callHttpClient({
method: endpoints.RunExperimentsForTrigger.method,
endpoint: endpoints.RunExperimentsForTrigger.url,
payload
});
this.updateExperiments(response.data.experiments);
},
async validateZip({ zip }) {
try {
const response = await globalMethods.callHttpClient({
method: endpoints.ValidateZip.method,
endpoint: endpoints.ValidateZip.url(zip)
});
const zipInfo = response.data;
if (zipInfo?.isValid === true) {
this.order.serviceLocation.zipCodeCtu = zipInfo.zipCodeCtu;
this.order.serviceLocation.defaultProviderNumber = zipInfo.providerNumber;
this.order.serviceLocation.state = zipInfo.state;
return Promise.resolve(zipInfo);
}
return Promise.reject(new Error('Invalid Zip Info'));
} catch (e) {
return Promise.reject(e);
}
},
async validateMobileZip({ zip }) {
const damageType = this.order.damage.isRepair ? 'Repair' : 'Replace';
try {
const response = await globalMethods.callHttpClient({
method: endpoints.ValidateZip.method,
endpoint: endpoints.ValidateMobileZip.url(zip, damageType)
});
const zipInfo = response.data;
if (zipInfo?.isValid === true) {
return Promise.resolve(zipInfo);
}
return Promise.reject(new Error('Invalid Zip Info'));
} catch (e) {
return Promise.reject(e);
}
},
async getBillToInfo(componentProviderNumber = null) {
const { order, issConfig } = this;
const params = new URLSearchParams({
parentAccountNumber: order.parentAccountNumber.toString(),
providerNumber: componentProviderNumber || this.providerNumber,
typeOfClaim: 'GLASS ONLY',
lineOfBusiness: 'PERSONAL',
isItac: this.isITAC
});
const response = await globalMethods.callHttpClient({
method: endpoints.GetBillToInfo.method,
endpoint: `${endpoints.GetBillToInfo.url}?${params.toString()}`,
bailoutOnError: false
});
const billToInfo = response.data;
issConfig.billToAccountNumber = billToInfo.toString();
},
async validateClientTag(clientTag) {
return globalMethods.callHttpClient({
method: endpoints.ValidateClientTag.method,
endpoint: `${endpoints.ValidateClientTag.url}/${clientTag}`
});
},
async validateClientSignature(clientTag, token, signature) {
const payload = {
clientTag,
token,
signature
};
return await globalMethods.callHttpClient({
method: endpoints.ValidateClientSignature.method,
endpoint: endpoints.ValidateClientSignature.url,
payload
});
},
saveServiceLocation(serviceLocationInfo) {
this.updateServiceLocation(serviceLocationInfo);
},
saveRegistrationAddressLookup({ isSelectedGlassAvailableForVehicle, vehicleInfo, registrationInfo }) {
// Reset dependent state when changing
if
(
registrationInfo?.address !== this.order.vehicle.registration?.address
|| registrationInfo?.city !== this.order.vehicle.registration?.city
|| registrationInfo?.state !== this.order.vehicle.registration?.state
|| registrationInfo?.zipCode !== this.order.vehicle.registration?.zipCode
|| registrationInfo?.firstName !== this.order.vehicle.registration?.firstName
|| registrationInfo?.lastName !== this.order.vehicle.registration?.lastName
) {
if (!isSelectedGlassAvailableForVehicle) {
this.resetDamageState();
this.resetGlassPartsState();
}
// Save new values
this.updateRegistration(registrationInfo);
}
if (vehicleInfo) {
this.updateVehicle(vehicleInfo);
}
},
saveVin({ isSelectedGlassAvailableForVehicle, vehicleInfo }) {
// Reset dependent state when changing
if (vehicleInfo.vin !== this.order.vehicle.vin) {
this.resetRegistrationAndDependencies();
if (!isSelectedGlassAvailableForVehicle) {
this.resetDamageState();
this.resetGlassPartsState();
}
// Save new values
this.updateVehicle(vehicleInfo);
}
},
saveRegistrationLicensePlateLookup({ isSelectedGlassAvailableForVehicle, vehicleInfo, registrationInfo }) {
// Reset dependent state when changing
if (registrationInfo?.licensePlate !== this.order.vehicle.registration?.licensePlate
|| registrationInfo?.state !== this.order.vehicle.registration?.state) {
this.resetRegistrationAndDependencies();
if (!isSelectedGlassAvailableForVehicle) {
// Dependencies already cleared in above statement
this.resetDamageState();
this.resetGlassPartsState();
}
// Save new values
this.updateVehicle(vehicleInfo);
}
this.updateRegistration(registrationInfo);
},
setBailout(bailoutData) {
const params = new URL(document.location.toString()).searchParams;
const currentPage = params.get('issPage');
this.updatePageData({
page: issPageValues.BAILOUT_PAGE,
data: {
url: window.location.href,
page: currentPage || 'Unknown Page',
bailoutCode: bailoutData.code,
errorMessage: bailoutData.message,
submit: false
}
});
},
setBailoutContactInfo(contact) {
this.order.customer.firstName = contact.firstName;
this.order.customer.lastName = contact.lastName;
this.order.customer.emailAddress = contact.email;
this.updatePhoneNumbers({
home: contact.phoneNumber,
service: contact.phoneNumber
});
this.pageData(issPageValues.BAILOUT_PAGE).submit = true;
},
resetRegistrationAndDependencies() {
this.resetRegistrationState();
this.resetGlassPartsState();
this.updateVaps(null);
},
resetDamageAndDependencies() {
this.resetDamageState();
this.resetGlassPartsState();
this.updateVaps(null);
},
resetPartsAndDependencies() {
this.resetGlassPartsState();
this.updateVaps(null);
this.resetServiceLocationAndDependencies();
},
resetServiceLocation() {
this.order.serviceLocation.state = null;
this.order.serviceLocation.zipCode = null;
this.order.serviceLocation.zipCodeCtu = null;
this.order.serviceLocation.defaultProviderNumber = null;
this.order.serviceLocation.appointmentType = null;
this.order.serviceLocation.IsSafeliteProvider = null;
this.resetServiceLocationProvider();
this.resetServiceLocationMobileAddress();
},
resetPageFields() {
this.resetOrder();
this.resetCustomer();
this.resetPolicy();
this.resetPayment();
this.resetContactInfo();
this.resetVehicleState();
this.resetDamageState();
this.resetGlassPartsState();
this.resetInsurance();
this.resetServiceLocation();
this.resetSchedule();
this.resetBailout();
this.resetSubmittedOrder();
},
savePaymentMethodChoice(paymentMethod) {
this.order.payment.paymentMethod = paymentMethod;
},
getPaymentSignature() {
return globalMethods.callHttpClient({
method: endpoints.GetPaymentSignature.method,
endpoint: endpoints.GetPaymentSignature.url
});
},
hasSubmittedOrder() {
return window.sessionStorage.getItem(webStorageConstants.SUBMITTED_ORDER) !== null;
},
getSubmittedOrder() {
return JSON.parse(window.sessionStorage.getItem(webStorageConstants.SUBMITTED_ORDER));
},
async createSubmittedOrder(submitType) {
if (this.hasSubmittedOrder()) {
return;
}
await this.getCarrierAccountInfo();
const submittedOrder = this.order;
const { experiments } = this.applicationUser;
const { issConfig, hasRecalibrationPart } = this;
submittedOrder.isUnverified = this.isUnverified;
submittedOrder.isVerified = this.isVerified;
submittedOrder.submitType = submitType;
submittedOrder.payment.isPayInAdvance = this.isPayInAdvance;
submittedOrder.hasRecalibrationPart = hasRecalibrationPart;
// set to sessionStorage
window.sessionStorage.setItem(webStorageConstants.SUBMITTED_ORDER, JSON.stringify(submittedOrder));
// clear vuex
this.resetState();
// delete cookie
deleteISSCookie();
// restore issConfig
this.issConfig = issConfig;
// restore user's experiments
this.applicationUser.experiments = experiments;
},
resetSubmittedOrder() {
// clear from sessionStorage
window.sessionStorage.removeItem(webStorageConstants.SUBMITTED_ORDER);
}
},
persist: {
// Default is localStorage, but sessionStorage is used here to ensure state is cleared when the browser tab is closed, preventing potential issues with stale data on return visits.
storage: sessionStorage
}
});
// Private Functions
function getHasRecalibrationPart(state) {
const hasRequiresRecalibration = getNonFalseValuesOfPropertyInArrayOfObjects(state.order.lineItems.glassParts, 'requiresRecalibration')?.length > 0;
const hasRecalibrationType = getNonFalseValuesOfPropertyInArrayOfObjects(state.order.lineItems.glassParts, 'recalibrationType')?.length > 0;
if (hasRequiresRecalibration) {
if (hasRecalibrationType) {
// Has both 'requiresRecalibration' and 'recalibrationType' and 'recalibrationType'
return (
getNonFalseValuesOfPropertyInArrayOfObjects(
state.order.lineItems.glassParts,
'recalibrationType'
)[0].toLowerCase() !== 'unknown'
);
}
// Has 'requiresRecalibration' but no 'recalibrationType' at all
return true;
}
// Does not have 'requiresRecalibration'
return false;
}
function getNonFalseValuesOfPropertyInArrayOfObjects(array, propertyName) {
return (array ?? []).map((x) => x[propertyName]).filter((x) => x);
}
function sortArrayOfObjectsByPropertyValue(arrayOfObjects, propertyName) {
if (!arrayOfObjects) return null;
return arrayOfObjects.sort((a, b) => {
if (a[propertyName] < b[propertyName]) return -1;
if (a[propertyName] > b[propertyName]) return 1;
return 0;
});
}
function convertGlassPieceNamingForApi(glassArray) {
if (!glassArray || glassArray.length === 0) return [];
// check if array already converted. (likely when a session has been saved previously and then reloaded)
if (glassArray[0].location !== undefined) {
return glassArray;
}
const converted = [];
glassArray.forEach((glass) => {
converted.push({
location: glass.glassLocation,
name: glass.glassName
});
});
return converted;
}
function convertResultsForApi(resultsArray) {
if (!resultsArray) return [];
const converted = [];
resultsArray.forEach((answer) => {
converted.push({
location: answer.glassLocation,
name: answer.glassName,
result: answer.result
});
});
return converted;
}
function convertGlassPieceNamingFromApi(glassArray) {
glassArray.forEach((glass) => {
glass.glassLocation = glass.glassPiece.location;
glass.glassName = glass.glassPiece.name;
delete glass.glassPiece;
return glass;
});
return glassArray;
}
function addPricesToLineItems(lineItems, pricingLineItems) {
const partOffset = {};
lineItems.forEach((lineItem) => {
if (lineItem.childParts) {
addPricesToLineItems(lineItem.childParts, pricingLineItems);
}
const { partNumber } = lineItem;
const pricedIndex = findLineItemIndex(pricingLineItems, partNumber, partOffset[partNumber] ?? 0);
if (pricedIndex !== -1) {
const pricedLineItem = pricingLineItems[pricedIndex];
lineItem.laborAmount = pricedLineItem.laborAmount;
lineItem.sellingPrice = pricedLineItem.sellingPrice;
lineItem.kitPrice = pricedLineItem.kitPrice;
partOffset[partNumber] = pricedIndex + 1;
}
});
return lineItems;
}
function addTaxesToPricedLineItems(pricedLineItems, taxingLineItems = []) {
pricedLineItems.forEach((pricedLineItem) => {
const lineItemIndex = taxingLineItems.findIndex((taxingLineItem) => taxingLineItem.partNumber === pricedLineItem.partNumber);
if (pricedLineItem.childParts) {
addTaxesToPricedLineItems(pricedLineItem.childParts, taxingLineItems);
}
const taxedLineItem = taxingLineItems.splice(lineItemIndex, 1)[0];
pricedLineItem.salesTax = taxedLineItem?.salesTax ?? 0;
});
return pricedLineItems;
}
function convertGlassPieceToBackEndCompatibleFormat(glassPieces) {
return glassPieces.map((glassPiece) => ({
location: glassPiece.glassLocation,
name: glassPiece.glassName
}));
}
function providersEqual(providerA, providerB) {
return (
providerA.providerNumber === providerB.providerNumber
&& providerA.address?.city === providerB.address?.city
&& providerA.address?.state === providerB.address?.state
&& providerA.address?.streetAddress === providerB.address?.streetAddress
&& providerA.address?.zipCode === providerB.address?.zipCode
);
// TODO: Change back to deepEqual once zipCodeCtu is added to saveSession.
}
function provisionalTriggersToString(provisionalTriggers) {
return `ProvisionalTriggers:${provisionalTriggers.join(',')}`;
}
function setClearOnSubmit(lineItemArray, shouldClearOnSubmit) {
const retArray = [];
if (lineItemArray && lineItemArray.length > 0) {
lineItemArray.forEach((part) => {
const newPart = { ...part };
newPart.clearOnSubmit = shouldClearOnSubmit;
retArray.push(newPart);
});
}
return retArray;
}