DigitalConsumer.ISS/src/store/index.js
Bill Richardson 309f08961b some updates for schedule
add period
fetch billTo on provider change (needed for time slots)
fix if Adak Alaska on load.
2026-02-18 10:05:32 -05:00

3090 lines
138 KiB
JavaScript

import { defineStore } from 'pinia';
import applicationConfig from '@/constants/application-config';
import bailoutCode from '@/constants/bailoutCode';
import bailoutMessage from '@/constants/bailoutMessage';
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,
getTaxLineItemQueryString
} from '@/helpers/querystring-helper';
import { getTopLevelGlassPartsWithRecal } from '@/helpers/recal-helper';
import { getDateForSavedSessionTimeout } from '@/helpers/session-helper';
import issPageValues from '@/router/router-constants/issPage-values';
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: {}
});
},
getIsVinbyAddressPermissible() {
try {
const response = globalMethods.callHttpClient({
method: endpoints.IsVinbyAddressPermissible.method,
endpoint: `${endpoints.IsVinbyAddressPermissible.url}?state=${this.order.customer.address.state}`,
payload: {}
});
return response;
} catch (responseError) {
return {
error: {
status: responseError.status
}
};
}
},
async getCoveragePolicyInfo() {
const { order, issConfig, applicationUser } = this;
const { policy } = order;
if (!issConfig.isCoverageEnabled || applicationUser.coverageLookupAttempts > 10) {
this.updateCoverageType(coverageType.NONE);
return Promise.resolve();
}
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
}
});
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);
}
return Promise.resolve();
} catch (e) {
this.updateCoverageType(coverageType.NONE);
return Promise.reject(e);
}
},
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;
},
registerClaim() {
const nonNumberCharRegex = /[^0-9]/g;
const { order, isITAC } = this;
return new Promise((resolve, reject) => {
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
}
}
}).then((response) => {
this.order.insuranceCoverage.claimNumber = response.data.claimNumber;
if (response.data.isSuccess) {
this.updateCoverageStatus(coverageStatuses.VERIFIED);
} else {
this.updateCoverageStatus(coverageStatuses.NO_COVERAGE);
}
return resolve(response);
}, (error) => {
this.updateCoverageStatus(coverageStatuses.NO_COVERAGE);
this.order.insuranceCoverage.claimNumber = null;
return reject(error);
});
});
},
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());
});
return new Promise((resolve, reject) => {
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
}
}).then((r) => {
this.order.policy.policyData = r.data.policyData;
this.updateDeductible(r.data);
return resolve(r);
}).catch((error) => reject(error));
});
},
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
});
return new Promise((resolve, reject) => {
globalMethods.callHttpClient({
method: endpoints.DuplicateSearch.method,
endpoint: `${endpoints.DuplicateSearch.url}?${params.toString()}`
}).then((r) => {
this.applicationUser.duplicateOrders = r.data ?? [];
return resolve(r.data);
}).catch((error) => {
this.applicationUser.duplicateOrders = [];
return reject(error);
});
});
},
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
}
}
}).catch((error) => {
console.error(error);
throw error;
});
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
}
});
},
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 }) {
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: false
}).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();
}
},
// 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;
try {
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()}`
});
const billToInfo = response.data;
if (billToInfo != null) {
issConfig.billToAccountNumber = billToInfo.toString();
return Promise.resolve();
}
return Promise.reject(new Error('Invalid billToInfo'));
} catch (e) {
return Promise.reject(e);
}
},
async validateClientTag(clientTag) {
return await 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;
}