From 1e1204fcfabb4da669c2d1c00379e16984971ef9 Mon Sep 17 00:00:00 2001 From: Scott Kiener Date: Tue, 14 Mar 2023 16:52:44 -0400 Subject: [PATCH] Merge pull request #973 from Safelite/defect/CSR-1168 CSR-1168 | Default service package selection changes --- src/layouts/quote/quote.vue | 15 +- .../service-package-question.spec.js | 207 ++++++++++++++++++ .../service-package-question.vue | 28 ++- 3 files changed, 246 insertions(+), 4 deletions(-) diff --git a/src/layouts/quote/quote.vue b/src/layouts/quote/quote.vue index dfada2db0..ad9321846 100644 --- a/src/layouts/quote/quote.vue +++ b/src/layouts/quote/quote.vue @@ -107,12 +107,14 @@ export default { ]; const resultMap = await settleAllPromises(promiseResultMap); - const glassParts = store.getters.order.lineItems.glassParts ?? []; + const clonedGlassParts = store.getters.order.lineItems.glassParts + ? JSON.parse(JSON.stringify(store.getters.order.lineItems.glassParts)) + : []; const availableLineItems = [ resultMap.rainDefense, ...resultMap.supportingItems, ...resultMap.wipers, - ...glassParts, + ...clonedGlassParts, ]; const pricingResults = await baseMixin.methods.dispatchStoreAction( @@ -124,6 +126,7 @@ export default { // Call the "next" function to complete the transition to this page. next((vm) => { vm.setCmsContent(resultMap.cmsContent); + vm.pricedGlassParts = clonedGlassParts; vm.supportingItems = resultMap.supportingItems; vm.availableLineItems = pricingResults; vm.isInsuranceSelected = vm.getDefaultIsInsuranceSelectedValue(vm.availableLineItems); @@ -135,6 +138,7 @@ export default { selectedVaps: null, availableLineItems: null, supportingItems: null, + pricedGlassParts: null, }; }, methods: { @@ -187,6 +191,13 @@ export default { if (this.$store.getters.order.accountNumber != applicationConfig.CASH_ACCOUNT_NUMBER) { this.supportingItems = this.filterOutFees(this.supportingItems); } + if (this.pricedGlassParts.length > 0) { + this.dispatchStoreAction( + this.storeActions.SAVE_GLASS_PARTS, + this.pricedGlassParts, + false + ); + } this.dispatchStoreAction( this.storeActions.SAVE_SUPPORTING_ITEMS, this.supportingItems, diff --git a/src/layouts/quote/service-package-question/service-package-question.spec.js b/src/layouts/quote/service-package-question/service-package-question.spec.js index cd10b893f..af04ff36a 100644 --- a/src/layouts/quote/service-package-question/service-package-question.spec.js +++ b/src/layouts/quote/service-package-question/service-package-question.spec.js @@ -135,6 +135,213 @@ describe("service-package-question.vue", () => { expectedModifiedAnswers[packageNameKey].tierThree ); }); + it("should not select a default package if ANY glass part or supporting item has no prices", async () => { + // Note, only the first WSREPAIR item has a 0 for laborAmount, this is enough to not try and select a default package + const wrapper = setupMocks({ + mountOptionsMockData: { + store: { + getters: { + lineItems: { + glassParts: [ + { + partNumber: "FW02627GBYNOEE", + description: "solar, 3rd visor band", + color: "Green Tint, Blue Shade", + partType: "WINDSHIELD", + canSafeliteRecalibrate: false, + requiresRecalibration: false, + requiresCapabilityQuestions: false, + recalibrationType: null, + childParts: null, + laborAmount: 5.0, + }, + ], + supportingItems: [ + { + partNumber: "SUPPLIES-REPAIR", + description: null, + partType: "REPAIR FEE", + laborAmount: 5.0, + }, + { + partNumber: "WSREPAIR", + description: null, + partType: "REPAIR FEE", + laborAmount: 0, + }, + { + partNumber: "WSREPAIR", + description: null, + partType: "REPAIR FEE", + laborAmount: 5.0, + }, + { + partNumber: "WSREPAIR", + description: null, + partType: "REPAIR FEE", + laborAmount: 5.0, + }, + ], + }, + order: { + damage: { + isRepair: false, + glassToReplace: [{ glassLocation: "Windshield" }], + }, + }, + }, + }, + }, + }); + + // Act + wrapper.setProps({ availableLineItems: null }); + + await nextTick(); + + // Assert + expect(wrapper.vm.selectedPackageName).toBe(null); + }); + it("should select a default package if ALL glass parts and supporting items have prices", async () => { + const wrapper = setupMocks({ + mountOptionsMockData: { + store: { + getters: { + lineItems: { + glassParts: [ + { + partNumber: "FW02627GBYNOEE", + description: "solar, 3rd visor band", + color: "Green Tint, Blue Shade", + partType: "WINDSHIELD", + canSafeliteRecalibrate: false, + requiresRecalibration: false, + requiresCapabilityQuestions: false, + recalibrationType: null, + childParts: null, + laborAmount: 5.0, + }, + ], + supportingItems: [ + { + partNumber: "SUPPLIES-REPAIR", + description: null, + partType: "REPAIR FEE", + laborAmount: 5.0, + }, + { + partNumber: "WSREPAIR", + description: null, + partType: "REPAIR FEE", + laborAmount: 5.0, + }, + { + partNumber: "WSREPAIR", + description: null, + partType: "REPAIR FEE", + laborAmount: 5.0, + }, + { + partNumber: "WSREPAIR", + description: null, + partType: "REPAIR FEE", + laborAmount: 5.0, + }, + ], + }, + order: { + damage: { + isRepair: false, + glassToReplace: [{ glassLocation: "Windshield" }], + }, + }, + }, + }, + }, + }); + + // Act + wrapper.setProps({ availableLineItems: null }); + + await nextTick(); + + // Assert + expect(wrapper.vm.selectedPackageName).toBe("TierOne"); + }); + it("should select TierThree default package if Rain Defense is on order", async () => { + // This tests the business intent that when returning to the page, the selected package is the lowest package that contains all VAPs on the order. + // In this case Rain Defense is only in Premium so Tier Three should be defaulted to + const wrapper = setupMocks({ + mountOptionsMockData: { + store: { + getters: { + lineItems: { + glassParts: [ + { + partNumber: "FW02627GBYNOEE", + description: "solar, 3rd visor band", + color: "Green Tint, Blue Shade", + partType: "WINDSHIELD", + canSafeliteRecalibrate: false, + requiresRecalibration: false, + requiresCapabilityQuestions: false, + recalibrationType: null, + childParts: null, + laborAmount: 5.0, + }, + ], + vaps: [ + { + partNumber: "RAIN DEFENSE", + partType: "RAIN DEFENSE", + }, + ], + supportingItems: [ + { + partNumber: "SUPPLIES-REPAIR", + description: null, + partType: "REPAIR FEE", + laborAmount: 5.0, + }, + { + partNumber: "WSREPAIR", + description: null, + partType: "REPAIR FEE", + laborAmount: 5.0, + }, + { + partNumber: "WSREPAIR", + description: null, + partType: "REPAIR FEE", + laborAmount: 5.0, + }, + { + partNumber: "WSREPAIR", + description: null, + partType: "REPAIR FEE", + laborAmount: 5.0, + }, + ], + }, + order: { + damage: { + isRepair: false, + glassToReplace: [{ glassLocation: "Windshield" }], + }, + }, + }, + }, + }, + }); + + // Act + wrapper.setProps({ availableLineItems: null }); + + await nextTick(); + + // Assert + expect(wrapper.vm.selectedPackageName).toBe("TierThree"); + }); }); describe("service-package-question.vue, matching business rules for package display", () => { // mock scenarios in figma: diff --git a/src/layouts/quote/service-package-question/service-package-question.vue b/src/layouts/quote/service-package-question/service-package-question.vue index eede868a5..e66871830 100644 --- a/src/layouts/quote/service-package-question/service-package-question.vue +++ b/src/layouts/quote/service-package-question/service-package-question.vue @@ -42,7 +42,7 @@ export default { }, watch: { availableLineItems() { - if (this.$store.getters.lineItems.vaps) { + if (this.allGlassPartsAndSupportingItemsHavePrices(this.$store.getters.lineItems)) { this.selectDefaultPackage(); } }, @@ -212,7 +212,7 @@ export default { selectDefaultPackage() { const vapsFromStore = this.$store.getters.lineItems.vaps; let lowestTierForPackage = packageNames.TIER_ONE; - if (vapsFromStore.length > 0) { + if (vapsFromStore?.length > 0) { vapsFromStore.every((vapsItem) => { let lowestTierForThisItem = this.getLowestTierForThisItem(vapsItem); if (lowestTierForThisItem === packageNames.TIER_THREE) { @@ -228,6 +228,30 @@ export default { } this.selectedPackageName = lowestTierForPackage; }, + allGlassPartsAndSupportingItemsHavePrices(lineItems) { + if (lineItems?.glassParts) { + for (let i = 0; i < lineItems.glassParts.length; i++) { + if (this.priceIsNullOrZero(lineItems.glassParts[i])) { + return false; + } + } + } + if (lineItems?.supportingItems) { + for (let i = 0; i < lineItems.supportingItems.length; i++) { + if (this.priceIsNullOrZero(lineItems.supportingItems[i])) { + return false; + } + } + } + return true; + }, + priceIsNullOrZero(lineItem) { + return ( + (lineItem.kitPrice == null || lineItem.kitPrice == 0) && + (lineItem.laborAmount == null || lineItem.laborAmount == 0) && + (lineItem.sellingPrice == null || lineItem.sellingPrice == 0) + ); + }, getLowestTierForThisItem(vapsItem) { let lowestTierForThisItem = null; switch (vapsItem.partType) {