diff --git a/src/constants/store-actions.js b/src/constants/store-actions.js index 2cfd08a8e..1861ac2c1 100644 --- a/src/constants/store-actions.js +++ b/src/constants/store-actions.js @@ -52,7 +52,7 @@ const storeActions = { RESET_SAVE_SESSION_PROMISE: "resetSaveSessionPromise", GET_SIGNATURE: "getSignature", VALIDATE_ORDER_PROMO_AND_SAVE_SERVER_DATA: "validateOrderPromoAndSaveServerData", - REVALIDATE_ORDER_PROMOS_AND_UPDATE_STORE: "revalidateOrderPromosAndUpdateStore", + REVALIDATE_ORDER_PROMOS_AND_SAVE_SERVER_DATA: "revalidateOrderPromosAndSaveServerData", // DEPENDENCY MUTATIONS RESET_DAMAGE_STATE_AND_DEPENDENCIES: "resetDamageAndDependencies", @@ -87,6 +87,7 @@ const storeActions = { "saveSupportingItemsSuppressingStateResetting", SAVE_VAPS: "saveVaps", SAVE_PROMOS: "savePromos", + SAVE_INACTIVE_PROMOS: "saveInactivePromos", SAVE_CUSTOMER_DETAILS: "saveCustomerDetails", SAVE_SERVICE_LOCATION_TECH_NOTES: "saveServiceLocationTechNotes", SAVE_CCTOKEN: "saveCCToken", diff --git a/src/helpers/promotions-helper.js b/src/helpers/promotions-helper.js index 08f7daa8f..a5d94789b 100644 --- a/src/helpers/promotions-helper.js +++ b/src/helpers/promotions-helper.js @@ -37,6 +37,8 @@ export function getLineItemsThatMatchPromos(promos, availableLineItems) { return matchingLineItems; } +// Note: Addable VAPs for the Promo Validation endpoint can also be on the order already +// There is no need to only send un-added VAPs in this array. export function getAddableVapsFromAvailableLineItems(availableLineItems) { const addableVaps = []; addableVaps.push(...findLineItemsWithPartType(partTypeStrings.FRONT_WIPER, availableLineItems)); @@ -75,11 +77,22 @@ export async function revalidatePromosAndValidateNewPromo( if (hasActivePromos || hasHasInactivePromos) { revalidatePromoResponse = await baseMixin.methods.dispatchStoreActionWithLogging( - storeActions.REVALIDATE_ORDER_PROMOS_AND_UPDATE_STORE, - null, + storeActions.REVALIDATE_ORDER_PROMOS_AND_SAVE_SERVER_DATA, + {}, pageNameToLog, false ); + baseMixin.methods.dispatchStoreAction( + storeActions.SAVE_PROMOS, + revalidatePromoResponse.promoLineItems, + false + ); + const revalidationErrorPromoCodes = revalidatePromoResponse.errors.map((x) => x.promoCode); + baseMixin.methods.dispatchStoreAction( + storeActions.SAVE_INACTIVE_PROMOS, + revalidationErrorPromoCodes, + false + ); } if (hasNewPromo) { validatePromoResponse = await baseMixin.methods.dispatchStoreActionWithLogging( diff --git a/src/layouts/payment-method/payment-method.vue b/src/layouts/payment-method/payment-method.vue index 866703110..416946648 100644 --- a/src/layouts/payment-method/payment-method.vue +++ b/src/layouts/payment-method/payment-method.vue @@ -84,6 +84,12 @@ import store from "@/store"; import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; import { paymentMethods } from "@/constants/payment-method-constants"; import { experimentSettings } from "@/constants/experiments"; +import { + revalidatePromosAndValidateNewPromo, + getAddableVapsFromAvailableLineItems, +} from "@/helpers/promotions-helper"; +import { queryStrings } from "@/constants/query-strings"; +import { getQuerystringParameter } from "@/helpers/querystring-helper"; import { Form } from "vee-validate"; import { defineRule } from "vee-validate"; @@ -159,6 +165,19 @@ export default { false ); + // Promo logic + const promoCodeFromQueryString = getQuerystringParameter(queryStrings.PROMO); + + const { validatePromoResponse, revalidatePromoResponse } = + await revalidatePromosAndValidateNewPromo( + promoCodeFromQueryString, + availableLineItems, + "payment-method" + ); + + availableLineItems.push(...(validatePromoResponse?.orderPromos ?? [])); + // End of promo logic + const taxedAvailableLineItems = await baseMixin.methods.dispatchStoreActionWithLogging( storeActions.TAX_ORDER_ITEMS_AND_SAVE_SERVER_DATA, { @@ -195,6 +214,7 @@ export default { lineItems: [], availableLineItems: [], paymentMethodInternalModel: this.getPaymentMethodFromStore(), + inactivePromos: this.getInactivePromosFromStore(), }; }, methods: { @@ -266,6 +286,24 @@ export default { updateFooterButtonText(newValue) { this.$refs.navbar.updateButtonText(newValue); }, + getInactivePromosFromStore() { + return this.$store.getters.order.payment.inactivePromos; + }, + async revalidatePromos() { + const revalidatePromoResponse = await baseMixin.methods.dispatchStoreActionWithLogging( + storeActions.REVALIDATE_ORDER_PROMOS_AND_SAVE_SERVER_DATA, + { + activePromosToUse: this.lineItems.promos, + inactivePromosToUse: this.inactivePromos, + lineItemsToUse: this.lineItems, + }, + "payment-method", + false + ); + + this.lineItems.promos = revalidatePromoResponse.promoLineItems; + this.inactivePromos = revalidatePromoResponse.errors.map((x) => x.promoCode); + }, backButtonAction() { this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route); }, @@ -290,6 +328,11 @@ export default { ); await this.dispatchStoreAction(storeActions.SAVE_VAPS, this.lineItems.vaps, false); await this.dispatchStoreAction(storeActions.SAVE_PROMOS, this.lineItems.promos, false); + await this.dispatchStoreAction( + storeActions.SAVE_INACTIVE_PROMOS, + this.inactivePromos, + false + ); if (this.paymentMethod == paymentMethods.LATER) { // this creates the final work order diff --git a/src/layouts/quote/quote.vue b/src/layouts/quote/quote.vue index 507532f4e..d956632ef 100644 --- a/src/layouts/quote/quote.vue +++ b/src/layouts/quote/quote.vue @@ -83,7 +83,7 @@ import { payWithInsuranceStates } from "@/constants/pay-with-insurance-states"; import { revalidatePromosAndValidateNewPromo } from "@/helpers/promotions-helper"; import { queryStrings } from "@/constants/query-strings"; import { getQuerystringParameter } from "@/helpers/querystring-helper"; -import { setTransitionHooks } from "vue"; + defineRule("option-required", required(errorMessages.OPTION_REQUIRED)); export default { @@ -168,7 +168,7 @@ export default { vm.supportingItems = resultMap.supportingItems; vm.availableLineItems = pricingResults; vm.isInsuranceSelected = vm.getDefaultIsInsuranceSelectedValue(vm.availableLineItems); - vm.newValidatedPromos = validatePromoResponse?.data.orderPromos; + vm.newValidatedPromos = validatePromoResponse?.orderPromos; }); }, data() { diff --git a/src/store/index.js b/src/store/index.js index c096fa8fd..e2915a1af 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -2107,6 +2107,9 @@ export const actions = { savePromos(context, promos) { context.commit(storeMutations.UPDATE_PROMOS, promos); }, + saveInactivePromos(context, inactivePromos) { + context.commit(storeMutations.UPDATE_INACTIVE_PROMOS, inactivePromos); + }, // Price order actions async priceOrderItemsAndSaveServerData( @@ -2240,11 +2243,15 @@ export const actions = { return pricedAvailableLineItems; }, + // The parameter is an array of ALL available front wipers and rain defense + // for the vehicle. There is no need to confirm an addableVap is not already on the order + // is an optional parameter if the lineItems in the store may not be up to date async validateOrderPromoAndSaveServerData( context, - { payload: { promoCode, addableVaps }, pageNameToLog } + { payload: { promoCode, lineItemsToUse, addableVaps }, pageNameToLog } ) { const order = context.getters.order; + lineItemsToUse = lineItemsToUse ?? order.lineItems; addGuidToLineItemsIfNotAlreadyThere(addableVaps); const requestObject = { promoCode: promoCode, @@ -2256,7 +2263,7 @@ export const actions = { eon: order.eon, isRepair: order.damage.isRepair, glassToReplace: renameGlassToReplaceAttributes(order.damage.glassToReplace), - lineItemsOnOrder: getArrayOfAllLineItems(order.lineItems), + lineItemsOnOrder: getArrayOfAllLineItems(lineItemsToUse), parentAccountNumber: order.payment.parentAccountNumber, referralSequenceNumber: order.referralSequenceNumber, serviceState: order.serviceLocation.state, @@ -2289,13 +2296,22 @@ export const actions = { ); } - return validateResponse; + return validateResponse?.data; }, - async revalidateOrderPromosAndUpdateStore(context, { pageNameToLog }) { + // All payload parameters are optional - will use store data if not provided + async revalidateOrderPromosAndSaveServerData( + context, + { payload: { activePromosToUse, inactivePromosToUse, lineItemsToUse }, pageNameToLog } + ) { const order = context.getters.order; + activePromosToUse = activePromosToUse ?? order.lineItems.promos; + inactivePromosToUse = inactivePromosToUse ?? order.payment.inactivePromos; + lineItemsToUse = lineItemsToUse ? deepClone(lineItemsToUse) : deepClone(order.lineItems); + lineItemsToUse.promos = activePromosToUse; + let requestObject = { - inactivePromos: order.payment.inactivePromos, + inactivePromos: inactivePromosToUse, order: { appointmentType: order.serviceLocation.appointmentType, carId: order.vehicle.carId, @@ -2303,7 +2319,7 @@ export const actions = { eon: order.eon, isRepair: order.damage.isRepair, glassToReplace: renameGlassToReplaceAttributes(order.damage.glassToReplace), - lineItemsOnOrder: getArrayOfAllLineItems(order.lineItems), + lineItemsOnOrder: getArrayOfAllLineItems(lineItemsToUse), parentAccountNumber: order.payment.parentAccountNumber, referralSequenceNumber: order.referralSequenceNumber, serviceState: order.serviceLocation.state, @@ -2324,16 +2340,12 @@ export const actions = { pageNameToLog: pageNameToLog, }); - const revalidationErrorPromoCodes = revalidateResponse.data.errors.map((x) => x.promoCode); - - context.commit(storeMutations.UPDATE_PROMOS, revalidateResponse.data.promoLineItems); - context.commit(storeMutations.UPDATE_INACTIVE_PROMOS, revalidationErrorPromoCodes); context.commit( storeMutations.UPDATE_LINE_ITEMS_SERVER_DATA, revalidateResponse.data.lineItemsServerData ); - return revalidateResponse; + return revalidateResponse?.data; }, // Misc order actions