diff --git a/src/fmg-components/cart/cart.vue b/src/fmg-components/cart/cart.vue index e9152dd9d..4da3982cd 100644 --- a/src/fmg-components/cart/cart.vue +++ b/src/fmg-components/cart/cart.vue @@ -322,7 +322,6 @@ export default { false ); } - this.$emit("itemRemoved"); }, async saveVaps(lineItems) { diff --git a/src/fmg-components/promo-modal-question/promo-modal-question.vue b/src/fmg-components/promo-modal-question/promo-modal-question.vue index 1e87d5bb5..8efad6f3e 100644 --- a/src/fmg-components/promo-modal-question/promo-modal-question.vue +++ b/src/fmg-components/promo-modal-question/promo-modal-question.vue @@ -290,18 +290,8 @@ export default { ); if (promoCodeData.isValid) { if (this.taxPromos) { - const vapsToAdd = getVapsThatNeedToBeAddedToSatisfyPromos( - promoCodeData.promoCode, - this.addableVaps, - this.lineItems - ); - const pricedLineItemsToTax = { - glassParts: this.lineItems.glassParts, - promos: promoCodeData.promoCode, - supportingItems: this.lineItems.supportingItems, - vaps: [...this.lineItems.vaps, ...vapsToAdd], - }; - + const pricedLineItemsToTax = []; + pricedLineItemsToTax.push(...promoCodeData.promoCode); // promoCodeData.promoCode should be an array const taxedLineItems = await baseMixin.methods.dispatchStoreActionWithLogging( storeActions.TAX_ORDER_ITEMS_AND_SAVE_SERVER_DATA, @@ -324,10 +314,25 @@ export default { // Match all line items to the line items as they are in the store // and rebuild the original structure. - this.lineItems = taxedLineItems; - } else { - this.lineItems?.promos.push(...promoCodeData.promoCode); + this.lineItems = mapTaxedLineItemsToStoreFormat( + taxedLineItems, + this.lineItems + ); + const taxedVaps = mapTaxedLineItemsToStoreFormat( + taxedLineItems, + this.addableVaps + ); + + const getVaps = getVapsThatNeedToBeAddedToSatisfyPromos( + promoCodeData.promoCode, + taxedVaps, + this.lineItems + ); + + this.lineItems.vaps?.push(...getVaps); } + this.lineItems?.promos.push(...promoCodeData.promoCode); + this.$emit("promoAdded", this.lineItems); this.closeModal(); diff --git a/src/helpers/pricing-helper.js b/src/helpers/pricing-helper.js index 0a8b85d7e..9aa317353 100644 --- a/src/helpers/pricing-helper.js +++ b/src/helpers/pricing-helper.js @@ -99,23 +99,3 @@ export async function getPricingByDayPartWithPrice(pageNameToLog) { return pricingResults[0]; } - -export function addPricesToLineItems(lineItems, pricingLineItems) { - lineItems.forEach((lineItem) => { - const lineItemIndex = pricingLineItems.findIndex( - (pricingLineItem) => pricingLineItem.partNumber === lineItem.partNumber - ); - - if (lineItem.childParts) { - addPricesToLineItems(lineItem.childParts, pricingLineItems); - } - - const pricedLineItem = pricingLineItems.splice(lineItemIndex, 1)[0]; - lineItem.laborAmount = pricedLineItem.laborAmount; - lineItem.sellingPrice = pricedLineItem.sellingPrice; - lineItem.kitPrice = pricedLineItem.kitPrice; - lineItem.salesTax = pricedLineItem.salesTax; - }); - - return lineItems; -} diff --git a/src/layouts/payment-method/payment-method.vue b/src/layouts/payment-method/payment-method.vue index abee992bf..2c51f42a1 100644 --- a/src/layouts/payment-method/payment-method.vue +++ b/src/layouts/payment-method/payment-method.vue @@ -34,8 +34,7 @@ :isItac="isItac" :isNoComp="isNoComp" :isExpandedOnLoad="false" - :isMSRFeeApplicable="isMSRFeeApplicable" - @itemRemoved="evaluatePromosAndTaxItemsOnOrder" /> + :isMSRFeeApplicable="isMSRFeeApplicable" /> wiper.partType == partTypeStrings.FRONT_WIPER + ) ?? []; + + const rearWipersOnOrder = + lineItemsFromStore.vaps.filter( + (wiper) => wiper.partType == partTypeStrings.REAR_WIPER + ) ?? []; + + const orderHasFrontWipers = frontWipersOnOrder.length > 0; + const orderHasRearWipers = rearWipersOnOrder.length > 0; + + const wipersPromise = + !orderHasFrontWipers || !orderHasRearWipers + ? baseMixin.methods.dispatchStoreActionWithLogging( + storeActions.GET_WIPERS, + { + serviceZipCode: store.getters.order.serviceLocation.zipCode, + carId: store.getters.vehicle.carId, + }, + "payment-method" + ) + : Promise.resolve([]); const rainRepelPromise = baseMixin.methods.dispatchStoreActionWithLogging( storeActions.GET_RAIN_REPEL, @@ -198,6 +224,9 @@ export default { "payment-method" ); + // const reviewDropdownPromise = reviewDropdown.methods.loadInitialData(); + // (removed temporarily for Heritage parity effort) + const promiseResultMap = [ { resultKey: "cmsContent", @@ -211,68 +240,80 @@ export default { resultKey: "rainRepel", promise: rainRepelPromise, }, + // { + // resultKey: "reviewDropdownData", + // promise: reviewDropdownPromise, + // }, + // (removed temporarily for Heritage parity effort) ]; const resultMap = await settleAllPromises(promiseResultMap); - let lineItemsFromStore = deepClone(store.getters.order.lineItems); const glassParts = lineItemsFromStore.glassParts ?? []; const supportingItems = lineItemsFromStore.supportingItems ?? []; const vaps = lineItemsFromStore.vaps ?? []; - const availableVaps = [resultMap.rainRepel, ...resultMap.wipers]; + // if the order already has wipers on it from the quote page, use those as the available wipers + // instead of what comes from the backend. This is to prevent issues with part interchange. + const availableFrontWipers = orderHasFrontWipers + ? frontWipersOnOrder + : (resultMap.wipers.filter((wiper) => wiper.partType == partTypeStrings.FRONT_WIPER) ?? + []); + const availableRearWipers = orderHasRearWipers + ? rearWipersOnOrder + : (resultMap.wipers.filter((wiper) => wiper.partType == partTypeStrings.REAR_WIPER) ?? + []); - const lineItemsOnOrderAndAvailableVaps = [ - ...availableVaps, - ...glassParts, + const allLineItems = [ + resultMap.rainRepel, ...supportingItems, + ...availableFrontWipers, + ...availableRearWipers, + ...glassParts, ...vaps, ]; - // All line items are already priced except availableVaps - // Price everything again to ensure that serverData has all values - // Specifically this addresses an error where insurance client glass parts are not in serverData - // See CASH-1713 for details - const pricedLineItems = await baseMixin.methods.dispatchStoreActionWithLogging( + const lineItemsToTax = Array.from( + new Map(allLineItems.map((item) => [item.partNumber, item])).values() + ); + + const availableVaps = [ + resultMap.rainRepel, + ...availableFrontWipers, + ...availableRearWipers, + ]; + + const pricedLineItemsToTax = await baseMixin.methods.dispatchStoreActionWithLogging( storeActions.PRICE_ORDER_ITEMS_AND_SAVE_SERVER_DATA, { - availableLineItems: lineItemsOnOrderAndAvailableVaps, + availableLineItems: lineItemsToTax, }, "payment-method", false ); - // Add prices to the availableVaps - const pricedAvailableVaps = addPricesToLineItems(availableVaps, pricedLineItems); - // Promo logic // Populate the previous state of promos for toast message usage in "next()" const oldActivePromos = store.getters.lineItems.promos?.slice(0); const oldInactivePromos = store.getters.order.payment.inactivePromos?.slice(0); const promoCodeFromQueryString = consumeQueryFromStash(queryStrings.PROMO); - // New promos are saved to store with this const { validatePromoResponse, revalidatePromoResponse } = await revalidatePromosAndValidateQueryStringPromo( promoCodeFromQueryString, - lineItemsOnOrderAndAvailableVaps, + pricedLineItemsToTax, "payment-method" ); - // update lineItemsFromStore with newly added promos - let lineItemsForCart = deepClone(store.getters.order.lineItems); - delete lineItemsForCart.serverData; + // Add newly validated promos to the array to get taxed + const newValidatedPromos = validatePromoResponse?.orderPromos ?? []; + newValidatedPromos.push( + ...(revalidatePromoResponse ? revalidatePromoResponse.promoLineItems : []) + ); + pricedLineItemsToTax.push(...newValidatedPromos); // End of promo logic - const vapsToAddToCart = getVapsThatNeedToBeAddedToSatisfyPromos( - lineItemsForCart.promos ?? [], - availableVaps, - lineItemsForCart - ); - lineItemsForCart.vaps = lineItemsForCart.vaps ?? []; - lineItemsForCart.vaps.push(...vapsToAddToCart); - // Tax items on order - lineItemsForCart = await baseMixin.methods.dispatchStoreActionWithLogging( + const taxedLineItems = await baseMixin.methods.dispatchStoreActionWithLogging( storeActions.TAX_ORDER_ITEMS_AND_SAVE_SERVER_DATA, { billToAccountNumber: store.getters.payment.billToAccountNumber, @@ -281,17 +322,31 @@ export default { serviceLocationCity: store.getters.order.serviceLocation.city, serviceLocationState: store.getters.order.serviceLocation.state, serviceLocationZipCode: store.getters.order.serviceLocation.zipCode, - pricedLineItems: lineItemsForCart, + pricedLineItems: pricedLineItemsToTax, }, "payment-method", false ); + // Match all line items to the line items as they are in the store + // and rebuild the original structure. + const lineItems = mapTaxedLineItemsToStoreFormat(taxedLineItems, lineItemsFromStore); + const taxedVaps = mapTaxedLineItemsToStoreFormat(taxedLineItems, availableVaps); + + lineItems.promos = newValidatedPromos ?? []; + const vapsToAddToCart = getVapsThatNeedToBeAddedToSatisfyPromos( + newValidatedPromos, + taxedVaps, + lineItems + ); + lineItems.vaps = lineItems.vaps ?? []; + lineItems.vaps.push(...vapsToAddToCart); + // Call the "next" function to complete the transition to this page. next((vm) => { vm.setCmsContent(resultMap.cmsContent); - vm.availableVaps = pricedAvailableVaps; - vm.lineItems = lineItemsForCart; + vm.availableVaps = taxedVaps; + vm.lineItems = lineItems; vm.inactivePromos = removeCurrentlyActivePromoCodesFromInactivePromos( vm.lineItems.promos, vm.inactivePromos @@ -586,28 +641,6 @@ export default { this.pageName ); }, - async evaluatePromosAndTaxItemsOnOrder() { - //Revalidate promos if there are any inactive, or active promos - const hasInactivePromos = this.inactivePromos.length > 0; - const hasActivePromos = this.lineItems.promos.length > 0; - if (hasInactivePromos || hasActivePromos) { - await this.revalidatePromos(); - } - this.lineItems = await baseMixin.methods.dispatchStoreActionWithLogging( - storeActions.TAX_ORDER_ITEMS_AND_SAVE_SERVER_DATA, - { - billToAccountNumber: store.getters.payment.billToAccountNumber, - providerNumber: store.getters.order.serviceLocation.provider.providerNumber, - appointmentType: store.getters.order.serviceLocation.appointmentType, - serviceLocationCity: store.getters.order.serviceLocation.city, - serviceLocationState: store.getters.order.serviceLocation.state, - serviceLocationZipCode: store.getters.order.serviceLocation.zipCode, - pricedLineItems: this.lineItems, - }, - "payment-method", - false - ); - }, hasSubmittedOrder() { return baseMixin.methods.hasSubmittedOrder(); }, @@ -828,6 +861,7 @@ export default { ) { return; } + if (oldValue.promos.length < newValue.promos.length) { const oldPromoCodes = oldValue.promos.map( (promoObject) => promoObject.promoCode diff --git a/src/layouts/payment/payment.spec.js b/src/layouts/payment/payment.spec.js index 1b36d0644..ad98814d2 100644 --- a/src/layouts/payment/payment.spec.js +++ b/src/layouts/payment/payment.spec.js @@ -319,6 +319,7 @@ describe("payment.vue", () => { ); // Assert + expect(vmMock.availableVaps).not.toBeUndefined(); expect(vmMock.lineItems).not.toBeUndefined(); expect(vmMock.setCmsContent).toBeCalled(); diff --git a/src/layouts/payment/payment.vue b/src/layouts/payment/payment.vue index b8e481174..992795321 100644 --- a/src/layouts/payment/payment.vue +++ b/src/layouts/payment/payment.vue @@ -42,7 +42,7 @@ { vm.setCmsContent(resultMap.cmsContent); - vm.lineItems = deepClone(store.getters.order.lineItems); + vm.availableVaps = taxedVaps; + vm.lineItems = lineItems; vm.$nextTick(() => { if (vm.$refs.cart) { diff --git a/src/layouts/quote/quote.vue b/src/layouts/quote/quote.vue index 8bab96d5f..c76222cac 100644 --- a/src/layouts/quote/quote.vue +++ b/src/layouts/quote/quote.vue @@ -65,7 +65,6 @@ pageName="quote" :taxPromos="false" :useDefaultCashParentAccount="true" - @promoAdded="promoAdded" modalWidgetName="PromoModalWidget" /> @@ -577,6 +576,9 @@ export default { isInsuranceContinueButtonText() { return this.getCmsContent("isInsuranceContinueButtonText", "Text"); }, + lineItemsCloneForWatcher() { + return Object.assign({}, this.lineItems); + }, isRecalibrationOnOrder() { return store.getters.isRecalibrationOnOrder; }, @@ -852,9 +854,31 @@ export default { await this.forwardButtonAction(); } }, - promoAdded(lineItems) { - const alert = createPromoSuccessAlert(lineItems.promos[0].promoCode); - this.$refs.funnelHeader.pushGlobalAlert(alert, alert.shouldAutoFade); + }, + watch: { + lineItemsCloneForWatcher: { + handler(newValue, oldValue) { + if ( + !oldValue || + oldValue.length == 0 || + !oldValue.vaps || + !newValue || + newValue.length == 0 + ) { + return; + } + if (oldValue.promos.length < newValue.promos.length) { + const oldPromoCodes = oldValue.promos.map( + (promoObject) => promoObject.promoCode + ); + const newlyActivatedPromoCodes = newValue.promos.filter( + (newPromo) => !oldPromoCodes.includes(newPromo.promoCode) + ); + const alert = createPromoSuccessAlert(newlyActivatedPromoCodes[0].promoCode); + this.$refs.funnelHeader.pushGlobalAlert(alert, alert.shouldAutoFade); + } + }, + deep: true, }, }, components: { diff --git a/src/layouts/schedule/schedule.vue b/src/layouts/schedule/schedule.vue index 7c9d9f444..716c819e2 100644 --- a/src/layouts/schedule/schedule.vue +++ b/src/layouts/schedule/schedule.vue @@ -460,47 +460,111 @@ export default { }; }, async beforeRouteEnter(to, from, next) { - const serviceZipCode = store.getters.order.serviceLocation.zipCode; + const isPricingByDayExperiment = experimentMixin.methods.hasSettingEqualTo( + experimentSettings.PRICING_BY_DAY, + "true" + ); + const showPricingByDay = !store.getters.payment.isInsurance && isPricingByDayExperiment; + // Get pricingByDayBasePrice needed for Pricing By Day + const lineItems = deepClone(store.getters.order.lineItems); + const isRecalibrationOnOrder = store.getters.isRecalibrationOnOrder; + const shouldHideRecalibration = + experimentMixin.methods.hasSettingEqualTo( + experimentSettings.RECAL_PRICE_REMOVE, + "true" + ) && isRecalibrationOnOrder; + const glassParts = + isRecalibrationOnOrder && shouldHideRecalibration + ? getItemsWithoutRecalParts(lineItems.glassParts) + : (lineItems.glassParts ?? []); + const supportingItemsWithoutFees = baseMixin.methods.filterOutCertainPartTypesOrNumbers( + lineItems.supportingItems, + { + partNumbersToRemove: [ + partNumberStrings.RECYCLE_FEE, + partNumberStrings.PRICING_BY_DAY_UPCHARGE, + ], + } + ); + const lineItemsToBePriced = { + glassParts: glassParts, + supportingItems: supportingItemsWithoutFees, + vaps: lineItems.vaps ?? [], + promos: lineItems.promos ?? [], + }; + const priceString = getAmountDue(lineItemsToBePriced, false); // pass the IncludeTax param as false + const priceStringIntegerRoundedDown = priceString?.split(".")[0]; // same method used as getDisplayPrice() in service-package-radio used on /quote + const pricingByDayBasePrice = parseInt(priceStringIntegerRoundedDown); + let includePricingByDayUpcharge = false; + let appointmentType = store.getters.order.serviceLocation.appointmentType; + + // Check to see if date should be pre-selected + let scheduleFromStore = await store.getters.order.schedule; + let preSelectedDate; + + if (scheduleFromStore.date && scheduleFromStore.date.length > 0) { + preSelectedDate = scheduleFromStore.date; + + if (appointmentType === AppointmentTypeStrings.MOBILE) { + preSelectedDate += "-mobile"; + } + + // Check to see if pre-selected date should have pricing by day upcharge + if (showPricingByDay) { + // is this preSelectedDate a higher priced pricingByDay day? + const dayIndex = convertDateStringToDate(scheduleFromStore?.date).getDay(); + const dayObject = DAYS_OF_WEEK[dayIndex]; + if (dayObject.isPricingByDayUpchargeDay) { + includePricingByDayUpcharge = true; + } + } + } + + // Set up promises const cmsContentPromise = fetchCmsContentForPage(to.name); + const alertReasonsPromise = locationAlerts.methods.loadInitialData( store.getters.order.serviceLocation.zipCodeCtu, store.getters.order.serviceLocation.provider?.address?.zipCodeCtu ); + + const serviceZipCode = store.getters.order.serviceLocation.zipCode; + const zipCodeDataPromise = getZipCodeData(serviceZipCode, to.name); const serviceabilityDetailsPromise = getServiceabilityDetails( serviceZipCode, null, - "schedule" - ); - let zipCodeData; - const zipCodeDataPromise = getZipCodeData(serviceZipCode, to.name); - let shopProviderData; - const shopProviderDataPromise = getShopProviderData(serviceZipCode, to.name); - const zipCodeDataAndShopProviderDataPromise = Promise.all([ - zipCodeDataPromise, - shopProviderDataPromise, - ]); - const mobileFeePartPromise = zipCodeDataAndShopProviderDataPromise.then( - ([zipCodeDataResult, shopProviderDataResult]) => { - zipCodeData = zipCodeDataResult; - shopProviderData = shopProviderDataResult; - return baseMixin.methods.dispatchStoreActionWithLogging( - storeActions.GET_MOBILE_FEE_PART, - { - serviceZipCode: serviceZipCode, - serviceZipCodeCtu: zipCodeData.zipCodeCtu, - mobileProviderNumber: shopProviderData.data.mobileProviderNumber, - }, - to.name, - false - ); - } + to.name ); + const mobileFeePartPromise = getPricedMobileFeePart(serviceZipCode, to.name); + const shopProviderData = await getShopProviderData(serviceZipCode, to.name); + const providerNumber = shopProviderData?.data?.shopProviders[0]?.providerNumber; + + // Get pricingByDayUpcharge needed for Pricing By Day + const pricingByDayUpchargePartPromise = showPricingByDay + ? getPricingByDayPartWithPrice() + : null; + const premiumFeePromise = baseMixin.methods.dispatchStoreActionWithLogging( storeActions.GET_MOBILE_PREMIUM_FEE, null, to.name ); + const premiumFeeWithPricePromise = premiumFeePromise.then((result) => { + if (result.data) { + return baseMixin.methods.dispatchStoreActionWithLogging( + storeActions.PRICE_ORDER_ITEMS_AND_SAVE_SERVER_DATA, + { + availableLineItems: [result.data], + }, + to.name, + false + ); + } else { + return result.data; + } + }); + // Settle promises and get results const promiseResultMap = [ { @@ -511,6 +575,18 @@ export default { resultKey: "alertReasons", promise: alertReasonsPromise, }, + { + resultKey: "pricingByDayUpchargePart", + promise: pricingByDayUpchargePartPromise, + }, + { + resultKey: "premiumFeeWithPrice", + promise: premiumFeeWithPricePromise, + }, + { + resultKey: "zipCodeData", + promise: zipCodeDataPromise, + }, { resultKey: "mobileFeePart", promise: mobileFeePartPromise, @@ -519,70 +595,39 @@ export default { resultKey: "serviceabilityDetails", promise: serviceabilityDetailsPromise, }, - { - resultKey: "premiumFee", - promise: premiumFeePromise, - }, ]; + const resultMap = await settleAllPromises(promiseResultMap); - const itemsToPrice = []; - if (resultMap.mobileFeePart) { - itemsToPrice.push(resultMap.mobileFeePart); - } - if (resultMap.premiumFee) { - itemsToPrice.push(resultMap.premiumFee); - } - let pricedMobileFeePart = null; - let pricedPremiumFee = null; - - if (itemsToPrice.length) { - const pricedItems = await baseMixin.methods.dispatchStoreActionWithLogging( - storeActions.PRICE_ORDER_ITEMS_AND_SAVE_SERVER_DATA, - { - availableLineItems: itemsToPrice, - }, - to.name, - false - ); - pricedMobileFeePart = pricedItems.find( - (item) => item.partNumber === resultMap.mobileFeePart.partNumber - ); - pricedPremiumFee = pricedItems.find( - (item) => item.partNumber === resultMap.premiumFee.partNumber - ); - } - - let appointmentType = store.getters.order.serviceLocation.appointmentType; - // Check to see if date should be pre-selected - let scheduleFromStore = await store.getters.order.schedule; - let preSelectedDate; - if (scheduleFromStore.date && scheduleFromStore.date.length > 0) { - preSelectedDate = scheduleFromStore.date; - - if (appointmentType === AppointmentTypeStrings.MOBILE) { - preSelectedDate += "-mobile"; - } - } + // add pricing by day data + const pricingByDayUpcharge = + showPricingByDay && resultMap.pricingByDayUpchargePart + ? await baseMixin.methods.getTotalLineItemPrice( + resultMap.pricingByDayUpchargePart, + false + ) + : null; // Call the "next" function to complete the transition to this page. next((vm) => { vm.setCmsContent(resultMap.cmsContent); vm.$refs.locationAlerts.initializeComponent(resultMap.alertReasons); - vm.mobilePremiumAppointmentFee = pricedPremiumFee; + vm.mobilePremiumAppointmentFee = resultMap.premiumFeeWithPrice + ? resultMap.premiumFeeWithPrice[0] + : null; vm.updateFooterButtonText(vm.selectedTimeSlotInfo); - vm.pricingByDayUpchargeLineItem = null; // Pricing By Day Upcharge Line Item is not used in this version - vm.includePricingByDayUpcharge = false; // Pricing By Day Upcharge is not used in this version - vm.isPricingByDayExperiment = false; // Pricing By Day Experiment is not used in this version - vm.pricingByDayBasePrice = null; // Pricing By Day Base Price is not used in this version - vm.pricingByDayUpcharge = null; // Pricing By Day Upcharge is not used in this version - vm.showPricingByDay = false; // Pricing By Day is not used in this version + vm.pricingByDayUpchargeLineItem = resultMap.pricingByDayUpchargePart; + vm.includePricingByDayUpcharge = includePricingByDayUpcharge; + vm.isPricingByDayExperiment = isPricingByDayExperiment; + vm.pricingByDayBasePrice = pricingByDayBasePrice; + vm.pricingByDayUpcharge = pricingByDayUpcharge; + vm.showPricingByDay = showPricingByDay; vm.preSelectedDate = preSelectedDate; vm.appointmentType = appointmentType; vm.setData( - zipCodeData, + resultMap.zipCodeData, resultMap.serviceabilityDetails, - pricedMobileFeePart, + resultMap.mobileFeePart, shopProviderData.data ); vm.initializeDatePicker(); diff --git a/src/store/index.js b/src/store/index.js index dbee4f357..475076c86 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -59,7 +59,6 @@ import { } from "@/helpers/recal-helper"; import { externalParameterStatus } from "@/constants/external-parameters"; import { experimentSettings } from "@/constants/experiments"; -import { addPricesToLineItems } from "@/helpers/pricing-helper"; // Export State const getDefaultState = () => { @@ -3064,14 +3063,8 @@ export const actions = { pageNameToLog, } ) { - const arrayOfLineItems = [ - ...(pricedLineItems.glassParts ?? []), - ...(pricedLineItems.promos ?? []), - ...(pricedLineItems.supportingItems ?? []), - ...(pricedLineItems.vaps ?? []), - ]; const flattenedLineItemsWithChildParts = - getFlattenedArrayOfLineItemsWithChildParts(arrayOfLineItems); + getFlattenedArrayOfLineItemsWithChildParts(pricedLineItems); const lineItemsWithOnlyPriceInfo = flattenedLineItemsWithChildParts.map((lineItem) => ({ partNumber: lineItem.partNumber, @@ -3120,12 +3113,8 @@ export const actions = { }); context.commit(storeMutations.UPDATE_LINE_ITEMS_SERVER_DATA, response.data.serverData); - Object.keys(pricedLineItems).forEach((key) => { - pricedLineItems[key] = addTaxesToPricedLineItems( - pricedLineItems[key] ?? [], - response.data.taxedLineItems - ); - }); + + pricedLineItems = addTaxesToPricedLineItems(pricedLineItems, response.data.taxedLineItems); return pricedLineItems; }, @@ -3807,6 +3796,26 @@ function convertGlassPieceNamingFromApi(glassArray) { return glassArray; } +function addPricesToLineItems(lineItems, pricingLineItems) { + lineItems.forEach((lineItem) => { + const lineItemIndex = pricingLineItems.findIndex( + (pricingLineItem) => pricingLineItem.partNumber === lineItem.partNumber + ); + + if (lineItem.childParts) { + addPricesToLineItems(lineItem.childParts, pricingLineItems); + } + + const pricedLineItem = pricingLineItems.splice(lineItemIndex, 1)[0]; + lineItem.laborAmount = pricedLineItem.laborAmount; + lineItem.sellingPrice = pricedLineItem.sellingPrice; + lineItem.kitPrice = pricedLineItem.kitPrice; + lineItem.salesTax = pricedLineItem.salesTax; + }); + + return lineItems; +} + function addTaxesToPricedLineItems(pricedLineItems, taxingLineItems = []) { pricedLineItems.forEach((pricedLineItem) => { const lineItemIndex = taxingLineItems.findIndex(