AfterPay Updates

This commit is contained in:
Bill Richardson 2024-03-06 15:58:33 -05:00
parent ecc056c686
commit 6c013bc0ad
9 changed files with 352 additions and 47 deletions

View file

@ -116,6 +116,10 @@ const endpoints = Object.freeze({
url: `${ACCOUNT_BASE_URL}/`,
method: 'GET'
},
TaxOrderItems: {
url: '/price/api/v1/price/taxed-order-items',
method: 'GET'
},
LogExperimentExposureIfAssigned: {
url: `${EXPERIMENTS_BASE_URL}/log-exposure`,
method: 'POST'

View file

@ -23,7 +23,13 @@ export default {
return this.genericVehicleImage;
}
const { imageUrl } = this.mainStore.order.vehicle;
let imageUrl = '';
if (this.mainStore.hasSubmittedOrder()) {
imageUrl = this.mainStore.submittedOrder.vehicle.imageUrl;
} else {
imageUrl = this.mainStore.order.vehicle.imageUrl;
}
if (!imageUrl || imageUrl === 'NULL') {
return this.getUnmatchedVehicleIcon();
}

View file

@ -58,7 +58,9 @@ import settleAllPromises from '@/helpers/layout-helper';
import { Form } from 'vee-validate';
import BaseFormMixin from '@/mixins/base-form-mixin.js';
import { useMainStore } from '@/store';
import { get12HourTimeFormat, get12HourTimeMobileFormat, convertDateStringToDate,
import { get12HourTimeFormat,
get12HourTimeMobileFormat,
convertDateStringToDate,
getDisplayTextForDurationLength } from '@/helpers/date-helper.js';
import { toTitleCase } from '@/helpers/text-helper.js';
import { AppointmentTypeStrings } from '@/constants/schedule-constants';
@ -66,14 +68,15 @@ import { AppointmentTypeStrings } from '@/constants/schedule-constants';
export default {
name: 'order-confirmation',
components: {
// eslint-disable-next-line vue/no-reserved-component-names
Form,
siteHeader,
vehicleBanner,
siteFooter,
// eslint-disable-next-line vue/no-reserved-component-names
Form
siteFooter
},
mixins: [BaseFormMixin],
async beforeRouteEnter(to, from, next) {
useMainStore().createSubmittedOrder();
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
// Settle promises and get results
@ -90,7 +93,8 @@ export default {
},
setup() {
const mainStore = useMainStore();
return { mainStore };
const { submittedOrder } = mainStore;
return { mainStore, submittedOrder };
},
computed: {
carrierName() {
@ -106,16 +110,16 @@ export default {
return this.getCmsContent('OrderConfirmationContent', 'Image');
},
appointmentType() {
return this.mainStore.order.serviceLocation.appointmentType;
return this.submittedOrder.serviceLocation.appointmentType;
},
appointmentDate() {
return this.mainStore.order.schedule.date;
return this.submittedOrder.schedule.date;
},
appointmentStartTime() {
return this.mainStore.order.schedule.startTime;
return this.submittedOrder.schedule.startTime;
},
appointmentEndTime() {
return this.mainStore.order.schedule.endTime;
return this.submittedOrder.schedule.endTime;
},
appointmentDateFormatted() {
// This conversion ensures we don't get get GMT induced date changes
@ -144,35 +148,35 @@ export default {
return this.getBodyText2FromCms('DropOffAndInShopWordingWidget');
},
serviceLocationAddress() {
return this.mainStore.order.serviceLocation.address;
return this.submittedOrder.serviceLocation.address;
},
serviceLocationAddress2() {
return this.mainStore.order.serviceLocation.address2;
return this.submittedOrder.serviceLocation.address2;
},
serviceLocationCity() {
return this.mainStore.order.serviceLocation.city;
return this.submittedOrder.serviceLocation.city;
},
serviceLocationState() {
return this.mainStore.order.serviceLocation.state;
return this.submittedOrder.serviceLocation.state;
},
serviceLocationZipCode() {
return this.mainStore.order.serviceLocation.zipCode;
return this.submittedOrder.serviceLocation.zipCode;
},
serviceLocationFullAddress() {
// eslint-disable-next-line max-len
return `<br/>${this.serviceLocationAddress}, ${this.serviceLocationAddress2 ? `${this.serviceLocationAddress2},` : ''}<br/> ${this.serviceLocationCity}, ${this.serviceLocationState} ${this.serviceLocationZipCode}<br/>`;
return `${this.serviceLocationAddress}, ${this.serviceLocationAddress2 ? `${this.serviceLocationAddress2},` : ''}<br/> ${this.serviceLocationCity}, ${this.serviceLocationState} ${this.serviceLocationZipCode}`;
},
providerAddress() {
return toTitleCase(this.mainStore.order.serviceLocation.provider.address.streetAddress);
return toTitleCase(this.submittedOrder.serviceLocation.provider.address.streetAddress);
},
providerCity() {
return toTitleCase(this.mainStore.order.serviceLocation.provider.address.city);
return toTitleCase(this.submittedOrder.serviceLocation.provider.address.city);
},
providerState() {
return this.mainStore.order.serviceLocation.provider.address.state;
return this.submittedOrder.serviceLocation.provider.address.state;
},
providerZipCode() {
return this.mainStore.order.serviceLocation.provider.address.zipCode;
return this.submittedOrder.serviceLocation.provider.address.zipCode;
},
providerFullAddress() {
// eslint-disable-next-line max-len
@ -217,18 +221,19 @@ export default {
}
},
mobileAppointment() {
return this.mainStore.isMobileAppointment;
return this.submittedOrder.serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE
|| this.submittedOrder.serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP;
},
inShopAppointment() {
return this.mainStore.isInShopAppointment;
return this.submittedOrder.serviceLocation.appointmentType === AppointmentTypeStrings.IN_SHOP;
},
dropOffAppointment() {
return this.mainStore.isDropOffAppointment;
return this.submittedOrder.serviceLocation.appointmentType === AppointmentTypeStrings.DROP_OFF;
},
inShopAppointmentDuration() {
const inshopDurationTime = getDisplayTextForDurationLength(
this.mainStore.order.schedule.jobMinMinutes,
this.mainStore.order.schedule.jobMaxMinutes
this.submittedOrder.schedule.jobMinMinutes,
this.submittedOrder.schedule.jobMaxMinutes
);
return inshopDurationTime;
}
@ -310,6 +315,9 @@ $page-side-padding: 1.5rem;
}
.appointment-text {
:deep(p) {
margin: 0;
}
:deep(strong) {
font-weight: $font-weight-bold;
color: $black;

View file

@ -33,7 +33,6 @@
ref="siteFooter"
cmsWidgetName="SiteFooterWidget"
:isForwardActionDisabled="!meta.valid"
:isBackButtonHidden="shouldHideBackButton"
:isStackedVertically="true"
@backClicked="navigateBack"
@ForwardClicked="forwardButtonAction" />

View file

@ -1,9 +1,5 @@
<template>
<Form
ref="theForm"
v-slot="{ meta }"
@submit="onSubmit"
@invalidSubmit="onInvalidSubmit">
<Form>
<div class="page-container-grouped-styles">
<div class="fade-on-route-transition position-relative">
<siteHeader cmsWidgetName="SiteHeaderWidget" />
@ -21,12 +17,12 @@
</div>
<siteFooter
ref="siteFooter"
cmsWidgetName="SiteFooterWidget"
:isForwardActionDisabled="true"
:isForwardButtonHidden="true"
@ForwardClicked="forwardButtonAction"
@backClicked="backButtonAction" />
ref="siteFooter"
cmsWidgetName="SiteFooterWidget"
:isForwardActionDisabled="true"
:isForwardButtonHidden="true"
@ForwardClicked="forwardButtonAction"
@backClicked="backButtonAction" />
</div>
</div>
@ -367,6 +363,7 @@ import issPageValues from '@/router/router-constants/issPage-values.js';
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
import settleAllPromises from '@/helpers/layout-helper';
import { Form } from 'vee-validate';
import baseMixin from '@/mixins/base-mixin.js';
import BaseFormMixin from '@/mixins/base-form-mixin.js';
import { useMainStore } from '@/store';
import iframeResize from 'iframe-resizer/js/iframeResizer.js';
@ -402,6 +399,9 @@ export default {
const paymentSignaturePromise = await useMainStore().getPaymentSignature();
const wipersPromise = useMainStore().getWipers();
const rainDefensePromise = useMainStore().getRainDefense();
// Settle promises and get results
const promiseResultMap = [
{
@ -411,16 +411,50 @@ export default {
{
resultKey: 'paymentSignature',
promise: paymentSignaturePromise
},
{
resultKey: 'wipers',
promise: wipersPromise
},
{
resultKey: 'rainDefense',
promise: rainDefensePromise
}
];
// use resultMap to populate layout content.
const resultMap = await settleAllPromises(promiseResultMap);
const lineItemsFromStore = useMainStore().lineItems;
const glassParts = lineItemsFromStore.glassParts ?? [];
const supportingItems = lineItemsFromStore.supportingItems ?? [];
const lineItemsToTax = [
resultMap.rainDefense,
...supportingItems,
...resultMap.wipers,
...glassParts
];
const availableVaps = [resultMap.rainDefense, ...resultMap.wipers];
const pricedLineItemsToTax = await useMainStore().priceOrderItemsAndSaveServerData(lineItemsToTax);
const taxedLineItems = await useMainStore().taxOrderItemsAndSaveServerData(pricedLineItemsToTax);
// Match all line items to the line items as they are in the store
// and rebuild the original structure.
const taxLineItems = useMainStore().mapTaxedLineItemsToStoreFormat(taxedLineItems, lineItemsFromStore);
const taxedVaps = useMainStore().mapTaxedLineItemsToStoreFormat(taxedLineItems, availableVaps);
next((vm) => {
vm.setCmsContent(resultMap.cmsContent);
vm.setData(taxedVaps, taxLineItems);
vm.$nextTick(() => {
if (vm.$refs.cart) {
const { cartItems } = vm.$refs.cart;
vm.getPayInAdvanceLineItems(cartItems);
} else {
vm.getMockPiaLineItems();
}
vm.fetchSignatureInfo(resultMap.paymentSignature);
vm.setIFrameListener();
});
@ -460,11 +494,11 @@ export default {
computed: {
payInAdvanceResponseUrl() {
const { protocol, host } = window.location;
return `${protocol}//${host}/?issPage=${issPageValues.PAYMENT_RETURN}&src=iss-nextgen`;
return `${protocol}//${host}/?issPage=${issPageValues.PAYMENT_RETURN}&src=concept-funnel`;
},
payInAdvanceCancelUrl() {
const { protocol, host } = window.location;
return `${protocol}//${host}/?issPage=${issPageValues.PAYMENT_METHOD}&src=iss-nextgen`;
return `${protocol}//${host}/?issPage=${issPageValues.PAYMENT_METHOD}&src=concept-funnel`;
},
dynamicCSSUrl() {
const { protocol, hostname, port } = window.location;
@ -553,6 +587,10 @@ export default {
&& paymentMethodReqs
);
},
setData(taxedVaps, taxLineItems) {
this.availableVaps = taxedVaps;
this.lineItems = taxLineItems;
},
getWorkOrderNumber() {
const { workOrderNumber } = useMainStore().order;
if (workOrderNumber) {
@ -597,11 +635,37 @@ export default {
return useMainStore().payment.payInAdvanceType;
}
},
getPayInAdvanceLineItems(cartItems) {
const { glassParts } = useMainStore().order.lineItems;
let lineItems = [];
if (glassParts === null) {
lineItems = ['Labor|0|1', 'Repair supplies|0|1'];
} else {
lineItems = ['Parts and labor|0|1'];
}
cartItems.forEach((item) => {
if (item.name !== null && item.category !== 'promos') {
lineItems.push(`${item.name}|${(item.salesTax + item.subTotal).toFixed(2)}|1`);
}
});
this.payInAdvanceLineItems = lineItems.join('||');
},
getMockPiaLineItems() {
let lineItems = [];
lineItems = ['Parts and labor|0|1'];
lineItems.push('New wiper blades|75.22|1');
lineItems.push('Recycling|37.60|1');
this.payInAdvanceLineItems = lineItems.join('||');
},
getAmountDue() {
return 0;
return baseMixin.methods.getAmountDue(useMainStore().lineItems);
},
getDisplayAmountDue() {
return 0;
return baseMixin.methods.getDisplayAmountDue(useMainStore().lineItems);
},
fetchSignatureInfo(signatureInfo) {
this.authToken = signatureInfo.token;
@ -631,7 +695,8 @@ export default {
handleIFrameContentWindowMessage(event) {
if (typeof event.data === 'string') {
if (event.data.indexOf('afterpayClosed') > -1) {
this.backButtonAction();
console.log('trigger back button...');
// this.backButtonAction();
}
if (event.data.indexOf('creditCardSubmit') > -1) {
this.setUIBlock(true);

View file

@ -36,6 +36,58 @@ export default {
savePageDataToStore(page, data) {
useMainStore().updatePageData({ page, data });
},
getTotalPriceOfAllLineItemsAndChildParts(lineItems, includeTax) {
let totalPrice = 0;
lineItems.forEach((lineItem) => {
totalPrice += this.getTotalLineItemPrice(lineItem, includeTax);
if (lineItem.childParts) {
totalPrice += this.getTotalPriceOfAllLineItemsAndChildParts(
lineItem.childParts,
includeTax
);
}
});
return totalPrice;
},
getTotalLineItemPrice(lineItem, includeTax) {
if (includeTax) {
return (
lineItem.kitPrice
+ lineItem.laborAmount
+ lineItem.sellingPrice
+ lineItem.salesTax
);
}
return lineItem.kitPrice + lineItem.laborAmount + lineItem.sellingPrice;
},
getDisplayAmountDue(lineItems) {
return this.getAmountDue(lineItems).toLocaleString('en-US', {
style: 'currency',
currency: 'USD'
});
},
getAmountDue(lineItems) {
let amountDue = 0;
if (lineItems.glassParts) {
amountDue += this.getTotalPriceOfAllLineItemsAndChildParts(
lineItems.glassParts,
false
);
}
if (lineItems.supportingItems) {
amountDue += this.getTotalPriceOfAllLineItemsAndChildParts(
lineItems.supportingItems,
false
);
}
if (lineItems.vaps) {
amountDue += this.getTotalPriceOfAllLineItemsAndChildParts(lineItems.vaps, false);
}
if (lineItems.promos) {
amountDue += this.getTotalPriceOfAllLineItemsAndChildParts(lineItems.promos, false);
}
return ((amountDue * 100) / 100).toFixed(2);
},
scrollToPageTop() {
const container = document.getElementsByClassName('page-container-grouped-styles')[0];
container.scrollTo({ top: 0, left: 0, behavior: 'smooth' });

View file

@ -46,6 +46,13 @@ const routes = [
await runExperiments(issPageToUse); // fmg has this further down
}
// Intercept all navigation if a submitted order exists in storage
if (useMainStore().hasSubmittedOrder()) {
if (to.query.issPage !== issPageValues.ENTRY_PAGE) {
return await GoToOrderConfirmationPage(next);
}
}
// If the saved session has timed out, clear the session, execute 404 logic.
if (getISSCookie() !== null && !isSavedSessionStillActive()) {
// await baseMixin.methods.dispatchStoreAction(storeActions.RESET_STATE);
@ -127,8 +134,16 @@ router.beforeEach(async (to, from) => {
showIssLoadingModal(true);
}
const toQueryPage = to.query?.issPage;
const notToPayInAdvanceReturn = toQueryPage !== issPageValues.PAYMENT_RETURN;
const isInIframe = fromQueryPage === issPageValues.PAYMENT_PAGE;
if (isInIframe) {
// fromPaymentToConfirmation workaround for navigating from an iframe but
// isInIframe evaluates to false for some reason when navigating from payment to confirmation
const fromPaymentToConfirmation =
fromQueryPage === issPageValues.PAYMENT_PAGE && toQueryPage === issPageValues.ORDER_CONFIRMATION;
if ((isInIframe && notToPayInAdvanceReturn) || fromPaymentToConfirmation) {
// need to set window.top.location.href directly when navigating out of an iframe
// especially when navigating with browser buttons
const newUrl = `${window.top.location.origin}${to.href}`;
@ -347,6 +362,20 @@ async function GoToAccessIsDenied(next) {
});
}
async function GoToOrderConfirmationPage(next) {
const nextPageName = issPageValues.ORDER_CONFIRMATION;
router.addRoute({
path: '/',
name: nextPageName,
component: lazyLoadComponent(nextPageName)
});
next({
name: nextPageName,
query: { issPage: nextPageName }
});
}
async function GoToStartOn404(next, msgCopy = null, msgHeadline = null) {
const errorPageName = issPageValues.WELCOME_PAGE;
router.addRoute({

View file

@ -654,7 +654,7 @@ const routingTable = () => [
},
{
scenario: navigationScenarios.PAY_IN_ADVANCE_SUCCESS,
destinationIssPageValue: issPageValues.CONFIRMATION
destinationIssPageValue: issPageValues.ORDER_CONFIRMATION
}
]
},

View file

@ -12,6 +12,7 @@ import issPageValues from '@/router/router-constants/issPage-values';
import damageLocationsSelected from '@/constants/damage-locations-selected';
import coverageStatuses from '@/constants/coverage-statuses';
import { AppointmentTypeStrings, PREMIUM_FEE_PART_TYPE } from '@/constants/schedule-constants';
import { deepClone } from '@/helpers/object-helper';
import { convertDateStringToDate, getDateDifferenceInDays, militaryToTwelveHourTime } from '@/helpers/date-helper';
import { paymentMethods } from '@/constants/payment-method-constants';
import webStorageConstants from '@/constants/web-storage-constants';
@ -371,7 +372,8 @@ export const useMainStore = defineStore({
}),
experimentSettings: (state) => state.applicationUser.experiments
.map((x) => x.settings)
.reduce((r, c) => Object.assign(r, c), {}) ?? {}
.reduce((r, c) => Object.assign(r, c), {}) ?? {},
submittedOrder: () => JSON.parse(window.sessionStorage.getItem('submittedOrder'))
},
actions:
{
@ -902,8 +904,8 @@ export const useMainStore = defineStore({
const { carId } = this.order.vehicle;
// WARNING
// TODO: this is temp test code until serviceLocation is complete.
// const serviceZipCode = this.order.serviceLocation.zipCode;
const serviceZipCode = '44902';
const serviceZipCode = this.order.serviceLocation.zipCode;
// const serviceZipCode = '44902';
return globalMethods
.callHttpClient({
method: endpoints.GetWipers.method,
@ -1047,7 +1049,68 @@ export const useMainStore = defineStore({
endpoint: `${endpoints.GetServiceabilityDetails.url}?zip=${serviceZipCode}&carId=${carId}&${lineItems}&${glassPieces}`
});
},
mapTaxedLineItemsToStoreFormat(availableLineItems, storeLineItems) {
// clone the lineItems array because what we're passing in is referencing the store directly
const lineItems = deepClone(storeLineItems);
// eslint-disable-next-line no-restricted-syntax, prefer-const
for (let [category, lineItemsInCategory] of Object.entries(lineItems)) {
lineItemsInCategory = lineItemsInCategory ?? [];
if (category === 'supportingItems') {
// if the category is supporting items we need to filter out the items that aren't repair chips
const nonRepairChipSupportItemsLineItems = lineItemsInCategory.filter((lineItem) => lineItem.partNumber !== 'WSREPAIR');
/*
Because repair chips all have the same part number but different prices based on the quantity,
we have to sort the store line items and available line items by descending labor amount in order to
map the tax correctly to each repair chip
*/
// get the supporting items that ARE repair chips and sort them by descending labor amount
let repairChipLineItems = lineItemsInCategory.filter((lineItem) => lineItem.partNumber === 'WSREPAIR');
repairChipLineItems = repairChipLineItems.sort((a, b) => parseFloat(b.laborAmount) - parseFloat(a.laborAmount));
// get the supporting items from the available line items (taxed) that ARE repair chips and sort them by descending labor amount
let availableRepairChipLineItems = availableLineItems.filter((lineItem) => lineItem.partNumber === 'WSREPAIR');
availableRepairChipLineItems = availableRepairChipLineItems.sort((a, b) => parseFloat(b.laborAmount) - parseFloat(a.laborAmount));
// go through each one of those mapping the taxes to the correct chip
for (let i = 0; i < availableRepairChipLineItems.length; i++) {
repairChipLineItems[i].salesTax = availableRepairChipLineItems[i].salesTax;
}
// then we map the non-repair chip items based on part number
for (
let lineItemIndex = 0;
lineItemIndex < nonRepairChipSupportItemsLineItems.length;
lineItemIndex++
) {
const availableLineItem = availableLineItems.find((ali) =>
ali.partNumber === nonRepairChipSupportItemsLineItems[lineItemIndex].partNumber);
if (availableLineItem) {
nonRepairChipSupportItemsLineItems[lineItemIndex].salesTax =
availableLineItem.salesTax;
}
}
// finally we splice the two arrays back into one
lineItemsInCategory = nonRepairChipSupportItemsLineItems.concat(repairChipLineItems);
} else {
for (
let lineItemIndex = 0;
lineItemIndex < lineItemsInCategory.length;
lineItemIndex++
) {
const availableLineItem = availableLineItems.find((ali) => ali.partNumber === lineItemsInCategory[lineItemIndex].partNumber);
if (availableLineItem) {
lineItemsInCategory[lineItemIndex].salesTax = availableLineItem.salesTax;
}
}
}
}
return lineItems;
},
lookupVehicleByVin(vin) {
return globalMethods.callHttpClient({
method: endpoints.LookupVehicleByVin.method,
@ -1791,6 +1854,66 @@ export const useMainStore = defineStore({
// context.commit(storeMutations.UPDATE_LINE_ITEMS_SERVER_DATA, response.data.serverData);
return addPricesToLineItems(availableLineItems, response.data.lineItems);
},
// Tax order actions
async taxOrderItemsAndSaveServerData(pricedLineItems) {
const { order } = this;
const { serviceLocation } = order;
const billToAccountNumber = this.issConfig.parentAccountNumber.toString(); // payment
const { providerNumber } = serviceLocation.provider;
const { appointmentType } = serviceLocation;
const serviceLocationCity = serviceLocation.city;
const serviceLocationState = serviceLocation.state;
const serviceLocationZipCode = serviceLocation.zipCode;
const flattenedLineItemsWithChildParts = getFlattenedArrayOfLineItemsWithChildParts(pricedLineItems);
const lineItemsWithOnlyPriceInfo = flattenedLineItemsWithChildParts.map((lineItem) => ({
partNumber: lineItem.partNumber,
laborAmount: lineItem.laborAmount ?? 0,
kitPrice: lineItem.kitPrice ?? 0,
sellingPrice: lineItem.sellingPrice ?? 0
}));
const pricedLineItemsFormattedForRequest = buildQueryStringParameterFromArrayOfComplexObjects(
lineItemsWithOnlyPriceInfo,
'lineItems'
);
let queryString = '';
if (appointmentType === 'Mobile') {
queryString =
`ParentAccountNumber=${applicationConfig.CASH_PARENT_ACCOUNT_NUMBER}`
+ `&BillToAccountNumber=${billToAccountNumber}`
+ `&ProviderNumber=${providerNumber}`
+ `&AppointmentType=${appointmentType}`
+ `&ServiceLocation.City=${serviceLocationCity}`
+ `&ServiceLocation.State=${serviceLocationState}`
+ `&ServiceLocation.ZipCode=${serviceLocationZipCode}`
+ `&${pricedLineItemsFormattedForRequest}`;
} else {
queryString =
`ParentAccountNumber=${applicationConfig.CASH_PARENT_ACCOUNT_NUMBER}`
+ `&BillToAccountNumber=${billToAccountNumber}`
+ `&ProviderNumber=${providerNumber}`
+ `&AppointmentType=${appointmentType}`
+ `&${pricedLineItemsFormattedForRequest}`;
}
const lineItemServerData = this.order.lineItems.serverData;
if (lineItemServerData) {
queryString += `&ServerData=${encodeURIComponent(lineItemServerData)}`;
}
const retPricedLineItems = await globalMethods.callHttpClient({
method: endpoints.TaxOrderItems.method,
endpoint: `${endpoints.TaxOrderItems.url}?${queryString}`
}).then((response) => {
this.order.lineItems.serverData = response.data.serverData;
return addTaxesToPricedLineItems(pricedLineItems, response.data.taxedLineItems);
});
return retPricedLineItems;
},
saveProviderPreferenceData(data) {
this.updatePageData({ page: issPageValues.PROVIDER_PREFERENCE, data });
},
@ -2156,6 +2279,7 @@ export const useMainStore = defineStore({
this.resetDamageState();
this.resetInsurance();
this.resetBailout();
this.resetSubmittedOrder();
},
savePaymentMethodChoice(paymentMethod) {
const isPayInAdvance = paymentMethod !== paymentMethods.PAY_AT_TIME_OF_SERVICE;
@ -2180,6 +2304,7 @@ export const useMainStore = defineStore({
}
const submittedOrder = this.order;
const { experiments } = this.applicationUser;
const { issConfig } = this;
// set to local storage
window.sessionStorage.setItem(webStorageConstants.SUBMITTED_ORDER, JSON.stringify(submittedOrder));
@ -2187,6 +2312,8 @@ export const useMainStore = defineStore({
// clear vuex
this.resetState();
// restore issConfig
this.issConfig = issConfig;
// restore user's experiments
this.applicationUser.experiments = experiments;
},
@ -2295,6 +2422,21 @@ function addPricesToLineItems(lineItems, pricingLineItems) {
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 getLineItemQueryStringForPricing(lineItems) {
return lineItems.map((lineItem, index) => {
let queryStringSnippet = `&LineItems[${index}].partNumber=${lineItem.partNumber}`;