diff --git a/src/layouts/quote/quote.spec.js b/src/layouts/quote/quote.spec.js index e5d4d54fb..dccc73346 100644 --- a/src/layouts/quote/quote.spec.js +++ b/src/layouts/quote/quote.spec.js @@ -78,6 +78,8 @@ describe("quote.vue", () => { }; }); + wrapper.vm.pricedGlassParts = []; + //Act await wrapper.vm.forwardButtonAction(); @@ -107,6 +109,8 @@ describe("quote.vue", () => { }; }); + wrapper.vm.pricedGlassParts = []; + //Act await wrapper.vm.forwardButtonAction(); diff --git a/src/layouts/quote/quote.vue b/src/layouts/quote/quote.vue index 853cd2abf..786b046b9 100644 --- a/src/layouts/quote/quote.vue +++ b/src/layouts/quote/quote.vue @@ -102,12 +102,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( @@ -119,6 +121,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); @@ -130,6 +133,7 @@ export default { selectedVaps: null, availableLineItems: null, supportingItems: null, + pricedGlassParts: null, }; }, methods: { @@ -183,6 +187,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 796da19e9..cca37bb45 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) {