CSR-1520 | Package selection promo logic
This commit is contained in:
parent
10dbe7bf42
commit
2516adc2fc
7 changed files with 85 additions and 6 deletions
|
|
@ -52,7 +52,7 @@ https://safelite.atlassian.net/wiki/spaces/DC/pages/76644418/Button+Question+Com
|
|||
:isWide="isWide"
|
||||
:validationRules="validationRules"
|
||||
:textPosition="textPosition"
|
||||
:additionalButtonData="additionalButtonData"
|
||||
:additionalButtonData="answer.additionalButtonData"
|
||||
:lastValuePushedToGa="lastValuePushedToGa"
|
||||
:setLastValuePushedToGa="setLastValuePushedToGa"
|
||||
:suppressError="suppressError"
|
||||
|
|
@ -252,6 +252,7 @@ export default {
|
|||
buttonFooterCopy: answer.buttonFooterCopy ?? answer.buttonFooterCopy,
|
||||
buttonImage: answer.buttonImage ?? answer.AnswerImageUrl,
|
||||
buttonImageId: answer.buttonImageId ?? answer.ImageId,
|
||||
additionalButtonData: answer.additionalButtonData ?? answer.additionalButtonData,
|
||||
groupName: this.formatString(this.groupName),
|
||||
value:
|
||||
answer.value ??
|
||||
|
|
|
|||
|
|
@ -10,8 +10,37 @@ export const promoPartNumberStrings = {
|
|||
GLASS_CLEANER_DISCOUNT_PART_NUMBER: "DISC GLASS CLN",
|
||||
};
|
||||
|
||||
export const addableVapsPromoPartNumbers = [
|
||||
promoPartNumberStrings.RAIN_DEFENSE_DISCOUNT_PART_NUMBER,
|
||||
promoPartNumberStrings.WIPER_DISCOUNT_PART_NUMBER,
|
||||
];
|
||||
|
||||
export const pagesToStripPromoQueryStringFrom = ["quote", "payment-method"];
|
||||
|
||||
export function getPromosWithAddableVaps(promoList) {
|
||||
if (!promoList.length) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return promoList.filter((promo) =>
|
||||
addableVapsPromoPartNumbers.includes(promo.partNumber)
|
||||
);
|
||||
}
|
||||
|
||||
export function getLineItemsThatMatchPromos(promos, availableLineItems) {
|
||||
const matchingLineItems = [];
|
||||
promos.forEach((promo) => {
|
||||
promo.discountedLineItemIds.forEach((discountedLineItemId) => {
|
||||
matchingLineItems.push(
|
||||
...availableLineItems.filter(
|
||||
(lineItem) => lineItem.id === discountedLineItemId
|
||||
)
|
||||
);
|
||||
});
|
||||
});
|
||||
return matchingLineItems;
|
||||
}
|
||||
|
||||
export function getAddableVapsFromAvailableLineItems(availableLineItems) {
|
||||
const addableVaps = [];
|
||||
addableVaps.push(...findLineItemsWithPartType(partTypeStrings.FRONT_WIPER, availableLineItems));
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
:groupName="groupName"
|
||||
buttonTypeString="listButtonHorizontal"
|
||||
v-model="selectedValues"
|
||||
:additionalButtonData="additionalButtonData"
|
||||
isRequired />
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -25,7 +24,13 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
answersFromCms() {
|
||||
return this.getCmsContent(this.cmsWidgetName, "Answers");
|
||||
const answers = this.getCmsContent(this.cmsWidgetName, "Answers");
|
||||
if (answers) {
|
||||
answers.forEach(
|
||||
(answer) => (answer.additionalButtonData = this.additionalButtonData)
|
||||
);
|
||||
}
|
||||
return answers;
|
||||
},
|
||||
additionalButtonData() {
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ describe("service-package-question.vue", () => {
|
|||
price: 35.5,
|
||||
},
|
||||
],
|
||||
activePromos: [],
|
||||
};
|
||||
const packageNameKey = "05_01_CSR_Quote_Standard_Repair";
|
||||
Object.assign(processedCmsContent, mockProcessedCmsContent[packageNameKey]);
|
||||
|
|
@ -291,6 +292,7 @@ describe("service-package-question.vue, matching business rules for package disp
|
|||
price: 35.5,
|
||||
},
|
||||
],
|
||||
activePromos: [],
|
||||
};
|
||||
});
|
||||
it("should match the 05_01_CSR_Quote_Standard_Repair mock", () => {
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ import {
|
|||
import {
|
||||
getPromosThatMatchLineItemsOnOrder,
|
||||
removeVapsPromosFromPromoArray,
|
||||
getPromosWithAddableVaps,
|
||||
getLineItemsThatMatchPromos,
|
||||
} from "@/helpers/promotions-helper";
|
||||
|
||||
export default {
|
||||
|
|
@ -54,7 +56,10 @@ export default {
|
|||
},
|
||||
watch: {
|
||||
availableLineItems() {
|
||||
if (this.$store.getters.payment.isInsurance != null) {
|
||||
if (
|
||||
this.$store.getters.payment.isInsurance != null ||
|
||||
getPromosWithAddableVaps(this.activePromos).length
|
||||
) {
|
||||
this.selectDefaultPackage();
|
||||
}
|
||||
},
|
||||
|
|
@ -217,13 +222,16 @@ export default {
|
|||
return price;
|
||||
},
|
||||
selectDefaultPackage() {
|
||||
const promosWithAddableVaps = getPromosWithAddableVaps(this.activePromos);
|
||||
const vapsThatMatchPromos = getLineItemsThatMatchPromos(promosWithAddableVaps, this.nullSafeAvailableLineItems);
|
||||
const vapsFromStore = this.$store.getters.lineItems.vaps ?? [];
|
||||
const vapsToUseForDefaultPackageSelection = this.combineLineItemsWithoutDuplicates(vapsThatMatchPromos, vapsFromStore);
|
||||
|
||||
this.selectedPackageName = getHighestRequiredTier(
|
||||
this.glassToReplace,
|
||||
this.nullSafeAvailableLineItems,
|
||||
this.isRepair,
|
||||
vapsFromStore
|
||||
vapsToUseForDefaultPackageSelection
|
||||
);
|
||||
},
|
||||
getVapsLineItemsForSelectedPackage(packageName) {
|
||||
|
|
@ -244,6 +252,19 @@ export default {
|
|||
|
||||
return vapsLineItemsForSelectedPackage;
|
||||
},
|
||||
combineLineItemsWithoutDuplicates(lineItemsOne, lineItemsTwo) {
|
||||
const combinedLineItemArray = [...lineItemsTwo];
|
||||
lineItemsOne.forEach((lineItemOne) => {
|
||||
if (
|
||||
!lineItemsTwo.filter(
|
||||
(lineItemTwo) => lineItemTwo.id === lineItemOne.id
|
||||
).length
|
||||
) {
|
||||
combinedLineItemArray.push(lineItemOne);
|
||||
}
|
||||
});
|
||||
return combinedLineItemArray;
|
||||
},
|
||||
getCustomValueFromString(str) {
|
||||
switch (str) {
|
||||
case "isRecalibrationOnOrder":
|
||||
|
|
|
|||
|
|
@ -122,6 +122,8 @@ const mockProps = {
|
|||
buttonBodyCopy:
|
||||
"<ul><li>buttonBodyCopy test copy</li><li>2</li><li>3</li><li>4</li><li>5</li></ul>",
|
||||
buttonFooterCopy: "buttonFooterCopy test copy",
|
||||
buttonAuxillaryCopy: "buttonAuxillaryCopy test copy",
|
||||
additionalButtonData: { strikeThroughPrice: "strikeThroughPrice test copy"},
|
||||
};
|
||||
|
||||
function setupMocks({ mountOptionsMockData = {} }) {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,13 @@
|
|||
<div class="package-specs">
|
||||
<p class="m-0">
|
||||
<span v-html="this.buttonLabel"></span>
|
||||
<span class="pricing-info" v-html="this.buttonAuxillaryCopy"></span>
|
||||
<span class="pricing-info">
|
||||
<span
|
||||
class="strikethrough-price"
|
||||
v-if="shouldDisplayStrikeThroughPrice"
|
||||
v-html="this.additionalButtonData.strikeThroughPrice"></span>
|
||||
<span v-html="this.buttonAuxillaryCopy"></span>
|
||||
</span>
|
||||
</p>
|
||||
<p
|
||||
class="sub-label m-0"
|
||||
|
|
@ -76,6 +82,12 @@ export default {
|
|||
arrayOfListItemsFromBodyText() {
|
||||
return this.getArrayOfListItemsFromRawCmsCopy(this.buttonBodyCopy);
|
||||
},
|
||||
shouldDisplayStrikeThroughPrice() {
|
||||
const displayPrice = this.buttonAuxillaryCopy.substring(
|
||||
this.buttonAuxillaryCopy.indexOf("$")
|
||||
);
|
||||
return displayPrice != this.additionalButtonData.strikeThroughPrice;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
getRouterLinkDisplayTextFromCopy,
|
||||
|
|
@ -219,6 +231,13 @@ export default {
|
|||
&.pricing-info {
|
||||
color: $green;
|
||||
font-size: 0.875rem;
|
||||
span.strikethrough-price {
|
||||
text-decoration: line-through;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 400;
|
||||
color: $gray-550;
|
||||
padding-right: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
&.sub-label {
|
||||
|
|
|
|||
Loading…
Reference in a new issue