diff --git a/src/fmg-components/cart/cart.spec.js b/src/fmg-components/cart/cart.spec.js index 6cec9ed3b..f06a49a90 100644 --- a/src/fmg-components/cart/cart.spec.js +++ b/src/fmg-components/cart/cart.spec.js @@ -309,40 +309,6 @@ describe("cart.vue", () => { expect(found).toBe(true); }); - // Service package discount Fee Cart Item - test("only if there is service package discount fee for the package, a service package discount cart item should be added to the cart", () => { - // Arrange - const lineItems = { - glassParts: [], - supportingItems: [ - { - description: null, - id: "bc00294e-6baa-403e-866e-52c267187a15", - kitPrice: 0, - laborAmount: 0, - partNumber: "DISC CASHSAVE70", - partType: "SERVICE PACKAGE DISCOUNT", - salesTax: null, - sellingPrice: -70, - }, - ], - vaps: [], - promos: [], - }; - - const availableVaps = []; - - // Act - const { wrapper } = setupMocks({ - props: { - modelValue: lineItems, - availableVaps: availableVaps, - }, - }); - // Assert - expect(wrapper.vm.servicePackageDiscountCartItem).toBeNull(); - }); - // Other Supporting Items Cart Item test("if there are other supporting items on the order, an other supporting items cart item should be added to the cart but should not be displayed", () => { // Arrange diff --git a/src/fmg-components/cart/cart.vue b/src/fmg-components/cart/cart.vue index 4da3982cd..d1bd2a939 100644 --- a/src/fmg-components/cart/cart.vue +++ b/src/fmg-components/cart/cart.vue @@ -312,16 +312,30 @@ export default { this.lineItems[category] = this.lineItems[category].filter( (lineItemsToKeep) => lineItemsToKeep.cartItemType != cartItemType ); + let shouldSaveSupportingItems = category == cartItemCategories.SUPPORTING_ITEMS; if (category == cartItemCategories.VAPS || category == cartItemCategories.PROMOS) { this.saveVaps(this.lineItems); + // Check if service package discount should be removed after vaps change + if ( + this.servicePackageDiscountCartItem && + this.discountPackageNames != this.packageLevel + ) { + this.lineItems.supportingItems = this.lineItems.supportingItems.filter( + (lineItemsToKeep) => + lineItemsToKeep.cartItemType != + this.servicePackageDiscountCartItem.cartItemType + ); + shouldSaveSupportingItems = true; + } } - if (category == cartItemCategories.SUPPORTING_ITEMS) { + if (shouldSaveSupportingItems) { await this.dispatchStoreAction( storeActions.SAVE_SUPPORTING_ITEMS_SUPPRESSING_STATE_RESETTING, this.lineItems.supportingItems, false ); } + this.$emit("itemRemoved"); }, async saveVaps(lineItems) { @@ -470,14 +484,7 @@ export default { } if (this.servicePackageDiscountCartItem) { - if (this.discountPackageNames != this.packageLevel) { - this.removeItem( - this.servicePackageDiscountCartItem.cartItemType, - cartItemCategories.SUPPORTING_ITEMS - ); - } else { - cartItems.push(this.servicePackageDiscountCartItem); - } + cartItems.push(this.servicePackageDiscountCartItem); } if (this.premiumAppointmentDiscountCartItem) { 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 8efad6f3e..1e87d5bb5 100644 --- a/src/fmg-components/promo-modal-question/promo-modal-question.vue +++ b/src/fmg-components/promo-modal-question/promo-modal-question.vue @@ -290,8 +290,18 @@ export default { ); if (promoCodeData.isValid) { if (this.taxPromos) { - const pricedLineItemsToTax = []; - pricedLineItemsToTax.push(...promoCodeData.promoCode); // promoCodeData.promoCode should be an array + 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 taxedLineItems = await baseMixin.methods.dispatchStoreActionWithLogging( storeActions.TAX_ORDER_ITEMS_AND_SAVE_SERVER_DATA, @@ -314,25 +324,10 @@ export default { // Match all line items to the line items as they are in the store // and rebuild the original structure. - 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 = taxedLineItems; + } else { + this.lineItems?.promos.push(...promoCodeData.promoCode); } - 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 9aa317353..68de04515 100644 --- a/src/helpers/pricing-helper.js +++ b/src/helpers/pricing-helper.js @@ -99,3 +99,25 @@ 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); + } + + if (lineItemIndex !== -1) { + 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 2c51f42a1..680d060dc 100644 --- a/src/layouts/payment-method/payment-method.vue +++ b/src/layouts/payment-method/payment-method.vue @@ -34,7 +34,8 @@ :isItac="isItac" :isNoComp="isNoComp" :isExpandedOnLoad="false" - :isMSRFeeApplicable="isMSRFeeApplicable" /> + :isMSRFeeApplicable="isMSRFeeApplicable" + @itemRemoved="evaluatePromosAndTaxItemsOnOrder" /> { + // this assumes childparts will never be a glass part + lineItem.isChildPart = childPartRecursiveCall; + flattenedArray.push(lineItem); + if (lineItem.childParts) { + flattenedArray = [ + ...flattenedArray, + ...getFlattenedArrayOfLineItemsWithChildParts(lineItem.childParts, true), + ]; + } + }); + + return flattenedArray; +} + export default { name: "paymentMethod", props: { @@ -191,32 +200,14 @@ export default { // Call APIs const cmsContentPromise = fetchCmsContentForPage(to.name); - const lineItemsFromStore = deepClone(store.getters.order.lineItems); - - const frontWipersOnOrder = - lineItemsFromStore.vaps.filter( - (wiper) => 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 wipersPromise = baseMixin.methods.dispatchStoreActionWithLogging( + storeActions.GET_WIPERS, + { + serviceZipCode: store.getters.order.serviceLocation.zipCode, + carId: store.getters.vehicle.carId, + }, + "payment-method" + ); const rainRepelPromise = baseMixin.methods.dispatchStoreActionWithLogging( storeActions.GET_RAIN_REPEL, @@ -224,9 +215,6 @@ export default { "payment-method" ); - // const reviewDropdownPromise = reviewDropdown.methods.loadInitialData(); - // (removed temporarily for Heritage parity effort) - const promiseResultMap = [ { resultKey: "cmsContent", @@ -240,57 +228,40 @@ 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 ?? []; - // 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 availableVaps = [resultMap.rainRepel, ...resultMap.wipers]; - const allLineItems = [ - resultMap.rainRepel, - ...supportingItems, - ...availableFrontWipers, - ...availableRearWipers, + const lineItemsOnOrderAndAvailableVaps = [ + ...availableVaps, ...glassParts, + ...supportingItems, ...vaps, ]; - 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( + // 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 + let pricedLineItems = await baseMixin.methods.dispatchStoreActionWithLogging( storeActions.PRICE_ORDER_ITEMS_AND_SAVE_SERVER_DATA, { - availableLineItems: lineItemsToTax, + availableLineItems: lineItemsOnOrderAndAvailableVaps, }, "payment-method", false ); + pricedLineItems = getFlattenedArrayOfLineItemsWithChildParts(pricedLineItems); + + // Add prices to the availableVaps + const pricedAvailableVaps = addPricesToLineItems(availableVaps, pricedLineItems); // Promo logic // Populate the previous state of promos for toast message usage in "next()" @@ -298,22 +269,38 @@ export default { 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, - pricedLineItemsToTax, + lineItemsOnOrderAndAvailableVaps, "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 taxedLineItems = await baseMixin.methods.dispatchStoreActionWithLogging( + const vapsToAddToCart = getVapsThatNeedToBeAddedToSatisfyPromos( + lineItemsForCart.promos ?? [], + availableVaps, + lineItemsForCart + ); + // Add prices to all line items, sometimes they are not there when they come back from heritage + // See CASH-1713 for details + lineItemsForCart.glassParts = addPricesToLineItems( + lineItemsForCart.glassParts ?? [], + pricedLineItems + ); + lineItemsForCart.supportingItems = addPricesToLineItems( + lineItemsForCart.supportingItems ?? [], + pricedLineItems + ); + lineItemsForCart.vaps = addPricesToLineItems(lineItemsForCart.vaps ?? [], pricedLineItems); + lineItemsForCart.vaps.push(...vapsToAddToCart); + // Tax items on order + lineItemsForCart = await baseMixin.methods.dispatchStoreActionWithLogging( storeActions.TAX_ORDER_ITEMS_AND_SAVE_SERVER_DATA, { billToAccountNumber: store.getters.payment.billToAccountNumber, @@ -322,31 +309,17 @@ export default { serviceLocationCity: store.getters.order.serviceLocation.city, serviceLocationState: store.getters.order.serviceLocation.state, serviceLocationZipCode: store.getters.order.serviceLocation.zipCode, - pricedLineItems: pricedLineItemsToTax, + pricedLineItems: lineItemsForCart, }, "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 = taxedVaps; - vm.lineItems = lineItems; + vm.availableVaps = pricedAvailableVaps; + vm.lineItems = lineItemsForCart; vm.inactivePromos = removeCurrentlyActivePromoCodesFromInactivePromos( vm.lineItems.promos, vm.inactivePromos @@ -641,6 +614,28 @@ 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(); }, @@ -861,7 +856,6 @@ 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 ad98814d2..1b36d0644 100644 --- a/src/layouts/payment/payment.spec.js +++ b/src/layouts/payment/payment.spec.js @@ -319,7 +319,6 @@ 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 992795321..b8e481174 100644 --- a/src/layouts/payment/payment.vue +++ b/src/layouts/payment/payment.vue @@ -42,7 +42,7 @@ { vm.setCmsContent(resultMap.cmsContent); - vm.availableVaps = taxedVaps; - vm.lineItems = lineItems; + vm.lineItems = deepClone(store.getters.order.lineItems); vm.$nextTick(() => { if (vm.$refs.cart) { diff --git a/src/layouts/quote/quote.vue b/src/layouts/quote/quote.vue index c76222cac..8bab96d5f 100644 --- a/src/layouts/quote/quote.vue +++ b/src/layouts/quote/quote.vue @@ -65,6 +65,7 @@ pageName="quote" :taxPromos="false" :useDefaultCashParentAccount="true" + @promoAdded="promoAdded" modalWidgetName="PromoModalWidget" /> @@ -576,9 +577,6 @@ export default { isInsuranceContinueButtonText() { return this.getCmsContent("isInsuranceContinueButtonText", "Text"); }, - lineItemsCloneForWatcher() { - return Object.assign({}, this.lineItems); - }, isRecalibrationOnOrder() { return store.getters.isRecalibrationOnOrder; }, @@ -854,31 +852,9 @@ export default { await this.forwardButtonAction(); } }, - }, - 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, + promoAdded(lineItems) { + const alert = createPromoSuccessAlert(lineItems.promos[0].promoCode); + this.$refs.funnelHeader.pushGlobalAlert(alert, alert.shouldAutoFade); }, }, components: { diff --git a/src/layouts/schedule/schedule.vue b/src/layouts/schedule/schedule.vue index a670d7c5d..1690d831d 100644 --- a/src/layouts/schedule/schedule.vue +++ b/src/layouts/schedule/schedule.vue @@ -460,111 +460,47 @@ export default { }; }, async beforeRouteEnter(to, from, next) { - const isPricingByDayExperiment = experimentMixin.methods.hasSettingEqualTo( - experimentSettings.PRICING_BY_DAY, - "true" - ); - const showPricingByDay = !store.getters.payment.isInsurance && isPricingByDayExperiment; + const serviceZipCode = store.getters.order.serviceLocation.zipCode; - // 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, - to.name + "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 + ); + } ); - 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 = [ { @@ -575,18 +511,6 @@ export default { resultKey: "alertReasons", promise: alertReasonsPromise, }, - { - resultKey: "pricingByDayUpchargePart", - promise: pricingByDayUpchargePartPromise, - }, - { - resultKey: "premiumFeeWithPrice", - promise: premiumFeeWithPricePromise, - }, - { - resultKey: "zipCodeData", - promise: zipCodeDataPromise, - }, { resultKey: "mobileFeePart", promise: mobileFeePartPromise, @@ -595,39 +519,75 @@ 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); + } - // add pricing by day data - const pricingByDayUpcharge = - showPricingByDay && resultMap.pricingByDayUpchargePart - ? await baseMixin.methods.getTotalLineItemPrice( - resultMap.pricingByDayUpchargePart, - false - ) - : null; + 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"; + } + } // 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 = resultMap.premiumFeeWithPrice - ? resultMap.premiumFeeWithPrice[0] - : null; + vm.mobilePremiumAppointmentFee = pricedPremiumFee; vm.updateFooterButtonText(vm.selectedTimeSlotInfo); - vm.pricingByDayUpchargeLineItem = resultMap.pricingByDayUpchargePart; - vm.includePricingByDayUpcharge = includePricingByDayUpcharge; - vm.isPricingByDayExperiment = isPricingByDayExperiment; - vm.pricingByDayBasePrice = pricingByDayBasePrice; - vm.pricingByDayUpcharge = pricingByDayUpcharge; - vm.showPricingByDay = showPricingByDay; + 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.preSelectedDate = preSelectedDate; vm.appointmentType = appointmentType; +<<<<<<< HEAD vm.setDataOnLoad( resultMap.zipCodeData, +======= + vm.setData( + zipCodeData, +>>>>>>> release/2025.11.06 resultMap.serviceabilityDetails, - resultMap.mobileFeePart, + pricedMobileFeePart, shopProviderData.data ); vm.initializeDatePicker(); diff --git a/src/store/index.js b/src/store/index.js index 475076c86..dbee4f357 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -59,6 +59,7 @@ 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 = () => { @@ -3063,8 +3064,14 @@ export const actions = { pageNameToLog, } ) { + const arrayOfLineItems = [ + ...(pricedLineItems.glassParts ?? []), + ...(pricedLineItems.promos ?? []), + ...(pricedLineItems.supportingItems ?? []), + ...(pricedLineItems.vaps ?? []), + ]; const flattenedLineItemsWithChildParts = - getFlattenedArrayOfLineItemsWithChildParts(pricedLineItems); + getFlattenedArrayOfLineItemsWithChildParts(arrayOfLineItems); const lineItemsWithOnlyPriceInfo = flattenedLineItemsWithChildParts.map((lineItem) => ({ partNumber: lineItem.partNumber, @@ -3113,8 +3120,12 @@ export const actions = { }); context.commit(storeMutations.UPDATE_LINE_ITEMS_SERVER_DATA, response.data.serverData); - - pricedLineItems = addTaxesToPricedLineItems(pricedLineItems, response.data.taxedLineItems); + Object.keys(pricedLineItems).forEach((key) => { + pricedLineItems[key] = addTaxesToPricedLineItems( + pricedLineItems[key] ?? [], + response.data.taxedLineItems + ); + }); return pricedLineItems; }, @@ -3796,26 +3807,6 @@ 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(