diff --git a/src/constants/store-actions.js b/src/constants/store-actions.js index 26bcc25e1..4590249f3 100644 --- a/src/constants/store-actions.js +++ b/src/constants/store-actions.js @@ -114,6 +114,7 @@ const storeActions = { SAVE_IS_RECAL_ACKNOWLEDGED_FOR_SCHEDULING: "saveIsRecalAcknowledgedForScheduling", SAVE_IS_OEM_GLASS_SELECTED: "saveIsOemGlassSelected", SAVE_IS_MSR_FEE_APPLICABLE: "saveIsMSRFeeApplicable", + SAVE_IS_MSR_FEE_COVERED_BY_INSURANCE: "saveIsMSRFeeCoveredByInsurance", CREATE_SUBMITTED_STATE: "createSubmittedState", RESET_SUBMITTED_STATE: "resetSubmittedState", diff --git a/src/constants/store-mutations.js b/src/constants/store-mutations.js index 5c6c2e22d..b1344dcb5 100644 --- a/src/constants/store-mutations.js +++ b/src/constants/store-mutations.js @@ -72,6 +72,7 @@ const storeMutations = { UPDATE_IS_RECAL_ACKNOWLEDGED_FOR_SCHEDULING: "updateIsRecalAcknowledgedForScheduling", UPDATE_IS_OEM_GLASS_SELECTED: "updateIsOemGlassSelected", UPDATE_IS_MSR_FEE_APPLICABLE: "updateIsMSRFeeApplicable", + UPDATE_IS_MSR_FEE_COVERED_BY_INSURANCE: "updateIsMSRFeeCoveredByInsurance", UPDATE_CASH_PRICE_SUBTOTAL: "updateCashPriceSubTotal", // EVENT BUS MUTATIONS diff --git a/src/fmg-components/cart/cart.vue b/src/fmg-components/cart/cart.vue index e890e53cc..7de87b678 100644 --- a/src/fmg-components/cart/cart.vue +++ b/src/fmg-components/cart/cart.vue @@ -77,7 +77,7 @@ i % 2 == 0 ? 'even' : 'odd', cartItem.isRemovable ? 'removable-cart-item' : '', ]"> - {{ cartItem.name }} + {{ cartItem.name }} + + {{ msrFeeCartItem.name }} + + Info Icon + + +
+
@@ -162,6 +179,7 @@ import textLink from "@/ux-components/text-link/text-link"; import textBlock from "@/digital-components/text-block/text-block"; import contentGroupModal from "@/fmg-components/content-group-modal/content-group-modal"; import promoModalQuestion from "@/fmg-components/promo-modal-question/promo-modal-question"; +import removeMsrFeeModal from "./remove-msr-fee-modal/remove-msr-fee-modal.vue"; // Mixins import baseMixin from "@/mixins/base-mixin.js"; @@ -183,6 +201,7 @@ import { getSalesTax, getAmountDueWithDonation, } from "@/helpers/pricing-helper.js"; +import { formatToUSDollar } from "@/helpers/cms-content-helper"; // Constants import { partTypeStrings } from "@/constants/part-type-strings"; @@ -191,6 +210,7 @@ import { cartItemTypes } from "@/constants/cart-item-types"; import { coverageStatus, cartItemTypesCoveredByInsurance } from "@/constants/insurance"; import { experimentSettings } from "@/constants/experiments"; import { quotePageDiscountTable } from "@/constants/quote-page-discounts"; +import { partNumberStrings } from "@/constants/part-number-strings"; export default { name: "cart", @@ -203,6 +223,7 @@ export default { pageName: String, allowItemRemoval: Boolean, recyclingModalCmsWidgetName: String, + msrModalCmsWidgetName: String, showAsPaid: Boolean, isInsurance: Boolean, insuranceDeductible: Number, @@ -214,6 +235,7 @@ export default { isExpandedOnLoad: Boolean, isCollapsible: { type: Boolean, default: true }, isMSRFeeApplicable: Boolean, + IsMSRFeeCoveredByInsurance: Boolean, donationCartItem: Object, }, data() { @@ -311,6 +333,10 @@ export default { }, async removeItem(cartItemType, category) { + if (cartItemType == cartItemTypes.MOBILE_FEE && this.isMSRFeeApplicable) { + this.$refs.removeMsrFeeModal.openModal(); + return false; + } this.lineItems[category] = this.lineItems[category].filter( (lineItemsToKeep) => lineItemsToKeep.cartItemType != cartItemType ); @@ -375,6 +401,12 @@ export default { } return []; }, + shouldShowInfoIcon(cartItem) { + return cartItem == this.recycleFeeCartItem || cartItem == this.msrFeeCartItem; + }, + switchToInshop() { + this.$emit("switchToInshop"); + }, }, computed: { isCartReadyToLoad() { @@ -490,6 +522,10 @@ export default { cartItems.push(this.mobileFeeCartItem); } + if (this.msrFeeCartItem) { + cartItems.push(this.msrFeeCartItem); + } + if (this.quotePageDiscountCartItem) { cartItems.push(this.quotePageDiscountCartItem); } @@ -892,7 +928,9 @@ export default { let cartItem = null; let showMobileFeeCartItem = false; const mobileFeeLineItem = this.supportingItems.find( - (lineItem) => lineItem.partType == partTypeStrings.MOBILE_FEE + (lineItem) => + lineItem.partType == partTypeStrings.MOBILE_FEE && + lineItem.partNumber == partTypeStrings.MOBILE_FEE ); var mobileTotal = @@ -929,6 +967,67 @@ export default { } return cartItem; }, + msrFeeCartItemName() { + return this.getCmsContent("MSRFeeTextWidget", "Text"); + }, + getMsrFeeLineItem() { + return this.supportingItems.find( + (lineItem) => + lineItem.partType == partTypeStrings.MOBILE_FEE && + lineItem.partNumber == partNumberStrings.MOBILE_STATIC_RECAL_FEE + ); + }, + msrFeeCartItem() { + let cartItem = null; + const msrFeeLineItem = this.getMsrFeeLineItem; + const shouldCreateMsrFeeCartItem = + this.isInsurance && + !this.IsMSRFeeCoveredByInsurance && + msrFeeLineItem && + this.msrFeeAmount > 0; + + if (shouldCreateMsrFeeCartItem) { + cartItem = { + name: this.msrFeeCartItemName, + category: cartItemCategories.SUPPORTING_ITEMS, + cartItemType: cartItemTypes.MOBILE_FEE, + isDisplayed: this.isInsurance, + isRemovable: true, + subTotal: 0, + salesTax: 0, + lineItems: [], + isCoveredByInsurance: this.IsMSRFeeCoveredByInsurance, + }; + msrFeeLineItem.cartItemType = cartItem.cartItemType; + cartItem.lineItems.push(msrFeeLineItem); + cartItem.subTotal += this.msrFeeAmount; + cartItem.salesTax += msrFeeLineItem.salesTax ?? 0; + } + return cartItem; + }, + msrFeeAmount() { + const msrFeeLineItem = this.getMsrFeeLineItem; + if (!msrFeeLineItem) { + return 0; + } + return ( + msrFeeLineItem.laborAmount + msrFeeLineItem.sellingPrice + msrFeeLineItem.kitPrice + ); + }, + msrModalTextBlock() { + let cmsContentText = this.getCmsContent("MSRModal", "BodyText"); + if (cmsContentText) { + cmsContentText = cmsContentText.replaceAll( + "{custom:mobileFee}", + formatToUSDollar(this.msrFeeAmount) + ); + cmsContentText = cmsContentText.replaceAll( + "{custom:submittedOrder.policy.insuranceCompanyName}", + this.insuranceCompanyName + ); + } + return cmsContentText; + }, quotePageDiscountCartItemName() { return this.getCmsContent("ServicePackageDiscountTextWidget", "Text"); }, @@ -1189,6 +1288,7 @@ export default { textLink, contentGroupModal, promoModalQuestion, + removeMsrFeeModal, }, }; @@ -1289,6 +1389,10 @@ export default { order: 3; margin-right: 100%; text-decoration: none; + + &#msr-fee-cartItem { + margin: 0 0 0 0.2rem; + } } } .package-type, diff --git a/src/fmg-components/cart/remove-msr-fee-modal/remove-msr-fee-modal.vue b/src/fmg-components/cart/remove-msr-fee-modal/remove-msr-fee-modal.vue new file mode 100644 index 000000000..6c2cd1fb6 --- /dev/null +++ b/src/fmg-components/cart/remove-msr-fee-modal/remove-msr-fee-modal.vue @@ -0,0 +1,153 @@ + + + + diff --git a/src/fmg-components/content-group-modal/content-group-modal.vue b/src/fmg-components/content-group-modal/content-group-modal.vue index 25c50b2df..e4a5241c4 100644 --- a/src/fmg-components/content-group-modal/content-group-modal.vue +++ b/src/fmg-components/content-group-modal/content-group-modal.vue @@ -26,6 +26,7 @@ export default { name: "content-group-modal", props: { cmsWidgetName: String, + customBodyText: String, footerButtonActionName: { type: String, default: null, @@ -43,6 +44,9 @@ export default { return this.getCmsContent(this.cmsWidgetName, "SubheaderText"); }, ModalBodyText() { + if (this.customBodyText) { + return this.customBodyText; + } return this.getCmsContent(this.cmsWidgetName, "BodyText"); }, ModalSubBodyText() { diff --git a/src/helpers/pricing-helper.js b/src/helpers/pricing-helper.js index 68de04515..9564b5c1f 100644 --- a/src/helpers/pricing-helper.js +++ b/src/helpers/pricing-helper.js @@ -2,6 +2,7 @@ import store from "@/store"; import { storeActions } from "@/constants/store-actions"; import baseMixin from "@/mixins/base-mixin.js"; import { deepClone } from "@/helpers/object-helper"; +import { partNumberStrings } from "@/constants/part-number-strings"; export function getDisplayAmountDue(lineItemsObject, includeTax = true) { return getAmountDue(lineItemsObject, includeTax).toLocaleString("en-US", { @@ -32,6 +33,10 @@ export function getAmountDue(lineItemsObject, includeTax = true) { if (store.getters.coverageIsVerified && !order.policy.isNoComp && !order.policy.isItac) { amountDue = order.policy.currentDeductible; + + if (order.isMSRFeeApplicable && !order.isMSRFeeCoveredByInsurance) { + amountDue += getMSRFeePartPrice(lineItemsObject?.supportingItems, includeTax); + } } if (lineItemsObject?.vaps) { @@ -100,6 +105,20 @@ export async function getPricingByDayPartWithPrice(pageNameToLog) { return pricingResults[0]; } +export function getMSRFeePartPrice(supportingItems, includeTax) { + let msrFeePrice = 0; + const msrFeeLineItem = supportingItems?.find( + (lineItem) => lineItem.partNumber === partNumberStrings.MOBILE_STATIC_RECAL_FEE + ); + if (msrFeeLineItem) { + msrFeePrice = baseMixin?.methods?.getTotalPriceOfAllLineItemsAndChildParts( + [msrFeeLineItem], + includeTax + ); + } + return msrFeePrice; +} + export function addPricesToLineItems(lineItems, pricingLineItems) { lineItems.forEach((lineItem) => { const lineItemIndex = pricingLineItems.findIndex( diff --git a/src/layouts/confirmation/confirmation.vue b/src/layouts/confirmation/confirmation.vue index fa0e53425..e26c5f9b1 100644 --- a/src/layouts/confirmation/confirmation.vue +++ b/src/layouts/confirmation/confirmation.vue @@ -62,6 +62,7 @@ :showAsPaid="isPia" servicePackageOptionsCmsName="ServicePackageTitle" recyclingModalCmsWidgetName="RecycleModal" + msrModalCmsWidgetName="MSRModal" :isInsurance="isInsurance" :insuranceDeductible="currentDeductible" :insuranceCompanyName="insuranceCompanyName" @@ -70,7 +71,8 @@ :isItac="isItac" :isNoComp="isNoComp" :isExpandedOnLoad="false" - :isMSRFeeApplicable="isMSRFeeApplicable" /> + :isMSRFeeApplicable="isMSRFeeApplicable" + :IsMSRFeeCoveredByInsurance="isMSRFeeCoveredByInsurance" />
@@ -419,6 +421,9 @@ export default { isMSRFeeApplicable() { return this.submittedOrder?.isMSRFeeApplicable; }, + isMSRFeeCoveredByInsurance() { + return this.submittedOrder?.isMSRFeeCoveredByInsurance; + }, isInsurance() { return this.submittedOrder?.payment?.isInsurance; }, diff --git a/src/layouts/payment-adyen/payment-adyen.vue b/src/layouts/payment-adyen/payment-adyen.vue index 4a4936a7f..693263ebb 100644 --- a/src/layouts/payment-adyen/payment-adyen.vue +++ b/src/layouts/payment-adyen/payment-adyen.vue @@ -29,6 +29,7 @@ v-model="lineItems" servicePackageOptionsCmsName="ServicePackageTitle" recyclingModalCmsWidgetName="RecycleModal" + msrModalCmsWidgetName="MSRModal" :isInsurance="isInsurance" :insuranceDeductible="currentDeductible" :insuranceCompanyName="insuranceCompanyName" diff --git a/src/layouts/payment-method/payment-method.vue b/src/layouts/payment-method/payment-method.vue index 48f076f84..e5b08bdbc 100644 --- a/src/layouts/payment-method/payment-method.vue +++ b/src/layouts/payment-method/payment-method.vue @@ -26,6 +26,7 @@ pageName="payment-method" servicePackageOptionsCmsName="ServicePackageTitle" recyclingModalCmsWidgetName="RecycleModal" + msrModalCmsWidgetName="MSRModal" :isInsurance="isInsurance" :insuranceDeductible="currentDeductible" :insuranceCompanyName="insuranceCompanyName" @@ -35,7 +36,9 @@ :isNoComp="isNoComp" :isExpandedOnLoad="false" :isMSRFeeApplicable="isMSRFeeApplicable" - @itemRemoved="evaluatePromosAndTaxItemsOnOrder" /> + :IsMSRFeeCoveredByInsurance="isMSRFeeCoveredByInsurance" + @itemRemoved="evaluatePromosAndTaxItemsOnOrder" + @switchToInshop="navigateToSchedulePage" /> { isRecalAckOptIn: false, isRecalAcknowledgedForScheduling: "", isMSRFeeApplicable: false, + isMSRFeeCoveredByInsurance: false, }, applicationUser: { eventBus: [], @@ -359,6 +360,9 @@ export const mutations = { updateIsMSRFeeApplicable(state, isMSRFeeApplicable) { state.order.isMSRFeeApplicable = isMSRFeeApplicable; }, + updateIsMSRFeeCoveredByInsurance(state, isMSRFeeCoveredByInsurance) { + state.order.isMSRFeeCoveredByInsurance = isMSRFeeCoveredByInsurance; + }, updateCashPriceSubTotal(state, cashPriceSubTotal) { state.order.cashPriceSubTotal = cashPriceSubTotal === "" ? null : cashPriceSubTotal.toString(); @@ -2611,6 +2615,7 @@ export const actions = { lockToken: order.lockToken, isRecalAckOptIn: order.isRecalAckOptIn, isMSRFeeApplicable: order.isMSRFeeApplicable, + isMSRFeeCoveredByInsurance: order.isMSRFeeCoveredByInsurance, cashPriceSubTotal: order.cashPriceSubTotal, }, }, @@ -3043,6 +3048,13 @@ export const actions = { context.commit(storeMutations.UPDATE_IS_MSR_FEE_APPLICABLE, isMSRFeeApplicable); }, + saveIsMSRFeeCoveredByInsurance(context, isMSRFeeCoveredByInsurance) { + context.commit( + storeMutations.UPDATE_IS_MSR_FEE_COVERED_BY_INSURANCE, + isMSRFeeCoveredByInsurance + ); + }, + saveParentAccountNumber(context, parentAccountNumber) { context.commit(storeMutations.UPDATE_PARENT_ACCT_NUMBER, parentAccountNumber); },