CSR-1452 | Rewrite save promo functions
Combined inactive and active into one method -new save method prevents the same promos ending up in inactive AND active at the same time -query string promos save to inactive automatically
This commit is contained in:
parent
044ce50de9
commit
f8f9749d3a
7 changed files with 113 additions and 31 deletions
|
|
@ -86,8 +86,7 @@ const storeActions = {
|
|||
SAVE_SUPPORTING_ITEMS_SUPPRESSING_STATE_RESETTING:
|
||||
"saveSupportingItemsSuppressingStateResetting",
|
||||
SAVE_VAPS: "saveVaps",
|
||||
SAVE_PROMOS: "savePromos",
|
||||
SAVE_INACTIVE_PROMOS: "saveInactivePromos",
|
||||
SAVE_ACTIVE_AND_OR_INACTIVE_PROMOS: "saveActiveAndOrInactivePromos",
|
||||
SAVE_CUSTOMER_DETAILS: "saveCustomerDetails",
|
||||
SAVE_SERVICE_LOCATION_TECH_NOTES: "saveServiceLocationTechNotes",
|
||||
SAVE_CCTOKEN: "saveCCToken",
|
||||
|
|
|
|||
|
|
@ -17,9 +17,31 @@ export const addableVapsPromoPartNumbers = [
|
|||
];
|
||||
|
||||
const promoErrorCodes = {
|
||||
CANNOT_COMBINE: "SimilarPromoAlreadyOnOrder",
|
||||
UNKNOWN: "Unknown",
|
||||
PROMO_NOT_YET_IN_USE: "PromoNotYetInUse",
|
||||
PROMO_USAGE_COUNT_EXCEEDED: "PromoUsageCountExceeded",
|
||||
PROMO_EXPIRED: "PromoExpired",
|
||||
PROMO_DOES_NOT_EXIST: "PromoDoesNotExist",
|
||||
PROMO_STACKING_NOT_ALLOWED: "PromoStackingNotAllowed",
|
||||
SIMILAR_PROMO_ALREADY_ON_ORDER: "SimilarPromoAlreadyOnOrder",
|
||||
INVALID_PROMO_ON_ORDER: "InvalidPromoOnOrder",
|
||||
PROMO_VALIDATION_ERROR: "PromoValidationError",
|
||||
NO_SUITABLE_ITEM_FOR_PROMO: "NoSuitableItemForPromo",
|
||||
};
|
||||
|
||||
const stackingPromoErrorCodes = [
|
||||
promoErrorCodes.PROMO_STACKING_NOT_ALLOWED,
|
||||
promoErrorCodes.SIMILAR_PROMO_ALREADY_ON_ORDER,
|
||||
];
|
||||
|
||||
const excludeFromInactivePromoErrorCodes = [
|
||||
promoErrorCodes.UNKNOWN,
|
||||
promoErrorCodes.PROMO_NOT_YET_IN_USE,
|
||||
promoErrorCodes.PROMO_USAGE_COUNT_EXCEEDED,
|
||||
promoErrorCodes.PROMO_EXPIRED,
|
||||
promoErrorCodes.PROMO_DOES_NOT_EXIST,
|
||||
];
|
||||
|
||||
export const pagesToStripPromoQueryStringFrom = ["quote", "payment-method"];
|
||||
|
||||
export function getPromosWithAddableVaps(promoList) {
|
||||
|
|
@ -67,35 +89,36 @@ export function removeVapsPromosFromPromoArray(promoArray) {
|
|||
return filteredPromoArray;
|
||||
}
|
||||
|
||||
export async function revalidatePromosAndValidateNewPromo(
|
||||
export async function revalidatePromosAndValidateQueryStringPromo(
|
||||
newPromo,
|
||||
pricedLineItems,
|
||||
pageNameToLog
|
||||
) {
|
||||
const hasActivePromos = store.getters.order.lineItems.promos;
|
||||
const hasHasInactivePromos = store.getters.order.lineItems.inactivePromos;
|
||||
const hasInactivePromos = store.getters.payment.inactivePromos;
|
||||
const hasNewPromo = !!newPromo;
|
||||
const addableVaps = getAddableVapsFromAvailableLineItems(pricedLineItems);
|
||||
|
||||
let validatePromoResponse = null;
|
||||
let revalidatePromoResponse = null;
|
||||
|
||||
if (hasActivePromos || hasHasInactivePromos) {
|
||||
if (
|
||||
(hasActivePromos && hasActivePromos.length) ||
|
||||
(hasInactivePromos && hasInactivePromos.length)
|
||||
) {
|
||||
revalidatePromoResponse = await baseMixin.methods.dispatchStoreActionWithLogging(
|
||||
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,
|
||||
storeActions.SAVE_ACTIVE_AND_OR_INACTIVE_PROMOS,
|
||||
{
|
||||
activePromos: revalidatePromoResponse.promoLineItems,
|
||||
inactivePromos: revalidationErrorPromoCodes,
|
||||
},
|
||||
false
|
||||
);
|
||||
}
|
||||
|
|
@ -109,8 +132,22 @@ export async function revalidatePromosAndValidateNewPromo(
|
|||
pageNameToLog,
|
||||
false
|
||||
);
|
||||
if (!excludeFromInactivePromoErrorCodes.includes(validatePromoResponse.errorCode)) {
|
||||
// Save any valid (applied or not) query string promoCode to inactivePromos
|
||||
// in order to not lose the query string promoCode if back button is pressed
|
||||
const inactivePromoCodes = store.getters.payment.inactivePromos ?? [];
|
||||
if (!inactivePromoCodes.includes(newPromo)) {
|
||||
inactivePromoCodes.push(newPromo);
|
||||
baseMixin.methods.dispatchStoreAction(
|
||||
storeActions.SAVE_ACTIVE_AND_OR_INACTIVE_PROMOS,
|
||||
{
|
||||
inactivePromos: inactivePromoCodes,
|
||||
},
|
||||
false
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return { validatePromoResponse, revalidatePromoResponse };
|
||||
}
|
||||
|
||||
|
|
@ -243,7 +280,7 @@ function getPromoCodesFromPromoObjectsWithoutDuplicates(promos) {
|
|||
function createPromoSuccessAlert(promoCode) {
|
||||
return {
|
||||
messageHeadline: "Promo applied!",
|
||||
messageCopy: `Promo "${promoCode}" was successfully applied to your cart.`,
|
||||
messageCopy: `Promo "${promoCode.toUpperCase()}" was successfully applied to your cart.`,
|
||||
type: "alert-success",
|
||||
isDismissible: true,
|
||||
shouldAutoFade: true,
|
||||
|
|
@ -257,10 +294,10 @@ function createPromoErrorAlert(promoCode, errorCode = null, additionalInfo) {
|
|||
shouldAutoFade: false,
|
||||
isDismissible: true,
|
||||
};
|
||||
if (errorCode == promoErrorCodes.CANNOT_COMBINE) {
|
||||
alert.messageCopy = `Sorry, promo code "${promoCode}" cannot be combined with ${additionalInfo[0]}`;
|
||||
if (stackingPromoErrorCodes.includes(errorCode)) {
|
||||
alert.messageCopy = `Sorry, promo code "${promoCode.toUpperCase()}" cannot be combined with "${additionalInfo[0].toUpperCase()}"`;
|
||||
} else {
|
||||
alert.messageCopy = `Sorry, promo code "${promoCode}" is not valid`;
|
||||
alert.messageCopy = `Sorry, promo code "${promoCode.toUpperCase()}" is not valid`;
|
||||
}
|
||||
return alert;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
|||
import { paymentMethods } from "@/constants/payment-method-constants";
|
||||
import { experimentSettings } from "@/constants/experiments";
|
||||
import {
|
||||
revalidatePromosAndValidateNewPromo,
|
||||
revalidatePromosAndValidateQueryStringPromo,
|
||||
buildToastMessagesFromRevalidateOrValidatePromoResponse,
|
||||
getVapsThatNeedToBeAddedToSatisfyPromos,
|
||||
} from "@/helpers/promotions-helper";
|
||||
|
|
@ -165,7 +165,7 @@ export default {
|
|||
|
||||
const promoCodeFromQueryString = getQuerystringParameter(queryStrings.PROMO);
|
||||
const { validatePromoResponse, revalidatePromoResponse } =
|
||||
await revalidatePromosAndValidateNewPromo(
|
||||
await revalidatePromosAndValidateQueryStringPromo(
|
||||
promoCodeFromQueryString,
|
||||
pricedLineItemsToTax,
|
||||
"payment-method"
|
||||
|
|
@ -360,10 +360,12 @@ export default {
|
|||
false
|
||||
);
|
||||
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,
|
||||
this.dispatchStoreAction(
|
||||
storeActions.SAVE_ACTIVE_AND_OR_INACTIVE_PROMOS,
|
||||
{
|
||||
activePromos: this.lineItems.promos,
|
||||
inactivePromos: this.inactivePromos,
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -190,7 +190,7 @@ import { AppointmentTypeStrings } from "@/constants/schedule-constants";
|
|||
import baseMixin from "@/mixins/base-mixin.js";
|
||||
import { mapTaxedLineItemsToStoreFormat } from "../../store";
|
||||
import {
|
||||
revalidatePromosAndValidateNewPromo,
|
||||
revalidatePromosAndValidateQueryStringPromo,
|
||||
getAddableVapsFromAvailableLineItems,
|
||||
getVapsThatNeedToBeAddedToSatisfyPromos,
|
||||
} from "@/helpers/promotions-helper";
|
||||
|
|
@ -324,7 +324,7 @@ export default {
|
|||
const promoCodeFromQueryString = getQuerystringParameter(queryStrings.PROMO);
|
||||
|
||||
const { validatePromoResponse, revalidatePromoResponse } =
|
||||
await revalidatePromosAndValidateNewPromo(
|
||||
await revalidatePromosAndValidateQueryStringPromo(
|
||||
promoCodeFromQueryString,
|
||||
pricedLineItemsToTax,
|
||||
"payment"
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ jest.mock("@/helpers/heritage-integration/navigation-helper", () => ({
|
|||
}));
|
||||
|
||||
jest.mock("@/helpers/promotions-helper", () => ({
|
||||
revalidatePromosAndValidateNewPromo: jest.fn(() => {
|
||||
revalidatePromosAndValidateQueryStringPromo: jest.fn(() => {
|
||||
return { validatePromoResponse: null, revalidatePromoResponse: null };
|
||||
}),
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ import { navigateToHeritageFunnel } from "@/helpers/heritage-integration/navigat
|
|||
import { applicationConfig } from "@/constants/application-config";
|
||||
import { payWithInsuranceStates } from "@/constants/pay-with-insurance-states";
|
||||
import {
|
||||
revalidatePromosAndValidateNewPromo,
|
||||
revalidatePromosAndValidateQueryStringPromo,
|
||||
buildToastMessagesFromRevalidateOrValidatePromoResponse,
|
||||
} from "@/helpers/promotions-helper";
|
||||
import { queryStrings } from "@/constants/query-strings";
|
||||
|
|
@ -161,7 +161,7 @@ export default {
|
|||
const promoCodeFromQueryString = getQuerystringParameter(queryStrings.PROMO);
|
||||
|
||||
const { validatePromoResponse, revalidatePromoResponse } =
|
||||
await revalidatePromosAndValidateNewPromo(
|
||||
await revalidatePromosAndValidateQueryStringPromo(
|
||||
promoCodeFromQueryString,
|
||||
pricingResults,
|
||||
"quote"
|
||||
|
|
@ -291,7 +291,11 @@ export default {
|
|||
}
|
||||
|
||||
this.dispatchStoreAction(this.storeActions.SAVE_VAPS, this.selectedVaps, false);
|
||||
this.dispatchStoreAction(this.storeActions.SAVE_PROMOS, this.allActivePromos, false);
|
||||
this.dispatchStoreAction(
|
||||
this.storeActions.SAVE_ACTIVE_AND_OR_INACTIVE_PROMOS,
|
||||
{ activePromos: this.allActivePromos },
|
||||
false
|
||||
);
|
||||
|
||||
const payment = this.$store.getters.payment;
|
||||
if (payment.isInsurance) {
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import {
|
|||
getDisplayTextForDurationLength,
|
||||
} from "@/layouts/schedule/helpers/schedule-helper";
|
||||
import { paymentMethods } from "@/constants/payment-method-constants";
|
||||
|
||||
import { getPromoCodeWithoutBundleIdentifier } from "@/helpers/promotions-helper";
|
||||
import { getDateDifferenceInDays } from "@/helpers/date-helper";
|
||||
// Export State
|
||||
const getDefaultState = () => {
|
||||
|
|
@ -2125,6 +2125,46 @@ export const actions = {
|
|||
saveInactivePromos(context, inactivePromos) {
|
||||
context.commit(storeMutations.UPDATE_INACTIVE_PROMOS, inactivePromos);
|
||||
},
|
||||
// Manage promo saving to ensure a promoCode never ends up in both active and inactive
|
||||
saveActiveAndOrInactivePromos(context, { activePromos = null, inactivePromos = null }) {
|
||||
let activePromosToSave;
|
||||
let inactivePromosToSave;
|
||||
if (!activePromos && !inactivePromos) {
|
||||
// Allow double null to save empty arrays to store
|
||||
activePromosToSave = [];
|
||||
inactivePromosToSave = [];
|
||||
} else if (activePromos && inactivePromos) {
|
||||
// Prioritize active promos when both inactive and active are supplied
|
||||
activePromosToSave = activePromos;
|
||||
const activePromoCodes = activePromos.map((promoObject) =>
|
||||
getPromoCodeWithoutBundleIdentifier(promoObject.promoCode)
|
||||
);
|
||||
inactivePromosToSave = inactivePromos.filter((inactivePromo) => {
|
||||
return !activePromoCodes.includes(inactivePromo);
|
||||
});
|
||||
} else if (!activePromos) {
|
||||
// Only inactivePromos supplied
|
||||
inactivePromosToSave = inactivePromos;
|
||||
activePromosToSave = (context.getters.lineItems.promos ?? []).filter((activePromo) => {
|
||||
return !inactivePromosToSave.includes(
|
||||
getPromoCodeWithoutBundleIdentifier(activePromo.promoCode)
|
||||
);
|
||||
});
|
||||
} else if (!inactivePromos) {
|
||||
// Only activePromos supplied
|
||||
activePromosToSave = activePromos;
|
||||
const activePromoCodes = activePromos.map((promoObject) =>
|
||||
getPromoCodeWithoutBundleIdentifier(promoObject.promoCode)
|
||||
);
|
||||
inactivePromosToSave = (context.getters.payment.inactivePromos ?? []).filter(
|
||||
(inactivePromo) => {
|
||||
return !activePromoCodes.includes(inactivePromo);
|
||||
}
|
||||
);
|
||||
}
|
||||
context.commit(storeMutations.UPDATE_PROMOS, activePromosToSave);
|
||||
context.commit(storeMutations.UPDATE_INACTIVE_PROMOS, inactivePromosToSave);
|
||||
},
|
||||
|
||||
// Price order actions
|
||||
async priceOrderItemsAndSaveServerData(
|
||||
|
|
|
|||
Loading…
Reference in a new issue